[
  {
    "path": ".devcontainer/devcontainer.json",
    "content": "{\n  \"image\": \"mcr.microsoft.com/devcontainers/python:3.14-trixie\",\n  \"postCreateCommand\": \"/bin/bash -c 'python -m pip install uv && python -m uv sync & git clone https://github.com/reflex-dev/reflex-examples; wait'\",\n  \"forwardPorts\": [3000, 8000],\n  \"portsAttributes\": {\n    \"3000\": {\n      \"label\": \"Frontend\",\n      \"onAutoForward\": \"notify\"\n    },\n    \"8000\": {\n      \"label\": \"Backend\"\n    }\n  }\n}\n"
  },
  {
    "path": ".github/CODEOWNERS",
    "content": "@reflex-dev/reflex-team\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: \"\"\nassignees: \"\"\n---\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\nSteps to reproduce the behavior:\n\n- Code/Link to Repo:\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Screenshots**\nIf applicable, add screenshots to help explain your problem.\n\n**Specifics (please complete the following information):**\n\n- Python Version:\n- Reflex Version:\n- OS:\n- Browser (Optional):\n\n**Additional context**\nAdd any other context about the problem here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/build_issue.md",
    "content": "---\nname: Build Issue\nabout: Report an issue related to reflex.build\ntitle: \"[BUILD] \" # This acts as a hint, but users can change it.\nlabels: build\nassignees: \"\"\n---\n\n## Describe the issue\n\nProvide details about the issue.\n\n...\n\n## Expected behavior\n\nWhat should have happened?\n\n...\n\n## Steps to reproduce (if applicable)\n\n1.\n2.\n3.\n\n## Environment\n\n- Reflex Version:\n- Python Version:\n- OS:\n- Browser:\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/cloud_issue.md",
    "content": "---\nname: Cloud Issue\nabout: Report an issue related to Reflex Cloud\ntitle: \"[CLOUD] \" # This acts as a hint, but users can change it.\nlabels: cloud\nassignees: \"\"\n---\n\n## Describe the issue\n\nProvide details about the issue.\n\n...\n\n## Expected behavior\n\nWhat should have happened?\n\n...\n\n## Steps to reproduce (if applicable)\n\n1.\n2.\n3.\n\n## Environment\n\n- Reflex Version:\n- Python Version:\n- OS:\n- Browser:\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/custom_component_request.md",
    "content": "---\nname: Custom Component Request\nabout: Suggest a new custom component for Reflex\ntitle: \"\"\nlabels: \"custom component request\"\nassignees: \"\"\n---\n\n**Describe the Custom Component**\nA clear and concise description of what the custom component does.\n\n- What is the purpose of the custom component?\n\n- What is the expected behavior of the custom component?\n\n- What are the use cases for the custom component?\n\n**Specifics (please complete the following information):**\n\n- Do you have a specific react package in mind? (Optional):\n\n**Additional context**\nAdd any other context about the custom component here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/enhancement_request.md",
    "content": "---\nname: Enhancement Request\nabout: Suggest an enhancement for an existing Reflex feature.\ntitle: \"\"\nlabels: \"enhancement\"\nassignees: \"\"\n---\n\n**Describe the Enhancement you want**\nA clear and concise description of what the improvement does.\n\n- Which feature do you want to improve? (and what problem does it have)\n\n- What is the benefit of the enhancement?\n\n- Show an example/usecase were the improvement are needed.\n\n**Additional context**\nAdd any other context here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/enterprise_issue.md",
    "content": "---\nname: Enterprise Issue\nabout: Report an issue related to Reflex Enterprise\ntitle: \"[ENTERPRISE] \" # This acts as a hint, but users can change it.\nlabels: enterprise\nassignees: \"\"\n---\n\n## Describe the issue\n\nProvide details about the issue.\n\n...\n\n## Expected behavior\n\nWhat should have happened?\n\n...\n\n## Steps to reproduce (if applicable)\n\n1.\n2.\n3.\n\n## Environment\n\n- Reflex Version:\n- Python Version:\n- OS:\n- Browser:\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature Request\nabout: Suggest a new feature for Reflex\ntitle: \"\"\nlabels: \"feature request\"\nassignees: \"\"\n---\n\n**Describe the Features**\nA clear and concise description of what the features does.\n\n- What is the purpose of the feature?\n\n- Show an example / use cases for the new feature.\n\n**Additional context**\nAdd any other context here.\n"
  },
  {
    "path": ".github/actions/setup_build_env/action.yml",
    "content": "# Entry conditions:\n# - `setup/checkout` has already happened\n# - working dir is the root directory of your project (e.g. `reflex/`).\n# - You have a `uv.lock` file in the root directory of your project\n# - You have a `pyproject.toml` file in the root directory of your project\n#\n# Exit conditions:\n# - Python of version `python-version` is ready to be invoked as `python`.\n# - If `run-uv-sync` is true, deps as defined in `pyproject.toml` will have been installed into the venv at `create-venv-at-path`.\n\nname: \"Setup Reflex build environment\"\ndescription: \"Sets up Python, install uv (cached), install project deps (cached)\"\ninputs:\n  python-version:\n    description: \"Python version setup\"\n    required: true\n  run-uv-sync:\n    description: \"Whether to run uv sync on current dir\"\n    required: false\n    default: false\n  create-venv-at-path:\n    description: \"Path to venv (if uv sync is enabled)\"\n    required: false\n    default: \".venv\"\n\nruns:\n  using: \"composite\"\n  steps:\n    - name: Install UV\n      uses: astral-sh/setup-uv@v6\n      with:\n        python-version: ${{ inputs.python-version }}\n        enable-cache: true\n        prune-cache: false\n        activate-environment: true\n        cache-dependency-glob: \"uv.lock\"\n    - name: Setup Node\n      uses: actions/setup-node@v4\n      with:\n        node-version: 22\n    - name: Install Dependencies\n      if: inputs.run-uv-sync == 'true'\n      run: uv sync\n      shell: bash\n"
  },
  {
    "path": ".github/codeql-config.yml",
    "content": "paths:\n  - .github\n  - reflex\n  - reflex/.templates\npaths-ignore:\n  - \"**/tests/**\"\n"
  },
  {
    "path": ".github/pull_request_template.md",
    "content": "### All Submissions:\n\n- [ ] Have you followed the guidelines stated in [CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md) file?\n- [ ] Have you checked to ensure there aren't any other open [Pull Requests](https://github.com/reflex-dev/reflex/pulls) for the desired changed?\n\n<!-- You can erase any parts of this template not applicable to your Pull Request. -->\n\n### Type of change\n\nPlease delete options that are not relevant.\n\n- [ ] Bug fix (non-breaking change which fixes an issue)\n- [ ] New feature (non-breaking change which adds functionality)\n- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)\n- [ ] This change requires a documentation update\n\n### New Feature Submission:\n\n- [ ] Does your submission pass the tests?\n- [ ] Have you linted your code locally prior to submission?\n\n### Changes To Core Features:\n\n- [ ] Have you added an explanation of what your changes do and why you'd like us to include them?\n- [ ] Have you written new tests for your core changes, as applicable?\n- [ ] Have you successfully ran tests with your changes locally?\n\n### **After** these steps, you're ready to open a pull request.\n\n    a. Give a descriptive title to your PR.\n\n    b. Describe your changes.\n\n    c. Put `closes #XXXX` in your comment to auto-close the issue that your PR fixes (if such).\n"
  },
  {
    "path": ".github/workflows/check_node_latest.yml",
    "content": "name: integration-node-latest\npermissions:\n  contents: read\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n    branches:\n      - main\n\nenv:\n  REFLEX_TELEMETRY_ENABLED: false\n\njobs:\n  check_latest_node:\n    runs-on: ubuntu-22.04\n    strategy:\n      matrix:\n        split_index: [1, 2]\n        node-version: [\"node\"]\n      fail-fast: false\n\n    steps:\n      - uses: actions/checkout@v4\n      - uses: ./.github/actions/setup_build_env\n        with:\n          python-version: 3.13\n          run-uv-sync: true\n\n      - uses: actions/setup-node@v4\n        with:\n          node-version: ${{ matrix.node-version }}\n      - run: uv run playwright install --with-deps\n      - run: |\n          uv run pytest tests/test_node_version.py -v\n          uv run pytest tests/integration --splits 2 -v --group ${{matrix.split_index}}\n"
  },
  {
    "path": ".github/workflows/check_outdated_dependencies.yml",
    "content": "name: check-outdated-dependencies\npermissions:\n  contents: read\n\non:\n  push: # This will trigger the action when a pull request is opened or updated.\n    branches:\n      - \"release/**\" # This will trigger the action when any branch starting with \"release/\" is created.\n  workflow_dispatch: # Allow manual triggering if needed.\n\njobs:\n  backend:\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v3\n\n      - uses: ./.github/actions/setup_build_env\n        with:\n          python-version: 3.13\n          run-uv-sync: true\n\n      - name: Check outdated backend dependencies\n        run: |\n          outdated=$(uv pip list --outdated)\n          echo \"Outdated:\"\n          echo \"$outdated\"\n\n          filtered_outdated=$(echo \"$outdated\" | grep -vE 'pyright|ruff' || true)\n\n          if [ ! -z \"$filtered_outdated\" ]; then\n            echo \"Outdated dependencies found:\"\n            echo \"$filtered_outdated\"\n            exit 1\n          else\n            echo \"All dependencies are up to date. (pyright and ruff are ignored)\"\n          fi\n\n  frontend:\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n      - uses: ./.github/actions/setup_build_env\n        with:\n          python-version: 3.13\n          run-uv-sync: true\n\n      - name: Clone Reflex Website Repo\n        uses: actions/checkout@v4\n        with:\n          repository: reflex-dev/reflex-web\n          ref: main\n          path: reflex-web\n      - name: Compile pyproject.toml into requirements.txt\n        working-directory: ./reflex-web\n        run: |\n          uv pip compile pyproject.toml --no-annotate --no-header --no-deps --output-file requirements.txt\n          grep -ivE \"reflex \" requirements.txt > requirements.txt.tmp && mv requirements.txt.tmp requirements.txt\n      - name: Install Requirements for reflex-web\n        working-directory: ./reflex-web\n        run: uv pip install -r requirements.txt\n      - name: Init Website for reflex-web\n        working-directory: ./reflex-web\n        run: uv run reflex init\n      - name: Run Website and Check for errors\n        run: |\n          uv run bash scripts/integration.sh ./reflex-web dev\n      - name: Check outdated frontend dependencies\n        working-directory: ./reflex-web/.web\n        run: |\n          raw_outdated=$(/home/runner/.local/share/reflex/bun/bin/bun outdated)\n          outdated=$(echo \"$raw_outdated\" | grep -vE '\\|\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\|' || true)\n          echo \"Outdated:\"\n          echo \"$outdated\"\n\n          # Ignore 3rd party dependencies that are not updated.\n          filtered_outdated=$(echo \"$outdated\" | grep -vE 'Package|@chakra-ui|lucide-react|@splinetool/runtime|ag-grid-react|framer-motion|ag-grid' || true)\n          no_extra=$(echo \"$filtered_outdated\" | grep -vE '\\|\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-' || true)\n\n\n          if [ ! -z \"$no_extra\" ]; then\n            echo \"Outdated dependencies found:\"\n            echo \"$filtered_outdated\"\n            exit 1\n          else\n            echo \"All dependencies are up to date. (3rd party packages are ignored)\"\n          fi\n"
  },
  {
    "path": ".github/workflows/codeql.yml",
    "content": "# For most projects, this workflow file will not need changing; you simply need\n# to commit it to your repository.\n#\n# You may wish to alter this file to override the set of languages analyzed,\n# or to provide custom queries or build logic.\n#\n# ******** NOTE ********\n# We have attempted to detect the languages in your repository. Please check\n# the `language` matrix defined below to confirm you have the correct set of\n# supported CodeQL languages.\n#\nname: \"CodeQL Advanced\"\n\non:\n  push:\n    branches: [\"main\"]\n  pull_request:\n    branches: [\"main\"]\n  schedule:\n    - cron: \"36 7 * * 4\"\n\njobs:\n  analyze:\n    name: Analyze (${{ matrix.language }})\n    # Runner size impacts CodeQL analysis time. To learn more, please see:\n    #   - https://gh.io/recommended-hardware-resources-for-running-codeql\n    #   - https://gh.io/supported-runners-and-hardware-resources\n    #   - https://gh.io/using-larger-runners (GitHub.com only)\n    # Consider using larger runners or machines with greater resources for possible analysis time improvements.\n    runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}\n    permissions:\n      # required for all workflows\n      security-events: write\n\n      # required to fetch internal or private CodeQL packs\n      packages: read\n\n      # only required for workflows in private repositories\n      actions: read\n      contents: read\n\n    strategy:\n      fail-fast: false\n      matrix:\n        include:\n          - language: javascript-typescript\n            build-mode: none\n          - language: python\n            build-mode: none\n          - language: actions\n            build-mode: none\n        # CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'\n        # Use `c-cpp` to analyze code written in C, C++ or both\n        # Use 'java-kotlin' to analyze code written in Java, Kotlin or both\n        # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both\n        # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,\n        # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.\n        # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how\n        # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v4\n\n      # Add any setup steps before running the `github/codeql-action/init` action.\n      # This includes steps like installing compilers or runtimes (`actions/setup-node`\n      # or others). This is typically only required for manual builds.\n      # - name: Setup runtime (example)\n      #   uses: actions/setup-example@v1\n\n      # Initializes the CodeQL tools for scanning.\n      - name: Initialize CodeQL\n        uses: github/codeql-action/init@v4\n        with:\n          languages: ${{ matrix.language }}\n          config-file: .github/codeql-config.yml\n          build-mode: ${{ matrix.build-mode }}\n          # If you wish to specify custom queries, you can do so here or in a config file.\n          # By default, queries listed here will override any specified in a config file.\n          # Prefix the list here with \"+\" to use these queries and those in the config file.\n\n          # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs\n          # queries: security-extended,security-and-quality\n\n      # If the analyze step fails for one of the languages you are analyzing with\n      # \"We were unable to automatically build your code\", modify the matrix above\n      # to set the build mode to \"manual\" for that language. Then modify this step\n      # to build your code.\n      # ℹ️ Command-line programs to run using the OS shell.\n      # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun\n      - if: matrix.build-mode == 'manual'\n        shell: bash\n        run: |\n          echo 'If you are using a \"manual\" build mode for one or more of the' \\\n            'languages you are analyzing, replace this with the commands to build' \\\n            'your code, for example:'\n          echo '  make bootstrap'\n          echo '  make release'\n          exit 1\n\n      - name: Perform CodeQL Analysis\n        uses: github/codeql-action/analyze@v4\n        with:\n          category: \"/language:${{matrix.language}}\"\n"
  },
  {
    "path": ".github/workflows/dependency-review.yml",
    "content": "name: \"Dependency Review\"\non: [pull_request]\n\npermissions:\n  contents: read\n\njobs:\n  dependency-review:\n    runs-on: ubuntu-latest\n    steps:\n      - name: \"Checkout Repository\"\n        uses: actions/checkout@v4\n      - name: \"Dependency Review\"\n        uses: actions/dependency-review-action@v4\n        with:\n          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\n          allow-dependencies-licenses: \"pkg:pypi/lazy-loader\"\n"
  },
  {
    "path": ".github/workflows/integration_app_harness.yml",
    "content": "name: integration-app-harness\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.event.pull_request.id }}\n  cancel-in-progress: true\n\non:\n  push:\n    branches: [\"main\"]\n    paths-ignore:\n      - \"**/*.md\"\n  pull_request:\n    branches: [\"main\"]\n    paths-ignore:\n      - \"**/*.md\"\nenv:\n  APP_HARNESS_HEADLESS: 1\n  PYTHONUNBUFFERED: 1\n\npermissions:\n  contents: read\n\njobs:\n  integration-app-harness:\n    timeout-minutes: 30\n    strategy:\n      matrix:\n        state_manager: [\"redis\", \"memory\"]\n        python-version: [\"3.11\", \"3.12\", \"3.13\", \"3.14\"]\n        split_index: [1, 2]\n      fail-fast: false\n    runs-on: ubuntu-22.04\n    services:\n      # Label used to access the service container\n      redis:\n        image: ${{ matrix.state_manager == 'redis' && 'redis' || '' }}\n        # Set health checks to wait until redis has started\n        options: >-\n          --health-cmd \"redis-cli ping\"\n          --health-interval 10s\n          --health-timeout 5s\n          --health-retries 5\n        ports:\n          # Maps port 6379 on service container to the host\n          - 6379:6379\n    steps:\n      - uses: actions/checkout@v4\n      - uses: ./.github/actions/setup_build_env\n        with:\n          python-version: ${{ matrix.python-version }}\n          run-uv-sync: true\n\n      - name: Install playwright\n        run: uv run playwright install chromium --only-shell\n\n      - name: Run app harness tests\n        env:\n          REFLEX_REDIS_URL: ${{ matrix.state_manager == 'redis' && 'redis://localhost:6379' || '' }}\n        run: uv run pytest tests/integration --reruns 3 -v --maxfail=5 --splits 2 --group ${{matrix.split_index}}\n"
  },
  {
    "path": ".github/workflows/integration_tests.yml",
    "content": "name: integration-tests\n\non:\n  push:\n    branches: [\"main\"]\n    paths-ignore:\n      - \"**/*.md\"\n  pull_request:\n    branches: [\"main\"]\n    paths-ignore:\n      - \"**/*.md\"\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.event.pull_request.id }}\n  cancel-in-progress: true\n\npermissions:\n  contents: read\n\ndefaults:\n  run:\n    shell: bash\n\nenv:\n  # Windows CI would fail without this.\n  # Ref: https://gist.github.com/NodeJSmith/e7e37f2d3f162456869f015f842bcf15\n  # TODO: can we fix windows encoding natively within reflex? Bug above can hit real users too (less common, but possible)\n  # - Catch encoding errors when printing logs\n  # - Best effort print lines that contain illegal chars (map to some default char, etc.)\n  PYTHONIOENCODING: \"utf8\"\n  REFLEX_TELEMETRY_ENABLED: false\n  NODE_OPTIONS: \"--max_old_space_size=8192\"\n  PR_TITLE: ${{ github.event.pull_request.title }}\n\njobs:\n  example-counter-and-nba-proxy:\n    env:\n      OUTPUT_FILE: import_benchmark.json\n    timeout-minutes: 30\n    strategy:\n      # Prioritize getting more information out of the workflow (even if something fails)\n      fail-fast: false\n      matrix:\n        # Show OS combos first in GUI\n        os: [ubuntu-latest, windows-latest]\n        python-version: [\"3.10\", \"3.11\", \"3.12\", \"3.13\"]\n\n    runs-on: ${{ matrix.os }}\n    steps:\n      - uses: actions/checkout@v4\n      - uses: ./.github/actions/setup_build_env\n        with:\n          python-version: ${{ matrix.python-version }}\n          run-uv-sync: true\n\n      - name: Clone Reflex Examples Repo\n        uses: actions/checkout@v4\n        with:\n          repository: reflex-dev/reflex-examples\n          path: reflex-examples\n      - name: Install requirements for counter example\n        working-directory: ./reflex-examples/counter\n        run: |\n          uv pip install -r requirements.txt\n      - name: Check export --backend-only before init for counter example\n        working-directory: ./reflex-examples/counter\n        run: |\n          uv run reflex export --backend-only\n      - name: Check run --backend-only before init for counter example\n        run: |\n          uv run bash scripts/integration.sh ./reflex-examples/counter dev 8001 --backend-only --backend-port 8001\n      - name: Init Website for counter example\n        working-directory: ./reflex-examples/counter\n        run: |\n          uv run reflex init --loglevel debug\n      - name: Check export for counter example\n        working-directory: ./reflex-examples/counter\n        run: |\n          uv run reflex export\n      - name: Run Website and Check for errors\n        run: |\n          # Check that npm is home\n          npm -v\n          uv run bash scripts/integration.sh ./reflex-examples/counter dev\n      - name: Install requirements for nba proxy example\n        working-directory: ./reflex-examples/nba-proxy\n        run: |\n          uv pip install -r requirements.txt\n      - name: Check export --backend-only before init for nba-proxy example\n        working-directory: ./reflex-examples/nba-proxy\n        run: |\n          uv run reflex export --backend-only\n      - name: Init Website for nba-proxy example\n        working-directory: ./reflex-examples/nba-proxy\n        run: |\n          uv run reflex init --loglevel debug\n      - name: Run Website and Check for errors\n        run: |\n          # Check that npm is home\n          npm -v\n          uv run bash scripts/integration.sh ./reflex-examples/nba-proxy dev\n\n  reflex-web:\n    strategy:\n      fail-fast: false\n      matrix:\n        python-version: [\"3.11\", \"3.12\"]\n\n    env:\n      REFLEX_WEB_WINDOWS_OVERRIDE: \"1\"\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: ./.github/actions/setup_build_env\n        with:\n          python-version: ${{ matrix.python-version }}\n          run-uv-sync: true\n\n      - name: Clone Reflex Website Repo\n        uses: actions/checkout@v4\n        with:\n          repository: reflex-dev/reflex-web\n          ref: main\n          path: reflex-web\n          submodules: recursive\n\n      - name: Compile pyproject.toml into requirements.txt\n        working-directory: ./reflex-web\n        run: |\n          uv pip compile pyproject.toml --no-annotate --no-header --no-deps --output-file requirements.txt\n          grep -ivE \"reflex \" requirements.txt > requirements.txt.tmp && mv requirements.txt.tmp requirements.txt\n      - name: Install Requirements for reflex-web\n        working-directory: ./reflex-web\n        run: uv pip install -r requirements.txt\n      - name: Init Website for reflex-web\n        working-directory: ./reflex-web\n        run: uv run --active --no-sync reflex init\n      - name: Run Website and Check for errors\n        run: |\n          # Check that npm is home\n          npm -v\n          uv run --active --no-sync bash scripts/integration.sh ./reflex-web prod\n\n  rx-shout-from-template:\n    strategy:\n      fail-fast: false\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: ./.github/actions/setup_build_env\n        with:\n          python-version: 3.14\n          run-uv-sync: true\n\n      - name: Create app directory\n        run: mkdir rx-shout-from-template\n      - name: Init reflex-web from template\n        run: uv run reflex init --template https://github.com/masenf/rx_shout\n        working-directory: ./rx-shout-from-template\n      - name: ignore reflex pin in requirements\n        run: sed -i -e '/reflex==/d' requirements.txt\n        working-directory: ./rx-shout-from-template\n      - name: Install additional dependencies\n        run: uv pip install -r requirements.txt\n        working-directory: ./rx-shout-from-template\n      - name: Run Website and Check for errors\n        run: |\n          # Check that npm is home\n          npm -v\n          uv run bash scripts/integration.sh ./rx-shout-from-template prod\n\n  reflex-web-macos:\n    if: github.event_name == 'push' && github.ref == 'refs/heads/main'\n    strategy:\n      fail-fast: false\n      matrix:\n        # Note: py311 version chosen due to available arm64 darwin builds.\n        python-version: [\"3.11\", \"3.12\"]\n    runs-on: macos-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: ./.github/actions/setup_build_env\n        with:\n          python-version: ${{ matrix.python-version }}\n          run-uv-sync: true\n\n      - name: Clone Reflex Website Repo\n        uses: actions/checkout@v4\n        with:\n          repository: reflex-dev/reflex-web\n          ref: main\n          path: reflex-web\n          submodules: recursive\n      - name: Compile pyproject.toml into requirements.txt\n        working-directory: ./reflex-web\n        run: |\n          uv pip compile pyproject.toml --no-annotate --no-header --no-deps --output-file requirements.txt\n          grep -ivE \"reflex \" requirements.txt > requirements.txt.tmp && mv requirements.txt.tmp requirements.txt\n      - name: Install Requirements for reflex-web\n        working-directory: ./reflex-web\n        run: uv pip install -r requirements.txt\n      - name: Init Website for reflex-web\n        working-directory: ./reflex-web\n        run: uv run --active --no-sync reflex init\n      - name: Run Website and Check for errors\n        run: |\n          # Check that npm is home\n          npm -v\n          uv run --active --no-sync bash scripts/integration.sh ./reflex-web prod\n"
  },
  {
    "path": ".github/workflows/performance.yml",
    "content": "name: performance-tests\npermissions:\n  contents: read\n\non:\n  push:\n    branches:\n      - \"main\" # or \"master\"\n    paths-ignore:\n      - \"**/*.md\"\n  pull_request:\n  workflow_dispatch:\n\nenv:\n  REFLEX_TELEMETRY_ENABLED: false\n  NODE_OPTIONS: \"--max_old_space_size=8192\"\n  PR_TITLE: ${{ github.event.pull_request.title }}\n  APP_HARNESS_HEADLESS: 1\n  PYTHONUNBUFFERED: 1\n\njobs:\n  benchmarks:\n    name: Run benchmarks\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Install uv\n        uses: astral-sh/setup-uv@v6\n\n      - name: Set up Python\n        uses: actions/setup-python@v5\n        with:\n          python-version: \"3.14\"\n\n      - name: Install dependencies\n        run: uv sync --all-extras --dev\n\n      - name: Run benchmarks\n        uses: CodSpeedHQ/action@v4\n        with:\n          mode: instrumentation\n          run: uv run pytest -v tests/benchmarks --codspeed\n"
  },
  {
    "path": ".github/workflows/pre-commit.yml",
    "content": "name: pre-commit\npermissions:\n  contents: read\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.event.pull_request.id }}\n  cancel-in-progress: true\n\non:\n  pull_request:\n    branches: [\"main\"]\n  push:\n    # Note even though this job is called \"pre-commit\" and runs \"pre-commit\", this job will run\n    # also POST-commit on main also!  In case there are mishandled merge conflicts / bad auto-resolves\n    # when merging into main branch.\n    branches: [\"main\"]\n\njobs:\n  pre-commit:\n    timeout-minutes: 30\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: ./.github/actions/setup_build_env\n        with:\n          python-version: 3.14\n          run-uv-sync: true\n      - uses: actions/checkout@v4\n        with:\n          clean: false\n      - run: uv run pre-commit run --all-files --show-diff-on-failure\n"
  },
  {
    "path": ".github/workflows/publish.yml",
    "content": "name: Publish to PyPI\n\non:\n  workflow_dispatch:\n\njobs:\n  publish:\n    runs-on: ubuntu-latest\n    environment:\n      name: pypi\n    permissions:\n      id-token: write\n      contents: read\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n\n      - name: Install uv\n        uses: astral-sh/setup-uv@v7\n\n      - name: Build\n        run: uv build\n\n      - name: Verify .pyi files in wheel\n        run: |\n          if unzip -l dist/*.whl | grep '\\.pyi$'; then\n            echo \"✓ .pyi files found in distribution\"\n          else\n            echo \"Error: No .pyi files found in wheel\"\n            exit 1\n          fi\n\n      - name: Publish\n        run: uv publish\n"
  },
  {
    "path": ".github/workflows/reflex_init_in_docker_test.yml",
    "content": "name: reflex-init-in-docker-test\npermissions:\n  contents: read\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.event.pull_request.id }}\n  cancel-in-progress: true\n\non:\n  push:\n    branches: [\"main\"]\n    paths-ignore:\n      - \"**/*.md\"\n  pull_request:\n    branches: [\"main\"]\n    paths-ignore:\n      - \"**/*.md\"\n\njobs:\n  # TODO we can extend to various starting points (e.g. Ubuntu with node, without node, with unzip, without unzip, etc.)\n  # Currently starting point is: Ubuntu + unzip, xz-utils, Python suite.  No node.\n  reflex-install-and-init:\n    timeout-minutes: 30\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n\n      - shell: bash\n        run: |\n          # Run reflex init in a docker container\n\n          # cwd is repo root\n          docker build -f tests/integration/init-test/Dockerfile -t reflex-init-test tests/integration/init-test\n          docker run --rm -v $(pwd):/reflex-repo/ reflex-init-test /reflex-repo/tests/integration/init-test/in_docker_test_script.sh\n"
  },
  {
    "path": ".github/workflows/unit_tests.yml",
    "content": "name: unit-tests\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.event.pull_request.id }}\n  cancel-in-progress: true\n\non:\n  push:\n    branches: [\"main\"]\n    paths-ignore:\n      - \"**/*.md\"\n  pull_request:\n    branches: [\"main\"]\n    paths-ignore:\n      - \"**/*.md\"\n\npermissions:\n  contents: read\n\ndefaults:\n  run:\n    shell: bash\n\njobs:\n  unit-tests:\n    timeout-minutes: 30\n    strategy:\n      fail-fast: false\n      matrix:\n        os: [ubuntu-latest, windows-latest]\n        python-version: [\"3.10\", \"3.11\", \"3.12\", \"3.13\", \"3.14\"]\n    runs-on: ${{ matrix.os }}\n\n    # Service containers to run with `runner-job`\n    services:\n      # Label used to access the service container\n      redis:\n        image: ${{ matrix.os == 'ubuntu-latest' && 'redis' || '' }}\n        # Set health checks to wait until redis has started\n        options: >-\n          --health-cmd \"redis-cli ping\"\n          --health-interval 10s\n          --health-timeout 5s\n          --health-retries 5\n        ports:\n          # Maps port 6379 on service container to the host\n          - 6379:6379\n    steps:\n      - uses: actions/checkout@v4\n      - uses: ./.github/actions/setup_build_env\n        with:\n          python-version: ${{ matrix.python-version }}\n          run-uv-sync: true\n\n      - name: Run unit tests\n        run: |\n          export PYTHONUNBUFFERED=1\n          uv run pytest tests/units --cov --no-cov-on-fail --cov-report=\n      - name: Run unit tests w/ redis\n        if: ${{ matrix.os == 'ubuntu-latest' }}\n        run: |\n          export PYTHONUNBUFFERED=1\n          export REFLEX_REDIS_URL=redis://localhost:6379\n          uv run pytest tests/units --cov --no-cov-on-fail --cov-report=\n      - name: Run unit tests w/ redis and OPLOCK_ENABLED\n        if: ${{ matrix.os == 'ubuntu-latest' }}\n        run: |\n          export PYTHONUNBUFFERED=1\n          export REFLEX_REDIS_URL=redis://localhost:6379\n          export REFLEX_OPLOCK_ENABLED=true\n          uv run pytest tests/units --cov --no-cov-on-fail --cov-report=\n      # Change to explicitly install v1 when reflex-hosting-cli is compatible with v2\n      - name: Run unit tests w/ pydantic v1\n        run: |\n          export PYTHONUNBUFFERED=1\n          uv pip install \"pydantic~=1.10\"\n          uv run pytest tests/units --cov --no-cov-on-fail --cov-report=\n      - name: Generate coverage report\n        run: uv run coverage html\n\n  unit-tests-macos:\n    timeout-minutes: 30\n    if: github.event_name == 'push' && github.ref == 'refs/heads/main'\n    strategy:\n      fail-fast: false\n      matrix:\n        python-version: [\"3.10\", \"3.11\", \"3.12\", \"3.13\", \"3.14\"]\n    runs-on: macos-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: ./.github/actions/setup_build_env\n        with:\n          python-version: ${{ matrix.python-version }}\n          run-uv-sync: true\n\n      - name: Run unit tests\n        run: |\n          export PYTHONUNBUFFERED=1\n          uv run pytest tests/units --cov --no-cov-on-fail --cov-report=\n      - name: Run unit tests w/ pydantic v1\n        run: |\n          export PYTHONUNBUFFERED=1\n          uv pip install \"pydantic~=1.10\"\n          uv run pytest tests/units --cov --no-cov-on-fail --cov-report=\n"
  },
  {
    "path": ".gitignore",
    "content": "**/.DS_Store\n**/*.pyc\nassets/external/*\ndist/*\nexamples/\n.web\n.states\n.idea\n.vscode\n.coverage\n.coverage.*\n.venv\nvenv\nrequirements.txt\n.pyi_generator_last_run\n.pyi_generator_diff\nreflex.db\n.codspeed\n.env\n.env.*\nnode_modules\npackage-lock.json\n*.pyi\n.pre-commit-config.yaml"
  },
  {
    "path": ".python-version",
    "content": "3.14"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participation in our\ncommunity a harassment-free experience for everyone, regardless of age, body\nsize, visible or invisible disability, ethnicity, sex characteristics, gender\nidentity and expression, level of experience, education, socioeconomic status,\nnationality, personal appearance, race, religion, or sexual identity\nand orientation.\n\nWe pledge to act and interact in ways that contribute to an open, welcoming,\ndiverse, inclusive, and healthy community.\n\n## Our Standards\n\nExamples of behavior that contributes to a positive environment for our\ncommunity include:\n\n- Demonstrating empathy and kindness toward other people\n- Being respectful of differing opinions, viewpoints, and experiences\n- Giving and gracefully accepting constructive feedback\n- Accepting responsibility and apologizing to those affected by our mistakes,\n  and learning from the experience\n- Focusing on what is best not just for us as individuals, but for the\n  overall community\n\nExamples of unacceptable behavior include:\n\n- The use of sexualized language or imagery, and sexual attention or\n  advances of any kind\n- Trolling, insulting or derogatory comments, and personal or political attacks\n- Public or private harassment\n- Publishing others' private information, such as a physical or email\n  address, without their explicit permission\n- Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Enforcement Responsibilities\n\nCommunity leaders are responsible for clarifying and enforcing our standards of\nacceptable behavior and will take appropriate and fair corrective action in\nresponse to any behavior that they deem inappropriate, threatening, offensive,\nor harmful.\n\nCommunity leaders have the right and responsibility to remove, edit, or reject\ncomments, commits, code, wiki edits, issues, and other contributions that are\nnot aligned to this Code of Conduct, and will communicate reasons for moderation\ndecisions when appropriate.\n\n## Scope\n\nThis Code of Conduct applies within all community spaces, and also applies when\nan individual is officially representing the community in public spaces.\nExamples of representing our community include using an official e-mail address,\nposting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported to the community leaders responsible for enforcement at\nopensource@reflex.dev.\nAll complaints will be reviewed and investigated promptly and fairly.\n\nAll community leaders are obligated to respect the privacy and security of the\nreporter of any incident.\n\n## Enforcement Guidelines\n\nCommunity leaders will follow these Community Impact Guidelines in determining\nthe consequences for any action they deem in violation of this Code of Conduct:\n\n### 1. Correction\n\n**Community Impact**: Use of inappropriate language or other behavior deemed\nunprofessional or unwelcome in the community.\n\n**Consequence**: A private, written warning from community leaders, providing\nclarity around the nature of the violation and an explanation of why the\nbehavior was inappropriate. A public apology may be requested.\n\n### 2. Warning\n\n**Community Impact**: A violation through a single incident or series\nof actions.\n\n**Consequence**: A warning with consequences for continued behavior. No\ninteraction with the people involved, including unsolicited interaction with\nthose enforcing the Code of Conduct, for a specified period of time. This\nincludes avoiding interactions in community spaces as well as external channels\nlike social media. Violating these terms may lead to a temporary or\npermanent ban.\n\n### 3. Temporary Ban\n\n**Community Impact**: A serious violation of community standards, including\nsustained inappropriate behavior.\n\n**Consequence**: A temporary ban from any sort of interaction or public\ncommunication with the community for a specified period of time. No public or\nprivate interaction with the people involved, including unsolicited interaction\nwith those enforcing the Code of Conduct, is allowed during this period.\nViolating these terms may lead to a permanent ban.\n\n### 4. Permanent Ban\n\n**Community Impact**: Demonstrating a pattern of violation of community\nstandards, including sustained inappropriate behavior, harassment of an\nindividual, or aggression toward or disparagement of classes of individuals.\n\n**Consequence**: A permanent ban from any sort of public interaction within\nthe community as well as any sort of private interaction with the people.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage],\nversion 2.0, available at\nhttps://www.contributor-covenant.org/version/2/0/code_of_conduct.html.\n\nCommunity Impact Guidelines were inspired by [Mozilla's code of conduct\nenforcement ladder](https://github.com/mozilla/diversity).\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see the FAQ at\nhttps://www.contributor-covenant.org/faq. Translations are available at\nhttps://www.contributor-covenant.org/translations.\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Reflex Contributing Guidelines\n\nFor an extensive guide on the different ways to contribute to Reflex see our [Contributing Guide on Notion](https://www.notion.so/reflex-dev/2107ab2bc166497db951b8d742748284?v=f0eaff78fa984b5ab15d204af58907d7).\n\n## Running a Local Build of Reflex\n\nHere is a quick guide on how to run Reflex repo locally so you can start contributing to the project.\n\n**Prerequisites:**\n\n- 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).\n\n**1. Fork this repository:**\nFork this repository by clicking on the `Fork` button on the top right.\n\n**2. Clone Reflex and navigate into the repo:**\n\n```bash\ngit clone https://github.com/<YOUR-USERNAME>/reflex.git\ncd reflex\n```\n\n**3. Install your local Reflex build:**\n\n```bash\nuv sync\n```\n\n**4. Now create an examples folder so you can test the local Python build in this repository.**\n\n- We have the `examples` folder in the `.gitignore`, so your changes in `reflex/examples` won't be reflected in your commit.\n\n```bash\nmkdir examples\ncd examples\n```\n\n**5. Init and Run**\n\n```bash\nuv run reflex init\nuv run reflex run\n```\n\nAll the changes you make to the repository will be reflected in your running app.\n\n- We have the examples folder in the .gitignore, so your changes in reflex/examples won't be reflected in your commit.\n\n## 🧪 Testing and QA\n\nAny feature or significant change added should be accompanied with unit tests.\n\nWithin the 'test' directory of Reflex you can add to a test file already there or create a new test python file if it doesn't fit into the existing layout.\n\n#### What to unit test?\n\n- Any feature or significant change that has been added.\n- Any edge cases or potential problem areas.\n- Any interactions between different parts of the code.\n\n## ✅ Making a PR\n\nOnce you solve a current issue or improvement to Reflex, you can make a PR, and we will review the changes.\n\nBefore submitting, a pull request, ensure the following steps are taken and test passing.\n\nIn your `reflex` directory run make sure all the unit tests are still passing using the following command.\nThis will fail if code coverage is below 70%.\n\n```bash\nuv run pytest tests/units --cov --no-cov-on-fail --cov-report=\n```\n\nNext make sure all the following tests pass. This ensures that every new change has proper documentation and type checking.\n\n```bash\nuv run ruff check .\nuv run pyright reflex tests\nfind reflex tests -name \"*.py\" -not -path reflex/reflex.py | xargs uv run darglint\n```\n\nFinally, run `ruff` to format your code.\n\n```bash\nuv run ruff format .\n```\n\nConsider installing git pre-commit hooks so Ruff, Pyright, Darglint and `make_pyi` will run automatically before each commit.\n\n```bash\nuv run pre-commit install\n```\n\nThat's it you can now submit your PR. Thanks for contributing to Reflex!\n\n## Editing Templates\n\nTo edit the templates in Reflex you can do so in two way.\n\nChange to the basic `blank` template can be done in the `reflex/.templates/apps/blank` directory.\n\nOthers 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.\n\n## Other Notes\n\nFor 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.\n\n(Please check in with the team before adding a new component to Reflex we are cautious about adding new components to Reflex's core.)\n\n```bash\nuv run python -m reflex.utils.pyi_generator\n```\n"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        https://www.apache.org/licenses/LICENSE-2.0\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION \n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright 2023, Pynecone, Inc.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "MCP_README.md",
    "content": "# Reflex MCP Server\n\nThe Reflex MCP Server provides comprehensive access to Reflex framework documentation and component information through the Model Context Protocol (MCP). This server is deployed and ready to use with your MCP-compatible AI tools.\n\nCheck the documentation at https://reflex.dev/docs/ai-builder/integrations/mcp-overview\n"
  },
  {
    "path": "README.md",
    "content": "<div align=\"center\">\n<img src=\"https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex.svg\" alt=\"Reflex Logo\" width=\"300px\">\n\n<hr>\n\n### **✨ Performant, customizable web apps in pure Python. Deploy in seconds. ✨**\n\n[![PyPI version](https://badge.fury.io/py/reflex.svg)](https://badge.fury.io/py/reflex)\n![versions](https://img.shields.io/pypi/pyversions/reflex.svg)\n[![Documentation](https://img.shields.io/badge/Documentation%20-Introduction%20-%20%23007ec6)](https://reflex.dev/docs/getting-started/introduction)\n[![PyPI Downloads](https://static.pepy.tech/badge/reflex)](https://pepy.tech/projects/reflex)\n[![Discord](https://img.shields.io/discord/1029853095527727165?color=%237289da&label=Discord)](https://discord.gg/T5WSbC2YtQ)\n[![Twitter](https://img.shields.io/twitter/follow/getreflex)](https://x.com/getreflex)\n\n</div>\n\n---\n\n[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) | [Español](https://github.com/reflex-dev/reflex/blob/main/docs/es/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) | [Tiếng Việt](https://github.com/reflex-dev/reflex/blob/main/docs/vi/README.md)\n\n---\n\n> [!NOTE]\n> 🚀 **Try [Reflex Build](https://build.reflex.dev/)** – our AI-powered app builder that generates full-stack Reflex applications in seconds.\n\n---\n\n# Introduction\n\nReflex is a library to build full-stack web apps in pure Python.\n\nKey features:\n\n- **Pure Python** - Write your app's frontend and backend all in Python, no need to learn Javascript.\n- **Full Flexibility** - Reflex is easy to get started with, but can also scale to complex apps.\n- **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.\n\nSee our [architecture page](https://reflex.dev/blog/2024-03-21-reflex-architecture/#the-reflex-architecture) to learn how Reflex works under the hood.\n\n## ⚙️ Installation\n\n**Important:** We strongly recommend using a virtual environment to ensure the `reflex` command is available in your PATH.\n\n## 🥳 Create your first app\n\n### 1. Create the project directory\n\nReplace `my_app_name` with your project name:\n\n```bash\nmkdir my_app_name\ncd my_app_name\n```\n\n### 2. Set up a virtual environment\n\nCreate and activate virtual environment\n\n```bash\n# On Windows:\npython -m venv .venv\n.venv\\Scripts\\activate\n\n# On macOS/Linux:\npython3 -m venv .venv\nsource .venv/bin/activate\n```\n\n### 3. Install Reflex\n\nReflex is available as a pip package (Requires Python 3.10+):\n\n```bash\npip install reflex\n```\n\n### 4. Initialize the project\n\nThis command initializes a template app in your new directory:\n\n```bash\nreflex init\n```\n\n### 5. Run the app\n\nYou can run this app in development mode:\n\n```bash\nreflex run\n```\n\nYou should see your app running at http://localhost:3000.\n\nNow 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.\n\n### Troubleshooting\n\nIf you installed Reflex without a virtual environment and the `reflex` command is not found, you can run commands using: `python3 -m reflex init` and `python3 -m reflex run`\n\n## 🫧 Example App\n\nLet'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.\n\n&nbsp;\n\n<div align=\"center\">\n<img src=\"https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/dalle.gif\" alt=\"A frontend wrapper for DALL·E, shown in the process of generating an image.\" width=\"550\" />\n</div>\n\n&nbsp;\n\nHere is the complete code to create this. This is all done in one Python file!\n\n```python\nimport reflex as rx\nimport openai\n\nopenai_client = openai.OpenAI()\n\n\nclass State(rx.State):\n    \"\"\"The app state.\"\"\"\n\n    prompt = \"\"\n    image_url = \"\"\n    processing = False\n    complete = False\n\n    def get_image(self):\n        \"\"\"Get the image from the prompt.\"\"\"\n        if self.prompt == \"\":\n            return rx.window_alert(\"Prompt Empty\")\n\n        self.processing, self.complete = True, False\n        yield\n        response = openai_client.images.generate(\n            prompt=self.prompt, n=1, size=\"1024x1024\"\n        )\n        self.image_url = response.data[0].url\n        self.processing, self.complete = False, True\n\n\ndef index():\n    return rx.center(\n        rx.vstack(\n            rx.heading(\"DALL-E\", font_size=\"1.5em\"),\n            rx.input(\n                placeholder=\"Enter a prompt..\",\n                on_blur=State.set_prompt,\n                width=\"25em\",\n            ),\n            rx.button(\n                \"Generate Image\",\n                on_click=State.get_image,\n                width=\"25em\",\n                loading=State.processing\n            ),\n            rx.cond(\n                State.complete,\n                rx.image(src=State.image_url, width=\"20em\"),\n            ),\n            align=\"center\",\n        ),\n        width=\"100%\",\n        height=\"100vh\",\n    )\n\n# Add state and page to the app.\napp = rx.App()\napp.add_page(index, title=\"Reflex:DALL-E\")\n```\n\n## Let's break this down.\n\n<div align=\"center\">\n<img src=\"https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/dalle_colored_code_example.png\" alt=\"Explaining the differences between backend and frontend parts of the DALL-E app.\" width=\"900\" />\n</div>\n\n### **Reflex UI**\n\nLet's start with the UI.\n\n```python\ndef index():\n    return rx.center(\n        ...\n    )\n```\n\nThis `index` function defines the frontend of the app.\n\nWe use different components such as `center`, `vstack`, `input`, and `button` to build the frontend. Components can be nested within each other\nto create complex layouts. And you can use keyword args to style them with the full power of CSS.\n\nReflex comes with [60+ built-in components](https://reflex.dev/docs/library) to help you get started. We are actively adding more components, and it's easy to [create your own components](https://reflex.dev/docs/wrapping-react/overview/).\n\n### **State**\n\nReflex represents your UI as a function of your state.\n\n```python\nclass State(rx.State):\n    \"\"\"The app state.\"\"\"\n    prompt = \"\"\n    image_url = \"\"\n    processing = False\n    complete = False\n\n```\n\nThe state defines all the variables (called vars) in an app that can change and the functions that change them.\n\nHere the state is comprised of a `prompt` and `image_url`. There are also the booleans `processing` and `complete` to indicate when to disable the button (during image generation) and when to show the resulting image.\n\n### **Event Handlers**\n\n```python\ndef get_image(self):\n    \"\"\"Get the image from the prompt.\"\"\"\n    if self.prompt == \"\":\n        return rx.window_alert(\"Prompt Empty\")\n\n    self.processing, self.complete = True, False\n    yield\n    response = openai_client.images.generate(\n        prompt=self.prompt, n=1, size=\"1024x1024\"\n    )\n    self.image_url = response.data[0].url\n    self.processing, self.complete = False, True\n```\n\nWithin the state, we define functions called event handlers that change the state vars. Event handlers are the way that we can modify the state in Reflex. They can be called in response to user actions, such as clicking a button or typing in a text box. These actions are called events.\n\nOur DALL·E app has an event handler, `get_image` which gets this image from the OpenAI API. Using `yield` in the middle of an event handler will cause the UI to update. Otherwise the UI will update at the end of the event handler.\n\n### **Routing**\n\nFinally, we define our app.\n\n```python\napp = rx.App()\n```\n\nWe add a page from the root of the app to the index component. We also add a title that will show up in the page preview/browser tab.\n\n```python\napp.add_page(index, title=\"DALL-E\")\n```\n\nYou can create a multi-page app by adding more pages.\n\n## 📑 Resources\n\n<div align=\"center\">\n\n📑 [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;\n\n</div>\n\n## ✅ Status\n\nReflex launched in December 2022 with the name Pynecone.\n\n🚀 Introducing [Reflex Build](https://build.reflex.dev/) — Our AI-Powered Builder\nReflex Build uses AI to generate complete full-stack Python applications. It helps you quickly create, customize, and refine your Reflex apps — from frontend components to backend logic — so you can focus on your ideas instead of boilerplate code. Whether you’re prototyping or scaling, Reflex Build accelerates development by intelligently scaffolding and optimizing your app’s entire stack.\n\nAlongside this, [Reflex Cloud](https://cloud.reflex.dev) launched in 2025 to offer the best hosting experience for your Reflex apps. We’re continuously improving the platform with new features and capabilities.\n\nReflex has new releases and features coming every week! Make sure to :star: star and :eyes: watch this repository to stay up to date.\n\n## Contributing\n\nWe welcome contributions of any size! Below are some good ways to get started in the Reflex community.\n\n- **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.\n- **GitHub Discussions**: A great way to talk about features you want added or things that are confusing/need clarification.\n- **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.\n\nWe 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)\n\n## All Thanks To Our Contributors:\n\n<a href=\"https://github.com/reflex-dev/reflex/graphs/contributors\">\n  <img src=\"https://contrib.rocks/image?repo=reflex-dev/reflex\" />\n</a>\n\n## License\n\nReflex is open-source and licensed under the [Apache License 2.0](https://raw.githubusercontent.com/reflex-dev/reflex/main/LICENSE).\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Security Policy\n\n## Supported Versions\n\n| Version  | Supported          |\n| -------- | ------------------ |\n| >= 0.7.0 | :white_check_mark: |\n\n## Reporting a Vulnerability\n\nPlease report any security vulnerabilities by using: https://github.com/reflex-dev/reflex/security/advisories/new\n"
  },
  {
    "path": "docker-example/README.md",
    "content": "# Reflex Docker Examples\n\nThis directory contains several examples of how to deploy Reflex apps using docker.\n\nIn all cases, ensure that your `requirements.txt` file is up to date and\nincludes the `reflex` package.\n\n## `simple-two-port`\n\nThe most basic production deployment exposes two HTTP ports and relies on an\nexisting load balancer to forward the traffic appropriately.\n\n## `simple-one-port`\n\nThis deployment exports the frontend statically and serves it via a single HTTP\nport using Caddy. This is useful for platforms that only support a single port\nor where running a node server in the container is undesirable.\n\n## `production-compose`\n\nThis deployment is intended for use with a standalone VPS that is only hosting a\nsingle Reflex app. It provides the entire stack in a single `compose.yaml`\nincluding a webserver, one or more backend instances, redis, and a postgres\ndatabase.\n\n## `production-app-platform`\n\nThis example deployment is intended for use with App hosting platforms, like\nAzure, AWS, or Google Cloud Run. It is the backend of the deployment, which\ndepends on a separately hosted redis instance and static frontend deployment.\n"
  },
  {
    "path": "docker-example/production-app-platform/.dockerignore",
    "content": ".web\n.git\n__pycache__/*\nDockerfile\nuploaded_files\n"
  },
  {
    "path": "docker-example/production-app-platform/Dockerfile",
    "content": "# This docker file is intended to be used with container hosting services\n#\n# After deploying this image, get the URL pointing to the backend service\n# and run API_URL=https://path-to-my-container.example.com reflex export frontend\n# then copy the contents of `frontend.zip` to your static file server (github pages, s3, etc).\n#\n# Azure Static Web App example:\n#    npx @azure/static-web-apps-cli deploy --env production --app-location .web/build/client\n#\n# For dynamic routes to function properly, ensure that 404s are redirected to /404 on the\n# static file host (for github pages, this works out of the box; remember to create .nojekyll).\n#\n# For azure static web apps, add `staticwebapp.config.json` to to `.web/build/client` with the following:\n#  {\n#     \"responseOverrides\": {\n#        \"404\": {\n#            \"rewrite\": \"/404.html\"\n#        }\n#     }\n#  }\n#\n# Note: many container hosting platforms require amd64 images, so when building on an M1 Mac\n# for example, pass `docker build --platform=linux/amd64 ...`\n\n# Stage 1: init\nFROM python:3.13 as init\n\nARG uv=/root/.local/bin/uv\n\n# Install `uv` for faster package bootstrapping\nADD --chmod=755 https://astral.sh/uv/install.sh /install.sh\nRUN /install.sh && rm /install.sh\n\n# Copy local context to `/app` inside container (see .dockerignore)\nWORKDIR /app\nCOPY . .\nRUN mkdir -p /app/data /app/uploaded_files\n\n# Create virtualenv which will be copied into final container\nENV VIRTUAL_ENV=/app/.venv\nENV PATH=\"$VIRTUAL_ENV/bin:$PATH\"\nRUN $uv venv\n\n# Install app requirements and reflex inside virtualenv\nRUN $uv pip install -r requirements.txt\n\n# Deploy templates and prepare app\nRUN reflex init\n\n# Stage 2: copy artifacts into slim image \nFROM python:3.13-slim\nWORKDIR /app\nRUN adduser --disabled-password --home /app reflex\nCOPY --chown=reflex --from=init /app /app\n# Install libpq-dev for psycopg (skip if not using postgres).\nRUN apt-get update -y && apt-get install -y libpq-dev && rm -rf /var/lib/apt/lists/*\nUSER reflex\nENV PATH=\"/app/.venv/bin:$PATH\" PYTHONUNBUFFERED=1\n\n# Needed until Reflex properly passes SIGTERM on backend.\nSTOPSIGNAL SIGKILL\n\n# Always apply migrations before starting the backend.\nCMD [ -d alembic ] && reflex db migrate; \\\n    exec reflex run --env prod --backend-only --backend-port ${PORT:-8000}\n"
  },
  {
    "path": "docker-example/production-app-platform/README.md",
    "content": "# production-app-platform\n\nThis example deployment is intended for use with App hosting platforms, like\nAzure, AWS, or Google Cloud Run.\n\n## Architecture\n\nThe production deployment consists of a few pieces:\n\n- Backend container - built by `Dockerfile` Runs the Reflex backend\n  service on port 8000 and is scalable to multiple instances.\n- Redis container - A single instance the standard `redis` docker image should\n  share private networking with the backend\n- Static frontend - HTML/CSS/JS files that are hosted via a CDN or static file\n  server. This is not included in the docker image.\n\n## Deployment\n\nThese general steps do not cover the specifics of each platform, but all platforms should\nsupport the concepts described here.\n\n### Vnet\n\nAll containers in the deployment should be hooked up to the same virtual private\nnetwork so they can access the redis service and optionally the database server.\nThe vnet should not be exposed to the internet, use an ingress rule to terminate\nTLS at the load balancer and forward the traffic to a backend service replica.\n\n### Redis\n\nDeploy a `redis` instance on the vnet.\n\n### Backend\n\nThe backend is built by the `Dockerfile` in this directory. When deploying the\nbackend, be sure to set REFLEX_REDIS_URL=redis://internal-redis-hostname to connect to\nthe redis service.\n\n### Ingress\n\nConfigure the load balancer for the app to forward traffic to port 8000 on the\nbackend service replicas. Most platforms will generate an ingress hostname\nautomatically. Make sure when you access the ingress endpoint on `/ping` that it\nreturns \"pong\", indicating that the backend is up an available.\n\n### Frontend\n\nThe frontend should be hosted on a static file server or CDN.\n\n**Important**: when exporting the frontend, set the API_URL environment variable\nto the ingress hostname of the backend service.\n\nIf you will host the frontend from a path other than the root, set the\n`REFLEX_FRONTEND_PATH` environment variable appropriately when exporting the frontend.\n\nMost static hosts will automatically use the `/404.html` file to handle 404\nerrors. _This is essential for dynamic routes to work correctly._ Ensure that\nmissing routes return the `/404.html` content to the user if this is not the\ndefault behavior.\n\n_For Github Pages_: ensure the file `.nojekyll` is present in the root of the repo\nto avoid special processing of underscore-prefix directories, like `_next`.\n\n## Platform Notes\n\nThe following sections are currently a work in progress and may be incomplete.\n\n### Azure\n\nIn the Azure load balancer, per-message deflate is not supported. Add the following\nto your `rxconfig.py` to workaround this issue.\n\n```python\nimport uvicorn.workers\n\nimport reflex as rx\n\n\nclass NoWSPerMessageDeflate(uvicorn.workers.UvicornH11Worker):\n    CONFIG_KWARGS = {\n        **uvicorn.workers.UvicornH11Worker.CONFIG_KWARGS,\n        \"ws_per_message_deflate\": False,\n    }\n\n\nconfig = rx.Config(\n    app_name=\"my_app\",\n    gunicorn_worker_class=\"rxconfig.NoWSPerMessageDeflate\",\n)\n```\n\n#### Persistent Storage\n\nIf you need to use a database or upload files, you cannot save them to the\ncontainer volume. Use Azure Files and mount it into the container at /app/uploaded_files.\n\n#### Resource Types\n\n- Create a new vnet with 10.0.0.0/16\n  - Create a new subnet for redis, database, and containers\n- Deploy redis as a Container Instances\n- Deploy database server as \"Azure Database for PostgreSQL\"\n  - Create a new database for the app\n  - Set db-url as a secret containing the db user/password connection string\n- Deploy Storage account for uploaded files\n  - Enable access from the vnet and container subnet\n  - Create a new file share\n  - In the environment, create a new files share (get the storage key)\n- Deploy the backend as a Container App\n  - Create a custom Container App Environment linked up to the same vnet as the redis container.\n  - Set REFLEX_REDIS_URL and REFLEX_DB_URL environment variables\n  - Add the volume from the environment\n  - Add the volume mount to the container\n- Deploy the frontend as a Static Web App\n"
  },
  {
    "path": "docker-example/production-compose/.dockerignore",
    "content": ".web\n.git\n__pycache__/*\nDockerfile\nCaddy.Dockerfile\ncompose.yaml\ncompose.*.yaml\nuploaded_files\n"
  },
  {
    "path": "docker-example/production-compose/Caddy.Dockerfile",
    "content": "FROM library/caddy\n\nCOPY --from=local/reflex-app /app/.web/build/client /srv\nADD Caddyfile /etc/caddy/Caddyfile"
  },
  {
    "path": "docker-example/production-compose/Caddyfile",
    "content": "{$DOMAIN}\n\nencode gzip\n\n@backend_routes path /_event/* /ping /_upload /_upload/*\nhandle @backend_routes {\n\treverse_proxy app:8000\n}\n\nroot * /srv\nroute {\n\ttry_files {path} {path}/ /404.html\n\tfile_server\n}\n"
  },
  {
    "path": "docker-example/production-compose/Dockerfile",
    "content": "# This docker file is intended to be used with docker compose to deploy a production\n# instance of a Reflex app.\n\n# Stage 1: init\nFROM python:3.13 as init\n\nARG uv=/root/.local/bin/uv\n\n# Install `uv` for faster package bootstrapping\nADD --chmod=755 https://astral.sh/uv/install.sh /install.sh\nRUN /install.sh && rm /install.sh\n\n# Copy local context to `/app` inside container (see .dockerignore)\nWORKDIR /app\nCOPY . .\nRUN mkdir -p /app/data /app/uploaded_files\n\n# Create virtualenv which will be copied into final container\nENV VIRTUAL_ENV=/app/.venv\nENV PATH=\"$VIRTUAL_ENV/bin:$PATH\"\nRUN $uv venv\n\n# Install app requirements and reflex inside virtualenv\nRUN $uv pip install -r requirements.txt\n\n# Deploy templates and prepare app\nRUN reflex init\n\n# Export static copy of frontend to /app/.web/build/client\nRUN reflex export --frontend-only --no-zip\n\n# Copy static files out of /app to save space in backend image\nRUN mv .web/build/client /tmp/client\nRUN rm -rf .web && mkdir -p .web/build\nRUN mv /tmp/client .web/build/client\n\n# Stage 2: copy artifacts into slim image \nFROM python:3.13-slim\nWORKDIR /app\nRUN adduser --disabled-password --home /app reflex\nCOPY --chown=reflex --from=init /app /app\n# Install libpq-dev for psycopg (skip if not using postgres).\nRUN apt-get update -y && apt-get install -y libpq-dev && rm -rf /var/lib/apt/lists/*\nUSER reflex\nENV PATH=\"/app/.venv/bin:$PATH\" PYTHONUNBUFFERED=1\n\n# Needed until Reflex properly passes SIGTERM on backend.\nSTOPSIGNAL SIGKILL\n\n# Always apply migrations before starting the backend.\nCMD [ -d alembic ] && reflex db migrate; \\\n    exec reflex run --env prod --backend-only\n"
  },
  {
    "path": "docker-example/production-compose/README.md",
    "content": "# production-compose\n\nThis example production deployment uses automatic TLS with Caddy serving static\nfiles for the frontend and proxying requests to both the frontend and backend.\nIt is intended for use with a standalone VPS that is only hosting a single\nReflex app.\n\nThe production app container (`Dockerfile`), builds and exports the frontend\nstatically (to be served by Caddy). The resulting image only runs the backend\nservice.\n\nThe `webserver` service, based on `Caddy.Dockerfile`, copies the static frontend\nand `Caddyfile` into the container to configure the reverse proxy routes that will\nforward requests to the backend service. Caddy will automatically provision TLS\nfor localhost or the domain specified in the environment variable `DOMAIN`.\n\nThis type of deployment should use less memory and be more performant since\nnodejs is not required at runtime.\n\n## Customize `Caddyfile` (optional)\n\nIf the app uses additional backend API routes, those should be added to the\n`@backend_routes` path matcher to ensure they are forwarded to the backend.\n\n## Build Reflex Production Service\n\nDuring build, set `DOMAIN` environment variable to the domain where the app will\nbe hosted! (Do not include http or https, it will always use https).\n\n**If `DOMAIN` is not provided, the service will default to `localhost`.**\n\n```bash\nDOMAIN=example.com docker compose build\n```\n\nThis will build both the `app` service from the `prod.Dockerfile` and the `webserver`\nservice via `Caddy.Dockerfile`.\n\n## Run Reflex Production Service\n\n```bash\nDOMAIN=example.com docker compose up\n```\n\nThe app should be available at the specified domain via HTTPS. Certificate\nprovisioning will occur automatically and may take a few minutes.\n\n### Data Persistence\n\nNamed docker volumes are used to persist the app database (`db-data`),\nuploaded_files (`upload-data`), and caddy TLS keys and certificates\n(`caddy-data`).\n\n## More Robust Deployment\n\nFor a more robust deployment, consider bringing the service up with\n`compose.prod.yaml` which includes postgres database and redis cache, allowing\nthe backend to run with multiple workers and service more requests.\n\n```bash\nDOMAIN=example.com docker compose -f compose.yaml -f compose.prod.yaml up -d\n```\n\nPostgres uses its own named docker volume for data persistence.\n\n## Admin Tools\n\nWhen needed, the services in `compose.tools.yaml` can be brought up, providing\ngraphical database administration (Adminer on http://localhost:8080) and a\nredis cache browser (redis-commander on http://localhost:8081). It is not recommended\nto deploy these services if they are not in active use.\n\n```bash\nDOMAIN=example.com docker compose -f compose.yaml -f compose.prod.yaml -f compose.tools.yaml up -d\n```\n"
  },
  {
    "path": "docker-example/production-compose/compose.prod.yaml",
    "content": "# Use this override file to run the app in prod mode with postgres and redis\n#     docker compose -f compose.yaml -f compose.prod.yaml up -d\nservices:\n  db:\n    image: postgres\n    restart: always\n    environment:\n      POSTGRES_PASSWORD: secret\n    volumes:\n      - postgres-data:/var/lib/postgresql/data\n\n  redis:\n    image: redis\n    restart: always\n\n  app:\n    environment:\n      REFLEX_DB_URL: postgresql+psycopg://postgres:secret@db/postgres\n      REFLEX_REDIS_URL: redis://redis:6379\n    depends_on:\n      - db\n      - redis\n\nvolumes:\n  postgres-data:\n"
  },
  {
    "path": "docker-example/production-compose/compose.tools.yaml",
    "content": "# Use this override file with `compose.prod.yaml` to run admin tools\n# for production services.\n#     docker compose -f compose.yaml -f compose.prod.yaml -f compose.tools.yaml up -d\nservices:\n  adminer:\n    image: adminer\n    ports:\n      - 8080:8080\n\n  redis-commander:\n    image: ghcr.io/joeferner/redis-commander:latest\n    environment:\n      - REDIS_HOSTS=local:redis:6379\n    ports:\n      - \"8081:8081\"\n\nvolumes:\n  redis-ui-settings:\n"
  },
  {
    "path": "docker-example/production-compose/compose.yaml",
    "content": "# Base compose file production deployment of reflex app with Caddy webserver\n# providing TLS termination and reverse proxying.\n#\n# See `compose.prod.yaml` for more robust and performant deployment option.\n#\n# During build and run, set environment DOMAIN pointing\n# to publicly accessible domain where app will be hosted\nservices:\n  app:\n    image: local/reflex-app\n    environment:\n      REFLEX_DB_URL: sqlite:///data/reflex.db\n    build:\n      context: .\n    volumes:\n      - db-data:/app/data\n      - upload-data:/app/uploaded_files\n    restart: always\n\n  webserver:\n    environment:\n      DOMAIN: ${DOMAIN:-localhost}\n    ports:\n      - 443:443\n      - 80:80 # For acme-challenge via HTTP.\n    build:\n      context: .\n      dockerfile: Caddy.Dockerfile\n    volumes:\n      - caddy-data:/root/.caddy\n    restart: always\n    depends_on:\n      - app\n\nvolumes:\n  # SQLite data\n  db-data:\n  # Uploaded files\n  upload-data:\n  # TLS keys and certificates\n  caddy-data:\n"
  },
  {
    "path": "docker-example/production-one-port/.dockerignore",
    "content": ".web\n!.web/bun.lockb\n!.web/package.json\n"
  },
  {
    "path": "docker-example/production-one-port/Caddyfile",
    "content": ":{$PORT}\n\nencode gzip\n\n@backend_routes path /_event/* /ping /_upload /_upload/*\nhandle @backend_routes {\n\treverse_proxy localhost:8000\n}\n\nroot * /srv\nroute {\n\ttry_files {path} {path}/ /404.html\n\tfile_server\n}\n"
  },
  {
    "path": "docker-example/production-one-port/Dockerfile",
    "content": "# This Dockerfile is used to deploy a single-container Reflex app instance\n# to services like Render, Railway, Heroku, GCP, and others.\n\n# If the service expects a different port, provide it here (f.e Render expects port 10000)\nARG PORT=8080\n# Only set for local/direct access. When TLS is used, the API_URL is assumed to be the same as the frontend.\nARG API_URL\n\n# It uses a reverse proxy to serve the frontend statically and proxy to backend\n# from a single exposed port, expecting TLS termination to be handled at the\n# edge by the given platform.\nFROM python:3.13 as builder\n\nRUN mkdir -p /app/.web\nRUN python -m venv /app/.venv\nENV PATH=\"/app/.venv/bin:$PATH\"\n\nWORKDIR /app\n\n# Install python app requirements and reflex in the container\nCOPY requirements.txt .\nRUN pip install -r requirements.txt\n\n# Install reflex helper utilities like bun/node\nCOPY rxconfig.py ./\nRUN reflex init\n\n# Install pre-cached frontend dependencies (if exist)\nCOPY *.web/bun.lockb *.web/package.json .web/\nRUN if [ -f .web/bun.lockb ]; then cd .web && ~/.local/share/reflex/bun/bin/bun install --frozen-lockfile; fi\n\n# Copy local context to `/app` inside container (see .dockerignore)\nCOPY . .\n\nARG PORT API_URL\n# Download other npm dependencies and compile frontend\nRUN REFLEX_API_URL=${API_URL:-http://localhost:$PORT} reflex export --loglevel debug --frontend-only --no-zip && mv .web/build/client/* /srv/ && rm -rf .web\n\n\n# Final image with only necessary files\nFROM python:3.13-slim\n\n# Install Caddy and redis server inside image\nRUN apt-get update -y && apt-get install -y caddy redis-server && rm -rf /var/lib/apt/lists/*\n\nARG PORT API_URL\nENV PATH=\"/app/.venv/bin:$PATH\" PORT=$PORT REFLEX_API_URL=${API_URL:-http://localhost:$PORT} REFLEX_REDIS_URL=redis://localhost PYTHONUNBUFFERED=1\n\nWORKDIR /app\nCOPY --from=builder /app /app\nCOPY --from=builder /srv /srv\n\n# Needed until Reflex properly passes SIGTERM on backend.\nSTOPSIGNAL SIGKILL\n\nEXPOSE $PORT\n\n# Apply migrations before starting the backend.\nCMD [ -d alembic ] && reflex db migrate; \\\n    caddy start && \\\n    redis-server --daemonize yes && \\\n    exec reflex run --env prod --backend-only\n"
  },
  {
    "path": "docker-example/production-one-port/README.md",
    "content": "# production-one-port\n\nThis docker deployment runs Reflex in prod mode, exposing a single HTTP port:\n\n- `8080` (`$PORT`) - Caddy server hosting the frontend statically and proxying requests to the backend.\n\nThe deployment also runs a local Redis server to store state for each user.\n\nConceptually it is similar to the `simple-one-port` example except it:\n\n- has layer caching for python, reflex, and node dependencies\n- uses multi-stage build to reduce the size of the final image\n\nUsing this method may be preferable for deploying in memory constrained\nenvironments, because it serves a static frontend export, rather than running\nthe Vite server via node.\n\n## Build\n\n```console\ndocker build -t reflex-production-one-port .\n```\n\n## Run\n\n```console\ndocker run -p 8080:8080 reflex-production-one-port\n```\n\nNote that this container has _no persistence_ and will lose all data when\nstopped. You can use bind mounts or named volumes to persist the database and\nuploaded_files directories as needed.\n\n## Usage\n\nThis container should be used with an existing load balancer or reverse proxy to\nterminate TLS.\n\nIt is also useful for deploying to simple app platforms, such as Render or Heroku.\n"
  },
  {
    "path": "docker-example/simple-one-port/.dockerignore",
    "content": ".web\n.git\n__pycache__/*\nDockerfile\nuploaded_files\n"
  },
  {
    "path": "docker-example/simple-one-port/Caddyfile",
    "content": ":{$PORT}\n\nencode gzip\n\n@backend_routes path /_event/* /ping /_upload /_upload/*\nhandle @backend_routes {\n\treverse_proxy localhost:8000\n}\n\nroot * /srv\nroute {\n\ttry_files {path} {path}/ /404.html\n\tfile_server\n}\n"
  },
  {
    "path": "docker-example/simple-one-port/Dockerfile",
    "content": "# This Dockerfile is used to deploy a single-container Reflex app instance\n# to services like Render, Railway, Heroku, GCP, and others.\n\n# It uses a reverse proxy to serve the frontend statically and proxy to backend\n# from a single exposed port, expecting TLS termination to be handled at the\n# edge by the given platform.\nFROM python:3.13\n\n# If the service expects a different port, provide it here (f.e Render expects port 10000)\nARG PORT=8080\n# Only set for local/direct access. When TLS is used, the API_URL is assumed to be the same as the frontend.\nARG API_URL\nENV PORT=$PORT REFLEX_API_URL=${API_URL:-http://localhost:$PORT} REFLEX_REDIS_URL=redis://localhost PYTHONUNBUFFERED=1\n\n# Install Caddy and redis server inside image\nRUN apt-get update -y && apt-get install -y caddy redis-server && rm -rf /var/lib/apt/lists/*\n\nWORKDIR /app\n\n# Copy local context to `/app` inside container (see .dockerignore)\nCOPY . .\n\n# Install app requirements and reflex in the container\nRUN pip install -r requirements.txt\n\n# Deploy templates and prepare app\nRUN reflex init\n\n# Download all npm dependencies and compile frontend\nRUN reflex export --frontend-only --no-zip && mv .web/build/client/* /srv/ && rm -rf .web\n\n# Needed until Reflex properly passes SIGTERM on backend.\nSTOPSIGNAL SIGKILL\n\nEXPOSE $PORT\n\n# Apply migrations before starting the backend.\nCMD [ -d alembic ] && reflex db migrate; \\\n    caddy start && \\\n    redis-server --daemonize yes && \\\n    exec reflex run --env prod --backend-only\n"
  },
  {
    "path": "docker-example/simple-one-port/README.md",
    "content": "# simple-one-port\n\nThis docker deployment runs Reflex in prod mode, exposing a single HTTP port:\n\n- `8080` (`$PORT`) - Caddy server hosting the frontend statically and proxying requests to the backend.\n\nThe deployment also runs a local Redis server to store state for each user.\n\nUsing this method may be preferable for deploying in memory constrained\nenvironments, because it serves a static frontend export, rather than running\nthe Vite server via node.\n\nFor platforms which only terminate TLS to a single port, this container can be\ndeployed instead of the `simple-two-port` example.\n\n## Build\n\n```console\ndocker build -t reflex-simple-one-port .\n```\n\n## Run\n\n```console\ndocker run -p 8080:8080 reflex-simple-one-port\n```\n\nNote that this container has _no persistence_ and will lose all data when\nstopped. You can use bind mounts or named volumes to persist the database and\nuploaded_files directories as needed.\n\n## Usage\n\nThis container should be used with an existing load balancer or reverse proxy to\nterminate TLS.\n\nIt is also useful for deploying to simple app platforms, such as Render or Heroku.\n"
  },
  {
    "path": "docker-example/simple-two-port/.dockerignore",
    "content": ".web\n.git\n__pycache__/*\nDockerfile\nuploaded_files\n"
  },
  {
    "path": "docker-example/simple-two-port/Dockerfile",
    "content": "# This Dockerfile is used to deploy a simple single-container Reflex app instance.\nFROM python:3.13\n\nRUN apt-get update && apt-get install -y redis-server && rm -rf /var/lib/apt/lists/*\nENV REFLEX_REDIS_URL=redis://localhost PYTHONUNBUFFERED=1\n\n# Copy local context to `/app` inside container (see .dockerignore)\nWORKDIR /app\nCOPY . .\n\n# Install app requirements and reflex in the container\nRUN pip install -r requirements.txt\n\n# Deploy templates and prepare app\nRUN reflex init\n\n# Download all npm dependencies and compile frontend\nRUN reflex export --frontend-only --no-zip\n\n# Needed until Reflex properly passes SIGTERM on backend.\nSTOPSIGNAL SIGKILL\n\n# Always apply migrations before starting the backend.\nCMD [ -d alembic ] && reflex db migrate; \\\n    redis-server --daemonize yes && \\\n    exec reflex run --env prod\n"
  },
  {
    "path": "docker-example/simple-two-port/README.md",
    "content": "# simple-two-port\n\nThis docker deployment runs Reflex in prod mode, exposing two HTTP ports:\n\n- `3000` - node server using optimized production build\n- `8000` - python gunicorn server hosting the Reflex backend\n\nThe deployment also runs a local Redis server to store state for each user.\n\n## Build\n\n```console\ndocker build -t reflex-simple-two-port .\n```\n\n## Run\n\n```console\ndocker run -p 3000:3000 -p 8000:8000 reflex-simple-two-port\n```\n\nNote that this container has _no persistence_ and will lose all data when\nstopped. You can use bind mounts or named volumes to persist the database and\nuploaded_files directories as needed.\n\n## Usage\n\nThis container should be used with an existing load balancer or reverse proxy to\nroute traffic to the appropriate port inside the container.\n\nFor example, the following Caddyfile can be used to terminate TLS and forward\ntraffic to the frontend and backend from outside the container.\n\n```\nmy-domain.com\n\nencode gzip\n\n@backend_routes path /_event/* /ping /_upload /_upload/*\nhandle @backend_routes {\n\treverse_proxy localhost:8000\n}\n\nreverse_proxy localhost:3000\n```\n"
  },
  {
    "path": "docs/DEBUGGING.md",
    "content": "# Debugging\n\nIt is possible to run Reflex apps in dev mode under a debugger.\n\n1. Run Reflex as a module: `python -m reflex run --env dev`\n2. Set current working directory to the dir containing `rxconfig.py`\n\n## VSCode\n\nThe following launch configuration can be used to interactively debug a Reflex\napp with breakpoints.\n\n```json\n{\n  \"version\": \"0.2.0\",\n  \"configurations\": [\n    {\n      \"name\": \"Reflex App\",\n      \"type\": \"python\",\n      \"request\": \"launch\",\n      \"module\": \"reflex\",\n      \"args\": \"run --env dev\",\n      \"justMyCode\": true,\n      \"cwd\": \"${fileDirname}/..\"\n    }\n  ]\n}\n```\n"
  },
  {
    "path": "docs/de/README.md",
    "content": "<div align=\"center\">\n<img src=\"/docs/images/reflex.svg\" alt=\"Reflex Logo\" width=\"300px\">\n<hr>\n\n### **✨ Performante, anpassbare Web-Apps in purem Python. Bereitstellung in Sekunden. ✨**\n\n[![PyPI version](https://badge.fury.io/py/reflex.svg)](https://badge.fury.io/py/reflex)\n![versions](https://img.shields.io/pypi/pyversions/reflex.svg)\n[![Documentation](https://img.shields.io/badge/Documentation%20-Introduction%20-%20%23007ec6)](https://reflex.dev/docs/getting-started/introduction)\n[![PyPI Downloads](https://static.pepy.tech/badge/reflex)](https://pepy.tech/projects/reflex)\n[![Discord](https://img.shields.io/discord/1029853095527727165?color=%237289da&label=Discord)](https://discord.gg/T5WSbC2YtQ)\n\n</div>\n\n---\n\n[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) | [Español](https://github.com/reflex-dev/reflex/blob/main/docs/es/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) | [Tiếng Việt](https://github.com/reflex-dev/reflex/blob/main/docs/vi/README.md)\n\n---\n\n# Reflex\n\nReflex ist eine Bibliothek, mit der man Full-Stack-Web-Applikationen in purem Python erstellen kann.\n\nWesentliche Merkmale:\n\n- **Pures Python** - Schreibe dein Front- und Backend in Python, es gibt also keinen Grund, JavaScript zu lernen.\n- **Volle Flexibilität** - Reflex ist einfach zu handhaben, kann aber auch für komplexe Anwendungen skaliert werden.\n- **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.\n\nAuf unserer [Architektur-Seite](https://reflex.dev/blog/2024-03-21-reflex-architecture/#the-reflex-architecture) erfahren Sie, wie Reflex unter der Haube funktioniert.\n\n## ⚙️ Installation\n\nÖffne ein Terminal und führe den folgenden Befehl aus (benötigt Python 3.10+):\n\n```bash\npip install reflex\n```\n\n## 🥳 Erstelle deine erste App\n\nDie Installation von `reflex` installiert auch das `reflex`-Kommandozeilen-Tool.\n\nTeste, ob die Installation erfolgreich war, indem du ein neues Projekt erstellst. (Ersetze `my_app_name` durch deinen Projektnamen):\n\n```bash\nmkdir my_app_name\ncd my_app_name\nreflex init\n```\n\nDieser Befehl initialisiert eine Vorlage in deinem neuen Verzeichnis.\n\nDu kannst diese App im Entwicklungsmodus ausführen:\n\n```bash\nreflex run\n```\n\nDu solltest deine App unter http://localhost:3000 laufen sehen.\n\nNun 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.\n\n## 🫧 Beispiel-App\n\nLass 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.\n\n&nbsp;\n\n<div align=\"center\">\n<img src=\"/docs/images/dalle.gif\" alt=\"Eine Benutzeroberfläche für DALL·E, die im Prozess der Bildgenerierung gezeigt wird.\" width=\"550\" />\n</div>\n\n&nbsp;\n\nHier ist der komplette Code, um dies zu erstellen. Das alles wird in einer Python-Datei gemacht!\n\n```python\nimport reflex as rx\nimport openai\n\nopenai_client = openai.OpenAI()\n\n\nclass State(rx.State):\n    \"\"\"Der Zustand der App.\"\"\"\n\n    prompt = \"\"\n    image_url = \"\"\n    processing = False\n    complete = False\n\n    def get_image(self):\n        \"\"\"Hole das Bild aus dem Prompt.\"\"\"\n        if self.prompt == \"\":\n            return rx.window_alert(\"Prompt Empty\")\n\n        self.processing, self.complete = True, False\n        yield\n        response = openai_client.images.generate(\n            prompt=self.prompt, n=1, size=\"1024x1024\"\n        )\n        self.image_url = response.data[0].url\n        self.processing, self.complete = False, True\n\n\ndef index():\n    return rx.center(\n        rx.vstack(\n            rx.heading(\"DALL-E\", font_size=\"1.5em\"),\n            rx.input(\n                placeholder=\"Enter a prompt..\",\n                on_blur=State.set_prompt,\n                width=\"25em\",\n            ),\n            rx.button(\n                \"Generate Image\",\n                on_click=State.get_image,\n                width=\"25em\",\n                loading=State.processing\n            ),\n            rx.cond(\n                State.complete,\n                rx.image(src=State.image_url, width=\"20em\"),\n            ),\n            align=\"center\",\n        ),\n        width=\"100%\",\n        height=\"100vh\",\n    )\n\n# Füge Zustand und Seite zur App hinzu.\napp = rx.App()\napp.add_page(index, title=\"Reflex:DALL-E\")\n```\n\n## Schauen wir uns das mal genauer an.\n\n<div align=\"center\">\n<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\" />\n</div>\n\n### **Reflex-UI**\n\nFangen wir mit der Benutzeroberfläche an.\n\n```python\ndef index():\n    return rx.center(\n        ...\n    )\n```\n\nDiese `index`-Funktion definiert das Frontend der App.\n\nWir verwenden verschiedene Komponenten wie `center`, `vstack`, `input` und `button`, um das Frontend zu erstellen. Komponenten können ineinander verschachtelt werden, um komplexe Layouts zu erstellen. Und du kannst Schlüsselwortargumente verwenden, um sie mit der vollen Kraft von CSS zu stylen.\n\nReflex wird mit [über 60 eingebauten Komponenten](https://reflex.dev/docs/library) geliefert, die dir den Einstieg erleichtern. Wir fügen aktiv weitere Komponenten hinzu, und es ist einfach, [eigene Komponenten zu erstellen](https://reflex.dev/docs/wrapping-react/overview/).\n\n### **State**\n\nReflex stellt deine Benutzeroberfläche als Funktion deines Zustands dar.\n\n```python\nclass State(rx.State):\n    \"\"\"Der Zustand der App.\"\"\"\n    prompt = \"\"\n    image_url = \"\"\n    processing = False\n    complete = False\n\n```\n\nDer Zustand definiert alle Variablen (genannt Vars) in einer App, die sich ändern können, und die Funktionen, die sie ändern.\n\nHier besteht der Zustand aus einem `prompt` und einer `image_url`. Es gibt auch die Booleans `processing` und `complete`, um anzuzeigen, wann der Button deaktiviert werden soll (während der Bildgenerierung) und wann das resultierende Bild angezeigt werden soll.\n\n### **Event-Handler**\n\n```python\ndef get_image(self):\n    \"\"\"Hole das Bild aus dem Prompt.\"\"\"\n    if self.prompt == \"\":\n        return rx.window_alert(\"Prompt Empty\")\n\n    self.processing, self.complete = True, False\n    yield\n    response = openai_client.images.generate(\n        prompt=self.prompt, n=1, size=\"1024x1024\"\n    )\n    self.image_url = response.data[0].url\n    self.processing, self.complete = False, True\n```\n\nInnerhalb des Zustands definieren wir Funktionen, die als Event-Handler bezeichnet werden und die Zustand-Variablen ändern. Event-Handler sind die Art und Weise, wie wir den Zustand in Reflex ändern können. Sie können als Reaktion auf Benutzeraktionen aufgerufen werden, z.B. beim Klicken auf eine Schaltfläche oder bei der Eingabe in ein Textfeld. Diese Aktionen werden als Ereignisse bezeichnet.\n\nUnsere DALL-E.-App hat einen Event-Handler, `get_image`, der dieses Bild von der OpenAI-API abruft. Die Verwendung von `yield` in der Mitte eines Event-Handlers führt zu einer Aktualisierung der Benutzeroberfläche. Andernfalls wird die Benutzeroberfläche am Ende des Ereignishandlers aktualisiert.\n\n### **Routing**\n\nSchließlich definieren wir unsere App.\n\n```python\napp = rx.App()\n```\n\nWir fügen der Indexkomponente eine Seite aus dem Stammverzeichnis der Anwendung hinzu. Wir fügen auch einen Titel hinzu, der in der Seitenvorschau/Browser-Registerkarte angezeigt wird.\n\n```python\napp.add_page(index, title=\"DALL-E\")\n```\n\nDu kannst eine mehrseitige App erstellen, indem du weitere Seiten hinzufügst.\n\n## 📑 Ressourcen\n\n<div align=\"center\">\n\n📑 [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; 🖼️ [Templates](https://reflex.dev/templates/) &nbsp; | &nbsp; 🛸 [Bereitstellung](https://reflex.dev/docs/hosting/deploy-quick-start) &nbsp;\n\n</div>\n\n## ✅ Status\n\nReflex wurde im Dezember 2022 unter dem Namen Pynecone gestartet.\n\nAb 2025 wurde [Reflex Cloud](https://cloud.reflex.dev) gestartet, um die beste Hosting-Erfahrung für Reflex-Apps zu bieten. Wir werden es weiterhin entwickeln und mehr Funktionen implementieren.\n\nReflex hat wöchentliche Veröffentlichungen und neue Features! Stelle sicher, dass du dieses Repository mit einem :star: Stern markierst und :eyes: beobachtest, um auf dem Laufenden zu bleiben.\n\n## Beitragende\n\nWir begrüßen Beiträge jeder Größe! Hier sind einige gute Möglichkeiten, um in der Reflex-Community zu starten.\n\n- **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.\n- **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.\n- **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.\n\nWir 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.\n\n## Vielen Dank an unsere Mitwirkenden:\n\n<a href=\"https://github.com/reflex-dev/reflex/graphs/contributors\">\n  <img src=\"https://contrib.rocks/image?repo=reflex-dev/reflex\" />\n</a>\n\n## Lizenz\n\nReflex ist Open-Source und lizenziert unter der [Apache License 2.0](/LICENSE).\n"
  },
  {
    "path": "docs/es/README.md",
    "content": "<div align=\"center\">\n<img src=\"/docs/images/reflex.svg\" alt=\"Reflex Logo\" width=\"300px\">\n<hr>\n\n### **✨ Aplicaciones web personalizables y eficaces en Python puro. Despliega tu aplicación en segundos. ✨**\n\n[![PyPI version](https://badge.fury.io/py/reflex.svg)](https://badge.fury.io/py/reflex)\n![Versiones](https://img.shields.io/pypi/pyversions/reflex.svg)\n[![Documentación](https://img.shields.io/badge/Documentation%20-Introduction%20-%20%23007ec6)](https://reflex.dev/docs/getting-started/introduction)\n[![PyPI Downloads](https://static.pepy.tech/badge/reflex)](https://pepy.tech/projects/reflex)\n[![Discord](https://img.shields.io/discord/1029853095527727165?color=%237289da&label=Discord)](https://discord.gg/T5WSbC2YtQ)\n\n</div>\n\n---\n\n[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) | [Español](https://github.com/reflex-dev/reflex/blob/main/docs/es/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) | [Tiếng Việt](https://github.com/reflex-dev/reflex/blob/main/docs/vi/README.md)\n\n---\n\n# Reflex\n\nReflex es una biblioteca para construir aplicaciones web full-stack en Python puro.\n\nCaracterísticas clave:\n\n- **Python puro** - Escribe el frontend y backend de tu aplicación en Python, sin necesidad de aprender JavaScript.\n- **Flexibilidad total** - Reflex es fácil para empezar, pero también puede escalar a aplicaciones complejas.\n- **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.\n\nConsulta 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.\n\n## ⚙️ Instalación\n\nAbra un terminal y ejecute (Requiere Python 3.10+):\n\n```bash\npip install reflex\n```\n\n## 🥳 Crea tu primera aplicación\n\nAl instalar `reflex` también se instala la herramienta de línea de comandos `reflex`.\n\nCompruebe que la instalación se ha realizado correctamente creando un nuevo proyecto. (Sustituye `my_app_name` por el nombre de tu proyecto):\n\n```bash\nmkdir my_app_name\ncd my_app_name\nreflex init\n```\n\nEste comando inicializa una plantilla en tu nuevo directorio.\n\nPuedes iniciar esta aplicación en modo de desarrollo:\n\n```bash\nreflex run\n```\n\nDebería ver su aplicación ejecutándose en http://localhost:3000.\n\nAhora 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.\n\n## 🫧 Ejemplo de una Aplicación\n\nVeamos 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.\n\n&nbsp;\n\n<div align=\"center\">\n<img src=\"/docs/images/dalle.gif\" alt=\"Un envoltorio frontend para DALL·E, mostrado en el proceso de generar una imagen.\" width=\"550\" />\n</div>\n\n&nbsp;\n\nAquí está el código completo para crear esto. ¡Todo esto se hace en un archivo de Python!\n\n```python\nimport reflex as rx\nimport openai\n\nopenai_client = openai.OpenAI()\n\nclass State(rx.State):\n    \"\"\"El estado de la aplicación\"\"\"\n    prompt = \"\"\n    image_url = \"\"\n    processing = False\n    complete = False\n\n    def get_image(self):\n        \"\"\"Obtiene la imagen desde la consulta.\"\"\"\n        if self.prompt == \"\":\n            return rx.window_alert(\"Prompt Empty\")\n\n        self.processing, self.complete = True, False\n        yield\n        response = openai_client.images.generate(\n            prompt=self.prompt, n=1, size=\"1024x1024\"\n        )\n        self.image_url = response.data[0].url\n        self.processing, self.complete = False, True\n\n\ndef index():\n    return rx.center(\n        rx.vstack(\n            rx.heading(\"DALL-E\", font_size=\"1.5em\"),\n            rx.input(\n                placeholder=\"Enter a prompt..\",\n                on_blur=State.set_prompt,\n                width=\"25em\",\n            ),\n            rx.button(\n                \"Generate Image\",\n                on_click=State.get_image,\n                width=\"25em\",\n                loading=State.processing\n            ),\n            rx.cond(\n                State.complete,\n                rx.image(src=State.image_url, width=\"20em\"),\n            ),\n            align=\"center\",\n        ),\n        width=\"100%\",\n        height=\"100vh\",\n    )\n\n# Agrega el estado y la pagina a la aplicación\napp = rx.App()\napp.add_page(index, title=\"Reflex:DALL-E\")\n```\n\n## Vamos a analizarlo.\n\n<div align=\"center\">\n<img src=\"/docs/images/dalle_colored_code_example.png\" alt=\"Explicando las diferencias entre las partes del backend y frontend de la aplicación DALL-E.\" width=\"900\" />\n</div>\n\n### **Reflex UI**\n\nEmpezemos por la interfaz de usuario (UI).\n\n```python\ndef index():\n    return rx.center(\n        ...\n    )\n```\n\nEsta función `index` define el frontend de la aplicación.\n\nUtilizamos diferentes componentes como `center`, `vstack`, `input`, y `button` para construir el frontend. Los componentes pueden anidarse unos dentro de otros para crear diseños complejos. Además, puedes usar argumentos de tipo keyword para darles estilo con toda la potencia de CSS.\n\nReflex viene con [mas de 60 componentes incorporados](https://reflex.dev/docs/library) para ayudarle a empezar. Estamos añadiendo activamente más componentes y es fácil [crear sus propios componentes](https://reflex.dev/docs/wrapping-react/overview/).\n\n### **Estado**\n\nReflex representa su UI como una función de su estado (State).\n\n```python\nclass State(rx.State):\n    \"\"\"El estado de la aplicación\"\"\"\n    prompt = \"\"\n    image_url = \"\"\n    processing = False\n    complete = False\n```\n\nEl estado (State) define todas las variables (llamadas vars) de una aplicación que pueden cambiar y las funciones que las modifican.\n\nAquí el estado se compone de `prompt` e `image_url`. También están los booleanos `processing` y `complete` para indicar cuando se deshabilite el botón (durante la generación de la imagen) y cuando se muestre la imagen resultante.\n\n### **Manejadores de Evento**\n\n```python\ndef get_image(self):\n    \"\"\"Obtiene la imagen desde la consulta.\"\"\"\n    if self.prompt == \"\":\n        return rx.window_alert(\"Prompt Empty\")\n\n    self.processing, self.complete = True, False\n    yield\n    response = openai_client.images.generate(\n        prompt=self.prompt, n=1, size=\"1024x1024\"\n    )\n    self.image_url = response.data[0].url\n    self.processing, self.complete = False, True\n```\n\nDentro del estado, definimos funciones llamadas manejadores de eventos que cambian las variables de estado. Los Manejadores de Evento son la manera que podemos modificar el estado en Reflex. Pueden ser activados en respuesta a las acciones del usuario, como hacer clic en un botón o escribir en un cuadro de texto. Estas acciones se llaman eventos.\n\nNuestra aplicación DALL·E tiene un manipulador de eventos, `get_image` que recibe esta imagen del OpenAI API. El uso de `yield` en medio de un manipulador de eventos hará que la UI se actualice. De lo contrario, la interfaz se actualizará al final del manejador de eventos.\n\n### **Enrutamiento**\n\nPor último, definimos nuestra app.\n\n```python\napp = rx.App()\n```\n\nAñadimos una página desde la raíz (root) de la aplicación al componente de índice (index). También agregamos un título que se mostrará en la vista previa de la página/pestaña del navegador.\n\n```python\napp.add_page(index, title=\"DALL-E\")\n```\n\nPuedes crear una aplicación multipágina añadiendo más páginas.\n\n## 📑 Recursos\n\n<div align=\"center\">\n\n📑 [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; 🖼️ [Templates](https://reflex.dev/templates/) &nbsp; | &nbsp; 🛸 [Despliegue](https://reflex.dev/docs/hosting/deploy-quick-start) &nbsp;\n\n</div>\n\n## ✅ Estado\n\nReflex se lanzó en diciembre de 2022 con el nombre de Pynecone.\n\nA partir de 2025, [Reflex Cloud](https://cloud.reflex.dev) se ha lanzado para proporcionar la mejor experiencia de alojamiento para aplicaciones Reflex. Continuaremos desarrollándolo e implementando más características.\n\n¡Reflex tiene nuevas versiones y características cada semana! Asegúrate de :star: marcar como favorito y :eyes: seguir este repositorio para mantenerte actualizado.\n\n## Contribuciones\n\n¡Aceptamos contribuciones de cualquier tamaño! A continuación encontrará algunas buenas formas de iniciarse en la comunidad Reflex.\n\n- **Ú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.\n- **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.\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.\n\nBuscamos colaboradores, sin importar su nivel o experiencia. Para contribuir consulta [CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)\n\n## Todo Gracias A Nuestros Contribuidores:\n\n<a href=\"https://github.com/reflex-dev/reflex/graphs/contributors\">\n  <img src=\"https://contrib.rocks/image?repo=reflex-dev/reflex\" />\n</a>\n\n## Licencia\n\nReflex es de código abierto y está licenciado bajo la [Apache License 2.0](/LICENSE).\n"
  },
  {
    "path": "docs/in/README.md",
    "content": "<div align=\"center\">\n<img src=\"/docs/images/reflex_dark.svg#gh-light-mode-only\" alt=\"Reflex लोगो\" width=\"300px\">\n<img src=\"/docs/images/reflex_light.svg#gh-dark-mode-only\" alt=\"Reflex लोगो\" width=\"300px\">\n\n<hr>\n\n### **✨ प्रदर्शनकारी, अनुकूलित वेब ऐप्स, शुद्ध Python में। सेकंडों में तैनात करें। ✨**\n\n[![PyPI version](https://badge.fury.io/py/reflex.svg)](https://badge.fury.io/py/reflex)\n![versions](https://img.shields.io/pypi/pyversions/reflex.svg)\n[![Documentation](https://img.shields.io/badge/Documentation%20-Introduction%20-%20%23007ec6)](https://reflex.dev/docs/getting-started/introduction)\n[![PyPI Downloads](https://static.pepy.tech/badge/reflex)](https://pepy.tech/projects/reflex)\n[![Discord](https://img.shields.io/discord/1029853095527727165?color=%237289da&label=Discord)](https://discord.gg/T5WSbC2YtQ)\n\n</div>\n\n---\n\n[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) | [Español](https://github.com/reflex-dev/reflex/blob/main/docs/es/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) | [Tiếng Việt](https://github.com/reflex-dev/reflex/blob/main/docs/vi/README.md)\n\n# Reflex\n\nReflex शुद्ध पायथन में पूर्ण-स्टैक वेब ऐप्स बनाने के लिए एक लाइब्रेरी है।\n\nमुख्य विशेषताएँ:\n\n- **शुद्ध पायथन** - अपने ऐप के फ्रंटएंड और बैकएंड को पायथन में लिखें, जावास्क्रिप्ट सीखने की जरूरत नहीं है।\n- **पूर्ण लचीलापन** - Reflex के साथ शुरुआत करना आसान है, लेकिन यह जटिल ऐप्स के लिए भी स्केल कर सकता है।\n- **तुरंत तैनाती** - बिल्डिंग के बाद, अपने ऐप को [एकल कमांड](https://reflex.dev/docs/hosting/deploy-quick-start/) के साथ तैनात करें या इसे अपने सर्वर पर होस्ट करें।\n\nReflex के अंदर के कामकाज को जानने के लिए हमारे [आर्किटेक्चर पेज](https://reflex.dev/blog/2024-03-21-reflex-architecture/#the-reflex-architecture) को देखें।\n\n## ⚙️ इंस्टॉलेशन (Installation)\n\nएक टर्मिनल खोलें और चलाएं (Python 3.10+ की आवश्यकता है):\n\n```bash\npip install reflex\n```\n\n## 🥳 अपना पहला ऐप बनाएं (Create your first App)\n\nreflex को इंस्टॉल करने से ही reflex कमांड लाइन टूल भी इंस्टॉल हो जाता है।\n\nसुनिश्चित करें कि इंस्टॉलेशन सफल थी, एक नया प्रोजेक्ट बनाकर इसे टेस्ट करें। ('my_app_name' की जगह अपने प्रोजेक्ट का नाम रखें):\n\n```bash\nmkdir my_app_name\ncd my_app_name\nreflex init\n```\n\nयह कमांड आपकी नयी डायरेक्टरी में एक टेम्पलेट ऐप को प्रारंभ करता है।\n\nआप इस ऐप को development मोड में चला सकते हैं:\n\n```bash\nreflex run\n```\n\nआपको http://localhost:3000 पर अपने ऐप को चलते हुए देखना चाहिए।\n\nअब आप my_app_name/my_app_name.py में source कोड को संशोधित कर सकते हैं। Reflex में तेज रिफ्रेश की सुविधा है, इसलिए जब आप अपनी कोड को सहेजते हैं, तो आप अपने बदलावों को तुरंत देख सकते हैं।\n\n## 🫧 उदाहरण ऐप (Example App)\n\nएक उदाहरण पर चलते हैं: [DALL·E](https://platform.openai.com/docs/guides/images/image-generation?context=node) से एक इमेज उत्पन्न करने के लिए UI। सरलता के लिए, हम सिर्फ [OpenAI API](https://platform.openai.com/docs/api-reference/authentication) को बुलाते हैं, लेकिन आप इसे ML मॉडल से बदल सकते हैं locally।\n\n&nbsp;\n\n<div align=\"center\">\n<img src=\"/docs/images/dalle.gif\" alt=\"DALL·E के लिए एक फ्रंटएंड रैपर, छवि उत्पन्न करने की प्रक्रिया में दिखाया गया।\" width=\"550\" />\n</div>\n\n&nbsp;\n\nयहाँ पर इसका पूरा कोड है जिससे यह बनाया जा सकता है। यह सब एक ही Python फ़ाइल में किया गया है!\n\n```python\nimport reflex as rx\nimport openai\n\nopenai_client = openai.OpenAI()\n\n\nclass State(rx.State):\n    \"\"\"The app state.\"\"\"\n\n    prompt = \"\"\n    image_url = \"\"\n    processing = False\n    complete = False\n\n    def get_image(self):\n        \"\"\"Get the image from the prompt.\"\"\"\n        if self.prompt == \"\":\n            return rx.window_alert(\"Prompt Empty\")\n\n        self.processing, self.complete = True, False\n        yield\n        response = openai_client.images.generate(\n            prompt=self.prompt, n=1, size=\"1024x1024\"\n        )\n        self.image_url = response.data[0].url\n        self.processing, self.complete = False, True\n\n\ndef index():\n    return rx.center(\n        rx.vstack(\n            rx.heading(\"DALL-E\", font_size=\"1.5em\"),\n            rx.input(\n                placeholder=\"Enter a prompt..\",\n                on_blur=State.set_prompt,\n                width=\"25em\",\n            ),\n            rx.button(\n                \"Generate Image\",\n                on_click=State.get_image,\n                width=\"25em\",\n                loading=State.processing\n            ),\n            rx.cond(\n                State.complete,\n                rx.image(src=State.image_url, width=\"20em\"),\n            ),\n            align=\"center\",\n        ),\n        width=\"100%\",\n        height=\"100vh\",\n    )\n\n# Add state and page to the app.\napp = rx.App()\napp.add_page(index, title=\"Reflex:DALL-E\")\n```\n\n## इसे समझते हैं।\n\n<div align=\"center\">\n<img src=\"/docs/images/dalle_colored_code_example.png\" alt=\"DALL-E ऐप के बैकएंड और फ्रंटएंड भागों के बीच के अंतर की व्याख्या करता है।\" width=\"900\" />\n</div>\n\n### **Reflex UI**\n\nहम UI के साथ शुरू करेंगे।\n\n```python\ndef index():\n    return rx.center(\n        ...\n    )\n```\n\nयह `index` फ़ंक्शन एप्लिकेशन की फ़्रंटएंड को परिभाषित करता है।\n\nहम फ़्रंटएंड बनाने के लिए `center`, `vstack`, `input`, और `button` जैसे विभिन्न components का उपयोग करते हैं। Components को एक-दूसरे के भीतर डाल सकते हैं विस्तारित लेआउट बनाने के लिए। और आप CSS की पूरी ताक़त के साथ इन्हें स्टाइल करने के लिए कीवर्ड आर्ग्यूमेंट (keyword args) का उपयोग कर सकते हैं।\n\nरिफ़्लेक्स के पास [60+ built-in components](https://reflex.dev/docs/library) हैं जो आपको शुरुआती मदद के लिए हैं। हम बहुत से components जोड़ रहे हैं, और अपने खुद के components बनाना भी आसान है। [create your own components](https://reflex.dev/docs/wrapping-react/overview/)\n\n### **स्टेट (State)**\n\nReflex आपके UI को आपकी स्टेट (state) के एक फ़ंक्शन के रूप में प्रस्तुत करता है।\n\n```python\nclass State(rx.State):\n    \"\"\"The app state.\"\"\"\n    prompt = \"\"\n    image_url = \"\"\n    processing = False\n    complete = False\n```\n\nस्टेट (state) ऐप में उन सभी वेरिएबल्स (vars) को परिभाषित करती है जो बदल सकती हैं और उन फ़ंक्शनों को जो उन्हें बदलते हैं।\n\nयहां स्टेट (state) में `prompt` और `image_url` शामिल हैं। प्रगति और छवि दिखाने के लिए `processing` और `complete` बूलियन भी हैं।\n\n### **इवेंट हैंडलर (Event Handlers)**\n\n```python\ndef get_image(self):\n    \"\"\"Get the image from the prompt.\"\"\"\n    if self.prompt == \"\":\n        return rx.window_alert(\"Prompt Empty\")\n\n    self.processing, self.complete = True, False\n    yield\n    response = openai_client.images.generate(\n        prompt=self.prompt, n=1, size=\"1024x1024\"\n    )\n    self.image_url = response.data[0].url\n    self.processing, self.complete = False, True\n```\n\nस्टेट (state) के अंदर, हम इवेंट हैंडलर्स (event handlers) को परिभाषित करते हैं जो स्टेट वेरिएबल्स को बदलते हैं। इवेंट हैंडलर्स (event handlers) से reflex में स्टेट (state) को मॉडिफ़ाय किया जा सकता हैं। इन्हें उपयोगकर्ता क्रियाओं (user actions) के प्रति प्रतिक्रिया (response) के रूप में बुलाया जा सकता है, जैसे कि बटन को क्लिक करना या टेक्स्ट बॉक्स में टाइप करना। इन क्रियाओं को इवेंट्स (events) कहा जाता है।\n\nहमारे DALL·E. ऐप में एक इवेंट हैंडलर `get_image` है जिससे यह OpenAI API से इमेज प्राप्त करता है। इवेंट हैंडलर में `yield` का उपयोग करने कि वजह से UI अपडेट हो जाएगा। अन्यथा UI इवेंट हैंडलर के अंत में अपडेट होगा।\n\n### **रूटिंग (Routing)**\n\nआखिरकार, हम अपने एप्लिकेशन को परिभाषित करते हैं।\n\n```python\napp = rx.App()\n```\n\nहम अपने एप्लिकेशन के रूट से इंडेक्स कॉम्पोनेंट तक एक पेज को जोड़ते हैं। हम एक शीर्षक भी जोड़ते हैं जो पेज प्रीव्यू/ब्राउज़र टैब में दिखाई देगा।\n\n```python\napp.add_page(index, title=\"DALL-E\")\n```\n\nआप और पेज जोड़कर एक मल्टी-पेज एप्लिकेशन बना सकते हैं।\n\n## 📑 संसाधन (Resources)\n\n<div align=\"center\">\n\n📑 [दस्तावेज़](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/templates/) &nbsp; | &nbsp; 🛸 [तैनाती](https://reflex.dev/docs/hosting/deploy-quick-start) &nbsp;\n\n</div>\n\n## ✅ स्टेटस (Status)\n\nReflex दिसंबर 2022 में Pynecone नाम से शुरू हुआ।\n\n2025 की शुरुआत से, [Reflex Cloud](https://cloud.reflex.dev) लॉन्च किया गया है जो Reflex ऐप्स के लिए सर्वोत्तम होस्टिंग अनुभव प्रदान करता है। हम इसे विकसित करना और अधिक सुविधाएँ लागू करना जारी रखेंगे।\n\nReflex में हर सप्ताह नए रिलीज़ और फीचर्स आ रहे हैं! सुनिश्चित करें कि :star: स्टार और :eyes: वॉच इस रेपोजिटरी को अपडेट रहने के लिए।\n\n## (योगदान) Contributing\n\nहम हर तरह के योगदान का स्वागत करते हैं! रिफ्लेक्स कम्यूनिटी में शुरुआत करने के कुछ अच्छे तरीके नीचे दिए गए हैं।\n\n- **Join Our Discord** (डिस्कॉर्ड सर्वर से जुड़ें): हमारा [Discord](https://discord.gg/T5WSbC2YtQ) रिफ्लेक्स प्रोजेक्ट पर सहायता प्राप्त करने और आप कैसे योगदान दे सकते हैं, इस पर चर्चा करने के लिए सबसे अच्छी जगह है।\n- **GitHub Discussions** (गिटहब चर्चाएँ): उन सुविधाओं के बारे में बात करने का एक शानदार तरीका जिन्हें आप जोड़ना चाहते हैं या ऐसी चीज़ें जो भ्रमित करने वाली हैं/स्पष्टीकरण की आवश्यकता है।\n- **GitHub Issues** (गिटहब समस्याएं): [Issues](https://github.com/reflex-dev/reflex/issues) बग की रिपोर्ट करने का एक शानदार तरीका है। इसके अतिरिक्त, आप किसी मौजूदा समस्या को हल करने का प्रयास कर सकते हैं और एक पीआर सबमिट कर सकते हैं।\n\nहम सक्रिय रूप से योगदानकर्ताओं की तलाश कर रहे हैं, चाहे आपका कौशल स्तर या अनुभव कुछ भी हो। योगदान करने के लिए [CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md) देखें।\n\n## हमारे सभी योगदानकर्ताओं का धन्यवाद:\n\n<a href=\"https://github.com/reflex-dev/reflex/graphs/contributors\">\n  <img src=\"https://contrib.rocks/image?repo=reflex-dev/reflex\" />\n</a>\n\n## लाइसेंस (License)\n\nरिफ्लेक्स ओपन-सोर्स है और [अपाचे लाइसेंस 2.0](/LICENSE) के तहत लाइसेंस प्राप्त है।\n"
  },
  {
    "path": "docs/it/README.md",
    "content": "<div align=\"center\">\n<img src=\"/docs/images/reflex.svg\" alt=\"Reflex Logo\" width=\"300px\">\n<hr>\n\n### **✨ App web performanti e personalizzabili in puro Python. Distribuisci in pochi secondi. ✨**\n\n[![PyPI version](https://badge.fury.io/py/reflex.svg)](https://badge.fury.io/py/reflex)\n![versions](https://img.shields.io/pypi/pyversions/reflex.svg)\n[![Documentaiton](https://img.shields.io/badge/Documentation%20-Introduction%20-%20%23007ec6)](https://reflex.dev/docs/getting-started/introduction)\n[![PyPI Downloads](https://static.pepy.tech/badge/reflex)](https://pepy.tech/projects/reflex)\n[![Discord](https://img.shields.io/discord/1029853095527727165?color=%237289da&label=Discord)](https://discord.gg/T5WSbC2YtQ)\n\n</div>\n\n---\n\n[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) | [Español](https://github.com/reflex-dev/reflex/blob/main/docs/es/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) | [Tiếng Việt](https://github.com/reflex-dev/reflex/blob/main/docs/vi/README.md)\n\n---\n\n# Reflex\n\nReflex è una libreria per sviluppare applicazioni web full-stack in Python puro.\n\nCaratteristiche principali:\n\n- **Python Puro** - Scrivi il frontend e il backend della tua app interamente in Python, senza bisogno di imparare Javascript.\n- **Flessibilità Totale** - Reflex è facile da iniziare, ma può anche gestire app complesse.\n- **Distribuzione Istantanea** - Dopo lo sviluppo, distribuisci la tua app con un [singolo comando](https://reflex.dev/docs/hosting/deploy-quick-start/) o ospitala sul tuo server.\n\nConsulta la nostra [pagina di architettura](https://reflex.dev/blog/2024-03-21-reflex-architecture/#the-reflex-architecture) per scoprire come funziona Reflex sotto il cofano.\n\n## ⚙️ Installazione\n\nApri un terminale ed esegui (Richiede Python 3.10+):\n\n```bash\npip install reflex\n```\n\n## 🥳 Crea la tua prima app\n\nInstallando `reflex` si installa anche lo strumento da riga di comando `reflex`.\n\nVerifica che l'installazione sia stata eseguita correttamente creando un nuovo progetto. (Sostituisci `nome_app` con il nome del tuo progetto):\n\n```bash\nmkdir nome_app\ncd nome_app\nreflex init\n```\n\nQuesto comando inizializza un'app template nella tua nuova directory.\n\nPuoi eseguire questa app in modalità sviluppo con:\n\n```bash\nreflex run\n```\n\nDovresti vedere la tua app in esecuzione su http://localhost:3000.\n\nOra puoi modificare il codice sorgente in `nome_app/nome_app.py`. Reflex offre aggiornamenti rapidi, così puoi vedere le tue modifiche istantaneamente quando salvi il tuo codice.\n\n## 🫧 Esempio App\n\nEsaminiamo un esempio: creare un'interfaccia utente per la generazione di immagini attorno a [DALL·E](https://platform.openai.com/docs/guides/images/image-generation?context=node). Per semplicità, chiamiamo semplicemente l'[API OpenAI](https://platform.openai.com/docs/api-reference/authentication), ma potresti sostituirla con un modello ML eseguito localmente.\n\n&nbsp;\n\n<div align=\"center\">\n<img src=\"/docs/images/dalle.gif\" alt=\"Un wrapper frontend per DALL·E, mostrato nel processo di generazione di un'immagine.\" width=\"550\" />\n</div>\n\n&nbsp;\n\nEcco il codice completo per crearlo. Tutto fatto in un unico file Python!\n\n```python\nimport reflex as rx\nimport openai\n\nopenai_client = openai.OpenAI()\n\n\nclass State(rx.State):\n    \"\"\"Lo stato dell'app.\"\"\"\n\n    prompt = \"\"\n    image_url = \"\"\n    processing = False\n    complete = False\n\n    def get_image(self):\n        \"\"\"Ottieni l'immagine dal prompt.\"\"\"\n        if self.prompt == \"\":\n            return rx.window_alert(\"Prompt Vuoto\")\n\n        self.processing, self.complete = True, False\n        yield\n        response = openai_client.images.generate(\n            prompt=self.prompt, n=1, size=\"1024x1024\"\n        )\n        self.image_url = response.data[0].url\n        self.processing, self.complete = False, True\n\n\ndef index():\n    return rx.center(\n        rx.vstack(\n            rx.heading(\"DALL-E\", font_size=\"1.5em\"),\n            rx.input(\n                placeholder=\"Inserisci un prompt..\",\n                on_blur=State.set_prompt,\n                width=\"25em\",\n            ),\n            rx.button(\n                \"Genera Immagine\",\n                on_click=State.get_image,\n                width=\"25em\",\n                loading=State.processing\n            ),\n            rx.cond(\n                State.complete,\n                rx.image(src=State.image_url, width=\"20em\"),\n            ),\n            align=\"center\",\n        ),\n        width=\"100%\",\n        height=\"100vh\",\n    )\n\n# Aggiungi stato e pagina all'app.\napp = rx.App()\napp.add_page(index, title=\"Reflex:DALL-E\")\n```\n\n## Analizziamolo.\n\n<div align=\"center\">\n<img src=\"/docs/images/dalle_colored_code_example.png\" alt=\"Spiegazione delle differenze tra le parti backend e frontend dell'app DALL-E.\" width=\"900\" />\n</div>\n\n### **Reflex UI**\n\nCominciamo con l'UI.\n\n```python\ndef index():\n    return rx.center(\n        ...\n    )\n```\n\nQuesta funzione `index` definisce il frontend dell'app.\n\nUtilizziamo diversi componenti come `center`, `vstack`, `input`, e `button` per costruire il frontend. I componenti possono essere annidati gli uni negli altri per creare layout complessi. E puoi utilizzare argomenti chiave per stilizzarli con tutta la potenza di CSS.\n\nReflex offre [più di 60 componenti integrati](https://reflex.dev/docs/library) per aiutarti a iniziare. Stiamo attivamente aggiungendo più componenti ed è facile [creare i tuoi componenti](https://reflex.dev/docs/wrapping-react/overview/).\n\n### **Stato (State)**\n\nReflex rappresenta la tua UI come una funzione del tuo stato.\n\n```python\nclass State(rx.State):\n    \"\"\"Lo stato dell'app.\"\"\"\n    prompt = \"\"\n    image_url = \"\"\n    processing = False\n    complete = False\n\n```\n\nLo stato definisce tutte le variabili (chiamate vars) in un'app che possono cambiare e le funzioni che le cambiano.\n\nQui lo stato è composto da un `prompt` e `image_url`. Ci sono anche i booleani `processing` e `complete` per indicare quando disabilitare il pulsante (durante la generazione dell'immagine) e quando mostrare l'immagine risultante.\n\n### **Gestori di Eventi (Event Handlers)**\n\n```python\ndef get_image(self):\n    \"\"\"Ottieni l'immagine dal prompt.\"\"\"\n    if self.prompt == \"\":\n        return rx.window_alert(\"Prompt Vuoto\")\n\n    self.processing, self.complete = True, False\n    yield\n    response = openai_client.images.generate(\n        prompt=self.prompt, n=1, size=\"1024x1024\"\n    )\n    self.image_url = response.data[0].url\n    self.processing, self.complete = False, True\n```\n\nDentro 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.\n\nLa 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.\n\n### **Instradamento (Routing)**\n\nInfine, definiamo la nostra app.\n\n```python\napp = rx.App()\n```\n\nAggiungiamo una pagina dalla radice dell'app al componente dell'indice. Aggiungiamo anche un titolo che apparirà nell'anteprima della pagina/scheda del browser.\n\n```python\napp.add_page(index, title=\"DALL-E\")\n```\n\nPuoi creare un'app multi-pagina aggiungendo altre pagine.\n\n## 📑 Risorse\n\n<div align=\"center\">\n\n📑 [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; 🖼️ [Templates](https://reflex.dev/templates/) &nbsp; | &nbsp; 🛸 [Distribuzione](https://reflex.dev/docs/hosting/deploy-quick-start) &nbsp;\n\n</div>\n\n## ✅ Stato\n\nReflex è stato lanciato nel dicembre 2022 con il nome Pynecone.\n\nA partire dal 2025, [Reflex Cloud](https://cloud.reflex.dev) è stato lanciato per fornire la migliore esperienza di hosting per le app Reflex. Continueremo a svilupparlo e implementare più funzionalità.\n\nReflex ha nuove versioni e funzionalità in arrivo ogni settimana! Assicurati di :star: mettere una stella e :eyes: osservare questa repository per rimanere aggiornato.\n\n## Contribuire\n\nDiamo il benvenuto a contributi di qualsiasi dimensione! Di seguito sono alcuni modi per iniziare nella comunità Reflex.\n\n- **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.\n- **Discussioni su GitHub**: Un ottimo modo per parlare delle funzionalità che desideri aggiungere o di cose che creano confusione o necessitano chiarimenti.\n- **GitHub Issues**: Le [Issues](https://github.com/reflex-dev/reflex/issues) sono un ottimo modo per segnalare bug. Inoltre, puoi provare a risolvere un problema esistente e inviare un PR.\n\nStiamo attivamente cercando collaboratori, indipendentemente dal tuo livello di abilità o esperienza. Per contribuire, consulta [CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)\n\n## Un Grazie a Tutti i Nostri Contributori:\n\n<a href=\"https://github.com/reflex-dev/reflex/graphs/contributors\">\n  <img src=\"https://contrib.rocks/image?repo=reflex-dev/reflex\" />\n</a>\n\n## Licenza\n\nReflex è open-source e rilasciato sotto la [Licenza Apache 2.0](/LICENSE).\n"
  },
  {
    "path": "docs/ja/README.md",
    "content": "<div align=\"center\">\n<img src=\"/docs/images/reflex.svg\" alt=\"Reflex Logo\" width=\"300px\">\n<hr>\n\n### **✨ 即時デプロイが可能な、Pure Python で作ったパフォーマンスと汎用性が高い Web アプリケーション ✨**\n\n[![PyPI version](https://badge.fury.io/py/reflex.svg)](https://badge.fury.io/py/reflex)\n![versions](https://img.shields.io/pypi/pyversions/reflex.svg)\n[![Documentation](https://img.shields.io/badge/Documentation%20-Introduction%20-%20%23007ec6)](https://reflex.dev/docs/getting-started/introduction)\n[![PyPI Downloads](https://static.pepy.tech/badge/reflex)](https://pepy.tech/projects/reflex)\n[![Discord](https://img.shields.io/discord/1029853095527727165?color=%237289da&label=Discord)](https://discord.gg/T5WSbC2YtQ)\n\n</div>\n\n---\n\n[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) | [Español](https://github.com/reflex-dev/reflex/blob/main/docs/es/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) | [Tiếng Việt](https://github.com/reflex-dev/reflex/blob/main/docs/vi/README.md)\n\n---\n\n# Reflex\n\nReflex は Python のみでフルスタック Web アプリケーションを作成できるライブラリです。\n\n主な特徴:\n\n- **Pure Python** - Web アプリケーションのフロントエンドとバックエンドを Python のみで実装できるため、Javascript を学ぶ必要がありません。\n- **高い柔軟性** - Reflex は簡単に始められて、複雑なアプリケーションまで作成できます。\n- **即時デプロイ** - ビルド後、すぐにデプロイが可能です。[単純な CLI コマンド](https://reflex.dev/docs/hosting/deploy-quick-start/)を使ったアプリケーションのデプロイや、自身のサーバーへのホストができます。\n\nReflex がどのように動作しているかを知るには、[アーキテクチャページ](https://reflex.dev/blog/2024-03-21-reflex-architecture/#the-reflex-architecture)をご覧ください。\n\n## ⚙️ インストール\n\nターミナルを開いて以下のコマンドを実行してください。（Python 3.10 以上が必要です。）:\n\n```bash\npip install reflex\n```\n\n## 🥳 最初のアプリケーションを作ろう\n\n`reflex`をインストールすると、`reflex`の CLI ツールが自動でインストールされます。\n\n新しいプロジェクトを作成して、インストールが成功しているかを確認しましょう。（`my_app_name`を自身のプロジェクト名に書き換えて実行ください。）:\n\n```bash\nmkdir my_app_name\ncd my_app_name\nreflex init\n```\n\n上記のコマンドを実行すると、新しいフォルダにテンプレートアプリを作成します。\n\n下記のコマンドを実行すると、開発モードでアプリを開始します。\n\n```bash\nreflex run\n```\n\nhttp://localhost:3000 にアクセスしてアプリの動作を見ることができます。\n\n`my_app_name/my_app_name.py`のソースコードを編集してみましょう！Reflex は fast refresh なので、ソースを保存した直後に変更が Web ページに反映されます。\n\n## 🫧 実装例\n\n実装例を見てみましょう: [DALL·E](https://platform.openai.com/docs/guides/images/image-generation?context=node)を中心とした画像生成 UI を作成しました。説明を簡単にするためにここでは[OpenAI API](https://platform.openai.com/docs/api-reference/authentication)を呼んでいますが、ローカルで動作している機械学習モデルに置き換えることも可能です。\n\n&nbsp;\n\n<div align=\"center\">\n<img src=\"/docs/images/dalle.gif\" alt=\"DALL·Eのフロントエンドラッパーです。画像を生成している過程を表示しています。\" width=\"550\" />\n</div>\n\n&nbsp;\n\n画像生成 UI のソースコードの全貌を見てみましょう。下記のように、単一の Python ファイルで作れます！\n\n```python\nimport reflex as rx\nimport openai\n\nopenai_client = openai.OpenAI()\n\n\nclass State(rx.State):\n    \"\"\"アプリのステート\"\"\"\n\n    prompt = \"\"\n    image_url = \"\"\n    processing = False\n    complete = False\n\n    def get_image(self):\n        \"\"\"プロンプトからイメージを取得する\"\"\"\n        if self.prompt == \"\":\n            return rx.window_alert(\"Prompt Empty\")\n\n        self.processing, self.complete = True, False\n        yield\n        response = openai_client.images.generate(\n            prompt=self.prompt, n=1, size=\"1024x1024\"\n        )\n        self.image_url = response.data[0].url\n        self.processing, self.complete = False, True\n\n\ndef index():\n    return rx.center(\n        rx.vstack(\n            rx.heading(\"DALL-E\", font_size=\"1.5em\"),\n            rx.input(\n                placeholder=\"Enter a prompt..\",\n                on_blur=State.set_prompt,\n                width=\"25em\",\n            ),\n            rx.button(\n                \"Generate Image\",\n                on_click=State.get_image,\n                width=\"25em\",\n                loading=State.processing\n            ),\n            rx.cond(\n                State.complete,\n                rx.image(src=State.image_url, width=\"20em\"),\n            ),\n            align=\"center\",\n        ),\n        width=\"100%\",\n        height=\"100vh\",\n    )\n\n# ステートとページをアプリに追加\napp = rx.App()\napp.add_page(index, title=\"Reflex:DALL-E\")\n```\n\n## それぞれの実装を見てみましょう\n\n<div align=\"center\">\n<img src=\"/docs/images/dalle_colored_code_example.png\" alt=\"DALL-E appのフロントエンドとバックエンドのパーツの違いを説明しています。\" width=\"900\" />\n</div>\n\n### **Reflex UI**\n\nUI から見てみましょう。\n\n```python\ndef index():\n    return rx.center(\n        ...\n    )\n```\n\n`index`関数において、アプリのフロントエンドを定義しています。\n\nフロントエンドを実装するにあたり、`center`、`vstack`、`input`、`button`など異なるコンポーネントを使用しています。コンポーネントはお互いにネストが可能であり、複雑なレイアウトを作成できます。また、keyword args を使うことで、CSS の機能をすべて使ったスタイルが可能です。\n\nReflex は[60 を超える内臓コンポーネント](https://reflex.dev/docs/library)があるため、すぐに始められます。私たちは、積極的にコンポーネントを追加していますが、簡単に[自身のコンポーネントを追加](https://reflex.dev/docs/wrapping-react/overview/)することも可能です。\n\n### **ステート**\n\nReflex はステートの関数を用いて UI を表示します。\n\n```python\nclass State(rx.State):\n    \"\"\"アプリのステート\"\"\"\n    prompt = \"\"\n    image_url = \"\"\n    processing = False\n    complete = False\n\n```\n\nステートでは、アプリで変更が可能な全ての変数（vars と呼びます）と、vars の変更が可能な関数を定義します。\n\nこの例では、ステートを`prompt`と`image_url`で構成しています。そして、ブール型の`processing`と`complete`を用いて、ボタンを無効にするタイミング（画像生成中）や生成された画像を表示するタイミングを示しています。\n\n### **イベントハンドラ**\n\n```python\ndef get_image(self):\n    \"\"\"プロンプトからイメージを取得する\"\"\"\n    if self.prompt == \"\":\n        return rx.window_alert(\"Prompt Empty\")\n\n    self.processing, self.complete = True, False\n    yield\n    response = openai_client.images.generate(\n        prompt=self.prompt, n=1, size=\"1024x1024\"\n    )\n    self.image_url = response.data[0].url\n    self.processing, self.complete = False, True\n```\n\nステートにおいて、ステートの vars を変更できるイベントハンドラ関数を定義しています。イベントハンドラは Reflex において、ステートの vars を変更する方法です。ボタンクリックやテキストボックスの入力など、ユーザのアクションに応じてイベントハンドラが呼ばれます。\n\nDALL·E.アプリには、OpenAI API からイメージを取得する`get_image`関数があります。イベントハンドラの最後で UI の更新がかかるため、関数の途中に`yield`を入れることで先に UI を更新しています。\n\n### **ルーティング**\n\n最後に、アプリを定義します。\n\n```python\napp = rx.App()\n```\n\nアプリにページを追加し、ドキュメントルートを index コンポーネントにルーティングしています。更に、ページのプレビューやブラウザタブに表示されるタイトルを記載しています。\n\n```python\napp.add_page(index, title=\"DALL-E\")\n```\n\nページを追加することで、マルチページアプリケーションを作成できます。\n\n## 📑 リソース\n\n<div align=\"center\">\n\n📑 [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;\n\n</div>\n\n## ✅ ステータス\n\n2022 年 12 月に、Reflex は Pynecone という名前でローンチしました。\n\n2025 年から [Reflex Cloud](https://cloud.reflex.dev) がローンチされ、Reflex アプリケーションの最高のホスティング体験を提供しています。私たちは引き続き開発を続け、より多くの機能を実装していきます。\n\nReflex は毎週、新しいリリースや機能追加を行っています！最新情報を逃さないために、 :star: Star や :eyes: Watch をお願いします。\n\n## コントリビュート\n\n様々なサイズのコントリビュートを歓迎しています！Reflex コミュニティに入るための方法を、いくつかリストアップします。\n\n- **Discord に参加**: [Discord](https://discord.gg/T5WSbC2YtQ)は、Reflex プロジェクトの相談や、コントリビュートについての話し合いをするための、最適な場所です。\n- **GitHub Discussions**: GitHub Discussions では、追加したい機能や、複雑で解明が必要な事柄についての議論に適している場所です。\n- **GitHub Issues**: [Issues](https://github.com/reflex-dev/reflex/issues)はバグの報告に適している場所です。また、課題を解決した PR のサブミットにチャレンジしていただくことも、可能です。\n\nスキルや経験に関わらず、私たちはコントリビュータを積極的に探しています。コントリビュートするために、[CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)をご覧ください。\n\n## 私たちのコントリビュータに感謝！:\n\n<a href=\"https://github.com/reflex-dev/reflex/graphs/contributors\">\n  <img src=\"https://contrib.rocks/image?repo=reflex-dev/reflex\" />\n</a>\n\n## ライセンス\n\nReflex はオープンソースであり、[Apache License 2.0](/LICENSE)に基づいてライセンス供与されます。\n"
  },
  {
    "path": "docs/kr/README.md",
    "content": "<div align=\"center\">\n<img src=\"/docs/images/reflex.svg\" alt=\"Reflex Logo\" width=\"300px\">\n<hr>\n\n### **✨ 순수 Python으로 고성능 사용자 정의 웹앱을 만들어 보세요. 몇 초만에 배포 가능합니다. ✨**\n\n[![PyPI version](https://badge.fury.io/py/reflex.svg)](https://badge.fury.io/py/reflex)\n![versions](https://img.shields.io/pypi/pyversions/reflex.svg)\n[![Documentation](https://img.shields.io/badge/Documentation%20-Introduction%20-%20%23007ec6)](https://reflex.dev/docs/getting-started/introduction)\n[![PyPI Downloads](https://static.pepy.tech/badge/reflex)](https://pepy.tech/projects/reflex)\n[![Discord](https://img.shields.io/discord/1029853095527727165?color=%237289da&label=Discord)](https://discord.gg/T5WSbC2YtQ)\n\n</div>\n\n---\n\n[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) | [Español](https://github.com/reflex-dev/reflex/blob/main/docs/es/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) | [Tiếng Việt](https://github.com/reflex-dev/reflex/blob/main/docs/vi/README.md)\n\n---\n\n# Reflex\n\nReflex는 순수 Python으로 풀스택 웹 앱을 구축하기 위한 라이브러리입니다.\n\n주요 기능:\n\n- **순수 Python** - 앱의 프론트엔드와 백엔드를 모두 Python으로 작성하며, Javascript를 배울 필요가 없습니다.\n- **완전한 유연성** - Reflex는 시작하기 쉽지만, 복잡한 앱으로도 확장할 수 있습니다.\n- **즉시 배포** - 앱을 빌드한 후 [단일 명령어](https://reflex.dev/docs/hosting/deploy-quick-start/)로 배포하거나 자체 서버에서 호스팅할 수 있습니다.\n\nReflex가 내부적으로 어떻게 작동하는지 알아보려면 [아키텍처 페이지](https://reflex.dev/blog/2024-03-21-reflex-architecture/#the-reflex-architecture)를 참조하세요.\n\n## ⚙️ 설치\n\n터미널을 열고 실행하세요. (Python 3.10+ 필요):\n\n```bash\npip install reflex\n```\n\n## 🥳 첫 앱 만들기\n\n`reflex`를 설치하면, `reflex` 명령어 라인 도구도 설치됩니다.\n\n새 프로젝트를 생성하여 설치가 성공적인지 확인합니다. (`my_app_name`을 프로젝트 이름으로 변경합니다.):\n\n```bash\nmkdir my_app_name\ncd my_app_name\nreflex init\n```\n\n이 명령어는 새 디렉토리에 템플릿 앱을 초기화합니다.\n\n개발 모드에서 이 앱을 실행할 수 있습니다:\n\n```bash\nreflex run\n```\n\nhttp://localhost:3000 에서 앱이 실행 됩니다.\n\n이제 `my_app_name/my_app_name.py`에서 소스코드를 수정할 수 있습니다. Reflex는 빠른 새로고침을 지원하므로 코드를 저장할 때마다 즉시 변경 사항을 볼 수 있습니다.\n\n## 🫧 예시 앱\n\n예시를 살펴보겠습니다: [DALL·E](https://platform.openai.com/docs/guides/images/image-generation?context=node)를 중심으로 이미지 생성 UI를 만들어 보겠습니다. 간단하게 하기 위해 [OpenAI API](https://platform.openai.com/docs/api-reference/authentication)를 호출했지만, 이를 로컬에서 실행되는 ML 모델로 대체할 수 있습니다.\n\n&nbsp;\n\n<div align=\"center\">\n<img src=\"/docs/images/dalle.gif\" alt=\"A frontend wrapper for DALL·E, shown in the process of generating an image.\" width=\"550\" />\n</div>\n\n&nbsp;\n\n이것이 완성된 코드입니다. 이 모든 것은 하나의 Python 파일에서 이루어집니다!\n\n```python\nimport reflex as rx\nimport openai\n\nopenai_client = openai.OpenAI()\n\n\nclass State(rx.State):\n    \"\"\"The app state.\"\"\"\n\n    prompt = \"\"\n    image_url = \"\"\n    processing = False\n    complete = False\n\n    def get_image(self):\n        \"\"\"Get the image from the prompt.\"\"\"\n        if self.prompt == \"\":\n            return rx.window_alert(\"Prompt Empty\")\n\n        self.processing, self.complete = True, False\n        yield\n        response = openai_client.images.generate(\n            prompt=self.prompt, n=1, size=\"1024x1024\"\n        )\n        self.image_url = response.data[0].url\n        self.processing, self.complete = False, True\n\n\ndef index():\n    return rx.center(\n        rx.vstack(\n            rx.heading(\"DALL-E\", font_size=\"1.5em\"),\n            rx.input(\n                placeholder=\"Enter a prompt..\",\n                on_blur=State.set_prompt,\n                width=\"25em\",\n            ),\n            rx.button(\n                \"Generate Image\",\n                on_click=State.get_image,\n                width=\"25em\",\n                loading=State.processing\n            ),\n            rx.cond(\n                State.complete,\n                rx.image(src=State.image_url, width=\"20em\"),\n            ),\n            align=\"center\",\n        ),\n        width=\"100%\",\n        height=\"100vh\",\n    )\n\n# Add state and page to the app.\napp = rx.App()\napp.add_page(index, title=\"Reflex:DALL-E\")\n```\n\n## 하나씩 살펴보겠습니다.\n\n<div align=\"center\">\n<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\" />\n</div>\n\n### **Reflex UI**\n\nUI부터 시작해봅시다.\n\n```python\ndef index():\n    return rx.center(\n        ...\n    )\n```\n\n`index` 함수는 앱의 프론트엔드를 정의합니다.\n\n`center`, `vstack`, `input`, `button`과 같은 다양한 컴포넌트를 사용하여 프론트엔드를 구축합니다.\n컴포넌트들은 복잡한 레이아웃을 만들기 위해 서로 중첩될 수 있습니다.\n그리고 키워드 인자를 사용하여 CSS의 모든 기능을 사용하여 스타일을 지정할 수 있습니다.\n\nReflex는 시작하기 위한 [60개 이상의 기본 컴포넌트](https://reflex.dev/docs/library)를 제공하고 있습니다. 더 많은 컴포넌트를 추가하고 있으며, [자신만의 컴포넌트를 생성하는 것](https://reflex.dev/docs/wrapping-react/overview/)도 쉽습니다.\n\n### **State**\n\nReflex는 UI를 State 함수로 표현합니다.\n\n```python\nclass State(rx.State):\n    \"\"\"The app state.\"\"\"\n    prompt = \"\"\n    image_url = \"\"\n    processing = False\n    complete = False\n```\n\nstate는 앱에서 변경될 수 있는 모든 변수(vars로 불림)와 이러한 변수를 변경하는 함수를 정의합니다.\n\n여기서 state는 `prompt`와 `image_url`로 구성됩니다. 또한 `processing`과 `complete`라는 불리언 값이 있습니다. 이 값들은 이미지 생성 중 버튼을 비활성화할 때와, 결과 이미지를 표시할 때를 나타냅니다.\n\n### **Event Handlers**\n\n```python\ndef get_image(self):\n    \"\"\"Get the image from the prompt.\"\"\"\n    if self.prompt == \"\":\n        return rx.window_alert(\"Prompt Empty\")\n\n    self.processing, self.complete = True, False\n    yield\n    response = openai_client.images.generate(\n        prompt=self.prompt, n=1, size=\"1024x1024\"\n    )\n    self.image_url = response.data[0].url\n    self.processing, self.complete = False, True\n```\n\nState 내에서, state vars를 변경하는 이벤트 핸들러라고 불리는 함수를 정의합니다. 이벤트 핸들러는 Reflex에서 state를 변경하는 방법입니다. 버튼을 클릭하거나 텍스트 상자에 입력하는 것과 같이 사용자 동작에 응답하여 호출될 수 있습니다. 이러한 동작을 이벤트라고 합니다.\n\nDALL·E. 앱에는 OpenAI API에서 이미지를 가져오는 `get_image` 이벤트 핸들러가 있습니다. 이벤트 핸들러의 중간에 `yield`를 사용하면 UI가 업데이트됩니다. 그렇지 않으면 UI는 이벤트 핸들러의 끝에서 업데이트됩니다.\n\n### **Routing**\n\n마지막으로, 앱을 정의합니다.\n\n```python\napp = rx.App()\n```\n\n앱의 루트에서 index 컴포넌트로 페이지를 추가합니다. 또한 페이지 미리보기/브라우저 탭에 표시될 제목도 추가합니다.\n\n```python\napp.add_page(index, title=\"DALL-E\")\n```\n\n여러 페이지를 추가하여 멀티 페이지 앱을 만들 수 있습니다.\n\n## 📑 자료\n\n<div align=\"center\">\n\n📑 [문서](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/templates/) &nbsp; | &nbsp; 🛸 [배포](https://reflex.dev/docs/hosting/deploy-quick-start) &nbsp;\n\n</div>\n\n## ✅ 상태\n\nReflex는 2022년 12월 Pynecone이라는 이름으로 출시되었습니다.\n\n2025년부터 [Reflex Cloud](https://cloud.reflex.dev)가 출시되어 Reflex 앱을 위한 최상의 호스팅 경험을 제공합니다. 우리는 계속해서 개발하고 더 많은 기능을 구현할 예정입니다.\n\nReflex는 매주 새로운 릴리즈와 기능을 제공합니다! 최신 정보를 확인하려면 :star: Star와 :eyes: Watch를 눌러 이 저장소를 확인하세요.\n\n## 기여\n\n우리는 모든 기여를 환영합니다! 아래는 Reflex 커뮤니티에 참여하는 좋은 방법입니다.\n\n- **Discord 참여**: 우리의 [Discord](https://discord.gg/T5WSbC2YtQ)는 Reflex 프로젝트에 대한 도움을 받고 기여하는 방법을 논의하는 최고의 장소입니다.\n- **GitHub Discussions**: 추가하고 싶은 기능이나 혼란스럽거나 해결이 필요한 것들에 대해 이야기하는 좋은 방법입니다.\n- **GitHub Issues**: [Issues](https://github.com/reflex-dev/reflex/issues)는 버그를 보고하는 훌륭한 방법입니다. 또한, 기존의 이슈를 해결하고 PR을 제출할 수 있습니다.\n\n우리는 능력이나 경험에 상관없이 적극적으로 기여자를 찾고 있습니다. 기여하려면 [CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)를 확인하세요.\n\n## 모든 기여자들에게 감사드립니다:\n\n<a href=\"https://github.com/reflex-dev/reflex/graphs/contributors\">\n  <img src=\"https://contrib.rocks/image?repo=reflex-dev/reflex\" />\n</a>\n\n## License\n\nReflex는 오픈소스이며 [Apache License 2.0](/LICENSE)로 라이선스가 부여됩니다.\n"
  },
  {
    "path": "docs/pe/README.md",
    "content": "<div align=\"center\">\n<img src=\"/docs/images/reflex.svg\" alt=\"Reflex Logo\" width=\"300px\">\n<hr>\n\n### **✨ برنامه های تحت وب قابل تنظیم، کارآمد تماما پایتونی که در چند ثانیه مستقر(دپلوی) می‎شود. ✨**\n\n[![PyPI version](https://badge.fury.io/py/reflex.svg)](https://badge.fury.io/py/reflex)\n![versions](https://img.shields.io/pypi/pyversions/reflex.svg)\n[![Documentation](https://img.shields.io/badge/Documentation%20-Introduction%20-%20%23007ec6)](https://reflex.dev/docs/getting-started/introduction)\n[![PyPI Downloads](https://static.pepy.tech/badge/reflex)](https://pepy.tech/projects/reflex)\n[![Discord](https://img.shields.io/discord/1029853095527727165?color=%237289da&label=Discord)](https://discord.gg/T5WSbC2YtQ)\n\n</div>\n\n---\n\n[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) | [Español](https://github.com/reflex-dev/reflex/blob/main/docs/es/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) | [Tiếng Việt](https://github.com/reflex-dev/reflex/blob/main/docs/vi/README.md)\n\n---\n\n# Reflex - رفلکس\n\nرفلکس(Reflex) یک کتابخانه برای ساخت برنامه های وب فول استک تماما پایتونی است.\n\nویژگی های کلیدی:\n\n- **تماما پایتونی** - فرانت اند و بک اند برنامه خود را همه در پایتون بنویسید، بدون نیاز به یادگیری جاوا اسکریپت.\n- **انعطاف پذیری کامل** - شروع به کار با Reflex آسان است، اما می تواند به برنامه های پیچیده نیز تبدیل شود.\n- **دپلوی فوری** - پس از ساخت، برنامه خود را با [یک دستور](https://reflex.dev/docs/hosting/deploy-quick-start/) دپلوی کنید یا آن را روی سرور خود میزبانی کنید.\n\nبرای آشنایی با نحوه عملکرد Reflex [صفحه معماری](https://reflex.dev/blog/2024-03-21-reflex-architecture/#the-reflex-architecture) را ببینید.\n\n## ⚙️ Installation - نصب و راه اندازی\n\nیک ترمینال را باز کنید و اجرا کنید (نیازمند Python 3.10+):\n\n```bash\npip install reflex\n```\n\n## 🥳 اولین برنامه خود را ایجاد کنید\n\nنصب `reflex` همچنین `reflex` در خط فرمان را نصب میکند.\n\nبا ایجاد یک پروژه جدید موفقیت آمیز بودن نصب را تست کنید. (`my_app_name` را با اسم پروژه خودتان جایگزین کنید):\n\n```bash\nmkdir my_app_name\ncd my_app_name\nreflex init\n```\n\nاین دستور یک برنامه الگو(تمپلیت) را در فهرست(دایرکتوری) جدید شما مقداردهی اولیه می کند\n\nمی توانید این برنامه را در حالت توسعه(development) اجرا کنید:\n\n```bash\nreflex run\n```\n\nباید برنامه خود را در حال اجرا ببینید در http://localhost:3000.\n\nاکنون می‌توانید کد منبع را در «my_app_name/my_app_name.py» تغییر دهید. Reflex دارای تازه‌سازی‌های سریعی است، بنابراین می‌توانید تغییرات خود را بلافاصله پس از ذخیره کد خود مشاهده کنید.\n\n## 🫧 Example App - برنامه نمونه\n\nبیایید یک مثال بزنیم: ایجاد یک رابط کاربری برای تولید تصویر [DALL·E](https://platform.openai.com/docs/guides/images/image-generation?context=node). برای سادگی، ما فراخوانی میکنیم [OpenAI API](https://platform.openai.com/docs/api-reference/authentication), اما می توانید آن را با یک مدل ML که به صورت محلی اجرا می شود جایگزین کنید.\n\n&nbsp;\n\n<div align=\"center\">\n<img src=\"/docs/images/dalle.gif\" alt=\"A frontend wrapper for DALL·E, shown in the process of generating an image.\" width=\"550\" />\n</div>\n\n&nbsp;\n\nدر اینجا کد کامل برای ایجاد این پروژه آمده است. همه اینها در یک فایل پایتون انجام می شود!\n\n```python\nimport reflex as rx\nimport openai\n\nopenai_client = openai.OpenAI()\n\n\nclass State(rx.State):\n    \"\"\"The app state.\"\"\"\n\n    prompt = \"\"\n    image_url = \"\"\n    processing = False\n    complete = False\n\n    def get_image(self):\n        \"\"\"Get the image from the prompt.\"\"\"\n        if self.prompt == \"\":\n            return rx.window_alert(\"Prompt Empty\")\n\n        self.processing, self.complete = True, False\n        yield\n        response = openai_client.images.generate(\n            prompt=self.prompt, n=1, size=\"1024x1024\"\n        )\n        self.image_url = response.data[0].url\n        self.processing, self.complete = False, True\n\n\ndef index():\n    return rx.center(\n        rx.vstack(\n            rx.heading(\"DALL-E\", font_size=\"1.5em\"),\n            rx.input(\n                placeholder=\"Enter a prompt..\",\n                on_blur=State.set_prompt,\n                width=\"25em\",\n            ),\n            rx.button(\n                \"Generate Image\",\n                on_click=State.get_image,\n                width=\"25em\",\n                loading=State.processing\n            ),\n            rx.cond(\n                State.complete,\n                rx.image(src=State.image_url, width=\"20em\"),\n            ),\n            align=\"center\",\n        ),\n        width=\"100%\",\n        height=\"100vh\",\n    )\n\n# Add state and page to the app.\napp = rx.App()\napp.add_page(index, title=\"Reflex:DALL-E\")\n```\n\n## بیاید سادش کنیم\n\n<div align=\"center\">\n<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\" />\n</div>\n\n### **Reflex UI - رابط کاربری رفلکس**\n\nبیایید با رابط کاربری شروع کنیم.\n\n```python\ndef index():\n    return rx.center(\n        ...\n    )\n```\n\nتابع `index` قسمت فرانت اند برنامه را تعریف می کند.\n\nما از اجزای مختلفی مثل `center`, `vstack`, `input` و `button` استفاده میکنیم تا فرانت اند را بسازیم. اجزاء را می توان درون یکدیگر قرار داد\nبرای ایجاد طرح بندی های پیچیده می توانید از args کلمات کلیدی برای استایل دادن به آنها از CSS استفاده کنید.\n\nرفلکس دارای [بیش از 60 جزء](https://reflex.dev/docs/library) برای کمک به شما برای شروع. ما به طور فعال اجزای بیشتری را اضافه می کنیم, و این خیلی آسان است که [اجزا خود را بسازید](https://reflex.dev/docs/wrapping-react/overview/).\n\n### **State - حالت**\n\nرفلکس رابط کاربری شما را به عنوان تابعی از وضعیت شما نشان می دهد.\n\n```python\nclass State(rx.State):\n    \"\"\"The app state.\"\"\"\n    prompt = \"\"\n    image_url = \"\"\n    processing = False\n    complete = False\n\n```\n\nحالت تمام متغیرها(variables) (به نام vars) را در یک برنامه که می توانند تغییر دهند و توابعی که آنها را تغییر می دهند تعریف می کند..\n\nدر اینجا حالت از یک `prompt` و `image_url` تشکیل شده است. همچنین دو بولی `processing` و `complete` برای نشان دادن زمان غیرفعال کردن دکمه (در طول تولید تصویر) و زمان نمایش تصویر نتیجه وجود دارد.\n\n### **Event Handlers - کنترل کنندگان رویداد**\n\n```python\ndef get_image(self):\n    \"\"\"Get the image from the prompt.\"\"\"\n    if self.prompt == \"\":\n        return rx.window_alert(\"Prompt Empty\")\n\n    self.processing, self.complete = True, False\n    yield\n    response = openai_client.images.generate(\n        prompt=self.prompt, n=1, size=\"1024x1024\"\n    )\n    self.image_url = response.data[0].url\n    self.processing, self.complete = False, True\n```\n\nدر داخل حالت، توابعی به نام کنترل کننده رویداد تعریف می کنیم که متغیرهای حالت را تغییر می دهند. کنترل کننده های رویداد راهی هستند که می توانیم وضعیت را در Reflex تغییر دهیم. آنها را می توان در پاسخ به اقدامات کاربر، مانند کلیک کردن روی یک دکمه یا تایپ کردن در یک متن، فراخوانی کرد. به این اعمال وقایع می گویند.\n\nبرنامه DALL·E ما دارای یک کنترل کننده رویداد، `get_image` است که این تصویر را از OpenAI API دریافت می کند. استفاده از `yield` در وسط کنترل‌کننده رویداد باعث به‌روزرسانی رابط کاربری می‌شود. در غیر این صورت رابط کاربری در پایان کنترل کننده رویداد به روز می شود.\n\n### **Routing - مسیریابی**\n\nبالاخره اپلیکیشن خود را تعریف می کنیم.\n\n```python\napp = rx.App()\n```\n\nما یک صفحه از root برنامه را به جزء index اضافه می کنیم. ما همچنین عنوانی را اضافه می کنیم که در برگه پیش نمایش/مرورگر صفحه نمایش داده می شود.\n\n```python\napp.add_page(index, title=\"DALL-E\")\n```\n\nبا افزودن صفحات بیشتر می توانید یک برنامه چند صفحه ای ایجاد کنید.\n\n## 📑 Resources - منابع\n\n<div align=\"center\">\n\n📑 [اسناد](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/templates/) &nbsp; | &nbsp; 🛸 [استقرار](https://reflex.dev/docs/hosting/deploy-quick-start) &nbsp;\n\n</div>\n\n## ✅ Status - وضعیت\n\nرفلکس(reflex) در دسامبر 2022 با نام Pynecone راه اندازی شد.\n\nاز سال 2025، [Reflex Cloud](https://cloud.reflex.dev) برای فراهم کردن بهترین تجربه میزبانی برای برنامه های Reflex راه‌اندازی شده است. ما به توسعه آن ادامه خواهیم داد و ویژگی‌های بیشتری را پیاده‌سازی خواهیم کرد.\n\nرفلکس(reflex) هر هفته نسخه ها و ویژگی های جدیدی دارد! مطمئن شوید که :star: ستاره و :eyes: این مخزن را تماشا کنید تا به روز بمانید.\n\n## Contributing - مشارکت کردن\n\nما از مشارکت در هر اندازه استقبال می کنیم! در زیر چند راه خوب برای شروع در انجمن رفلکس آورده شده است.\n\n- **به Discord ما بپیوندید**: [Discord](https://discord.gg/T5WSbC2YtQ) ما بهترین مکان برای دریافت کمک در مورد پروژه Reflex و بحث در مورد اینکه چگونه می توانید کمک کنید است.\n- **بحث های GitHub**: راهی عالی برای صحبت در مورد ویژگی هایی که می خواهید اضافه کنید یا چیزهایی که گیج کننده هستند/نیاز به توضیح دارند.\n- **قسمت مشکلات GitHub**: [قسمت مشکلات](https://github.com/reflex-dev/reflex/issues) یک راه عالی برای گزارش اشکال هستند. علاوه بر این، می توانید یک مشکل موجود را حل کنید و یک PR(pull request) ارسال کنید.\n\nما فعالانه به دنبال مشارکت کنندگان هستیم، فارغ از سطح مهارت یا تجربه شما. برای مشارکت [CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md) را بررسی کنید.\n\n## All Thanks To Our Contributors - با تشکر از همکاران ما:\n\n<a href=\"https://github.com/reflex-dev/reflex/graphs/contributors\">\n  <img src=\"https://contrib.rocks/image?repo=reflex-dev/reflex\" />\n</a>\n\n## License - مجوز\n\nرفلکس متن باز و تحت مجوز [Apache License 2.0](/LICENSE) است.\n"
  },
  {
    "path": "docs/pt/pt_br/README.md",
    "content": "<div align=\"center\">\n<img src=\"/docs/images/reflex.svg\" alt=\"Reflex Logo\" width=\"300px\">\n<hr>\n\n### **✨ Web apps customizáveis, performáticos, em Python puro. Faça deploy em segundos. ✨**\n\n[![Versão PyPI](https://badge.fury.io/py/reflex.svg)](https://badge.fury.io/py/reflex)\n![versões](https://img.shields.io/pypi/pyversions/reflex.svg)\n[![Documentação](https://img.shields.io/badge/Documentation%20-Introduction%20-%20%23007ec6)](https://reflex.dev/docs/getting-started/introduction)\n[![PyPI Downloads](https://static.pepy.tech/badge/reflex)](https://pepy.tech/projects/reflex)\n[![Discord](https://img.shields.io/discord/1029853095527727165?color=%237289da&label=Discord)](https://discord.gg/T5WSbC2YtQ)\n\n</div>\n\n---\n\n[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) | [Español](https://github.com/reflex-dev/reflex/blob/main/docs/es/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) | [Tiếng Việt](https://github.com/reflex-dev/reflex/blob/main/docs/vi/README.md)\n\n---\n\n# Reflex\n\nReflex é uma biblioteca para construir aplicações web full-stack em Python puro.\n\nPrincipais características:\n\n- **Python Puro** - Escreva o frontend e o backend da sua aplicação inteiramente em Python, sem necessidade de aprender Javascript.\n- **Flexibilidade Total** - O Reflex é fácil de começar a usar, mas também pode escalar para aplicações complexas.\n- **Deploy Instantâneo** - Após a construção, faça o deploy da sua aplicação com um [único comando](https://reflex.dev/docs/hosting/deploy-quick-start/) ou hospede-a em seu próprio servidor.\n\nVeja nossa [página de arquitetura](https://reflex.dev/blog/2024-03-21-reflex-architecture/#the-reflex-architecture) para aprender como o Reflex funciona internamente.\n\n## ⚙️ Instalação\n\nAbra um terminal e execute (Requer Python 3.10+):\n\n```bash\npip install reflex\n```\n\n## 🥳 Crie o seu primeiro app\n\nInstalar `reflex` também instala a ferramenta de linha de comando `reflex`.\n\nCrie um novo projeto para verificar se a instalação foi bem sucedida. (Mude `nome_do_meu_app` com o nome do seu projeto):\n\n```bash\nmkdir nome_do_meu_app\ncd nome_do_meu_app\nreflex init\n```\n\nEste comando inicializa um app base no seu novo diretório.\n\nVocê pode executar este app em modo desenvolvimento:\n\n```bash\nreflex run\n```\n\nVocê deve conseguir verificar seu app sendo executado em http://localhost:3000.\n\nAgora, 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 instantaneamente quando você salva o seu código.\n\n## 🫧 Exemplo de App\n\nVeja o seguinte exemplo: criar uma interface de criação de imagens por meio do [DALL·E](https://platform.openai.com/docs/guides/images/image-generation?context=node). Para fins de simplicidade, vamos apenas chamar a [API da OpenAI](https://platform.openai.com/docs/api-reference/authentication), mas você pode substituir esta solução por um modelo de ML executado localmente.\n\n&nbsp;\n\n<div align=\"center\">\n<img src=\"/docs/images/dalle.gif\" alt=\"Um encapsulador frontend para o DALL-E, mostrado no processo de criação de uma imagem.\" width=\"550\" />\n</div>\n\n&nbsp;\n\nAqui está o código completo para criar este projeto. Isso tudo foi feito apenas em um arquivo Python!\n\n```python\nimport reflex as rx\nimport openai\n\nopenai_client = openai.OpenAI()\n\n\nclass State(rx.State):\n    \"\"\"Estado da aplicação.\"\"\"\n\n    prompt = \"\"\n    image_url = \"\"\n    processing = False\n    complete = False\n\n    def get_image(self):\n        \"\"\"Obtenção da imagem a partir do prompt.\"\"\"\n        if self.prompt == \"\":\n            return rx.window_alert(\"Prompt Empty\")\n\n        self.processing, self.complete = True, False\n        yield\n        response = openai_client.images.generate(\n            prompt=self.prompt, n=1, size=\"1024x1024\"\n        )\n        self.image_url = response.data[0].url\n        self.processing, self.complete = False, True\n\n\ndef index():\n    return rx.center(\n        rx.vstack(\n            rx.heading(\"DALL-E\", font_size=\"1.5em\"),\n            rx.input(\n                placeholder=\"Enter a prompt..\",\n                on_blur=State.set_prompt,\n                width=\"25em\",\n            ),\n            rx.button(\n                \"Generate Image\",\n                on_click=State.get_image,\n                width=\"25em\",\n                loading=State.processing\n            ),\n            rx.cond(\n                State.complete,\n                rx.image(src=State.image_url, width=\"20em\"),\n            ),\n            align=\"center\",\n        ),\n        width=\"100%\",\n        height=\"100vh\",\n    )\n\n# Adição do estado e da página no app.\napp = rx.App()\napp.add_page(index, title=\"Reflex:DALL-E\")\n```\n\n## Vamos por partes.\n\n<div align=\"center\">\n<img src=\"/docs/images/dalle_colored_code_example.png\" alt=\"Explicando as diferenças entre as partes de backend e frontend do app DALL-E.\" width=\"900\" />\n</div>\n\n### **Reflex UI**\n\nVamos começar com a UI (Interface de Usuário)\n\n```python\ndef index():\n    return rx.center(\n        ...\n    )\n```\n\nEsta função `index` define o frontend do app.\n\nUsamos diferentes componentes, como `center`, `vstack`, `input` e `button`, para construir o frontend. Componentes podem ser aninhados um no do outro\npara criar layouts mais complexos. E você pode usar argumentos de chave-valor para estilizá-los com todo o poder do CSS.\n\nO Reflex vem com [60+ componentes nativos](https://reflex.dev/docs/library) para te ajudar a começar. Estamos adicionando ativamente mais componentes, e é fácil [criar seus próprios componentes](https://reflex.dev/docs/wrapping-react/overview/).\n\n### **Estado**\n\nO Reflex representa a sua UI como uma função do seu estado.\n\n```python\nclass State(rx.State):\n    \"\"\"Estado da aplicação.\"\"\"\n    prompt = \"\"\n    image_url = \"\"\n    processing = False\n    complete = False\n\n```\n\nO estado define todas as variáveis (chamadas de vars) em um app que podem mudar e as funções que as alteram.\n\nAqui, o estado é composto por um `prompt` e uma `image_url`. Há também os booleanos `processing` e `complete` para indicar quando desabilitar o botão (durante a geração da imagem) e quando mostrar a imagem resultante.\n\n### **Handlers de Eventos**\n\n```python\ndef get_image(self):\n    \"\"\"Obtenção da imagem a partir do prompt.\"\"\"\n    if self.prompt == \"\":\n        return rx.window_alert(\"Prompt Empty\")\n\n    self.processing, self.complete = True, False\n    yield\n    response = openai_client.images.generate(\n        prompt=self.prompt, n=1, size=\"1024x1024\"\n    )\n    self.image_url = response.data[0].url\n    self.processing, self.complete = False, True\n```\n\nDentro do estado, são definidas funções chamadas de Handlers de Eventos, que podem mudar as variáveis do estado. Handlers de Eventos são a forma com a qual podemos modificar o estado dentro do Reflex. Eles podem ser chamados como resposta a uma ação do usuário, como o clique de um botão ou a escrita em uma caixa de texto. Estas ações são chamadas de eventos.\n\nNosso app DALL-E possui um Handler de Evento chamado `get_image`, que obtêm a imagem da API da OpenAI. Usar `yield` no meio de um Handler de Evento causa a atualização da UI do seu app. Caso contrário, a UI seria atualizada no fim da execução de um Handler de Evento.\n\n### **Rotas**\n\nFinalmente, definimos nosso app.\n\n```python\napp = rx.App()\n```\n\nAdicionamos uma página na raíz do app, apontando para o componente index. Também adicionamos um título que irá aparecer na visualização da página/aba do navegador.\n\n```python\napp.add_page(index, title=\"DALL-E\")\n```\n\nVocê pode criar um app com múltiplas páginas adicionando mais páginas.\n\n## 📑 Recursos\n\n<div align=\"center\">\n\n📑 [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; 🖼️ [Templates](https://reflex.dev/templates/) &nbsp; | &nbsp; 🛸 [Deployment](https://reflex.dev/docs/hosting/deploy-quick-start) &nbsp;\n\n</div>\n\n## ✅ Status\n\nO Reflex foi lançado em Dezembro de 2022 com o nome Pynecone.\n\nA partir de 2025, o [Reflex Cloud](https://cloud.reflex.dev) foi lançado para fornecer a melhor experiência de hospedagem para apps Reflex. Continuaremos a desenvolvê-lo e implementar mais recursos.\n\nO Reflex tem novas versões e recursos chegando toda semana! Certifique-se de marcar com :star: estrela e :eyes: observar este repositório para se manter atualizado.\n\n## Contribuições\n\nNós somos abertos a contribuições de qualquer tamanho! Abaixo, seguem algumas boas formas de começar a contribuir para a comunidade do Reflex.\n\n- **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.\n- **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.\n- **Issues no GitHub**: [Issues](https://github.com/reflex-dev/reflex/issues) são uma excelente forma de reportar bugs. Além disso, você pode tentar resolver alguma issue existente e enviar um PR.\n\nEstamos ativamente buscando novos contribuidores, não importa o seu nível de habilidade ou experiência. Para contribuir, confira [CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md).\n\n## Todo Agradecimento aos Nossos Contribuidores:\n\n<a href=\"https://github.com/reflex-dev/reflex/graphs/contributors\">\n  <img src=\"https://contrib.rocks/image?repo=reflex-dev/reflex\" />\n</a>\n\n## Licença\n\nO Reflex é de código aberto e licenciado sob a [Apache License 2.0](/LICENSE).\n"
  },
  {
    "path": "docs/tr/README.md",
    "content": "<div align=\"center\">\n<img src=\"/docs/images/reflex.svg\" alt=\"Reflex Logo\" width=\"300px\">\n<hr>\n\n### **✨ Saf Python'da performanslı, özelleştirilebilir web uygulamaları. Saniyeler içinde dağıtın. ✨**\n\n[![PyPI version](https://badge.fury.io/py/reflex.svg)](https://badge.fury.io/py/reflex)\n![versions](https://img.shields.io/pypi/pyversions/reflex.svg)\n[![Documentation](https://img.shields.io/badge/Documentation%20-Introduction%20-%20%23007ec6)](https://reflex.dev/docs/getting-started/introduction)\n[![PyPI Downloads](https://static.pepy.tech/badge/reflex)](https://pepy.tech/projects/reflex)\n[![Discord](https://img.shields.io/discord/1029853095527727165?color=%237289da&label=Discord)](https://discord.gg/T5WSbC2YtQ)\n\n</div>\n\n---\n\n[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) | [Español](https://github.com/reflex-dev/reflex/blob/main/docs/es/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) | [Tiếng Việt](https://github.com/reflex-dev/reflex/blob/main/docs/vi/README.md)\n\n---\n\n# Reflex\n\nReflex, saf Python'da tam yığın web uygulamaları oluşturmak için bir kütüphanedir.\n\nTemel özellikler:\n\n- **Saf Python** - Uygulamanızın ön uç ve arka uç kısımlarının tamamını Python'da yazın, Javascript öğrenmenize gerek yok.\n- **Tam Esneklik** - Reflex ile başlamak kolaydır, ancak karmaşık uygulamalara da ölçeklenebilir.\n- **Anında Dağıtım** - Oluşturduktan sonra, uygulamanızı [tek bir komutla](https://reflex.dev/docs/hosting/deploy-quick-start/) dağıtın veya kendi sunucunuzda barındırın.\n\nReflex'in perde arkasında nasıl çalıştığını öğrenmek için [mimari sayfamıza](https://reflex.dev/blog/2024-03-21-reflex-architecture/#the-reflex-architecture) göz atın.\n\n## ⚙️ Kurulum\n\nBir terminal açın ve çalıştırın (Python 3.10+ gerekir):\n\n```bash\npip install reflex\n```\n\n## 🥳 İlk Uygulamanı Oluştur\n\n`reflex`'i kurduğunuzda `reflex` komut satırı aracınıda kurmuş olursunuz.\n\nKurulumun başarılı olduğunu test etmek için yeni bir proje oluşturun. (`my_app_name`'i proje ismiyle değiştirin.):\n\n```bash\nmkdir my_app_name\ncd my_app_name\nreflex init\n```\n\nBu komut ile birlikte yeni oluşturduğunuz dizinde bir şablon uygulaması oluşturur.\n\nUygulamanızı geliştirme modunda başlatabilirsiniz:\n\n```bash\nreflex run\n```\n\nUygulamanızın http://localhost:3000 adresinde çalıştığını görmelisiniz.\n\nŞimdi `my_app_name/my_app_name.py` yolundaki kaynak kodu düzenleyebilirsiniz. Reflex'in hızlı yenileme özelliği vardır, böylece kodunuzu kaydettiğinizde değişikliklerinizi anında görebilirsiniz.\n\n## 🫧 Örnek Uygulama\n\nBir örnek üzerinden gidelim: [DALL·E](https://platform.openai.com/docs/guides/images/image-generation?context=node) kullanarak bir görüntü oluşturma arayüzü oluşturalım. Basit olması açısından, yalnızca [OpenAI API](https://platform.openai.com/docs/api-reference/authentication)'ını kullanıyoruz, ancak bunu yerel olarak çalıştırılan bir ML modeliyle değiştirebilirsiniz.\n\n&nbsp;\n\n<div align=\"center\">\n<img src=\"/docs/images/dalle.gif\" alt=\"A frontend wrapper for DALL·E, shown in the process of generating an image.\" width=\"550\" />\n</div>\n\n&nbsp;\n\nİşte bunu oluşturmak için kodun tamamı. Her şey sadece bir Python dosyasıyla hazırlandı!\n\n```python\nimport reflex as rx\nimport openai\n\nopenai_client = openai.OpenAI()\n\n\nclass State(rx.State):\n    \"\"\"Uygulama durumu.\"\"\"\n    prompt = \"\"\n    image_url = \"\"\n    processing = False\n    complete = False\n\n    def get_image(self):\n        \"\"\"Prompt'tan görüntüyü alın.\"\"\"\n        if self.prompt == \"\":\n            return rx.window_alert(\"Prompt Empty\")\n\n        self.processing, self.complete = True, False\n        yield\n        response = openai_client.images.generate(\n            prompt=self.prompt, n=1, size=\"1024x1024\"\n        )\n        self.image_url = response.data[0].url\n        self.processing, self.complete = False, True\n\n\ndef index():\n    return rx.center(\n        rx.vstack(\n            rx.heading(\"DALL-E\", font_size=\"1.5em\"),\n            rx.input(\n                placeholder=\"Enter a prompt..\",\n                on_blur=State.set_prompt,\n                width=\"25em\",\n            ),\n            rx.button(\n                \"Generate Image\",\n                on_click=State.get_image,\n                width=\"25em\",\n                loading=State.processing\n            ),\n            rx.cond(\n                State.complete,\n                rx.image(src=State.image_url, width=\"20em\"),\n            ),\n            align=\"center\",\n        ),\n        width=\"100%\",\n        height=\"100vh\",\n    )\n\n# Sayfa ve durumu uygulamaya ekleyin.\napp = rx.App()\napp.add_page(index, title=\"Reflex:DALL-E\")\n```\n\n## Daha Detaylı İceleyelim\n\n<div align=\"center\">\n<img src=\"/docs/images/dalle_colored_code_example.png\" alt=\"DALL-E uygulamasının arka uç ve ön uç kısımları arasındaki farkları açıklama.\" width=\"900\" />\n</div>\n\n### **Reflex UI**\n\nUI (Kullanıcı Arayüzü) ile başlayalım.\n\n```python\ndef index():\n    return rx.center(\n        ...\n    )\n```\n\nBu `index` fonkisyonu uygulamanın frontend'ini tanımlar.\n\nFrontend'i oluşturmak için `center`, `vstack`, `input`, ve `button` gibi farklı bileşenler kullanıyoruz. Karmaşık düzenler oluşturmak için bileşenleri birbirinin içine yerleştirilebiliriz. Ayrıca bunları CSS'nin tüm gücüyle şekillendirmek için anahtar kelime argümanları kullanabilirsiniz.\n\nReflex, işinizi kolaylaştırmak için [60'tan fazla dahili bileşen](https://reflex.dev/docs/library) içerir. Aktif olarak yeni bileşen ekliyoruz ve [kendi bileşenlerinizi oluşturmak](https://reflex.dev/docs/wrapping-react/overview/) oldukça kolay.\n\n### **Durum (State)**\n\nReflex arayüzünüzü durumunuzun bir fonksiyonu olarak temsil eder.\n\n```python\nclass State(rx.State):\n    \"\"\"Uygulama durumu.\"\"\"\n    prompt = \"\"\n    image_url = \"\"\n    processing = False\n    complete = False\n```\n\nDurum (State), bir uygulamadaki değişebilen tüm değişkenleri (vars olarak adlandırılır) ve bunları değiştiren fonksiyonları tanımlar.\n\nBurada durum `prompt` ve `image_url`inden oluşur. Ayrıca düğmenin ne zaman devre dışı bırakılacağını (görüntü oluşturma sırasında) ve görüntünün ne zaman gösterileceğini belirtmek için `processing` ve `complete` booleanları da vardır.\n\n### **Olay İşleyicileri (Event Handlers)**\n\n```python\ndef get_image(self):\n    \"\"\"Prompt'tan görüntüyü alın.\"\"\"\n    if self.prompt == \"\":\n        return rx.window_alert(\"Prompt Empty\")\n\n    self.processing, self.complete = True, False\n    yield\n    response = openai_client.images.generate(\n        prompt=self.prompt, n=1, size=\"1024x1024\"\n    )\n    self.image_url = response.data[0].url\n    self.processing, self.complete = False, True\n```\n\nDurum içinde, durum değişkenlerini değiştiren olay işleyicileri adı verilen fonksiyonları tanımlarız. Olay işleyicileri, Reflex'te durumu değiştirebilmemizi sağlar. Bir düğmeye tıklamak veya bir metin kutusuna yazı yazmak gibi kullanıcı eylemlerine yanıt olarak çağrılabilirler. Bu eylemlere olay denir.\n\nDALL·E uygulamamız OpenAI API'ından bu görüntüyü almak için `get_image` adlı bir olay işleyicisine sahiptir. Bir olay işleyicisinin ortasında `yield`ın kullanılması UI'ın güncellenmesini sağlar. Aksi takdirde UI olay işleyicisinin sonunda güncellenecektir.\n\n### **Yönlendirme (Routing)**\n\nEn sonunda uygulamamızı tanımlıyoruz.\n\n```python\napp = rx.App()\n```\n\nUygulamamızın kök dizinine index bileşeninden bir sayfa ekliyoruz. Ayrıca sayfa önizlemesinde/tarayıcı sekmesinde görünecek bir başlık ekliyoruz.\n\n```python\napp.add_page(index, title=\"DALL-E\")\n```\n\nDaha fazla sayfa ekleyerek çok sayfalı bir uygulama oluşturabilirsiniz.\n\n## 📑 Kaynaklar\n\n<div align=\"center\">\n\n📑 [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;\n\n</div>\n\n## ✅ Durum\n\nReflex, Aralık 2022'de Pynecone adıyla piyasaya sürüldü.\n\n2025'in başından itibaren, Reflex uygulamaları için en iyi barındırma deneyimini sunmak amacıyla [Reflex Cloud](https://cloud.reflex.dev) hizmete girmiştir. Bunu geliştirmeye ve daha fazla özellik eklemeye devam edeceğiz.\n\nReflex'in her hafta yeni sürümleri ve özellikleri geliyor! Güncel kalmak için bu depoyu :star: yıldızlamayı ve :eyes: izlediğinizden emin olun.\n\n## Katkı\n\nHer boyuttaki katkıları memnuniyetle karşılıyoruz! Aşağıda Reflex topluluğuna adım atmanın bazı yolları mevcut.\n\n- **Discord Kanalımıza Katılın**: [Discord'umuz](https://discord.gg/T5WSbC2YtQ), Reflex projeniz hakkında yardım almak ve nasıl katkıda bulunabileceğinizi tartışmak için en iyi yerdir.\n- **GitHub Discussions**: Eklemek istediğiniz özellikler veya kafa karıştırıcı, açıklığa kavuşturulması gereken şeyler hakkında konuşmanın harika bir yolu.\n- **GitHub Issues**: [Issues](https://github.com/reflex-dev/reflex/issues) hataları bildirmenin mükemmel bir yoludur. Ayrıca mevcut bir sorunu deneyip çözebilir ve bir PR (Pull Requests) gönderebilirsiniz.\n\nBeceri düzeyiniz veya deneyiminiz ne olursa olsun aktif olarak katkıda bulunacak kişiler arıyoruz. Katkı sağlamak için katkı sağlama rehberimize bakabilirsiniz: [CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)\n\n## Hepsi Katkıda Bulunanlar Sayesinde:\n\n<a href=\"https://github.com/reflex-dev/reflex/graphs/contributors\">\n  <img src=\"https://contrib.rocks/image?repo=reflex-dev/reflex\" />\n</a>\n\n## Lisans\n\nReflex açık kaynaklıdır ve [Apache License 2.0](/LICENSE) altında lisanslıdır.\n"
  },
  {
    "path": "docs/vi/README.md",
    "content": "<div align=\"center\">\n<img src=\"/docs/images/reflex.svg\" alt=\"Reflex Logo\" width=\"300px\">\n<hr>\n\n### **✨ Ứng dụng web hiệu suất cao, tùy chỉnh bằng Python thuần. Deploy trong vài giây. ✨**\n\n[![PyPI version](https://badge.fury.io/py/reflex.svg)](https://badge.fury.io/py/reflex)\n![versions](https://img.shields.io/pypi/pyversions/reflex.svg)\n[![Documentation](https://img.shields.io/badge/Documentation%20-Introduction%20-%20%23007ec6)](https://reflex.dev/docs/getting-started/introduction)\n[![PyPI Downloads](https://static.pepy.tech/badge/reflex)](https://pepy.tech/projects/reflex)\n[![Discord](https://img.shields.io/discord/1029853095527727165?color=%237289da&label=Discord)](https://discord.gg/T5WSbC2YtQ)\n\n</div>\n\n---\n\n[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) | [Español](https://github.com/reflex-dev/reflex/blob/main/docs/es/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) | [Tiếng Việt](https://github.com/reflex-dev/reflex/blob/main/docs/vi/README.md)\n\n---\n\n# Reflex\n\nReflex là một thư viện để xây dựng ứng dụng web toàn bộ bằng Python thuần.\n\nCác tính năng chính:\n\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.\n- **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.\n- **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.\n\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.\n\n## ⚙️ Cài đặt\n\nMở cửa sổ lệnh và chạy (Yêu cầu Python phiên bản 3.10+):\n\n```bash\npip install reflex\n```\n\n## 🥳 Tạo ứng dụng đầu tiên\n\nCài đặt `reflex` cũng như cài đặt công cụ dòng lệnh `reflex`.\n\nKiểm tra việc cài đặt đã thành công hay chưa bằng cách tạo mới một ứng dụng. (Thay `my_app_name` bằng tên ứng dụng của bạn):\n\n```bash\nmkdir my_app_name\ncd my_app_name\nreflex init\n```\n\nLệnh này tạo ra một ứng dụng mẫu trong một thư mục mới.\n\nBạn có thể chạy ứng dụng ở chế độ phát triển.\n\n```bash\nreflex run\n```\n\nBạn có thể xem ứng dụng của bạn ở địa chỉ http://localhost:3000.\n\nBạ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.\n\n## 🫧 Ứng dụng ví dụ\n\nBắ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.\n\n&nbsp;\n\n<div align=\"center\">\n<img src=\"/docs/images/dalle.gif\" alt=\"A frontend wrapper for DALL·E, shown in the process of generating an image.\" width=\"550\" />\n</div>\n\n&nbsp;\n\nĐâ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!\n\n```python\nimport reflex as rx\nimport openai\n\nopenai_client = openai.OpenAI()\n\n\nclass State(rx.State):\n    \"\"\"The app state.\"\"\"\n\n    prompt = \"\"\n    image_url = \"\"\n    processing = False\n    complete = False\n\n    def get_image(self):\n        \"\"\"Get the image from the prompt.\"\"\"\n        if self.prompt == \"\":\n            return rx.window_alert(\"Prompt Empty\")\n\n        self.processing, self.complete = True, False\n        yield\n        response = openai_client.images.generate(\n            prompt=self.prompt, n=1, size=\"1024x1024\"\n        )\n        self.image_url = response.data[0].url\n        self.processing, self.complete = False, True\n\n\ndef index():\n    return rx.center(\n        rx.vstack(\n            rx.heading(\"DALL-E\", font_size=\"1.5em\"),\n            rx.input(\n                placeholder=\"Enter a prompt..\",\n                on_blur=State.set_prompt,\n                width=\"25em\",\n            ),\n            rx.button(\n                \"Generate Image\",\n                on_click=State.get_image,\n                width=\"25em\",\n                loading=State.processing\n            ),\n            rx.cond(\n                State.complete,\n                rx.image(src=State.image_url, width=\"20em\"),\n            ),\n            align=\"center\",\n        ),\n        width=\"100%\",\n        height=\"100vh\",\n    )\n\n# Add state and page to the app.\napp = rx.App()\napp.add_page(index, title=\"Reflex:DALL-E\")\n```\n\n## Hãy phân tích chi tiết.\n\n<div align=\"center\">\n<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\" />\n</div>\n\n### **Reflex UI**\n\nBắt đầu với giao diện chính.\n\n```python\ndef index():\n    return rx.center(\n        ...\n    )\n```\n\nHàm `index` định nghĩa phần giao diện chính của ứng dụng.\n\nChúng tôi sử dụng các component (thành phần) khác nhau như `center`, `vstack`, `input` và `button` để xây dựng giao diện phía trước.\nCác component có thể được lồng vào nhau để tạo ra các bố cục phức tạp. Và bạn cũng có thể sử dụng từ khoá `args` để tận dụng đầy đủ sức mạnh của CSS.\n\nReflex có đến hơn [60 component được xây dựng sẵn](https://reflex.dev/docs/library) để giúp bạn bắt đầu. Chúng ta có thể tạo ra một component mới khá dễ dàng, thao khảo: [xây dựng component của riêng bạn](https://reflex.dev/docs/wrapping-react/overview/).\n\n### **State**\n\nReflex biểu diễn giao diện bằng các hàm của state (trạng thái).\n\n```python\nclass State(rx.State):\n    \"\"\"The app state.\"\"\"\n    prompt = \"\"\n    image_url = \"\"\n    processing = False\n    complete = False\n\n```\n\nMột state định nghĩa các biến (được gọi là vars) có thể thay đổi trong một ứng dụng và cho phép các hàm có thể thay đổi chúng.\n\nTại đây state được cấu thành từ một `prompt` và `image_url`.\nCó cũng những biến boolean `processing` và `complete`\nđể chỉ ra khi nào tắt nút (trong quá trình tạo hình ảnh)\nvà khi nào hiển thị hình ảnh kết quả.\n\n### **Event Handlers**\n\n```python\ndef get_image(self):\n    \"\"\"Get the image from the prompt.\"\"\"\n    if self.prompt == \"\":\n        return rx.window_alert(\"Prompt Empty\")\n\n    self.processing, self.complete = True, False\n    yield\n    response = openai_client.images.generate(\n        prompt=self.prompt, n=1, size=\"1024x1024\"\n    )\n    self.image_url = response.data[0].url\n    self.processing, self.complete = False, True\n```\n\nVới các state, chúng ta định nghĩa các hàm có thể thay đổi state vars được gọi là event handlers. Event handler là cách chúng ta có thể thay đổi state trong Reflex. Chúng có thể là phản hồi khi người dùng thao tác, chằng hạn khi nhấn vào nút hoặc khi đang nhập trong text box. Các hành động này được gọi là event.\n\nỨng dụng DALL·E. của chúng ta có một event handler, `get_image` để lấy hình ảnh từ OpenAI API. Sử dụng từ khoá `yield` in ở giữa event handler để cập nhật giao diện. Hoặc giao diện có thể cập nhật ở cuối event handler.\n\n### **Routing**\n\nCuối cùng, chúng ta định nghĩa một ứng dụng.\n\n```python\napp = rx.App()\n```\n\nChú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.\n\n```python\napp.add_page(index, title=\"DALL-E\")\n```\n\nBạn có thể tạo một ứng dụng nhiều trang bằng cách thêm trang.\n\n## 📑 Tài liệu\n\n<div align=\"center\">\n\n📑 [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;\n\n</div>\n\n## ✅ Status\n\nReflex phát hành vào tháng 12/2022 với tên là Pynecone.\n\nTừ năm 2025, [Reflex Cloud](https://cloud.reflex.dev) đã ra mắt để cung cấp trải nghiệm lưu trữ tốt nhất cho các ứng dụng Reflex. Chúng tôi sẽ tiếp tục phát triển và triển khai thêm nhiều tính năng mới.\n\nReflex ra phiên bản mới với các tính năng mới hàng tuần! Hãy :star: star và :eyes: watch repo này để thấy các cập nhật mới nhất.\n\n## Contributing\n\nChú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.\n\n- **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.\n- **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õ.\n- **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.\n\nChú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\n[CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)\n\n## Xin cảm ơn các Contributors:\n\n<a href=\"https://github.com/reflex-dev/reflex/graphs/contributors\">\n  <img src=\"https://contrib.rocks/image?repo=reflex-dev/reflex\" />\n</a>\n\n## License\n\nReflex là mã nguồn mở và sử dụng giấy phép [Apache License 2.0](/LICENSE).\n"
  },
  {
    "path": "docs/zh/zh_cn/README.md",
    "content": "<div align=\"center\">\n<img src=\"/docs/images/reflex.svg\" alt=\"Reflex Logo\" width=\"300px\">\n<hr>\n\n### **✨ 使用 Python 创建高效且可自定义的网页应用程序,几秒钟内即可部署.✨**\n\n[![PyPI version](https://badge.fury.io/py/reflex.svg)](https://badge.fury.io/py/reflex)\n![versions](https://img.shields.io/pypi/pyversions/reflex.svg)\n[![Documentaiton](https://img.shields.io/badge/Documentation%20-Introduction%20-%20%23007ec6)](https://reflex.dev/docs/getting-started/introduction)\n[![PyPI Downloads](https://static.pepy.tech/badge/reflex)](https://pepy.tech/projects/reflex)\n[![Discord](https://img.shields.io/discord/1029853095527727165?color=%237289da&label=Discord)](https://discord.gg/T5WSbC2YtQ)\n\n</div>\n\n---\n\n[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) | [Español](https://github.com/reflex-dev/reflex/blob/main/docs/es/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) | [Tiếng Việt](https://github.com/reflex-dev/reflex/blob/main/docs/vi/README.md)\n\n---\n\n# Reflex\n\nReflex 是一个使用纯 Python 构建全栈 web 应用的库。\n\n关键特性：\n\n- **纯 Python** - 前端、后端开发全都使用 Python，不需要学习 Javascript。\n- **完整的灵活性** - Reflex 很容易上手, 并且也可以扩展到复杂的应用程序。\n- **立即部署** - 构建后，使用[单个命令](https://reflex.dev/docs/hosting/deploy-quick-start/)就能部署应用程序；或者也可以将其托管在您自己的服务器上。\n\n请参阅我们的[架构页](https://reflex.dev/blog/2024-03-21-reflex-architecture/#the-reflex-architecture)了解 Reflex 如何工作。\n\n## ⚙️ 安装\n\n打开一个终端并且运行(要求 Python3.10+):\n\n```bash\npip install reflex\n```\n\n## 🥳 创建您的第一个应用程序\n\n安装 Reflex 的同时也会安装 `reflex` 命令行工具.\n\n通过创建一个新项目来测试是否安装成功(请把 my_app_name 替代为您的项目名字):\n\n```bash\nmkdir my_app_name\ncd my_app_name\nreflex init\n```\n\n这段命令会在新文件夹初始化一个应用程序模板.\n\n您可以在开发者模式下运行这个应用程序:\n\n```bash\nreflex run\n```\n\n您可以看到您的应用程序运行在 http://localhost:3000.\n\n现在您可以在以下位置修改代码 `my_app_name/my_app_name.py`,Reflex 拥有快速刷新(fast refresh),所以您可以在保存代码后马上看到更改.\n\n## 🫧 范例\n\n让我们来看一个例子: 创建一个使用 [DALL·E](https://platform.openai.com/docs/guides/images/image-generation?context=node) 进行图像生成的图形界面.为了保持范例简单,我们只使用 OpenAI API,但是您可以将其替换成本地端的 ML 模型.\n\n&nbsp;\n\n<div align=\"center\">\n<img src=\"/docs/images/dalle.gif\" alt=\"DALL·E的前端界面, 展示了图片生成的进程\" width=\"550\" />\n</div>\n\n&nbsp;\n\n这是这个范例的完整代码,只需要一个 Python 文件就可以完成!\n\n```python\nimport reflex as rx\nimport openai\n\nopenai_client = openai.OpenAI()\n\n\nclass State(rx.State):\n    \"\"\"The app state.\"\"\"\n\n    prompt = \"\"\n    image_url = \"\"\n    processing = False\n    complete = False\n\n    def get_image(self):\n        \"\"\"Get the image from the prompt.\"\"\"\n        if self.prompt == \"\":\n            return rx.window_alert(\"Prompt Empty\")\n\n        self.processing, self.complete = True, False\n        yield\n        response = openai_client.images.generate(\n            prompt=self.prompt, n=1, size=\"1024x1024\"\n        )\n        self.image_url = response.data[0].url\n        self.processing, self.complete = False, True\n\n\ndef index():\n    return rx.center(\n        rx.vstack(\n            rx.heading(\"DALL-E\", font_size=\"1.5em\"),\n            rx.input(\n                placeholder=\"Enter a prompt..\",\n                on_blur=State.set_prompt,\n                width=\"25em\",\n            ),\n            rx.button(\n                \"Generate Image\",\n                on_click=State.get_image,\n                width=\"25em\",\n                loading=State.processing\n            ),\n            rx.cond(\n                State.complete,\n                rx.image(src=State.image_url, width=\"20em\"),\n            ),\n            align=\"center\",\n        ),\n        width=\"100%\",\n        height=\"100vh\",\n    )\n\n# Add state and page to the app.\napp = rx.App()\napp.add_page(index, title=\"Reflex:DALL-E\")\n```\n\n## 让我们分解以上步骤.\n\n<div align=\"center\">\n<img src=\"/docs/images/dalle_colored_code_example.png\" alt=\"解释 DALL-E app 的前端和后端部分的区别。\" width=\"900\" />\n</div>\n\n### **Reflex UI**\n\n让我们从 UI 开始.\n\n```python\ndef index():\n    return rx.center(\n        ...\n    )\n```\n\n这个 `index` 函数定义了应用程序的前端.\n\n我们用不同的组件比如 `center`, `vstack`, `input`, 和 `button` 来创建前端, 组件之间可以相互嵌入,来创建复杂的布局.\n并且您可以使用关键字参数来使用 CSS 的全部功能.\n\nReflex 拥有 [60+ 个内置组件](https://reflex.dev/docs/library) 来帮助您开始创建应用程序. 我们正在积极添加组件, 但是您也可以容易的 [创建自己的组件](https://reflex.dev/docs/wrapping-react/overview/).\n\n### **State**\n\nReflex 用 State 来渲染您的 UI.\n\n```python\nclass State(rx.State):\n    \"\"\"The app state.\"\"\"\n    prompt = \"\"\n    image_url = \"\"\n    processing = False\n    complete = False\n\n```\n\nState 定义了所有可能会发生变化的变量(称为 vars)以及能够改变这些变量的函数.\n\n在这个范例中,State 由 `prompt` 和 `image_url` 组成.此外,State 还包含有两个布尔值 `processing` 和 `complete`,用于指示何时显示循环进度指示器和图像.\n\n### **Event Handlers**\n\n```python\ndef get_image(self):\n    \"\"\"Get the image from the prompt.\"\"\"\n    if self.prompt == \"\":\n        return rx.window_alert(\"Prompt Empty\")\n\n    self.processing, self.complete = True, False\n    yield\n    response = openai_client.images.generate(\n        prompt=self.prompt, n=1, size=\"1024x1024\"\n    )\n    self.image_url = response.data[0].url\n    self.processing, self.complete = False, True\n```\n\n在 State 中,我们定义了称为事件处理器(event handlers)的函数,用于改变状态变量(state vars).在 Reflex 中,事件处理器是我们可以修改状态的方式.它们可以作为对用户操作的响应而被调用,例如点击一个按钮或在文本框中输入.这些操作被称为事件.\n\n我们的 DALL·E 应用有一个事件处理器,名为 `get_image`,它用于从 OpenAI API 获取图像.在事件处理器中使用 `yield` 将导致 UI 进行更新.否则,UI 将在事件处理器结束时进行更新.\n\n### **Routing**\n\n最后,定义我们的应用程序.\n\n```python\napp = rx.App()\n```\n\n我们添加从应用程序根目录到 index 组件的路由.我们还添加了一个在页面预览或浏览器标签中显示的标题.\n\n```python\napp.add_page(index, title=\"DALL-E\")\n```\n\n您可以通过增加更多页面来创建一个多页面的应用.\n\n## 📑 资源\n\n<div align=\"center\">\n\n📑 [文档](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/templates/) &nbsp; | &nbsp; 🛸 [部署](https://reflex.dev/docs/hosting/deploy-quick-start) &nbsp;\n\n</div>\n\n## ✅ Reflex 的状态\n\nReflex 于 2022 年 12 月以 Pynecone 的名称推出.\n\n从 2025 年开始，[Reflex Cloud](https://cloud.reflex.dev)已经推出，为 Reflex 应用提供最佳的托管体验。我们将继续开发并实现更多功能。\n\nReflex 每周都有新功能和发布新版本! 确保您按下 :star: 收藏和 :eyes: 关注 这个 仓库来确保知道最新信息.\n\n## 贡献\n\n我们欢迎任何大小的贡献,以下是几个好的方法来加入 Reflex 社群.\n\n- **加入我们的 Discord**: 我们的 [Discord](https://discord.gg/T5WSbC2YtQ) 是帮助您加入 Reflex 项目和讨论或贡献最棒的地方.\n- **GitHub Discussions**: 一个来讨论您想要添加的功能或是需要澄清的事情的好地方.\n- **GitHub Issues**: [Issues](https://github.com/reflex-dev/reflex/issues)是报告错误的绝佳地方,另外您可以试着解决一些现有 issue 并提交 PR.\n\n我们正在积极寻找贡献者,无关您的技能或经验水平. 若要贡献，请查看[CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)\n\n## 感谢我们所有的贡献者:\n\n<a href=\"https://github.com/reflex-dev/reflex/graphs/contributors\">\n  <img src=\"https://contrib.rocks/image?repo=reflex-dev/reflex\" />\n</a>\n\n## 授权\n\nReflex 是一个开源项目,使用 [Apache License 2.0](/LICENSE) 授权.\n"
  },
  {
    "path": "docs/zh/zh_tw/README.md",
    "content": "<div align=\"center\">\n<img src=\"/docs/images/reflex.svg\" alt=\"Reflex Logo\" width=\"300px\">\n<hr>\n\n**✨ 使用 Python 建立高效且可自訂的網頁應用程式，幾秒鐘內即可部署。✨**\n\n[![PyPI version](https://badge.fury.io/py/reflex.svg)](https://badge.fury.io/py/reflex)\n![versions](https://img.shields.io/pypi/pyversions/reflex.svg)\n[![Documentaiton](https://img.shields.io/badge/Documentation%20-Introduction%20-%20%23007ec6)](https://reflex.dev/docs/getting-started/introduction)\n[![PyPI Downloads](https://static.pepy.tech/badge/reflex)](https://pepy.tech/projects/reflex)\n[![Discord](https://img.shields.io/discord/1029853095527727165?color=%237289da&label=Discord)](https://discord.gg/T5WSbC2YtQ)\n\n</div>\n\n---\n\n[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) | [Español](https://github.com/reflex-dev/reflex/blob/main/docs/es/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) | [Tiếng Việt](https://github.com/reflex-dev/reflex/blob/main/docs/vi/README.md)\n\n---\n\n# Reflex\n\nReflex 是一個可以用純 Python 構建全端網頁應用程式的函式庫。\n\n主要特色：\n\n- **純 Python** - 您可以用 Python 撰寫應用程式的前端和後端，無需學習 Javascript。\n- **完全靈活性** - Reflex 易於上手，但也可以擴展到複雜的應用程式。\n- **立即部署** - 構建後，只需使用[單一指令](https://reflex.dev/docs/hosting/deploy-quick-start/)即可部署您的應用程式，或在您自己的伺服器上託管。\n\n請參閱我們的[架構頁面](https://reflex.dev/blog/2024-03-21-reflex-architecture/#the-reflex-architecture)了解 Reflex 如何在底層運作。\n\n## ⚙️ 安裝\n\n開啟一個終端機並且執行 (需要 Python 3.10+):\n\n```bash\npip install reflex\n```\n\n## 🥳 建立你的第一個應用程式\n\n安裝 Reflex 的同時也會安裝 `reflex` 命令行工具。\n\n通過創建一個新專案來測試是否安裝成功。(把 my_app_name 作為新專案名稱):\n\n```bash\nmkdir my_app_name\ncd my_app_name\nreflex init\n```\n\n此命令會初始化一個應用程式模板在你的新資料夾中。\n\n你可以在開發者模式運行這個應用程式:\n\n```bash\nreflex run\n```\n\n你可以看到你的應用程式運行在 http://localhost:3000。\n\n現在在以下位置修改原始碼 `my_app_name/my_app_name.py`，Reflex 擁有快速刷新功能，存儲程式碼後便可立即看到改變。\n\n## 🫧 範例應用程式\n\n讓我們來看一個例子: 建立一個使用 DALL·E 的圖形使用者介面，為了保持範例簡單，我們只呼叫 OpenAI API，而這部份可以置換掉，改為執行成本地端的 ML 模型。\n\n&nbsp;\n\n<div align=\"center\">\n<img src=\"/docs/images/dalle.gif\" alt=\"A frontend wrapper for DALL·E, shown in the process of generating an image.\" width=\"550\" />\n</div>\n\n&nbsp;\n\n下方為該應用之完整程式碼，這一切都只需要一個 Python 檔案就能作到!\n\n```python\nimport reflex as rx\nimport openai\n\nopenai_client = openai.OpenAI()\n\n\nclass State(rx.State):\n    \"\"\"應用程式狀態\"\"\"\n    prompt = \"\"\n    image_url = \"\"\n    processing = False\n    complete = False\n\n    def get_image(self):\n        \"\"\"透過提示詞取得圖片\"\"\"\n        if self.prompt == \"\":\n            return rx.window_alert(\"Prompt Empty\")\n\n        self.processing, self.complete = True, False\n        yield\n        response = openai_client.images.generate(\n            prompt=self.prompt, n=1, size=\"1024x1024\"\n        )\n        self.image_url = response.data[0].url\n        self.processing, self.complete = False, True\n\n\ndef index():\n    return rx.center(\n        rx.vstack(\n            rx.heading(\"DALL-E\", font_size=\"1.5em\"),\n            rx.input(\n                placeholder=\"Enter a prompt..\",\n                on_blur=State.set_prompt,\n                width=\"25em\",\n            ),\n            rx.button(\n                \"Generate Image\",\n                on_click=State.get_image,\n                width=\"25em\",\n                loading=State.processing\n            ),\n            rx.cond(\n                State.complete,\n                rx.image(src=State.image_url, width=\"20em\"),\n            ),\n            align=\"center\",\n        ),\n        width=\"100%\",\n        height=\"100vh\",\n    )\n\n# 把狀態跟頁面添加到應用程式。\napp = rx.App()\napp.add_page(index, title=\"Reflex:DALL-E\")\n```\n\n## 讓我們來拆解一下。\n\n<div align=\"center\">\n<img src=\"/docs/images/dalle_colored_code_example.png\" alt=\"解釋 DALL-E app 的前端和後端部分的區別。\" width=\"900\" />\n</div>\n\n### **Reflex 使用者介面**\n\n讓我們從使用介面開始。\n\n```python\ndef index():\n    return rx.center(\n        ...\n    )\n```\n\n這個 `index` 函式定義了應用程式的前端.\n\n我們用不同的元件像是 `center`, `vstack`, `input`, 和 `button` 來建立前端，元件之間可互相套入以建立出複雜的版面配置。並且您可使用關鍵字引數 _keyword args_ 運行 CSS 全部功能來設計這些元件們的樣式。\n\nReflex 擁有 [60+ 內建元件](https://reflex.dev/docs/library) 來幫助你開始建立應用程式。我們正積極添加元件，你也可以簡單地 [創建自己所屬的元件](https://reflex.dev/docs/wrapping-react/overview/)。\n\n### **應用程式狀態**\n\nReflex 使用應用程式狀態中的函式來渲染你的 UI。\n\n```python\nclass State(rx.State):\n    \"\"\"應用程式狀態\"\"\"\n    prompt = \"\"\n    image_url = \"\"\n    processing = False\n    complete = False\n\n```\n\n應用程式狀態定義了應用程式中所有可以更改的變數及變更他們的函式 (稱為 vars)。\n\n這裡的狀態由 `prompt` 和 `image_url`組成， 以及布林變數 `processing` 和 `complete` 來指示何時顯示進度條及圖片。\n\n### **事件處理程序**\n\n```python\ndef get_image(self):\n    \"\"\"透過提示詞取得圖片\"\"\"\n    if self.prompt == \"\":\n        return rx.window_alert(\"Prompt Empty\")\n\n    self.processing, self.complete = True, False\n    yield\n    response = openai_client.images.generate(\n        prompt=self.prompt, n=1, size=\"1024x1024\"\n    )\n    self.image_url = response.data[0].url\n    self.processing, self.complete = False, True\n```\n\n在應用程式狀態中，我們定義稱之為事件處理程序的函式來改變其 vars. 事件處理程序是我們用來改變 Reflex 應用程式狀態的方法。\n\n當使用者動作被響應時，對應的事件處理程序就會被呼叫。點擊按鈕或是文字框輸入都是使用者動作，它們被稱之為事件。\n\n我們的 DALL·E. 應用程式有一個事件處理程序 `get_image`，它透過 Open AI API 取得圖片。在事件處理程序中使用 `yield` 將讓使用者介面中途更新，若不使用的話，使用介面只能在事件處理程序結束時才更新。\n\n### **路由**\n\n最後，我們定義我們的應用程式 app。\n\n```python\napp = rx.App()\n```\n\n添加從應用程式根目錄(root of the app) 到 index 元件的路由。 我們也添加了一個標題將會顯示在 預覽/瀏覽 分頁。\n\n```python\napp.add_page(index, title=\"DALL-E\")\n```\n\n你可以添加更多頁面至路由藉此來建立多頁面應用程式(multi-page app)\n\n## 📑 資源\n\n<div align=\"center\">\n\n📑 [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;\n\n</div>\n\n## ✅ 產品狀態\n\nReflex 在 2022 年 12 月以 Pynecone 的名字推出。\n\n自 2025 年起，[Reflex Cloud](https://cloud.reflex.dev) 已推出，為 Reflex 應用程式提供最佳的託管體驗。我們將繼續開發並實施更多功能。\n\nReflex 每周都有新功能和釋出新版本! 確保你按下 :star: 和 :eyes: watch 這個 repository 來確保知道最新資訊。\n\n## 貢獻\n\n我們歡迎任何大小的貢獻，以下是一些加入 Reflex 社群的好方法。\n\n- **加入我們的 Discord**: 我們的 [Discord](https://discord.gg/T5WSbC2YtQ) 是獲取 Reflex 專案幫助和討論如何貢獻的最佳地方。\n- **GitHub Discussions**: 這是一個討論您想新增的功能或對於一些困惑/需要澄清事項的好方法。\n- **GitHub Issues**: 在 [Issues](https://github.com/reflex-dev/reflex/issues) 頁面報告錯誤是一個絕佳的方式。此外，您也可以嘗試解決現有 Issue 並提交 PR。\n\n我們積極尋找貢獻者，不論您的技能水平或經驗如何。要貢獻，請查看 [CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)\n\n## 感謝所有貢獻者:\n\n<a href=\"https://github.com/reflex-dev/reflex/graphs/contributors\">\n  <img src=\"https://contrib.rocks/image?repo=reflex-dev/reflex\" />\n</a>\n\n## 授權\n\nReflex 是一個開源專案且使用 [Apache License 2.0](/LICENSE) 授權。\n"
  },
  {
    "path": "pyi_hashes.json",
    "content": "{\n  \"reflex/__init__.pyi\": \"0a3ae880e256b9fd3b960e12a2cb51a7\",\n  \"reflex/components/__init__.pyi\": \"ac05995852baa81062ba3d18fbc489fb\",\n  \"reflex/components/base/__init__.pyi\": \"16e47bf19e0d62835a605baa3d039c5a\",\n  \"reflex/components/base/app_wrap.pyi\": \"22e94feaa9fe675bcae51c412f5b67f1\",\n  \"reflex/components/base/body.pyi\": \"e8ab029a730824bab6d4211203609e6a\",\n  \"reflex/components/base/document.pyi\": \"311c53c90a60587a82e760103758a3cf\",\n  \"reflex/components/base/error_boundary.pyi\": \"a678cceea014cb16048647257cd24ba6\",\n  \"reflex/components/base/fragment.pyi\": \"745f1be02c23a0b25d7c52d7423ec76a\",\n  \"reflex/components/base/link.pyi\": \"0bc1d26ee29d8864aed14a12991bd47d\",\n  \"reflex/components/base/meta.pyi\": \"129aecf65ab53f756c4d1cbe1d0b188d\",\n  \"reflex/components/base/script.pyi\": \"e5f506d1d0d6712cb9e597a781eb3941\",\n  \"reflex/components/base/strict_mode.pyi\": \"6b72e16caadf7158ab744a0ab751b010\",\n  \"reflex/components/core/__init__.pyi\": \"007170b97e58bdf28b2aee381d91c0c7\",\n  \"reflex/components/core/auto_scroll.pyi\": \"18068d22aca7244a08cd0c5a897c0950\",\n  \"reflex/components/core/banner.pyi\": \"fd93e7a92961de8524718ad32135c37c\",\n  \"reflex/components/core/clipboard.pyi\": \"a844eb927d9bc2a43f5e88161b258539\",\n  \"reflex/components/core/debounce.pyi\": \"055da7aa890f44fb4d48bd5978f1a874\",\n  \"reflex/components/core/helmet.pyi\": \"43f8497c8fafe51e29dca1dd535d143a\",\n  \"reflex/components/core/html.pyi\": \"86eb9d4c1bb4807547b2950d9a32e9fd\",\n  \"reflex/components/core/sticky.pyi\": \"cb763b986a9b0654d1a3f33440dfcf60\",\n  \"reflex/components/core/upload.pyi\": \"6dc28804a6dddf903e31162e87c1b023\",\n  \"reflex/components/core/window_events.pyi\": \"af33ccec866b9540ee7fbec6dbfbd151\",\n  \"reflex/components/datadisplay/__init__.pyi\": \"52755871369acbfd3a96b46b9a11d32e\",\n  \"reflex/components/datadisplay/code.pyi\": \"b86769987ef4d1cbdddb461be88539fd\",\n  \"reflex/components/datadisplay/dataeditor.pyi\": \"9b85f3cf6156293cd9961eb17a0ea684\",\n  \"reflex/components/datadisplay/shiki_code_block.pyi\": \"1d53e75b6be0d3385a342e7b3011babd\",\n  \"reflex/components/el/__init__.pyi\": \"0adfd001a926a2a40aee94f6fa725ecc\",\n  \"reflex/components/el/element.pyi\": \"c5974a92fbc310e42d0f6cfdd13472f4\",\n  \"reflex/components/el/elements/__init__.pyi\": \"29512d7a6b29c6dc5ff68d3b31f26528\",\n  \"reflex/components/el/elements/base.pyi\": \"3f74c7ea573ea29b055b0cd48b040d2c\",\n  \"reflex/components/el/elements/forms.pyi\": \"8b6bb2fbaf4bad828b076e2f7c8444d0\",\n  \"reflex/components/el/elements/inline.pyi\": \"3549cd6ad45217aa6387800911b641c3\",\n  \"reflex/components/el/elements/media.pyi\": \"9b97220aa99783d402b6e278c4069043\",\n  \"reflex/components/el/elements/metadata.pyi\": \"24448004b7aa07f1225028a85bd49fef\",\n  \"reflex/components/el/elements/other.pyi\": \"0c4d5d0b955d8596bf6cf4a48d7decdb\",\n  \"reflex/components/el/elements/scripts.pyi\": \"d33df9f21f7e838376b2b5024beef7c9\",\n  \"reflex/components/el/elements/sectioning.pyi\": \"3c5a7e4caa9c25da0ae788f02466eac4\",\n  \"reflex/components/el/elements/tables.pyi\": \"686eb70ea7d8c4dafb0cc5c284e76184\",\n  \"reflex/components/el/elements/typography.pyi\": \"684e83dde887dba12badd0fb75c87c04\",\n  \"reflex/components/gridjs/datatable.pyi\": \"98a7e1b3f3b60cafcdfcd8879750ee42\",\n  \"reflex/components/lucide/icon.pyi\": \"1db10f2b544908dd20c56ca4bc33d5e0\",\n  \"reflex/components/markdown/markdown.pyi\": \"4c4bca6fb0643abb90aca9c0bb87f722\",\n  \"reflex/components/moment/moment.pyi\": \"e1952f1c2c82cef85d91e970d1be64ab\",\n  \"reflex/components/plotly/plotly.pyi\": \"4311a0aae2abcc9226abb6a273f96372\",\n  \"reflex/components/radix/__init__.pyi\": \"5d8e3579912473e563676bfc71f29191\",\n  \"reflex/components/radix/primitives/__init__.pyi\": \"01c388fe7a1f5426a16676404344edf6\",\n  \"reflex/components/radix/primitives/accordion.pyi\": \"19484eca0ad53f538f5db04c09921738\",\n  \"reflex/components/radix/primitives/base.pyi\": \"9ef34884fb6028dc017df5e2db639c81\",\n  \"reflex/components/radix/primitives/dialog.pyi\": \"9ee73362bb59619c482b6b0d07033f37\",\n  \"reflex/components/radix/primitives/drawer.pyi\": \"921e45dfaf5b9131ef27c561c3acca2e\",\n  \"reflex/components/radix/primitives/form.pyi\": \"17002a3e9d7f52b3207614f6c1c9a24a\",\n  \"reflex/components/radix/primitives/progress.pyi\": \"c917952d57ddb3e138a40c4005120d5e\",\n  \"reflex/components/radix/primitives/slider.pyi\": \"4ff06f0025d47f166132909b09ab96f8\",\n  \"reflex/components/radix/themes/__init__.pyi\": \"582b4a7ead62b2ae8605e17fa084c063\",\n  \"reflex/components/radix/themes/base.pyi\": \"3e1ccd5ce5fef0b2898025193ee3d069\",\n  \"reflex/components/radix/themes/color_mode.pyi\": \"dda570583355d8c0d8f607be457ba7a1\",\n  \"reflex/components/radix/themes/components/__init__.pyi\": \"efa279ee05479d7bb8a64d49da808d03\",\n  \"reflex/components/radix/themes/components/alert_dialog.pyi\": \"eed422fcc1ff5ccf3dbf6934699bd0b1\",\n  \"reflex/components/radix/themes/components/aspect_ratio.pyi\": \"71de4160d79840561c48b570197a4152\",\n  \"reflex/components/radix/themes/components/avatar.pyi\": \"e40c2f0fda6d2c028d83681a27f3fb96\",\n  \"reflex/components/radix/themes/components/badge.pyi\": \"58fd1a9c5d2f8762e2a0370311731ff5\",\n  \"reflex/components/radix/themes/components/button.pyi\": \"50f0b08ad5d1d1054ab537152f0f5c43\",\n  \"reflex/components/radix/themes/components/callout.pyi\": \"547f2570ffbd10db36b745566e9f1b17\",\n  \"reflex/components/radix/themes/components/card.pyi\": \"f7adb83f7b001a11bdd7fd6791fb3ffb\",\n  \"reflex/components/radix/themes/components/checkbox.pyi\": \"8eabb6887a5d0849a43e086a284814c2\",\n  \"reflex/components/radix/themes/components/checkbox_cards.pyi\": \"1d567fd04b4425abd5cc5aad10108aa9\",\n  \"reflex/components/radix/themes/components/checkbox_group.pyi\": \"8638582a623036f8893a3fa6080f2672\",\n  \"reflex/components/radix/themes/components/context_menu.pyi\": \"b9499d8bdd2c5565621fea5fe7d7a25a\",\n  \"reflex/components/radix/themes/components/data_list.pyi\": \"6f8d9c582e084c23966b992158193b72\",\n  \"reflex/components/radix/themes/components/dialog.pyi\": \"d2615f1a68c80ff930444d054b598c13\",\n  \"reflex/components/radix/themes/components/dropdown_menu.pyi\": \"43f8770c9adf93c73398d68f79048424\",\n  \"reflex/components/radix/themes/components/hover_card.pyi\": \"a96f4433237f9994decf935deff9f269\",\n  \"reflex/components/radix/themes/components/icon_button.pyi\": \"f12a874bad243a81e5c8740a1d86c6bc\",\n  \"reflex/components/radix/themes/components/inset.pyi\": \"bd7a2186b553bd4c86d83ff50c784066\",\n  \"reflex/components/radix/themes/components/popover.pyi\": \"91f8edefeb232cc6d48690b1838144c2\",\n  \"reflex/components/radix/themes/components/progress.pyi\": \"0e59587d5b3c8fe0d0067587f144e5b0\",\n  \"reflex/components/radix/themes/components/radio.pyi\": \"f375aa5ac746679618ea7dad257e3224\",\n  \"reflex/components/radix/themes/components/radio_cards.pyi\": \"9dc34a1ce2a1924eb1f41438ef84e80b\",\n  \"reflex/components/radix/themes/components/radio_group.pyi\": \"173254cf91908bcf6aa4fa21a747e2cf\",\n  \"reflex/components/radix/themes/components/scroll_area.pyi\": \"2e3539b0f6895dda127ee96e9864dbf9\",\n  \"reflex/components/radix/themes/components/segmented_control.pyi\": \"1776f1ad936bae402007802b1ee98906\",\n  \"reflex/components/radix/themes/components/select.pyi\": \"2c7aee592972ff5f05da08154aa981c8\",\n  \"reflex/components/radix/themes/components/separator.pyi\": \"79e550cc10ee455f35d75d0e236fedd2\",\n  \"reflex/components/radix/themes/components/skeleton.pyi\": \"a25d3ceb56f99f736ea463579845c454\",\n  \"reflex/components/radix/themes/components/slider.pyi\": \"305a34c14ca8656ca9267e4c31aaa388\",\n  \"reflex/components/radix/themes/components/spinner.pyi\": \"b7e689e7d75635e379242fd113a1ea9a\",\n  \"reflex/components/radix/themes/components/switch.pyi\": \"f1ba948750a74126cda990e89a3ec7ef\",\n  \"reflex/components/radix/themes/components/table.pyi\": \"eefbbd1904deae3d166fcad28b20fd4a\",\n  \"reflex/components/radix/themes/components/tabs.pyi\": \"a533d2509a6798fe0ab7275b0152519d\",\n  \"reflex/components/radix/themes/components/text_area.pyi\": \"4af55e5d18a5b9d56717bf31b23ea543\",\n  \"reflex/components/radix/themes/components/text_field.pyi\": \"232618b744076db98d861ea1b9eb3192\",\n  \"reflex/components/radix/themes/components/tooltip.pyi\": \"2b8366200ce92ec4784ca3ec4152e676\",\n  \"reflex/components/radix/themes/layout/__init__.pyi\": \"73eefc509a49215b1797b5b5d28d035e\",\n  \"reflex/components/radix/themes/layout/base.pyi\": \"5be31d7dadd23ab544e53762423d123e\",\n  \"reflex/components/radix/themes/layout/box.pyi\": \"dbaed1c50c668805fc7b71d22f878254\",\n  \"reflex/components/radix/themes/layout/center.pyi\": \"17323694217e8ad7611adb683f8d96ce\",\n  \"reflex/components/radix/themes/layout/container.pyi\": \"24222fd7ffa2dc05f709eab6c7b9643c\",\n  \"reflex/components/radix/themes/layout/flex.pyi\": \"0307e9dbe6a5784140121d77c8f67a86\",\n  \"reflex/components/radix/themes/layout/grid.pyi\": \"95c9edb8bdd4e39dc1bd6bc2a8ca0933\",\n  \"reflex/components/radix/themes/layout/list.pyi\": \"049ecf827ef0ba8de2d76dbf7b1c562c\",\n  \"reflex/components/radix/themes/layout/section.pyi\": \"a51952b9b5c8227aa3024373dedcad5d\",\n  \"reflex/components/radix/themes/layout/spacer.pyi\": \"c35accf0f2f742c90a23675ff1fb960d\",\n  \"reflex/components/radix/themes/layout/stack.pyi\": \"271d3315c6196356d3ced759520d4e7d\",\n  \"reflex/components/radix/themes/typography/__init__.pyi\": \"b8ef970530397e9984004961f3aaee62\",\n  \"reflex/components/radix/themes/typography/blockquote.pyi\": \"080c71899532f5dbf4cf143e7a5ad3bf\",\n  \"reflex/components/radix/themes/typography/code.pyi\": \"7ffe785d55979cf8ff97ea040f3e2b64\",\n  \"reflex/components/radix/themes/typography/heading.pyi\": \"0ebb38915cd0521fd59c569e04d288bb\",\n  \"reflex/components/radix/themes/typography/link.pyi\": \"64878125a37d47d676c9adf8156d8c41\",\n  \"reflex/components/radix/themes/typography/text.pyi\": \"50f9ca15a941e4b77ddd12e77aa3c03e\",\n  \"reflex/components/react_player/audio.pyi\": \"0e1690ff1f1f39bc748278d292238350\",\n  \"reflex/components/react_player/react_player.pyi\": \"5ccd373b94ed1d3934ae6afc46bd6fe4\",\n  \"reflex/components/react_player/video.pyi\": \"998671c06103d797c554d9278eb3b2a0\",\n  \"reflex/components/react_router/dom.pyi\": \"3042fa630b7e26a7378fe045d7fbf4af\",\n  \"reflex/components/recharts/__init__.pyi\": \"6ee7f1ca2c0912f389ba6f3251a74d99\",\n  \"reflex/components/recharts/cartesian.pyi\": \"d138261ab8259d5208c2f028b9f708bd\",\n  \"reflex/components/recharts/charts.pyi\": \"013036b9c00ad85a570efdb813c1bc40\",\n  \"reflex/components/recharts/general.pyi\": \"d87ff9b85b2a204be01753690df4fb11\",\n  \"reflex/components/recharts/polar.pyi\": \"b8b1a3e996e066facdf4f8c9eb363137\",\n  \"reflex/components/recharts/recharts.pyi\": \"d5c9fc57a03b419748f0408c23319eee\",\n  \"reflex/components/sonner/toast.pyi\": \"dca44901640cda9d58c62ff8434faa3e\"\n}\n"
  },
  {
    "path": "pyproject.toml",
    "content": "[project]\nname = \"reflex\"\nversion = \"0.9.0dev1\"\ndescription = \"Web apps in pure Python.\"\nlicense.text = \"Apache-2.0\"\nauthors = [\n  { name = \"Nikhil Rao\" },\n  { name = \"Alek Petuskey\" },\n  { name = \"Masen Furer\" },\n  { name = \"Elijah Ahianyo\" },\n  { name = \"Thomas Brandeho\" },\n  { name = \"Khaleel Al-Adhami\" },\n]\nmaintainers = [\n  { name = \"Masen Furer\" },\n  { name = \"Khaleel Al-Adhami\" },\n  { email = \"maintainers@reflex.dev\" },\n]\nreadme = \"README.md\"\nkeywords = [\"web\", \"framework\"]\nrequires-python = \">=3.10,<4.0\"\ndependencies = [\n  \"alembic >=1.15.2,<2.0\",\n  \"click >=8.2\",\n  \"granian[reload] >=2.5.5\",\n  \"httpx >=0.23.3,<1.0\",\n  \"packaging >=24.2,<27\",\n  \"platformdirs >=4.3.7,<5.0\",\n  \"psutil >=7.0.0,<8.0; sys_platform == 'win32'\",\n  \"pydantic >=1.10.21,<3.0\",\n  \"python-multipart >=0.0.20,<1.0\",\n  \"python-socketio >=5.12.0,<6.0\",\n  \"redis >=5.2.1,<8.0\",\n  \"reflex-hosting-cli >=0.1.61\",\n  \"rich >=13,<15\",\n  \"sqlmodel >=0.0.27,<0.1\",\n  \"starlette >=0.47.0\",\n  \"typing_extensions >=4.13.0\",\n  \"wrapt >=1.17.0,<3.0\",\n]\n\nclassifiers = [\n  \"Development Status :: 4 - Beta\",\n  \"License :: OSI Approved :: Apache Software License\",\n  \"Programming Language :: Python :: 3\",\n  \"Programming Language :: Python :: 3.10\",\n  \"Programming Language :: Python :: 3.11\",\n  \"Programming Language :: Python :: 3.12\",\n  \"Programming Language :: Python :: 3.13\",\n  \"Programming Language :: Python :: 3.14\",\n]\n\n[project.optional-dependencies]\ndb = [\n  \"alembic >=1.15.2,<2.0\",\n  \"pydantic >=1.10.21,<3.0\",\n  \"sqlmodel >=0.0.24,<0.1\",\n]\nmonitoring = [\"pyleak >=0.1.14,<1.0\"]\n\n[project.urls]\nhomepage = \"https://reflex.dev\"\nrepository = \"https://github.com/reflex-dev/reflex\"\ndocumentation = \"https://reflex.dev/docs/getting-started/introduction\"\n\n[project.scripts]\nreflex = \"reflex.reflex:cli\"\n\n[dependency-groups]\ndev = [\n  \"asynctest\",\n  \"darglint\",\n  \"dill\",\n  \"fastapi\",\n  \"hatchling\",\n  \"libsass\",\n  \"numpy\",\n  \"pandas\",\n  \"pillow\",\n  \"playwright\",\n  \"plotly\",\n  \"pre-commit\",\n  \"psutil\",\n  \"psycopg[binary]\",\n  \"pyleak >=0.1.14,<1.0\",\n  \"pyright\",\n  \"pytest-asyncio\",\n  \"pytest-benchmark\",\n  \"pytest-codspeed\",\n  \"pytest-cov\",\n  \"pytest-mock\",\n  \"pytest-playwright\",\n  \"pytest-rerunfailures\",\n  \"pytest-split\",\n  \"pytest\",\n  \"python-dotenv\",\n  \"ruff\",\n  \"selenium\",\n  \"starlette-admin\",\n  \"toml\",\n  \"uvicorn\",\n]\n\n\n[build-system]\nrequires = [\"hatchling\"]\nbuild-backend = \"hatchling.build\"\n\n[tool.hatch.build]\ninclude = [\"reflex\", \"scripts/hatch_build.py\"]\ntargets.sdist.artifacts = [\"*.pyi\"]\ntargets.wheel.artifacts = [\"*.pyi\"]\n\n[tool.hatch.build.hooks.custom]\npath = \"scripts/hatch_build.py\"\ndependencies = [\"plotly\", \"ruff\", \"pre_commit\", \"toml\"]\nrequire-runtime-dependencies = true\n\n[tool.pyright]\nreportIncompatibleMethodOverride = false\n\n[tool.ruff]\ntarget-version = \"py310\"\noutput-format = \"concise\"\nlint.isort.split-on-trailing-comma = false\npreview = true\nlint.select = [\"ALL\"]\nlint.ignore = [\n  \"A\",\n  \"ANN002\",\n  \"ANN003\",\n  \"ANN2\",\n  \"ANN4\",\n  \"ARG\",\n  \"BLE\",\n  \"C901\",\n  \"COM\",\n  \"CPY001\",\n  \"D205\",\n  \"DOC202\",\n  \"DOC501\",\n  \"DOC502\",\n  \"DTZ\",\n  \"E501\",\n  \"F403\",\n  \"FBT\",\n  \"FIX\",\n  \"FURB189\",\n  \"FURB140\",\n  \"G004\",\n  \"ISC003\",\n  \"PLC\",\n  \"PLR\",\n  \"PLW\",\n  \"PT011\",\n  \"PT012\",\n  \"PYI\",\n  \"RUF012\",\n  \"RUF067\",\n  \"S\",\n  \"SLF\",\n  \"SLOT\",\n  \"TC\",\n  \"TD\",\n  \"TRY0\",\n]\nlint.pydocstyle.convention = \"google\"\nlint.flake8-bugbear.extend-immutable-calls = [\n  \"reflex.utils.types.Unset\",\n  \"reflex.vars.base.Var.create\",\n]\n\n[tool.ruff.lint.per-file-ignores]\n\"__init__.py\" = [\"F401\"]\n\"tests/*.py\" = [\n  \"ANN001\",\n  \"D100\",\n  \"D103\",\n  \"D104\",\n  \"INP\",\n  \"B018\",\n  \"PERF\",\n  \"T\",\n  \"N\",\n]\n\"benchmarks/*.py\" = [\"ANN001\", \"D100\", \"D103\", \"D104\", \"B018\", \"PERF\", \"T\", \"N\"]\n\"reflex/.templates/*.py\" = [\"D100\", \"D103\", \"D104\"]\n\"*.pyi\" = [\"D301\", \"D415\", \"D417\", \"D418\", \"E742\", \"N\", \"PGH\"]\n\"pyi_generator.py\" = [\"N802\"]\n\"reflex/constants/*.py\" = [\"N\"]\n\"reflex/.templates/apps/blank/code/*\" = [\"INP001\"]\n\"*/blank.py\" = [\"I001\"]\n\n[tool.pytest.ini_options]\nfilterwarnings = \"ignore:fields may not start with an underscore:RuntimeWarning\"\nasyncio_default_fixture_loop_scope = \"function\"\nasyncio_mode = \"auto\"\n\n[tool.codespell]\nskip = \"docs/*,*.html,examples/*, *.pyi, poetry.lock, uv.lock\"\nignore-words-list = \"te, TreeE\"\n\n\n[tool.coverage.run]\nsource = [\"reflex\"]\nbranch = true\nomit = [\n  \"*/pyi_generator.py\",\n  \"reflex/__main__.py\",\n  \"reflex/app_module_for_backend.py\",\n  \"reflex/components/chakra/*\",\n  \"reflex/experimental/*\",\n]\n\n[tool.coverage.report]\nshow_missing = true\n# TODO bump back to 79\nfail_under = 70\nprecision = 2\nignore_errors = true\n\nexclude_also = [\n  \"def __repr__\",\n  # Don't complain about missing debug-only code:\n  \"if self.debug\",\n  # Don't complain if tests don't hit defensive assertion code:\n  \"raise AssertionError\",\n  \"raise NotImplementedError\",\n  # Regexes for lines to exclude from consideration\n  \"if 0:\",\n  # Don't complain if non-runnable code isn't run:\n  \"if __name__ == .__main__.:\",\n  # Don't complain about abstract methods, they aren't run:\n  \"@(abc.)?abstractmethod\",\n  # Don't complain about overloaded methods:\n  \"@overload\",\n]\n\n[tool.coverage.html]\ndirectory = \"coverage_html_report\"\n\n[tool.pre-commit]\nfail_fast = true\n\n[[tool.pre-commit.repos]]\nrepo = \"https://github.com/astral-sh/ruff-pre-commit\"\nrev = \"v0.15.6\"\nhooks = [\n  { id = \"ruff-format\", args = [\n    \"reflex\",\n    \"tests\",\n  ] },\n  { id = \"ruff-check\", args = [\n    \"--fix\",\n    \"--exit-non-zero-on-fix\",\n  ], exclude = \"^integration/benchmarks/\" },\n]\n\n[[tool.pre-commit.repos]]\nrepo = \"https://github.com/codespell-project/codespell\"\nrev = \"v2.4.1\"\nhooks = [\n  { id = \"codespell\", args = [\n    \"reflex\",\n  ], additional_dependencies = [\n    \"tomli\",\n  ] },\n]\n\n# Run pyi check before pyright because pyright can fail if pyi files are wrong.\n[[tool.pre-commit.repos]]\nrepo = \"local\"\nhooks = [\n  { id = \"update-pyi-files\", name = \"update-pyi-files\", always_run = true, language = \"system\", require_serial = true, description = \"Update pyi files as needed\", entry = \"python3 scripts/make_pyi.py\" },\n]\n\n[[tool.pre-commit.repos]]\nrepo = \"https://github.com/RobertCraigie/pyright-python\"\nrev = \"v1.1.408\"\nhooks = [{ id = \"pyright\", args = [\"reflex\", \"tests\"], language = \"system\" }]\n\n[[tool.pre-commit.repos]]\nrepo = \"https://github.com/pre-commit/mirrors-prettier\"\nrev = \"f62a70a3a7114896b062de517d72829ea1c884b6\"\nhooks = [{ id = \"prettier\", require_serial = true }]\n\n[tool.uv]\nrequired-version = \">=0.7.0\"\n"
  },
  {
    "path": "reflex/.templates/apps/blank/code/__init__.py",
    "content": ""
  },
  {
    "path": "reflex/.templates/apps/blank/code/blank.py",
    "content": "\"\"\"Welcome to Reflex! This file outlines the steps to create a basic app.\"\"\"\n\nimport reflex as rx\n\nfrom rxconfig import config\n\n\nclass State(rx.State):\n    \"\"\"The app state.\"\"\"\n\n\ndef index() -> rx.Component:\n    # Welcome Page (Index)\n    return rx.container(\n        rx.color_mode.button(position=\"top-right\"),\n        rx.vstack(\n            rx.heading(\"Welcome to Reflex!\", size=\"9\"),\n            rx.text(\n                \"Get started by editing \",\n                rx.code(f\"{config.app_name}/{config.app_name}.py\"),\n                size=\"5\",\n            ),\n            rx.link(\n                rx.button(\"Check out our docs!\"),\n                href=\"https://reflex.dev/docs/getting-started/introduction/\",\n                is_external=True,\n            ),\n            spacing=\"5\",\n            justify=\"center\",\n            min_height=\"85vh\",\n        ),\n    )\n\n\napp = rx.App()\napp.add_page(index)\n"
  },
  {
    "path": "reflex/.templates/web/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n/_static\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# next.js\n/.next/\n/out/\n\n# production\n/build\n\n# misc\n.DS_Store\n*.pem\n\n# debug\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# local env files\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\n# vercel\n.vercel\n\n# DS_Store\n.DS_Store"
  },
  {
    "path": "reflex/.templates/web/app/entry.client.js",
    "content": "import { startTransition } from \"react\";\nimport { hydrateRoot } from \"react-dom/client\";\nimport { HydratedRouter } from \"react-router/dom\";\nimport { createElement } from \"react\";\n\nstartTransition(() => {\n  hydrateRoot(document, createElement(HydratedRouter));\n});\n"
  },
  {
    "path": "reflex/.templates/web/app/routes.js",
    "content": "import { route } from \"@react-router/dev/routes\";\nimport { flatRoutes } from \"@react-router/fs-routes\";\n\nexport default [\n  ...(await flatRoutes({\n    ignoredRouteFiles: [\"routes/\\\\[404\\\\]._index.jsx\"],\n  })),\n  route(\"*\", \"routes/[404]._index.jsx\"),\n];\n"
  },
  {
    "path": "reflex/.templates/web/components/reflex/radix_themes_color_mode_provider.js",
    "content": "import { useTheme } from \"$/utils/react-theme\";\nimport { createElement, useEffect } from \"react\";\nimport { ColorModeContext, defaultColorMode } from \"$/utils/context\";\n\nexport default function RadixThemesColorModeProvider({ children }) {\n  const { theme, resolvedTheme, setTheme } = useTheme();\n\n  const toggleColorMode = () => {\n    setTheme(resolvedTheme === \"light\" ? \"dark\" : \"light\");\n  };\n\n  const setColorMode = (mode) => {\n    const allowedModes = [\"light\", \"dark\", \"system\"];\n    if (!allowedModes.includes(mode)) {\n      console.error(\n        `Invalid color mode \"${mode}\". Defaulting to \"${defaultColorMode}\".`,\n      );\n      mode = defaultColorMode;\n    }\n    setTheme(mode);\n  };\n\n  useEffect(() => {\n    const radixRoot = document.querySelector(\n      '.radix-themes[data-is-root-theme=\"true\"]',\n    );\n    if (radixRoot) {\n      radixRoot.classList.remove(\"light\", \"dark\");\n      radixRoot.classList.add(resolvedTheme);\n    }\n  }, [resolvedTheme]);\n\n  return createElement(\n    ColorModeContext.Provider,\n    {\n      value: {\n        rawColorMode: theme,\n        resolvedColorMode: resolvedTheme,\n        toggleColorMode,\n        setColorMode,\n      },\n    },\n    children,\n  );\n}\n"
  },
  {
    "path": "reflex/.templates/web/components/shiki/code.js",
    "content": "import { useEffect, useState, createElement } from \"react\";\nimport { codeToHtml } from \"shiki\";\n\n/**\n * Code component that uses Shiki to convert code to HTML and render it.\n *\n * @param code - The code to be highlighted.\n * @param theme - The theme to be used for highlighting.\n * @param language - The language of the code.\n * @param transformers - The transformers to be applied to the code.\n * @param decorations - The decorations to be applied to the code.\n * @param divProps - Additional properties to be passed to the div element.\n * @returns The rendered code block.\n */\nexport function Code({\n  code,\n  theme,\n  language,\n  transformers,\n  decorations,\n  ...divProps\n}) {\n  const [codeResult, setCodeResult] = useState(\"\");\n  useEffect(() => {\n    async function fetchCode() {\n      const result = await codeToHtml(code, {\n        lang: language,\n        theme,\n        transformers,\n        decorations,\n      });\n      setCodeResult(result);\n    }\n    fetchCode();\n  }, [code, language, theme, transformers, decorations]);\n  return createElement(\"div\", {\n    dangerouslySetInnerHTML: { __html: codeResult },\n    ...divProps,\n  });\n}\n"
  },
  {
    "path": "reflex/.templates/web/jsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    \"paths\": {\n      \"$/*\": [\"*\"],\n      \"@/*\": [\"public/*\"]\n    }\n  }\n}\n"
  },
  {
    "path": "reflex/.templates/web/postcss.config.js",
    "content": "export default {\n  plugins: {\n    \"postcss-import\": {},\n    autoprefixer: {},\n  },\n};\n"
  },
  {
    "path": "reflex/.templates/web/react-router.config.js",
    "content": "export default {\n  future: {\n    unstable_optimizeDeps: true,\n  },\n  ssr: false,\n};\n"
  },
  {
    "path": "reflex/.templates/web/styles/__reflex_style_reset.css",
    "content": "@layer __reflex_base {\n  /*\n    1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)\n    2. Remove default margins and padding\n    3. Reset all borders.\n  */\n\n  *,\n  ::after,\n  ::before,\n  ::backdrop,\n  ::file-selector-button {\n    box-sizing: border-box; /* 1 */\n    margin: 0; /* 2 */\n    padding: 0; /* 2 */\n    border: 0 solid; /* 3 */\n  }\n\n  /*\n    1. Use a consistent sensible line-height in all browsers.\n    2. Prevent adjustments of font size after orientation changes in iOS.\n    3. Use a more readable tab size.\n    4. Use the user's configured `sans` font-family by default.\n    5. Use the user's configured `sans` font-feature-settings by default.\n    6. Use the user's configured `sans` font-variation-settings by default.\n    7. Disable tap highlights on iOS.\n  */\n\n  html,\n  :host {\n    line-height: 1.5; /* 1 */\n    -webkit-text-size-adjust: 100%; /* 2 */\n    tab-size: 4; /* 3 */\n    font-family:\n      --default-font-family, ui-sans-serif, system-ui, sans-serif,\n      \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\",\n      \"Noto Color Emoji\"; /* 4 */\n    font-feature-settings: --default-font-feature-settings, normal; /* 5 */\n    font-variation-settings: --default-font-variation-settings, normal; /* 6 */\n    -webkit-tap-highlight-color: transparent; /* 7 */\n  }\n\n  /*\n    1. Add the correct height in Firefox.\n    2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)\n    3. Reset the default border style to a 1px solid border.\n  */\n\n  hr {\n    height: 0; /* 1 */\n    color: inherit; /* 2 */\n    border-top-width: 1px; /* 3 */\n  }\n\n  /*\n    Add the correct text decoration in Chrome, Edge, and Safari.\n  */\n\n  abbr:where([title]) {\n    -webkit-text-decoration: underline dotted;\n    text-decoration: underline dotted;\n  }\n\n  /*\n    Remove the default font size and weight for headings.\n  */\n\n  h1,\n  h2,\n  h3,\n  h4,\n  h5,\n  h6 {\n    font-size: inherit;\n    font-weight: inherit;\n  }\n\n  /*\n    Reset links to optimize for opt-in styling instead of opt-out.\n  */\n\n  a {\n    color: inherit;\n    -webkit-text-decoration: inherit;\n    text-decoration: inherit;\n  }\n\n  /*\n    Add the correct font weight in Edge and Safari.\n  */\n\n  b,\n  strong {\n    font-weight: bolder;\n  }\n\n  /*\n    1. Use the user's configured `mono` font-family by default.\n    2. Use the user's configured `mono` font-feature-settings by default.\n    3. Use the user's configured `mono` font-variation-settings by default.\n    4. Correct the odd `em` font sizing in all browsers.\n  */\n\n  code,\n  kbd,\n  samp,\n  pre {\n    font-family:\n      --default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco,\n      Consolas, \"Liberation Mono\", \"Courier New\", monospace; /* 1 */\n    font-feature-settings: --default-mono-font-feature-settings, normal; /* 2 */\n    font-variation-settings:\n      --default-mono-font-variation-settings, normal; /* 3 */\n    font-size: 1em; /* 4 */\n  }\n\n  /*\n    Add the correct font size in all browsers.\n  */\n\n  small {\n    font-size: 80%;\n  }\n\n  /*\n    Prevent `sub` and `sup` elements from affecting the line height in all browsers.\n  */\n\n  sub,\n  sup {\n    font-size: 75%;\n    line-height: 0;\n    position: relative;\n    vertical-align: baseline;\n  }\n\n  sub {\n    bottom: -0.25em;\n  }\n\n  sup {\n    top: -0.5em;\n  }\n\n  /*\n    1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)\n    2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)\n    3. Remove gaps between table borders by default.\n  */\n\n  table {\n    text-indent: 0; /* 1 */\n    border-color: inherit; /* 2 */\n    border-collapse: collapse; /* 3 */\n  }\n\n  /*\n    Use the modern Firefox focus style for all focusable elements.\n  */\n\n  :-moz-focusring {\n    outline: auto;\n  }\n\n  /*\n    Add the correct vertical alignment in Chrome and Firefox.\n  */\n\n  progress {\n    vertical-align: baseline;\n  }\n\n  /*\n    Add the correct display in Chrome and Safari.\n  */\n\n  summary {\n    display: list-item;\n  }\n\n  /*\n    Make lists unstyled by default.\n  */\n\n  ol,\n  ul,\n  menu {\n    list-style: none;\n  }\n\n  /*\n    1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)\n    2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)\n       This can trigger a poorly considered lint error in some tools but is included by design.\n  */\n\n  img,\n  svg,\n  video,\n  canvas,\n  audio,\n  iframe,\n  embed,\n  object {\n    display: block; /* 1 */\n    vertical-align: middle; /* 2 */\n  }\n\n  /*\n    Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)\n  */\n\n  img,\n  video {\n    max-width: 100%;\n    height: auto;\n  }\n\n  /*\n    1. Inherit font styles in all browsers.\n    2. Remove border radius in all browsers.\n    3. Remove background color in all browsers.\n    4. Ensure consistent opacity for disabled states in all browsers.\n  */\n\n  button,\n  input,\n  select,\n  optgroup,\n  textarea,\n  ::file-selector-button {\n    font: inherit; /* 1 */\n    font-feature-settings: inherit; /* 1 */\n    font-variation-settings: inherit; /* 1 */\n    letter-spacing: inherit; /* 1 */\n    color: inherit; /* 1 */\n    border-radius: 0; /* 2 */\n    background-color: transparent; /* 3 */\n    opacity: 1; /* 4 */\n  }\n\n  /*\n    Restore default font weight.\n  */\n\n  :where(select:is([multiple], [size])) optgroup {\n    font-weight: bolder;\n  }\n\n  /*\n    Restore indentation.\n  */\n\n  :where(select:is([multiple], [size])) optgroup option {\n    padding-inline-start: 20px;\n  }\n\n  /*\n    Restore space after button.\n  */\n\n  ::file-selector-button {\n    margin-inline-end: 4px;\n  }\n\n  /*\n    Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)\n  */\n\n  ::placeholder {\n    opacity: 1;\n  }\n\n  /*\n    Set the default placeholder color to a semi-transparent version of the current text color in browsers that do not\n    crash when using `color-mix(…)` with `currentcolor`. (https://github.com/tailwindlabs/tailwindcss/issues/17194)\n  */\n\n  @supports (not (-webkit-appearance: -apple-pay-button)) /* Not Safari */ or\n    (contain-intrinsic-size: 1px) /* Safari 17+ */ {\n    ::placeholder {\n      color: color-mix(in oklab, currentcolor 50%, transparent);\n    }\n  }\n\n  /*\n    Prevent resizing textareas horizontally by default.\n  */\n\n  textarea {\n    resize: vertical;\n  }\n\n  /*\n    Remove the inner padding in Chrome and Safari on macOS.\n  */\n\n  ::-webkit-search-decoration {\n    -webkit-appearance: none;\n  }\n\n  /*\n    1. Ensure date/time inputs have the same height when empty in iOS Safari.\n    2. Ensure text alignment can be changed on date/time inputs in iOS Safari.\n  */\n\n  ::-webkit-date-and-time-value {\n    min-height: 1lh; /* 1 */\n    text-align: inherit; /* 2 */\n  }\n\n  /*\n    Prevent height from changing on date/time inputs in macOS Safari when the input is set to `display: block`.\n  */\n\n  ::-webkit-datetime-edit {\n    display: inline-flex;\n  }\n\n  /*\n    Remove excess padding from pseudo-elements in date/time inputs to ensure consistent height across browsers.\n  */\n\n  ::-webkit-datetime-edit-fields-wrapper {\n    padding: 0;\n  }\n\n  ::-webkit-datetime-edit,\n  ::-webkit-datetime-edit-year-field,\n  ::-webkit-datetime-edit-month-field,\n  ::-webkit-datetime-edit-day-field,\n  ::-webkit-datetime-edit-hour-field,\n  ::-webkit-datetime-edit-minute-field,\n  ::-webkit-datetime-edit-second-field,\n  ::-webkit-datetime-edit-millisecond-field,\n  ::-webkit-datetime-edit-meridiem-field {\n    padding-block: 0;\n  }\n\n  /*\n    Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)\n  */\n\n  :-moz-ui-invalid {\n    box-shadow: none;\n  }\n\n  /*\n    Correct the inability to style the border radius in iOS Safari.\n  */\n\n  button,\n  input:where([type=\"button\"], [type=\"reset\"], [type=\"submit\"]),\n  ::file-selector-button {\n    appearance: button;\n  }\n\n  /*\n    Correct the cursor style of increment and decrement buttons in Safari.\n  */\n\n  ::-webkit-inner-spin-button,\n  ::-webkit-outer-spin-button {\n    height: auto;\n  }\n\n  /*\n    Make elements with the HTML hidden attribute stay hidden by default.\n  */\n\n  [hidden]:where(:not([hidden=\"until-found\"])) {\n    display: none !important;\n  }\n}\n"
  },
  {
    "path": "reflex/.templates/web/utils/helpers/dataeditor.js",
    "content": "import { GridCellKind } from \"@glideapps/glide-data-grid\";\n\nexport function getDEColumn(columns, col) {\n  let c = columns[col];\n  c.pos = col;\n  return c;\n}\n\nexport function getDERow(data, row) {\n  return data[row];\n}\n\nexport function locateCell(row, column) {\n  if (Array.isArray(row)) {\n    return row[column.pos];\n  } else {\n    return row[column.id];\n  }\n}\n\nexport function formatCell(value, column) {\n  const editable = column.editable ?? true;\n  switch (column.type) {\n    case \"int\":\n    case \"float\":\n      return {\n        kind: GridCellKind.Number,\n        data: value,\n        displayData: value + \"\",\n        readonly: !editable,\n        allowOverlay: editable,\n      };\n    case \"datetime\":\n    // value = moment format?\n    case \"str\":\n      return {\n        kind: GridCellKind.Text,\n        data: value,\n        displayData: value,\n        readonly: !editable,\n        allowOverlay: editable,\n      };\n    case \"bool\":\n      return {\n        kind: GridCellKind.Boolean,\n        data: value,\n        readonly: !editable,\n      };\n    default:\n      console.log(\n        \"Warning: column.type is undefined for column.title=\" + column.title,\n      );\n      return {\n        kind: GridCellKind.Text,\n        data: value,\n        displayData: column.type,\n      };\n  }\n}\n\nexport function formatDataEditorCells(col, row, columns, data) {\n  if (row < data.length && col < columns.length) {\n    const column = getDEColumn(columns, col);\n    const rowData = getDERow(data, row);\n    const cellData = locateCell(rowData, column);\n    return formatCell(cellData, column);\n  }\n  return { kind: GridCellKind.Loading };\n}\n"
  },
  {
    "path": "reflex/.templates/web/utils/helpers/debounce.js",
    "content": "const debounce_timeout_id = {};\n\n/**\n * Generic debounce helper\n *\n * @param {string} name - the name of the event to debounce\n * @param {function} func - the function to call after debouncing\n * @param {number} delay - the time in milliseconds to wait before calling the function\n */\nexport default function debounce(name, func, delay) {\n  const key = `${name}__${delay}`;\n  clearTimeout(debounce_timeout_id[key]);\n  debounce_timeout_id[key] = setTimeout(() => {\n    func();\n    delete debounce_timeout_id[key];\n  }, delay);\n}\n"
  },
  {
    "path": "reflex/.templates/web/utils/helpers/paste.js",
    "content": "import { useEffect, useRef } from \"react\";\n\nconst handle_paste_data = (clipboardData) =>\n  new Promise((resolve, reject) => {\n    const pasted_data = [];\n    const n_items = clipboardData.items.length;\n    const extract_data = (item) => {\n      const type = item.type;\n      if (item.kind === \"string\") {\n        item.getAsString((data) => {\n          pasted_data.push([type, data]);\n          if (pasted_data.length === n_items) {\n            resolve(pasted_data);\n          }\n        });\n      } else if (item.kind === \"file\") {\n        const file = item.getAsFile();\n        const reader = new FileReader();\n        reader.onload = (e) => {\n          pasted_data.push([type, e.target.result]);\n          if (pasted_data.length === n_items) {\n            resolve(pasted_data);\n          }\n        };\n        if (type.indexOf(\"text/\") === 0) {\n          reader.readAsText(file);\n        } else {\n          reader.readAsDataURL(file);\n        }\n      }\n    };\n    for (const item of clipboardData.items) {\n      extract_data(item);\n    }\n  });\n\nexport default function usePasteHandler(target_ids, event_actions, on_paste) {\n  const onPasteRef = useRef(on_paste);\n  const eventActionsRef = useRef(event_actions);\n\n  useEffect(() => {\n    onPasteRef.current = on_paste;\n  }, [on_paste]);\n  useEffect(() => {\n    eventActionsRef.current = event_actions;\n  }, [event_actions]);\n\n  useEffect(() => {\n    const handle_paste = (_ev) => {\n      eventActionsRef.current?.preventDefault && _ev.preventDefault();\n      eventActionsRef.current?.stopPropagation && _ev.stopPropagation();\n      handle_paste_data(_ev.clipboardData).then(onPasteRef.current);\n    };\n\n    let cleanupListeners = null;\n    let observer = null;\n\n    const attachListeners = (targets) => {\n      targets.forEach((target) =>\n        target.addEventListener(\"paste\", handle_paste, false),\n      );\n      return () => {\n        targets.forEach((target) =>\n          target.removeEventListener(\"paste\", handle_paste, false),\n        );\n      };\n    };\n\n    const tryAttach = () => {\n      if (target_ids.length === 0) {\n        cleanupListeners = attachListeners([document]);\n        return true;\n      }\n      const targets = target_ids\n        .map((id) => document.getElementById(id))\n        .filter((element) => !!element);\n\n      if (targets.length === target_ids.length) {\n        cleanupListeners = attachListeners(targets);\n        return true;\n      }\n\n      return false;\n    };\n\n    if (!tryAttach()) {\n      observer = new MutationObserver(() => {\n        if (tryAttach()) {\n          observer.disconnect();\n          observer = null;\n        }\n      });\n      observer.observe(document.body, { childList: true, subtree: true });\n    }\n\n    return () => {\n      if (observer) {\n        observer.disconnect();\n      }\n      if (cleanupListeners) {\n        cleanupListeners();\n      }\n    };\n  }, [target_ids]);\n}\n"
  },
  {
    "path": "reflex/.templates/web/utils/helpers/range.js",
    "content": "/**\n * Simulate the python range() builtin function.\n * inspired by https://dev.to/guyariely/using-python-range-in-javascript-337p\n *\n * If needed outside of an iterator context, use `Array.from(range(10))` or\n * spread syntax `[...range(10)]` to get an array.\n *\n * @param {number} start: the start or end of the range.\n * @param {number} stop: the end of the range.\n * @param {number} step: the step of the range.\n * @returns {object} an object with a Symbol.iterator method over the range\n */\nexport default function range(start, stop, step) {\n  return {\n    [Symbol.iterator]() {\n      if (stop === undefined) {\n        stop = start;\n        start = 0;\n      }\n      if (step === undefined) {\n        step = 1;\n      }\n\n      let i = start - step;\n\n      return {\n        next() {\n          i += step;\n          if ((step > 0 && i < stop) || (step < 0 && i > stop)) {\n            return {\n              value: i,\n              done: false,\n            };\n          }\n          return {\n            value: undefined,\n            done: true,\n          };\n        },\n      };\n    },\n  };\n}\n"
  },
  {
    "path": "reflex/.templates/web/utils/helpers/throttle.js",
    "content": "const in_throttle = {};\n\n/**\n * Generic throttle helper\n *\n * @param {string} name - the name of the event to throttle\n * @param {number} limit - time in milliseconds between events\n * @returns true if the event is allowed to execute, false if it is throttled\n */\nexport default function throttle(name, limit) {\n  const key = `${name}__${limit}`;\n  if (!in_throttle[key]) {\n    in_throttle[key] = true;\n\n    setTimeout(() => {\n      delete in_throttle[key];\n    }, limit);\n    // function was not throttled, so allow execution\n    return true;\n  }\n  return false;\n}\n"
  },
  {
    "path": "reflex/.templates/web/utils/helpers/upload.js",
    "content": "import JSON5 from \"json5\";\nimport env from \"$/env.json\";\n\n/**\n * Upload files to the server.\n *\n * @param state The state to apply the delta to.\n * @param handler The handler to use.\n * @param upload_id The upload id to use.\n * @param on_upload_progress The function to call on upload progress.\n * @param socket the websocket connection\n * @param extra_headers Extra headers to send with the request.\n * @param refs The refs object to store the abort controller in.\n * @param getBackendURL Function to get the backend URL.\n * @param getToken Function to get the Reflex token.\n *\n * @returns The response from posting to the UPLOADURL endpoint.\n */\nexport const uploadFiles = async (\n  handler,\n  files,\n  upload_id,\n  on_upload_progress,\n  extra_headers,\n  socket,\n  refs,\n  getBackendURL,\n  getToken,\n) => {\n  // return if there's no file to upload\n  if (files === undefined || files.length === 0) {\n    return false;\n  }\n\n  const upload_ref_name = `__upload_controllers_${upload_id}`;\n\n  if (refs[upload_ref_name]) {\n    console.log(\"Upload already in progress for \", upload_id);\n    return false;\n  }\n\n  // Track how many partial updates have been processed for this upload.\n  let resp_idx = 0;\n  const eventHandler = (progressEvent) => {\n    const event_callbacks = socket._callbacks.$event;\n    // Whenever called, responseText will contain the entire response so far.\n    const chunks = progressEvent.event.target.responseText.trim().split(\"\\n\");\n    // So only process _new_ chunks beyond resp_idx.\n    chunks.slice(resp_idx).map((chunk_json) => {\n      try {\n        const chunk = JSON5.parse(chunk_json);\n        event_callbacks.map((f, ix) => {\n          f(chunk)\n            .then(() => {\n              if (ix === event_callbacks.length - 1) {\n                // Mark this chunk as processed.\n                resp_idx += 1;\n              }\n            })\n            .catch((e) => {\n              if (progressEvent.progress === 1) {\n                // Chunk may be incomplete, so only report errors when full response is available.\n                console.log(\"Error processing chunk\", chunk, e);\n              }\n              return;\n            });\n        });\n      } catch (e) {\n        if (progressEvent.progress === 1) {\n          console.log(\"Error parsing chunk\", chunk_json, e);\n        }\n        return;\n      }\n    });\n  };\n\n  const controller = new AbortController();\n  const formdata = new FormData();\n\n  // Add the token and handler to the file name.\n  files.forEach((file) => {\n    formdata.append(\"files\", file, file.path || file.name);\n  });\n\n  // Send the file to the server.\n  refs[upload_ref_name] = controller;\n\n  return new Promise((resolve, reject) => {\n    const xhr = new XMLHttpRequest();\n\n    // Set up event handlers\n    xhr.onload = function () {\n      if (xhr.status >= 200 && xhr.status < 300) {\n        resolve({\n          data: xhr.responseText,\n          status: xhr.status,\n          statusText: xhr.statusText,\n          headers: {\n            get: (name) => xhr.getResponseHeader(name),\n          },\n        });\n      } else {\n        reject(new Error(`HTTP error! status: ${xhr.status}`));\n      }\n    };\n\n    xhr.onerror = function () {\n      reject(new Error(\"Network error\"));\n    };\n\n    xhr.onabort = function () {\n      reject(new Error(\"Upload aborted\"));\n    };\n\n    // Handle upload progress\n    if (on_upload_progress) {\n      xhr.upload.onprogress = function (event) {\n        if (event.lengthComputable) {\n          const progressEvent = {\n            loaded: event.loaded,\n            total: event.total,\n            progress: event.loaded / event.total,\n          };\n          on_upload_progress(progressEvent);\n        }\n      };\n    }\n\n    // Handle download progress with streaming response parsing\n    xhr.onprogress = function (event) {\n      if (eventHandler) {\n        const progressEvent = {\n          event: {\n            target: {\n              responseText: xhr.responseText,\n            },\n          },\n          progress: event.lengthComputable ? event.loaded / event.total : 0,\n        };\n        eventHandler(progressEvent);\n      }\n    };\n\n    // Handle abort controller\n    controller.signal.addEventListener(\"abort\", () => {\n      xhr.abort();\n    });\n\n    // Configure and send request\n    xhr.open(\"POST\", getBackendURL(env.UPLOAD));\n    xhr.setRequestHeader(\"Reflex-Client-Token\", getToken());\n    xhr.setRequestHeader(\"Reflex-Event-Handler\", handler);\n    for (const [key, value] of Object.entries(extra_headers || {})) {\n      xhr.setRequestHeader(key, value);\n    }\n\n    try {\n      xhr.send(formdata);\n    } catch (error) {\n      reject(error);\n    }\n  })\n    .catch((error) => {\n      console.log(\"Upload error:\", error.message);\n      return false;\n    })\n    .finally(() => {\n      delete refs[upload_ref_name];\n    });\n};\n"
  },
  {
    "path": "reflex/.templates/web/utils/react-theme.js",
    "content": "import {\n  createContext,\n  useContext,\n  useState,\n  useEffect,\n  createElement,\n  useRef,\n  useMemo,\n} from \"react\";\n\nimport { isDevMode, defaultColorMode } from \"$/utils/context\";\n\nconst ThemeContext = createContext({\n  theme: defaultColorMode,\n  resolvedTheme: defaultColorMode !== \"system\" ? defaultColorMode : \"light\",\n  setTheme: () => {},\n});\n\nexport function ThemeProvider({ children, defaultTheme = \"system\" }) {\n  const [theme, setTheme] = useState(defaultTheme);\n  const [systemTheme, setSystemTheme] = useState(\n    defaultTheme !== \"system\" ? defaultTheme : \"light\",\n  );\n  const [isInitialized, setIsInitialized] = useState(false);\n\n  const firstRender = useRef(true);\n\n  useEffect(() => {\n    if (!firstRender.current) {\n      return;\n    }\n\n    firstRender.current = false;\n\n    if (isDevMode) {\n      const lastCompiledTheme = localStorage.getItem(\"last_compiled_theme\");\n      if (lastCompiledTheme !== defaultColorMode) {\n        // on app startup, make sure the application color mode is persisted correctly.\n        localStorage.setItem(\"last_compiled_theme\", defaultColorMode);\n        setIsInitialized(true);\n        return;\n      }\n    }\n\n    // Load saved theme from localStorage\n    const savedTheme = localStorage.getItem(\"theme\") || defaultTheme;\n    setTheme(savedTheme);\n    setIsInitialized(true);\n  });\n\n  const resolvedTheme = useMemo(\n    () => (theme === \"system\" ? systemTheme : theme),\n    [theme, systemTheme],\n  );\n\n  useEffect(() => {\n    // Set up media query for system preference detection\n    const mediaQuery = window.matchMedia(\"(prefers-color-scheme: dark)\");\n\n    // Listen for system preference changes\n    const handleChange = () => {\n      setSystemTheme(mediaQuery.matches ? \"dark\" : \"light\");\n    };\n\n    handleChange();\n\n    mediaQuery.addEventListener(\"change\", handleChange);\n\n    return () => {\n      mediaQuery.removeEventListener(\"change\", handleChange);\n    };\n  });\n\n  // Save theme to localStorage whenever it changes\n  // Skip saving only if theme key already exists and we haven't initialized yet\n  useEffect(() => {\n    const existingTheme = localStorage.getItem(\"theme\");\n    if (!isInitialized && existingTheme !== null) return;\n    localStorage.setItem(\"theme\", theme);\n  }, [theme]);\n\n  useEffect(() => {\n    if (!isInitialized) return;\n    const root = window.document.documentElement;\n    root.classList.remove(\"light\", \"dark\");\n    root.classList.add(resolvedTheme);\n    root.style.colorScheme = resolvedTheme;\n  }, [resolvedTheme, isInitialized]);\n\n  return createElement(\n    ThemeContext.Provider,\n    { value: { theme, resolvedTheme, setTheme } },\n    children,\n  );\n}\n\nexport function useTheme() {\n  return useContext(ThemeContext);\n}\n"
  },
  {
    "path": "reflex/.templates/web/utils/state.js",
    "content": "// State management for Reflex web apps.\nimport io from \"socket.io-client\";\nimport JSON5 from \"json5\";\nimport env from \"$/env.json\";\nimport reflexEnvironment from \"$/reflex.json\";\nimport Cookies from \"universal-cookie\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n  useLocation,\n  useNavigate,\n  useSearchParams,\n  useParams,\n} from \"react-router\";\nimport {\n  initialEvents,\n  initialState,\n  onLoadInternalEvent,\n  state_name,\n  exception_state_name,\n} from \"$/utils/context\";\nimport debounce from \"$/utils/helpers/debounce\";\nimport throttle from \"$/utils/helpers/throttle\";\nimport { uploadFiles } from \"$/utils/helpers/upload\";\n\n// Endpoint URLs.\nconst EVENTURL = env.EVENT;\n\n// These hostnames indicate that the backend and frontend are reachable via the same domain.\nconst SAME_DOMAIN_HOSTNAMES = [\"localhost\", \"0.0.0.0\", \"::\", \"0:0:0:0:0:0:0:0\"];\n\n// Global variable to hold the token.\nlet token;\n\n// Key for the token in the session storage.\nconst TOKEN_KEY = \"token\";\n\n// create cookie instance\nconst cookies = new Cookies();\n\n// Dictionary holding component references.\nexport const refs = {};\n\n// Flag ensures that only one event is processing on the backend concurrently.\nlet event_processing = false;\n// Array holding pending events to be processed.\nconst event_queue = [];\n\n/**\n * Generate a UUID (Used for session tokens).\n * Taken from: https://stackoverflow.com/questions/105034/how-do-i-create-a-guid-uuid\n * @returns A UUID.\n */\nexport const generateUUID = () => {\n  let d = new Date().getTime(),\n    d2 = (performance && performance.now && performance.now() * 1000) || 0;\n  return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\n    let r = Math.random() * 16;\n    if (d > 0) {\n      r = ((d + r) % 16) | 0;\n      d = Math.floor(d / 16);\n    } else {\n      r = ((d2 + r) % 16) | 0;\n      d2 = Math.floor(d2 / 16);\n    }\n    return (c == \"x\" ? r : (r & 0x7) | 0x8).toString(16);\n  });\n};\n\n/**\n * Get the token for the current session.\n * @returns The token.\n */\nexport const getToken = () => {\n  if (token) {\n    return token;\n  }\n  if (typeof window !== \"undefined\") {\n    if (!window.sessionStorage.getItem(TOKEN_KEY)) {\n      window.sessionStorage.setItem(TOKEN_KEY, generateUUID());\n    }\n    token = window.sessionStorage.getItem(TOKEN_KEY);\n  }\n  return token;\n};\n\n/**\n * Get the URL for the backend server\n * @param url_str The URL string to parse.\n * @returns The given URL modified to point to the actual backend server.\n */\nexport const getBackendURL = (url_str) => {\n  if ((url_str ?? undefined) === undefined) {\n    url_str = env.PING;\n  }\n  // Get backend URL object from the endpoint.\n  const endpoint = new URL(url_str);\n  if (\n    typeof window !== \"undefined\" &&\n    SAME_DOMAIN_HOSTNAMES.includes(endpoint.hostname)\n  ) {\n    // Use the frontend domain to access the backend\n    const frontend_hostname = window.location.hostname;\n    endpoint.hostname = frontend_hostname;\n    if (window.location.protocol === \"https:\") {\n      if (endpoint.protocol === \"ws:\") {\n        endpoint.protocol = \"wss:\";\n      } else if (endpoint.protocol === \"http:\") {\n        endpoint.protocol = \"https:\";\n      }\n      endpoint.port = \"\"; // Assume websocket is on https port via load balancer.\n    }\n  }\n  return endpoint;\n};\n\n/**\n * Check if the backend is disabled.\n *\n * @returns True if the backend is disabled, false otherwise.\n */\nexport const isBackendDisabled = () => {\n  const cookie = document.cookie\n    .split(\"; \")\n    .find((row) => row.startsWith(\"backend-enabled=\"));\n  return cookie !== undefined && cookie.split(\"=\")[1] == \"false\";\n};\n\n/**\n * Determine if any event in the event queue is stateful.\n *\n * @returns True if there's any event that requires state and False if none of them do.\n */\nexport const isStateful = () => {\n  if (event_queue.length === 0) {\n    return false;\n  }\n  return event_queue.some((event) => event.name.startsWith(\"reflex___state\"));\n};\n\n/**\n * Apply a delta to the state.\n * @param state The state to apply the delta to.\n * @param delta The delta to apply.\n */\nexport const applyDelta = (state, delta) => {\n  return { ...state, ...delta };\n};\n\n/**\n * Evaluate a dynamic component.\n * @param component The component to evaluate.\n * @returns The evaluated component.\n */\nexport const evalReactComponent = async (component) => {\n  if (!window.React && window.__reflex) {\n    window.React = window.__reflex.react;\n  }\n  const encodedJs = encodeURIComponent(component);\n  const dataUri = \"data:text/javascript;charset=utf-8,\" + encodedJs;\n  const module = await eval(`import(dataUri)`);\n  return module.default;\n};\n\n/**\n * Only Queue and process events when websocket connection exists.\n * @param event The event to queue.\n * @param socket The socket object to send the event on.\n * @param navigate The navigate function from React Router\n * @param params The params object from React Router\n *\n * @returns Adds event to queue and processes it if websocket exits, does nothing otherwise.\n */\nexport const queueEventIfSocketExists = async (\n  events,\n  socket,\n  navigate,\n  params,\n) => {\n  if (!socket) {\n    return;\n  }\n  await queueEvents(events, socket, false, navigate, params);\n};\n\n/**\n * Check if a string is a valid HTTP URL.\n * @param string The string to check.\n *\n * @returns The URL object if valid, undefined otherwise.\n * */\nfunction urlFrom(string) {\n  try {\n    return new URL(string);\n  } catch {\n    return undefined;\n  }\n  return undefined;\n}\n\n/**\n * Handle frontend event or send the event to the backend via Websocket.\n * @param event The event to send.\n * @param socket The socket object to send the event on.\n * @param navigate The navigate function from useNavigate\n * @param params The params object from useParams\n *\n * @returns True if the event was sent, false if it was handled locally.\n */\nexport const applyEvent = async (event, socket, navigate, params) => {\n  // Handle special events\n  if (event.name == \"_redirect\") {\n    if ((event.payload.path ?? undefined) === undefined) {\n      return false;\n    }\n    if (event.payload.external) {\n      window.open(\n        event.payload.path,\n        \"_blank\",\n        \"noopener\" + (event.payload.popup ? \",popup\" : \"\"),\n      );\n      return false;\n    }\n    const url = urlFrom(event.payload.path);\n    let pathname = event.payload.path;\n    if (url) {\n      if (url.host !== window.location.host) {\n        // External URL\n        window.location.assign(event.payload.path);\n        return false;\n      } else {\n        pathname = url.pathname + url.search + url.hash;\n      }\n    }\n    if (event.payload.replace) {\n      navigate(pathname, { replace: true });\n    } else {\n      navigate(pathname);\n    }\n    return false;\n  }\n\n  if (event.name == \"_remove_cookie\") {\n    cookies.remove(event.payload.key, { ...event.payload.options });\n    queueEventIfSocketExists(initialEvents(), socket, navigate, params);\n    return false;\n  }\n\n  if (event.name == \"_clear_local_storage\") {\n    localStorage.clear();\n    queueEventIfSocketExists(initialEvents(), socket, navigate, params);\n    return false;\n  }\n\n  if (event.name == \"_remove_local_storage\") {\n    localStorage.removeItem(event.payload.key);\n    queueEventIfSocketExists(initialEvents(), socket, navigate, params);\n    return false;\n  }\n\n  if (event.name == \"_clear_session_storage\") {\n    sessionStorage.clear();\n    queueEventIfSocketExists(initialEvents(), socket, navigate, params);\n    return false;\n  }\n\n  if (event.name == \"_remove_session_storage\") {\n    sessionStorage.removeItem(event.payload.key);\n    queueEventIfSocketExists(initialEvents(), socket, navigate, params);\n    return false;\n  }\n\n  if (event.name == \"_download\") {\n    const a = document.createElement(\"a\");\n    a.hidden = true;\n    a.href = event.payload.url;\n    // Special case when linking to uploaded files\n    if (a.href.includes(\"getBackendURL(env.UPLOAD)\")) {\n      a.href = eval?.(\n        event.payload.url.replace(\n          \"getBackendURL(env.UPLOAD)\",\n          `\"${getBackendURL(env.UPLOAD)}\"`,\n        ),\n      );\n    }\n    a.download = event.payload.filename;\n    a.click();\n    a.remove();\n    return false;\n  }\n\n  if (event.name == \"_set_focus\") {\n    const ref =\n      event.payload.ref in refs ? refs[event.payload.ref] : event.payload.ref;\n    const current = ref?.current;\n    if (current === undefined || current?.focus === undefined) {\n      console.error(\n        `No element found for ref ${event.payload.ref} in _set_focus`,\n      );\n    } else {\n      current.focus();\n    }\n    return false;\n  }\n\n  if (event.name == \"_blur_focus\") {\n    const ref =\n      event.payload.ref in refs ? refs[event.payload.ref] : event.payload.ref;\n    const current = ref?.current;\n    if (current === undefined || current?.blur === undefined) {\n      console.error(\n        `No element found for ref ${event.payload.ref} in _blur_focus`,\n      );\n    } else {\n      current.blur();\n    }\n    return false;\n  }\n\n  if (event.name == \"_set_value\") {\n    const ref =\n      event.payload.ref in refs ? refs[event.payload.ref] : event.payload.ref;\n    if (ref.current) {\n      ref.current.value = event.payload.value;\n    }\n    return false;\n  }\n\n  if (\n    event.name == \"_call_function\" &&\n    typeof event.payload.function !== \"string\"\n  ) {\n    try {\n      const eval_result = event.payload.function();\n      if (event.payload.callback) {\n        const final_result =\n          !!eval_result && typeof eval_result.then === \"function\"\n            ? await eval_result\n            : eval_result;\n        const callback =\n          typeof event.payload.callback === \"string\"\n            ? eval(event.payload.callback)\n            : event.payload.callback;\n        callback(final_result);\n      }\n    } catch (e) {\n      console.log(\"_call_function\", e);\n      if (window && window?.onerror) {\n        window.onerror(e.message, null, null, null, e);\n      }\n    }\n    return false;\n  }\n\n  if (event.name == \"_call_script\" || event.name == \"_call_function\") {\n    try {\n      const eval_result =\n        event.name == \"_call_script\"\n          ? eval(event.payload.javascript_code)\n          : eval(event.payload.function)();\n\n      if (event.payload.callback) {\n        const final_result =\n          !!eval_result && typeof eval_result.then === \"function\"\n            ? await eval_result\n            : eval_result;\n        const callback =\n          typeof event.payload.callback === \"string\"\n            ? eval(event.payload.callback)\n            : event.payload.callback;\n        callback(final_result);\n      }\n    } catch (e) {\n      console.log(\"_call_script\", e);\n      if (window && window?.onerror) {\n        window.onerror(e.message, null, null, null, e);\n      }\n    }\n    return false;\n  }\n\n  // Update token and router data (if missing).\n  event.token = getToken();\n  if (\n    event.router_data === undefined ||\n    Object.keys(event.router_data).length === 0\n  ) {\n    // Since we don't have router directly, we need to get info from our hooks\n    event.router_data = {\n      pathname: window.location.pathname,\n      query: {\n        ...Object.fromEntries(new URLSearchParams(window.location.search)),\n        ...params(),\n      },\n      asPath:\n        window.location.pathname +\n        window.location.search +\n        window.location.hash,\n    };\n  }\n\n  // Send the event to the server.\n  if (socket) {\n    socket.emit(\"event\", event);\n    return true;\n  }\n\n  return false;\n};\n\n/**\n * Send an event to the server via REST.\n * @param event The current event.\n * @param socket The socket object to send the response event(s) on.\n * @param navigate The navigate function from React Router\n * @param params The params object from React Router\n *\n * @returns Whether the event was sent.\n */\nexport const applyRestEvent = async (event, socket, navigate, params) => {\n  let eventSent = false;\n  if (event.handler === \"uploadFiles\") {\n    if (event.payload.files === undefined || event.payload.files.length === 0) {\n      // Submit the event over the websocket to trigger the event handler.\n      return await applyEvent(\n        ReflexEvent(event.name, { files: [] }),\n        socket,\n        navigate,\n        params,\n      );\n    }\n\n    // Start upload, but do not wait for it, which would block other events.\n    uploadFiles(\n      event.name,\n      event.payload.files,\n      event.payload.upload_id,\n      event.payload.on_upload_progress,\n      event.payload.extra_headers,\n      socket,\n      refs,\n      getBackendURL,\n      getToken,\n    );\n    return false;\n  }\n  return eventSent;\n};\n\n/**\n * Resolve a socket reference to the actual socket object.\n * Handles both ref objects ({ current: Socket }) and raw sockets.\n * @param socket Either a ref object or raw socket.\n * @returns The actual socket object.\n */\nconst resolveSocket = (socket) => {\n  return socket?.current ?? socket;\n};\n\n/**\n * Queue events to be processed and trigger processing of queue.\n * @param events Array of events to queue.\n * @param socket The socket object to send the event on.\n * @param prepend Whether to place the events at the beginning of the queue.\n * @param navigate The navigate function from React Router\n * @param params The params object from React Router\n */\nexport const queueEvents = async (\n  events,\n  socket,\n  prepend,\n  navigate,\n  params,\n) => {\n  if (prepend) {\n    // Drain the existing queue and place it after the given events.\n    events = [\n      ...events,\n      ...Array.from({ length: event_queue.length }).map(() =>\n        event_queue.shift(),\n      ),\n    ];\n  }\n  event_queue.push(...events.filter((e) => e !== undefined && e !== null));\n  await processEvent(resolveSocket(socket), navigate, params);\n};\n\n/**\n * Process an event off the event queue.\n * @param socket The socket object to send the event on.\n * @param navigate The navigate function from React Router\n * @param params The params object from React Router\n */\nexport const processEvent = async (socket, navigate, params) => {\n  // Only proceed if the socket is up or no event in the queue uses state, otherwise we throw the event into the void\n  if (isStateful() && !(socket && socket.connected)) {\n    return;\n  }\n\n  // Only proceed if we're not already processing an event.\n  if (event_queue.length === 0 || event_processing) {\n    return;\n  }\n\n  // Set processing to true to block other events from being processed.\n  event_processing = true;\n\n  // Apply the next event in the queue.\n  const event = event_queue.shift();\n\n  let eventSent = false;\n  // Process events with handlers via REST and all others via websockets.\n  if (event.handler) {\n    eventSent = await applyRestEvent(event, socket, navigate, params);\n  } else {\n    eventSent = await applyEvent(event, socket, navigate, params);\n  }\n  // If no event was sent, set processing to false.\n  if (!eventSent) {\n    event_processing = false;\n    // recursively call processEvent to drain the queue, since there is\n    // no state update to trigger the useEffect event loop.\n    await processEvent(socket, navigate, params);\n  }\n};\n\n/**\n * Connect to a websocket and set the handlers.\n * @param socket The socket object to connect.\n * @param dispatch The function to queue state update\n * @param transports The transports to use.\n * @param setConnectErrors The function to update connection error value.\n * @param client_storage The client storage object from context.js\n * @param navigate The navigate function from React Router\n * @param params The params object from React Router\n */\nexport const connect = async (\n  socket,\n  dispatch,\n  transports,\n  setConnectErrors,\n  client_storage = {},\n  navigate,\n  params,\n) => {\n  // Socket already allocated, just reconnect it if needed.\n  if (socket.current) {\n    if (!socket.current.connected) {\n      socket.current.reconnect();\n    }\n    return;\n  }\n\n  // Get backend URL object from the endpoint.\n  const endpoint = getBackendURL(EVENTURL);\n  const on_hydrated_queue = [];\n\n  // Create the socket.\n  socket.current = io(endpoint.href, {\n    path: endpoint[\"pathname\"],\n    transports: transports,\n    protocols: [reflexEnvironment.version],\n    autoUnref: false,\n    query: { token: getToken() },\n    reconnection: false, // Reconnection will be handled manually.\n  });\n  socket.current.wait_connect = !socket.current.connected;\n  // Ensure undefined fields in events are sent as null instead of removed\n  socket.current.io.encoder.replacer = (k, v) => (v === undefined ? null : v);\n  socket.current.io.decoder.tryParse = (str) => {\n    try {\n      return JSON5.parse(str);\n    } catch (e) {\n      return false;\n    }\n  };\n  // Set up a reconnect helper function\n  socket.current.reconnect = () => {\n    if (\n      socket.current &&\n      !socket.current.connected &&\n      !socket.current.wait_connect\n    ) {\n      socket.current.wait_connect = true;\n      socket.current.rehydrate = true;\n      socket.current.io.opts.query = { token: getToken() }; // Update token for reconnect.\n      socket.current.connect();\n    }\n  };\n\n  function checkVisibility() {\n    if (document.visibilityState === \"visible\") {\n      if (!socket.current) {\n        connect(\n          socket,\n          dispatch,\n          transports,\n          setConnectErrors,\n          client_storage,\n          navigate,\n          params,\n        );\n      } else if (!socket.current.connected) {\n        console.log(\"Socket is disconnected, attempting to reconnect \");\n        socket.current.reconnect();\n      } else {\n        console.log(\"Socket is reconnected \");\n      }\n    }\n  }\n\n  const disconnectTrigger = (event) => {\n    if (socket.current?.connected) {\n      console.log(\"Disconnect websocket on unload\");\n      socket.current.disconnect();\n    }\n  };\n\n  const pagehideHandler = (event) => {\n    if (event.persisted && socket.current?.connected) {\n      console.log(\"Disconnect backend before bfcache on navigation\");\n      socket.current.disconnect();\n    }\n  };\n\n  // Once the socket is open, hydrate the page.\n  socket.current.on(\"connect\", async () => {\n    socket.current.wait_connect = false;\n    setConnectErrors([]);\n    window.addEventListener(\"pagehide\", pagehideHandler);\n    window.addEventListener(\"beforeunload\", disconnectTrigger);\n    window.addEventListener(\"unload\", disconnectTrigger);\n    if (socket.current.rehydrate) {\n      socket.current.rehydrate = false;\n      queueEvents(\n        initialEvents(),\n        socket,\n        true,\n        navigate,\n        () => params.current,\n      );\n    }\n    // Drain any initial events from the queue.\n    while (event_queue.length > 0 && !event_processing) {\n      await processEvent(socket.current, navigate, () => params.current);\n    }\n  });\n\n  socket.current.on(\"connect_error\", (error) => {\n    socket.current.wait_connect = false;\n    let n_connect_errors = 0;\n    setConnectErrors((connectErrors) => {\n      const new_errors = [...connectErrors.slice(-9), error];\n      n_connect_errors = new_errors.length;\n      return new_errors;\n    });\n    window.setTimeout(() => {\n      if (socket.current && !socket.current.connected) {\n        socket.current.reconnect();\n      }\n    }, 200 * n_connect_errors); // Incremental backoff\n  });\n\n  // When the socket disconnects reset the event_processing flag\n  socket.current.on(\"disconnect\", (reason, details) => {\n    socket.current.wait_connect = false;\n    const try_reconnect =\n      reason !== \"io server disconnect\" && reason !== \"io client disconnect\";\n    event_processing = false;\n    window.removeEventListener(\"unload\", disconnectTrigger);\n    window.removeEventListener(\"beforeunload\", disconnectTrigger);\n    window.removeEventListener(\"pagehide\", pagehideHandler);\n    if (try_reconnect) {\n      // Attempt to reconnect transient non-intentional disconnects.\n      socket.current.reconnect();\n    }\n  });\n\n  // On each received message, queue the updates and events.\n  socket.current.on(\"event\", async (update) => {\n    for (const substate in update.delta) {\n      dispatch[substate](update.delta[substate]);\n      // handle events waiting for `is_hydrated`\n      if (\n        substate === state_name &&\n        update.delta[substate]?.is_hydrated_rx_state_\n      ) {\n        queueEvents(on_hydrated_queue, socket, false, navigate, params);\n        on_hydrated_queue.length = 0;\n      }\n    }\n    applyClientStorageDelta(client_storage, update.delta);\n    if (update.final !== null) {\n      event_processing = !update.final;\n    }\n    if (update.events) {\n      queueEvents(update.events, socket, false, navigate, params);\n    }\n  });\n  socket.current.on(\"reload\", async (event) => {\n    event_processing = false;\n    on_hydrated_queue.push(event);\n    queueEvents(initialEvents(), socket, true, navigate, params);\n  });\n  socket.current.on(\"new_token\", async (new_token) => {\n    token = new_token;\n    window.sessionStorage.setItem(TOKEN_KEY, new_token);\n  });\n\n  document.addEventListener(\"visibilitychange\", checkVisibility);\n};\n\n/**\n * Create an event object.\n * @param {string} name The name of the event.\n * @param {Object.<string, Any>} payload The payload of the event.\n * @param {Object.<string, (number|boolean)>} event_actions The actions to take on the event.\n * @param {string} handler The client handler to process event.\n * @returns The event object.\n */\nexport const ReflexEvent = (\n  name,\n  payload = {},\n  event_actions = {},\n  handler = null,\n) => {\n  return { name, payload, handler, event_actions };\n};\n\n/**\n * Package client-side storage values as payload to send to the\n * backend with the hydrate event\n * @param client_storage The client storage object from context.js\n * @returns payload dict of client storage values\n */\nexport const hydrateClientStorage = (client_storage) => {\n  const client_storage_values = {};\n  if (client_storage.cookies) {\n    for (const state_key in client_storage.cookies) {\n      const cookie_options = client_storage.cookies[state_key];\n      const cookie_name = cookie_options.name || state_key;\n      const cookie_value = cookies.get(cookie_name, { doNotParse: true });\n      if (cookie_value !== undefined) {\n        client_storage_values[state_key] = cookie_value;\n      }\n    }\n  }\n  if (client_storage.local_storage && typeof window !== \"undefined\") {\n    for (const state_key in client_storage.local_storage) {\n      const options = client_storage.local_storage[state_key];\n      const local_storage_value = localStorage.getItem(\n        options.name || state_key,\n      );\n      if (local_storage_value !== null) {\n        client_storage_values[state_key] = local_storage_value;\n      }\n    }\n  }\n  if (client_storage.session_storage && typeof window != \"undefined\") {\n    for (const state_key in client_storage.session_storage) {\n      const session_options = client_storage.session_storage[state_key];\n      const session_storage_value = sessionStorage.getItem(\n        session_options.name || state_key,\n      );\n      if (session_storage_value != null) {\n        client_storage_values[state_key] = session_storage_value;\n      }\n    }\n  }\n  if (\n    client_storage.cookies ||\n    client_storage.local_storage ||\n    client_storage.session_storage\n  ) {\n    return client_storage_values;\n  }\n  return {};\n};\n\n/**\n * Update client storage values based on backend state delta.\n * @param client_storage The client storage object from context.js\n * @param delta The state update from the backend\n */\nconst applyClientStorageDelta = (client_storage, delta) => {\n  // find the main state and check for is_hydrated\n  const unqualified_states = Object.keys(delta).filter(\n    (key) => key.split(\".\").length === 1,\n  );\n  if (unqualified_states.length === 1) {\n    const main_state = delta[unqualified_states[0]];\n    if (\n      main_state.is_hydrated_rx_state_ !== undefined &&\n      !main_state.is_hydrated_rx_state_\n    ) {\n      // skip if the state is not hydrated yet, since all client storage\n      // values are sent in the hydrate event\n      return;\n    }\n  }\n  // Save known client storage values to cookies and localStorage.\n  for (const substate in delta) {\n    for (const key in delta[substate]) {\n      const state_key = `${substate}.${key}`;\n      if (client_storage.cookies && state_key in client_storage.cookies) {\n        const cookie_options = { ...client_storage.cookies[state_key] };\n        const cookie_name = cookie_options.name || state_key;\n        delete cookie_options.name; // name is not a valid cookie option\n        cookies.set(cookie_name, delta[substate][key], cookie_options);\n      } else if (\n        client_storage.local_storage &&\n        state_key in client_storage.local_storage &&\n        typeof window !== \"undefined\"\n      ) {\n        const options = client_storage.local_storage[state_key];\n        localStorage.setItem(options.name || state_key, delta[substate][key]);\n      } else if (\n        client_storage.session_storage &&\n        state_key in client_storage.session_storage &&\n        typeof window !== \"undefined\"\n      ) {\n        const session_options = client_storage.session_storage[state_key];\n        sessionStorage.setItem(\n          session_options.name || state_key,\n          delta[substate][key],\n        );\n      }\n    }\n  }\n};\n\n/**\n * Establish websocket event loop for a React Router page.\n * @param dispatch The reducer dispatch function to update state.\n * @param initial_events The initial app events.\n * @param client_storage The client storage object from context.js\n *\n * @returns [addEvents, connectErrors] -\n *   addEvents is used to queue an event, and\n *   connectErrors is an array of reactive js error from the websocket connection (or null if connected).\n */\nexport const useEventLoop = (\n  dispatch,\n  initial_events = () => [],\n  client_storage = {},\n) => {\n  const socket = useRef(null);\n  const location = useLocation();\n  const navigate = useNavigate();\n  const paramsR = useParams();\n  const prevLocationRef = useRef(location);\n  const [searchParams] = useSearchParams();\n  const [connectErrors, setConnectErrors] = useState([]);\n  const params = useRef(paramsR);\n  const mounted = useRef(false);\n\n  useEffect(() => {\n    const { \"*\": splat, ...remainingParams } = paramsR;\n    if (splat) {\n      params.current = { ...remainingParams, splat: splat.split(\"/\") };\n    } else {\n      params.current = remainingParams;\n    }\n  }, [paramsR]);\n\n  const ensureSocketConnected = useCallback(async () => {\n    if (!mounted.current) {\n      // During hot reload, some components may still have a reference to\n      // addEvents, so avoid reconnecting the socket of an unmounted event loop.\n      return;\n    }\n    // only use websockets if state is present and backend is not disabled (reflex cloud).\n    if (\n      Object.keys(initialState).length > 1 &&\n      !isBackendDisabled() &&\n      !socket.current?.connected\n    ) {\n      // Initialize the websocket connection.\n      await connect(\n        socket,\n        dispatch,\n        [env.TRANSPORT],\n        setConnectErrors,\n        client_storage,\n        navigate,\n        () => params.current,\n      );\n    }\n  }, [\n    socket,\n    dispatch,\n    setConnectErrors,\n    client_storage,\n    navigate,\n    params,\n    mounted,\n  ]);\n\n  // Function to add new events to the event queue.\n  const addEvents = useCallback((events, args, event_actions) => {\n    const _events = events.filter((e) => e !== undefined && e !== null);\n    if (!event_actions?.temporal) {\n      // Reconnect socket if needed for non-temporal events.\n      ensureSocketConnected();\n    }\n\n    if (!(args instanceof Array)) {\n      args = [args];\n    }\n\n    event_actions = _events.reduce(\n      (acc, e) => ({ ...acc, ...e.event_actions }),\n      event_actions ?? {},\n    );\n\n    const _e = args.filter((o) => o?.preventDefault !== undefined)[0];\n\n    if (event_actions?.preventDefault && _e?.preventDefault) {\n      _e.preventDefault();\n    }\n    if (event_actions?.stopPropagation && _e?.stopPropagation) {\n      _e.stopPropagation();\n    }\n    const combined_name = _events.map((e) => e.name).join(\"+++\");\n    if (event_actions?.temporal) {\n      if (!socket.current || !socket.current.connected) {\n        return; // don't queue when the backend is not connected\n      }\n    }\n    if (event_actions?.throttle) {\n      // If throttle returns false, the events are not added to the queue.\n      if (!throttle(combined_name, event_actions.throttle)) {\n        return;\n      }\n    }\n    if (event_actions?.debounce) {\n      // If debounce is used, queue the events after some delay\n      debounce(\n        combined_name,\n        () =>\n          queueEvents(_events, socket, false, navigate, () => params.current),\n        event_actions.debounce,\n      );\n    } else {\n      queueEvents(_events, socket, false, navigate, () => params.current);\n    }\n  }, []);\n\n  const sentHydrate = useRef(false); // Avoid double-hydrate due to React strict-mode\n  useEffect(() => {\n    if (!sentHydrate.current) {\n      queueEvents(\n        initial_events(),\n        socket,\n        true,\n        navigate,\n        () => params.current,\n      );\n      sentHydrate.current = true;\n    }\n  }, []);\n\n  // Handle frontend errors and send them to the backend via websocket.\n  useEffect(() => {\n    if (typeof window === \"undefined\") {\n      return;\n    }\n\n    window.onerror = function (msg, url, lineNo, columnNo, error) {\n      addEvents([\n        ReflexEvent(`${exception_state_name}.handle_frontend_exception`, {\n          info: error.name + \": \" + error.message + \"\\n\" + error.stack,\n          component_stack: \"\",\n        }),\n      ]);\n      return false;\n    };\n\n    //NOTE: Only works in Chrome v49+\n    //https://github.com/mknichel/javascript-errors?tab=readme-ov-file#promise-rejection-events\n    window.onunhandledrejection = function (event) {\n      addEvents([\n        ReflexEvent(`${exception_state_name}.handle_frontend_exception`, {\n          info:\n            event.reason?.name +\n            \": \" +\n            event.reason?.message +\n            \"\\n\" +\n            event.reason?.stack,\n          component_stack: \"\",\n        }),\n      ]);\n      return false;\n    };\n  }, []);\n\n  // Handle socket connect/disconnect.\n  useEffect(() => {\n    // Initialize the websocket connection.\n    mounted.current = true;\n    ensureSocketConnected();\n\n    // Cleanup function.\n    return () => {\n      mounted.current = false;\n      if (socket.current) {\n        socket.current.disconnect();\n        socket.current.off();\n        socket.current = null;\n      }\n    };\n  }, []);\n\n  // Main event loop.\n  useEffect(() => {\n    // Skip if the backend is disabled\n    if (isBackendDisabled() || !socket.current || !socket.current.connected) {\n      return;\n    }\n    (async () => {\n      // Process all outstanding events.\n      while (event_queue.length > 0 && !event_processing) {\n        await ensureSocketConnected();\n        await processEvent(socket.current, navigate, () => params.current);\n      }\n    })();\n  });\n\n  // localStorage event handling\n  useEffect(() => {\n    const storage_to_state_map = {};\n\n    if (client_storage.local_storage && typeof window !== \"undefined\") {\n      for (const state_key in client_storage.local_storage) {\n        const options = client_storage.local_storage[state_key];\n        if (options.sync) {\n          const local_storage_value_key = options.name || state_key;\n          storage_to_state_map[local_storage_value_key] = state_key;\n        }\n      }\n    }\n\n    // e is StorageEvent\n    const handleStorage = (e) => {\n      if (storage_to_state_map[e.key]) {\n        const vars = {};\n        vars[storage_to_state_map[e.key]] = e.newValue;\n        const event = ReflexEvent(\n          `${state_name}.reflex___state____update_vars_internal_state.update_vars_internal`,\n          { vars: vars },\n        );\n        addEvents([event], e);\n      }\n    };\n\n    window.addEventListener(\"storage\", handleStorage);\n    return () => window.removeEventListener(\"storage\", handleStorage);\n  });\n\n  const handleNavigationEvents = useRef(false);\n  // Route after the initial page hydration\n  useEffect(() => {\n    // The first time this effect runs is initial load, so don't handle\n    // any navigation events.\n    if (!handleNavigationEvents.current) {\n      handleNavigationEvents.current = true;\n      return;\n    }\n    if (location.state?.fromNotFound) {\n      // If the redirect is from a 404 page, we skip onLoadInternalEvent,\n      // since it was already run when the 404 page was first rendered.\n      return;\n    }\n    // This will run when the location changes\n    if (\n      location.pathname + location.search ===\n      prevLocationRef.current.pathname + prevLocationRef.current.search\n    ) {\n      if (location.hash) {\n        // If the hash is the same, we don't need to do anything.\n        return;\n      }\n    }\n\n    // Equivalent to routeChangeStart - runs when navigation begins\n    const main_state_dispatch = dispatch[\"reflex___state____state\"];\n    if (main_state_dispatch !== undefined) {\n      main_state_dispatch({ is_hydrated_rx_state_: false });\n    }\n\n    // Equivalent to routeChangeComplete - runs after navigation completes\n    addEvents(onLoadInternalEvent());\n\n    // Update the ref\n    prevLocationRef.current = location;\n  }, [location, dispatch, onLoadInternalEvent, addEvents]);\n\n  return [addEvents, connectErrors];\n};\n\n/***\n * Check if a value is truthy in python.\n * @param val The value to check.\n * @returns True if the value is truthy, false otherwise.\n */\nexport const isTrue = (val) => {\n  if (Array.isArray(val)) return val.length > 0;\n  if (val === Object(val)) return Object.keys(val).length > 0;\n  return Boolean(val);\n};\n\n/***\n * Check if a value is not null or undefined.\n * @param val The value to check.\n * @returns True if the value is not null or undefined, false otherwise.\n */\nexport const isNotNullOrUndefined = (val) => {\n  return (val ?? undefined) !== undefined;\n};\n\n/**\n * Get the value from a ref.\n * @param ref The ref to get the value from.\n * @returns The value.\n */\nexport const getRefValue = (ref) => {\n  if (!ref || !ref.current) {\n    return;\n  }\n  if (ref.current.type == \"checkbox\") {\n    return ref.current.checked; // chakra\n  } else if (\n    ref.current.className?.includes(\"rt-CheckboxRoot\") ||\n    ref.current.className?.includes(\"rt-SwitchRoot\")\n  ) {\n    return ref.current.ariaChecked == \"true\"; // radix\n  } else if (ref.current.className?.includes(\"rt-SliderRoot\")) {\n    // find the actual slider\n    return ref.current.querySelector(\".rt-SliderThumb\")?.ariaValueNow;\n  } else {\n    //querySelector(\":checked\") is needed to get value from radio_group\n    return (\n      ref.current.value ||\n      (ref.current.querySelector &&\n        ref.current.querySelector(\":checked\") &&\n        ref.current.querySelector(\":checked\")?.value)\n    );\n  }\n};\n\n/**\n * Get the values from a ref array.\n * @param refs The refs to get the values from.\n * @returns The values array.\n */\nexport const getRefValues = (refs) => {\n  if (!refs) {\n    return;\n  }\n  // getAttribute is used by RangeSlider because it doesn't assign value\n  return refs.map((ref) =>\n    ref.current\n      ? ref.current.value || ref.current.getAttribute(\"aria-valuenow\")\n      : null,\n  );\n};\n\n/**\n * Spread two arrays or two objects.\n * @param first The first array or object.\n * @param second The second array or object.\n * @returns The final merged array or object.\n */\nexport const spreadArraysOrObjects = (first, second) => {\n  if (Array.isArray(first) && Array.isArray(second)) {\n    return [...first, ...second];\n  } else if (typeof first === \"object\" && typeof second === \"object\") {\n    return { ...first, ...second };\n  } else {\n    throw new Error(\"Both parameters must be either arrays or objects.\");\n  }\n};\n"
  },
  {
    "path": "reflex/.templates/web/vite-plugin-safari-cachebust.js",
    "content": "/* vite-plugin-safari-cachebust.js\n *\n * Rewrite modulepreload <link> tags and ESM imports to include a cache-busting\n * query parameter for Safari browser.\n *\n * https://github.com/remix-run/react-router/issues/12761\n *\n * The issue seems to be Safari over-aggressive caching of ESM imports (and modulepreload)\n * which does not respect the cache-control headers sent by the server. This approach\n * allows hot reload to work in Safari when adding routes or changing dependencies.\n *\n * No equivalent transformation is needed for production builds, as the\n * output already contains the file hash in the name.\n */\n\n/**\n * @typedef {import('vite').Plugin} Plugin\n * @typedef {import('vite').ViteDevServer} ViteDevServer\n * @typedef {import('http').IncomingMessage} IncomingMessage\n * @typedef {import('http').ServerResponse} ServerResponse\n * @typedef {import('connect').NextHandleFunction} NextHandleFunction\n */\n\nconst pluginName = \"vite-plugin-safari-cachebust\";\n\n/**\n * Creates a Vite plugin that adds cache-busting for Safari browsers\n * @returns {Plugin} The Vite plugin\n */\nexport default function safariCacheBustPlugin() {\n  return {\n    name: pluginName,\n    /**\n     * Configure the dev server with the Safari middleware\n     * @param {ViteDevServer} server - The Vite dev server instance\n     */\n    configureServer(server) {\n      server.middlewares.use(createSafariMiddleware());\n    },\n  };\n}\n\n/**\n * Determines if the user agent is Safari\n * @param {string} ua - The user agent string\n * @returns {boolean} True if the browser is Safari\n */\nfunction isSafari(ua) {\n  return /Safari/.test(ua) && !/Chrome/.test(ua);\n}\n\n/**\n * Creates a middleware that adds cache-busting for Safari browsers\n * @returns {NextHandleFunction} The middleware function\n */\nfunction createSafariMiddleware() {\n  // Set when a log message for rewriting n links has been emitted.\n  let _have_logged_n = -1;\n\n  /**\n   * Rewrites module import links in HTML content with cache-busting parameters\n   * @param {string} html - The HTML content to process\n   * @returns {string} The processed HTML content\n   */\n  function rewriteModuleImports(html) {\n    const currentTimestamp = new Date().getTime();\n    const parts = html.split(/(<link\\s+rel=\"modulepreload\"[^>]*>)/g);\n    /** @type {[string, string][]} */\n    const replacements = parts\n      .map((chunk) => {\n        const match = chunk.match(\n          /<link\\s+rel=\"modulepreload\"\\s+href=\"([^\"]+)\"(.*?)\\/?>/,\n        );\n        if (!match) return;\n\n        const [fullMatch, href, rest] = match;\n        if (/^(https?:)?\\/\\//.test(href)) return;\n\n        try {\n          const newHref = href.includes(\"?\")\n            ? `${href}&__reflex_ts=${currentTimestamp}`\n            : `${href}?__reflex_ts=${currentTimestamp}`;\n          return [href, newHref];\n        } catch {\n          // no worries;\n        }\n      })\n      .filter(Boolean);\n    if (replacements.length && _have_logged_n !== replacements.length) {\n      _have_logged_n = replacements.length;\n      console.debug(\n        `[${pluginName}] Rewrote ${replacements.length} modulepreload links with __reflex_ts param.`,\n      );\n    }\n    return replacements.reduce((accumulator, [target, replacement]) => {\n      return accumulator.split(target).join(replacement);\n    }, html);\n  }\n\n  /**\n   * Middleware function to handle Safari cache busting\n   * @param {IncomingMessage} req - The incoming request\n   * @param {ServerResponse} res - The server response\n   * @param {(err?: any) => void} next - The next middleware function\n   * @returns {void}\n   */\n  return function safariCacheBustMiddleware(req, res, next) {\n    const ua = req.headers[\"user-agent\"] || \"\";\n    // Remove our special cache bust query param to avoid affecting lower middleware layers.\n    if (\n      req.url &&\n      (req.url.includes(\"?__reflex_ts=\") || req.url.includes(\"&__reflex_ts=\"))\n    ) {\n      req.url = req.url.replace(/(\\?|&)__reflex_ts=\\d+/, \"\");\n      return next();\n    }\n\n    // Only apply this middleware for Safari browsers.\n    if (!isSafari(ua)) return next();\n\n    // Only transform requests that want HTML.\n    const header_accept = req.headers[\"accept\"] || \"\";\n    if (\n      typeof header_accept !== \"string\" ||\n      !header_accept.includes(\"text/html\")\n    ) {\n      return next();\n    }\n\n    let buffer = \"\";\n    const _end = res.end.bind(res);\n\n    res.setHeader(\"x-modified-by\", \"vite-plugin-safari-cachebust\");\n    /**\n     * Overridden write method to collect chunks\n     * @param {any} chunk - The chunk to write\n     * @param {...any} args - Additional arguments\n     * @returns {boolean} Result of the write operation\n     */\n    res.write = function (chunk, ...args) {\n      buffer += chunk instanceof Buffer ? chunk.toString(\"utf-8\") : chunk;\n      return true;\n    };\n\n    /**\n     * Overridden end method to process and send the final response\n     * @param {any} chunk - The final chunk to write\n     * @param {...any} args - Additional arguments\n     * @returns {ServerResponse<IncomingMessage>} The server response\n     */\n    res.end = function (chunk, ...args) {\n      if (chunk) {\n        buffer += chunk instanceof Buffer ? chunk.toString(\"utf-8\") : chunk;\n      }\n      buffer = rewriteModuleImports(buffer);\n      return _end(buffer, ...args);\n    };\n    return next();\n  };\n}\n"
  },
  {
    "path": "reflex/__init__.py",
    "content": "\"\"\"Import all classes and functions the end user will need to make an app.\n\nAnything imported here will be available in the default Reflex import as `rx.*`.\n\nDynamic Imports\n---------------\nReflex utilizes dynamic imports, or lazy loading, to reduce startup/import times.\nWith this approach, imports are delayed until they are actually needed. We use\nthe `lazy_loader` library(https://github.com/scientific-python/lazy_loader) to achieve this.\n\nHow it works\n--------------\n`lazy_loader.attach` takes two optional arguments: `submodules` and `submod_attrs`.\n- `submodules` typically points to directories or files to be accessed.\n- `submod_attrs` defines a mapping of directory or file names as keys with a list\n  of attributes or modules to access.\n\nExample directory structure:\n\nreflex/\n    |_ components/\n            |_ radix/\n                |_ themes/\n                    |_ components/\n                        |_ box.py\n\nTo add `box` under the `rx` namespace (`rx.box`), add the relative path to `submod_attrs` in\n`reflex/__init__.py` (this file):\n\n```python\nlazy_loader.attach(\n    submodules={\"components\"},\n    submod_attrs={\n        \"components.radix.themes.components.box\": [\"box\"]\n    }\n)\n```\n\nThis implies that `box` will be imported from `reflex/components/radix/themes/components/box.py`.\n\nTo add box under the `rx.radix` namespace (`rx.radix.box`), add the relative path to the\nsubmod_attrs argument in `reflex/components/radix/__init__.py`:\n\n```python\nlazy_loader.attach(\n    submodules = {\"themes\"},\n    submod_attrs = {\n        \"themes.components.box\": [\"box\"]\n    }\n)\n```\n\nNote: It is important to specify the immediate submodules of a directory in the submodules\nargument to ensure they are registered at runtime. For example, 'components' for reflex,\n'radix' for components, 'themes' for radix, etc.\n\n\nPyi_generator\n--------------\nTo generate `.pyi` files for `__init__.py` files, we read the `_SUBMODULES` and `_SUBMOD_ATTRS`\nattributes to generate the import statements. It is highly recommended to define these with\nthe provided annotations to facilitate their generation.\n\n\nAliases\n------------\nThis is a special case to specify an alias for a component.\nAs an example, we use this typically for `rx.list` where defining `list` attribute in the list.py\novershadows python's list object which messes up the pyi generation for `list.pyi`. As a result, aliases\nshould be used for similar cases like this. Note that this logic is employed to fix the pyi generation and alias\nshould still be defined or accessible. Check out the __getattr__ logic in `reflex/components/radix/themes/layouts/list.py`\n\n```python\nlazy_loader.attach(\n    submodules={\"components\"},\n    submod_attrs={\n        \"components.radix.themes.layouts\": [(\"list_ns\", \"list\")]\n    }\n)\n```\n\nIn the example above, you will be able to do `rx.list`\n\"\"\"\n\nfrom __future__ import annotations\n\nimport sys\n\nfrom reflex.utils import lazy_loader\n\nif sys.version_info < (3, 11):\n    from reflex.utils import console\n\n    console.warn(\n        \"Reflex support for Python 3.10 is deprecated and will be removed in a future release. Please upgrade to Python 3.11 or higher for continued support.\"\n    )\n    del console\ndel sys\n\nRADIX_THEMES_MAPPING: dict = {\n    \"components.radix.themes.base\": [\"color_mode\", \"theme\", \"theme_panel\"],\n    \"components.radix.themes.color_mode\": [\"color_mode\"],\n}\nRADIX_THEMES_COMPONENTS_MAPPING: dict = {\n    **{\n        f\"components.radix.themes.components.{mod}\": [mod]\n        for mod in [\n            \"alert_dialog\",\n            \"aspect_ratio\",\n            \"avatar\",\n            \"badge\",\n            \"button\",\n            \"callout\",\n            \"card\",\n            \"checkbox\",\n            \"context_menu\",\n            \"data_list\",\n            \"dialog\",\n            \"hover_card\",\n            \"icon_button\",\n            \"input\",\n            \"inset\",\n            \"popover\",\n            \"scroll_area\",\n            \"select\",\n            \"skeleton\",\n            \"slider\",\n            \"spinner\",\n            \"switch\",\n            \"table\",\n            \"tabs\",\n            \"text_area\",\n            \"tooltip\",\n            \"segmented_control\",\n            \"radio_cards\",\n            \"checkbox_cards\",\n            \"checkbox_group\",\n        ]\n    },\n    \"components.radix.themes.components.text_field\": [\"text_field\", \"input\"],\n    \"components.radix.themes.components.radio_group\": [\"radio\", \"radio_group\"],\n    \"components.radix.themes.components.dropdown_menu\": [\"menu\", \"dropdown_menu\"],\n    \"components.radix.themes.components.separator\": [\"divider\", \"separator\"],\n    \"components.radix.themes.components.progress\": [\"progress\"],\n}\n\nRADIX_THEMES_LAYOUT_MAPPING: dict = {\n    \"components.radix.themes.layout.box\": [\n        \"box\",\n    ],\n    \"components.radix.themes.layout.center\": [\n        \"center\",\n    ],\n    \"components.radix.themes.layout.container\": [\n        \"container\",\n    ],\n    \"components.radix.themes.layout.flex\": [\n        \"flex\",\n    ],\n    \"components.radix.themes.layout.grid\": [\n        \"grid\",\n    ],\n    \"components.radix.themes.layout.section\": [\n        \"section\",\n    ],\n    \"components.radix.themes.layout.spacer\": [\n        \"spacer\",\n    ],\n    \"components.radix.themes.layout.stack\": [\n        \"stack\",\n        \"hstack\",\n        \"vstack\",\n    ],\n    \"components.radix.themes.layout.list\": [\n        (\"list_ns\", \"list\"),\n        \"list_item\",\n        \"ordered_list\",\n        \"unordered_list\",\n    ],\n}\n\nRADIX_THEMES_TYPOGRAPHY_MAPPING: dict = {\n    \"components.radix.themes.typography.blockquote\": [\n        \"blockquote\",\n    ],\n    \"components.radix.themes.typography.code\": [\n        \"code\",\n    ],\n    \"components.radix.themes.typography.heading\": [\n        \"heading\",\n    ],\n    \"components.radix.themes.typography.link\": [\n        \"link\",\n    ],\n    \"components.radix.themes.typography.text\": [\n        \"text\",\n    ],\n}\n\nRADIX_PRIMITIVES_MAPPING: dict = {\n    \"components.radix.primitives.accordion\": [\n        \"accordion\",\n    ],\n    \"components.radix.primitives.drawer\": [\n        \"drawer\",\n    ],\n    \"components.radix.primitives.form\": [\n        \"form\",\n    ],\n    \"components.radix.primitives.progress\": [\n        \"progress\",\n    ],\n}\n\nRADIX_PRIMITIVES_SHORTCUT_MAPPING: dict = {\n    k: v for k, v in RADIX_PRIMITIVES_MAPPING.items() if \"progress\" not in k\n}\n\nCOMPONENTS_CORE_MAPPING: dict = {\n    \"components.core.banner\": [\n        \"connection_banner\",\n        \"connection_modal\",\n    ],\n    \"components.core.cond\": [\"cond\", \"color_mode_cond\"],\n    \"components.core.foreach\": [\"foreach\"],\n    \"components.core.debounce\": [\"debounce_input\"],\n    \"components.core.html\": [\"html\"],\n    \"components.core.match\": [\"match\"],\n    \"components.core.clipboard\": [\"clipboard\"],\n    \"components.core.colors\": [\"color\"],\n    \"components.core.breakpoints\": [\"breakpoints\"],\n    \"components.core.responsive\": [\n        \"desktop_only\",\n        \"mobile_and_tablet\",\n        \"mobile_only\",\n        \"tablet_and_desktop\",\n        \"tablet_only\",\n    ],\n    \"components.core.upload\": [\n        \"cancel_upload\",\n        \"clear_selected_files\",\n        \"get_upload_dir\",\n        \"get_upload_url\",\n        \"selected_files\",\n        \"upload\",\n    ],\n    \"components.core.auto_scroll\": [\"auto_scroll\"],\n    \"components.core.window_events\": [\"window_event_listener\"],\n}\n\nCOMPONENTS_BASE_MAPPING: dict = {\n    \"components.base.fragment\": [\"fragment\", \"Fragment\"],\n    \"components.base.script\": [\"script\", \"Script\"],\n}\n\nRADIX_MAPPING: dict = {\n    **RADIX_THEMES_MAPPING,\n    **RADIX_THEMES_COMPONENTS_MAPPING,\n    **RADIX_THEMES_TYPOGRAPHY_MAPPING,\n    **RADIX_THEMES_LAYOUT_MAPPING,\n    **RADIX_PRIMITIVES_SHORTCUT_MAPPING,\n}\n\n_MAPPING: dict = {\n    \"experimental\": [\"_x\"],\n    \"admin\": [\"AdminDash\"],\n    \"app\": [\"App\", \"UploadFile\"],\n    \"assets\": [\"asset\"],\n    \"base\": [\"Base\"],\n    \"components.component\": [\n        \"Component\",\n        \"NoSSRComponent\",\n        \"memo\",\n        \"ComponentNamespace\",\n    ],\n    \"components.el.elements.media\": [\"image\"],\n    \"components.lucide\": [\"icon\"],\n    **COMPONENTS_BASE_MAPPING,\n    \"components\": [\"el\", \"radix\", \"lucide\", \"recharts\"],\n    \"components.markdown\": [\"markdown\"],\n    **RADIX_MAPPING,\n    \"components.plotly\": [\"plotly\"],\n    \"components.react_player\": [\"audio\", \"video\"],\n    **COMPONENTS_CORE_MAPPING,\n    \"components.datadisplay.code\": [\n        \"code_block\",\n    ],\n    \"components.datadisplay.dataeditor\": [\n        \"data_editor\",\n        \"data_editor_theme\",\n    ],\n    \"components.sonner.toast\": [\"toast\"],\n    \"components.props\": [\"PropsBase\"],\n    \"components.datadisplay.logo\": [\"logo\"],\n    \"components.gridjs\": [\"data_table\"],\n    \"components.moment\": [\"MomentDelta\", \"moment\"],\n    \"config\": [\"Config\", \"DBConfig\"],\n    \"constants\": [\"Env\"],\n    \"constants.colors\": [\"Color\"],\n    \"event\": [\n        \"event\",\n        \"EventChain\",\n        \"EventHandler\",\n        \"call_script\",\n        \"call_function\",\n        \"run_script\",\n        \"clear_local_storage\",\n        \"clear_session_storage\",\n        \"console_log\",\n        \"download\",\n        \"noop\",\n        \"prevent_default\",\n        \"redirect\",\n        \"remove_cookie\",\n        \"remove_local_storage\",\n        \"remove_session_storage\",\n        \"set_clipboard\",\n        \"set_focus\",\n        \"scroll_to\",\n        \"set_value\",\n        \"stop_propagation\",\n        \"upload_files\",\n        \"window_alert\",\n    ],\n    \"istate.storage\": [\n        \"Cookie\",\n        \"LocalStorage\",\n        \"SessionStorage\",\n    ],\n    \"middleware\": [\"middleware\", \"Middleware\"],\n    \"model\": [\"asession\", \"session\", \"Model\", \"ModelRegistry\"],\n    \"page\": [\"page\"],\n    \"state\": [\n        \"var\",\n        \"ComponentState\",\n        \"State\",\n        \"dynamic\",\n    ],\n    \"istate.shared\": [\"SharedState\"],\n    \"istate.wrappers\": [\"get_state\"],\n    \"style\": [\"Style\", \"toggle_color_mode\"],\n    \"utils.imports\": [\"ImportDict\", \"ImportVar\"],\n    \"utils.misc\": [\"run_in_thread\"],\n    \"utils.serializers\": [\"serializer\"],\n    \"vars\": [\"Var\", \"field\", \"Field\"],\n}\n\n_SUBMODULES: set[str] = {\n    \"components\",\n    \"app\",\n    \"style\",\n    \"admin\",\n    \"base\",\n    \"model\",\n    \"testing\",\n    \"utils\",\n    \"vars\",\n    \"config\",\n    \"compiler\",\n    \"plugins\",\n}\n_SUBMOD_ATTRS: dict = _MAPPING\ngetattr, __dir__, __all__ = lazy_loader.attach(\n    __name__,\n    submodules=_SUBMODULES,\n    submod_attrs=_SUBMOD_ATTRS,\n)\n\n\ndef __getattr__(name: str):\n    return getattr(name)\n"
  },
  {
    "path": "reflex/__main__.py",
    "content": "\"\"\"reflex package invocation entry point.\"\"\"\n\nfrom .reflex import cli\n\nif __name__ == \"__main__\":\n    cli()\n"
  },
  {
    "path": "reflex/admin.py",
    "content": "\"\"\"The Reflex Admin Dashboard.\"\"\"\n\nfrom __future__ import annotations\n\nfrom dataclasses import dataclass, field\nfrom typing import TYPE_CHECKING\n\nif TYPE_CHECKING:\n    from starlette_admin.base import BaseAdmin as Admin\n\n\n@dataclass\nclass AdminDash:\n    \"\"\"Data used to build the admin dashboard.\"\"\"\n\n    models: list = field(default_factory=list)\n    view_overrides: dict = field(default_factory=dict)\n    admin: Admin | None = None\n"
  },
  {
    "path": "reflex/app.py",
    "content": "\"\"\"The main Reflex app.\"\"\"\n\nfrom __future__ import annotations\n\nimport asyncio\nimport concurrent.futures\nimport contextlib\nimport copy\nimport dataclasses\nimport functools\nimport inspect\nimport json\nimport operator\nimport sys\nimport time\nimport traceback\nimport urllib.parse\nfrom collections.abc import (\n    AsyncGenerator,\n    AsyncIterator,\n    Awaitable,\n    Callable,\n    Coroutine,\n    Mapping,\n    Sequence,\n)\nfrom datetime import datetime\nfrom itertools import chain\nfrom pathlib import Path\nfrom timeit import default_timer as timer\nfrom types import SimpleNamespace\nfrom typing import TYPE_CHECKING, Any, BinaryIO, ParamSpec, get_args, get_type_hints\n\nfrom rich.progress import MofNCompleteColumn, Progress, TimeElapsedColumn\nfrom socketio import ASGIApp as EngineIOApp\nfrom socketio import AsyncNamespace, AsyncServer\nfrom starlette.applications import Starlette\nfrom starlette.datastructures import Headers\nfrom starlette.datastructures import UploadFile as StarletteUploadFile\nfrom starlette.exceptions import HTTPException\nfrom starlette.middleware import cors\nfrom starlette.requests import ClientDisconnect, Request\nfrom starlette.responses import JSONResponse, Response, StreamingResponse\nfrom starlette.staticfiles import StaticFiles\nfrom typing_extensions import Unpack\n\nfrom reflex import constants\nfrom reflex.admin import AdminDash\nfrom reflex.app_mixins import AppMixin, LifespanMixin, MiddlewareMixin\nfrom reflex.compiler import compiler\nfrom reflex.compiler import utils as compiler_utils\nfrom reflex.compiler.compiler import (\n    ExecutorSafeFunctions,\n    compile_theme,\n    readable_name_from_component,\n)\nfrom reflex.components.base.app_wrap import AppWrap\nfrom reflex.components.base.error_boundary import ErrorBoundary\nfrom reflex.components.base.fragment import Fragment\nfrom reflex.components.base.strict_mode import StrictMode\nfrom reflex.components.component import (\n    CUSTOM_COMPONENTS,\n    Component,\n    ComponentStyle,\n    evaluate_style_namespaces,\n)\nfrom reflex.components.core.banner import (\n    backend_disabled,\n    connection_pulser,\n    connection_toaster,\n)\nfrom reflex.components.core.breakpoints import set_breakpoints\nfrom reflex.components.core.sticky import sticky\nfrom reflex.components.radix import themes\nfrom reflex.components.sonner.toast import toast\nfrom reflex.config import get_config\nfrom reflex.environment import ExecutorType, environment\nfrom reflex.event import (\n    _EVENT_FIELDS,\n    Event,\n    EventSpec,\n    EventType,\n    IndividualEventType,\n    get_hydrate_event,\n    noop,\n)\nfrom reflex.istate.manager import StateModificationContext\nfrom reflex.istate.proxy import StateProxy\nfrom reflex.page import DECORATED_PAGES\nfrom reflex.route import (\n    get_route_args,\n    replace_brackets_with_keywords,\n    verify_route_validity,\n)\nfrom reflex.state import (\n    BaseState,\n    RouterData,\n    State,\n    StateManager,\n    StateUpdate,\n    _split_substate_key,\n    _substate_key,\n    all_base_state_classes,\n    code_uses_state_contexts,\n)\nfrom reflex.utils import (\n    codespaces,\n    console,\n    exceptions,\n    format,\n    frontend_skeleton,\n    js_runtimes,\n    path_ops,\n    prerequisites,\n    types,\n)\nfrom reflex.utils.exec import (\n    get_compile_context,\n    is_prod_mode,\n    is_testing_env,\n    should_prerender_routes,\n)\nfrom reflex.utils.imports import ImportVar\nfrom reflex.utils.misc import run_in_thread\nfrom reflex.utils.token_manager import RedisTokenManager, TokenManager\nfrom reflex.utils.types import ASGIApp, Message, Receive, Scope, Send\n\nif TYPE_CHECKING:\n    from reflex.vars import Var\n\n    # Define custom types.\n    ComponentCallable = Callable[[], Component | tuple[Component, ...] | str | Var]\nelse:\n    ComponentCallable = Callable[[], Component | tuple[Component, ...] | str]\n\nReducer = Callable[[Event], Coroutine[Any, Any, StateUpdate]]\n\n\ndef default_frontend_exception_handler(exception: Exception) -> None:\n    \"\"\"Default frontend exception handler function.\n\n    Args:\n        exception: The exception.\n\n    \"\"\"\n    console.error(f\"[Reflex Frontend Exception]\\n {exception}\\n\")\n\n\ndef default_backend_exception_handler(exception: Exception) -> EventSpec:\n    \"\"\"Default backend exception handler function.\n\n    Args:\n        exception: The exception.\n\n    Returns:\n        EventSpec: The window alert event.\n\n    \"\"\"\n    from reflex.components.sonner.toast import toast\n\n    error = traceback.format_exc()\n\n    console.error(f\"[Reflex Backend Exception]\\n {error}\\n\")\n\n    error_message = (\n        [\"Contact the website administrator.\"]\n        if is_prod_mode()\n        else [f\"{type(exception).__name__}: {exception}.\", \"See logs for details.\"]\n    )\n\n    return toast(\n        \"An error occurred.\",\n        level=\"error\",\n        fallback_to_alert=True,\n        description=\"<br/>\".join(error_message),\n        position=\"top-center\",\n        id=\"backend_error\",\n        style={\"width\": \"500px\"},\n    )\n\n\ndef extra_overlay_function() -> Component | None:\n    \"\"\"Extra overlay function to add to the overlay component.\n\n    Returns:\n        The extra overlay function.\n    \"\"\"\n    config = get_config()\n\n    extra_config = config.extra_overlay_function\n    config_overlay = None\n    if extra_config:\n        module, _, function_name = extra_config.rpartition(\".\")\n        try:\n            module = __import__(module)\n            config_overlay = Fragment.create(getattr(module, function_name)())\n            config_overlay._get_all_imports()\n        except Exception as e:\n            from reflex.compiler.utils import save_error\n\n            log_path = save_error(e)\n\n            console.error(\n                f\"Error loading extra_overlay_function {extra_config}. Error saved to {log_path}\"\n            )\n\n    return config_overlay\n\n\ndef default_overlay_component() -> Component:\n    \"\"\"Default overlay_component attribute for App.\n\n    Returns:\n        The default overlay_component, which is a connection_modal.\n    \"\"\"\n    from reflex.components.component import memo\n\n    def default_overlay_components():\n        return Fragment.create(\n            connection_pulser(),\n            connection_toaster(),\n            *(\n                [backend_disabled()]\n                if get_compile_context() == constants.CompileContext.DEPLOY\n                else []\n            ),\n            *codespaces.codespaces_auto_redirect(),\n        )\n\n    return Fragment.create(memo(default_overlay_components)())\n\n\ndef default_error_boundary(*children: Component, **props) -> Component:\n    \"\"\"Default error_boundary attribute for App.\n\n    Args:\n        *children: The children to render in the error boundary.\n        **props: The props to pass to the error boundary.\n\n    Returns:\n        The default error_boundary, which is an ErrorBoundary.\n\n    \"\"\"\n    return ErrorBoundary.create(\n        *children,\n        **props,\n    )\n\n\n@dataclasses.dataclass(frozen=True)\nclass UploadFile(StarletteUploadFile):\n    \"\"\"A file uploaded to the server.\n\n    Args:\n        file: The standard Python file object (non-async).\n        filename: The original file name.\n        size: The size of the file in bytes.\n        headers: The headers of the request.\n    \"\"\"\n\n    file: BinaryIO\n\n    path: Path | None = dataclasses.field(default=None)\n\n    size: int | None = dataclasses.field(default=None)\n\n    headers: Headers = dataclasses.field(default_factory=Headers)\n\n    @property\n    def filename(self) -> str | None:\n        \"\"\"Get the name of the uploaded file.\n\n        Returns:\n            The name of the uploaded file.\n        \"\"\"\n        return self.name\n\n    @property\n    def name(self) -> str | None:\n        \"\"\"Get the name of the uploaded file.\n\n        Returns:\n            The name of the uploaded file.\n        \"\"\"\n        if self.path:\n            return self.path.name\n        return None\n\n\n@dataclasses.dataclass(\n    frozen=True,\n)\nclass UnevaluatedPage:\n    \"\"\"An uncompiled page.\"\"\"\n\n    component: Component | ComponentCallable\n    route: str\n    title: Var | str | None\n    description: Var | str | None\n    image: str\n    on_load: EventType[()] | None\n    meta: Sequence[Mapping[str, Any] | Component]\n    context: Mapping[str, Any]\n\n    def merged_with(self, other: UnevaluatedPage) -> UnevaluatedPage:\n        \"\"\"Merge the other page into this one.\n\n        Args:\n            other: The other page to merge with.\n\n        Returns:\n            The merged page.\n        \"\"\"\n        return dataclasses.replace(\n            self,\n            title=self.title if self.title is not None else other.title,\n            description=self.description\n            if self.description is not None\n            else other.description,\n            on_load=self.on_load if self.on_load is not None else other.on_load,\n            context=self.context if self.context is not None else other.context,\n        )\n\n\nP = ParamSpec(\"P\")\n\n\n@dataclasses.dataclass()\nclass App(MiddlewareMixin, LifespanMixin):\n    \"\"\"The main Reflex app that encapsulates the backend and frontend.\n\n    Every Reflex app needs an app defined in its main module.\n\n    ```python\n    # app.py\n    import reflex as rx\n\n    # Define state and pages\n    ...\n\n    app = rx.App(\n        # Set global level style.\n        style={...},\n        # Set the top level theme.\n        theme=rx.theme(accent_color=\"blue\"),\n    )\n    ```\n    \"\"\"\n\n    # The global [theme](https://reflex.dev/docs/styling/theming/#theme) for the entire app.\n    theme: Component | None = dataclasses.field(\n        default_factory=lambda: themes.theme(accent_color=\"blue\")\n    )\n\n    # The [global style](https://reflex.dev/docs/styling/overview/#global-styles}) for the app.\n    style: ComponentStyle = dataclasses.field(default_factory=dict)\n\n    # A list of URLs to [stylesheets](https://reflex.dev/docs/styling/custom-stylesheets/) to include in the app.\n    stylesheets: list[str] = dataclasses.field(default_factory=list)\n\n    # Whether to include CSS reset for margin and padding (defaults to True).\n    reset_style: bool = dataclasses.field(default=True)\n\n    # A component that is present on every page (defaults to the Connection Error banner).\n    overlay_component: Component | ComponentCallable | None = dataclasses.field(\n        default=None\n    )\n\n    # App wraps to be applied to the whole app. Expected to be a dictionary of (order, name) to a function that takes whether the state is enabled and optionally returns a component.\n    app_wraps: dict[tuple[int, str], Callable[[bool], Component | None]] = (\n        dataclasses.field(\n            default_factory=lambda: {\n                (55, \"ErrorBoundary\"): (\n                    lambda stateful: default_error_boundary(\n                        **({\"on_error\": noop()} if not stateful else {})\n                    )\n                ),\n                (5, \"Overlay\"): (\n                    lambda stateful: default_overlay_component() if stateful else None\n                ),\n                (4, \"ExtraOverlay\"): lambda stateful: extra_overlay_function(),\n            }\n        )\n    )\n\n    # Extra app wraps to be applied to the whole app.\n    extra_app_wraps: dict[tuple[int, str], Callable[[bool], Component | None]] = (\n        dataclasses.field(default_factory=dict)\n    )\n\n    # Components to add to the head of every page.\n    head_components: list[Component] = dataclasses.field(default_factory=list)\n\n    # The Socket.IO AsyncServer instance.\n    sio: AsyncServer | None = None\n\n    # The language to add to the html root tag of every page.\n    html_lang: str | None = None\n\n    # Attributes to add to the html root tag of every page.\n    html_custom_attrs: dict[str, str] | None = None\n\n    # A map from a route to an unevaluated page.\n    _unevaluated_pages: dict[str, UnevaluatedPage] = dataclasses.field(\n        default_factory=dict\n    )\n\n    # A map from a page route to the component to render. Users should use `add_page`.\n    _pages: dict[str, Component] = dataclasses.field(default_factory=dict)\n\n    # A mapping of pages which created states as they were being evaluated.\n    _stateful_pages: dict[str, None] = dataclasses.field(default_factory=dict)\n\n    # The backend API object.\n    _api: Starlette | None = None\n\n    # The state class to use for the app.\n    _state: type[BaseState] | None = None\n\n    # Whether to enable state for the app. If False, the app will not use state.\n    enable_state: bool = True\n\n    # Class to manage many client states.\n    _state_manager: StateManager | None = None\n\n    # Mapping from a route to event handlers to trigger when the page loads.\n    _load_events: dict[str, list[IndividualEventType[()]]] = dataclasses.field(\n        default_factory=dict\n    )\n\n    # Admin dashboard to view and manage the database.\n    admin_dash: AdminDash | None = None\n\n    # The async server name space.\n    _event_namespace: EventNamespace | None = None\n\n    # Background tasks that are currently running.\n    _background_tasks: set[asyncio.Task] = dataclasses.field(default_factory=set)\n\n    # Frontend Error Handler Function\n    frontend_exception_handler: Callable[[Exception], None] = (\n        default_frontend_exception_handler\n    )\n\n    # Backend Error Handler Function\n    backend_exception_handler: Callable[\n        [Exception], EventSpec | list[EventSpec] | None\n    ] = default_backend_exception_handler\n\n    # Put the toast provider in the app wrap.\n    toaster: Component | None = dataclasses.field(default_factory=toast.provider)\n\n    # Transform the ASGI app before running it.\n    api_transformer: (\n        Sequence[Callable[[ASGIApp], ASGIApp] | Starlette]\n        | Callable[[ASGIApp], ASGIApp]\n        | Starlette\n        | None\n    ) = None\n\n    @property\n    def event_namespace(self) -> EventNamespace | None:\n        \"\"\"Get the event namespace.\n\n        Returns:\n            The event namespace.\n        \"\"\"\n        return self._event_namespace\n\n    def __post_init__(self):\n        \"\"\"Initialize the app.\n\n        Raises:\n            ValueError: If the event namespace is not provided in the config.\n                        Also, if there are multiple client subclasses of rx.BaseState(Subclasses of rx.BaseState should consist\n                        of the DefaultState and the client app state).\n        \"\"\"\n        # Special case to allow test cases have multiple subclasses of rx.BaseState.\n        if not is_testing_env() and BaseState.__subclasses__() != [State]:\n            # Only rx.State is allowed as Base State subclass.\n            msg = \"rx.BaseState cannot be subclassed directly. Use rx.State instead\"\n            raise ValueError(msg)\n\n        get_config(reload=True)\n\n        if \"breakpoints\" in self.style:\n            set_breakpoints(self.style.pop(\"breakpoints\"))\n\n        # Set up the API.\n        self._api = Starlette()\n        App._add_cors(self._api)\n        self._add_default_endpoints()\n\n        for clz in App.__mro__:\n            if clz == App:\n                continue\n            if issubclass(clz, AppMixin):\n                clz._init_mixin(self)\n\n        if self.enable_state:\n            self._enable_state()\n\n        # Set up the admin dash.\n        self._setup_admin_dash()\n\n        if sys.platform == \"win32\" and not is_prod_mode():\n            # Hack to fix Windows hot reload issue.\n            from reflex.utils.compat import windows_hot_reload_lifespan_hack\n\n            self.register_lifespan_task(windows_hot_reload_lifespan_hack)\n\n    def _enable_state(self) -> None:\n        \"\"\"Enable state for the app.\"\"\"\n        if not self._state:\n            self._state = State\n        self._setup_state()\n\n    def _setup_state(self) -> None:\n        \"\"\"Set up the state for the app.\n\n        Raises:\n            RuntimeError: If the socket server is invalid.\n        \"\"\"\n        if not self._state:\n            return\n\n        config = get_config()\n\n        # Set up the state manager.\n        self._state_manager = StateManager.create(state=self._state)\n\n        # Set up the Socket.IO AsyncServer.\n        if not self.sio:\n            self.sio = AsyncServer(\n                async_mode=\"asgi\",\n                cors_allowed_origins=(\n                    (\n                        \"*\"\n                        if config.cors_allowed_origins == (\"*\",)\n                        else list(config.cors_allowed_origins)\n                    )\n                    if config.transport == \"websocket\"\n                    else []\n                ),\n                cors_credentials=config.transport == \"websocket\",\n                max_http_buffer_size=environment.REFLEX_SOCKET_MAX_HTTP_BUFFER_SIZE.get(),\n                ping_interval=environment.REFLEX_SOCKET_INTERVAL.get(),\n                ping_timeout=environment.REFLEX_SOCKET_TIMEOUT.get(),\n                json=SimpleNamespace(\n                    dumps=staticmethod(format.json_dumps),\n                    loads=staticmethod(json.loads),\n                ),\n                allow_upgrades=False,\n                transports=[config.transport],\n            )\n        elif getattr(self.sio, \"async_mode\", \"\") != \"asgi\":\n            msg = f\"Custom `sio` must use `async_mode='asgi'`, not '{self.sio.async_mode}'.\"\n            raise RuntimeError(msg)\n\n        # Create the socket app. Note event endpoint constant replaces the default 'socket.io' path.\n        socket_app = EngineIOApp(self.sio, socketio_path=\"\")\n        namespace = config.get_event_namespace()\n\n        # Create the event namespace and attach the main app. Not related to any paths.\n        self._event_namespace = EventNamespace(namespace, self)\n\n        # Register the event namespace with the socket.\n        self.sio.register_namespace(self.event_namespace)\n        # Mount the socket app with the API.\n        if self._api:\n\n            class HeaderMiddleware:\n                def __init__(self, app: ASGIApp):\n                    self.app = app\n\n                async def __call__(self, scope: Scope, receive: Receive, send: Send):\n                    original_send = send\n\n                    async def modified_send(message: Message):\n                        if message[\"type\"] == \"websocket.accept\":\n                            if scope.get(\"subprotocols\"):\n                                # The following *does* say \"subprotocol\" instead of \"subprotocols\", intentionally.\n                                message[\"subprotocol\"] = scope[\"subprotocols\"][0]\n\n                            headers = dict(message.get(\"headers\", []))\n                            header_key = b\"sec-websocket-protocol\"\n                            if subprotocol := headers.get(header_key):\n                                message[\"headers\"] = [\n                                    *message.get(\"headers\", []),\n                                    (header_key, subprotocol),\n                                ]\n\n                        return await original_send(message)\n\n                    return await self.app(scope, receive, modified_send)\n\n            socket_app_with_headers = HeaderMiddleware(socket_app)\n            self._api.mount(str(constants.Endpoint.EVENT), socket_app_with_headers)\n\n        # Check the exception handlers\n        self._validate_exception_handlers()\n\n    def __repr__(self) -> str:\n        \"\"\"Get the string representation of the app.\n\n        Returns:\n            The string representation of the app.\n        \"\"\"\n        return f\"<App state={self._state.__name__ if self._state else None}>\"\n\n    def __call__(self) -> ASGIApp:\n        \"\"\"Run the backend api instance.\n\n        Returns:\n            The backend api.\n\n        Raises:\n            ValueError: If the app has not been initialized.\n        \"\"\"\n        from reflex.assets import remove_stale_external_asset_symlinks\n        from reflex.vars.base import GLOBAL_CACHE\n\n        # Clean up stale symlinks in assets/external/ before compiling, so that\n        # rx.asset(shared=True) symlink re-creation doesn't trigger further reloads.\n        remove_stale_external_asset_symlinks()\n\n        self._compile(prerender_routes=should_prerender_routes())\n\n        config = get_config()\n\n        for plugin in config.plugins:\n            plugin.post_compile(app=self)\n\n        # We will not be making more vars, so we can clear the global cache to free up memory.\n        GLOBAL_CACHE.clear()\n\n        if not self._api:\n            msg = \"The app has not been initialized.\"\n            raise ValueError(msg)\n\n        asgi_app = self._api\n\n        if environment.REFLEX_MOUNT_FRONTEND_COMPILED_APP.get():\n            asgi_app.mount(\n                \"/\" + config.frontend_path.strip(\"/\"),\n                StaticFiles(\n                    directory=prerequisites.get_web_dir()\n                    / constants.Dirs.STATIC\n                    / config.frontend_path.strip(\"/\"),\n                    html=True,\n                ),\n                name=\"frontend\",\n            )\n\n        if self.api_transformer is not None:\n            api_transformers: Sequence[Starlette | Callable[[ASGIApp], ASGIApp]] = (\n                [self.api_transformer]\n                if not isinstance(self.api_transformer, Sequence)\n                else self.api_transformer\n            )\n\n            for api_transformer in api_transformers:\n                if isinstance(api_transformer, Starlette):\n                    # Mount the api to the starlette app.\n                    App._add_cors(api_transformer)\n                    api_transformer.mount(\"\", asgi_app)\n                    asgi_app = api_transformer\n                else:\n                    # Transform the asgi app.\n                    asgi_app = api_transformer(asgi_app)\n\n        top_asgi_app = Starlette(lifespan=self._run_lifespan_tasks)\n        top_asgi_app.mount(\"\", asgi_app)\n        App._add_cors(top_asgi_app)\n\n        return top_asgi_app\n\n    def _add_default_endpoints(self):\n        \"\"\"Add default api endpoints (ping).\"\"\"\n        # To test the server.\n        if not self._api:\n            return\n\n        self._api.add_route(\n            str(constants.Endpoint.PING),\n            ping,\n            methods=[\"GET\"],\n        )\n        self._api.add_route(\n            str(constants.Endpoint.HEALTH),\n            health,\n            methods=[\"GET\"],\n        )\n\n    def _add_optional_endpoints(self):\n        \"\"\"Add optional api endpoints (_upload).\"\"\"\n        from reflex.components.core.upload import Upload, get_upload_dir\n\n        if not self._api:\n            return\n        upload_is_used_marker = (\n            prerequisites.get_backend_dir() / constants.Dirs.UPLOAD_IS_USED\n        )\n        if Upload.is_used or upload_is_used_marker.exists():\n            # To upload files.\n            self._api.add_route(\n                str(constants.Endpoint.UPLOAD),\n                upload(self),\n                methods=[\"POST\"],\n            )\n\n            # To access uploaded files.\n            self._api.mount(\n                str(constants.Endpoint.UPLOAD),\n                StaticFiles(directory=get_upload_dir()),\n                name=\"uploaded_files\",\n            )\n\n            upload_is_used_marker.parent.mkdir(parents=True, exist_ok=True)\n            upload_is_used_marker.touch()\n        if codespaces.is_running_in_codespaces():\n            self._api.add_route(\n                str(constants.Endpoint.AUTH_CODESPACE),\n                codespaces.auth_codespace,\n                methods=[\"GET\"],\n            )\n        if environment.REFLEX_ADD_ALL_ROUTES_ENDPOINT.get():\n            self.add_all_routes_endpoint()\n\n    @staticmethod\n    def _add_cors(api: Starlette):\n        \"\"\"Add CORS middleware to the app.\n\n        Args:\n            api: The Starlette app to add CORS middleware to.\n        \"\"\"\n        api.add_middleware(\n            cors.CORSMiddleware,\n            allow_credentials=True,\n            allow_methods=[\"*\"],\n            allow_headers=[\"*\"],\n            allow_origins=get_config().cors_allowed_origins,\n        )\n\n    @property\n    def state_manager(self) -> StateManager:\n        \"\"\"Get the state manager.\n\n        Returns:\n            The initialized state manager.\n\n        Raises:\n            ValueError: if the state has not been initialized.\n        \"\"\"\n        if self._state_manager is None:\n            msg = \"The state manager has not been initialized.\"\n            raise ValueError(msg)\n        return self._state_manager\n\n    @staticmethod\n    def _generate_component(component: Component | ComponentCallable) -> Component:\n        \"\"\"Generate a component from a callable.\n\n        Args:\n            component: The component function to call or Component to return as-is.\n\n        Returns:\n            The generated component.\n        \"\"\"\n        from reflex.compiler.compiler import into_component\n\n        return into_component(component)\n\n    def add_page(\n        self,\n        component: Component | ComponentCallable | None = None,\n        route: str | None = None,\n        title: str | Var | None = None,\n        description: str | Var | None = None,\n        image: str = constants.DefaultPage.IMAGE,\n        on_load: EventType[()] | None = None,\n        meta: Sequence[Mapping[str, Any] | Component] = constants.DefaultPage.META_LIST,\n        context: dict[str, Any] | None = None,\n    ):\n        \"\"\"Add a page to the app.\n\n        If the component is a callable, by default the route is the name of the\n        function. Otherwise, a route must be provided.\n\n        Args:\n            component: The component to display at the page.\n            route: The route to display the component at.\n            title: The title of the page.\n            description: The description of the page.\n            image: The image to display on the page.\n            on_load: The event handler(s) that will be called each time the page load.\n            meta: The metadata of the page.\n            context: Values passed to page for custom page-specific logic.\n\n        Raises:\n            PageValueError: When the component is not set for a non-404 page.\n            RouteValueError: When the specified route name already exists.\n        \"\"\"\n        # If the route is not set, get it from the callable.\n        if route is None:\n            if not isinstance(component, Callable):\n                msg = \"Route must be set if component is not a callable.\"\n                raise exceptions.RouteValueError(msg)\n            # Format the route.\n            route = format.format_route(format.to_kebab_case(component.__name__))\n        else:\n            route = format.format_route(route)\n\n        if route == constants.Page404.SLUG:\n            if component is None:\n                from reflex.components.el.elements import span\n\n                component = span(\"404: Page not found\")\n            component = self._generate_component(component)\n            title = title or constants.Page404.TITLE\n            description = description or constants.Page404.DESCRIPTION\n            image = image or constants.Page404.IMAGE\n        else:\n            if component is None:\n                msg = \"Component must be set for a non-404 page.\"\n                raise exceptions.PageValueError(msg)\n\n        # Check if the route given is valid\n        verify_route_validity(route)\n\n        unevaluated_page = UnevaluatedPage(\n            component=component,\n            route=route,\n            title=title,\n            description=description,\n            image=image,\n            on_load=on_load,\n            meta=meta,\n            context=context or {},\n        )\n\n        if route in self._unevaluated_pages:\n            if self._unevaluated_pages[route].component is component:\n                unevaluated_page = unevaluated_page.merged_with(\n                    self._unevaluated_pages[route]\n                )\n                console.warn(\n                    f\"Page {route} is being redefined with the same component.\"\n                )\n            else:\n                route_name = (\n                    f\"`{route}` or `/`\"\n                    if route == constants.PageNames.INDEX_ROUTE\n                    else f\"`{route}`\"\n                )\n                existing_component = self._unevaluated_pages[route].component\n                msg = (\n                    f\"Tried to add page {readable_name_from_component(component)} with route {route_name} but \"\n                    f\"page {readable_name_from_component(existing_component)} with the same route already exists. \"\n                    \"Make sure you do not have two pages with the same route.\"\n                )\n                raise exceptions.RouteValueError(msg)\n\n        # Setup dynamic args for the route.\n        # this state assignment is only required for tests using the deprecated state kwarg for App\n        state = self._state or State\n        state.setup_dynamic_args(get_route_args(route))\n\n        self._load_events[route] = (\n            (on_load if isinstance(on_load, list) else [on_load])\n            if on_load is not None\n            else []\n        )\n\n        self._unevaluated_pages[route] = unevaluated_page\n\n    def _compile_page(self, route: str, save_page: bool = True):\n        \"\"\"Compile a page.\n\n        Args:\n            route: The route of the page to compile.\n            save_page: If True, the compiled page is saved to self._pages.\n        \"\"\"\n        n_states_before = len(all_base_state_classes)\n        component = compiler.compile_unevaluated_page(\n            route, self._unevaluated_pages[route], self.style, self.theme\n        )\n\n        # Indicate that evaluating this page creates one or more state classes.\n        if len(all_base_state_classes) > n_states_before:\n            self._stateful_pages[route] = None\n\n        # Add the page.\n        self._check_routes_conflict(route)\n        if save_page:\n            self._pages[route] = component\n\n    @functools.cached_property\n    def router(self) -> Callable[[str], str | None]:\n        \"\"\"Get the route computer function.\n\n        Returns:\n            The route computer function.\n        \"\"\"\n        from reflex.route import get_router\n\n        return get_router(list(dict.fromkeys([*self._unevaluated_pages, *self._pages])))\n\n    def get_load_events(self, path: str) -> list[IndividualEventType[()]]:\n        \"\"\"Get the load events for a route.\n\n        Args:\n            path: The route to get the load events for.\n\n        Returns:\n            The load events for the route.\n        \"\"\"\n        four_oh_four_load_events = self._load_events.get(\"404\", [])\n        route = self.router(path)\n        if not route:\n            # If the path is not a valid route, return the 404 page load events.\n            return four_oh_four_load_events\n        return self._load_events.get(\n            route,\n            four_oh_four_load_events,\n        )\n\n    def _check_routes_conflict(self, new_route: str):\n        \"\"\"Verify if there is any conflict between the new route and any existing route.\n\n        Based on conflicts that React Router would throw if not intercepted.\n\n        Args:\n            new_route: the route being newly added.\n\n        Raises:\n            RouteValueError: exception showing which conflict exist with the route to be added\n        \"\"\"\n        from reflex.utils.exceptions import RouteValueError\n\n        if \"[\" not in new_route:\n            return\n\n        segments = (\n            constants.RouteRegex.SINGLE_SEGMENT,\n            constants.RouteRegex.DOUBLE_SEGMENT,\n            constants.RouteRegex.DOUBLE_CATCHALL_SEGMENT,\n        )\n        for route in self._pages:\n            replaced_route = replace_brackets_with_keywords(route)\n            for rw, r, nr in zip(\n                replaced_route.split(\"/\"),\n                route.split(\"/\"),\n                new_route.split(\"/\"),\n                strict=False,\n            ):\n                if rw in segments and r != nr:\n                    # If the slugs in the segments of both routes are not the same, then the route is invalid\n                    msg = f\"You cannot use different slug names for the same dynamic path in  {route} and {new_route} ('{r}' != '{nr}')\"\n                    raise RouteValueError(msg)\n                if rw not in segments and r != nr:\n                    # if the section being compared in both routes is not a dynamic segment(i.e not wrapped in brackets)\n                    # then we are guaranteed that the route is valid and there's no need checking the rest.\n                    # eg. /posts/[id]/info/[slug1] and /posts/[id]/info1/[slug1] is always going to be valid since\n                    # info1 will break away into its own tree.\n                    break\n\n    def _setup_admin_dash(self):\n        \"\"\"Setup the admin dash.\"\"\"\n        try:\n            from starlette_admin.contrib.sqla.admin import Admin\n            from starlette_admin.contrib.sqla.view import ModelView\n\n            from reflex.model import Model\n        except ImportError:\n            return\n\n        # Get the admin dash.\n        if not self._api:\n            return\n\n        admin_dash = self.admin_dash\n\n        if admin_dash and admin_dash.models:\n            # Build the admin dashboard\n            admin = admin_dash.admin or Admin(\n                engine=Model.get_db_engine(),\n                title=\"Reflex Admin Dashboard\",\n                logo_url=\"https://reflex.dev/Reflex.svg\",\n            )\n\n            for model in admin_dash.models:\n                view = admin_dash.view_overrides.get(model, ModelView)\n                admin.add_view(view(model))\n\n            admin.mount_to(self._api)\n\n    def _get_frontend_packages(self, imports: dict[str, set[ImportVar]]):\n        \"\"\"Gets the frontend packages to be installed and filters out the unnecessary ones.\n\n        Args:\n            imports: A dictionary containing the imports used in the current page.\n\n        Example:\n            >>> _get_frontend_packages({\"react\": \"16.14.0\", \"react-dom\": \"16.14.0\"})\n        \"\"\"\n        dependencies = constants.PackageJson.DEPENDENCIES\n        dev_dependencies = constants.PackageJson.DEV_DEPENDENCIES\n        page_imports = {\n            i\n            for i, tags in imports.items()\n            if i not in dependencies\n            and i not in dev_dependencies\n            and not any(i.startswith(prefix) for prefix in [\"/\", \"$/\", \".\"])\n            and i != \"\"\n            and any(tag.install for tag in tags)\n        }\n        pinned = {i.rpartition(\"@\")[0] for i in page_imports if \"@\" in i}\n        page_imports = {i for i in page_imports if i not in pinned}\n\n        frontend_packages = get_config().frontend_packages\n        filtered_frontend_packages = []\n        for package in frontend_packages:\n            if package in page_imports:\n                console.warn(\n                    f\"React packages and their dependencies are inferred from Component.library and Component.lib_dependencies, remove `{package}` from `frontend_packages`\"\n                )\n                continue\n            filtered_frontend_packages.append(package)\n        page_imports.update(filtered_frontend_packages)\n        js_runtimes.install_frontend_packages(page_imports, get_config())\n\n    def _app_root(self, app_wrappers: dict[tuple[int, str], Component]) -> Component:\n        for component in tuple(app_wrappers.values()):\n            app_wrappers.update(component._get_all_app_wrap_components())\n        order = sorted(app_wrappers, key=operator.itemgetter(0), reverse=True)\n        root = copy.deepcopy(app_wrappers[order[0]])\n\n        def reducer(parent: Component, key: tuple[int, str]) -> Component:\n            child = copy.deepcopy(app_wrappers[key])\n            parent.children.append(child)\n            return child\n\n        functools.reduce(\n            lambda parent, key: reducer(parent, key),\n            order[1:],\n            root,\n        )\n        return root\n\n    def _should_compile(self) -> bool:\n        \"\"\"Check if the app should be compiled.\n\n        Returns:\n            Whether the app should be compiled.\n        \"\"\"\n        # Check the environment variable.\n        if environment.REFLEX_SKIP_COMPILE.get():\n            return False\n\n        nocompile = prerequisites.get_web_dir() / constants.NOCOMPILE_FILE\n\n        # Check the nocompile file.\n        if nocompile.exists():\n            # Delete the nocompile file\n            nocompile.unlink(missing_ok=True)\n            return False\n\n        # By default, compile the app.\n        return True\n\n    def _add_overlay_to_component(\n        self, component: Component, overlay_component: Component\n    ) -> Component:\n        children = component.children\n\n        if children[0] == overlay_component:\n            return component\n\n        return Fragment.create(overlay_component, *children)\n\n    def _setup_overlay_component(self):\n        \"\"\"If a State is not used and no overlay_component is specified, do not render the connection modal.\"\"\"\n        if self.overlay_component is None:\n            return\n        console.deprecate(\n            feature_name=\"overlay_component\",\n            reason=\"Use `extra_app_wraps` to add the overlay component instead.\",\n            deprecation_version=\"0.8.2\",\n            removal_version=\"0.9.0\",\n        )\n        overlay_component = self._generate_component(self.overlay_component)\n        for k, component in self._pages.items():\n            self._pages[k] = self._add_overlay_to_component(\n                component, overlay_component\n            )\n\n    def _setup_sticky_badge(self):\n        \"\"\"Add the sticky badge to the app.\"\"\"\n        from reflex.components.component import memo\n\n        @memo\n        def memoized_badge():\n            sticky_badge = sticky()\n            sticky_badge._add_style_recursive({})\n            return sticky_badge\n\n        self.app_wraps[0, \"StickyBadge\"] = lambda _: memoized_badge()\n\n    def _apply_decorated_pages(self):\n        \"\"\"Add @rx.page decorated pages to the app.\"\"\"\n        app_name = get_config().app_name\n        for render, kwargs in DECORATED_PAGES[app_name]:\n            self.add_page(render, **kwargs)\n\n    def _validate_var_dependencies(self, state: type[BaseState] | None = None) -> None:\n        \"\"\"Validate the dependencies of the vars in the app.\n\n        Args:\n            state: The state to validate the dependencies for.\n\n        Raises:\n            VarDependencyError: When a computed var has an invalid dependency.\n        \"\"\"\n        if not self._state:\n            return\n\n        if not state:\n            state = self._state\n\n        for var in state.computed_vars.values():\n            if not var._cache:\n                continue\n            deps = var._deps(objclass=state)\n            for state_name, dep_set in deps.items():\n                state_cls = (\n                    state.get_root_state().get_class_substate(state_name)\n                    if state_name != state.get_full_name()\n                    else state\n                )\n                for dep in dep_set:\n                    if dep not in state_cls.vars and dep not in state_cls.backend_vars:\n                        msg = f\"ComputedVar {var._name} on state {state.__name__} has an invalid dependency {state_name}.{dep}\"\n                        raise exceptions.VarDependencyError(msg)\n\n        for substate in state.class_subclasses:\n            self._validate_var_dependencies(substate)\n\n    def _compile(\n        self,\n        prerender_routes: bool = False,\n        dry_run: bool = False,\n        use_rich: bool = True,\n    ):\n        \"\"\"Compile the app and output it to the pages folder.\n\n        Args:\n            prerender_routes: Whether to prerender the routes.\n            dry_run: Whether to compile the app without saving it.\n            use_rich: Whether to use rich progress bars.\n\n        Raises:\n            ReflexRuntimeError: When any page uses state, but no rx.State subclass is defined.\n            FileNotFoundError: When a plugin requires a file that does not exist.\n        \"\"\"\n        from reflex.utils.exceptions import ReflexRuntimeError\n\n        self._apply_decorated_pages()\n\n        self._pages = {}\n\n        def get_compilation_time() -> str:\n            return str(datetime.now().time()).split(\".\")[0]\n\n        should_compile = self._should_compile()\n        backend_dir = prerequisites.get_backend_dir()\n        if not dry_run and not should_compile and backend_dir.exists():\n            stateful_pages_marker = backend_dir / constants.Dirs.STATEFUL_PAGES\n            if stateful_pages_marker.exists():\n                with stateful_pages_marker.open(\"r\") as f:\n                    stateful_pages = json.load(f)\n                for route in stateful_pages:\n                    console.debug(f\"BE Evaluating stateful page: {route}\")\n                    self._compile_page(route, save_page=False)\n            self._add_optional_endpoints()\n            return\n\n        # Render a default 404 page if the user didn't supply one\n        if constants.Page404.SLUG not in self._unevaluated_pages:\n            self.add_page(route=constants.Page404.SLUG)\n\n        # Fix up the style.\n        self.style = evaluate_style_namespaces(self.style)\n\n        # Add the app wrappers.\n        app_wrappers: dict[tuple[int, str], Component] = {\n            # Default app wrap component renders {children}\n            (0, \"AppWrap\"): AppWrap.create()\n        }\n\n        if self.theme is not None:\n            # If a theme component was provided, wrap the app with it\n            app_wrappers[20, \"Theme\"] = self.theme\n\n        # Get the env mode.\n        config = get_config()\n\n        if config.react_strict_mode:\n            app_wrappers[200, \"StrictMode\"] = StrictMode.create()\n\n        if not should_compile and not dry_run:\n            with console.timing(\"Evaluate Pages (Backend)\"):\n                for route in self._unevaluated_pages:\n                    console.debug(f\"Evaluating page: {route}\")\n                    self._compile_page(route, save_page=should_compile)\n\n            # Save the pages which created new states at eval time.\n            self._write_stateful_pages_marker()\n\n            # Add the optional endpoints (_upload)\n            self._add_optional_endpoints()\n\n            return\n\n        # Create a progress bar.\n        progress = (\n            Progress(\n                *Progress.get_default_columns()[:-1],\n                MofNCompleteColumn(),\n                TimeElapsedColumn(),\n            )\n            if use_rich\n            else console.PoorProgress()\n        )\n\n        # try to be somewhat accurate - but still not 100%\n        adhoc_steps_without_executor = 7\n        fixed_pages_within_executor = 4\n        plugin_count = len(config.plugins)\n        progress.start()\n        task = progress.add_task(\n            f\"[{get_compilation_time()}] Compiling:\",\n            total=len(self._unevaluated_pages)\n            + ((len(self._unevaluated_pages) + len(self._pages)) * 3)\n            + fixed_pages_within_executor\n            + adhoc_steps_without_executor\n            + plugin_count,\n        )\n\n        with console.timing(\"Evaluate Pages (Frontend)\"):\n            performance_metrics: list[tuple[str, float]] = []\n            for route in self._unevaluated_pages:\n                console.debug(f\"Evaluating page: {route}\")\n                start = timer()\n                self._compile_page(route, save_page=should_compile)\n                end = timer()\n                performance_metrics.append((route, end - start))\n                progress.advance(task)\n            console.debug(\n                \"Slowest pages:\\n\"\n                + \"\\n\".join(\n                    f\"{route}: {time * 1000:.1f}ms\"\n                    for route, time in sorted(\n                        performance_metrics, key=operator.itemgetter(1), reverse=True\n                    )[:10]\n                )\n            )\n            # Save the pages which created new states at eval time.\n            self._write_stateful_pages_marker()\n\n        # Add the optional endpoints (_upload)\n        self._add_optional_endpoints()\n\n        self._validate_var_dependencies()\n        self._setup_overlay_component()\n\n        if config.show_built_with_reflex is None:\n            if (\n                get_compile_context() == constants.CompileContext.DEPLOY\n                and prerequisites.get_user_tier() in [\"pro\", \"team\", \"enterprise\"]\n            ):\n                config.show_built_with_reflex = False\n            else:\n                config.show_built_with_reflex = True\n\n        if is_prod_mode() and config.show_built_with_reflex:\n            self._setup_sticky_badge()\n\n        progress.advance(task)\n\n        # Store the compile results.\n        compile_results: list[tuple[str, str]] = []\n\n        progress.advance(task)\n\n        # Track imports found.\n        all_imports = {}\n\n        if (toaster := self.toaster) is not None:\n            from reflex.components.component import memo\n\n            @memo\n            def memoized_toast_provider():\n                return toaster\n\n            toast_provider = Fragment.create(memoized_toast_provider())\n\n            app_wrappers[44, \"ToasterProvider\"] = toast_provider\n\n        # Add the app wraps to the app.\n        for key, app_wrap in chain(\n            self.app_wraps.items(), self.extra_app_wraps.items()\n        ):\n            # If the app wrap is a callable, generate the component\n            component = app_wrap(self._state is not None)\n            if component is not None:\n                app_wrappers[key] = component\n\n        # Compile custom components.\n        (\n            memo_components_output,\n            memo_components_result,\n            memo_components_imports,\n        ) = compiler.compile_memo_components(dict.fromkeys(CUSTOM_COMPONENTS.values()))\n        compile_results.append((memo_components_output, memo_components_result))\n        all_imports.update(memo_components_imports)\n        progress.advance(task)\n\n        with console.timing(\"Collect all imports and app wraps\"):\n            # This has to happen before compiling stateful components as that\n            # prevents recursive functions from reaching all components.\n            for component in self._pages.values():\n                # Add component._get_all_imports() to all_imports.\n                all_imports.update(component._get_all_imports())\n\n                # Add the app wrappers from this component.\n                app_wrappers.update(component._get_all_app_wrap_components())\n\n                progress.advance(task)\n\n        # Perform auto-memoization of stateful components.\n        with console.timing(\"Auto-memoize StatefulComponents\"):\n            (\n                stateful_components_path,\n                stateful_components_code,\n                page_components,\n            ) = compiler.compile_stateful_components(\n                self._pages.values(),\n                progress_function=lambda task=task: progress.advance(task),\n            )\n            progress.advance(task)\n\n        # Catch \"static\" apps (that do not define a rx.State subclass) which are trying to access rx.State.\n        if code_uses_state_contexts(stateful_components_code) and self._state is None:\n            msg = (\n                \"To access rx.State in frontend components, at least one \"\n                \"subclass of rx.State must be defined in the app.\"\n            )\n            raise ReflexRuntimeError(msg)\n        compile_results.append((stateful_components_path, stateful_components_code))\n\n        progress.advance(task)\n\n        # Compile the root document before fork.\n        compile_results.append(\n            compiler.compile_document_root(\n                self.head_components,\n                html_lang=self.html_lang,\n                html_custom_attrs=(\n                    {\"suppressHydrationWarning\": True, **self.html_custom_attrs}\n                    if self.html_custom_attrs\n                    else {\"suppressHydrationWarning\": True}\n                ),\n            )\n        )\n\n        progress.advance(task)\n\n        # Copy the assets.\n        assets_src = Path.cwd() / constants.Dirs.APP_ASSETS\n        if assets_src.is_dir() and not dry_run:\n            with console.timing(\"Copy assets\"):\n                path_ops.update_directory_tree(\n                    src=assets_src,\n                    dest=(\n                        Path.cwd() / prerequisites.get_web_dir() / constants.Dirs.PUBLIC\n                    ),\n                )\n\n        executor = ExecutorType.get_executor_from_environment()\n\n        for route, component in zip(self._pages, page_components, strict=True):\n            ExecutorSafeFunctions.COMPONENTS[route] = component\n\n        modify_files_tasks: list[tuple[str, str, Callable[[str], str]]] = []\n\n        with console.timing(\"Compile to Javascript\"), executor as executor:\n            result_futures: list[\n                concurrent.futures.Future[\n                    list[tuple[str, str]] | tuple[str, str] | None\n                ]\n            ] = []\n\n            def _submit_work(\n                fn: Callable[P, list[tuple[str, str]] | tuple[str, str] | None],\n                *args: P.args,\n                **kwargs: P.kwargs,\n            ):\n                f = executor.submit(fn, *args, **kwargs)\n                f.add_done_callback(lambda _: progress.advance(task))\n                result_futures.append(f)\n\n            # Compile the pre-compiled pages.\n            for route in self._pages:\n                _submit_work(\n                    ExecutorSafeFunctions.compile_page,\n                    route,\n                )\n\n            # Compile the root stylesheet with base styles.\n            _submit_work(\n                compiler.compile_root_stylesheet, self.stylesheets, self.reset_style\n            )\n\n            # Compile the theme.\n            _submit_work(compile_theme, self.style)\n\n            def _submit_work_without_advancing(\n                fn: Callable[P, list[tuple[str, str]] | tuple[str, str] | None],\n                *args: P.args,\n                **kwargs: P.kwargs,\n            ):\n                f = executor.submit(fn, *args, **kwargs)\n                result_futures.append(f)\n\n            for plugin in config.plugins:\n                plugin.pre_compile(\n                    add_save_task=_submit_work_without_advancing,\n                    add_modify_task=(\n                        lambda *args, plugin=plugin: modify_files_tasks.append((\n                            plugin.__class__.__module__ + plugin.__class__.__name__,\n                            *args,\n                        ))\n                    ),\n                    unevaluated_pages=list(self._unevaluated_pages.values()),\n                )\n\n            # Wait for all compilation tasks to complete.\n            for future in concurrent.futures.as_completed(result_futures):\n                if (result := future.result()) is not None:\n                    if isinstance(result, list):\n                        compile_results.extend(result)\n                    else:\n                        compile_results.append(result)\n\n        progress.advance(task, advance=len(config.plugins))\n\n        app_root = self._app_root(app_wrappers=app_wrappers)\n\n        # Get imports from AppWrap components.\n        all_imports.update(app_root._get_all_imports())\n\n        progress.advance(task)\n\n        # Compile the contexts.\n        compile_results.append(\n            compiler.compile_contexts(self._state, self.theme),\n        )\n        if self.theme is not None:\n            # Fix #2992 by removing the top-level appearance prop\n            self.theme.appearance = None  # pyright: ignore[reportAttributeAccessIssue]\n        progress.advance(task)\n\n        # Compile the app root.\n        compile_results.append(\n            compiler.compile_app(app_root),\n        )\n        progress.advance(task)\n\n        progress.stop()\n\n        if dry_run:\n            return\n\n        # Install frontend packages.\n        with console.timing(\"Install Frontend Packages\"):\n            self._get_frontend_packages(all_imports)\n\n        # Setup the react-router.config.js\n        frontend_skeleton.update_react_router_config(\n            prerender_routes=prerender_routes,\n        )\n\n        if is_prod_mode():\n            # Empty the .web pages directory.\n            compiler.purge_web_pages_dir()\n        else:\n            # In dev mode, delete removed pages and update existing pages.\n            keep_files = [Path(output_path) for output_path, _ in compile_results]\n            for p in Path(\n                prerequisites.get_web_dir()\n                / constants.Dirs.PAGES\n                / constants.Dirs.ROUTES\n            ).rglob(\"*\"):\n                if p.is_file() and p not in keep_files:\n                    # Remove pages that are no longer in the app.\n                    p.unlink()\n\n        output_mapping: dict[Path, str] = {}\n        for output_path, code in compile_results:\n            path = compiler_utils.resolve_path_of_web_dir(output_path)\n            if path in output_mapping:\n                console.warn(\n                    f\"Path {path} has two different outputs. The first one will be used.\"\n                )\n            else:\n                output_mapping[path] = code\n\n        for plugin in config.plugins:\n            for static_file_path, content in plugin.get_static_assets():\n                path = compiler_utils.resolve_path_of_web_dir(static_file_path)\n                if path in output_mapping:\n                    console.warn(\n                        f\"Plugin {plugin.__class__.__name__} is trying to write to {path} but it already exists. The plugin file will be ignored.\"\n                    )\n                else:\n                    output_mapping[path] = (\n                        content.decode(\"utf-8\")\n                        if isinstance(content, bytes)\n                        else content\n                    )\n\n        for plugin_name, file_path, modify_fn in modify_files_tasks:\n            path = compiler_utils.resolve_path_of_web_dir(file_path)\n            file_content = output_mapping.get(path)\n            if file_content is None:\n                if path.exists():\n                    file_content = path.read_text()\n                else:\n                    msg = f\"Plugin {plugin_name} is trying to modify {path} but it does not exist.\"\n                    raise FileNotFoundError(msg)\n            output_mapping[path] = modify_fn(file_content)\n\n        with console.timing(\"Write to Disk\"):\n            for output_path, code in output_mapping.items():\n                compiler_utils.write_file(output_path, code)\n\n    def _write_stateful_pages_marker(self):\n        \"\"\"Write list of routes that create dynamic states for the backend to use later.\"\"\"\n        if self._state is not None:\n            stateful_pages_marker = (\n                prerequisites.get_backend_dir() / constants.Dirs.STATEFUL_PAGES\n            )\n            stateful_pages_marker.parent.mkdir(parents=True, exist_ok=True)\n            with stateful_pages_marker.open(\"w\") as f:\n                json.dump(list(self._stateful_pages), f)\n\n    def add_all_routes_endpoint(self):\n        \"\"\"Add an endpoint to the app that returns all the routes.\"\"\"\n        if not self._api:\n            return\n\n        def all_routes(_request: Request) -> Response:\n            return JSONResponse(list(self._unevaluated_pages.keys()))\n\n        self._api.add_route(\n            str(constants.Endpoint.ALL_ROUTES), all_routes, methods=[\"GET\"]\n        )\n\n    @contextlib.asynccontextmanager\n    async def modify_state(\n        self,\n        token: str,\n        background: bool = False,\n        previous_dirty_vars: dict[str, set[str]] | None = None,\n        **context: Unpack[StateModificationContext],\n    ) -> AsyncIterator[BaseState]:\n        \"\"\"Modify the state out of band.\n\n        Args:\n            token: The token to modify the state for.\n            background: Whether the modification is happening in a background task.\n            previous_dirty_vars: Vars that are considered dirty from a previous operation.\n\n        Yields:\n            The state to modify.\n\n        Raises:\n            RuntimeError: If the app has not been initialized yet.\n        \"\"\"\n        if self.event_namespace is None:\n            msg = \"App has not been initialized yet.\"\n            raise RuntimeError(msg)\n\n        # Get exclusive access to the state.\n        async with self.state_manager.modify_state_with_links(\n            token, previous_dirty_vars=previous_dirty_vars, **context\n        ) as state:\n            # No other event handler can modify the state while in this context.\n            yield state\n            delta = await state._get_resolved_delta()\n            state._clean()\n            if delta:\n                # When the frontend vars are modified emit the delta to the frontend.\n                await self.event_namespace.emit_update(\n                    update=StateUpdate(\n                        delta=delta,\n                        final=True if not background else None,\n                    ),\n                    token=token,\n                )\n\n    def _process_background(\n        self, state: BaseState, event: Event\n    ) -> asyncio.Task | None:\n        \"\"\"Process an event in the background and emit updates as they arrive.\n\n        Args:\n            state: The state to process the event for.\n            event: The event to process.\n\n        Returns:\n            Task if the event was backgroundable, otherwise None\n        \"\"\"\n        substate, handler = state._get_event_handler(event)\n\n        if not handler.is_background:\n            return None\n\n        substate = StateProxy(substate, event)\n\n        async def _coro():\n            \"\"\"Coroutine to process the event and emit updates inside an asyncio.Task.\n\n            Raises:\n                RuntimeError: If the app has not been initialized yet.\n            \"\"\"\n            if self.event_namespace is None:\n                msg = \"App has not been initialized yet.\"\n                raise RuntimeError(msg)\n\n            # Process the event.\n            async for update in state._process_event(\n                handler=handler, state=substate, payload=event.payload\n            ):\n                # Postprocess the event.\n                update = await self._postprocess(state, event, update)\n\n                # Send the update to the client.\n                await self.event_namespace.emit_update(\n                    update=update,\n                    token=event.token,\n                )\n\n        task = asyncio.create_task(\n            _coro(),\n            name=f\"reflex_background_task|{event.name}|{time.time()}|{event.token}\",\n        )\n        self._background_tasks.add(task)\n        # Clean up task from background_tasks set when complete.\n        task.add_done_callback(self._background_tasks.discard)\n        return task\n\n    def _validate_exception_handlers(self):\n        \"\"\"Validate the custom event exception handlers for front- and backend.\n\n        Raises:\n            ValueError: If the custom exception handlers are invalid.\n\n        \"\"\"\n        frontend_arg_spec = {\n            \"exception\": Exception,\n        }\n\n        backend_arg_spec = {\n            \"exception\": Exception,\n        }\n\n        for handler_domain, handler_fn, handler_spec in zip(\n            [\"frontend\", \"backend\"],\n            [self.frontend_exception_handler, self.backend_exception_handler],\n            [\n                frontend_arg_spec,\n                backend_arg_spec,\n            ],\n            strict=True,\n        ):\n            if hasattr(handler_fn, \"__name__\"):\n                fn_name_ = handler_fn.__name__\n            else:\n                fn_name_ = type(handler_fn).__name__\n\n            if isinstance(handler_fn, functools.partial):\n                msg = f\"Provided custom {handler_domain} exception handler `{fn_name_}` is a partial function. Please provide a named function instead.\"\n                raise ValueError(msg)\n\n            if not callable(handler_fn):\n                msg = f\"Provided custom {handler_domain} exception handler `{fn_name_}` is not a function.\"\n                raise ValueError(msg)\n\n            # Allow named functions only as lambda functions cannot be introspected\n            if fn_name_ == \"<lambda>\":\n                msg = f\"Provided custom {handler_domain} exception handler `{fn_name_}` is a lambda function. Please use a named function instead.\"\n                raise ValueError(msg)\n\n            # Check if the function has the necessary annotations and types in the right order\n            argspec = inspect.getfullargspec(handler_fn)\n            arg_annotations = {\n                k: eval(v) if isinstance(v, str) else v\n                for k, v in argspec.annotations.items()\n                if k not in [\"args\", \"kwargs\", \"return\"]\n            }\n\n            for required_arg_index, required_arg in enumerate(handler_spec):\n                if required_arg not in arg_annotations:\n                    msg = f\"Provided custom {handler_domain} exception handler `{fn_name_}` does not take the required argument `{required_arg}`\"\n                    raise ValueError(msg)\n                if list(arg_annotations.keys())[required_arg_index] != required_arg:\n                    msg = (\n                        f\"Provided custom {handler_domain} exception handler `{fn_name_}` has the wrong argument order.\"\n                        f\"Expected `{required_arg}` as the {required_arg_index + 1} argument but got `{list(arg_annotations.keys())[required_arg_index]}`\"\n                    )\n                    raise ValueError(msg)\n\n                if not issubclass(arg_annotations[required_arg], Exception):\n                    msg = (\n                        f\"Provided custom {handler_domain} exception handler `{fn_name_}` has the wrong type for {required_arg} argument.\"\n                        f\"Expected to be `Exception` but got `{arg_annotations[required_arg]}`\"\n                    )\n                    raise ValueError(msg)\n\n            # Check if the return type is valid for backend exception handler\n            if handler_domain == \"backend\":\n                sig = inspect.signature(self.backend_exception_handler)\n                return_type = (\n                    eval(sig.return_annotation)\n                    if isinstance(sig.return_annotation, str)\n                    else sig.return_annotation\n                )\n\n                valid = bool(\n                    return_type == EventSpec\n                    or return_type == EventSpec | None\n                    or return_type == list[EventSpec]\n                    or return_type == inspect.Signature.empty\n                    or return_type is None\n                )\n\n                if not valid:\n                    msg = (\n                        f\"Provided custom {handler_domain} exception handler `{fn_name_}` has the wrong return type.\"\n                        f\"Expected `EventSpec | list[EventSpec] | None` but got `{return_type}`\"\n                    )\n                    raise ValueError(msg)\n\n\nasync def process(\n    app: App, event: Event, sid: str, headers: dict, client_ip: str\n) -> AsyncGenerator[StateUpdate]:\n    \"\"\"Process an event.\n\n    Args:\n        app: The app to process the event for.\n        event: The event to process.\n        sid: The Socket.IO session id.\n        headers: The client headers.\n        client_ip: The client_ip.\n\n    Yields:\n        The state updates after processing the event.\n\n    Raises:\n        Exception: If a reflex specific error occurs during processing the event.\n    \"\"\"\n    from reflex.utils import telemetry\n\n    try:\n        # Add request data to the state.\n        router_data = event.router_data\n        router_data.update({\n            constants.RouteVar.QUERY: format.format_query_params(event.router_data),\n            constants.RouteVar.CLIENT_TOKEN: event.token,\n            constants.RouteVar.SESSION_ID: sid,\n            constants.RouteVar.HEADERS: headers,\n            constants.RouteVar.CLIENT_IP: client_ip,\n        })\n        # Get the state for the session exclusively.\n        async with app.state_manager.modify_state_with_links(\n            event.substate_token, event=event\n        ) as state:\n            # When this is a brand new instance of the state, signal the\n            # frontend to reload before processing it.\n            if (\n                not state.router_data\n                and event.name != get_hydrate_event(state)\n                and app.event_namespace is not None\n            ):\n                await asyncio.create_task(\n                    app.event_namespace.emit(\n                        \"reload\",\n                        data=event,\n                        to=sid,\n                    ),\n                    name=f\"reflex_emit_reload|{event.name}|{time.time()}|{event.token}\",\n                )\n                return\n            router_data[constants.RouteVar.PATH] = \"/\" + (\n                app.router(path) or \"404\"\n                if (path := router_data.get(constants.RouteVar.PATH))\n                else \"404\"\n            ).removeprefix(\"/\")\n            # re-assign only when the value is different\n            if state.router_data != router_data:\n                # assignment will recurse into substates and force recalculation of\n                # dependent ComputedVar (dynamic route variables)\n                state.router_data = router_data\n                state.router = RouterData.from_router_data(router_data)\n\n            # Preprocess the event.\n            update = await app._preprocess(state, event)\n\n            # If there was an update, yield it.\n            if update is not None:\n                yield update\n\n            # Only process the event if there is no update.\n            else:\n                if app._process_background(state, event) is not None:\n                    # `final=True` allows the frontend send more events immediately.\n                    yield StateUpdate(final=True)\n                else:\n                    # Process the event synchronously.\n                    async for update in state._process(event):\n                        # Postprocess the event.\n                        update = await app._postprocess(state, event, update)\n\n                        # Yield the update.\n                        yield update\n    except Exception as ex:\n        telemetry.send_error(ex, context=\"backend\")\n\n        app.backend_exception_handler(ex)\n        raise\n\n\ndef ping(_request: Request) -> Response:\n    \"\"\"Test API endpoint.\n\n    Args:\n        _request: The Starlette request object.\n\n    Returns:\n        The response.\n    \"\"\"\n    return JSONResponse(\"pong\")\n\n\nasync def health(_request: Request) -> JSONResponse:\n    \"\"\"Health check endpoint to assess the status of the database and Redis services.\n\n    Args:\n        _request: The Starlette request object.\n\n    Returns:\n        JSONResponse: A JSON object with the health status:\n            - \"status\" (bool): Overall health, True if all checks pass.\n            - \"db\" (bool or str): Database status - True, False, or \"NA\".\n            - \"redis\" (bool or str): Redis status - True, False, or \"NA\".\n    \"\"\"\n    health_status = {\"status\": True}\n    status_code = 200\n\n    tasks = []\n\n    if prerequisites.check_db_used():\n        from reflex.model import get_db_status\n\n        tasks.append(run_in_thread(get_db_status))\n    if prerequisites.check_redis_used():\n        tasks.append(prerequisites.get_redis_status())\n\n    results = await asyncio.gather(*tasks)\n\n    for result in results:\n        health_status |= result\n\n    if \"redis\" in health_status and health_status[\"redis\"] is None:\n        health_status[\"redis\"] = False\n\n    if not all(health_status.values()):\n        health_status[\"status\"] = False\n        status_code = 503\n\n    return JSONResponse(content=health_status, status_code=status_code)\n\n\nclass _UploadStreamingResponse(StreamingResponse):\n    \"\"\"Streaming response that always releases upload form resources.\"\"\"\n\n    _on_finish: Callable[[], Awaitable[None]]\n\n    def __init__(\n        self,\n        *args: Any,\n        on_finish: Callable[[], Awaitable[None]],\n        **kwargs: Any,\n    ) -> None:\n        super().__init__(*args, **kwargs)\n        self._on_finish = on_finish\n\n    async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:\n        try:\n            await super().__call__(scope, receive, send)\n        finally:\n            await self._on_finish()\n\n\ndef upload(app: App):\n    \"\"\"Upload a file.\n\n    Args:\n        app: The app to upload the file for.\n\n    Returns:\n        The upload function.\n    \"\"\"\n\n    async def upload_file(request: Request):\n        \"\"\"Upload a file.\n\n        Args:\n            request: The Starlette request object.\n\n        Returns:\n            StreamingResponse yielding newline-delimited JSON of StateUpdate\n            emitted by the upload handler.\n\n        Raises:\n            UploadValueError: if there are no args with supported annotation.\n            UploadTypeError: if a background task is used as the handler.\n            HTTPException: when the request does not include token / handler headers.\n        \"\"\"\n        from reflex.utils.exceptions import UploadTypeError, UploadValueError\n\n        # Get the files from the request.\n        try:\n            form_data = await request.form()\n        except ClientDisconnect:\n            return Response()  # user cancelled\n\n        form_data_closed = False\n\n        async def _close_form_data() -> None:\n            \"\"\"Close the parsed form data exactly once.\"\"\"\n            nonlocal form_data_closed\n            if form_data_closed:\n                return\n            form_data_closed = True\n            await form_data.close()\n\n        async def _create_upload_event() -> Event:\n            \"\"\"Create an upload event using the live Starlette temp files.\n\n            Returns:\n                The upload event backed by the original temp files.\n            \"\"\"\n            files = form_data.getlist(\"files\")\n            if not files:\n                msg = \"No files were uploaded.\"\n                raise UploadValueError(msg)\n\n            token = request.headers.get(\"reflex-client-token\")\n            handler = request.headers.get(\"reflex-event-handler\")\n\n            if not token or not handler:\n                raise HTTPException(\n                    status_code=400,\n                    detail=\"Missing reflex-client-token or reflex-event-handler header.\",\n                )\n\n            # Get the state for the session.\n            substate_token = _substate_key(token, handler.rpartition(\".\")[0])\n            state = await app.state_manager.get_state(substate_token)\n\n            handler_upload_param = ()\n\n            _current_state, event_handler = state._get_event_handler(handler)\n\n            if event_handler.is_background:\n                msg = f\"@rx.event(background=True) is not supported for upload handler `{handler}`.\"\n                raise UploadTypeError(msg)\n            func = event_handler.fn\n            if isinstance(func, functools.partial):\n                func = func.func\n            for k, v in get_type_hints(func).items():\n                if types.is_generic_alias(v) and types._issubclass(\n                    get_args(v)[0],\n                    UploadFile,\n                ):\n                    handler_upload_param = (k, v)\n                    break\n\n            if not handler_upload_param:\n                msg = (\n                    f\"`{handler}` handler should have a parameter annotated as \"\n                    \"list[rx.UploadFile]\"\n                )\n                raise UploadValueError(msg)\n\n            # Keep the parsed form data alive until the upload event finishes so\n            # the underlying Starlette temp files remain available to the handler.\n            file_uploads = []\n            for file in files:\n                if not isinstance(file, StarletteUploadFile):\n                    raise UploadValueError(\n                        \"Uploaded file is not an UploadFile.\" + str(file)\n                    )\n                file_uploads.append(\n                    UploadFile(\n                        file=file.file,\n                        path=Path(file.filename.lstrip(\"/\")) if file.filename else None,\n                        size=file.size,\n                        headers=file.headers,\n                    )\n                )\n\n            return Event(\n                token=token,\n                name=handler,\n                payload={handler_upload_param[0]: file_uploads},\n            )\n\n        event: Event | None = None\n        try:\n            event = await _create_upload_event()\n        finally:\n            if event is None:\n                await _close_form_data()\n\n        async def _ndjson_updates():\n            \"\"\"Process the upload event, generating ndjson updates.\n\n            Yields:\n                Each state update as JSON followed by a new line.\n            \"\"\"\n            # Process the event.\n            async with app.state_manager.modify_state_with_links(\n                event.substate_token, event=event\n            ) as state:\n                async for update in state._process(event):\n                    # Postprocess the event.\n                    update = await app._postprocess(state, event, update)\n                    yield update.json() + \"\\n\"\n\n        # Stream updates to client\n        return _UploadStreamingResponse(\n            _ndjson_updates(),\n            media_type=\"application/x-ndjson\",\n            on_finish=_close_form_data,\n        )\n\n    return upload_file\n\n\nclass EventNamespace(AsyncNamespace):\n    \"\"\"The event namespace.\"\"\"\n\n    # The application object.\n    app: App\n\n    def __init__(self, namespace: str, app: App):\n        \"\"\"Initialize the event namespace.\n\n        Args:\n            namespace: The namespace.\n            app: The application object.\n        \"\"\"\n        super().__init__(namespace)\n        self.app = app\n\n        # Use TokenManager for distributed duplicate tab prevention\n        self._token_manager = TokenManager.create()\n\n    @property\n    def token_to_sid(self) -> Mapping[str, str]:\n        \"\"\"Get token to SID mapping for backward compatibility.\n\n        Note: this mapping is read-only.\n\n        Returns:\n            The token to SID mapping.\n        \"\"\"\n        # For backward compatibility, expose the underlying dict\n        return self._token_manager.token_to_sid\n\n    @property\n    def sid_to_token(self) -> dict[str, str]:\n        \"\"\"Get SID to token mapping for backward compatibility.\n\n        Returns:\n            The SID to token mapping dict.\n        \"\"\"\n        # For backward compatibility, expose the underlying dict\n        return self._token_manager.sid_to_token\n\n    async def on_connect(self, sid: str, environ: dict):\n        \"\"\"Event for when the websocket is connected.\n\n        Args:\n            sid: The Socket.IO session id.\n            environ: The request information, including HTTP headers.\n        \"\"\"\n        if isinstance(self._token_manager, RedisTokenManager):\n            # Make sure this instance is watching for updates from other instances.\n            self._token_manager.ensure_lost_and_found_task(self.emit_update)\n        query_params = urllib.parse.parse_qs(environ.get(\"QUERY_STRING\", \"\"))\n        token_list = query_params.get(\"token\", [])\n        if token_list:\n            await self.link_token_to_sid(sid, token_list[0])\n        else:\n            console.warn(f\"No token provided in connection for session {sid}\")\n\n        subprotocol = environ.get(\"HTTP_SEC_WEBSOCKET_PROTOCOL\")\n        if subprotocol and subprotocol != constants.Reflex.VERSION:\n            console.warn(\n                f\"Frontend version {subprotocol} for session {sid} does not match the backend version {constants.Reflex.VERSION}.\"\n            )\n\n    def on_disconnect(self, sid: str) -> asyncio.Task | None:\n        \"\"\"Event for when the websocket disconnects.\n\n        Args:\n            sid: The Socket.IO session id.\n\n        Returns:\n            An asyncio Task for cleaning up the token, or None.\n        \"\"\"\n        # Get token before cleaning up\n        disconnect_token = self.sid_to_token.get(sid)\n        if disconnect_token:\n            # Use async cleanup through token manager\n            task = asyncio.create_task(\n                self._token_manager.disconnect_token(disconnect_token, sid),\n                name=f\"reflex_disconnect_token|{disconnect_token}|{time.time()}\",\n            )\n            # Don't await to avoid blocking disconnect, but handle potential errors\n            task.add_done_callback(\n                lambda t: (\n                    t.exception()\n                    and console.error(f\"Token cleanup error: {t.exception()}\")\n                )\n            )\n            return task\n        return None\n\n    async def emit_update(self, update: StateUpdate, token: str) -> None:\n        \"\"\"Emit an update to the client.\n\n        Args:\n            update: The state update to send.\n            token: The client token (tab) associated with the event.\n        \"\"\"\n        client_token, _ = _split_substate_key(token)\n        socket_record = self._token_manager.token_to_socket.get(client_token)\n        if (\n            socket_record is None\n            or socket_record.instance_id != self._token_manager.instance_id\n        ):\n            if isinstance(self._token_manager, RedisTokenManager):\n                # The socket belongs to another instance of the app, send it to the lost and found.\n                if not await self._token_manager.emit_lost_and_found(\n                    client_token, update\n                ):\n                    console.warn(\n                        f\"Failed to send delta to lost and found for client {token!r}\"\n                    )\n            else:\n                # If the socket record is None, we are not connected to a client. Prevent sending\n                # updates to all clients.\n                console.warn(\n                    f\"Attempting to send delta to disconnected client {token!r}\"\n                )\n            return\n        # Creating a task prevents the update from being blocked behind other coroutines.\n        await asyncio.create_task(\n            self.emit(str(constants.SocketEvent.EVENT), update, to=socket_record.sid),\n            name=f\"reflex_emit_event|{token}|{socket_record.sid}|{time.time()}\",\n        )\n\n    async def on_event(self, sid: str, data: Any):\n        \"\"\"Event for receiving front-end websocket events.\n\n        Args:\n            sid: The Socket.IO session id.\n            data: The event data.\n\n        Raises:\n            RuntimeError: If the Socket.IO is badly initialized.\n            EventDeserializationError: If the event data is not a dictionary.\n        \"\"\"\n        fields = data\n\n        if isinstance(fields, str):\n            console.warn(\n                \"Received event data as a string. This generally should not happen and may indicate a bug.\"\n                f\" Event data: {fields}\"\n            )\n            try:\n                fields = json.loads(fields)\n            except json.JSONDecodeError as ex:\n                msg = f\"Failed to deserialize event data: {fields}.\"\n                raise exceptions.EventDeserializationError(msg) from ex\n\n        if not isinstance(fields, dict):\n            msg = f\"Event data must be a dictionary, but received {fields} of type {type(fields)}.\"\n            raise exceptions.EventDeserializationError(msg)\n\n        try:\n            # Get the event.\n            event = Event(**{k: v for k, v in fields.items() if k in _EVENT_FIELDS})\n        except (TypeError, ValueError) as ex:\n            msg = f\"Failed to deserialize event data: {fields}.\"\n            raise exceptions.EventDeserializationError(msg) from ex\n\n        # Correct the token if it doesn't match what we expect for this SID\n        expected_token = self.sid_to_token.get(sid)\n        if expected_token and event.token != expected_token:\n            # Create new event with corrected token since Event is frozen\n            from dataclasses import replace\n\n            event = replace(event, token=expected_token)\n\n        # Get the event environment.\n        if self.app.sio is None:\n            msg = \"Socket.IO is not initialized.\"\n            raise RuntimeError(msg)\n        environ = self.app.sio.get_environ(sid, self.namespace)\n        if environ is None:\n            msg = \"Socket.IO environ is not initialized.\"\n            raise RuntimeError(msg)\n\n        # Get the client headers.\n        headers = {\n            k.decode(\"utf-8\"): v.decode(\"utf-8\")\n            for (k, v) in environ[\"asgi.scope\"][\"headers\"]\n        }\n\n        # Get the client IP\n        try:\n            client_ip = environ[\"asgi.scope\"][\"client\"][0]\n            headers[\"asgi-scope-client\"] = client_ip\n        except (KeyError, IndexError):\n            client_ip = environ.get(\"REMOTE_ADDR\", \"0.0.0.0\")\n\n        # Unroll reverse proxy forwarded headers.\n        client_ip = (\n            headers\n            .get(\n                \"x-forwarded-for\",\n                client_ip,\n            )\n            .partition(\",\")[0]\n            .strip()\n        )\n\n        async with contextlib.aclosing(\n            process(self.app, event, sid, headers, client_ip)\n        ) as updates_gen:\n            # Process the events.\n            async for update in updates_gen:\n                # Emit the update from processing the event.\n                await self.emit_update(update=update, token=event.token)\n\n    async def on_ping(self, sid: str):\n        \"\"\"Event for testing the API endpoint.\n\n        Args:\n            sid: The Socket.IO session id.\n        \"\"\"\n        # Emit the test event.\n        await self.emit(str(constants.SocketEvent.PING), \"pong\", to=sid)\n\n    async def link_token_to_sid(self, sid: str, token: str):\n        \"\"\"Link a token to a session id.\n\n        Args:\n            sid: The Socket.IO session id.\n            token: The client token.\n        \"\"\"\n        # Use TokenManager for duplicate detection and Redis support\n        new_token = await self._token_manager.link_token_to_sid(token, sid)\n\n        if new_token:\n            # Duplicate detected, emit new token to client\n            await self.emit(\"new_token\", new_token, to=sid)\n\n        # Update client state to apply new sid/token for running background tasks.\n        async with self.app.state_manager.modify_state(\n            _substate_key(new_token or token, self.app.state_manager.state)\n        ) as state:\n            state.router_data[constants.RouteVar.SESSION_ID] = sid\n            state.router = RouterData.from_router_data(state.router_data)\n"
  },
  {
    "path": "reflex/app_mixins/__init__.py",
    "content": "\"\"\"Reflex AppMixins package.\"\"\"\n\nfrom .lifespan import LifespanMixin\nfrom .middleware import MiddlewareMixin\nfrom .mixin import AppMixin\n"
  },
  {
    "path": "reflex/app_mixins/lifespan.py",
    "content": "\"\"\"Mixin that allow tasks to run during the whole app lifespan.\"\"\"\n\nfrom __future__ import annotations\n\nimport asyncio\nimport contextlib\nimport dataclasses\nimport functools\nimport inspect\nimport time\nfrom collections.abc import Callable, Coroutine\n\nfrom starlette.applications import Starlette\n\nfrom reflex.utils import console\nfrom reflex.utils.exceptions import InvalidLifespanTaskTypeError\n\nfrom .mixin import AppMixin\n\n\n@dataclasses.dataclass\nclass LifespanMixin(AppMixin):\n    \"\"\"A Mixin that allow tasks to run during the whole app lifespan.\"\"\"\n\n    # Lifespan tasks that are planned to run.\n    lifespan_tasks: set[asyncio.Task | Callable] = dataclasses.field(\n        default_factory=set\n    )\n\n    @contextlib.asynccontextmanager\n    async def _run_lifespan_tasks(self, app: Starlette):\n        running_tasks = []\n        try:\n            async with contextlib.AsyncExitStack() as stack:\n                for task in self.lifespan_tasks:\n                    run_msg = f\"Started lifespan task: {task.__name__} as {{type}}\"  # pyright: ignore [reportAttributeAccessIssue]\n                    if isinstance(task, asyncio.Task):\n                        running_tasks.append(task)\n                    else:\n                        task_name = task.__name__\n                        signature = inspect.signature(task)\n                        if \"app\" in signature.parameters:\n                            task = functools.partial(task, app=app)\n                        t_ = task()\n                        if isinstance(t_, contextlib._AsyncGeneratorContextManager):\n                            await stack.enter_async_context(t_)\n                            console.debug(run_msg.format(type=\"asynccontextmanager\"))\n                        elif isinstance(t_, Coroutine):\n                            task_ = asyncio.create_task(\n                                t_,\n                                name=f\"reflex_lifespan_task|{task_name}|{time.time()}\",\n                            )\n                            task_.add_done_callback(lambda t: t.result())\n                            running_tasks.append(task_)\n                            console.debug(run_msg.format(type=\"coroutine\"))\n                        else:\n                            console.debug(run_msg.format(type=\"function\"))\n                yield\n        finally:\n            for task in running_tasks:\n                console.debug(f\"Canceling lifespan task: {task}\")\n                task.cancel(msg=\"lifespan_cleanup\")\n        # Disassociate sid / token pairings so they can be reconnected properly.\n        try:\n            event_namespace = self.event_namespace  # pyright: ignore[reportAttributeAccessIssue]\n        except AttributeError:\n            pass\n        else:\n            try:\n                if event_namespace:\n                    await event_namespace._token_manager.disconnect_all()\n            except Exception as e:\n                console.error(f\"Error during lifespan cleanup: {e}\")\n        # Flush any pending writes from the state manager.\n        try:\n            state_manager = self.state_manager  # pyright: ignore[reportAttributeAccessIssue]\n        except AttributeError:\n            pass\n        else:\n            await state_manager.close()\n\n    def register_lifespan_task(self, task: Callable | asyncio.Task, **task_kwargs):\n        \"\"\"Register a task to run during the lifespan of the app.\n\n        Args:\n            task: The task to register.\n            **task_kwargs: The kwargs of the task.\n\n        Raises:\n            InvalidLifespanTaskTypeError: If the task is a generator function.\n        \"\"\"\n        if inspect.isgeneratorfunction(task) or inspect.isasyncgenfunction(task):\n            msg = f\"Task {task.__name__} of type generator must be decorated with contextlib.asynccontextmanager.\"\n            raise InvalidLifespanTaskTypeError(msg)\n\n        task_name = task.__name__  # pyright: ignore [reportAttributeAccessIssue]\n        if task_kwargs:\n            original_task = task\n            task = functools.partial(task, **task_kwargs)  # pyright: ignore [reportArgumentType]\n            functools.update_wrapper(task, original_task)  # pyright: ignore [reportArgumentType]\n        self.lifespan_tasks.add(task)\n        console.debug(f\"Registered lifespan task: {task_name}\")\n"
  },
  {
    "path": "reflex/app_mixins/middleware.py",
    "content": "\"\"\"Middleware Mixin that allow to add middleware to the app.\"\"\"\n\nfrom __future__ import annotations\n\nimport dataclasses\nimport inspect\n\nfrom reflex.event import Event\nfrom reflex.middleware import HydrateMiddleware, Middleware\nfrom reflex.state import BaseState, StateUpdate\n\nfrom .mixin import AppMixin\n\n\n@dataclasses.dataclass\nclass MiddlewareMixin(AppMixin):\n    \"\"\"Middleware Mixin that allow to add middleware to the app.\"\"\"\n\n    # Middleware to add to the app. Users should use `add_middleware`.\n    _middlewares: list[Middleware] = dataclasses.field(default_factory=list)\n\n    def _init_mixin(self):\n        self._middlewares.append(HydrateMiddleware())\n\n    def add_middleware(self, middleware: Middleware, index: int | None = None):\n        \"\"\"Add middleware to the app.\n\n        Args:\n            middleware: The middleware to add.\n            index: The index to add the middleware at.\n        \"\"\"\n        if index is None:\n            self._middlewares.append(middleware)\n        else:\n            self._middlewares.insert(index, middleware)\n\n    async def _preprocess(self, state: BaseState, event: Event) -> StateUpdate | None:\n        \"\"\"Preprocess the event.\n\n        This is where middleware can modify the event before it is processed.\n        Each middleware is called in the order it was added to the app.\n\n        If a middleware returns an update, the event is not processed and the\n        update is returned.\n\n        Args:\n            state: The state to preprocess.\n            event: The event to preprocess.\n\n        Returns:\n            An optional state to return.\n        \"\"\"\n        for middleware in self._middlewares:\n            out = middleware.preprocess(app=self, state=state, event=event)  # pyright: ignore [reportArgumentType]\n            if inspect.isawaitable(out):\n                out = await out\n            if out is not None:\n                return out\n        return None\n\n    async def _postprocess(\n        self, state: BaseState, event: Event, update: StateUpdate\n    ) -> StateUpdate:\n        \"\"\"Postprocess the event.\n\n        This is where middleware can modify the delta after it is processed.\n        Each middleware is called in the order it was added to the app.\n\n        Args:\n            state: The state to postprocess.\n            event: The event to postprocess.\n            update: The current state update.\n\n        Returns:\n            The state update to return.\n        \"\"\"\n        out = update\n        for middleware in self._middlewares:\n            out = middleware.postprocess(\n                app=self,  # pyright: ignore [reportArgumentType]\n                state=state,\n                event=event,\n                update=update,\n            )\n            if inspect.isawaitable(out):\n                out = await out\n        return out  # pyright: ignore[reportReturnType]\n"
  },
  {
    "path": "reflex/app_mixins/mixin.py",
    "content": "\"\"\"Default mixin for all app mixins.\"\"\"\n\nimport dataclasses\n\n\n@dataclasses.dataclass\nclass AppMixin:\n    \"\"\"Define the base class for all app mixins.\"\"\"\n\n    def _init_mixin(self):\n        \"\"\"Initialize the mixin.\n\n        Any App mixin can override this method to perform any initialization.\n        \"\"\"\n"
  },
  {
    "path": "reflex/assets.py",
    "content": "\"\"\"Helper functions for adding assets to the app.\"\"\"\n\nimport inspect\nfrom pathlib import Path\n\nfrom reflex import constants\nfrom reflex.environment import EnvironmentVariables\n\n\ndef remove_stale_external_asset_symlinks():\n    \"\"\"Remove broken symlinks and empty directories in assets/external/.\n\n    When a Python module directory that uses rx.asset(shared=True) is renamed\n    or deleted, stale symlinks remain in assets/external/ pointing to the old\n    path. This cleanup prevents issues with file watchers detecting symlink\n    re-creation during import.\n    \"\"\"\n    external_dir = (\n        Path.cwd() / constants.Dirs.APP_ASSETS / constants.Dirs.EXTERNAL_APP_ASSETS\n    )\n    if not external_dir.exists():\n        return\n\n    # Remove broken symlinks.\n    broken = [\n        p\n        for p in external_dir.rglob(\"*\")\n        if p.is_symlink() and not p.resolve().exists()\n    ]\n    for path in broken:\n        path.unlink()\n\n    # Remove empty directories left behind (deepest first).\n    for dirpath in sorted(external_dir.rglob(\"*\"), reverse=True):\n        if dirpath.is_dir() and not dirpath.is_symlink() and not any(dirpath.iterdir()):\n            dirpath.rmdir()\n\n\ndef asset(\n    path: str,\n    shared: bool = False,\n    subfolder: str | None = None,\n    _stack_level: int = 1,\n) -> str:\n    \"\"\"Add an asset to the app, either shared as a symlink or local.\n\n    Shared/External/Library assets:\n        Place the file next to your including python file.\n        Links the file to the app's external assets directory.\n\n    Example:\n    ```python\n    # my_custom_javascript.js is a shared asset located next to the including python file.\n    rx.script(src=rx.asset(path=\"my_custom_javascript.js\", shared=True))\n    rx.image(src=rx.asset(path=\"test_image.png\", shared=True, subfolder=\"subfolder\"))\n    ```\n\n    Local/Internal assets:\n        Place the file in the app's assets/ directory.\n\n    Example:\n    ```python\n    # local_image.png is an asset located in the app's assets/ directory. It cannot be shared when developing a library.\n    rx.image(src=rx.asset(path=\"local_image.png\"))\n    ```\n\n    Args:\n        path: The relative path of the asset.\n        subfolder: The directory to place the shared asset in.\n        shared: Whether to expose the asset to other apps.\n        _stack_level: The stack level to determine the calling file, defaults to\n            the immediate caller 1. When using rx.asset via a helper function,\n            increase this number for each helper function in the stack.\n\n    Returns:\n        The relative URL to the asset.\n\n    Raises:\n        FileNotFoundError: If the file does not exist.\n        ValueError: If subfolder is provided for local assets.\n    \"\"\"\n    assets = constants.Dirs.APP_ASSETS\n    backend_only = EnvironmentVariables.REFLEX_BACKEND_ONLY.get()\n\n    # Local asset handling\n    if not shared:\n        cwd = Path.cwd()\n        src_file_local = cwd / assets / path\n        if subfolder is not None:\n            msg = \"Subfolder is not supported for local assets.\"\n            raise ValueError(msg)\n        if not backend_only and not src_file_local.exists():\n            msg = f\"File not found: {src_file_local}\"\n            raise FileNotFoundError(msg)\n        return f\"/{path}\"\n\n    # Shared asset handling\n    # Determine the file by which the asset is exposed.\n    frame = inspect.stack()[_stack_level]\n    calling_file = frame.filename\n    module = inspect.getmodule(frame[0])\n    assert module is not None\n\n    external = constants.Dirs.EXTERNAL_APP_ASSETS\n    src_file_shared = Path(calling_file).parent / path\n    if not src_file_shared.exists():\n        msg = f\"File not found: {src_file_shared}\"\n        raise FileNotFoundError(msg)\n\n    caller_module_path = module.__name__.replace(\".\", \"/\")\n    subfolder = f\"{caller_module_path}/{subfolder}\" if subfolder else caller_module_path\n\n    # Symlink the asset to the app's external assets directory if running frontend.\n    if not backend_only:\n        # Create the asset folder in the currently compiling app.\n        asset_folder = Path.cwd() / assets / external / subfolder\n        asset_folder.mkdir(parents=True, exist_ok=True)\n\n        dst_file = asset_folder / path\n\n        if not dst_file.exists() and (\n            not dst_file.is_symlink() or dst_file.resolve() != src_file_shared.resolve()\n        ):\n            try:\n                dst_file.symlink_to(src_file_shared)\n            except FileExistsError:\n                # This happens when Simon builds the app on a bind mount in a docker container.\n                dst_file.unlink()\n                dst_file.symlink_to(src_file_shared)\n\n    return f\"/{external}/{subfolder}/{path}\"\n"
  },
  {
    "path": "reflex/base.py",
    "content": "\"\"\"Define the base Reflex class.\"\"\"\n\nfrom importlib.util import find_spec\n\nif find_spec(\"pydantic\") and find_spec(\"pydantic.v1\"):\n    from pydantic.v1 import BaseModel\n\n    from reflex.utils.compat import ModelMetaclassLazyAnnotations\n\n    class Base(BaseModel, metaclass=ModelMetaclassLazyAnnotations):\n        \"\"\"The base class subclassed by all Reflex classes.\n\n        This class wraps Pydantic and provides common methods such as\n        serialization and setting fields.\n\n        Any data structure that needs to be transferred between the\n        frontend and backend should subclass this class.\n        \"\"\"\n\n        class Config:\n            \"\"\"Pydantic config.\"\"\"\n\n            arbitrary_types_allowed = True\n            use_enum_values = True\n            extra = \"allow\"\n\n        def __init_subclass__(cls):\n            \"\"\"Warn that rx.Base is deprecated.\"\"\"\n            from reflex.utils import console\n\n            console.deprecate(\n                feature_name=\"rx.Base\",\n                reason=f\"{cls!r} is subclassing rx.Base. You can subclass from `pydantic.BaseModel` directly instead or use dataclasses if possible.\",\n                deprecation_version=\"0.8.15\",\n                removal_version=\"0.9.0\",\n            )\n            super().__init_subclass__()\n\n        def json(self) -> str:\n            \"\"\"Convert the object to a json string.\n\n            Returns:\n                The object as a json string.\n            \"\"\"\n            from reflex.utils.serializers import serialize\n\n            return self.__config__.json_dumps(\n                self.dict(),\n                default=serialize,\n            )\n\nelse:\n\n    class PydanticNotFoundFallback:\n        \"\"\"Fallback base class for environments without Pydantic.\"\"\"\n\n        def __init__(self, *args, **kwargs):\n            \"\"\"Initialize the base class.\n\n            Args:\n                *args: Positional arguments.\n                **kwargs: Keyword arguments.\n\n            Raises:\n                ImportError: As Pydantic is not installed.\n            \"\"\"\n            msg = (\n                \"Pydantic is not installed. Please install it to use rx.Base.\"\n                \"You can install it with `pip install pydantic`.\"\n            )\n            raise ImportError(msg)\n\n    Base = PydanticNotFoundFallback  # pyright: ignore[reportAssignmentType]\n"
  },
  {
    "path": "reflex/compiler/__init__.py",
    "content": "\"\"\"The Reflex compiler.\"\"\"\n"
  },
  {
    "path": "reflex/compiler/compiler.py",
    "content": "\"\"\"Compiler for the reflex apps.\"\"\"\n\nfrom __future__ import annotations\n\nimport sys\nfrom collections.abc import Callable, Iterable, Sequence\nfrom inspect import getmodule\nfrom pathlib import Path\nfrom typing import TYPE_CHECKING, Any\n\nfrom reflex import constants\nfrom reflex.compiler import templates, utils\nfrom reflex.components.base.fragment import Fragment\nfrom reflex.components.component import (\n    BaseComponent,\n    Component,\n    ComponentStyle,\n    CustomComponent,\n    StatefulComponent,\n)\nfrom reflex.config import get_config\nfrom reflex.constants.compiler import PageNames, ResetStylesheet\nfrom reflex.constants.state import FIELD_MARKER\nfrom reflex.environment import environment\nfrom reflex.state import BaseState\nfrom reflex.style import SYSTEM_COLOR_MODE\nfrom reflex.utils import console, path_ops\nfrom reflex.utils.exceptions import ReflexError\nfrom reflex.utils.exec import is_prod_mode\nfrom reflex.utils.format import to_title_case\nfrom reflex.utils.imports import ImportVar, ParsedImportDict\nfrom reflex.utils.prerequisites import get_web_dir\nfrom reflex.vars.base import LiteralVar, Var\n\n\ndef _apply_common_imports(\n    imports: dict[str, list[ImportVar]],\n):\n    imports.setdefault(\"@emotion/react\", []).append(ImportVar(\"jsx\"))\n    imports.setdefault(\"react\", []).extend(\n        [ImportVar(\"Fragment\"), ImportVar(\"useEffect\")],\n    )\n\n\ndef _compile_document_root(root: Component) -> str:\n    \"\"\"Compile the document root.\n\n    Args:\n        root: The document root to compile.\n\n    Returns:\n        The compiled document root.\n    \"\"\"\n    document_root_imports = root._get_all_imports()\n    _apply_common_imports(document_root_imports)\n    return templates.document_root_template(\n        imports=utils.compile_imports(document_root_imports),\n        document=root.render(),\n    )\n\n\ndef _normalize_library_name(lib: str) -> str:\n    \"\"\"Normalize the library name.\n\n    Args:\n        lib: The library name to normalize.\n\n    Returns:\n        The normalized library name.\n    \"\"\"\n    if lib == \"react\":\n        return \"React\"\n    return lib.replace(\"$/\", \"\").replace(\"@\", \"\").replace(\"/\", \"_\").replace(\"-\", \"_\")\n\n\ndef _compile_app(app_root: Component) -> str:\n    \"\"\"Compile the app template component.\n\n    Args:\n        app_root: The app root to compile.\n\n    Returns:\n        The compiled app.\n    \"\"\"\n    from reflex.components.dynamic import bundled_libraries\n\n    window_libraries = [\n        (_normalize_library_name(name), name) for name in bundled_libraries\n    ]\n\n    window_libraries_deduped = list(dict.fromkeys(window_libraries))\n\n    app_root_imports = app_root._get_all_imports()\n    _apply_common_imports(app_root_imports)\n\n    return templates.app_root_template(\n        imports=utils.compile_imports(app_root_imports),\n        custom_codes=app_root._get_all_custom_code(),\n        hooks=app_root._get_all_hooks(),\n        window_libraries=window_libraries_deduped,\n        render=app_root.render(),\n        dynamic_imports=app_root._get_all_dynamic_imports(),\n    )\n\n\ndef _compile_theme(theme: str) -> str:\n    \"\"\"Compile the theme.\n\n    Args:\n        theme: The theme to compile.\n\n    Returns:\n        The compiled theme.\n    \"\"\"\n    return templates.theme_template(theme=theme)\n\n\ndef _compile_contexts(state: type[BaseState] | None, theme: Component | None) -> str:\n    \"\"\"Compile the initial state and contexts.\n\n    Args:\n        state: The app state.\n        theme: The top-level app theme.\n\n    Returns:\n        The compiled context file.\n    \"\"\"\n    appearance = getattr(theme, \"appearance\", None)\n    if appearance is None or str(LiteralVar.create(appearance)) == '\"inherit\"':\n        appearance = LiteralVar.create(SYSTEM_COLOR_MODE)\n\n    return (\n        templates.context_template(\n            initial_state=utils.compile_state(state),\n            state_name=state.get_name(),\n            client_storage=utils.compile_client_storage(state),\n            is_dev_mode=not is_prod_mode(),\n            default_color_mode=str(appearance),\n        )\n        if state\n        else templates.context_template(\n            is_dev_mode=not is_prod_mode(),\n            default_color_mode=str(appearance),\n        )\n    )\n\n\ndef _compile_page(component: BaseComponent) -> str:\n    \"\"\"Compile the component.\n\n    Args:\n        component: The component to compile.\n\n    Returns:\n        The compiled component.\n    \"\"\"\n    imports = component._get_all_imports()\n    _apply_common_imports(imports)\n    imports = utils.compile_imports(imports)\n\n    # Compile the code to render the component.\n    return templates.page_template(\n        imports=imports,\n        dynamic_imports=sorted(component._get_all_dynamic_imports()),\n        custom_codes=component._get_all_custom_code(),\n        hooks=component._get_all_hooks(),\n        render=component.render(),\n    )\n\n\ndef compile_root_stylesheet(\n    stylesheets: list[str], reset_style: bool = True\n) -> tuple[str, str]:\n    \"\"\"Compile the root stylesheet.\n\n    Args:\n        stylesheets: The stylesheets to include in the root stylesheet.\n        reset_style: Whether to include CSS reset for margin and padding.\n\n    Returns:\n        The path and code of the compiled root stylesheet.\n    \"\"\"\n    output_path = utils.get_root_stylesheet_path()\n\n    code = _compile_root_stylesheet(stylesheets, reset_style)\n\n    return output_path, code\n\n\ndef _validate_stylesheet(stylesheet_full_path: Path, assets_app_path: Path) -> None:\n    \"\"\"Validate the stylesheet.\n\n    Args:\n        stylesheet_full_path: The stylesheet to validate.\n        assets_app_path: The path to the assets directory.\n\n    Raises:\n        ValueError: If the stylesheet is not supported.\n        FileNotFoundError: If the stylesheet is not found.\n    \"\"\"\n    suffix = stylesheet_full_path.suffix[1:] if stylesheet_full_path.suffix else \"\"\n    if suffix not in constants.Reflex.STYLESHEETS_SUPPORTED:\n        msg = f\"Stylesheet file {stylesheet_full_path} is not supported.\"\n        raise ValueError(msg)\n    if not stylesheet_full_path.absolute().is_relative_to(assets_app_path.absolute()):\n        msg = f\"Cannot include stylesheets from outside the assets directory: {stylesheet_full_path}\"\n        raise FileNotFoundError(msg)\n    if not stylesheet_full_path.name:\n        msg = f\"Stylesheet file name cannot be empty: {stylesheet_full_path}\"\n        raise ValueError(msg)\n    if (\n        len(\n            stylesheet_full_path\n            .absolute()\n            .relative_to(assets_app_path.absolute())\n            .parts\n        )\n        == 1\n        and stylesheet_full_path.stem == PageNames.STYLESHEET_ROOT\n    ):\n        msg = f\"Stylesheet file name cannot be '{PageNames.STYLESHEET_ROOT}': {stylesheet_full_path}\"\n        raise ValueError(msg)\n\n\nRADIX_THEMES_STYLESHEET = \"@radix-ui/themes/styles.css\"\n\n\ndef _compile_root_stylesheet(stylesheets: list[str], reset_style: bool = True) -> str:\n    \"\"\"Compile the root stylesheet.\n\n    Args:\n        stylesheets: The stylesheets to include in the root stylesheet.\n        reset_style: Whether to include CSS reset for margin and padding.\n\n    Returns:\n        The compiled root stylesheet.\n\n    Raises:\n        FileNotFoundError: If a specified stylesheet in assets directory does not exist.\n    \"\"\"\n    # Add stylesheets from plugins.\n    sheets = []\n\n    # Add CSS reset if enabled\n    if reset_style:\n        # Reference the vendored style reset file (automatically copied from .templates/web)\n        sheets.append(f\"./{ResetStylesheet.FILENAME}\")\n\n    sheets.extend(\n        [RADIX_THEMES_STYLESHEET]\n        + [\n            sheet\n            for plugin in get_config().plugins\n            for sheet in plugin.get_stylesheet_paths()\n        ]\n    )\n\n    failed_to_import_sass = False\n    assets_app_path = Path.cwd() / constants.Dirs.APP_ASSETS\n\n    stylesheets_files: list[Path] = []\n    stylesheets_urls = []\n\n    for stylesheet in stylesheets:\n        if not utils.is_valid_url(stylesheet):\n            # check if stylesheet provided exists.\n            stylesheet_full_path = assets_app_path / stylesheet.strip(\"/\")\n\n            if not stylesheet_full_path.exists():\n                msg = f\"The stylesheet file {stylesheet_full_path} does not exist.\"\n                raise FileNotFoundError(msg)\n\n            if stylesheet_full_path.is_dir():\n                all_files = (\n                    file\n                    for ext in constants.Reflex.STYLESHEETS_SUPPORTED\n                    for file in stylesheet_full_path.rglob(\"*.\" + ext)\n                )\n                for file in all_files:\n                    if file.is_dir():\n                        continue\n                    # Validate the stylesheet.\n                    _validate_stylesheet(file, assets_app_path)\n                    stylesheets_files.append(file)\n\n            else:\n                # Validate the stylesheet.\n                _validate_stylesheet(stylesheet_full_path, assets_app_path)\n                stylesheets_files.append(stylesheet_full_path)\n        else:\n            stylesheets_urls.append(stylesheet)\n\n    sheets.extend(dict.fromkeys(stylesheets_urls))\n\n    for stylesheet in stylesheets_files:\n        target_path = stylesheet.relative_to(assets_app_path).with_suffix(\".css\")\n        target = get_web_dir() / constants.Dirs.STYLES / target_path\n\n        target.parent.mkdir(parents=True, exist_ok=True)\n\n        if stylesheet.suffix == \".css\":\n            path_ops.cp(src=stylesheet, dest=target, overwrite=True)\n        else:\n            try:\n                from sass import compile as sass_compile\n\n                target.write_text(\n                    data=sass_compile(\n                        filename=str(stylesheet),\n                        output_style=\"compressed\",\n                    ),\n                    encoding=\"utf8\",\n                )\n            except ImportError:\n                failed_to_import_sass = True\n\n        str_target_path = \"./\" + str(target_path)\n        sheets.append(str_target_path) if str_target_path not in sheets else None\n\n    if failed_to_import_sass:\n        console.error(\n            'The `libsass` package is required to compile sass/scss stylesheet files. Run `pip install \"libsass>=0.23.0\"`.'\n        )\n\n    return templates.styles_template(stylesheets=sheets)\n\n\ndef _compile_component(component: Component | StatefulComponent) -> str:\n    \"\"\"Compile a single component.\n\n    Args:\n        component: The component to compile.\n\n    Returns:\n        The compiled component.\n    \"\"\"\n    return templates.component_template(component=component)\n\n\ndef _compile_memo_components(\n    components: Iterable[CustomComponent],\n) -> tuple[str, dict[str, list[ImportVar]]]:\n    \"\"\"Compile the components.\n\n    Args:\n        components: The components to compile.\n\n    Returns:\n        The compiled components.\n    \"\"\"\n    imports = {\n        \"react\": [ImportVar(tag=\"memo\")],\n        f\"$/{constants.Dirs.STATE_PATH}\": [ImportVar(tag=\"isTrue\")],\n    }\n    component_renders = []\n\n    # Compile each component.\n    for component in components:\n        component_render, component_imports = utils.compile_custom_component(component)\n        component_renders.append(component_render)\n        imports = utils.merge_imports(imports, component_imports)\n\n    _apply_common_imports(imports)\n\n    dynamic_imports = {\n        comp_import: None\n        for comp_render in component_renders\n        if \"dynamic_imports\" in comp_render\n        for comp_import in comp_render[\"dynamic_imports\"]\n    }\n\n    custom_codes = {\n        comp_custom_code: None\n        for comp_render in component_renders\n        for comp_custom_code in comp_render.get(\"custom_code\", [])\n    }\n\n    # Compile the components page.\n    return (\n        templates.memo_components_template(\n            imports=utils.compile_imports(imports),\n            components=component_renders,\n            dynamic_imports=sorted(dynamic_imports),\n            custom_codes=custom_codes,\n        ),\n        imports,\n    )\n\n\ndef _get_shared_components_recursive(\n    component: BaseComponent,\n    rendered_components: dict[str, None],\n    all_import_dicts: list[ParsedImportDict],\n):\n    \"\"\"Get the shared components for a component and its children.\n\n    A shared component is a StatefulComponent that appears in 2 or more\n    pages and is a candidate for writing to a common file and importing\n    into each page where it is used.\n\n    Args:\n        component: The component to collect shared StatefulComponents for.\n        rendered_components: A dict to store the rendered shared components in.\n        all_import_dicts: A list to store the imports of all shared components in.\n    \"\"\"\n    for child in component.children:\n        # Depth-first traversal.\n        _get_shared_components_recursive(child, rendered_components, all_import_dicts)\n\n    # When the component is referenced by more than one page, render it\n    # to be included in the STATEFUL_COMPONENTS module.\n    # Skip this step in dev mode, thereby avoiding potential hot reload errors for larger apps\n    if isinstance(component, StatefulComponent) and component.references > 1:\n        # Reset this flag to render the actual component.\n        component.rendered_as_shared = False\n\n        # Include dynamic imports in the shared component.\n        if dynamic_imports := component._get_all_dynamic_imports():\n            rendered_components.update(dict.fromkeys(dynamic_imports))\n\n        # Include custom code in the shared component.\n        rendered_components.update(component._get_all_custom_code(export=True))\n\n        # Include all imports in the shared component.\n        all_import_dicts.append(component._get_all_imports())\n\n        # Indicate that this component now imports from the shared file.\n        component.rendered_as_shared = True\n\n\ndef _compile_stateful_components(\n    page_components: list[BaseComponent],\n) -> str:\n    \"\"\"Walk the page components and extract shared stateful components.\n\n    Any StatefulComponent that is shared by more than one page will be rendered\n    to a separate module and marked rendered_as_shared so subsequent\n    renderings will import the component from the shared module instead of\n    directly including the code for it.\n\n    Args:\n        page_components: The Components or StatefulComponents to compile.\n\n    Returns:\n        The rendered stateful components code.\n    \"\"\"\n    all_import_dicts = []\n    rendered_components = {}\n\n    for page_component in page_components:\n        _get_shared_components_recursive(\n            page_component, rendered_components, all_import_dicts\n        )\n\n    # Don't import from the file that we're about to create.\n    all_imports = utils.merge_imports(*all_import_dicts)\n    all_imports.pop(\n        f\"$/{constants.Dirs.UTILS}/{constants.PageNames.STATEFUL_COMPONENTS}\", None\n    )\n    if rendered_components:\n        _apply_common_imports(all_imports)\n\n    return templates.stateful_components_template(\n        imports=utils.compile_imports(all_imports),\n        memoized_code=\"\\n\".join(rendered_components),\n    )\n\n\ndef compile_document_root(\n    head_components: list[Component],\n    html_lang: str | None = None,\n    html_custom_attrs: dict[str, Var | Any] | None = None,\n) -> tuple[str, str]:\n    \"\"\"Compile the document root.\n\n    Args:\n        head_components: The components to include in the head.\n        html_lang: The language of the document, will be added to the html root element.\n        html_custom_attrs: custom attributes added to the html root element.\n\n    Returns:\n        The path and code of the compiled document root.\n    \"\"\"\n    # Get the path for the output file.\n    output_path = str(\n        get_web_dir() / constants.Dirs.PAGES / constants.PageNames.DOCUMENT_ROOT\n    )\n\n    # Create the document root.\n    document_root = utils.create_document_root(\n        head_components, html_lang=html_lang, html_custom_attrs=html_custom_attrs\n    )\n\n    # Compile the document root.\n    code = _compile_document_root(document_root)\n    return output_path, code\n\n\ndef compile_app(app_root: Component) -> tuple[str, str]:\n    \"\"\"Compile the app root.\n\n    Args:\n        app_root: The app root component to compile.\n\n    Returns:\n        The path and code of the compiled app wrapper.\n    \"\"\"\n    # Get the path for the output file.\n    output_path = str(\n        get_web_dir() / constants.Dirs.PAGES / constants.PageNames.APP_ROOT\n    )\n\n    # Compile the document root.\n    code = _compile_app(app_root)\n    return output_path, code\n\n\ndef compile_theme(style: ComponentStyle) -> tuple[str, str]:\n    \"\"\"Compile the theme.\n\n    Args:\n        style: The style to compile.\n\n    Returns:\n        The path and code of the compiled theme.\n    \"\"\"\n    output_path = utils.get_theme_path()\n\n    # Create the theme.\n    theme = utils.create_theme(style)\n\n    # Compile the theme.\n    code = _compile_theme(str(LiteralVar.create(theme)))\n    return output_path, code\n\n\ndef compile_contexts(\n    state: type[BaseState] | None,\n    theme: Component | None,\n) -> tuple[str, str]:\n    \"\"\"Compile the initial state / context.\n\n    Args:\n        state: The app state.\n        theme: The top-level app theme.\n\n    Returns:\n        The path and code of the compiled context.\n    \"\"\"\n    # Get the path for the output file.\n    output_path = utils.get_context_path()\n\n    return output_path, _compile_contexts(state, theme)\n\n\ndef compile_page(path: str, component: BaseComponent) -> tuple[str, str]:\n    \"\"\"Compile a single page.\n\n    Args:\n        path: The path to compile the page to.\n        component: The component to compile.\n\n    Returns:\n        The path and code of the compiled page.\n    \"\"\"\n    # Get the path for the output file.\n    output_path = utils.get_page_path(path)\n\n    # Add the style to the component.\n    code = _compile_page(component)\n    return output_path, code\n\n\ndef compile_memo_components(\n    components: Iterable[CustomComponent],\n) -> tuple[str, str, dict[str, list[ImportVar]]]:\n    \"\"\"Compile the custom components.\n\n    Args:\n        components: The custom components to compile.\n\n    Returns:\n        The path and code of the compiled components.\n    \"\"\"\n    # Get the path for the output file.\n    output_path = utils.get_components_path()\n\n    # Compile the components.\n    code, imports = _compile_memo_components(components)\n    return output_path, code, imports\n\n\ndef compile_stateful_components(\n    pages: Iterable[Component],\n    progress_function: Callable[[], None],\n) -> tuple[str, str, list[BaseComponent]]:\n    \"\"\"Separately compile components that depend on State vars.\n\n    StatefulComponents are compiled as their own component functions with their own\n    useContext declarations, which allows page components to be stateless and avoid\n    re-rendering along with parts of the page that actually depend on state.\n\n    Args:\n        pages: The pages to extract stateful components from.\n        progress_function: A function to call to indicate progress, called once per page.\n\n    Returns:\n        The path and code of the compiled stateful components.\n    \"\"\"\n    output_path = utils.get_stateful_components_path()\n\n    page_components = []\n    for page in pages:\n        # Compile the stateful components\n        page_component = StatefulComponent.compile_from(page) or page\n        progress_function()\n        page_components.append(page_component)\n\n    code = _compile_stateful_components(page_components) if is_prod_mode() else \"\"\n    return output_path, code, page_components\n\n\ndef purge_web_pages_dir():\n    \"\"\"Empty out .web/pages directory.\"\"\"\n    if not is_prod_mode() and environment.REFLEX_PERSIST_WEB_DIR.get():\n        # Skip purging the web directory in dev mode if REFLEX_PERSIST_WEB_DIR is set.\n        return\n\n    # Empty out the web pages directory.\n    utils.empty_dir(\n        get_web_dir() / constants.Dirs.PAGES,\n        keep_files=[\"routes.js\", \"entry.client.js\"],\n    )\n\n\nif TYPE_CHECKING:\n    from reflex.app import ComponentCallable, UnevaluatedPage\n\n\ndef _into_component_once(\n    component: Component\n    | ComponentCallable\n    | tuple[Component, ...]\n    | str\n    | Var\n    | int\n    | float,\n) -> Component | None:\n    \"\"\"Convert a component to a Component.\n\n    Args:\n        component: The component to convert.\n\n    Returns:\n        The converted component.\n    \"\"\"\n    if isinstance(component, Component):\n        return component\n    if isinstance(component, (Var, int, float, str)):\n        return Fragment.create(component)\n    if isinstance(component, Sequence):\n        return Fragment.create(*component)\n    return None\n\n\ndef readable_name_from_component(\n    component: Component | ComponentCallable,\n) -> str | None:\n    \"\"\"Get the readable name of a component.\n\n    Args:\n        component: The component to get the name of.\n\n    Returns:\n        The readable name of the component.\n    \"\"\"\n    if isinstance(component, Component):\n        return type(component).__name__\n    if isinstance(component, (Var, int, float, str)):\n        return str(component)\n    if isinstance(component, Sequence):\n        return \", \".join(str(c) for c in component)\n    if callable(component):\n        module_name = getattr(component, \"__module__\", None)\n        if module_name is not None:\n            module = getmodule(component)\n            if module is not None:\n                module_name = module.__name__\n        if module_name is not None:\n            return f\"{module_name}.{component.__name__}\"\n        return component.__name__\n    return None\n\n\ndef _modify_exception(e: Exception) -> None:\n    \"\"\"Modify the exception to make it more readable.\n\n    Args:\n        e: The exception to modify.\n    \"\"\"\n    if len(e.args) == 1 and isinstance((msg := e.args[0]), str):\n        while (state_index := msg.find(\"reflex___\")) != -1:\n            dot_index = msg.find(\".\", state_index)\n            if dot_index == -1:\n                break\n            state_name = msg[state_index:dot_index]\n            module_dot_state_name = state_name.replace(\"___\", \".\").rsplit(\"__\", 1)[-1]\n            module_path, _, state_snake_case = module_dot_state_name.rpartition(\".\")\n            if not state_snake_case:\n                break\n            actual_state_name = to_title_case(state_snake_case)\n            msg = (\n                f\"{msg[:state_index]}{module_path}.{actual_state_name}{msg[dot_index:]}\"\n            )\n\n        msg = msg.replace(FIELD_MARKER, \"\")\n\n        e.args = (msg,)\n\n\ndef into_component(component: Component | ComponentCallable) -> Component:\n    \"\"\"Convert a component to a Component.\n\n    Args:\n        component: The component to convert.\n\n    Returns:\n        The converted component.\n\n    Raises:\n        TypeError: If the component is not a Component.\n\n    # noqa: DAR401\n    \"\"\"\n    if (converted := _into_component_once(component)) is not None:\n        return converted\n    if not callable(component):\n        msg = f\"Expected a Component or callable, got {component!r} of type {type(component)}\"\n        raise TypeError(msg)\n\n    try:\n        component_called = component()\n    except KeyError as e:\n        if isinstance(e, ReflexError):\n            _modify_exception(e)\n            raise\n        key = e.args[0] if e.args else None\n        if key is not None and isinstance(key, Var):\n            raise TypeError(\n                \"Cannot access a primitive map with a Var. Consider calling rx.Var.create() on the map.\"\n            ).with_traceback(e.__traceback__) from None\n        raise\n    except TypeError as e:\n        if isinstance(e, ReflexError):\n            _modify_exception(e)\n            raise\n        message = e.args[0] if e.args else None\n        if message and isinstance(message, str):\n            if message.endswith(\"has no len()\") and (\n                \"ArrayCastedVar\" in message\n                or \"ObjectCastedVar\" in message\n                or \"StringCastedVar\" in message\n            ):\n                raise TypeError(\n                    \"Cannot pass a Var to a built-in function. Consider using .length() for accessing the length of an iterable Var.\"\n                ).with_traceback(e.__traceback__) from None\n            if message.endswith((\n                \"indices must be integers or slices, not NumberCastedVar\",\n                \"indices must be integers or slices, not BooleanCastedVar\",\n            )):\n                raise TypeError(\n                    \"Cannot index into a primitive sequence with a Var. Consider calling rx.Var.create() on the sequence.\"\n                ).with_traceback(e.__traceback__) from None\n        if \"CastedVar\" in str(e):\n            raise TypeError(\n                \"Cannot pass a Var to a built-in function. Consider moving the operation to the backend, using existing Var operations, or defining a custom Var operation.\"\n            ).with_traceback(e.__traceback__) from None\n        raise\n    except ReflexError as e:\n        _modify_exception(e)\n        raise\n\n    if (converted := _into_component_once(component_called)) is not None:\n        return converted\n\n    msg = f\"Expected a Component, got {component_called!r} of type {type(component_called)}\"\n    raise TypeError(msg)\n\n\ndef compile_unevaluated_page(\n    route: str,\n    page: UnevaluatedPage,\n    style: ComponentStyle | None = None,\n    theme: Component | None = None,\n) -> Component:\n    \"\"\"Compiles an uncompiled page into a component and adds meta information.\n\n    Args:\n        route: The route of the page.\n        page: The uncompiled page object.\n        style: The style of the page.\n        theme: The theme of the page.\n\n    Returns:\n        The compiled component and whether state should be enabled.\n\n    Raises:\n        Exception: If an error occurs while evaluating the page.\n    \"\"\"\n    try:\n        # Generate the component if it is a callable.\n        component = into_component(page.component)\n\n        component._add_style_recursive(style or {}, theme)\n\n        from reflex.utils.format import make_default_page_title\n\n        component = Fragment.create(component)\n\n        meta_args = {\n            \"title\": (\n                page.title\n                if page.title is not None\n                else make_default_page_title(get_config().app_name, route)\n            ),\n            \"image\": page.image,\n            \"meta\": page.meta,\n        }\n\n        if page.description is not None:\n            meta_args[\"description\"] = page.description\n\n        # Add meta information to the component.\n        utils.add_meta(\n            component,\n            **meta_args,\n        )\n\n    except Exception as e:\n        if sys.version_info >= (3, 11):\n            e.add_note(f\"Happened while evaluating page {route!r}\")\n        raise\n    else:\n        return component\n\n\nclass ExecutorSafeFunctions:\n    \"\"\"Helper class to allow parallelisation of parts of the compilation process.\n\n    This class (and its class attributes) are available at global scope.\n\n    In a multiprocessing context (like when using a ProcessPoolExecutor), the content of this\n    global class is logically replicated to any FORKED process.\n\n    How it works:\n    * Before the child process is forked, ensure that we stash any input data required by any future\n      function call in the child process.\n    * After the child process is forked, the child process will have a copy of the global class, which\n      includes the previously stashed input data.\n    * Any task submitted to the child process simply needs a way to communicate which input data the\n      requested function call requires.\n\n    Why do we need this? Passing input data directly to child process often not possible because the input data is not picklable.\n    The mechanic described here removes the need to pickle the input data at all.\n\n    Limitations:\n    * This can never support returning unpicklable OUTPUT data.\n    * Any object mutations done by the child process will not propagate back to the parent process (fork goes one way!).\n\n    \"\"\"\n\n    COMPONENTS: dict[str, BaseComponent] = {}\n    UNCOMPILED_PAGES: dict[str, UnevaluatedPage] = {}\n\n    @classmethod\n    def compile_page(cls, route: str) -> tuple[str, str]:\n        \"\"\"Compile a page.\n\n        Args:\n            route: The route of the page to compile.\n\n        Returns:\n            The path and code of the compiled page.\n        \"\"\"\n        return compile_page(route, cls.COMPONENTS[route])\n\n    @classmethod\n    def compile_unevaluated_page(\n        cls,\n        route: str,\n        style: ComponentStyle,\n        theme: Component | None,\n    ) -> tuple[str, Component, tuple[str, str]]:\n        \"\"\"Compile an unevaluated page.\n\n        Args:\n            route: The route of the page to compile.\n            style: The style of the page.\n            theme: The theme of the page.\n\n        Returns:\n            The route, compiled component, and compiled page.\n        \"\"\"\n        component = compile_unevaluated_page(\n            route, cls.UNCOMPILED_PAGES[route], style, theme\n        )\n        return route, component, compile_page(route, component)\n\n    @classmethod\n    def compile_theme(cls, style: ComponentStyle | None) -> tuple[str, str]:\n        \"\"\"Compile the theme.\n\n        Args:\n            style: The style to compile.\n\n        Returns:\n            The path and code of the compiled theme.\n\n        Raises:\n            ValueError: If the style is not set.\n        \"\"\"\n        if style is None:\n            msg = \"STYLE should be set\"\n            raise ValueError(msg)\n        return compile_theme(style)\n"
  },
  {
    "path": "reflex/compiler/templates.py",
    "content": "\"\"\"Templates to use in the reflex compiler.\"\"\"\n\nfrom __future__ import annotations\n\nimport json\nfrom collections.abc import Iterable, Mapping\nfrom typing import TYPE_CHECKING, Any, Literal\n\nfrom reflex import constants\nfrom reflex.constants import Hooks\nfrom reflex.constants.state import CAMEL_CASE_MEMO_MARKER\nfrom reflex.utils.format import format_state_name, json_dumps\nfrom reflex.vars.base import VarData\n\nif TYPE_CHECKING:\n    from reflex.compiler.utils import _ImportDict\n    from reflex.components.component import Component, StatefulComponent\n\n\ndef _sort_hooks(\n    hooks: dict[str, VarData | None],\n) -> tuple[list[str], list[str], list[str]]:\n    \"\"\"Sort the hooks by their position.\n\n    Args:\n        hooks: The hooks to sort.\n\n    Returns:\n        The sorted hooks.\n    \"\"\"\n    internal_hooks = []\n    pre_trigger_hooks = []\n    post_trigger_hooks = []\n\n    for hook, data in hooks.items():\n        if data and data.position and data.position == Hooks.HookPosition.INTERNAL:\n            internal_hooks.append(hook)\n        elif not data or (\n            not data.position\n            or data.position == constants.Hooks.HookPosition.PRE_TRIGGER\n        ):\n            pre_trigger_hooks.append(hook)\n        elif (\n            data\n            and data.position\n            and data.position == constants.Hooks.HookPosition.POST_TRIGGER\n        ):\n            post_trigger_hooks.append(hook)\n\n    return internal_hooks, pre_trigger_hooks, post_trigger_hooks\n\n\nclass _RenderUtils:\n    @staticmethod\n    def render(component: Mapping[str, Any] | str) -> str:\n        if isinstance(component, str):\n            return component or \"null\"\n        if \"iterable\" in component:\n            return _RenderUtils.render_iterable_tag(component)\n        if \"match_cases\" in component:\n            return _RenderUtils.render_match_tag(component)\n        if \"cond_state\" in component:\n            return _RenderUtils.render_condition_tag(component)\n        if (contents := component.get(\"contents\")) is not None:\n            return contents or \"null\"\n        return _RenderUtils.render_tag(component)\n\n    @staticmethod\n    def render_tag(component: Mapping[str, Any]) -> str:\n        name = component.get(\"name\") or \"Fragment\"\n        props = f\"{{{','.join(component['props'])}}}\"\n        rendered_children = [\n            _RenderUtils.render(child)\n            for child in component.get(\"children\", [])\n            if child\n        ]\n\n        return f\"jsx({name},{props},{','.join(rendered_children)})\"\n\n    @staticmethod\n    def render_condition_tag(component: Any) -> str:\n        return f\"({component['cond_state']}?({_RenderUtils.render(component['true_value'])}):({_RenderUtils.render(component['false_value'])}))\"\n\n    @staticmethod\n    def render_iterable_tag(component: Any) -> str:\n        children_rendered = \"\".join([\n            _RenderUtils.render(child) for child in component.get(\"children\", [])\n        ])\n        return f\"Array.prototype.map.call({component['iterable_state']} ?? [],(({component['arg_name']},{component['arg_index']})=>({children_rendered})))\"\n\n    @staticmethod\n    def render_match_tag(component: Any) -> str:\n        cases_code = \"\"\n        for conditions, return_value in component[\"match_cases\"]:\n            for condition in conditions:\n                cases_code += f\"    case JSON.stringify({condition}):\\n\"\n            cases_code += f\"\"\"      return {_RenderUtils.render(return_value)};\n      break;\n\"\"\"\n\n        return f\"\"\"(() => {{\n  switch (JSON.stringify({component[\"cond\"]})) {{\n{cases_code}    default:\n      return {_RenderUtils.render(component[\"default\"])};\n      break;\n  }}\n}})()\"\"\"\n\n    @staticmethod\n    def get_import(module: _ImportDict) -> str:\n        default_import = module[\"default\"]\n        rest_imports = module[\"rest\"]\n\n        if default_import and rest_imports:\n            rest_imports_str = \",\".join(sorted(rest_imports))\n            return f'import {default_import}, {{{rest_imports_str}}} from \"{module[\"lib\"]}\"'\n        if default_import:\n            return f'import {default_import} from \"{module[\"lib\"]}\"'\n        if rest_imports:\n            rest_imports_str = \",\".join(sorted(rest_imports))\n            return f'import {{{rest_imports_str}}} from \"{module[\"lib\"]}\"'\n        return f'import \"{module[\"lib\"]}\"'\n\n\ndef rxconfig_template(app_name: str):\n    \"\"\"Template for the Reflex config file.\n\n    Args:\n        app_name: The name of the application.\n\n    Returns:\n        Rendered Reflex config file content as string.\n    \"\"\"\n    return f\"\"\"import reflex as rx\n\nconfig = rx.Config(\n    app_name=\"{app_name}\",\n    plugins=[\n        rx.plugins.SitemapPlugin(),\n        rx.plugins.TailwindV4Plugin(),\n    ]\n)\"\"\"\n\n\ndef document_root_template(*, imports: list[_ImportDict], document: dict[str, Any]):\n    \"\"\"Template for the document root.\n\n    Args:\n        imports: List of import statements.\n        document: Document root component.\n\n    Returns:\n        Rendered document root code as string.\n    \"\"\"\n    imports_rendered = \"\\n\".join([_RenderUtils.get_import(mod) for mod in imports])\n    return f\"\"\"{imports_rendered}\n\nexport function Layout({{children}}) {{\n  return (\n    {_RenderUtils.render(document)}\n  )\n}}\"\"\"\n\n\ndef app_root_template(\n    *,\n    imports: list[_ImportDict],\n    custom_codes: Iterable[str],\n    hooks: dict[str, VarData | None],\n    window_libraries: list[tuple[str, str]],\n    render: dict[str, Any],\n    dynamic_imports: set[str],\n):\n    \"\"\"Template for the App root.\n\n    Args:\n        imports: The list of import statements.\n        custom_codes: The set of custom code snippets.\n        hooks: The dictionary of hooks.\n        window_libraries: The list of window libraries.\n        render: The dictionary of render functions.\n        dynamic_imports: The set of dynamic imports.\n\n    Returns:\n        Rendered App root component as string.\n    \"\"\"\n    imports_str = \"\\n\".join([_RenderUtils.get_import(mod) for mod in imports])\n    dynamic_imports_str = \"\\n\".join(dynamic_imports)\n\n    custom_code_str = \"\\n\".join(custom_codes)\n\n    import_window_libraries = \"\\n\".join([\n        f'import * as {lib_alias} from \"{lib_path}\";'\n        for lib_alias, lib_path in window_libraries\n    ])\n\n    window_imports_str = \"\\n\".join([\n        f'    \"{lib_path}\": {lib_alias},' for lib_alias, lib_path in window_libraries\n    ])\n\n    return f\"\"\"\n{imports_str}\n{dynamic_imports_str}\nimport {{ EventLoopProvider, StateProvider, defaultColorMode }} from \"$/utils/context\";\nimport {{ ThemeProvider }} from '$/utils/react-theme';\nimport {{ Layout as AppLayout }} from './_document';\nimport {{ Outlet }} from 'react-router';\n{import_window_libraries}\n\n{custom_code_str}\n\nfunction AppWrap({{children}}) {{\n{_render_hooks(hooks)}\nreturn ({_RenderUtils.render(render)})\n}}\n\n\nexport function Layout({{children}}) {{\n  useEffect(() => {{\n    // Make contexts and state objects available globally for dynamic eval'd components\n    let windowImports = {{\n      {window_imports_str}\n    }};\n    window[\"__reflex\"] = windowImports;\n  }}, []);\n\n  return jsx(AppLayout, {{}},\n    jsx(ThemeProvider, {{defaultTheme: defaultColorMode, attribute: \"class\"}},\n      jsx(StateProvider, {{}},\n        jsx(EventLoopProvider, {{}},\n          jsx(AppWrap, {{}}, children)\n        )\n      )\n    )\n  );\n}}\n\nexport default function App() {{\n  return jsx(Outlet, {{}});\n}}\n\n\"\"\"\n\n\ndef theme_template(theme: str):\n    \"\"\"Template for the theme file.\n\n    Args:\n        theme: The theme to render.\n\n    Returns:\n        Rendered theme file content as string.\n    \"\"\"\n    return f\"\"\"export default {theme}\"\"\"\n\n\ndef context_template(\n    *,\n    is_dev_mode: bool,\n    default_color_mode: str,\n    initial_state: dict[str, Any] | None = None,\n    state_name: str | None = None,\n    client_storage: dict[str, dict[str, dict[str, Any]]] | None = None,\n):\n    \"\"\"Template for the context file.\n\n    Args:\n        initial_state: The initial state for the context.\n        state_name: The name of the state.\n        client_storage: The client storage for the context.\n        is_dev_mode: Whether the app is in development mode.\n        default_color_mode: The default color mode for the context.\n\n    Returns:\n        Rendered context file content as string.\n    \"\"\"\n    initial_state = initial_state or {}\n    state_contexts_str = \"\".join([\n        f\"{format_state_name(state_name)}: createContext(null),\"\n        for state_name in initial_state\n    ])\n\n    state_str = (\n        rf\"\"\"\nexport const state_name = \"{state_name}\"\n\nexport const exception_state_name = \"{constants.CompileVars.FRONTEND_EXCEPTION_STATE_FULL}\"\n\n// These events are triggered on initial load and each page navigation.\nexport const onLoadInternalEvent = () => {{\n    const internal_events = [];\n\n    // Get tracked cookie and local storage vars to send to the backend.\n    const client_storage_vars = hydrateClientStorage(clientStorage);\n    // But only send the vars if any are actually set in the browser.\n    if (client_storage_vars && Object.keys(client_storage_vars).length !== 0) {{\n        internal_events.push(\n            ReflexEvent(\n                '{state_name}.{constants.CompileVars.UPDATE_VARS_INTERNAL}',\n                {{vars: client_storage_vars}},\n            ),\n        );\n    }}\n\n    // `on_load_internal` triggers the correct on_load event(s) for the current page.\n    // If the page does not define any on_load event, this will just set `is_hydrated = true`.\n    internal_events.push(ReflexEvent('{state_name}.{constants.CompileVars.ON_LOAD_INTERNAL}'));\n\n    return internal_events;\n}}\n\n// The following events are sent when the websocket connects or reconnects.\nexport const initialEvents = () => [\n    ReflexEvent('{state_name}.{constants.CompileVars.HYDRATE}'),\n    ...onLoadInternalEvent()\n]\n    \"\"\"\n        if state_name\n        else \"\"\"\nexport const state_name = undefined\n\nexport const exception_state_name = undefined\n\nexport const onLoadInternalEvent = () => []\n\nexport const initialEvents = () => []\n\"\"\"\n    )\n\n    state_reducer_str = \"\\n\".join(\n        rf'const [{format_state_name(state_name)}, dispatch_{format_state_name(state_name)}] = useReducer(applyDelta, initialState[\"{state_name}\"])'\n        for state_name in initial_state\n    )\n\n    create_state_contexts_str = \"\\n\".join(\n        rf\"createElement(StateContexts.{format_state_name(state_name)},{{value: {format_state_name(state_name)}}},\"\n        for state_name in initial_state\n    )\n\n    dispatchers_str = \"\\n\".join(\n        f'\"{state_name}\": dispatch_{format_state_name(state_name)},'\n        for state_name in initial_state\n    )\n\n    return rf\"\"\"import {{ createContext, useContext, useMemo, useReducer, useState, createElement, useEffect }} from \"react\"\nimport {{ applyDelta, ReflexEvent, hydrateClientStorage, useEventLoop, refs }} from \"$/utils/state\"\nimport {{ jsx }} from \"@emotion/react\";\n\nexport const initialState = {\"{}\" if not initial_state else json_dumps(initial_state)}\n\nexport const defaultColorMode = {default_color_mode}\nexport const ColorModeContext = createContext(null);\nexport const UploadFilesContext = createContext(null);\nexport const DispatchContext = createContext(null);\nexport const StateContexts = {{{state_contexts_str}}};\nexport const EventLoopContext = createContext(null);\nexport const clientStorage = {\"{}\" if client_storage is None else json.dumps(client_storage)}\n\n{state_str}\n\nexport const isDevMode = {json.dumps(is_dev_mode)};\n\nexport function UploadFilesProvider({{ children }}) {{\n  const [filesById, setFilesById] = useState({{}})\n  refs[\"__clear_selected_files\"] = (id) => setFilesById(filesById => {{\n    const newFilesById = {{...filesById}}\n    delete newFilesById[id]\n    return newFilesById\n  }})\n  return createElement(\n    UploadFilesContext.Provider,\n    {{ value: [filesById, setFilesById] }},\n    children\n  );\n}}\n\nexport function ClientSide(component) {{\n  return ({{ children, ...props }}) => {{\n    const [Component, setComponent] = useState(null);\n    useEffect(() => {{\n      async function load() {{\n        const comp = await component();\n        setComponent(() => comp);\n      }}\n      load();\n    }}, []);\n    return Component ? jsx(Component, props, children) : null;\n  }};\n}}\n\nexport function EventLoopProvider({{ children }}) {{\n  const dispatch = useContext(DispatchContext)\n  const [addEvents, connectErrors] = useEventLoop(\n    dispatch,\n    initialEvents,\n    clientStorage,\n  )\n  return createElement(\n    EventLoopContext.Provider,\n    {{ value: [addEvents, connectErrors] }},\n    children\n  );\n}}\n\nexport function StateProvider({{ children }}) {{\n  {state_reducer_str}\n  const dispatchers = useMemo(() => {{\n    return {{\n      {dispatchers_str}\n    }}\n  }}, [])\n\n  return (\n    {create_state_contexts_str}\n    createElement(DispatchContext, {{value: dispatchers}}, children)\n    {\")\" * len(initial_state)}\n  )\n}}\"\"\"\n\n\ndef component_template(component: Component | StatefulComponent):\n    \"\"\"Template to render a component tag.\n\n    Args:\n        component: The component to render.\n\n    Returns:\n        Rendered component as string.\n    \"\"\"\n    return _RenderUtils.render(component.render())\n\n\ndef page_template(\n    imports: Iterable[_ImportDict],\n    dynamic_imports: Iterable[str],\n    custom_codes: Iterable[str],\n    hooks: dict[str, VarData | None],\n    render: dict[str, Any],\n):\n    \"\"\"Template for a single react page.\n\n    Args:\n        imports: List of import statements.\n        dynamic_imports: List of dynamic import statements.\n        custom_codes: List of custom code snippets.\n        hooks: Dictionary of hooks.\n        render: Render function for the component.\n\n    Returns:\n        Rendered React page component as string.\n    \"\"\"\n    imports_str = \"\\n\".join([_RenderUtils.get_import(imp) for imp in imports])\n    custom_code_str = \"\\n\".join(custom_codes)\n    dynamic_imports_str = \"\\n\".join(dynamic_imports)\n\n    hooks_str = _render_hooks(hooks)\n    return f\"\"\"{imports_str}\n\n{dynamic_imports_str}\n\n{custom_code_str}\n\nexport default function Component() {{\n{hooks_str}\n\n  return (\n    {_RenderUtils.render(render)}\n  )\n}}\"\"\"\n\n\ndef package_json_template(\n    scripts: dict[str, str],\n    dependencies: dict[str, str],\n    dev_dependencies: dict[str, str],\n    overrides: dict[str, str],\n):\n    \"\"\"Template for package.json.\n\n    Args:\n        scripts: The scripts to include in the package.json file.\n        dependencies: The dependencies to include in the package.json file.\n        dev_dependencies: The devDependencies to include in the package.json file.\n        overrides: The overrides to include in the package.json file.\n\n    Returns:\n        Rendered package.json content as string.\n    \"\"\"\n    return json.dumps({\n        \"name\": \"reflex\",\n        \"type\": \"module\",\n        \"scripts\": scripts,\n        \"dependencies\": dependencies,\n        \"devDependencies\": dev_dependencies,\n        \"overrides\": overrides,\n    })\n\n\ndef vite_config_template(\n    base: str,\n    hmr: bool,\n    force_full_reload: bool,\n    experimental_hmr: bool,\n    sourcemap: bool | Literal[\"inline\", \"hidden\"],\n    allowed_hosts: bool | list[str] = False,\n):\n    \"\"\"Template for vite.config.js.\n\n    Args:\n        base: The base path for the Vite config.\n        hmr: Whether to enable hot module replacement.\n        force_full_reload: Whether to force a full reload on changes.\n        experimental_hmr: Whether to enable experimental HMR features.\n        sourcemap: The sourcemap configuration.\n        allowed_hosts: Allow all hosts (True), specific hosts (list of strings), or only localhost (False).\n\n    Returns:\n        Rendered vite.config.js content as string.\n    \"\"\"\n    if allowed_hosts is True:\n        allowed_hosts_line = \"\\n    allowedHosts: true,\"\n    elif isinstance(allowed_hosts, list) and allowed_hosts:\n        allowed_hosts_line = f\"\\n    allowedHosts: {json.dumps(allowed_hosts)},\"\n    else:\n        allowed_hosts_line = \"\"\n    return rf\"\"\"import {{ fileURLToPath, URL }} from \"url\";\nimport {{ reactRouter }} from \"@react-router/dev/vite\";\nimport {{ defineConfig }} from \"vite\";\nimport safariCacheBustPlugin from \"./vite-plugin-safari-cachebust\";\n\n// Ensure that bun always uses the react-dom/server.node functions.\nfunction alwaysUseReactDomServerNode() {{\n  return {{\n    name: \"vite-plugin-always-use-react-dom-server-node\",\n    enforce: \"pre\",\n\n    resolveId(source, importer) {{\n      if (\n        typeof importer === \"string\" &&\n        importer.endsWith(\"/entry.server.node.tsx\") &&\n        source.includes(\"react-dom/server\")\n      ) {{\n        return this.resolve(\"react-dom/server.node\", importer, {{\n          skipSelf: true,\n        }});\n      }}\n      return null;\n    }},\n  }};\n}}\n\nfunction fullReload() {{\n  return {{\n    name: \"full-reload\",\n    enforce: \"pre\",\n    handleHotUpdate({{ server }}) {{\n      server.ws.send({{\n        type: \"full-reload\",\n      }});\n      return [];\n    }}\n  }};\n}}\n\nexport default defineConfig((config) => ({{\n  plugins: [\n    alwaysUseReactDomServerNode(),\n    reactRouter(),\n    safariCacheBustPlugin(),\n  ].concat({\"[fullReload()]\" if force_full_reload else \"[]\"}),\n  build: {{\n    assetsDir: \"{base}assets\".slice(1),\n    sourcemap: {\"true\" if sourcemap is True else \"false\" if sourcemap is False else repr(sourcemap)},\n    rollupOptions: {{\n      onwarn(warning, warn) {{\n        if (warning.code === \"EVAL\" && warning.id && warning.id.endsWith(\"state.js\")) return;\n        warn(warning);\n      }},\n      jsx: {{}},\n      output: {{\n        advancedChunks: {{\n          groups: [\n            {{\n              test: /env.json/,\n              name: \"reflex-env\",\n            }},\n          ],\n        }},\n      }},\n    }},\n  }},\n  experimental: {{\n    enableNativePlugin: false,\n    hmr: {\"true\" if experimental_hmr else \"false\"},\n  }},\n  server: {{\n    port: process.env.PORT,{allowed_hosts_line}\n    hmr: {\"true\" if hmr else \"false\"},\n    watch: {{\n      ignored: [\n        \"**/.web/backend/**\",\n        \"**/.web/reflex.install_frontend_packages.cached\",\n      ],\n    }},\n  }},\n  resolve: {{\n    mainFields: [\"browser\", \"module\", \"jsnext\"],\n    alias: [\n      {{\n        find: \"$\",\n        replacement: fileURLToPath(new URL(\"./\", import.meta.url)),\n      }},\n      {{\n        find: \"@\",\n        replacement: fileURLToPath(new URL(\"./public\", import.meta.url)),\n      }},\n    ],\n  }},\n}}));\"\"\"\n\n\ndef stateful_component_template(\n    tag_name: str, memo_trigger_hooks: list[str], component: Component, export: bool\n):\n    \"\"\"Template for stateful component.\n\n    Args:\n        tag_name: The tag name for the component.\n        memo_trigger_hooks: The memo trigger hooks for the component.\n        component: The component to render.\n        export: Whether to export the component.\n\n    Returns:\n        Rendered stateful component code as string.\n    \"\"\"\n    all_hooks = component._get_all_hooks()\n    return f\"\"\"\n{\"export \" if export else \"\"}function {tag_name} () {{\n  {_render_hooks(all_hooks, memo_trigger_hooks)}\n  return (\n    {_RenderUtils.render(component.render())}\n  )\n}}\n\"\"\"\n\n\ndef stateful_components_template(imports: list[_ImportDict], memoized_code: str) -> str:\n    \"\"\"Template for stateful components.\n\n    Args:\n        imports: List of import statements.\n        memoized_code: Memoized code for stateful components.\n\n    Returns:\n        Rendered stateful components code as string.\n    \"\"\"\n    imports_str = \"\\n\".join([_RenderUtils.get_import(imp) for imp in imports])\n    return f\"{imports_str}\\n{memoized_code}\"\n\n\ndef memo_components_template(\n    imports: list[_ImportDict],\n    components: list[dict[str, Any]],\n    dynamic_imports: Iterable[str],\n    custom_codes: Iterable[str],\n) -> str:\n    \"\"\"Template for custom component.\n\n    Args:\n        imports: List of import statements.\n        components: List of component definitions.\n        dynamic_imports: List of dynamic import statements.\n        custom_codes: List of custom code snippets.\n\n    Returns:\n        Rendered custom component code as string.\n    \"\"\"\n    imports_str = \"\\n\".join([_RenderUtils.get_import(imp) for imp in imports])\n    dynamic_imports_str = \"\\n\".join(dynamic_imports)\n    custom_code_str = \"\\n\".join(custom_codes)\n\n    components_code = \"\"\n    for component in components:\n        components_code += f\"\"\"\nexport const {component[\"name\"]} = memo(({{ {\",\".join([f\"{prop}:{prop}{CAMEL_CASE_MEMO_MARKER}\" for prop in component.get(\"props\", [])])} }}) => {{\n    {_render_hooks(component.get(\"hooks\", {}))}\n    return(\n        {_RenderUtils.render(component[\"render\"])}\n    )\n}});\n\"\"\"\n\n    return f\"\"\"\n{imports_str}\n\n{dynamic_imports_str}\n\n{custom_code_str}\n\n{components_code}\"\"\"\n\n\ndef styles_template(stylesheets: list[str]) -> str:\n    \"\"\"Template for styles.css.\n\n    Args:\n        stylesheets: List of stylesheets to include.\n\n    Returns:\n        Rendered styles.css content as string.\n    \"\"\"\n    return \"@layer __reflex_base;\\n\" + \"\\n\".join([\n        f\"@import url('{sheet_name}');\" for sheet_name in stylesheets\n    ])\n\n\ndef _render_hooks(hooks: dict[str, VarData | None], memo: list | None = None) -> str:\n    \"\"\"Render hooks for macros.\n\n    Args:\n        hooks: Dictionary of hooks to render.\n        memo: Optional list of memo hooks.\n\n    Returns:\n        Rendered hooks code as string.\n    \"\"\"\n    internal, pre_trigger, post_trigger = _sort_hooks(hooks)\n    internal_str = \"\\n\".join(internal)\n    pre_trigger_str = \"\\n\".join(pre_trigger)\n    post_trigger_str = \"\\n\".join(post_trigger)\n    memo_str = \"\\n\".join(memo) if memo is not None else \"\"\n    return f\"{internal_str}\\n{pre_trigger_str}\\n{memo_str}\\n{post_trigger_str}\"\n"
  },
  {
    "path": "reflex/compiler/utils.py",
    "content": "\"\"\"Common utility functions used in the compiler.\"\"\"\n\nfrom __future__ import annotations\n\nimport asyncio\nimport concurrent.futures\nimport operator\nimport traceback\nfrom collections.abc import Mapping, Sequence\nfrom datetime import datetime\nfrom pathlib import Path\nfrom typing import Any, TypedDict\nfrom urllib.parse import urlparse\n\nfrom reflex import constants\nfrom reflex.components.base import Description, Image, Scripts\nfrom reflex.components.base.document import Links, ScrollRestoration\nfrom reflex.components.base.document import Meta as ReactMeta\nfrom reflex.components.component import Component, ComponentStyle, CustomComponent\nfrom reflex.components.el.elements.metadata import Head, Link, Meta, Title\nfrom reflex.components.el.elements.other import Html\nfrom reflex.components.el.elements.sectioning import Body\nfrom reflex.constants.state import FIELD_MARKER\nfrom reflex.istate.storage import Cookie, LocalStorage, SessionStorage\nfrom reflex.state import BaseState, _resolve_delta\nfrom reflex.style import Style\nfrom reflex.utils import format, imports, path_ops\nfrom reflex.utils.imports import ImportVar, ParsedImportDict\nfrom reflex.utils.prerequisites import get_web_dir\nfrom reflex.vars.base import Field, Var, VarData\n\n# To re-export this function.\nmerge_imports = imports.merge_imports\n\n\ndef compile_import_statement(fields: list[ImportVar]) -> tuple[str, list[str]]:\n    \"\"\"Compile an import statement.\n\n    Args:\n        fields: The set of fields to import from the library.\n\n    Returns:\n        The libraries for default and rest.\n        default: default library. When install \"import def from library\".\n        rest: rest of libraries. When install \"import {rest1, rest2} from library\"\n\n    Raises:\n        ValueError: If there is more than one default import.\n    \"\"\"\n    # ignore the ImportVar fields with render=False during compilation\n    fields_set = {field for field in fields if field.render}\n\n    # Check for default imports.\n    defaults = {field for field in fields_set if field.is_default}\n    if len(defaults) >= 2:\n        msg = \"Only one default import is allowed.\"\n        raise ValueError(msg)\n\n    # Get the default import, and the specific imports.\n    default = next(iter({field.name for field in defaults}), \"\")\n    rest = {field.name for field in fields_set - defaults}\n\n    return default, sorted(rest)\n\n\ndef validate_imports(import_dict: ParsedImportDict):\n    \"\"\"Verify that the same Tag is not used in multiple import.\n\n    Args:\n        import_dict: The dict of imports to validate\n\n    Raises:\n        ValueError: if a conflict on \"tag/alias\" is detected for an import.\n    \"\"\"\n    used_tags = {}\n    for lib, imported_items in import_dict.items():\n        for imported_item in imported_items:\n            import_name = (\n                f\"{imported_item.tag}/{imported_item.alias}\"\n                if imported_item.alias\n                else imported_item.tag\n            )\n            if import_name in used_tags:\n                already_imported = used_tags[import_name]\n                if (already_imported[0] == \"$\" and already_imported[1:] == lib) or (\n                    lib[0] == \"$\" and lib[1:] == already_imported\n                ):\n                    used_tags[import_name] = lib if lib[0] == \"$\" else already_imported\n                    continue\n                msg = f\"Can not compile, the tag {import_name} is used multiple time from {lib} and {used_tags[import_name]}\"\n                raise ValueError(msg)\n            if import_name is not None:\n                used_tags[import_name] = lib\n\n\nclass _ImportDict(TypedDict):\n    lib: str\n    default: str\n    rest: list[str]\n\n\ndef compile_imports(import_dict: ParsedImportDict) -> list[_ImportDict]:\n    \"\"\"Compile an import dict.\n\n    Args:\n        import_dict: The import dict to compile.\n\n    Returns:\n        The list of import dict.\n\n    Raises:\n        ValueError: If an import in the dict is invalid.\n    \"\"\"\n    collapsed_import_dict: ParsedImportDict = imports.collapse_imports(import_dict)\n    validate_imports(collapsed_import_dict)\n    import_dicts: list[_ImportDict] = []\n    for lib, fields in collapsed_import_dict.items():\n        # prevent lib from being rendered on the page if all imports are non rendered kind\n        if not any(f.render for f in fields):\n            continue\n\n        lib_paths: dict[str, list[ImportVar]] = {}\n\n        for field in fields:\n            lib_paths.setdefault(field.package_path, []).append(field)\n\n        compiled = {\n            path: compile_import_statement(fields) for path, fields in lib_paths.items()\n        }\n\n        for path, (default, rest) in compiled.items():\n            if not lib:\n                if default:\n                    msg = \"No default field allowed for empty library.\"\n                    raise ValueError(msg)\n                if rest is None or len(rest) == 0:\n                    msg = \"No fields to import.\"\n                    raise ValueError(msg)\n                import_dicts.extend(get_import_dict(module) for module in sorted(rest))\n                continue\n\n            # remove the version before rendering the package imports\n            formatted_lib = format.format_library_name(lib) + (\n                path if path != \"/\" else \"\"\n            )\n\n            import_dicts.append(get_import_dict(formatted_lib, default, rest))\n    return import_dicts\n\n\ndef get_import_dict(\n    lib: str, default: str = \"\", rest: list[str] | None = None\n) -> _ImportDict:\n    \"\"\"Get dictionary for import template.\n\n    Args:\n        lib: The importing react library.\n        default: The default module to import.\n        rest: The rest module to import.\n\n    Returns:\n        A dictionary for import template.\n    \"\"\"\n    return _ImportDict(\n        lib=lib,\n        default=default,\n        rest=rest or [],\n    )\n\n\ndef save_error(error: Exception) -> str:\n    \"\"\"Save the error to a file.\n\n    Args:\n        error: The error to save.\n\n    Returns:\n        The path of the saved error.\n    \"\"\"\n    timestamp = datetime.now().strftime(\"%Y-%m-%d__%H-%M-%S\")\n    constants.Reflex.LOGS_DIR.mkdir(parents=True, exist_ok=True)\n    log_path = constants.Reflex.LOGS_DIR / f\"error_{timestamp}.log\"\n    traceback.TracebackException.from_exception(error).print(file=log_path.open(\"w+\"))\n    return str(log_path)\n\n\ndef _sorted_keys(d: Mapping[str, Any]) -> dict[str, Any]:\n    \"\"\"Sort the keys of a dictionary.\n\n    Args:\n        d: The dictionary to sort.\n\n    Returns:\n        A new dictionary with sorted keys.\n    \"\"\"\n    return dict(sorted(d.items(), key=operator.itemgetter(0)))\n\n\ndef compile_state(state: type[BaseState]) -> dict:\n    \"\"\"Compile the state of the app.\n\n    Args:\n        state: The app state object.\n\n    Returns:\n        A dictionary of the compiled state.\n    \"\"\"\n    initial_state = state(_reflex_internal_init=True).dict(initial=True)\n    try:\n        _ = asyncio.get_running_loop()\n    except RuntimeError:\n        pass\n    else:\n        with concurrent.futures.ThreadPoolExecutor() as pool:\n            resolved_initial_state = pool.submit(\n                asyncio.run, _resolve_delta(initial_state)\n            ).result()\n            return _sorted_keys(resolved_initial_state)\n\n    # Normally the compile runs before any event loop starts, we asyncio.run is available for calling.\n    return _sorted_keys(asyncio.run(_resolve_delta(initial_state)))\n\n\ndef _compile_client_storage_field(\n    field: Field,\n) -> (\n    tuple[\n        type[Cookie] | type[LocalStorage] | type[SessionStorage],\n        dict[str, Any],\n    ]\n    | tuple[None, None]\n):\n    \"\"\"Compile the given cookie, local_storage or session_storage field.\n\n    Args:\n        field: The possible cookie field to compile.\n\n    Returns:\n        A dictionary of the compiled cookie or None if the field is not cookie-like.\n    \"\"\"\n    for field_type in (Cookie, LocalStorage, SessionStorage):\n        if isinstance(field.default, field_type):\n            cs_obj = field.default\n        elif isinstance(field.type_, type) and issubclass(field.type_, field_type):\n            cs_obj = field.type_()\n        else:\n            continue\n        return field_type, cs_obj.options()\n    return None, None\n\n\ndef _compile_client_storage_recursive(\n    state: type[BaseState],\n) -> tuple[\n    dict[str, dict[str, Any]], dict[str, dict[str, Any]], dict[str, dict[str, Any]]\n]:\n    \"\"\"Compile the client-side storage for the given state recursively.\n\n    Args:\n        state: The app state object.\n\n    Returns:\n        A tuple of the compiled client-side storage info: (cookies, local_storage, session_storage).\n    \"\"\"\n    cookies: dict[str, dict[str, Any]] = {}\n    local_storage: dict[str, dict[str, Any]] = {}\n    session_storage: dict[str, dict[str, Any]] = {}\n    state_name = state.get_full_name()\n    for name, field in state.__fields__.items():\n        if name in state.inherited_vars:\n            # only include vars defined in this state\n            continue\n        state_key = f\"{state_name}.{name}\" + FIELD_MARKER\n        field_type, options = _compile_client_storage_field(field)\n        if field_type is None or options is None:\n            continue\n        if field_type is Cookie:\n            cookies[state_key] = options\n        elif field_type is LocalStorage:\n            local_storage[state_key] = options\n        elif field_type is SessionStorage:\n            session_storage[state_key] = options\n        else:\n            continue\n    for substate in state.get_substates():\n        (\n            substate_cookies,\n            substate_local_storage,\n            substate_session_storage,\n        ) = _compile_client_storage_recursive(substate)\n        cookies.update(substate_cookies)\n        local_storage.update(substate_local_storage)\n        session_storage.update(substate_session_storage)\n    return cookies, local_storage, session_storage\n\n\ndef compile_client_storage(\n    state: type[BaseState],\n) -> dict[str, dict[str, dict[str, Any]]]:\n    \"\"\"Compile the client-side storage for the given state.\n\n    Args:\n        state: The app state object.\n\n    Returns:\n        A dictionary of the compiled client-side storage info.\n    \"\"\"\n    cookies, local_storage, session_storage = _compile_client_storage_recursive(state)\n    return {\n        constants.COOKIES: cookies,\n        constants.LOCAL_STORAGE: local_storage,\n        constants.SESSION_STORAGE: session_storage,\n    }\n\n\ndef compile_custom_component(\n    component: CustomComponent,\n) -> tuple[dict, ParsedImportDict]:\n    \"\"\"Compile a custom component.\n\n    Args:\n        component: The custom component to compile.\n\n    Returns:\n        A tuple of the compiled component and the imports required by the component.\n    \"\"\"\n    # Render the component.\n    render = component.get_component()\n\n    # Get the imports.\n    imports: ParsedImportDict = {\n        lib: fields\n        for lib, fields in render._get_all_imports().items()\n        if lib != component.library\n    }\n\n    imports.setdefault(\"@emotion/react\", []).append(ImportVar(\"jsx\"))\n\n    # Concatenate the props.\n    props = list(component.props)\n\n    # Compile the component.\n    return (\n        {\n            \"name\": component.tag,\n            \"props\": props,\n            \"render\": render.render(),\n            \"hooks\": render._get_all_hooks(),\n            \"custom_code\": render._get_all_custom_code(),\n            \"dynamic_imports\": render._get_all_dynamic_imports(),\n        },\n        imports,\n    )\n\n\ndef create_document_root(\n    head_components: Sequence[Component] | None = None,\n    html_lang: str | None = None,\n    html_custom_attrs: dict[str, Var | Any] | None = None,\n) -> Component:\n    \"\"\"Create the document root.\n\n    Args:\n        head_components: The components to add to the head.\n        html_lang: The language of the document, will be added to the html root element.\n        html_custom_attrs: custom attributes added to the html root element.\n\n    Returns:\n        The document root.\n    \"\"\"\n    from reflex.utils.misc import preload_color_theme\n\n    existing_meta_types = set()\n\n    for component in head_components or []:\n        if isinstance(component, Meta):\n            if component.char_set is not None:  # pyright: ignore[reportAttributeAccessIssue]\n                existing_meta_types.add(\"char_set\")\n            if (\n                (name := component.name) is not None  # pyright: ignore[reportAttributeAccessIssue]\n                and name.equals(Var.create(\"viewport\"))\n            ):\n                existing_meta_types.add(\"viewport\")\n\n    # Always include the framework meta and link tags.\n    always_head_components = [\n        ReactMeta.create(),\n        Link.create(\n            rel=\"stylesheet\",\n            type=\"text/css\",\n            href=Var(\n                \"reflexGlobalStyles\",\n                _var_data=VarData(\n                    imports={\n                        \"$/styles/__reflex_global_styles.css?url\": [\n                            ImportVar(tag=\"reflexGlobalStyles\", is_default=True)\n                        ]\n                    }\n                ),\n            ),\n        ),\n        Links.create(),\n    ]\n    maybe_head_components = []\n    # Only include these if the user has not specified them.\n    if \"char_set\" not in existing_meta_types:\n        maybe_head_components.append(Meta.create(char_set=\"utf-8\"))\n    if \"viewport\" not in existing_meta_types:\n        maybe_head_components.append(\n            Meta.create(name=\"viewport\", content=\"width=device-width, initial-scale=1\")\n        )\n\n    # Add theme preload script as the very first component to prevent FOUC\n    theme_preload_components = [preload_color_theme()]\n\n    head_components = [\n        *theme_preload_components,\n        *(head_components or []),\n        *maybe_head_components,\n        *always_head_components,\n    ]\n    html_component = Html.create(\n        Head.create(*head_components),\n        Body.create(\n            Var(\"children\"),\n            ScrollRestoration.create(),\n            Scripts.create(),\n        ),\n        lang=html_lang or \"en\",\n        custom_attrs=html_custom_attrs or {},\n    )\n    hooks = html_component._get_all_hooks()\n    if hooks:\n        msg = \"You cannot use stateful components or hooks in the document root. Check your head components.\"\n        raise ValueError(msg)\n    return html_component\n\n\ndef create_theme(style: ComponentStyle) -> dict:\n    \"\"\"Create the base style for the app.\n\n    Args:\n        style: The style dict for the app.\n\n    Returns:\n        The base style for the app.\n    \"\"\"\n    # Get the global style from the style dict.\n    style_rules = Style({k: v for k, v in style.items() if isinstance(k, str)})\n\n    root_style = {\n        # Root styles.\n        \":root\": Style({\n            f\"*{k}\": v for k, v in style_rules.items() if k.startswith(\":\")\n        }),\n        # Body styles.\n        \"body\": Style(\n            {k: v for k, v in style_rules.items() if not k.startswith(\":\")},\n        ),\n    }\n\n    # Return the theme.\n    return {\"styles\": {\"global\": root_style}}\n\n\ndef _format_route_part(part: str) -> str:\n    if part.startswith(\"[\") and part.endswith(\"]\"):\n        if part.startswith((\"[...\", \"[[...\")):\n            return \"$\"\n        if part.startswith(\"[[\"):\n            return \"($\" + part.removeprefix(\"[[\").removesuffix(\"]]\") + \")\"\n        # We don't add [] here since we are reusing them from the input\n        return \"$\" + part\n    return \"[\" + part + \"]\"\n\n\ndef _path_to_file_stem(path: str) -> str:\n    if path == \"index\":\n        return \"_index\"\n    path = path if path != \"index\" else \"/\"\n    name = \".\".join([_format_route_part(part) for part in path.split(\"/\")]).lstrip(\".\")\n    return name + \"._index\" if not name.endswith(\"$\") else name\n\n\ndef get_page_path(path: str) -> str:\n    \"\"\"Get the path of the compiled JS file for the given page.\n\n    Args:\n        path: The path of the page.\n\n    Returns:\n        The path of the compiled JS file.\n    \"\"\"\n    return str(\n        get_web_dir()\n        / constants.Dirs.PAGES\n        / constants.Dirs.ROUTES\n        / (_path_to_file_stem(path) + constants.Ext.JSX)\n    )\n\n\ndef get_theme_path() -> str:\n    \"\"\"Get the path of the base theme style.\n\n    Returns:\n        The path of the theme style.\n    \"\"\"\n    return str(\n        get_web_dir()\n        / constants.Dirs.UTILS\n        / (constants.PageNames.THEME + constants.Ext.JS)\n    )\n\n\ndef get_root_stylesheet_path() -> str:\n    \"\"\"Get the path of the app root file.\n\n    Returns:\n        The path of the app root file.\n    \"\"\"\n    return str(\n        get_web_dir()\n        / constants.Dirs.STYLES\n        / (constants.PageNames.STYLESHEET_ROOT + constants.Ext.CSS)\n    )\n\n\ndef get_context_path() -> str:\n    \"\"\"Get the path of the context / initial state file.\n\n    Returns:\n        The path of the context module.\n    \"\"\"\n    return str(get_web_dir() / (constants.Dirs.CONTEXTS_PATH + constants.Ext.JS))\n\n\ndef get_components_path() -> str:\n    \"\"\"Get the path of the compiled components.\n\n    Returns:\n        The path of the compiled components.\n    \"\"\"\n    return str(\n        get_web_dir()\n        / constants.Dirs.UTILS\n        / (constants.PageNames.COMPONENTS + constants.Ext.JSX),\n    )\n\n\ndef get_stateful_components_path() -> str:\n    \"\"\"Get the path of the compiled stateful components.\n\n    Returns:\n        The path of the compiled stateful components.\n    \"\"\"\n    return str(\n        get_web_dir()\n        / constants.Dirs.UTILS\n        / (constants.PageNames.STATEFUL_COMPONENTS + constants.Ext.JSX)\n    )\n\n\ndef add_meta(\n    page: Component,\n    title: str,\n    image: str,\n    meta: Sequence[Mapping[str, Any] | Component],\n    description: str | None = None,\n) -> Component:\n    \"\"\"Add metadata to a page.\n\n    Args:\n        page: The component for the page.\n        title: The title of the page.\n        image: The image for the page.\n        meta: The metadata list.\n        description: The description of the page.\n\n    Returns:\n        The component with the metadata added.\n    \"\"\"\n    meta_tags = [\n        item if isinstance(item, Component) else Meta.create(**item) for item in meta\n    ]\n\n    children: list[Any] = [Title.create(title)]\n    if description:\n        children.append(Description.create(content=description))\n    children.append(Image.create(content=image))\n\n    page.children.extend(children)\n    page.children.extend(meta_tags)\n\n    return page\n\n\ndef resolve_path_of_web_dir(path: str | Path) -> Path:\n    \"\"\"Get the path under the web directory.\n\n    Args:\n        path: The path to get. It can be a relative or absolute path.\n\n    Returns:\n        The path under the web directory.\n    \"\"\"\n    path = Path(path)\n    web_dir = get_web_dir()\n    if path.is_relative_to(web_dir):\n        return path.absolute()\n    return (web_dir / path).absolute()\n\n\ndef write_file(path: str | Path, code: str):\n    \"\"\"Write the given code to the given path.\n\n    Args:\n        path: The path to write the code to.\n        code: The code to write.\n    \"\"\"\n    path = Path(path)\n    path.parent.mkdir(parents=True, exist_ok=True)\n    if path.exists() and path.read_text(encoding=\"utf-8\") == code:\n        return\n    path.write_text(code, encoding=\"utf-8\")\n\n\ndef empty_dir(path: str | Path, keep_files: list[str] | None = None):\n    \"\"\"Remove all files and folders in a directory except for the keep_files.\n\n    Args:\n        path: The path to the directory that will be emptied\n        keep_files: List of filenames or foldernames that will not be deleted.\n    \"\"\"\n    path = Path(path)\n\n    # If the directory does not exist, return.\n    if not path.exists():\n        return\n\n    # Remove all files and folders in the directory.\n    keep_files = keep_files or []\n    for element in path.iterdir():\n        if element.name not in keep_files:\n            path_ops.rm(element)\n\n\ndef is_valid_url(url: str) -> bool:\n    \"\"\"Check if a url is valid.\n\n    Args:\n        url: The Url to check.\n\n    Returns:\n        Whether url is valid.\n    \"\"\"\n    result = urlparse(url)\n    return all([result.scheme, result.netloc])\n"
  },
  {
    "path": "reflex/components/__init__.py",
    "content": "\"\"\"Import all the components.\"\"\"\n\nfrom __future__ import annotations\n\nfrom reflex.utils import lazy_loader\n\n_SUBMODULES: set[str] = {\n    \"lucide\",\n    \"core\",\n    \"datadisplay\",\n    \"gridjs\",\n    \"markdown\",\n    \"moment\",\n    \"plotly\",\n    \"radix\",\n    \"react_player\",\n    \"react_router\",\n    \"sonner\",\n    \"el\",\n    \"base\",\n    \"recharts\",\n}\n\n_SUBMOD_ATTRS: dict[str, list[str]] = {\n    \"component\": [\n        \"Component\",\n        \"NoSSRComponent\",\n    ],\n}\n__getattr__, __dir__, __all__ = lazy_loader.attach(\n    __name__,\n    submodules=_SUBMODULES,\n    submod_attrs=_SUBMOD_ATTRS,\n)\n"
  },
  {
    "path": "reflex/components/base/__init__.py",
    "content": "\"\"\"Base components.\"\"\"\n\nfrom __future__ import annotations\n\nfrom reflex.utils import lazy_loader\n\n_SUBMODULES: set[str] = {\"app_wrap\", \"bare\"}\n\n_SUBMOD_ATTRS: dict[str, list[str]] = {\n    \"body\": [\"Body\"],\n    \"document\": [\"Scripts\", \"Outlet\", \"ScrollRestoration\", \"Links\", \"Meta\"],\n    \"fragment\": [\n        \"Fragment\",\n        \"fragment\",\n    ],\n    \"error_boundary\": [\n        \"ErrorBoundary\",\n        \"error_boundary\",\n    ],\n    \"link\": [\"RawLink\", \"ScriptTag\"],\n    \"meta\": [\"Description\", \"Image\", \"Meta\", \"Title\"],\n    \"script\": [\"Script\", \"script\"],\n}\n\n__getattr__, __dir__, __all__ = lazy_loader.attach(\n    __name__,\n    submodules=_SUBMODULES,\n    submod_attrs=_SUBMOD_ATTRS,\n)\n"
  },
  {
    "path": "reflex/components/base/app_wrap.py",
    "content": "\"\"\"Top-level component that wraps the entire app.\"\"\"\n\nfrom reflex.components.base.fragment import Fragment\nfrom reflex.components.component import Component\nfrom reflex.vars.base import Var\n\n\nclass AppWrap(Fragment):\n    \"\"\"Top-level component that wraps the entire app.\"\"\"\n\n    @classmethod\n    def create(cls) -> Component:\n        \"\"\"Create a new AppWrap component.\n\n        Returns:\n            A new AppWrap component containing {children}.\n        \"\"\"\n        return super().create(Var(_js_expr=\"children\"))\n"
  },
  {
    "path": "reflex/components/base/bare.py",
    "content": "\"\"\"A bare component.\"\"\"\n\nfrom __future__ import annotations\n\nfrom collections.abc import Iterator, Sequence\nfrom typing import Any\n\nfrom reflex.components.component import BaseComponent, Component, ComponentStyle\nfrom reflex.components.tags import Tag\nfrom reflex.components.tags.tagless import Tagless\nfrom reflex.environment import PerformanceMode, environment\nfrom reflex.utils import console\nfrom reflex.utils.decorator import once\nfrom reflex.utils.imports import ParsedImportDict\nfrom reflex.vars import BooleanVar, ObjectVar, Var\nfrom reflex.vars.base import GLOBAL_CACHE, VarData\nfrom reflex.vars.sequence import LiteralStringVar\n\n\n@once\ndef get_performance_mode():\n    \"\"\"Get the performance mode.\n\n    Returns:\n        The performance mode.\n    \"\"\"\n    return environment.REFLEX_PERF_MODE.get()\n\n\ndef validate_str(value: str):\n    \"\"\"Validate a string value.\n\n    Args:\n        value: The value to validate.\n\n    Raises:\n        ValueError: If the value is a Var and the performance mode is set to raise.\n    \"\"\"\n    perf_mode = get_performance_mode()\n    if perf_mode != PerformanceMode.OFF and value.startswith(\"reflex___state\"):\n        if perf_mode == PerformanceMode.WARN:\n            console.warn(\n                f\"Output includes {value!s} which will be displayed as a string. If you are calling `str` on a Var, consider using .to_string() instead.\"\n            )\n        elif perf_mode == PerformanceMode.RAISE:\n            msg = f\"Output includes {value!s} which will be displayed as a string. If you are calling `str` on a Var, consider using .to_string() instead.\"\n            raise ValueError(msg)\n\n\ndef _components_from_var(var: Var) -> Sequence[BaseComponent]:\n    var_data = var._get_all_var_data()\n    return var_data.components if var_data else ()\n\n\nclass Bare(Component):\n    \"\"\"A component with no tag.\"\"\"\n\n    contents: Var[Any]\n\n    @classmethod\n    def create(cls, contents: Any) -> Component:\n        \"\"\"Create a Bare component, with no tag.\n\n        Args:\n            contents: The contents of the component.\n\n        Returns:\n            The component.\n        \"\"\"\n        if isinstance(contents, Var):\n            if isinstance(contents, LiteralStringVar):\n                validate_str(contents._var_value)\n            return cls._unsafe_create(children=[], contents=contents)\n        if isinstance(contents, str):\n            validate_str(contents)\n        contents = Var.create(contents if contents is not None else \"\")\n\n        return cls._unsafe_create(children=[], contents=contents)\n\n    def _get_all_hooks_internal(self) -> dict[str, VarData | None]:\n        \"\"\"Include the hooks for the component.\n\n        Returns:\n            The hooks for the component.\n        \"\"\"\n        hooks = super()._get_all_hooks_internal()\n        if isinstance(self.contents, Var):\n            for component in _components_from_var(self.contents):\n                hooks |= component._get_all_hooks_internal()\n        return hooks\n\n    def _get_all_hooks(self) -> dict[str, VarData | None]:\n        \"\"\"Include the hooks for the component.\n\n        Returns:\n            The hooks for the component.\n        \"\"\"\n        hooks = super()._get_all_hooks()\n        if isinstance(self.contents, Var):\n            for component in _components_from_var(self.contents):\n                hooks |= component._get_all_hooks()\n        return hooks\n\n    def _get_all_imports(self, collapse: bool = False) -> ParsedImportDict:\n        \"\"\"Include the imports for the component.\n\n        Args:\n            collapse: Whether to collapse the imports.\n\n        Returns:\n            The imports for the component.\n        \"\"\"\n        imports = super()._get_all_imports(collapse=collapse)\n        if isinstance(self.contents, Var):\n            var_data = self.contents._get_all_var_data()\n            if var_data:\n                imports |= {k: list(v) for k, v in var_data.imports}\n        return imports\n\n    def _get_all_dynamic_imports(self) -> set[str]:\n        \"\"\"Get dynamic imports for the component.\n\n        Returns:\n            The dynamic imports.\n        \"\"\"\n        dynamic_imports = super()._get_all_dynamic_imports()\n        if isinstance(self.contents, Var):\n            for component in _components_from_var(self.contents):\n                dynamic_imports |= component._get_all_dynamic_imports()\n        return dynamic_imports\n\n    def _get_all_custom_code(self) -> dict[str, None]:\n        \"\"\"Get custom code for the component.\n\n        Returns:\n            The custom code.\n        \"\"\"\n        custom_code = super()._get_all_custom_code()\n        if isinstance(self.contents, Var):\n            for component in _components_from_var(self.contents):\n                custom_code |= component._get_all_custom_code()\n        return custom_code\n\n    def _get_all_app_wrap_components(\n        self, *, ignore_ids: set[int] | None = None\n    ) -> dict[tuple[int, str], Component]:\n        \"\"\"Get the components that should be wrapped in the app.\n\n        Args:\n            ignore_ids: The ids to ignore when collecting components.\n\n        Returns:\n            The components that should be wrapped in the app.\n        \"\"\"\n        ignore_ids = ignore_ids or set()\n        app_wrap_components = super()._get_all_app_wrap_components(\n            ignore_ids=ignore_ids\n        )\n        if isinstance(self.contents, Var):\n            for component in _components_from_var(self.contents):\n                component_id = id(component)\n                if isinstance(component, Component) and component_id not in ignore_ids:\n                    ignore_ids.add(component_id)\n                    app_wrap_components |= component._get_all_app_wrap_components(\n                        ignore_ids=ignore_ids\n                    )\n        return app_wrap_components\n\n    def _get_all_refs(self) -> dict[str, None]:\n        \"\"\"Get the refs for the children of the component.\n\n        Returns:\n            The refs for the children.\n        \"\"\"\n        refs = super()._get_all_refs()\n        if isinstance(self.contents, Var):\n            for component in _components_from_var(self.contents):\n                refs |= component._get_all_refs()\n        return refs\n\n    def _render(self) -> Tag:\n        contents = (\n            Var.create(self.contents)\n            if not isinstance(self.contents, Var)\n            else self.contents\n        )\n        if isinstance(contents, (BooleanVar, ObjectVar)):\n            return Tagless(contents=f\"{contents.to_string()!s}\")\n        return Tagless(contents=f\"{contents!s}\")\n\n    def render(self) -> dict:\n        \"\"\"Render the component as a dictionary.\n\n        This is overridden to provide a short performant path for rendering.\n\n        Returns:\n            The rendered component.\n        \"\"\"\n        contents = (\n            Var.create(self.contents)\n            if not isinstance(self.contents, Var)\n            else self.contents\n        )\n        if isinstance(contents, (BooleanVar, ObjectVar)):\n            return {\"contents\": f\"{contents.to_string()!s}\"}\n        return {\"contents\": f\"{contents!s}\"}\n\n    def _add_style_recursive(\n        self, style: ComponentStyle, theme: Component | None = None\n    ) -> Component:\n        \"\"\"Add style to the component and its children.\n\n        Args:\n            style: The style to add.\n            theme: The theme to add.\n\n        Returns:\n            The component with the style added.\n        \"\"\"\n        new_self = super()._add_style_recursive(style, theme)\n\n        are_components_touched = False\n\n        if isinstance(self.contents, Var):\n            for component in _components_from_var(self.contents):\n                if isinstance(component, Component):\n                    component._add_style_recursive(style, theme)\n                    are_components_touched = True\n\n        if are_components_touched:\n            GLOBAL_CACHE.clear()\n\n        return new_self\n\n    def _get_vars(\n        self, include_children: bool = False, ignore_ids: set[int] | None = None\n    ) -> Iterator[Var]:\n        \"\"\"Walk all Vars used in this component.\n\n        Args:\n            include_children: Whether to include Vars from children.\n            ignore_ids: The ids to ignore.\n\n        Yields:\n            The contents if it is a Var, otherwise nothing.\n        \"\"\"\n        yield self.contents\n"
  },
  {
    "path": "reflex/components/base/body.py",
    "content": "\"\"\"Display the page body.\"\"\"\n\nfrom reflex.components.el import elements\n\n\nclass Body(elements.Body):\n    \"\"\"A body component.\"\"\"\n"
  },
  {
    "path": "reflex/components/base/document.py",
    "content": "\"\"\"Document components.\"\"\"\n\nfrom reflex.components.component import Component\n\n\nclass ReactRouterLib(Component):\n    \"\"\"Root document components.\"\"\"\n\n    library = \"react-router\"\n\n\nclass Meta(ReactRouterLib):\n    \"\"\"The document meta tags.\"\"\"\n\n    tag = \"Meta\"\n\n\nclass Links(ReactRouterLib):\n    \"\"\"The document link tags.\"\"\"\n\n    tag = \"Links\"\n\n\nclass ScrollRestoration(ReactRouterLib):\n    \"\"\"The document scroll restoration.\"\"\"\n\n    tag = \"ScrollRestoration\"\n\n\nclass Outlet(ReactRouterLib):\n    \"\"\"The document outlet.\"\"\"\n\n    tag = \"Outlet\"\n\n\nclass Scripts(ReactRouterLib):\n    \"\"\"The document main scripts.\"\"\"\n\n    tag = \"Scripts\"\n"
  },
  {
    "path": "reflex/components/base/error_boundary.py",
    "content": "\"\"\"A React Error Boundary component that catches unhandled frontend exceptions.\"\"\"\n\nfrom __future__ import annotations\n\nfrom reflex.components.component import Component\nfrom reflex.components.datadisplay.logo import svg_logo\nfrom reflex.components.el import a, button, div, h2, hr, p, pre, svg\nfrom reflex.event import EventHandler, set_clipboard\nfrom reflex.state import FrontendEventExceptionState\nfrom reflex.vars.base import Var\nfrom reflex.vars.function import ArgsFunctionOperation\nfrom reflex.vars.object import ObjectVar\n\n\ndef on_error_spec(\n    error: ObjectVar[dict[str, str]], info: ObjectVar[dict[str, str]]\n) -> tuple[Var[str], Var[str]]:\n    \"\"\"The spec for the on_error event handler.\n\n    Args:\n        error: The error message.\n        info: Additional information about the error.\n\n    Returns:\n        The arguments for the event handler.\n    \"\"\"\n    return (\n        error.name.to(str) + \": \" + error.message.to(str) + \"\\n\" + error.stack.to(str),\n        info.componentStack,\n    )\n\n\n_ERROR_DISPLAY: str = r\"\"\"event_args.error.name + ': ' + event_args.error.message + '\\n' + event_args.error.stack\"\"\"\n\n\nclass ErrorBoundary(Component):\n    \"\"\"A React Error Boundary component that catches unhandled frontend exceptions.\"\"\"\n\n    library = \"react-error-boundary@6.1.1\"\n    tag = \"ErrorBoundary\"\n\n    # Fired when the boundary catches an error.\n    on_error: EventHandler[on_error_spec]\n\n    # Rendered instead of the children when an error is caught.\n    fallback_render: Var[Component]\n\n    @classmethod\n    def create(cls, *children, **props):\n        \"\"\"Create an ErrorBoundary component.\n\n        Args:\n            *children: The children of the component.\n            **props: The props of the component.\n\n        Returns:\n            The ErrorBoundary component.\n        \"\"\"\n        if \"on_error\" not in props:\n            props[\"on_error\"] = FrontendEventExceptionState.handle_frontend_exception\n        if \"fallback_render\" not in props:\n            props[\"fallback_render\"] = ArgsFunctionOperation.create(\n                (\"event_args\",),\n                Var.create(\n                    div(\n                        div(\n                            div(\n                                svg(\n                                    svg.circle(cx=\"12\", cy=\"12\", r=\"10\"),\n                                    svg.path(d=\"M16 16s-1.5-2-4-2-4 2-4 2\"),\n                                    svg.line(x1=\"9\", x2=\"9.01\", y1=\"9\", y2=\"9\"),\n                                    svg.line(x1=\"15\", x2=\"15.01\", y1=\"9\", y2=\"9\"),\n                                    xmlns=\"http://www.w3.org/2000/svg\",\n                                    width=\"25vmin\",\n                                    view_box=\"0 0 24 24\",\n                                    class_name=\"lucide lucide-frown-icon lucide-frown\",\n                                    custom_attrs={\n                                        \"fill\": \"none\",\n                                        \"stroke\": \"currentColor\",\n                                        \"stroke-width\": \"2\",\n                                        \"stroke-linecap\": \"round\",\n                                        \"stroke-linejoin\": \"round\",\n                                    },\n                                ),\n                                h2(\n                                    \"An error occurred while rendering this page.\",\n                                    font_size=\"5vmin\",\n                                    font_weight=\"bold\",\n                                ),\n                                opacity=\"0.5\",\n                                display=\"flex\",\n                                gap=\"4vmin\",\n                                align_items=\"center\",\n                            ),\n                            p(\n                                \"This is an error with the application itself. Refreshing the page might help.\",\n                                opacity=\"0.75\",\n                                margin_block=\"1rem\",\n                            ),\n                            div(\n                                div(\n                                    pre(\n                                        Var(_js_expr=_ERROR_DISPLAY),\n                                        word_break=\"break-word\",\n                                        white_space=\"pre-wrap\",\n                                    ),\n                                    padding=\"0.5rem\",\n                                ),\n                                width=\"100%\",\n                                background=\"color-mix(in srgb, currentColor 5%, transparent)\",\n                                max_height=\"15rem\",\n                                overflow=\"auto\",\n                                border_radius=\"0.4rem\",\n                            ),\n                            button(\n                                \"Copy\",\n                                on_click=set_clipboard(Var(_js_expr=_ERROR_DISPLAY)),\n                                padding=\"0.35rem 1.35rem\",\n                                margin_block=\"0.5rem\",\n                                margin_inline_start=\"auto\",\n                                background=\"color-mix(in srgb, currentColor 15%, transparent)\",\n                                border_radius=\"0.4rem\",\n                                width=\"fit-content\",\n                                _hover={\n                                    \"background\": \"color-mix(in srgb, currentColor 25%, transparent)\"\n                                },\n                                _active={\n                                    \"background\": \"color-mix(in srgb, currentColor 35%, transparent)\"\n                                },\n                            ),\n                            hr(\n                                border_color=\"currentColor\",\n                                opacity=\"0.25\",\n                            ),\n                            a(\n                                div(\n                                    \"Built with \",\n                                    svg_logo(\"currentColor\"),\n                                    display=\"flex\",\n                                    align_items=\"baseline\",\n                                    justify_content=\"center\",\n                                    font_family=\"monospace\",\n                                    gap=\"0.5rem\",\n                                ),\n                                href=\"https://reflex.dev\",\n                            ),\n                            display=\"flex\",\n                            flex_direction=\"column\",\n                            gap=\"0.5rem\",\n                            max_width=\"min(80ch, 90vw)\",\n                            border_radius=\"0.25rem\",\n                            padding=\"1rem\",\n                        ),\n                        height=\"100%\",\n                        width=\"100%\",\n                        position=\"absolute\",\n                        background_color=\"#fff\",\n                        color=\"#000\",\n                        display=\"flex\",\n                        align_items=\"center\",\n                        justify_content=\"center\",\n                    )\n                ),\n                _var_type=Component,\n            )\n        else:\n            props[\"fallback_render\"] = ArgsFunctionOperation.create(\n                (\"event_args\",),\n                props[\"fallback_render\"],\n                _var_type=Component,\n            )\n        return super().create(*children, **props)\n\n\nerror_boundary = ErrorBoundary.create\n"
  },
  {
    "path": "reflex/components/base/fragment.py",
    "content": "\"\"\"React fragments to enable bare returns of component trees from functions.\"\"\"\n\nfrom reflex.components.component import Component\n\n\nclass Fragment(Component):\n    \"\"\"A React fragment to return multiple components from a function without wrapping it in a container.\"\"\"\n\n    library = \"react\"\n    tag = \"Fragment\"\n\n\nfragment = Fragment.create\n"
  },
  {
    "path": "reflex/components/base/link.py",
    "content": "\"\"\"Display the title of the current page.\"\"\"\n\nfrom reflex.components.el.elements.base import BaseHTML\nfrom reflex.vars.base import Var\n\n\nclass RawLink(BaseHTML):\n    \"\"\"A component that displays the title of the current page.\"\"\"\n\n    tag = \"link\"\n\n    # The href.\n    href: Var[str]\n\n    # The type of link.\n    rel: Var[str]\n\n\nclass ScriptTag(BaseHTML):\n    \"\"\"A script tag with the specified type and source.\"\"\"\n\n    tag = \"script\"\n\n    # The type of script represented.\n    type_: Var[str]\n\n    # The URI of an external script.\n    source: Var[str]\n\n    # Metadata to verify the content of the script.\n    integrity: Var[str]\n\n    # Whether to allow cross-origin requests.\n    crossorigin: Var[str]\n\n    # Indicates which referrer to send when fetching the script.\n    referrer_policy: Var[str]\n\n    # Whether to asynchronously load the script.\n    is_async: Var[bool]\n\n    # Whether to defer loading the script.\n    defer: Var[bool]\n"
  },
  {
    "path": "reflex/components/base/meta.py",
    "content": "\"\"\"Display the title of the current page.\"\"\"\n\nfrom __future__ import annotations\n\nfrom reflex.components.base.bare import Bare\nfrom reflex.components.el import elements\nfrom reflex.components.el.elements.metadata import Meta as Meta  # for compatibility\nfrom reflex.vars.base import Var\n\n\nclass Title(elements.Title):\n    \"\"\"A component that displays the title of the current page.\"\"\"\n\n    def render(self) -> dict:\n        \"\"\"Render the title component.\n\n        Returns:\n            The rendered title component.\n\n        Raises:\n            ValueError: If the title is not a single string.\n        \"\"\"\n        # Make sure the title is a single string.\n        if len(self.children) != 1 or not isinstance(self.children[0], Bare):\n            msg = \"Title must be a single string.\"\n            raise ValueError(msg)\n        return super().render()\n\n\nclass Description(elements.Meta):\n    \"\"\"A component that displays the title of the current page.\"\"\"\n\n    # The type of the description.\n    name: Var[str] = Var.create(\"description\")\n\n\nclass Image(elements.Meta):\n    \"\"\"A component that displays the title of the current page.\"\"\"\n\n    # The type of the image.\n    property: Var[str] = Var.create(\"og:image\")\n"
  },
  {
    "path": "reflex/components/base/script.py",
    "content": "\"\"\"Wrapper for the script element. Uses the Helmet component to manage the head.\"\"\"\n\nfrom __future__ import annotations\n\nfrom reflex.components import el as elements\nfrom reflex.components.core.helmet import helmet\nfrom reflex.utils import console\n\n\nclass Script(elements.Script):\n    \"\"\"Wrapper for the script element.\"\"\"\n\n    @classmethod\n    def create(\n        cls,\n        *children,\n        **props,\n    ):\n        \"\"\"Display the script element.\n\n        Args:\n            *children: The children of the element.\n            **props: The properties of the element.\n\n        Returns:\n            The script element.\n\n        Raises:\n            ValueError: If neither children nor src is specified.\n        \"\"\"\n        async_ = props.pop(\"async_\", None)\n        char_set = props.pop(\"char_set\", None)\n        cross_origin = props.pop(\"cross_origin\", None)\n        defer = props.pop(\"defer\", None)\n        integrity = props.pop(\"integrity\", None)\n        referrer_policy = props.pop(\"referrer_policy\", None)\n        src = props.pop(\"src\", None)\n        type = props.pop(\"type\", None)\n        key = props.pop(\"key\", None)\n        id = props.pop(\"id\", None)\n        class_name = props.pop(\"class_name\", None)\n        custom_attrs = props.pop(\"custom_attrs\", None)\n        on_mount = props.pop(\"on_mount\", None)\n        on_unmount = props.pop(\"on_unmount\", None)\n\n        if props:\n            console.warn(\n                f\"rx.script does not support the following properties: {list(props.keys())}\"\n            )\n\n        if not children and not src:\n            msg = \"You must specify either children or src for the script element.\"\n            raise ValueError(msg)\n\n        return helmet(\n            elements.Script.create(\n                *children,\n                async_=async_,\n                char_set=char_set,\n                cross_origin=cross_origin,\n                defer=defer,\n                integrity=integrity,\n                referrer_policy=referrer_policy,\n                src=src,\n                type=type,\n                key=key,\n                id=id,\n                class_name=class_name,\n                custom_attrs=custom_attrs,\n                on_mount=on_mount,\n                on_unmount=on_unmount,\n            )\n        )\n\n\nscript = Script.create\n"
  },
  {
    "path": "reflex/components/base/strict_mode.py",
    "content": "\"\"\"Module for the StrictMode component.\"\"\"\n\nfrom reflex.components.component import Component\n\n\nclass StrictMode(Component):\n    \"\"\"A React strict mode component to enable strict mode for its children.\"\"\"\n\n    library = \"react\"\n    tag = \"StrictMode\"\n"
  },
  {
    "path": "reflex/components/component.py",
    "content": "\"\"\"Base component definitions.\"\"\"\n\nfrom __future__ import annotations\n\nimport contextlib\nimport copy\nimport dataclasses\nimport enum\nimport functools\nimport inspect\nimport typing\nfrom abc import ABC, ABCMeta, abstractmethod\nfrom collections.abc import Callable, Iterable, Iterator, Mapping, Sequence\nfrom dataclasses import _MISSING_TYPE, MISSING\nfrom functools import wraps\nfrom hashlib import md5\nfrom types import SimpleNamespace\nfrom typing import TYPE_CHECKING, Any, ClassVar, TypeVar, cast, get_args, get_origin\n\nfrom rich.markup import escape\nfrom typing_extensions import dataclass_transform\n\nimport reflex.state\nfrom reflex import constants\nfrom reflex.compiler.templates import stateful_component_template\nfrom reflex.components.core.breakpoints import Breakpoints\nfrom reflex.components.dynamic import load_dynamic_serializer\nfrom reflex.components.field import BaseField, FieldBasedMeta\nfrom reflex.components.tags import Tag\nfrom reflex.constants import (\n    Dirs,\n    EventTriggers,\n    Hooks,\n    Imports,\n    MemoizationDisposition,\n    MemoizationMode,\n    PageNames,\n)\nfrom reflex.constants.compiler import SpecialAttributes\nfrom reflex.constants.state import CAMEL_CASE_MEMO_MARKER, FRONTEND_EVENT_STATE\nfrom reflex.event import (\n    EventCallback,\n    EventChain,\n    EventHandler,\n    EventSpec,\n    args_specs_from_fields,\n    no_args_event_spec,\n    parse_args_spec,\n    pointer_event_spec,\n    run_script,\n    unwrap_var_annotation,\n)\nfrom reflex.style import Style, format_as_emotion\nfrom reflex.utils import console, format, imports, types\nfrom reflex.utils.imports import ImportDict, ImportVar, ParsedImportDict\nfrom reflex.vars import VarData\nfrom reflex.vars.base import (\n    CachedVarOperation,\n    LiteralNoneVar,\n    LiteralVar,\n    Var,\n    cached_property_no_lock,\n)\nfrom reflex.vars.function import ArgsFunctionOperation, FunctionStringVar, FunctionVar\nfrom reflex.vars.number import ternary_operation\nfrom reflex.vars.object import ObjectVar\nfrom reflex.vars.sequence import LiteralArrayVar, LiteralStringVar, StringVar\n\nFIELD_TYPE = TypeVar(\"FIELD_TYPE\")\n\n\nclass ComponentField(BaseField[FIELD_TYPE]):\n    \"\"\"A field for a component.\"\"\"\n\n    def __init__(\n        self,\n        default: FIELD_TYPE | _MISSING_TYPE = MISSING,\n        default_factory: Callable[[], FIELD_TYPE] | None = None,\n        is_javascript: bool | None = None,\n        annotated_type: type[Any] | _MISSING_TYPE = MISSING,\n    ) -> None:\n        \"\"\"Initialize the field.\n\n        Args:\n            default: The default value for the field.\n            default_factory: The default factory for the field.\n            is_javascript: Whether the field is a javascript property.\n            annotated_type: The annotated type for the field.\n        \"\"\"\n        super().__init__(default, default_factory, annotated_type)\n        self.is_javascript = is_javascript\n\n    def __repr__(self) -> str:\n        \"\"\"Represent the field in a readable format.\n\n        Returns:\n            The string representation of the field.\n        \"\"\"\n        annotated_type_str = (\n            f\", annotated_type={self.annotated_type!r}\"\n            if self.annotated_type is not MISSING\n            else \"\"\n        )\n        if self.default is not MISSING:\n            return f\"ComponentField(default={self.default!r}, is_javascript={self.is_javascript!r}{annotated_type_str})\"\n        return f\"ComponentField(default_factory={self.default_factory!r}, is_javascript={self.is_javascript!r}{annotated_type_str})\"\n\n\ndef field(\n    default: FIELD_TYPE | _MISSING_TYPE = MISSING,\n    default_factory: Callable[[], FIELD_TYPE] | None = None,\n    is_javascript_property: bool | None = None,\n) -> FIELD_TYPE:\n    \"\"\"Create a field for a component.\n\n    Args:\n        default: The default value for the field.\n        default_factory: The default factory for the field.\n        is_javascript_property: Whether the field is a javascript property.\n\n    Returns:\n        The field for the component.\n\n    Raises:\n        ValueError: If both default and default_factory are specified.\n    \"\"\"\n    if default is not MISSING and default_factory is not None:\n        msg = \"cannot specify both default and default_factory\"\n        raise ValueError(msg)\n    return ComponentField(  # pyright: ignore [reportReturnType]\n        default=default,\n        default_factory=default_factory,\n        is_javascript=is_javascript_property,\n    )\n\n\n@dataclass_transform(kw_only_default=True, field_specifiers=(field,))\nclass BaseComponentMeta(FieldBasedMeta, ABCMeta):\n    \"\"\"Meta class for BaseComponent.\"\"\"\n\n    if TYPE_CHECKING:\n        _inherited_fields: Mapping[str, ComponentField]\n        _own_fields: Mapping[str, ComponentField]\n        _fields: Mapping[str, ComponentField]\n        _js_fields: Mapping[str, ComponentField]\n\n    @classmethod\n    def _process_annotated_fields(\n        cls,\n        namespace: dict[str, Any],\n        annotations: dict[str, Any],\n        inherited_fields: dict[str, ComponentField],\n    ) -> dict[str, ComponentField]:\n        own_fields: dict[str, ComponentField] = {}\n\n        for key, annotation in annotations.items():\n            value = namespace.get(key, MISSING)\n\n            if types.is_classvar(annotation):\n                # If the annotation is a classvar, skip it.\n                continue\n\n            if value is MISSING:\n                value = ComponentField(\n                    default=None,\n                    is_javascript=(key[0] != \"_\"),\n                    annotated_type=annotation,\n                )\n            elif not isinstance(value, ComponentField):\n                value = ComponentField(\n                    default=value,\n                    is_javascript=(\n                        (key[0] != \"_\")\n                        if (existing_field := inherited_fields.get(key)) is None\n                        else existing_field.is_javascript\n                    ),\n                    annotated_type=annotation,\n                )\n            else:\n                value = ComponentField(\n                    default=value.default,\n                    default_factory=value.default_factory,\n                    is_javascript=value.is_javascript,\n                    annotated_type=annotation,\n                )\n\n            own_fields[key] = value\n\n        return own_fields\n\n    @classmethod\n    def _create_field(\n        cls,\n        annotated_type: Any,\n        default: Any = MISSING,\n        default_factory: Callable[[], Any] | None = None,\n    ) -> ComponentField:\n        return ComponentField(\n            annotated_type=annotated_type,\n            default=default,\n            default_factory=default_factory,\n            is_javascript=True,  # Default for components\n        )\n\n    @classmethod\n    def _process_field_overrides(\n        cls,\n        namespace: dict[str, Any],\n        annotations: dict[str, Any],\n        inherited_fields: dict[str, Any],\n    ) -> dict[str, ComponentField]:\n        own_fields: dict[str, ComponentField] = {}\n\n        for key, value, inherited_field in [\n            (key, value, inherited_field)\n            for key, value in namespace.items()\n            if key not in annotations\n            and ((inherited_field := inherited_fields.get(key)) is not None)\n        ]:\n            new_field = ComponentField(\n                default=value,\n                is_javascript=inherited_field.is_javascript,\n                annotated_type=inherited_field.annotated_type,\n            )\n            own_fields[key] = new_field\n\n        return own_fields\n\n    @classmethod\n    def _finalize_fields(\n        cls,\n        namespace: dict[str, Any],\n        inherited_fields: dict[str, ComponentField],\n        own_fields: dict[str, ComponentField],\n    ) -> None:\n        # Call parent implementation\n        super()._finalize_fields(namespace, inherited_fields, own_fields)\n\n        # Add JavaScript fields mapping\n        all_fields = namespace[\"_fields\"]\n        namespace[\"_js_fields\"] = {\n            key: value\n            for key, value in all_fields.items()\n            if value.is_javascript is True\n        }\n\n\nclass BaseComponent(metaclass=BaseComponentMeta):\n    \"\"\"The base class for all Reflex components.\n\n    This is something that can be rendered as a Component via the Reflex compiler.\n    \"\"\"\n\n    # The children nested within the component.\n    children: list[BaseComponent] = field(\n        default_factory=list, is_javascript_property=False\n    )\n\n    # The library that the component is based on.\n    library: str | None = field(default=None, is_javascript_property=False)\n\n    # List here the non-react dependency needed by `library`\n    lib_dependencies: list[str] = field(\n        default_factory=list, is_javascript_property=False\n    )\n\n    # The tag to use when rendering the component.\n    tag: str | None = field(default=None, is_javascript_property=False)\n\n    def __init__(\n        self,\n        **kwargs,\n    ):\n        \"\"\"Initialize the component.\n\n        Args:\n            **kwargs: The kwargs to pass to the component.\n        \"\"\"\n        for key, value in kwargs.items():\n            setattr(self, key, value)\n        for name, value in self.get_fields().items():\n            if name not in kwargs:\n                setattr(self, name, value.default_value())\n\n    def set(self, **kwargs):\n        \"\"\"Set the component props.\n\n        Args:\n            **kwargs: The kwargs to set.\n\n        Returns:\n            The component with the updated props.\n        \"\"\"\n        for key, value in kwargs.items():\n            setattr(self, key, value)\n        return self\n\n    def __eq__(self, value: Any) -> bool:\n        \"\"\"Check if the component is equal to another value.\n\n        Args:\n            value: The value to compare to.\n\n        Returns:\n            Whether the component is equal to the value.\n        \"\"\"\n        return type(self) is type(value) and bool(\n            getattr(self, key) == getattr(value, key) for key in self.get_fields()\n        )\n\n    @classmethod\n    def get_fields(cls) -> Mapping[str, ComponentField]:\n        \"\"\"Get the fields of the component.\n\n        Returns:\n            The fields of the component.\n        \"\"\"\n        return cls._fields\n\n    @classmethod\n    def get_js_fields(cls) -> Mapping[str, ComponentField]:\n        \"\"\"Get the javascript fields of the component.\n\n        Returns:\n            The javascript fields of the component.\n        \"\"\"\n        return cls._js_fields\n\n    @abstractmethod\n    def render(self) -> dict:\n        \"\"\"Render the component.\n\n        Returns:\n            The dictionary for template of the component.\n        \"\"\"\n\n    @abstractmethod\n    def _get_all_hooks_internal(self) -> dict[str, VarData | None]:\n        \"\"\"Get the reflex internal hooks for the component and its children.\n\n        Returns:\n            The code that should appear just before user-defined hooks.\n        \"\"\"\n\n    @abstractmethod\n    def _get_all_hooks(self) -> dict[str, VarData | None]:\n        \"\"\"Get the React hooks for this component.\n\n        Returns:\n            The code that should appear just before returning the rendered component.\n        \"\"\"\n\n    @abstractmethod\n    def _get_all_imports(self) -> ParsedImportDict:\n        \"\"\"Get all the libraries and fields that are used by the component.\n\n        Returns:\n            The import dict with the required imports.\n        \"\"\"\n\n    @abstractmethod\n    def _get_all_dynamic_imports(self) -> set[str]:\n        \"\"\"Get dynamic imports for the component.\n\n        Returns:\n            The dynamic imports.\n        \"\"\"\n\n    @abstractmethod\n    def _get_all_custom_code(self) -> dict[str, None]:\n        \"\"\"Get custom code for the component.\n\n        Returns:\n            The custom code.\n        \"\"\"\n\n    @abstractmethod\n    def _get_all_refs(self) -> dict[str, None]:\n        \"\"\"Get the refs for the children of the component.\n\n        Returns:\n            The refs for the children.\n        \"\"\"\n\n\nclass ComponentNamespace(SimpleNamespace):\n    \"\"\"A namespace to manage components with subcomponents.\"\"\"\n\n    def __hash__(self) -> int:  # pyright: ignore [reportIncompatibleVariableOverride]\n        \"\"\"Get the hash of the namespace.\n\n        Returns:\n            The hash of the namespace.\n        \"\"\"\n        return hash(type(self).__name__)\n\n\ndef evaluate_style_namespaces(style: ComponentStyle) -> dict:\n    \"\"\"Evaluate namespaces in the style.\n\n    Args:\n        style: The style to evaluate.\n\n    Returns:\n        The evaluated style.\n    \"\"\"\n    return {\n        k.__call__ if isinstance(k, ComponentNamespace) else k: v\n        for k, v in style.items()\n    }\n\n\n# Map from component to styling.\nComponentStyle = dict[str | type[BaseComponent] | Callable | ComponentNamespace, Any]\nComponentChildTypes = (*types.PrimitiveTypes, Var, BaseComponent, type(None))\n\n\ndef _satisfies_type_hint(obj: Any, type_hint: Any) -> bool:\n    return types._isinstance(\n        obj,\n        type_hint,\n        nested=1,\n        treat_var_as_type=True,\n        treat_mutable_obj_as_immutable=(\n            isinstance(obj, Var) and not isinstance(obj, LiteralVar)\n        ),\n    )\n\n\ndef satisfies_type_hint(obj: Any, type_hint: Any) -> bool:\n    \"\"\"Check if an object satisfies a type hint.\n\n    Args:\n        obj: The object to check.\n        type_hint: The type hint to check against.\n\n    Returns:\n        Whether the object satisfies the type hint.\n    \"\"\"\n    if _satisfies_type_hint(obj, type_hint):\n        return True\n    if _satisfies_type_hint(obj, type_hint | None):\n        obj = (\n            obj\n            if not isinstance(obj, Var)\n            else (obj._var_value if isinstance(obj, LiteralVar) else obj)\n        )\n        console.warn(\n            \"Passing None to a Var that is not explicitly marked as Optional (| None) is deprecated. \"\n            f\"Passed {obj!s} of type {escape(str(type(obj) if not isinstance(obj, Var) else obj._var_type))} to {escape(str(type_hint))}.\"\n        )\n        return True\n    return False\n\n\ndef _components_from(\n    component_or_var: BaseComponent | Var,\n) -> tuple[BaseComponent, ...]:\n    \"\"\"Get the components from a component or Var.\n\n    Args:\n        component_or_var: The component or Var to get the components from.\n\n    Returns:\n        The components.\n    \"\"\"\n    if isinstance(component_or_var, Var):\n        var_data = component_or_var._get_all_var_data()\n        return var_data.components if var_data else ()\n    if isinstance(component_or_var, BaseComponent):\n        return (component_or_var,)\n    return ()\n\n\ndef _hash_str(value: str) -> str:\n    return md5(f'\"{value}\"'.encode(), usedforsecurity=False).hexdigest()\n\n\ndef _hash_sequence(value: Sequence) -> str:\n    return _hash_str(str([_deterministic_hash(v) for v in value]))\n\n\ndef _hash_dict(value: dict) -> str:\n    return _hash_sequence(\n        sorted([(k, _deterministic_hash(v)) for k, v in value.items()])\n    )\n\n\ndef _deterministic_hash(value: object) -> str:\n    \"\"\"Hash a rendered dictionary.\n\n    Args:\n        value: The dictionary to hash.\n\n    Returns:\n        The hash of the dictionary.\n\n    Raises:\n        TypeError: If the value is not hashable.\n    \"\"\"\n    if value is None:\n        # Hash None as a special case.\n        return \"None\"\n    if isinstance(value, (int, float, enum.Enum)):\n        # Hash numbers and booleans directly.\n        return str(value)\n    if isinstance(value, str):\n        return _hash_str(value)\n    if isinstance(value, dict):\n        return _hash_dict(value)\n    if isinstance(value, (tuple, list)):\n        # Hash tuples by hashing each element.\n        return _hash_sequence(value)\n    if isinstance(value, Var):\n        return _hash_str(\n            str((value._js_expr, _deterministic_hash(value._get_all_var_data())))\n        )\n    if dataclasses.is_dataclass(value):\n        return _hash_dict({\n            k.name: getattr(value, k.name) for k in dataclasses.fields(value)\n        })\n    if isinstance(value, BaseComponent):\n        # If the value is a component, hash its rendered code.\n        return _hash_dict(value.render())\n\n    msg = (\n        f\"Cannot hash value `{value}` of type `{type(value).__name__}`. \"\n        \"Only BaseComponent, Var, VarData, dict, str, tuple, and enum.Enum are supported.\"\n    )\n    raise TypeError(msg)\n\n\nDEFAULT_TRIGGERS: Mapping[str, types.ArgsSpec | Sequence[types.ArgsSpec]] = {\n    EventTriggers.ON_FOCUS: no_args_event_spec,\n    EventTriggers.ON_BLUR: no_args_event_spec,\n    EventTriggers.ON_CLICK: pointer_event_spec,  # pyright: ignore [reportAssignmentType]\n    EventTriggers.ON_CONTEXT_MENU: pointer_event_spec,  # pyright: ignore [reportAssignmentType]\n    EventTriggers.ON_DOUBLE_CLICK: pointer_event_spec,  # pyright: ignore [reportAssignmentType]\n    EventTriggers.ON_MOUSE_DOWN: no_args_event_spec,\n    EventTriggers.ON_MOUSE_ENTER: no_args_event_spec,\n    EventTriggers.ON_MOUSE_LEAVE: no_args_event_spec,\n    EventTriggers.ON_MOUSE_MOVE: no_args_event_spec,\n    EventTriggers.ON_MOUSE_OUT: no_args_event_spec,\n    EventTriggers.ON_MOUSE_OVER: no_args_event_spec,\n    EventTriggers.ON_MOUSE_UP: no_args_event_spec,\n    EventTriggers.ON_SCROLL: no_args_event_spec,\n    EventTriggers.ON_SCROLL_END: no_args_event_spec,\n    EventTriggers.ON_MOUNT: no_args_event_spec,\n    EventTriggers.ON_UNMOUNT: no_args_event_spec,\n}\n\nT = TypeVar(\"T\", bound=\"Component\")\n\n\nclass Component(BaseComponent, ABC):\n    \"\"\"A component with style, event trigger and other props.\"\"\"\n\n    # The style of the component.\n    style: Style = field(default_factory=Style, is_javascript_property=False)\n\n    # A mapping from event triggers to event chains.\n    event_triggers: dict[str, EventChain | Var] = field(\n        default_factory=dict, is_javascript_property=False\n    )\n\n    # The alias for the tag.\n    alias: str | None = field(default=None, is_javascript_property=False)\n\n    # Whether the component is a global scope tag. True for tags like `html`, `head`, `body`.\n    _is_tag_in_global_scope: ClassVar[bool] = False\n\n    # Whether the import is default or named.\n    is_default: bool | None = field(default=False, is_javascript_property=False)\n\n    # A unique key for the component.\n    key: Any = field(default=None, is_javascript_property=False)\n\n    # The id for the component.\n    id: Any = field(default=None, is_javascript_property=False)\n\n    # The Var to pass as the ref to the component.\n    ref: Var | None = field(default=None, is_javascript_property=False)\n\n    # The class name for the component.\n    class_name: Any = field(default=None, is_javascript_property=False)\n\n    # Special component props.\n    special_props: list[Var] = field(default_factory=list, is_javascript_property=False)\n\n    # components that cannot be children\n    _invalid_children: ClassVar[list[str]] = []\n\n    # only components that are allowed as children\n    _valid_children: ClassVar[list[str]] = []\n\n    # only components that are allowed as parent\n    _valid_parents: ClassVar[list[str]] = []\n\n    # props to change the name of\n    _rename_props: ClassVar[dict[str, str]] = {}\n\n    # custom attribute\n    custom_attrs: dict[str, Var | Any] = field(\n        default_factory=dict, is_javascript_property=False\n    )\n\n    # When to memoize this component and its children.\n    _memoization_mode: MemoizationMode = field(\n        default_factory=MemoizationMode, is_javascript_property=False\n    )\n\n    # State class associated with this component instance\n    State: type[reflex.state.State] | None = field(\n        default=None, is_javascript_property=False\n    )\n\n    def add_imports(self) -> ImportDict | list[ImportDict]:\n        \"\"\"Add imports for the component.\n\n        This method should be implemented by subclasses to add new imports for the component.\n\n        Implementations do NOT need to call super(). The result of calling\n        add_imports in each parent class will be merged internally.\n\n        Returns:\n            The additional imports for this component subclass.\n\n        The format of the return value is a dictionary where the keys are the\n        library names (with optional npm-style version specifications) mapping\n        to a single name to be imported, or a list names to be imported.\n\n        For advanced use cases, the values can be ImportVar instances (for\n        example, to provide an alias or mark that an import is the default\n        export from the given library).\n\n        ```python\n        return {\n            \"react\": \"useEffect\",\n            \"react-draggable\": [\"DraggableCore\", rx.ImportVar(tag=\"Draggable\", is_default=True)],\n        }\n        ```\n        \"\"\"\n        return {}\n\n    def add_hooks(self) -> list[str | Var]:\n        \"\"\"Add hooks inside the component function.\n\n        Hooks are pieces of literal Javascript code that is inserted inside the\n        React component function.\n\n        Each logical hook should be a separate string in the list.\n\n        Common strings will be deduplicated and inserted into the component\n        function only once, so define const variables and other identical code\n        in their own strings to avoid defining the same const or hook multiple\n        times.\n\n        If a hook depends on specific data from the component instance, be sure\n        to use unique values inside the string to _avoid_ deduplication.\n\n        Implementations do NOT need to call super(). The result of calling\n        add_hooks in each parent class will be merged and deduplicated internally.\n\n        Returns:\n            The additional hooks for this component subclass.\n\n        ```python\n        return [\n            \"const [count, setCount] = useState(0);\",\n            \"useEffect(() => { setCount((prev) => prev + 1); console.log(`mounted ${count} times`); }, []);\",\n        ]\n        ```\n        \"\"\"\n        return []\n\n    def add_custom_code(self) -> list[str]:\n        \"\"\"Add custom Javascript code into the page that contains this component.\n\n        Custom code is inserted at module level, after any imports.\n\n        Each string of custom code is deduplicated per-page, so take care to\n        avoid defining the same const or function differently from different\n        component instances.\n\n        Custom code is useful for defining global functions or constants which\n        can then be referenced inside hooks or used by component vars.\n\n        Implementations do NOT need to call super(). The result of calling\n        add_custom_code in each parent class will be merged and deduplicated internally.\n\n        Returns:\n            The additional custom code for this component subclass.\n\n        ```python\n        return [\n            \"const translatePoints = (event) => { return { x: event.clientX, y: event.clientY }; };\",\n        ]\n        ```\n        \"\"\"\n        return []\n\n    @classmethod\n    def __init_subclass__(cls, **kwargs):\n        \"\"\"Set default properties.\n\n        Args:\n            **kwargs: The kwargs to pass to the superclass.\n        \"\"\"\n        super().__init_subclass__(**kwargs)\n\n        # Ensure renamed props from parent classes are applied to the subclass.\n        if cls._rename_props:\n            inherited_rename_props = {}\n            for parent in reversed(cls.mro()):\n                if issubclass(parent, Component) and parent._rename_props:\n                    inherited_rename_props.update(parent._rename_props)\n            cls._rename_props = inherited_rename_props\n\n    def __init__(self, **kwargs):\n        \"\"\"Initialize the custom component.\n\n        Args:\n            **kwargs: The kwargs to pass to the component.\n        \"\"\"\n        console.error(\n            \"Instantiating components directly is not supported.\"\n            f\" Use `{self.__class__.__name__}.create` method instead.\"\n        )\n\n    def _post_init(self, *args, **kwargs):\n        \"\"\"Initialize the component.\n\n        Args:\n            *args: Args to initialize the component.\n            **kwargs: Kwargs to initialize the component.\n\n        Raises:\n            TypeError: If an invalid prop is passed.\n            ValueError: If an event trigger passed is not valid.\n        \"\"\"\n        # Set the id and children initially.\n        children = kwargs.get(\"children\", [])\n\n        self._validate_component_children(children)\n\n        # Get the component fields, triggers, and props.\n        fields = self.get_fields()\n        component_specific_triggers = self.get_event_triggers()\n        props = self.get_props()\n\n        # Add any events triggers.\n        if \"event_triggers\" not in kwargs:\n            kwargs[\"event_triggers\"] = {}\n        kwargs[\"event_triggers\"] = kwargs[\"event_triggers\"].copy()\n\n        # Iterate through the kwargs and set the props.\n        for key, value in kwargs.items():\n            if (\n                key.startswith(\"on_\")\n                and key not in component_specific_triggers\n                and key not in props\n            ):\n                valid_triggers = sorted(component_specific_triggers.keys())\n                msg = (\n                    f\"The {(comp_name := type(self).__name__)} does not take in an `{key}` event trigger. \"\n                    f\"Valid triggers for {comp_name}: {valid_triggers}. \"\n                    f\"If {comp_name} is a third party component make sure to add `{key}` to the component's event triggers. \"\n                    f\"visit https://reflex.dev/docs/wrapping-react/guide/#event-triggers for more info.\"\n                )\n                raise ValueError(msg)\n            if key in component_specific_triggers:\n                # Event triggers are bound to event chains.\n                is_var = False\n            elif key in props:\n                # Set the field type.\n                is_var = (\n                    field.type_origin is Var if (field := fields.get(key)) else False\n                )\n            else:\n                continue\n\n            # Check whether the key is a component prop.\n            if is_var:\n                try:\n                    kwargs[key] = LiteralVar.create(value)\n\n                    # Get the passed type and the var type.\n                    passed_type = kwargs[key]._var_type\n                    expected_type = types.get_args(\n                        types.get_field_type(type(self), key)\n                    )[0]\n                except TypeError:\n                    # If it is not a valid var, check the base types.\n                    passed_type = type(value)\n                    expected_type = types.get_field_type(type(self), key)\n\n                if not satisfies_type_hint(value, expected_type):\n                    value_name = value._js_expr if isinstance(value, Var) else value\n\n                    additional_info = (\n                        \" You can call `.bool()` on the value to convert it to a boolean.\"\n                        if expected_type is bool and isinstance(value, Var)\n                        else \"\"\n                    )\n\n                    raise TypeError(\n                        f\"Invalid var passed for prop {type(self).__name__}.{key}, expected type {expected_type}, got value {value_name} of type {passed_type}.\"\n                        + additional_info\n                    )\n            # Check if the key is an event trigger.\n            if key in component_specific_triggers:\n                kwargs[\"event_triggers\"][key] = EventChain.create(\n                    value=value,\n                    args_spec=component_specific_triggers[key],\n                    key=key,\n                )\n\n        # Remove any keys that were added as events.\n        for key in kwargs[\"event_triggers\"]:\n            kwargs.pop(key, None)\n\n        # Place data_ and aria_ attributes into custom_attrs\n        special_attributes = [\n            key\n            for key in kwargs\n            if key not in fields and SpecialAttributes.is_special(key)\n        ]\n        if special_attributes:\n            custom_attrs = kwargs.setdefault(\"custom_attrs\", {})\n            custom_attrs.update({\n                format.to_kebab_case(key): kwargs.pop(key) for key in special_attributes\n            })\n\n        # Add style props to the component.\n        style = kwargs.get(\"style\", {})\n        if isinstance(style, Sequence):\n            if any(not isinstance(s, Mapping) for s in style):\n                msg = \"Style must be a dictionary or a list of dictionaries.\"\n                raise TypeError(msg)\n            # Merge styles, the later ones overriding keys in the earlier ones.\n            style = {\n                k: v\n                for style_dict in style\n                for k, v in cast(Mapping, style_dict).items()\n            }\n\n        if isinstance(style, (Breakpoints, Var)):\n            style = {\n                # Assign the Breakpoints to the self-referential selector to avoid squashing down to a regular dict.\n                \"&\": style,\n            }\n\n        fields_style = self.get_fields()[\"style\"]\n\n        kwargs[\"style\"] = Style({\n            **fields_style.default_value(),\n            **style,\n            **{attr: value for attr, value in kwargs.items() if attr not in fields},\n        })\n\n        # Convert class_name to str if it's list\n        class_name = kwargs.get(\"class_name\", \"\")\n        if isinstance(class_name, (list, tuple)):\n            has_var = False\n            for c in class_name:\n                if isinstance(c, str):\n                    continue\n                if isinstance(c, Var):\n                    if not isinstance(c, StringVar) and not issubclass(\n                        c._var_type, str\n                    ):\n                        msg = f\"Invalid class_name passed for prop {type(self).__name__}.class_name, expected type str, got value {c._js_expr} of type {c._var_type}.\"\n                        raise TypeError(msg)\n                    has_var = True\n                else:\n                    msg = f\"Invalid class_name passed for prop {type(self).__name__}.class_name, expected type str, got value {c} of type {type(c)}.\"\n                    raise TypeError(msg)\n            if has_var:\n                kwargs[\"class_name\"] = LiteralArrayVar.create(\n                    class_name, _var_type=list[str]\n                ).join(\" \")\n            else:\n                kwargs[\"class_name\"] = \" \".join(class_name)\n        elif (\n            isinstance(class_name, Var)\n            and not isinstance(class_name, StringVar)\n            and not issubclass(class_name._var_type, str)\n        ):\n            msg = f\"Invalid class_name passed for prop {type(self).__name__}.class_name, expected type str, got value {class_name._js_expr} of type {class_name._var_type}.\"\n            raise TypeError(msg)\n        # Construct the component.\n        for key, value in kwargs.items():\n            setattr(self, key, value)\n\n    @classmethod\n    def get_event_triggers(cls) -> dict[str, types.ArgsSpec | Sequence[types.ArgsSpec]]:\n        \"\"\"Get the event triggers for the component.\n\n        Returns:\n            The event triggers.\n        \"\"\"\n        # Look for component specific triggers,\n        # e.g. variable declared as EventHandler types.\n        return DEFAULT_TRIGGERS | args_specs_from_fields(cls.get_fields())  # pyright: ignore [reportOperatorIssue]\n\n    def __repr__(self) -> str:\n        \"\"\"Represent the component in React.\n\n        Returns:\n            The code to render the component.\n        \"\"\"\n        return format.json_dumps(self.render())\n\n    def __str__(self) -> str:\n        \"\"\"Represent the component in React.\n\n        Returns:\n            The code to render the component.\n        \"\"\"\n        from reflex.compiler.compiler import _compile_component\n\n        return _compile_component(self)\n\n    def _exclude_props(self) -> list[str]:\n        \"\"\"Props to exclude when adding the component props to the Tag.\n\n        Returns:\n            A list of component props to exclude.\n        \"\"\"\n        return []\n\n    def _render(self, props: dict[str, Any] | None = None) -> Tag:\n        \"\"\"Define how to render the component in React.\n\n        Args:\n            props: The props to render (if None, then use get_props).\n\n        Returns:\n            The tag to render.\n        \"\"\"\n        # Create the base tag.\n        name = (self.tag if not self.alias else self.alias) or \"\"\n        if self._is_tag_in_global_scope and self.library is None:\n            name = '\"' + name + '\"'\n\n        # Create the base tag.\n        tag = Tag(\n            name=name,\n            special_props=self.special_props.copy(),\n        )\n\n        if props is None:\n            # Add component props to the tag.\n            props = {\n                attr.removesuffix(\"_\"): getattr(self, attr) for attr in self.get_props()\n            }\n\n            # Add ref to element if `ref` is None and `id` is not None.\n            if self.ref is not None:\n                props[\"ref\"] = self.ref\n            elif (ref := self.get_ref()) is not None:\n                props[\"ref\"] = Var(_js_expr=ref)\n        else:\n            props = props.copy()\n\n        props.update(\n            **{\n                trigger: handler\n                for trigger, handler in self.event_triggers.items()\n                if trigger not in {EventTriggers.ON_MOUNT, EventTriggers.ON_UNMOUNT}\n            },\n            key=self.key,\n            id=self.id,\n            class_name=self.class_name,\n        )\n        props.update(self._get_style())\n        props.update(self.custom_attrs)\n\n        # remove excluded props from prop dict before adding to tag.\n        for prop_to_exclude in self._exclude_props():\n            props.pop(prop_to_exclude, None)\n\n        return tag.add_props(**props)\n\n    @classmethod\n    @functools.cache\n    def get_props(cls) -> Iterable[str]:\n        \"\"\"Get the unique fields for the component.\n\n        Returns:\n            The unique fields.\n        \"\"\"\n        return cls.get_js_fields()\n\n    @classmethod\n    @functools.cache\n    def get_initial_props(cls) -> set[str]:\n        \"\"\"Get the initial props to set for the component.\n\n        Returns:\n            The initial props to set.\n        \"\"\"\n        return set()\n\n    @functools.cached_property\n    def _get_component_prop_property(self) -> Sequence[BaseComponent]:\n        return [\n            component\n            for prop in self.get_props()\n            if (value := getattr(self, prop)) is not None\n            and isinstance(value, (BaseComponent, Var))\n            for component in _components_from(value)\n        ]\n\n    def _get_components_in_props(self) -> Sequence[BaseComponent]:\n        \"\"\"Get the components in the props.\n\n        Returns:\n            The components in the props\n        \"\"\"\n        return self._get_component_prop_property\n\n    @classmethod\n    def _validate_children(cls, children: tuple | list):\n        from reflex.utils.exceptions import ChildrenTypeError\n\n        for child in children:\n            if isinstance(child, (tuple, list)):\n                cls._validate_children(child)\n\n            # Make sure the child is a valid type.\n            if isinstance(child, dict) or not isinstance(child, ComponentChildTypes):\n                raise ChildrenTypeError(component=cls.__name__, child=child)\n\n    @classmethod\n    def create(cls: type[T], *children, **props) -> T:\n        \"\"\"Create the component.\n\n        Args:\n            *children: The children of the component.\n            **props: The props of the component.\n\n        Returns:\n            The component.\n        \"\"\"\n        # Import here to avoid circular imports.\n        from reflex.components.base.bare import Bare\n        from reflex.components.base.fragment import Fragment\n\n        # Filter out None props\n        props = {key: value for key, value in props.items() if value is not None}\n\n        # Validate all the children.\n        cls._validate_children(children)\n\n        children_normalized = [\n            (\n                child\n                if isinstance(child, Component)\n                else (\n                    Fragment.create(*child)\n                    if isinstance(child, tuple)\n                    else Bare.create(contents=LiteralVar.create(child))\n                )\n            )\n            for child in children\n        ]\n\n        return cls._create(children_normalized, **props)\n\n    @classmethod\n    def _create(cls: type[T], children: Sequence[BaseComponent], **props: Any) -> T:\n        \"\"\"Create the component.\n\n        Args:\n            children: The children of the component.\n            **props: The props of the component.\n\n        Returns:\n            The component.\n        \"\"\"\n        comp = cls.__new__(cls)\n        super(Component, comp).__init__(id=props.get(\"id\"), children=list(children))\n        comp._post_init(children=list(children), **props)\n        return comp\n\n    @classmethod\n    def _unsafe_create(\n        cls: type[T], children: Sequence[BaseComponent], **props: Any\n    ) -> T:\n        \"\"\"Create the component without running post_init.\n\n        Args:\n            children: The children of the component.\n            **props: The props of the component.\n\n        Returns:\n            The component.\n        \"\"\"\n        comp = cls.__new__(cls)\n        super(Component, comp).__init__(id=props.get(\"id\"), children=list(children))\n        for prop, value in props.items():\n            setattr(comp, prop, value)\n        return comp\n\n    def add_style(self) -> dict[str, Any] | None:\n        \"\"\"Add style to the component.\n\n        Downstream components can override this method to return a style dict\n        that will be applied to the component.\n\n        Returns:\n            The style to add.\n        \"\"\"\n        return None\n\n    def _add_style(self) -> Style:\n        \"\"\"Call add_style for all bases in the MRO.\n\n        Downstream components should NOT override. Use add_style instead.\n\n        Returns:\n            The style to add.\n        \"\"\"\n        styles = []\n\n        # Walk the MRO to call all `add_style` methods.\n        for base in self._iter_parent_classes_with_method(\"add_style\"):\n            s = base.add_style(self)\n            if s is not None:\n                styles.append(s)\n\n        style_ = Style()\n        for s in reversed(styles):\n            style_.update(s)\n        return style_\n\n    def _get_component_style(self, styles: ComponentStyle | Style) -> Style | None:\n        \"\"\"Get the style to the component from `App.style`.\n\n        Args:\n            styles: The style to apply.\n\n        Returns:\n            The style of the component.\n        \"\"\"\n        component_style = None\n        if (style := styles.get(type(self))) is not None:  # pyright: ignore [reportArgumentType]\n            component_style = Style(style)\n        if (style := styles.get(self.create)) is not None:  # pyright: ignore [reportArgumentType]\n            component_style = Style(style)\n        return component_style\n\n    def _add_style_recursive(\n        self, style: ComponentStyle | Style, theme: Component | None = None\n    ) -> Component:\n        \"\"\"Add additional style to the component and its children.\n\n        Apply order is as follows (with the latest overriding the earliest):\n        1. Default style from `_add_style`/`add_style`.\n        2. User-defined style from `App.style`.\n        3. User-defined style from `Component.style`.\n        4. style dict and css props passed to the component instance.\n\n        Args:\n            style: A dict from component to styling.\n            theme: The theme to apply. (for retro-compatibility with deprecated _apply_theme API)\n\n        Returns:\n            The component with the additional style.\n\n        Raises:\n            UserWarning: If `_add_style` has been overridden.\n        \"\"\"\n        # 1. Default style from `_add_style`/`add_style`.\n        if type(self)._add_style != Component._add_style:\n            msg = \"Do not override _add_style directly. Use add_style instead.\"\n            raise UserWarning(msg)\n        new_style = self._add_style()\n        style_vars = [new_style._var_data]\n\n        # 2. User-defined style from `App.style`.\n        component_style = self._get_component_style(style)\n        if component_style:\n            new_style.update(component_style)\n            style_vars.append(component_style._var_data)\n\n        # 4. style dict and css props passed to the component instance.\n        new_style.update(self.style)\n        style_vars.append(self.style._var_data)\n\n        new_style._var_data = VarData.merge(*style_vars)\n\n        # Assign the new style\n        self.style = new_style\n\n        # Recursively add style to the children.\n        for child in self.children:\n            # Skip BaseComponent and StatefulComponent children.\n            if not isinstance(child, Component):\n                continue\n            child._add_style_recursive(style, theme)\n        return self\n\n    def _get_style(self) -> dict:\n        \"\"\"Get the style for the component.\n\n        Returns:\n            The dictionary of the component style as value and the style notation as key.\n        \"\"\"\n        if isinstance(self.style, Var):\n            return {\"css\": self.style}\n        emotion_style = format_as_emotion(self.style)\n        return (\n            {\"css\": LiteralVar.create(emotion_style)}\n            if emotion_style is not None\n            else {}\n        )\n\n    def render(self) -> dict:\n        \"\"\"Render the component.\n\n        Returns:\n            The dictionary for template of component.\n        \"\"\"\n        tag = self._render()\n        rendered_dict = dict(\n            tag.set(\n                children=[child.render() for child in self.children],\n            )\n        )\n        self._replace_prop_names(rendered_dict)\n        return rendered_dict\n\n    def _replace_prop_names(self, rendered_dict: dict) -> None:\n        \"\"\"Replace the prop names in the render dictionary.\n\n        Args:\n            rendered_dict: The render dictionary with all the component props and event handlers.\n        \"\"\"\n        # fast path\n        if not self._rename_props:\n            return\n\n        for ix, prop in enumerate(rendered_dict[\"props\"]):\n            for old_prop, new_prop in self._rename_props.items():\n                if prop.startswith(old_prop):\n                    rendered_dict[\"props\"][ix] = prop.replace(old_prop, new_prop, 1)\n\n    def _validate_component_children(self, children: list[Component]):\n        \"\"\"Validate the children components.\n\n        Args:\n            children: The children of the component.\n\n        \"\"\"\n        from reflex.components.base.fragment import Fragment\n        from reflex.components.core.cond import Cond\n        from reflex.components.core.foreach import Foreach\n        from reflex.components.core.match import Match\n\n        no_valid_parents_defined = all(child._valid_parents == [] for child in children)\n        if (\n            not self._invalid_children\n            and not self._valid_children\n            and no_valid_parents_defined\n        ):\n            return\n\n        comp_name = type(self).__name__\n        allowed_components = [\n            comp.__name__ for comp in (Fragment, Foreach, Cond, Match)\n        ]\n\n        def validate_child(child: Any):\n            child_name = type(child).__name__\n\n            # Iterate through the immediate children of fragment\n            if isinstance(child, Fragment):\n                for c in child.children:\n                    validate_child(c)\n\n            if isinstance(child, Cond):\n                validate_child(child.children[0])\n                validate_child(child.children[1])\n\n            if isinstance(child, Match):\n                for cases in child.match_cases:\n                    validate_child(cases[-1])\n                validate_child(child.default)\n\n            if self._invalid_children and child_name in self._invalid_children:\n                msg = f\"The component `{comp_name}` cannot have `{child_name}` as a child component\"\n                raise ValueError(msg)\n\n            if self._valid_children and child_name not in [\n                *self._valid_children,\n                *allowed_components,\n            ]:\n                valid_child_list = \", \".join([\n                    f\"`{v_child}`\" for v_child in self._valid_children\n                ])\n                msg = f\"The component `{comp_name}` only allows the components: {valid_child_list} as children. Got `{child_name}` instead.\"\n                raise ValueError(msg)\n\n            if child._valid_parents and all(\n                clz_name not in [*child._valid_parents, *allowed_components]\n                for clz_name in self._iter_parent_classes_names()\n            ):\n                valid_parent_list = \", \".join([\n                    f\"`{v_parent}`\" for v_parent in child._valid_parents\n                ])\n                msg = f\"The component `{child_name}` can only be a child of the components: {valid_parent_list}. Got `{comp_name}` instead.\"\n                raise ValueError(msg)\n\n        for child in children:\n            validate_child(child)\n\n    @staticmethod\n    def _get_vars_from_event_triggers(\n        event_triggers: dict[str, EventChain | Var],\n    ) -> Iterator[tuple[str, list[Var]]]:\n        \"\"\"Get the Vars associated with each event trigger.\n\n        Args:\n            event_triggers: The event triggers from the component instance.\n\n        Yields:\n            tuple of (event_name, event_vars)\n        \"\"\"\n        for event_trigger, event in event_triggers.items():\n            if isinstance(event, Var):\n                yield event_trigger, [event]\n            elif isinstance(event, EventChain):\n                event_args = []\n                for spec in event.events:\n                    if isinstance(spec, EventSpec):\n                        for args in spec.args:\n                            event_args.extend(args)\n                    else:\n                        event_args.append(spec)\n                yield event_trigger, event_args\n\n    def _get_vars(\n        self, include_children: bool = False, ignore_ids: set[int] | None = None\n    ) -> Iterator[Var]:\n        \"\"\"Walk all Vars used in this component.\n\n        Args:\n            include_children: Whether to include Vars from children.\n            ignore_ids: The ids to ignore.\n\n        Yields:\n            Each var referenced by the component (props, styles, event handlers).\n        \"\"\"\n        ignore_ids = ignore_ids or set()\n        vars: list[Var] | None = getattr(self, \"__vars\", None)\n        if vars is not None:\n            yield from vars\n        vars = self.__vars = []\n        # Get Vars associated with event trigger arguments.\n        for _, event_vars in self._get_vars_from_event_triggers(self.event_triggers):\n            vars.extend(event_vars)\n\n        # Get Vars associated with component props.\n        for prop in self.get_props():\n            prop_var = getattr(self, prop)\n            if isinstance(prop_var, Var):\n                vars.append(prop_var)\n\n        # Style keeps track of its own VarData instance, so embed in a temp Var that is yielded.\n        if (isinstance(self.style, dict) and self.style) or isinstance(self.style, Var):\n            vars.append(\n                Var(\n                    _js_expr=\"style\",\n                    _var_type=str,\n                    _var_data=VarData.merge(self.style._var_data),\n                )\n            )\n\n        # Special props are always Var instances.\n        vars.extend(self.special_props)\n\n        # Get Vars associated with common Component props.\n        for comp_prop in (\n            self.class_name,\n            self.id,\n            self.key,\n            *self.custom_attrs.values(),\n        ):\n            if isinstance(comp_prop, Var):\n                vars.append(comp_prop)\n            elif isinstance(comp_prop, str):\n                # Collapse VarData encoded in f-strings.\n                var = LiteralStringVar.create(comp_prop)\n                if var._get_all_var_data() is not None:\n                    vars.append(var)\n\n        # Get Vars associated with children.\n        if include_children:\n            for child in self.children:\n                if not isinstance(child, Component) or id(child) in ignore_ids:\n                    continue\n                ignore_ids.add(id(child))\n                child_vars = child._get_vars(\n                    include_children=include_children, ignore_ids=ignore_ids\n                )\n                vars.extend(child_vars)\n\n        yield from vars\n\n    def _event_trigger_values_use_state(self) -> bool:\n        \"\"\"Check if the values of a component's event trigger use state.\n\n        Returns:\n            True if any of the component's event trigger values uses State.\n        \"\"\"\n        for trigger in self.event_triggers.values():\n            if isinstance(trigger, EventChain):\n                for event in trigger.events:\n                    if isinstance(event, EventCallback):\n                        continue\n                    if isinstance(event, EventSpec):\n                        if (\n                            event.handler.state_full_name\n                            and event.handler.state_full_name != FRONTEND_EVENT_STATE\n                        ):\n                            return True\n                    else:\n                        if event._var_state:\n                            return True\n            elif isinstance(trigger, Var) and trigger._var_state:\n                return True\n        return False\n\n    def _has_stateful_event_triggers(self):\n        \"\"\"Check if component or children have any event triggers that use state.\n\n        Returns:\n            True if the component or children have any event triggers that uses state.\n        \"\"\"\n        if self.event_triggers and self._event_trigger_values_use_state():\n            return True\n        for child in self.children:\n            if isinstance(child, Component) and child._has_stateful_event_triggers():\n                return True\n        return False\n\n    @classmethod\n    def _iter_parent_classes_names(cls) -> Iterator[str]:\n        for clz in cls.mro():\n            if clz is Component:\n                break\n            yield clz.__name__\n\n    @classmethod\n    def _iter_parent_classes_with_method(cls, method: str) -> Sequence[type[Component]]:\n        \"\"\"Iterate through parent classes that define a given method.\n\n        Used for handling the `add_*` API functions that internally simulate a super() call chain.\n\n        Args:\n            method: The method to look for.\n\n        Returns:\n            A sequence of parent classes that define the method (differently than the base).\n        \"\"\"\n        current_class_method = getattr(Component, method, None)\n        seen_methods = (\n            {current_class_method} if current_class_method is not None else set()\n        )\n        clzs: list[type[Component]] = []\n        for clz in cls.mro():\n            if clz is Component:\n                break\n            if not issubclass(clz, Component):\n                continue\n            method_func = getattr(clz, method, None)\n            if not callable(method_func) or method_func in seen_methods:\n                continue\n            seen_methods.add(method_func)\n            clzs.append(clz)\n        return clzs\n\n    def _get_custom_code(self) -> str | None:\n        \"\"\"Get custom code for the component.\n\n        Returns:\n            The custom code.\n        \"\"\"\n        return None\n\n    def _get_all_custom_code(self) -> dict[str, None]:\n        \"\"\"Get custom code for the component and its children.\n\n        Returns:\n            The custom code.\n        \"\"\"\n        # Store the code in a set to avoid duplicates.\n        code: dict[str, None] = {}\n\n        # Add the custom code for this component.\n        custom_code = self._get_custom_code()\n        if custom_code is not None:\n            code[custom_code] = None\n\n        for component in self._get_components_in_props():\n            code |= component._get_all_custom_code()\n\n        # Add the custom code from add_custom_code method.\n        for clz in self._iter_parent_classes_with_method(\"add_custom_code\"):\n            for item in clz.add_custom_code(self):\n                code[item] = None\n\n        # Add the custom code for the children.\n        for child in self.children:\n            code |= child._get_all_custom_code()\n\n        # Return the code.\n        return code\n\n    def _get_dynamic_imports(self) -> str | None:\n        \"\"\"Get dynamic import for the component.\n\n        Returns:\n            The dynamic import.\n        \"\"\"\n        return None\n\n    def _get_all_dynamic_imports(self) -> set[str]:\n        \"\"\"Get dynamic imports for the component and its children.\n\n        Returns:\n            The dynamic imports.\n        \"\"\"\n        # Store the import in a set to avoid duplicates.\n        dynamic_imports: set[str] = set()\n\n        # Get dynamic import for this component.\n        dynamic_import = self._get_dynamic_imports()\n        if dynamic_import:\n            dynamic_imports.add(dynamic_import)\n\n        # Get the dynamic imports from children\n        for child in self.children:\n            dynamic_imports |= child._get_all_dynamic_imports()\n\n        for component in self._get_components_in_props():\n            dynamic_imports |= component._get_all_dynamic_imports()\n\n        # Return the dynamic imports\n        return dynamic_imports\n\n    def _get_dependencies_imports(self) -> ParsedImportDict:\n        \"\"\"Get the imports from lib_dependencies for installing.\n\n        Returns:\n            The dependencies imports of the component.\n        \"\"\"\n        return {\n            dep: [ImportVar(tag=None, render=False)] for dep in self.lib_dependencies\n        }\n\n    def _get_hooks_imports(self) -> ParsedImportDict:\n        \"\"\"Get the imports required by certain hooks.\n\n        Returns:\n            The imports required for all selected hooks.\n        \"\"\"\n        imports_ = {}\n\n        if self._get_ref_hook() is not None:\n            # Handle hooks needed for attaching react refs to DOM nodes.\n            imports_.setdefault(\"react\", set()).add(ImportVar(tag=\"useRef\"))\n            imports_.setdefault(f\"$/{Dirs.STATE_PATH}\", set()).add(\n                ImportVar(tag=\"refs\")\n            )\n\n        if self._get_mount_lifecycle_hook():\n            # Handle hooks for `on_mount` / `on_unmount`.\n            imports_.setdefault(\"react\", set()).add(ImportVar(tag=\"useEffect\"))\n\n        other_imports = []\n        user_hooks = self._get_hooks()\n        user_hooks_data = (\n            VarData.merge(user_hooks._get_all_var_data())\n            if user_hooks is not None and isinstance(user_hooks, Var)\n            else None\n        )\n        if user_hooks_data is not None:\n            other_imports.append(user_hooks_data.imports)\n        other_imports.extend(\n            hook_vardata.imports\n            for hook_vardata in self._get_added_hooks().values()\n            if hook_vardata is not None\n        )\n\n        return imports.merge_imports(imports_, *other_imports)\n\n    def _get_imports(self) -> ParsedImportDict:\n        \"\"\"Get all the libraries and fields that are used by the component.\n\n        Returns:\n            The imports needed by the component.\n        \"\"\"\n        imports_ = (\n            {self.library: [self.import_var]}\n            if self.library is not None and self.tag is not None\n            else {}\n        )\n\n        # Get static imports required for event processing.\n        event_imports = Imports.EVENTS if self.event_triggers else {}\n\n        # Collect imports from Vars used directly by this component.\n        var_imports = [\n            dict(var_data.imports)\n            for var in self._get_vars()\n            if (var_data := var._get_all_var_data()) is not None\n        ]\n\n        added_import_dicts: list[ParsedImportDict] = []\n        for clz in self._iter_parent_classes_with_method(\"add_imports\"):\n            list_of_import_dict = clz.add_imports(self)\n\n            if not isinstance(list_of_import_dict, list):\n                added_import_dicts.append(imports.parse_imports(list_of_import_dict))\n            else:\n                added_import_dicts.extend([\n                    imports.parse_imports(item) for item in list_of_import_dict\n                ])\n\n        return imports.merge_parsed_imports(\n            self._get_dependencies_imports(),\n            self._get_hooks_imports(),\n            imports_,\n            event_imports,\n            *var_imports,\n            *added_import_dicts,\n        )\n\n    def _get_all_imports(self, collapse: bool = False) -> ParsedImportDict:\n        \"\"\"Get all the libraries and fields that are used by the component and its children.\n\n        Args:\n            collapse: Whether to collapse the imports by removing duplicates.\n\n        Returns:\n            The import dict with the required imports.\n        \"\"\"\n        imports_ = imports.merge_parsed_imports(\n            self._get_imports(), *[child._get_all_imports() for child in self.children]\n        )\n        return imports.collapse_imports(imports_) if collapse else imports_\n\n    def _get_mount_lifecycle_hook(self) -> str | None:\n        \"\"\"Generate the component lifecycle hook.\n\n        Returns:\n            The useEffect hook for managing `on_mount` and `on_unmount` events.\n        \"\"\"\n        # pop on_mount and on_unmount from event_triggers since these are handled by\n        # hooks, not as actually props in the component\n        on_mount = self.event_triggers.get(EventTriggers.ON_MOUNT, None)\n        on_unmount = self.event_triggers.get(EventTriggers.ON_UNMOUNT, None)\n        if on_mount is not None:\n            on_mount = str(LiteralVar.create(on_mount)) + \"()\"\n        if on_unmount is not None:\n            on_unmount = str(LiteralVar.create(on_unmount)) + \"()\"\n        if on_mount is not None or on_unmount is not None:\n            return f\"\"\"\n                useEffect(() => {{\n                    {on_mount or \"\"}\n                    return () => {{\n                        {on_unmount or \"\"}\n                    }}\n                }}, []);\"\"\"\n        return None\n\n    def _get_ref_hook(self) -> Var | None:\n        \"\"\"Generate the ref hook for the component.\n\n        Returns:\n            The useRef hook for managing refs.\n        \"\"\"\n        ref = self.get_ref()\n        if ref is not None:\n            return Var(\n                f\"const {ref} = useRef(null); {Var(_js_expr=ref)._as_ref()!s} = {ref};\",\n                _var_data=VarData(position=Hooks.HookPosition.INTERNAL),\n            )\n        return None\n\n    def _get_vars_hooks(self) -> dict[str, VarData | None]:\n        \"\"\"Get the hooks required by vars referenced in this component.\n\n        Returns:\n            The hooks for the vars.\n        \"\"\"\n        vars_hooks = {}\n        for var in self._get_vars():\n            var_data = var._get_all_var_data()\n            if var_data is not None:\n                vars_hooks.update(\n                    var_data.hooks\n                    if isinstance(var_data.hooks, dict)\n                    else {\n                        k: VarData(position=Hooks.HookPosition.INTERNAL)\n                        for k in var_data.hooks\n                    }\n                )\n                for component in var_data.components:\n                    vars_hooks.update(component._get_all_hooks())\n        return vars_hooks\n\n    def _get_events_hooks(self) -> dict[str, VarData | None]:\n        \"\"\"Get the hooks required by events referenced in this component.\n\n        Returns:\n            The hooks for the events.\n        \"\"\"\n        return (\n            {Hooks.EVENTS: VarData(position=Hooks.HookPosition.INTERNAL)}\n            if self.event_triggers\n            else {}\n        )\n\n    def _get_hooks_internal(self) -> dict[str, VarData | None]:\n        \"\"\"Get the React hooks for this component managed by the framework.\n\n        Downstream components should NOT override this method to avoid breaking\n        framework functionality.\n\n        Returns:\n            The internally managed hooks.\n        \"\"\"\n        return {\n            **{\n                str(hook): VarData(position=Hooks.HookPosition.INTERNAL)\n                for hook in [self._get_ref_hook(), self._get_mount_lifecycle_hook()]\n                if hook is not None\n            },\n            **self._get_vars_hooks(),\n            **self._get_events_hooks(),\n        }\n\n    def _get_added_hooks(self) -> dict[str, VarData | None]:\n        \"\"\"Get the hooks added via `add_hooks` method.\n\n        Returns:\n            The deduplicated hooks and imports added by the component and parent components.\n        \"\"\"\n        code = {}\n\n        def extract_var_hooks(hook: Var):\n            var_data = VarData.merge(hook._get_all_var_data())\n            if var_data is not None:\n                for sub_hook in var_data.hooks:\n                    code[sub_hook] = None\n\n            if str(hook) in code:\n                code[str(hook)] = VarData.merge(var_data, code[str(hook)])\n            else:\n                code[str(hook)] = var_data\n\n        # Add the hook code from add_hooks for each parent class (this is reversed to preserve\n        # the order of the hooks in the final output)\n        for clz in reversed(self._iter_parent_classes_with_method(\"add_hooks\")):\n            for hook in clz.add_hooks(self):\n                if isinstance(hook, Var):\n                    extract_var_hooks(hook)\n                else:\n                    code[hook] = None\n\n        return code\n\n    def _get_hooks(self) -> str | None:\n        \"\"\"Get the React hooks for this component.\n\n        Downstream components should override this method to add their own hooks.\n\n        Returns:\n            The hooks for just this component.\n        \"\"\"\n        return\n\n    def _get_all_hooks_internal(self) -> dict[str, VarData | None]:\n        \"\"\"Get the reflex internal hooks for the component and its children.\n\n        Returns:\n            The code that should appear just before user-defined hooks.\n        \"\"\"\n        # Store the code in a set to avoid duplicates.\n        code = self._get_hooks_internal()\n\n        # Add the hook code for the children.\n        for child in self.children:\n            code.update(child._get_all_hooks_internal())\n\n        return code\n\n    def _get_all_hooks(self) -> dict[str, VarData | None]:\n        \"\"\"Get the React hooks for this component and its children.\n\n        Returns:\n            The code that should appear just before returning the rendered component.\n        \"\"\"\n        code = {}\n\n        # Add the internal hooks for this component.\n        code.update(self._get_hooks_internal())\n\n        # Add the hook code for this component.\n        hooks = self._get_hooks()\n        if hooks is not None:\n            code[hooks] = None\n\n        code.update(self._get_added_hooks())\n\n        # Add the hook code for the children.\n        for child in self.children:\n            code.update(child._get_all_hooks())\n\n        return code\n\n    def get_ref(self) -> str | None:\n        \"\"\"Get the name of the ref for the component.\n\n        Returns:\n            The ref name.\n        \"\"\"\n        # do not create a ref if the id is dynamic or unspecified\n        if self.id is None or isinstance(self.id, Var):\n            return None\n        return format.format_ref(self.id)\n\n    def _get_all_refs(self) -> dict[str, None]:\n        \"\"\"Get the refs for the children of the component.\n\n        Returns:\n            The refs for the children.\n        \"\"\"\n        refs = {}\n        ref = self.get_ref()\n        if ref is not None:\n            refs[ref] = None\n        for child in self.children:\n            refs |= child._get_all_refs()\n        for component in self._get_components_in_props():\n            refs |= component._get_all_refs()\n\n        return refs\n\n    @property\n    def import_var(self):\n        \"\"\"The tag to import.\n\n        Returns:\n            An import var.\n        \"\"\"\n        # If the tag is dot-qualified, only import the left-most name.\n        tag = self.tag.partition(\".\")[0] if self.tag else None\n        alias = self.alias.partition(\".\")[0] if self.alias else None\n        return ImportVar(tag=tag, is_default=self.is_default, alias=alias)\n\n    @staticmethod\n    def _get_app_wrap_components() -> dict[tuple[int, str], Component]:\n        \"\"\"Get the app wrap components for the component.\n\n        Returns:\n            The app wrap components.\n        \"\"\"\n        return {}\n\n    def _get_all_app_wrap_components(\n        self, *, ignore_ids: set[int] | None = None\n    ) -> dict[tuple[int, str], Component]:\n        \"\"\"Get the app wrap components for the component and its children.\n\n        Args:\n            ignore_ids: A set of component IDs to ignore. Used to avoid duplicates.\n\n        Returns:\n            The app wrap components.\n        \"\"\"\n        ignore_ids = ignore_ids or set()\n        # Store the components in a set to avoid duplicates.\n        components = self._get_app_wrap_components()\n\n        for component in tuple(components.values()):\n            component_id = id(component)\n            if component_id in ignore_ids:\n                continue\n            ignore_ids.add(component_id)\n            components.update(\n                component._get_all_app_wrap_components(ignore_ids=ignore_ids)\n            )\n\n        # Add the app wrap components for the children.\n        for child in self.children:\n            child_id = id(child)\n            # Skip BaseComponent and StatefulComponent children.\n            if not isinstance(child, Component) or child_id in ignore_ids:\n                continue\n            ignore_ids.add(child_id)\n            components.update(child._get_all_app_wrap_components(ignore_ids=ignore_ids))\n\n        # Return the components.\n        return components\n\n\nclass CustomComponent(Component):\n    \"\"\"A custom user-defined component.\"\"\"\n\n    # Use the components library.\n    library = f\"$/{Dirs.COMPONENTS_PATH}\"\n\n    # The function that creates the component.\n    component_fn: Callable[..., Component] = field(default=Component.create)\n\n    # The props of the component.\n    props: dict[str, Any] = field(default_factory=dict)\n\n    def _post_init(self, **kwargs):\n        \"\"\"Initialize the custom component.\n\n        Args:\n            **kwargs: The kwargs to pass to the component.\n        \"\"\"\n        component_fn = kwargs.get(\"component_fn\")\n\n        # Set the props.\n        props_types = typing.get_type_hints(component_fn) if component_fn else {}\n        props = {key: value for key, value in kwargs.items() if key in props_types}\n        kwargs = {key: value for key, value in kwargs.items() if key not in props_types}\n\n        event_types = {\n            key\n            for key in props\n            if (\n                (get_origin((annotation := props_types.get(key))) or annotation)\n                == EventHandler\n            )\n        }\n\n        def get_args_spec(key: str) -> types.ArgsSpec | Sequence[types.ArgsSpec]:\n            type_ = props_types[key]\n\n            return (\n                args[0]\n                if (args := get_args(type_))\n                else (\n                    annotation_args[1]\n                    if get_origin(\n                        annotation := inspect.getfullargspec(component_fn).annotations[\n                            key\n                        ]\n                    )\n                    is typing.Annotated\n                    and (annotation_args := get_args(annotation))\n                    else no_args_event_spec\n                )\n            )\n\n        super()._post_init(\n            event_triggers={\n                key: EventChain.create(\n                    value=props[key],\n                    args_spec=get_args_spec(key),\n                    key=key,\n                )\n                for key in event_types\n            },\n            **kwargs,\n        )\n\n        to_camel_cased_props = {\n            format.to_camel_case(key): None for key in props if key not in event_types\n        }\n        self.get_props = lambda: to_camel_cased_props  # pyright: ignore [reportIncompatibleVariableOverride]\n\n        # Unset the style.\n        self.style = Style()\n\n        # Set the tag to the name of the function.\n        self.tag = format.to_title_case(self.component_fn.__name__)\n\n        for key, value in props.items():\n            # Skip kwargs that are not props.\n            if key not in props_types:\n                continue\n\n            camel_cased_key = format.to_camel_case(key)\n\n            # Get the type based on the annotation.\n            type_ = props_types[key]\n\n            # Handle event chains.\n            if type_ is EventHandler:\n                inspect.getfullargspec(component_fn).annotations[key]\n                self.props[camel_cased_key] = EventChain.create(\n                    value=value, args_spec=get_args_spec(key), key=key\n                )\n                continue\n\n            value = LiteralVar.create(value)\n            self.props[camel_cased_key] = value\n            setattr(self, camel_cased_key, value)\n\n    def __eq__(self, other: Any) -> bool:\n        \"\"\"Check if the component is equal to another.\n\n        Args:\n            other: The other component.\n\n        Returns:\n            Whether the component is equal to the other.\n        \"\"\"\n        return isinstance(other, CustomComponent) and self.tag == other.tag\n\n    def __hash__(self) -> int:\n        \"\"\"Get the hash of the component.\n\n        Returns:\n            The hash of the component.\n        \"\"\"\n        return hash(self.tag)\n\n    @classmethod\n    def get_props(cls) -> Iterable[str]:\n        \"\"\"Get the props for the component.\n\n        Returns:\n            The set of component props.\n        \"\"\"\n        return ()\n\n    @staticmethod\n    def _get_event_spec_from_args_spec(name: str, event: EventChain) -> Callable:\n        \"\"\"Get the event spec from the args spec.\n\n        Args:\n            name: The name of the event\n            event: The args spec.\n\n        Returns:\n            The event spec.\n        \"\"\"\n\n        def fn(*args):\n            return run_script(Var(name).to(FunctionVar).call(*args))\n\n        if event.args_spec:\n            arg_spec = (\n                event.args_spec\n                if not isinstance(event.args_spec, Sequence)\n                else event.args_spec[0]\n            )\n            names = inspect.getfullargspec(arg_spec).args\n            fn.__signature__ = inspect.Signature(  # pyright: ignore[reportFunctionMemberAccess]\n                parameters=[\n                    inspect.Parameter(\n                        name=name,\n                        kind=inspect.Parameter.POSITIONAL_ONLY,\n                        annotation=arg._var_type,\n                    )\n                    for name, arg in zip(\n                        names, parse_args_spec(event.args_spec)[0], strict=True\n                    )\n                ]\n            )\n\n        return fn\n\n    def get_prop_vars(self) -> list[Var | Callable]:\n        \"\"\"Get the prop vars.\n\n        Returns:\n            The prop vars.\n        \"\"\"\n        return [\n            Var(\n                _js_expr=name + CAMEL_CASE_MEMO_MARKER,\n                _var_type=(prop._var_type if isinstance(prop, Var) else type(prop)),\n            ).guess_type()\n            if isinstance(prop, Var) or not isinstance(prop, EventChain)\n            else CustomComponent._get_event_spec_from_args_spec(\n                name + CAMEL_CASE_MEMO_MARKER, prop\n            )\n            for name, prop in self.props.items()\n        ]\n\n    @functools.cache  # noqa: B019\n    def get_component(self) -> Component:\n        \"\"\"Render the component.\n\n        Returns:\n            The code to render the component.\n        \"\"\"\n        component = self.component_fn(*self.get_prop_vars())\n\n        try:\n            from reflex.utils.prerequisites import get_and_validate_app\n\n            style = get_and_validate_app().app.style\n        except Exception:\n            style = {}\n\n        component._add_style_recursive(style)\n        return component\n\n    def _get_all_app_wrap_components(\n        self, *, ignore_ids: set[int] | None = None\n    ) -> dict[tuple[int, str], Component]:\n        \"\"\"Get the app wrap components for the custom component.\n\n        Args:\n            ignore_ids: A set of IDs to ignore to avoid infinite recursion.\n\n        Returns:\n            The app wrap components.\n        \"\"\"\n        ignore_ids = ignore_ids or set()\n        component = self.get_component()\n        if id(component) in ignore_ids:\n            return {}\n        ignore_ids.add(id(component))\n        return self.get_component()._get_all_app_wrap_components(ignore_ids=ignore_ids)\n\n\nCUSTOM_COMPONENTS: dict[str, CustomComponent] = {}\n\n\ndef _register_custom_component(\n    component_fn: Callable[..., Component],\n):\n    \"\"\"Register a custom component to be compiled.\n\n    Args:\n        component_fn: The function that creates the component.\n\n    Returns:\n        The custom component.\n\n    Raises:\n        TypeError: If the tag name cannot be determined.\n    \"\"\"\n    dummy_props = {\n        prop: (\n            Var(\n                \"\",\n                _var_type=unwrap_var_annotation(annotation),\n            ).guess_type()\n            if not types.safe_issubclass(annotation, EventHandler)\n            else EventSpec(handler=EventHandler(fn=no_args_event_spec))\n        )\n        for prop, annotation in typing.get_type_hints(component_fn).items()\n        if prop != \"return\"\n    }\n    dummy_component = CustomComponent._create(\n        children=[],\n        component_fn=component_fn,\n        **dummy_props,\n    )\n    if dummy_component.tag is None:\n        msg = f\"Could not determine the tag name for {component_fn!r}\"\n        raise TypeError(msg)\n    CUSTOM_COMPONENTS[dummy_component.tag] = dummy_component\n    return dummy_component\n\n\ndef custom_component(\n    component_fn: Callable[..., Component],\n) -> Callable[..., CustomComponent]:\n    \"\"\"Create a custom component from a function.\n\n    Args:\n        component_fn: The function that creates the component.\n\n    Returns:\n        The decorated function.\n    \"\"\"\n\n    @wraps(component_fn)\n    def wrapper(*children, **props) -> CustomComponent:\n        # Remove the children from the props.\n        props.pop(\"children\", None)\n        return CustomComponent._create(\n            children=list(children), component_fn=component_fn, **props\n        )\n\n    # Register this component so it can be compiled.\n    dummy_component = _register_custom_component(component_fn)\n    if tag := dummy_component.tag:\n        object.__setattr__(\n            wrapper,\n            \"_as_var\",\n            lambda: Var(\n                tag,\n                _var_type=type[Component],\n                _var_data=VarData(\n                    imports={\n                        f\"$/{constants.Dirs.UTILS}/components\": [ImportVar(tag=tag)],\n                        \"@emotion/react\": [\n                            ImportVar(tag=\"jsx\"),\n                        ],\n                    }\n                ),\n            ),\n        )\n\n    return wrapper\n\n\n# Alias memo to custom_component.\nmemo = custom_component\n\n\nclass NoSSRComponent(Component):\n    \"\"\"A dynamic component that is not rendered on the server.\"\"\"\n\n    def _get_import_name(self) -> str | None:\n        if not self.library:\n            return None\n        return f\"${self.library}\" if self.library.startswith(\"/\") else self.library\n\n    def _get_imports(self) -> ParsedImportDict:\n        \"\"\"Get the imports for the component.\n\n        Returns:\n            The imports for dynamically importing the component at module load time.\n        \"\"\"\n        # React lazy import mechanism.\n        dynamic_import = {\n            f\"$/{constants.Dirs.UTILS}/context\": [ImportVar(tag=\"ClientSide\")],\n        }\n\n        # The normal imports for this component.\n        imports_ = super()._get_imports()\n\n        # Do NOT import the main library/tag statically.\n        import_name = self._get_import_name()\n        if import_name is not None:\n            with contextlib.suppress(ValueError):\n                imports_[import_name].remove(self.import_var)\n            imports_[import_name].append(ImportVar(tag=None, render=False))\n\n        return imports.merge_imports(\n            dynamic_import,\n            imports_,\n            self._get_dependencies_imports(),\n        )\n\n    def _get_dynamic_imports(self) -> str:\n        # extract the correct import name from library name\n        base_import_name = self._get_import_name()\n        if base_import_name is None:\n            msg = \"Undefined library for NoSSRComponent\"\n            raise ValueError(msg)\n        import_name = format.format_library_name(base_import_name)\n\n        library_import = f\"import('{import_name}')\"\n        mod_import = (\n            # https://nextjs.org/docs/pages/building-your-application/optimizing/lazy-loading#with-named-exports\n            f\".then((mod) => mod.{self.tag})\"\n            if not self.is_default\n            else \".then((mod) => mod.default.default ?? mod.default)\"\n        )\n        return (\n            f\"const {self.alias or self.tag} = ClientSide(() => \"\n            + library_import\n            + mod_import\n            + \")\"\n        )\n\n\nclass StatefulComponent(BaseComponent):\n    \"\"\"A component that depends on state and is rendered outside of the page component.\n\n    If a StatefulComponent is used in multiple pages, it will be rendered to a common file and\n    imported into each page that uses it.\n\n    A stateful component has a tag name that includes a hash of the code that it renders\n    to. This tag name refers to the specific component with the specific props that it\n    was created with.\n    \"\"\"\n\n    # A lookup table to caching memoized component instances.\n    tag_to_stateful_component: ClassVar[dict[str, StatefulComponent]] = {}\n\n    # Reference to the original component that was memoized into this component.\n    component: Component = field(\n        default_factory=Component, is_javascript_property=False\n    )\n\n    # How many times this component is referenced in the app.\n    references: int = field(default=0, is_javascript_property=False)\n\n    # Whether the component has already been rendered to a shared file.\n    rendered_as_shared: bool = field(default=False, is_javascript_property=False)\n\n    memo_trigger_hooks: list[str] = field(\n        default_factory=list, is_javascript_property=False\n    )\n\n    @classmethod\n    def create(cls, component: Component) -> StatefulComponent | None:\n        \"\"\"Create a stateful component from a component.\n\n        Args:\n            component: The component to memoize.\n\n        Returns:\n            The stateful component or None if the component should not be memoized.\n        \"\"\"\n        from reflex.components.core.foreach import Foreach\n\n        if component._memoization_mode.disposition == MemoizationDisposition.NEVER:\n            # Never memoize this component.\n            return None\n\n        if component.tag is None:\n            # Only memoize components with a tag.\n            return None\n\n        # If _var_data is found in this component, it is a candidate for auto-memoization.\n        should_memoize = False\n\n        # If the component requests to be memoized, then ignore other checks.\n        if component._memoization_mode.disposition == MemoizationDisposition.ALWAYS:\n            should_memoize = True\n\n        if not should_memoize:\n            # Determine if any Vars have associated data.\n            for prop_var in component._get_vars(include_children=True):\n                if prop_var._get_all_var_data():\n                    should_memoize = True\n                    break\n\n        if not should_memoize:\n            # Check for special-cases in child components.\n            for child in component.children:\n                # Skip BaseComponent and StatefulComponent children.\n                if not isinstance(child, Component):\n                    continue\n                # Always consider Foreach something that must be memoized by the parent.\n                if isinstance(child, Foreach):\n                    should_memoize = True\n                    break\n                child = cls._child_var(child)\n                if isinstance(child, Var) and child._get_all_var_data():\n                    should_memoize = True\n                    break\n\n        if should_memoize or component.event_triggers:\n            # Render the component to determine tag+hash based on component code.\n            tag_name = cls._get_tag_name(component)\n            if tag_name is None:\n                return None\n\n            # Look up the tag in the cache\n            stateful_component = cls.tag_to_stateful_component.get(tag_name)\n            if stateful_component is None:\n                memo_trigger_hooks = cls._fix_event_triggers(component)\n                # Set the stateful component in the cache for the given tag.\n                stateful_component = cls.tag_to_stateful_component.setdefault(\n                    tag_name,\n                    cls(\n                        children=component.children,\n                        component=component,\n                        tag=tag_name,\n                        memo_trigger_hooks=memo_trigger_hooks,\n                    ),\n                )\n            # Bump the reference count -- multiple pages referencing the same component\n            # will result in writing it to a common file.\n            stateful_component.references += 1\n            return stateful_component\n\n        # Return None to indicate this component should not be memoized.\n        return None\n\n    @staticmethod\n    def _child_var(child: Component) -> Var | Component:\n        \"\"\"Get the Var from a child component.\n\n        This method is used for special cases when the StatefulComponent should actually\n        wrap the parent component of the child instead of recursing into the children\n        and memoizing them independently.\n\n        Args:\n            child: The child component.\n\n        Returns:\n            The Var from the child component or the child itself (for regular cases).\n        \"\"\"\n        from reflex.components.base.bare import Bare\n        from reflex.components.core.cond import Cond\n        from reflex.components.core.foreach import Foreach\n        from reflex.components.core.match import Match\n\n        if isinstance(child, Bare):\n            return child.contents\n        if isinstance(child, Cond):\n            return child.cond\n        if isinstance(child, Foreach):\n            return child.iterable\n        if isinstance(child, Match):\n            return child.cond\n        return child\n\n    @classmethod\n    def _get_tag_name(cls, component: Component) -> str | None:\n        \"\"\"Get the tag based on rendering the given component.\n\n        Args:\n            component: The component to render.\n\n        Returns:\n            The tag for the stateful component.\n        \"\"\"\n        # Get the render dict for the component.\n        rendered_code = component.render()\n        if not rendered_code:\n            # Never memoize non-visual components.\n            return None\n\n        # Compute the hash based on the rendered code.\n        code_hash = _hash_str(_deterministic_hash(rendered_code))\n\n        # Format the tag name including the hash.\n        return format.format_state_name(\n            f\"{component.tag or 'Comp'}_{code_hash}\"\n        ).capitalize()\n\n    def _render_stateful_code(\n        self,\n        export: bool = False,\n    ) -> str:\n        if not self.tag:\n            return \"\"\n        # Render the code for this component and hooks.\n        return stateful_component_template(\n            tag_name=self.tag,\n            memo_trigger_hooks=self.memo_trigger_hooks,\n            component=self.component,\n            export=export,\n        )\n\n    @classmethod\n    def _fix_event_triggers(\n        cls,\n        component: Component,\n    ) -> list[str]:\n        \"\"\"Render the code for a stateful component.\n\n        Args:\n            component: The component to render.\n\n        Returns:\n            The memoized event trigger hooks for the component.\n        \"\"\"\n        # Memoize event triggers useCallback to avoid unnecessary re-renders.\n        memo_event_triggers = tuple(cls._get_memoized_event_triggers(component).items())\n\n        # Trigger hooks stored separately to write after the normal hooks (see stateful_component.js.jinja2)\n        memo_trigger_hooks: list[str] = []\n\n        if memo_event_triggers:\n            # Copy the component to avoid mutating the original.\n            component = copy.copy(component)\n\n            for event_trigger, (\n                memo_trigger,\n                memo_trigger_hook,\n            ) in memo_event_triggers:\n                # Replace the event trigger with the memoized version.\n                memo_trigger_hooks.append(memo_trigger_hook)\n                component.event_triggers[event_trigger] = memo_trigger\n\n        return memo_trigger_hooks\n\n    @staticmethod\n    def _get_hook_deps(hook: str) -> list[str]:\n        \"\"\"Extract var deps from a hook.\n\n        Args:\n            hook: The hook line to extract deps from.\n\n        Returns:\n            A list of var names created by the hook declaration.\n        \"\"\"\n        # Ensure that the hook is a var declaration.\n        var_decl = hook.partition(\"=\")[0].strip()\n        if not any(var_decl.startswith(kw) for kw in [\"const \", \"let \", \"var \"]):\n            return []\n\n        # Extract the var name from the declaration.\n        _, _, var_name = var_decl.partition(\" \")\n        var_name = var_name.strip()\n\n        # Break up array and object destructuring if used.\n        if var_name.startswith((\"[\", \"{\")):\n            return [\n                v.strip().replace(\"...\", \"\") for v in var_name.strip(\"[]{}\").split(\",\")\n            ]\n        return [var_name]\n\n    @staticmethod\n    def _get_deps_from_event_trigger(\n        event: EventChain | EventSpec | Var,\n    ) -> dict[str, None]:\n        \"\"\"Get the dependencies accessed by event triggers.\n\n        Args:\n            event: The event trigger to extract deps from.\n\n        Returns:\n            The dependencies accessed by the event triggers.\n        \"\"\"\n        events: list = [event]\n        deps = {}\n\n        if isinstance(event, EventChain):\n            events.extend(event.events)\n\n        for ev in events:\n            if isinstance(ev, EventSpec):\n                for arg in ev.args:\n                    for a in arg:\n                        var_datas = VarData.merge(a._get_all_var_data())\n                        if var_datas and var_datas.deps is not None:\n                            deps |= {str(dep): None for dep in var_datas.deps}\n        return deps\n\n    @classmethod\n    def _get_memoized_event_triggers(\n        cls,\n        component: Component,\n    ) -> dict[str, tuple[Var, str]]:\n        \"\"\"Memoize event handler functions with useCallback to avoid unnecessary re-renders.\n\n        Args:\n            component: The component with events to memoize.\n\n        Returns:\n            A dict of event trigger name to a tuple of the memoized event trigger Var and\n            the hook code that memoizes the event handler.\n        \"\"\"\n        trigger_memo = {}\n        for event_trigger, event_args in component._get_vars_from_event_triggers(\n            component.event_triggers\n        ):\n            if event_trigger in {\n                EventTriggers.ON_MOUNT,\n                EventTriggers.ON_UNMOUNT,\n                EventTriggers.ON_SUBMIT,\n            }:\n                # Do not memoize lifecycle or submit events.\n                continue\n\n            # Get the actual EventSpec and render it.\n            event = component.event_triggers[event_trigger]\n            rendered_chain = str(LiteralVar.create(event))\n\n            # Hash the rendered EventChain to get a deterministic function name.\n            chain_hash = md5(str(rendered_chain).encode(\"utf-8\")).hexdigest()\n            memo_name = f\"{event_trigger}_{chain_hash}\"\n\n            # Calculate Var dependencies accessed by the handler for useCallback dep array.\n            var_deps = [\"addEvents\", \"ReflexEvent\"]\n\n            # Get deps from event trigger var data.\n            var_deps.extend(cls._get_deps_from_event_trigger(event))\n\n            # Get deps from hooks.\n            for arg in event_args:\n                var_data = arg._get_all_var_data()\n                if var_data is None:\n                    continue\n                for hook in var_data.hooks:\n                    var_deps.extend(cls._get_hook_deps(hook))\n            memo_var_data = VarData.merge(\n                *[var._get_all_var_data() for var in event_args],\n                VarData(\n                    imports={\"react\": [ImportVar(tag=\"useCallback\")]},\n                ),\n            )\n\n            # Store the memoized function name and hook code for this event trigger.\n            trigger_memo[event_trigger] = (\n                Var(_js_expr=memo_name)._replace(\n                    _var_type=EventChain, merge_var_data=memo_var_data\n                ),\n                f\"const {memo_name} = useCallback({rendered_chain}, [{', '.join(var_deps)}])\",\n            )\n        return trigger_memo\n\n    def _get_all_hooks_internal(self) -> dict[str, VarData | None]:\n        \"\"\"Get the reflex internal hooks for the component and its children.\n\n        Returns:\n            The code that should appear just before user-defined hooks.\n        \"\"\"\n        return {}\n\n    def _get_all_hooks(self) -> dict[str, VarData | None]:\n        \"\"\"Get the React hooks for this component.\n\n        Returns:\n            The code that should appear just before returning the rendered component.\n        \"\"\"\n        return {}\n\n    def _get_all_imports(self) -> ParsedImportDict:\n        \"\"\"Get all the libraries and fields that are used by the component.\n\n        Returns:\n            The import dict with the required imports.\n        \"\"\"\n        if self.rendered_as_shared:\n            return {\n                f\"$/{Dirs.UTILS}/{PageNames.STATEFUL_COMPONENTS}\": [\n                    ImportVar(tag=self.tag)\n                ]\n            }\n        return self.component._get_all_imports()\n\n    def _get_all_dynamic_imports(self) -> set[str]:\n        \"\"\"Get dynamic imports for the component.\n\n        Returns:\n            The dynamic imports.\n        \"\"\"\n        if self.rendered_as_shared:\n            return set()\n        return self.component._get_all_dynamic_imports()\n\n    def _get_all_custom_code(self, export: bool = False) -> dict[str, None]:\n        \"\"\"Get custom code for the component.\n\n        Args:\n            export: Whether to export the component.\n\n        Returns:\n            The custom code.\n        \"\"\"\n        if self.rendered_as_shared:\n            return {}\n        return self.component._get_all_custom_code() | ({\n            self._render_stateful_code(export=export): None\n        })\n\n    def _get_all_refs(self) -> dict[str, None]:\n        \"\"\"Get the refs for the children of the component.\n\n        Returns:\n            The refs for the children.\n        \"\"\"\n        if self.rendered_as_shared:\n            return {}\n        return self.component._get_all_refs()\n\n    def render(self) -> dict:\n        \"\"\"Define how to render the component in React.\n\n        Returns:\n            The tag to render.\n        \"\"\"\n        return dict(Tag(name=self.tag or \"\"))\n\n    def __str__(self) -> str:\n        \"\"\"Represent the component in React.\n\n        Returns:\n            The code to render the component.\n        \"\"\"\n        from reflex.compiler.compiler import _compile_component\n\n        return _compile_component(self)\n\n    @classmethod\n    def compile_from(cls, component: BaseComponent) -> BaseComponent:\n        \"\"\"Walk through the component tree and memoize all stateful components.\n\n        Args:\n            component: The component to memoize.\n\n        Returns:\n            The memoized component tree.\n        \"\"\"\n        if isinstance(component, Component):\n            if component._memoization_mode.recursive:\n                # Recursively memoize stateful children (default).\n                component.children = [\n                    cls.compile_from(child) for child in component.children\n                ]\n            # Memoize this component if it depends on state.\n            stateful_component = cls.create(component)\n            if stateful_component is not None:\n                return stateful_component\n        return component\n\n\nclass MemoizationLeaf(Component):\n    \"\"\"A component that does not separately memoize its children.\n\n    Any component which depends on finding the exact names of children\n    components within it, should be a memoization leaf so the compiler\n    does not replace the provided child tags with memoized tags.\n\n    During creation, a memoization leaf will mark itself as wanting to be\n    memoized if any of its children return any hooks.\n    \"\"\"\n\n    _memoization_mode = MemoizationMode(recursive=False)\n\n    @classmethod\n    def create(cls, *children, **props) -> Component:\n        \"\"\"Create a new memoization leaf component.\n\n        Args:\n            *children: The children of the component.\n            **props: The props of the component.\n\n        Returns:\n            The memoization leaf\n        \"\"\"\n        comp = super().create(*children, **props)\n        if comp._get_all_hooks():\n            comp._memoization_mode = dataclasses.replace(\n                comp._memoization_mode, disposition=MemoizationDisposition.ALWAYS\n            )\n        return comp\n\n\nload_dynamic_serializer()\n\n\nclass ComponentVar(Var[Component], python_types=BaseComponent):\n    \"\"\"A Var that represents a Component.\"\"\"\n\n\ndef empty_component() -> Component:\n    \"\"\"Create an empty component.\n\n    Returns:\n        An empty component.\n    \"\"\"\n    from reflex.components.base.bare import Bare\n\n    return Bare.create(\"\")\n\n\ndef render_dict_to_var(tag: dict | Component | str) -> Var:\n    \"\"\"Convert a render dict to a Var.\n\n    Args:\n        tag: The render dict.\n\n    Returns:\n        The Var.\n    \"\"\"\n    if not isinstance(tag, dict):\n        if isinstance(tag, Component):\n            return render_dict_to_var(tag.render())\n        return Var.create(tag)\n\n    if \"contents\" in tag:\n        return Var(tag[\"contents\"])\n\n    if \"iterable\" in tag:\n        function_return = LiteralArrayVar.create([\n            render_dict_to_var(child.render()) for child in tag[\"children\"]\n        ])\n\n        func = ArgsFunctionOperation.create(\n            (tag[\"arg_var_name\"], tag[\"index_var_name\"]),\n            function_return,\n        )\n\n        return FunctionStringVar.create(\"Array.prototype.map.call\").call(\n            tag[\"iterable\"]\n            if not isinstance(tag[\"iterable\"], ObjectVar)\n            else tag[\"iterable\"].items(),\n            func,\n        )\n\n    if \"match_cases\" in tag:\n        element = Var(tag[\"cond\"])\n\n        conditionals = render_dict_to_var(tag[\"default\"])\n\n        for case in tag[\"match_cases\"][::-1]:\n            conditions, return_value = case\n            condition = Var.create(False)\n            for pattern in conditions:\n                condition = condition | (\n                    Var(pattern).to_string() == element.to_string()\n                )\n\n            conditionals = ternary_operation(\n                condition,\n                render_dict_to_var(return_value),\n                conditionals,\n            )\n\n        return conditionals\n\n    if \"cond_state\" in tag:\n        return ternary_operation(\n            Var(tag[\"cond_state\"]),\n            render_dict_to_var(tag[\"true_value\"]),\n            render_dict_to_var(tag[\"false_value\"])\n            if tag[\"false_value\"] is not None\n            else LiteralNoneVar.create(),\n        )\n\n    props = Var(\"({\" + \",\".join(tag[\"props\"]) + \"})\")\n\n    raw_tag_name = tag.get(\"name\")\n    tag_name = Var(raw_tag_name or \"Fragment\")\n\n    return FunctionStringVar.create(\n        \"jsx\",\n    ).call(\n        tag_name,\n        props,\n        *[render_dict_to_var(child) for child in tag[\"children\"]],\n    )\n\n\n@dataclasses.dataclass(\n    eq=False,\n    frozen=True,\n    slots=True,\n)\nclass LiteralComponentVar(CachedVarOperation, LiteralVar, ComponentVar):\n    \"\"\"A Var that represents a Component.\"\"\"\n\n    _var_value: BaseComponent = dataclasses.field(default_factory=empty_component)\n\n    @cached_property_no_lock\n    def _cached_var_name(self) -> str:\n        \"\"\"Get the name of the var.\n\n        Returns:\n            The name of the var.\n        \"\"\"\n        return str(render_dict_to_var(self._var_value.render()))\n\n    @cached_property_no_lock\n    def _cached_get_all_var_data(self) -> VarData | None:\n        \"\"\"Get the VarData for the var.\n\n        Returns:\n            The VarData for the var.\n        \"\"\"\n        return VarData.merge(\n            self._var_data,\n            VarData(\n                imports={\n                    \"@emotion/react\": [\"jsx\"],\n                    \"react\": [\"Fragment\"],\n                },\n            ),\n            VarData(\n                imports=self._var_value._get_all_imports(),\n            ),\n        )\n\n    def __hash__(self) -> int:\n        \"\"\"Get the hash of the var.\n\n        Returns:\n            The hash of the var.\n        \"\"\"\n        return hash((type(self).__name__, self._js_expr))\n\n    @classmethod\n    def create(\n        cls,\n        value: Component,\n        _var_data: VarData | None = None,\n    ):\n        \"\"\"Create a var from a value.\n\n        Args:\n            value: The value of the var.\n            _var_data: Additional hooks and imports associated with the Var.\n\n        Returns:\n            The var.\n        \"\"\"\n        var_datas = [\n            var_data\n            for var in value._get_vars(include_children=True)\n            if (var_data := var._get_all_var_data())\n        ]\n\n        return LiteralComponentVar(\n            _js_expr=\"\",\n            _var_type=type(value),\n            _var_data=VarData.merge(\n                _var_data,\n                *var_datas,\n                VarData(\n                    components=(value,),\n                ),\n            ),\n            _var_value=value,\n        )\n"
  },
  {
    "path": "reflex/components/core/__init__.py",
    "content": "\"\"\"Core Reflex components.\"\"\"\n\nfrom __future__ import annotations\n\nfrom reflex.utils import lazy_loader\n\n_SUBMODULES: set[str] = {\"layout\"}\n\n_SUBMOD_ATTRS: dict[str, list[str]] = {\n    \"banner\": [\n        \"ConnectionBanner\",\n        \"ConnectionModal\",\n        \"ConnectionPulser\",\n        \"ConnectionToaster\",\n        \"connection_banner\",\n        \"connection_modal\",\n        \"connection_toaster\",\n        \"connection_pulser\",\n    ],\n    \"clipboard\": [\"Clipboard\", \"clipboard\"],\n    \"colors\": [\n        \"color\",\n    ],\n    \"cond\": [\"Cond\", \"color_mode_cond\", \"cond\"],\n    \"debounce\": [\"DebounceInput\", \"debounce_input\"],\n    \"foreach\": [\n        \"foreach\",\n        \"Foreach\",\n    ],\n    \"html\": [\"html\", \"Html\"],\n    \"helmet\": [\"Helmet\"],\n    \"match\": [\n        \"match\",\n        \"Match\",\n    ],\n    \"breakpoints\": [\"breakpoints\", \"set_breakpoints\"],\n    \"responsive\": [\n        \"desktop_only\",\n        \"mobile_and_tablet\",\n        \"mobile_only\",\n        \"tablet_and_desktop\",\n        \"tablet_only\",\n    ],\n    \"upload\": [\n        \"upload\",\n        \"cancel_upload\",\n        \"clear_selected_files\",\n        \"get_upload_dir\",\n        \"get_upload_url\",\n        \"selected_files\",\n    ],\n    \"auto_scroll\": [\"auto_scroll\"],\n    \"window_events\": [\"WindowEventListener\", \"window_event_listener\"],\n}\n\n__getattr__, __dir__, __all__ = lazy_loader.attach(\n    __name__,\n    submodules=_SUBMODULES,\n    submod_attrs=_SUBMOD_ATTRS,\n)\n"
  },
  {
    "path": "reflex/components/core/auto_scroll.py",
    "content": "\"\"\"A component that automatically scrolls to the bottom when new content is added.\"\"\"\n\nfrom __future__ import annotations\n\nimport dataclasses\n\nfrom reflex.components.el.elements.typography import Div\nfrom reflex.constants.compiler import MemoizationDisposition, MemoizationMode\nfrom reflex.utils.imports import ImportDict\nfrom reflex.vars.base import Var, get_unique_variable_name\n\n\nclass AutoScroll(Div):\n    \"\"\"A div that automatically scrolls to the bottom when new content is added.\"\"\"\n\n    _memoization_mode = MemoizationMode(\n        disposition=MemoizationDisposition.ALWAYS, recursive=False\n    )\n\n    @classmethod\n    def create(cls, *children, **props):\n        \"\"\"Create an AutoScroll component.\n\n        Args:\n            *children: The children of the component.\n            **props: The props of the component.\n\n        Returns:\n            An AutoScroll component.\n        \"\"\"\n        props.setdefault(\"overflow\", \"auto\")\n        props.setdefault(\"id\", get_unique_variable_name())\n        component = super().create(*children, **props)\n        if \"key\" in props:\n            component._memoization_mode = dataclasses.replace(\n                component._memoization_mode, recursive=True\n            )\n        return component\n\n    def add_imports(self) -> ImportDict | list[ImportDict]:\n        \"\"\"Add imports required for the component.\n\n        Returns:\n            The imports required for the component.\n        \"\"\"\n        return {\"react\": [\"useEffect\", \"useRef\"]}\n\n    def add_hooks(self) -> list[str | Var]:\n        \"\"\"Add hooks required for the component.\n\n        Returns:\n            The hooks required for the component.\n        \"\"\"\n        ref_name = self.get_ref()\n        unique_id = ref_name\n        return [\n            f\"const wasNearBottom_{unique_id} = useRef(false);\",\n            f\"const hadScrollbar_{unique_id} = useRef(false);\",\n            f\"\"\"\nconst checkIfNearBottom_{unique_id} = () => {{\n    if (!{ref_name}.current) return;\n\n    const container = {ref_name}.current;\n    const nearBottomThreshold = 50; // pixels from bottom to trigger auto-scroll\n\n    const distanceFromBottom = container.scrollHeight - container.scrollTop - container.clientHeight;\n\n    wasNearBottom_{unique_id}.current = distanceFromBottom <= nearBottomThreshold;\n\n    // Track if container had a scrollbar\n    hadScrollbar_{unique_id}.current = container.scrollHeight > container.clientHeight;\n}};\n\"\"\",\n            f\"\"\"\nconst scrollToBottomIfNeeded_{unique_id} = () => {{\n    if (!{ref_name}.current) return;\n\n    const container = {ref_name}.current;\n    const hasScrollbarNow = container.scrollHeight > container.clientHeight;\n\n    // Scroll if:\n    // 1. User was near bottom, OR\n    // 2. Container didn't have scrollbar before but does now\n    if (wasNearBottom_{unique_id}.current || (!hadScrollbar_{unique_id}.current && hasScrollbarNow)) {{\n      container.scrollTop = container.scrollHeight;\n    }}\n\n    // Update scrollbar state for next check\n    hadScrollbar_{unique_id}.current = hasScrollbarNow;\n}};\n\"\"\",\n            f\"\"\"\nuseEffect(() => {{\n    const container = {ref_name}.current;\n    if (!container) return;\n\n    scrollToBottomIfNeeded_{unique_id}();\n\n    // Create ResizeObserver to detect height changes\n    const resizeObserver = new ResizeObserver(() => {{\n        scrollToBottomIfNeeded_{unique_id}();\n    }});\n\n    // Track scroll position before height changes\n    container.addEventListener('scroll', checkIfNearBottom_{unique_id});\n\n    // Initial check\n    checkIfNearBottom_{unique_id}();\n\n    // Observe container for size changes\n    resizeObserver.observe(container);\n\n    return () => {{\n        container.removeEventListener('scroll', checkIfNearBottom_{unique_id});\n        resizeObserver.disconnect();\n    }};\n}});\n\"\"\",\n        ]\n\n\nauto_scroll = AutoScroll.create\n"
  },
  {
    "path": "reflex/components/core/banner.py",
    "content": "\"\"\"Banner components.\"\"\"\n\nfrom __future__ import annotations\n\nfrom reflex import constants\nfrom reflex.components.base.fragment import Fragment\nfrom reflex.components.component import Component\nfrom reflex.components.core.cond import cond\nfrom reflex.components.el.elements.typography import Div\nfrom reflex.components.lucide.icon import Icon\nfrom reflex.components.radix.themes.components.dialog import (\n    DialogContent,\n    DialogRoot,\n    DialogTitle,\n)\nfrom reflex.components.radix.themes.layout.flex import Flex\nfrom reflex.components.radix.themes.typography.text import Text\nfrom reflex.components.sonner.toast import ToastProps, toast_ref\nfrom reflex.constants import Dirs, Hooks, Imports\nfrom reflex.constants.compiler import CompileVars\nfrom reflex.environment import environment\nfrom reflex.utils.imports import ImportVar\nfrom reflex.vars import VarData\nfrom reflex.vars.base import LiteralVar, Var\nfrom reflex.vars.function import FunctionStringVar\nfrom reflex.vars.number import BooleanVar\nfrom reflex.vars.sequence import LiteralArrayVar\n\nconnect_error_var_data: VarData = VarData(\n    imports=Imports.EVENTS,\n    hooks={Hooks.EVENTS: None},\n)\n\nconnect_errors = Var(\n    _js_expr=CompileVars.CONNECT_ERROR, _var_data=connect_error_var_data\n)\n\nconnection_error = Var(\n    _js_expr=\"((connectErrors.length > 0) ? connectErrors[connectErrors.length - 1].message : '')\",\n    _var_data=connect_error_var_data,\n)\n\nconnection_errors_count = Var(\n    _js_expr=\"connectErrors.length\", _var_data=connect_error_var_data\n)\n\nhas_connection_errors = Var(\n    _js_expr=\"(connectErrors.length > 0)\", _var_data=connect_error_var_data\n).to(BooleanVar)\n\nhas_too_many_connection_errors = Var(\n    _js_expr=\"(connectErrors.length >= 2)\", _var_data=connect_error_var_data\n).to(BooleanVar)\n\n\nclass WebsocketTargetURL(Var):\n    \"\"\"A component that renders the websocket target URL.\"\"\"\n\n    @classmethod\n    def create(cls) -> Var:\n        \"\"\"Create a websocket target URL component.\n\n        Returns:\n            The websocket target URL component.\n        \"\"\"\n        return Var(\n            _js_expr=\"getBackendURL(env.EVENT).href\",\n            _var_data=VarData(\n                imports={\n                    \"$/env.json\": [ImportVar(tag=\"env\", is_default=True)],\n                    f\"$/{Dirs.STATE_PATH}\": [ImportVar(tag=\"getBackendURL\")],\n                },\n            ),\n            _var_type=WebsocketTargetURL,\n        )\n\n\ndef default_connection_error() -> list[str | Var | Component]:\n    \"\"\"Get the default connection error message.\n\n    Returns:\n        The default connection error message.\n    \"\"\"\n    return [\n        \"Cannot connect to server: \",\n        connection_error,\n        \". Check if server is reachable at \",\n        WebsocketTargetURL.create(),\n    ]\n\n\nclass ConnectionToaster(Fragment):\n    \"\"\"A connection toaster component.\"\"\"\n\n    def add_hooks(self) -> list[str | Var]:\n        \"\"\"Add the hooks for the connection toaster.\n\n        Returns:\n            The hooks for the connection toaster.\n        \"\"\"\n        toast_id = \"websocket-error\"\n        target_url = WebsocketTargetURL.create()\n        props = ToastProps(\n            description=LiteralVar.create(\n                f\"Check if server is reachable at {target_url}\",\n            ),\n            close_button=True,\n            duration=120000,\n            id=toast_id,\n        )  # pyright: ignore [reportCallIssue]\n\n        if environment.REFLEX_DOES_BACKEND_COLD_START.get():\n            loading_message = Var.create(\"Backend is starting.\")\n            backend_is_loading_toast_var = Var(\n                f\"toast?.loading({loading_message!s}, {{...toast_props, description: '', closeButton: false, onDismiss: () => setUserDismissed(true)}},)\"\n            )\n            backend_is_not_responding = Var.create(\"Backend is not responding.\")\n            backend_is_down_toast_var = Var(\n                f\"toast?.error({backend_is_not_responding!s}, {{...toast_props, description: '', onDismiss: () => setUserDismissed(true)}},)\"\n            )\n            toast_var = Var(\n                f\"\"\"\nif (waitedForBackend) {{\n    {backend_is_down_toast_var!s}\n}} else {{\n    {backend_is_loading_toast_var!s};\n}}\nsetTimeout(() => {{\n    if ({has_too_many_connection_errors!s}) {{\n        setWaitedForBackend(true);\n    }}\n}}, {environment.REFLEX_BACKEND_COLD_START_TIMEOUT.get() * 1000});\n\"\"\"\n            )\n        else:\n            loading_message = Var.create(\n                f\"Cannot connect to server: {connection_error}.\"\n            )\n            toast_var = Var(\n                f\"toast?.error({loading_message!s}, {{...toast_props, onDismiss: () => setUserDismissed(true)}},)\"\n            )\n\n        individual_hooks = [\n            Var(f\"const toast = {toast_ref};\"),\n            f\"const toast_props = {LiteralVar.create(props)!s};\",\n            \"const [userDismissed, setUserDismissed] = useState(false);\",\n            \"const [waitedForBackend, setWaitedForBackend] = useState(false);\",\n            FunctionStringVar(\n                \"useEffect\",\n                _var_data=VarData(\n                    imports={\n                        \"react\": (\"useEffect\", \"useState\"),\n                        **(\n                            dict(var_data.imports)\n                            if (var_data := target_url._get_all_var_data()) is not None\n                            else {}\n                        ),\n                    }\n                ),\n            ).call(\n                # TODO: This breaks the assumption that Vars are JS expressions\n                Var(\n                    _js_expr=f\"\"\"\n() => {{\n    if ({has_too_many_connection_errors!s}) {{\n        if (!userDismissed) {{\n            {toast_var!s}\n        }}\n    }} else {{\n        toast?.dismiss(\"{toast_id}\");\n        setUserDismissed(false);  // after reconnection reset dismissed state\n    }}\n}}\n\"\"\"\n                ),\n                LiteralArrayVar.create([connect_errors, Var(\"waitedForBackend\")]),\n            ),\n        ]\n\n        return [\n            Hooks.EVENTS,\n            *individual_hooks,\n        ]\n\n    @classmethod\n    def create(cls, *children, **props) -> Component:\n        \"\"\"Create a connection toaster component.\n\n        Args:\n            *children: The children of the component.\n            **props: The properties of the component.\n\n        Returns:\n            The connection toaster component.\n        \"\"\"\n        return super().create(*children, **props)\n\n\nclass ConnectionBanner(Component):\n    \"\"\"A connection banner component.\"\"\"\n\n    @classmethod\n    def create(cls, comp: Component | None = None) -> Component:\n        \"\"\"Create a connection banner component.\n\n        Args:\n            comp: The component to render when there's a server connection error.\n\n        Returns:\n            The connection banner component.\n        \"\"\"\n        if not comp:\n            comp = Flex.create(\n                Text.create(\n                    *default_connection_error(),\n                    color=\"black\",\n                    size=\"4\",\n                ),\n                justify=\"center\",\n                background_color=\"crimson\",\n                width=\"100vw\",\n                padding=\"5px\",\n                position=\"fixed\",\n            )\n\n        return cond(has_connection_errors, comp)\n\n\nclass ConnectionModal(Component):\n    \"\"\"A connection status modal window.\"\"\"\n\n    @classmethod\n    def create(cls, comp: Component | None = None) -> Component:\n        \"\"\"Create a connection banner component.\n\n        Args:\n            comp: The component to render when there's a server connection error.\n\n        Returns:\n            The connection banner component.\n        \"\"\"\n        if not comp:\n            comp = Text.create(*default_connection_error())\n        return cond(\n            has_too_many_connection_errors,\n            DialogRoot.create(\n                DialogContent.create(\n                    DialogTitle.create(\"Connection Error\"),\n                    comp,\n                ),\n                open=has_too_many_connection_errors,\n                z_index=9999,\n            ),\n        )\n\n\nclass WifiOffPulse(Icon):\n    \"\"\"A wifi_off icon with an animated opacity pulse.\"\"\"\n\n    @classmethod\n    def create(cls, *children, **props) -> Icon:\n        \"\"\"Create a wifi_off icon with an animated opacity pulse.\n\n        Args:\n            *children: The children of the component.\n            **props: The properties of the component.\n\n        Returns:\n            The icon component with default props applied.\n        \"\"\"\n        pulse_var = Var(r\"keyframes({ from: { opacity: 0 }, to: { opacity: 1 } })\").to(\n            str\n        )\n        return super().create(\n            \"wifi_off\",\n            color=props.pop(\"color\", \"crimson\"),\n            size=props.pop(\"size\", 32),\n            z_index=props.pop(\"z_index\", 9999),\n            position=props.pop(\"position\", \"fixed\"),\n            bottom=props.pop(\"bottom\", \"33px\"),\n            right=props.pop(\"right\", \"33px\"),\n            animation=LiteralVar.create(f\"{pulse_var} 1s infinite\"),\n            **props,\n        )\n\n    def add_imports(self) -> dict[str, str | ImportVar | list[str | ImportVar]]:\n        \"\"\"Add imports for the WifiOffPulse component.\n\n        Returns:\n            The import dict.\n        \"\"\"\n        return {\"@emotion/react\": [ImportVar(tag=\"keyframes\")]}\n\n\nclass ConnectionPulser(Div):\n    \"\"\"A connection pulser component.\"\"\"\n\n    @classmethod\n    def create(cls, **props) -> Component:\n        \"\"\"Create a connection pulser component.\n\n        Args:\n            **props: The properties of the component.\n\n        Returns:\n            The connection pulser component.\n        \"\"\"\n        return super().create(\n            cond(\n                has_connection_errors,\n                WifiOffPulse.create(**props),\n            ),\n            title=f\"Connection Error: {connection_error}\",\n            position=\"fixed\",\n            width=\"100vw\",\n            height=\"0\",\n        )\n\n\nclass BackendDisabled(Div):\n    \"\"\"A component that displays a message when the backend is disabled.\"\"\"\n\n    @classmethod\n    def create(cls, **props) -> Component:\n        \"\"\"Create a backend disabled component.\n\n        Args:\n            **props: The properties of the component.\n\n        Returns:\n            The backend disabled component.\n        \"\"\"\n        import reflex as rx\n\n        is_backend_disabled = Var(\n            \"backendDisabled\",\n            _var_type=bool,\n            _var_data=VarData(\n                hooks={\n                    \"const [backendDisabled, setBackendDisabled] = useState(false);\": None,\n                    \"useEffect(() => { setBackendDisabled(isBackendDisabled()); }, []);\": None,\n                },\n                imports={\n                    f\"$/{constants.Dirs.STATE_PATH}\": [\n                        ImportVar(tag=\"isBackendDisabled\")\n                    ],\n                },\n            ),\n        )\n\n        return super().create(\n            rx.cond(\n                is_backend_disabled,\n                rx.box(\n                    rx.el.link(\n                        rel=\"preconnect\",\n                        href=\"https://fonts.googleapis.com\",\n                    ),\n                    rx.el.link(\n                        rel=\"preconnect\",\n                        href=\"https://fonts.gstatic.com\",\n                        crossorigin=\"\",\n                    ),\n                    rx.el.link(\n                        href=\"https://fonts.googleapis.com/css2?family=Instrument+Sans:ital,wght@0,500;0,600&display=swap\",\n                        rel=\"stylesheet\",\n                    ),\n                    rx.box(\n                        rx.vstack(\n                            rx.text(\n                                \"This app is paused\",\n                                font_size=\"1.5rem\",\n                                font_weight=\"600\",\n                                line_height=\"1.25rem\",\n                                letter_spacing=\"-0.0375rem\",\n                            ),\n                            rx.hstack(\n                                rx.el.svg(\n                                    rx.el.path(\n                                        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\",\n                                        fill_rule=\"evenodd\",\n                                        clip_rule=\"evenodd\",\n                                        fill=rx.color(\"amber\", 11),\n                                    ),\n                                    width=\"16\",\n                                    height=\"16\",\n                                    viewBox=\"0 0 16 16\",\n                                    fill=\"none\",\n                                    xmlns=\"http://www.w3.org/2000/svg\",\n                                    margin_top=\"0.125rem\",\n                                    flex_shrink=\"0\",\n                                ),\n                                rx.text(\n                                    \"If you are the owner of this app, visit \",\n                                    rx.link(\n                                        \"Reflex Cloud\",\n                                        color=rx.color(\"amber\", 11),\n                                        underline=\"always\",\n                                        _hover={\n                                            \"color\": rx.color(\"amber\", 11),\n                                            \"text_decoration_color\": rx.color(\n                                                \"amber\", 11\n                                            ),\n                                        },\n                                        text_decoration_color=rx.color(\"amber\", 10),\n                                        href=\"https://cloud.reflex.dev/\",\n                                        font_weight=\"600\",\n                                        is_external=True,\n                                    ),\n                                    \" for more information on how to resume your app.\",\n                                    font_size=\"0.875rem\",\n                                    font_weight=\"500\",\n                                    line_height=\"1.25rem\",\n                                    letter_spacing=\"-0.01094rem\",\n                                    color=rx.color(\"amber\", 11),\n                                ),\n                                align=\"start\",\n                                gap=\"0.625rem\",\n                                border_radius=\"0.75rem\",\n                                border_width=\"1px\",\n                                border_color=rx.color(\"amber\", 5),\n                                background_color=rx.color(\"amber\", 3),\n                                padding=\"0.625rem\",\n                            ),\n                            rx.link(\n                                rx.el.button(\n                                    \"Resume app\",\n                                    color=\"rgba(252, 252, 253, 1)\",\n                                    font_size=\"0.875rem\",\n                                    font_weight=\"600\",\n                                    line_height=\"1.25rem\",\n                                    letter_spacing=\"-0.01094rem\",\n                                    height=\"2.5rem\",\n                                    padding=\"0rem 0.75rem\",\n                                    width=\"100%\",\n                                    border_radius=\"0.75rem\",\n                                    background=f\"linear-gradient(180deg, {rx.color('violet', 9)} 0%, {rx.color('violet', 10)} 100%)\",\n                                    _hover={\n                                        \"background\": f\"linear-gradient(180deg, {rx.color('violet', 10)} 0%, {rx.color('violet', 10)} 100%)\",\n                                    },\n                                ),\n                                width=\"100%\",\n                                underline=\"none\",\n                                href=\"https://cloud.reflex.dev/\",\n                                is_external=True,\n                            ),\n                            gap=\"1rem\",\n                        ),\n                        font_family='\"Instrument Sans\", \"Helvetica\", \"Arial\", sans-serif',\n                        position=\"fixed\",\n                        top=\"50%\",\n                        left=\"50%\",\n                        transform=\"translate(-50%, -50%)\",\n                        width=\"60ch\",\n                        max_width=\"90vw\",\n                        border_radius=\"0.75rem\",\n                        border_width=\"1px\",\n                        border_color=rx.color(\"slate\", 4),\n                        padding=\"1.5rem\",\n                        background_color=rx.color(\"slate\", 1),\n                        box_shadow=\"0px 2px 5px 0px light-dark(rgba(28, 32, 36, 0.03), rgba(0, 0, 0, 0.00))\",\n                    ),\n                    position=\"fixed\",\n                    z_index=9999,\n                    backdrop_filter=\"grayscale(1) blur(5px)\",\n                    width=\"100dvw\",\n                    height=\"100dvh\",\n                ),\n            )\n        )\n\n\nconnection_banner = ConnectionBanner.create\nconnection_modal = ConnectionModal.create\nconnection_toaster = ConnectionToaster.create\nconnection_pulser = ConnectionPulser.create\nbackend_disabled = BackendDisabled.create\n"
  },
  {
    "path": "reflex/components/core/breakpoints.py",
    "content": "\"\"\"Breakpoints utility.\"\"\"\n\nfrom __future__ import annotations\n\nfrom typing import TypeVar\n\nbreakpoints_values = [\"30em\", \"48em\", \"62em\", \"80em\", \"96em\"]\nbreakpoint_names = [\"xs\", \"sm\", \"md\", \"lg\", \"xl\"]\n\n\ndef set_breakpoints(values: tuple[str, str, str, str, str]):\n    \"\"\"Overwrite default breakpoint values.\n\n    Args:\n        values: CSS values in order defining the breakpoints of responsive layouts\n    \"\"\"\n    breakpoints_values.clear()\n    breakpoints_values.extend(values)\n\n\nK = TypeVar(\"K\", bound=str)\nV = TypeVar(\"V\")\n\n\nclass Breakpoints(dict[K, V]):\n    \"\"\"A responsive styling helper.\"\"\"\n\n    def factorize(self):\n        \"\"\"Removes references to breakpoints names and instead replaces them with their corresponding values.\n\n        Returns:\n            The factorized breakpoints.\n        \"\"\"\n        return Breakpoints({\n            (\n                breakpoints_values[breakpoint_names.index(k)]\n                if k in breakpoint_names\n                else (\"0px\" if k == \"initial\" else k)\n            ): v\n            for k, v in self.items()\n            if v is not None\n        })\n\n    @classmethod\n    def create(\n        cls,\n        custom: dict[K, V] | None = None,\n        initial: V | None = None,\n        xs: V | None = None,\n        sm: V | None = None,\n        md: V | None = None,\n        lg: V | None = None,\n        xl: V | None = None,\n    ):\n        \"\"\"Create a new instance of the helper. Only provide a custom component OR use named props.\n\n        Args:\n            custom: Custom mapping using CSS values or variables.\n            initial: Styling when in the initial width\n            xs: Styling when in the extra-small width\n            sm: Styling when in the small width\n            md: Styling when in the medium width\n            lg: Styling when in the large width\n            xl: Styling when in the extra-large width\n\n        Returns:\n            The responsive mapping.\n\n        Raises:\n            ValueError: If both custom and any other named parameters are provided.\n        \"\"\"\n        thresholds = [initial, xs, sm, md, lg, xl]\n\n        if custom is not None:\n            if any(threshold is not None for threshold in thresholds):\n                msg = \"Named props cannot be used with custom thresholds\"\n                raise ValueError(msg)\n\n            return Breakpoints(custom)\n        return Breakpoints({\n            k: v\n            for k, v in zip([\"initial\", *breakpoint_names], thresholds, strict=True)\n            if v is not None\n        })\n\n\nbreakpoints = Breakpoints.create\n\nT = TypeVar(\"T\")\n\nResponsive = T | Breakpoints[str, T]\n"
  },
  {
    "path": "reflex/components/core/clipboard.py",
    "content": "\"\"\"Global on_paste handling for Reflex app.\"\"\"\n\nfrom __future__ import annotations\n\nfrom collections.abc import Sequence\n\nfrom reflex.components.base.fragment import Fragment\nfrom reflex.components.tags.tag import Tag\nfrom reflex.constants.compiler import Hooks\nfrom reflex.event import EventChain, EventHandler, passthrough_event_spec\nfrom reflex.utils.format import format_prop, wrap\nfrom reflex.utils.imports import ImportVar\nfrom reflex.vars import get_unique_variable_name\nfrom reflex.vars.base import Var, VarData\n\n\nclass Clipboard(Fragment):\n    \"\"\"Clipboard component.\"\"\"\n\n    # The element ids to attach the event listener to. Defaults to all child components or the document.\n    targets: Var[Sequence[str]]\n\n    # 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.\n    on_paste: EventHandler[passthrough_event_spec(list[tuple[str, str]])]\n\n    # Save the original event actions for the on_paste event.\n    on_paste_event_actions: Var[dict[str, bool | int]]\n\n    @classmethod\n    def create(cls, *children, **props):\n        \"\"\"Create a Clipboard component.\n\n        Args:\n            *children: The children of the component.\n            **props: The properties of the component.\n\n        Returns:\n            The Clipboard Component.\n        \"\"\"\n        if \"targets\" not in props:\n            # Add all children as targets if not specified.\n            targets = props.setdefault(\"targets\", [])\n            for c in children:\n                if c.id is None:\n                    c.id = f\"clipboard_{get_unique_variable_name()}\"\n                targets.append(c.id)\n\n        if \"on_paste\" in props:\n            # Capture the event actions for the on_paste handler if not specified.\n            props.setdefault(\"on_paste_event_actions\", props[\"on_paste\"].event_actions)\n\n        return super().create(*children, **props)\n\n    def _exclude_props(self) -> list[str]:\n        return [*super()._exclude_props(), \"on_paste\", \"on_paste_event_actions\"]\n\n    def _render(self) -> Tag:\n        tag = super()._render()\n        # Ensure a different Fragment component is created whenever targets differ\n        return tag.remove_props(\"targets\").add_props(key=self.targets)\n\n    def add_imports(self) -> dict[str, ImportVar]:\n        \"\"\"Add the imports for the Clipboard component.\n\n        Returns:\n            The import dict for the component.\n        \"\"\"\n        return {\n            \"$/utils/helpers/paste.js\": ImportVar(\n                tag=\"usePasteHandler\", is_default=True\n            ),\n        }\n\n    def add_hooks(self) -> list[str | Var[str]]:\n        \"\"\"Add hook to register paste event listener.\n\n        Returns:\n            The hooks to add to the component.\n        \"\"\"\n        on_paste = self.event_triggers[\"on_paste\"]\n        if on_paste is None:\n            return []\n        if isinstance(on_paste, EventChain):\n            on_paste = wrap(str(format_prop(on_paste)).strip(\"{}\"), \"(\")\n        hook_expr = f\"usePasteHandler({self.targets!s}, {self.on_paste_event_actions!s}, {on_paste!s})\"\n\n        return [\n            Var(\n                hook_expr,\n                _var_type=\"str\",\n                _var_data=VarData(position=Hooks.HookPosition.POST_TRIGGER),\n            ),\n        ]\n\n\nclipboard = Clipboard.create\n"
  },
  {
    "path": "reflex/components/core/colors.py",
    "content": "\"\"\"The colors used in Reflex are a wrapper around https://www.radix-ui.com/colors.\"\"\"\n\nfrom reflex.constants.base import REFLEX_VAR_OPENING_TAG\nfrom reflex.constants.colors import (\n    COLORS,\n    MAX_SHADE_VALUE,\n    MIN_SHADE_VALUE,\n    Color,\n    ColorType,\n    ShadeType,\n)\nfrom reflex.vars.base import Var\n\n\ndef color(\n    color: ColorType | Var[str],\n    shade: ShadeType | Var[int] = 7,\n    alpha: bool | Var[bool] = False,\n) -> Color:\n    \"\"\"Create a color object.\n\n    Args:\n        color: The color to use.\n        shade: The shade of the color to use.\n        alpha: Whether to use the alpha variant of the color.\n\n    Returns:\n        The color object.\n\n    Raises:\n        ValueError: If the color, shade, or alpha are not valid.\n    \"\"\"\n    if isinstance(color, str):\n        if color not in COLORS and REFLEX_VAR_OPENING_TAG not in color:\n            msg = f\"Color must be one of {COLORS}, received {color}\"\n            raise ValueError(msg)\n    elif not isinstance(color, Var):\n        msg = \"Color must be a string or a Var\"\n        raise ValueError(msg)\n\n    if isinstance(shade, int):\n        if shade < MIN_SHADE_VALUE or shade > MAX_SHADE_VALUE:\n            msg = f\"Shade must be between {MIN_SHADE_VALUE} and {MAX_SHADE_VALUE}\"\n            raise ValueError(msg)\n    elif not isinstance(shade, Var):\n        msg = \"Shade must be an integer or a Var\"\n        raise ValueError(msg)\n\n    if not isinstance(alpha, (bool, Var)):\n        msg = \"Alpha must be a boolean or a Var\"\n        raise ValueError(msg)\n\n    return Color(color, shade, alpha)\n"
  },
  {
    "path": "reflex/components/core/cond.py",
    "content": "\"\"\"Create a list of components from an iterable.\"\"\"\n\nfrom __future__ import annotations\n\nfrom typing import Any, overload\n\nfrom reflex.components.base.fragment import Fragment\nfrom reflex.components.component import BaseComponent, Component\nfrom reflex.components.tags import CondTag, Tag\nfrom reflex.constants import Dirs\nfrom reflex.style import LIGHT_COLOR_MODE, resolved_color_mode\nfrom reflex.utils import types\nfrom reflex.utils.imports import ImportDict, ImportVar\nfrom reflex.vars import VarData\nfrom reflex.vars.base import LiteralVar, Var\nfrom reflex.vars.number import ternary_operation\n\n_IS_TRUE_IMPORT: ImportDict = {\n    f\"$/{Dirs.STATE_PATH}\": [ImportVar(tag=\"isTrue\")],\n}\n\n\nclass Cond(Component):\n    \"\"\"Render one of two components based on a condition.\"\"\"\n\n    # The cond to determine which component to render.\n    cond: Var[Any]\n\n    @classmethod\n    def create(\n        cls,\n        cond: Var,\n        comp1: BaseComponent,\n        comp2: BaseComponent | types.Unset = types.Unset(),\n    ) -> Component:\n        \"\"\"Create a conditional component.\n\n        Args:\n            cond: The cond to determine which component to render.\n            comp1: The component to render if the cond is true.\n            comp2: The component to render if the cond is false.\n\n        Returns:\n            The conditional component.\n        \"\"\"\n        # Wrap everything in fragments.\n        if type(comp1) is not Fragment:\n            comp1 = Fragment.create(comp1)\n        if isinstance(comp2, types.Unset) or type(comp2) is not Fragment:\n            comp2 = (\n                Fragment.create(comp2)\n                if not isinstance(comp2, types.Unset)\n                else Fragment.create()\n            )\n        return Fragment.create(\n            cls._create(\n                children=[comp1, comp2],\n                cond=cond,\n            )\n        )\n\n    def _render(self) -> Tag:\n        return CondTag(\n            cond_state=str(self.cond),\n            true_value=self.children[0].render(),\n            false_value=self.children[1].render(),\n        )\n\n    def render(self) -> dict:\n        \"\"\"Render the component.\n\n        Returns:\n            The dictionary for template of component.\n        \"\"\"\n        return {\n            \"cond_state\": str(self.cond),\n            \"true_value\": self.children[0].render(),\n            \"false_value\": self.children[1].render(),\n        }\n\n    def add_imports(self) -> ImportDict:\n        \"\"\"Add imports for the Cond component.\n\n        Returns:\n            The import dict for the component.\n        \"\"\"\n        var_data = VarData.merge(self.cond._get_all_var_data())\n\n        imports = var_data.old_school_imports() if var_data else {}\n\n        return {**imports, **_IS_TRUE_IMPORT}\n\n\n@overload\ndef cond(condition: Any, c1: Component, c2: Any, /) -> Component: ...  # pyright: ignore [reportOverlappingOverload]\n\n\n@overload\ndef cond(condition: Any, c1: Component, /) -> Component: ...\n\n\n@overload\ndef cond(condition: Any, c1: Any, c2: Component, /) -> Component: ...  # pyright: ignore [reportOverlappingOverload]\n\n\n@overload\ndef cond(condition: Any, c1: Any, c2: Any, /) -> Var: ...\n\n\ndef cond(condition: Any, c1: Any, c2: Any = types.Unset(), /) -> Component | Var:\n    \"\"\"Create a conditional component or Prop.\n\n    Args:\n        condition: The cond to determine which component to render.\n        c1: The component or prop to render if the cond_var is true.\n        c2: The component or prop to render if the cond_var is false.\n\n    Returns:\n        The conditional component.\n\n    Raises:\n        ValueError: If the arguments are invalid.\n    \"\"\"\n    # Convert the condition to a Var.\n    cond_var = LiteralVar.create(condition)\n    if cond_var is None:\n        msg = \"The condition must be set.\"\n        raise ValueError(msg)\n\n    # If the first component is a component, create a Cond component.\n    if isinstance(c1, BaseComponent):\n        if not isinstance(c2, types.Unset) and not isinstance(c2, BaseComponent):\n            return Cond.create(cond_var.bool(), c1, Fragment.create(c2))\n        return Cond.create(cond_var.bool(), c1, c2)\n\n    # Otherwise, create a conditional Var.\n    # Check that the second argument is valid.\n    if isinstance(c2, BaseComponent):\n        return Cond.create(cond_var.bool(), Fragment.create(c1), c2)\n    if isinstance(c2, types.Unset):\n        msg = \"For conditional vars, the second argument must be set.\"\n        raise ValueError(msg)\n\n    # convert the truth and false cond parts into vars so the _var_data can be obtained.\n    c1_var = Var.create(c1)\n    c2_var = Var.create(c2)\n\n    if c1_var is cond_var or c1_var.equals(cond_var):\n        c1_var = c1_var.to(types.value_inside_optional(c1_var._var_type))\n\n    # Create the conditional var.\n    return ternary_operation(\n        cond_var.bool(),\n        c1_var,\n        c2_var,\n    )\n\n\n@overload\ndef color_mode_cond(light: Component, dark: Component | None = None) -> Component: ...  # pyright: ignore [reportOverlappingOverload]\n\n\n@overload\ndef color_mode_cond(light: Any, dark: Any = None) -> Var: ...\n\n\ndef color_mode_cond(light: Any, dark: Any = None) -> Var | Component:\n    \"\"\"Create a component or Prop based on color_mode.\n\n    Args:\n        light: The component or prop to render if color_mode is default\n        dark: The component or prop to render if color_mode is non-default\n\n    Returns:\n        The conditional component or prop.\n    \"\"\"\n    return cond(\n        resolved_color_mode == LiteralVar.create(LIGHT_COLOR_MODE),\n        light,\n        dark,\n    )\n"
  },
  {
    "path": "reflex/components/core/debounce.py",
    "content": "\"\"\"Wrapper around react-debounce-input.\"\"\"\n\nfrom __future__ import annotations\n\nfrom typing import Any\n\nfrom reflex.components.component import Component\nfrom reflex.constants import EventTriggers\nfrom reflex.event import EventHandler, no_args_event_spec\nfrom reflex.vars import VarData\nfrom reflex.vars.base import Var\n\nDEFAULT_DEBOUNCE_TIMEOUT = 300\n\n\nclass DebounceInput(Component):\n    \"\"\"The DebounceInput component is used to buffer input events on the client side.\n\n    It is intended to wrap various form controls and should be used whenever a\n    fully-controlled input is needed to prevent lost input data when the backend\n    is experiencing high latency.\n    \"\"\"\n\n    library = \"react-debounce-input@3.3.0\"\n    tag = \"DebounceInput\"\n    is_default = True\n\n    # Minimum input characters before triggering the on_change event\n    min_length: Var[int]\n\n    # Time to wait between end of input and triggering on_change\n    debounce_timeout: Var[int] = Var.create(DEFAULT_DEBOUNCE_TIMEOUT)\n\n    # If true, notify when Enter key is pressed\n    force_notify_by_enter: Var[bool]\n\n    # If true, notify when form control loses focus\n    force_notify_on_blur: Var[bool]\n\n    # If provided, create a fully-controlled input\n    value: Var[str | int | float]\n\n    # The ref to attach to the created input\n    input_ref: Var[str]\n\n    # The element to wrap\n    element: Var[type[Component]]\n\n    # Fired when the input value changes\n    on_change: EventHandler[no_args_event_spec]\n\n    @classmethod\n    def create(cls, *children: Component, **props: Any) -> Component:\n        \"\"\"Create a DebounceInput component.\n\n        Carry first child props directly on this tag.\n\n        Since react-debounce-input wants to create and manage the underlying\n        input component itself, we carry all props, events, and styles from\n        the child, and then neuter the child's render method so it produces no output.\n\n        Args:\n            children: The child component to wrap.\n            props: The component props.\n\n        Returns:\n            The DebounceInput component.\n\n        Raises:\n            RuntimeError: unless exactly one child element is provided.\n            ValueError: if the child element does not have an on_change handler.\n        \"\"\"\n        if len(children) != 1:\n            msg = (\n                \"Provide a single child for DebounceInput, such as rx.input() or \"\n                \"rx.text_area()\"\n            )\n            raise RuntimeError(msg)\n\n        child = children[0]\n        if \"on_change\" not in child.event_triggers:\n            msg = \"DebounceInput child requires an on_change handler\"\n            raise ValueError(msg)\n\n        # Carry known props and event_triggers from the child.\n        props_from_child = {\n            p: getattr(child, p)\n            for p in cls.get_props()\n            if getattr(child, p, None) is not None\n        }\n        props[EventTriggers.ON_CHANGE] = child.event_triggers.pop(\n            EventTriggers.ON_CHANGE\n        )\n        props = {**props_from_child, **props}\n\n        # Carry all other child props directly via custom_attrs\n        other_props = {\n            p: getattr(child, p)\n            for p in child.get_props()\n            if p not in props_from_child and getattr(child, p) is not None\n        }\n        props.setdefault(\"custom_attrs\", {}).update(other_props, **child.custom_attrs)\n\n        # Carry base Component props.\n        props.setdefault(\"style\", {}).update(child.style)\n        if child.class_name is not None:\n            props[\"class_name\"] = f\"{props.get('class_name', '')} {child.class_name}\"\n        for field in (\"key\", \"special_props\"):\n            if getattr(child, field) is not None:\n                props[field] = getattr(child, field)\n        child_ref = child.get_ref()\n        if props.get(\"input_ref\") is None and child_ref:\n            props[\"input_ref\"] = Var(_js_expr=child_ref, _var_type=str)\n        if child.id is not None:\n            props[\"id\"] = child.id\n\n        # Set the child element to wrap, including any imports/hooks from the child.\n        props.setdefault(\n            \"element\",\n            Var(\n                _js_expr=str(child.alias or child.tag),\n                _var_type=type[Component],\n                _var_data=VarData(\n                    imports=child._get_imports(),\n                    hooks=child._get_all_hooks(),\n                ),\n            ),\n        )\n\n        component = super().create(**props)\n        component._get_style = child._get_style\n        component.event_triggers.update(child.event_triggers)\n        component.children = child.children\n        component._rename_props = child._rename_props  # pyright: ignore[reportAttributeAccessIssue]\n        outer_get_all_custom_code = component._get_all_custom_code\n        component._get_all_custom_code = lambda: (\n            outer_get_all_custom_code() | (child._get_all_custom_code())\n        )\n        return component\n\n    def _render(self):\n        return super()._render().remove_props(\"ref\")\n\n\ndebounce_input = DebounceInput.create\n"
  },
  {
    "path": "reflex/components/core/foreach.py",
    "content": "\"\"\"Create a list of components from an iterable.\"\"\"\n\nfrom __future__ import annotations\n\nimport functools\nimport inspect\nfrom collections.abc import Callable, Iterable\nfrom hashlib import md5\nfrom typing import Any\n\nfrom reflex.components.base.fragment import Fragment\nfrom reflex.components.component import Component, field\nfrom reflex.components.core.cond import cond\nfrom reflex.components.tags import IterTag\nfrom reflex.constants import MemoizationMode\nfrom reflex.constants.state import FIELD_MARKER\nfrom reflex.state import ComponentState\nfrom reflex.utils import types\nfrom reflex.utils.exceptions import UntypedVarError\nfrom reflex.vars.base import LiteralVar, Var\n\n\nclass ForeachVarError(TypeError):\n    \"\"\"Raised when the iterable type is Any.\"\"\"\n\n\nclass ForeachRenderError(TypeError):\n    \"\"\"Raised when there is an error with the foreach render function.\"\"\"\n\n\nclass Foreach(Component):\n    \"\"\"A component that takes in an iterable and a render function and renders a list of components.\"\"\"\n\n    _memoization_mode = MemoizationMode(recursive=False)\n\n    # The iterable to create components from.\n    iterable: Var[Iterable]\n\n    # A function from the render args to the component.\n    render_fn: Callable = field(default=Fragment.create, is_javascript_property=False)\n\n    @classmethod\n    def create(\n        cls,\n        iterable: Var[Iterable] | Iterable,\n        render_fn: Callable,\n    ) -> Foreach:\n        \"\"\"Create a foreach component.\n\n        Args:\n            iterable: The iterable to create components from.\n            render_fn: A function from the render args to the component.\n\n        Returns:\n            The foreach component.\n\n        Raises:\n            ForeachVarError: If the iterable is of type Any.\n            TypeError: If the render function is a ComponentState.\n            UntypedVarError: If the iterable is of type Any without a type annotation.\n\n        # noqa: DAR401 with_traceback\n        # noqa: DAR402 UntypedVarError\n        \"\"\"\n        from reflex.vars import ArrayVar, ObjectVar, StringVar\n\n        iterable = (\n            LiteralVar.create(iterable).guess_type()\n            if not isinstance(iterable, Var)\n            else iterable.guess_type()\n        )\n\n        if iterable._var_type == Any:\n            msg = (\n                f\"Could not foreach over var `{iterable!s}` of type Any. \"\n                \"(If you are trying to foreach over a state var, add a type annotation to the var). \"\n                \"See https://reflex.dev/docs/library/dynamic-rendering/foreach/\"\n            )\n            raise ForeachVarError(msg)\n\n        if (\n            hasattr(render_fn, \"__qualname__\")\n            and render_fn.__qualname__ == ComponentState.create.__qualname__\n        ):\n            msg = \"Using a ComponentState as `render_fn` inside `rx.foreach` is not supported yet.\"\n            raise TypeError(msg)\n\n        if isinstance(iterable, ObjectVar):\n            iterable = iterable.entries()\n\n        if isinstance(iterable, StringVar):\n            iterable = iterable.split()\n\n        if not isinstance(iterable, ArrayVar):\n            msg = (\n                f\"Could not foreach over var `{iterable!s}` of type {iterable._var_type}. \"\n                \"See https://reflex.dev/docs/library/dynamic-rendering/foreach/\"\n            )\n            raise ForeachVarError(msg)\n\n        if types.is_optional(iterable._var_type):\n            iterable = cond(iterable, iterable, [])\n\n        component = cls._create(\n            children=[],\n            iterable=iterable,\n            render_fn=render_fn,\n        )\n        try:\n            # Keep a ref to a rendered component to determine correct imports/hooks/styles.\n            component.children = [component._render().render_component()]\n        except UntypedVarError as e:\n            raise UntypedVarError(\n                iterable,\n                \"foreach\",\n                \"https://reflex.dev/docs/library/dynamic-rendering/foreach/\",\n            ).with_traceback(e.__traceback__) from None\n        return component\n\n    def _render(self) -> IterTag:\n        props = {}\n\n        render_sig = inspect.signature(self.render_fn)\n        params = list(render_sig.parameters.values())\n\n        # Validate the render function signature.\n        if len(params) == 0 or len(params) > 2:\n            msg = (\n                \"Expected 1 or 2 parameters in foreach render function, got \"\n                f\"{[p.name for p in params]}. See \"\n                \"https://reflex.dev/docs/library/dynamic-rendering/foreach/\"\n            )\n            raise ForeachRenderError(msg)\n\n        if len(params) >= 1:\n            # Determine the arg var name based on the params accepted by render_fn.\n            props[\"arg_var_name\"] = params[0].name + FIELD_MARKER\n\n        if len(params) == 2:\n            # Determine the index var name based on the params accepted by render_fn.\n            props[\"index_var_name\"] = params[1].name + FIELD_MARKER\n        else:\n            render_fn = self.render_fn\n            # Otherwise, use a deterministic index, based on the render function bytecode.\n            if (render_fn_code := getattr(render_fn, \"__code__\", None)) is not None:\n                code_hash = md5(render_fn_code.co_code).hexdigest()\n            elif isinstance(render_fn, functools.partial):\n                code_hash = md5(render_fn.func.__code__.co_code).hexdigest()\n            else:\n                code_hash = md5(repr(render_fn).encode()).hexdigest()\n            props[\"index_var_name\"] = f\"index_{code_hash}\"\n\n        return IterTag(\n            iterable=self.iterable,\n            render_fn=self.render_fn,\n            children=self.children,\n            **props,\n        )\n\n    def render(self):\n        \"\"\"Render the component.\n\n        Returns:\n            The dictionary for template of component.\n        \"\"\"\n        tag = self._render()\n\n        return dict(\n            tag,\n            iterable_state=str(tag.iterable),\n            arg_name=tag.arg_var_name,\n            arg_index=tag.index_var_name,\n        )\n\n\nforeach = Foreach.create\n"
  },
  {
    "path": "reflex/components/core/helmet.py",
    "content": "\"\"\"Helmet component module.\"\"\"\n\nfrom reflex.components.component import Component\n\n\nclass Helmet(Component):\n    \"\"\"A helmet component.\"\"\"\n\n    library = \"react-helmet@6.1.0\"\n\n    tag = \"Helmet\"\n\n\nhelmet = Helmet.create\n"
  },
  {
    "path": "reflex/components/core/html.py",
    "content": "\"\"\"A html component.\"\"\"\n\nfrom reflex.components.el.elements.typography import Div\nfrom reflex.vars.base import Var\n\n\nclass Html(Div):\n    \"\"\"Render the html.\n\n    Returns:\n        The code to render the html component.\n    \"\"\"\n\n    # The HTML to render.\n    dangerouslySetInnerHTML: Var[dict[str, str]]  # noqa: N815\n\n    @classmethod\n    def create(cls, *children, **props):\n        \"\"\"Create a html component.\n\n        Args:\n            *children: The children of the component.\n            **props: The props to pass to the component.\n\n        Returns:\n            The html component.\n\n        Raises:\n            ValueError: If children are not provided or more than one child is provided.\n        \"\"\"\n        # If children are not provided, throw an error.\n        if len(children) != 1:\n            msg = \"Must provide children to the html component.\"\n            raise ValueError(msg)\n        props[\"dangerouslySetInnerHTML\"] = {\"__html\": children[0]}\n\n        # Apply the default classname\n        given_class_name = props.pop(\"class_name\", [])\n        if isinstance(given_class_name, str):\n            given_class_name = [given_class_name]\n        props[\"class_name\"] = [\"rx-Html\", *given_class_name]\n\n        # Create the component.\n        return super().create(**props)\n\n\nhtml = Html.create\n"
  },
  {
    "path": "reflex/components/core/layout/__init__.py",
    "content": "\"\"\"Core layout components.\"\"\"\n"
  },
  {
    "path": "reflex/components/core/match.py",
    "content": "\"\"\"rx.match.\"\"\"\n\nimport textwrap\nfrom typing import Any, cast\n\nfrom reflex.components.base import Fragment\nfrom reflex.components.component import BaseComponent, Component, MemoizationLeaf, field\nfrom reflex.components.tags import Tag\nfrom reflex.components.tags.match_tag import MatchTag\nfrom reflex.style import Style\nfrom reflex.utils import format\nfrom reflex.utils.exceptions import MatchTypeError\nfrom reflex.utils.imports import ImportDict\nfrom reflex.vars import VarData\nfrom reflex.vars.base import LiteralVar, Var\n\n\nclass Match(MemoizationLeaf):\n    \"\"\"Match cases based on a condition.\"\"\"\n\n    # The condition to determine which case to match.\n    cond: Var[Any]\n\n    # The list of match cases to be matched.\n    match_cases: list[tuple[list[Var], BaseComponent]] = field(\n        default_factory=list, is_javascript_property=False\n    )\n\n    # The catchall case to match.\n    default: BaseComponent = field(\n        default_factory=Fragment.create, is_javascript_property=False\n    )\n\n    @classmethod\n    def create(cls, cond: Any, *cases) -> Component | Var:\n        \"\"\"Create a Match Component.\n\n        Args:\n            cond: The condition to determine which case to match.\n            cases: This list of cases to match.\n\n        Returns:\n            The match component.\n\n        Raises:\n            ValueError: When a default case is not provided for cases with Var return types.\n        \"\"\"\n        match_cond_var = cls._create_condition_var(cond)\n        cases, default = cls._process_cases(list(cases))\n        match_cases = cls._process_match_cases(cases)\n\n        match_cases = cls._validate_return_types(match_cases)\n\n        if default is None and isinstance(match_cases[0][1], Var):\n            msg = \"For cases with return types as Vars, a default case must be provided\"\n            raise ValueError(msg)\n\n        return cls._create_match_cond_var_or_component(\n            match_cond_var, match_cases, default\n        )\n\n    @classmethod\n    def _create_condition_var(cls, cond: Any) -> Var:\n        \"\"\"Convert the condition to a Var.\n\n        Args:\n            cond: The condition.\n\n        Returns:\n            The condition as a base var\n\n        Raises:\n            ValueError: If the condition is not provided.\n        \"\"\"\n        match_cond_var = LiteralVar.create(cond)\n\n        if match_cond_var is None:\n            msg = \"The condition must be set\"\n            raise ValueError(msg)\n        return match_cond_var\n\n    @classmethod\n    def _process_cases(\n        cls, cases: list\n    ) -> tuple[list[tuple], Var | BaseComponent | None]:\n        \"\"\"Process the list of match cases and the catchall default case.\n\n        Args:\n            cases: The list of match cases.\n\n        Returns:\n            The default case and the list of match case tuples.\n\n        Raises:\n            ValueError: If there are multiple default cases.\n        \"\"\"\n        if not cases:\n            msg = \"rx.match should have at least one case.\"\n            raise ValueError(msg)\n\n        if not isinstance(cases[-1], tuple):\n            *cases, default_return = cases\n            default_return = (\n                cls._create_case_var_with_var_data(default_return)\n                if not isinstance(default_return, BaseComponent)\n                else default_return\n            )\n        else:\n            default_return = None\n\n        if any(case for case in cases if not isinstance(case, tuple)):\n            msg = \"rx.match should have tuples of cases and one default case as the last argument.\"\n            raise ValueError(msg)\n\n        if not cases:\n            msg = \"rx.match should have at least one case.\"\n            raise ValueError(msg)\n\n        return cases, default_return\n\n    @classmethod\n    def _create_case_var_with_var_data(cls, case_element: Any) -> Var:\n        \"\"\"Convert a case element into a Var.If the case\n        is a Style type, we extract the var data and merge it with the\n        newly created Var.\n\n        Args:\n            case_element: The case element.\n\n        Returns:\n            The case element Var.\n        \"\"\"\n        var_data = case_element._var_data if isinstance(case_element, Style) else None\n        return LiteralVar.create(case_element, _var_data=var_data)\n\n    @classmethod\n    def _process_match_cases(\n        cls, cases: list[tuple]\n    ) -> list[tuple[list[Var], BaseComponent | Var]]:\n        \"\"\"Process the individual match cases.\n\n        Args:\n            cases: The match cases.\n\n        Returns:\n            The processed match cases.\n\n        Raises:\n            ValueError: If the default case is not the last case or the tuple elements are less than 2.\n        \"\"\"\n        match_cases: list[tuple[list[Var], BaseComponent | Var]] = []\n        for case_index, case in enumerate(cases):\n            # There should be at least two elements in a case tuple(a condition and return value)\n            if len(case) < 2:\n                msg = \"A case tuple should have at least a match case element and a return value.\"\n                raise ValueError(msg)\n\n            *conditions, return_value = case\n\n            conditions_vars: list[Var] = []\n            for condition_index, condition in enumerate(conditions):\n                if isinstance(condition, BaseComponent):\n                    msg = f\"Match condition {condition_index} of case {case_index} cannot be a component.\"\n                    raise ValueError(msg)\n                conditions_vars.append(cls._create_case_var_with_var_data(condition))\n\n            return_value = (\n                cls._create_case_var_with_var_data(return_value)\n                if not isinstance(return_value, BaseComponent)\n                else return_value\n            )\n\n            if not isinstance(return_value, (Var, BaseComponent)):\n                msg = \"Return value must be a var or component\"\n                raise ValueError(msg)\n\n            match_cases.append((conditions_vars, return_value))\n\n        return match_cases\n\n    @classmethod\n    def _validate_return_types(\n        cls, match_cases: list[tuple[list[Var], BaseComponent | Var]]\n    ) -> list[tuple[list[Var], Var]] | list[tuple[list[Var], BaseComponent]]:\n        \"\"\"Validate that match cases have the same return types.\n\n        Args:\n            match_cases: The match cases.\n\n        Returns:\n            The validated match cases.\n\n        Raises:\n            MatchTypeError: If the return types of cases are different.\n        \"\"\"\n        first_case_return = match_cases[0][-1]\n        return_type = type(first_case_return)\n\n        if isinstance(first_case_return, BaseComponent):\n            return_type = BaseComponent\n        elif isinstance(first_case_return, Var):\n            return_type = Var\n\n        cases = []\n        for index, case in enumerate(match_cases):\n            conditions, return_value = case\n            if not isinstance(return_value, return_type):\n                msg = (\n                    f\"Match cases should have the same return types. Case {index} with return \"\n                    f\"value `{return_value._js_expr if isinstance(return_value, Var) else textwrap.shorten(str(return_value), width=250)}`\"\n                    f\" of type {type(return_value)!r} is not {return_type}\"\n                )\n                raise MatchTypeError(msg)\n            cases.append((conditions, return_value))\n        return cases\n\n    @classmethod\n    def _create_match_cond_var_or_component(\n        cls,\n        match_cond_var: Var,\n        match_cases: list[tuple[list[Var], BaseComponent]]\n        | list[tuple[list[Var], Var]],\n        default: Var | BaseComponent | None,\n    ) -> Component | Var:\n        \"\"\"Create and return the match condition var or component.\n\n        Args:\n            match_cond_var: The match condition.\n            match_cases: The list of match cases.\n            default: The default case.\n\n        Returns:\n            The match component wrapped in a fragment or the match var.\n        \"\"\"\n        if isinstance(match_cases[0][1], BaseComponent):\n            if default is None:\n                default = Fragment.create()\n\n            return Fragment.create(\n                cls._create(\n                    cond=match_cond_var,\n                    match_cases=match_cases,\n                    default=default,\n                    children=[case[1] for case in match_cases] + [default],  # pyright: ignore [reportArgumentType]\n                )\n            )\n\n        match_cases = cast(\"list[tuple[list[Var], Var]]\", match_cases)\n        default = cast(\"Var\", default)\n\n        return Var(\n            _js_expr=format.format_match(\n                cond=str(match_cond_var),\n                match_cases=match_cases,\n                default=default,\n            ),\n            _var_type=default._var_type,\n            _var_data=VarData.merge(\n                match_cond_var._get_all_var_data(),\n                *[el._get_all_var_data() for case in match_cases for el in case[0]],\n                *[case[1]._get_all_var_data() for case in match_cases],\n                default._get_all_var_data(),\n            ),\n        )\n\n    def _render(self) -> Tag:\n        return MatchTag(\n            cond=str(self.cond),\n            match_cases=[\n                ([str(cond) for cond in conditions], return_value.render())\n                for conditions, return_value in self.match_cases\n            ],\n            default=self.default.render(),\n        )\n\n    def render(self) -> dict:\n        \"\"\"Render the component.\n\n        Returns:\n            The dictionary for template of component.\n        \"\"\"\n        return dict(self._render())\n\n    def add_imports(self) -> ImportDict:\n        \"\"\"Add imports for the Match component.\n\n        Returns:\n            The import dict.\n        \"\"\"\n        var_data = VarData.merge(self.cond._get_all_var_data())\n        return var_data.old_school_imports() if var_data else {}\n\n\nmatch = Match.create\n"
  },
  {
    "path": "reflex/components/core/responsive.py",
    "content": "\"\"\"Responsive components.\"\"\"\n\nfrom reflex.components.radix.themes.layout.box import Box\n\n\n# Add responsive styles shortcuts.\ndef mobile_only(*children, **props):\n    \"\"\"Create a component that is only visible on mobile.\n\n    Args:\n        *children: The children to pass to the component.\n        **props: The props to pass to the component.\n\n    Returns:\n        The component.\n    \"\"\"\n    return Box.create(*children, **props, display=[\"block\", \"none\", \"none\", \"none\"])\n\n\ndef tablet_only(*children, **props):\n    \"\"\"Create a component that is only visible on tablet.\n\n    Args:\n        *children: The children to pass to the component.\n        **props: The props to pass to the component.\n\n    Returns:\n        The component.\n    \"\"\"\n    return Box.create(*children, **props, display=[\"none\", \"block\", \"block\", \"none\"])\n\n\ndef desktop_only(*children, **props):\n    \"\"\"Create a component that is only visible on desktop.\n\n    Args:\n        *children: The children to pass to the component.\n        **props: The props to pass to the component.\n\n    Returns:\n        The component.\n    \"\"\"\n    return Box.create(*children, **props, display=[\"none\", \"none\", \"none\", \"block\"])\n\n\ndef tablet_and_desktop(*children, **props):\n    \"\"\"Create a component that is only visible on tablet and desktop.\n\n    Args:\n        *children: The children to pass to the component.\n        **props: The props to pass to the component.\n\n    Returns:\n        The component.\n    \"\"\"\n    return Box.create(*children, **props, display=[\"none\", \"block\", \"block\", \"block\"])\n\n\ndef mobile_and_tablet(*children, **props):\n    \"\"\"Create a component that is only visible on mobile and tablet.\n\n    Args:\n        *children: The children to pass to the component.\n        **props: The props to pass to the component.\n\n    Returns:\n        The component.\n    \"\"\"\n    return Box.create(*children, **props, display=[\"block\", \"block\", \"block\", \"none\"])\n"
  },
  {
    "path": "reflex/components/core/sticky.py",
    "content": "\"\"\"Components for displaying the Reflex sticky logo.\"\"\"\n\nfrom reflex.components.component import ComponentNamespace\nfrom reflex.components.core.colors import color\nfrom reflex.components.core.cond import color_mode_cond\nfrom reflex.components.core.responsive import desktop_only\nfrom reflex.components.el.elements.inline import A\nfrom reflex.components.el.elements.media import Path, Rect, Svg\nfrom reflex.components.radix.themes.typography.text import Text\nfrom reflex.style import Style\n\n\nclass StickyLogo(Svg):\n    \"\"\"A simple Reflex logo SVG with only the letter R.\"\"\"\n\n    @classmethod\n    def create(cls):\n        \"\"\"Create the simple Reflex logo SVG.\n\n        Returns:\n            The simple Reflex logo SVG.\n        \"\"\"\n        return super().create(\n            Rect.create(width=\"16\", height=\"16\", rx=\"2\", fill=\"#6E56CF\"),\n            Path.create(d=\"M10 9V13H12V9H10Z\", fill=\"white\"),\n            Path.create(d=\"M4 3V13H6V9H10V7H6V5H10V7H12V3H4Z\", fill=\"white\"),\n            width=\"16\",\n            height=\"16\",\n            viewBox=\"0 0 16 16\",\n            xmlns=\"http://www.w3.org/2000/svg\",\n        )\n\n    def add_style(self):\n        \"\"\"Add the style to the component.\n\n        Returns:\n            The style of the component.\n        \"\"\"\n        return Style({\n            \"fill\": \"white\",\n        })\n\n\nclass StickyLabel(Text):\n    \"\"\"A label that displays the Reflex sticky.\"\"\"\n\n    @classmethod\n    def create(cls):\n        \"\"\"Create the sticky label.\n\n        Returns:\n            The sticky label.\n        \"\"\"\n        return super().create(\"Built with Reflex\")\n\n    def add_style(self):\n        \"\"\"Add the style to the component.\n\n        Returns:\n            The style of the component.\n        \"\"\"\n        return Style({\n            \"color\": color(\"slate\", 1),\n            \"font_weight\": \"600\",\n            \"font_family\": \"'Instrument Sans', sans-serif\",\n            \"font_size\": \"0.875rem\",\n            \"line_height\": \"1rem\",\n            \"letter_spacing\": \"-0.00656rem\",\n        })\n\n\nclass StickyBadge(A):\n    \"\"\"A badge that displays the Reflex sticky logo.\"\"\"\n\n    @classmethod\n    def create(cls):\n        \"\"\"Create the sticky badge.\n\n        Returns:\n            The sticky badge.\n        \"\"\"\n        return super().create(\n            StickyLogo.create(),\n            desktop_only(StickyLabel.create()),\n            href=\"https://reflex.dev\",\n            target=\"_blank\",\n            width=\"auto\",\n            padding=\"0.375rem\",\n            align=\"center\",\n            text_align=\"center\",\n        )\n\n    def add_style(self):\n        \"\"\"Add the style to the component.\n\n        Returns:\n            The style of the component.\n        \"\"\"\n        return Style(\n            {\n                \"position\": \"fixed\",\n                \"bottom\": \"1rem\",\n                \"right\": \"1rem\",\n                \"display\": \"flex\",\n                \"flex-direction\": \"row\",\n                \"gap\": \"0.375rem\",\n                \"align-items\": \"center\",\n                \"width\": \"auto\",\n                \"border-radius\": \"0.5rem\",\n                \"color\": color_mode_cond(\"#E5E7EB\", \"#27282B\"),\n                \"border\": color_mode_cond(\"1px solid #27282B\", \"1px solid #E5E7EB\"),\n                \"background-color\": color_mode_cond(\"#151618\", \"#FCFCFD\"),\n                \"padding\": \"0.375rem\",\n                \"transition\": \"background-color 0.2s ease-in-out\",\n                \"box-shadow\": \"0 1px 2px 0 rgba(0, 0, 0, 0.05)\",\n                \"z-index\": \"9998\",\n                \"cursor\": \"pointer\",\n            },\n        )\n\n\nclass StickyNamespace(ComponentNamespace):\n    \"\"\"Sticky components namespace.\"\"\"\n\n    __call__ = staticmethod(StickyBadge.create)\n    label = staticmethod(StickyLabel.create)\n    logo = staticmethod(StickyLogo.create)\n\n\nsticky = StickyNamespace()\n"
  },
  {
    "path": "reflex/components/core/upload.py",
    "content": "\"\"\"A file upload component.\"\"\"\n\nfrom __future__ import annotations\n\nfrom collections.abc import Callable, Sequence\nfrom pathlib import Path\nfrom typing import Any, ClassVar\n\nfrom reflex.app import UploadFile\nfrom reflex.components.base.fragment import Fragment\nfrom reflex.components.component import (\n    Component,\n    ComponentNamespace,\n    MemoizationLeaf,\n    StatefulComponent,\n    field,\n)\nfrom reflex.components.core.cond import cond\nfrom reflex.components.el.elements.forms import Input\nfrom reflex.components.radix.themes.layout.box import Box\nfrom reflex.components.sonner.toast import toast\nfrom reflex.constants import Dirs\nfrom reflex.constants.compiler import Hooks, Imports\nfrom reflex.environment import environment\nfrom reflex.event import (\n    CallableEventSpec,\n    EventChain,\n    EventHandler,\n    EventSpec,\n    call_event_fn,\n    call_event_handler,\n    parse_args_spec,\n    passthrough_event_spec,\n    run_script,\n    upload_files,\n)\nfrom reflex.style import Style\nfrom reflex.utils import format\nfrom reflex.utils.imports import ImportVar\nfrom reflex.vars import VarData\nfrom reflex.vars.base import Var, get_unique_variable_name\nfrom reflex.vars.function import FunctionVar\nfrom reflex.vars.object import ObjectVar\nfrom reflex.vars.sequence import ArrayVar, LiteralStringVar\n\nDEFAULT_UPLOAD_ID: str = \"default\"\n\nupload_files_context_var_data: VarData = VarData(\n    imports={\n        \"react\": \"useContext\",\n        f\"$/{Dirs.CONTEXTS_PATH}\": \"UploadFilesContext\",\n    },\n    hooks={\n        \"const [filesById, setFilesById] = useContext(UploadFilesContext);\": None,\n    },\n)\n\n\ndef upload_file(id_: str | Var[str] = DEFAULT_UPLOAD_ID) -> Var:\n    \"\"\"Get the file upload drop trigger.\n\n    This var is passed to the dropzone component to update the file list when a\n    drop occurs.\n\n    Args:\n        id_: The id of the upload to get the drop trigger for.\n\n    Returns:\n        A var referencing the file upload drop trigger.\n    \"\"\"\n    id_var = LiteralStringVar.create(id_) if not isinstance(id_, Var) else id_\n    var_name = f\"\"\"e => setFilesById(filesById => {{\n    const updatedFilesById = Object.assign({{}}, filesById);\n    updatedFilesById[{id_var!s}] = e;\n    return updatedFilesById;\n  }})\n    \"\"\"\n\n    return Var(\n        _js_expr=var_name,\n        _var_type=EventChain,\n        _var_data=VarData.merge(\n            upload_files_context_var_data, id_var._get_all_var_data()\n        ),\n    )\n\n\ndef selected_files(id_: str | Var[str] = DEFAULT_UPLOAD_ID) -> Var:\n    \"\"\"Get the list of selected files.\n\n    Args:\n        id_: The id of the upload to get the selected files for.\n\n    Returns:\n        A var referencing the list of selected file paths.\n    \"\"\"\n    id_var = LiteralStringVar.create(id_) if not isinstance(id_, Var) else id_\n    return Var(\n        _js_expr=f\"(filesById[{id_var!s}] ? filesById[{id_var!s}].map((f) => f.name) : [])\",\n        _var_type=list[str],\n        _var_data=VarData.merge(\n            upload_files_context_var_data, id_var._get_all_var_data()\n        ),\n    ).guess_type()\n\n\n@CallableEventSpec\ndef clear_selected_files(id_: str = DEFAULT_UPLOAD_ID) -> EventSpec:\n    \"\"\"Clear the list of selected files.\n\n    Args:\n        id_: The id of the upload to clear.\n\n    Returns:\n        An event spec that clears the list of selected files when triggered.\n    \"\"\"\n    # UploadFilesProvider assigns a special function to clear selected files\n    # into the shared global refs object to make it accessible outside a React\n    # component via `run_script` (otherwise backend could never clear files).\n    return run_script(Var(\"__clear_selected_files\")._as_ref().to(FunctionVar).call(id_))\n\n\ndef cancel_upload(upload_id: str) -> EventSpec:\n    \"\"\"Cancel an upload.\n\n    Args:\n        upload_id: The id of the upload to cancel.\n\n    Returns:\n        An event spec that cancels the upload when triggered.\n    \"\"\"\n    controller = Var(f\"__upload_controllers_{upload_id}\")._as_ref()\n    return run_script(f\"{controller}?.abort()\")\n\n\ndef get_upload_dir() -> Path:\n    \"\"\"Get the directory where uploaded files are stored.\n\n    Returns:\n        The directory where uploaded files are stored.\n    \"\"\"\n    Upload.is_used = True\n\n    uploaded_files_dir = environment.REFLEX_UPLOADED_FILES_DIR.get()\n    uploaded_files_dir.mkdir(parents=True, exist_ok=True)\n    return uploaded_files_dir\n\n\nuploaded_files_url_prefix = Var(\n    _js_expr=\"getBackendURL(env.UPLOAD)\",\n    _var_data=VarData(\n        imports={\n            f\"$/{Dirs.STATE_PATH}\": \"getBackendURL\",\n            \"$/env.json\": ImportVar(tag=\"env\", is_default=True),\n        }\n    ),\n).to(str)\n\n\ndef get_upload_url(file_path: str | Var[str]) -> Var[str]:\n    \"\"\"Get the URL of an uploaded file.\n\n    Args:\n        file_path: The path of the uploaded file.\n\n    Returns:\n        The URL of the uploaded file to be rendered from the frontend (as a str-encoded Var).\n    \"\"\"\n    Upload.is_used = True\n\n    return Var.create(f\"{uploaded_files_url_prefix}/{file_path}\")\n\n\n_on_drop_spec = passthrough_event_spec(list[UploadFile])\n\n\ndef _default_drop_rejected(rejected_files: ArrayVar[list[dict[str, Any]]]) -> EventSpec:\n    \"\"\"Event handler for showing a toast with rejected file info.\n\n    Args:\n        rejected_files: The files that were rejected.\n\n    Returns:\n        An event spec that shows a toast with the rejected file info when triggered.\n    \"\"\"\n\n    def _format_rejected_file_record(rf: ObjectVar[dict[str, Any]]) -> str:\n        rf = rf.to(ObjectVar, dict[str, dict[str, Any]])\n        file = rf[\"file\"].to(ObjectVar, dict[str, Any])\n        errors = rf[\"errors\"].to(ArrayVar, list[dict[str, Any]])\n        return f\"{file['path']}: {errors.foreach(lambda kv: kv['message']).join(', ')}\"  # noqa: FURB118\n\n    return toast.error(\n        title=\"Files not Accepted\",\n        description=rejected_files\n        .to(ArrayVar)\n        .foreach(_format_rejected_file_record)\n        .join(\"\\n\\n\"),\n        close_button=True,\n        style={\"white_space\": \"pre-line\"},\n    )\n\n\nclass UploadFilesProvider(Component):\n    \"\"\"AppWrap component that provides a dict of selected files by ID via useContext.\"\"\"\n\n    library = f\"$/{Dirs.CONTEXTS_PATH}\"\n    tag = \"UploadFilesProvider\"\n\n\nclass GhostUpload(Fragment):\n    \"\"\"A ghost upload component.\"\"\"\n\n    # Fired when files are dropped.\n    on_drop: EventHandler[_on_drop_spec]\n\n    # Fired when dropped files do not meet the specified criteria.\n    on_drop_rejected: EventHandler[_on_drop_spec]\n\n\nclass Upload(MemoizationLeaf):\n    \"\"\"A file upload component.\"\"\"\n\n    library = \"react-dropzone@15.0.0\"\n\n    tag = \"\"\n\n    # The list of accepted file types. This should be a dictionary of MIME types as keys and array of file formats as\n    # values.\n    # supported MIME types: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types\n    accept: Var[dict[str, Sequence] | None]\n\n    # Whether the dropzone is disabled.\n    disabled: Var[bool]\n\n    # The maximum number of files that can be uploaded.\n    max_files: Var[int]\n\n    # The maximum file size (bytes) that can be uploaded.\n    max_size: Var[int]\n\n    # The minimum file size (bytes) that can be uploaded.\n    min_size: Var[int]\n\n    # Whether to allow multiple files to be uploaded.\n    multiple: Var[bool]\n\n    # Whether to disable click to upload.\n    no_click: Var[bool]\n\n    # Whether to disable drag and drop.\n    no_drag: Var[bool]\n\n    # Whether to disable using the space/enter keys to upload.\n    no_keyboard: Var[bool]\n\n    # Marked True when any Upload component is created.\n    is_used: ClassVar[bool] = False\n\n    # Fired when files are dropped.\n    on_drop: EventHandler[_on_drop_spec]\n\n    # Fired when dropped files do not meet the specified criteria.\n    on_drop_rejected: EventHandler[_on_drop_spec]\n\n    # Style rules to apply when actively dragging.\n    drag_active_style: Style | None = field(default=None, is_javascript_property=False)\n\n    @classmethod\n    def create(cls, *children, **props) -> Component:\n        \"\"\"Create an upload component.\n\n        Args:\n            *children: The children of the component.\n            **props: The properties of the component.\n\n        Returns:\n            The upload component.\n        \"\"\"\n        # Mark the Upload component as used in the app.\n        cls.is_used = True\n\n        props.setdefault(\"multiple\", True)\n\n        # Apply the default classname\n        given_class_name = props.pop(\"class_name\", [])\n        if isinstance(given_class_name, str):\n            given_class_name = [given_class_name]\n        props[\"class_name\"] = [\"rx-Upload\", *given_class_name]\n\n        # get only upload component props\n        supported_props = set(cls.get_props()) | {\"on_drop\"}\n        upload_props = {\n            key: value for key, value in props.items() if key in supported_props\n        }\n\n        # Create the component.\n        upload_props[\"id\"] = upload_id = props.get(\"id\", DEFAULT_UPLOAD_ID)\n\n        if upload_props.get(\"on_drop\") is None:\n            # If on_drop is not provided, save files to be uploaded later.\n            upload_props[\"on_drop\"] = upload_file(upload_id)\n        else:\n            on_drop = (\n                [on_drop_prop]\n                if not isinstance(on_drop_prop := upload_props[\"on_drop\"], Sequence)\n                else list(on_drop_prop)\n            )\n            for ix, event in enumerate(on_drop):\n                if isinstance(event, EventHandler):\n                    event = event(upload_files(upload_id))\n                if isinstance(event, EventSpec):\n                    # Call the lambda to get the event chain.\n                    event = call_event_handler(event, _on_drop_spec)\n                elif isinstance(event, Callable):\n                    # Call the lambda to get the event chain.\n                    event = call_event_fn(event, _on_drop_spec)\n                if isinstance(event, EventSpec):\n                    # Update the provided args for direct use with on_drop.\n                    event = event.with_args(\n                        args=tuple(\n                            cls._update_arg_tuple_for_on_drop(arg_value)\n                            for arg_value in event.args\n                        ),\n                    )\n                on_drop[ix] = event\n            upload_props[\"on_drop\"] = on_drop\n\n        if upload_props.get(\"on_drop_rejected\") is None:\n            # If on_drop_rejected is not provided, show an error toast.\n            upload_props[\"on_drop_rejected\"] = _default_drop_rejected\n\n        input_props_unique_name = get_unique_variable_name()\n        root_props_unique_name = get_unique_variable_name()\n        is_drag_active_unique_name = get_unique_variable_name()\n        drag_active_css_class_unique_name = get_unique_variable_name() + \"-drag-active\"\n\n        # Handle special style when dragging over the drop zone.\n        if \"drag_active_style\" in props:\n            props.setdefault(\"style\", Style())[\n                f\"&:where(.{drag_active_css_class_unique_name})\"\n            ] = props.pop(\"drag_active_style\")\n            props[\"class_name\"].append(\n                cond(\n                    Var(is_drag_active_unique_name),\n                    drag_active_css_class_unique_name,\n                    \"\",\n                ),\n            )\n\n        event_triggers = StatefulComponent._get_memoized_event_triggers(\n            GhostUpload.create(\n                on_drop=upload_props[\"on_drop\"],\n                on_drop_rejected=upload_props[\"on_drop_rejected\"],\n            )\n        )\n        callback_hooks = []\n        for trigger_name, (event_var, callback_str) in event_triggers.items():\n            upload_props[trigger_name] = event_var\n            callback_hooks.append(callback_str)\n\n        upload_props = {\n            format.to_camel_case(key): value for key, value in upload_props.items()\n        }\n\n        use_dropzone_arguments = Var.create(upload_props)\n\n        left_side = (\n            \"const { \"\n            f\"getRootProps: {root_props_unique_name}, \"\n            f\"getInputProps: {input_props_unique_name}, \"\n            f\"isDragActive: {is_drag_active_unique_name}\"\n            \"}\"\n        )\n        right_side = f\"useDropzone({use_dropzone_arguments!s})\"\n\n        var_data = VarData.merge(\n            VarData(\n                imports=Imports.EVENTS,\n                hooks={Hooks.EVENTS: None},\n            ),\n            use_dropzone_arguments._get_all_var_data(),\n            VarData(\n                hooks={\n                    **dict.fromkeys(callback_hooks, None),\n                    f\"{left_side} = {right_side};\": None,\n                },\n                imports={\n                    \"react-dropzone\": \"useDropzone\",\n                    **Imports.EVENTS,\n                },\n            ),\n        )\n\n        # The file input to use.\n        upload = Input.create(type=\"file\")\n        upload.special_props = [\n            Var(\n                _js_expr=f\"{input_props_unique_name}()\",\n                _var_type=None,\n                _var_data=var_data,\n            )\n        ]\n\n        # The dropzone to use.\n        zone = Box.create(\n            upload,\n            *children,\n            **{k: v for k, v in props.items() if k not in supported_props},\n        )\n        zone.special_props = [\n            Var(\n                _js_expr=f\"{root_props_unique_name}()\",\n                _var_type=None,\n                _var_data=var_data,\n            )\n        ]\n\n        return super().create(\n            zone,\n        )\n\n    @classmethod\n    def _update_arg_tuple_for_on_drop(cls, arg_value: tuple[Var, Var]):\n        \"\"\"Helper to update caller-provided EventSpec args for direct use with on_drop.\n\n        Args:\n            arg_value: The arg tuple to update (if necessary).\n\n        Returns:\n            The updated arg_value tuple when arg is \"files\", otherwise the original arg_value.\n        \"\"\"\n        if arg_value[0]._js_expr == \"files\":\n            placeholders, _ = parse_args_spec(_on_drop_spec)\n            placeholder = placeholders[0]\n            return (arg_value[0], placeholder)\n        return arg_value\n\n    @staticmethod\n    def _get_app_wrap_components() -> dict[tuple[int, str], Component]:\n        return {\n            (5, \"UploadFilesProvider\"): UploadFilesProvider.create(),\n        }\n\n\nclass StyledUpload(Upload):\n    \"\"\"The styled Upload Component.\"\"\"\n\n    @classmethod\n    def create(cls, *children, **props) -> Component:\n        \"\"\"Create the styled upload component.\n\n        Args:\n            *children: The children of the component.\n            **props: The properties of the component.\n\n        Returns:\n            The styled upload component.\n        \"\"\"\n        # Set default props.\n        props.setdefault(\"border\", \"1px dashed var(--accent-12)\")\n        props.setdefault(\"padding\", \"5em\")\n        props.setdefault(\"textAlign\", \"center\")\n\n        # Mark the Upload component as used in the app.\n        Upload.is_used = True\n\n        return super().create(\n            *children,\n            **props,\n        )\n\n\nclass UploadNamespace(ComponentNamespace):\n    \"\"\"Upload component namespace.\"\"\"\n\n    root = Upload.create\n    __call__ = StyledUpload.create\n\n\nupload = UploadNamespace()\n"
  },
  {
    "path": "reflex/components/core/window_events.py",
    "content": "\"\"\"Window event listener component for Reflex.\"\"\"\n\nfrom __future__ import annotations\n\nfrom typing import Any, cast\n\nimport reflex as rx\nfrom reflex.components.base.fragment import Fragment\nfrom reflex.components.component import StatefulComponent, field\nfrom reflex.constants.compiler import Hooks\nfrom reflex.event import key_event, no_args_event_spec\nfrom reflex.vars.base import Var, VarData\nfrom reflex.vars.object import ObjectVar\n\n\ndef _on_resize_spec() -> tuple[Var[int], Var[int]]:\n    \"\"\"Args spec for the on_resize event trigger.\n\n    Returns:\n        A tuple containing window width and height variables.\n    \"\"\"\n    return (Var(\"window.innerWidth\"), Var(\"window.innerHeight\"))\n\n\ndef _on_scroll_spec() -> tuple[Var[float], Var[float]]:\n    \"\"\"Args spec for the on_scroll event trigger.\n\n    Returns:\n        A tuple containing window scroll X and Y position variables.\n    \"\"\"\n    return (Var(\"window.scrollX\"), Var(\"window.scrollY\"))\n\n\ndef _on_visibility_change_spec() -> tuple[Var[bool]]:\n    \"\"\"Args spec for the on_visibility_change event trigger.\n\n    Returns:\n        A tuple containing the document hidden state variable.\n    \"\"\"\n    return (Var(\"document.hidden\"),)\n\n\ndef _on_storage_spec(e: ObjectVar) -> tuple[Var[str], Var[str], Var[str], Var[str]]:\n    \"\"\"Args spec for the on_storage event trigger.\n\n    Args:\n        e: The storage event.\n\n    Returns:\n        A tuple containing key, old value, new value, and URL variables.\n    \"\"\"\n    return (e.key.to(str), e.oldValue.to(str), e.newValue.to(str), e.url.to(str))\n\n\nclass WindowEventListener(Fragment):\n    \"\"\"A component that listens for window events.\"\"\"\n\n    # Event handlers\n    on_resize: rx.EventHandler[_on_resize_spec]\n    on_scroll: rx.EventHandler[_on_scroll_spec]\n    on_focus: rx.EventHandler[no_args_event_spec]\n    on_blur: rx.EventHandler[no_args_event_spec]\n    on_visibility_change: rx.EventHandler[_on_visibility_change_spec]\n    on_before_unload: rx.EventHandler[no_args_event_spec]\n    on_key_down: rx.EventHandler[key_event]\n    on_popstate: rx.EventHandler[no_args_event_spec]\n    on_storage: rx.EventHandler[_on_storage_spec]\n\n    hooks: list[str] = field(default_factory=list, is_javascript_property=False)\n\n    @classmethod\n    def create(cls, **props) -> WindowEventListener:\n        \"\"\"Create a WindowEventListener component.\n\n        Args:\n            **props: The props to set on the component.\n\n        Returns:\n            The created component.\n        \"\"\"\n        real_component = cast(\"WindowEventListener\", super().create(**props))\n        hooks = StatefulComponent._fix_event_triggers(real_component)\n        real_component.hooks = hooks\n        return real_component\n\n    def _exclude_props(self) -> list[str]:\n        \"\"\"Exclude event handler props from being passed to Fragment.\n\n        Returns:\n            List of prop names to exclude from the Fragment.\n        \"\"\"\n        return [*super()._exclude_props(), *self.event_triggers.keys()]\n\n    def add_hooks(self) -> list[str | Var[Any]]:\n        \"\"\"Add hooks to register window event listeners.\n\n        Returns:\n            The hooks to add to the component.\n        \"\"\"\n        hooks: list[str | Var[Any]] = [*self.hooks]\n\n        for prop_name, event_trigger in self.event_triggers.items():\n            # Get JS event name: remove on_ prefix and underscores\n            event_name = prop_name.removeprefix(\"on_\").replace(\"_\", \"\")\n\n            hook_expr = f\"\"\"\nuseEffect(() => {{\n    if (typeof window === 'undefined') return;\n    const fn = {Var.create(event_trigger)};\n    window.addEventListener('{event_name}', fn);\n    return () => window.removeEventListener('{event_name}', fn);\n}}, []);\n                \"\"\"\n\n            hooks.append(\n                Var(\n                    hook_expr,\n                    _var_data=VarData(position=Hooks.HookPosition.POST_TRIGGER),\n                )\n            )\n\n        return hooks\n\n\nwindow_event_listener = WindowEventListener.create\n"
  },
  {
    "path": "reflex/components/datadisplay/__init__.py",
    "content": "\"\"\"Data grid components.\"\"\"\n\nfrom __future__ import annotations\n\nfrom reflex.utils import lazy_loader\n\n_SUBMOD_ATTRS: dict[str, list[str]] = {\n    \"code\": [\n        \"CodeBlock\",\n        \"code_block\",\n        \"LiteralCodeLanguage\",\n    ],\n    \"dataeditor\": [\"data_editor\", \"data_editor_theme\", \"DataEditorTheme\"],\n    \"logo\": [\"logo\"],\n}\n\n__getattr__, __dir__, __all__ = lazy_loader.attach(\n    __name__,\n    submod_attrs=_SUBMOD_ATTRS,\n)\n"
  },
  {
    "path": "reflex/components/datadisplay/code.py",
    "content": "\"\"\"A code component.\"\"\"\n\nfrom __future__ import annotations\n\nimport dataclasses\nfrom typing import ClassVar, Literal\n\nfrom reflex.components.component import Component, ComponentNamespace, field\nfrom reflex.components.core.cond import color_mode_cond\nfrom reflex.components.lucide.icon import Icon\nfrom reflex.components.markdown.markdown import MarkdownComponentMap\nfrom reflex.components.radix.themes.components.button import Button\nfrom reflex.components.radix.themes.layout.box import Box\nfrom reflex.constants.colors import Color\nfrom reflex.event import set_clipboard\nfrom reflex.style import Style\nfrom reflex.utils import format\nfrom reflex.utils.imports import ImportVar\nfrom reflex.vars.base import LiteralVar, Var, VarData\n\nLiteralCodeLanguage = Literal[\n    \"abap\",\n    \"abnf\",\n    \"actionscript\",\n    \"ada\",\n    \"agda\",\n    \"al\",\n    \"antlr4\",\n    \"apacheconf\",\n    \"apex\",\n    \"apl\",\n    \"applescript\",\n    \"aql\",\n    \"arduino\",\n    \"arff\",\n    \"asciidoc\",\n    \"asm6502\",\n    \"asmatmel\",\n    \"aspnet\",\n    \"autohotkey\",\n    \"autoit\",\n    \"avisynth\",\n    \"avro-idl\",\n    \"bash\",\n    \"basic\",\n    \"batch\",\n    \"bbcode\",\n    \"bicep\",\n    \"birb\",\n    \"bison\",\n    \"bnf\",\n    \"brainfuck\",\n    \"brightscript\",\n    \"bro\",\n    \"bsl\",\n    \"c\",\n    \"cfscript\",\n    \"chaiscript\",\n    \"cil\",\n    \"clike\",\n    \"clojure\",\n    \"cmake\",\n    \"cobol\",\n    \"coffeescript\",\n    \"concurnas\",\n    \"coq\",\n    \"core\",\n    \"cpp\",\n    \"crystal\",\n    \"csharp\",\n    \"cshtml\",\n    \"csp\",\n    \"css\",\n    \"css-extras\",\n    \"csv\",\n    \"cypher\",\n    \"d\",\n    \"dart\",\n    \"dataweave\",\n    \"dax\",\n    \"dhall\",\n    \"diff\",\n    \"django\",\n    \"dns-zone-file\",\n    \"docker\",\n    \"dot\",\n    \"ebnf\",\n    \"editorconfig\",\n    \"eiffel\",\n    \"ejs\",\n    \"elixir\",\n    \"elm\",\n    \"erb\",\n    \"erlang\",\n    \"etlua\",\n    \"excel-formula\",\n    \"factor\",\n    \"false\",\n    \"firestore-security-rules\",\n    \"flow\",\n    \"fortran\",\n    \"fsharp\",\n    \"ftl\",\n    \"gap\",\n    \"gcode\",\n    \"gdscript\",\n    \"gedcom\",\n    \"gherkin\",\n    \"git\",\n    \"glsl\",\n    \"gml\",\n    \"gn\",\n    \"go\",\n    \"go-module\",\n    \"graphql\",\n    \"groovy\",\n    \"haml\",\n    \"handlebars\",\n    \"haskell\",\n    \"haxe\",\n    \"hcl\",\n    \"hlsl\",\n    \"hoon\",\n    \"hpkp\",\n    \"hsts\",\n    \"http\",\n    \"ichigojam\",\n    \"icon\",\n    \"icu-message-format\",\n    \"idris\",\n    \"iecst\",\n    \"ignore\",\n    \"index\",\n    \"inform7\",\n    \"ini\",\n    \"io\",\n    \"j\",\n    \"java\",\n    \"javadoc\",\n    \"javadoclike\",\n    \"javascript\",\n    \"javastacktrace\",\n    \"jexl\",\n    \"jolie\",\n    \"jq\",\n    \"js-extras\",\n    \"js-templates\",\n    \"jsdoc\",\n    \"json\",\n    \"json5\",\n    \"jsonp\",\n    \"jsstacktrace\",\n    \"jsx\",\n    \"julia\",\n    \"keepalived\",\n    \"keyman\",\n    \"kotlin\",\n    \"kumir\",\n    \"kusto\",\n    \"latex\",\n    \"latte\",\n    \"less\",\n    \"lilypond\",\n    \"liquid\",\n    \"lisp\",\n    \"livescript\",\n    \"llvm\",\n    \"log\",\n    \"lolcode\",\n    \"lua\",\n    \"magma\",\n    \"makefile\",\n    \"markdown\",\n    \"markup\",\n    \"markup-templating\",\n    \"matlab\",\n    \"maxscript\",\n    \"mel\",\n    \"mermaid\",\n    \"mizar\",\n    \"mongodb\",\n    \"monkey\",\n    \"moonscript\",\n    \"n1ql\",\n    \"n4js\",\n    \"nand2tetris-hdl\",\n    \"naniscript\",\n    \"nasm\",\n    \"neon\",\n    \"nevod\",\n    \"nginx\",\n    \"nim\",\n    \"nix\",\n    \"nsis\",\n    \"objectivec\",\n    \"ocaml\",\n    \"opencl\",\n    \"openqasm\",\n    \"oz\",\n    \"parigp\",\n    \"parser\",\n    \"pascal\",\n    \"pascaligo\",\n    \"pcaxis\",\n    \"peoplecode\",\n    \"perl\",\n    \"php\",\n    \"php-extras\",\n    \"phpdoc\",\n    \"plsql\",\n    \"powerquery\",\n    \"powershell\",\n    \"processing\",\n    \"prolog\",\n    \"promql\",\n    \"properties\",\n    \"protobuf\",\n    \"psl\",\n    \"pug\",\n    \"puppet\",\n    \"pure\",\n    \"purebasic\",\n    \"purescript\",\n    \"python\",\n    \"q\",\n    \"qml\",\n    \"qore\",\n    \"qsharp\",\n    \"r\",\n    \"racket\",\n    \"reason\",\n    \"regex\",\n    \"rego\",\n    \"renpy\",\n    \"rest\",\n    \"rip\",\n    \"roboconf\",\n    \"robotframework\",\n    \"ruby\",\n    \"rust\",\n    \"sas\",\n    \"sass\",\n    \"scala\",\n    \"scheme\",\n    \"scss\",\n    \"shell-session\",\n    \"smali\",\n    \"smalltalk\",\n    \"smarty\",\n    \"sml\",\n    \"solidity\",\n    \"solution-file\",\n    \"soy\",\n    \"sparql\",\n    \"splunk-spl\",\n    \"sqf\",\n    \"sql\",\n    \"squirrel\",\n    \"stan\",\n    \"stylus\",\n    \"swift\",\n    \"systemd\",\n    \"t4-cs\",\n    \"t4-templating\",\n    \"t4-vb\",\n    \"tap\",\n    \"tcl\",\n    \"textile\",\n    \"toml\",\n    \"tremor\",\n    \"tsx\",\n    \"tt2\",\n    \"turtle\",\n    \"twig\",\n    \"typescript\",\n    \"typoscript\",\n    \"unrealscript\",\n    \"uorazor\",\n    \"uri\",\n    \"v\",\n    \"vala\",\n    \"vbnet\",\n    \"velocity\",\n    \"verilog\",\n    \"vhdl\",\n    \"vim\",\n    \"visual-basic\",\n    \"warpscript\",\n    \"wasm\",\n    \"web-idl\",\n    \"wiki\",\n    \"wolfram\",\n    \"wren\",\n    \"xeora\",\n    \"xml-doc\",\n    \"xojo\",\n    \"xquery\",\n    \"yaml\",\n    \"yang\",\n    \"zig\",\n]\n\n\ndef construct_theme_var(theme: str) -> Var[Theme]:\n    \"\"\"Construct a theme var.\n\n    Args:\n        theme: The theme to construct.\n\n    Returns:\n        The constructed theme var.\n    \"\"\"\n    return Var(\n        theme,\n        _var_data=VarData(\n            imports={\n                f\"react-syntax-highlighter/dist/esm/styles/prism/{format.to_kebab_case(theme)}\": [\n                    ImportVar(tag=theme, is_default=True, install=False)\n                ]\n            }\n        ),\n    )\n\n\n@dataclasses.dataclass(init=False)\nclass Theme:\n    \"\"\"Themes for the CodeBlock component.\"\"\"\n\n    a11y_dark: ClassVar[Var[Theme]] = construct_theme_var(\"a11yDark\")\n    atom_dark: ClassVar[Var[Theme]] = construct_theme_var(\"atomDark\")\n    cb: ClassVar[Var[Theme]] = construct_theme_var(\"cb\")\n    coldark_cold: ClassVar[Var[Theme]] = construct_theme_var(\"coldarkCold\")\n    coldark_dark: ClassVar[Var[Theme]] = construct_theme_var(\"coldarkDark\")\n    coy: ClassVar[Var[Theme]] = construct_theme_var(\"coy\")\n    coy_without_shadows: ClassVar[Var[Theme]] = construct_theme_var(\"coyWithoutShadows\")\n    darcula: ClassVar[Var[Theme]] = construct_theme_var(\"darcula\")\n    dark: ClassVar[Var[Theme]] = construct_theme_var(\"oneDark\")\n    dracula: ClassVar[Var[Theme]] = construct_theme_var(\"dracula\")\n    duotone_dark: ClassVar[Var[Theme]] = construct_theme_var(\"duotoneDark\")\n    duotone_earth: ClassVar[Var[Theme]] = construct_theme_var(\"duotoneEarth\")\n    duotone_forest: ClassVar[Var[Theme]] = construct_theme_var(\"duotoneForest\")\n    duotone_light: ClassVar[Var[Theme]] = construct_theme_var(\"duotoneLight\")\n    duotone_sea: ClassVar[Var[Theme]] = construct_theme_var(\"duotoneSea\")\n    duotone_space: ClassVar[Var[Theme]] = construct_theme_var(\"duotoneSpace\")\n    funky: ClassVar[Var[Theme]] = construct_theme_var(\"funky\")\n    ghcolors: ClassVar[Var[Theme]] = construct_theme_var(\"ghcolors\")\n    gruvbox_dark: ClassVar[Var[Theme]] = construct_theme_var(\"gruvboxDark\")\n    gruvbox_light: ClassVar[Var[Theme]] = construct_theme_var(\"gruvboxLight\")\n    holi_theme: ClassVar[Var[Theme]] = construct_theme_var(\"holiTheme\")\n    hopscotch: ClassVar[Var[Theme]] = construct_theme_var(\"hopscotch\")\n    light: ClassVar[Var[Theme]] = construct_theme_var(\"oneLight\")\n    lucario: ClassVar[Var[Theme]] = construct_theme_var(\"lucario\")\n    material_dark: ClassVar[Var[Theme]] = construct_theme_var(\"materialDark\")\n    material_light: ClassVar[Var[Theme]] = construct_theme_var(\"materialLight\")\n    material_oceanic: ClassVar[Var[Theme]] = construct_theme_var(\"materialOceanic\")\n    night_owl: ClassVar[Var[Theme]] = construct_theme_var(\"nightOwl\")\n    nord: ClassVar[Var[Theme]] = construct_theme_var(\"nord\")\n    okaidia: ClassVar[Var[Theme]] = construct_theme_var(\"okaidia\")\n    one_dark: ClassVar[Var[Theme]] = construct_theme_var(\"oneDark\")\n    one_light: ClassVar[Var[Theme]] = construct_theme_var(\"oneLight\")\n    pojoaque: ClassVar[Var[Theme]] = construct_theme_var(\"pojoaque\")\n    prism: ClassVar[Var[Theme]] = construct_theme_var(\"prism\")\n    shades_of_purple: ClassVar[Var[Theme]] = construct_theme_var(\"shadesOfPurple\")\n    solarized_dark_atom: ClassVar[Var[Theme]] = construct_theme_var(\"solarizedDarkAtom\")\n    solarizedlight: ClassVar[Var[Theme]] = construct_theme_var(\"solarizedlight\")\n    synthwave84: ClassVar[Var[Theme]] = construct_theme_var(\"synthwave84\")\n    tomorrow: ClassVar[Var[Theme]] = construct_theme_var(\"tomorrow\")\n    twilight: ClassVar[Var[Theme]] = construct_theme_var(\"twilight\")\n    vs: ClassVar[Var[Theme]] = construct_theme_var(\"vs\")\n    vs_dark: ClassVar[Var[Theme]] = construct_theme_var(\"vsDark\")\n    vsc_dark_plus: ClassVar[Var[Theme]] = construct_theme_var(\"vscDarkPlus\")\n    xonokai: ClassVar[Var[Theme]] = construct_theme_var(\"xonokai\")\n    z_touch: ClassVar[Var[Theme]] = construct_theme_var(\"zTouch\")\n\n\nfor theme_name in dir(Theme):\n    if theme_name.startswith(\"_\"):\n        continue\n    setattr(Theme, theme_name, getattr(Theme, theme_name)._replace(_var_type=Theme))\n\n\nclass CodeBlock(Component, MarkdownComponentMap):\n    \"\"\"A code block.\"\"\"\n\n    library = \"react-syntax-highlighter@16.1.1\"\n\n    tag = \"PrismAsyncLight\"\n\n    alias = \"SyntaxHighlighter\"\n\n    # The theme to use (\"light\" or \"dark\").\n    theme: Var[Theme | str] = Theme.one_light\n\n    # The language to use.\n    language: Var[LiteralCodeLanguage] = Var.create(\"python\")\n\n    # The code to display.\n    code: Var[str]\n\n    # If this is enabled line numbers will be shown next to the code block.\n    show_line_numbers: Var[bool]\n\n    # The starting line number to use.\n    starting_line_number: Var[int]\n\n    # Whether to wrap long lines.\n    wrap_long_lines: Var[bool]\n\n    # A custom style for the code block.\n    custom_style: dict[str, str | Var | Color] = field(\n        default_factory=dict, is_javascript_property=False\n    )\n\n    # Props passed down to the code tag.\n    code_tag_props: Var[dict[str, str | dict[str, str]]]\n\n    # Whether a copy button should appear.\n    can_copy: bool | None = field(\n        default=False,\n        is_javascript_property=False,\n    )\n\n    # A custom copy button to override the default one.\n    copy_button: bool | Component | None = field(\n        default=None,\n        is_javascript_property=False,\n    )\n\n    @classmethod\n    def create(\n        cls,\n        *children,\n        **props,\n    ):\n        \"\"\"Create a text component.\n\n        Args:\n            *children: The children of the component.\n            **props: The props to pass to the component.\n\n        Returns:\n            The text component.\n        \"\"\"\n        # This component handles style in a special prop.\n        custom_style = props.pop(\"custom_style\", {})\n        can_copy = props.pop(\"can_copy\", False)\n        copy_button = props.pop(\"copy_button\", None)\n\n        # react-syntax-highlighter doesn't have an explicit \"light\" or \"dark\" theme so we use one-light and one-dark\n        # themes respectively to ensure code compatibility.\n        if \"theme\" not in props:\n            # Default color scheme responds to global color mode.\n            props[\"theme\"] = color_mode_cond(\n                light=Theme.one_light,\n                dark=Theme.one_dark,\n            )\n\n        if can_copy:\n            code = children[0]\n            copy_button = (\n                copy_button\n                if copy_button is not None\n                else Button.create(\n                    Icon.create(tag=\"copy\"),\n                    on_click=set_clipboard(code),\n                    style=Style({\"position\": \"absolute\", \"top\": \"0.5em\", \"right\": \"0\"}),\n                )\n            )\n            custom_style.update({\"padding\": \"1em 3.2em 1em 1em\"})\n        else:\n            copy_button = None\n\n        # Transfer style props to the custom style prop.\n        for key, value in props.items():\n            if key not in cls.get_fields():\n                custom_style[key] = value\n\n        # Carry the children (code) via props\n        if children:\n            props[\"code\"] = children[0]\n            if not isinstance(props[\"code\"], Var):\n                props[\"code\"] = LiteralVar.create(props[\"code\"])\n\n        # Create the component.\n        code_block = super().create(\n            **props,\n            custom_style=Style(custom_style),\n        )\n\n        if copy_button:\n            return Box.create(code_block, copy_button, position=\"relative\")\n        return code_block\n\n    def add_style(self):\n        \"\"\"Add style to the component.\"\"\"\n        self.custom_style.update(self.style)\n\n    def _render(self):\n        out = super()._render()\n\n        theme = self.theme\n\n        return (\n            out\n            .add_props(style=theme)\n            .remove_props(\"theme\", \"code\")\n            .add_props(\n                children=self.code,\n            )\n        )\n\n\nclass CodeblockNamespace(ComponentNamespace):\n    \"\"\"Namespace for the CodeBlock component.\"\"\"\n\n    themes = Theme\n\n    __call__ = CodeBlock.create\n\n\ncode_block = CodeblockNamespace()\n"
  },
  {
    "path": "reflex/components/datadisplay/dataeditor.py",
    "content": "\"\"\"Data Editor component from glide-data-grid.\"\"\"\n\nfrom __future__ import annotations\n\nimport dataclasses\nfrom collections.abc import Mapping, Sequence\nfrom enum import Enum\nfrom typing import Any, Literal, TypedDict\n\nfrom reflex.components.component import Component, NoSSRComponent\nfrom reflex.components.literals import LiteralRowMarker\nfrom reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec\nfrom reflex.utils import console, format, types\nfrom reflex.utils.imports import ImportDict, ImportVar\nfrom reflex.utils.serializers import serializer\nfrom reflex.vars import get_unique_variable_name\nfrom reflex.vars.base import Var\nfrom reflex.vars.function import FunctionStringVar\nfrom reflex.vars.sequence import ArrayVar\n\n\n# TODO: Fix the serialization issue for custom types.\nclass GridColumnIcons(Enum):\n    \"\"\"An Enum for the available icons in DataEditor.\"\"\"\n\n    Array = \"array\"\n    AudioUri = \"audio_uri\"\n    Boolean = \"boolean\"\n    HeaderCode = \"code\"\n    Date = \"date\"\n    Email = \"email\"\n    Emoji = \"emoji\"\n    GeoDistance = \"geo_distance\"\n    IfThenElse = \"if_then_else\"\n    Image = \"image\"\n    JoinStrings = \"join_strings\"\n    Lookup = \"lookup\"\n    Markdown = \"markdown\"\n    Math = \"math\"\n    Number = \"number\"\n    Phone = \"phone\"\n    Reference = \"reference\"\n    Rollup = \"rollup\"\n    RowID = \"row_id\"\n    SingleValue = \"single_value\"\n    SplitString = \"split_string\"\n    String = \"string\"\n    TextTemplate = \"text_template\"\n    Time = \"time\"\n    Uri = \"uri\"\n    VideoUri = \"video_uri\"\n\n\n@dataclasses.dataclass\nclass DataEditorThemeBase:\n    \"\"\"The theme for the DataEditor component.\"\"\"\n\n    accent_color: str | None = None\n    accent_fg: str | None = None\n    accent_light: str | None = None\n    base_font_style: str | None = None\n    bg_bubble: str | None = None\n    bg_bubble_selected: str | None = None\n    bg_cell: str | None = None\n    bg_cell_medium: str | None = None\n    bg_header: str | None = None\n    bg_header_has_focus: str | None = None\n    bg_header_hovered: str | None = None\n    bg_icon_header: str | None = None\n    bg_search_result: str | None = None\n    border_color: str | None = None\n    cell_horizontal_padding: int | None = None\n    cell_vertical_padding: int | None = None\n    drilldown_border: str | None = None\n    editor_font_size: str | None = None\n    fg_icon_header: str | None = None\n    font_family: str | None = None\n    header_bottom_border_color: str | None = None\n    header_font_style: str | None = None\n    horizontal_border_color: str | None = None\n    line_height: int | None = None\n    link_color: str | None = None\n    text_bubble: str | None = None\n    text_dark: str | None = None\n    text_group_header: str | None = None\n    text_header: str | None = None\n    text_header_selected: str | None = None\n    text_light: str | None = None\n    text_medium: str | None = None\n\n\n@dataclasses.dataclass(init=False)\nclass DataEditorTheme(DataEditorThemeBase):\n    \"\"\"The theme for the DataEditor component.\"\"\"\n\n    def __init__(self, **kwargs: Any):\n        \"\"\"Initialize the DataEditorTheme.\n\n        Args:\n            **kwargs: The keyword arguments to initialize the theme.\n        \"\"\"\n        kwargs = {format.to_snake_case(k): v for k, v in kwargs.items()}\n        super().__init__(**kwargs)\n\n\nclass Bounds(TypedDict):\n    \"\"\"The bounds of the group header.\"\"\"\n\n    x: int\n    y: int\n    width: int\n    height: int\n\n\nclass CompatSelection(TypedDict):\n    \"\"\"The selection.\"\"\"\n\n    items: list\n\n\nclass Rectangle(TypedDict):\n    \"\"\"The bounds of the group header.\"\"\"\n\n    x: int\n    y: int\n    width: int\n    height: int\n\n\nclass GridSelectionCurrent(TypedDict):\n    \"\"\"The current selection.\"\"\"\n\n    cell: tuple[int, int]\n    range: Rectangle\n    rangeStack: list[Rectangle]\n\n\nclass GridSelection(TypedDict):\n    \"\"\"The grid selection.\"\"\"\n\n    current: GridSelectionCurrent | None\n    columns: CompatSelection\n    rows: CompatSelection\n\n\nclass GroupHeaderClickedEventArgs(TypedDict):\n    \"\"\"The arguments for the group header clicked event.\"\"\"\n\n    kind: str\n    group: str\n    location: tuple[int, int]\n    bounds: Bounds\n    isEdge: bool\n    shiftKey: bool\n    ctrlKey: bool\n    metaKey: bool\n    isTouch: bool\n    localEventX: int\n    localEventY: int\n    button: int\n    buttons: int\n    scrollEdge: tuple[int, int]\n\n\nclass GridCell(TypedDict):\n    \"\"\"The grid cell.\"\"\"\n\n    span: list[int] | None\n\n\nclass GridColumn(TypedDict):\n    \"\"\"The grid column.\"\"\"\n\n    title: str\n    group: str | None\n\n\nclass DataEditor(NoSSRComponent):\n    \"\"\"The DataEditor Component.\"\"\"\n\n    tag = \"DataEditor\"\n    is_default = True\n    library: str | None = \"@glideapps/glide-data-grid@6.0.3\"\n    lib_dependencies: list[str] = [\n        \"lodash@4.17.23\",\n        \"react-responsive-carousel@3.2.23\",\n    ]\n\n    # Number of rows.\n    rows: Var[int]\n\n    # Headers of the columns for the data grid.\n    columns: Var[Sequence[dict[str, Any]]]\n\n    # The data.\n    data: Var[Sequence[Sequence[Any]]]\n\n    # The name of the callback used to find the data to display.\n    get_cell_content: Var[str]\n\n    # Allow selection for copying.\n    get_cells_for_selection: Var[bool]\n\n    # Allow paste.\n    on_paste: Var[bool]\n\n    # Controls the drawing of the focus ring.\n    draw_focus_ring: Var[bool]\n\n    # Enables or disables the overlay shadow when scrolling horizontally.\n    fixed_shadow_x: Var[bool]\n\n    # Enables or disables the overlay shadow when scrolling vertically.\n    fixed_shadow_y: Var[bool]\n\n    # Controls the presence of the fill indicator\n    fill_handle: Var[bool]\n\n    # The number of columns which should remain in place when scrolling horizontally. Doesn't include rowMarkers.\n    freeze_columns: Var[int]\n\n    # Controls the header of the group header row.\n    group_header_height: Var[int]\n\n    # Controls the height of the header row.\n    header_height: Var[int]\n\n    # Additional header icons:\n    # header_icons: Var[Any] # (TODO: must be a map of name: svg) #noqa: ERA001\n\n    # The maximum width a column can be automatically sized to.\n    max_column_auto_width: Var[int]\n\n    # The maximum width a column can be resized to.\n    max_column_width: Var[int]\n\n    # The minimum width a column can be resized to.\n    min_column_width: Var[int]\n\n    # Determines the height of each row.\n    row_height: Var[int]\n\n    # Kind of row markers. Options are: \"none\", \"number\", \"checkbox\", \"both\", \"checkbox-visible\", \"clickable-number\".\n    row_markers: Var[LiteralRowMarker]\n\n    # Changes the starting index for row markers.\n    row_marker_start_index: Var[int]\n\n    # Sets the width of row markers in pixels, if unset row markers will automatically size.\n    row_marker_width: Var[int]\n\n    # Enable horizontal smooth scrolling.\n    smooth_scroll_x: Var[bool]\n\n    # Enable vertical smooth scrolling.\n    smooth_scroll_y: Var[bool]\n\n    # Controls the drawing of the left hand vertical border of a column. If set to a boolean value it controls all borders.\n    vertical_border: Var[bool]  # TODO: support a mapping (dict[int, bool])\n\n    # Allow columns selections. (\"none\", \"single\", \"multi\")\n    column_select: Var[Literal[\"none\", \"single\", \"multi\"]]\n\n    # Allow range selections. (\"none\", \"cell\", \"rect\", \"multi-cell\", \"multi-rect\").\n    range_select: Var[Literal[\"none\", \"cell\", \"rect\", \"multi-cell\", \"multi-rect\"]]\n\n    # Allow row selections. (\"none\", \"single\", \"multi\").\n    row_select: Var[Literal[\"none\", \"single\", \"multi\"]]\n\n    # Prevent diagonal scrolling.\n    prevent_diagonal_scrolling: Var[bool]\n\n    # Allow to scroll past the limit of the actual content on the horizontal axis.\n    overscroll_x: Var[int]\n\n    # Allow to scroll past the limit of the actual content on the vertical axis.\n    overscroll_y: Var[int]\n\n    # Initial scroll offset on the horizontal axis.\n    scroll_offset_x: Var[int]\n\n    # Initial scroll offset on the vertical axis.\n    scroll_offset_y: Var[int]\n\n    # Controls which types of range selections can exist at the same time. (\"exclusive\", \"mixed\").\n    range_selection_blending: Var[Literal[\"exclusive\", \"mixed\"]]\n\n    # Controls which types of column selections can exist at the same time. (\"exclusive\", \"mixed\").\n    column_selection_blending: Var[Literal[\"exclusive\", \"mixed\"]]\n\n    # Controls which types of row selections can exist at the same time. (\"exclusive\", \"mixed\").\n    row_selection_blending: Var[Literal[\"exclusive\", \"mixed\"]]\n\n    # Controls row marker selection behavior. \"auto\" adapts to touch/mouse, \"multi\" acts as if Ctrl is pressed. (\"auto\", \"multi\").\n    row_selection_mode: Var[Literal[\"auto\", \"multi\"]]\n\n    # Controls how spans are handled in selections. (\"default\", \"allowPartial\").\n    span_range_behavior: Var[Literal[\"default\", \"allowPartial\"]]\n\n    # global theme\n    theme: Var[DataEditorTheme | dict]\n\n    # Fired when a cell is activated.\n    on_cell_activated: EventHandler[passthrough_event_spec(tuple[int, int])]\n\n    # Fired when a cell is clicked.\n    on_cell_clicked: EventHandler[passthrough_event_spec(tuple[int, int])]\n\n    # Fired when a cell is right-clicked.\n    on_cell_context_menu: EventHandler[passthrough_event_spec(tuple[int, int])]\n\n    # Fired when a cell is edited.\n    on_cell_edited: EventHandler[passthrough_event_spec(tuple[int, int], GridCell)]\n\n    # Fired when a group header is clicked.\n    on_group_header_clicked: EventHandler[\n        passthrough_event_spec(tuple[int, int], GridCell)\n    ]\n\n    # Fired when a group header is right-clicked.\n    on_group_header_context_menu: EventHandler[\n        passthrough_event_spec(int, GroupHeaderClickedEventArgs)\n    ]\n\n    # Fired when a group header is renamed.\n    on_group_header_renamed: EventHandler[passthrough_event_spec(str, str)]\n\n    # Fired when a header is clicked.\n    on_header_clicked: EventHandler[passthrough_event_spec(tuple[int, int])]\n\n    # Fired when a header is right-clicked.\n    on_header_context_menu: EventHandler[passthrough_event_spec(tuple[int, int])]\n\n    # Fired when a header menu item is clicked.\n    on_header_menu_click: EventHandler[passthrough_event_spec(int, Rectangle)]\n\n    # Fired when an item is hovered.\n    on_item_hovered: EventHandler[passthrough_event_spec(tuple[int, int])]\n\n    # Fired when a selection is deleted.\n    on_delete: EventHandler[passthrough_event_spec(GridSelection)]\n\n    # Fired when editing is finished.\n    on_finished_editing: EventHandler[\n        passthrough_event_spec(GridCell | None, tuple[int, int])\n    ]\n\n    # Fired when a row is appended.\n    on_row_appended: EventHandler[no_args_event_spec]\n\n    # The current grid selection state (columns, rows, and current cell/range). Must be used when on_grid_selection_change is used otherwise updates will not be reflected in the grid.\n    grid_selection: Var[GridSelection]\n\n    # Fired when the grid selection changes. Will pass the current selection, the selected columns and the selected rows.\n    on_grid_selection_change: EventHandler[passthrough_event_spec(GridSelection)]\n\n    # Fired when the selection is cleared.\n    on_selection_cleared: EventHandler[no_args_event_spec]\n\n    # Fired when a column is resized.\n    on_column_resize: EventHandler[passthrough_event_spec(GridColumn, int)]\n\n    # Shows search bar.\n    show_search: Var[bool]\n\n    # Fired when the search close button is clicked.\n    on_search_close: EventHandler[no_args_event_spec]\n\n    def add_imports(self) -> ImportDict:\n        \"\"\"Add imports for the component.\n\n        Returns:\n            The import dict.\n        \"\"\"\n        if self.library is None:\n            return {}\n        return {\n            \"\": f\"{format.format_library_name(self.library)}/dist/index.css\",\n            self.library: [\"GridCellKind\", \"CompactSelection\"],\n            \"$/utils/helpers/dataeditor.js\": ImportVar(\n                tag=\"formatDataEditorCells\", is_default=False, install=False\n            ),\n        }\n\n    def add_custom_code(self) -> list[str]:\n        \"\"\"Add custom code for reconstructing GridSelection with CompactSelection objects.\n\n        Note: When using on_grid_selection_change, Glide Data Grid will not update its internal selection state automatically. Instead,\n        the grid_selection prop must be updated with a GridSelection object that has CompactSelection objects for the columns and rows properties.\n        This function provides the necessary JavaScript code to reconstruct the GridSelection object from a dict representation.\n\n        Returns:\n            JavaScript code to reconstruct GridSelection.\n        \"\"\"\n        return [\n            \"\"\"\n        function reconstructGridSelection(selection) {\n            if (!selection || typeof selection !== 'object') {\n                return undefined;\n            }\n\n            const reconstructCompactSelection = (data) => {\n                if (!data || !data.items || !Array.isArray(data.items)) {\n                    return CompactSelection.empty();\n                }\n\n                const items = data.items;\n                if (items.length === 0) {\n                    return CompactSelection.empty();\n                }\n\n                let result = CompactSelection.empty();\n\n                // Items are stored as [start, end) ranges in CompactSelection internal format\n                for (const item of items) {\n                    if (Array.isArray(item) && item.length === 2) {\n                        const [start, end] = item;\n                        result = result.add([start, end]);\n                    }\n                }\n\n                return result;\n            };\n\n            return {\n                current: selection.current || undefined,\n                columns: reconstructCompactSelection(selection.columns),\n                rows: reconstructCompactSelection(selection.rows)\n            };\n        }\n                    \"\"\"\n        ]\n\n    def add_hooks(self) -> list[str]:\n        \"\"\"Get the hooks to render.\n\n        Returns:\n            The hooks to render.\n        \"\"\"\n        # Define the id of the component in case multiple are used in the same page.\n        editor_id = get_unique_variable_name()\n\n        # Define the name of the getData callback associated with this component and assign to get_cell_content.\n        if self.get_cell_content is not None:\n            data_callback = self.get_cell_content._js_expr\n        else:\n            data_callback = f\"getData_{editor_id}\"\n            self.get_cell_content = Var(_js_expr=data_callback)\n\n        code = [f\"function {data_callback}([col, row]){{\"]\n\n        columns_path = str(self.columns)\n        data_path = str(self.data)\n\n        code.extend([\n            f\"    return formatDataEditorCells(col, row, {columns_path}, {data_path});\",\n            \"  }\",\n        ])\n\n        return [\"\\n\".join(code)]\n\n    @classmethod\n    def create(cls, *children, **props) -> Component:\n        \"\"\"Create the DataEditor component.\n\n        Args:\n            *children: The children of the data editor.\n            **props: The props of the data editor.\n\n        Returns:\n            The DataEditor component.&\n\n        Raises:\n            ValueError: invalid input.\n        \"\"\"\n        from reflex.components.el import Div\n\n        columns = props.get(\"columns\", [])\n        data = props.get(\"data\", [])\n        rows = props.get(\"rows\")\n\n        # If rows is not provided, determine from data.\n        if rows is None:\n            if isinstance(data, Var) and not isinstance(data, ArrayVar):\n                msg = \"DataEditor data must be an ArrayVar if rows is not provided.\"\n                raise ValueError(msg)\n\n            props[\"rows\"] = data.length() if isinstance(data, ArrayVar) else len(data)\n\n        if not isinstance(columns, Var) and len(columns):\n            if types.is_dataframe(type(data)) or (\n                isinstance(data, Var) and types.is_dataframe(data._var_type)\n            ):\n                msg = \"Cannot pass in both a pandas dataframe and columns to the data_editor component.\"\n                raise ValueError(msg)\n            props[\"columns\"] = [\n                format.format_data_editor_column(col) for col in columns\n            ]\n\n        if \"theme\" in props:\n            theme = props.get(\"theme\")\n            if isinstance(theme, Mapping):\n                props[\"theme\"] = DataEditorTheme(**theme)\n\n        # Allow by default to select a region of cells in the grid.\n        props.setdefault(\"get_cells_for_selection\", True)\n\n        # Disable on_paste by default if not provided.\n        props.setdefault(\"on_paste\", False)\n\n        if props.pop(\"get_cell_content\", None) is not None:\n            console.warn(\n                \"get_cell_content is not user configurable, the provided value will be discarded\"\n            )\n\n        # Apply the reconstruction function to grid_selection if it's a Var\n        if (grid_selection := props.get(\"grid_selection\")) is not None and isinstance(\n            grid_selection, Var\n        ):\n            props[\"grid_selection\"] = FunctionStringVar.create(\n                \"reconstructGridSelection\"\n            ).call(grid_selection)\n\n        grid = super().create(*children, **props)\n        return Div.create(\n            grid,\n            width=props.pop(\"width\", \"100%\"),\n            height=props.pop(\"height\", \"100%\"),\n        )\n\n    @staticmethod\n    def _get_app_wrap_components() -> dict[tuple[int, str], Component]:\n        \"\"\"Get the app wrap components for the component.\n\n        Returns:\n            The app wrap components.\n        \"\"\"\n        from reflex.components.el import Div\n\n        class Portal(Div):\n            def get_ref(self):\n                return None\n\n        return {\n            (-1, \"DataEditorPortal\"): Portal.create(\n                id=\"portal\",\n                position=\"fixed\",\n                top=0,\n            )\n        }\n\n\n@serializer\ndef serialize_dataeditortheme(theme: DataEditorTheme):\n    \"\"\"The serializer for the data editor theme.\n\n    Args:\n        theme: The theme to serialize.\n\n    Returns:\n        The serialized theme.\n    \"\"\"\n    return {\n        format.to_camel_case(k): v for k, v in theme.__dict__.items() if v is not None\n    }\n\n\ndata_editor = DataEditor.create\ndata_editor_theme = DataEditorTheme\n"
  },
  {
    "path": "reflex/components/datadisplay/logo.py",
    "content": "\"\"\"A Reflex logo component.\"\"\"\n\nimport reflex as rx\n\nSVG_COLOR = rx.color_mode_cond(\"#110F1F\", \"white\")\n\n\ndef svg_logo(color: str | rx.Var[str] = SVG_COLOR, **props):\n    \"\"\"A Reflex logo SVG.\n\n    Args:\n        color: The color of the logo.\n        props: Extra props to pass to the svg component.\n\n    Returns:\n        The Reflex logo SVG.\n    \"\"\"\n\n    def logo_path(d: str):\n        return rx.el.path(d=d)\n\n    paths = [\n        \"M0 11.5999V0.399902H8.96V4.8799H6.72V2.6399H2.24V4.8799H6.72V7.1199H2.24V11.5999H0ZM6.72 11.5999V7.1199H8.96V11.5999H6.72Z\",\n        \"M11.2 11.5999V0.399902H17.92V2.6399H13.44V4.8799H17.92V7.1199H13.44V9.3599H17.92V11.5999H11.2Z\",\n        \"M20.16 11.5999V0.399902H26.88V2.6399H22.4V4.8799H26.88V7.1199H22.4V11.5999H20.16Z\",\n        \"M29.12 11.5999V0.399902H31.36V9.3599H35.84V11.5999H29.12Z\",\n        \"M38.08 11.5999V0.399902H44.8V2.6399H40.32V4.8799H44.8V7.1199H40.32V9.3599H44.8V11.5999H38.08Z\",\n        \"M47.04 4.8799V0.399902H49.28V4.8799H47.04ZM53.76 4.8799V0.399902H56V4.8799H53.76ZM49.28 7.1199V4.8799H53.76V7.1199H49.28ZM47.04 11.5999V7.1199H49.28V11.5999H47.04ZM53.76 11.5999V7.1199H56V11.5999H53.76Z\",\n    ]\n\n    return rx.el.svg(\n        *[logo_path(d) for d in paths],\n        rx.el.title(\"Reflex\"),\n        aria_label=\"Reflex\",\n        role=\"img\",\n        width=props.pop(\"width\", \"56\"),\n        height=props.pop(\"height\", \"12\"),\n        fill=color,\n        xmlns=\"http://www.w3.org/2000/svg\",\n        **props,\n    )\n\n\ndef logo(**props):\n    \"\"\"A Reflex logo.\n\n    Args:\n        **props: The props to pass to the component.\n\n    Returns:\n        The logo component.\n    \"\"\"\n    return rx.center(\n        rx.link(\n            rx.hstack(\n                \"Built with \",\n                svg_logo(),\n                text_align=\"center\",\n                align=\"center\",\n                padding=\"1em\",\n            ),\n            href=\"https://reflex.dev\",\n            size=\"3\",\n        ),\n        width=props.pop(\"width\", \"100%\"),\n        **props,\n    )\n"
  },
  {
    "path": "reflex/components/datadisplay/shiki_code_block.py",
    "content": "\"\"\"Shiki syntax hghlighter component.\"\"\"\n\nfrom __future__ import annotations\n\nimport dataclasses\nimport re\nfrom collections import defaultdict\nfrom dataclasses import dataclass\nfrom typing import Any, Literal\n\nfrom reflex.components.component import Component, ComponentNamespace, field\nfrom reflex.components.core.colors import color\nfrom reflex.components.core.cond import color_mode_cond\nfrom reflex.components.el.elements.forms import Button\nfrom reflex.components.lucide.icon import Icon\nfrom reflex.components.markdown.markdown import MarkdownComponentMap\nfrom reflex.components.props import NoExtrasAllowedProps\nfrom reflex.components.radix.themes.layout.box import Box\nfrom reflex.event import run_script, set_clipboard\nfrom reflex.style import Style\nfrom reflex.utils.exceptions import VarTypeError\nfrom reflex.utils.imports import ImportVar\nfrom reflex.vars.base import LiteralVar, Var\nfrom reflex.vars.function import FunctionStringVar\nfrom reflex.vars.sequence import StringVar, string_replace_operation\n\n\ndef copy_script() -> Any:\n    \"\"\"Copy script for the code block and modify the child SVG element.\n\n    Returns:\n        Any: The result of calling the script.\n    \"\"\"\n    return run_script(\n        \"\"\"\n// Event listener for the parent click\ndocument.addEventListener('click', function(event) {\n    // Find the closest button (parent element)\n    const parent = event.target.closest('button');\n    // If the parent is found\n    if (parent) {\n        // Find the SVG element within the parent\n        const svgIcon = parent.querySelector('svg');\n        // If the SVG exists, proceed with the script\n        if (svgIcon) {\n            const originalPath = svgIcon.innerHTML;\n            const checkmarkPath = '<polyline points=\"20 6 9 17 4 12\"></polyline>';  // Checkmark SVG path\n            function transition(element, scale, opacity) {\n                element.style.transform = `scale(${scale})`;\n                element.style.opacity = opacity;\n            }\n            // Animate the SVG\n            transition(svgIcon, 0, '0');\n            setTimeout(() => {\n                svgIcon.innerHTML = checkmarkPath;  // Replace content with checkmark\n                svgIcon.setAttribute('viewBox', '0 0 24 24');  // Adjust viewBox if necessary\n                transition(svgIcon, 1, '1');\n                setTimeout(() => {\n                    transition(svgIcon, 0, '0');\n                    setTimeout(() => {\n                        svgIcon.innerHTML = originalPath;  // Restore original SVG content\n                        transition(svgIcon, 1, '1');\n                    }, 125);\n                }, 600);\n            }, 125);\n        } else {\n            // console.error('SVG element not found within the parent.');\n        }\n    } else {\n        // console.error('Parent element not found.');\n    }\n})\n\"\"\"\n    )\n\n\nSHIKIJS_TRANSFORMER_FNS = {\n    \"transformerNotationDiff\",\n    \"transformerNotationHighlight\",\n    \"transformerNotationWordHighlight\",\n    \"transformerNotationFocus\",\n    \"transformerNotationErrorLevel\",\n    \"transformerRenderWhitespace\",\n    \"transformerMetaHighlight\",\n    \"transformerMetaWordHighlight\",\n    \"transformerCompactLineOptions\",\n    # TODO: this transformer when included adds a weird behavior which removes other code lines. Need to figure out why.\n    # \"transformerRemoveLineBreak\",\n    \"transformerRemoveNotationEscape\",\n}\nLINE_NUMBER_STYLING = {\n    \"code\": {\n        \"counter-reset\": \"step\",\n        \"counter-increment\": \"step 0\",\n        \"display\": \"grid\",\n        \"line-height\": \"1.7\",\n        \"font-size\": \"0.875em\",\n    },\n    \"code .line::before\": {\n        \"content\": \"counter(step)\",\n        \"counter-increment\": \"step\",\n        \"width\": \"1rem\",\n        \"margin-right\": \"1.5rem\",\n        \"display\": \"inline-block\",\n        \"text-align\": \"right\",\n        \"color\": \"rgba(115,138,148,.4)\",\n    },\n}\nBOX_PARENT_STYLING = {\n    \"pre\": {\n        \"margin\": \"0\",\n        \"padding\": \"24px\",\n        \"background\": \"transparent\",\n        \"overflow-x\": \"auto\",\n        \"border-radius\": \"6px\",\n    },\n}\n\nTHEME_MAPPING = {\n    \"light\": \"one-light\",\n    \"dark\": \"one-dark-pro\",\n    \"a11y-dark\": \"github-dark\",\n}\nLANGUAGE_MAPPING = {\"bash\": \"shellscript\"}\nLiteralCodeLanguage = Literal[\n    \"abap\",\n    \"actionscript-3\",\n    \"ada\",\n    \"angular-html\",\n    \"angular-ts\",\n    \"apache\",\n    \"apex\",\n    \"apl\",\n    \"applescript\",\n    \"ara\",\n    \"asciidoc\",\n    \"asm\",\n    \"astro\",\n    \"awk\",\n    \"ballerina\",\n    \"bat\",\n    \"beancount\",\n    \"berry\",\n    \"bibtex\",\n    \"bicep\",\n    \"blade\",\n    \"c\",\n    \"cadence\",\n    \"clarity\",\n    \"clojure\",\n    \"cmake\",\n    \"cobol\",\n    \"codeowners\",\n    \"codeql\",\n    \"coffee\",\n    \"common-lisp\",\n    \"coq\",\n    \"cpp\",\n    \"crystal\",\n    \"csharp\",\n    \"css\",\n    \"csv\",\n    \"cue\",\n    \"cypher\",\n    \"d\",\n    \"dart\",\n    \"dax\",\n    \"desktop\",\n    \"diff\",\n    \"docker\",\n    \"dotenv\",\n    \"dream-maker\",\n    \"edge\",\n    \"elixir\",\n    \"elm\",\n    \"emacs-lisp\",\n    \"erb\",\n    \"erlang\",\n    \"fennel\",\n    \"fish\",\n    \"fluent\",\n    \"fortran-fixed-form\",\n    \"fortran-free-form\",\n    \"fsharp\",\n    \"gdresource\",\n    \"gdscript\",\n    \"gdshader\",\n    \"genie\",\n    \"gherkin\",\n    \"git-commit\",\n    \"git-rebase\",\n    \"gleam\",\n    \"glimmer-js\",\n    \"glimmer-ts\",\n    \"glsl\",\n    \"gnuplot\",\n    \"go\",\n    \"graphql\",\n    \"groovy\",\n    \"hack\",\n    \"haml\",\n    \"handlebars\",\n    \"haskell\",\n    \"haxe\",\n    \"hcl\",\n    \"hjson\",\n    \"hlsl\",\n    \"html\",\n    \"html-derivative\",\n    \"http\",\n    \"hxml\",\n    \"hy\",\n    \"imba\",\n    \"ini\",\n    \"java\",\n    \"javascript\",\n    \"jinja\",\n    \"jison\",\n    \"json\",\n    \"json5\",\n    \"jsonc\",\n    \"jsonl\",\n    \"jsonnet\",\n    \"jssm\",\n    \"jsx\",\n    \"julia\",\n    \"kotlin\",\n    \"kusto\",\n    \"latex\",\n    \"lean\",\n    \"less\",\n    \"liquid\",\n    \"log\",\n    \"logo\",\n    \"lua\",\n    \"luau\",\n    \"make\",\n    \"markdown\",\n    \"marko\",\n    \"matlab\",\n    \"mdc\",\n    \"mdx\",\n    \"mermaid\",\n    \"mojo\",\n    \"move\",\n    \"narrat\",\n    \"nextflow\",\n    \"nginx\",\n    \"nim\",\n    \"nix\",\n    \"nushell\",\n    \"objective-c\",\n    \"objective-cpp\",\n    \"ocaml\",\n    \"pascal\",\n    \"perl\",\n    \"php\",\n    \"plain\",\n    \"plsql\",\n    \"po\",\n    \"postcss\",\n    \"powerquery\",\n    \"powershell\",\n    \"prisma\",\n    \"prolog\",\n    \"proto\",\n    \"pug\",\n    \"puppet\",\n    \"purescript\",\n    \"python\",\n    \"qml\",\n    \"qmldir\",\n    \"qss\",\n    \"r\",\n    \"racket\",\n    \"raku\",\n    \"razor\",\n    \"reg\",\n    \"regexp\",\n    \"rel\",\n    \"riscv\",\n    \"rst\",\n    \"ruby\",\n    \"rust\",\n    \"sas\",\n    \"sass\",\n    \"scala\",\n    \"scheme\",\n    \"scss\",\n    \"shaderlab\",\n    \"shellscript\",\n    \"shellsession\",\n    \"smalltalk\",\n    \"solidity\",\n    \"soy\",\n    \"sparql\",\n    \"splunk\",\n    \"sql\",\n    \"ssh-config\",\n    \"stata\",\n    \"stylus\",\n    \"svelte\",\n    \"swift\",\n    \"system-verilog\",\n    \"systemd\",\n    \"tasl\",\n    \"tcl\",\n    \"templ\",\n    \"terraform\",\n    \"tex\",\n    \"toml\",\n    \"ts-tags\",\n    \"tsv\",\n    \"tsx\",\n    \"turtle\",\n    \"twig\",\n    \"typescript\",\n    \"typespec\",\n    \"typst\",\n    \"v\",\n    \"vala\",\n    \"vb\",\n    \"verilog\",\n    \"vhdl\",\n    \"viml\",\n    \"vue\",\n    \"vue-html\",\n    \"vyper\",\n    \"wasm\",\n    \"wenyan\",\n    \"wgsl\",\n    \"wikitext\",\n    \"wolfram\",\n    \"xml\",\n    \"xsl\",\n    \"yaml\",\n    \"zenscript\",\n    \"zig\",\n]\nLiteralCodeTheme = Literal[\n    \"andromeeda\",\n    \"aurora-x\",\n    \"ayu-dark\",\n    \"catppuccin-frappe\",\n    \"catppuccin-latte\",\n    \"catppuccin-macchiato\",\n    \"catppuccin-mocha\",\n    \"dark-plus\",\n    \"dracula\",\n    \"dracula-soft\",\n    \"everforest-dark\",\n    \"everforest-light\",\n    \"github-dark\",\n    \"github-dark-default\",\n    \"github-dark-dimmed\",\n    \"github-dark-high-contrast\",\n    \"github-light\",\n    \"github-light-default\",\n    \"github-light-high-contrast\",\n    \"houston\",\n    \"laserwave\",\n    \"light-plus\",\n    \"material-theme\",\n    \"material-theme-darker\",\n    \"material-theme-lighter\",\n    \"material-theme-ocean\",\n    \"material-theme-palenight\",\n    \"min-dark\",\n    \"min-light\",\n    \"monokai\",\n    \"night-owl\",\n    \"nord\",\n    \"one-dark-pro\",\n    \"one-light\",\n    \"plastic\",\n    \"poimandres\",\n    \"red\",\n    # rose-pine themes dont work with the current version of shikijs transformers\n    # https://github.com/shikijs/shiki/issues/730\n    \"rose-pine\",\n    \"rose-pine-dawn\",\n    \"rose-pine-moon\",\n    \"slack-dark\",\n    \"slack-ochin\",\n    \"snazzy-light\",\n    \"solarized-dark\",\n    \"solarized-light\",\n    \"synthwave-84\",\n    \"tokyo-night\",\n    \"vesper\",\n    \"vitesse-black\",\n    \"vitesse-dark\",\n    \"vitesse-light\",\n]\n\n\nclass Position(NoExtrasAllowedProps):\n    \"\"\"Position of the decoration.\"\"\"\n\n    line: int\n    character: int\n\n\nclass ShikiDecorations(NoExtrasAllowedProps):\n    \"\"\"Decorations for the code block.\"\"\"\n\n    start: int | Position\n    end: int | Position\n    tag_name: str = \"span\"\n    properties: dict[str, Any] = {}\n    always_wrap: bool = False\n\n\n@dataclass(kw_only=True)\nclass ShikiBaseTransformers:\n    \"\"\"Base for creating transformers.\"\"\"\n\n    library: str = \"\"\n    fns: list[FunctionStringVar] = dataclasses.field(default_factory=list)\n    style: Style | None = dataclasses.field(default=None)\n\n\n@dataclass(kw_only=True)\nclass ShikiJsTransformer(ShikiBaseTransformers):\n    \"\"\"A Wrapped shikijs transformer.\"\"\"\n\n    library: str = \"@shikijs/transformers@3.3.0\"\n    fns: list[FunctionStringVar] = dataclasses.field(\n        default_factory=lambda: [\n            FunctionStringVar.create(fn) for fn in SHIKIJS_TRANSFORMER_FNS\n        ]\n    )\n    style: Style | None = dataclasses.field(\n        default_factory=lambda: Style({\n            \"code\": {\n                \"line-height\": \"1.7\",\n                \"font-size\": \"0.875em\",\n                \"display\": \"grid\",\n            },\n            # Diffs\n            \".diff\": {\n                \"margin\": \"0 -24px\",\n                \"padding\": \"0 24px\",\n                \"width\": \"calc(100% + 48px)\",\n                \"display\": \"inline-block\",\n            },\n            \".diff.add\": {\n                \"background-color\": \"rgba(16, 185, 129, .14)\",\n                \"position\": \"relative\",\n            },\n            \".diff.remove\": {\n                \"background-color\": \"rgba(244, 63, 94, .14)\",\n                \"opacity\": \"0.7\",\n                \"position\": \"relative\",\n            },\n            \".diff.remove:after\": {\n                \"position\": \"absolute\",\n                \"left\": \"10px\",\n                \"content\": \"'-'\",\n                \"color\": \"#b34e52\",\n            },\n            \".diff.add:after\": {\n                \"position\": \"absolute\",\n                \"left\": \"10px\",\n                \"content\": \"'+'\",\n                \"color\": \"#18794e\",\n            },\n            # Highlight\n            \".highlighted\": {\n                \"background-color\": \"rgba(142, 150, 170, .14)\",\n                \"margin\": \"0 -24px\",\n                \"padding\": \"0 24px\",\n                \"width\": \"calc(100% + 48px)\",\n                \"display\": \"inline-block\",\n            },\n            \".highlighted.error\": {\n                \"background-color\": \"rgba(244, 63, 94, .14)\",\n            },\n            \".highlighted.warning\": {\n                \"background-color\": \"rgba(234, 179, 8, .14)\",\n            },\n            # Highlighted Word\n            \".highlighted-word\": {\n                \"background-color\": color(\"gray\", 2),\n                \"border\": f\"1px solid {color('gray', 5)}\",\n                \"padding\": \"1px 3px\",\n                \"margin\": \"-1px -3px\",\n                \"border-radius\": \"4px\",\n            },\n            # Focused Lines\n            \".has-focused .line:not(.focused)\": {\n                \"opacity\": \"0.7\",\n                \"filter\": \"blur(0.095rem)\",\n                \"transition\": \"filter .35s, opacity .35s\",\n            },\n            \".has-focused:hover .line:not(.focused)\": {\n                \"opacity\": \"1\",\n                \"filter\": \"none\",\n            },\n            # White Space\n            # \".tab, .space\": {\n            #     \"position\": \"relative\", # noqa: ERA001\n            # },\n            # \".tab::before\": {\n            #     \"content\": \"'⇥'\", # noqa: ERA001\n            #     \"position\": \"absolute\", # noqa: ERA001\n            #     \"opacity\": \"0.3\",# noqa: ERA001\n            # },\n            # \".space::before\": {\n            #     \"content\": \"'·'\", # noqa: ERA001\n            #     \"position\": \"absolute\", # noqa: ERA001\n            #     \"opacity\": \"0.3\", # noqa: ERA001\n            # },\n        })\n    )\n\n    def __init__(self, **kwargs):\n        \"\"\"Initialize the transformer.\n\n        Args:\n            kwargs: Kwargs to initialize the props.\n\n        \"\"\"\n        fns = kwargs.pop(\"fns\", None)\n        style = kwargs.pop(\"style\", None)\n        if fns:\n            kwargs[\"fns\"] = [\n                (\n                    FunctionStringVar.create(x)\n                    if not isinstance(x, FunctionStringVar)\n                    else x\n                )\n                for x in fns\n            ]\n\n        if style:\n            kwargs[\"style\"] = Style(style)\n        super().__init__(**kwargs)\n\n\nclass ShikiCodeBlock(Component, MarkdownComponentMap):\n    \"\"\"A Code block.\"\"\"\n\n    library = \"/components/shiki/code\"\n\n    tag = \"Code\"\n\n    alias = \"ShikiCode\"\n\n    lib_dependencies: list[str] = [\"shiki@3.3.0\"]\n\n    # The language to use.\n    language: Var[LiteralCodeLanguage] = Var.create(\"python\")\n\n    # The theme to use (\"light\" or \"dark\").\n    theme: Var[LiteralCodeTheme] = Var.create(\"one-light\")\n\n    # The set of themes to use for different modes.\n    themes: Var[list[dict[str, Any]] | dict[str, str]]\n\n    # The code to display.\n    code: Var[str]\n\n    # The transformers to use for the syntax highlighter.\n    transformers: Var[list[ShikiBaseTransformers | dict[str, Any]]] = Var.create([])\n\n    # The decorations to use for the syntax highlighter.\n    decorations: Var[list[ShikiDecorations]] = Var.create([])\n\n    @classmethod\n    def create(\n        cls,\n        *children,\n        **props,\n    ) -> Component:\n        \"\"\"Create a code block component using [shiki syntax highlighter](https://shiki.matsu.io/).\n\n        Args:\n            *children: The children of the component.\n            **props: The props to pass to the component.\n\n        Returns:\n            The code block component.\n        \"\"\"\n        # Separate props for the code block and the wrapper\n        code_block_props = {}\n        code_wrapper_props = {}\n        decorations = props.pop(\"decorations\", [])\n\n        class_props = cls.get_props()\n\n        # Distribute props between the code block and wrapper\n        for key, value in props.items():\n            (code_block_props if key in class_props else code_wrapper_props)[key] = (\n                value\n            )\n\n        # cast decorations into ShikiDecorations.\n        decorations = [\n            ShikiDecorations(**decoration)\n            if not isinstance(decoration, ShikiDecorations)\n            else decoration\n            for decoration in decorations\n        ]\n        code_block_props[\"decorations\"] = decorations\n\n        code_block_props[\"code\"] = children[0]\n        code_block = super().create(**code_block_props)\n\n        transformer_styles = {}\n        # Collect styles from transformers and wrapper\n        for transformer in code_block.transformers._var_value:  # pyright: ignore [reportAttributeAccessIssue]\n            if isinstance(transformer, ShikiBaseTransformers) and transformer.style:\n                transformer_styles.update(transformer.style)\n        transformer_styles.update(code_wrapper_props.pop(\"style\", {}))\n\n        return Box.create(\n            code_block,\n            *children[1:],\n            style=Style({**transformer_styles, **BOX_PARENT_STYLING}),\n            **code_wrapper_props,\n        )\n\n    def add_imports(self) -> dict[str, list[str]]:\n        \"\"\"Add the necessary imports.\n        We add all referenced transformer functions as imports from their corresponding\n        libraries.\n\n        Returns:\n            Imports for the component.\n\n        Raises:\n            ValueError: If the transformers are not of type LiteralVar.\n        \"\"\"\n        imports = defaultdict(list)\n        if not isinstance(self.transformers, LiteralVar):\n            msg = f\"transformers should be a LiteralVar type. Got {type(self.transformers)} instead.\"\n            raise ValueError(msg)\n        for transformer in self.transformers._var_value:\n            if isinstance(transformer, ShikiBaseTransformers):\n                imports[transformer.library].extend([\n                    ImportVar(tag=str(fn)) for fn in transformer.fns\n                ])\n                if transformer.library not in self.lib_dependencies:\n                    self.lib_dependencies.append(transformer.library)\n        return imports\n\n    @classmethod\n    def create_transformer(cls, library: str, fns: list[str]) -> ShikiBaseTransformers:\n        \"\"\"Create a transformer from a third party library.\n\n        Args:\n            library: The name of the library.\n            fns: The str names of the functions/callables to invoke from the library.\n\n        Returns:\n            A transformer for the specified library.\n\n        Raises:\n            ValueError: If a supplied function name is not valid str.\n        \"\"\"\n        if any(not isinstance(fn_name, str) for fn_name in fns):\n            msg = f\"the function names should be str names of functions in the specified transformer: {library!r}\"\n            raise ValueError(msg)\n        return ShikiBaseTransformers(\n            library=library,\n            fns=[FunctionStringVar.create(fn) for fn in fns],  # pyright: ignore [reportCallIssue]\n        )\n\n    def _render(self, props: dict[str, Any] | None = None):\n        \"\"\"Renders the component with the given properties, processing transformers if present.\n\n        Args:\n            props: Optional properties to pass to the render function.\n\n        Returns:\n            Rendered component output.\n        \"\"\"\n        # Ensure props is initialized from class attributes if not provided\n        props = props or {\n            attr.rstrip(\"_\"): getattr(self, attr) for attr in self.get_props()\n        }\n\n        # Extract transformers and apply transformations\n        transformers = props.get(\"transformers\")\n        if transformers is not None:\n            transformed_values = self._process_transformers(transformers._var_value)\n            props[\"transformers\"] = LiteralVar.create(transformed_values)\n\n        return super()._render(props)\n\n    def _process_transformers(self, transformer_list: list) -> list:\n        \"\"\"Processes a list of transformers, applying transformations where necessary.\n\n        Args:\n            transformer_list: List of transformer objects or values.\n\n        Returns:\n            list: A list of transformed values.\n        \"\"\"\n        processed = []\n\n        for transformer in transformer_list:\n            if isinstance(transformer, ShikiBaseTransformers):\n                processed.extend(fn.call() for fn in transformer.fns)\n            else:\n                processed.append(transformer)\n\n        return processed\n\n\nclass ShikiHighLevelCodeBlock(ShikiCodeBlock):\n    \"\"\"High level component for the shiki syntax highlighter.\"\"\"\n\n    # If this is enabled, the default transformers(shikijs transformer) will be used.\n    use_transformers: Var[bool]\n\n    # If this is enabled line numbers will be shown next to the code block.\n    show_line_numbers: Var[bool]\n\n    # Whether a copy button should appear.\n    can_copy: bool = field(default=False, is_javascript_property=False)\n\n    # copy_button: A custom copy button to override the default one.\n    copy_button: Component | bool | None = field(\n        default=None, is_javascript_property=False\n    )\n\n    @classmethod\n    def create(\n        cls,\n        *children,\n        **props,\n    ) -> Component:\n        \"\"\"Create a code block component using [shiki syntax highlighter](https://shiki.matsu.io/).\n\n        Args:\n            *children: The children of the component.\n            **props: The props to pass to the component.\n\n        Returns:\n            The code block component.\n        \"\"\"\n        use_transformers = props.pop(\"use_transformers\", False)\n        show_line_numbers = props.pop(\"show_line_numbers\", False)\n        language = props.pop(\"language\", None)\n        can_copy = props.pop(\"can_copy\", False)\n        copy_button = props.pop(\"copy_button\", None)\n\n        if use_transformers:\n            props[\"transformers\"] = [ShikiJsTransformer()]\n\n        if language is not None:\n            props[\"language\"] = cls._map_languages(language)\n\n        # line numbers are generated via css\n        if show_line_numbers:\n            props[\"style\"] = {**LINE_NUMBER_STYLING, **props.get(\"style\", {})}\n\n        theme = props.pop(\"theme\", None)\n        props[\"theme\"] = props[\"theme\"] = (\n            cls._map_themes(theme)\n            if theme is not None\n            else color_mode_cond(  # Default color scheme responds to global color mode.\n                light=\"one-light\",\n                dark=\"one-dark-pro\",\n            )\n        )\n\n        if can_copy:\n            code = children[0]\n            copy_button = (\n                copy_button\n                if copy_button is not None\n                else Button.create(\n                    Icon.create(tag=\"copy\", size=16, color=color(\"gray\", 11)),\n                    on_click=[\n                        set_clipboard(cls._strip_transformer_triggers(code)),\n                        copy_script(),\n                    ],\n                    style=Style({\n                        \"position\": \"absolute\",\n                        \"top\": \"4px\",\n                        \"right\": \"4px\",\n                        \"background\": color(\"gray\", 3),\n                        \"border\": \"1px solid\",\n                        \"border-color\": color(\"gray\", 5),\n                        \"border-radius\": \"6px\",\n                        \"padding\": \"5px\",\n                        \"opacity\": \"1\",\n                        \"cursor\": \"pointer\",\n                        \"_hover\": {\n                            \"background\": color(\"gray\", 4),\n                        },\n                        \"transition\": \"background 0.250s ease-out\",\n                        \"&>svg\": {\n                            \"transition\": \"transform 0.250s ease-out, opacity 0.250s ease-out\",\n                        },\n                        \"_active\": {\n                            \"background\": color(\"gray\", 5),\n                        },\n                    }),\n                )\n            )\n\n        if copy_button:\n            return ShikiCodeBlock.create(\n                children[0], copy_button, position=\"relative\", **props\n            )\n        return ShikiCodeBlock.create(children[0], **props)\n\n    @staticmethod\n    def _map_themes(theme: str) -> str:\n        if isinstance(theme, str) and theme in THEME_MAPPING:\n            return THEME_MAPPING[theme]\n        return theme\n\n    @staticmethod\n    def _map_languages(language: str) -> str:\n        if isinstance(language, str) and language in LANGUAGE_MAPPING:\n            return LANGUAGE_MAPPING[language]\n        return language\n\n    @staticmethod\n    def _strip_transformer_triggers(code: str | StringVar) -> StringVar | str:\n        if not isinstance(code, (StringVar, str)):\n            msg = f\"code should be string literal or a StringVar type. Got {type(code)} instead.\"\n            raise VarTypeError(msg)\n        regex_pattern = r\"[\\/#]+ *\\[!code.*?\\]\"\n\n        if isinstance(code, Var):\n            return string_replace_operation(\n                code, StringVar(_js_expr=f\"/{regex_pattern}/g\", _var_type=str), \"\"\n            )\n        if isinstance(code, str):\n            return re.sub(regex_pattern, \"\", code)\n        return None\n\n\nclass TransformerNamespace(ComponentNamespace):\n    \"\"\"Namespace for the Transformers.\"\"\"\n\n    shikijs = ShikiJsTransformer\n\n\nclass CodeblockNamespace(ComponentNamespace):\n    \"\"\"Namespace for the CodeBlock component.\"\"\"\n\n    root = staticmethod(ShikiCodeBlock.create)\n    create_transformer = staticmethod(ShikiCodeBlock.create_transformer)\n    transformers = TransformerNamespace()\n    __call__ = staticmethod(ShikiHighLevelCodeBlock.create)\n\n\ncode_block = CodeblockNamespace()\n"
  },
  {
    "path": "reflex/components/dynamic.py",
    "content": "\"\"\"Components that are dynamically generated on the backend.\"\"\"\n\nfrom typing import TYPE_CHECKING, Union\n\nfrom reflex import constants\nfrom reflex.utils import imports\nfrom reflex.utils.exceptions import DynamicComponentMissingLibraryError\nfrom reflex.utils.format import format_library_name\nfrom reflex.utils.serializers import serializer\nfrom reflex.vars import Var, get_unique_variable_name\nfrom reflex.vars.base import VarData, transform\n\nif TYPE_CHECKING:\n    from reflex.components.component import Component\n\n\ndef get_cdn_url(lib: str) -> str:\n    \"\"\"Get the CDN URL for a library.\n\n    Args:\n        lib: The library to get the CDN URL for.\n\n    Returns:\n        The CDN URL for the library.\n    \"\"\"\n    return f\"https://cdn.jsdelivr.net/npm/{lib}\" + \"/+esm\"\n\n\nbundled_libraries = [\n    \"react\",\n    \"@radix-ui/themes\",\n    \"@emotion/react\",\n    f\"$/{constants.Dirs.UTILS}/context\",\n    f\"$/{constants.Dirs.UTILS}/state\",\n    f\"$/{constants.Dirs.UTILS}/components\",\n]\n\n\ndef bundle_library(component: Union[\"Component\", str]):\n    \"\"\"Bundle a library with the component.\n\n    Args:\n        component: The component to bundle the library with.\n\n    Raises:\n        DynamicComponentMissingLibraryError: Raised when a dynamic component is missing a library.\n    \"\"\"\n    if isinstance(component, str):\n        bundled_libraries.append(component)\n        return\n    if component.library is None:\n        msg = \"Component must have a library to bundle.\"\n        raise DynamicComponentMissingLibraryError(msg)\n    bundled_libraries.append(format_library_name(component.library))\n\n\ndef load_dynamic_serializer():\n    \"\"\"Load the serializer for dynamic components.\"\"\"\n    # Causes a circular import, so we import here.\n    from reflex.components.component import Component\n\n    @serializer\n    def make_component(component: Component) -> str:\n        \"\"\"Generate the code for a dynamic component.\n\n        Args:\n            component: The component to generate code for.\n\n        Returns:\n            The generated code\n        \"\"\"\n        # Causes a circular import, so we import here.\n        from reflex.compiler import compiler, templates, utils\n        from reflex.components.base.bare import Bare\n\n        component = Bare.create(Var.create(component))\n\n        rendered_components = {}\n        # Include dynamic imports in the shared component.\n        if dynamic_imports := component._get_all_dynamic_imports():\n            rendered_components.update(dict.fromkeys(dynamic_imports))\n\n        # Include custom code in the shared component.\n        rendered_components.update(component._get_all_custom_code())\n\n        rendered_components[\n            templates.stateful_component_template(\n                tag_name=\"MySSRComponent\",\n                memo_trigger_hooks=[],\n                component=component,\n                export=True,\n            )\n        ] = None\n\n        libs_in_window = bundled_libraries\n\n        component_imports = component._get_all_imports()\n        compiler._apply_common_imports(component_imports)\n\n        imports = {}\n        for lib, names in component_imports.items():\n            formatted_lib_name = format_library_name(lib)\n            if (\n                not lib.startswith((\".\", \"/\", \"$/\"))\n                and not lib.startswith(\"http\")\n                and formatted_lib_name not in libs_in_window\n            ):\n                imports[get_cdn_url(lib)] = names\n            else:\n                imports[lib] = names\n\n        module_code_lines = templates.stateful_components_template(\n            imports=utils.compile_imports(imports),\n            memoized_code=\"\\n\".join(rendered_components),\n        ).splitlines()\n\n        # Rewrite imports from `/` to destructure from window\n        for ix, line in enumerate(module_code_lines[:]):\n            if line.startswith(\"import \"):\n                if 'from \"$/' in line or 'from \"/' in line:\n                    module_code_lines[ix] = (\n                        line\n                        .replace(\"import \", \"const \", 1)\n                        .replace(\" as \", \": \")\n                        .replace(\" from \", \" = window['__reflex'][\", 1)\n                        + \"]\"\n                    )\n                else:\n                    for lib in libs_in_window:\n                        if f'from \"{lib}\"' in line:\n                            module_code_lines[ix] = (\n                                line\n                                .replace(\"import \", \"const \", 1)\n                                .replace(\n                                    f' from \"{lib}\"', f\" = window.__reflex['{lib}']\", 1\n                                )\n                                .replace(\" as \", \": \")\n                            )\n            if line.startswith(\"export function\"):\n                module_code_lines[ix] = line.replace(\n                    \"export function\", \"export default function\", 1\n                )\n            line_stripped = line.strip()\n            if line_stripped.startswith(\"{\") and line_stripped.endswith(\"}\"):\n                module_code_lines[ix] = line_stripped[1:-1]\n\n        module_code_lines.insert(0, \"const React = window.__reflex.react;\")\n\n        function_line = next(\n            index\n            for index, line in enumerate(module_code_lines)\n            if line.startswith(\"export default function\")\n        )\n\n        module_code_lines = [\n            line\n            for _, line in sorted(\n                enumerate(module_code_lines),\n                key=lambda x: (\n                    not (x[1].startswith(\"import \") and x[0] < function_line),\n                    x[0],\n                ),\n            )\n        ]\n\n        return \"\\n\".join([\n            \"//__reflex_evaluate\",\n            *module_code_lines,\n        ])\n\n    @transform\n    def evaluate_component(js_string: Var[str]) -> Var[Component]:\n        \"\"\"Evaluate a component.\n\n        Args:\n            js_string: The JavaScript string to evaluate.\n\n        Returns:\n            The evaluated JavaScript string.\n        \"\"\"\n        unique_var_name = get_unique_variable_name()\n\n        return js_string._replace(\n            _js_expr=unique_var_name,\n            _var_type=Component,\n            merge_var_data=VarData.merge(\n                VarData(\n                    imports={\n                        f\"$/{constants.Dirs.STATE_PATH}\": [\n                            imports.ImportVar(tag=\"evalReactComponent\"),\n                        ],\n                        \"react\": [\n                            imports.ImportVar(tag=\"useState\"),\n                            imports.ImportVar(tag=\"useEffect\"),\n                        ],\n                    },\n                    hooks={\n                        f\"const [{unique_var_name}, set_{unique_var_name}] = useState(null);\": None,\n                        \"useEffect(() => {\"\n                        \"let isMounted = true;\"\n                        f\"evalReactComponent({js_string!s})\"\n                        \".then((component) => {\"\n                        \"if (isMounted) {\"\n                        f\"set_{unique_var_name}(component);\"\n                        \"}\"\n                        \"});\"\n                        \"return () => {\"\n                        \"isMounted = false;\"\n                        \"};\"\n                        \"}\"\n                        f\", [{js_string!s}]);\": None,\n                    },\n                ),\n            ),\n        )\n"
  },
  {
    "path": "reflex/components/el/__init__.py",
    "content": "\"\"\"The el package exports raw HTML elements.\"\"\"\n\nfrom __future__ import annotations\n\nfrom reflex.utils import lazy_loader\n\nfrom . import elements\n\n_SUBMODULES: set[str] = {\"elements\"}\n_SUBMOD_ATTRS: dict[str, list[str]] = {\n    # rx.el.a is replaced by React Router's Link.\n    f\"elements.{k}\": [attr for attr in attrs if attr != \"a\"]\n    for k, attrs in elements._MAPPING.items()\n}\n_EXTRA_MAPPINGS: dict[str, str] = {\n    \"a\": \"reflex.components.react_router.link\",\n}\n\n__getattr__, __dir__, __all__ = lazy_loader.attach(\n    __name__,\n    submodules=_SUBMODULES,\n    submod_attrs=_SUBMOD_ATTRS,\n    **_EXTRA_MAPPINGS,\n)\n"
  },
  {
    "path": "reflex/components/el/element.py",
    "content": "\"\"\"Base class definition for raw HTML elements.\"\"\"\n\nfrom typing import ClassVar\n\nfrom reflex.components.component import Component\n\n\nclass Element(Component):\n    \"\"\"The base class for all raw HTML elements.\"\"\"\n\n    _is_tag_in_global_scope: ClassVar[bool] = True\n\n    def __eq__(self, other: object):\n        \"\"\"Two elements are equal if they have the same tag.\n\n        Args:\n            other: The other element.\n\n        Returns:\n            True if the elements have the same tag, False otherwise.\n        \"\"\"\n        return isinstance(other, Element) and self.tag == other.tag\n"
  },
  {
    "path": "reflex/components/el/elements/__init__.py",
    "content": "\"\"\"Element classes.\"\"\"\n\nfrom __future__ import annotations\n\nfrom reflex.utils import lazy_loader\n\n_MAPPING = {\n    \"forms\": [\n        \"button\",\n        \"datalist\",\n        \"fieldset\",\n        \"form\",\n        \"input\",\n        \"label\",\n        \"legend\",\n        \"meter\",\n        \"optgroup\",\n        \"option\",\n        \"output\",\n        \"progress\",\n        \"select\",\n        \"textarea\",\n    ],\n    \"inline\": [\n        \"a\",\n        \"abbr\",\n        \"b\",\n        \"bdi\",\n        \"bdo\",\n        \"br\",\n        \"cite\",\n        \"code\",\n        \"data\",\n        \"dfn\",\n        \"em\",\n        \"i\",\n        \"kbd\",\n        \"mark\",\n        \"q\",\n        \"rp\",\n        \"rt\",\n        \"ruby\",\n        \"s\",\n        \"samp\",\n        \"small\",\n        \"span\",\n        \"strong\",\n        \"sub\",\n        \"sup\",\n        \"time\",\n        \"u\",\n        \"wbr\",\n    ],\n    \"media\": [\n        \"area\",\n        \"audio\",\n        \"img\",\n        \"image\",\n        \"map\",\n        \"track\",\n        \"video\",\n        \"embed\",\n        \"iframe\",\n        \"object\",\n        \"picture\",\n        \"portal\",\n        \"source\",\n        \"svg\",\n        \"text\",\n        \"line\",\n        \"circle\",\n        \"g\",\n        \"ellipse\",\n        \"rect\",\n        \"polygon\",\n        \"path\",\n        \"stop\",\n        \"linear_gradient\",\n        \"radial_gradient\",\n        \"defs\",\n        \"marker\",\n    ],\n    \"metadata\": [\n        \"base\",\n        \"head\",\n        \"link\",\n        \"meta\",\n        \"title\",\n        \"style\",\n    ],\n    \"other\": [\"details\", \"dialog\", \"summary\", \"slot\", \"template\", \"math\", \"html\"],\n    \"scripts\": [\"canvas\", \"noscript\", \"script\"],\n    \"sectioning\": [\n        \"address\",\n        \"article\",\n        \"aside\",\n        \"body\",\n        \"header\",\n        \"footer\",\n        \"h1\",\n        \"h2\",\n        \"h3\",\n        \"h4\",\n        \"h5\",\n        \"h6\",\n        \"main\",\n        \"nav\",\n        \"section\",\n    ],\n    \"tables\": [\n        \"caption\",\n        \"col\",\n        \"colgroup\",\n        \"table\",\n        \"td\",\n        \"tfoot\",\n        \"th\",\n        \"thead\",\n        \"tr\",\n        \"tbody\",\n    ],\n    \"typography\": [\n        \"blockquote\",\n        \"dd\",\n        \"div\",\n        \"dl\",\n        \"dt\",\n        \"figcaption\",\n        \"figure\",\n        \"hr\",\n        \"ol\",\n        \"li\",\n        \"p\",\n        \"pre\",\n        \"ul\",\n        \"ins\",\n        \"del_\",\n        \"Del\",\n    ],\n}\n\n\nEXCLUDE = [\"del_\", \"Del\", \"image\", \"style\"]\nfor v in _MAPPING.values():\n    from reflex.utils.format import to_camel_case\n\n    v.extend([\n        to_camel_case(mod)[0].upper() + to_camel_case(mod)[1:]\n        for mod in v\n        if mod not in EXCLUDE\n    ])\n\n_MAPPING[\"metadata\"].extend([\"StyleEl\"])\n\n_SUBMOD_ATTRS: dict[str, list[str]] = _MAPPING\n\n__getattr__, __dir__, __all__ = lazy_loader.attach(\n    __name__,\n    submod_attrs=_SUBMOD_ATTRS,\n)\n"
  },
  {
    "path": "reflex/components/el/elements/base.py",
    "content": "\"\"\"Base classes.\"\"\"\n\nfrom typing import Literal\n\nfrom reflex.components.el.element import Element\nfrom reflex.vars.base import Var\n\nAutoCapitalize = Literal[\"off\", \"none\", \"on\", \"sentences\", \"words\", \"characters\"]\nContentEditable = Literal[\"inherit\", \"plaintext-only\"] | bool\nEnterKeyHint = Literal[\"enter\", \"done\", \"go\", \"next\", \"previous\", \"search\", \"send\"]\nInputMode = Literal[\n    \"none\", \"text\", \"tel\", \"url\", \"email\", \"numeric\", \"decimal\", \"search\", \"search\"\n]\nAriaRole = Literal[\n    \"alert\",\n    \"alertdialog\",\n    \"application\",\n    \"article\",\n    \"banner\",\n    \"button\",\n    \"cell\",\n    \"checkbox\",\n    \"columnheader\",\n    \"combobox\",\n    \"complementary\",\n    \"contentinfo\",\n    \"definition\",\n    \"dialog\",\n    \"directory\",\n    \"document\",\n    \"feed\",\n    \"figure\",\n    \"form\",\n    \"grid\",\n    \"gridcell\",\n    \"group\",\n    \"heading\",\n    \"img\",\n    \"link\",\n    \"list\",\n    \"listbox\",\n    \"listitem\",\n    \"log\",\n    \"main\",\n    \"marquee\",\n    \"math\",\n    \"menu\",\n    \"menubar\",\n    \"menuitem\",\n    \"menuitemcheckbox\",\n    \"menuitemradio\",\n    \"navigation\",\n    \"none\",\n    \"note\",\n    \"option\",\n    \"presentation\",\n    \"progressbar\",\n    \"radio\",\n    \"radiogroup\",\n    \"region\",\n    \"row\",\n    \"rowgroup\",\n    \"rowheader\",\n    \"scrollbar\",\n    \"search\",\n    \"searchbox\",\n    \"separator\",\n    \"slider\",\n    \"spinbutton\",\n    \"status\",\n    \"switch\",\n    \"tab\",\n    \"table\",\n    \"tablist\",\n    \"tabpanel\",\n    \"term\",\n    \"textbox\",\n    \"timer\",\n    \"toolbar\",\n    \"tooltip\",\n    \"tree\",\n    \"treegrid\",\n    \"treeitem\",\n]\n\n\nclass BaseHTML(Element):\n    \"\"\"Base class for common attributes.\"\"\"\n\n    # Provides a hint for generating a keyboard shortcut for the current element.\n    access_key: Var[str]\n\n    # Controls whether and how text input is automatically capitalized as it is entered/edited by the user.\n    auto_capitalize: Var[AutoCapitalize]\n\n    # Indicates whether the element's content is editable.\n    content_editable: Var[ContentEditable]\n\n    # Defines the ID of a <menu> element which will serve as the element's context menu.\n    context_menu: Var[str]\n\n    # Defines the text direction. Allowed values are ltr (Left-To-Right) or rtl (Right-To-Left)\n    dir: Var[str]\n\n    # Defines whether the element can be dragged.\n    draggable: Var[bool]\n\n    # Hints what media types the media element is able to play.\n    enter_key_hint: Var[EnterKeyHint]\n\n    # Defines whether the element is hidden.\n    hidden: Var[bool]\n\n    # Defines the type of the element.\n    input_mode: Var[InputMode]\n\n    # Defines the name of the element for metadata purposes.\n    item_prop: Var[str]\n\n    # Defines the language used in the element.\n    lang: Var[str]\n\n    # Defines the role of the element.\n    role: Var[AriaRole]\n\n    # Assigns a slot in a shadow DOM shadow tree to an element.\n    slot: Var[str]\n\n    # Defines whether the element may be checked for spelling errors.\n    spell_check: Var[bool]\n\n    # Defines the position of the current element in the tabbing order.\n    tab_index: Var[int]\n\n    # Defines a tooltip for the element.\n    title: Var[str]\n"
  },
  {
    "path": "reflex/components/el/elements/forms.py",
    "content": "\"\"\"Forms classes.\"\"\"\n\nfrom __future__ import annotations\n\nfrom collections.abc import Iterator\nfrom hashlib import md5\nfrom typing import Any, ClassVar, Literal\n\nfrom reflex.components.el.element import Element\nfrom reflex.components.tags.tag import Tag\nfrom reflex.constants import Dirs, EventTriggers\nfrom reflex.event import (\n    FORM_DATA,\n    EventChain,\n    EventHandler,\n    checked_input_event,\n    float_input_event,\n    input_event,\n    int_input_event,\n    key_event,\n    on_submit_event,\n    on_submit_string_event,\n    prevent_default,\n)\nfrom reflex.utils.imports import ImportDict\nfrom reflex.vars import VarData\nfrom reflex.vars.base import LiteralVar, Var\nfrom reflex.vars.number import ternary_operation\n\nfrom .base import BaseHTML\n\n\ndef _handle_submit_js_template(\n    handle_submit_unique_name: str,\n    form_data: str,\n    field_ref_mapping: str,\n    on_submit_event_chain: str,\n    reset_on_submit: str,\n) -> str:\n    \"\"\"Generate handle submit JS using f-string formatting.\n\n    Args:\n        handle_submit_unique_name: Unique name for the handle submit function.\n        form_data: Name of the form data variable.\n        field_ref_mapping: JSON string of field reference mappings.\n        on_submit_event_chain: Event chain for the submit handler.\n        reset_on_submit: Boolean string indicating if form should reset after submit.\n\n    Returns:\n        JavaScript code for the form submit handler.\n    \"\"\"\n    return f\"\"\"\n    const handleSubmit_{handle_submit_unique_name} = useCallback((ev) => {{\n        const $form = ev.target\n        ev.preventDefault()\n        const {form_data} = {{...Object.fromEntries(new FormData($form).entries()), ...{field_ref_mapping}}};\n\n        ({on_submit_event_chain}(ev));\n\n        if ({reset_on_submit}) {{\n            $form.reset()\n        }}\n    }})\n    \"\"\"\n\n\nButtonType = Literal[\"submit\", \"reset\", \"button\"]\n\n\nclass Button(BaseHTML):\n    \"\"\"Display the button element.\"\"\"\n\n    tag = \"button\"\n\n    # Automatically focuses the button when the page loads\n    auto_focus: Var[bool]\n\n    # Disables the button\n    disabled: Var[bool]\n\n    # Associates the button with a form (by id)\n    form: Var[str]\n\n    # URL to send the form data to (for type=\"submit\" buttons)\n    form_action: Var[str]\n\n    # How the form data should be encoded when submitting to the server (for type=\"submit\" buttons)\n    form_enc_type: Var[str]\n\n    # HTTP method to use for sending form data (for type=\"submit\" buttons)\n    form_method: Var[str]\n\n    # Bypasses form validation when submitting (for type=\"submit\" buttons)\n    form_no_validate: Var[bool]\n\n    # Specifies where to display the response after submitting the form (for type=\"submit\" buttons)\n    form_target: Var[str]\n\n    # Name of the button, used when sending form data\n    name: Var[str]\n\n    # Type of the button (submit, reset, or button)\n    type: Var[ButtonType]\n\n    # Value of the button, used when sending form data\n    value: Var[str | int | float]\n\n    _invalid_children: ClassVar[list[str]] = [\"Button\"]\n\n\nclass Datalist(BaseHTML):\n    \"\"\"Display the datalist element.\"\"\"\n\n    tag = \"datalist\"\n\n\nclass Fieldset(Element):\n    \"\"\"Display the fieldset element.\"\"\"\n\n    tag = \"fieldset\"\n\n    # Disables all the form control descendants of the fieldset\n    disabled: Var[bool]\n\n    # Associates the fieldset with a form (by id)\n    form: Var[str]\n\n    # Name of the fieldset, used for scripting\n    name: Var[str]\n\n\nclass Form(BaseHTML):\n    \"\"\"Display the form element.\"\"\"\n\n    tag = \"form\"\n\n    # MIME types the server accepts for file upload\n    accept: Var[str]\n\n    # Character encodings to be used for form submission\n    accept_charset: Var[str]\n\n    # URL where the form's data should be submitted\n    action: Var[str]\n\n    # Whether the form should have autocomplete enabled\n    auto_complete: Var[str]\n\n    # Encoding type for the form data when submitted\n    enc_type: Var[str]\n\n    # HTTP method to use for form submission\n    method: Var[str]\n\n    # Name of the form\n    name: Var[str]\n\n    # Indicates that the form should not be validated on submit\n    no_validate: Var[bool]\n\n    # Where to display the response after submitting the form\n    target: Var[str]\n\n    # If true, the form will be cleared after submit.\n    reset_on_submit: Var[bool] = Var.create(False)\n\n    # The name used to make this form's submit handler function unique.\n    handle_submit_unique_name: Var[str]\n\n    # Fired when the form is submitted\n    on_submit: EventHandler[on_submit_event, on_submit_string_event]\n\n    @classmethod\n    def create(cls, *children, **props):\n        \"\"\"Create a form component.\n\n        Args:\n            *children: The children of the form.\n            **props: The properties of the form.\n\n        Returns:\n            The form component.\n        \"\"\"\n        if \"on_submit\" not in props:\n            props[\"on_submit\"] = prevent_default\n\n        if \"handle_submit_unique_name\" in props:\n            return super().create(*children, **props)\n\n        # Render the form hooks and use the hash of the resulting code to create a unique name.\n        props[\"handle_submit_unique_name\"] = \"\"\n        form = super().create(*children, **props)\n        form.handle_submit_unique_name = md5(  # pyright: ignore[reportAttributeAccessIssue]\n            str(form._get_all_hooks()).encode(\"utf-8\")\n        ).hexdigest()\n        return form\n\n    def add_imports(self) -> ImportDict:\n        \"\"\"Add imports needed by the form component.\n\n        Returns:\n            The imports for the form component.\n        \"\"\"\n        return {\n            \"react\": \"useCallback\",\n            f\"$/{Dirs.STATE_PATH}\": [\"getRefValue\", \"getRefValues\"],\n        }\n\n    def add_hooks(self) -> list[str]:\n        \"\"\"Add hooks for the form.\n\n        Returns:\n            The hooks for the form.\n        \"\"\"\n        if EventTriggers.ON_SUBMIT not in self.event_triggers:\n            return []\n        return [\n            _handle_submit_js_template(\n                handle_submit_unique_name=str(self.handle_submit_unique_name),\n                form_data=str(FORM_DATA),\n                field_ref_mapping=str(LiteralVar.create(self._get_form_refs())),\n                on_submit_event_chain=str(\n                    LiteralVar.create(self.event_triggers[EventTriggers.ON_SUBMIT])\n                ),\n                reset_on_submit=str(self.reset_on_submit).lower(),\n            )\n        ]\n\n    def _render(self) -> Tag:\n        render_tag = super()._render()\n        if EventTriggers.ON_SUBMIT in self.event_triggers:\n            render_tag = render_tag.add_props(**{\n                EventTriggers.ON_SUBMIT: Var(\n                    _js_expr=f\"handleSubmit_{self.handle_submit_unique_name}\",\n                    _var_type=EventChain,\n                )\n            })\n        return render_tag\n\n    def _get_form_refs(self) -> dict[str, Any]:\n        # Send all the input refs to the handler.\n        form_refs = {}\n        for ref in self._get_all_refs():\n            # when ref start with refs_ it's an array of refs, so we need different method\n            # to collect data\n            if ref.startswith(\"refs_\"):\n                ref_var = Var(_js_expr=ref[:-3])._as_ref()\n                form_refs[ref[len(\"refs_\") : -3]] = Var(\n                    _js_expr=f\"getRefValues({ref_var!s})\",\n                    _var_data=VarData.merge(ref_var._get_all_var_data()),\n                )\n            else:\n                ref_var = Var(_js_expr=ref)._as_ref()\n                form_refs[ref[4:]] = Var(\n                    _js_expr=f\"getRefValue({ref_var!s})\",\n                    _var_data=VarData.merge(ref_var._get_all_var_data()),\n                )\n        return form_refs\n\n    def _get_vars(\n        self, include_children: bool = True, ignore_ids: set[int] | None = None\n    ) -> Iterator[Var]:\n        yield from super()._get_vars(\n            include_children=include_children, ignore_ids=ignore_ids\n        )\n        yield from self._get_form_refs().values()\n\n    def _exclude_props(self) -> list[str]:\n        return [\n            *super()._exclude_props(),\n            \"reset_on_submit\",\n            \"handle_submit_unique_name\",\n        ]\n\n\nHTMLInputTypeAttribute = Literal[\n    \"button\",\n    \"checkbox\",\n    \"color\",\n    \"date\",\n    \"datetime-local\",\n    \"email\",\n    \"file\",\n    \"hidden\",\n    \"image\",\n    \"month\",\n    \"number\",\n    \"password\",\n    \"radio\",\n    \"range\",\n    \"reset\",\n    \"search\",\n    \"submit\",\n    \"tel\",\n    \"text\",\n    \"time\",\n    \"url\",\n    \"week\",\n]\n\n\nclass BaseInput(BaseHTML):\n    \"\"\"A base class for input elements.\"\"\"\n\n    tag = \"input\"\n\n    # Accepted types of files when the input is file type\n    accept: Var[str]\n\n    # Alternate text for input type=\"image\"\n    alt: Var[str]\n\n    # Whether the input should have autocomplete enabled\n    auto_complete: Var[str]\n\n    # Automatically focuses the input when the page loads\n    auto_focus: Var[bool]\n\n    # Captures media from the user (camera or microphone)\n    capture: Var[Literal[\"user\", \"environment\"] | bool]\n\n    # Indicates whether the input is checked (for checkboxes and radio buttons)\n    checked: Var[bool]\n\n    # The initial value (for checkboxes and radio buttons)\n    default_checked: Var[bool]\n\n    # The initial value for a text field\n    default_value: Var[str | int | float]\n\n    # Disables the input\n    disabled: Var[bool]\n\n    # Associates the input with a form (by id)\n    form: Var[str]\n\n    # URL to send the form data to (for type=\"submit\" buttons)\n    form_action: Var[str]\n\n    # How the form data should be encoded when submitting to the server (for type=\"submit\" buttons)\n    form_enc_type: Var[str]\n\n    # HTTP method to use for sending form data (for type=\"submit\" buttons)\n    form_method: Var[str]\n\n    # Bypasses form validation when submitting (for type=\"submit\" buttons)\n    form_no_validate: Var[bool]\n\n    # Specifies where to display the response after submitting the form (for type=\"submit\" buttons)\n    form_target: Var[str]\n\n    # References a datalist for suggested options\n    list: Var[str]\n\n    # Specifies the maximum value for the input\n    max: Var[str | int | float]\n\n    # Specifies the maximum number of characters allowed in the input\n    max_length: Var[int | float]\n\n    # Specifies the minimum number of characters required in the input\n    min_length: Var[int | float]\n\n    # Specifies the minimum value for the input\n    min: Var[str | int | float]\n\n    # Indicates whether multiple values can be entered in an input of the type email or file\n    multiple: Var[bool]\n\n    # Name of the input, used when sending form data\n    name: Var[str]\n\n    # Regex pattern the input's value must match to be valid\n    pattern: Var[str]\n\n    # Placeholder text in the input\n    placeholder: Var[str]\n\n    # Indicates whether the input is read-only\n    read_only: Var[bool]\n\n    # Indicates that the input is required\n    required: Var[bool]\n\n    # Specifies the visible width of a text control\n    size: Var[str | int | float]\n\n    # URL for image inputs\n    src: Var[str]\n\n    # Specifies the legal number intervals for an input\n    step: Var[str | int | float]\n\n    # Specifies the type of input\n    type: Var[HTMLInputTypeAttribute]\n\n    # Value of the input\n    value: Var[str | int | float]\n\n    # Fired when a key is pressed down\n    on_key_down: EventHandler[key_event]\n\n    # Fired when a key is released\n    on_key_up: EventHandler[key_event]\n\n\nclass CheckboxInput(BaseInput):\n    \"\"\"Display the input element.\"\"\"\n\n    # Fired when the input value changes\n    on_change: EventHandler[checked_input_event]\n\n    # Fired when the input gains focus\n    on_focus: EventHandler[checked_input_event]\n\n    # Fired when the input loses focus\n    on_blur: EventHandler[checked_input_event]\n\n\nclass ValueNumberInput(BaseInput):\n    \"\"\"Display the input element.\"\"\"\n\n    # Fired when the input value changes\n    on_change: EventHandler[float_input_event, int_input_event, input_event]\n\n    # Fired when the input gains focus\n    on_focus: EventHandler[float_input_event, int_input_event, input_event]\n\n    # Fired when the input loses focus\n    on_blur: EventHandler[float_input_event, int_input_event, input_event]\n\n\nclass Input(BaseInput):\n    \"\"\"Display the input element.\"\"\"\n\n    # Fired when the input value changes\n    on_change: EventHandler[input_event]\n\n    # Fired when the input gains focus\n    on_focus: EventHandler[input_event]\n\n    # Fired when the input loses focus\n    on_blur: EventHandler[input_event]\n\n    @classmethod\n    def create(cls, *children, **props):\n        \"\"\"Create an Input component.\n\n        Args:\n            *children: The children of the component.\n            **props: The properties of the component.\n\n        Returns:\n            The component.\n        \"\"\"\n        value = props.get(\"value\")\n\n        # React expects an empty string(instead of null) for controlled inputs.\n        if value is not None:\n            value_var = Var.create(value)\n            props[\"value\"] = ternary_operation(\n                value_var.is_not_none(), value_var, Var.create(\"\")\n            )\n\n        if cls is Input:\n            input_type = props.get(\"type\")\n\n            if isinstance(input_type, str) and input_type == \"checkbox\":\n                # Checkbox inputs should use the CheckboxInput class\n                return CheckboxInput.create(*children, **props)\n\n            if isinstance(input_type, str) and (\n                input_type == \"number\" or input_type == \"range\"\n            ):\n                # Number inputs should use the ValueNumberInput class\n                return ValueNumberInput.create(*children, **props)\n\n        return super().create(*children, **props)\n\n\nclass Label(BaseHTML):\n    \"\"\"Display the label element.\"\"\"\n\n    tag = \"label\"\n\n    # ID of a form control with which the label is associated\n    html_for: Var[str]\n\n    # Associates the label with a form (by id)\n    form: Var[str]\n\n\nclass Legend(BaseHTML):\n    \"\"\"Display the legend element.\"\"\"\n\n    tag = \"legend\"\n\n\nclass Meter(BaseHTML):\n    \"\"\"Display the meter element.\"\"\"\n\n    tag = \"meter\"\n\n    # Associates the meter with a form (by id)\n    form: Var[str]\n\n    # High limit of range (above this is considered high value)\n    high: Var[str | int | float]\n\n    # Low limit of range (below this is considered low value)\n    low: Var[str | int | float]\n\n    # Maximum value of the range\n    max: Var[str | int | float]\n\n    # Minimum value of the range\n    min: Var[str | int | float]\n\n    # Optimum value in the range\n    optimum: Var[str | int | float]\n\n    # Current value of the meter\n    value: Var[str | int | float]\n\n\nclass Optgroup(BaseHTML):\n    \"\"\"Display the optgroup element.\"\"\"\n\n    tag = \"optgroup\"\n\n    # Disables the optgroup\n    disabled: Var[bool]\n\n    # Label for the optgroup\n    label: Var[str]\n\n\nclass Option(BaseHTML):\n    \"\"\"Display the option element.\"\"\"\n\n    tag = \"option\"\n\n    # Disables the option\n    disabled: Var[bool]\n\n    # Label for the option, if the text is not the label\n    label: Var[str]\n\n    # Indicates that the option is initially selected\n    selected: Var[bool]\n\n    # Value to be sent as form data\n    value: Var[str | int | float]\n\n\nclass Output(BaseHTML):\n    \"\"\"Display the output element.\"\"\"\n\n    tag = \"output\"\n\n    # Associates the output with one or more elements (by their IDs)\n    html_for: Var[str]\n\n    # Associates the output with a form (by id)\n    form: Var[str]\n\n    # Name of the output element for form submission\n    name: Var[str]\n\n\nclass Progress(BaseHTML):\n    \"\"\"Display the progress element.\"\"\"\n\n    tag = \"progress\"\n\n    # Associates the progress element with a form (by id)\n    form: Var[str]\n\n    # Maximum value of the progress indicator\n    max: Var[str | int | float]\n\n    # Current value of the progress indicator\n    value: Var[str | int | float]\n\n\nclass Select(BaseHTML):\n    \"\"\"Display the select element.\"\"\"\n\n    tag = \"select\"\n\n    # Whether the form control should have autocomplete enabled\n    auto_complete: Var[str]\n\n    # Automatically focuses the select when the page loads\n    auto_focus: Var[bool]\n\n    # Disables the select control\n    disabled: Var[bool]\n\n    # Associates the select with a form (by id)\n    form: Var[str]\n\n    # Indicates that multiple options can be selected\n    multiple: Var[bool]\n\n    # Name of the select, used when submitting the form\n    name: Var[str]\n\n    # Indicates that the select control must have a selected option\n    required: Var[bool]\n\n    # Number of visible options in a drop-down list\n    size: Var[str | int]\n\n    # Fired when the select value changes\n    on_change: EventHandler[input_event]\n\n    # The controlled value of the select, read only unless used with on_change\n    value: Var[str]\n\n    # The default value of the select when initially rendered\n    default_value: Var[str]\n\n\nAUTO_HEIGHT_JS = \"\"\"\nconst autoHeightOnInput = (e, is_enabled) => {\n    if (is_enabled) {\n        const el = e.target;\n        el.style.overflowY = \"scroll\";\n        el.style.height = \"auto\";\n        el.style.height = (e.target.scrollHeight) + \"px\";\n        if (el.form && !el.form.data_resize_on_reset) {\n            el.form.addEventListener(\"reset\", () => window.setTimeout(() => autoHeightOnInput(e, is_enabled), 0))\n            el.form.data_resize_on_reset = true;\n        }\n    }\n}\n\"\"\"\n\n\nENTER_KEY_SUBMIT_JS = \"\"\"\nconst enterKeySubmitOnKeyDown = (e, is_enabled) => {\n    if (is_enabled && e.which === 13 && !e.shiftKey) {\n        e.preventDefault();\n        if (!e.repeat) {\n            if (e.target.form) {\n                e.target.form.requestSubmit();\n            }\n        }\n    }\n}\n\"\"\"\n\n\nclass Textarea(BaseHTML):\n    \"\"\"Display the textarea element.\"\"\"\n\n    tag = \"textarea\"\n\n    # Whether the form control should have autocomplete enabled\n    auto_complete: Var[str]\n\n    # Automatically focuses the textarea when the page loads\n    auto_focus: Var[bool]\n\n    # Automatically fit the content height to the text (use min-height with this prop)\n    auto_height: Var[bool]\n\n    # Visible width of the text control, in average character widths\n    cols: Var[str | int]\n\n    # The default value of the textarea when initially rendered\n    default_value: Var[str]\n\n    # Name part of the textarea to submit in 'dir' and 'name' pair when form is submitted\n    dirname: Var[str]\n\n    # Disables the textarea\n    disabled: Var[bool]\n\n    # Enter key submits form (shift-enter adds new line)\n    enter_key_submit: Var[bool]\n\n    # Associates the textarea with a form (by id)\n    form: Var[str]\n\n    # Maximum number of characters allowed in the textarea\n    max_length: Var[str | int]\n\n    # Minimum number of characters required in the textarea\n    min_length: Var[str | int]\n\n    # Name of the textarea, used when submitting the form\n    name: Var[str]\n\n    # Placeholder text in the textarea\n    placeholder: Var[str]\n\n    # Indicates whether the textarea is read-only\n    read_only: Var[bool]\n\n    # Indicates that the textarea is required\n    required: Var[bool]\n\n    # Visible number of lines in the text control\n    rows: Var[str | int]\n\n    # The controlled value of the textarea, read only unless used with on_change\n    value: Var[str]\n\n    # How the text in the textarea is to be wrapped when submitting the form\n    wrap: Var[str]\n\n    # Fired when the input value changes\n    on_change: EventHandler[input_event]\n\n    # Fired when the input gains focus\n    on_focus: EventHandler[input_event]\n\n    # Fired when the input loses focus\n    on_blur: EventHandler[input_event]\n\n    # Fired when a key is pressed down\n    on_key_down: EventHandler[key_event]\n\n    # Fired when a key is released\n    on_key_up: EventHandler[key_event]\n\n    @classmethod\n    def create(cls, *children, **props):\n        \"\"\"Create a textarea component.\n\n        Args:\n            *children: The children of the textarea.\n            **props: The properties of the textarea.\n\n        Returns:\n            The textarea component.\n\n        Raises:\n            ValueError: when `enter_key_submit` is combined with `on_key_down`.\n        \"\"\"\n        enter_key_submit = props.get(\"enter_key_submit\")\n        auto_height = props.get(\"auto_height\")\n        custom_attrs = props.setdefault(\"custom_attrs\", {})\n\n        if enter_key_submit is not None:\n            enter_key_submit = Var.create(enter_key_submit)\n            if \"on_key_down\" in props:\n                msg = \"Cannot combine `enter_key_submit` with `on_key_down`.\"\n                raise ValueError(msg)\n            custom_attrs[\"on_key_down\"] = Var(\n                _js_expr=f\"(e) => enterKeySubmitOnKeyDown(e, {enter_key_submit!s})\",\n                _var_data=VarData.merge(enter_key_submit._get_all_var_data()),\n            )\n        if auto_height is not None:\n            auto_height = Var.create(auto_height)\n            custom_attrs[\"on_input\"] = Var(\n                _js_expr=f\"(e) => autoHeightOnInput(e, {auto_height!s})\",\n                _var_data=VarData.merge(auto_height._get_all_var_data()),\n            )\n        return super().create(*children, **props)\n\n    def _exclude_props(self) -> list[str]:\n        return [\n            *super()._exclude_props(),\n            \"auto_height\",\n            \"enter_key_submit\",\n        ]\n\n    def _get_all_custom_code(self) -> dict[str, None]:\n        \"\"\"Include the custom code for auto_height and enter_key_submit functionality.\n\n        Returns:\n            The custom code for the component.\n        \"\"\"\n        custom_code = super()._get_all_custom_code()\n        if self.auto_height is not None:\n            custom_code[AUTO_HEIGHT_JS] = None\n        if self.enter_key_submit is not None:\n            custom_code[ENTER_KEY_SUBMIT_JS] = None\n        return custom_code\n\n\nbutton = Button.create\ndatalist = Datalist.create\nfieldset = Fieldset.create\nform = Form.create\ninput = Input.create\nlabel = Label.create\nlegend = Legend.create\nmeter = Meter.create\noptgroup = Optgroup.create\noption = Option.create\noutput = Output.create\nprogress = Progress.create\nselect = Select.create\ntextarea = Textarea.create\n"
  },
  {
    "path": "reflex/components/el/elements/inline.py",
    "content": "\"\"\"Inline classes.\"\"\"\n\nfrom typing import ClassVar, Literal\n\nfrom reflex.vars.base import Var\n\nfrom .base import BaseHTML\n\nReferrerPolicy = Literal[\n    \"\",\n    \"no-referrer\",\n    \"no-referrer-when-downgrade\",\n    \"origin\",\n    \"origin-when-cross-origin\",\n    \"same-origin\",\n    \"strict-origin\",\n    \"strict-origin-when-cross-origin\",\n    \"unsafe-url\",\n]\n\n\nclass A(BaseHTML):  # Inherits common attributes from BaseMeta\n    \"\"\"Display the 'a' element.\"\"\"\n\n    tag = \"a\"\n\n    # Specifies that the target (the file specified in the href attribute) will be downloaded when a user clicks on the hyperlink.\n    download: Var[str | bool]\n\n    # Specifies the URL of the page the link goes to\n    href: Var[str]\n\n    # Specifies the language of the linked document\n    href_lang: Var[str]\n\n    # Specifies what media/device the linked document is optimized for\n    media: Var[str]\n\n    # Specifies which referrer is sent when fetching the resource\n    ping: Var[str]\n\n    # Specifies the relationship between the current document and the linked document\n    referrer_policy: Var[ReferrerPolicy]\n\n    # Specifies the relationship between the linked document and the current document\n    rel: Var[str]\n\n    # Specifies where to open the linked document\n    target: Var[str | Literal[\"_self\", \"_blank\", \"_parent\", \"_top\"]]\n\n    _invalid_children: ClassVar[list[str]] = [\"A\"]\n\n\nclass Abbr(BaseHTML):\n    \"\"\"Display the abbr element.\"\"\"\n\n    tag = \"abbr\"\n\n\nclass B(BaseHTML):\n    \"\"\"Display the b element.\"\"\"\n\n    tag = \"b\"\n\n\nclass Bdi(BaseHTML):\n    \"\"\"Display the bdi element.\"\"\"\n\n    tag = \"bdi\"\n\n\nclass Bdo(BaseHTML):\n    \"\"\"Display the bdo element.\"\"\"\n\n    tag = \"bdo\"\n\n\nclass Br(BaseHTML):\n    \"\"\"Display the br element.\"\"\"\n\n    tag = \"br\"\n\n\nclass Cite(BaseHTML):\n    \"\"\"Display the cite element.\"\"\"\n\n    tag = \"cite\"\n\n\nclass Code(BaseHTML):\n    \"\"\"Display the code element.\"\"\"\n\n    tag = \"code\"\n\n\nclass Data(BaseHTML):\n    \"\"\"Display the data element.\"\"\"\n\n    tag = \"data\"\n\n    # Specifies the machine-readable translation of the data element.\n    value: Var[str | int | float]\n\n\nclass Dfn(BaseHTML):\n    \"\"\"Display the dfn element.\"\"\"\n\n    tag = \"dfn\"\n\n\nclass Em(BaseHTML):\n    \"\"\"Display the em element.\"\"\"\n\n    tag = \"em\"\n\n\nclass I(BaseHTML):  # noqa: E742\n    \"\"\"Display the i element.\"\"\"\n\n    tag = \"i\"\n\n\nclass Kbd(BaseHTML):\n    \"\"\"Display the kbd element.\"\"\"\n\n    tag = \"kbd\"\n\n\nclass Mark(BaseHTML):\n    \"\"\"Display the mark element.\"\"\"\n\n    tag = \"mark\"\n\n\nclass Q(BaseHTML):\n    \"\"\"Display the q element.\"\"\"\n\n    tag = \"q\"\n\n    # Specifies the source URL of the quote.\n    cite: Var[str]\n\n\nclass Rp(BaseHTML):\n    \"\"\"Display the rp element.\"\"\"\n\n    tag = \"rp\"\n\n\nclass Rt(BaseHTML):\n    \"\"\"Display the rt element.\"\"\"\n\n    tag = \"rt\"\n\n\nclass Ruby(BaseHTML):\n    \"\"\"Display the ruby element.\"\"\"\n\n    tag = \"ruby\"\n\n\nclass S(BaseHTML):\n    \"\"\"Display the s element.\"\"\"\n\n    tag = \"s\"\n\n\nclass Samp(BaseHTML):\n    \"\"\"Display the samp element.\"\"\"\n\n    tag = \"samp\"\n\n\nclass Small(BaseHTML):\n    \"\"\"Display the small element.\"\"\"\n\n    tag = \"small\"\n\n\nclass Span(BaseHTML):\n    \"\"\"Display the span element.\"\"\"\n\n    tag = \"span\"\n\n\nclass Strong(BaseHTML):\n    \"\"\"Display the strong element.\"\"\"\n\n    tag = \"strong\"\n\n\nclass Sub(BaseHTML):\n    \"\"\"Display the sub element.\"\"\"\n\n    tag = \"sub\"\n\n\nclass Sup(BaseHTML):\n    \"\"\"Display the sup element.\"\"\"\n\n    tag = \"sup\"\n\n\nclass Time(BaseHTML):\n    \"\"\"Display the time element.\"\"\"\n\n    tag = \"time\"\n\n    # Specifies the date and/or time of the element.\n    date_time: Var[str]\n\n\nclass U(BaseHTML):\n    \"\"\"Display the u element.\"\"\"\n\n    tag = \"u\"\n\n\nclass Wbr(BaseHTML):\n    \"\"\"Display the wbr element.\"\"\"\n\n    tag = \"wbr\"\n\n\na = A.create\nabbr = Abbr.create\nb = B.create\nbdi = Bdi.create\nbdo = Bdo.create\nbr = Br.create\ncite = Cite.create\ncode = Code.create\ndata = Data.create\ndfn = Dfn.create\nem = Em.create\ni = I.create\nkbd = Kbd.create\nmark = Mark.create\nq = Q.create\nrp = Rp.create\nrt = Rt.create\nruby = Ruby.create\ns = S.create\nsamp = Samp.create\nsmall = Small.create\nspan = Span.create\nstrong = Strong.create\nsub = Sub.create\nsup = Sup.create\ntime = Time.create\nu = U.create\nwbr = Wbr.create\n"
  },
  {
    "path": "reflex/components/el/elements/media.py",
    "content": "\"\"\"Media classes.\"\"\"\n\nfrom typing import Any, Literal\n\nfrom reflex import Component, ComponentNamespace\nfrom reflex.components.el.elements.inline import ReferrerPolicy\nfrom reflex.constants.colors import Color\nfrom reflex.vars.base import Var\n\nfrom .base import BaseHTML\n\n\nclass Area(BaseHTML):\n    \"\"\"Display the area element.\"\"\"\n\n    tag = \"area\"\n\n    # Alternate text for the area, used for accessibility\n    alt: Var[str]\n\n    # Coordinates to define the shape of the area\n    coords: Var[str]\n\n    # Specifies that the target will be downloaded when clicked\n    download: Var[str | bool]\n\n    # Hyperlink reference for the area\n    href: Var[str]\n\n    # Language of the linked resource\n    href_lang: Var[str]\n\n    # Specifies what media/device the linked resource is optimized for\n    media: Var[str]\n\n    # Specifies which referrer information to send with the link\n    referrer_policy: Var[ReferrerPolicy]\n\n    # Specifies the relationship of the target object to the link object\n    rel: Var[str]\n\n    # Defines the shape of the area (rectangle, circle, polygon)\n    shape: Var[str]\n\n    # Specifies where to open the linked document\n    target: Var[str]\n\n\nCrossOrigin = Literal[\"anonymous\", \"use-credentials\", \"\"]\n\n\nclass Audio(BaseHTML):\n    \"\"\"Display the audio element.\"\"\"\n\n    tag = \"audio\"\n\n    # Specifies that the audio will start playing as soon as it is ready\n    auto_play: Var[bool]\n\n    # Displays the standard audio controls\n    controls: Var[bool]\n\n    # Configures the CORS requests for the element\n    cross_origin: Var[CrossOrigin]\n\n    # Specifies that the audio will loop\n    loop: Var[bool]\n\n    # Indicates whether the audio is muted by default\n    muted: Var[bool]\n\n    # Specifies how the audio file should be preloaded\n    preload: Var[str]\n\n    # URL of the audio to play\n    src: Var[str]\n\n\nImageDecoding = Literal[\"async\", \"auto\", \"sync\"]\nImageLoading = Literal[\"eager\", \"lazy\"]\n\n\nclass Img(BaseHTML):\n    \"\"\"Display the img element.\"\"\"\n\n    tag = \"img\"\n\n    # Alternative text for the image\n    alt: Var[str]\n\n    # Configures the CORS requests for the image\n    cross_origin: Var[CrossOrigin]\n\n    # How the image should be decoded\n    decoding: Var[ImageDecoding]\n\n    # Specifies the loading behavior of the image\n    loading: Var[ImageLoading]\n\n    # Referrer policy for the image\n    referrer_policy: Var[ReferrerPolicy]\n\n    # Sizes of the image for different layouts\n    sizes: Var[str]\n\n    # URL of the image to display\n    src: Var[Any]\n\n    # A set of source sizes and URLs for responsive images\n    src_set: Var[str]\n\n    # The name of the map to use with the image\n    use_map: Var[str]\n\n    @classmethod\n    def create(cls, *children, **props) -> Component:\n        \"\"\"Override create method to apply source attribute to value if user fails to pass in attribute.\n\n        Args:\n            *children: The children of the component.\n            **props: The props of the component.\n\n        Returns:\n            The component.\n        \"\"\"\n        return (\n            super().create(src=children[0], **props)\n            if children\n            else super().create(*children, **props)\n        )\n\n\nclass Map(BaseHTML):\n    \"\"\"Display the map element.\"\"\"\n\n    tag = \"map\"\n\n    # Name of the map, referenced by the 'usemap' attribute in 'img' and 'object' elements\n    name: Var[str]\n\n\nclass Track(BaseHTML):\n    \"\"\"Display the track element.\"\"\"\n\n    tag = \"track\"\n\n    # Indicates that the track should be enabled unless the user's preferences indicate otherwise\n    default: Var[bool]\n\n    # Specifies the kind of text track\n    kind: Var[str]\n\n    # Title of the text track, used by the browser when listing available text tracks\n    label: Var[str]\n\n    # URL of the track file\n    src: Var[str]\n\n    # Language of the track text data\n    src_lang: Var[str]\n\n\nclass Video(BaseHTML):\n    \"\"\"Display the video element.\"\"\"\n\n    tag = \"video\"\n\n    # Specifies that the video will start playing as soon as it is ready\n    auto_play: Var[bool]\n\n    # Displays the standard video controls\n    controls: Var[bool]\n\n    # Configures the CORS requests for the video\n    cross_origin: Var[CrossOrigin]\n\n    # Specifies that the video will loop\n    loop: Var[bool]\n\n    # Indicates whether the video is muted by default\n    muted: Var[bool]\n\n    # Indicates that the video should play 'inline', inside its element's playback area\n    plays_inline: Var[bool]\n\n    # URL of an image to show while the video is downloading, or until the user hits the play button\n    poster: Var[str]\n\n    # Specifies how the video file should be preloaded\n    preload: Var[str]\n\n    # URL of the video to play\n    src: Var[str]\n\n\nclass Embed(BaseHTML):\n    \"\"\"Display the embed element.\"\"\"\n\n    tag = \"embed\"\n\n    # URL of the embedded content\n    src: Var[str]\n\n    # Media type of the embedded content\n    type: Var[str]\n\n\nclass Iframe(BaseHTML):\n    \"\"\"Display the iframe element.\"\"\"\n\n    tag = \"iframe\"\n\n    # Permissions policy for the iframe\n    allow: Var[str]\n\n    # Specifies the loading behavior of the iframe\n    loading: Var[Literal[\"eager\", \"lazy\"]]\n\n    # Name of the iframe, used as a target for hyperlinks and forms\n    name: Var[str]\n\n    # Referrer policy for the iframe\n    referrer_policy: Var[ReferrerPolicy]\n\n    # Security restrictions for the content in the iframe\n    sandbox: Var[str]\n\n    # URL of the document to display in the iframe\n    src: Var[str]\n\n    # HTML content to embed directly within the iframe\n    src_doc: Var[str]\n\n\nclass Object(BaseHTML):\n    \"\"\"Display the object element.\"\"\"\n\n    tag = \"object\"\n\n    # URL of the data to be used by the object\n    data: Var[str]\n\n    # Associates the object with a form element\n    form: Var[str]\n\n    # Name of the object, used for scripting or as a target for forms and links\n    name: Var[str]\n\n    # Media type of the data specified in the data attribute\n    type: Var[str]\n\n    # Name of an image map to use with the object\n    use_map: Var[str]\n\n\nclass Picture(BaseHTML):\n    \"\"\"Display the picture element.\"\"\"\n\n    tag = \"picture\"\n\n\nclass Portal(BaseHTML):\n    \"\"\"Display the portal element.\"\"\"\n\n    tag = \"portal\"\n\n\nclass Source(BaseHTML):\n    \"\"\"Display the source element.\"\"\"\n\n    tag = \"source\"\n\n    # Media query indicating what device the linked resource is optimized for\n    media: Var[str]\n\n    # Sizes of the source for different layouts\n    sizes: Var[str]\n\n    # URL of the media file or an image for the element to use\n    src: Var[str]\n\n    # A set of source sizes and URLs for responsive images\n    src_set: Var[str]\n\n    # Media type of the source\n    type: Var[str]\n\n\nclass Svg(BaseHTML):\n    \"\"\"Display the svg element.\"\"\"\n\n    tag = \"svg\"\n    # The width of the svg.\n    width: Var[str | int]\n    # The height of the svg.\n    height: Var[str | int]\n    # The XML namespace declaration.\n    xmlns: Var[str]\n    # The viewBox attribute defines the position and dimension, in user space, of an SVG viewport.\n    view_box: Var[str]\n    # Controls how the SVG scales to fit its viewport.\n    preserve_aspect_ratio: Var[str]\n    # Defines a list of transform definitions that are applied to an element and the element's children.\n    transform: Var[str]\n\n\nclass Text(BaseHTML):\n    \"\"\"The SVG text component.\"\"\"\n\n    tag = \"text\"\n    # The x coordinate of the starting point of the text baseline.\n    x: Var[str | int]\n    # The y coordinate of the starting point of the text baseline.\n    y: Var[str | int]\n    # Shifts the text position horizontally from a previous text element.\n    dx: Var[str | int]\n    # Shifts the text position vertically from a previous text element.\n    dy: Var[str | int]\n    # Rotates orientation of each individual glyph.\n    rotate: Var[str | int]\n    # How the text is stretched or compressed to fit the width defined by the text_length attribute.\n    length_adjust: Var[str]\n    # A width that the text should be scaled to fit.\n    text_length: Var[str | int]\n\n\nclass Line(BaseHTML):\n    \"\"\"The SVG line component.\"\"\"\n\n    tag = \"line\"\n    # The x-axis coordinate of the line starting point.\n    x1: Var[str | int]\n    # The x-axis coordinate of the the line ending point.\n    x2: Var[str | int]\n    # The y-axis coordinate of the line starting point.\n    y1: Var[str | int]\n    # The y-axis coordinate of the the line ending point.\n    y2: Var[str | int]\n    # The total path length, in user units.\n    path_length: Var[int]\n\n\nclass Circle(BaseHTML):\n    \"\"\"The SVG circle component.\"\"\"\n\n    tag = \"circle\"\n    # The x-axis coordinate of the center of the circle.\n    cx: Var[str | int]\n    # The y-axis coordinate of the center of the circle.\n    cy: Var[str | int]\n    # The radius of the circle.\n    r: Var[str | int]\n    # The total length for the circle's circumference, in user units.\n    path_length: Var[int]\n\n\nclass Ellipse(BaseHTML):\n    \"\"\"The SVG ellipse component.\"\"\"\n\n    tag = \"ellipse\"\n    # The x position of the center of the ellipse.\n    cx: Var[str | int]\n    # The y position of the center of the ellipse.\n    cy: Var[str | int]\n    # The radius of the ellipse on the x axis.\n    rx: Var[str | int]\n    # The radius of the ellipse on the y axis.\n    ry: Var[str | int]\n    # The total length for the ellipse's circumference, in user units.\n    path_length: Var[int]\n\n\nclass Rect(BaseHTML):\n    \"\"\"The SVG rect component.\"\"\"\n\n    tag = \"rect\"\n    # The x coordinate of the rect.\n    x: Var[str | int]\n    # The y coordinate of the rect.\n    y: Var[str | int]\n    # The width of the rect\n    width: Var[str | int]\n    # The height of the rect.\n    height: Var[str | int]\n    # The horizontal corner radius of the rect. Defaults to ry if it is specified.\n    rx: Var[str | int]\n    # The vertical corner radius of the rect. Defaults to rx if it is specified.\n    ry: Var[str | int]\n    # The total length of the rectangle's perimeter, in user units.\n    path_length: Var[int]\n\n\nclass Polygon(BaseHTML):\n    \"\"\"The SVG polygon component.\"\"\"\n\n    tag = \"polygon\"\n    # defines the list of points (pairs of x,y absolute coordinates) required to draw the polygon.\n    points: Var[str]\n    # This prop lets specify the total length for the path, in user units.\n    path_length: Var[int]\n\n\nclass Polyline(BaseHTML):\n    \"\"\"The SVG polyline component.\"\"\"\n\n    tag = \"polyline\"\n    # List of points (pairs of x,y coordinates) that define the polyline.\n    points: Var[str]\n    # The total path length, in user units.\n    path_length: Var[int]\n\n\nclass Defs(BaseHTML):\n    \"\"\"Display the defs element.\"\"\"\n\n    tag = \"defs\"\n\n\nclass LinearGradient(BaseHTML):\n    \"\"\"Display the linearGradient element.\"\"\"\n\n    tag = \"linearGradient\"\n\n    # Units for the gradient.\n    gradient_units: Var[str | bool]\n\n    # Transform applied to the gradient.\n    gradient_transform: Var[str | bool]\n\n    # Method used to spread the gradient.\n    spread_method: Var[str | bool]\n\n    # Reference to another gradient to inherit from.\n    href: Var[str]\n\n    # X coordinate of the starting point of the gradient.\n    x1: Var[str | int | float]\n\n    # X coordinate of the ending point of the gradient.\n    x2: Var[str | int | float]\n\n    # Y coordinate of the starting point of the gradient.\n    y1: Var[str | int | float]\n\n    # Y coordinate of the ending point of the gradient.\n    y2: Var[str | int | float]\n\n\nclass RadialGradient(BaseHTML):\n    \"\"\"Display the radialGradient element.\"\"\"\n\n    tag = \"radialGradient\"\n\n    # The x coordinate of the end circle of the radial gradient.\n    cx: Var[str | int | float]\n\n    # The y coordinate of the end circle of the radial gradient.\n    cy: Var[str | int | float]\n\n    # The radius of the start circle of the radial gradient.\n    fr: Var[str | int | float]\n\n    # The x coordinate of the start circle of the radial gradient.\n    fx: Var[str | int | float]\n\n    # The y coordinate of the start circle of the radial gradient.\n    fy: Var[str | int | float]\n\n    # Units for the gradient.\n    gradient_units: Var[str | bool]\n\n    # Transform applied to the gradient.\n    gradient_transform: Var[str | bool]\n\n    # Reference to another gradient to inherit from.\n    href: Var[str]\n\n    # The radius of the end circle of the radial gradient.\n    r: Var[str | int | float]\n\n    # Method used to spread the gradient.\n    spread_method: Var[str | bool]\n\n\nclass Stop(BaseHTML):\n    \"\"\"Display the stop element.\"\"\"\n\n    tag = \"stop\"\n\n    # Offset of the gradient stop.\n    offset: Var[str | float | int]\n\n    # Color of the gradient stop.\n    stop_color: Var[str | Color | bool]\n\n    # Opacity of the gradient stop.\n    stop_opacity: Var[str | float | int | bool]\n\n\nclass Path(BaseHTML):\n    \"\"\"Display the path element.\"\"\"\n\n    tag = \"path\"\n\n    # Defines the shape of the path.\n    d: Var[str | int | float]\n    # The total path length, in user units.\n    path_length: Var[int]\n\n\nclass Marker(BaseHTML):\n    \"\"\"Display the marker element.\"\"\"\n\n    tag = \"marker\"\n\n    # The height of the marker viewport.\n    marker_height: Var[str | int | float]\n\n    # The width of the marker viewport.\n    marker_width: Var[str | int | float]\n\n    # The coordinate system for the marker attributes.\n    marker_units: Var[str]\n\n    # The orientation of the marker relative to the shape it is attached to.\n    orient: Var[str | int | float]\n\n    # How the svg fragment must be deformed if it is embedded in a container with a different aspect ratio.\n    preserve_aspect_ratio: Var[str]\n\n    # The x coordinate for the reference point of the marker.\n    ref_x: Var[str | int | float]\n\n    # The y coordinate for the reference point of the marker.\n    ref_y: Var[str | int | float]\n\n    # The bound of the SVG viewport for the current SVG fragment.\n    view_box: Var[str]\n\n\nclass G(BaseHTML):\n    \"\"\"The SVG g component, used to group other SVG elements.\"\"\"\n\n    tag = \"g\"\n\n    # The fill color of the group.\n    fill: Var[str | Color]\n\n    # The fill opacity of the group.\n    fill_opacity: Var[str | int | float]\n\n    # The stroke color of the group.\n    stroke: Var[str | Color]\n\n    # The stroke opacity of the group.\n    stroke_opacity: Var[str | int | float]\n\n    # The stroke width of the group.\n    stroke_width: Var[str | int | float]\n\n    # The transform applied to the group.\n    transform: Var[str]\n\n\nclass SvgImage(BaseHTML):\n    \"\"\"The SVG image component.\"\"\"\n\n    tag = \"image\"\n\n    # URL of the image to display.\n    href: Var[str]\n\n    # X coordinate of the image.\n    x: Var[str | int]\n\n    # Y coordinate of the image.\n    y: Var[str | int]\n\n    # Width of the image.\n    width: Var[str | int]\n\n    # Height of the image.\n    height: Var[str | int]\n\n    # How the image should scale to fit its viewport.\n    preserve_aspect_ratio: Var[str]\n\n    # CORS settings for the image.\n    crossorigin: Var[str]\n\n\nclass Use(BaseHTML):\n    \"\"\"The SVG use component for reusing defined elements.\"\"\"\n\n    tag = \"use\"\n\n    # Reference to the element to reuse.\n    href: Var[str]\n\n    # X coordinate where the referenced element should be positioned.\n    x: Var[str | int]\n\n    # Y coordinate where the referenced element should be positioned.\n    y: Var[str | int]\n\n    # Width of the referenced element.\n    width: Var[str | int]\n\n    # Height of the referenced element.\n    height: Var[str | int]\n\n\nclass TSpan(BaseHTML):\n    \"\"\"The SVG tspan component for text spans within text elements.\"\"\"\n\n    tag = \"tspan\"\n\n    # X coordinate of the text.\n    x: Var[str | int]\n\n    # Y coordinate of the text.\n    y: Var[str | int]\n\n    # Horizontal offset from the previous text element.\n    dx: Var[str | int]\n\n    # Vertical offset from the previous text element.\n    dy: Var[str | int]\n\n    # Rotation of the text.\n    rotate: Var[str | int]\n\n    # How the text is stretched or compressed to fit the width defined by text_length.\n    length_adjust: Var[str]\n\n    # A width that the text should be scaled to fit.\n    text_length: Var[str | int]\n\n\nclass TextPath(BaseHTML):\n    \"\"\"The SVG textPath component for text along a path.\"\"\"\n\n    tag = \"textPath\"\n\n    # Reference to the path along which the text should be rendered.\n    href: Var[str]\n\n    # Inline path data.\n    path: Var[str]\n\n    # Distance along the path from its beginning to the initial position of the text.\n    start_offset: Var[str | int]\n\n    # Method for rendering text along the path.\n    method: Var[str]\n\n    # Spacing method for text.\n    spacing: Var[str]\n\n    # Which side of the path the text should be rendered on.\n    side: Var[str]\n\n    # How the text is stretched or compressed to fit the specified length.\n    length_adjust: Var[str]\n\n    # Target length for the text.\n    text_length: Var[str | int]\n\n\nclass Pattern(BaseHTML):\n    \"\"\"The SVG pattern component for defining repeating patterns.\"\"\"\n\n    tag = \"pattern\"\n\n    # X coordinate of the pattern.\n    x: Var[str | int]\n\n    # Y coordinate of the pattern.\n    y: Var[str | int]\n\n    # Width of the pattern.\n    width: Var[str | int]\n\n    # Height of the pattern.\n    height: Var[str | int]\n\n    # Units for the pattern coordinates.\n    pattern_units: Var[str]\n\n    # Units for the pattern content coordinates.\n    pattern_content_units: Var[str]\n\n    # Transform applied to the pattern.\n    pattern_transform: Var[str]\n\n    # ViewBox definition for the pattern.\n    view_box: Var[str]\n\n    # How the pattern should scale to fit its viewport.\n    preserve_aspect_ratio: Var[str]\n\n    # Reference to another pattern to inherit from.\n    href: Var[str]\n\n\nclass ClipPath(BaseHTML):\n    \"\"\"The SVG clipPath component for defining clipping paths.\"\"\"\n\n    tag = \"clipPath\"\n\n    # Units for the clipping path coordinates.\n    clip_path_units: Var[str]\n\n\nclass Symbol(BaseHTML):\n    \"\"\"The SVG symbol component for defining reusable symbols.\"\"\"\n\n    tag = \"symbol\"\n\n    # ViewBox definition for the symbol.\n    view_box: Var[str]\n\n    # How the symbol should scale to fit its viewport.\n    preserve_aspect_ratio: Var[str]\n\n    # Reference X coordinate.\n    ref_x: Var[str | int]\n\n    # Reference Y coordinate.\n    ref_y: Var[str | int]\n\n\nclass Mask(BaseHTML):\n    \"\"\"The SVG mask component for defining masks.\"\"\"\n\n    tag = \"mask\"\n\n    # X coordinate of the mask.\n    x: Var[str | int]\n\n    # Y coordinate of the mask.\n    y: Var[str | int]\n\n    # Width of the mask.\n    width: Var[str | int]\n\n    # Height of the mask.\n    height: Var[str | int]\n\n    # Units for the mask coordinates.\n    mask_units: Var[str]\n\n    # Units for the mask content coordinates.\n    mask_content_units: Var[str]\n\n\nclass ForeignObject(BaseHTML):\n    \"\"\"The SVG foreignObject component for embedding foreign content.\"\"\"\n\n    tag = \"foreignObject\"\n\n    # X coordinate of the foreign object.\n    x: Var[str | int]\n\n    # Y coordinate of the foreign object.\n    y: Var[str | int]\n\n    # Width of the foreign object.\n    width: Var[str | int]\n\n    # Height of the foreign object.\n    height: Var[str | int]\n\n\nclass SvgA(BaseHTML):\n    \"\"\"The SVG anchor component for creating links.\"\"\"\n\n    tag = \"a\"\n\n    # URL of the link.\n    href: Var[str]\n\n    # Where to open the linked resource.\n    target: Var[str]\n\n    # Download attribute for the link.\n    download: Var[str]\n\n    # Relationship between the current document and the linked resource.\n    rel: Var[str]\n\n    # Language of the linked resource.\n    hreflang: Var[str]\n\n    # MIME type of the linked resource.\n    type: Var[str]\n\n    # Referrer policy for the link.\n    referrerpolicy: Var[str]\n\n\nclass Animate(BaseHTML):\n    \"\"\"The SVG animate component for animations.\"\"\"\n\n    tag = \"animate\"\n\n    # Name of the attribute to animate.\n    attribute_name: Var[str]\n\n    # Starting value of the animation.\n    from_: Var[str]\n\n    # Ending value of the animation.\n    to: Var[str]\n\n    # Duration of the animation.\n    dur: Var[str]\n\n    # When the animation should begin.\n    begin: Var[str]\n\n    # When the animation should end.\n    end: Var[str]\n\n    # Number of times to repeat the animation.\n    repeat_count: Var[str]\n\n    # How values should be calculated during the animation.\n    calc_mode: Var[str]\n\n    # List of values for the animation.\n    values: Var[str]\n\n    # Key times for the animation values.\n    key_times: Var[str]\n\n    # Key splines for smooth transitions.\n    key_splines: Var[str]\n\n    # Whether animation values should accumulate.\n    accumulate: Var[str]\n\n    # Whether animation values should be additive.\n    additive: Var[str]\n\n    # Reference to the target element.\n    href: Var[str]\n\n\nclass AnimateMotion(BaseHTML):\n    \"\"\"The SVG animateMotion component for motion animations.\"\"\"\n\n    tag = \"animateMotion\"\n\n    # Path along which to animate.\n    path: Var[str]\n\n    # Duration of the animation.\n    dur: Var[str]\n\n    # When the animation should begin.\n    begin: Var[str]\n\n    # When the animation should end.\n    end: Var[str]\n\n    # Number of times to repeat the animation.\n    repeat_count: Var[str]\n\n    # Rotation behavior during motion.\n    rotate: Var[str]\n\n    # Key times for the motion.\n    key_times: Var[str]\n\n    # Key points along the path.\n    key_points: Var[str]\n\n    # Reference to the target element.\n    href: Var[str]\n\n\nclass AnimateTransform(BaseHTML):\n    \"\"\"The SVG animateTransform component for transform animations.\"\"\"\n\n    tag = \"animateTransform\"\n\n    # Name of the transform attribute to animate.\n    attribute_name: Var[str]\n\n    # Type of transformation.\n    type: Var[str]\n\n    # Starting value of the transformation.\n    from_: Var[str]\n\n    # Ending value of the transformation.\n    to: Var[str]\n\n    # Duration of the animation.\n    dur: Var[str]\n\n    # When the animation should begin.\n    begin: Var[str]\n\n    # When the animation should end.\n    end: Var[str]\n\n    # Number of times to repeat the animation.\n    repeat_count: Var[str]\n\n    # List of values for the transformation.\n    values: Var[str]\n\n    # Reference to the target element.\n    href: Var[str]\n\n\nclass Set(BaseHTML):\n    \"\"\"The SVG set component for setting attribute values.\"\"\"\n\n    tag = \"set\"\n\n    # Name of the attribute to set.\n    attribute_name: Var[str]\n\n    # Value to set the attribute to.\n    to: Var[str]\n\n    # When to set the attribute.\n    begin: Var[str]\n\n    # Duration for which to maintain the value.\n    dur: Var[str]\n\n    # When to end the setting.\n    end: Var[str]\n\n    # Reference to the target element.\n    href: Var[str]\n\n\nclass MPath(BaseHTML):\n    \"\"\"The SVG mpath component for motion path references.\"\"\"\n\n    tag = \"mpath\"\n\n    # Reference to a path element.\n    href: Var[str]\n\n\nclass Desc(BaseHTML):\n    \"\"\"The SVG desc component for descriptions.\"\"\"\n\n    tag = \"desc\"\n\n\nclass Title(BaseHTML):\n    \"\"\"The SVG title component for titles.\"\"\"\n\n    tag = \"title\"\n\n\nclass Metadata(BaseHTML):\n    \"\"\"The SVG metadata component for metadata.\"\"\"\n\n    tag = \"metadata\"\n\n\nclass Script(BaseHTML):\n    \"\"\"The SVG script component for scripts.\"\"\"\n\n    tag = \"script\"\n\n    # MIME type of the script.\n    type: Var[str]\n\n    # URL of external script.\n    href: Var[str]\n\n    # CORS settings for the script.\n    crossorigin: Var[str]\n\n\nclass SvgStyle(BaseHTML):\n    \"\"\"The SVG style component for stylesheets.\"\"\"\n\n    tag = \"style\"\n\n    # MIME type of the stylesheet.\n    type: Var[str]\n\n    # Media query for the stylesheet.\n    media: Var[str]\n\n    # Title of the stylesheet.\n    title: Var[str]\n\n\nclass Switch(BaseHTML):\n    \"\"\"The SVG switch component for conditional processing.\"\"\"\n\n    tag = \"switch\"\n\n\nclass View(BaseHTML):\n    \"\"\"The SVG view component for view definitions.\"\"\"\n\n    tag = \"view\"\n\n    # ViewBox definition for the view.\n    view_box: Var[str]\n\n    # How the view should scale to fit its viewport.\n    preserve_aspect_ratio: Var[str]\n\n\nclass SVG(ComponentNamespace):\n    \"\"\"SVG component namespace.\"\"\"\n\n    text = staticmethod(Text.create)\n    line = staticmethod(Line.create)\n    circle = staticmethod(Circle.create)\n    ellipse = staticmethod(Ellipse.create)\n    rect = staticmethod(Rect.create)\n    polygon = staticmethod(Polygon.create)\n    polyline = staticmethod(Polyline.create)\n    path = staticmethod(Path.create)\n    stop = staticmethod(Stop.create)\n    linear_gradient = staticmethod(LinearGradient.create)\n    radial_gradient = staticmethod(RadialGradient.create)\n    defs = staticmethod(Defs.create)\n    marker = staticmethod(Marker.create)\n    g = staticmethod(G.create)\n    image = staticmethod(SvgImage.create)\n    use = staticmethod(Use.create)\n    tspan = staticmethod(TSpan.create)\n    text_path = staticmethod(TextPath.create)\n    pattern = staticmethod(Pattern.create)\n    clip_path = staticmethod(ClipPath.create)\n    symbol = staticmethod(Symbol.create)\n    mask = staticmethod(Mask.create)\n    foreign_object = staticmethod(ForeignObject.create)\n    a = staticmethod(SvgA.create)\n    animate = staticmethod(Animate.create)\n    animate_motion = staticmethod(AnimateMotion.create)\n    animate_transform = staticmethod(AnimateTransform.create)\n    set = staticmethod(Set.create)\n    mpath = staticmethod(MPath.create)\n    desc = staticmethod(Desc.create)\n    title = staticmethod(Title.create)\n    metadata = staticmethod(Metadata.create)\n    script = staticmethod(Script.create)\n    style = staticmethod(SvgStyle.create)\n    switch = staticmethod(Switch.create)\n    view = staticmethod(View.create)\n    __call__ = staticmethod(Svg.create)\n\n\ntext = Text.create\nline = Line.create\ncircle = Circle.create\nellipse = Ellipse.create\nrect = Rect.create\npolygon = Polygon.create\npolyline = Polyline.create\npath = Path.create\nstop = Stop.create\nlinear_gradient = LinearGradient.create\nradial_gradient = RadialGradient.create\ndefs = Defs.create\nmarker = Marker.create\ng = G.create\nuse = Use.create\ntspan = TSpan.create\ntext_path = TextPath.create\npattern = Pattern.create\nclip_path = ClipPath.create\nsymbol = Symbol.create\nmask = Mask.create\nforeign_object = ForeignObject.create\nanimate = Animate.create\nanimate_motion = AnimateMotion.create\nanimate_transform = AnimateTransform.create\nset_svg = Set.create\nmpath = MPath.create\ndesc = Desc.create\nmetadata = Metadata.create\nswitch = Switch.create\nview = View.create\narea = Area.create\naudio = Audio.create\nimage = img = Img.create\nmap = Map.create\ntrack = Track.create\nvideo = Video.create\nembed = Embed.create\niframe = Iframe.create\nobject = Object.create\npicture = Picture.create\nportal = Portal.create\nsource = Source.create\nsvg = SVG()\n"
  },
  {
    "path": "reflex/components/el/elements/metadata.py",
    "content": "\"\"\"Metadata classes.\"\"\"\n\nfrom reflex.components.el.element import Element\nfrom reflex.components.el.elements.inline import ReferrerPolicy\nfrom reflex.components.el.elements.media import CrossOrigin\nfrom reflex.vars.base import Var\n\nfrom .base import BaseHTML\n\n\nclass Base(BaseHTML):\n    \"\"\"Display the base element.\"\"\"\n\n    tag = \"base\"\n\n    href: Var[str]\n    target: Var[str]\n\n\nclass Head(BaseHTML):\n    \"\"\"Display the head element.\"\"\"\n\n    tag = \"head\"\n\n\nclass Link(BaseHTML):\n    \"\"\"Display the link element.\"\"\"\n\n    tag = \"link\"\n\n    # Specifies the CORS settings for the linked resource\n    cross_origin: Var[CrossOrigin]\n\n    # Specifies the URL of the linked document/resource\n    href: Var[str]\n\n    # Specifies the language of the text in the linked document\n    href_lang: Var[str]\n\n    # Allows a browser to check the fetched link for integrity\n    integrity: Var[str]\n\n    # Specifies on what device the linked document will be displayed\n    media: Var[str]\n\n    # Specifies the referrer policy of the linked document\n    referrer_policy: Var[ReferrerPolicy]\n\n    # Specifies the relationship between the current document and the linked one\n    rel: Var[str]\n\n    # Specifies the sizes of icons for visual media\n    sizes: Var[str]\n\n    # Specifies the MIME type of the linked document\n    type: Var[str]\n\n\nclass Meta(BaseHTML):  # Inherits common attributes from BaseHTML\n    \"\"\"Display the meta element.\"\"\"\n\n    tag = \"meta\"  # The HTML tag for this element is <meta>\n\n    # Specifies the character encoding for the HTML document\n    char_set: Var[str]\n\n    # Defines the content of the metadata\n    content: Var[str]\n\n    # Provides an HTTP header for the information/value of the content attribute\n    http_equiv: Var[str]\n\n    # Specifies a name for the metadata\n    name: Var[str]\n\n    # The type of metadata value.\n    property: Var[str]\n\n\nclass Title(Element):\n    \"\"\"Display the title element.\"\"\"\n\n    tag = \"title\"\n\n\n# Had to be named with an underscore so it doesn't conflict with reflex.style Style in pyi\nclass StyleEl(Element):\n    \"\"\"Display the style element.\"\"\"\n\n    tag = \"style\"\n\n    media: Var[str]\n\n    suppress_hydration_warning: Var[bool] = Var.create(True)\n\n\nbase = Base.create\nhead = Head.create\nlink = Link.create\nmeta = Meta.create\ntitle = Title.create\nstyle = StyleEl.create\n"
  },
  {
    "path": "reflex/components/el/elements/other.py",
    "content": "\"\"\"Other classes.\"\"\"\n\nfrom reflex.vars.base import Var\n\nfrom .base import BaseHTML\n\n\nclass Details(BaseHTML):\n    \"\"\"Display the details element.\"\"\"\n\n    tag = \"details\"\n\n    # Indicates whether the details will be visible (expanded) to the user\n    open: Var[bool]\n\n\nclass Dialog(BaseHTML):\n    \"\"\"Display the dialog element.\"\"\"\n\n    tag = \"dialog\"\n\n    # Indicates whether the dialog is active and can be interacted with\n    open: Var[bool]\n\n\nclass Summary(BaseHTML):\n    \"\"\"Display the summary element.\n\n    Used as a summary or caption for a <details> element.\n    \"\"\"\n\n    tag = \"summary\"\n\n\nclass Slot(BaseHTML):\n    \"\"\"Display the slot element.\n\n    Used as a placeholder inside a web component.\n    \"\"\"\n\n    tag = \"slot\"\n\n\nclass Template(BaseHTML):\n    \"\"\"Display the template element.\n\n    Used for declaring fragments of HTML that can be cloned and inserted in the document.\n    \"\"\"\n\n    tag = \"template\"\n\n\nclass Math(BaseHTML):\n    \"\"\"Display the math element.\n\n    Represents a mathematical expression.\n    \"\"\"\n\n    tag = \"math\"\n\n\nclass Html(BaseHTML):\n    \"\"\"Display the html element.\"\"\"\n\n    tag = \"html\"\n\n    # Specifies the URL of the document's cache manifest (obsolete in HTML5)\n    manifest: Var[str]\n\n\ndetails = Details.create\ndialog = Dialog.create\nsummary = Summary.create\nslot = Slot.create\ntemplate = Template.create\nmath = Math.create\nhtml = Html.create\n"
  },
  {
    "path": "reflex/components/el/elements/scripts.py",
    "content": "\"\"\"Scripts classes.\"\"\"\n\nfrom reflex.components.el.elements.inline import ReferrerPolicy\nfrom reflex.components.el.elements.media import CrossOrigin\nfrom reflex.vars.base import Var\n\nfrom .base import BaseHTML\n\n\nclass Canvas(BaseHTML):\n    \"\"\"Display the canvas element.\"\"\"\n\n    tag = \"canvas\"\n\n\nclass Noscript(BaseHTML):\n    \"\"\"Display the noscript element.\"\"\"\n\n    tag = \"noscript\"\n\n\nclass Script(BaseHTML):\n    \"\"\"Display the script element.\"\"\"\n\n    tag = \"script\"\n\n    # Indicates that the script should be executed asynchronously\n    async_: Var[bool]\n\n    # Character encoding of the external script\n    char_set: Var[str]\n\n    # Configures the CORS requests for the script\n    cross_origin: Var[CrossOrigin]\n\n    # Indicates that the script should be executed after the page has finished parsing\n    defer: Var[bool]\n\n    # Security feature allowing browsers to verify what they fetch\n    integrity: Var[str]\n\n    # Specifies which referrer information to send when fetching the script\n    referrer_policy: Var[ReferrerPolicy]\n\n    # URL of an external script\n    src: Var[str]\n\n    # Specifies the MIME type of the script\n    type: Var[str]\n\n\ncanvas = Canvas.create\nnoscript = Noscript.create\nscript = Script.create\n"
  },
  {
    "path": "reflex/components/el/elements/sectioning.py",
    "content": "\"\"\"Sectioning classes.\"\"\"\n\nfrom .base import BaseHTML\n\n\nclass Body(BaseHTML):\n    \"\"\"Display the body element.\"\"\"\n\n    tag = \"body\"\n\n\nclass Address(BaseHTML):\n    \"\"\"Display the address element.\"\"\"\n\n    tag = \"address\"\n\n\nclass Article(BaseHTML):\n    \"\"\"Display the article element.\"\"\"\n\n    tag = \"article\"\n\n\nclass Aside(BaseHTML):\n    \"\"\"Display the aside element.\"\"\"\n\n    tag = \"aside\"\n\n\nclass Footer(BaseHTML):\n    \"\"\"Display the footer element.\"\"\"\n\n    tag = \"footer\"\n\n\nclass Header(BaseHTML):\n    \"\"\"Display the header element.\"\"\"\n\n    tag = \"header\"\n\n\nclass H1(BaseHTML):\n    \"\"\"Display the h1 element.\"\"\"\n\n    tag = \"h1\"\n\n\nclass H2(BaseHTML):\n    \"\"\"Display the h1 element.\"\"\"\n\n    tag = \"h2\"\n\n\nclass H3(BaseHTML):\n    \"\"\"Display the h1 element.\"\"\"\n\n    tag = \"h3\"\n\n\nclass H4(BaseHTML):\n    \"\"\"Display the h1 element.\"\"\"\n\n    tag = \"h4\"\n\n\nclass H5(BaseHTML):\n    \"\"\"Display the h1 element.\"\"\"\n\n    tag = \"h5\"\n\n\nclass H6(BaseHTML):\n    \"\"\"Display the h1 element.\"\"\"\n\n    tag = \"h6\"\n\n\nclass Main(BaseHTML):\n    \"\"\"Display the main element.\"\"\"\n\n    tag = \"main\"\n\n\nclass Nav(BaseHTML):\n    \"\"\"Display the nav element.\"\"\"\n\n    tag = \"nav\"\n\n\nclass Section(BaseHTML):\n    \"\"\"Display the section element.\"\"\"\n\n    tag = \"section\"\n\n\naddress = Address.create\narticle = Article.create\naside = Aside.create\nbody = Body.create\nheader = Header.create\nfooter = Footer.create\nh1 = H1.create\nh2 = H2.create\nh3 = H3.create\nh4 = H4.create\nh5 = H5.create\nh6 = H6.create\nmain = Main.create\nnav = Nav.create\nsection = Section.create\n"
  },
  {
    "path": "reflex/components/el/elements/tables.py",
    "content": "\"\"\"Tables classes.\"\"\"\n\nfrom typing import Literal\n\nfrom reflex.vars.base import Var\n\nfrom .base import BaseHTML\n\n\nclass Caption(BaseHTML):\n    \"\"\"Display the caption element.\"\"\"\n\n    tag = \"caption\"\n\n\nclass Col(BaseHTML):\n    \"\"\"Display the col element.\"\"\"\n\n    tag = \"col\"\n\n    # Number of columns the col element spans\n    span: Var[int]\n\n\nclass Colgroup(BaseHTML):\n    \"\"\"Display the colgroup element.\"\"\"\n\n    tag = \"colgroup\"\n\n    # Number of columns the colgroup element spans\n    span: Var[int]\n\n\nclass Table(BaseHTML):\n    \"\"\"Display the table element.\"\"\"\n\n    tag = \"table\"\n\n    # Alignment of the table\n    align: Var[Literal[\"left\", \"center\", \"right\"]]\n\n    # Provides a summary of the table's purpose and structure\n    summary: Var[str]\n\n\nclass Tbody(BaseHTML):\n    \"\"\"Display the tbody element.\"\"\"\n\n    tag = \"tbody\"\n\n\nclass Td(BaseHTML):\n    \"\"\"Display the td element.\"\"\"\n\n    tag = \"td\"\n\n    # Alignment of the content within the table cell\n    align: Var[Literal[\"left\", \"center\", \"right\", \"justify\", \"char\"]]\n\n    # Number of columns a cell should span\n    col_span: Var[int]\n\n    # IDs of the headers associated with this cell\n    headers: Var[str]\n\n    # Number of rows a cell should span\n    row_span: Var[int]\n\n\nclass Tfoot(BaseHTML):\n    \"\"\"Display the tfoot element.\"\"\"\n\n    tag = \"tfoot\"\n\n\nclass Th(BaseHTML):\n    \"\"\"Display the th element.\"\"\"\n\n    tag = \"th\"\n\n    # Alignment of the content within the table header cell\n    align: Var[Literal[\"left\", \"center\", \"right\", \"justify\", \"char\"]]\n\n    # Number of columns a header cell should span\n    col_span: Var[int]\n\n    # IDs of the headers associated with this header cell\n    headers: Var[str]\n\n    # Number of rows a header cell should span\n    row_span: Var[int]\n\n    # Scope of the header cell (row, col, rowgroup, colgroup)\n    scope: Var[str]\n\n\nclass Thead(BaseHTML):\n    \"\"\"Display the thead element.\"\"\"\n\n    tag = \"thead\"\n\n\nclass Tr(BaseHTML):\n    \"\"\"Display the tr element.\"\"\"\n\n    tag = \"tr\"\n\n\ncaption = Caption.create\ncol = Col.create\ncolgroup = Colgroup.create\ntable = Table.create\ntbody = Tbody.create\ntd = Td.create\ntfoot = Tfoot.create\nth = Th.create\nthead = Thead.create\ntr = Tr.create\n"
  },
  {
    "path": "reflex/components/el/elements/typography.py",
    "content": "\"\"\"Typography classes.\"\"\"\n\nfrom typing import ClassVar, Literal\n\nfrom reflex.vars.base import Var\n\nfrom .base import BaseHTML\n\n\nclass Blockquote(BaseHTML):\n    \"\"\"Display the blockquote element.\"\"\"\n\n    tag = \"blockquote\"\n\n    # Define the title of a work.\n    cite: Var[str]\n\n\nclass Dd(BaseHTML):\n    \"\"\"Display the dd element.\"\"\"\n\n    tag = \"dd\"\n\n\nclass Div(BaseHTML):\n    \"\"\"Display the div element.\"\"\"\n\n    tag = \"div\"\n\n\nclass Dl(BaseHTML):\n    \"\"\"Display the dl element.\"\"\"\n\n    tag = \"dl\"\n\n\nclass Dt(BaseHTML):\n    \"\"\"Display the dt element.\"\"\"\n\n    tag = \"dt\"\n\n\nclass Figcaption(BaseHTML):\n    \"\"\"Display the figcaption element.\"\"\"\n\n    tag = \"figcaption\"\n\n\nclass Figure(BaseHTML):\n    \"\"\"Display the figure element.\"\"\"\n\n    tag = \"figure\"\n\n\nclass Hr(BaseHTML):\n    \"\"\"Display the hr element.\"\"\"\n\n    tag = \"hr\"\n\n\nclass Li(BaseHTML):\n    \"\"\"Display the li element.\"\"\"\n\n    tag = \"li\"\n\n\nclass Menu(BaseHTML):\n    \"\"\"Display the menu element.\"\"\"\n\n    tag = \"menu\"\n\n    # Specifies that the menu element is a context menu.\n    type: Var[str]\n\n\nclass Ol(BaseHTML):\n    \"\"\"Display the ol element.\"\"\"\n\n    tag = \"ol\"\n\n    # Reverses the order of the list.\n    reversed: Var[bool]\n\n    # Specifies the start value of the first list item in an ordered list.\n    start: Var[int]\n\n    # Specifies the kind of marker to use in the list (letters or numbers).\n    type: Var[Literal[\"1\", \"a\", \"A\", \"i\", \"I\"]]\n\n\nclass P(BaseHTML):\n    \"\"\"Display the p element.\"\"\"\n\n    tag = \"p\"\n\n    _invalid_children: ClassVar[list] = [\"P\", \"Ol\", \"Ul\", \"Div\"]\n\n\nclass Pre(BaseHTML):\n    \"\"\"Display the pre element.\"\"\"\n\n    tag = \"pre\"\n\n\nclass Ul(BaseHTML):\n    \"\"\"Display the ul element.\"\"\"\n\n    tag = \"ul\"\n\n\nclass Ins(BaseHTML):\n    \"\"\"Display the ins element.\"\"\"\n\n    tag = \"ins\"\n\n    # Specifies the URL of the document that explains the reason why the text was inserted/changed.\n    cite: Var[str]\n\n    # Specifies the date and time of when the text was inserted/changed.\n    date_time: Var[str]\n\n\nclass Del(BaseHTML):\n    \"\"\"Display the del element.\"\"\"\n\n    tag = \"del\"\n\n    # Specifies the URL of the document that explains the reason why the text was deleted.\n    cite: Var[str]\n\n    # Specifies the date and time of when the text was deleted.\n    date_time: Var[str]\n\n\nblockquote = Blockquote.create\ndd = Dd.create\ndiv = Div.create\ndl = Dl.create\ndt = Dt.create\nfigcaption = Figcaption.create\nfigure = Figure.create\nhr = Hr.create\nli = Li.create\nol = Ol.create\np = P.create\npre = Pre.create\nul = Ul.create\nins = Ins.create\ndel_ = Del.create  # 'del' is a reserved keyword in Python\n"
  },
  {
    "path": "reflex/components/field.py",
    "content": "\"\"\"Shared field infrastructure for components and props.\"\"\"\n\nfrom __future__ import annotations\n\nfrom collections.abc import Callable\nfrom dataclasses import _MISSING_TYPE, MISSING\nfrom typing import Annotated, Any, Generic, TypeVar, get_origin\n\nfrom reflex.utils import types\nfrom reflex.utils.compat import annotations_from_namespace\n\nFIELD_TYPE = TypeVar(\"FIELD_TYPE\")\n\n\nclass BaseField(Generic[FIELD_TYPE]):\n    \"\"\"Base field class used by internal metadata classes.\"\"\"\n\n    def __init__(\n        self,\n        default: FIELD_TYPE | _MISSING_TYPE = MISSING,\n        default_factory: Callable[[], FIELD_TYPE] | None = None,\n        annotated_type: type[Any] | _MISSING_TYPE = MISSING,\n    ) -> None:\n        \"\"\"Initialize the field.\n\n        Args:\n            default: The default value for the field.\n            default_factory: The default factory for the field.\n            annotated_type: The annotated type for the field.\n        \"\"\"\n        self.default = default\n        self.default_factory = default_factory\n        self.outer_type_ = self.annotated_type = annotated_type\n\n        # Process type annotation\n        type_origin = get_origin(annotated_type) or annotated_type\n        if type_origin is Annotated:\n            type_origin = annotated_type.__origin__  # pyright: ignore [reportAttributeAccessIssue]\n            # For Annotated types, use the actual type inside the annotation\n            self.type_ = annotated_type\n        else:\n            # For other types (including Union), preserve the original type\n            self.type_ = annotated_type\n        self.type_origin = type_origin\n\n    def default_value(self) -> FIELD_TYPE:\n        \"\"\"Get the default value for the field.\n\n        Returns:\n            The default value for the field.\n\n        Raises:\n            ValueError: If no default value or factory is provided.\n        \"\"\"\n        if self.default is not MISSING:\n            return self.default\n        if self.default_factory is not None:\n            return self.default_factory()\n        msg = \"No default value or factory provided.\"\n        raise ValueError(msg)\n\n\nclass FieldBasedMeta(type):\n    \"\"\"Shared metaclass for field-based classes like components and props.\n\n    Provides common field inheritance and processing logic for both\n    PropsBaseMeta and BaseComponentMeta.\n    \"\"\"\n\n    def __new__(\n        cls, name: str, bases: tuple[type, ...], namespace: dict[str, Any]\n    ) -> type:\n        \"\"\"Create a new field-based class.\n\n        Args:\n            name: The name of the class.\n            bases: The base classes.\n            namespace: The class namespace.\n\n        Returns:\n            The new class.\n        \"\"\"\n        # Collect inherited fields from base classes\n        inherited_fields = cls._collect_inherited_fields(bases)\n\n        # Get annotations from the namespace\n        annotations = cls._resolve_annotations(namespace, name)\n\n        # Process field overrides (fields with values but no annotations)\n        own_fields = cls._process_field_overrides(\n            namespace, annotations, inherited_fields\n        )\n\n        # Process annotated fields\n        own_fields.update(\n            cls._process_annotated_fields(namespace, annotations, inherited_fields)\n        )\n\n        # Finalize fields and store on class\n        cls._finalize_fields(namespace, inherited_fields, own_fields)\n\n        return super().__new__(cls, name, bases, namespace)\n\n    @classmethod\n    def _collect_inherited_fields(cls, bases: tuple[type, ...]) -> dict[str, Any]:\n        inherited_fields: dict[str, Any] = {}\n\n        # Collect inherited fields from base classes\n        for base in bases[::-1]:\n            if hasattr(base, \"_inherited_fields\"):\n                inherited_fields.update(base._inherited_fields)\n        for base in bases[::-1]:\n            if hasattr(base, \"_own_fields\"):\n                inherited_fields.update(base._own_fields)\n\n        return inherited_fields\n\n    @classmethod\n    def _resolve_annotations(\n        cls, namespace: dict[str, Any], name: str\n    ) -> dict[str, Any]:\n        return types.resolve_annotations(\n            annotations_from_namespace(namespace),\n            namespace[\"__module__\"],\n        )\n\n    @classmethod\n    def _process_field_overrides(\n        cls,\n        namespace: dict[str, Any],\n        annotations: dict[str, Any],\n        inherited_fields: dict[str, Any],\n    ) -> dict[str, Any]:\n        own_fields: dict[str, Any] = {}\n\n        for key, value in namespace.items():\n            if key not in annotations and key in inherited_fields:\n                inherited_field = inherited_fields[key]\n                new_field = cls._create_field(\n                    annotated_type=inherited_field.annotated_type,\n                    default=value,\n                    default_factory=None,\n                )\n                own_fields[key] = new_field\n\n        return own_fields\n\n    @classmethod\n    def _process_annotated_fields(\n        cls,\n        namespace: dict[str, Any],\n        annotations: dict[str, Any],\n        inherited_fields: dict[str, Any],\n    ) -> dict[str, Any]:\n        raise NotImplementedError\n\n    @classmethod\n    def _create_field(\n        cls,\n        annotated_type: Any,\n        default: Any = MISSING,\n        default_factory: Callable[[], Any] | None = None,\n    ) -> Any:\n        raise NotImplementedError\n\n    @classmethod\n    def _finalize_fields(\n        cls,\n        namespace: dict[str, Any],\n        inherited_fields: dict[str, Any],\n        own_fields: dict[str, Any],\n    ) -> None:\n        # Combine all fields\n        all_fields = inherited_fields | own_fields\n\n        # Set field names for compatibility\n        for field_name, field in all_fields.items():\n            field._name = field_name\n\n        # Store field mappings on the class\n        namespace[\"_own_fields\"] = own_fields\n        namespace[\"_inherited_fields\"] = inherited_fields\n        namespace[\"_fields\"] = all_fields\n"
  },
  {
    "path": "reflex/components/gridjs/__init__.py",
    "content": "\"\"\"Grid components.\"\"\"\n\nfrom .datatable import DataTable\n\ndata_table = DataTable.create\n"
  },
  {
    "path": "reflex/components/gridjs/datatable.py",
    "content": "\"\"\"Table components.\"\"\"\n\nfrom __future__ import annotations\n\nfrom collections.abc import Sequence\nfrom typing import Any\n\nfrom reflex.components.component import NoSSRComponent\nfrom reflex.components.tags import Tag\nfrom reflex.utils import types\nfrom reflex.utils.imports import ImportDict\nfrom reflex.utils.serializers import serialize\nfrom reflex.vars.base import LiteralVar, Var, is_computed_var\n\n\nclass Gridjs(NoSSRComponent):\n    \"\"\"A component that wraps a nivo bar component.\"\"\"\n\n    library = \"gridjs-react@6.1.1\"\n\n    lib_dependencies: list[str] = [\"gridjs@6.2.0\"]\n\n\nclass DataTable(Gridjs):\n    \"\"\"A data table component.\"\"\"\n\n    tag = \"Grid\"\n\n    alias = \"DataTableGrid\"\n\n    # The data to display. Either a list of lists or a pandas dataframe.\n    data: Any\n\n    # The list of columns to display. Required if data is a list and should not be provided\n    # if the data field is a dataframe\n    columns: Var[Sequence]\n\n    # Enable a search bar.\n    search: Var[bool]\n\n    # Enable sorting on columns.\n    sort: Var[bool]\n\n    # Enable resizable columns.\n    resizable: Var[bool]\n\n    # Enable pagination.\n    pagination: Var[bool | dict]\n\n    @classmethod\n    def create(cls, *children, **props):\n        \"\"\"Create a datatable component.\n\n        Args:\n            *children: The children of the component.\n            **props: The props to pass to the component.\n\n        Returns:\n            The datatable component.\n\n        Raises:\n            ValueError: If a pandas dataframe is passed in and columns are also provided.\n        \"\"\"\n        data = props.get(\"data\")\n        columns = props.get(\"columns\")\n\n        # The annotation should be provided if data is a computed var. We need this to know how to\n        # render pandas dataframes.\n        if is_computed_var(data) and data._var_type == Any:\n            msg = \"Annotation of the computed var assigned to the data field should be provided.\"\n            raise ValueError(msg)\n\n        if (\n            columns is not None\n            and is_computed_var(columns)\n            and columns._var_type == Any\n        ):\n            msg = \"Annotation of the computed var assigned to the column field should be provided.\"\n            raise ValueError(msg)\n\n        # If data is a pandas dataframe and columns are provided throw an error.\n        if (\n            types.is_dataframe(type(data))\n            or (isinstance(data, Var) and types.is_dataframe(data._var_type))\n        ) and columns is not None:\n            msg = \"Cannot pass in both a pandas dataframe and columns to the data_table component.\"\n            raise ValueError(msg)\n\n        # If data is a list and columns are not provided, throw an error\n        if (\n            (isinstance(data, Var) and types.typehint_issubclass(data._var_type, list))\n            or isinstance(data, list)\n        ) and columns is None:\n            msg = \"column field should be specified when the data field is a list type\"\n            raise ValueError(msg)\n\n        # Create the component.\n        return super().create(\n            *children,\n            **props,\n        )\n\n    def add_imports(self) -> ImportDict:\n        \"\"\"Add the imports for the datatable component.\n\n        Returns:\n            The import dict for the component.\n        \"\"\"\n        return {\"\": \"gridjs/dist/theme/mermaid.css\"}\n\n    def _render(self) -> Tag:\n        if isinstance(self.data, Var) and types.is_dataframe(self.data._var_type):\n            self.columns = self.data._replace(\n                _js_expr=f\"{self.data._js_expr}.columns\",\n                _var_type=list[Any],\n            )\n            self.data = self.data._replace(\n                _js_expr=f\"{self.data._js_expr}.data\",\n                _var_type=list[list[Any]],\n            )\n        if types.is_dataframe(type(self.data)):\n            # If given a pandas df break up the data and columns\n            data = serialize(self.data)\n            if not isinstance(data, dict):\n                msg = \"Serialized dataframe should be a dict.\"\n                raise ValueError(msg)\n            self.columns = LiteralVar.create(data[\"columns\"])\n            self.data = LiteralVar.create(data[\"data\"])\n\n        # Render the table.\n        return super()._render()\n"
  },
  {
    "path": "reflex/components/literals.py",
    "content": "\"\"\"Literal custom type used by Reflex.\"\"\"\n\nfrom typing import Literal\n\n# Base Literals\nLiteralInputType = Literal[\n    \"button\",\n    \"checkbox\",\n    \"color\",\n    \"date\",\n    \"datetime-local\",\n    \"email\",\n    \"file\",\n    \"hidden\",\n    \"image\",\n    \"month\",\n    \"number\",\n    \"password\",\n    \"radio\",\n    \"range\",\n    \"reset\",\n    \"search\",\n    \"submit\",\n    \"tel\",\n    \"text\",\n    \"time\",\n    \"url\",\n    \"week\",\n]\n\n\nLiteralRowMarker = Literal[\n    \"none\", \"number\", \"checkbox\", \"both\", \"checkbox-visible\", \"clickable-number\"\n]\n"
  },
  {
    "path": "reflex/components/lucide/__init__.py",
    "content": "\"\"\"Lucide Icon Component.\"\"\"\n\nfrom .icon import Icon\n\nicon = Icon.create\n"
  },
  {
    "path": "reflex/components/lucide/icon.py",
    "content": "\"\"\"Lucide Icon component.\"\"\"\n\nfrom reflex.components.component import Component\nfrom reflex.utils import console, format\nfrom reflex.utils.imports import ImportVar\nfrom reflex.vars.base import LiteralVar, Var\nfrom reflex.vars.sequence import LiteralStringVar, StringVar\n\nLUCIDE_LIBRARY = \"lucide-react@0.577.0\"\n\n\nclass LucideIconComponent(Component):\n    \"\"\"Lucide Icon Component.\"\"\"\n\n    library = LUCIDE_LIBRARY\n\n\nclass Icon(LucideIconComponent):\n    \"\"\"An Icon component.\"\"\"\n\n    tag = \"None\"\n\n    # The size of the icon in pixels.\n    size: Var[int]\n\n    @classmethod\n    def create(cls, *children, **props) -> Component:\n        \"\"\"Initialize the Icon component.\n\n        Run some additional checks on Icon component.\n\n        Args:\n            *children: The positional arguments\n            **props: The keyword arguments\n\n        Returns:\n            The created component.\n\n        Raises:\n            AttributeError: The errors tied to bad usage of the Icon component.\n            TypeError: If the icon name is not a string.\n        \"\"\"\n        if children:\n            if len(children) == 1:\n                child = Var.create(children[0]).guess_type()\n                if not isinstance(child, StringVar):\n                    msg = f\"Icon name must be a string, got {children[0]._var_type if isinstance(children[0], Var) else children[0]}\"\n                    raise AttributeError(msg)\n                props[\"tag\"] = children[0]\n            else:\n                msg = f\"Passing multiple children to Icon component is not allowed: remove positional arguments {children[1:]} to fix\"\n                raise AttributeError(msg)\n        if \"tag\" not in props:\n            msg = \"Missing 'tag' keyword-argument for Icon\"\n            raise AttributeError(msg)\n\n        tag_var: Var | LiteralVar = Var.create(props.pop(\"tag\"))\n        if isinstance(tag_var, LiteralVar):\n            if isinstance(tag_var, LiteralStringVar):\n                tag = format.to_snake_case(tag_var._var_value.lower())\n            else:\n                msg = f\"Icon name must be a string, got {type(tag_var)}\"\n                raise TypeError(msg)\n        elif isinstance(tag_var, Var):\n            tag_stringified = tag_var.guess_type()\n            if not isinstance(tag_stringified, StringVar):\n                msg = f\"Icon name must be a string, got {tag_var._var_type}\"\n                raise TypeError(msg)\n            return DynamicIcon.create(name=tag_stringified.replace(\"_\", \"-\"), **props)\n\n        if tag not in LUCIDE_ICON_LIST:\n            icons_sorted = sorted(\n                LUCIDE_ICON_LIST,\n                key=lambda s, tag=tag: format.length_of_largest_common_substring(\n                    tag, s\n                ),\n                reverse=True,\n            )\n            console.warn(\n                f\"Invalid icon tag: {tag}. Please use one of the following: {', '.join(icons_sorted[0:10])}, ...\"\n                \"\\nSee full list at https://reflex.dev/docs/library/data-display/icon/#icons-list. Using 'circle_help' icon instead.\"\n            )\n            tag = \"circle_help\"\n\n        props[\"tag\"] = LUCIDE_ICON_MAPPING_OVERRIDE.get(tag, format.to_title_case(tag))\n        props[\"alias\"] = f\"Lucide{props['tag']}\"\n        return super().create(**props)\n\n\nclass DynamicIcon(LucideIconComponent):\n    \"\"\"A DynamicIcon component.\"\"\"\n\n    tag = \"DynamicIcon\"\n\n    name: Var[str]\n    size: Var[int]\n\n    def _get_imports(self):\n        imports_ = super()._get_imports()\n        if self.library:\n            imports_.pop(self.library)\n        imports_[LUCIDE_LIBRARY] = [\n            ImportVar(\"DynamicIcon\", package_path=\"/dynamic.mjs\")\n        ]\n        return imports_\n\n\nLUCIDE_ICON_LIST = [\n    \"a_arrow_down\",\n    \"a_arrow_up\",\n    \"a_large_small\",\n    \"accessibility\",\n    \"activity\",\n    \"air_vent\",\n    \"airplay\",\n    \"alarm_clock_check\",\n    \"alarm_clock_minus\",\n    \"alarm_clock_off\",\n    \"alarm_clock_plus\",\n    \"alarm_clock\",\n    \"alarm_smoke\",\n    \"album\",\n    \"align_center_horizontal\",\n    \"align_center_vertical\",\n    \"align_center\",\n    \"align_end_horizontal\",\n    \"align_end_vertical\",\n    \"align_horizontal_distribute_center\",\n    \"align_horizontal_distribute_end\",\n    \"align_horizontal_distribute_start\",\n    \"align_horizontal_justify_center\",\n    \"align_horizontal_justify_end\",\n    \"align_horizontal_justify_start\",\n    \"align_horizontal_space_around\",\n    \"align_horizontal_space_between\",\n    \"align_justify\",\n    \"align_left\",\n    \"align_right\",\n    \"align_start_horizontal\",\n    \"align_start_vertical\",\n    \"align_vertical_distribute_center\",\n    \"align_vertical_distribute_end\",\n    \"align_vertical_distribute_start\",\n    \"align_vertical_justify_center\",\n    \"align_vertical_justify_end\",\n    \"align_vertical_justify_start\",\n    \"align_vertical_space_around\",\n    \"align_vertical_space_between\",\n    \"ambulance\",\n    \"ampersand\",\n    \"ampersands\",\n    \"amphora\",\n    \"anchor\",\n    \"angry\",\n    \"annoyed\",\n    \"antenna\",\n    \"anvil\",\n    \"aperture\",\n    \"app_window_mac\",\n    \"app_window\",\n    \"apple\",\n    \"archive_restore\",\n    \"archive_x\",\n    \"archive\",\n    \"area_chart\",\n    \"armchair\",\n    \"arrow_big_down_dash\",\n    \"arrow_big_down\",\n    \"arrow_big_left_dash\",\n    \"arrow_big_left\",\n    \"arrow_big_right_dash\",\n    \"arrow_big_right\",\n    \"arrow_big_up_dash\",\n    \"arrow_big_up\",\n    \"arrow_down_0_1\",\n    \"arrow_down_1_0\",\n    \"arrow_down_a_z\",\n    \"arrow_down_from_line\",\n    \"arrow_down_left\",\n    \"arrow_down_narrow_wide\",\n    \"arrow_down_right\",\n    \"arrow_down_to_dot\",\n    \"arrow_down_to_line\",\n    \"arrow_down_up\",\n    \"arrow_down_wide_narrow\",\n    \"arrow_down_z_a\",\n    \"arrow_down\",\n    \"arrow_left_from_line\",\n    \"arrow_left_right\",\n    \"arrow_left_to_line\",\n    \"arrow_left\",\n    \"arrow_right_from_line\",\n    \"arrow_right_left\",\n    \"arrow_right_to_line\",\n    \"arrow_right\",\n    \"arrow_up_0_1\",\n    \"arrow_up_1_0\",\n    \"arrow_up_a_z\",\n    \"arrow_up_down\",\n    \"arrow_up_from_dot\",\n    \"arrow_up_from_line\",\n    \"arrow_up_left\",\n    \"arrow_up_narrow_wide\",\n    \"arrow_up_right\",\n    \"arrow_up_to_line\",\n    \"arrow_up_wide_narrow\",\n    \"arrow_up_z_a\",\n    \"arrow_up\",\n    \"arrows_up_from_line\",\n    \"asterisk\",\n    \"at_sign\",\n    \"atom\",\n    \"audio_lines\",\n    \"audio_waveform\",\n    \"award\",\n    \"axe\",\n    \"axis_3d\",\n    \"baby\",\n    \"backpack\",\n    \"badge_alert\",\n    \"badge_cent\",\n    \"badge_check\",\n    \"badge_dollar_sign\",\n    \"badge_euro\",\n    \"badge_help\",\n    \"badge_indian_rupee\",\n    \"badge_info\",\n    \"badge_japanese_yen\",\n    \"badge_minus\",\n    \"badge_percent\",\n    \"badge_plus\",\n    \"badge_pound_sterling\",\n    \"badge_russian_ruble\",\n    \"badge_swiss_franc\",\n    \"badge_turkish_lira\",\n    \"badge_x\",\n    \"badge\",\n    \"baggage_claim\",\n    \"balloon\",\n    \"ban\",\n    \"banana\",\n    \"bandage\",\n    \"banknote_arrow_down\",\n    \"banknote_x\",\n    \"banknote\",\n    \"bar_chart_2\",\n    \"bar_chart_3\",\n    \"bar_chart_4\",\n    \"bar_chart_big\",\n    \"bar_chart_horizontal_big\",\n    \"bar_chart_horizontal\",\n    \"bar_chart\",\n    \"barcode\",\n    \"barrel\",\n    \"baseline\",\n    \"bath\",\n    \"battery_charging\",\n    \"battery_full\",\n    \"battery_low\",\n    \"battery_medium\",\n    \"battery_plus\",\n    \"battery_warning\",\n    \"battery\",\n    \"beaker\",\n    \"bean_off\",\n    \"bean\",\n    \"bed_double\",\n    \"bed_single\",\n    \"bed\",\n    \"beef\",\n    \"beer_off\",\n    \"beer\",\n    \"bell_dot\",\n    \"bell_electric\",\n    \"bell_minus\",\n    \"bell_off\",\n    \"bell_plus\",\n    \"bell_ring\",\n    \"bell\",\n    \"between_horizontal_end\",\n    \"between_horizontal_start\",\n    \"between_vertical_end\",\n    \"between_vertical_start\",\n    \"biceps_flexed\",\n    \"bike\",\n    \"binary\",\n    \"binoculars\",\n    \"biohazard\",\n    \"bird\",\n    \"birdhouse\",\n    \"bitcoin\",\n    \"blend\",\n    \"blinds\",\n    \"blocks\",\n    \"bluetooth_connected\",\n    \"bluetooth_off\",\n    \"bluetooth_searching\",\n    \"bluetooth\",\n    \"bold\",\n    \"bolt\",\n    \"bomb\",\n    \"bone\",\n    \"book_a\",\n    \"book_alert\",\n    \"book_audio\",\n    \"book_check\",\n    \"book_copy\",\n    \"book_dashed\",\n    \"book_down\",\n    \"book_headphones\",\n    \"book_heart\",\n    \"book_image\",\n    \"book_key\",\n    \"book_lock\",\n    \"book_marked\",\n    \"book_minus\",\n    \"book_open_check\",\n    \"book_open_text\",\n    \"book_open\",\n    \"book_plus\",\n    \"book_search\",\n    \"book_text\",\n    \"book_type\",\n    \"book_up_2\",\n    \"book_up\",\n    \"book_user\",\n    \"book_x\",\n    \"book\",\n    \"bookmark_check\",\n    \"bookmark_minus\",\n    \"bookmark_plus\",\n    \"bookmark_x\",\n    \"bookmark\",\n    \"boom_box\",\n    \"bot_message_square\",\n    \"bot_off\",\n    \"bot\",\n    \"bottle_wine\",\n    \"bow_arrow\",\n    \"box_select\",\n    \"box\",\n    \"boxes\",\n    \"braces\",\n    \"brackets\",\n    \"brain_circuit\",\n    \"brain_cog\",\n    \"brain\",\n    \"brick_wall_fire\",\n    \"brick_wall_shield\",\n    \"brick_wall\",\n    \"briefcase_business\",\n    \"briefcase_conveyor_belt\",\n    \"briefcase_medical\",\n    \"briefcase\",\n    \"bring_to_front\",\n    \"brush_cleaning\",\n    \"brush\",\n    \"bubbles\",\n    \"bug_off\",\n    \"bug_play\",\n    \"bug\",\n    \"building_2\",\n    \"building\",\n    \"bus_front\",\n    \"bus\",\n    \"cable_car\",\n    \"cable\",\n    \"cake_slice\",\n    \"cake\",\n    \"calculator\",\n    \"calendar_1\",\n    \"calendar_arrow_down\",\n    \"calendar_arrow_up\",\n    \"calendar_check_2\",\n    \"calendar_check\",\n    \"calendar_clock\",\n    \"calendar_cog\",\n    \"calendar_days\",\n    \"calendar_fold\",\n    \"calendar_heart\",\n    \"calendar_minus_2\",\n    \"calendar_minus\",\n    \"calendar_off\",\n    \"calendar_plus_2\",\n    \"calendar_plus\",\n    \"calendar_range\",\n    \"calendar_search\",\n    \"calendar_sync\",\n    \"calendar_x_2\",\n    \"calendar_x\",\n    \"calendar\",\n    \"calendars\",\n    \"camera_off\",\n    \"camera\",\n    \"candlestick_chart\",\n    \"candy_cane\",\n    \"candy_off\",\n    \"candy\",\n    \"cannabis_off\",\n    \"cannabis\",\n    \"captions_off\",\n    \"captions\",\n    \"car_front\",\n    \"car_taxi_front\",\n    \"car\",\n    \"caravan\",\n    \"card_sim\",\n    \"carrot\",\n    \"case_lower\",\n    \"case_sensitive\",\n    \"case_upper\",\n    \"cassette_tape\",\n    \"cast\",\n    \"castle\",\n    \"cat\",\n    \"cctv\",\n    \"chart_area\",\n    \"chart_bar_big\",\n    \"chart_bar_decreasing\",\n    \"chart_bar_increasing\",\n    \"chart_bar_stacked\",\n    \"chart_bar\",\n    \"chart_candlestick\",\n    \"chart_column_big\",\n    \"chart_column_decreasing\",\n    \"chart_column_increasing\",\n    \"chart_column_stacked\",\n    \"chart_column\",\n    \"chart_gantt\",\n    \"chart_line\",\n    \"chart_network\",\n    \"chart_no_axes_column_decreasing\",\n    \"chart_no_axes_column_increasing\",\n    \"chart_no_axes_column\",\n    \"chart_no_axes_combined\",\n    \"chart_no_axes_gantt\",\n    \"chart_pie\",\n    \"chart_scatter\",\n    \"chart_spline\",\n    \"check_check\",\n    \"check_line\",\n    \"check\",\n    \"chef_hat\",\n    \"cherry\",\n    \"chess_bishop\",\n    \"chess_king\",\n    \"chess_knight\",\n    \"chess_pawn\",\n    \"chess_queen\",\n    \"chess_rook\",\n    \"chevron_down\",\n    \"chevron_first\",\n    \"chevron_last\",\n    \"chevron_left\",\n    \"chevron_right\",\n    \"chevron_up\",\n    \"chevrons_down_up\",\n    \"chevrons_down\",\n    \"chevrons_left_right_ellipsis\",\n    \"chevrons_left_right\",\n    \"chevrons_left\",\n    \"chevrons_right_left\",\n    \"chevrons_right\",\n    \"chevrons_up_down\",\n    \"chevrons_up\",\n    \"chrome\",\n    \"chromium\",\n    \"church\",\n    \"cigarette_off\",\n    \"cigarette\",\n    \"circle_alert\",\n    \"circle_arrow_down\",\n    \"circle_arrow_left\",\n    \"circle_arrow_out_down_left\",\n    \"circle_arrow_out_down_right\",\n    \"circle_arrow_out_up_left\",\n    \"circle_arrow_out_up_right\",\n    \"circle_arrow_right\",\n    \"circle_arrow_up\",\n    \"circle_check_big\",\n    \"circle_check\",\n    \"circle_chevron_down\",\n    \"circle_chevron_left\",\n    \"circle_chevron_right\",\n    \"circle_chevron_up\",\n    \"circle_dashed\",\n    \"circle_divide\",\n    \"circle_dollar_sign\",\n    \"circle_dot_dashed\",\n    \"circle_dot\",\n    \"circle_ellipsis\",\n    \"circle_equal\",\n    \"circle_fading_arrow_up\",\n    \"circle_fading_plus\",\n    \"circle_gauge\",\n    \"circle_help\",\n    \"circle_minus\",\n    \"circle_off\",\n    \"circle_parking_off\",\n    \"circle_parking\",\n    \"circle_pause\",\n    \"circle_percent\",\n    \"circle_pile\",\n    \"circle_play\",\n    \"circle_plus\",\n    \"circle_pound_sterling\",\n    \"circle_power\",\n    \"circle_slash_2\",\n    \"circle_slash\",\n    \"circle_small\",\n    \"circle_star\",\n    \"circle_stop\",\n    \"circle_user_round\",\n    \"circle_user\",\n    \"circle_x\",\n    \"circle\",\n    \"circuit_board\",\n    \"citrus\",\n    \"clapperboard\",\n    \"clipboard_check\",\n    \"clipboard_clock\",\n    \"clipboard_copy\",\n    \"clipboard_list\",\n    \"clipboard_minus\",\n    \"clipboard_paste\",\n    \"clipboard_pen_line\",\n    \"clipboard_pen\",\n    \"clipboard_plus\",\n    \"clipboard_type\",\n    \"clipboard_x\",\n    \"clipboard\",\n    \"clock_1\",\n    \"clock_10\",\n    \"clock_11\",\n    \"clock_12\",\n    \"clock_2\",\n    \"clock_3\",\n    \"clock_4\",\n    \"clock_5\",\n    \"clock_6\",\n    \"clock_7\",\n    \"clock_8\",\n    \"clock_9\",\n    \"clock_alert\",\n    \"clock_arrow_down\",\n    \"clock_arrow_up\",\n    \"clock_check\",\n    \"clock_fading\",\n    \"clock_plus\",\n    \"clock\",\n    \"closed_caption\",\n    \"cloud_alert\",\n    \"cloud_backup\",\n    \"cloud_check\",\n    \"cloud_cog\",\n    \"cloud_download\",\n    \"cloud_drizzle\",\n    \"cloud_fog\",\n    \"cloud_hail\",\n    \"cloud_lightning\",\n    \"cloud_moon_rain\",\n    \"cloud_moon\",\n    \"cloud_off\",\n    \"cloud_rain_wind\",\n    \"cloud_rain\",\n    \"cloud_snow\",\n    \"cloud_sun_rain\",\n    \"cloud_sun\",\n    \"cloud_sync\",\n    \"cloud_upload\",\n    \"cloud\",\n    \"cloudy\",\n    \"clover\",\n    \"club\",\n    \"code_xml\",\n    \"code\",\n    \"codepen\",\n    \"codesandbox\",\n    \"coffee\",\n    \"cog\",\n    \"coins\",\n    \"columns_2\",\n    \"columns_3_cog\",\n    \"columns_3\",\n    \"columns_4\",\n    \"combine\",\n    \"command\",\n    \"compass\",\n    \"component\",\n    \"computer\",\n    \"concierge_bell\",\n    \"cone\",\n    \"construction\",\n    \"contact_round\",\n    \"contact\",\n    \"container\",\n    \"contrast\",\n    \"cookie\",\n    \"cooking_pot\",\n    \"copy_check\",\n    \"copy_minus\",\n    \"copy_plus\",\n    \"copy_slash\",\n    \"copy_x\",\n    \"copy\",\n    \"copyleft\",\n    \"copyright\",\n    \"corner_down_left\",\n    \"corner_down_right\",\n    \"corner_left_down\",\n    \"corner_left_up\",\n    \"corner_right_down\",\n    \"corner_right_up\",\n    \"corner_up_left\",\n    \"corner_up_right\",\n    \"cpu\",\n    \"creative_commons\",\n    \"credit_card\",\n    \"croissant\",\n    \"crop\",\n    \"cross\",\n    \"crosshair\",\n    \"crown\",\n    \"cuboid\",\n    \"cup_soda\",\n    \"currency\",\n    \"cylinder\",\n    \"dam\",\n    \"database_backup\",\n    \"database_search\",\n    \"database_zap\",\n    \"database\",\n    \"decimals_arrow_left\",\n    \"decimals_arrow_right\",\n    \"delete\",\n    \"dessert\",\n    \"diameter\",\n    \"diamond_minus\",\n    \"diamond_percent\",\n    \"diamond_plus\",\n    \"diamond\",\n    \"dice_1\",\n    \"dice_2\",\n    \"dice_3\",\n    \"dice_4\",\n    \"dice_5\",\n    \"dice_6\",\n    \"dices\",\n    \"diff\",\n    \"disc_2\",\n    \"disc_3\",\n    \"disc_album\",\n    \"disc\",\n    \"divide\",\n    \"dna_off\",\n    \"dna\",\n    \"dock\",\n    \"dog\",\n    \"dollar_sign\",\n    \"donut\",\n    \"door_closed_locked\",\n    \"door_closed\",\n    \"door_open\",\n    \"dot\",\n    \"download\",\n    \"drafting_compass\",\n    \"drama\",\n    \"dribbble\",\n    \"drill\",\n    \"drone\",\n    \"droplet_off\",\n    \"droplet\",\n    \"droplets\",\n    \"drum\",\n    \"drumstick\",\n    \"dumbbell\",\n    \"ear_off\",\n    \"ear\",\n    \"earth_lock\",\n    \"earth\",\n    \"eclipse\",\n    \"egg_fried\",\n    \"egg_off\",\n    \"egg\",\n    \"ellipse\",\n    \"ellipsis_vertical\",\n    \"ellipsis\",\n    \"equal_approximately\",\n    \"equal_not\",\n    \"equal\",\n    \"eraser\",\n    \"ethernet_port\",\n    \"euro\",\n    \"ev_charger\",\n    \"expand\",\n    \"external_link\",\n    \"eye_closed\",\n    \"eye_off\",\n    \"eye\",\n    \"facebook\",\n    \"factory\",\n    \"fan\",\n    \"fast_forward\",\n    \"feather\",\n    \"fence\",\n    \"ferris_wheel\",\n    \"figma\",\n    \"file_archive\",\n    \"file_audio_2\",\n    \"file_audio\",\n    \"file_axis_3d\",\n    \"file_badge_2\",\n    \"file_badge\",\n    \"file_bar_chart_2\",\n    \"file_bar_chart\",\n    \"file_box\",\n    \"file_chart_column_increasing\",\n    \"file_chart_column\",\n    \"file_chart_line\",\n    \"file_chart_pie\",\n    \"file_check_2\",\n    \"file_check\",\n    \"file_clock\",\n    \"file_code_2\",\n    \"file_code\",\n    \"file_cog\",\n    \"file_diff\",\n    \"file_digit\",\n    \"file_down\",\n    \"file_heart\",\n    \"file_image\",\n    \"file_input\",\n    \"file_json_2\",\n    \"file_json\",\n    \"file_key_2\",\n    \"file_key\",\n    \"file_line_chart\",\n    \"file_lock_2\",\n    \"file_lock\",\n    \"file_minus_2\",\n    \"file_minus\",\n    \"file_music\",\n    \"file_output\",\n    \"file_pen_line\",\n    \"file_pen\",\n    \"file_pie_chart\",\n    \"file_plus_2\",\n    \"file_plus\",\n    \"file_question\",\n    \"file_scan\",\n    \"file_search_2\",\n    \"file_search\",\n    \"file_sliders\",\n    \"file_spreadsheet\",\n    \"file_stack\",\n    \"file_symlink\",\n    \"file_terminal\",\n    \"file_text\",\n    \"file_type_2\",\n    \"file_type\",\n    \"file_up\",\n    \"file_user\",\n    \"file_video_2\",\n    \"file_video\",\n    \"file_volume_2\",\n    \"file_volume\",\n    \"file_warning\",\n    \"file_x_2\",\n    \"file_x\",\n    \"file\",\n    \"files\",\n    \"film\",\n    \"filter_x\",\n    \"filter\",\n    \"fingerprint_pattern\",\n    \"fingerprint\",\n    \"fire_extinguisher\",\n    \"fish_off\",\n    \"fish_symbol\",\n    \"fish\",\n    \"fishing_hook\",\n    \"fishing_rod\",\n    \"flag_off\",\n    \"flag_triangle_left\",\n    \"flag_triangle_right\",\n    \"flag\",\n    \"flame_kindling\",\n    \"flame\",\n    \"flashlight_off\",\n    \"flashlight\",\n    \"flask_conical_off\",\n    \"flask_conical\",\n    \"flask_round\",\n    \"flip_horizontal_2\",\n    \"flip_horizontal\",\n    \"flip_vertical_2\",\n    \"flip_vertical\",\n    \"flower_2\",\n    \"flower\",\n    \"focus\",\n    \"fold_horizontal\",\n    \"fold_vertical\",\n    \"folder_archive\",\n    \"folder_check\",\n    \"folder_clock\",\n    \"folder_closed\",\n    \"folder_code\",\n    \"folder_cog\",\n    \"folder_dot\",\n    \"folder_down\",\n    \"folder_git_2\",\n    \"folder_git\",\n    \"folder_heart\",\n    \"folder_input\",\n    \"folder_kanban\",\n    \"folder_key\",\n    \"folder_lock\",\n    \"folder_minus\",\n    \"folder_open_dot\",\n    \"folder_open\",\n    \"folder_output\",\n    \"folder_pen\",\n    \"folder_plus\",\n    \"folder_root\",\n    \"folder_search_2\",\n    \"folder_search\",\n    \"folder_symlink\",\n    \"folder_sync\",\n    \"folder_tree\",\n    \"folder_up\",\n    \"folder_x\",\n    \"folder\",\n    \"folders\",\n    \"footprints\",\n    \"forklift\",\n    \"form\",\n    \"forward\",\n    \"frame\",\n    \"framer\",\n    \"frown\",\n    \"fuel\",\n    \"fullscreen\",\n    \"funnel_plus\",\n    \"funnel_x\",\n    \"funnel\",\n    \"gallery_horizontal_end\",\n    \"gallery_horizontal\",\n    \"gallery_thumbnails\",\n    \"gallery_vertical_end\",\n    \"gallery_vertical\",\n    \"gamepad_2\",\n    \"gamepad_directional\",\n    \"gamepad\",\n    \"gantt_chart\",\n    \"gauge\",\n    \"gavel\",\n    \"gem\",\n    \"georgian_lari\",\n    \"ghost\",\n    \"gift\",\n    \"git_branch_minus\",\n    \"git_branch_plus\",\n    \"git_branch\",\n    \"git_commit_horizontal\",\n    \"git_commit_vertical\",\n    \"git_compare_arrows\",\n    \"git_compare\",\n    \"git_fork\",\n    \"git_graph\",\n    \"git_merge_conflict\",\n    \"git_merge\",\n    \"git_pull_request_arrow\",\n    \"git_pull_request_closed\",\n    \"git_pull_request_create_arrow\",\n    \"git_pull_request_create\",\n    \"git_pull_request_draft\",\n    \"git_pull_request\",\n    \"github\",\n    \"gitlab\",\n    \"glass_water\",\n    \"glasses\",\n    \"globe_lock\",\n    \"globe_off\",\n    \"globe_x\",\n    \"globe\",\n    \"goal\",\n    \"gpu\",\n    \"grab\",\n    \"graduation_cap\",\n    \"grape\",\n    \"grid_2x_2_check\",\n    \"grid_2x_2_plus\",\n    \"grid_2x_2_x\",\n    \"grid_2x_2\",\n    \"grid_2x2\",\n    \"grid_3x_3\",\n    \"grid_3x2\",\n    \"grid_3x3\",\n    \"grip_horizontal\",\n    \"grip_vertical\",\n    \"grip\",\n    \"group\",\n    \"guitar\",\n    \"ham\",\n    \"hamburger\",\n    \"hammer\",\n    \"hand_coins\",\n    \"hand_fist\",\n    \"hand_heart\",\n    \"hand_helping\",\n    \"hand_metal\",\n    \"hand_platter\",\n    \"hand\",\n    \"handbag\",\n    \"handshake\",\n    \"hard_drive_download\",\n    \"hard_drive_upload\",\n    \"hard_drive\",\n    \"hard_hat\",\n    \"hash\",\n    \"hat_glasses\",\n    \"haze\",\n    \"hd\",\n    \"hdmi_port\",\n    \"heading_1\",\n    \"heading_2\",\n    \"heading_3\",\n    \"heading_4\",\n    \"heading_5\",\n    \"heading_6\",\n    \"heading\",\n    \"headphone_off\",\n    \"headphones\",\n    \"headset\",\n    \"heart_crack\",\n    \"heart_handshake\",\n    \"heart_minus\",\n    \"heart_off\",\n    \"heart_plus\",\n    \"heart_pulse\",\n    \"heart\",\n    \"heater\",\n    \"helicopter\",\n    \"hexagon\",\n    \"highlighter\",\n    \"history\",\n    \"home\",\n    \"hop_off\",\n    \"hop\",\n    \"hospital\",\n    \"hotel\",\n    \"hourglass\",\n    \"house_heart\",\n    \"house_plug\",\n    \"house_plus\",\n    \"house_wifi\",\n    \"house\",\n    \"ice_cream_bowl\",\n    \"ice_cream_cone\",\n    \"id_card_lanyard\",\n    \"id_card\",\n    \"image_down\",\n    \"image_minus\",\n    \"image_off\",\n    \"image_play\",\n    \"image_plus\",\n    \"image_up\",\n    \"image_upscale\",\n    \"image\",\n    \"images\",\n    \"import\",\n    \"inbox\",\n    \"indent_decrease\",\n    \"indent_increase\",\n    \"indian_rupee\",\n    \"infinity\",\n    \"info\",\n    \"inspection_panel\",\n    \"instagram\",\n    \"italic\",\n    \"iteration_ccw\",\n    \"iteration_cw\",\n    \"japanese_yen\",\n    \"joystick\",\n    \"kanban\",\n    \"kayak\",\n    \"key_round\",\n    \"key_square\",\n    \"key\",\n    \"keyboard_music\",\n    \"keyboard_off\",\n    \"keyboard\",\n    \"lamp_ceiling\",\n    \"lamp_desk\",\n    \"lamp_floor\",\n    \"lamp_wall_down\",\n    \"lamp_wall_up\",\n    \"lamp\",\n    \"land_plot\",\n    \"landmark\",\n    \"languages\",\n    \"laptop_minimal_check\",\n    \"laptop_minimal\",\n    \"laptop\",\n    \"lasso_select\",\n    \"lasso\",\n    \"laugh\",\n    \"layers_2\",\n    \"layers_3\",\n    \"layers_plus\",\n    \"layers\",\n    \"layout_dashboard\",\n    \"layout_grid\",\n    \"layout_list\",\n    \"layout_panel_left\",\n    \"layout_panel_top\",\n    \"layout_template\",\n    \"leaf\",\n    \"leafy_green\",\n    \"lectern\",\n    \"lens_concave\",\n    \"lens_convex\",\n    \"letter_text\",\n    \"library_big\",\n    \"library\",\n    \"life_buoy\",\n    \"ligature\",\n    \"lightbulb_off\",\n    \"lightbulb\",\n    \"line_chart\",\n    \"line_dot_right_horizontal\",\n    \"line_squiggle\",\n    \"link_2_off\",\n    \"link_2\",\n    \"link\",\n    \"linkedin\",\n    \"list_check\",\n    \"list_checks\",\n    \"list_chevrons_down_up\",\n    \"list_collapse\",\n    \"list_end\",\n    \"list_filter_plus\",\n    \"list_filter\",\n    \"list_minus\",\n    \"list_music\",\n    \"list_ordered\",\n    \"list_plus\",\n    \"list_restart\",\n    \"list_start\",\n    \"list_todo\",\n    \"list_tree\",\n    \"list_video\",\n    \"list_x\",\n    \"list\",\n    \"loader_circle\",\n    \"loader_pinwheel\",\n    \"loader\",\n    \"locate_fixed\",\n    \"locate_off\",\n    \"locate\",\n    \"location_edit\",\n    \"lock_keyhole_open\",\n    \"lock_keyhole\",\n    \"lock_open\",\n    \"lock\",\n    \"log_in\",\n    \"log_out\",\n    \"logs\",\n    \"lollipop\",\n    \"luggage\",\n    \"magnet\",\n    \"mail_check\",\n    \"mail_minus\",\n    \"mail_open\",\n    \"mail_plus\",\n    \"mail_question\",\n    \"mail_search\",\n    \"mail_warning\",\n    \"mail_x\",\n    \"mail\",\n    \"mailbox\",\n    \"mails\",\n    \"map_minus\",\n    \"map_pin_check_inside\",\n    \"map_pin_check\",\n    \"map_pin_house\",\n    \"map_pin_minus_inside\",\n    \"map_pin_minus\",\n    \"map_pin_off\",\n    \"map_pin_plus_inside\",\n    \"map_pin_plus\",\n    \"map_pin_x_inside\",\n    \"map_pin_x\",\n    \"map_pin\",\n    \"map_pinned\",\n    \"map_plus\",\n    \"map\",\n    \"mars_stroke\",\n    \"martini\",\n    \"maximize_2\",\n    \"maximize\",\n    \"medal\",\n    \"megaphone_off\",\n    \"megaphone\",\n    \"meh\",\n    \"memory_stick\",\n    \"menu\",\n    \"merge\",\n    \"message_circle_check\",\n    \"message_circle_code\",\n    \"message_circle_dashed\",\n    \"message_circle_heart\",\n    \"message_circle_more\",\n    \"message_circle_off\",\n    \"message_circle_plus\",\n    \"message_circle_question\",\n    \"message_circle_reply\",\n    \"message_circle_warning\",\n    \"message_circle_x\",\n    \"message_circle\",\n    \"message_square_check\",\n    \"message_square_code\",\n    \"message_square_dashed\",\n    \"message_square_diff\",\n    \"message_square_dot\",\n    \"message_square_heart\",\n    \"message_square_lock\",\n    \"message_square_more\",\n    \"message_square_off\",\n    \"message_square_plus\",\n    \"message_square_quote\",\n    \"message_square_reply\",\n    \"message_square_share\",\n    \"message_square_text\",\n    \"message_square_warning\",\n    \"message_square_x\",\n    \"message_square\",\n    \"messages_square\",\n    \"metronome\",\n    \"mic_off\",\n    \"mic_vocal\",\n    \"mic\",\n    \"microchip\",\n    \"microscope\",\n    \"microwave\",\n    \"milestone\",\n    \"milk_off\",\n    \"milk\",\n    \"minimize_2\",\n    \"minimize\",\n    \"minus\",\n    \"mirror_rectangular\",\n    \"mirror_round\",\n    \"monitor_check\",\n    \"monitor_cloud\",\n    \"monitor_cog\",\n    \"monitor_dot\",\n    \"monitor_down\",\n    \"monitor_off\",\n    \"monitor_pause\",\n    \"monitor_play\",\n    \"monitor_smartphone\",\n    \"monitor_speaker\",\n    \"monitor_stop\",\n    \"monitor_up\",\n    \"monitor_x\",\n    \"monitor\",\n    \"moon_star\",\n    \"moon\",\n    \"motorbike\",\n    \"mountain_snow\",\n    \"mountain\",\n    \"mouse_left\",\n    \"mouse_off\",\n    \"mouse_pointer_2_off\",\n    \"mouse_pointer_2\",\n    \"mouse_pointer_ban\",\n    \"mouse_pointer_click\",\n    \"mouse_pointer\",\n    \"mouse_right\",\n    \"mouse\",\n    \"move_3d\",\n    \"move_diagonal_2\",\n    \"move_diagonal\",\n    \"move_down_left\",\n    \"move_down_right\",\n    \"move_down\",\n    \"move_horizontal\",\n    \"move_left\",\n    \"move_right\",\n    \"move_up_left\",\n    \"move_up_right\",\n    \"move_up\",\n    \"move_vertical\",\n    \"move\",\n    \"music_2\",\n    \"music_3\",\n    \"music_4\",\n    \"music\",\n    \"navigation_2_off\",\n    \"navigation_2\",\n    \"navigation_off\",\n    \"navigation\",\n    \"network\",\n    \"newspaper\",\n    \"nfc\",\n    \"non_binary\",\n    \"notebook_pen\",\n    \"notebook_tabs\",\n    \"notebook_text\",\n    \"notebook\",\n    \"notepad_text_dashed\",\n    \"notepad_text\",\n    \"nut_off\",\n    \"nut\",\n    \"octagon_alert\",\n    \"octagon_minus\",\n    \"octagon_pause\",\n    \"octagon_x\",\n    \"octagon\",\n    \"omega\",\n    \"option\",\n    \"orbit\",\n    \"origami\",\n    \"package_2\",\n    \"package_check\",\n    \"package_minus\",\n    \"package_open\",\n    \"package_plus\",\n    \"package_search\",\n    \"package_x\",\n    \"package\",\n    \"paint_bucket\",\n    \"paint_roller\",\n    \"paintbrush_2\",\n    \"paintbrush_vertical\",\n    \"paintbrush\",\n    \"palette\",\n    \"panda\",\n    \"panel_bottom_close\",\n    \"panel_bottom_dashed\",\n    \"panel_bottom_open\",\n    \"panel_bottom\",\n    \"panel_left_close\",\n    \"panel_left_dashed\",\n    \"panel_left_open\",\n    \"panel_left_right_dashed\",\n    \"panel_left\",\n    \"panel_right_close\",\n    \"panel_right_dashed\",\n    \"panel_right_open\",\n    \"panel_right\",\n    \"panel_top_bottom_dashed\",\n    \"panel_top_close\",\n    \"panel_top_dashed\",\n    \"panel_top_open\",\n    \"panel_top\",\n    \"panels_left_bottom\",\n    \"panels_right_bottom\",\n    \"panels_top_left\",\n    \"paperclip\",\n    \"parentheses\",\n    \"parking_meter\",\n    \"party_popper\",\n    \"pause\",\n    \"paw_print\",\n    \"pc_case\",\n    \"pen_line\",\n    \"pen_off\",\n    \"pen_tool\",\n    \"pen\",\n    \"pencil_line\",\n    \"pencil_off\",\n    \"pencil_ruler\",\n    \"pencil\",\n    \"pentagon\",\n    \"percent\",\n    \"person_standing\",\n    \"philippine_peso\",\n    \"phone_call\",\n    \"phone_forwarded\",\n    \"phone_incoming\",\n    \"phone_missed\",\n    \"phone_off\",\n    \"phone_outgoing\",\n    \"phone\",\n    \"pi\",\n    \"piano\",\n    \"pickaxe\",\n    \"picture_in_picture_2\",\n    \"picture_in_picture\",\n    \"pie_chart\",\n    \"piggy_bank\",\n    \"pilcrow_left\",\n    \"pilcrow_right\",\n    \"pilcrow\",\n    \"pill_bottle\",\n    \"pill\",\n    \"pin_off\",\n    \"pin\",\n    \"pipette\",\n    \"pizza\",\n    \"plane_landing\",\n    \"plane_takeoff\",\n    \"plane\",\n    \"play\",\n    \"plug_2\",\n    \"plug_zap_2\",\n    \"plug_zap\",\n    \"plug\",\n    \"plus\",\n    \"pocket_knife\",\n    \"pocket\",\n    \"podcast\",\n    \"pointer_off\",\n    \"pointer\",\n    \"popcorn\",\n    \"popsicle\",\n    \"pound_sterling\",\n    \"power_off\",\n    \"power\",\n    \"presentation\",\n    \"printer_check\",\n    \"printer_x\",\n    \"printer\",\n    \"projector\",\n    \"proportions\",\n    \"puzzle\",\n    \"pyramid\",\n    \"qr_code\",\n    \"quote\",\n    \"rabbit\",\n    \"radar\",\n    \"radiation\",\n    \"radical\",\n    \"radio_receiver\",\n    \"radio_tower\",\n    \"radio\",\n    \"radius\",\n    \"rail_symbol\",\n    \"rainbow\",\n    \"rat\",\n    \"ratio\",\n    \"receipt_cent\",\n    \"receipt_euro\",\n    \"receipt_indian_rupee\",\n    \"receipt_japanese_yen\",\n    \"receipt_pound_sterling\",\n    \"receipt_russian_ruble\",\n    \"receipt_swiss_franc\",\n    \"receipt_text\",\n    \"receipt_turkish_lira\",\n    \"receipt\",\n    \"rectangle_circle\",\n    \"rectangle_ellipsis\",\n    \"rectangle_goggles\",\n    \"rectangle_horizontal\",\n    \"rectangle_vertical\",\n    \"recycle\",\n    \"redo_2\",\n    \"redo_dot\",\n    \"redo\",\n    \"refresh_ccw_dot\",\n    \"refresh_ccw\",\n    \"refresh_cw_off\",\n    \"refresh_cw\",\n    \"refrigerator\",\n    \"regex\",\n    \"remove_formatting\",\n    \"repeat_1\",\n    \"repeat_2\",\n    \"repeat\",\n    \"replace_all\",\n    \"replace\",\n    \"reply_all\",\n    \"reply\",\n    \"rewind\",\n    \"ribbon\",\n    \"rocket\",\n    \"rocking_chair\",\n    \"roller_coaster\",\n    \"rose\",\n    \"rotate_3d\",\n    \"rotate_ccw_key\",\n    \"rotate_ccw_square\",\n    \"rotate_ccw\",\n    \"rotate_cw_square\",\n    \"rotate_cw\",\n    \"route_off\",\n    \"route\",\n    \"router\",\n    \"rows_2\",\n    \"rows_3\",\n    \"rows_4\",\n    \"rss\",\n    \"ruler_dimension_line\",\n    \"ruler\",\n    \"russian_ruble\",\n    \"sailboat\",\n    \"salad\",\n    \"sandwich\",\n    \"satellite_dish\",\n    \"satellite\",\n    \"saudi_riyal\",\n    \"save_all\",\n    \"save_off\",\n    \"save\",\n    \"scale_3d\",\n    \"scale\",\n    \"scaling\",\n    \"scan_barcode\",\n    \"scan_eye\",\n    \"scan_face\",\n    \"scan_heart\",\n    \"scan_line\",\n    \"scan_qr_code\",\n    \"scan_search\",\n    \"scan_text\",\n    \"scan\",\n    \"scatter_chart\",\n    \"school\",\n    \"scissors_line_dashed\",\n    \"scissors\",\n    \"scooter\",\n    \"screen_share_off\",\n    \"screen_share\",\n    \"scroll_text\",\n    \"scroll\",\n    \"search_alert\",\n    \"search_check\",\n    \"search_code\",\n    \"search_slash\",\n    \"search_x\",\n    \"search\",\n    \"section\",\n    \"send_horizontal\",\n    \"send_to_back\",\n    \"send\",\n    \"separator_horizontal\",\n    \"separator_vertical\",\n    \"server_cog\",\n    \"server_crash\",\n    \"server_off\",\n    \"server\",\n    \"settings_2\",\n    \"settings\",\n    \"shapes\",\n    \"share_2\",\n    \"share\",\n    \"sheet\",\n    \"shell\",\n    \"shelving_unit\",\n    \"shield_alert\",\n    \"shield_ban\",\n    \"shield_check\",\n    \"shield_ellipsis\",\n    \"shield_half\",\n    \"shield_minus\",\n    \"shield_off\",\n    \"shield_plus\",\n    \"shield_question\",\n    \"shield_user\",\n    \"shield_x\",\n    \"shield\",\n    \"ship_wheel\",\n    \"ship\",\n    \"shirt\",\n    \"shopping_bag\",\n    \"shopping_basket\",\n    \"shopping_cart\",\n    \"shovel\",\n    \"shower_head\",\n    \"shredder\",\n    \"shrimp\",\n    \"shrink\",\n    \"shrub\",\n    \"shuffle\",\n    \"sigma\",\n    \"signal_high\",\n    \"signal_low\",\n    \"signal_medium\",\n    \"signal_zero\",\n    \"signal\",\n    \"signature\",\n    \"signpost_big\",\n    \"signpost\",\n    \"siren\",\n    \"skip_back\",\n    \"skip_forward\",\n    \"skull\",\n    \"slack\",\n    \"slash\",\n    \"slice\",\n    \"sliders_horizontal\",\n    \"sliders_vertical\",\n    \"smartphone_charging\",\n    \"smartphone_nfc\",\n    \"smartphone\",\n    \"smile_plus\",\n    \"smile\",\n    \"snail\",\n    \"snowflake\",\n    \"soap_dispenser_droplet\",\n    \"sofa\",\n    \"solar_panel\",\n    \"soup\",\n    \"space\",\n    \"spade\",\n    \"sparkle\",\n    \"sparkles\",\n    \"speaker\",\n    \"speech\",\n    \"spell_check_2\",\n    \"spell_check\",\n    \"spline_pointer\",\n    \"spline\",\n    \"split\",\n    \"spool\",\n    \"spotlight\",\n    \"spray_can\",\n    \"sprout\",\n    \"square_activity\",\n    \"square_arrow_down_left\",\n    \"square_arrow_down_right\",\n    \"square_arrow_down\",\n    \"square_arrow_left\",\n    \"square_arrow_out_down_left\",\n    \"square_arrow_out_down_right\",\n    \"square_arrow_out_up_left\",\n    \"square_arrow_out_up_right\",\n    \"square_arrow_right_enter\",\n    \"square_arrow_right_exit\",\n    \"square_arrow_right\",\n    \"square_arrow_up_left\",\n    \"square_arrow_up_right\",\n    \"square_arrow_up\",\n    \"square_asterisk\",\n    \"square_bottom_dashed_scissors\",\n    \"square_chart_gantt\",\n    \"square_check_big\",\n    \"square_check\",\n    \"square_chevron_down\",\n    \"square_chevron_left\",\n    \"square_chevron_right\",\n    \"square_chevron_up\",\n    \"square_code\",\n    \"square_dashed_bottom_code\",\n    \"square_dashed_bottom\",\n    \"square_dashed_kanban\",\n    \"square_dashed_mouse_pointer\",\n    \"square_dashed_top_solid\",\n    \"square_dashed\",\n    \"square_divide\",\n    \"square_dot\",\n    \"square_equal\",\n    \"square_function\",\n    \"square_gantt_chart\",\n    \"square_kanban\",\n    \"square_library\",\n    \"square_m\",\n    \"square_menu\",\n    \"square_minus\",\n    \"square_mouse_pointer\",\n    \"square_parking_off\",\n    \"square_parking\",\n    \"square_pen\",\n    \"square_percent\",\n    \"square_pi\",\n    \"square_pilcrow\",\n    \"square_play\",\n    \"square_plus\",\n    \"square_power\",\n    \"square_radical\",\n    \"square_round_corner\",\n    \"square_scissors\",\n    \"square_sigma\",\n    \"square_slash\",\n    \"square_split_horizontal\",\n    \"square_split_vertical\",\n    \"square_square\",\n    \"square_stack\",\n    \"square_terminal\",\n    \"square_user_round\",\n    \"square_user\",\n    \"square_x\",\n    \"square_centerline_dashed_horizontal\",\n    \"square_centerline_dashed_vertical\",\n    \"square\",\n    \"squares_exclude\",\n    \"squares_intersect\",\n    \"squares_subtract\",\n    \"squares_unite\",\n    \"squircle_dashed\",\n    \"squircle\",\n    \"squirrel\",\n    \"stamp\",\n    \"star_half\",\n    \"star_off\",\n    \"star\",\n    \"step_back\",\n    \"step_forward\",\n    \"stethoscope\",\n    \"sticker\",\n    \"sticky_note\",\n    \"stone\",\n    \"store\",\n    \"stretch_horizontal\",\n    \"stretch_vertical\",\n    \"strikethrough\",\n    \"subscript\",\n    \"sun_dim\",\n    \"sun_medium\",\n    \"sun_moon\",\n    \"sun_snow\",\n    \"sun\",\n    \"sunrise\",\n    \"sunset\",\n    \"superscript\",\n    \"swatch_book\",\n    \"swiss_franc\",\n    \"switch_camera\",\n    \"sword\",\n    \"swords\",\n    \"syringe\",\n    \"table_2\",\n    \"table_cells_merge\",\n    \"table_cells_split\",\n    \"table_columns_split\",\n    \"table_of_contents\",\n    \"table_properties\",\n    \"table_rows_split\",\n    \"table\",\n    \"tablet_smartphone\",\n    \"tablet\",\n    \"tablets\",\n    \"tag\",\n    \"tags\",\n    \"tally_1\",\n    \"tally_2\",\n    \"tally_3\",\n    \"tally_4\",\n    \"tally_5\",\n    \"tangent\",\n    \"target\",\n    \"telescope\",\n    \"tent_tree\",\n    \"tent\",\n    \"terminal\",\n    \"test_tube_diagonal\",\n    \"test_tube\",\n    \"test_tubes\",\n    \"text_cursor_input\",\n    \"text_cursor\",\n    \"text_quote\",\n    \"text_search\",\n    \"text_select\",\n    \"text\",\n    \"theater\",\n    \"thermometer_snowflake\",\n    \"thermometer_sun\",\n    \"thermometer\",\n    \"thumbs_down\",\n    \"thumbs_up\",\n    \"ticket_check\",\n    \"ticket_minus\",\n    \"ticket_percent\",\n    \"ticket_plus\",\n    \"ticket_slash\",\n    \"ticket_x\",\n    \"ticket\",\n    \"tickets_plane\",\n    \"tickets\",\n    \"timer_off\",\n    \"timer_reset\",\n    \"timer\",\n    \"toggle_left\",\n    \"toggle_right\",\n    \"toilet\",\n    \"tool_case\",\n    \"toolbox\",\n    \"tornado\",\n    \"torus\",\n    \"touchpad_off\",\n    \"touchpad\",\n    \"towel_rack\",\n    \"tower_control\",\n    \"toy_brick\",\n    \"tractor\",\n    \"traffic_cone\",\n    \"train_front_tunnel\",\n    \"train_front\",\n    \"train_track\",\n    \"tram_front\",\n    \"transgender\",\n    \"trash_2\",\n    \"trash\",\n    \"tree_deciduous\",\n    \"tree_palm\",\n    \"tree_pine\",\n    \"trees\",\n    \"trello\",\n    \"trending_down\",\n    \"trending_up_down\",\n    \"trending_up\",\n    \"triangle_alert\",\n    \"triangle_dashed\",\n    \"triangle_right\",\n    \"triangle\",\n    \"trophy\",\n    \"truck_electric\",\n    \"truck\",\n    \"turkish_lira\",\n    \"turntable\",\n    \"turtle\",\n    \"tv_2\",\n    \"tv_minimal_play\",\n    \"tv_minimal\",\n    \"tv\",\n    \"twitch\",\n    \"twitter\",\n    \"type_outline\",\n    \"type\",\n    \"umbrella_off\",\n    \"umbrella\",\n    \"underline\",\n    \"undo_2\",\n    \"undo_dot\",\n    \"undo\",\n    \"unfold_horizontal\",\n    \"unfold_vertical\",\n    \"ungroup\",\n    \"university\",\n    \"unlink_2\",\n    \"unlink\",\n    \"unplug\",\n    \"upload\",\n    \"usb\",\n    \"user_check\",\n    \"user_cog\",\n    \"user_key\",\n    \"user_lock\",\n    \"user_minus\",\n    \"user_pen\",\n    \"user_plus\",\n    \"user_round_check\",\n    \"user_round_cog\",\n    \"user_round_key\",\n    \"user_round_minus\",\n    \"user_round_pen\",\n    \"user_round_plus\",\n    \"user_round_search\",\n    \"user_round_x\",\n    \"user_round\",\n    \"user_search\",\n    \"user_star\",\n    \"user_x\",\n    \"user\",\n    \"users_round\",\n    \"users\",\n    \"utensils_crossed\",\n    \"utensils\",\n    \"utility_pole\",\n    \"van\",\n    \"variable\",\n    \"vault\",\n    \"vector_square\",\n    \"vegan\",\n    \"venetian_mask\",\n    \"venus_and_mars\",\n    \"venus\",\n    \"vibrate_off\",\n    \"vibrate\",\n    \"video_off\",\n    \"video\",\n    \"videotape\",\n    \"view\",\n    \"voicemail\",\n    \"volleyball\",\n    \"volume_1\",\n    \"volume_2\",\n    \"volume_off\",\n    \"volume_x\",\n    \"volume\",\n    \"vote\",\n    \"wallet_cards\",\n    \"wallet_minimal\",\n    \"wallet\",\n    \"wallpaper\",\n    \"wand_sparkles\",\n    \"wand\",\n    \"warehouse\",\n    \"washing_machine\",\n    \"watch\",\n    \"waves_arrow_down\",\n    \"waves_arrow_up\",\n    \"waves_ladder\",\n    \"waves\",\n    \"waypoints\",\n    \"webcam\",\n    \"webhook_off\",\n    \"webhook\",\n    \"weight_tilde\",\n    \"weight\",\n    \"wheat_off\",\n    \"wheat\",\n    \"whole_word\",\n    \"wifi_cog\",\n    \"wifi_high\",\n    \"wifi_low\",\n    \"wifi_off\",\n    \"wifi_pen\",\n    \"wifi_sync\",\n    \"wifi_zero\",\n    \"wifi\",\n    \"wind_arrow_down\",\n    \"wind\",\n    \"wine_off\",\n    \"wine\",\n    \"workflow\",\n    \"worm\",\n    \"wrap_text\",\n    \"wrench\",\n    \"x_line_top\",\n    \"x\",\n    \"youtube\",\n    \"zap_off\",\n    \"zap\",\n    \"zoom_in\",\n    \"zoom_out\",\n]\n\n# The default transformation of some icon names doesn't match how the\n# icons are exported from Lucide. Manual overrides can go here.\nLUCIDE_ICON_MAPPING_OVERRIDE = {\n    \"grid_3x2\": \"Grid3x2Icon\",\n    \"fingerprint\": \"FingerprintPattern\",\n}\n"
  },
  {
    "path": "reflex/components/markdown/__init__.py",
    "content": "\"\"\"Markdown components.\"\"\"\n\nfrom .markdown import markdown as markdown\n"
  },
  {
    "path": "reflex/components/markdown/markdown.py",
    "content": "\"\"\"Markdown component.\"\"\"\n\nfrom __future__ import annotations\n\nimport dataclasses\nimport textwrap\nfrom collections.abc import Callable, Sequence\nfrom functools import lru_cache\nfrom hashlib import md5\nfrom types import SimpleNamespace\nfrom typing import Any\n\nfrom reflex.components.component import (\n    BaseComponent,\n    Component,\n    ComponentNamespace,\n    CustomComponent,\n    field,\n)\nfrom reflex.components.el.elements.typography import Div\nfrom reflex.components.tags.tag import Tag\nfrom reflex.utils import console\nfrom reflex.utils.imports import ImportDict, ImportTypes, ImportVar\nfrom reflex.vars.base import LiteralVar, Var, VarData\nfrom reflex.vars.function import ArgsFunctionOperation, DestructuredArg\nfrom reflex.vars.number import ternary_operation\nfrom reflex.vars.sequence import LiteralArrayVar\n\n# Special vars used in the component map.\n_CHILDREN = Var(_js_expr=\"children\", _var_type=str)\n_PROPS = Var(_js_expr=\"props\")\n_PROPS_SPREAD = Var(_js_expr=\"...props\")\n_REST = Var(_js_expr=\"rest\")\n_REST_SPREAD = Var(_js_expr=\"...rest\")\n_MOCK_ARG = Var(_js_expr=\"\", _var_type=str)\n_LANGUAGE = Var(_js_expr=\"_language\", _var_type=str)\n\n\nclass Plugin(SimpleNamespace):\n    \"\"\"Create new remark/rehype plugin or access pre-wrapped plugins.\"\"\"\n\n    @staticmethod\n    def create(\n        package: str,\n        tag: str,\n        additional_imports: dict[str, ImportTypes] | None = None,\n        **import_var_kwargs,\n    ) -> Var:\n        \"\"\"Create a plugin Var.\n\n        Args:\n            package: The package to import the plugin from.\n            tag: The imported identifier.\n            additional_imports: Additional imports to include in the VarData, such as CSS.\n            **import_var_kwargs: Additional kwargs to pass to the ImportVar.\n\n        Returns:\n            The plugin Var.\n        \"\"\"\n        import_var_kwargs.setdefault(\"is_default\", True)\n        return Var(\n            _js_expr=tag,\n            _var_data=VarData(\n                imports={\n                    package: ImportVar(\n                        tag=tag,\n                        **import_var_kwargs,\n                    ),\n                    **(additional_imports or {}),\n                }\n            ),\n        )\n\n    __call__ = create\n\n    math = create(\"remark-math@6.0.0\", \"remarkMath\")\n    gfm = create(\"remark-gfm@4.0.1\", \"remarkGfm\")\n    unwrap_images = create(\"rehype-unwrap-images@1.0.0\", \"rehypeUnwrapImages\")\n    katex = create(\n        \"rehype-katex@7.0.1\",\n        \"rehypeKatex\",\n        additional_imports={\n            \"\": \"katex/dist/katex.min.css\",\n        },\n    )\n    raw = create(\"rehype-raw@7.0.0\", \"rehypeRaw\")\n    _undefined = Var(_js_expr=\"() => undefined\")\n\n\ndef _h1(value: object):\n    from reflex.components.radix.themes.typography.heading import Heading\n\n    return Heading.create(value, as_=\"h1\", size=\"6\", margin_y=\"0.5em\")\n\n\ndef _h2(value: object):\n    from reflex.components.radix.themes.typography.heading import Heading\n\n    return Heading.create(value, as_=\"h2\", size=\"5\", margin_y=\"0.5em\")\n\n\ndef _h3(value: object):\n    from reflex.components.radix.themes.typography.heading import Heading\n\n    return Heading.create(value, as_=\"h3\", size=\"4\", margin_y=\"0.5em\")\n\n\ndef _h4(value: object):\n    from reflex.components.radix.themes.typography.heading import Heading\n\n    return Heading.create(value, as_=\"h4\", size=\"3\", margin_y=\"0.5em\")\n\n\ndef _h5(value: object):\n    from reflex.components.radix.themes.typography.heading import Heading\n\n    return Heading.create(value, as_=\"h5\", size=\"2\", margin_y=\"0.5em\")\n\n\ndef _h6(value: object):\n    from reflex.components.radix.themes.typography.heading import Heading\n\n    return Heading.create(value, as_=\"h6\", size=\"1\", margin_y=\"0.5em\")\n\n\ndef _p(value: object):\n    from reflex.components.radix.themes.typography.text import Text\n\n    return Text.create(value, margin_y=\"1em\")\n\n\ndef _ul(value: object):\n    from reflex.components.radix.themes.layout.list import UnorderedList\n\n    return UnorderedList.create(value, margin_y=\"1em\")\n\n\ndef _ol(value: object):\n    from reflex.components.radix.themes.layout.list import OrderedList\n\n    return OrderedList.create(value, margin_y=\"1em\")\n\n\ndef _li(value: object):\n    from reflex.components.radix.themes.layout.list import ListItem\n\n    return ListItem.create(value, margin_y=\"0.5em\")\n\n\ndef _a(value: object):\n    from reflex.components.radix.themes.typography.link import Link\n\n    return Link.create(value)\n\n\ndef _code(value: object):\n    from reflex.components.radix.themes.typography.code import Code\n\n    return Code.create(value)\n\n\ndef _codeblock(value: object, **props):\n    from reflex.components.datadisplay.code import CodeBlock\n\n    return CodeBlock.create(value, margin_y=\"1em\", wrap_long_lines=True, **props)\n\n\n# Component Mapping\n@lru_cache\ndef get_base_component_map() -> dict[str, Callable]:\n    \"\"\"Get the base component map.\n\n    Returns:\n        The base component map.\n    \"\"\"\n    return {\n        \"h1\": _h1,\n        \"h2\": _h2,\n        \"h3\": _h3,\n        \"h4\": _h4,\n        \"h5\": _h5,\n        \"h6\": _h6,\n        \"p\": _p,\n        \"ul\": _ul,\n        \"ol\": _ol,\n        \"li\": _li,\n        \"a\": _a,\n        \"code\": _code,\n        \"pre\": _codeblock,\n    }\n\n\n@dataclasses.dataclass()\nclass MarkdownComponentMap:\n    \"\"\"Mixin class for handling custom component maps in Markdown components.\"\"\"\n\n    _explicit_return: bool = dataclasses.field(default=False)\n\n    @classmethod\n    def get_component_map_custom_code(cls) -> Var:\n        \"\"\"Get the custom code for the component map.\n\n        Returns:\n            The custom code for the component map.\n        \"\"\"\n        return Var(\"\")\n\n    @classmethod\n    def create_map_fn_var(\n        cls,\n        fn_body: Var | None = None,\n        fn_args: Sequence[str] | None = None,\n        explicit_return: bool | None = None,\n        var_data: VarData | None = None,\n    ) -> Var:\n        \"\"\"Create a function Var for the component map.\n\n        Args:\n            fn_body: The formatted component as a string.\n            fn_args: The function arguments.\n            explicit_return: Whether to use explicit return syntax.\n            var_data: The var data for the function.\n\n        Returns:\n            The function Var for the component map.\n        \"\"\"\n        fn_args = fn_args or cls.get_fn_args()\n        fn_body = fn_body if fn_body is not None else cls.get_fn_body()\n        explicit_return = explicit_return or cls._explicit_return\n\n        return ArgsFunctionOperation.create(\n            args_names=(DestructuredArg(fields=tuple(fn_args)),),\n            return_expr=fn_body,\n            explicit_return=explicit_return,\n            _var_data=var_data,\n        )\n\n    @classmethod\n    def get_fn_args(cls) -> Sequence[str]:\n        \"\"\"Get the function arguments for the component map.\n\n        Returns:\n            The function arguments as a list of strings.\n        \"\"\"\n        return [\"node\", _CHILDREN._js_expr, _PROPS_SPREAD._js_expr]\n\n    @classmethod\n    def get_fn_body(cls) -> Var:\n        \"\"\"Get the function body for the component map.\n\n        Returns:\n            The function body as a string.\n        \"\"\"\n        return Var(_js_expr=\"undefined\", _var_type=None)\n\n\nclass Markdown(Component):\n    \"\"\"A markdown component.\"\"\"\n\n    library = \"react-markdown@10.1.0\"\n\n    tag = \"ReactMarkdown\"\n\n    is_default = True\n\n    # The component map from a tag to a lambda that creates a component.\n    component_map: dict[str, Any] = field(\n        default_factory=dict, is_javascript_property=False\n    )\n\n    # The hash of the component map, generated at create() time.\n    component_map_hash: str = field(default=\"\", is_javascript_property=False)\n\n    # Remark plugins to use when rendering the content. Provide (plugin, options) if the plugin requires options.\n    remark_plugins: Var[Sequence[Var | tuple[Var, Var]]]\n\n    # Rehype (HTML processor) plugins to use when rendering the content. Provide (plugin, options) if the plugin requires options.\n    rehype_plugins: Var[Sequence[Var | tuple[Var, Var]]]\n\n    @classmethod\n    def create(\n        cls,\n        *children,\n        **props,\n    ) -> Component:\n        \"\"\"Create a markdown component.\n\n        Args:\n            *children: The children of the component.\n            **props: The properties of the component.\n\n        Returns:\n            The markdown component.\n\n        Raises:\n            ValueError: If the children are not valid.\n        \"\"\"\n        if len(children) != 1 or not isinstance(children[0], (str, Var)):\n            msg = \"Markdown component must have exactly one child containing the markdown source.\"\n            raise ValueError(msg)\n\n        # Update the base component map with the custom component map.\n        component_map = {**get_base_component_map(), **props.pop(\"component_map\", {})}\n        if \"codeblock\" in component_map:\n            console.deprecate(\n                feature_name=\"'codeblock' in component_map\",\n                reason=\"Use 'pre' instead of 'codeblock' to customize code block rendering in markdown\",\n                deprecation_version=\"0.8.25\",\n                removal_version=\"0.9.0\",\n            )\n            component_map[\"pre\"] = component_map.pop(\"codeblock\")\n\n        # Get the markdown source.\n        src = children[0]\n\n        # Dedent the source.\n        if isinstance(src, str):\n            src = textwrap.dedent(src)\n\n        # Create the component.\n        return super().create(\n            src,\n            component_map=component_map,\n            component_map_hash=cls._component_map_hash(component_map),\n            **props,\n        )\n\n    def add_imports(self) -> ImportDict | list[ImportDict]:\n        \"\"\"Add imports for the markdown component.\n\n        Returns:\n            The imports for the markdown component.\n        \"\"\"\n        return [\n            *[\n                component(_MOCK_ARG)._get_all_imports()\n                for component in self.component_map.values()\n            ],\n            *(\n                [codeblock_var_data.old_school_imports()]\n                if (\n                    codeblock_var_data\n                    := self._get_codeblock_fn_var()._get_all_var_data()\n                )\n                is not None\n                else []\n            ),\n        ]\n\n    def _get_tag_map_fn_var(self, tag: str) -> Var:\n        return self._get_map_fn_var_from_children(self.get_component(tag), tag)\n\n    def format_component_map(self) -> dict[str, Var]:\n        \"\"\"Format the component map for rendering.\n\n        Returns:\n            The formatted component map.\n        \"\"\"\n        components = {\n            tag: self._get_tag_map_fn_var(tag)\n            for tag in self.component_map\n            if tag != \"pre\"\n        }\n\n        # Special handling for code blocks to extract the language.\n        components[\"pre\"] = self._get_codeblock_fn_var()\n\n        return components\n\n    def _get_codeblock_fn_var(self) -> Var:\n        \"\"\"Get the function variable for codeblock.\n\n        This function creates a Var that represents a function to handle\n        both code blocks in markdown.\n\n        Returns:\n            The Var for pre code.\n        \"\"\"\n        # Get any custom code from the code block \"pre\" component.\n        custom_code_list = self._get_map_fn_custom_code_from_children(\n            self.get_component(\"pre\")\n        )\n        var_data = VarData.merge(*[\n            code._get_all_var_data()\n            for code in custom_code_list\n            if isinstance(code, Var)\n        ])\n        codeblock_custom_code = \"\\n\".join(map(str, custom_code_list))\n\n        # Format the code to handle code block with language extraction.\n        formatted_code = f\"\"\"\nconst {{node: childNode, className, children: components, {_PROPS_SPREAD._js_expr}}} = {_REST._js_expr}.children.props;\nconst {_CHILDREN._js_expr} = String(Array.isArray(components) ? components.join('\\\\n') : components).replace(/\\\\n$/, '');\nconst match = (className || '').match(/language-(?<lang>.*)/);\nlet {_LANGUAGE!s} = match ? match[1] : '';\n{codeblock_custom_code};\n            return {self.format_component(\"pre\", language=_LANGUAGE)};\n        \"\"\".replace(\"\\n\", \" \")\n\n        return MarkdownComponentMap.create_map_fn_var(\n            fn_body=Var(_js_expr=formatted_code),\n            fn_args=[\"node\", _REST_SPREAD._js_expr],\n            explicit_return=True,\n            var_data=var_data,\n        )\n\n    def get_component(self, tag: str, **props) -> Component:\n        \"\"\"Get the component for a tag and props.\n\n        Args:\n            tag: The tag of the component.\n            **props: The props of the component.\n\n        Returns:\n            The component.\n\n        Raises:\n            ValueError: If the tag is invalid.\n        \"\"\"\n        # Check the tag is valid.\n        if tag not in self.component_map:\n            msg = f\"No markdown component found for tag: {tag}.\"\n            raise ValueError(msg)\n\n        # If the children are set as a prop, don't pass them as children.\n        children = [_CHILDREN] if props.get(\"children\") is None else []\n        # Get the component.\n        return self.component_map[tag](*children, **props).set(special_props=[_PROPS])\n\n    def format_component(self, tag: str, **props) -> str:\n        \"\"\"Format a component for rendering in the component map.\n\n        Args:\n            tag: The tag of the component.\n            **props: Extra props to pass to the component function.\n\n        Returns:\n            The formatted component.\n        \"\"\"\n        return str(self.get_component(tag, **props)).replace(\"\\n\", \"\")\n\n    def _get_map_fn_var_from_children(self, component: Component, tag: str) -> Var:\n        \"\"\"Create a function Var for the component map for the specified tag.\n\n        Args:\n            component: The component to check for custom code.\n            tag: The tag of the component.\n\n        Returns:\n            The function Var for the component map.\n        \"\"\"\n        formatted_component = Var(\n            _js_expr=f\"({self.format_component(tag)})\", _var_type=str\n        )\n        if isinstance(component, MarkdownComponentMap):\n            return component.create_map_fn_var(fn_body=formatted_component)\n\n        # fallback to the default fn Var creation if the component is not a MarkdownComponentMap.\n        return MarkdownComponentMap.create_map_fn_var(fn_body=formatted_component)\n\n    def _get_map_fn_custom_code_from_children(\n        self, component: BaseComponent\n    ) -> list[str | Var]:\n        \"\"\"Recursively get markdown custom code from children components.\n\n        Args:\n            component: The component to check for custom code.\n\n        Returns:\n            A list of markdown custom code strings.\n        \"\"\"\n        custom_code_list: list[str | Var] = []\n        if isinstance(component, MarkdownComponentMap):\n            custom_code_list.append(component.get_component_map_custom_code())\n\n        # If the component is a custom component(rx.memo), obtain the underlining\n        # component and get the custom code from the children.\n        if isinstance(component, CustomComponent):\n            custom_code_list.extend(\n                self._get_map_fn_custom_code_from_children(\n                    component.component_fn(*component.get_prop_vars())\n                )\n            )\n        elif isinstance(component, Component):\n            for child in component.children:\n                custom_code_list.extend(\n                    self._get_map_fn_custom_code_from_children(child)\n                )\n\n        return custom_code_list\n\n    @staticmethod\n    def _component_map_hash(component_map: dict) -> str:\n        inp = str({\n            tag: (\n                f\"{component.__module__}.{component.__qualname__}\"\n                if (\n                    \"<\" not in component.__name__\n                )  # simple way to check against lambdas\n                else component(_MOCK_ARG)\n            )\n            for tag, component in component_map.items()\n        }).encode()\n        return md5(inp).hexdigest()\n\n    def _get_component_map_name(self) -> str:\n        return f\"ComponentMap_{self.component_map_hash}\"\n\n    def _get_custom_code(self) -> str | None:\n        hooks = {}\n        from reflex.compiler.templates import _render_hooks\n\n        for component_factory in self.component_map.values():\n            comp = component_factory(_MOCK_ARG)\n            hooks.update(comp._get_all_hooks())\n        formatted_hooks = _render_hooks(hooks)\n        return f\"\"\"\n        function {self._get_component_map_name()} () {{\n            {formatted_hooks}\n            return (\n                {LiteralVar.create(self.format_component_map())!s}\n            )\n        }}\n        \"\"\"\n\n    def _render(self) -> Tag:\n        return (\n            super()\n            ._render()\n            .add_props(\n                components=Var(_js_expr=f\"{self._get_component_map_name()}()\"),\n            )\n            .remove_props(\"componentMap\", \"componentMapHash\")\n        )\n\n\nclass MarkdownWrapper(Div):\n    \"\"\"A markdown component, with optional div-wrapping when style props are given.\"\"\"\n\n    @classmethod\n    def create(\n        cls,\n        *children,\n        use_math: bool | Var[bool] = True,\n        use_gfm: bool | Var[bool] = True,\n        use_unwrap_images: bool | Var[bool] = True,\n        use_katex: bool | Var[bool] = True,\n        use_raw: bool | Var[bool] = True,\n        **props,\n    ) -> Component:\n        \"\"\"Create a markdown component.\n\n        Args:\n            *children: The children of the component.\n            use_math: Whether to use the remark-math plugin.\n            use_gfm: Whether to use the GitHub Flavored Markdown plugin.\n            use_unwrap_images: Whether to use the unwrap images plugin.\n            use_katex: Whether to use the KaTeX plugin.\n            use_raw: Whether to use the raw HTML plugin.\n            **props: The properties of the component.\n\n        Returns:\n            The markdown component or div wrapping markdown component.\n\n        Raises:\n            ValueError: If the children are not valid.\n        \"\"\"\n        # Assemble the plugin lists.\n        builtin_remark_plugins = []\n        if isinstance(use_math, Var):\n            builtin_remark_plugins.append(\n                ternary_operation(\n                    use_math, markdown.plugin.math, markdown.plugin._undefined\n                )\n            )\n        elif use_math:\n            builtin_remark_plugins.append(markdown.plugin.math)\n        if isinstance(use_gfm, Var):\n            builtin_remark_plugins.append(\n                ternary_operation(\n                    use_gfm, markdown.plugin.gfm, markdown.plugin._undefined\n                )\n            )\n        elif use_gfm:\n            builtin_remark_plugins.append(markdown.plugin.gfm)\n        remark_plugins = LiteralArrayVar.create(builtin_remark_plugins)\n        if (user_remark_plugins := props.pop(\"remark_plugins\", None)) is not None:\n            if not isinstance(user_remark_plugins, Var):\n                user_remark_plugins = Var.create(user_remark_plugins)\n            remark_plugins = remark_plugins + user_remark_plugins.to(list)\n\n        builtin_rehype_plugins = []\n        if isinstance(use_katex, Var):\n            builtin_rehype_plugins.append(\n                ternary_operation(\n                    use_katex, markdown.plugin.katex, markdown.plugin._undefined\n                )\n            )\n        elif use_katex:\n            builtin_rehype_plugins.append(markdown.plugin.katex)\n        if isinstance(use_raw, Var):\n            builtin_rehype_plugins.append(\n                ternary_operation(\n                    use_raw, markdown.plugin.raw, markdown.plugin._undefined\n                )\n            )\n        elif use_raw:\n            builtin_rehype_plugins.append(markdown.plugin.raw)\n        if isinstance(use_unwrap_images, Var):\n            builtin_rehype_plugins.append(\n                ternary_operation(\n                    use_unwrap_images,\n                    markdown.plugin.unwrap_images,\n                    markdown.plugin._undefined,\n                )\n            )\n        elif use_unwrap_images:\n            builtin_rehype_plugins.append(markdown.plugin.unwrap_images)\n        rehype_plugins = LiteralArrayVar.create(builtin_rehype_plugins)\n        if (user_rehype_plugins := props.pop(\"rehype_plugins\", None)) is not None:\n            if not isinstance(user_rehype_plugins, Var):\n                user_rehype_plugins = Var.create(user_rehype_plugins)\n            rehype_plugins = rehype_plugins + user_rehype_plugins.to(list)\n\n        return super().create(\n            Markdown.create(\n                *children,\n                component_map=props.pop(\"component_map\", {}),\n                remark_plugins=remark_plugins.to(list[Var | tuple[Var, Var]]),\n                rehype_plugins=rehype_plugins.to(list[Var | tuple[Var, Var]]),\n            ),\n            **props,\n        )\n\n\nclass MarkdownNamespace(ComponentNamespace):\n    \"\"\"A namespace for markdown components.\"\"\"\n\n    __call__ = staticmethod(MarkdownWrapper.create)\n    root = staticmethod(Markdown.create)\n    plugin = Plugin()\n\n\nmarkdown = MarkdownNamespace()\n"
  },
  {
    "path": "reflex/components/moment/__init__.py",
    "content": "\"\"\"Moment.js component.\"\"\"\n\nfrom .moment import Moment, MomentDelta\n\nmoment = Moment.create\n"
  },
  {
    "path": "reflex/components/moment/moment.py",
    "content": "\"\"\"Moment component for humanized date rendering.\"\"\"\n\nimport dataclasses\nfrom datetime import date, datetime, time, timedelta\n\nfrom reflex.components.component import NoSSRComponent\nfrom reflex.event import EventHandler, passthrough_event_spec\nfrom reflex.utils.imports import ImportDict\nfrom reflex.vars.base import LiteralVar, Var\n\n\n@dataclasses.dataclass(frozen=True)\nclass MomentDelta:\n    \"\"\"A delta used for add/subtract prop in Moment.\"\"\"\n\n    years: int | None = dataclasses.field(default=None)\n    quarters: int | None = dataclasses.field(default=None)\n    months: int | None = dataclasses.field(default=None)\n    weeks: int | None = dataclasses.field(default=None)\n    days: int | None = dataclasses.field(default=None)\n    hours: int | None = dataclasses.field(default=None)\n    minutes: int | None = dataclasses.field(default=None)\n    seconds: int | None = dataclasses.field(default=None)\n    milliseconds: int | None = dataclasses.field(default=None)\n\n\nclass Moment(NoSSRComponent):\n    \"\"\"The Moment component.\"\"\"\n\n    tag: str | None = \"Moment\"\n    is_default = True\n    library: str | None = \"react-moment@1.2.2\"\n    lib_dependencies: list[str] = [\"moment@2.30.1\"]\n\n    # How often the date update (how often time update / 0 to disable).\n    interval: Var[int]\n\n    # Formats the date according to the given format string.\n    format: Var[str]\n\n    # When formatting duration time, the largest-magnitude tokens are automatically trimmed when they have no value.\n    trim: Var[bool]\n\n    #  Use the parse attribute to tell moment how to parse the given date when non-standard.\n    parse: Var[str]\n\n    # Add a delta to the base date (keys are \"years\", \"quarters\", \"months\", \"weeks\", \"days\", \"hours\", \"minutes\", \"seconds\")\n    add: Var[MomentDelta]\n\n    # Subtract a delta to the base date (keys are \"years\", \"quarters\", \"months\", \"weeks\", \"days\", \"hours\", \"minutes\", \"seconds\")\n    subtract: Var[MomentDelta]\n\n    # Displays the date as the time from now, e.g. \"5 minutes ago\".\n    from_now: Var[bool]\n\n    # Displays the relative time in a short format using abbreviated units (e.g., \"1h\", \"2d\", \"3mo\", \"1y\" instead of \"1 hour ago\", \"2 days ago\", etc.).\n    from_now_short: Var[bool]\n\n    # Setting fromNowDuring will display the relative time as with fromNow but just during its value in milliseconds, after that format will be used instead.\n    from_now_during: Var[int]\n\n    # Similar to fromNow, but gives the opposite interval.\n    to_now: Var[bool]\n\n    # Adds a title attribute to the element with the complete date.\n    with_title: Var[bool]\n\n    # How the title date is formatted when using the withTitle attribute.\n    title_format: Var[str]\n\n    # Show the different between this date and the rendered child.\n    diff: Var[str]\n\n    # Display the diff as decimal.\n    decimal: Var[bool]\n\n    # Display the diff in given unit.\n    unit: Var[str]\n\n    # Shows the duration (elapsed time) between two dates. duration property should be behind date property time-wise.\n    duration: Var[str]\n\n    # The date to display (also work if passed as children).\n    date: Var[str | datetime | date | time | timedelta]\n\n    # Shows the duration (elapsed time) between now and the provided datetime.\n    duration_from_now: Var[bool]\n\n    # Tells Moment to parse the given date value as a unix timestamp.\n    unix: Var[bool]\n\n    # Outputs the result in local time.\n    local: Var[bool]\n\n    # Display the date in the given timezone.\n    tz: Var[str]\n\n    # The locale to use when rendering.\n    locale: Var[str]\n\n    # Fires when the date changes.\n    on_change: EventHandler[passthrough_event_spec(str)]\n\n    def add_imports(self) -> ImportDict:\n        \"\"\"Add the imports for the Moment component.\n\n        Returns:\n            The import dict for the component.\n        \"\"\"\n        imports = {}\n\n        if isinstance(self.locale, LiteralVar):\n            imports[\"\"] = f\"moment/locale/{self.locale._var_value}\"\n        elif self.locale is not None:\n            # If the user is using a variable for the locale, we can't know the\n            # value at compile time so import all locales available.\n            imports[\"\"] = \"moment/min/locales\"\n        if self.tz is not None:\n            imports[\"moment-timezone\"] = \"\"\n\n        return imports\n"
  },
  {
    "path": "reflex/components/plotly/__init__.py",
    "content": "\"\"\"Plotly components.\"\"\"\n\nfrom reflex.components.component import ComponentNamespace\n\nfrom .plotly import (\n    Plotly,\n    PlotlyBasic,\n    PlotlyCartesian,\n    PlotlyFinance,\n    PlotlyGeo,\n    PlotlyGl2d,\n    PlotlyGl3d,\n    PlotlyMapbox,\n    PlotlyStrict,\n)\n\n\nclass PlotlyNamespace(ComponentNamespace):\n    \"\"\"Plotly namespace.\"\"\"\n\n    __call__ = Plotly.create\n    basic = PlotlyBasic.create\n    cartesian = PlotlyCartesian.create\n    geo = PlotlyGeo.create\n    gl2d = PlotlyGl2d.create\n    gl3d = PlotlyGl3d.create\n    finance = PlotlyFinance.create\n    mapbox = PlotlyMapbox.create\n    strict = PlotlyStrict.create\n\n\nplotly = PlotlyNamespace()\n"
  },
  {
    "path": "reflex/components/plotly/plotly.py",
    "content": "\"\"\"Component for displaying a plotly graph.\"\"\"\n\nfrom __future__ import annotations\n\nfrom typing import TYPE_CHECKING, Any, TypedDict, TypeVar\n\nfrom reflex.components.component import Component, NoSSRComponent\nfrom reflex.components.core.cond import color_mode_cond\nfrom reflex.event import EventHandler, no_args_event_spec\nfrom reflex.utils import console\nfrom reflex.utils.imports import ImportDict, ImportVar\nfrom reflex.vars.base import LiteralVar, Var\n\ntry:\n    from plotly.graph_objs import Figure\n    from plotly.graph_objs.layout import Template\n\nexcept ImportError:\n    console.warn(\"Plotly is not installed. Please run `pip install plotly`.\")\n    if not TYPE_CHECKING:\n        Figure = Any\n        Template = Any\n\n\ndef _event_points_data_signature(e0: Var) -> tuple[Var[list[Point]]]:\n    \"\"\"For plotly events with event data containing a point array.\n\n    Args:\n        e0: The event data.\n\n    Returns:\n        The event data and the extracted points.\n    \"\"\"\n    return (Var(_js_expr=f\"extractPoints({e0}?.points)\"),)\n\n\nT = TypeVar(\"T\")\n\nItemOrList = T | list[T]\n\n\nclass BBox(TypedDict):\n    \"\"\"Bounding box for a point in a plotly graph.\"\"\"\n\n    x0: float | int | None\n    x1: float | int | None\n    y0: float | int | None\n    y1: float | int | None\n    z0: float | int | None\n    z1: float | int | None\n\n\nclass Point(TypedDict):\n    \"\"\"A point in a plotly graph.\"\"\"\n\n    x: float | int | None\n    y: float | int | None\n    z: float | int | None\n    lat: float | int | None\n    lon: float | int | None\n    curveNumber: int | None\n    pointNumber: int | None\n    pointNumbers: list[int] | None\n    pointIndex: int | None\n    markerColor: ItemOrList[ItemOrList[float | int | str | None]] | None\n    markerSize: ItemOrList[ItemOrList[float | int | None,]] | None\n    bbox: BBox | None\n\n\nclass Plotly(NoSSRComponent):\n    \"\"\"Display a plotly graph.\"\"\"\n\n    library = \"react-plotly.js@2.6.0\"\n\n    lib_dependencies: list[str] = [\"plotly.js@3.4.0\"]\n\n    tag = \"Plot\"\n\n    is_default = True\n\n    # The figure to display. This can be a plotly figure or a plotly data json.\n    data: Var[Figure]\n\n    # The layout of the graph.\n    layout: Var[dict]\n\n    # The template for visual appearance of the graph.\n    template: Var[Template]\n\n    # The config of the graph.\n    config: Var[dict]\n\n    # If true, the graph will resize when the window is resized.\n    use_resize_handler: Var[bool] = LiteralVar.create(True)\n\n    # Fired after the plot is redrawn.\n    on_after_plot: EventHandler[no_args_event_spec]\n\n    # Fired after the plot was animated.\n    on_animated: EventHandler[no_args_event_spec]\n\n    # Fired while animating a single frame (does not currently pass data through).\n    on_animating_frame: EventHandler[no_args_event_spec]\n\n    # Fired when an animation is interrupted (to start a new animation for example).\n    on_animation_interrupted: EventHandler[no_args_event_spec]\n\n    # Fired when the plot is responsively sized.\n    on_autosize: EventHandler[no_args_event_spec]\n\n    # Fired whenever mouse moves over a plot.\n    on_before_hover: EventHandler[no_args_event_spec]\n\n    # Fired when a plotly UI button is clicked.\n    on_button_clicked: EventHandler[no_args_event_spec]\n\n    # Fired when the plot is clicked.\n    on_click: EventHandler[_event_points_data_signature]\n\n    # Fired when a selection is cleared (via double click).\n    on_deselect: EventHandler[no_args_event_spec]\n\n    # Fired when the plot is double clicked.\n    on_double_click: EventHandler[no_args_event_spec]\n\n    # Fired when a plot element is hovered over.\n    on_hover: EventHandler[_event_points_data_signature]\n\n    # Fired after the plot is laid out (zoom, pan, etc).\n    on_relayout: EventHandler[no_args_event_spec]\n\n    # Fired while the plot is being laid out.\n    on_relayouting: EventHandler[no_args_event_spec]\n\n    # Fired after the plot style is changed.\n    on_restyle: EventHandler[no_args_event_spec]\n\n    # Fired after the plot is redrawn.\n    on_redraw: EventHandler[no_args_event_spec]\n\n    # Fired after selecting plot elements.\n    on_selected: EventHandler[_event_points_data_signature]\n\n    # Fired while dragging a selection.\n    on_selecting: EventHandler[_event_points_data_signature]\n\n    # Fired while an animation is occurring.\n    on_transitioning: EventHandler[no_args_event_spec]\n\n    # Fired when a transition is stopped early.\n    on_transition_interrupted: EventHandler[no_args_event_spec]\n\n    # Fired when a hovered element is no longer hovered.\n    on_unhover: EventHandler[_event_points_data_signature]\n\n    def add_imports(self) -> dict[str, str]:\n        \"\"\"Add imports for the plotly component.\n\n        Returns:\n            The imports for the plotly component.\n        \"\"\"\n        return {\n            # For merging plotly data/layout/templates.\n            \"mergician@v2.0.2\": \"mergician\"\n        }\n\n    def add_custom_code(self) -> list[str]:\n        \"\"\"Add custom codes for processing the plotly points data.\n\n        Returns:\n            Custom code snippets for the module level.\n        \"\"\"\n        return [\n            \"const removeUndefined = (obj) => {Object.keys(obj).forEach(key => obj[key] === undefined && delete obj[key]); return obj}\",\n            \"\"\"\nconst extractPoints = (points) => {\n    if (!points) return [];\n    return points.map(point => {\n        const bbox = point.bbox ? removeUndefined({\n            x0: point.bbox.x0,\n            x1: point.bbox.x1,\n            y0: point.bbox.y0,\n            y1: point.bbox.y1,\n            z0: point.bbox.y0,\n            z1: point.bbox.y1,\n        }) : undefined;\n        return removeUndefined({\n            x: point.x,\n            y: point.y,\n            z: point.z,\n            lat: point.lat,\n            lon: point.lon,\n            curveNumber: point.curveNumber,\n            pointNumber: point.pointNumber,\n            pointNumbers: point.pointNumbers,\n            pointIndex: point.pointIndex,\n            markerColor: point['marker.color'],\n            markerSize: point['marker.size'],\n            bbox: bbox,\n        })\n    })\n}\n\"\"\",\n        ]\n\n    @classmethod\n    def create(cls, *children, **props) -> Component:\n        \"\"\"Create the Plotly component.\n\n        Args:\n            *children: The children of the component.\n            **props: The properties of the component.\n\n        Returns:\n            The Plotly component.\n        \"\"\"\n        from plotly.graph_objs.layout import Template\n        from plotly.io import templates\n\n        responsive_template = color_mode_cond(\n            light=LiteralVar.create(templates[\"plotly\"]),\n            dark=LiteralVar.create(templates[\"plotly_dark\"]),\n        )\n        if isinstance(responsive_template, Var):\n            # Mark the conditional Var as a Template to avoid type mismatch\n            responsive_template = responsive_template.to(Template)\n        props.setdefault(\"template\", responsive_template)\n        return super().create(*children, **props)\n\n    def _exclude_props(self) -> set[str]:\n        # These props are handled specially in the _render function\n        return {\"data\", \"layout\", \"template\"}\n\n    def _render(self):\n        tag = super()._render()\n        figure = self.data.to(dict) if self.data is not None else Var.create({})\n        merge_dicts = []  # Data will be merged and spread from these dict Vars\n        if self.layout is not None:\n            # Why is this not a literal dict? Great question... it didn't work\n            # reliably because of how _var_name_unwrapped strips the outer curly\n            # brackets if any of the contained Vars depend on state.\n            layout_dict = LiteralVar.create({\"layout\": self.layout})\n            merge_dicts.append(layout_dict)\n        if self.template is not None:\n            template_dict = LiteralVar.create({\"layout\": {\"template\": self.template}})\n            merge_dicts.append(template_dict._without_data())\n        if merge_dicts:\n            tag = tag.set(\n                special_props=[\n                    *tag.special_props,\n                    # Merge all dictionaries and spread the result over props.\n                    Var(\n                        _js_expr=f\"{{...mergician({figure!s},\"\n                        f\"{','.join(str(md) for md in merge_dicts)})}}\",\n                    ),\n                ]\n            )\n        else:\n            tag = tag.set(\n                special_props=[\n                    *tag.special_props,\n                    # Spread the figure dict over props, nothing to merge.\n                    Var(_js_expr=str(figure)),\n                ]\n            )\n        return tag\n\n\nCREATE_PLOTLY_COMPONENT: ImportDict = {\n    \"react-plotly.js\": [\n        ImportVar(\n            tag=\"createPlotlyComponent\",\n            is_default=True,\n            package_path=\"/factory\",\n        ),\n    ]\n}\n\n\ndef dynamic_plotly_import(name: str, package: str) -> str:\n    \"\"\"Create a dynamic import for a plotly component.\n\n    Args:\n        name: The name of the component.\n        package: The package path of the component.\n\n    Returns:\n        The dynamic import for the plotly component.\n    \"\"\"\n    library_import = f\"import('{package}')\"\n    mod_import = \".then((mod) => createPlotlyComponent(mod))\"\n    return f\"\"\"\nconst {name} = ClientSide(() =>\n    {library_import}{mod_import}\n)\n\"\"\"\n\n\nclass PlotlyBasic(Plotly):\n    \"\"\"Display a basic plotly graph.\"\"\"\n\n    tag: str = \"BasicPlotlyPlot\"\n\n    library = \"react-plotly.js@2.6.0\"\n\n    lib_dependencies: list[str] = [\"plotly.js-basic-dist-min@3.4.0\"]\n\n    def add_imports(self) -> ImportDict | list[ImportDict]:\n        \"\"\"Add imports for the plotly basic component.\n\n        Returns:\n            The imports for the plotly basic component.\n        \"\"\"\n        return CREATE_PLOTLY_COMPONENT\n\n    def _get_dynamic_imports(self) -> str:\n        \"\"\"Get the dynamic imports for the plotly basic component.\n\n        Returns:\n            The dynamic imports for the plotly basic component.\n        \"\"\"\n        return dynamic_plotly_import(self.tag, \"plotly.js-basic-dist-min\")\n\n\nclass PlotlyCartesian(Plotly):\n    \"\"\"Display a plotly cartesian graph.\"\"\"\n\n    tag: str = \"CartesianPlotlyPlot\"\n\n    library = \"react-plotly.js@2.6.0\"\n\n    lib_dependencies: list[str] = [\"plotly.js-cartesian-dist-min@3.4.0\"]\n\n    def add_imports(self) -> ImportDict | list[ImportDict]:\n        \"\"\"Add imports for the plotly cartesian component.\n\n        Returns:\n            The imports for the plotly cartesian component.\n        \"\"\"\n        return CREATE_PLOTLY_COMPONENT\n\n    def _get_dynamic_imports(self) -> str:\n        \"\"\"Get the dynamic imports for the plotly cartesian component.\n\n        Returns:\n            The dynamic imports for the plotly cartesian component.\n        \"\"\"\n        return dynamic_plotly_import(self.tag, \"plotly.js-cartesian-dist-min\")\n\n\nclass PlotlyGeo(Plotly):\n    \"\"\"Display a plotly geo graph.\"\"\"\n\n    tag: str = \"GeoPlotlyPlot\"\n\n    library = \"react-plotly.js@2.6.0\"\n\n    lib_dependencies: list[str] = [\"plotly.js-geo-dist-min@3.4.0\"]\n\n    def add_imports(self) -> ImportDict | list[ImportDict]:\n        \"\"\"Add imports for the plotly geo component.\n\n        Returns:\n            The imports for the plotly geo component.\n        \"\"\"\n        return CREATE_PLOTLY_COMPONENT\n\n    def _get_dynamic_imports(self) -> str:\n        \"\"\"Get the dynamic imports for the plotly geo component.\n\n        Returns:\n            The dynamic imports for the plotly geo component.\n        \"\"\"\n        return dynamic_plotly_import(self.tag, \"plotly.js-geo-dist-min\")\n\n\nclass PlotlyGl3d(Plotly):\n    \"\"\"Display a plotly 3d graph.\"\"\"\n\n    tag: str = \"Gl3dPlotlyPlot\"\n\n    library = \"react-plotly.js@2.6.0\"\n\n    lib_dependencies: list[str] = [\"plotly.js-gl3d-dist-min@3.4.0\"]\n\n    def add_imports(self) -> ImportDict | list[ImportDict]:\n        \"\"\"Add imports for the plotly 3d component.\n\n        Returns:\n            The imports for the plotly 3d component.\n        \"\"\"\n        return CREATE_PLOTLY_COMPONENT\n\n    def _get_dynamic_imports(self) -> str:\n        \"\"\"Get the dynamic imports for the plotly 3d component.\n\n        Returns:\n            The dynamic imports for the plotly 3d component.\n        \"\"\"\n        return dynamic_plotly_import(self.tag, \"plotly.js-gl3d-dist-min\")\n\n\nclass PlotlyGl2d(Plotly):\n    \"\"\"Display a plotly 2d graph.\"\"\"\n\n    tag: str = \"Gl2dPlotlyPlot\"\n\n    library = \"react-plotly.js@2.6.0\"\n\n    lib_dependencies: list[str] = [\"plotly.js-gl2d-dist-min@3.4.0\"]\n\n    def add_imports(self) -> ImportDict | list[ImportDict]:\n        \"\"\"Add imports for the plotly 2d component.\n\n        Returns:\n            The imports for the plotly 2d component.\n        \"\"\"\n        return CREATE_PLOTLY_COMPONENT\n\n    def _get_dynamic_imports(self) -> str:\n        \"\"\"Get the dynamic imports for the plotly 2d component.\n\n        Returns:\n            The dynamic imports for the plotly 2d component.\n        \"\"\"\n        return dynamic_plotly_import(self.tag, \"plotly.js-gl2d-dist-min\")\n\n\nclass PlotlyMapbox(Plotly):\n    \"\"\"Display a plotly mapbox graph.\"\"\"\n\n    tag: str = \"MapboxPlotlyPlot\"\n\n    library = \"react-plotly.js@2.6.0\"\n\n    lib_dependencies: list[str] = [\"plotly.js-mapbox-dist-min@3.4.0\"]\n\n    def add_imports(self) -> ImportDict | list[ImportDict]:\n        \"\"\"Add imports for the plotly mapbox component.\n\n        Returns:\n            The imports for the plotly mapbox component.\n        \"\"\"\n        return CREATE_PLOTLY_COMPONENT\n\n    def _get_dynamic_imports(self) -> str:\n        \"\"\"Get the dynamic imports for the plotly mapbox component.\n\n        Returns:\n            The dynamic imports for the plotly mapbox component.\n        \"\"\"\n        return dynamic_plotly_import(self.tag, \"plotly.js-mapbox-dist-min\")\n\n\nclass PlotlyFinance(Plotly):\n    \"\"\"Display a plotly finance graph.\"\"\"\n\n    tag: str = \"FinancePlotlyPlot\"\n\n    library = \"react-plotly.js@2.6.0\"\n\n    lib_dependencies: list[str] = [\"plotly.js-finance-dist-min@3.4.0\"]\n\n    def add_imports(self) -> ImportDict | list[ImportDict]:\n        \"\"\"Add imports for the plotly finance component.\n\n        Returns:\n            The imports for the plotly finance component.\n        \"\"\"\n        return CREATE_PLOTLY_COMPONENT\n\n    def _get_dynamic_imports(self) -> str:\n        \"\"\"Get the dynamic imports for the plotly finance component.\n\n        Returns:\n            The dynamic imports for the plotly finance component.\n        \"\"\"\n        return dynamic_plotly_import(self.tag, \"plotly.js-finance-dist-min\")\n\n\nclass PlotlyStrict(Plotly):\n    \"\"\"Display a plotly strict graph.\"\"\"\n\n    tag: str = \"StrictPlotlyPlot\"\n\n    library = \"react-plotly.js@2.6.0\"\n\n    lib_dependencies: list[str] = [\"plotly.js-strict-dist-min@3.4.0\"]\n\n    def add_imports(self) -> ImportDict | list[ImportDict]:\n        \"\"\"Add imports for the plotly strict component.\n\n        Returns:\n            The imports for the plotly strict component.\n        \"\"\"\n        return CREATE_PLOTLY_COMPONENT\n\n    def _get_dynamic_imports(self) -> str:\n        \"\"\"Get the dynamic imports for the plotly strict component.\n\n        Returns:\n            The dynamic imports for the plotly strict component.\n        \"\"\"\n        return dynamic_plotly_import(self.tag, \"plotly.js-strict-dist-min\")\n"
  },
  {
    "path": "reflex/components/props.py",
    "content": "\"\"\"A class that holds props to be passed or applied to a component.\"\"\"\n\nfrom __future__ import annotations\n\nfrom collections.abc import Callable\nfrom dataclasses import _MISSING_TYPE, MISSING\nfrom typing import Any, TypeVar, get_args, get_origin\n\nfrom typing_extensions import dataclass_transform\n\nfrom reflex.components.field import BaseField, FieldBasedMeta\nfrom reflex.event import EventChain, args_specs_from_fields\nfrom reflex.utils import format\nfrom reflex.utils.exceptions import InvalidPropValueError\nfrom reflex.utils.serializers import serializer\nfrom reflex.utils.types import is_union\nfrom reflex.vars.object import LiteralObjectVar\n\nPROPS_FIELD_TYPE = TypeVar(\"PROPS_FIELD_TYPE\")\n\n\ndef _get_props_subclass(field_type: Any) -> type | None:\n    \"\"\"Extract the Props subclass from a field type annotation.\n\n    Args:\n        field_type: The type annotation to check.\n\n    Returns:\n        The Props subclass if found, None otherwise.\n    \"\"\"\n    from reflex.utils.types import typehint_issubclass\n\n    # For direct class types, we can return them directly if they're Props subclasses\n    if isinstance(field_type, type):\n        return field_type if typehint_issubclass(field_type, PropsBase) else None\n\n    # For Union types, check each union member\n    if is_union(field_type):\n        for arg in get_args(field_type):\n            result = _get_props_subclass(arg)\n            if result is not None:\n                return result\n\n    return None\n\n\ndef _find_props_in_list_annotation(field_type: Any) -> type | None:\n    \"\"\"Find Props subclass within a list type annotation.\n\n    Args:\n        field_type: The type annotation to check (e.g., list[SomeProps] or list[SomeProps] | None).\n\n    Returns:\n        The Props subclass if found in a list annotation, None otherwise.\n    \"\"\"\n    origin = get_origin(field_type)\n    if origin is list:\n        args = get_args(field_type)\n        if args:\n            return _get_props_subclass(args[0])\n\n    # Handle Union types - check if any union member is a list\n    if is_union(field_type):\n        for arg in get_args(field_type):\n            if arg is not type(None):  # Skip None from Optional\n                list_element = _find_props_in_list_annotation(arg)\n                if list_element is not None:\n                    return list_element\n\n    return None\n\n\nclass PropsField(BaseField[PROPS_FIELD_TYPE]):\n    \"\"\"A field for a props class.\"\"\"\n\n    def __init__(\n        self,\n        default: PROPS_FIELD_TYPE | _MISSING_TYPE = MISSING,\n        default_factory: Callable[[], PROPS_FIELD_TYPE] | None = None,\n        annotated_type: type[Any] | _MISSING_TYPE = MISSING,\n    ) -> None:\n        \"\"\"Initialize the field.\n\n        Args:\n            default: The default value for the field.\n            default_factory: The default factory for the field.\n            annotated_type: The annotated type for the field.\n        \"\"\"\n        super().__init__(default, default_factory, annotated_type)\n        self._name: str = \"\"  # Will be set by metaclass\n\n    @property\n    def required(self) -> bool:\n        \"\"\"Check if the field is required (for Pydantic compatibility).\n\n        Returns:\n            True if the field has no default value or factory.\n        \"\"\"\n        return self.default is MISSING and self.default_factory is None\n\n    @property\n    def name(self) -> str | None:\n        \"\"\"Field name (for Pydantic compatibility).\n\n        Note: This is set by the metaclass when processing fields.\n\n        Returns:\n            The field name if set, None otherwise.\n        \"\"\"\n        return getattr(self, \"_name\", None)\n\n    def get_default(self) -> Any:\n        \"\"\"Get the default value (for Pydantic compatibility).\n\n        Returns:\n            The default value for the field, or None if required.\n        \"\"\"\n        try:\n            return self.default_value()\n        except ValueError:\n            # Field is required (no default)\n            return None\n\n    def __repr__(self) -> str:\n        \"\"\"Represent the field in a readable format.\n\n        Returns:\n            The string representation of the field.\n        \"\"\"\n        annotated_type_str = (\n            f\", annotated_type={self.annotated_type!r}\"\n            if self.annotated_type is not MISSING\n            else \"\"\n        )\n        if self.default is not MISSING:\n            return f\"PropsField(default={self.default!r}{annotated_type_str})\"\n        return (\n            f\"PropsField(default_factory={self.default_factory!r}{annotated_type_str})\"\n        )\n\n\ndef props_field(\n    default: PROPS_FIELD_TYPE | _MISSING_TYPE = MISSING,\n    default_factory: Callable[[], PROPS_FIELD_TYPE] | None = None,\n) -> PROPS_FIELD_TYPE:\n    \"\"\"Create a field for a props class.\n\n    Args:\n        default: The default value for the field.\n        default_factory: The default factory for the field.\n\n    Returns:\n        The field for the props class.\n\n    Raises:\n        ValueError: If both default and default_factory are specified.\n    \"\"\"\n    if default is not MISSING and default_factory is not None:\n        msg = \"cannot specify both default and default_factory\"\n        raise ValueError(msg)\n    return PropsField(  # pyright: ignore [reportReturnType]\n        default=default,\n        default_factory=default_factory,\n        annotated_type=MISSING,\n    )\n\n\n@dataclass_transform(field_specifiers=(props_field,))\nclass PropsBaseMeta(FieldBasedMeta):\n    \"\"\"Meta class for PropsBase.\"\"\"\n\n    @classmethod\n    def _process_annotated_fields(\n        cls,\n        namespace: dict[str, Any],\n        annotations: dict[str, Any],\n        inherited_fields: dict[str, PropsField],\n    ) -> dict[str, PropsField]:\n        own_fields: dict[str, PropsField] = {}\n\n        for key, annotation in annotations.items():\n            value = namespace.get(key, MISSING)\n\n            if value is MISSING:\n                # Field with only annotation, no default value\n                field = PropsField(annotated_type=annotation, default=None)\n            elif not isinstance(value, PropsField):\n                # Field with default value\n                field = PropsField(annotated_type=annotation, default=value)\n            else:\n                # Field is already a PropsField, update annotation\n                field = PropsField(\n                    annotated_type=annotation,\n                    default=value.default,\n                    default_factory=value.default_factory,\n                )\n\n            own_fields[key] = field\n\n        return own_fields\n\n    @classmethod\n    def _create_field(\n        cls,\n        annotated_type: Any,\n        default: Any = MISSING,\n        default_factory: Callable[[], Any] | None = None,\n    ) -> PropsField:\n        return PropsField(\n            annotated_type=annotated_type,\n            default=default,\n            default_factory=default_factory,\n        )\n\n    @classmethod\n    def _finalize_fields(\n        cls,\n        namespace: dict[str, Any],\n        inherited_fields: dict[str, PropsField],\n        own_fields: dict[str, PropsField],\n    ) -> None:\n        # Call parent implementation\n        super()._finalize_fields(namespace, inherited_fields, own_fields)\n\n        # Add Pydantic compatibility\n        namespace[\"__fields__\"] = namespace[\"_fields\"]\n\n\nclass PropsBase(metaclass=PropsBaseMeta):\n    \"\"\"Base for a class containing props that can be serialized as a JS object.\"\"\"\n\n    def __init__(self, **kwargs):\n        \"\"\"Initialize the props with field values.\n\n        Args:\n            **kwargs: The field values to set.\n        \"\"\"\n        # Set field values from kwargs with nested object instantiation\n        for key, value in kwargs.items():\n            field_info = self.get_fields().get(key)\n            if field_info:\n                field_type = field_info.annotated_type\n\n                # Check if this field expects a specific Props type and we got a dict\n                if isinstance(value, dict):\n                    props_class = _get_props_subclass(field_type)\n                    if props_class is not None:\n                        value = props_class(**value)\n\n                # Check if this field expects a list of Props and we got a list of dicts\n                elif isinstance(value, list):\n                    element_type = _find_props_in_list_annotation(field_type)\n                    if element_type is not None:\n                        # Convert each dict in the list to the appropriate Props class\n                        value = [\n                            element_type(**item) if isinstance(item, dict) else item\n                            for item in value\n                        ]\n\n            setattr(self, key, value)\n\n        # Set default values for fields not provided\n        for field_name, field in self.get_fields().items():\n            if field_name not in kwargs:\n                if field.default is not MISSING:\n                    setattr(self, field_name, field.default)\n                elif field.default_factory is not None:\n                    setattr(self, field_name, field.default_factory())\n                # Note: Fields with no default and no factory remain unset (required fields)\n\n        # Convert EventHandler to EventChain\n        args_specs = args_specs_from_fields(self.get_fields())\n        for handler_name, args_spec in args_specs.items():\n            if (handler := getattr(self, handler_name, None)) is not None:\n                setattr(\n                    self,\n                    handler_name,\n                    EventChain.create(\n                        value=handler,\n                        args_spec=args_spec,\n                        key=handler_name,\n                    ),\n                )\n\n    @classmethod\n    def get_fields(cls) -> dict[str, Any]:\n        \"\"\"Get the fields of the object.\n\n        Returns:\n            The fields of the object.\n        \"\"\"\n        return getattr(cls, \"_fields\", {})\n\n    def json(self) -> str:\n        \"\"\"Convert the object to a json-like string.\n\n        Vars will be unwrapped so they can represent actual JS var names and functions.\n\n        Keys will be converted to camelCase.\n\n        Returns:\n            The object as a Javascript Object literal.\n        \"\"\"\n        return LiteralObjectVar.create({\n            format.to_camel_case(key): value for key, value in self.dict().items()\n        }).json()\n\n    def dict(\n        self,\n        exclude_none: bool = True,\n        include: set[str] | None = None,\n        exclude: set[str] | None = None,\n        **kwargs,\n    ):\n        \"\"\"Convert the object to a dictionary.\n\n        Keys will be converted to camelCase.\n        By default, None values are excluded (exclude_none=True).\n\n        Args:\n            exclude_none: Whether to exclude None values.\n            include: Fields to include in the output.\n            exclude: Fields to exclude from the output.\n            **kwargs: Additional keyword arguments (for compatibility).\n\n        Returns:\n            The object as a dictionary.\n        \"\"\"\n        result = {}\n\n        for field_name in self.get_fields():\n            if hasattr(self, field_name):\n                value = getattr(self, field_name)\n\n                # Apply include/exclude filters\n                if include is not None and field_name not in include:\n                    continue\n                if exclude is not None and field_name in exclude:\n                    continue\n\n                # Apply exclude_none logic\n                if exclude_none and value is None:\n                    continue\n\n                # Recursively convert nested structures\n                value = self._convert_to_camel_case(\n                    value, exclude_none, include, exclude\n                )\n\n                # Convert key to camelCase\n                camel_key = format.to_camel_case(field_name)\n                result[camel_key] = value\n\n        return result\n\n    def _convert_to_camel_case(\n        self,\n        value: Any,\n        exclude_none: bool = True,\n        include: set[str] | None = None,\n        exclude: set[str] | None = None,\n    ) -> Any:\n        \"\"\"Recursively convert nested dictionaries and lists to camelCase.\n\n        Args:\n            value: The value to convert.\n            exclude_none: Whether to exclude None values.\n            include: Fields to include in the output.\n            exclude: Fields to exclude from the output.\n\n        Returns:\n            The converted value with camelCase keys.\n        \"\"\"\n        if isinstance(value, PropsBase):\n            # Convert nested PropsBase objects\n            return value.dict(\n                exclude_none=exclude_none, include=include, exclude=exclude\n            )\n        if isinstance(value, dict):\n            # Convert dictionary keys to camelCase\n            return {\n                format.to_camel_case(k): self._convert_to_camel_case(\n                    v, exclude_none, include, exclude\n                )\n                for k, v in value.items()\n                if not (exclude_none and v is None)\n            }\n        if isinstance(value, (list, tuple)):\n            # Convert list/tuple items recursively\n            return [\n                self._convert_to_camel_case(item, exclude_none, include, exclude)\n                for item in value\n            ]\n        # Return primitive values as-is\n        return value\n\n\n@serializer(to=dict)\ndef serialize_props_base(value: PropsBase) -> dict:\n    \"\"\"Serialize a PropsBase instance.\n\n    Unlike serialize_base, this preserves callables (lambdas) since they're\n    needed for AG Grid and other components that process them on the frontend.\n\n    Args:\n        value: The PropsBase instance to serialize.\n\n    Returns:\n        Dictionary representation of the PropsBase instance.\n    \"\"\"\n    return value.dict()\n\n\nclass NoExtrasAllowedProps(PropsBase):\n    \"\"\"A class that holds props to be passed or applied to a component with no extra props allowed.\"\"\"\n\n    def __init__(self, component_name: str | None = None, **kwargs):\n        \"\"\"Initialize the props with validation.\n\n        Args:\n            component_name: The custom name of the component.\n            kwargs: Kwargs to initialize the props.\n\n        Raises:\n            InvalidPropValueError: If invalid props are passed on instantiation.\n        \"\"\"\n        component_name = component_name or type(self).__name__\n\n        # Validate fields BEFORE setting them\n        known_fields = set(self.__class__.get_fields().keys())\n        provided_fields = set(kwargs.keys())\n        invalid_fields = provided_fields - known_fields\n\n        if invalid_fields:\n            invalid_fields_str = \", \".join(invalid_fields)\n            supported_props_str = \", \".join(f'\"{field}\"' for field in known_fields)\n            msg = f\"Invalid prop(s) {invalid_fields_str} for {component_name!r}. Supported props are {supported_props_str}\"\n            raise InvalidPropValueError(msg)\n\n        # Use parent class initialization after validation\n        super().__init__(**kwargs)\n"
  },
  {
    "path": "reflex/components/radix/__init__.py",
    "content": "\"\"\"Namespace for components provided by @radix-ui packages.\"\"\"\n\nfrom __future__ import annotations\n\nfrom reflex import RADIX_MAPPING\nfrom reflex.utils import lazy_loader\n\n_SUBMODULES: set[str] = {\"themes\", \"primitives\"}\n\n_SUBMOD_ATTRS: dict[str, list[str]] = {\n    \"\".join(k.split(\"components.radix.\")[-1]): v for k, v in RADIX_MAPPING.items()\n}\n__getattr__, __dir__, __all__ = lazy_loader.attach(\n    __name__,\n    submodules=_SUBMODULES,\n    submod_attrs=_SUBMOD_ATTRS,\n)\n"
  },
  {
    "path": "reflex/components/radix/primitives/__init__.py",
    "content": "\"\"\"Radix primitive components (https://www.radix-ui.com/primitives).\"\"\"\n\nfrom __future__ import annotations\n\nfrom reflex import RADIX_PRIMITIVES_MAPPING\nfrom reflex.utils import lazy_loader\n\n_SUBMOD_ATTRS: dict[str, list[str]] = {\n    \"\".join(k.split(\"components.radix.primitives.\")[-1]): v\n    for k, v in RADIX_PRIMITIVES_MAPPING.items()\n} | {\"dialog\": [\"dialog\"]}\n\n__getattr__, __dir__, __all__ = lazy_loader.attach(\n    __name__,\n    submod_attrs=_SUBMOD_ATTRS,\n)\n"
  },
  {
    "path": "reflex/components/radix/primitives/accordion.py",
    "content": "\"\"\"Radix accordion components.\"\"\"\n\nfrom __future__ import annotations\n\nfrom collections.abc import Sequence\nfrom typing import Any, ClassVar, Literal\n\nfrom reflex.components.component import Component, ComponentNamespace\nfrom reflex.components.core.colors import color\nfrom reflex.components.core.cond import cond\nfrom reflex.components.lucide.icon import Icon\nfrom reflex.components.radix.primitives.base import RadixPrimitiveComponent\nfrom reflex.components.radix.themes.base import LiteralAccentColor, LiteralRadius\nfrom reflex.constants.compiler import MemoizationMode\nfrom reflex.event import EventHandler\nfrom reflex.style import Style\nfrom reflex.vars import get_uuid_string_var\nfrom reflex.vars.base import LiteralVar, Var\n\nLiteralAccordionType = Literal[\"single\", \"multiple\"]\nLiteralAccordionDir = Literal[\"ltr\", \"rtl\"]\nLiteralAccordionOrientation = Literal[\"vertical\", \"horizontal\"]\nLiteralAccordionVariant = Literal[\"classic\", \"soft\", \"surface\", \"outline\", \"ghost\"]\n\nDEFAULT_ANIMATION_DURATION = 250\nDEFAULT_ANIMATION_EASING = \"cubic-bezier(0.87, 0, 0.13, 1)\"\n\n\ndef _inherited_variant_selector(\n    variant: Var[LiteralAccordionVariant] | LiteralAccordionVariant,\n    *selectors: str,\n) -> str:\n    \"\"\"Create a multi CSS selector for targeting variant against the given selectors.\n\n    Args:\n        variant: The variant to target.\n        selectors: The selectors to apply the variant to (default &)\n\n    Returns:\n        A CSS selector that is more specific on elements that directly set the variant.\n    \"\"\"\n    if not selectors:\n        selectors = (\"&\",)\n    # Prefer the `data-variant` that is set directly on the selector,\n    # but also inherit the `data-variant` from any parent element.\n    return \", \".join([\n        f\"{selector}[data-variant='{variant}'], *:where([data-variant='{variant}']) {selector}\"\n        for selector in selectors\n    ])\n\n\nclass AccordionComponent(RadixPrimitiveComponent):\n    \"\"\"Base class for all @radix-ui/accordion components.\"\"\"\n\n    library = \"@radix-ui/react-accordion@1.2.12\"\n\n    # The color scheme of the component.\n    color_scheme: Var[LiteralAccentColor]\n\n    # The variant of the component.\n    variant: Var[LiteralAccordionVariant]\n\n    def add_style(self):\n        \"\"\"Add style to the component.\"\"\"\n        if self.color_scheme is not None:\n            self.custom_attrs[\"data-accent-color\"] = self.color_scheme\n        if self.variant is not None:\n            self.custom_attrs[\"data-variant\"] = self.variant\n\n    def _exclude_props(self) -> list[str]:\n        return [\"color_scheme\", \"variant\"]\n\n\ndef on_value_change(value: Var[str | list[str]]) -> tuple[Var[str | list[str]]]:\n    \"\"\"Handle the on_value_change event.\n\n    Args:\n        value: The value of the event.\n\n    Returns:\n        The value of the event.\n    \"\"\"\n    return (value,)\n\n\nclass AccordionRoot(AccordionComponent):\n    \"\"\"An accordion component.\"\"\"\n\n    tag = \"Root\"\n\n    alias = \"RadixAccordionRoot\"\n\n    # The type of accordion (single or multiple).\n    type: Var[LiteralAccordionType]\n\n    # The value of the item to expand.\n    value: Var[str | Sequence[str]]\n\n    # The default value of the item to expand.\n    default_value: Var[str | Sequence[str]]\n\n    # Whether or not the accordion is collapsible.\n    collapsible: Var[bool]\n\n    # Whether or not the accordion is disabled.\n    disabled: Var[bool]\n\n    # The reading direction of the accordion when applicable.\n    dir: Var[LiteralAccordionDir]\n\n    # The orientation of the accordion.\n    orientation: Var[LiteralAccordionOrientation]\n\n    # The radius of the accordion corners.\n    radius: Var[LiteralRadius]\n\n    # The time in milliseconds to animate open and close\n    duration: Var[int] = LiteralVar.create(DEFAULT_ANIMATION_DURATION)\n\n    # The easing function to use for the animation.\n    easing: Var[str] = LiteralVar.create(DEFAULT_ANIMATION_EASING)\n\n    # Whether to show divider lines between items.\n    show_dividers: Var[bool]\n\n    _valid_children: ClassVar[list[str]] = [\"AccordionItem\"]\n\n    # Fired when the opened the accordions changes.\n    on_value_change: EventHandler[on_value_change]\n\n    def _exclude_props(self) -> list[str]:\n        return [\n            *super()._exclude_props(),\n            \"radius\",\n            \"duration\",\n            \"easing\",\n            \"show_dividers\",\n        ]\n\n    def add_style(self):\n        \"\"\"Add style to the component.\n\n        Returns:\n            The style of the component.\n        \"\"\"\n        if self.radius is not None:\n            self.custom_attrs[\"data-radius\"] = self.radius\n        if self.variant is None:\n            # The default variant is classic\n            self.custom_attrs[\"data-variant\"] = \"classic\"\n\n        style = {\n            \"border_radius\": \"var(--radius-4)\",\n            \"box_shadow\": f\"0 2px 10px {color('black', 1, alpha=True)}\",\n            \"&[data-variant='classic']\": {\n                \"background_color\": color(\"accent\", 9),\n                \"box_shadow\": f\"0 2px 10px {color('black', 4, alpha=True)}\",\n            },\n            \"&[data-variant='soft']\": {\n                \"background_color\": color(\"accent\", 3),\n            },\n            \"&[data-variant='outline']\": {\n                \"border\": f\"1px solid {color('accent', 6)}\",\n            },\n            \"&[data-variant='surface']\": {\n                \"border\": f\"1px solid {color('accent', 6)}\",\n                \"background_color\": \"var(--accent-surface)\",\n            },\n            \"&[data-variant='ghost']\": {\n                \"background_color\": \"none\",\n                \"box_shadow\": \"None\",\n            },\n            \"--animation-duration\": f\"{self.duration}ms\",\n            \"--animation-easing\": self.easing,\n        }\n        if self.show_dividers is not None:\n            style[\"--divider-px\"] = cond(self.show_dividers, \"1px\", \"0\")\n        else:\n            style[\"&[data-variant='outline']\"][\"--divider-px\"] = \"1px\"\n            style[\"&[data-variant='surface']\"][\"--divider-px\"] = \"1px\"\n        return Style(style)\n\n\nclass AccordionItem(AccordionComponent):\n    \"\"\"An accordion component.\"\"\"\n\n    tag = \"Item\"\n\n    alias = \"RadixAccordionItem\"\n\n    # A unique identifier for the item.\n    value: Var[str]\n\n    # When true, prevents the user from interacting with the item.\n    disabled: Var[bool]\n\n    # The header of the accordion item.\n    header: Var[Component | str]\n\n    # The content of the accordion item.\n    content: Var[Component | str | None] = Var.create(None)\n\n    _valid_children: ClassVar[list[str]] = [\n        \"AccordionHeader\",\n        \"AccordionTrigger\",\n        \"AccordionContent\",\n    ]\n\n    _valid_parents: ClassVar[list[str]] = [\"AccordionRoot\"]\n\n    @classmethod\n    def create(\n        cls,\n        *children,\n        **props,\n    ) -> Component:\n        \"\"\"Create an accordion item.\n\n        Args:\n            *children: The list of children to use if header and content are not provided.\n            **props: Additional properties to apply to the accordion item.\n\n        Returns:\n            The accordion item.\n        \"\"\"\n        header = props.pop(\"header\", None)\n        content = props.pop(\"content\", None)\n\n        # The item requires a value to toggle (use a random unique name if not provided).\n        value = props.pop(\"value\", get_uuid_string_var())\n\n        if \"AccordionItem\" not in (\n            cls_name := props.pop(\"class_name\", \"AccordionItem\")\n        ):\n            cls_name = f\"{cls_name} AccordionItem\"\n\n        color_scheme = props.get(\"color_scheme\")\n        variant = props.get(\"variant\")\n\n        if (header is not None) and (content is not None):\n            children = [\n                AccordionHeader.create(\n                    AccordionTrigger.create(\n                        header,\n                        AccordionIcon.create(\n                            color_scheme=color_scheme,\n                            variant=variant,\n                        ),\n                        color_scheme=color_scheme,\n                        variant=variant,\n                    ),\n                    color_scheme=color_scheme,\n                    variant=variant,\n                ),\n                AccordionContent.create(\n                    content,\n                    color_scheme=color_scheme,\n                    variant=variant,\n                ),\n            ]\n\n        return super().create(*children, value=value, **props, class_name=cls_name)\n\n    def add_style(self) -> dict[str, Any] | None:\n        \"\"\"Add style to the component.\n\n        Returns:\n            The style of the component.\n        \"\"\"\n        divider_style = f\"var(--divider-px) solid {color('gray', 6, alpha=True)}\"\n        return {\n            \"overflow\": \"hidden\",\n            \"width\": \"100%\",\n            \"margin_top\": \"1px\",\n            \"border_top\": divider_style,\n            \"&:first-child\": {\n                \"margin_top\": 0,\n                \"border_top\": 0,\n                \"border_top_left_radius\": \"var(--radius-4)\",\n                \"border_top_right_radius\": \"var(--radius-4)\",\n            },\n            \"&:last-child\": {\n                \"border_bottom_left_radius\": \"var(--radius-4)\",\n                \"border_bottom_right_radius\": \"var(--radius-4)\",\n            },\n            \"&:focus-within\": {\n                \"position\": \"relative\",\n                \"z_index\": 1,\n            },\n            _inherited_variant_selector(\"ghost\", \"&:first-child\"): {\n                \"border_radius\": 0,\n                \"border_top\": divider_style,\n            },\n            _inherited_variant_selector(\"ghost\", \"&:last-child\"): {\n                \"border_radius\": 0,\n                \"border_bottom\": divider_style,\n            },\n        }\n\n    def _exclude_props(self) -> list[str]:\n        return [\"header\", \"content\"]\n\n\nclass AccordionHeader(AccordionComponent):\n    \"\"\"An accordion component.\"\"\"\n\n    tag = \"Header\"\n\n    alias = \"RadixAccordionHeader\"\n\n    @classmethod\n    def create(cls, *children, **props) -> Component:\n        \"\"\"Create the Accordion header component.\n\n        Args:\n            *children: The children of the component.\n            **props: The properties of the component.\n\n        Returns:\n            The Accordion header Component.\n        \"\"\"\n        if \"AccordionHeader\" not in (\n            cls_name := props.pop(\"class_name\", \"AccordionHeader\")\n        ):\n            cls_name = f\"{cls_name} AccordionHeader\"\n\n        return super().create(*children, class_name=cls_name, **props)\n\n    def add_style(self) -> dict[str, Any] | None:\n        \"\"\"Add style to the component.\n\n        Returns:\n            The style of the component.\n        \"\"\"\n        return {\n            \"display\": \"flex\",\n            # Reset some values to ensure consistent styling without tailwind reset.\n            \"margin\": \"0\",\n        }\n\n\nclass AccordionTrigger(AccordionComponent):\n    \"\"\"An accordion component.\"\"\"\n\n    tag = \"Trigger\"\n\n    alias = \"RadixAccordionTrigger\"\n\n    _memoization_mode = MemoizationMode(recursive=False)\n\n    @classmethod\n    def create(cls, *children, **props) -> Component:\n        \"\"\"Create the Accordion trigger component.\n\n        Args:\n            *children: The children of the component.\n            **props: The properties of the component.\n\n        Returns:\n            The Accordion trigger Component.\n        \"\"\"\n        if \"AccordionTrigger\" not in (\n            cls_name := props.pop(\"class_name\", \"AccordionTrigger\")\n        ):\n            cls_name = f\"{cls_name} AccordionTrigger\"\n\n        return super().create(*children, class_name=cls_name, **props)\n\n    def add_style(self) -> dict[str, Any] | None:\n        \"\"\"Add style to the component.\n\n        Returns:\n            The style of the component.\n        \"\"\"\n        return {\n            \"color\": color(\"accent\", 11),\n            \"font_size\": \"1.1em\",\n            \"line_height\": 1,\n            \"justify_content\": \"space-between\",\n            \"align_items\": \"center\",\n            \"flex\": 1,\n            \"display\": \"flex\",\n            \"padding\": \"var(--space-3) var(--space-4)\",\n            \"width\": \"100%\",\n            \"box_shadow\": f\"0 var(--divider-px) 0 {color('gray', 6, alpha=True)}\",\n            \"&[data-state='open'] > .AccordionChevron\": {\n                \"transform\": \"rotate(180deg)\",\n            },\n            \"&:hover\": {\n                \"background_color\": color(\"accent\", 4),\n            },\n            \"& > .AccordionChevron\": {\n                \"transition\": \"transform var(--animation-duration) var(--animation-easing)\",\n            },\n            _inherited_variant_selector(\"classic\"): {\n                \"color\": \"var(--accent-contrast)\",\n                \"&:hover\": {\n                    \"background_color\": color(\"accent\", 10),\n                },\n                \"& > .AccordionChevron\": {\n                    \"color\": \"var(--accent-contrast)\",\n                },\n            },\n            # Reset some values to ensure consistent styling without tailwind reset.\n            \"background\": \"none\",\n            \"border\": \"none\",\n        }\n\n\nclass AccordionIcon(Icon):\n    \"\"\"An accordion icon component.\"\"\"\n\n    @classmethod\n    def create(cls, *children, **props) -> Component:\n        \"\"\"Create the Accordion icon component.\n\n        Args:\n            *children: The children of the component.\n            **props: The properties of the component.\n\n        Returns:\n            The Accordion icon Component.\n        \"\"\"\n        if \"AccordionChevron\" not in (\n            cls_name := props.pop(\"class_name\", \"AccordionChevron\")\n        ):\n            cls_name = f\"{cls_name} AccordionChevron\"\n\n        return super().create(tag=\"chevron_down\", class_name=cls_name, **props)\n\n\nSLIDE_DOWN = Var(\n    r'keyframes({ from: { height: 0 }, to: { height: \"var(--radix-accordion-content-height)\" } })'\n)\nSLIDE_UP = Var(\n    r'keyframes({ from: { height: \"var(--radix-accordion-content-height)\" }, to: { height: 0 } })'\n)\n\n\nclass AccordionContent(AccordionComponent):\n    \"\"\"An accordion component.\"\"\"\n\n    tag = \"Content\"\n\n    alias = \"RadixAccordionContent\"\n\n    def add_imports(self) -> dict:\n        \"\"\"Add imports to the component.\n\n        Returns:\n            The imports of the component.\n        \"\"\"\n        return {\"@emotion/react\": \"keyframes\"}\n\n    @classmethod\n    def create(cls, *children, **props) -> Component:\n        \"\"\"Create the Accordion content component.\n\n        Args:\n            *children: The children of the component.\n            **props: The properties of the component.\n\n        Returns:\n            The Accordion content Component.\n        \"\"\"\n        if \"AccordionContent\" not in (\n            cls_name := props.pop(\"class_name\", \"AccordionContent\")\n        ):\n            cls_name = f\"{cls_name} AccordionContent\"\n\n        return super().create(*children, class_name=cls_name, **props)\n\n    def add_style(self) -> dict[str, Any] | None:\n        \"\"\"Add style to the component.\n\n        Returns:\n            The style of the component.\n        \"\"\"\n        slide_down = SLIDE_DOWN.to(str) + Var.create(\n            \" var(--animation-duration) var(--animation-easing)\",\n        )\n\n        slide_up = SLIDE_UP.to(str) + Var.create(\n            \" var(--animation-duration) var(--animation-easing)\",\n        )\n\n        return {\n            \"overflow\": \"hidden\",\n            \"color\": color(\"accent\", 11),\n            \"padding_x\": \"var(--space-4)\",\n            # Apply before and after content to avoid height animation jank.\n            \"&:before, &:after\": {\n                \"content\": \"' '\",\n                \"display\": \"block\",\n                \"height\": \"var(--space-3)\",\n            },\n            \"&[data-state='open']\": {\"animation\": slide_down},\n            \"&[data-state='closed']\": {\"animation\": slide_up},\n            _inherited_variant_selector(\"classic\"): {\n                \"color\": \"var(--accent-contrast)\",\n            },\n        }\n\n\nclass Accordion(ComponentNamespace):\n    \"\"\"Accordion component.\"\"\"\n\n    content = staticmethod(AccordionContent.create)\n    header = staticmethod(AccordionHeader.create)\n    item = staticmethod(AccordionItem.create)\n    icon = staticmethod(AccordionIcon.create)\n    root = staticmethod(AccordionRoot.create)\n    trigger = staticmethod(AccordionTrigger.create)\n\n\naccordion = Accordion()\n"
  },
  {
    "path": "reflex/components/radix/primitives/base.py",
    "content": "\"\"\"The base component for Radix primitives.\"\"\"\n\nfrom typing import Any\n\nfrom reflex.components.component import Component\nfrom reflex.components.tags.tag import Tag\nfrom reflex.utils import format\nfrom reflex.vars.base import Var\n\n\nclass RadixPrimitiveComponent(Component):\n    \"\"\"Basic component for radix Primitives.\"\"\"\n\n    # Change the default rendered element for the one passed as a child.\n    as_child: Var[bool]\n\n\nclass RadixPrimitiveComponentWithClassName(RadixPrimitiveComponent):\n    \"\"\"Basic component for radix Primitives with a class name prop.\"\"\"\n\n    def _render(self) -> Tag:\n        return (\n            super()\n            ._render()\n            .add_props(\n                class_name=f\"{format.to_title_case(self.tag or '')} {self.class_name or ''}\"\n            )\n        )\n\n\nclass RadixPrimitiveTriggerComponent(RadixPrimitiveComponent):\n    \"\"\"Base class for Trigger, Close, Cancel, and Accept components.\n\n    These components trigger some action in an overlay component that depends on the\n    on_click event, and thus if a child is provided and has on_click specified, it\n    will overtake the internal action, unless it is wrapped in some inert component,\n    in this case, a Flex.\n    \"\"\"\n\n    @classmethod\n    def create(cls, *children: Any, **props: Any) -> Component:\n        \"\"\"Create a new RadixPrimitiveTriggerComponent instance.\n\n        Args:\n            children: The children of the component.\n            props: The properties of the component.\n\n        Returns:\n            The new RadixPrimitiveTriggerComponent instance.\n        \"\"\"\n        from reflex.components.el.elements.typography import Div\n\n        for child in children:\n            if \"on_click\" in getattr(child, \"event_triggers\", {}):\n                children = (Div.create(*children),)\n                break\n        return super().create(*children, **props)\n"
  },
  {
    "path": "reflex/components/radix/primitives/dialog.py",
    "content": "\"\"\"Interactive components provided by @radix-ui/react-dialog.\"\"\"\n\nfrom typing import Any, ClassVar\n\nfrom reflex.components.component import ComponentNamespace\nfrom reflex.components.el import elements\nfrom reflex.constants.compiler import MemoizationMode\nfrom reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec\nfrom reflex.vars.base import Var\n\nfrom .base import RadixPrimitiveComponent, RadixPrimitiveTriggerComponent\n\n\nclass DialogElement(RadixPrimitiveComponent):\n    \"\"\"Base class for all @radix-ui/react-dialog components.\"\"\"\n\n    library = \"@radix-ui/react-dialog@1.1.15\"\n\n\nclass DialogRoot(DialogElement):\n    \"\"\"Root component for Dialog.\"\"\"\n\n    tag = \"Root\"\n    alias = \"RadixPrimitiveDialogRoot\"\n\n    # The controlled open state of the dialog.\n    open: Var[bool]\n\n    # Fired when the open state changes.\n    on_open_change: EventHandler[passthrough_event_spec(bool)]\n\n    # The open state of the dialog when it is initially rendered. Use when you do not need to control its open state.\n    default_open: Var[bool]\n\n    # The modality of the dialog. When set to true, interaction with outside elements will be disabled and only dialog content will be visible to screen readers.\n    modal: Var[bool]\n\n    _valid_children: ClassVar[list[str]] = [\n        \"DialogTrigger\",\n        \"DialogPortal\",\n    ]\n\n\nclass DialogPortal(DialogElement):\n    \"\"\"Portal component for Dialog.\"\"\"\n\n    tag = \"Portal\"\n    alias = \"RadixPrimitiveDialogPortal\"\n\n    # Used to force mounting when more control is needed. Useful when controlling animation with React animation libraries. If used on this part, it will be inherited by Dialog.Overlay and Dialog.Content.\n    force_mount: Var[bool]\n\n    # Specify a container element to portal the content into.\n    container: Var[Any]\n\n    _valid_parents: ClassVar[list[str]] = [\"DialogRoot\"]\n\n\nclass DialogOverlay(DialogElement):\n    \"\"\"A layer that covers the inert portion of the view when the dialog is open.\"\"\"\n\n    tag = \"Overlay\"\n    alias = \"RadixPrimitiveDialogOverlay\"\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior.\n    as_child: Var[bool]\n\n    # Used to force mounting when more control is needed. Useful when controlling animation with React animation libraries. It inherits from Dialog.Portal.\n    force_mount: Var[bool]\n\n    _valid_parents: ClassVar[list[str]] = [\"DialogPortal\"]\n\n\nclass DialogTrigger(DialogElement, RadixPrimitiveTriggerComponent):\n    \"\"\"Trigger an action or event, to open a Dialog modal.\"\"\"\n\n    tag = \"Trigger\"\n    alias = \"RadixPrimitiveDialogTrigger\"\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior.\n    as_child: Var[bool]\n\n    _memoization_mode = MemoizationMode(recursive=False)\n\n    _valid_parents: ClassVar[list[str]] = [\"DialogRoot\"]\n\n\nclass DialogContent(elements.Div, DialogElement):\n    \"\"\"Content component to display inside a Dialog modal.\"\"\"\n\n    tag = \"Content\"\n    alias = \"RadixPrimitiveDialogContent\"\n\n    # Used to force mounting when more control is needed. Useful when controlling animation with React animation libraries. It inherits from Dialog.Portal.\n    force_mount: Var[bool]\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior.\n    as_child: Var[bool]\n\n    # Fired when the dialog is opened.\n    on_open_auto_focus: EventHandler[no_args_event_spec]\n\n    # Fired when the dialog is closed.\n    on_close_auto_focus: EventHandler[no_args_event_spec]\n\n    # Fired when the escape key is pressed.\n    on_escape_key_down: EventHandler[no_args_event_spec]\n\n    # Fired when the pointer is down outside the dialog.\n    on_pointer_down_outside: EventHandler[no_args_event_spec]\n\n    # Fired when the pointer interacts outside the dialog.\n    on_interact_outside: EventHandler[no_args_event_spec]\n\n    _valid_parents: ClassVar[list[str]] = [\"DialogPortal\"]\n\n\nclass DialogTitle(DialogElement):\n    \"\"\"Title component to display inside a Dialog modal.\"\"\"\n\n    tag = \"Title\"\n    alias = \"RadixPrimitiveDialogTitle\"\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior.\n    as_child: Var[bool]\n\n\nclass DialogDescription(DialogElement):\n    \"\"\"Description component to display inside a Dialog modal.\"\"\"\n\n    tag = \"Description\"\n    alias = \"RadixPrimitiveDialogDescription\"\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior.\n    as_child: Var[bool]\n\n\nclass DialogClose(DialogElement, RadixPrimitiveTriggerComponent):\n    \"\"\"Close button component to close an open Dialog modal.\"\"\"\n\n    tag = \"Close\"\n    alias = \"RadixPrimitiveDialogClose\"\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior.\n    as_child: Var[bool]\n\n\nclass Dialog(ComponentNamespace):\n    \"\"\"Dialog components namespace.\"\"\"\n\n    root = __call__ = staticmethod(DialogRoot.create)\n    portal = staticmethod(DialogPortal.create)\n    trigger = staticmethod(DialogTrigger.create)\n    title = staticmethod(DialogTitle.create)\n    overlay = staticmethod(DialogOverlay.create)\n    content = staticmethod(DialogContent.create)\n    description = staticmethod(DialogDescription.create)\n    close = staticmethod(DialogClose.create)\n\n\ndialog = Dialog()\n"
  },
  {
    "path": "reflex/components/radix/primitives/drawer.py",
    "content": "\"\"\"Drawer components based on Radix primitives.\"\"\"\n\n# Based on Vaul: https://github.com/emilkowalski/vaul\n# Style based on https://ui.shadcn.com/docs/components/drawer\nfrom __future__ import annotations\n\nfrom collections.abc import Sequence\nfrom typing import Any, Literal\n\nfrom reflex.components.component import Component, ComponentNamespace\nfrom reflex.components.radix.primitives.base import RadixPrimitiveComponent\nfrom reflex.components.radix.themes.base import Theme\nfrom reflex.components.radix.themes.layout.flex import Flex\nfrom reflex.constants.compiler import MemoizationMode\nfrom reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec\nfrom reflex.vars.base import Var\n\n\nclass DrawerComponent(RadixPrimitiveComponent):\n    \"\"\"A Drawer component.\"\"\"\n\n    library = \"vaul@1.1.2\"\n\n    lib_dependencies: list[str] = [\"@radix-ui/react-dialog@1.1.15\"]\n\n\nLiteralDirectionType = Literal[\"top\", \"bottom\", \"left\", \"right\"]\n\n\nclass DrawerRoot(DrawerComponent):\n    \"\"\"The Root component of a Drawer, contains all parts of a drawer.\"\"\"\n\n    tag = \"Drawer.Root\"\n\n    alias = \"Vaul\" + tag\n\n    # The open state of the drawer when it is initially rendered. Use when you do not need to control its open state.\n    default_open: Var[bool]\n\n    # Whether the drawer is open or not.\n    open: Var[bool]\n\n    # Fires when the drawer is opened or closed.\n    on_open_change: EventHandler[passthrough_event_spec(bool)]\n\n    # When `False`, it allows interaction with elements outside of the drawer without closing it. Defaults to `True`.\n    modal: Var[bool]\n\n    # Direction of the drawer. This adjusts the animations and the drag direction. Defaults to `\"bottom\"`\n    direction: Var[LiteralDirectionType]\n\n    # Gets triggered after the open or close animation ends, it receives an open argument with the open state of the drawer by the time the function was triggered.\n    on_animation_end: EventHandler[passthrough_event_spec(bool)]\n\n    # When `False`, dragging, clicking outside, pressing esc, etc. will not close the drawer. Use this in combination with the open prop, otherwise you won't be able to open/close the drawer.\n    dismissible: Var[bool]\n\n    # When `True`, dragging will only be possible by the handle.\n    handle_only: Var[bool]\n\n    # Array of numbers from 0 to 100 that corresponds to % of the screen a given snap point should take up. Should go from least visible. Also Accept px values, which doesn't take screen height into account.\n    snap_points: Sequence[str | float] | None\n\n    # Index of a snapPoint from which the overlay fade should be applied. Defaults to the last snap point.\n    fade_from_index: Var[int]\n\n    # Duration for which the drawer is not draggable after scrolling content inside of the drawer. Defaults to 500ms\n    scroll_lock_timeout: Var[int]\n\n    # When `True`, it prevents scroll restoration. Defaults to `True`.\n    prevent_scroll_restoration: Var[bool]\n\n    # Enable background scaling, it requires container element with `vaul-drawer-wrapper` attribute to scale its background.\n    should_scale_background: Var[bool]\n\n    # Number between 0 and 1 that determines when the drawer should be closed.\n    close_threshold: Var[float]\n\n\nclass DrawerTrigger(DrawerComponent):\n    \"\"\"The button that opens the dialog.\"\"\"\n\n    tag = \"Drawer.Trigger\"\n\n    alias = \"Vaul\" + tag\n\n    # Defaults to true, if the first child acts as the trigger.\n    as_child: Var[bool] = Var.create(True)\n\n    _memoization_mode = MemoizationMode(recursive=False)\n\n    @classmethod\n    def create(cls, *children: Any, **props: Any) -> Component:\n        \"\"\"Create a new DrawerTrigger instance.\n\n        Args:\n            *children: The children of the element.\n            **props: The properties of the element.\n\n        Returns:\n            The new DrawerTrigger instance.\n        \"\"\"\n        for child in children:\n            if \"on_click\" in getattr(child, \"event_triggers\", {}):\n                children = (Flex.create(*children),)\n                break\n        return super().create(*children, **props)\n\n\nclass DrawerPortal(DrawerComponent):\n    \"\"\"Portals your drawer into the body.\"\"\"\n\n    tag = \"Drawer.Portal\"\n\n    alias = \"Vaul\" + tag\n\n\n# Based on https://www.radix-ui.com/primitives/docs/components/dialog#content\nclass DrawerContent(DrawerComponent):\n    \"\"\"Content that should be rendered in the drawer.\"\"\"\n\n    tag = \"Drawer.Content\"\n\n    alias = \"Vaul\" + tag\n\n    # Style set partially based on the source code at https://ui.shadcn.com/docs/components/drawer\n    def add_style(self) -> dict:\n        \"\"\"Get the style for the component.\n\n        Returns:\n            The dictionary of the component style as value and the style notation as key.\n        \"\"\"\n        return {\n            \"left\": \"0\",\n            \"right\": \"0\",\n            \"bottom\": \"0\",\n            \"top\": \"0\",\n            \"position\": \"fixed\",\n            \"z_index\": 50,\n            \"display\": \"flex\",\n        }\n\n    # Fired when the drawer content is opened.\n    on_open_auto_focus: EventHandler[no_args_event_spec]\n\n    # Fired when the drawer content is closed.\n    on_close_auto_focus: EventHandler[no_args_event_spec]\n\n    # Fired when the escape key is pressed.\n    on_escape_key_down: EventHandler[no_args_event_spec]\n\n    # Fired when the pointer is down outside the drawer content.\n    on_pointer_down_outside: EventHandler[no_args_event_spec]\n\n    # Fired when interacting outside the drawer content.\n    on_interact_outside: EventHandler[no_args_event_spec]\n\n    @classmethod\n    def create(cls, *children, **props):\n        \"\"\"Create a Drawer Content.\n         We wrap the Drawer content in an `rx.theme` to make radix themes definitions available to\n         rendered div in the DOM. This is because Vaul Drawer injects the Drawer overlay content in a sibling\n         div to the root div rendered by radix which contains styling definitions. Wrapping in `rx.theme`\n         makes the styling available to the overlay.\n\n        Args:\n            *children: The list of children to use.\n            **props: Additional properties to apply to the drawer content.\n\n        Returns:\n                 The drawer content.\n        \"\"\"\n        comp = super().create(*children, **props)\n\n        return Theme.create(comp)\n\n\nclass DrawerOverlay(DrawerComponent):\n    \"\"\"A layer that covers the inert portion of the view when the dialog is open.\"\"\"\n\n    tag = \"Drawer.Overlay\"\n\n    alias = \"Vaul\" + tag\n\n    # Style set based on the source code at https://ui.shadcn.com/docs/components/drawer\n    def add_style(self) -> dict:\n        \"\"\"Get the style for the component.\n\n        Returns:\n            The dictionary of the component style as value and the style notation as key.\n        \"\"\"\n        return {\n            \"position\": \"fixed\",\n            \"left\": \"0\",\n            \"right\": \"0\",\n            \"bottom\": \"0\",\n            \"top\": \"0\",\n            \"z_index\": 50,\n            \"background\": \"rgba(0, 0, 0, 0.5)\",\n        }\n\n\nclass DrawerClose(DrawerTrigger):\n    \"\"\"A button that closes the drawer.\"\"\"\n\n    tag = \"Drawer.Close\"\n\n    alias = \"Vaul\" + tag\n\n\nclass DrawerTitle(DrawerComponent):\n    \"\"\"A title for the drawer.\"\"\"\n\n    tag = \"Drawer.Title\"\n\n    alias = \"Vaul\" + tag\n\n    # Style set based on the source code at https://ui.shadcn.com/docs/components/drawer\n    def add_style(self) -> dict:\n        \"\"\"Get the style for the component.\n\n        Returns:\n            The dictionary of the component style as value and the style notation as key.\n        \"\"\"\n        return {\n            \"font-size\": \"1.125rem\",\n            \"font-weight\": \"600\",\n            \"line-height\": \"1\",\n            \"letter-spacing\": \"-0.05em\",\n        }\n\n\nclass DrawerDescription(DrawerComponent):\n    \"\"\"A description for the drawer.\"\"\"\n\n    tag = \"Drawer.Description\"\n\n    alias = \"Vaul\" + tag\n\n    # Style set based on the source code at https://ui.shadcn.com/docs/components/drawer\n    def add_style(self) -> dict:\n        \"\"\"Get the style for the component.\n\n        Returns:\n            The dictionary of the component style as value and the style notation as key.\n        \"\"\"\n        return {\n            \"font-size\": \"0.875rem\",\n        }\n\n\nclass DrawerHandle(DrawerComponent):\n    \"\"\"A description for the drawer.\"\"\"\n\n    tag = \"Drawer.Handle\"\n\n    alias = \"Vaul\" + tag\n\n\nclass Drawer(ComponentNamespace):\n    \"\"\"A namespace for Drawer components.\"\"\"\n\n    root = __call__ = staticmethod(DrawerRoot.create)\n    trigger = staticmethod(DrawerTrigger.create)\n    portal = staticmethod(DrawerPortal.create)\n    content = staticmethod(DrawerContent.create)\n    overlay = staticmethod(DrawerOverlay.create)\n    close = staticmethod(DrawerClose.create)\n    title = staticmethod(DrawerTitle.create)\n    description = staticmethod(DrawerDescription.create)\n    handle = staticmethod(DrawerHandle.create)\n\n\ndrawer = Drawer()\n"
  },
  {
    "path": "reflex/components/radix/primitives/form.py",
    "content": "\"\"\"Radix form component.\"\"\"\n\nfrom __future__ import annotations\n\nfrom typing import Any, Literal\n\nfrom reflex.components.component import ComponentNamespace\nfrom reflex.components.core.debounce import DebounceInput\nfrom reflex.components.el.elements.forms import Form as HTMLForm\nfrom reflex.components.radix.themes.components.text_field import TextFieldRoot\nfrom reflex.event import EventHandler, no_args_event_spec\nfrom reflex.vars.base import Var\n\nfrom .base import RadixPrimitiveComponentWithClassName\n\n\nclass FormComponent(RadixPrimitiveComponentWithClassName):\n    \"\"\"Base class for all @radix-ui/react-form components.\"\"\"\n\n    library = \"@radix-ui/react-form@0.1.8\"\n\n\nclass FormRoot(FormComponent, HTMLForm):\n    \"\"\"The root component of a radix form.\"\"\"\n\n    tag = \"Root\"\n\n    alias = \"RadixFormRoot\"\n\n    # Fired when the errors are cleared.\n    on_clear_server_errors: EventHandler[no_args_event_spec]\n\n    def add_style(self) -> dict[str, Any] | None:\n        \"\"\"Add style to the component.\n\n        Returns:\n            The style of the component.\n        \"\"\"\n        return {\"width\": \"100%\"}\n\n\nclass FormField(FormComponent):\n    \"\"\"A form field component.\"\"\"\n\n    tag = \"Field\"\n\n    alias = \"RadixFormField\"\n\n    # The name of the form field, that is passed down to the control and used to match with validation messages.\n    name: Var[str]\n\n    # Flag to mark the form field as invalid, for server side validation.\n    server_invalid: Var[bool]\n\n    def add_style(self) -> dict[str, Any] | None:\n        \"\"\"Add style to the component.\n\n        Returns:\n            The style of the component.\n        \"\"\"\n        return {\"display\": \"grid\", \"margin_bottom\": \"10px\"}\n\n\nclass FormLabel(FormComponent):\n    \"\"\"A form label component.\"\"\"\n\n    tag = \"Label\"\n\n    alias = \"RadixFormLabel\"\n\n    def add_style(self) -> dict[str, Any] | None:\n        \"\"\"Add style to the component.\n\n        Returns:\n            The style of the component.\n        \"\"\"\n        return {\"font_size\": \"15px\", \"font_weight\": \"500\", \"line_height\": \"35px\"}\n\n\nclass FormControl(FormComponent):\n    \"\"\"A form control component.\"\"\"\n\n    tag = \"Control\"\n\n    alias = \"RadixFormControl\"\n\n    @classmethod\n    def create(cls, *children, **props):\n        \"\"\"Create a Form Control component.\n\n        Args:\n            *children: The children of the form.\n            **props: The properties of the form.\n\n        Returns:\n            The form control component.\n\n        Raises:\n            ValueError: If the number of children is greater than 1.\n            TypeError: If a child exists but it is not a TextFieldInput.\n        \"\"\"\n        if len(children) > 1:\n            msg = f\"FormControl can only have at most one child, got {len(children)} children\"\n            raise ValueError(msg)\n        for child in children:\n            if not isinstance(child, (TextFieldRoot, DebounceInput)):\n                msg = \"Only Radix TextFieldRoot and DebounceInput are allowed as children of FormControl\"\n                raise TypeError(msg)\n        return super().create(*children, **props)\n\n\nLiteralMatcher = Literal[\n    \"badInput\",\n    \"patternMismatch\",\n    \"rangeOverflow\",\n    \"rangeUnderflow\",\n    \"stepMismatch\",\n    \"tooLong\",\n    \"tooShort\",\n    \"typeMismatch\",\n    \"valid\",\n    \"valueMissing\",\n]\n\n\nclass FormMessage(FormComponent):\n    \"\"\"A form message component.\"\"\"\n\n    tag = \"Message\"\n\n    alias = \"RadixFormMessage\"\n\n    # Used to target a specific field by name when rendering outside of a Field part.\n    name: Var[str]\n\n    # Used to indicate on which condition the message should be visible.\n    match: Var[LiteralMatcher]\n\n    # Forces the message to be shown. This is useful when using server-side validation.\n    force_match: Var[bool]\n\n    def add_style(self) -> dict[str, Any] | None:\n        \"\"\"Add style to the component.\n\n        Returns:\n            The style of the component.\n        \"\"\"\n        return {\"font_size\": \"13px\", \"opacity\": \"0.8\", \"color\": \"white\"}\n\n\nclass FormValidityState(FormComponent):\n    \"\"\"A form validity state component.\"\"\"\n\n    tag = \"ValidityState\"\n    alias = \"RadixFormValidityState\"\n\n\nclass FormSubmit(FormComponent):\n    \"\"\"A form submit component.\"\"\"\n\n    tag = \"Submit\"\n    alias = \"RadixFormSubmit\"\n\n\n# This class is created mainly for reflex-web docs.\nclass Form(FormRoot):\n    \"\"\"The Form component.\"\"\"\n\n\nclass FormNamespace(ComponentNamespace):\n    \"\"\"Form components.\"\"\"\n\n    root = staticmethod(FormRoot.create)\n    control = staticmethod(FormControl.create)\n    field = staticmethod(FormField.create)\n    label = staticmethod(FormLabel.create)\n    message = staticmethod(FormMessage.create)\n    submit = staticmethod(FormSubmit.create)\n    validity_state = staticmethod(FormValidityState.create)\n    __call__ = staticmethod(Form.create)\n\n\nform = FormNamespace()\n"
  },
  {
    "path": "reflex/components/radix/primitives/progress.py",
    "content": "\"\"\"Progress.\"\"\"\n\nfrom __future__ import annotations\n\nfrom typing import Any\n\nfrom reflex.components.component import Component, ComponentNamespace\nfrom reflex.components.core.colors import color\nfrom reflex.components.radix.primitives.accordion import DEFAULT_ANIMATION_DURATION\nfrom reflex.components.radix.primitives.base import RadixPrimitiveComponentWithClassName\nfrom reflex.components.radix.themes.base import LiteralAccentColor, LiteralRadius\nfrom reflex.vars.base import Var\n\n\nclass ProgressComponent(RadixPrimitiveComponentWithClassName):\n    \"\"\"A Progress component.\"\"\"\n\n    library = \"@radix-ui/react-progress@1.1.8\"\n\n\nclass ProgressRoot(ProgressComponent):\n    \"\"\"The Progress Root component.\"\"\"\n\n    tag = \"Root\"\n    alias = \"RadixProgressRoot\"\n\n    # Override theme radius for progress bar: \"none\" | \"small\" | \"medium\" | \"large\" | \"full\"\n    radius: Var[LiteralRadius]\n\n    def add_style(self) -> dict[str, Any] | None:\n        \"\"\"Add style to the component.\n\n        Returns:\n            The style of the component.\n        \"\"\"\n        if self.radius is not None:\n            self.custom_attrs[\"data-radius\"] = self.radius\n\n        return {\n            \"position\": \"relative\",\n            \"overflow\": \"hidden\",\n            \"background\": color(\"gray\", 3, alpha=True),\n            \"border_radius\": \"max(var(--radius-2), var(--radius-full))\",\n            \"width\": \"100%\",\n            \"height\": \"20px\",\n            \"boxShadow\": f\"inset 0 0 0 1px {color('gray', 5, alpha=True)}\",\n        }\n\n    def _exclude_props(self) -> list[str]:\n        return [\"radius\"]\n\n\nclass ProgressIndicator(ProgressComponent):\n    \"\"\"The Progress bar indicator.\"\"\"\n\n    tag = \"Indicator\"\n\n    alias = \"RadixProgressIndicator\"\n\n    # The current progress value.\n    value: Var[int | None]\n\n    # The maximum progress value.\n    max: Var[int | None]\n\n    # The color scheme of the progress indicator.\n    color_scheme: Var[LiteralAccentColor]\n\n    def add_style(self) -> dict[str, Any] | None:\n        \"\"\"Add style to the component.\n\n        Returns:\n            The style of the component.\n        \"\"\"\n        if self.color_scheme is not None:\n            self.custom_attrs[\"data-accent-color\"] = self.color_scheme\n\n        return {\n            \"background_color\": color(\"accent\", 9),\n            \"width\": \"100%\",\n            \"height\": \"100%\",\n            \"transition\": f\"transform {DEFAULT_ANIMATION_DURATION}ms linear\",\n            \"&[data_state='loading']\": {\n                \"transition\": f\"transform {DEFAULT_ANIMATION_DURATION}ms linear\",\n            },\n            \"transform\": f\"translateX(calc(-100% + ({self.value} / {self.max} * 100%)))\",\n            \"boxShadow\": \"inset 0 0 0 1px var(--gray-a5)\",\n        }\n\n    def _exclude_props(self) -> list[str]:\n        return [\"color_scheme\"]\n\n\nclass Progress(ProgressRoot):\n    \"\"\"The high-level Progress component.\"\"\"\n\n    # Override theme color for progress bar indicator\n    color_scheme: Var[LiteralAccentColor]\n\n    # The current progress value.\n    value: Var[int | None]\n\n    # The maximum progress value.\n    max: Var[int | None]\n\n    @classmethod\n    def create(cls, **props) -> Component:\n        \"\"\"High-level API for progress bar.\n\n        Args:\n            **props: The props of the progress bar.\n\n        Returns:\n            The progress bar.\n        \"\"\"\n        progress_indicator_props = {}\n        if \"color_scheme\" in props:\n            progress_indicator_props[\"color_scheme\"] = props.pop(\"color_scheme\")\n\n        return ProgressRoot.create(\n            ProgressIndicator.create(\n                value=props.pop(\"value\", 0),\n                max=props.pop(\"max\", 100),\n                **progress_indicator_props,\n            ),\n            **props,\n        )\n\n\nclass ProgressNamespace(ComponentNamespace):\n    \"\"\"High-level API for progress bar.\"\"\"\n\n    root = staticmethod(ProgressRoot.create)\n    indicator = staticmethod(ProgressIndicator.create)\n    __call__ = staticmethod(Progress.create)\n\n\nprogress = ProgressNamespace()\n"
  },
  {
    "path": "reflex/components/radix/primitives/slider.py",
    "content": "\"\"\"Radix slider components.\"\"\"\n\nfrom __future__ import annotations\n\nfrom collections.abc import Sequence\nfrom typing import Any, Literal\n\nfrom reflex.components.component import Component, ComponentNamespace\nfrom reflex.components.radix.primitives.base import RadixPrimitiveComponentWithClassName\nfrom reflex.event import EventHandler, passthrough_event_spec\nfrom reflex.vars.base import Var\n\nLiteralSliderOrientation = Literal[\"horizontal\", \"vertical\"]\nLiteralSliderDir = Literal[\"ltr\", \"rtl\"]\n\n\nclass SliderComponent(RadixPrimitiveComponentWithClassName):\n    \"\"\"Base class for all @radix-ui/react-slider components.\"\"\"\n\n    library = \"@radix-ui/react-slider@1.3.6\"\n\n\nclass SliderRoot(SliderComponent):\n    \"\"\"The Slider component containing all slider parts.\"\"\"\n\n    tag = \"Root\"\n    alias = \"RadixSliderRoot\"\n\n    default_value: Var[Sequence[int]]\n\n    value: Var[Sequence[int]]\n\n    name: Var[str]\n\n    disabled: Var[bool]\n\n    orientation: Var[LiteralSliderOrientation]\n\n    dir: Var[LiteralSliderDir]\n\n    inverted: Var[bool]\n\n    min: Var[int]\n\n    max: Var[int]\n\n    step: Var[int]\n\n    min_steps_between_thumbs: Var[int]\n\n    # Fired when the value of a thumb changes.\n    on_value_change: EventHandler[passthrough_event_spec(list[float])]\n\n    # Fired when a thumb is released.\n    on_value_commit: EventHandler[passthrough_event_spec(list[float])]\n\n    def add_style(self) -> dict[str, Any] | None:\n        \"\"\"Add style to the component.\n\n        Returns:\n            The style of the component.\n        \"\"\"\n        return {\n            \"position\": \"relative\",\n            \"display\": \"flex\",\n            \"align_items\": \"center\",\n            \"user_select\": \"none\",\n            \"touch_action\": \"none\",\n            \"width\": \"200px\",\n            \"height\": \"20px\",\n            \"&[data-orientation='vertical']\": {\n                \"flex_direction\": \"column\",\n                \"width\": \"20px\",\n                \"height\": \"100px\",\n            },\n        }\n\n\nclass SliderTrack(SliderComponent):\n    \"\"\"A Slider Track component.\"\"\"\n\n    tag = \"Track\"\n    alias = \"RadixSliderTrack\"\n\n    def add_style(self) -> dict[str, Any] | None:\n        \"\"\"Add style to the component.\n\n        Returns:\n            The style of the component.\n        \"\"\"\n        return {\n            \"position\": \"relative\",\n            \"flex_grow\": \"1\",\n            \"background_color\": \"black\",\n            \"border_radius\": \"9999px\",\n            \"height\": \"3px\",\n            \"&[data-orientation='vertical']\": {\"width\": \"3px\"},\n        }\n\n\nclass SliderRange(SliderComponent):\n    \"\"\"A SliderRange component.\"\"\"\n\n    tag = \"Range\"\n    alias = \"RadixSliderRange\"\n\n    def add_style(self) -> dict[str, Any] | None:\n        \"\"\"Add style to the component.\n\n        Returns:\n            The style of the component.\n        \"\"\"\n        return {\n            \"position\": \"absolute\",\n            \"background_color\": \"white\",\n            \"height\": \"100%\",\n            \"&[data-orientation='vertical']\": {\"width\": \"100%\"},\n        }\n\n\nclass SliderThumb(SliderComponent):\n    \"\"\"A SliderThumb component.\"\"\"\n\n    tag = \"Thumb\"\n    alias = \"RadixSliderThumb\"\n\n    def add_style(self) -> dict[str, Any] | None:\n        \"\"\"Add style to the component.\n\n        Returns:\n            The style of the component.\n        \"\"\"\n        return {\n            \"display\": \"block\",\n            \"width\": \"20px\",\n            \"height\": \"20px\",\n            \"background_color\": \"black\",\n            \"box_shadow\": \"0 2px 10px black\",\n            \"border_radius\": \"10px\",\n            \"&:hover\": {\n                \"background_color\": \"gray\",\n            },\n            \"&:focus\": {\n                \"outline\": \"none\",\n                \"box_shadow\": \"0 0 0 4px gray\",\n            },\n        }\n\n\nclass Slider(ComponentNamespace):\n    \"\"\"High level API for slider.\"\"\"\n\n    root = staticmethod(SliderRoot.create)\n    track = staticmethod(SliderTrack.create)\n    range = staticmethod(SliderRange.create)\n    thumb = staticmethod(SliderThumb.create)\n\n    @staticmethod\n    def __call__(**props) -> Component:\n        \"\"\"High level API for slider.\n\n        Args:\n            **props: The props of the slider.\n\n        Returns:\n            A slider component.\n        \"\"\"\n        track = SliderTrack.create(SliderRange.create())\n        # if default_value is not set, the thumbs will not render properly but the slider will still work\n        if \"default_value\" in props:\n            children = [\n                track,\n                *[SliderThumb.create() for _ in props.get(\"default_value\", [])],\n            ]\n        else:\n            children = [\n                track,\n                #     Foreach.create(props.get(\"value\"), lambda e: SliderThumb.create()),  # foreach doesn't render Thumbs properly # noqa: ERA001\n            ]\n\n        return SliderRoot.create(*children, **props)\n\n\nslider = Slider()\n"
  },
  {
    "path": "reflex/components/radix/themes/__init__.py",
    "content": "\"\"\"Namespace for components provided by the @radix-ui/themes library.\"\"\"\n\nfrom __future__ import annotations\n\nfrom reflex.utils import lazy_loader\n\n_SUBMODULES: set[str] = {\"components\", \"layout\", \"typography\"}\n_SUBMOD_ATTRS: dict[str, list[str]] = {\n    \"base\": [\n        \"theme\",\n        \"theme_panel\",\n    ],\n    \"color_mode\": [\n        \"color_mode\",\n    ],\n}\n\n__getattr__, __dir__, __all__ = lazy_loader.attach(\n    __name__,\n    submodules=_SUBMODULES,\n    submod_attrs=_SUBMOD_ATTRS,\n)\n"
  },
  {
    "path": "reflex/components/radix/themes/base.py",
    "content": "\"\"\"Base classes for radix-themes components.\"\"\"\n\nfrom __future__ import annotations\n\nfrom typing import Any, ClassVar, Literal\n\nfrom reflex.components import Component\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.tags import Tag\nfrom reflex.utils.imports import ImportDict, ImportVar\nfrom reflex.vars.base import Var\n\nLiteralAlign = Literal[\"start\", \"center\", \"end\", \"baseline\", \"stretch\"]\nLiteralJustify = Literal[\"start\", \"center\", \"end\", \"between\"]\nLiteralSpacing = Literal[\"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\"]\nLiteralVariant = Literal[\"classic\", \"solid\", \"soft\", \"surface\", \"outline\", \"ghost\"]\nLiteralAppearance = Literal[\"inherit\", \"light\", \"dark\"]\nLiteralGrayColor = Literal[\"gray\", \"mauve\", \"slate\", \"sage\", \"olive\", \"sand\", \"auto\"]\nLiteralPanelBackground = Literal[\"solid\", \"translucent\"]\nLiteralRadius = Literal[\"none\", \"small\", \"medium\", \"large\", \"full\"]\nLiteralScaling = Literal[\"90%\", \"95%\", \"100%\", \"105%\", \"110%\"]\nLiteralAccentColor = Literal[\n    \"tomato\",\n    \"red\",\n    \"ruby\",\n    \"crimson\",\n    \"pink\",\n    \"plum\",\n    \"purple\",\n    \"violet\",\n    \"iris\",\n    \"indigo\",\n    \"blue\",\n    \"cyan\",\n    \"teal\",\n    \"jade\",\n    \"green\",\n    \"grass\",\n    \"brown\",\n    \"orange\",\n    \"sky\",\n    \"mint\",\n    \"lime\",\n    \"yellow\",\n    \"amber\",\n    \"gold\",\n    \"bronze\",\n    \"gray\",\n]\n\n\nclass CommonMarginProps(Component):\n    \"\"\"Many radix-themes elements accept shorthand margin props.\"\"\"\n\n    # Margin: \"0\" - \"9\" # noqa: ERA001\n    m: Var[LiteralSpacing]\n\n    # Margin horizontal: \"0\" - \"9\"\n    mx: Var[LiteralSpacing]\n\n    # Margin vertical: \"0\" - \"9\"\n    my: Var[LiteralSpacing]\n\n    # Margin top: \"0\" - \"9\"\n    mt: Var[LiteralSpacing]\n\n    # Margin right: \"0\" - \"9\"\n    mr: Var[LiteralSpacing]\n\n    # Margin bottom: \"0\" - \"9\"\n    mb: Var[LiteralSpacing]\n\n    # Margin left: \"0\" - \"9\"\n    ml: Var[LiteralSpacing]\n\n\nclass CommonPaddingProps(Component):\n    \"\"\"Many radix-themes elements accept shorthand padding props.\"\"\"\n\n    # Padding: \"0\" - \"9\" # noqa: ERA001\n    p: Var[Responsive[LiteralSpacing]]\n\n    # Padding horizontal: \"0\" - \"9\"\n    px: Var[Responsive[LiteralSpacing]]\n\n    # Padding vertical: \"0\" - \"9\"\n    py: Var[Responsive[LiteralSpacing]]\n\n    # Padding top: \"0\" - \"9\"\n    pt: Var[Responsive[LiteralSpacing]]\n\n    # Padding right: \"0\" - \"9\"\n    pr: Var[Responsive[LiteralSpacing]]\n\n    # Padding bottom: \"0\" - \"9\"\n    pb: Var[Responsive[LiteralSpacing]]\n\n    # Padding left: \"0\" - \"9\"\n    pl: Var[Responsive[LiteralSpacing]]\n\n\nclass RadixLoadingProp(Component):\n    \"\"\"Base class for components that can be in a loading state.\"\"\"\n\n    # If set, show an rx.spinner instead of the component children.\n    loading: Var[bool]\n\n\nclass RadixThemesComponent(Component):\n    \"\"\"Base class for all @radix-ui/themes components.\"\"\"\n\n    library = \"@radix-ui/themes@3.3.0\"\n\n    # \"Fake\" prop color_scheme is used to avoid shadowing CSS prop \"color\".\n    _rename_props: ClassVar[dict[str, str]] = {\"colorScheme\": \"color\"}\n\n    @classmethod\n    def create(\n        cls,\n        *children,\n        **props,\n    ) -> Component:\n        \"\"\"Create a new component instance.\n\n        Will prepend \"RadixThemes\" to the component tag to avoid conflicts with\n        other UI libraries for common names, like Text and Button.\n\n        Args:\n            *children: Child components.\n            **props: Component properties.\n\n        Returns:\n            A new component instance.\n        \"\"\"\n        component = super().create(*children, **props)\n        if component.library is None:\n            component.library = RadixThemesComponent.get_fields()[\n                \"library\"\n            ].default_value()\n        component.alias = \"RadixThemes\" + (component.tag or type(component).__name__)\n        return component\n\n    @staticmethod\n    def _get_app_wrap_components() -> dict[tuple[int, str], Component]:\n        return {\n            (45, \"RadixThemesColorModeProvider\"): RadixThemesColorModeProvider.create(),\n        }\n\n\nclass RadixThemesTriggerComponent(RadixThemesComponent):\n    \"\"\"Base class for Trigger, Close, Cancel, and Accept components.\n\n    These components trigger some action in an overlay component that depends on the\n    on_click event, and thus if a child is provided and has on_click specified, it\n    will overtake the internal action, unless it is wrapped in some inert component,\n    in this case, a Flex.\n    \"\"\"\n\n    @classmethod\n    def create(cls, *children: Any, **props: Any) -> Component:\n        \"\"\"Create a new RadixThemesTriggerComponent instance.\n\n        Args:\n            children: The children of the component.\n            props: The properties of the component.\n\n        Returns:\n            The new RadixThemesTriggerComponent instance.\n        \"\"\"\n        from .layout.flex import Flex\n\n        for child in children:\n            if \"on_click\" in getattr(child, \"event_triggers\", {}):\n                children = (Flex.create(*children),)\n                break\n        return super().create(*children, **props)\n\n\nclass Theme(RadixThemesComponent):\n    \"\"\"A theme provider for radix components.\n\n    This should be applied as `App.theme` to apply the theme to all radix\n    components in the app with the given settings.\n\n    It can also be used in a normal page to apply specified properties to all\n    child elements as an override of the main theme.\n    \"\"\"\n\n    tag = \"Theme\"\n\n    # Whether to apply the themes background color to the theme node. Defaults to True.\n    has_background: Var[bool]\n\n    # Override light or dark mode theme: \"inherit\" | \"light\" | \"dark\". Defaults to \"inherit\".\n    appearance: Var[LiteralAppearance]\n\n    # The color used for default buttons, typography, backgrounds, etc\n    accent_color: Var[LiteralAccentColor]\n\n    # The shade of gray, defaults to \"auto\".\n    gray_color: Var[LiteralGrayColor]\n\n    # Whether panel backgrounds are translucent: \"solid\" | \"translucent\" (default)\n    panel_background: Var[LiteralPanelBackground]\n\n    # Element border radius: \"none\" | \"small\" | \"medium\" | \"large\" | \"full\". Defaults to \"medium\".\n    radius: Var[LiteralRadius]\n\n    # Scale of all theme items: \"90%\" | \"95%\" | \"100%\" | \"105%\" | \"110%\". Defaults to \"100%\"\n    scaling: Var[LiteralScaling]\n\n    @classmethod\n    def create(\n        cls,\n        *children,\n        color_mode: LiteralAppearance | None = None,\n        theme_panel: bool = False,\n        **props,\n    ) -> Component:\n        \"\"\"Create a new Radix Theme specification.\n\n        Args:\n            *children: Child components.\n            color_mode: Map to appearance prop.\n            theme_panel: Whether to include a panel for editing the theme.\n            **props: Component properties.\n\n        Returns:\n            A new component instance.\n        \"\"\"\n        if color_mode is not None:\n            props[\"appearance\"] = color_mode\n        if theme_panel:\n            children = [ThemePanel.create(), *children]\n        return super().create(*children, **props)\n\n    def add_imports(self) -> ImportDict | list[ImportDict]:\n        \"\"\"Add imports for the Theme component.\n\n        Returns:\n            The import dict.\n        \"\"\"\n        return {\n            \"$/utils/theme\": [ImportVar(tag=\"theme\", is_default=True)],\n        }\n\n    def _render(self, props: dict[str, Any] | None = None) -> Tag:\n        tag = super()._render(props)\n        return tag.add_props(\n            css=Var(\n                _js_expr=\"{...theme.styles.global[':root'], ...theme.styles.global.body}\"\n            ),\n        ).remove_props(\"appearance\")\n\n\nclass ThemePanel(RadixThemesComponent):\n    \"\"\"Visual editor for creating and editing themes.\n\n    Include as a child component of Theme to use in your app.\n    \"\"\"\n\n    tag = \"ThemePanel\"\n\n    # Whether the panel is open. Defaults to False.\n    default_open: Var[bool]\n\n    def add_imports(self) -> dict[str, str]:\n        \"\"\"Add imports for the ThemePanel component.\n\n        Returns:\n            The import dict.\n        \"\"\"\n        return {\"react\": \"useEffect\"}\n\n\nclass RadixThemesColorModeProvider(Component):\n    \"\"\"React-themes integration for radix themes components.\"\"\"\n\n    library = \"$/components/reflex/radix_themes_color_mode_provider\"\n    tag = \"RadixThemesColorModeProvider\"\n    is_default = True\n\n\ntheme = Theme.create\ntheme_panel = ThemePanel.create\n"
  },
  {
    "path": "reflex/components/radix/themes/color_mode.py",
    "content": "\"\"\"A switch component for toggling color_mode.\n\nTo style components based on color mode, use style props with `color_mode_cond`:\n\n```\nrx.text(\n    \"Hover over me\",\n    _hover={\n        \"background\": rx.color_mode_cond(\n            light=\"var(--accent-2)\",\n            dark=\"var(--accent-4)\",\n        ),\n    },\n)\n```\n\"\"\"\n\nfrom __future__ import annotations\n\nfrom typing import Any, Literal, get_args\n\nfrom reflex.components.component import BaseComponent, field\nfrom reflex.components.core.cond import Cond, color_mode_cond, cond\nfrom reflex.components.lucide.icon import Icon\nfrom reflex.components.radix.themes.components.dropdown_menu import dropdown_menu\nfrom reflex.components.radix.themes.components.switch import Switch\nfrom reflex.style import (\n    LIGHT_COLOR_MODE,\n    color_mode,\n    resolved_color_mode,\n    set_color_mode,\n    toggle_color_mode,\n)\nfrom reflex.vars.base import Var\nfrom reflex.vars.sequence import LiteralArrayVar\n\nfrom .components.icon_button import IconButton\n\nDEFAULT_LIGHT_ICON: Icon = Icon.create(tag=\"sun\")\nDEFAULT_DARK_ICON: Icon = Icon.create(tag=\"moon\")\n\n\nclass ColorModeIcon(Cond):\n    \"\"\"Displays the current color mode as an icon.\"\"\"\n\n    @classmethod\n    def create(\n        cls,\n        light_component: BaseComponent | None = None,\n        dark_component: BaseComponent | None = None,\n    ):\n        \"\"\"Create an icon component based on color_mode.\n\n        Args:\n            light_component: the component to display when color mode is default\n            dark_component: the component to display when color mode is dark (non-default)\n\n        Returns:\n            The conditionally rendered component\n        \"\"\"\n        return color_mode_cond(\n            light=light_component or DEFAULT_LIGHT_ICON,\n            dark=dark_component or DEFAULT_DARK_ICON,\n        )\n\n\nLiteralPosition = Literal[\"top-left\", \"top-right\", \"bottom-left\", \"bottom-right\"]\n\nposition_values: list[str] = list(get_args(LiteralPosition))\n\nposition_map: dict[str, list[str]] = {\n    \"position\": position_values,\n    \"left\": [\"top-left\", \"bottom-left\"],\n    \"right\": [\"top-right\", \"bottom-right\"],\n    \"top\": [\"top-left\", \"top-right\"],\n    \"bottom\": [\"bottom-left\", \"bottom-right\"],\n}\n\n\n# needed to inverse contains for find\ndef _find(const: list[str], var: Any):\n    return LiteralArrayVar.create(const).contains(var)\n\n\ndef _set_var_default(\n    props: dict, position: Any, prop: str, default1: str, default2: str | Var = \"\"\n):\n    props.setdefault(\n        prop, cond(_find(position_map[prop], position), default1, default2)\n    )\n\n\ndef _set_static_default(props: dict, position: Any, prop: str, default: str):\n    if prop in position:\n        props.setdefault(prop, default)\n\n\nclass ColorModeIconButton(IconButton):\n    \"\"\"Icon Button for toggling light / dark mode via toggle_color_mode.\"\"\"\n\n    # The position of the icon button. Follow document flow if None.\n    position: LiteralPosition | Var[LiteralPosition] | None = field(\n        default=None, is_javascript_property=False\n    )\n\n    # Allow picking the \"system\" value for the color mode.\n    allow_system: bool = field(default=False, is_javascript_property=False)\n\n    @classmethod\n    def create(\n        cls,\n        **props,\n    ):\n        \"\"\"Create an icon button component that calls toggle_color_mode on click.\n\n        Args:\n            **props: The props to pass to the component.\n\n        Returns:\n            The button component.\n        \"\"\"\n        position: str | Var = props.pop(\"position\", None)\n        allow_system = props.pop(\"allow_system\", False)\n\n        # position is used to set nice defaults for positioning the icon button\n        if isinstance(position, Var):\n            _set_var_default(props, position, \"position\", \"fixed\", position)\n            _set_var_default(props, position, \"bottom\", \"2rem\")\n            _set_var_default(props, position, \"top\", \"2rem\")\n            _set_var_default(props, position, \"left\", \"2rem\")\n            _set_var_default(props, position, \"right\", \"2rem\")\n        elif position is not None:\n            if position in position_values:\n                props.setdefault(\"position\", \"fixed\")\n                _set_static_default(props, position, \"bottom\", \"2rem\")\n                _set_static_default(props, position, \"top\", \"2rem\")\n                _set_static_default(props, position, \"left\", \"2rem\")\n                _set_static_default(props, position, \"right\", \"2rem\")\n            else:\n                props[\"position\"] = position\n\n        props.setdefault(\"background\", \"transparent\")\n        props.setdefault(\"color\", \"inherit\")\n        props.setdefault(\"z_index\", \"20\")\n        props.setdefault(\":hover\", {\"cursor\": \"pointer\"})\n\n        if allow_system:\n\n            def color_mode_item(_color_mode: Literal[\"light\", \"dark\", \"system\"]):\n                return dropdown_menu.item(\n                    _color_mode.title(), on_click=set_color_mode(_color_mode)\n                )\n\n            return dropdown_menu.root(\n                dropdown_menu.trigger(\n                    super().create(\n                        ColorModeIcon.create(),\n                    ),\n                    **props,\n                ),\n                dropdown_menu.content(\n                    color_mode_item(\"light\"),\n                    color_mode_item(\"dark\"),\n                    color_mode_item(\"system\"),\n                ),\n            )\n        return IconButton.create(\n            ColorModeIcon.create(),\n            on_click=toggle_color_mode,\n            **props,\n        )\n\n\nclass ColorModeSwitch(Switch):\n    \"\"\"Switch for toggling light / dark mode via toggle_color_mode.\"\"\"\n\n    @classmethod\n    def create(cls, *children, **props):\n        \"\"\"Create a switch component bound to color_mode.\n\n        Args:\n            *children: The children of the component.\n            **props: The props to pass to the component.\n\n        Returns:\n            The switch component.\n        \"\"\"\n        return Switch.create(\n            *children,\n            checked=resolved_color_mode != LIGHT_COLOR_MODE,\n            on_change=toggle_color_mode,\n            **props,\n        )\n\n\nclass ColorModeNamespace(Var):\n    \"\"\"Namespace for color mode components.\"\"\"\n\n    icon = staticmethod(ColorModeIcon.create)\n    button = staticmethod(ColorModeIconButton.create)\n    switch = staticmethod(ColorModeSwitch.create)\n\n\ncolor_mode = color_mode_var_and_namespace = ColorModeNamespace(\n    _js_expr=color_mode._js_expr,\n    _var_type=color_mode._var_type,\n    _var_data=color_mode._get_all_var_data(),\n)\n"
  },
  {
    "path": "reflex/components/radix/themes/components/__init__.py",
    "content": "\"\"\"Radix themes components.\"\"\"\n\nfrom __future__ import annotations\n\nfrom reflex import RADIX_THEMES_COMPONENTS_MAPPING\nfrom reflex.utils import lazy_loader\n\n_SUBMOD_ATTRS: dict[str, list[str]] = {\n    \"\".join(k.split(\"components.radix.themes.components.\")[-1]): v\n    for k, v in RADIX_THEMES_COMPONENTS_MAPPING.items()\n}\n\n__getattr__, __dir__, __all__ = lazy_loader.attach(\n    __name__,\n    submod_attrs=_SUBMOD_ATTRS,\n)\n"
  },
  {
    "path": "reflex/components/radix/themes/components/alert_dialog.py",
    "content": "\"\"\"Interactive components provided by @radix-ui/themes.\"\"\"\n\nfrom typing import Literal\n\nfrom reflex.components.component import ComponentNamespace\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.el import elements\nfrom reflex.components.radix.themes.base import (\n    RadixThemesComponent,\n    RadixThemesTriggerComponent,\n)\nfrom reflex.constants.compiler import MemoizationMode\nfrom reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec\nfrom reflex.vars.base import Var\n\nLiteralContentSize = Literal[\"1\", \"2\", \"3\", \"4\"]\n\n\nclass AlertDialogRoot(RadixThemesComponent):\n    \"\"\"Contains all the parts of the dialog.\"\"\"\n\n    tag = \"AlertDialog.Root\"\n\n    # The controlled open state of the dialog.\n    open: Var[bool]\n\n    # Fired when the open state changes.\n    on_open_change: EventHandler[passthrough_event_spec(bool)]\n\n    # The open state of the dialog when it is initially rendered. Use when you do not need to control its open state.\n    default_open: Var[bool]\n\n\nclass AlertDialogTrigger(RadixThemesTriggerComponent):\n    \"\"\"Wraps the control that will open the dialog.\"\"\"\n\n    tag = \"AlertDialog.Trigger\"\n\n    _memoization_mode = MemoizationMode(recursive=False)\n\n\nclass AlertDialogContent(elements.Div, RadixThemesComponent):\n    \"\"\"Contains the content of the dialog. This component is based on the div element.\"\"\"\n\n    tag = \"AlertDialog.Content\"\n\n    # The size of the content.\n    size: Var[Responsive[LiteralContentSize]]\n\n    # Whether to force mount the content on open.\n    force_mount: Var[bool]\n\n    # Fired when the dialog is opened.\n    on_open_auto_focus: EventHandler[no_args_event_spec]\n\n    # Fired when the dialog is closed.\n    on_close_auto_focus: EventHandler[no_args_event_spec]\n\n    # Fired when the escape key is pressed.\n    on_escape_key_down: EventHandler[no_args_event_spec]\n\n\nclass AlertDialogTitle(RadixThemesComponent):\n    \"\"\"An accessible title that is announced when the dialog is opened.\n    This part is based on the Heading component with a pre-defined font size and\n    leading trim on top.\n    \"\"\"\n\n    tag = \"AlertDialog.Title\"\n\n\nclass AlertDialogDescription(RadixThemesComponent):\n    \"\"\"An optional accessible description that is announced when the dialog is opened.\n    This part is based on the Text component with a pre-defined font size.\n    \"\"\"\n\n    tag = \"AlertDialog.Description\"\n\n\nclass AlertDialogAction(RadixThemesTriggerComponent):\n    \"\"\"Wraps the control that will close the dialog. This should be distinguished\n    visually from the Cancel control.\n    \"\"\"\n\n    tag = \"AlertDialog.Action\"\n\n\nclass AlertDialogCancel(RadixThemesTriggerComponent):\n    \"\"\"Wraps the control that will close the dialog. This should be distinguished\n    visually from the Action control.\n    \"\"\"\n\n    tag = \"AlertDialog.Cancel\"\n\n\nclass AlertDialog(ComponentNamespace):\n    \"\"\"AlertDialog components namespace.\"\"\"\n\n    root = staticmethod(AlertDialogRoot.create)\n    trigger = staticmethod(AlertDialogTrigger.create)\n    content = staticmethod(AlertDialogContent.create)\n    title = staticmethod(AlertDialogTitle.create)\n    description = staticmethod(AlertDialogDescription.create)\n    action = staticmethod(AlertDialogAction.create)\n    cancel = staticmethod(AlertDialogCancel.create)\n\n\nalert_dialog = AlertDialog()\n"
  },
  {
    "path": "reflex/components/radix/themes/components/aspect_ratio.py",
    "content": "\"\"\"Interactive components provided by @radix-ui/themes.\"\"\"\n\nfrom reflex.components.radix.themes.base import RadixThemesComponent\nfrom reflex.vars.base import Var\n\n\nclass AspectRatio(RadixThemesComponent):\n    \"\"\"Displays content with a desired ratio.\"\"\"\n\n    tag = \"AspectRatio\"\n\n    # The ratio of the width to the height of the element\n    ratio: Var[float | int]\n\n\naspect_ratio = AspectRatio.create\n"
  },
  {
    "path": "reflex/components/radix/themes/components/avatar.py",
    "content": "\"\"\"Interactive components provided by @radix-ui/themes.\"\"\"\n\nfrom typing import Literal\n\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.radix.themes.base import (\n    LiteralAccentColor,\n    LiteralRadius,\n    RadixThemesComponent,\n)\nfrom reflex.vars.base import Var\n\nLiteralSize = Literal[\"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\"]\n\n\nclass Avatar(RadixThemesComponent):\n    \"\"\"An image element with a fallback for representing the user.\"\"\"\n\n    tag = \"Avatar\"\n\n    # The variant of the avatar\n    variant: Var[Literal[\"solid\", \"soft\"]]\n\n    # The size of the avatar: \"1\" - \"9\"\n    size: Var[Responsive[LiteralSize]]\n\n    # Color theme of the avatar\n    color_scheme: Var[LiteralAccentColor]\n\n    # Whether to render the avatar with higher contrast color against background\n    high_contrast: Var[bool]\n\n    # Override theme radius for avatar: \"none\" | \"small\" | \"medium\" | \"large\" | \"full\"\n    radius: Var[LiteralRadius]\n\n    # The src of the avatar image\n    src: Var[str]\n\n    # The rendered fallback text\n    fallback: Var[str]\n\n\navatar = Avatar.create\n"
  },
  {
    "path": "reflex/components/radix/themes/components/badge.py",
    "content": "\"\"\"Interactive components provided by @radix-ui/themes.\"\"\"\n\nfrom typing import Literal\n\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.el import elements\nfrom reflex.components.radix.themes.base import (\n    LiteralAccentColor,\n    LiteralRadius,\n    RadixThemesComponent,\n)\nfrom reflex.vars.base import Var\n\n\nclass Badge(elements.Span, RadixThemesComponent):\n    \"\"\"A stylized badge element.\"\"\"\n\n    tag = \"Badge\"\n\n    # The variant of the badge\n    variant: Var[Literal[\"solid\", \"soft\", \"surface\", \"outline\"]]\n\n    # The size of the badge\n    size: Var[Responsive[Literal[\"1\", \"2\", \"3\"]]]\n\n    # Color theme of the badge\n    color_scheme: Var[LiteralAccentColor]\n\n    # Whether to render the badge with higher contrast color against background\n    high_contrast: Var[bool]\n\n    # Override theme radius for badge: \"none\" | \"small\" | \"medium\" | \"large\" | \"full\"\n    radius: Var[LiteralRadius]\n\n\nbadge = Badge.create\n"
  },
  {
    "path": "reflex/components/radix/themes/components/button.py",
    "content": "\"\"\"Interactive components provided by @radix-ui/themes.\"\"\"\n\nfrom typing import Literal\n\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.el import elements\nfrom reflex.components.radix.themes.base import (\n    LiteralAccentColor,\n    LiteralRadius,\n    LiteralVariant,\n    RadixLoadingProp,\n    RadixThemesComponent,\n)\nfrom reflex.vars.base import Var\n\nLiteralButtonSize = Literal[\"1\", \"2\", \"3\", \"4\"]\n\n\nclass Button(elements.Button, RadixLoadingProp, RadixThemesComponent):\n    \"\"\"Trigger an action or event, such as submitting a form or displaying a dialog.\"\"\"\n\n    tag = \"Button\"\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior.\n    as_child: Var[bool]\n\n    # Button size \"1\" - \"4\"\n    size: Var[Responsive[LiteralButtonSize]]\n\n    # Variant of button: \"solid\" | \"soft\" | \"outline\" | \"ghost\"\n    variant: Var[LiteralVariant]\n\n    # Override theme color for button\n    color_scheme: Var[LiteralAccentColor]\n\n    # Whether to render the button with higher contrast color against background\n    high_contrast: Var[bool]\n\n    # Override theme radius for button: \"none\" | \"small\" | \"medium\" | \"large\" | \"full\"\n    radius: Var[LiteralRadius]\n\n\nbutton = Button.create\n"
  },
  {
    "path": "reflex/components/radix/themes/components/callout.py",
    "content": "\"\"\"Interactive components provided by @radix-ui/themes.\"\"\"\n\nfrom typing import Literal\n\nimport reflex as rx\nfrom reflex.components.component import Component, ComponentNamespace\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.el import elements\nfrom reflex.components.lucide.icon import Icon\nfrom reflex.components.radix.themes.base import LiteralAccentColor, RadixThemesComponent\nfrom reflex.vars.base import Var\n\nCalloutVariant = Literal[\"soft\", \"surface\", \"outline\"]\n\n\nclass CalloutRoot(elements.Div, RadixThemesComponent):\n    \"\"\"Groups Icon and Text parts of a Callout.\"\"\"\n\n    tag = \"Callout.Root\"\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior.\n    as_child: Var[bool]\n\n    # Size \"1\" - \"3\"\n    size: Var[Responsive[Literal[\"1\", \"2\", \"3\"]]]\n\n    # Variant of button: \"soft\" | \"surface\" | \"outline\"\n    variant: Var[CalloutVariant]\n\n    # Override theme color for button\n    color_scheme: Var[LiteralAccentColor]\n\n    # Whether to render the button with higher contrast color against background\n    high_contrast: Var[bool]\n\n\nclass CalloutIcon(elements.Div, RadixThemesComponent):\n    \"\"\"Provides width and height for the icon associated with the callout.\"\"\"\n\n    tag = \"Callout.Icon\"\n\n\nclass CalloutText(elements.P, RadixThemesComponent):\n    \"\"\"Renders the callout text. This component is based on the p element.\"\"\"\n\n    tag = \"Callout.Text\"\n\n\nclass Callout(CalloutRoot):\n    \"\"\"A short message to attract user's attention.\"\"\"\n\n    # The text of the callout.\n    text: Var[str]\n\n    # The icon of the callout.\n    icon: Var[str]\n\n    @classmethod\n    def create(cls, text: str | Var[str], **props) -> Component:\n        \"\"\"Create a callout component.\n\n        Args:\n            text: The text of the callout.\n            **props: The properties of the component.\n\n        Returns:\n            The callout component.\n        \"\"\"\n        return CalloutRoot.create(\n            (\n                CalloutIcon.create(Icon.create(tag=props[\"icon\"]))\n                if \"icon\" in props\n                else rx.fragment()\n            ),\n            CalloutText.create(text),\n            **props,\n        )\n\n\nclass CalloutNamespace(ComponentNamespace):\n    \"\"\"Callout components namespace.\"\"\"\n\n    root = staticmethod(CalloutRoot.create)\n    icon = staticmethod(CalloutIcon.create)\n    text = staticmethod(CalloutText.create)\n    __call__ = staticmethod(Callout.create)\n\n\ncallout = CalloutNamespace()\n"
  },
  {
    "path": "reflex/components/radix/themes/components/card.py",
    "content": "\"\"\"Interactive components provided by @radix-ui/themes.\"\"\"\n\nfrom typing import Literal\n\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.el import elements\nfrom reflex.components.radix.themes.base import RadixThemesComponent\nfrom reflex.vars.base import Var\n\n\nclass Card(elements.Div, RadixThemesComponent):\n    \"\"\"Container that groups related content and actions.\"\"\"\n\n    tag = \"Card\"\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior.\n    as_child: Var[bool]\n\n    # Card size: \"1\" - \"5\"\n    size: Var[Responsive[Literal[\"1\", \"2\", \"3\", \"4\", \"5\"],]]\n\n    # Variant of Card: \"surface\" | \"classic\" | \"ghost\"\n    variant: Var[Literal[\"surface\", \"classic\", \"ghost\"]]\n\n\ncard = Card.create\n"
  },
  {
    "path": "reflex/components/radix/themes/components/checkbox.py",
    "content": "\"\"\"Interactive components provided by @radix-ui/themes.\"\"\"\n\nfrom typing import Literal\n\nfrom reflex.components.component import Component, ComponentNamespace\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.radix.themes.base import (\n    LiteralAccentColor,\n    LiteralSpacing,\n    RadixThemesComponent,\n)\nfrom reflex.components.radix.themes.layout.flex import Flex\nfrom reflex.components.radix.themes.typography.text import Text\nfrom reflex.event import EventHandler, passthrough_event_spec\nfrom reflex.vars.base import Var\n\nLiteralCheckboxSize = Literal[\"1\", \"2\", \"3\"]\nLiteralCheckboxVariant = Literal[\"classic\", \"surface\", \"soft\"]\n\n\nclass Checkbox(RadixThemesComponent):\n    \"\"\"Selects a single value, typically for submission in a form.\"\"\"\n\n    tag = \"Checkbox\"\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior.\n    as_child: Var[bool]\n\n    # Checkbox size \"1\" - \"3\"\n    size: Var[Responsive[LiteralCheckboxSize]]\n\n    # Variant of checkbox: \"classic\" | \"surface\" | \"soft\"\n    variant: Var[LiteralCheckboxVariant]\n\n    # Override theme color for checkbox\n    color_scheme: Var[LiteralAccentColor]\n\n    # Whether to render the checkbox with higher contrast color against background\n    high_contrast: Var[bool]\n\n    # Whether the checkbox is checked by default\n    default_checked: Var[bool]\n\n    # Whether the checkbox is checked\n    checked: Var[bool]\n\n    # Whether the checkbox is disabled\n    disabled: Var[bool]\n\n    # Whether the checkbox is required\n    required: Var[bool]\n\n    # The name of the checkbox control when submitting the form.\n    name: Var[str]\n\n    # The value of the checkbox control when submitting the form.\n    value: Var[str]\n\n    # Props to rename\n    _rename_props = {\"onChange\": \"onCheckedChange\"}\n\n    # Fired when the checkbox is checked or unchecked.\n    on_change: EventHandler[passthrough_event_spec(bool)]\n\n\nclass HighLevelCheckbox(RadixThemesComponent):\n    \"\"\"A checkbox component with a label.\"\"\"\n\n    tag = \"Checkbox\"\n\n    # The text label for the checkbox.\n    text: Var[str]\n\n    # The gap between the checkbox and the label.\n    spacing: Var[LiteralSpacing]\n\n    # The size of the checkbox \"1\" - \"3\".\n    size: Var[LiteralCheckboxSize]\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior.\n    as_child: Var[bool]\n\n    # Variant of checkbox: \"classic\" | \"surface\" | \"soft\"\n    variant: Var[LiteralCheckboxVariant]\n\n    # Override theme color for checkbox\n    color_scheme: Var[LiteralAccentColor]\n\n    # Whether to render the checkbox with higher contrast color against background\n    high_contrast: Var[bool]\n\n    # Whether the checkbox is checked by default\n    default_checked: Var[bool]\n\n    # Whether the checkbox is checked\n    checked: Var[bool]\n\n    # Whether the checkbox is disabled\n    disabled: Var[bool]\n\n    # Whether the checkbox is required\n    required: Var[bool]\n\n    # The name of the checkbox control when submitting the form.\n    name: Var[str]\n\n    # The value of the checkbox control when submitting the form.\n    value: Var[str]\n\n    # Props to rename\n    _rename_props = {\"onChange\": \"onCheckedChange\"}\n\n    # Fired when the checkbox is checked or unchecked.\n    on_change: EventHandler[passthrough_event_spec(bool)]\n\n    @classmethod\n    def create(cls, text: Var[str] = Var.create(\"\"), **props) -> Component:\n        \"\"\"Create a checkbox with a label.\n\n        Args:\n            text: The text of the label.\n            **props: Additional properties to apply to the checkbox item.\n\n        Returns:\n            The checkbox component with a label.\n        \"\"\"\n        spacing = props.pop(\"spacing\", \"2\")\n        size = props.pop(\"size\", \"2\")\n        flex_props = {}\n        if \"gap\" in props:\n            flex_props[\"gap\"] = props.pop(\"gap\", None)\n\n        return Text.create(\n            Flex.create(\n                Checkbox.create(\n                    size=size,\n                    **props,\n                ),\n                text,\n                spacing=spacing,\n                **flex_props,\n            ),\n            as_=\"label\",\n            size=size,\n        )\n\n\nclass CheckboxNamespace(ComponentNamespace):\n    \"\"\"Checkbox components namespace.\"\"\"\n\n    __call__ = staticmethod(HighLevelCheckbox.create)\n\n\ncheckbox = CheckboxNamespace()\n"
  },
  {
    "path": "reflex/components/radix/themes/components/checkbox_cards.py",
    "content": "\"\"\"Components for the Radix CheckboxCards component.\"\"\"\n\nfrom types import SimpleNamespace\nfrom typing import Literal\n\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.radix.themes.base import LiteralAccentColor, RadixThemesComponent\nfrom reflex.vars.base import Var\n\n\nclass CheckboxCardsRoot(RadixThemesComponent):\n    \"\"\"Root element for a CheckboxCards component.\"\"\"\n\n    tag = \"CheckboxCards.Root\"\n\n    # The size of the checkbox cards: \"1\" | \"2\" | \"3\"\n    size: Var[Responsive[Literal[\"1\", \"2\", \"3\"]]]\n\n    # Variant of button: \"classic\" | \"surface\" | \"soft\"\n    variant: Var[Literal[\"classic\", \"surface\"]]\n\n    # Override theme color for button\n    color_scheme: Var[LiteralAccentColor]\n\n    # Uses a higher contrast color for the component.\n    high_contrast: Var[bool]\n\n    # The number of columns:\n    columns: Var[Responsive[str | Literal[\"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\"]]]\n\n    # The gap between the checkbox cards:\n    gap: Var[Responsive[str | Literal[\"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\"]]]\n\n\nclass CheckboxCardsItem(RadixThemesComponent):\n    \"\"\"An item in the CheckboxCards component.\"\"\"\n\n    tag = \"CheckboxCards.Item\"\n\n\nclass CheckboxCards(SimpleNamespace):\n    \"\"\"CheckboxCards components namespace.\"\"\"\n\n    root = staticmethod(CheckboxCardsRoot.create)\n    item = staticmethod(CheckboxCardsItem.create)\n\n\ncheckbox_cards = CheckboxCards()\n"
  },
  {
    "path": "reflex/components/radix/themes/components/checkbox_group.py",
    "content": "\"\"\"Components for the CheckboxGroup component of Radix Themes.\"\"\"\n\nfrom collections.abc import Sequence\nfrom types import SimpleNamespace\nfrom typing import Literal\n\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.radix.themes.base import LiteralAccentColor, RadixThemesComponent\nfrom reflex.vars.base import Var\n\n\nclass CheckboxGroupRoot(RadixThemesComponent):\n    \"\"\"Root element for a CheckboxGroup component.\"\"\"\n\n    tag = \"CheckboxGroup.Root\"\n\n    # Use the size prop to control the checkbox size.\n    size: Var[Responsive[Literal[\"1\", \"2\", \"3\"]]]\n\n    # Variant of button: \"classic\" | \"surface\" | \"soft\"\n    variant: Var[Literal[\"classic\", \"surface\", \"soft\"]]\n\n    # Override theme color for button\n    color_scheme: Var[LiteralAccentColor]\n\n    # Uses a higher contrast color for the component.\n    high_contrast: Var[bool]\n\n    # determines which checkboxes, if any, are checked by default.\n    default_value: Var[Sequence[str]]\n\n    # used to assign a name to the entire group of checkboxes\n    name: Var[str]\n\n\nclass CheckboxGroupItem(RadixThemesComponent):\n    \"\"\"An item in the CheckboxGroup component.\"\"\"\n\n    tag = \"CheckboxGroup.Item\"\n\n    # specifies the value associated with a particular checkbox option.\n    value: Var[str]\n\n    # Use the native disabled attribute to create a disabled checkbox.\n    disabled: Var[bool]\n\n\nclass CheckboxGroup(SimpleNamespace):\n    \"\"\"CheckboxGroup components namespace.\"\"\"\n\n    root = staticmethod(CheckboxGroupRoot.create)\n    item = staticmethod(CheckboxGroupItem.create)\n\n\ncheckbox_group = CheckboxGroup()\n"
  },
  {
    "path": "reflex/components/radix/themes/components/context_menu.py",
    "content": "\"\"\"Interactive components provided by @radix-ui/themes.\"\"\"\n\nfrom typing import ClassVar, Literal\n\nfrom reflex.components.component import ComponentNamespace\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.radix.themes.base import LiteralAccentColor, RadixThemesComponent\nfrom reflex.constants.compiler import MemoizationMode\nfrom reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec\nfrom reflex.vars.base import Var\n\nfrom .checkbox import Checkbox\nfrom .radio_group import HighLevelRadioGroup\n\nLiteralDirType = Literal[\"ltr\", \"rtl\"]\n\nLiteralSizeType = Literal[\"1\", \"2\"]\n\nLiteralVariantType = Literal[\"solid\", \"soft\"]\n\nLiteralSideType = Literal[\"top\", \"right\", \"bottom\", \"left\"]\n\nLiteralAlignType = Literal[\"start\", \"center\", \"end\"]\n\nLiteralStickyType = Literal[\n    \"partial\",\n    \"always\",\n]\n\n\nclass ContextMenuRoot(RadixThemesComponent):\n    \"\"\"Menu representing a set of actions, displayed at the origin of a pointer right-click or long-press.\"\"\"\n\n    tag = \"ContextMenu.Root\"\n\n    # The modality of the context menu. When set to true, interaction with outside elements will be disabled and only menu content will be visible to screen readers.\n    modal: Var[bool]\n\n    _invalid_children: ClassVar[list[str]] = [\"ContextMenuItem\"]\n\n    # Fired when the open state changes.\n    on_open_change: EventHandler[passthrough_event_spec(bool)]\n\n    # The reading direction of submenus when applicable. If omitted, inherits globally from DirectionProvider or assumes LTR (left-to-right) reading mode.\n    dir: Var[LiteralDirType]\n\n\nclass ContextMenuTrigger(RadixThemesComponent):\n    \"\"\"Wraps the element that will open the context menu.\"\"\"\n\n    tag = \"ContextMenu.Trigger\"\n\n    # Whether the trigger is disabled\n    disabled: Var[bool]\n\n    _valid_parents: ClassVar[list[str]] = [\"ContextMenuRoot\"]\n\n    _invalid_children: ClassVar[list[str]] = [\"ContextMenuContent\"]\n\n    _memoization_mode = MemoizationMode(recursive=False)\n\n\nclass ContextMenuContent(RadixThemesComponent):\n    \"\"\"The component that pops out when the context menu is open.\"\"\"\n\n    tag = \"ContextMenu.Content\"\n\n    # Dropdown Menu Content size \"1\" - \"2\"\n    size: Var[Responsive[LiteralSizeType]]\n\n    # Variant of Dropdown Menu Content: \"solid\" | \"soft\"\n    variant: Var[LiteralVariantType]\n\n    # Override theme color for Dropdown Menu Content\n    color_scheme: Var[LiteralAccentColor]\n\n    # Renders the Dropdown Menu Content in higher contrast\n    high_contrast: Var[bool]\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior. Defaults to False.\n    as_child: Var[bool]\n\n    # When True, keyboard navigation will loop from last item to first, and vice versa. Defaults to False.\n    loop: Var[bool]\n\n    # Used to force mounting when more control is needed. Useful when controlling animation with React animation libraries.\n    force_mount: Var[bool]\n\n    # The preferred side of the trigger to render against when open. Will be reversed when collisions occur and `avoid_collisions` is enabled.The position of the tooltip. Defaults to \"top\".\n    side: Var[LiteralSideType]\n\n    # The distance in pixels from the trigger. Defaults to 0.\n    side_offset: Var[float | int]\n\n    # The preferred alignment against the trigger. May change when collisions occur. Defaults to \"center\".\n    align: Var[LiteralAlignType]\n\n    # An offset in pixels from the \"start\" or \"end\" alignment options.\n    align_offset: Var[float | int]\n\n    # When true, overrides the side and align preferences to prevent collisions with boundary edges. Defaults to True.\n    avoid_collisions: Var[bool]\n\n    # The distance in pixels from the boundary edges where collision detection should occur. Accepts a number (same for all sides), or a partial padding object, for example: { \"top\": 20, \"left\": 20 }. Defaults to 0.\n    collision_padding: Var[float | int | dict[str, float | int]]\n\n    # The sticky behavior on the align axis. \"partial\" will keep the content in the boundary as long as the trigger is at least partially in the boundary whilst \"always\" will keep the content in the boundary regardless. Defaults to \"partial\".\n    sticky: Var[LiteralStickyType]\n\n    # Whether to hide the content when the trigger becomes fully occluded. Defaults to False.\n    hide_when_detached: Var[bool]\n\n    # Fired when focus moves back after closing.\n    on_close_auto_focus: EventHandler[no_args_event_spec]\n\n    # Fired when the escape key is pressed.\n    on_escape_key_down: EventHandler[no_args_event_spec]\n\n    # Fired when a pointer down event happens outside the context menu.\n    on_pointer_down_outside: EventHandler[no_args_event_spec]\n\n    # Fired when focus moves outside the context menu.\n    on_focus_outside: EventHandler[no_args_event_spec]\n\n    # Fired when the pointer interacts outside the context menu.\n    on_interact_outside: EventHandler[no_args_event_spec]\n\n\nclass ContextMenuSub(RadixThemesComponent):\n    \"\"\"Contains all the parts of a submenu.\"\"\"\n\n    tag = \"ContextMenu.Sub\"\n\n    # The controlled open state of the submenu. Must be used in conjunction with `on_open_change`.\n    open: Var[bool]\n\n    # The open state of the submenu when it is initially rendered. Use when you do not need to control its open state.\n    default_open: Var[bool]\n\n    # Fired when the open state changes.\n    on_open_change: EventHandler[passthrough_event_spec(bool)]\n\n\nclass ContextMenuSubTrigger(RadixThemesComponent):\n    \"\"\"An item that opens a submenu.\"\"\"\n\n    tag = \"ContextMenu.SubTrigger\"\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior. Defaults to False.\n    as_child: Var[bool]\n\n    # Whether the trigger is disabled\n    disabled: Var[bool]\n\n    # Optional text used for typeahead purposes. By default the typeahead behavior will use the .textContent of the item. Use this when the content is complex, or you have non-textual content inside.\n    text_value: Var[str]\n\n    _valid_parents: ClassVar[list[str]] = [\"ContextMenuContent\", \"ContextMenuSub\"]\n\n    _memoization_mode = MemoizationMode(recursive=False)\n\n\nclass ContextMenuSubContent(RadixThemesComponent):\n    \"\"\"The component that pops out when a submenu is open.\"\"\"\n\n    tag = \"ContextMenu.SubContent\"\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior. Defaults to False.\n    as_child: Var[bool]\n\n    # When True, keyboard navigation will loop from last item to first, and vice versa. Defaults to False.\n    loop: Var[bool]\n\n    # Used to force mounting when more control is needed. Useful when controlling animation with React animation libraries.\n    force_mount: Var[bool]\n\n    # The distance in pixels from the trigger. Defaults to 0.\n    side_offset: Var[float | int]\n\n    # An offset in pixels from the \"start\" or \"end\" alignment options.\n    align_offset: Var[float | int]\n\n    # When true, overrides the side and align preferences to prevent collisions with boundary edges. Defaults to True.\n    avoid_collisions: Var[bool]\n\n    # The distance in pixels from the boundary edges where collision detection should occur. Accepts a number (same for all sides), or a partial padding object, for example: { \"top\": 20, \"left\": 20 }. Defaults to 0.\n    collision_padding: Var[float | int | dict[str, float | int]]\n\n    # The sticky behavior on the align axis. \"partial\" will keep the content in the boundary as long as the trigger is at least partially in the boundary whilst \"always\" will keep the content in the boundary regardless. Defaults to \"partial\".\n    sticky: Var[LiteralStickyType]\n\n    # Whether to hide the content when the trigger becomes fully occluded. Defaults to False.\n    hide_when_detached: Var[bool]\n\n    _valid_parents: ClassVar[list[str]] = [\"ContextMenuSub\"]\n\n    # Fired when the escape key is pressed.\n    on_escape_key_down: EventHandler[no_args_event_spec]\n\n    # Fired when a pointer down event happens outside the context menu.\n    on_pointer_down_outside: EventHandler[no_args_event_spec]\n\n    # Fired when focus moves outside the context menu.\n    on_focus_outside: EventHandler[no_args_event_spec]\n\n    # Fired when interacting outside the context menu.\n    on_interact_outside: EventHandler[no_args_event_spec]\n\n\nclass ContextMenuItem(RadixThemesComponent):\n    \"\"\"The component that contains the context menu items.\"\"\"\n\n    tag = \"ContextMenu.Item\"\n\n    # Override theme color for button\n    color_scheme: Var[LiteralAccentColor]\n\n    # Shortcut to render a menu item as a link\n    shortcut: Var[str]\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior. Defaults to False.\n    as_child: Var[bool]\n\n    # When true, prevents the user from interacting with the item.\n    disabled: Var[bool]\n\n    # Optional text used for typeahead purposes. By default the typeahead behavior will use the content of the item. Use this when the content is complex, or you have non-textual content inside.\n    text_value: Var[str]\n\n    _valid_parents: ClassVar[list[str]] = [\n        \"ContextMenuContent\",\n        \"ContextMenuSubContent\",\n        \"ContextMenuGroup\",\n    ]\n\n    # Fired when the item is selected.\n    on_select: EventHandler[no_args_event_spec]\n\n\nclass ContextMenuSeparator(RadixThemesComponent):\n    \"\"\"Separates items in a context menu.\"\"\"\n\n    tag = \"ContextMenu.Separator\"\n\n\nclass ContextMenuCheckbox(Checkbox):\n    \"\"\"The component that contains the checkbox.\"\"\"\n\n    tag = \"ContextMenu.CheckboxItem\"\n\n    # Text to render as shortcut.\n    shortcut: Var[str]\n\n\nclass ContextMenuLabel(RadixThemesComponent):\n    \"\"\"The component that contains the label.\"\"\"\n\n    tag = \"ContextMenu.Label\"\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior. Defaults to False.\n    as_child: Var[bool]\n\n\nclass ContextMenuGroup(RadixThemesComponent):\n    \"\"\"The component that contains the group.\"\"\"\n\n    tag = \"ContextMenu.Group\"\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior. Defaults to False.\n    as_child: Var[bool]\n\n    _valid_parents: ClassVar[list[str]] = [\n        \"ContextMenuContent\",\n        \"ContextMenuSubContent\",\n    ]\n\n\nclass ContextMenuRadioGroup(RadixThemesComponent):\n    \"\"\"The component that contains context menu radio items.\"\"\"\n\n    tag = \"ContextMenu.RadioGroup\"\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior. Defaults to False.\n    as_child: Var[bool]\n\n    # The value of the selected item in the group.\n    value: Var[str]\n\n    # Props to rename\n    _rename_props = {\"onChange\": \"onValueChange\"}\n\n    # Fired when the value of the radio group changes.\n    on_change: EventHandler[passthrough_event_spec(str)]\n\n    _valid_parents: ClassVar[list[str]] = [\n        \"ContextMenuRadioItem\",\n        \"ContextMenuSubContent\",\n        \"ContextMenuContent\",\n        \"ContextMenuSub\",\n    ]\n\n\nclass ContextMenuRadioItem(HighLevelRadioGroup):\n    \"\"\"The component that contains context menu radio items.\"\"\"\n\n    tag = \"ContextMenu.RadioItem\"\n\n    # Override theme color for Dropdown Menu Content\n    color_scheme: Var[LiteralAccentColor]\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior. Defaults to False.\n    as_child: Var[bool]\n\n    # The unique value of the item.\n    value: Var[str]\n\n    # When true, prevents the user from interacting with the item.\n    disabled: Var[bool]\n\n    # Event handler called when the user selects an item (via mouse or keyboard). Calling event.preventDefault in this handler will prevent the context menu from closing when selecting that item.\n    on_select: EventHandler[no_args_event_spec]\n\n    # Optional text used for typeahead purposes. By default the typeahead behavior will use the .textContent of the item. Use this when the content is complex, or you have non-textual content inside.\n    text_value: Var[str]\n\n\nclass ContextMenu(ComponentNamespace):\n    \"\"\"Menu representing a set of actions, displayed at the origin of a pointer right-click or long-press.\"\"\"\n\n    root = staticmethod(ContextMenuRoot.create)\n    trigger = staticmethod(ContextMenuTrigger.create)\n    content = staticmethod(ContextMenuContent.create)\n    sub = staticmethod(ContextMenuSub.create)\n    sub_trigger = staticmethod(ContextMenuSubTrigger.create)\n    sub_content = staticmethod(ContextMenuSubContent.create)\n    item = staticmethod(ContextMenuItem.create)\n    separator = staticmethod(ContextMenuSeparator.create)\n    checkbox = staticmethod(ContextMenuCheckbox.create)\n    label = staticmethod(ContextMenuLabel.create)\n    group = staticmethod(ContextMenuGroup.create)\n    radio_group = staticmethod(ContextMenuRadioGroup.create)\n    radio = staticmethod(ContextMenuRadioItem.create)\n\n\ncontext_menu = ContextMenu()\n"
  },
  {
    "path": "reflex/components/radix/themes/components/data_list.py",
    "content": "\"\"\"Components for the DataList component of Radix Themes.\"\"\"\n\nfrom types import SimpleNamespace\nfrom typing import Literal\n\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.radix.themes.base import LiteralAccentColor, RadixThemesComponent\nfrom reflex.vars.base import Var\n\n\nclass DataListRoot(RadixThemesComponent):\n    \"\"\"Root element for a DataList component.\"\"\"\n\n    tag = \"DataList.Root\"\n\n    # The orientation of the data list item: \"horizontal\" | \"vertical\"\n    orientation: Var[Responsive[Literal[\"horizontal\", \"vertical\"]]]\n\n    # The size of the data list item: \"1\" | \"2\" | \"3\"\n    size: Var[Responsive[Literal[\"1\", \"2\", \"3\"]]]\n\n    # Trims the leading whitespace from the start or end of the text.\n    trim: Var[Responsive[Literal[\"normal\", \"start\", \"end\", \"both\"]]]\n\n\nclass DataListItem(RadixThemesComponent):\n    \"\"\"An item in the DataList component.\"\"\"\n\n    tag = \"DataList.Item\"\n\n    # The alignment of the data list item within its container.\n    align: Var[Responsive[Literal[\"start\", \"center\", \"end\", \"baseline\", \"stretch\"]]]\n\n\nclass DataListLabel(RadixThemesComponent):\n    \"\"\"A label in the DataList component.\"\"\"\n\n    tag = \"DataList.Label\"\n\n    # The width of the component\n    width: Var[Responsive[str]]\n\n    # The minimum width of the component\n    min_width: Var[Responsive[str]]\n\n    # The maximum width of the component\n    max_width: Var[Responsive[str]]\n\n    # The color scheme for the DataList component.\n    color_scheme: Var[LiteralAccentColor]\n\n\nclass DataListValue(RadixThemesComponent):\n    \"\"\"A value in the DataList component.\"\"\"\n\n    tag = \"DataList.Value\"\n\n\nclass DataList(SimpleNamespace):\n    \"\"\"DataList components namespace.\"\"\"\n\n    root = staticmethod(DataListRoot.create)\n    item = staticmethod(DataListItem.create)\n    label = staticmethod(DataListLabel.create)\n    value = staticmethod(DataListValue.create)\n\n\ndata_list = DataList()\n"
  },
  {
    "path": "reflex/components/radix/themes/components/dialog.py",
    "content": "\"\"\"Interactive components provided by @radix-ui/themes.\"\"\"\n\nfrom typing import Literal\n\nfrom reflex.components.component import ComponentNamespace\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.el import elements\nfrom reflex.components.radix.themes.base import (\n    RadixThemesComponent,\n    RadixThemesTriggerComponent,\n)\nfrom reflex.constants.compiler import MemoizationMode\nfrom reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec\nfrom reflex.vars.base import Var\n\n\nclass DialogRoot(RadixThemesComponent):\n    \"\"\"Root component for Dialog.\"\"\"\n\n    tag = \"Dialog.Root\"\n\n    # The controlled open state of the dialog.\n    open: Var[bool]\n\n    # Fired when the open state changes.\n    on_open_change: EventHandler[passthrough_event_spec(bool)]\n\n    # The open state of the dialog when it is initially rendered. Use when you do not need to control its open state.\n    default_open: Var[bool]\n\n\nclass DialogTrigger(RadixThemesTriggerComponent):\n    \"\"\"Trigger an action or event, to open a Dialog modal.\"\"\"\n\n    tag = \"Dialog.Trigger\"\n\n    _memoization_mode = MemoizationMode(recursive=False)\n\n\nclass DialogTitle(RadixThemesComponent):\n    \"\"\"Title component to display inside a Dialog modal.\"\"\"\n\n    tag = \"Dialog.Title\"\n\n\nclass DialogContent(elements.Div, RadixThemesComponent):\n    \"\"\"Content component to display inside a Dialog modal.\"\"\"\n\n    tag = \"Dialog.Content\"\n\n    # DialogContent size \"1\" - \"4\"\n    size: Var[Responsive[Literal[\"1\", \"2\", \"3\", \"4\"]]]\n\n    # Fired when the dialog is opened.\n    on_open_auto_focus: EventHandler[no_args_event_spec]\n\n    # Fired when the dialog is closed.\n    on_close_auto_focus: EventHandler[no_args_event_spec]\n\n    # Fired when the escape key is pressed.\n    on_escape_key_down: EventHandler[no_args_event_spec]\n\n    # Fired when the pointer is down outside the dialog.\n    on_pointer_down_outside: EventHandler[no_args_event_spec]\n\n    # Fired when the pointer interacts outside the dialog.\n    on_interact_outside: EventHandler[no_args_event_spec]\n\n\nclass DialogDescription(RadixThemesComponent):\n    \"\"\"Description component to display inside a Dialog modal.\"\"\"\n\n    tag = \"Dialog.Description\"\n\n\nclass DialogClose(RadixThemesTriggerComponent):\n    \"\"\"Close button component to close an open Dialog modal.\"\"\"\n\n    tag = \"Dialog.Close\"\n\n\nclass Dialog(ComponentNamespace):\n    \"\"\"Dialog components namespace.\"\"\"\n\n    root = __call__ = staticmethod(DialogRoot.create)\n    trigger = staticmethod(DialogTrigger.create)\n    title = staticmethod(DialogTitle.create)\n    content = staticmethod(DialogContent.create)\n    description = staticmethod(DialogDescription.create)\n    close = staticmethod(DialogClose.create)\n\n\ndialog = Dialog()\n"
  },
  {
    "path": "reflex/components/radix/themes/components/dropdown_menu.py",
    "content": "\"\"\"Interactive components provided by @radix-ui/themes.\"\"\"\n\nfrom typing import ClassVar, Literal\n\nfrom reflex.components.component import ComponentNamespace\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.radix.themes.base import (\n    LiteralAccentColor,\n    RadixThemesComponent,\n    RadixThemesTriggerComponent,\n)\nfrom reflex.constants.compiler import MemoizationMode\nfrom reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec\nfrom reflex.vars.base import Var\n\nLiteralDirType = Literal[\"ltr\", \"rtl\"]\n\nLiteralSizeType = Literal[\"1\", \"2\"]\n\nLiteralVariantType = Literal[\"solid\", \"soft\"]\n\nLiteralSideType = Literal[\"top\", \"right\", \"bottom\", \"left\"]\n\nLiteralAlignType = Literal[\"start\", \"center\", \"end\"]\n\nLiteralStickyType = Literal[\n    \"partial\",\n    \"always\",\n]\n\n\nclass DropdownMenuRoot(RadixThemesComponent):\n    \"\"\"The Dropdown Menu Root Component.\"\"\"\n\n    tag = \"DropdownMenu.Root\"\n\n    # The open state of the dropdown menu when it is initially rendered. Use when you do not need to control its open state.\n    default_open: Var[bool]\n\n    # The controlled open state of the dropdown menu. Must be used in conjunction with onOpenChange.\n    open: Var[bool]\n\n    # The modality of the dropdown menu. When set to true, interaction with outside elements will be disabled and only menu content will be visible to screen readers. Defaults to True.\n    modal: Var[bool]\n\n    # The reading direction of submenus when applicable. If omitted, inherits globally from DirectionProvider or assumes LTR (left-to-right) reading mode.\n    dir: Var[LiteralDirType]\n\n    _invalid_children: ClassVar[list[str]] = [\"DropdownMenuItem\"]\n\n    # Fired when the open state changes.\n    on_open_change: EventHandler[passthrough_event_spec(bool)]\n\n\nclass DropdownMenuTrigger(RadixThemesTriggerComponent):\n    \"\"\"The button that toggles the dropdown menu.\"\"\"\n\n    tag = \"DropdownMenu.Trigger\"\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior. Defaults to False.\n    as_child: Var[bool]\n\n    _valid_parents: ClassVar[list[str]] = [\"DropdownMenuRoot\"]\n\n    _invalid_children: ClassVar[list[str]] = [\"DropdownMenuContent\"]\n\n    _memoization_mode = MemoizationMode(recursive=False)\n\n\nclass DropdownMenuContent(RadixThemesComponent):\n    \"\"\"The Dropdown Menu Content component that pops out when the dropdown menu is open.\"\"\"\n\n    tag = \"DropdownMenu.Content\"\n\n    # Dropdown Menu Content size \"1\" - \"2\"\n    size: Var[Responsive[LiteralSizeType]]\n\n    # Variant of Dropdown Menu Content: \"solid\" | \"soft\"\n    variant: Var[LiteralVariantType]\n\n    # Override theme color for Dropdown Menu Content\n    color_scheme: Var[LiteralAccentColor]\n\n    # Renders the Dropdown Menu Content in higher contrast\n    high_contrast: Var[bool]\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior. Defaults to False.\n    as_child: Var[bool]\n\n    # When True, keyboard navigation will loop from last item to first, and vice versa. Defaults to False.\n    loop: Var[bool]\n\n    # Used to force mounting when more control is needed. Useful when controlling animation with React animation libraries.\n    force_mount: Var[bool]\n\n    # The preferred side of the trigger to render against when open. Will be reversed when collisions occur and `avoid_collisions` is enabled.The position of the tooltip. Defaults to \"top\".\n    side: Var[LiteralSideType]\n\n    # The distance in pixels from the trigger. Defaults to 0.\n    side_offset: Var[float | int]\n\n    # The preferred alignment against the trigger. May change when collisions occur. Defaults to \"center\".\n    align: Var[LiteralAlignType]\n\n    # An offset in pixels from the \"start\" or \"end\" alignment options.\n    align_offset: Var[float | int]\n\n    # When true, overrides the side and align preferences to prevent collisions with boundary edges. Defaults to True.\n    avoid_collisions: Var[bool]\n\n    # The distance in pixels from the boundary edges where collision detection should occur. Accepts a number (same for all sides), or a partial padding object, for example: { \"top\": 20, \"left\": 20 }. Defaults to 0.\n    collision_padding: Var[float | int | dict[str, float | int]]\n\n    # The sticky behavior on the align axis. \"partial\" will keep the content in the boundary as long as the trigger is at least partially in the boundary whilst \"always\" will keep the content in the boundary regardless. Defaults to \"partial\".\n    sticky: Var[LiteralStickyType]\n\n    # Whether to hide the content when the trigger becomes fully occluded. Defaults to False.\n    hide_when_detached: Var[bool]\n\n    # Fired when the dialog is closed.\n    on_close_auto_focus: EventHandler[no_args_event_spec]\n\n    # Fired when the escape key is pressed.\n    on_escape_key_down: EventHandler[no_args_event_spec]\n\n    # Fired when the pointer is down outside the dialog.\n    on_pointer_down_outside: EventHandler[no_args_event_spec]\n\n    # Fired when focus moves outside the dialog.\n    on_focus_outside: EventHandler[no_args_event_spec]\n\n    # Fired when the pointer interacts outside the dialog.\n    on_interact_outside: EventHandler[no_args_event_spec]\n\n\nclass DropdownMenuSubTrigger(RadixThemesTriggerComponent):\n    \"\"\"An item that opens a submenu.\"\"\"\n\n    tag = \"DropdownMenu.SubTrigger\"\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior. Defaults to False.\n    as_child: Var[bool]\n\n    # When true, prevents the user from interacting with the item.\n    disabled: Var[bool]\n\n    # Optional text used for typeahead purposes. By default the typeahead behavior will use the .textContent of the item. Use this when the content is complex, or you have non-textual content inside.\n    text_value: Var[str]\n\n    _valid_parents: ClassVar[list[str]] = [\"DropdownMenuContent\", \"DropdownMenuSub\"]\n\n    _memoization_mode = MemoizationMode(recursive=False)\n\n\nclass DropdownMenuSub(RadixThemesComponent):\n    \"\"\"Contains all the parts of a submenu.\"\"\"\n\n    tag = \"DropdownMenu.Sub\"\n\n    # The controlled open state of the submenu. Must be used in conjunction with `on_open_change`.\n    open: Var[bool]\n\n    # The open state of the submenu when it is initially rendered. Use when you do not need to control its open state.\n    default_open: Var[bool]\n\n    # Fired when the open state changes.\n    on_open_change: EventHandler[passthrough_event_spec(bool)]\n\n\nclass DropdownMenuSubContent(RadixThemesComponent):\n    \"\"\"The component that pops out when a submenu is open. Must be rendered inside DropdownMenuSub.\"\"\"\n\n    tag = \"DropdownMenu.SubContent\"\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior. Defaults to False.\n    as_child: Var[bool]\n\n    # When True, keyboard navigation will loop from last item to first, and vice versa. Defaults to False.\n    loop: Var[bool]\n\n    # Used to force mounting when more control is needed. Useful when controlling animation with React animation libraries.\n    force_mount: Var[bool]\n\n    # The distance in pixels from the trigger. Defaults to 0.\n    side_offset: Var[float | int]\n\n    # An offset in pixels from the \"start\" or \"end\" alignment options.\n    align_offset: Var[float | int]\n\n    # When true, overrides the side and align preferences to prevent collisions with boundary edges. Defaults to True.\n    avoid_collisions: Var[bool]\n\n    # The distance in pixels from the boundary edges where collision detection should occur. Accepts a number (same for all sides), or a partial padding object, for example: { \"top\": 20, \"left\": 20 }. Defaults to 0.\n    collision_padding: Var[float | int | dict[str, float | int]]\n\n    # The sticky behavior on the align axis. \"partial\" will keep the content in the boundary as long as the trigger is at least partially in the boundary whilst \"always\" will keep the content in the boundary regardless. Defaults to \"partial\".\n    sticky: Var[LiteralStickyType]\n\n    # Whether to hide the content when the trigger becomes fully occluded. Defaults to False.\n    hide_when_detached: Var[bool]\n\n    _valid_parents: ClassVar[list[str]] = [\"DropdownMenuSub\"]\n\n    # Fired when the escape key is pressed.\n    on_escape_key_down: EventHandler[no_args_event_spec]\n\n    # Fired when the pointer is down outside the dialog.\n    on_pointer_down_outside: EventHandler[no_args_event_spec]\n\n    # Fired when focus moves outside the dialog.\n    on_focus_outside: EventHandler[no_args_event_spec]\n\n    # Fired when the pointer interacts outside the dialog.\n    on_interact_outside: EventHandler[no_args_event_spec]\n\n\nclass DropdownMenuItem(RadixThemesComponent):\n    \"\"\"The Dropdown Menu Item Component.\"\"\"\n\n    tag = \"DropdownMenu.Item\"\n\n    # Override theme color for Dropdown Menu Item\n    color_scheme: Var[LiteralAccentColor]\n\n    # Shortcut to render a menu item as a link\n    shortcut: Var[str]\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior. Defaults to False.\n    as_child: Var[bool]\n\n    # When true, prevents the user from interacting with the item.\n    disabled: Var[bool]\n\n    # Optional text used for typeahead purposes. By default the typeahead behavior will use the .textContent of the item. Use this when the content is complex, or you have non-textual content inside.\n    text_value: Var[str]\n\n    _valid_parents: ClassVar[list[str]] = [\n        \"DropdownMenuContent\",\n        \"DropdownMenuSubContent\",\n    ]\n\n    # Fired when the item is selected.\n    on_select: EventHandler[no_args_event_spec]\n\n\nclass DropdownMenuSeparator(RadixThemesComponent):\n    \"\"\"Dropdown Menu Separator Component. Used to visually separate items in the dropdown menu.\"\"\"\n\n    tag = \"DropdownMenu.Separator\"\n\n\nclass DropdownMenu(ComponentNamespace):\n    \"\"\"DropdownMenu components namespace.\"\"\"\n\n    root = staticmethod(DropdownMenuRoot.create)\n    trigger = staticmethod(DropdownMenuTrigger.create)\n    content = staticmethod(DropdownMenuContent.create)\n    sub_trigger = staticmethod(DropdownMenuSubTrigger.create)\n    sub = staticmethod(DropdownMenuSub.create)\n    sub_content = staticmethod(DropdownMenuSubContent.create)\n    item = staticmethod(DropdownMenuItem.create)\n    separator = staticmethod(DropdownMenuSeparator.create)\n\n\nmenu = dropdown_menu = DropdownMenu()\n"
  },
  {
    "path": "reflex/components/radix/themes/components/hover_card.py",
    "content": "\"\"\"Interactive components provided by @radix-ui/themes.\"\"\"\n\nfrom typing import Literal\n\nfrom reflex.components.component import ComponentNamespace\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.el import elements\nfrom reflex.components.radix.themes.base import (\n    RadixThemesComponent,\n    RadixThemesTriggerComponent,\n)\nfrom reflex.constants.compiler import MemoizationMode\nfrom reflex.event import EventHandler, passthrough_event_spec\nfrom reflex.vars.base import Var\n\n\nclass HoverCardRoot(RadixThemesComponent):\n    \"\"\"For sighted users to preview content available behind a link.\"\"\"\n\n    tag = \"HoverCard.Root\"\n\n    # The open state of the hover card when it is initially rendered. Use when you do not need to control its open state.\n    default_open: Var[bool]\n\n    # The controlled open state of the hover card. Must be used in conjunction with onOpenChange.\n    open: Var[bool]\n\n    # The duration from when the mouse enters the trigger until the hover card opens.\n    open_delay: Var[int]\n\n    # The duration from when the mouse leaves the trigger until the hover card closes.\n    close_delay: Var[int]\n\n    # Fired when the open state changes.\n    on_open_change: EventHandler[passthrough_event_spec(bool)]\n\n\nclass HoverCardTrigger(RadixThemesTriggerComponent):\n    \"\"\"Wraps the link that will open the hover card.\"\"\"\n\n    tag = \"HoverCard.Trigger\"\n\n    _memoization_mode = MemoizationMode(recursive=False)\n\n\nclass HoverCardContent(elements.Div, RadixThemesComponent):\n    \"\"\"Contains the content of the open hover card.\"\"\"\n\n    tag = \"HoverCard.Content\"\n\n    # The preferred side of the trigger to render against when open. Will be reversed when collisions occur and avoidCollisions is enabled.\n    side: Var[Responsive[Literal[\"top\", \"right\", \"bottom\", \"left\"]]]\n\n    # The distance in pixels from the trigger.\n    side_offset: Var[int]\n\n    # The preferred alignment against the trigger. May change when collisions occur.\n    align: Var[Literal[\"start\", \"center\", \"end\"]]\n\n    # An offset in pixels from the \"start\" or \"end\" alignment options.\n    align_offset: Var[int]\n\n    # Whether or not the hover card should avoid collisions with its trigger.\n    avoid_collisions: Var[bool]\n\n    # The distance in pixels from the boundary edges where collision detection should occur. Accepts a number (same for all sides), or a partial padding object, for example: { top: 20, left: 20 }.\n    collision_padding: Var[float | int | dict[str, float | int]]\n\n    # The sticky behavior on the align axis. \"partial\" will keep the content in the boundary as long as the trigger is at least partially in the boundary whilst \"always\" will keep the content in the boundary regardless\n    sticky: Var[Literal[\"partial\", \"always\"]]\n\n    # Whether to hide the content when the trigger becomes fully occluded.\n    hide_when_detached: Var[bool]\n\n    # Hovercard size \"1\" - \"3\"\n    size: Var[Responsive[Literal[\"1\", \"2\", \"3\"]]]\n\n\nclass HoverCard(ComponentNamespace):\n    \"\"\"For sighted users to preview content available behind a link.\"\"\"\n\n    root = __call__ = staticmethod(HoverCardRoot.create)\n    trigger = staticmethod(HoverCardTrigger.create)\n    content = staticmethod(HoverCardContent.create)\n\n\nhover_card = HoverCard()\n"
  },
  {
    "path": "reflex/components/radix/themes/components/icon_button.py",
    "content": "\"\"\"Interactive components provided by @radix-ui/themes.\"\"\"\n\nfrom __future__ import annotations\n\nfrom typing import Literal\n\nfrom reflex.components.component import Component\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.core.match import Match\nfrom reflex.components.el import elements\nfrom reflex.components.lucide import Icon\nfrom reflex.components.radix.themes.base import (\n    LiteralAccentColor,\n    LiteralRadius,\n    LiteralVariant,\n    RadixLoadingProp,\n    RadixThemesComponent,\n)\nfrom reflex.style import Style\nfrom reflex.vars.base import Var\n\nLiteralButtonSize = Literal[\"1\", \"2\", \"3\", \"4\"]\n\nRADIX_TO_LUCIDE_SIZE = {\"1\": 12, \"2\": 24, \"3\": 36, \"4\": 48}\n\n\nclass IconButton(elements.Button, RadixLoadingProp, RadixThemesComponent):\n    \"\"\"A button designed specifically for usage with a single icon.\"\"\"\n\n    tag = \"IconButton\"\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior.\n    as_child: Var[bool]\n\n    # Button size \"1\" - \"4\"\n    size: Var[Responsive[LiteralButtonSize]]\n\n    # Variant of button: \"classic\" | \"solid\" | \"soft\" | \"surface\" | \"outline\" | \"ghost\"\n    variant: Var[LiteralVariant]\n\n    # Override theme color for button\n    color_scheme: Var[LiteralAccentColor]\n\n    # Whether to render the button with higher contrast color against background\n    high_contrast: Var[bool]\n\n    # Override theme radius for button: \"none\" | \"small\" | \"medium\" | \"large\" | \"full\"\n    radius: Var[LiteralRadius]\n\n    @classmethod\n    def create(cls, *children, **props) -> Component:\n        \"\"\"Create a IconButton component.\n\n        Args:\n            *children: The children of the component.\n            **props: The properties of the component.\n\n        Returns:\n            The IconButton component.\n\n        Raises:\n            ValueError: If no children are passed.\n        \"\"\"\n        if children:\n            if isinstance(children[0], str):\n                children = [\n                    Icon.create(\n                        children[0],\n                    )\n                ]\n        else:\n            msg = \"IconButton requires a child icon. Pass a string as the first child or a rx.icon.\"\n            raise ValueError(msg)\n        if \"size\" in props:\n            if isinstance(props[\"size\"], str):\n                children[0].size = RADIX_TO_LUCIDE_SIZE[props[\"size\"]]  # pyright: ignore[reportAttributeAccessIssue]\n            else:\n                size_map_var = Match.create(\n                    props[\"size\"],\n                    *list(RADIX_TO_LUCIDE_SIZE.items()),\n                    12,\n                )\n                if not isinstance(size_map_var, Var):\n                    msg = f\"Match did not return a Var: {size_map_var}\"\n                    raise ValueError(msg)\n                children[0].size = size_map_var  # pyright: ignore[reportAttributeAccessIssue]\n        return super().create(*children, **props)\n\n    def add_style(self):\n        \"\"\"Add style to the component.\n\n        Returns:\n            The style of the component.\n        \"\"\"\n        return Style({\"padding\": \"6px\"})\n\n\nicon_button = IconButton.create\n"
  },
  {
    "path": "reflex/components/radix/themes/components/inset.py",
    "content": "\"\"\"Interactive components provided by @radix-ui/themes.\"\"\"\n\nfrom typing import Literal\n\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.el import elements\nfrom reflex.components.radix.themes.base import RadixThemesComponent\nfrom reflex.vars.base import Var\n\nLiteralButtonSize = Literal[\"1\", \"2\", \"3\", \"4\"]\n\n\nclass Inset(elements.Div, RadixThemesComponent):\n    \"\"\"Applies a negative margin to allow content to bleed into the surrounding container.\"\"\"\n\n    tag = \"Inset\"\n\n    # The side\n    side: Var[Responsive[Literal[\"x\", \"y\", \"top\", \"bottom\", \"right\", \"left\"]]]\n\n    # How to clip the element's content: \"border-box\" | \"padding-box\"\n    clip: Var[Responsive[Literal[\"border-box\", \"padding-box\"]]]\n\n    # Padding\n    p: Var[Responsive[int | str]]\n\n    # Padding on the x axis\n    px: Var[Responsive[int | str]]\n\n    # Padding on the y axis\n    py: Var[Responsive[int | str]]\n\n    # Padding on the top\n    pt: Var[Responsive[int | str]]\n\n    # Padding on the right\n    pr: Var[Responsive[int | str]]\n\n    # Padding on the bottom\n    pb: Var[Responsive[int | str]]\n\n    # Padding on the left\n    pl: Var[Responsive[int | str]]\n\n\ninset = Inset.create\n"
  },
  {
    "path": "reflex/components/radix/themes/components/popover.py",
    "content": "\"\"\"Interactive components provided by @radix-ui/themes.\"\"\"\n\nfrom typing import Literal\n\nfrom reflex.components.component import ComponentNamespace\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.el import elements\nfrom reflex.components.radix.themes.base import (\n    RadixThemesComponent,\n    RadixThemesTriggerComponent,\n)\nfrom reflex.constants.compiler import MemoizationMode\nfrom reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec\nfrom reflex.vars.base import Var\n\n\nclass PopoverRoot(RadixThemesComponent):\n    \"\"\"Floating element for displaying rich content, triggered by a button.\"\"\"\n\n    tag = \"Popover.Root\"\n\n    # The controlled open state of the popover.\n    open: Var[bool]\n\n    # The modality of the popover. When set to true, interaction with outside elements will be disabled and only popover content will be visible to screen readers.\n    modal: Var[bool]\n\n    # Fired when the open state changes.\n    on_open_change: EventHandler[passthrough_event_spec(bool)]\n\n    # The open state of the popover when it is initially rendered. Use when you do not need to control its open state.\n    default_open: Var[bool]\n\n\nclass PopoverTrigger(RadixThemesTriggerComponent):\n    \"\"\"Wraps the control that will open the popover.\"\"\"\n\n    tag = \"Popover.Trigger\"\n\n    _memoization_mode = MemoizationMode(recursive=False)\n\n\nclass PopoverContent(elements.Div, RadixThemesComponent):\n    \"\"\"Contains content to be rendered in the open popover.\"\"\"\n\n    tag = \"Popover.Content\"\n\n    # Size of the button: \"1\" | \"2\" | \"3\" | \"4\"\n    size: Var[Responsive[Literal[\"1\", \"2\", \"3\", \"4\"]]]\n\n    # The preferred side of the anchor to render against when open. Will be reversed when collisions occur and avoidCollisions is enabled.\n    side: Var[Literal[\"top\", \"right\", \"bottom\", \"left\"]]\n\n    # The distance in pixels from the anchor.\n    side_offset: Var[int]\n\n    # The preferred alignment against the anchor. May change when collisions occur.\n    align: Var[Literal[\"start\", \"center\", \"end\"]]\n\n    # The vertical distance in pixels from the anchor.\n    align_offset: Var[int]\n\n    # When true, overrides the side andalign preferences to prevent collisions with boundary edges.\n    avoid_collisions: Var[bool]\n\n    # The distance in pixels from the boundary edges where collision detection should occur. Accepts a number (same for all sides), or a partial padding object, for example: { \"top\": 20, \"left\": 20 }. Defaults to 0.\n    collision_padding: Var[float | int | dict[str, float | int]]\n\n    # The sticky behavior on the align axis. \"partial\" will keep the content in the boundary as long as the trigger is at least partially in the boundary whilst \"always\" will keep the content in the boundary regardless. Defaults to \"partial\".\n    sticky: Var[Literal[\"partial\", \"always\"]]\n\n    # Whether to hide the content when the trigger becomes fully occluded. Defaults to False.\n    hide_when_detached: Var[bool]\n\n    # Fired when the dialog is opened.\n    on_open_auto_focus: EventHandler[no_args_event_spec]\n\n    # Fired when the dialog is closed.\n    on_close_auto_focus: EventHandler[no_args_event_spec]\n\n    # Fired when the escape key is pressed.\n    on_escape_key_down: EventHandler[no_args_event_spec]\n\n    # Fired when the pointer is down outside the dialog.\n    on_pointer_down_outside: EventHandler[no_args_event_spec]\n\n    # Fired when focus moves outside the dialog.\n    on_focus_outside: EventHandler[no_args_event_spec]\n\n    # Fired when the pointer interacts outside the dialog.\n    on_interact_outside: EventHandler[no_args_event_spec]\n\n\nclass PopoverClose(RadixThemesTriggerComponent):\n    \"\"\"Wraps the control that will close the popover.\"\"\"\n\n    tag = \"Popover.Close\"\n\n\nclass Popover(ComponentNamespace):\n    \"\"\"Floating element for displaying rich content, triggered by a button.\"\"\"\n\n    root = staticmethod(PopoverRoot.create)\n    trigger = staticmethod(PopoverTrigger.create)\n    content = staticmethod(PopoverContent.create)\n    close = staticmethod(PopoverClose.create)\n\n\npopover = Popover()\n"
  },
  {
    "path": "reflex/components/radix/themes/components/progress.py",
    "content": "\"\"\"Progress from Radix Themes.\"\"\"\n\nfrom typing import Literal\n\nfrom reflex.components.component import Component\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.radix.themes.base import LiteralAccentColor, RadixThemesComponent\nfrom reflex.style import Style\nfrom reflex.vars.base import Var\n\n\nclass Progress(RadixThemesComponent):\n    \"\"\"A progress bar component.\"\"\"\n\n    tag = \"Progress\"\n\n    # The value of the progress bar: 0 to max (default 100)\n    value: Var[int]\n\n    # The maximum progress value.\n    max: Var[int]\n\n    # The size of the progress bar: \"1\" | \"2\" | \"3\"\n    size: Var[Responsive[Literal[\"1\", \"2\", \"3\"]]]\n\n    # The variant of the progress bar: \"classic\" | \"surface\" | \"soft\"\n    variant: Var[Literal[\"classic\", \"surface\", \"soft\"]]\n\n    # The color theme of the progress bar\n    color_scheme: Var[LiteralAccentColor]\n\n    # Whether to render the progress bar with higher contrast color against background\n    high_contrast: Var[bool]\n\n    # Override theme radius for progress bar: \"none\" | \"small\" | \"medium\" | \"large\" | \"full\"\n    radius: Var[Literal[\"none\", \"small\", \"medium\", \"large\", \"full\"]]\n\n    # The duration of the progress bar animation. Once the duration times out, the progress bar will start an indeterminate animation.\n    duration: Var[str]\n\n    # The color of the progress bar fill animation.\n    fill_color: Var[str]\n\n    @staticmethod\n    def _color_selector(color: str) -> Style:\n        \"\"\"Return a style object with the correct color and css selector.\n\n        Args:\n            color: Color of the fill part.\n\n        Returns:\n            Style: Style object with the correct css selector and color.\n        \"\"\"\n        return Style({\".rt-ProgressIndicator\": {\"background_color\": color}})\n\n    @classmethod\n    def create(cls, *children, **props) -> Component:\n        \"\"\"Create a Progress component.\n\n        Args:\n            *children: The children of the component.\n            **props: The properties of the component.\n\n        Returns:\n            The Progress Component.\n        \"\"\"\n        props.setdefault(\"width\", \"100%\")\n        if \"fill_color\" in props:\n            color = props.get(\"fill_color\", \"\")\n            style = props.get(\"style\", {})\n            style = style | cls._color_selector(color)\n            props[\"style\"] = style\n\n        return super().create(*children, **props)\n\n\nprogress = Progress.create\n"
  },
  {
    "path": "reflex/components/radix/themes/components/radio.py",
    "content": "\"\"\"Radio component from Radix Themes.\"\"\"\n\nfrom typing import Literal\n\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.radix.themes.base import LiteralAccentColor, RadixThemesComponent\nfrom reflex.vars.base import Var\n\n\nclass Radio(RadixThemesComponent):\n    \"\"\"A radio component.\"\"\"\n\n    tag = \"Radio\"\n\n    # The size of the radio: \"1\" | \"2\" | \"3\"\n    size: Var[Responsive[Literal[\"1\", \"2\", \"3\"]]]\n\n    # Variant of button: \"classic\" | \"surface\" | \"soft\"\n    variant: Var[Literal[\"classic\", \"surface\", \"soft\"]]\n\n    # Override theme color for button\n    color_scheme: Var[LiteralAccentColor]\n\n    # Uses a higher contrast color for the component.\n    high_contrast: Var[bool]\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior.\n    as_child = Var[bool]\n\n\nradio = Radio.create\n"
  },
  {
    "path": "reflex/components/radix/themes/components/radio_cards.py",
    "content": "\"\"\"Radio component from Radix Themes.\"\"\"\n\nfrom types import SimpleNamespace\nfrom typing import ClassVar, Literal\n\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.radix.themes.base import LiteralAccentColor, RadixThemesComponent\nfrom reflex.event import EventHandler, passthrough_event_spec\nfrom reflex.vars.base import Var\n\n\nclass RadioCardsRoot(RadixThemesComponent):\n    \"\"\"Root element for RadioCards component.\"\"\"\n\n    tag = \"RadioCards.Root\"\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior.\n    as_child: Var[bool]\n\n    # The size of the checkbox cards: \"1\" | \"2\" | \"3\"\n    size: Var[Responsive[Literal[\"1\", \"2\", \"3\"]]]\n\n    # Variant of button: \"classic\" | \"surface\" | \"soft\"\n    variant: Var[Literal[\"classic\", \"surface\"]]\n\n    # Override theme color for button\n    color_scheme: Var[LiteralAccentColor]\n\n    # Uses a higher contrast color for the component.\n    high_contrast: Var[bool]\n\n    # The number of columns:\n    columns: Var[Responsive[str | Literal[\"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\"]]]\n\n    # The gap between the checkbox cards:\n    gap: Var[Responsive[str | Literal[\"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\"]]]\n\n    default_value: Var[str]\n\n    # The controlled value of the radio item to check. Should be used in conjunction with onValueChange.\n    value: Var[str]\n\n    # The name of the group. Submitted with its owning form as part of a name/value pair.\n    name: Var[str]\n\n    # When true, prevents the user from interacting with radio items.\n    disabled: Var[bool]\n\n    # When true, indicates that the user must check a radio item before the owning form can be submitted.\n    required: Var[bool]\n\n    # The orientation of the component.\n    orientation: Var[Literal[\"horizontal\", \"vertical\", \"undefined\"]]\n\n    # The reading direction of the radio group. If omitted,\n    # inherits globally from DirectionProvider or assumes LTR (left-to-right) reading mode.\n    dir: Var[Literal[\"ltr\", \"rtl\"]]\n\n    # When true, keyboard navigation will loop from last item to first, and vice versa.\n    loop: Var[bool]\n\n    # Event handler called when the value changes.\n    on_value_change: EventHandler[passthrough_event_spec(str)]\n\n\nclass RadioCardsItem(RadixThemesComponent):\n    \"\"\"Item element for RadioCards component.\"\"\"\n\n    tag = \"RadioCards.Item\"\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior.\n    as_child: Var[bool]\n\n    # The value given as data when submitted with a name.\n    value: Var[str]\n\n    # When true, prevents the user from interacting with the radio item.\n    disabled: Var[bool]\n\n    # When true, indicates that the user must check the radio item before the owning form can be submitted.\n    required: Var[bool]\n\n    _valid_parents: ClassVar[list[str]] = [\"RadioCardsRoot\"]\n\n\nclass RadioCards(SimpleNamespace):\n    \"\"\"RadioCards components namespace.\"\"\"\n\n    root = staticmethod(RadioCardsRoot.create)\n    item = staticmethod(RadioCardsItem.create)\n\n\nradio_cards = RadioCards()\n"
  },
  {
    "path": "reflex/components/radix/themes/components/radio_group.py",
    "content": "\"\"\"Interactive components provided by @radix-ui/themes.\"\"\"\n\nfrom __future__ import annotations\n\nfrom collections.abc import Sequence\nfrom typing import Literal\n\nimport reflex as rx\nfrom reflex.components.component import Component, ComponentNamespace\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.radix.themes.base import (\n    LiteralAccentColor,\n    LiteralSpacing,\n    RadixThemesComponent,\n)\nfrom reflex.components.radix.themes.layout.flex import Flex\nfrom reflex.components.radix.themes.typography.text import Text\nfrom reflex.event import EventHandler, passthrough_event_spec\nfrom reflex.utils import types\nfrom reflex.vars.base import LiteralVar, Var\nfrom reflex.vars.sequence import StringVar\n\nLiteralFlexDirection = Literal[\"row\", \"column\", \"row-reverse\", \"column-reverse\"]\n\n\nclass RadioGroupRoot(RadixThemesComponent):\n    \"\"\"A set of interactive radio buttons where only one can be selected at a time.\"\"\"\n\n    tag = \"RadioGroup.Root\"\n\n    # The size of the radio group: \"1\" | \"2\" | \"3\"\n    size: Var[Responsive[Literal[\"1\", \"2\", \"3\"]]] = LiteralVar.create(\"2\")\n\n    # The variant of the radio group\n    variant: Var[Literal[\"classic\", \"surface\", \"soft\"]] = LiteralVar.create(\"classic\")\n\n    # The color of the radio group\n    color_scheme: Var[LiteralAccentColor]\n\n    # Whether to render the radio group with higher contrast color against background\n    high_contrast: Var[bool]\n\n    # The controlled value of the radio item to check. Should be used in conjunction with on_change.\n    value: Var[str]\n\n    # The initial value of checked radio item. Should be used in conjunction with on_change.\n    default_value: Var[str]\n\n    # Whether the radio group is disabled\n    disabled: Var[bool]\n\n    # The name of the group. Submitted with its owning form as part of a name/value pair.\n    name: Var[str]\n\n    # Whether the radio group is required\n    required: Var[bool]\n\n    # Props to rename\n    _rename_props = {\"onChange\": \"onValueChange\"}\n\n    # Fired when the value of the radio group changes.\n    on_change: EventHandler[passthrough_event_spec(str)]\n\n\nclass RadioGroupItem(RadixThemesComponent):\n    \"\"\"An item in the group that can be checked.\"\"\"\n\n    tag = \"RadioGroup.Item\"\n\n    # The value of the radio item to check. Should be used in conjunction with on_change.\n    value: Var[str]\n\n    # When true, prevents the user from interacting with the radio item.\n    disabled: Var[bool]\n\n    # When true, indicates that the user must check the radio item before the owning form can be submitted.\n    required: Var[bool]\n\n\nclass HighLevelRadioGroup(RadixThemesComponent):\n    \"\"\"High level wrapper for the RadioGroup component.\"\"\"\n\n    # The items of the radio group.\n    items: Var[Sequence[str]]\n\n    # The direction of the radio group.\n    direction: Var[LiteralFlexDirection] = LiteralVar.create(\"row\")\n\n    # The gap between the items of the radio group.\n    spacing: Var[LiteralSpacing] = LiteralVar.create(\"2\")\n\n    # The size of the radio group.\n    size: Var[Literal[\"1\", \"2\", \"3\"]] = LiteralVar.create(\"2\")\n\n    # The variant of the radio group\n    variant: Var[Literal[\"classic\", \"surface\", \"soft\"]] = LiteralVar.create(\"classic\")\n\n    # The color of the radio group\n    color_scheme: Var[LiteralAccentColor]\n\n    # Whether to render the radio group with higher contrast color against background\n    high_contrast: Var[bool]\n\n    # The controlled value of the radio item to check. Should be used in conjunction with on_change.\n    value: Var[str]\n\n    # The initial value of checked radio item. Should be used in conjunction with on_change.\n    default_value: Var[str]\n\n    # Whether the radio group is disabled\n    disabled: Var[bool]\n\n    # The name of the group. Submitted with its owning form as part of a name/value pair.\n    name: Var[str]\n\n    # Whether the radio group is required\n    required: Var[bool]\n\n    # Props to rename\n    _rename_props = {\"onChange\": \"onValueChange\"}\n\n    @classmethod\n    def create(\n        cls,\n        items: Var[Sequence[str | int | float | list | dict | bool | None]],\n        **props,\n    ) -> Component:\n        \"\"\"Create a radio group component.\n\n        Args:\n            items: The items of the radio group.\n            **props: Additional properties to apply to the accordion item.\n\n        Returns:\n            The created radio group component.\n\n        Raises:\n            TypeError: If the type of items is invalid.\n        \"\"\"\n        direction = props.pop(\"direction\", \"row\")\n        spacing = props.pop(\"spacing\", \"2\")\n        size = props.pop(\"size\", \"2\")\n        variant = props.pop(\"variant\", \"classic\")\n        color_scheme = props.pop(\"color_scheme\", None)\n        default_value = props.pop(\"default_value\", \"\")\n\n        if not isinstance(items, (list, Var)) or (\n            isinstance(items, Var) and not types._issubclass(items._var_type, list)\n        ):\n            items_type = type(items) if not isinstance(items, Var) else items._var_type\n            msg = f\"The radio group component takes in a list, got {items_type} instead\"\n            raise TypeError(msg)\n\n        default_value = LiteralVar.create(default_value)\n\n        # convert only non-strings to json(JSON.stringify) so quotes are not rendered\n        # for string literal types.\n        if isinstance(default_value, str) or (\n            isinstance(default_value, Var) and default_value._var_type is str\n        ):\n            default_value = LiteralVar.create(default_value)\n        else:\n            default_value = LiteralVar.create(default_value).to_string()\n\n        def radio_group_item(value: Var) -> Component:\n            item_value = rx.cond(\n                value.js_type() == \"string\",\n                value,\n                value.to_string(),\n            ).to(StringVar)\n\n            return Text.create(\n                Flex.create(\n                    RadioGroupItem.create(\n                        value=item_value,\n                        disabled=props.get(\"disabled\", LiteralVar.create(False)),\n                    ),\n                    item_value,\n                    spacing=\"2\",\n                ),\n                size=size,\n                as_=\"label\",\n            )\n\n        children = [\n            rx.foreach(\n                items,\n                radio_group_item,\n            )\n        ]\n\n        return RadioGroupRoot.create(\n            Flex.create(\n                *children,\n                direction=direction,\n                spacing=spacing,\n            ),\n            size=size,\n            variant=variant,\n            color_scheme=color_scheme,\n            default_value=default_value,\n            **props,\n        )\n\n\nclass RadioGroup(ComponentNamespace):\n    \"\"\"RadioGroup components namespace.\"\"\"\n\n    root = staticmethod(RadioGroupRoot.create)\n    item = staticmethod(RadioGroupItem.create)\n    __call__ = staticmethod(HighLevelRadioGroup.create)\n\n\nradio = radio_group = RadioGroup()\n"
  },
  {
    "path": "reflex/components/radix/themes/components/scroll_area.py",
    "content": "\"\"\"Interactive components provided by @radix-ui/themes.\"\"\"\n\nfrom typing import Literal\n\nfrom reflex.components.radix.themes.base import RadixThemesComponent\nfrom reflex.vars.base import Var\n\n\nclass ScrollArea(RadixThemesComponent):\n    \"\"\"Custom styled, cross-browser scrollable area using native functionality.\"\"\"\n\n    tag = \"ScrollArea\"\n\n    # The alignment of the scroll area\n    scrollbars: Var[Literal[\"vertical\", \"horizontal\", \"both\"]]\n\n    # Describes the nature of scrollbar visibility, similar to how the scrollbar preferences in MacOS control visibility of native scrollbars. \"auto\" | \"always\" | \"scroll\" | \"hover\"\n    type: Var[Literal[\"auto\", \"always\", \"scroll\", \"hover\"]]\n\n    # If type is set to either \"scroll\" or \"hover\", this prop determines the length of time, in milliseconds, before the scrollbars are hidden after the user stops interacting with scrollbars.\n    scroll_hide_delay: Var[int]\n\n\nscroll_area = ScrollArea.create\n"
  },
  {
    "path": "reflex/components/radix/themes/components/segmented_control.py",
    "content": "\"\"\"SegmentedControl from Radix Themes.\"\"\"\n\nfrom __future__ import annotations\n\nfrom collections.abc import Sequence\nfrom types import SimpleNamespace\nfrom typing import ClassVar, Literal\n\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.radix.themes.base import LiteralAccentColor, RadixThemesComponent\nfrom reflex.event import EventHandler\nfrom reflex.vars.base import Var\n\n\ndef on_value_change(\n    value: Var[str | list[str]],\n) -> tuple[Var[str | list[str]]]:\n    \"\"\"Handle the on_value_change event.\n\n    Args:\n        value: The value of the event.\n\n    Returns:\n        The value of the event.\n    \"\"\"\n    return (value,)\n\n\nclass SegmentedControlRoot(RadixThemesComponent):\n    \"\"\"Root element for a SegmentedControl component.\"\"\"\n\n    tag = \"SegmentedControl.Root\"\n\n    # The size of the segmented control: \"1\" | \"2\" | \"3\"\n    size: Var[Responsive[Literal[\"1\", \"2\", \"3\"]]]\n\n    # Variant of button: \"classic\" | \"surface\"\n    variant: Var[Literal[\"classic\", \"surface\"]]\n\n    # The type of the segmented control, either \"single\" for selecting one option or \"multiple\" for selecting multiple options.\n    type: Var[Literal[\"single\", \"multiple\"]]\n\n    # Override theme color for button\n    color_scheme: Var[LiteralAccentColor]\n\n    # The radius of the segmented control: \"none\" | \"small\" | \"medium\" | \"large\" | \"full\"\n    radius: Var[Literal[\"none\", \"small\", \"medium\", \"large\", \"full\"]]\n\n    # The default value of the segmented control.\n    default_value: Var[str | Sequence[str]]\n\n    # The current value of the segmented control.\n    value: Var[str | Sequence[str]]\n\n    # Handles the `onChange` event for the SegmentedControl component.\n    on_change: EventHandler[on_value_change]\n\n    _rename_props = {\"onChange\": \"onValueChange\"}\n\n\nclass SegmentedControlItem(RadixThemesComponent):\n    \"\"\"An item in the SegmentedControl component.\"\"\"\n\n    tag = \"SegmentedControl.Item\"\n\n    # The value of the item.\n    value: Var[str]\n\n    _valid_parents: ClassVar[list[str]] = [\"SegmentedControlRoot\"]\n\n\nclass SegmentedControl(SimpleNamespace):\n    \"\"\"SegmentedControl components namespace.\"\"\"\n\n    root = staticmethod(SegmentedControlRoot.create)\n    item = staticmethod(SegmentedControlItem.create)\n\n\nsegmented_control = SegmentedControl()\n"
  },
  {
    "path": "reflex/components/radix/themes/components/select.py",
    "content": "\"\"\"Interactive components provided by @radix-ui/themes.\"\"\"\n\nfrom collections.abc import Sequence\nfrom typing import ClassVar, Literal\n\nimport reflex as rx\nfrom reflex.components.component import Component, ComponentNamespace\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.radix.themes.base import (\n    LiteralAccentColor,\n    LiteralRadius,\n    RadixThemesComponent,\n)\nfrom reflex.constants.compiler import MemoizationMode\nfrom reflex.event import no_args_event_spec, passthrough_event_spec\nfrom reflex.vars.base import Var\n\n\nclass SelectRoot(RadixThemesComponent):\n    \"\"\"Displays a list of options for the user to pick from, triggered by a button.\"\"\"\n\n    tag = \"Select.Root\"\n\n    # The size of the select: \"1\" | \"2\" | \"3\"\n    size: Var[Responsive[Literal[\"1\", \"2\", \"3\"]]]\n\n    # The value of the select when initially rendered. Use when you do not need to control the state of the select.\n    default_value: Var[str]\n\n    # The controlled value of the select. Should be used in conjunction with on_change.\n    value: Var[str]\n\n    # The open state of the select when it is initially rendered. Use when you do not need to control its open state.\n    default_open: Var[bool]\n\n    # The controlled open state of the select. Must be used in conjunction with on_open_change.\n    open: Var[bool]\n\n    # The name of the select control when submitting the form.\n    name: Var[str]\n\n    # When True, prevents the user from interacting with select.\n    disabled: Var[bool]\n\n    # When True, indicates that the user must select a value before the owning form can be submitted.\n    required: Var[bool]\n\n    # Props to rename\n    _rename_props = {\"onChange\": \"onValueChange\"}\n\n    # Fired when the value of the select changes.\n    on_change: rx.EventHandler[passthrough_event_spec(str)]\n\n    # Fired when the select is opened or closed.\n    on_open_change: rx.EventHandler[passthrough_event_spec(bool)]\n\n\nclass SelectTrigger(RadixThemesComponent):\n    \"\"\"The button that toggles the select.\"\"\"\n\n    tag = \"Select.Trigger\"\n\n    # Variant of the select trigger\n    variant: Var[Literal[\"classic\", \"surface\", \"soft\", \"ghost\"]]\n\n    # The color of the select trigger\n    color_scheme: Var[LiteralAccentColor]\n\n    # The radius of the select trigger\n    radius: Var[LiteralRadius]\n\n    # The placeholder of the select trigger\n    placeholder: Var[str]\n\n    _valid_parents: ClassVar[list[str]] = [\"SelectRoot\"]\n\n    _memoization_mode = MemoizationMode(recursive=False)\n\n\nclass SelectContent(RadixThemesComponent):\n    \"\"\"The component that pops out when the select is open.\"\"\"\n\n    tag = \"Select.Content\"\n\n    # The variant of the select content\n    variant: Var[Literal[\"solid\", \"soft\"]]\n\n    # The color of the select content\n    color_scheme: Var[LiteralAccentColor]\n\n    # Whether to render the select content with higher contrast color against background\n    high_contrast: Var[bool]\n\n    # The positioning mode to use, item-aligned is the default and behaves similarly to a native MacOS menu by positioning content relative to the active item. popper positions content in the same way as our other primitives, for example Popover or DropdownMenu.\n    position: Var[Literal[\"item-aligned\", \"popper\"]]\n\n    # The preferred side of the anchor to render against when open. Will be reversed when collisions occur and avoidCollisions is enabled. Only available when position is set to popper.\n    side: Var[Literal[\"top\", \"right\", \"bottom\", \"left\"]]\n\n    # The distance in pixels from the anchor. Only available when position is set to popper.\n    side_offset: Var[int]\n\n    # The preferred alignment against the anchor. May change when collisions occur. Only available when position is set to popper.\n    align: Var[Literal[\"start\", \"center\", \"end\"]]\n\n    # The vertical distance in pixels from the anchor. Only available when position is set to popper.\n    align_offset: Var[int]\n\n    # Fired when the select content is closed.\n    on_close_auto_focus: rx.EventHandler[no_args_event_spec]\n\n    # Fired when the escape key is pressed.\n    on_escape_key_down: rx.EventHandler[no_args_event_spec]\n\n    # Fired when a pointer down event happens outside the select content.\n    on_pointer_down_outside: rx.EventHandler[no_args_event_spec]\n\n\nclass SelectGroup(RadixThemesComponent):\n    \"\"\"Used to group multiple items.\"\"\"\n\n    tag = \"Select.Group\"\n\n    _valid_parents: ClassVar[list[str]] = [\"SelectContent\"]\n\n\nclass SelectItem(RadixThemesComponent):\n    \"\"\"The component that contains the select items.\"\"\"\n\n    tag = \"Select.Item\"\n\n    # The value given as data when submitting a form with a name.\n    value: Var[str]\n\n    # Whether the select item is disabled\n    disabled: Var[bool]\n\n    _valid_parents: ClassVar[list[str]] = [\"SelectGroup\", \"SelectContent\"]\n\n\nclass SelectLabel(RadixThemesComponent):\n    \"\"\"Used to render the label of a group, it isn't focusable using arrow keys.\"\"\"\n\n    tag = \"Select.Label\"\n\n    _valid_parents: ClassVar[list[str]] = [\"SelectGroup\"]\n\n\nclass SelectSeparator(RadixThemesComponent):\n    \"\"\"Used to visually separate items in the Select.\"\"\"\n\n    tag = \"Select.Separator\"\n\n\nclass HighLevelSelect(SelectRoot):\n    \"\"\"High level wrapper for the Select component.\"\"\"\n\n    # The items of the select.\n    items: Var[Sequence[str]]\n\n    # The placeholder of the select.\n    placeholder: Var[str]\n\n    # The label of the select.\n    label: Var[str]\n\n    # The color of the select.\n    color_scheme: Var[LiteralAccentColor]\n\n    # Whether to render the select with higher contrast color against background.\n    high_contrast: Var[bool]\n\n    # The variant of the select.\n    variant: Var[Literal[\"classic\", \"surface\", \"soft\", \"ghost\"]]\n\n    # The radius of the select.\n    radius: Var[LiteralRadius]\n\n    # The width of the select.\n    width: Var[str]\n\n    # The positioning mode to use. Default is \"item-aligned\".\n    position: Var[Literal[\"item-aligned\", \"popper\"]]\n\n    @classmethod\n    def create(cls, items: list[str] | Var[list[str]], **props) -> Component:\n        \"\"\"Create a select component.\n\n        Args:\n            items: The items of the select.\n            **props: Additional properties to apply to the select component.\n\n        Returns:\n            The select component.\n        \"\"\"\n        trigger_prop_list = [\n            \"id\",\n            \"placeholder\",\n            \"variant\",\n            \"radius\",\n            \"width\",\n            \"flex_shrink\",\n            \"custom_attrs\",\n        ]\n\n        content_props = {\n            prop: props.pop(prop)\n            for prop in [\"high_contrast\", \"position\"]\n            if prop in props\n        }\n\n        trigger_props = {\n            prop: props.pop(prop) for prop in trigger_prop_list if prop in props\n        }\n\n        color_scheme = props.pop(\"color_scheme\", None)\n\n        if color_scheme is not None:\n            content_props[\"color_scheme\"] = color_scheme\n            trigger_props[\"color_scheme\"] = color_scheme\n\n        label = props.pop(\"label\", None)\n\n        if isinstance(items, Var):\n            child = [\n                rx.foreach(items, lambda item: SelectItem.create(item, value=item))\n            ]\n        else:\n            child = [SelectItem.create(item, value=item) for item in items]\n\n        return SelectRoot.create(\n            SelectTrigger.create(\n                **trigger_props,\n            ),\n            SelectContent.create(\n                SelectGroup.create(\n                    SelectLabel.create(label) if label is not None else \"\",\n                    *child,\n                ),\n                **content_props,\n            ),\n            **props,\n        )\n\n\nclass Select(ComponentNamespace):\n    \"\"\"Select components namespace.\"\"\"\n\n    root = staticmethod(SelectRoot.create)\n    trigger = staticmethod(SelectTrigger.create)\n    content = staticmethod(SelectContent.create)\n    group = staticmethod(SelectGroup.create)\n    item = staticmethod(SelectItem.create)\n    separator = staticmethod(SelectSeparator.create)\n    label = staticmethod(SelectLabel.create)\n    __call__ = staticmethod(HighLevelSelect.create)\n\n\nselect = Select()\n"
  },
  {
    "path": "reflex/components/radix/themes/components/separator.py",
    "content": "\"\"\"Interactive components provided by @radix-ui/themes.\"\"\"\n\nfrom typing import Literal\n\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.radix.themes.base import LiteralAccentColor, RadixThemesComponent\nfrom reflex.vars.base import LiteralVar, Var\n\nLiteralSeparatorSize = Literal[\"1\", \"2\", \"3\", \"4\"]\n\n\nclass Separator(RadixThemesComponent):\n    \"\"\"Visually or semantically separates content.\"\"\"\n\n    tag = \"Separator\"\n\n    # The size of the separator: \"1\" | \"2\" | \"3\" | \"4\"\n    size: Var[Responsive[LiteralSeparatorSize]] = LiteralVar.create(\"4\")\n\n    # The color of the separator\n    color_scheme: Var[LiteralAccentColor]\n\n    # The orientation of the separator.\n    orientation: Var[Responsive[Literal[\"horizontal\", \"vertical\"]]]\n\n    # When true, signifies that it is purely visual, carries no semantic meaning, and ensures it is not present in the accessibility tree.\n    decorative: Var[bool]\n\n\n# Alias to divider.\ndivider = separator = Separator.create\n"
  },
  {
    "path": "reflex/components/radix/themes/components/skeleton.py",
    "content": "\"\"\"Skeleton theme from Radix components.\"\"\"\n\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.radix.themes.base import RadixLoadingProp, RadixThemesComponent\nfrom reflex.constants.compiler import MemoizationMode\nfrom reflex.vars.base import Var\n\n\nclass Skeleton(RadixLoadingProp, RadixThemesComponent):\n    \"\"\"Skeleton component.\"\"\"\n\n    tag = \"Skeleton\"\n\n    # The width of the skeleton\n    width: Var[Responsive[str]]\n\n    # The minimum width of the skeleton\n    min_width: Var[Responsive[str]]\n\n    # The maximum width of the skeleton\n    max_width: Var[Responsive[str]]\n\n    # The height of the skeleton\n    height: Var[Responsive[str]]\n\n    # The minimum height of the skeleton\n    min_height: Var[Responsive[str]]\n\n    # The maximum height of the skeleton\n    max_height: Var[Responsive[str]]\n\n    _memoization_mode = MemoizationMode(recursive=False)\n\n\nskeleton = Skeleton.create\n"
  },
  {
    "path": "reflex/components/radix/themes/components/slider.py",
    "content": "\"\"\"Interactive components provided by @radix-ui/themes.\"\"\"\n\nfrom __future__ import annotations\n\nfrom collections.abc import Sequence\nfrom typing import Literal\n\nfrom reflex.components.component import Component\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.radix.themes.base import LiteralAccentColor, RadixThemesComponent\nfrom reflex.event import EventHandler, passthrough_event_spec\nfrom reflex.utils.types import typehint_issubclass\nfrom reflex.vars.base import Var\n\non_value_event_spec = (\n    passthrough_event_spec(list[float]),\n    passthrough_event_spec(list[int]),\n)\n\n\nclass Slider(RadixThemesComponent):\n    \"\"\"Provides user selection from a range of values.\"\"\"\n\n    tag = \"Slider\"\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior.\n    as_child: Var[bool]\n\n    # Button size \"1\" - \"3\"\n    size: Var[Responsive[Literal[\"1\", \"2\", \"3\"]]]\n\n    # Variant of button\n    variant: Var[Literal[\"classic\", \"surface\", \"soft\"]]\n\n    # Override theme color for button\n    color_scheme: Var[LiteralAccentColor]\n\n    # Whether to render the button with higher contrast color against background\n    high_contrast: Var[bool]\n\n    # Override theme radius for button: \"none\" | \"small\" | \"full\"\n    radius: Var[Literal[\"none\", \"small\", \"full\"]]\n\n    # The value of the slider when initially rendered. Use when you do not need to control the state of the slider.\n    default_value: Var[Sequence[float | int] | float | int]\n\n    # The controlled value of the slider. Must be used in conjunction with onValueChange.\n    value: Var[Sequence[float | int]]\n\n    # The name of the slider. Submitted with its owning form as part of a name/value pair.\n    name: Var[str]\n\n    # The width of the slider.\n    width: Var[str | None] = Var.create(\"100%\")\n\n    # The minimum value of the slider.\n    min: Var[float | int]\n\n    # The maximum value of the slider.\n    max: Var[float | int]\n\n    # The step value of the slider.\n    step: Var[float | int]\n\n    # Whether the slider is disabled\n    disabled: Var[bool]\n\n    # The orientation of the slider.\n    orientation: Var[Literal[\"horizontal\", \"vertical\"]]\n\n    # Props to rename\n    _rename_props = {\"onChange\": \"onValueChange\"}\n\n    # Fired when the value of the slider changes.\n    on_change: EventHandler[on_value_event_spec]\n\n    # Fired when a thumb is released after being dragged.\n    on_value_commit: EventHandler[on_value_event_spec]\n\n    @classmethod\n    def create(\n        cls,\n        *children,\n        **props,\n    ) -> Component:\n        \"\"\"Create a Slider component.\n\n        Args:\n            *children: The children of the component.\n            **props: The properties of the component.\n\n        Returns:\n            The component.\n        \"\"\"\n        default_value = props.pop(\"default_value\", [50])\n        width = props.pop(\"width\", \"100%\")\n\n        if isinstance(default_value, Var):\n            if typehint_issubclass(default_value._var_type, int | float):\n                default_value = [default_value]\n\n        elif isinstance(default_value, (int, float)):\n            default_value = [default_value]\n\n        style = props.setdefault(\"style\", {})\n        style.update({\n            \"width\": width,\n        })\n        return super().create(*children, default_value=default_value, **props)\n\n\nslider = Slider.create\n"
  },
  {
    "path": "reflex/components/radix/themes/components/spinner.py",
    "content": "\"\"\"Radix Spinner Component.\"\"\"\n\nfrom typing import Literal\n\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.radix.themes.base import RadixLoadingProp, RadixThemesComponent\nfrom reflex.vars.base import Var\n\nLiteralSpinnerSize = Literal[\"1\", \"2\", \"3\"]\n\n\nclass Spinner(RadixLoadingProp, RadixThemesComponent):\n    \"\"\"A spinner component.\"\"\"\n\n    tag = \"Spinner\"\n\n    is_default = False\n\n    # The size of the spinner.\n    size: Var[Responsive[LiteralSpinnerSize]]\n\n\nspinner = Spinner.create\n"
  },
  {
    "path": "reflex/components/radix/themes/components/switch.py",
    "content": "\"\"\"Interactive components provided by @radix-ui/themes.\"\"\"\n\nfrom typing import Literal\n\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.radix.themes.base import LiteralAccentColor, RadixThemesComponent\nfrom reflex.event import EventHandler, passthrough_event_spec\nfrom reflex.vars.base import Var\n\nLiteralSwitchSize = Literal[\"1\", \"2\", \"3\"]\n\n\nclass Switch(RadixThemesComponent):\n    \"\"\"A toggle switch alternative to the checkbox.\"\"\"\n\n    tag = \"Switch\"\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior.\n    as_child: Var[bool]\n\n    # Whether the switch is checked by default\n    default_checked: Var[bool]\n\n    # Whether the switch is checked\n    checked: Var[bool]\n\n    # If true, prevent the user from interacting with the switch\n    disabled: Var[bool]\n\n    # If true, the user must interact with the switch to submit the form\n    required: Var[bool]\n\n    # The name of the switch (when submitting a form)\n    name: Var[str]\n\n    # The value associated with the \"on\" position\n    value: Var[str]\n\n    # Switch size \"1\" - \"4\"\n    size: Var[Responsive[LiteralSwitchSize]]\n\n    # Variant of switch: \"classic\" | \"surface\" | \"soft\"\n    variant: Var[Literal[\"classic\", \"surface\", \"soft\"]]\n\n    # Override theme color for switch\n    color_scheme: Var[LiteralAccentColor]\n\n    # Whether to render the switch with higher contrast color against background\n    high_contrast: Var[bool]\n\n    # Override theme radius for switch: \"none\" | \"small\" | \"full\"\n    radius: Var[Literal[\"none\", \"small\", \"full\"]]\n\n    # Props to rename\n    _rename_props = {\"onChange\": \"onCheckedChange\"}\n\n    # Fired when the value of the switch changes\n    on_change: EventHandler[passthrough_event_spec(bool)]\n\n\nswitch = Switch.create\n"
  },
  {
    "path": "reflex/components/radix/themes/components/table.py",
    "content": "\"\"\"Interactive components provided by @radix-ui/themes.\"\"\"\n\nfrom typing import ClassVar, Literal\n\nfrom reflex.components.component import ComponentNamespace\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.el import elements\nfrom reflex.components.radix.themes.base import CommonPaddingProps, RadixThemesComponent\nfrom reflex.vars.base import Var\n\n\nclass TableRoot(elements.Table, RadixThemesComponent):\n    \"\"\"A semantic table for presenting tabular data.\"\"\"\n\n    tag = \"Table.Root\"\n\n    # The size of the table: \"1\" | \"2\" | \"3\"\n    size: Var[Responsive[Literal[\"1\", \"2\", \"3\"]]]\n\n    # The variant of the table\n    variant: Var[Literal[\"surface\", \"ghost\"]]\n\n\nclass TableHeader(elements.Thead, RadixThemesComponent):\n    \"\"\"The header of the table defines column names and other non-data elements.\"\"\"\n\n    tag = \"Table.Header\"\n\n    _invalid_children: ClassVar[list[str]] = [\"TableBody\"]\n\n    _valid_parents: ClassVar[list[str]] = [\"TableRoot\"]\n\n\nclass TableRow(elements.Tr, RadixThemesComponent):\n    \"\"\"A row containing table cells.\"\"\"\n\n    tag = \"Table.Row\"\n\n    # The alignment of the row\n    align: Var[Literal[\"start\", \"center\", \"end\", \"baseline\"]]\n\n    _invalid_children: ClassVar[list[str]] = [\"TableBody\", \"TableHeader\", \"TableRow\"]\n\n\nclass TableColumnHeaderCell(elements.Th, RadixThemesComponent):\n    \"\"\"A table cell that is semantically treated as a column header.\"\"\"\n\n    tag = \"Table.ColumnHeaderCell\"\n\n    # The justification of the column\n    justify: Var[Literal[\"start\", \"center\", \"end\"]]\n\n    # The minimum width of the cell\n    min_width: Var[Responsive[str]]\n\n    # The maximum width of the cell\n    max_width: Var[Responsive[str]]\n\n    _invalid_children: ClassVar[list[str]] = [\n        \"TableBody\",\n        \"TableHeader\",\n        \"TableRow\",\n        \"TableCell\",\n        \"TableColumnHeaderCell\",\n        \"TableRowHeaderCell\",\n    ]\n\n\nclass TableBody(elements.Tbody, RadixThemesComponent):\n    \"\"\"The body of the table contains the data rows.\"\"\"\n\n    tag = \"Table.Body\"\n\n    _invalid_children: ClassVar[list[str]] = [\n        \"TableHeader\",\n        \"TableRowHeaderCell\",\n        \"TableColumnHeaderCell\",\n        \"TableCell\",\n    ]\n\n    _valid_parents: ClassVar[list[str]] = [\"TableRoot\"]\n\n\nclass TableCell(elements.Td, CommonPaddingProps, RadixThemesComponent):\n    \"\"\"A cell containing data.\"\"\"\n\n    tag = \"Table.Cell\"\n\n    # The justification of the column\n    justify: Var[Literal[\"start\", \"center\", \"end\"]]\n\n    # The minimum width of the cell\n    min_width: Var[Responsive[str]]\n\n    # The maximum width of the cell\n    max_width: Var[Responsive[str]]\n\n    _invalid_children: ClassVar[list[str]] = [\n        \"TableBody\",\n        \"TableHeader\",\n        \"TableRowHeaderCell\",\n        \"TableColumnHeaderCell\",\n        \"TableCell\",\n    ]\n\n\nclass TableRowHeaderCell(elements.Th, CommonPaddingProps, RadixThemesComponent):\n    \"\"\"A table cell that is semantically treated as a row header.\"\"\"\n\n    tag = \"Table.RowHeaderCell\"\n\n    # The justification of the column\n    justify: Var[Literal[\"start\", \"center\", \"end\"]]\n\n    # The minimum width of the cell\n    min_width: Var[Responsive[str]]\n\n    # The maximum width of the cell\n    max_width: Var[Responsive[str]]\n\n    _invalid_children: ClassVar[list[str]] = [\n        \"TableBody\",\n        \"TableHeader\",\n        \"TableRow\",\n        \"TableCell\",\n        \"TableColumnHeaderCell\",\n        \"TableRowHeaderCell\",\n    ]\n\n\nclass Table(ComponentNamespace):\n    \"\"\"Table components namespace.\"\"\"\n\n    root = staticmethod(TableRoot.create)\n    header = staticmethod(TableHeader.create)\n    body = staticmethod(TableBody.create)\n    row = staticmethod(TableRow.create)\n    cell = staticmethod(TableCell.create)\n    column_header_cell = staticmethod(TableColumnHeaderCell.create)\n    row_header_cell = staticmethod(TableRowHeaderCell.create)\n\n\ntable = Table()\n"
  },
  {
    "path": "reflex/components/radix/themes/components/tabs.py",
    "content": "\"\"\"Interactive components provided by @radix-ui/themes.\"\"\"\n\nfrom __future__ import annotations\n\nfrom typing import Any, ClassVar, Literal\n\nfrom reflex.components.component import Component, ComponentNamespace\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.core.colors import color\nfrom reflex.components.radix.themes.base import LiteralAccentColor, RadixThemesComponent\nfrom reflex.constants.compiler import MemoizationMode\nfrom reflex.event import EventHandler, passthrough_event_spec\nfrom reflex.vars.base import Var\n\nvertical_orientation_css = \"&[data-orientation='vertical']\"\n\n\nclass TabsRoot(RadixThemesComponent):\n    \"\"\"Set of content sections to be displayed one at a time.\"\"\"\n\n    tag = \"Tabs.Root\"\n\n    # The value of the tab that should be active when initially rendered. Use when you do not need to control the state of the tabs.\n    default_value: Var[str]\n\n    # The controlled value of the tab that should be active. Use when you need to control the state of the tabs.\n    value: Var[str]\n\n    # The orientation of the tabs.\n    orientation: Var[Literal[\"horizontal\", \"vertical\"]]\n\n    # Reading direction of the tabs.\n    dir: Var[Literal[\"ltr\", \"rtl\"]]\n\n    # The mode of activation for the tabs. \"automatic\" will activate the tab when focused. \"manual\" will activate the tab when clicked.\n    activation_mode: Var[Literal[\"automatic\", \"manual\"]]\n\n    # Props to rename\n    _rename_props = {\"onChange\": \"onValueChange\"}\n\n    # Fired when the value of the tabs changes.\n    on_change: EventHandler[passthrough_event_spec(str)]\n\n    def add_style(self) -> dict[str, Any] | None:\n        \"\"\"Add style for the component.\n\n        Returns:\n            The style to add.\n        \"\"\"\n        return {\n            vertical_orientation_css: {\n                \"display\": \"flex\",\n            }\n        }\n\n\nclass TabsList(RadixThemesComponent):\n    \"\"\"Contains the triggers that sit alongside the active content.\"\"\"\n\n    tag = \"Tabs.List\"\n\n    # Tabs size \"1\" - \"2\"\n    size: Var[Responsive[Literal[\"1\", \"2\"]]]\n\n    # When true, the tabs will loop when reaching the end.\n    loop: Var[bool]\n\n    def add_style(self):\n        \"\"\"Add style for the component.\n\n        Returns:\n            The style to add.\n        \"\"\"\n        return {\n            vertical_orientation_css: {\n                \"display\": \"block\",\n                \"box_shadow\": f\"inset -1px 0 0 0 {color('gray', 5, alpha=True)}\",\n            },\n        }\n\n\nclass TabsTrigger(RadixThemesComponent):\n    \"\"\"The button that activates its associated content.\"\"\"\n\n    tag = \"Tabs.Trigger\"\n\n    # The value of the tab. Must be unique for each tab.\n    value: Var[str]\n\n    # Whether the tab is disabled\n    disabled: Var[bool]\n\n    # The color of the line under the tab when active.\n    color_scheme: Var[LiteralAccentColor]\n\n    _valid_parents: ClassVar[list[str]] = [\"TabsList\"]\n\n    _memoization_mode = MemoizationMode(recursive=False)\n\n    @classmethod\n    def create(cls, *children, **props) -> Component:\n        \"\"\"Create a TabsTrigger component.\n\n        Args:\n            *children: The children of the component.\n            **props: The properties of the component.\n\n        Returns:\n            The TabsTrigger Component.\n        \"\"\"\n        if \"color_scheme\" in props:\n            custom_attrs = props.setdefault(\"custom_attrs\", {})\n            custom_attrs[\"data-accent-color\"] = props[\"color_scheme\"]\n        return super().create(*children, **props)\n\n    def _exclude_props(self) -> list[str]:\n        return [\"color_scheme\"]\n\n    def add_style(self) -> dict[str, Any] | None:\n        \"\"\"Add style for the component.\n\n        Returns:\n            The style to add.\n        \"\"\"\n        return {vertical_orientation_css: {\"width\": \"100%\"}}\n\n\nclass TabsContent(RadixThemesComponent):\n    \"\"\"Contains the content associated with each trigger.\"\"\"\n\n    tag = \"Tabs.Content\"\n\n    # The value of the tab. Must be unique for each tab.\n    value: Var[str]\n\n    # Used to force mounting when more control is needed. Useful when controlling animation with React animation libraries.\n    force_mount: Var[bool]\n\n    def add_style(self) -> dict[str, Any] | None:\n        \"\"\"Add style for the component.\n\n        Returns:\n            The style to add.\n        \"\"\"\n        return {\n            vertical_orientation_css: {\"width\": \"100%\", \"margin\": None},\n        }\n\n\nclass Tabs(ComponentNamespace):\n    \"\"\"Set of content sections to be displayed one at a time.\"\"\"\n\n    root = __call__ = staticmethod(TabsRoot.create)\n    list = staticmethod(TabsList.create)\n    trigger = staticmethod(TabsTrigger.create)\n    content = staticmethod(TabsContent.create)\n\n\ntabs = Tabs()\n"
  },
  {
    "path": "reflex/components/radix/themes/components/text_area.py",
    "content": "\"\"\"Interactive components provided by @radix-ui/themes.\"\"\"\n\nfrom typing import Literal\n\nfrom reflex.components.component import Component\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.core.debounce import DebounceInput\nfrom reflex.components.el import elements\nfrom reflex.components.radix.themes.base import (\n    LiteralAccentColor,\n    LiteralRadius,\n    RadixThemesComponent,\n)\nfrom reflex.vars.base import Var\n\nLiteralTextAreaSize = Literal[\"1\", \"2\", \"3\"]\n\nLiteralTextAreaResize = Literal[\"none\", \"vertical\", \"horizontal\", \"both\"]\n\n\nclass TextArea(RadixThemesComponent, elements.Textarea):\n    \"\"\"The input part of a TextArea, may be used by itself.\"\"\"\n\n    tag = \"TextArea\"\n\n    # The size of the text area: \"1\" | \"2\" | \"3\"\n    size: Var[Responsive[LiteralTextAreaSize]]\n\n    # The variant of the text area\n    variant: Var[Literal[\"classic\", \"surface\", \"soft\"]]\n\n    # The resize behavior of the text area: \"none\" | \"vertical\" | \"horizontal\" | \"both\"\n    resize: Var[Responsive[LiteralTextAreaResize]]\n\n    # The color of the text area\n    color_scheme: Var[LiteralAccentColor]\n\n    # The radius of the text area: \"none\" | \"small\" | \"medium\" | \"large\" | \"full\"\n    radius: Var[LiteralRadius]\n\n    # Whether the form control should have autocomplete enabled\n    auto_complete: Var[bool]\n\n    # Automatically focuses the textarea when the page loads\n    auto_focus: Var[bool]\n\n    # The default value of the textarea when initially rendered\n    default_value: Var[str]\n\n    # Name part of the textarea to submit in 'dir' and 'name' pair when form is submitted\n    dirname: Var[str]\n\n    # Disables the textarea\n    disabled: Var[bool]\n\n    # Associates the textarea with a form (by id)\n    form: Var[str]\n\n    # Maximum number of characters allowed in the textarea\n    max_length: Var[int]\n\n    # Minimum number of characters required in the textarea\n    min_length: Var[int]\n\n    # Name of the textarea, used when submitting the form\n    name: Var[str]\n\n    # Placeholder text in the textarea\n    placeholder: Var[str]\n\n    # Indicates whether the textarea is read-only\n    read_only: Var[bool]\n\n    # Indicates that the textarea is required\n    required: Var[bool]\n\n    # Visible number of lines in the text control\n    rows: Var[str]\n\n    # The controlled value of the textarea, read only unless used with on_change\n    value: Var[str]\n\n    # How the text in the textarea is to be wrapped when submitting the form\n    wrap: Var[str]\n\n    @classmethod\n    def create(cls, *children, **props) -> Component:\n        \"\"\"Create an Input component.\n\n        Args:\n            *children: The children of the component.\n            **props: The properties of the component.\n\n        Returns:\n            The component.\n        \"\"\"\n        if props.get(\"value\") is not None and props.get(\"on_change\") is not None:\n            # create a debounced input if the user requests full control to avoid typing jank\n            return DebounceInput.create(super().create(*children, **props))\n        return super().create(*children, **props)\n\n    def add_style(self):\n        \"\"\"Add the style to the component.\n\n        Returns:\n            The style of the component.\n        \"\"\"\n        added_style: dict[str, dict] = {}\n        added_style.setdefault(\"& textarea\", {})\n        if \"padding\" in self.style:\n            added_style[\"& textarea\"][\"padding\"] = self.style.pop(\"padding\")\n        return added_style\n\n\ntext_area = TextArea.create\n"
  },
  {
    "path": "reflex/components/radix/themes/components/text_field.py",
    "content": "\"\"\"Interactive components provided by @radix-ui/themes.\"\"\"\n\nfrom __future__ import annotations\n\nfrom typing import Literal\n\nfrom reflex.components.component import Component, ComponentNamespace\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.core.debounce import DebounceInput\nfrom reflex.components.el import elements\nfrom reflex.components.radix.themes.base import (\n    LiteralAccentColor,\n    LiteralRadius,\n    RadixThemesComponent,\n)\nfrom reflex.event import EventHandler, input_event, key_event\nfrom reflex.utils.types import is_optional\nfrom reflex.vars.base import Var\nfrom reflex.vars.number import ternary_operation\n\nLiteralTextFieldSize = Literal[\"1\", \"2\", \"3\"]\nLiteralTextFieldVariant = Literal[\"classic\", \"surface\", \"soft\"]\n\n\nclass TextFieldRoot(elements.Input, RadixThemesComponent):\n    \"\"\"Captures user input with an optional slot for buttons and icons.\"\"\"\n\n    tag = \"TextField.Root\"\n\n    # Text field size \"1\" - \"3\"\n    size: Var[Responsive[LiteralTextFieldSize]]\n\n    # Variant of text field: \"classic\" | \"surface\" | \"soft\"\n    variant: Var[LiteralTextFieldVariant]\n\n    # Override theme color for text field\n    color_scheme: Var[LiteralAccentColor]\n\n    # Override theme radius for text field: \"none\" | \"small\" | \"medium\" | \"large\" | \"full\"\n    radius: Var[LiteralRadius]\n\n    # Whether the input should have autocomplete enabled\n    auto_complete: Var[bool]\n\n    # The value of the input when initially rendered.\n    default_value: Var[str]\n\n    # Disables the input\n    disabled: Var[bool]\n\n    # Specifies the maximum number of characters allowed in the input\n    max_length: Var[int]\n\n    # Specifies the minimum number of characters required in the input\n    min_length: Var[int]\n\n    # Name of the input, used when sending form data\n    name: Var[str]\n\n    # Placeholder text in the input\n    placeholder: Var[str]\n\n    # Indicates whether the input is read-only\n    read_only: Var[bool]\n\n    # Indicates that the input is required\n    required: Var[bool]\n\n    # Specifies the type of input\n    type: Var[str]\n\n    # Value of the input\n    value: Var[str | int | float]\n\n    # References a datalist for suggested options\n    list: Var[str]\n\n    # Fired when the value of the textarea changes.\n    on_change: EventHandler[input_event]\n\n    # Fired when the textarea is focused.\n    on_focus: EventHandler[input_event]\n\n    # Fired when the textarea is blurred.\n    on_blur: EventHandler[input_event]\n\n    # Fired when a key is pressed down.\n    on_key_down: EventHandler[key_event]\n\n    # Fired when a key is released.\n    on_key_up: EventHandler[key_event]\n\n    @classmethod\n    def create(cls, *children, **props) -> Component:\n        \"\"\"Create an Input component.\n\n        Args:\n            *children: The children of the component.\n            **props: The properties of the component.\n\n        Returns:\n            The component.\n        \"\"\"\n        value = props.get(\"value\")\n\n        # React expects an empty string(instead of null) for controlled inputs.\n        if value is not None and is_optional(\n            (value_var := Var.create(value))._var_type\n        ):\n            value_var_is_not_none = value_var != Var.create(None)\n            value_var_is_not_undefined = value_var != Var(_js_expr=\"undefined\")\n            props[\"value\"] = ternary_operation(\n                value_var_is_not_none & value_var_is_not_undefined,\n                value,\n                Var.create(\"\"),\n            )\n\n        component = super().create(*children, **props)\n        if props.get(\"value\") is not None and props.get(\"on_change\") is not None:\n            # create a debounced input if the user requests full control to avoid typing jank\n            return DebounceInput.create(component)\n        return component\n\n\nclass TextFieldSlot(RadixThemesComponent):\n    \"\"\"Contains icons or buttons associated with an Input.\"\"\"\n\n    tag = \"TextField.Slot\"\n\n    # Override theme color for text field slot\n    color_scheme: Var[LiteralAccentColor]\n\n    # Which side of the input the slot should be placed on\n    side: Var[Literal[\"left\", \"right\"]]\n\n\nclass TextField(ComponentNamespace):\n    \"\"\"TextField components namespace.\"\"\"\n\n    slot = staticmethod(TextFieldSlot.create)\n    __call__ = staticmethod(TextFieldRoot.create)\n\n\ninput = text_field = TextField()\n"
  },
  {
    "path": "reflex/components/radix/themes/components/tooltip.py",
    "content": "\"\"\"Interactive components provided by @radix-ui/themes.\"\"\"\n\nfrom typing import Literal\n\nfrom reflex.components.component import Component\nfrom reflex.components.radix.themes.base import RadixThemesComponent\nfrom reflex.constants.compiler import MemoizationMode\nfrom reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec\nfrom reflex.utils import format\nfrom reflex.vars.base import Var\n\nLiteralSideType = Literal[\n    \"top\",\n    \"right\",\n    \"bottom\",\n    \"left\",\n]\n\nLiteralAlignType = Literal[\n    \"start\",\n    \"center\",\n    \"end\",\n]\n\nLiteralStickyType = Literal[\n    \"partial\",\n    \"always\",\n]\n\n\nARIA_LABEL_KEY = \"aria_label\"\n\n\n# The Tooltip inherits props from the Tooltip.Root, Tooltip.Portal, Tooltip.Content\nclass Tooltip(RadixThemesComponent):\n    \"\"\"Floating element that provides a control with contextual information via pointer or focus.\"\"\"\n\n    tag = \"Tooltip\"\n\n    # The content of the tooltip.\n    content: Var[str]\n\n    # The open state of the tooltip when it is initially rendered. Use when you do not need to control its open state.\n    default_open: Var[bool]\n\n    # The controlled open state of the tooltip. Must be used in conjunction with `on_open_change`.\n    open: Var[bool]\n\n    # The preferred side of the trigger to render against when open. Will be reversed when collisions occur and `avoid_collisions` is enabled.The position of the tooltip. Defaults to \"top\".\n    side: Var[LiteralSideType]\n\n    # The distance in pixels from the trigger. Defaults to 0.\n    side_offset: Var[float | int]\n\n    # The preferred alignment against the trigger. May change when collisions occur. Defaults to \"center\".\n    align: Var[LiteralAlignType]\n\n    # An offset in pixels from the \"start\" or \"end\" alignment options.\n    align_offset: Var[float | int]\n\n    # When true, overrides the side and align preferences to prevent collisions with boundary edges. Defaults to True.\n    avoid_collisions: Var[bool]\n\n    # The distance in pixels from the boundary edges where collision detection should occur. Accepts a number (same for all sides), or a partial padding object, for example: { \"top\": 20, \"left\": 20 }. Defaults to 0.\n    collision_padding: Var[float | int | dict[str, float | int]]\n\n    # The padding between the arrow and the edges of the content. If your content has border-radius, this will prevent it from overflowing the corners. Defaults to 0.\n    arrow_padding: Var[float | int]\n\n    # The sticky behavior on the align axis. \"partial\" will keep the content in the boundary as long as the trigger is at least partially in the boundary whilst \"always\" will keep the content in the boundary regardless. Defaults to \"partial\".\n    sticky: Var[LiteralStickyType]\n\n    # Whether to hide the content when the trigger becomes fully occluded. Defaults to False.\n    hide_when_detached: Var[bool]\n\n    # Override the duration in milliseconds to customize the open delay for a specific tooltip. Default is 700.\n    delay_duration: Var[float | int]\n\n    # Prevents Tooltip content from remaining open when hovering.\n    disable_hoverable_content: Var[bool]\n\n    # Used to force mounting when more control is needed. Useful when controlling animation with React animation libraries.\n    force_mount: Var[bool]\n\n    # By default, screenreaders will announce the content inside the component. If this is not descriptive enough, or you have content that cannot be announced, use aria-label as a more descriptive label.\n    aria_label: Var[str]\n\n    # Fired when the open state changes.\n    on_open_change: EventHandler[passthrough_event_spec(bool)]\n\n    # Fired when the escape key is pressed.\n    on_escape_key_down: EventHandler[no_args_event_spec]\n\n    # Fired when the pointer is down outside the tooltip.\n    on_pointer_down_outside: EventHandler[no_args_event_spec]\n\n    _memoization_mode = MemoizationMode(recursive=False)\n\n    @classmethod\n    def create(cls, *children, **props) -> Component:\n        \"\"\"Initialize the Tooltip component.\n\n        Run some additional handling on the props.\n\n        Args:\n            *children: The positional arguments\n            **props: The keyword arguments\n\n        Returns:\n            The created component.\n        \"\"\"\n        if props.get(ARIA_LABEL_KEY) is not None:\n            props[format.to_kebab_case(ARIA_LABEL_KEY)] = props.pop(ARIA_LABEL_KEY)\n\n        return super().create(*children, **props)\n\n\ntooltip = Tooltip.create\n"
  },
  {
    "path": "reflex/components/radix/themes/layout/__init__.py",
    "content": "\"\"\"Layout components.\"\"\"\n\nfrom __future__ import annotations\n\nfrom reflex import RADIX_THEMES_LAYOUT_MAPPING\nfrom reflex.utils import lazy_loader\n\n_SUBMOD_ATTRS: dict[str, list[str]] = {\n    \"\".join(k.split(\"components.radix.themes.layout.\")[-1]): v\n    for k, v in RADIX_THEMES_LAYOUT_MAPPING.items()\n}\n\n\n__getattr__, __dir__, __all__ = lazy_loader.attach(\n    __name__,\n    submod_attrs=_SUBMOD_ATTRS,\n)\n"
  },
  {
    "path": "reflex/components/radix/themes/layout/base.py",
    "content": "\"\"\"Declarative layout and common spacing props.\"\"\"\n\nfrom __future__ import annotations\n\nfrom typing import Literal\n\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.radix.themes.base import (\n    CommonMarginProps,\n    CommonPaddingProps,\n    RadixThemesComponent,\n)\nfrom reflex.vars.base import Var\n\nLiteralBoolNumber = Literal[\"0\", \"1\"]\n\n\nclass LayoutComponent(CommonMarginProps, CommonPaddingProps, RadixThemesComponent):\n    \"\"\"Box, Flex and Grid are foundational elements you'll use to construct\n    layouts. Box provides block-level spacing and sizing, while Flex and Grid\n    let you create flexible columns, rows and grids.\n    \"\"\"\n\n    # Whether the element will take up the smallest possible space: \"0\" | \"1\"\n    flex_shrink: Var[Responsive[LiteralBoolNumber]]\n\n    # Whether the element will take up the largest possible space: \"0\" | \"1\"\n    flex_grow: Var[Responsive[LiteralBoolNumber]]\n"
  },
  {
    "path": "reflex/components/radix/themes/layout/box.py",
    "content": "\"\"\"Declarative layout and common spacing props.\"\"\"\n\nfrom __future__ import annotations\n\nfrom reflex.components.el import elements\nfrom reflex.components.radix.themes.base import RadixThemesComponent\n\n\nclass Box(elements.Div, RadixThemesComponent):\n    \"\"\"A fundamental layout building block, based on `div` element.\"\"\"\n\n    tag = \"Box\"\n\n\nbox = Box.create\n"
  },
  {
    "path": "reflex/components/radix/themes/layout/center.py",
    "content": "\"\"\"A center component.\"\"\"\n\nfrom __future__ import annotations\n\nfrom typing import Any\n\nfrom .flex import Flex\n\n\nclass Center(Flex):\n    \"\"\"A center component.\"\"\"\n\n    def add_style(self) -> dict[str, Any] | None:\n        \"\"\"Add style that center the content.\n\n        Returns:\n            The style of the component.\n        \"\"\"\n        return {\n            \"display\": \"flex\",\n            \"align_items\": \"center\",\n            \"justify_content\": \"center\",\n        }\n\n\ncenter = Center.create\n"
  },
  {
    "path": "reflex/components/radix/themes/layout/container.py",
    "content": "\"\"\"Declarative layout and common spacing props.\"\"\"\n\nfrom __future__ import annotations\n\nfrom typing import Literal\n\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.el import elements\nfrom reflex.components.radix.themes.base import RadixThemesComponent\nfrom reflex.style import STACK_CHILDREN_FULL_WIDTH\nfrom reflex.vars.base import LiteralVar, Var\n\nLiteralContainerSize = Literal[\"1\", \"2\", \"3\", \"4\"]\n\n\nclass Container(elements.Div, RadixThemesComponent):\n    \"\"\"Constrains the maximum width of page content.\n\n    See https://www.radix-ui.com/themes/docs/components/container\n    \"\"\"\n\n    tag = \"Container\"\n\n    # The size of the container: \"1\" - \"4\" (default \"3\")\n    size: Var[Responsive[LiteralContainerSize]] = LiteralVar.create(\"3\")\n\n    @classmethod\n    def create(\n        cls,\n        *children,\n        padding: str = \"16px\",\n        stack_children_full_width: bool = False,\n        **props,\n    ):\n        \"\"\"Create the container component.\n\n        Args:\n            children: The children components.\n            padding: The padding of the container.\n            stack_children_full_width: If True, any vstack/hstack children will have 100% width.\n            props: The properties of the container.\n\n        Returns:\n            The container component.\n        \"\"\"\n        if stack_children_full_width:\n            props[\"style\"] = {**STACK_CHILDREN_FULL_WIDTH, **props.pop(\"style\", {})}\n        return super().create(\n            *children,\n            padding=padding,\n            **props,\n        )\n\n\ncontainer = Container.create\n"
  },
  {
    "path": "reflex/components/radix/themes/layout/flex.py",
    "content": "\"\"\"Declarative layout and common spacing props.\"\"\"\n\nfrom __future__ import annotations\n\nfrom typing import ClassVar, Literal\n\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.el import elements\nfrom reflex.components.radix.themes.base import (\n    LiteralAlign,\n    LiteralJustify,\n    LiteralSpacing,\n    RadixThemesComponent,\n)\nfrom reflex.vars.base import Var\n\nLiteralFlexDirection = Literal[\"row\", \"column\", \"row-reverse\", \"column-reverse\"]\nLiteralFlexWrap = Literal[\"nowrap\", \"wrap\", \"wrap-reverse\"]\n\n\nclass Flex(elements.Div, RadixThemesComponent):\n    \"\"\"Component for creating flex layouts.\"\"\"\n\n    tag = \"Flex\"\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior.\n    as_child: Var[bool]\n\n    # How child items are laid out: \"row\" | \"column\" | \"row-reverse\" | \"column-reverse\"\n    direction: Var[Responsive[LiteralFlexDirection]]\n\n    # Alignment of children along the main axis: \"start\" | \"center\" | \"end\" | \"baseline\" | \"stretch\"\n    align: Var[Responsive[LiteralAlign]]\n\n    # Alignment of children along the cross axis: \"start\" | \"center\" | \"end\" | \"between\"\n    justify: Var[Responsive[LiteralJustify]]\n\n    # Whether children should wrap when they reach the end of their container: \"nowrap\" | \"wrap\" | \"wrap-reverse\"\n    wrap: Var[Responsive[LiteralFlexWrap]]\n\n    # Gap between children: \"0\" - \"9\"\n    spacing: Var[Responsive[LiteralSpacing]]\n\n    # Reflex maps the \"spacing\" prop to \"gap\" prop.\n    _rename_props: ClassVar[dict[str, str]] = {\"spacing\": \"gap\"}\n\n\nflex = Flex.create\n"
  },
  {
    "path": "reflex/components/radix/themes/layout/grid.py",
    "content": "\"\"\"Declarative layout and common spacing props.\"\"\"\n\nfrom __future__ import annotations\n\nfrom typing import ClassVar, Literal\n\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.el import elements\nfrom reflex.components.radix.themes.base import (\n    LiteralAlign,\n    LiteralJustify,\n    LiteralSpacing,\n    RadixThemesComponent,\n)\nfrom reflex.vars.base import Var\n\nLiteralGridFlow = Literal[\"row\", \"column\", \"dense\", \"row-dense\", \"column-dense\"]\n\n\nclass Grid(elements.Div, RadixThemesComponent):\n    \"\"\"Component for creating grid layouts.\"\"\"\n\n    tag = \"Grid\"\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior.\n    as_child: Var[bool]\n\n    # Number of columns\n    columns: Var[Responsive[str]]\n\n    # Number of rows\n    rows: Var[Responsive[str]]\n\n    # How the grid items are laid out: \"row\" | \"column\" | \"dense\" | \"row-dense\" | \"column-dense\"\n    flow: Var[Responsive[LiteralGridFlow]]\n\n    # Alignment of children along the main axis: \"start\" | \"center\" | \"end\" | \"baseline\" | \"stretch\"\n    align: Var[Responsive[LiteralAlign]]\n\n    # Alignment of children along the cross axis: \"start\" | \"center\" | \"end\" | \"between\"\n    justify: Var[Responsive[LiteralJustify]]\n\n    # Gap between children: \"0\" - \"9\"\n    spacing: Var[Responsive[LiteralSpacing]]\n\n    # Gap between children horizontal: \"0\" - \"9\"\n    spacing_x: Var[Responsive[LiteralSpacing]]\n\n    # Gap between children vertical: \"0\" - \"9\"\n    spacing_y: Var[Responsive[LiteralSpacing]]\n\n    # Reflex maps the \"spacing\" prop to \"gap\" prop.\n    _rename_props: ClassVar[dict[str, str]] = {\n        \"spacing\": \"gap\",\n        \"spacing_x\": \"gap_x\",\n        \"spacing_y\": \"gap_y\",\n    }\n\n\ngrid = Grid.create\n"
  },
  {
    "path": "reflex/components/radix/themes/layout/list.py",
    "content": "\"\"\"List components.\"\"\"\n\nfrom __future__ import annotations\n\nfrom collections.abc import Iterable\nfrom typing import Any, Literal\n\nfrom reflex.components.component import ComponentNamespace\nfrom reflex.components.core.foreach import Foreach\nfrom reflex.components.el.elements.base import BaseHTML\nfrom reflex.components.el.elements.typography import Li, Ol, Ul\nfrom reflex.components.lucide.icon import Icon\nfrom reflex.components.markdown.markdown import MarkdownComponentMap\nfrom reflex.components.radix.themes.typography.text import Text\nfrom reflex.vars.base import Var\n\nLiteralListStyleTypeUnordered = Literal[\n    \"none\",\n    \"disc\",\n    \"circle\",\n    \"square\",\n]\n\nLiteralListStyleTypeOrdered = Literal[\n    \"none\",\n    \"decimal\",\n    \"decimal-leading-zero\",\n    \"lower-roman\",\n    \"upper-roman\",\n    \"lower-greek\",\n    \"lower-latin\",\n    \"upper-latin\",\n    \"armenian\",\n    \"georgian\",\n    \"lower-alpha\",\n    \"upper-alpha\",\n    \"hiragana\",\n    \"katakana\",\n]\n\n\nclass BaseList(BaseHTML, MarkdownComponentMap):\n    \"\"\"Base class for ordered and unordered lists.\"\"\"\n\n    tag = \"ul\"\n\n    # The style of the list. Default to \"none\".\n    list_style_type: Var[\n        LiteralListStyleTypeUnordered | LiteralListStyleTypeOrdered\n    ] = Var.create(\"none\")\n\n    # A list of items to add to the list.\n    items: Var[Iterable] = Var.create([])\n\n    @classmethod\n    def create(\n        cls,\n        *children,\n        **props,\n    ):\n        \"\"\"Create a list component.\n\n        Args:\n            *children: The children of the component.\n            **props: The properties of the component.\n\n        Returns:\n            The list component.\n        \"\"\"\n        items = props.pop(\"items\", None)\n        list_style_type = props.pop(\"list_style_type\", \"none\")\n\n        if not children and items is not None:\n            if isinstance(items, Var):\n                children = [Foreach.create(items, ListItem.create)]\n            else:\n                children = [ListItem.create(item) for item in items]\n        props[\"direction\"] = \"column\"\n        style = props.setdefault(\"style\", {})\n        style[\"list_style_type\"] = list_style_type\n        if \"gap\" in props:\n            style[\"gap\"] = props[\"gap\"]\n        return super().create(*children, **props)\n\n    def add_style(self) -> dict[str, Any] | None:\n        \"\"\"Add style to the component.\n\n        Returns:\n            The style of the component.\n        \"\"\"\n        return {\n            \"direction\": \"column\",\n        }\n\n    def _exclude_props(self) -> list[str]:\n        return [\"items\", \"list_style_type\"]\n\n\nclass UnorderedList(BaseList, Ul):\n    \"\"\"Display an unordered list.\"\"\"\n\n    tag = \"ul\"\n\n    @classmethod\n    def create(\n        cls,\n        *children,\n        **props,\n    ):\n        \"\"\"Create an unordered list component.\n\n        Args:\n            *children: The children of the component.\n            **props: The properties of the component.\n\n        Returns:\n            The list component.\n        \"\"\"\n        items = props.pop(\"items\", None)\n        list_style_type = props.pop(\"list_style_type\", \"disc\")\n\n        props[\"margin_left\"] = props.get(\"margin_left\", \"1.5rem\")\n        return super().create(\n            *children, items=items, list_style_type=list_style_type, **props\n        )\n\n\nclass OrderedList(BaseList, Ol):\n    \"\"\"Display an ordered list.\"\"\"\n\n    tag = \"ol\"\n\n    @classmethod\n    def create(\n        cls,\n        *children,\n        **props,\n    ):\n        \"\"\"Create an ordered list component.\n\n        Args:\n            *children: The children of the component.\n            **props: The properties of the component.\n\n        Returns:\n            The list component.\n        \"\"\"\n        items = props.pop(\"items\", None)\n        list_style_type = props.pop(\"list_style_type\", \"decimal\")\n\n        props[\"margin_left\"] = props.get(\"margin_left\", \"1.5rem\")\n        return super().create(\n            *children, items=items, list_style_type=list_style_type, **props\n        )\n\n\nclass ListItem(Li, MarkdownComponentMap):\n    \"\"\"Display an item of an ordered or unordered list.\"\"\"\n\n    @classmethod\n    def create(cls, *children, **props):\n        \"\"\"Create a list item component.\n\n        Args:\n            *children: The children of the component.\n            **props: The properties of the component.\n\n        Returns:\n            The list item component.\n        \"\"\"\n        for child in children:\n            if isinstance(child, Text):\n                child.as_ = \"span\"  # pyright: ignore[reportAttributeAccessIssue]\n            elif isinstance(child, Icon) and \"display\" not in child.style:\n                child.style[\"display\"] = \"inline\"\n        return super().create(*children, **props)\n\n\nclass List(ComponentNamespace):\n    \"\"\"List components.\"\"\"\n\n    item = staticmethod(ListItem.create)\n    ordered = staticmethod(OrderedList.create)\n    unordered = staticmethod(UnorderedList.create)\n    __call__ = staticmethod(BaseList.create)\n\n\nlist_ns = List()\nlist_item = list_ns.item\nordered_list = list_ns.ordered\nunordered_list = list_ns.unordered\n\n\ndef __getattr__(name: Any):\n    # special case for when accessing list to avoid shadowing\n    # python's built in list object.\n    if name == \"list\":\n        return list_ns\n    try:\n        return globals()[name]\n    except KeyError:\n        msg = f\"module '{__name__} has no attribute '{name}'\"\n        raise AttributeError(msg) from None\n"
  },
  {
    "path": "reflex/components/radix/themes/layout/section.py",
    "content": "\"\"\"Declarative layout and common spacing props.\"\"\"\n\nfrom __future__ import annotations\n\nfrom typing import Literal\n\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.el import elements\nfrom reflex.components.radix.themes.base import RadixThemesComponent\nfrom reflex.vars.base import LiteralVar, Var\n\nLiteralSectionSize = Literal[\"1\", \"2\", \"3\"]\n\n\nclass Section(elements.Section, RadixThemesComponent):\n    \"\"\"Denotes a section of page content.\"\"\"\n\n    tag = \"Section\"\n\n    # The size of the section: \"1\" - \"3\" (default \"2\")\n    size: Var[Responsive[LiteralSectionSize]] = LiteralVar.create(\"2\")\n\n\nsection = Section.create\n"
  },
  {
    "path": "reflex/components/radix/themes/layout/spacer.py",
    "content": "\"\"\"A spacer component.\"\"\"\n\nfrom __future__ import annotations\n\nfrom typing import Any\n\nfrom .flex import Flex\n\n\nclass Spacer(Flex):\n    \"\"\"A spacer component.\"\"\"\n\n    def add_style(self) -> dict[str, Any] | None:\n        \"\"\"Add style to the component.\n\n        Returns:\n            The style of the component.\n        \"\"\"\n        return {\n            \"flex\": 1,\n            \"justify_self\": \"stretch\",\n            \"align_self\": \"stretch\",\n        }\n\n\nspacer = Spacer.create\n"
  },
  {
    "path": "reflex/components/radix/themes/layout/stack.py",
    "content": "\"\"\"Stack components.\"\"\"\n\nfrom __future__ import annotations\n\nfrom reflex.components.component import Component\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.radix.themes.base import LiteralAlign, LiteralSpacing\nfrom reflex.vars.base import Var\n\nfrom .flex import Flex, LiteralFlexDirection\n\n\nclass Stack(Flex):\n    \"\"\"A stack component.\"\"\"\n\n    # The spacing between each stack item.\n    spacing: Var[Responsive[LiteralSpacing]] = Var.create(\"3\")\n\n    # The alignment of the stack items.\n    align: Var[Responsive[LiteralAlign]] = Var.create(\"start\")\n\n    @classmethod\n    def create(\n        cls,\n        *children,\n        **props,\n    ) -> Component:\n        \"\"\"Create a new instance of the component.\n\n        Args:\n            *children: The children of the stack.\n            **props: The properties of the stack.\n\n        Returns:\n            The stack component.\n        \"\"\"\n        # Apply the default classname\n        given_class_name = props.pop(\"class_name\", [])\n        if not isinstance(given_class_name, list):\n            given_class_name = [given_class_name]\n        props[\"class_name\"] = [\"rx-Stack\", *given_class_name]\n\n        return super().create(\n            *children,\n            **props,\n        )\n\n\nclass VStack(Stack):\n    \"\"\"A vertical stack component.\"\"\"\n\n    # The direction of the stack.\n    direction: Var[Responsive[LiteralFlexDirection]] = Var.create(\"column\")\n\n\nclass HStack(Stack):\n    \"\"\"A horizontal stack component.\"\"\"\n\n    # The direction of the stack.\n    direction: Var[Responsive[LiteralFlexDirection]] = Var.create(\"row\")\n\n\nstack = Stack.create\nhstack = HStack.create\nvstack = VStack.create\n"
  },
  {
    "path": "reflex/components/radix/themes/typography/__init__.py",
    "content": "\"\"\"Typographic components.\"\"\"\n\nfrom __future__ import annotations\n\nfrom reflex import RADIX_THEMES_TYPOGRAPHY_MAPPING\nfrom reflex.utils import lazy_loader\n\n_SUBMOD_ATTRS: dict[str, list[str]] = {\n    \"\".join(k.split(\"components.radix.themes.typography.\")[-1]): v\n    for k, v in RADIX_THEMES_TYPOGRAPHY_MAPPING.items()\n}\n\n__getattr__, __dir__, __all__ = lazy_loader.attach(\n    __name__,\n    submod_attrs=_SUBMOD_ATTRS,\n)\n"
  },
  {
    "path": "reflex/components/radix/themes/typography/base.py",
    "content": "\"\"\"Components for rendering text.\n\nhttps://www.radix-ui.com/themes/docs/theme/typography\n\"\"\"\n\nfrom __future__ import annotations\n\nfrom typing import Literal\n\nLiteralTextWeight = Literal[\"light\", \"regular\", \"medium\", \"bold\"]\nLiteralTextAlign = Literal[\"left\", \"center\", \"right\"]\nLiteralTextSize = Literal[\"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\"]\nLiteralTextTrim = Literal[\"normal\", \"start\", \"end\", \"both\"]\n"
  },
  {
    "path": "reflex/components/radix/themes/typography/blockquote.py",
    "content": "\"\"\"Components for rendering heading.\n\nhttps://www.radix-ui.com/themes/docs/theme/typography\n\"\"\"\n\nfrom __future__ import annotations\n\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.el import elements\nfrom reflex.components.radix.themes.base import LiteralAccentColor, RadixThemesComponent\nfrom reflex.vars.base import Var\n\nfrom .base import LiteralTextSize, LiteralTextWeight\n\n\nclass Blockquote(elements.Blockquote, RadixThemesComponent):\n    \"\"\"A block level extended quotation.\"\"\"\n\n    tag = \"Blockquote\"\n\n    # Text size: \"1\" - \"9\"\n    size: Var[Responsive[LiteralTextSize]]\n\n    # Thickness of text: \"light\" | \"regular\" | \"medium\" | \"bold\"\n    weight: Var[Responsive[LiteralTextWeight]]\n\n    # Overrides the accent color inherited from the Theme.\n    color_scheme: Var[LiteralAccentColor]\n\n    # Whether to render the text with higher contrast color\n    high_contrast: Var[bool]\n\n\nblockquote = Blockquote.create\n"
  },
  {
    "path": "reflex/components/radix/themes/typography/code.py",
    "content": "\"\"\"Components for rendering heading.\n\nhttps://www.radix-ui.com/themes/docs/theme/typography\n\"\"\"\n\nfrom __future__ import annotations\n\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.el import elements\nfrom reflex.components.markdown.markdown import MarkdownComponentMap\nfrom reflex.components.radix.themes.base import (\n    LiteralAccentColor,\n    LiteralVariant,\n    RadixThemesComponent,\n)\nfrom reflex.vars.base import Var\n\nfrom .base import LiteralTextSize, LiteralTextWeight\n\n\nclass Code(elements.Code, RadixThemesComponent, MarkdownComponentMap):\n    \"\"\"A block level extended quotation.\"\"\"\n\n    tag = \"Code\"\n\n    # The visual variant to apply: \"solid\" | \"soft\" | \"outline\" | \"ghost\"\n    variant: Var[LiteralVariant]\n\n    # Text size: \"1\" - \"9\"\n    size: Var[Responsive[LiteralTextSize]]\n\n    # Thickness of text: \"light\" | \"regular\" | \"medium\" | \"bold\"\n    weight: Var[Responsive[LiteralTextWeight]]\n\n    # Overrides the accent color inherited from the Theme.\n    color_scheme: Var[LiteralAccentColor]\n\n    # Whether to render the text with higher contrast color\n    high_contrast: Var[bool]\n\n\ncode = Code.create\n"
  },
  {
    "path": "reflex/components/radix/themes/typography/heading.py",
    "content": "\"\"\"Components for rendering heading.\n\nhttps://www.radix-ui.com/themes/docs/theme/typography\n\"\"\"\n\nfrom __future__ import annotations\n\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.el import elements\nfrom reflex.components.markdown.markdown import MarkdownComponentMap\nfrom reflex.components.radix.themes.base import LiteralAccentColor, RadixThemesComponent\nfrom reflex.vars.base import Var\n\nfrom .base import LiteralTextAlign, LiteralTextSize, LiteralTextTrim, LiteralTextWeight\n\n\nclass Heading(elements.H1, RadixThemesComponent, MarkdownComponentMap):\n    \"\"\"A foundational text primitive based on the <span> element.\"\"\"\n\n    tag = \"Heading\"\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior.\n    as_child: Var[bool]\n\n    # Change the default rendered element into a semantically appropriate alternative (cannot be used with asChild)\n    as_: Var[str]\n\n    # Text size: \"1\" - \"9\"\n    size: Var[Responsive[LiteralTextSize]]\n\n    # Thickness of text: \"light\" | \"regular\" | \"medium\" | \"bold\"\n    weight: Var[Responsive[LiteralTextWeight]]\n\n    # Alignment of text in element: \"left\" | \"center\" | \"right\"\n    align: Var[Responsive[LiteralTextAlign]]\n\n    # Removes the leading trim space: \"normal\" | \"start\" | \"end\" | \"both\"\n    trim: Var[Responsive[LiteralTextTrim]]\n\n    # Overrides the accent color inherited from the Theme.\n    color_scheme: Var[LiteralAccentColor]\n\n    # Whether to render the text with higher contrast color\n    high_contrast: Var[bool]\n\n\nheading = Heading.create\n"
  },
  {
    "path": "reflex/components/radix/themes/typography/link.py",
    "content": "\"\"\"Components for rendering heading.\n\nhttps://www.radix-ui.com/themes/docs/theme/typography\n\"\"\"\n\nfrom __future__ import annotations\n\nfrom typing import Literal\n\nfrom reflex.components.component import Component, MemoizationLeaf\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.core.colors import color\nfrom reflex.components.core.cond import cond\nfrom reflex.components.el.elements.inline import A\nfrom reflex.components.markdown.markdown import MarkdownComponentMap\nfrom reflex.components.radix.themes.base import LiteralAccentColor, RadixThemesComponent\nfrom reflex.components.react_router.dom import ReactRouterLink\nfrom reflex.utils.imports import ImportDict, ImportVar\nfrom reflex.vars.base import Var\n\nfrom .base import LiteralTextSize, LiteralTextTrim, LiteralTextWeight\n\nLiteralLinkUnderline = Literal[\"auto\", \"hover\", \"always\", \"none\"]\n\n\n_KNOWN_REACT_ROUTER_LINK_PROPS = frozenset(ReactRouterLink.get_props())\n\n\nclass Link(RadixThemesComponent, A, MemoizationLeaf, MarkdownComponentMap):\n    \"\"\"A semantic element for navigation between pages.\"\"\"\n\n    tag = \"Link\"\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior.\n    as_child: Var[bool]\n\n    # Text size: \"1\" - \"9\"\n    size: Var[Responsive[LiteralTextSize]]\n\n    # Thickness of text: \"light\" | \"regular\" | \"medium\" | \"bold\"\n    weight: Var[Responsive[LiteralTextWeight]]\n\n    # Removes the leading trim space: \"normal\" | \"start\" | \"end\" | \"both\"\n    trim: Var[Responsive[LiteralTextTrim]]\n\n    # Sets the visibility of the underline affordance: \"auto\" | \"hover\" | \"always\" | \"none\"\n    underline: Var[LiteralLinkUnderline]\n\n    # Overrides the accent color inherited from the Theme.\n    color_scheme: Var[LiteralAccentColor]\n\n    # Whether to render the text with higher contrast color\n    high_contrast: Var[bool]\n\n    # If True, the link will open in a new tab\n    is_external: Var[bool]\n\n    def add_imports(self) -> ImportDict:\n        \"\"\"Add imports for the Link component.\n\n        Returns:\n            The import dict.\n        \"\"\"\n        return {\n            \"react-router\": [ImportVar(tag=\"Link\", alias=\"ReactRouterLink\")],\n        }\n\n    @classmethod\n    def create(cls, *children, **props) -> Component:\n        \"\"\"Create a Link component.\n\n        Args:\n            *children: The children of the component.\n            **props: The props of the component.\n\n        Returns:\n            Component: The link component\n\n        Raises:\n            ValueError: in case of missing children\n        \"\"\"\n        props.setdefault(\"_hover\", {\"color\": color(\"accent\", 8)})\n        href = props.get(\"href\")\n\n        is_external = props.pop(\"is_external\", None)\n\n        if is_external is not None:\n            props[\"target\"] = cond(is_external, \"_blank\", \"\")\n\n        if href is not None:\n            if not len(children):\n                msg = \"Link without a child will not display\"\n                raise ValueError(msg)\n\n            if \"as_child\" not in props:\n                # Extract props for the ReactRouterLink, the rest go to the Link/A element.\n                react_router_link_props = {}\n                for prop in props.copy():\n                    if prop in _KNOWN_REACT_ROUTER_LINK_PROPS:\n                        react_router_link_props[prop] = props.pop(prop)\n\n                react_router_link_props[\"to\"] = react_router_link_props.pop(\n                    \"href\", href\n                )\n\n                # If user does not use `as_child`, by default we render using react_router_link to avoid page refresh during internal navigation\n                return super().create(\n                    ReactRouterLink.create(*children, **react_router_link_props),\n                    as_child=True,\n                    **props,\n                )\n        else:\n            props[\"href\"] = \"#\"\n\n        return super().create(*children, **props)\n\n\nlink = Link.create\n"
  },
  {
    "path": "reflex/components/radix/themes/typography/text.py",
    "content": "\"\"\"Components for rendering text.\n\nhttps://www.radix-ui.com/themes/docs/theme/typography\n\"\"\"\n\nfrom __future__ import annotations\n\nfrom typing import Literal\n\nfrom reflex.components.component import ComponentNamespace\nfrom reflex.components.core.breakpoints import Responsive\nfrom reflex.components.el import elements\nfrom reflex.components.markdown.markdown import MarkdownComponentMap\nfrom reflex.components.radix.themes.base import LiteralAccentColor, RadixThemesComponent\nfrom reflex.vars.base import Var\n\nfrom .base import LiteralTextAlign, LiteralTextSize, LiteralTextTrim, LiteralTextWeight\n\nLiteralType = Literal[\n    \"p\",\n    \"label\",\n    \"div\",\n    \"span\",\n    \"b\",\n    \"i\",\n    \"u\",\n    \"abbr\",\n    \"cite\",\n    \"del\",\n    \"em\",\n    \"ins\",\n    \"kbd\",\n    \"mark\",\n    \"s\",\n    \"samp\",\n    \"sub\",\n    \"sup\",\n]\n\n\nclass Text(elements.Span, RadixThemesComponent, MarkdownComponentMap):\n    \"\"\"A foundational text primitive based on the <span> element.\"\"\"\n\n    tag = \"Text\"\n\n    # Change the default rendered element for the one passed as a child, merging their props and behavior.\n    as_child: Var[bool]\n\n    # Change the default rendered element into a semantically appropriate alternative (cannot be used with asChild)\n    as_: Var[LiteralType] = Var.create(\"p\")\n\n    # Text size: \"1\" - \"9\"\n    size: Var[Responsive[LiteralTextSize]]\n\n    # Thickness of text: \"light\" | \"regular\" | \"medium\" | \"bold\"\n    weight: Var[Responsive[LiteralTextWeight]]\n\n    # Alignment of text in element: \"left\" | \"center\" | \"right\"\n    align: Var[Responsive[LiteralTextAlign]]\n\n    # Removes the leading trim space: \"normal\" | \"start\" | \"end\" | \"both\"\n    trim: Var[Responsive[LiteralTextTrim]]\n\n    # Overrides the accent color inherited from the Theme.\n    color_scheme: Var[LiteralAccentColor]\n\n    # Whether to render the text with higher contrast color\n    high_contrast: Var[bool]\n\n\nclass Span(Text):\n    \"\"\"A variant of text rendering as <span> element.\"\"\"\n\n    as_: Var[LiteralType] = Var.create(\"span\")\n\n\nclass Em(elements.Em, RadixThemesComponent):\n    \"\"\"Marks text to stress emphasis.\"\"\"\n\n    tag = \"Em\"\n\n\nclass Kbd(elements.Kbd, RadixThemesComponent):\n    \"\"\"Represents keyboard input or a hotkey.\"\"\"\n\n    tag = \"Kbd\"\n\n    # Text size: \"1\" - \"9\"\n    size: Var[LiteralTextSize]\n\n\nclass Quote(elements.Q, RadixThemesComponent):\n    \"\"\"A short inline quotation.\"\"\"\n\n    tag = \"Quote\"\n\n\nclass Strong(elements.Strong, RadixThemesComponent):\n    \"\"\"Marks text to signify strong importance.\"\"\"\n\n    tag = \"Strong\"\n\n\nclass TextNamespace(ComponentNamespace):\n    \"\"\"Checkbox components namespace.\"\"\"\n\n    __call__ = staticmethod(Text.create)\n    em = staticmethod(Em.create)\n    kbd = staticmethod(Kbd.create)\n    quote = staticmethod(Quote.create)\n    strong = staticmethod(Strong.create)\n    span = staticmethod(Span.create)\n\n\ntext = TextNamespace()\n"
  },
  {
    "path": "reflex/components/react_player/__init__.py",
    "content": "\"\"\"React Player component for audio and video.\"\"\"\n\nfrom . import react_player\nfrom .audio import Audio\nfrom .video import Video\n\naudio = Audio.create\nvideo = Video.create\n"
  },
  {
    "path": "reflex/components/react_player/audio.py",
    "content": "\"\"\"A audio component.\"\"\"\n\nfrom reflex.components.react_player.react_player import ReactPlayer\n\n\nclass Audio(ReactPlayer):\n    \"\"\"Audio component share with Video component.\"\"\"\n"
  },
  {
    "path": "reflex/components/react_player/react_player.py",
    "content": "\"\"\"React-Player component.\"\"\"\n\nfrom __future__ import annotations\n\nfrom typing import Any, TypedDict\n\nfrom reflex.components.component import Component\nfrom reflex.components.core.cond import cond\nfrom reflex.event import EventHandler, no_args_event_spec\nfrom reflex.utils import console\nfrom reflex.vars.base import Var\nfrom reflex.vars.object import ObjectVar\n\nReactPlayerEvent = ObjectVar[dict[str, dict[str, dict[str, Any]]]]\n\n\nclass Progress(TypedDict):\n    \"\"\"Callback containing played and loaded progress as a fraction, and playedSeconds and loadedSeconds in seconds.\"\"\"\n\n    played: float\n    playedSeconds: float\n    loaded: float\n    loadedSeconds: float\n    duration: float\n\n\ndef _on_progress_signature(event: ReactPlayerEvent) -> list[Var[Progress]]:\n    \"\"\"Type signature for on_progress event.\n\n    Args:\n        event: The event variable.\n\n    Returns:\n        The progress information extracted from the event.\n    \"\"\"\n    player_info = event[\"target\"][\"api\"][\"playerInfo\"].to(dict)\n    progress_state = player_info[\"progressState\"].to(dict)\n    current = progress_state[\"current\"].to(float)\n    loaded = progress_state[\"loaded\"].to(float)\n    duration = progress_state[\"duration\"].to(float)\n    return [\n        cond(\n            progress_state,\n            {\n                \"played\": cond(duration, current / duration, 0.0),\n                \"playedSeconds\": current,\n                \"loaded\": cond(duration, loaded / duration, 0.0),\n                \"loadedSeconds\": loaded,\n                \"duration\": duration,\n            },\n            {\n                \"played\": 0.0,\n                \"playedSeconds\": 0.0,\n                \"loaded\": 0.0,\n                \"loadedSeconds\": 0.0,\n                \"duration\": 0.0,\n            },\n        ).to(Progress)\n    ]\n\n\ndef _player_info_key_or_zero(event: ReactPlayerEvent, key: str) -> Var[float]:\n    \"\"\"Helper to extract a value from playerInfo or return 0.0 if not available.\n\n    Args:\n        event: The event variable.\n        key: The key to extract from playerInfo.\n\n    Returns:\n        The extracted value or 0.0 if not available.\n    \"\"\"\n    player_info = event[\"target\"][\"api\"][\"playerInfo\"].to(dict)\n    return cond(\n        player_info[key],\n        player_info[key],\n        0.0,\n    ).to(float)\n\n\ndef _on_time_update_signature(event: ReactPlayerEvent) -> list[Var[float]]:\n    \"\"\"Type signature for on_time_update event.\n\n    Args:\n        event: The event variable.\n\n    Returns:\n        The current timestamp in seconds.\n    \"\"\"\n    return [_player_info_key_or_zero(event, \"currentTime\")]\n\n\ndef _on_duration_change_signature(event: ReactPlayerEvent) -> list[Var[float]]:\n    \"\"\"Type signature for on_duration_change event.\n\n    Args:\n        event: The event variable.\n\n    Returns:\n        The active media's duration in seconds.\n    \"\"\"\n    return [_player_info_key_or_zero(event, \"duration\")]\n\n\ndef _on_rate_change_signature(event: ReactPlayerEvent) -> list[Var[float]]:\n    \"\"\"Type signature for on_rate_change event.\n\n    Args:\n        event: The event variable.\n\n    Returns:\n        The current playback rate.\n    \"\"\"\n    return [_player_info_key_or_zero(event, \"playbackRate\")]\n\n\n_DEPRECATED_PROP_MAP = {\n    \"url\": \"src\",\n    \"on_duration\": \"on_duration_change\",\n    \"on_playback_rate_change\": \"on_rate_change\",\n    \"on_seek\": \"on_seeked\",\n    \"on_buffer\": \"on_waiting\",\n    \"on_buffer_end\": \"on_playing\",\n    \"on_enable_pip\": \"on_enter_picture_in_picture\",\n    \"on_disable_pip\": \"on_leave_picture_in_picture\",\n}\n\n\nclass ReactPlayer(Component):\n    \"\"\"Using react-player and not implement all props and callback yet.\n    reference: https://github.com/cookpete/react-player.\n    \"\"\"\n\n    library = \"react-player@3.4.0\"\n\n    tag = \"ReactPlayer\"\n\n    is_default = True\n\n    # The url of a video or song to play\n    src: Var[str | list[str] | list[dict[str, str]]]\n\n    # Set to true or false to pause or play the media\n    playing: Var[bool]\n\n    # Set to true or false to loop the media\n    loop: Var[bool]\n\n    # Set to true or false to display native player controls.\n    controls: Var[bool] = Var.create(True)\n\n    # Set to true to show just the video thumbnail, which loads the full player on click\n    light: Var[bool]\n\n    # Set the volume of the player, between 0 and 1\n    volume: Var[float]\n\n    # Mutes the player\n    muted: Var[bool]\n\n    # Player-specific configuration parameters.\n    config: Var[dict[str, Any]]\n\n    # Set to true to disable the default remote playback option on supported devices.\n    disable_remote_playback: Var[bool]\n\n    # Called when media is loaded and ready to play. If playing is set to true, media will play immediately.\n    on_ready: EventHandler[no_args_event_spec]\n\n    # Called when media starts playing.\n    on_start: EventHandler[no_args_event_spec]\n\n    # Called when playing is set to true.\n    on_play: EventHandler[no_args_event_spec]\n\n    # Called when media starts or resumes playing after pausing or buffering.\n    on_playing: EventHandler[no_args_event_spec]\n\n    # Called while the video is loading only. Contains played and loaded progress as a fraction, and playedSeconds and loadedSeconds in seconds. eg { played: 0.12, playedSeconds: 11.3, loaded: 0.34, loadedSeconds: 16.7 }\n    on_progress: EventHandler[_on_progress_signature]\n\n    # Called when the media's current time changes (~4Hz, use .throttle to limit calls to backend).\n    on_time_update: EventHandler[_on_time_update_signature]\n\n    # Callback containing duration of the media, in seconds.\n    on_duration_change: EventHandler[_on_duration_change_signature]\n\n    # Called when media is paused.\n    on_pause: EventHandler[no_args_event_spec]\n\n    # Called when media starts buffering.\n    on_waiting: EventHandler[no_args_event_spec]\n\n    # Called when the media is seeking.\n    on_seeking: EventHandler[no_args_event_spec]\n\n    # Called when media seeks with seconds parameter.\n    on_seeked: EventHandler[_on_time_update_signature]\n\n    # Called when playback rate of the player changed. Only supported by YouTube, Vimeo (if enabled), Wistia, and file paths.\n    on_rate_change: EventHandler[_on_rate_change_signature]\n\n    # Called when media finishes playing. Does not fire when loop is set to true.\n    on_ended: EventHandler[no_args_event_spec]\n\n    # Called when an error occurs whilst attempting to play media.\n    on_error: EventHandler[no_args_event_spec]\n\n    # Called when user clicks the light mode preview.\n    on_click_preview: EventHandler[no_args_event_spec]\n\n    # Called when picture-in-picture mode is enabled.\n    on_enter_picture_in_picture: EventHandler[no_args_event_spec]\n\n    # Called when picture-in-picture mode is disabled.\n    on_leave_picture_in_picture: EventHandler[no_args_event_spec]\n\n    @classmethod\n    def create(cls, *children, **props) -> ReactPlayer:\n        \"\"\"Create a component.\n\n        Args:\n            children: The children of the component.\n            props: The props of the component.\n\n        Returns:\n            The created component.\n\n        Raises:\n            ValueError: If both a deprecated prop and its replacement are both passed.\n        \"\"\"\n        for prop, new_prop in _DEPRECATED_PROP_MAP.items():\n            if prop in props:\n                if new_prop in props:\n                    msg = (\n                        f\"The prop {prop!r} is deprecated, but the replacement {new_prop!r} is also passed. Please remove {prop!r}.\",\n                    )\n                    raise ValueError(msg)\n                console.warn(\n                    f\"The prop {prop!r} has been replaced by {new_prop!r}, please update your code.\",\n                )\n                props[new_prop] = props.pop(prop)\n        return super().create(*children, **props)  # type: ignore[return-value]\n\n    def _render(self, props: dict[str, Any] | None = None):\n        \"\"\"Render the component. Adds width and height set to None because\n        react-player will set them to some random value that overrides the\n        css width and height.\n\n        Args:\n            props: The props to pass to the component.\n\n        Returns:\n            The rendered component.\n        \"\"\"\n        return (\n            super()\n            ._render(props)\n            .add_props(\n                width=Var.create(None),\n                height=Var.create(None),\n            )\n        )\n"
  },
  {
    "path": "reflex/components/react_player/video.py",
    "content": "\"\"\"A video component.\"\"\"\n\nfrom reflex.components.react_player.react_player import ReactPlayer\n\n\nclass Video(ReactPlayer):\n    \"\"\"Video component share with audio component.\"\"\"\n"
  },
  {
    "path": "reflex/components/react_router/__init__.py",
    "content": "\"\"\"React-router internal components.\"\"\"\n\nfrom .dom import ReactRouterLink\n\nlink = ReactRouterLink.create\n"
  },
  {
    "path": "reflex/components/react_router/dom.py",
    "content": "\"\"\"Components for client side navigation within React Router applications.\"\"\"\n\nfrom __future__ import annotations\n\nfrom typing import ClassVar, Literal, TypedDict\n\nfrom reflex.components.el.elements.inline import A\nfrom reflex.vars.base import Var\n\nLiteralLinkDiscover = Literal[\"none\", \"render\"]\n\n\nclass To(TypedDict):\n    \"\"\"Structured object for navigating via the `to` prop.\"\"\"\n\n    # A URL pathname, beginning with a /\n    pathname: str\n\n    # A URL search string, beginning with a ?.\n    search: str\n\n    # A URL fragment identifier, beginning with a #.\n    hash: str\n\n\nclass ReactRouterLink(A):\n    \"\"\"Links are accessible elements used primarily for navigation. This component is styled to resemble a hyperlink and semantically renders an <a>.\"\"\"\n\n    library = \"react-router\"\n\n    tag = \"Link\"\n\n    alias = \"ReactRouterLink\"\n\n    # The page to link to.\n    to: Var[str | To]\n\n    # Replaces the current entry in the history stack instead of pushing a new one onto it.\n    replace: Var[bool]\n\n    # Will use document navigation instead of client side routing when the link is clicked: the browser will handle the transition normally (as if it were an <a href>).\n    reload_document: Var[bool]\n\n    # Prevents the scroll position from being reset to the top of the window when the link is clicked and the app is using ScrollRestoration. This only prevents new locations resetting scroll to the top, scroll position will be restored for back/forward button navigation.\n    prevent_scroll_reset: Var[bool]\n\n    # Defines the link discovery behavior\n    discover: Var[LiteralLinkDiscover]\n\n    # Enables a View Transition for this navigation.\n    view_transition: Var[bool]\n\n    @classmethod\n    def create(cls, *children, **props):\n        \"\"\"Create a ReactRouterLink component for client-side navigation.\n\n        Args:\n            *children: The children of the component.\n            **props: The props of the component.\n\n        Returns:\n            The ReactRouterLink component.\n        \"\"\"\n        # React Router special behavior is triggered on the `to` prop, not href.\n        if \"to\" not in props and \"href\" in props:\n            props[\"to\"] = props.pop(\"href\")\n        return super().create(*children, **props)\n\n    _invalid_children: ClassVar[list[str]] = [\"A\", \"ReactRouterLink\"]\n"
  },
  {
    "path": "reflex/components/recharts/__init__.py",
    "content": "\"\"\"Recharts components.\"\"\"\n\nfrom __future__ import annotations\n\nfrom reflex.utils import lazy_loader\n\n_SUBMOD_ATTRS: dict = {\n    \"cartesian\": [\n        \"area\",\n        \"Area\",\n        \"bar\",\n        \"Bar\",\n        \"line\",\n        \"Line\",\n        \"scatter\",\n        \"Scatter\",\n        \"x_axis\",\n        \"XAxis\",\n        \"y_axis\",\n        \"YAxis\",\n        \"z_axis\",\n        \"ZAxis\",\n        \"brush\",\n        \"Brush\",\n        \"cartesian_axis\",\n        \"CartesianAxis\",\n        \"cartesian_grid\",\n        \"CartesianGrid\",\n        \"reference_line\",\n        \"ReferenceLine\",\n        \"reference_dot\",\n        \"ReferenceDot\",\n        \"reference_area\",\n        \"ReferenceArea\",\n        \"error_bar\",\n        \"ErrorBar\",\n        \"funnel\",\n        \"Funnel\",\n    ],\n    \"charts\": [\n        \"area_chart\",\n        \"AreaChart\",\n        \"bar_chart\",\n        \"BarChart\",\n        \"line_chart\",\n        \"LineChart\",\n        \"composed_chart\",\n        \"ComposedChart\",\n        \"pie_chart\",\n        \"PieChart\",\n        \"radar_chart\",\n        \"RadarChart\",\n        \"radial_bar_chart\",\n        \"RadialBarChart\",\n        \"scatter_chart\",\n        \"ScatterChart\",\n        \"funnel_chart\",\n        \"FunnelChart\",\n        \"treemap\",\n        \"Treemap\",\n    ],\n    \"general\": [\n        \"responsive_container\",\n        \"ResponsiveContainer\",\n        \"legend\",\n        \"Legend\",\n        \"tooltip\",\n        \"graphing_tooltip\",\n        \"GraphingTooltip\",\n        \"label\",\n        \"Label\",\n        \"label_list\",\n        \"LabelList\",\n        \"cell\",\n        \"Cell\",\n    ],\n    \"polar\": [\n        \"pie\",\n        \"Pie\",\n        \"radar\",\n        \"Radar\",\n        \"radial_bar\",\n        \"RadialBar\",\n        \"polar_angle_axis\",\n        \"PolarAngleAxis\",\n        \"polar_grid\",\n        \"PolarGrid\",\n        \"polar_radius_axis\",\n        \"PolarRadiusAxis\",\n    ],\n    \"recharts\": [\n        \"LiteralAnimationEasing\",\n        \"LiteralAxisType\",\n        \"LiteralBarChartStackOffset\",\n        \"LiteralComposedChartBaseValue\",\n        \"LiteralCurveType\",\n        \"LiteralDirection\",\n        \"LiteralGridType\",\n        \"LiteralIconType\",\n        \"LiteralIfOverflow\",\n        \"LiteralInterval\",\n        \"LiteralLayout\",\n        \"LiteralLegendAlign\",\n        \"LiteralLegendType\",\n        \"LiteralLineType\",\n        \"LiteralOrientation\",\n        \"LiteralOrientationLeftRightMiddle\",\n        \"LiteralOrientationTopBottom\",\n        \"LiteralOrientationTopBottomLeftRight\",\n        \"LiteralPolarRadiusType\",\n        \"LiteralScale\",\n        \"LiteralShape\",\n        \"LiteralStackOffset\",\n        \"LiteralSyncMethod\",\n        \"LiteralVerticalAlign\",\n    ],\n}\n\n__getattr__, __dir__, __all__ = lazy_loader.attach(\n    __name__,\n    submod_attrs=_SUBMOD_ATTRS,\n)\n"
  },
  {
    "path": "reflex/components/recharts/cartesian.py",
    "content": "\"\"\"Cartesian charts in Recharts.\"\"\"\n\nfrom __future__ import annotations\n\nfrom collections.abc import Sequence\nfrom typing import Any, ClassVar, TypedDict\n\nfrom reflex.constants import EventTriggers\nfrom reflex.constants.colors import Color\nfrom reflex.event import EventHandler, no_args_event_spec\nfrom reflex.vars.base import LiteralVar, Var\n\nfrom .recharts import (\n    ACTIVE_DOT_TYPE,\n    LiteralAnimationEasing,\n    LiteralCurveType,\n    LiteralDirection,\n    LiteralIfOverflow,\n    LiteralInterval,\n    LiteralIntervalAxis,\n    LiteralLayout,\n    LiteralLegendType,\n    LiteralLineType,\n    LiteralOrientationLeftRight,\n    LiteralOrientationTopBottom,\n    LiteralOrientationTopBottomLeftRight,\n    LiteralPolarRadiusType,\n    LiteralScale,\n    LiteralShape,\n    LiteralTextAnchor,\n    Recharts,\n)\n\n\nclass Axis(Recharts):\n    \"\"\"A base class for axes in Recharts.\"\"\"\n\n    # The key of data displayed in the axis.\n    data_key: Var[str | int]\n\n    # If set true, the axis do not display in the chart. Default: False\n    hide: Var[bool]\n\n    # The width of axis which is usually calculated internally.\n    width: Var[str | int]\n\n    # The height of axis, which can be set by user.\n    height: Var[str | int]\n\n    # The type of axis 'number' | 'category'\n    type_: Var[LiteralPolarRadiusType]\n\n    # If set 0, all the ticks will be shown. If set preserveStart\", \"preserveEnd\" or \"preserveStartEnd\", the ticks which is to be shown or hidden will be calculated automatically. Default: \"preserveEnd\"\n    interval: Var[LiteralIntervalAxis | int]\n\n    # Allow the ticks of Axis to be decimals or not. Default: True\n    allow_decimals: Var[bool]\n\n    # When domain of the axis is specified and the type of the axis is 'number', if allowDataOverflow is set to be false, the domain will be adjusted when the minimum value of data is smaller than domain[0] or the maximum value of data is greater than domain[1] so that the axis displays all data values. If set to true, graphic elements (line, area, bars) will be clipped to conform to the specified domain. Default: False\n    allow_data_overflow: Var[bool]\n\n    # Allow the axis has duplicated categorys or not when the type of axis is \"category\". Default: True\n    allow_duplicated_category: Var[bool]\n\n    # The range of the axis. Work best in conjunction with allow_data_overflow. Default: [0, \"auto\"]\n    domain: Var[Sequence]\n\n    # If set false, no axis line will be drawn. Default: True\n    axis_line: Var[bool]\n\n    # If set true, flips ticks around the axis line, displaying the labels inside the chart instead of outside. Default: False\n    mirror: Var[bool]\n\n    # Reverse the ticks or not. Default: False\n    reversed: Var[bool]\n\n    # The label of axis, which appears next to the axis.\n    label: Var[str | int | dict[str, Any]]\n\n    # If 'auto' set, the scale function is decided by the type of chart, and the props type. 'auto' | 'linear' | 'pow' | 'sqrt' | 'log' | 'identity' | 'time' | 'band' | 'point' | 'ordinal' | 'quantile' | 'quantize' | 'utc' | 'sequential' | 'threshold'. Default: \"auto\"\n    scale: Var[LiteralScale]\n\n    # The unit of data displayed in the axis. This option will be used to represent an index unit in a scatter chart.\n    unit: Var[str | int]\n\n    # The name of data displayed in the axis. This option will be used to represent an index in a scatter chart.\n    name: Var[str | int]\n\n    # Set the values of axis ticks manually.\n    ticks: Var[Sequence[str | int]]\n\n    # If set false, no ticks will be drawn.\n    tick: Var[bool | dict]\n\n    # The count of axis ticks. Not used if 'type' is 'category'. Default: 5\n    tick_count: Var[int]\n\n    # If set false, no axis tick lines will be drawn. Default: True\n    tick_line: Var[bool]\n\n    # The length of tick line. Default: 6\n    tick_size: Var[int]\n\n    # The minimum gap between two adjacent labels. Default: 5\n    min_tick_gap: Var[int]\n\n    # The stroke color of axis. Default: rx.color(\"gray\", 9)\n    stroke: Var[str | Color] = LiteralVar.create(Color(\"gray\", 9))\n\n    # The text anchor of axis. Default: \"middle\"\n    text_anchor: Var[LiteralTextAnchor]\n\n    # The customized event handler of click on the ticks of this axis\n    on_click: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mousedown on the ticks of this axis\n    on_mouse_down: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseup on the ticks of this axis\n    on_mouse_up: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mousemove on the ticks of this axis\n    on_mouse_move: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseout on the ticks of this axis\n    on_mouse_out: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseenter on the ticks of this axis\n    on_mouse_enter: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseleave on the ticks of this axis\n    on_mouse_leave: EventHandler[no_args_event_spec]\n\n\nclass XAxis(Axis):\n    \"\"\"An XAxis component in Recharts.\"\"\"\n\n    tag = \"XAxis\"\n\n    alias = \"RechartsXAxis\"\n\n    # The orientation of axis 'top' | 'bottom'. Default: \"bottom\"\n    orientation: Var[LiteralOrientationTopBottom]\n\n    # The id of x-axis which is corresponding to the data. Default: 0\n    x_axis_id: Var[str | int]\n\n    # Ensures that all datapoints within a chart contribute to its domain calculation, even when they are hidden. Default: False\n    include_hidden: Var[bool]\n\n    # The angle of axis ticks. Default: 0\n    angle: Var[int]\n\n    # Specify the padding of x-axis. Default: {\"left\": 0, \"right\": 0}\n    padding: Var[dict[str, int]]\n\n\nclass YAxis(Axis):\n    \"\"\"A YAxis component in Recharts.\"\"\"\n\n    tag = \"YAxis\"\n\n    alias = \"RechartsYAxis\"\n\n    # The orientation of axis 'left' | 'right'. Default: \"left\"\n    orientation: Var[LiteralOrientationLeftRight]\n\n    # The id of y-axis which is corresponding to the data. Default: 0\n    y_axis_id: Var[str | int]\n\n    # Specify the padding of y-axis. Default: {\"top\": 0, \"bottom\": 0}\n    padding: Var[dict[str, int]]\n\n\nclass ZAxis(Recharts):\n    \"\"\"A ZAxis component in Recharts.\"\"\"\n\n    tag = \"ZAxis\"\n\n    alias = \"RechartsZAxis\"\n\n    # The key of data displayed in the axis.\n    data_key: Var[str | int]\n\n    # The unique id of z-axis. Default: 0\n    z_axis_id: Var[str | int]\n\n    # The range of axis. Default: [60, 400]\n    range: Var[Sequence[int]] = LiteralVar.create([60, 400])\n\n    # The unit of data displayed in the axis. This option will be used to represent an index unit in a scatter chart.\n    unit: Var[str | int]\n\n    # The name of data displayed in the axis. This option will be used to represent an index in a scatter chart.\n    name: Var[str | int]\n\n    # If 'auto' set, the scale function is decided by the type of chart, and the props type. Default: \"auto\"\n    scale: Var[LiteralScale]\n\n\nclass Brush(Recharts):\n    \"\"\"A Brush component in Recharts.\"\"\"\n\n    tag = \"Brush\"\n\n    alias = \"RechartsBrush\"\n\n    # Stroke color. Default: rx.color(\"gray\", 9)\n    stroke: Var[str | Color] = LiteralVar.create(Color(\"gray\", 9))\n\n    # The fill color of brush. Default: rx.color(\"gray\", 2)\n    fill: Var[str | Color] = LiteralVar.create(Color(\"gray\", 2))\n\n    # The key of data displayed in the axis.\n    data_key: Var[str | int]\n\n    # The x-coordinate of brush. Default: 0\n    x: Var[int]\n\n    # The y-coordinate of brush. Default: 0\n    y: Var[int]\n\n    # The width of brush. Default: 0\n    width: Var[int]\n\n    # The height of brush. Default: 40\n    height: Var[int]\n\n    # The original data of a LineChart, a BarChart or an AreaChart.\n    data: Var[Sequence[Any]]\n\n    # The width of each traveller. Default: 5\n    traveller_width: Var[int]\n\n    # The data with gap of refreshing chart. If the option is not set, the chart will be refreshed every time. Default: 1\n    gap: Var[int]\n\n    # The default start index of brush. If the option is not set, the start index will be 0. Default: 0\n    start_index: Var[int]\n\n    # The default end index of brush. If the option is not set, the end index will be calculated by the length of data.\n    end_index: Var[int]\n\n    @classmethod\n    def get_event_triggers(cls) -> dict[str, Var | Any]:\n        \"\"\"Get the event triggers that pass the component's value to the handler.\n\n        Returns:\n            A dict mapping the event trigger to the var that is passed to the handler.\n        \"\"\"\n        return {\n            EventTriggers.ON_CHANGE: no_args_event_spec,\n        }\n\n\nclass Cartesian(Recharts):\n    \"\"\"A base class for cartesian charts in Recharts.\"\"\"\n\n    # The layout of bar in the chart, usually inherited from parent. 'horizontal' | 'vertical'\n    layout: Var[LiteralLayout]\n\n    # The key of a group of data which should be unique in an area chart.\n    data_key: Var[str | int]\n\n    # The id of x-axis which is corresponding to the data. Default: 0\n    x_axis_id: Var[str | int]\n\n    # The id of y-axis which is corresponding to the data. Default: 0\n    y_axis_id: Var[str | int]\n\n    # The type of icon in legend. If set to 'none', no legend item will be rendered. 'line' | 'plainline' | 'square' | 'rect'| 'circle' | 'cross' | 'diamond' | 'star' | 'triangle' | 'wye' | 'none' optional\n    legend_type: Var[LiteralLegendType]\n\n    # If false set, labels will not be drawn. If true set, labels will be drawn which have the props calculated internally. Default: False\n    label: Var[bool | dict[str, Any]]\n\n    # If set false, animation of bar will be disabled. Default: True\n    is_animation_active: Var[bool]\n\n    # Specifies when the animation should begin, the unit of this option is ms. Default: 0\n    animation_begin: Var[int]\n\n    # Specifies the duration of animation, the unit of this option is ms. Default: 1500\n    animation_duration: Var[int]\n\n    # The type of easing function. Default: \"ease\"\n    animation_easing: Var[LiteralAnimationEasing]\n\n    # The unit of data. This option will be used in tooltip.\n    unit: Var[str | int]\n\n    # The name of data. This option will be used in tooltip and legend to represent the component. If no value was set to this option, the value of dataKey will be used alternatively.\n    name: Var[str | int]\n\n    # The customized event handler of animation start\n    on_animation_start: EventHandler[no_args_event_spec]\n\n    # The customized event handler of animation end\n    on_animation_end: EventHandler[no_args_event_spec]\n\n    # The customized event handler of click on the component in this group\n    on_click: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mousedown on the component in this group\n    on_mouse_down: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseup on the component in this group\n    on_mouse_up: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mousemove on the component in this group\n    on_mouse_move: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseover on the component in this group\n    on_mouse_over: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseout on the component in this group\n    on_mouse_out: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseenter on the component in this group\n    on_mouse_enter: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseleave on the component in this group\n    on_mouse_leave: EventHandler[no_args_event_spec]\n\n\nclass Area(Cartesian):\n    \"\"\"An Area component in Recharts.\"\"\"\n\n    tag = \"Area\"\n\n    alias = \"RechartsArea\"\n\n    # The color of the line stroke. Default: rx.color(\"accent\", 9)\n    stroke: Var[str | Color] = LiteralVar.create(Color(\"accent\", 9))\n\n    # The width of the line stroke. Default: 1\n    stroke_width: Var[str | int | float]\n\n    # The color of the area fill. Default: rx.color(\"accent\", 5)\n    fill: Var[str | Color] = LiteralVar.create(Color(\"accent\", 5))\n\n    # The interpolation type of area. And customized interpolation function can be set to type. 'basis' | 'basisClosed' | 'basisOpen' | 'bumpX' | 'bumpY' | 'bump' | 'linear' | 'linearClosed' | 'natural' | 'monotoneX' | 'monotoneY' | 'monotone' | 'step' | 'stepBefore' | 'stepAfter'. Default: \"monotone\"\n    type_: Var[LiteralCurveType] = LiteralVar.create(\"monotone\")\n\n    # If false set, dots will not be drawn. If true set, dots will be drawn which have the props calculated internally. Default: False\n    dot: Var[ACTIVE_DOT_TYPE]\n\n    # The dot is shown when user enter an area chart and this chart has tooltip. If false set, no active dot will not be drawn. If true set, active dot will be drawn which have the props calculated internally. Default: {stroke: rx.color(\"accent\", 2), fill: rx.color(\"accent\", 10)}\n    active_dot: Var[ACTIVE_DOT_TYPE] = LiteralVar.create({\n        \"stroke\": Color(\"accent\", 2),\n        \"fill\": Color(\"accent\", 10),\n    })\n\n    # The value which can describle the line, usually calculated internally.\n    base_line: Var[int | Sequence[dict[str, Any]]]\n\n    # The coordinates of all the points in the area, usually calculated internally.\n    points: Var[Sequence[dict[str, Any]]]\n\n    # The stack id of area, when two areas have the same value axis and same stack_id, then the two areas are stacked in order.\n    stack_id: Var[str | int]\n\n    # Whether to connect a graph area across null points. Default: False\n    connect_nulls: Var[bool]\n\n    # Valid children components\n    _valid_children: ClassVar[list[str]] = [\"LabelList\"]\n\n\nclass Bar(Cartesian):\n    \"\"\"A Bar component in Recharts.\"\"\"\n\n    tag = \"Bar\"\n\n    alias = \"RechartsBar\"\n\n    # The color of the line stroke.\n    stroke: Var[str | Color]\n\n    # The width of the line stroke.\n    stroke_width: Var[str | int | float]\n\n    # The width of the line stroke. Default: Color(\"accent\", 9)\n    fill: Var[str | Color] = LiteralVar.create(Color(\"accent\", 9))\n\n    # If false set, background of bars will not be drawn. If true set, background of bars will be drawn which have the props calculated internally. Default: False\n    background: Var[bool]\n\n    # The stack id of bar, when two bars have the same value axis and same stack_id, then the two bars are stacked in order.\n    stack_id: Var[str]\n\n    # The unit of data. This option will be used in tooltip.\n    unit: Var[str | int]\n\n    # The minimal height of a bar in a horizontal BarChart, or the minimal width of a bar in a vertical BarChart. By default, 0 values are not shown. To visualize a 0 (or close to zero) point, set the minimal point size to a pixel value like 3. In stacked bar charts, minPointSize might not be respected for tightly packed values. So we strongly recommend not using this prop in stacked BarCharts.\n    min_point_size: Var[int]\n\n    # The name of data. This option will be used in tooltip and legend to represent a bar. If no value was set to this option, the value of dataKey will be used alternatively.\n    name: Var[str | int]\n\n    # Size of the bar (if one bar_size is set then a bar_size must be set for all bars)\n    bar_size: Var[int]\n\n    # Max size of the bar\n    max_bar_size: Var[int]\n\n    # If set a value, the option is the radius of all the rounded corners. If set a array, the option are in turn the radiuses of top-left corner, top-right corner, bottom-right corner, bottom-left corner. Default: 0\n    radius: Var[int | Sequence[int]]\n\n    # The active bar is shown when a user enters a bar chart and this chart has tooltip. If set to false, no active bar will be drawn. If set to true, active bar will be drawn with the props calculated internally. If passed an object, active bar will be drawn, and the internally calculated props will be merged with the key value pairs of the passed object.\n    # active_bar: Var[Union[bool, dict[str, Any]]] #noqa: ERA001\n\n    # Valid children components\n    _valid_children: ClassVar[list[str]] = [\"Cell\", \"LabelList\", \"ErrorBar\"]\n\n\nclass Line(Cartesian):\n    \"\"\"A Line component in Recharts.\"\"\"\n\n    tag = \"Line\"\n\n    alias = \"RechartsLine\"\n\n    # The interpolation type of line. And customized interpolation function can be set to type. It's the same as type in Area.\n    type_: Var[LiteralCurveType]\n\n    # The color of the line stroke. Default: rx.color(\"accent\", 9)\n    stroke: Var[str | Color] = LiteralVar.create(Color(\"accent\", 9))\n\n    # The width of the line stroke. Default: 1\n    stroke_width: Var[str | int | float]\n\n    # The dot is shown when mouse enter a line chart and this chart has tooltip. If false set, no active dot will not be drawn. If true set, active dot will be drawn which have the props calculated internally. Default: {\"stroke\": rx.color(\"accent\", 10), \"fill\": rx.color(\"accent\", 4)}\n    dot: Var[ACTIVE_DOT_TYPE] = LiteralVar.create({\n        \"stroke\": Color(\"accent\", 10),\n        \"fill\": Color(\"accent\", 4),\n    })\n\n    # The dot is shown when user enter an area chart and this chart has tooltip. If false set, no active dot will not be drawn. If true set, active dot will be drawn which have the props calculated internally. Default: {\"stroke\": rx.color(\"accent\", 2), \"fill\": rx.color(\"accent\", 10)}\n    active_dot: Var[ACTIVE_DOT_TYPE] = LiteralVar.create({\n        \"stroke\": Color(\"accent\", 2),\n        \"fill\": Color(\"accent\", 10),\n    })\n\n    # Hides the line when true, useful when toggling visibility state via legend. Default: False\n    hide: Var[bool]\n\n    # Whether to connect a graph line across null points.\n    connect_nulls: Var[bool]\n\n    # The unit of data. This option will be used in tooltip.\n    unit: Var[str | int]\n\n    # The coordinates of all the points in the line, usually calculated internally.\n    points: Var[Sequence[dict[str, Any]]]\n\n    # The pattern of dashes and gaps used to paint the line.\n    stroke_dasharray: Var[str]\n\n    # Valid children components\n    _valid_children: ClassVar[list[str]] = [\"LabelList\", \"ErrorBar\"]\n\n\nclass Scatter(Recharts):\n    \"\"\"A Scatter component in Recharts.\"\"\"\n\n    tag = \"Scatter\"\n\n    alias = \"RechartsScatter\"\n\n    # The source data, in which each element is an object.\n    data: Var[Sequence[dict[str, Any]]]\n\n    # The name of the data. It is used to represent the scatter in legend.\n    name: Var[str]\n\n    # The type of icon in legend. If set to 'none', no legend item will be rendered. 'line' | 'plainline' | 'square' | 'rect'| 'circle' | 'cross' | 'diamond' | 'square' | 'star' | 'triangle' | 'wye' | 'none'. Default: \"circle\"\n    legend_type: Var[LiteralLegendType]\n\n    # The id of x-axis which is corresponding to the data. Default: 0\n    x_axis_id: Var[str | int]\n\n    # The id of y-axis which is corresponding to the data. Default: 0\n    y_axis_id: Var[str | int]\n\n    # The id of z-axis which is corresponding to the data. Default: 0\n    z_axis_id: Var[str | int]\n\n    # If false set, line will not be drawn. If true set, line will be drawn which have the props calculated internally. Default: False\n    line: Var[bool]\n\n    # If a string set, specified symbol will be used to show scatter item. 'circle' | 'cross' | 'diamond' | 'square' | 'star' | 'triangle' | 'wye'. Default: \"circle\"\n    shape: Var[LiteralShape]\n\n    # If 'joint' set, line will generated by just jointing all the points. If 'fitting' set, line will be generated by fitting algorithm. 'joint' | 'fitting'. Default: \"joint\"\n    line_type: Var[LiteralLineType]\n\n    # The fill color of the scatter. Default: rx.color(\"accent\", 9)\n    fill: Var[str | Color] = LiteralVar.create(Color(\"accent\", 9))\n\n    # Valid children components.\n    _valid_children: ClassVar[list[str]] = [\"LabelList\", \"ErrorBar\"]\n\n    # If set false, animation of bar will be disabled. Default: True in CSR, False in SSR\n    is_animation_active: Var[bool]\n\n    # Specifies when the animation should begin, the unit of this option is ms. Default: 0\n    animation_begin: Var[int]\n\n    # Specifies the duration of animation, the unit of this option is ms. Default: 1500\n    animation_duration: Var[int]\n\n    # The type of easing function. Default: \"ease\"\n    animation_easing: Var[LiteralAnimationEasing]\n\n    # The customized event handler of click on the component in this group\n    on_click: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mousedown on the component in this group\n    on_mouse_down: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseup on the component in this group\n    on_mouse_up: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mousemove on the component in this group\n    on_mouse_move: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseover on the component in this group\n    on_mouse_over: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseout on the component in this group\n    on_mouse_out: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseenter on the component in this group\n    on_mouse_enter: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseleave on the component in this group\n    on_mouse_leave: EventHandler[no_args_event_spec]\n\n\nclass Funnel(Recharts):\n    \"\"\"A Funnel component in Recharts.\"\"\"\n\n    tag = \"Funnel\"\n\n    alias = \"RechartsFunnel\"\n\n    # The source data, in which each element is an object.\n    data: Var[Sequence[dict[str, Any]]]\n\n    # The key or getter of a group of data which should be unique in a FunnelChart.\n    data_key: Var[str | int]\n\n    # The key of each sector's name. Default: \"name\"\n    name_key: Var[str]\n\n    # The type of icon in legend. If set to 'none', no legend item will be rendered. Default: \"line\"\n    legend_type: Var[LiteralLegendType]\n\n    # If set false, animation of line will be disabled. Default: True\n    is_animation_active: Var[bool]\n\n    # Specifies when the animation should begin, the unit of this option is ms. Default: 0\n    animation_begin: Var[int]\n\n    # Specifies the duration of animation, the unit of this option is ms. Default: 1500\n    animation_duration: Var[int]\n\n    # The type of easing function. 'ease' | 'ease-in' | 'ease-out' | 'ease-in-out' | 'linear'. Default \"ease\"\n    animation_easing: Var[LiteralAnimationEasing]\n\n    # Stroke color. Default: rx.color(\"gray\", 3)\n    stroke: Var[str | Color] = LiteralVar.create(Color(\"gray\", 3))\n\n    # The coordinates of all the trapezoids in the funnel, usually calculated internally.\n    trapezoids: Var[Sequence[dict[str, Any]]]\n\n    # Valid children components\n    _valid_children: ClassVar[list[str]] = [\"LabelList\", \"Cell\"]\n\n    # The customized event handler of animation start\n    on_animation_start: EventHandler[no_args_event_spec]\n\n    # The customized event handler of animation end\n    on_animation_end: EventHandler[no_args_event_spec]\n\n    # The customized event handler of click on the component in this group\n    on_click: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mousedown on the component in this group\n    on_mouse_down: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseup on the component in this group\n    on_mouse_up: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mousemove on the component in this group\n    on_mouse_move: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseover on the component in this group\n    on_mouse_over: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseout on the component in this group\n    on_mouse_out: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseenter on the component in this group\n    on_mouse_enter: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseleave on the component in this group\n    on_mouse_leave: EventHandler[no_args_event_spec]\n\n\nclass ErrorBar(Recharts):\n    \"\"\"An ErrorBar component in Recharts.\"\"\"\n\n    tag = \"ErrorBar\"\n\n    alias = \"RechartsErrorBar\"\n\n    # Only used for ScatterChart with error bars in two directions. Only accepts a value of \"x\" or \"y\" and makes the error bars lie in that direction.\n    direction: Var[LiteralDirection]\n\n    # The key of a group of data which should be unique in an area chart.\n    data_key: Var[str | int]\n\n    # The width of the error bar ends. Default: 5\n    width: Var[int]\n\n    # The stroke color of error bar. Default: rx.color(\"gray\", 8)\n    stroke: Var[str | Color] = LiteralVar.create(Color(\"gray\", 8))\n\n    # The stroke width of error bar. Default: 1.5\n    stroke_width: Var[str | int | float]\n\n\nclass Reference(Recharts):\n    \"\"\"A base class for reference components in Reference.\"\"\"\n\n    # The id of x-axis which is corresponding to the data. Default: 0\n    x_axis_id: Var[str | int]\n\n    # The id of y-axis which is corresponding to the data. Default: 0\n    y_axis_id: Var[str | int]\n\n    # Defines how to draw the reference line if it falls partly outside the canvas. If set to 'discard', the reference line will not be drawn at all. If set to 'hidden', the reference line will be clipped to the canvas. If set to 'visible', the reference line will be drawn completely. If set to 'extendDomain', the domain of the overflown axis will be extended such that the reference line fits into the canvas. Default: \"discard\"\n    if_overflow: Var[LiteralIfOverflow]\n\n    # If set a string or a number, default label will be drawn, and the option is content.\n    label: Var[str | int]\n\n\nclass Segment(TypedDict):\n    \"\"\"A segment in a ReferenceLine or ReferenceArea.\"\"\"\n\n    x: str | int\n    y: str | int\n\n\nclass ReferenceLine(Reference):\n    \"\"\"A ReferenceLine component in Recharts.\"\"\"\n\n    tag = \"ReferenceLine\"\n\n    alias = \"RechartsReferenceLine\"\n\n    # If set a string or a number, a vertical line perpendicular to the x-axis specified by xAxisId will be drawn. If the specified x-axis is a number axis, the type of x must be Number. If the specified x-axis is a category axis, the value of x must be one of the categorys, otherwise no line will be drawn.\n    x: Var[str | int]\n\n    # If set a string or a number, a horizontal line perpendicular to the y-axis specified by yAxisId will be drawn. If the specified y-axis is a number axis, the type of y must be Number. If the specified y-axis is a category axis, the value of y must be one of the categorys, otherwise no line will be drawn.\n    y: Var[str | int]\n\n    # The color of the reference line.\n    stroke: Var[str | Color]\n\n    # The width of the stroke. Default: 1\n    stroke_width: Var[str | int | float]\n\n    # Valid children components\n    _valid_children: ClassVar[list[str]] = [\"Label\"]\n\n    # Array of endpoints in { x, y } format. These endpoints would be used to draw the ReferenceLine.\n    segment: Var[Sequence[Segment]]\n\n\nclass ReferenceDot(Reference):\n    \"\"\"A ReferenceDot component in Recharts.\"\"\"\n\n    tag = \"ReferenceDot\"\n\n    alias = \"RechartsReferenceDot\"\n\n    # If set a string or a number, a vertical line perpendicular to the x-axis specified by xAxisId will be drawn. If the specified x-axis is a number axis, the type of x must be Number. If the specified x-axis is a category axis, the value of x must be one of the categorys, otherwise no line will be drawn.\n    x: Var[str | int]\n\n    # If set a string or a number, a horizontal line perpendicular to the y-axis specified by yAxisId will be drawn. If the specified y-axis is a number axis, the type of y must be Number. If the specified y-axis is a category axis, the value of y must be one of the categorys, otherwise no line will be drawn.\n    y: Var[str | int]\n\n    # The radius of dot.\n    r: Var[int]\n\n    # The color of the area fill.\n    fill: Var[str | Color]\n\n    # The color of the line stroke.\n    stroke: Var[str | Color]\n\n    # Valid children components\n    _valid_children: ClassVar[list[str]] = [\"Label\"]\n\n    # The customized event handler of click on the component in this chart\n    on_click: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mousedown on the component in this chart\n    on_mouse_down: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseup on the component in this chart\n    on_mouse_up: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseover on the component in this chart\n    on_mouse_over: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseout on the component in this chart\n    on_mouse_out: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseenter on the component in this chart\n    on_mouse_enter: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mousemove on the component in this chart\n    on_mouse_move: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseleave on the component in this chart\n    on_mouse_leave: EventHandler[no_args_event_spec]\n\n\nclass ReferenceArea(Recharts):\n    \"\"\"A ReferenceArea component in Recharts.\"\"\"\n\n    tag = \"ReferenceArea\"\n\n    alias = \"RechartsReferenceArea\"\n\n    # Stroke color\n    stroke: Var[str | Color]\n\n    # Fill color\n    fill: Var[str | Color]\n\n    # The opacity of area.\n    fill_opacity: Var[float]\n\n    # The id of x-axis which is corresponding to the data.\n    x_axis_id: Var[str | int]\n\n    # The id of y-axis which is corresponding to the data.\n    y_axis_id: Var[str | int]\n\n    # A boundary value of the area. If the specified x-axis is a number axis, the type of x must be Number. If the specified x-axis is a category axis, the value of x must be one of the categorys. If one of x1 or x2 is invalidate, the area will cover along x-axis.\n    x1: Var[str | int]\n\n    # A boundary value of the area. If the specified x-axis is a number axis, the type of x must be Number. If the specified x-axis is a category axis, the value of x must be one of the categorys. If one of x1 or x2 is invalidate, the area will cover along x-axis.\n    x2: Var[str | int]\n\n    # A boundary value of the area. If the specified y-axis is a number axis, the type of y must be Number. If the specified y-axis is a category axis, the value of y must be one of the categorys. If one of y1 or y2 is invalidate, the area will cover along y-axis.\n    y1: Var[str | int]\n\n    # A boundary value of the area. If the specified y-axis is a number axis, the type of y must be Number. If the specified y-axis is a category axis, the value of y must be one of the categorys. If one of y1 or y2 is invalidate, the area will cover along y-axis.\n    y2: Var[str | int]\n\n    # Defines how to draw the reference line if it falls partly outside the canvas. If set to 'discard', the reference line will not be drawn at all. If set to 'hidden', the reference line will be clipped to the canvas. If set to 'visible', the reference line will be drawn completely. If set to 'extendDomain', the domain of the overflown axis will be extended such that the reference line fits into the canvas. Default: \"discard\"\n    if_overflow: Var[LiteralIfOverflow]\n\n    # Valid children components\n    _valid_children: ClassVar[list[str]] = [\"Label\"]\n\n\nclass Grid(Recharts):\n    \"\"\"A base class for grid components in Recharts.\"\"\"\n\n    # The x-coordinate of grid. Default: 0\n    x: Var[int]\n\n    # The y-coordinate of grid. Default: 0\n    y: Var[int]\n\n    # The width of grid. Default: 0\n    width: Var[int]\n\n    # The height of grid. Default: 0\n    height: Var[int]\n\n\nclass CartesianGrid(Grid):\n    \"\"\"A CartesianGrid component in Recharts.\"\"\"\n\n    tag = \"CartesianGrid\"\n\n    alias = \"RechartsCartesianGrid\"\n\n    # The horizontal line configuration. Default: True\n    horizontal: Var[bool]\n\n    # The vertical line configuration. Default: True\n    vertical: Var[bool]\n\n    # The x-coordinates in pixel values of all vertical lines. Default: []\n    vertical_points: Var[Sequence[str | int]]\n\n    # The x-coordinates in pixel values of all vertical lines. Default: []\n    horizontal_points: Var[Sequence[str | int]]\n\n    # The background of grid.\n    fill: Var[str | Color]\n\n    # The opacity of the background used to fill the space between grid lines.\n    fill_opacity: Var[float]\n\n    # The pattern of dashes and gaps used to paint the lines of the grid.\n    stroke_dasharray: Var[str]\n\n    # the stroke color of grid. Default: rx.color(\"gray\", 7)\n    stroke: Var[str | Color] = LiteralVar.create(Color(\"gray\", 7))\n\n\nclass CartesianAxis(Grid):\n    \"\"\"A CartesianAxis component in Recharts.\"\"\"\n\n    tag = \"CartesianAxis\"\n\n    alias = \"RechartsCartesianAxis\"\n\n    # The orientation of axis 'top' | 'bottom' | 'left' | 'right'. Default: \"bottom\"\n    orientation: Var[LiteralOrientationTopBottomLeftRight]\n\n    # The box of viewing area. Default: {\"x\": 0, \"y\": 0, \"width\": 0, \"height\": 0}\n    view_box: Var[dict[str, Any]]\n\n    # If set false, no axis line will be drawn. If set a object, the option is the configuration of axis line. Default: True\n    axis_line: Var[bool | dict]\n\n    # If set false, no ticks will be drawn.\n    tick: Var[bool | dict]\n\n    # If set false, no axis tick lines will be drawn. If set a object, the option is the configuration of tick lines. Default: True\n    tick_line: Var[bool]\n\n    # The length of tick line. Default: 6\n    tick_size: Var[int]\n\n    # If set 0, all the ticks will be shown. If set preserveStart\", \"preserveEnd\" or \"preserveStartEnd\", the ticks which is to be shown or hidden will be calculated automatically. Default: \"preserveEnd\"\n    interval: Var[LiteralInterval]\n\n    # If set a string or a number, default label will be drawn, and the option is content.\n    label: Var[str | int]\n\n    # If set true, flips ticks around the axis line, displaying the labels inside the chart instead of outside. Default: False\n    mirror: Var[bool]\n\n    # The margin between tick line and tick.\n    tick_margin: Var[int]\n\n\narea = Area.create\nbar = Bar.create\nline = Line.create\nscatter = Scatter.create\nx_axis = XAxis.create\ny_axis = YAxis.create\nz_axis = ZAxis.create\nbrush = Brush.create\ncartesian_axis = CartesianAxis.create\ncartesian_grid = CartesianGrid.create\nreference_line = ReferenceLine.create\nreference_dot = ReferenceDot.create\nreference_area = ReferenceArea.create\nerror_bar = ErrorBar.create\nfunnel = Funnel.create\n"
  },
  {
    "path": "reflex/components/recharts/charts.py",
    "content": "\"\"\"A module that defines the chart components in Recharts.\"\"\"\n\nfrom __future__ import annotations\n\nfrom collections.abc import Sequence\nfrom typing import Any, ClassVar\n\nfrom reflex.components.component import Component\nfrom reflex.components.recharts.general import ResponsiveContainer\nfrom reflex.constants import EventTriggers\nfrom reflex.constants.colors import Color\nfrom reflex.event import EventHandler, no_args_event_spec\nfrom reflex.vars.base import Var\n\nfrom .recharts import (\n    LiteralAnimationEasing,\n    LiteralComposedChartBaseValue,\n    LiteralLayout,\n    LiteralStackOffset,\n    LiteralSyncMethod,\n    RechartsCharts,\n)\n\n\nclass ChartBase(RechartsCharts):\n    \"\"\"A component that wraps a Recharts charts.\"\"\"\n\n    # The width of chart container. String or Integer\n    width: Var[str | int] = Var.create(\"100%\")\n\n    # The height of chart container.\n    height: Var[str | int] = Var.create(\"100%\")\n\n    # The customized event handler of click on the component in this chart\n    on_click: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseenter on the component in this chart\n    on_mouse_enter: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mousemove on the component in this chart\n    on_mouse_move: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseleave on the component in this chart\n    on_mouse_leave: EventHandler[no_args_event_spec]\n\n    @staticmethod\n    def _ensure_valid_dimension(name: str, value: Any) -> None:\n        \"\"\"Ensure that the value is an int type or str percentage.\n\n        Unfortunately str Vars cannot be checked and are implicitly not allowed.\n\n        Args:\n            name: The name of the prop.\n            value: The value to check.\n\n        Raises:\n            ValueError: If the value is not an int type or str percentage.\n        \"\"\"\n        if value is None:\n            return\n        if isinstance(value, int):\n            return\n        if isinstance(value, str) and value.endswith(\"%\"):\n            return\n        if isinstance(value, Var) and issubclass(value._var_type, int):\n            return\n        msg = (\n            f\"Chart {name} must be specified as int pixels or percentage, not {value!r}. \"\n            \"CSS unit dimensions are allowed on parent container.\"\n        )\n        raise ValueError(msg)\n\n    @classmethod\n    def create(cls, *children: Any, **props: Any) -> Component:\n        \"\"\"Create a chart component.\n\n        Args:\n            *children: The children of the chart component.\n            **props: The properties of the chart component.\n\n        Returns:\n            The chart component wrapped in a responsive container.\n        \"\"\"\n        width = props.pop(\"width\", None)\n        height = props.pop(\"height\", None)\n        cls._ensure_valid_dimension(\"width\", width)\n        cls._ensure_valid_dimension(\"height\", height)\n\n        # Ensure that the min_height and min_width are set to prevent the chart from collapsing.\n        # We are using small values so that height and width can still be used over min_height and min_width.\n        # Without this, sometimes the chart will not be visible. Causing confusion to the user.\n        # With this, the user will see a small chart and can adjust the height and width and can figure out that the issue is with the size.\n        min_height = props.pop(\"min_height\", 10)\n        min_width = props.pop(\"min_width\", 10)\n\n        return ResponsiveContainer.create(\n            super().create(*children, **props),\n            width=width if width is not None else \"100%\",\n            height=height if height is not None else \"100%\",\n            min_width=min_width,\n            min_height=min_height,\n        )\n\n\nclass CategoricalChartBase(ChartBase):\n    \"\"\"A component that wraps a Categorical Recharts charts.\"\"\"\n\n    # The source data, in which each element is an object.\n    data: Var[Sequence[dict[str, Any]]]\n\n    # The sizes of whitespace around the chart, i.e. {\"top\": 50, \"right\": 30, \"left\": 20, \"bottom\": 5}.\n    margin: Var[dict[str, Any]]\n\n    # If any two categorical charts(rx.line_chart, rx.area_chart, rx.bar_chart, rx.composed_chart) have the same sync_id, these two charts can sync the position GraphingTooltip, and the start_index, end_index of Brush.\n    sync_id: Var[str]\n\n    # When sync_id is provided, allows customisation of how the charts will synchronize GraphingTooltips and brushes. Using 'index' (default setting), other charts will reuse current datum's index within the data array. In cases where data does not have the same length, this might yield unexpected results. In that case use 'value' which will try to match other charts values, or a fully custom function which will receive tick, data as argument and should return an index. 'index' | 'value' | function. Default: \"index\"\n    sync_method: Var[LiteralSyncMethod]\n\n    # The layout of area in the chart. 'horizontal' | 'vertical'. Default: \"horizontal\"\n    layout: Var[LiteralLayout]\n\n    # The type of offset function used to generate the lower and upper values in the series array. The four types are built-in offsets in d3-shape. 'expand' | 'none' | 'wiggle' | 'silhouette'\n    stack_offset: Var[LiteralStackOffset]\n\n\nclass AreaChart(CategoricalChartBase):\n    \"\"\"An Area chart component in Recharts.\"\"\"\n\n    tag = \"AreaChart\"\n\n    alias = \"RechartsAreaChart\"\n\n    # The base value of area. Number | 'dataMin' | 'dataMax' | 'auto'. Default: \"auto\"\n    base_value: Var[int | LiteralComposedChartBaseValue]\n\n    # Valid children components\n    _valid_children: ClassVar[list[str]] = [\n        \"XAxis\",\n        \"YAxis\",\n        \"ReferenceArea\",\n        \"ReferenceDot\",\n        \"ReferenceLine\",\n        \"Brush\",\n        \"CartesianGrid\",\n        \"Legend\",\n        \"GraphingTooltip\",\n        \"Area\",\n        \"Defs\",\n    ]\n\n\nclass BarChart(CategoricalChartBase):\n    \"\"\"A Bar chart component in Recharts.\"\"\"\n\n    tag = \"BarChart\"\n\n    alias = \"RechartsBarChart\"\n\n    # The gap between two bar categories, which can be a percent value or a fixed value. Percentage | Number. Default: \"10%\"\n    bar_category_gap: Var[str | int]\n\n    # The gap between two bars in the same category, which can be a percent value or a fixed value. Percentage | Number. Default: 4\n    bar_gap: Var[str | int]\n\n    # The width of all the bars in the chart. Number\n    bar_size: Var[int]\n\n    # The maximum width of all the bars in a horizontal BarChart, or maximum height in a vertical BarChart.\n    max_bar_size: Var[int]\n\n    # The type of offset function used to generate the lower and upper values in the series array. The four types are built-in offsets in d3-shape. Default: \"none\"\n    stack_offset: Var[LiteralStackOffset]\n\n    # If false set, stacked items will be rendered left to right. If true set, stacked items will be rendered right to left. (Render direction affects SVG layering, not x position.) Default: False\n    reverse_stack_order: Var[bool]\n\n    # Valid children components\n    _valid_children: ClassVar[list[str]] = [\n        \"XAxis\",\n        \"YAxis\",\n        \"ReferenceArea\",\n        \"ReferenceDot\",\n        \"ReferenceLine\",\n        \"Brush\",\n        \"CartesianGrid\",\n        \"Legend\",\n        \"GraphingTooltip\",\n        \"Bar\",\n    ]\n\n\nclass LineChart(CategoricalChartBase):\n    \"\"\"A Line chart component in Recharts.\"\"\"\n\n    tag = \"LineChart\"\n\n    alias = \"RechartsLineChart\"\n\n    # Valid children components\n    _valid_children: ClassVar[list[str]] = [\n        \"XAxis\",\n        \"YAxis\",\n        \"ReferenceArea\",\n        \"ReferenceDot\",\n        \"ReferenceLine\",\n        \"Brush\",\n        \"CartesianGrid\",\n        \"Legend\",\n        \"GraphingTooltip\",\n        \"Line\",\n    ]\n\n\nclass ComposedChart(CategoricalChartBase):\n    \"\"\"A Composed chart component in Recharts.\"\"\"\n\n    tag = \"ComposedChart\"\n\n    alias = \"RechartsComposedChart\"\n\n    # The base value of area. Number | 'dataMin' | 'dataMax' | 'auto'. Default: \"auto\"\n    base_value: Var[int | LiteralComposedChartBaseValue]\n\n    # The gap between two bar categories, which can be a percent value or a fixed value. Percentage | Number. Default: \"10%\"\n    bar_category_gap: Var[str | int]\n\n    # The gap between two bars in the same category. Default: 4\n    bar_gap: Var[int]\n\n    # The width or height of each bar. If the barSize is not specified, the size of the bar will be calculated by the barCategoryGap, barGap and the quantity of bar groups.\n    bar_size: Var[int]\n\n    # If false set, stacked items will be rendered left to right. If true set, stacked items will be rendered right to left. (Render direction affects SVG layering, not x position). Default: False\n    reverse_stack_order: Var[bool]\n\n    # Valid children components\n    _valid_children: ClassVar[list[str]] = [\n        \"XAxis\",\n        \"YAxis\",\n        \"ReferenceArea\",\n        \"ReferenceDot\",\n        \"ReferenceLine\",\n        \"Brush\",\n        \"CartesianGrid\",\n        \"Legend\",\n        \"GraphingTooltip\",\n        \"Area\",\n        \"Line\",\n        \"Bar\",\n    ]\n\n\nclass PieChart(ChartBase):\n    \"\"\"A Pie chart component in Recharts.\"\"\"\n\n    tag = \"PieChart\"\n\n    alias = \"RechartsPieChart\"\n\n    # The sizes of whitespace around the chart, i.e. {\"top\": 50, \"right\": 30, \"left\": 20, \"bottom\": 5}.\n    margin: Var[dict[str, Any]]\n\n    # Valid children components\n    _valid_children: ClassVar[list[str]] = [\n        \"PolarAngleAxis\",\n        \"PolarRadiusAxis\",\n        \"PolarGrid\",\n        \"Legend\",\n        \"GraphingTooltip\",\n        \"Pie\",\n    ]\n\n    # The customized event handler of mousedown on the sectors in this group\n    on_mouse_down: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseup on the sectors in this group\n    on_mouse_up: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseover on the sectors in this group\n    on_mouse_over: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseout on the sectors in this group\n    on_mouse_out: EventHandler[no_args_event_spec]\n\n\nclass RadarChart(ChartBase):\n    \"\"\"A Radar chart component in Recharts.\"\"\"\n\n    tag = \"RadarChart\"\n\n    alias = \"RechartsRadarChart\"\n\n    # The source data, in which each element is an object.\n    data: Var[Sequence[dict[str, Any]]]\n\n    # The sizes of whitespace around the chart, i.e. {\"top\": 50, \"right\": 30, \"left\": 20, \"bottom\": 5}. Default: {\"top\": 0, \"right\": 0, \"left\": 0, \"bottom\": 0}\n    margin: Var[dict[str, Any]]\n\n    # The The x-coordinate of center. If set a percentage, the final value is obtained by multiplying the percentage of width. Number | Percentage. Default: \"50%\"\n    cx: Var[int | str]\n\n    # The The y-coordinate of center. If set a percentage, the final value is obtained by multiplying the percentage of height. Number | Percentage. Default: \"50%\"\n    cy: Var[int | str]\n\n    # The angle of first radial direction line. Default: 90\n    start_angle: Var[int]\n\n    # The angle of last point in the circle which should be startAngle - 360 or startAngle + 360. We'll calculate the direction of chart by 'startAngle' and 'endAngle'. Default: -270\n    end_angle: Var[int]\n\n    # The inner radius of first circle grid. If set a percentage, the final value is obtained by multiplying the percentage of maxRadius which is calculated by the width, height, cx, cy. Number | Percentage. Default: 0\n    inner_radius: Var[int | str]\n\n    # The outer radius of last circle grid. If set a percentage, the final value is obtained by multiplying the percentage of maxRadius which is calculated by the width, height, cx, cy. Number | Percentage. Default: \"80%\"\n    outer_radius: Var[int | str]\n\n    # Valid children components\n    _valid_children: ClassVar[list[str]] = [\n        \"PolarAngleAxis\",\n        \"PolarRadiusAxis\",\n        \"PolarGrid\",\n        \"Legend\",\n        \"GraphingTooltip\",\n        \"Radar\",\n    ]\n\n    @classmethod\n    def get_event_triggers(cls) -> dict[str, Var | Any]:\n        \"\"\"Get the event triggers that pass the component's value to the handler.\n\n        Returns:\n            A dict mapping the event trigger to the var that is passed to the handler.\n        \"\"\"\n        return {\n            EventTriggers.ON_CLICK: no_args_event_spec,\n            EventTriggers.ON_MOUSE_ENTER: no_args_event_spec,\n            EventTriggers.ON_MOUSE_LEAVE: no_args_event_spec,\n        }\n\n\nclass RadialBarChart(ChartBase):\n    \"\"\"A RadialBar chart component in Recharts.\"\"\"\n\n    tag = \"RadialBarChart\"\n\n    alias = \"RechartsRadialBarChart\"\n\n    # The source data which each element is an object.\n    data: Var[Sequence[dict[str, Any]]]\n\n    # The sizes of whitespace around the chart. Default: {\"top\": 5, \"right\": 5, \"left\": 5 \"bottom\": 5}\n    margin: Var[dict[str, Any]]\n\n    # The The x-coordinate of center. If set a percentage, the final value is obtained by multiplying the percentage of width. Number | Percentage. Default: \"50%\"\n    cx: Var[int | str]\n\n    # The The y-coordinate of center. If set a percentage, the final value is obtained by multiplying the percentage of height. Number | Percentage. Default: \"50%\"\n    cy: Var[int | str]\n\n    # The angle of first radial direction line. Default: 0\n    start_angle: Var[int]\n\n    # The angle of last point in the circle which should be startAngle - 360 or startAngle + 360. We'll calculate the direction of chart by 'startAngle' and 'endAngle'. Default: 360\n    end_angle: Var[int]\n\n    # The inner radius of first circle grid. If set a percentage, the final value is obtained by multiplying the percentage of maxRadius which is calculated by the width, height, cx, cy. Number | Percentage. Default: \"30%\"\n    inner_radius: Var[int | str]\n\n    # The outer radius of last circle grid. If set a percentage, the final value is obtained by multiplying the percentage of maxRadius which is calculated by the width, height, cx, cy. Number | Percentage. Default: \"100%\"\n    outer_radius: Var[int | str]\n\n    # The gap between two bar categories, which can be a percent value or a fixed value. Percentage | Number. Default: \"10%\"\n    bar_category_gap: Var[int | str]\n\n    # The gap between two bars in the same category, which can be a percent value or a fixed value. Percentage | Number. Default: 4\n    bar_gap: Var[str]\n\n    # The size of each bar. If the barSize is not specified, the size of bar will be calculated by the barCategoryGap, barGap and the quantity of bar groups.\n    bar_size: Var[int]\n\n    # Valid children components\n    _valid_children: ClassVar[list[str]] = [\n        \"PolarAngleAxis\",\n        \"PolarRadiusAxis\",\n        \"PolarGrid\",\n        \"Legend\",\n        \"GraphingTooltip\",\n        \"RadialBar\",\n    ]\n\n\nclass ScatterChart(ChartBase):\n    \"\"\"A Scatter chart component in Recharts.\"\"\"\n\n    tag = \"ScatterChart\"\n\n    alias = \"RechartsScatterChart\"\n\n    # The sizes of whitespace around the chart. Default: {\"top\": 5, \"right\": 5, \"bottom\": 5, \"left\": 5}\n    margin: Var[dict[str, Any]]\n\n    # Valid children components\n    _valid_children: ClassVar[list[str]] = [\n        \"XAxis\",\n        \"YAxis\",\n        \"ZAxis\",\n        \"ReferenceArea\",\n        \"ReferenceDot\",\n        \"ReferenceLine\",\n        \"Brush\",\n        \"CartesianGrid\",\n        \"Legend\",\n        \"GraphingTooltip\",\n        \"Scatter\",\n    ]\n\n    @classmethod\n    def get_event_triggers(cls) -> dict[str, Var | Any]:\n        \"\"\"Get the event triggers that pass the component's value to the handler.\n\n        Returns:\n            A dict mapping the event trigger to the var that is passed to the handler.\n        \"\"\"\n        return {\n            EventTriggers.ON_CLICK: no_args_event_spec,\n            EventTriggers.ON_MOUSE_DOWN: no_args_event_spec,\n            EventTriggers.ON_MOUSE_UP: no_args_event_spec,\n            EventTriggers.ON_MOUSE_MOVE: no_args_event_spec,\n            EventTriggers.ON_MOUSE_OVER: no_args_event_spec,\n            EventTriggers.ON_MOUSE_OUT: no_args_event_spec,\n            EventTriggers.ON_MOUSE_ENTER: no_args_event_spec,\n            EventTriggers.ON_MOUSE_LEAVE: no_args_event_spec,\n        }\n\n\nclass FunnelChart(ChartBase):\n    \"\"\"A Funnel chart component in Recharts.\"\"\"\n\n    tag = \"FunnelChart\"\n\n    alias = \"RechartsFunnelChart\"\n\n    # The layout of bars in the chart. Default: \"centric\"\n    layout: Var[str]\n\n    # The sizes of whitespace around the chart. Default: {\"top\": 5, \"right\": 5, \"bottom\": 5, \"left\": 5}\n    margin: Var[dict[str, Any]]\n\n    # The stroke color of each bar. String | Object\n    stroke: Var[str | Color]\n\n    # Valid children components\n    _valid_children: ClassVar[list[str]] = [\"Legend\", \"GraphingTooltip\", \"Funnel\"]\n\n\nclass Treemap(RechartsCharts):\n    \"\"\"A Treemap chart component in Recharts.\"\"\"\n\n    tag = \"Treemap\"\n\n    alias = \"RechartsTreemap\"\n\n    # The width of chart container. String or Integer. Default: \"100%\"\n    width: Var[str | int] = Var.create(\"100%\")\n\n    # The height of chart container. String or Integer. Default: \"100%\"\n    height: Var[str | int] = Var.create(\"100%\")\n\n    # data of treemap. Array\n    data: Var[Sequence[dict[str, Any]]]\n\n    # The key of a group of data which should be unique in a treemap. String | Number. Default: \"value\"\n    data_key: Var[str | int]\n\n    # The key of each sector's name. String. Default: \"name\"\n    name_key: Var[str]\n\n    # The treemap will try to keep every single rectangle's aspect ratio near the aspectRatio given. Number\n    aspect_ratio: Var[int]\n\n    # If set false, animation of area will be disabled. Default: True\n    is_animation_active: Var[bool]\n\n    # Specifies when the animation should begin, the unit of this option is ms. Default: 0\n    animation_begin: Var[int]\n\n    # Specifies the duration of animation, the unit of this option is ms. Default: 1500\n    animation_duration: Var[int]\n\n    # The type of easing function. 'ease' | 'ease-in' | 'ease-out' | 'ease-in-out' | 'linear'. Default: \"ease\"\n    animation_easing: Var[LiteralAnimationEasing]\n\n    # The customized event handler of animation start\n    on_animation_start: EventHandler[no_args_event_spec]\n\n    # The customized event handler of animation end\n    on_animation_end: EventHandler[no_args_event_spec]\n\n    @classmethod\n    def create(cls, *children, **props) -> Component:\n        \"\"\"Create a chart component.\n\n        Args:\n            *children: The children of the chart component.\n            **props: The properties of the chart component.\n\n        Returns:\n            The Treemap component wrapped in a responsive container.\n        \"\"\"\n        return ResponsiveContainer.create(\n            super().create(*children, **props),\n            width=props.pop(\"width\", \"100%\"),\n            height=props.pop(\"height\", \"100%\"),\n        )\n\n\narea_chart = AreaChart.create\nbar_chart = BarChart.create\nline_chart = LineChart.create\ncomposed_chart = ComposedChart.create\npie_chart = PieChart.create\nradar_chart = RadarChart.create\nradial_bar_chart = RadialBarChart.create\nscatter_chart = ScatterChart.create\nfunnel_chart = FunnelChart.create\ntreemap = Treemap.create\n"
  },
  {
    "path": "reflex/components/recharts/general.py",
    "content": "\"\"\"General components for Recharts.\"\"\"\n\nfrom __future__ import annotations\n\nfrom collections.abc import Sequence\nfrom typing import Any, ClassVar\n\nfrom reflex.components.component import MemoizationLeaf\nfrom reflex.constants.colors import Color\nfrom reflex.event import EventHandler, no_args_event_spec\nfrom reflex.vars.base import LiteralVar, Var\n\nfrom .recharts import (\n    LiteralAnimationEasing,\n    LiteralIconType,\n    LiteralLayout,\n    LiteralLegendAlign,\n    LiteralPosition,\n    LiteralVerticalAlign,\n    Recharts,\n)\n\n\nclass ResponsiveContainer(Recharts, MemoizationLeaf):\n    \"\"\"A base class for responsive containers in Recharts.\"\"\"\n\n    tag = \"ResponsiveContainer\"\n\n    alias = \"RechartsResponsiveContainer\"\n\n    # The aspect ratio of the container. The final aspect ratio of the SVG element will be (width / height) * aspect. Number\n    aspect: Var[int]\n\n    # The width of chart container. Can be a number or string. Default: \"100%\"\n    width: Var[int | str]\n\n    # The height of chart container. Can be a number or string. Default: \"100%\"\n    height: Var[int | str]\n\n    # The minimum width of chart container. Number or string.\n    min_width: Var[int | str]\n\n    # The minimum height of chart container. Number or string.\n    min_height: Var[int | str]\n\n    # If specified a positive number, debounced function will be used to handle the resize event. Default: 0\n    debounce: Var[int]\n\n    # If specified provides a callback providing the updated chart width and height values.\n    on_resize: EventHandler[no_args_event_spec]\n\n    # Valid children components\n    _valid_children: ClassVar[list[str]] = [\n        \"AreaChart\",\n        \"BarChart\",\n        \"LineChart\",\n        \"PieChart\",\n        \"RadarChart\",\n        \"RadialBarChart\",\n        \"ResponsiveContainer\",\n        \"ScatterChart\",\n        \"Treemap\",\n        \"ComposedChart\",\n        \"FunnelChart\",\n    ]\n\n\nclass Legend(Recharts):\n    \"\"\"A Legend component in Recharts.\"\"\"\n\n    tag = \"Legend\"\n\n    alias = \"RechartsLegend\"\n\n    # The width of legend container. Number\n    width: Var[int]\n\n    # The height of legend container. Number\n    height: Var[int]\n\n    # The layout of legend items. 'horizontal' | 'vertical'. Default: \"horizontal\"\n    layout: Var[LiteralLayout]\n\n    # The alignment of legend items in 'horizontal' direction, which can be 'left', 'center', 'right'. Default: \"center\"\n    align: Var[LiteralLegendAlign]\n\n    # The alignment of legend items in 'vertical' direction, which can be 'top', 'middle', 'bottom'. Default: \"bottom\"\n    vertical_align: Var[LiteralVerticalAlign]\n\n    # The size of icon in each legend item. Default: 14\n    icon_size: Var[int]\n\n    # The type of icon in each legend item. 'line' | 'plainline' | 'square' | 'rect' | 'circle' | 'cross' | 'diamond' | 'star' | 'triangle' | 'wye'\n    icon_type: Var[LiteralIconType]\n\n    # The source data of the content to be displayed in the legend, usually calculated internally. Default: []\n    payload: Var[Sequence[dict[str, Any]]]\n\n    # The width of chart container, usually calculated internally.\n    chart_width: Var[int]\n\n    # The height of chart container, usually calculated internally.\n    chart_height: Var[int]\n\n    # The margin of chart container, usually calculated internally.\n    margin: Var[dict[str, Any]]\n\n    # The customized event handler of click on the items in this group\n    on_click: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mousedown on the items in this group\n    on_mouse_down: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseup on the items in this group\n    on_mouse_up: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mousemove on the items in this group\n    on_mouse_move: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseover on the items in this group\n    on_mouse_over: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseout on the items in this group\n    on_mouse_out: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseenter on the items in this group\n    on_mouse_enter: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseleave on the items in this group\n    on_mouse_leave: EventHandler[no_args_event_spec]\n\n\nclass GraphingTooltip(Recharts):\n    \"\"\"A Tooltip component in Recharts.\"\"\"\n\n    tag = \"Tooltip\"\n\n    alias = \"RechartsTooltip\"\n\n    # The separator between name and value. Default: \":\"\n    separator: Var[str]\n\n    # The offset size of tooltip. Number. Default: 10\n    offset: Var[int]\n\n    # When an item of the payload has value null or undefined, this item won't be displayed. Default: True\n    filter_null: Var[bool]\n\n    # If set false, no cursor will be drawn when tooltip is active. Default: {\"strokeWidth\": 1, \"fill\": rx.color(\"gray\", 3)}\n    cursor: Var[dict[str, Any] | bool] = LiteralVar.create({\n        \"strokeWidth\": 1,\n        \"fill\": Color(\"gray\", 3),\n    })\n\n    # The box of viewing area, which has the shape of {x: someVal, y: someVal, width: someVal, height: someVal}, usually calculated internally.\n    view_box: Var[dict[str, Any]]\n\n    # The style of default tooltip content item which is a li element. Default: {\"color\": rx.color(\"gray\", 12)}\n    item_style: Var[dict[str, Any]] = LiteralVar.create({\n        \"color\": Color(\"gray\", 12),\n    })\n\n    # The style of tooltip wrapper which is a dom element. Default: {}\n    wrapper_style: Var[dict[str, Any]]\n\n    # The style of tooltip content which is a dom element. Default: {\"background\": rx.color(\"gray\", 1), \"borderColor\": rx.color(\"gray\", 4), \"borderRadius\": \"8px\"}\n    content_style: Var[dict[str, Any]] = LiteralVar.create({\n        \"background\": Color(\"gray\", 1),\n        \"borderColor\": Color(\"gray\", 4),\n        \"borderRadius\": \"8px\",\n    })\n\n    # The style of default tooltip label which is a p element. Default: {\"color\": rx.color(\"gray\", 11)}\n    label_style: Var[dict[str, Any]] = LiteralVar.create({\"color\": Color(\"gray\", 11)})\n\n    # This option allows the tooltip to extend beyond the viewBox of the chart itself. Default: {\"x\": False, \"y\": False}\n    allow_escape_view_box: Var[dict[str, bool]]\n\n    # If set true, the tooltip is displayed. If set false, the tooltip is hidden, usually calculated internally. Default: False\n    active: Var[bool]\n\n    # If this field is set, the tooltip position will be fixed and will not move anymore.\n    position: Var[dict[str, Any]]\n\n    # The coordinate of tooltip which is usually calculated internally. Default: {\"x\": 0, \"y\": 0}\n    coordinate: Var[dict[str, Any]]\n\n    # If set false, animation of tooltip will be disabled. Default: True\n    is_animation_active: Var[bool]\n\n    # Specifies the duration of animation, the unit of this option is ms. Default: 1500\n    animation_duration: Var[int]\n\n    # The type of easing function. Default: \"ease\"\n    animation_easing: Var[LiteralAnimationEasing]\n\n\nclass Label(Recharts):\n    \"\"\"A Label component in Recharts.\"\"\"\n\n    tag = \"Label\"\n\n    alias = \"RechartsLabel\"\n\n    # The box of viewing area, which has the shape of {x: someVal, y: someVal, width: someVal, height: someVal}, usually calculated internally.\n    view_box: Var[dict[str, Any]]\n\n    # The value of label, which can be specified by this props or the children of <Label />\n    value: Var[str]\n\n    # The offset of label which can be specified by this props or the children of <Label />\n    offset: Var[int]\n\n    # The position of label which can be specified by this props or the children of <Label />\n    position: Var[LiteralPosition]\n\n\nclass LabelList(Recharts):\n    \"\"\"A LabelList component in Recharts.\"\"\"\n\n    tag = \"LabelList\"\n\n    alias = \"RechartsLabelList\"\n\n    # The key of a group of label values in data.\n    data_key: Var[str | int]\n\n    # The position of each label relative to it view box. \"Top\" | \"left\" | \"right\" | \"bottom\" | \"inside\" | \"outside\" | \"insideLeft\" | \"insideRight\" | \"insideTop\" | \"insideBottom\" | \"insideTopLeft\" | \"insideBottomLeft\" | \"insideTopRight\" | \"insideBottomRight\" | \"insideStart\" | \"insideEnd\" | \"end\" | \"center\"\n    position: Var[LiteralPosition]\n\n    # The offset to the specified \"position\". Default: 5\n    offset: Var[int]\n\n    # The fill color of each label. Default: rx.color(\"gray\", 10)\n    fill: Var[str | Color] = LiteralVar.create(Color(\"gray\", 10))\n\n    # The stroke color of each label. Default: \"none\"\n    stroke: Var[str | Color] = LiteralVar.create(\"none\")\n\n\nclass Cell(Recharts):\n    \"\"\"A Cell component in Recharts.\"\"\"\n\n    tag = \"Cell\"\n\n    alias = \"RechartsCell\"\n\n    # The presentation attribute of a rectangle in bar or a sector in pie.\n    fill: Var[str | Color]\n\n    # The presentation attribute of a rectangle in bar or a sector in pie.\n    stroke: Var[str | Color]\n\n\nresponsive_container = ResponsiveContainer.create\nlegend = Legend.create\ngraphing_tooltip = tooltip = GraphingTooltip.create\nlabel = Label.create\nlabel_list = LabelList.create\ncell = Cell.create\n"
  },
  {
    "path": "reflex/components/recharts/polar.py",
    "content": "\"\"\"Polar charts in Recharts.\"\"\"\n\nfrom __future__ import annotations\n\nfrom collections.abc import Sequence\nfrom typing import Any, ClassVar\n\nfrom reflex.constants import EventTriggers\nfrom reflex.constants.colors import Color\nfrom reflex.event import EventHandler, no_args_event_spec\nfrom reflex.vars.base import LiteralVar, Var\n\nfrom .recharts import (\n    ACTIVE_DOT_TYPE,\n    LiteralAnimationEasing,\n    LiteralGridType,\n    LiteralLegendType,\n    LiteralOrientationLeftRightMiddle,\n    LiteralPolarRadiusType,\n    LiteralScale,\n    Recharts,\n)\n\n\nclass Pie(Recharts):\n    \"\"\"A Pie chart component in Recharts.\"\"\"\n\n    tag = \"Pie\"\n\n    alias = \"RechartsPie\"\n\n    # The source data which each element is an object.\n    data: Var[Sequence[dict[str, Any]]]\n\n    # The key of each sector's value.\n    data_key: Var[str | int]\n\n    # The x-coordinate of center. If set a percentage, the final value is obtained by multiplying the percentage of container width. Default: \"50%\"\n    cx: Var[int | str]\n\n    # The y-coordinate of center. If set a percentage, the final value is obtained by multiplying the percentage of container height. Default: \"50%\"\n    cy: Var[int | str]\n\n    # The inner radius of pie, which can be set to a percent value. Default: 0\n    inner_radius: Var[int | str]\n\n    # The outer radius of pie, which can be set to a percent value. Default: \"80%\"\n    outer_radius: Var[int | str]\n\n    # The angle of first sector. Default: 0\n    start_angle: Var[int]\n\n    # The end angle of last sector, which should be unequal to start_angle. Default: 360\n    end_angle: Var[int]\n\n    # The minimum angle of each unzero data. Default: 0\n    min_angle: Var[int]\n\n    # The angle between two sectors. Default: 0\n    padding_angle: Var[int]\n\n    # The key of each sector's name. Default: \"name\"\n    name_key: Var[str]\n\n    # The type of icon in legend. If set to 'none', no legend item will be rendered. Default: \"rect\"\n    legend_type: Var[LiteralLegendType]\n\n    # If false set, labels will not be drawn. If true set, labels will be drawn which have the props calculated internally. Default: False\n    label: Var[bool | dict[str, Any]] = Var.create(False)\n\n    # If false set, label lines will not be drawn. If true set, label lines will be drawn which have the props calculated internally. Default: False\n    label_line: Var[bool | dict[str, Any]]\n\n    # Valid children components\n    _valid_children: ClassVar[list[str]] = [\"Cell\", \"LabelList\", \"Bare\"]\n\n    # Stoke color. Default: rx.color(\"accent\", 9)\n    stroke: Var[str | Color] = LiteralVar.create(Color(\"accent\", 9))\n\n    # Fill color. Default: rx.color(\"accent\", 3)\n    fill: Var[str | Color] = LiteralVar.create(Color(\"accent\", 3))\n\n    # If set false, animation of tooltip will be disabled. Default: true in CSR, and false in SSR\n    is_animation_active: Var[bool]\n\n    # Specifies when the animation should begin, the unit of this option is ms. Default: 400\n    animation_begin: Var[int]\n\n    # Specifies the duration of animation, the unit of this option is ms. Default: 1500\n    animation_duration: Var[int]\n\n    # The type of easing function. Default: \"ease\"\n    animation_easing: Var[LiteralAnimationEasing]\n\n    # The tabindex of wrapper surrounding the cells. Default: 0\n    root_tab_index: Var[int]\n\n    @classmethod\n    def get_event_triggers(cls) -> dict[str, Var | Any]:\n        \"\"\"Get the event triggers that pass the component's value to the handler.\n\n        Returns:\n            A dict mapping the event trigger to the var that is passed to the handler.\n        \"\"\"\n        return {\n            EventTriggers.ON_ANIMATION_START: no_args_event_spec,\n            EventTriggers.ON_ANIMATION_END: no_args_event_spec,\n            EventTriggers.ON_CLICK: no_args_event_spec,\n            EventTriggers.ON_MOUSE_MOVE: no_args_event_spec,\n            EventTriggers.ON_MOUSE_OVER: no_args_event_spec,\n            EventTriggers.ON_MOUSE_OUT: no_args_event_spec,\n            EventTriggers.ON_MOUSE_ENTER: no_args_event_spec,\n            EventTriggers.ON_MOUSE_LEAVE: no_args_event_spec,\n        }\n\n\nclass Radar(Recharts):\n    \"\"\"A Radar chart component in Recharts.\"\"\"\n\n    tag = \"Radar\"\n\n    alias = \"RechartsRadar\"\n\n    # The key of a group of data which should be unique in a radar chart.\n    data_key: Var[str | int]\n\n    # The coordinates of all the vertices of the radar shape, like [{ x, y }].\n    points: Var[Sequence[dict[str, Any]]]\n\n    # If false set, dots will not be drawn. Default: True\n    dot: Var[ACTIVE_DOT_TYPE]\n\n    # Stoke color. Default: rx.color(\"accent\", 9)\n    stroke: Var[str | Color] = LiteralVar.create(Color(\"accent\", 9))\n\n    # Fill color. Default: rx.color(\"accent\", 3)\n    fill: Var[str | Color] = LiteralVar.create(Color(\"accent\", 3))\n\n    # The opacity to fill the chart. Default: 0.6\n    fill_opacity: Var[float] = LiteralVar.create(0.6)\n\n    # The type of icon in legend. If set to 'none', no legend item will be rendered. Default: \"rect\"\n    legend_type: Var[LiteralLegendType]\n\n    # If false set, labels will not be drawn. Default: True\n    label: Var[bool | dict[str, Any]]\n\n    # If set false, animation of polygon will be disabled. Default: True in CSR, and False in SSR\n    is_animation_active: Var[bool]\n\n    # Specifies when the animation should begin, the unit of this option is ms. Default: 0\n    animation_begin: Var[int]\n\n    # Specifies the duration of animation, the unit of this option is ms. Default: 1500\n    animation_duration: Var[int]\n\n    # The type of easing function. 'ease' | 'ease-in' | 'ease-out' | 'ease-in-out' | 'linear'. Default: \"ease\"\n    animation_easing: Var[LiteralAnimationEasing]\n\n    # Valid children components\n    _valid_children: ClassVar[list[str]] = [\"LabelList\"]\n\n    @classmethod\n    def get_event_triggers(cls) -> dict[str, Var | Any]:\n        \"\"\"Get the event triggers that pass the component's value to the handler.\n\n        Returns:\n            A dict mapping the event trigger to the var that is passed to the handler.\n        \"\"\"\n        return {\n            EventTriggers.ON_ANIMATION_START: no_args_event_spec,\n            EventTriggers.ON_ANIMATION_END: no_args_event_spec,\n        }\n\n\nclass RadialBar(Recharts):\n    \"\"\"A RadialBar chart component in Recharts.\"\"\"\n\n    tag = \"RadialBar\"\n\n    alias = \"RechartsRadialBar\"\n\n    # The source data which each element is an object.\n    data: Var[Sequence[dict[str, Any]]]\n\n    # The key of a group of data which should be unique to show the meaning of angle axis.\n    data_key: Var[str | int]\n\n    # Min angle of each bar. A positive value between 0 and 360. Default: 0\n    min_angle: Var[int]\n\n    # The type of icon in legend. If set to 'none', no legend item will be rendered. Default: \"rect\"\n    legend_type: Var[LiteralLegendType]\n\n    # If false set, labels will not be drawn. If true set, labels will be drawn which have the props calculated internally. Default: False\n    label: Var[bool | dict[str, Any]]\n\n    # If false set, background sector will not be drawn. Default: False\n    background: Var[bool | dict[str, Any]]\n\n    # If set false, animation of radial bars will be disabled. Default: True\n    is_animation_active: Var[bool]\n\n    # Specifies when the animation should begin, the unit of this option is ms. Default: 0\n    animation_begin: Var[int]\n\n    # Specifies the duration of animation, the unit of this option is ms. Default 1500\n    animation_duration: Var[int]\n\n    # The type of easing function. 'ease' | 'ease-in' | 'ease-out' | 'ease-in-out' | 'linear'. Default: \"ease\"\n    animation_easing: Var[LiteralAnimationEasing]\n\n    # Valid children components\n    _valid_children: ClassVar[list[str]] = [\"Cell\", \"LabelList\"]\n\n    @classmethod\n    def get_event_triggers(cls) -> dict[str, Var | Any]:\n        \"\"\"Get the event triggers that pass the component's value to the handler.\n\n        Returns:\n            A dict mapping the event trigger to the var that is passed to the handler.\n        \"\"\"\n        return {\n            EventTriggers.ON_CLICK: no_args_event_spec,\n            EventTriggers.ON_MOUSE_MOVE: no_args_event_spec,\n            EventTriggers.ON_MOUSE_OVER: no_args_event_spec,\n            EventTriggers.ON_MOUSE_OUT: no_args_event_spec,\n            EventTriggers.ON_MOUSE_ENTER: no_args_event_spec,\n            EventTriggers.ON_MOUSE_LEAVE: no_args_event_spec,\n            EventTriggers.ON_ANIMATION_START: no_args_event_spec,\n            EventTriggers.ON_ANIMATION_END: no_args_event_spec,\n        }\n\n\nclass PolarAngleAxis(Recharts):\n    \"\"\"A PolarAngleAxis component in Recharts.\"\"\"\n\n    tag = \"PolarAngleAxis\"\n\n    alias = \"RechartsPolarAngleAxis\"\n\n    # The key of a group of data which should be unique to show the meaning of angle axis.\n    data_key: Var[str | int]\n\n    # The x-coordinate of center. If set a percentage, the final value is obtained by multiplying the percentage of container width.\n    cx: Var[int | str]\n\n    # The y-coordinate of center. If set a percentage, the final value is obtained by multiplying the percentage of container height.\n    cy: Var[int | str]\n\n    # The outer radius of circle grid. If set a percentage, the final value is obtained by multiplying the percentage of maxRadius which is calculated by the width, height, cx, cy.\n    radius: Var[int | str]\n\n    # If false set, axis line will not be drawn. If true set, axis line will be drawn which have the props calculated internally. If object set, axis line will be drawn which have the props mergered by the internal calculated props and the option. Default: True\n    axis_line: Var[bool | dict[str, Any]]\n\n    # The type of axis line. Default: \"polygon\"\n    axis_line_type: Var[LiteralGridType]\n\n    # If false set, tick lines will not be drawn. If true set, tick lines will be drawn which have the props calculated internally. If object set, tick lines will be drawn which have the props mergered by the internal calculated props and the option. Default: False\n    tick_line: Var[bool | dict[str, Any]] = LiteralVar.create(False)\n\n    # If false set, ticks will not be drawn. If true set, ticks will be drawn which have the props calculated internally. If object set, ticks will be drawn which have the props mergered by the internal calculated props and the option. Default: True\n    tick: Var[bool | dict[str, Any]]\n\n    # The array of every tick's value and angle.\n    ticks: Var[Sequence[dict[str, Any]]]\n\n    # The orientation of axis text. Default: \"outer\"\n    orientation: Var[str]\n\n    # The stroke color of axis. Default: rx.color(\"gray\", 10)\n    stroke: Var[str | Color] = LiteralVar.create(Color(\"gray\", 10))\n\n    # Allow the axis has duplicated categorys or not when the type of axis is \"category\". Default: True\n    allow_duplicated_category: Var[bool]\n\n    # Valid children components.\n    _valid_children: ClassVar[list[str]] = [\"Label\"]\n\n    # The customized event handler of click on the ticks of this axis.\n    on_click: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mousedown on the the ticks of this axis.\n    on_mouse_down: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseup on the ticks of this axis.\n    on_mouse_up: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mousemove on the ticks of this axis.\n    on_mouse_move: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseover on the ticks of this axis.\n    on_mouse_over: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseout on the ticks of this axis.\n    on_mouse_out: EventHandler[no_args_event_spec]\n\n    # The customized event handler of moustenter on the ticks of this axis.\n    on_mouse_enter: EventHandler[no_args_event_spec]\n\n    # The customized event handler of mouseleave on the ticks of this axis.\n    on_mouse_leave: EventHandler[no_args_event_spec]\n\n\nclass PolarGrid(Recharts):\n    \"\"\"A PolarGrid component in Recharts.\"\"\"\n\n    tag = \"PolarGrid\"\n\n    alias = \"RechartsPolarGrid\"\n\n    # The x-coordinate of center.\n    cx: Var[int]\n\n    # The y-coordinate of center.\n    cy: Var[int]\n\n    # The radius of the inner polar grid.\n    inner_radius: Var[int]\n\n    # The radius of the outer polar grid.\n    outer_radius: Var[int]\n\n    # The array of every line grid's angle.\n    polar_angles: Var[Sequence[int]]\n\n    # The array of every line grid's radius.\n    polar_radius: Var[Sequence[int]]\n\n    # The type of polar grids. 'polygon' | 'circle'. Default: \"polygon\"\n    grid_type: Var[LiteralGridType]\n\n    # The stroke color of grid. Default: rx.color(\"gray\", 10)\n    stroke: Var[str | Color] = LiteralVar.create(Color(\"gray\", 10))\n\n    # Valid children components\n    _valid_children: ClassVar[list[str]] = [\"RadarChart\", \"RadiarBarChart\"]\n\n\nclass PolarRadiusAxis(Recharts):\n    \"\"\"A PolarRadiusAxis component in Recharts.\"\"\"\n\n    tag = \"PolarRadiusAxis\"\n\n    alias = \"RechartsPolarRadiusAxis\"\n\n    # The angle of radial direction line to display axis text. Default: 0\n    angle: Var[int]\n\n    # The type of axis line. 'number' | 'category'. Default: \"category\"\n    type_: Var[LiteralPolarRadiusType]\n\n    # Allow the axis has duplicated categorys or not when the type of axis is \"category\". Default: True\n    allow_duplicated_category: Var[bool]\n\n    # The x-coordinate of center.\n    cx: Var[int]\n\n    # The y-coordinate of center.\n    cy: Var[int]\n\n    # If set to true, the ticks of this axis are reversed. Default: False\n    reversed: Var[bool]\n\n    # The orientation of axis text. Default: \"right\"\n    orientation: Var[LiteralOrientationLeftRightMiddle]\n\n    # If false set, axis line will not be drawn. If true set, axis line will be drawn which have the props calculated internally. If object set, axis line will be drawn which have the props mergered by the internal calculated props and the option. Default: True\n    axis_line: Var[bool | dict[str, Any]]\n\n    # If false set, ticks will not be drawn. If true set, ticks will be drawn which have the props calculated internally. If object set, ticks will be drawn which have the props mergered by the internal calculated props and the option. Default: True\n    tick: Var[bool | dict[str, Any]]\n\n    # The count of axis ticks. Not used if 'type' is 'category'. Default: 5\n    tick_count: Var[int]\n\n    # If 'auto' set, the scale function is linear scale. 'auto' | 'linear' | 'pow' | 'sqrt' | 'log' | 'identity' | 'time' | 'band' | 'point' | 'ordinal' | 'quantile' | 'quantize' | 'utc' | 'sequential' | 'threshold'. Default: \"auto\"\n    scale: Var[LiteralScale]\n\n    # Valid children components\n    _valid_children: ClassVar[list[str]] = [\"Label\"]\n\n    # The domain of the polar radius axis, specifying the minimum and maximum values. Default: [0, \"auto\"]\n    domain: Var[Sequence[int | str]]\n\n    # The stroke color of axis. Default: rx.color(\"gray\", 10)\n    stroke: Var[str | Color] = LiteralVar.create(Color(\"gray\", 10))\n\n    @classmethod\n    def get_event_triggers(cls) -> dict[str, Var | Any]:\n        \"\"\"Get the event triggers that pass the component's value to the handler.\n\n        Returns:\n            A dict mapping the event trigger to the var that is passed to the handler.\n        \"\"\"\n        return {\n            EventTriggers.ON_CLICK: no_args_event_spec,\n            EventTriggers.ON_MOUSE_MOVE: no_args_event_spec,\n            EventTriggers.ON_MOUSE_OVER: no_args_event_spec,\n            EventTriggers.ON_MOUSE_OUT: no_args_event_spec,\n            EventTriggers.ON_MOUSE_ENTER: no_args_event_spec,\n            EventTriggers.ON_MOUSE_LEAVE: no_args_event_spec,\n        }\n\n\npie = Pie.create\nradar = Radar.create\nradial_bar = RadialBar.create\npolar_angle_axis = PolarAngleAxis.create\npolar_grid = PolarGrid.create\npolar_radius_axis = PolarRadiusAxis.create\n"
  },
  {
    "path": "reflex/components/recharts/recharts.py",
    "content": "\"\"\"A component that wraps a recharts lib.\"\"\"\n\nfrom typing import Any, Literal\n\nfrom reflex.components.component import Component, MemoizationLeaf, NoSSRComponent\n\n\nclass Recharts(Component):\n    \"\"\"A component that wraps a recharts lib.\"\"\"\n\n    library = \"recharts@3.8.0\"\n\n    def _get_style(self) -> dict:\n        return {\"wrapperStyle\": self.style}\n\n\nclass RechartsCharts(NoSSRComponent, MemoizationLeaf):\n    \"\"\"A component that wraps a recharts lib.\"\"\"\n\n    library = \"recharts@3.8.0\"\n\n\nLiteralAnimationEasing = Literal[\"ease\", \"ease-in\", \"ease-out\", \"ease-in-out\", \"linear\"]\nLiteralIfOverflow = Literal[\"discard\", \"hidden\", \"visible\", \"extendDomain\"]\nLiteralShape = Literal[\n    \"square\", \"circle\", \"cross\", \"diamond\", \"star\", \"triangle\", \"wye\"\n]\nLiteralLineType = Literal[\"joint\", \"fitting\"]\nLiteralOrientation = Literal[\"top\", \"bottom\", \"left\", \"right\", \"middle\"]\nLiteralOrientationLeftRightMiddle = Literal[\"left\", \"right\", \"middle\"]\nLiteralOrientationTopBottom = Literal[\"top\", \"bottom\"]\nLiteralOrientationLeftRight = Literal[\"left\", \"right\"]\nLiteralOrientationTopBottomLeftRight = Literal[\"top\", \"bottom\", \"left\", \"right\"]\nLiteralScale = Literal[\n    \"auto\",\n    \"linear\",\n    \"pow\",\n    \"sqrt\",\n    \"log\",\n    \"identity\",\n    \"time\",\n    \"band\",\n    \"point\",\n    \"ordinal\",\n    \"quantile\",\n    \"quantize\",\n    \"utc\",\n    \"sequential\",\n    \"threshold\",\n]\nLiteralTextAnchor = Literal[\"start\", \"middle\", \"end\"]\nLiteralLayout = Literal[\"horizontal\", \"vertical\"]\nLiteralPolarRadiusType = Literal[\"auto\", \"number\", \"category\"]\nLiteralGridType = Literal[\"polygon\", \"circle\"]\nLiteralPosition = Literal[\n    \"top\",\n    \"left\",\n    \"right\",\n    \"bottom\",\n    \"inside\",\n    \"outside\",\n    \"insideLeft\",\n    \"insideRight\",\n    \"insideTop\",\n    \"insideBottom\",\n    \"insideTopLeft\",\n    \"insideBottomLeft\",\n    \"insideTopRight\",\n    \"insideBottomRight\",\n    \"insideStart\",\n    \"insideEnd\",\n    \"end\",\n    \"center\",\n]\nLiteralIconType = Literal[\n    \"circle\",\n    \"cross\",\n    \"diamond\",\n    \"line\",\n    \"plainline\",\n    \"rect\",\n    \"square\",\n    \"star\",\n    \"triangle\",\n    \"wye\",\n]\nLiteralLegendType = Literal[\n    \"circle\",\n    \"cross\",\n    \"diamond\",\n    \"line\",\n    \"plainline\",\n    \"rect\",\n    \"square\",\n    \"star\",\n    \"triangle\",\n    \"wye\",\n    \"none\",\n]\nLiteralLegendAlign = Literal[\"left\", \"center\", \"right\"]\nLiteralVerticalAlign = Literal[\"top\", \"middle\", \"bottom\"]\nLiteralStackOffset = Literal[\"expand\", \"none\", \"wiggle\", \"silhouette\"]\nLiteralBarChartStackOffset = Literal[\"expand\", \"none\", \"wiggle\", \"silhouette\", \"sign\"]\nLiteralComposedChartBaseValue = Literal[\"dataMin\", \"dataMax\", \"auto\"]\nLiteralAxisType = Literal[\"number\", \"category\"]\nLiteralCurveType = Literal[\n    \"basis\",\n    \"basisClosed\",\n    \"basisOpen\",\n    \"bumpX\",\n    \"bumpY\",\n    \"bump\",\n    \"linear\",\n    \"linearClosed\",\n    \"natural\",\n    \"monotoneX\",\n    \"monotoneY\",\n    \"monotone\",\n    \"step\",\n    \"stepBefore\",\n    \"stepAfter\",\n]\nLiteralDirection = Literal[\"x\", \"y\"]\nLiteralInterval = Literal[\"preserveStart\", \"preserveEnd\", \"preserveStartEnd\"]\nLiteralIntervalAxis = Literal[\n    \"preserveStart\", \"preserveEnd\", \"preserveStartEnd\", \"equidistantPreserveStart\"\n]\nLiteralSyncMethod = Literal[\"index\", \"value\"]\n\nACTIVE_DOT_TYPE = bool | dict[str, Any]\n"
  },
  {
    "path": "reflex/components/sonner/__init__.py",
    "content": "\"\"\"Init file for the sonner component.\"\"\"\n\nfrom .toast import toast\n"
  },
  {
    "path": "reflex/components/sonner/toast.py",
    "content": "\"\"\"Sonner toast component.\"\"\"\n\nfrom __future__ import annotations\n\nimport dataclasses\nfrom typing import Any, Literal\n\nfrom reflex.components.component import Component, ComponentNamespace\nfrom reflex.components.lucide.icon import Icon\nfrom reflex.components.props import NoExtrasAllowedProps\nfrom reflex.constants.base import Dirs\nfrom reflex.event import EventSpec, run_script\nfrom reflex.style import Style, resolved_color_mode\nfrom reflex.utils import format\nfrom reflex.utils.imports import ImportVar\nfrom reflex.utils.serializers import serializer\nfrom reflex.vars import VarData\nfrom reflex.vars.base import LiteralVar, Var\nfrom reflex.vars.function import FunctionVar\nfrom reflex.vars.number import ternary_operation\nfrom reflex.vars.object import ObjectVar\n\nLiteralPosition = Literal[\n    \"top-left\",\n    \"top-center\",\n    \"top-right\",\n    \"bottom-left\",\n    \"bottom-center\",\n    \"bottom-right\",\n]\n\ntoast_ref = Var(\n    _js_expr=\"refs['__toast']\",\n    _var_data=VarData(imports={f\"$/{Dirs.STATE_PATH}\": [ImportVar(tag=\"refs\")]}),\n)\n\n\n@dataclasses.dataclass\nclass ToastAction:\n    \"\"\"A toast action that render a button in the toast.\"\"\"\n\n    label: str\n    on_click: Any\n\n\n@serializer\ndef serialize_action(action: ToastAction) -> dict:\n    \"\"\"Serialize a toast action.\n\n    Args:\n        action: The toast action to serialize.\n\n    Returns:\n        The serialized toast action with on_click formatted to queue the given event.\n    \"\"\"\n    return {\n        \"label\": action.label,\n        \"onClick\": format.format_queue_events(action.on_click),\n    }\n\n\ndef _toast_callback_signature(toast: Var) -> list[Var]:\n    \"\"\"The signature for the toast callback, stripping out unserializable keys.\n\n    Args:\n        toast: The toast variable.\n\n    Returns:\n        A function call stripping non-serializable members of the toast object.\n    \"\"\"\n    return [\n        Var(\n            _js_expr=f\"(() => {{let {{action, cancel, onDismiss, onAutoClose, ...rest}} = {toast!s}; return rest}})()\"\n        )\n    ]\n\n\nclass ToastProps(NoExtrasAllowedProps):\n    \"\"\"Props for the toast component.\"\"\"\n\n    # Toast's title, renders above the description.\n    title: str | Var | None\n\n    # Toast's description, renders underneath the title.\n    description: str | Var | None\n\n    # Whether to show the close button.\n    close_button: bool | None\n\n    # Dark toast in light mode and vice versa.\n    invert: bool | None\n\n    # Control the sensitivity of the toast for screen readers\n    important: bool | None\n\n    # Time in milliseconds that should elapse before automatically closing the toast.\n    duration: int | None\n\n    # Position of the toast.\n    position: LiteralPosition | None\n\n    # If false, it'll prevent the user from dismissing the toast.\n    dismissible: bool | None\n\n    # TODO: fix serialization of icons for toast? (might not be possible yet)\n    # Icon displayed in front of toast's text, aligned vertically.\n    # icon: Icon | None = None # noqa: ERA001\n\n    # TODO: fix implementation for action / cancel buttons\n    # Renders a primary button, clicking it will close the toast.\n    action: ToastAction | None\n\n    # Renders a secondary button, clicking it will close the toast.\n    cancel: ToastAction | None\n\n    # Custom id for the toast.\n    id: str | Var | None\n\n    # Removes the default styling, which allows for easier customization.\n    unstyled: bool | None\n\n    # Custom style for the toast.\n    style: Style | None\n\n    # Class name for the toast.\n    class_name: str | None\n\n    # XXX: These still do not seem to work\n    # Custom style for the toast primary button.\n    action_button_styles: Style | None\n\n    # Custom style for the toast secondary button.\n    cancel_button_styles: Style | None\n\n    # The function gets called when either the close button is clicked, or the toast is swiped.\n    on_dismiss: Any | None\n\n    # Function that gets called when the toast disappears automatically after it's timeout (duration` prop).\n    on_auto_close: Any | None\n\n    def dict(self, *args: Any, **kwargs: Any) -> dict[str, Any]:\n        \"\"\"Convert the object to a dictionary.\n\n        Args:\n            *args: The arguments to pass to the base class.\n            **kwargs: The keyword arguments to pass to the base\n\n        Returns:\n            The object as a dictionary with ToastAction fields intact.\n        \"\"\"\n        d = super().dict(*args, **kwargs)\n        # Keep these fields as ToastAction so they can be serialized specially\n        if \"action\" in d:\n            d[\"action\"] = self.action\n            if isinstance(self.action, dict):\n                d[\"action\"] = ToastAction(**self.action)\n        if \"cancel\" in d:\n            d[\"cancel\"] = self.cancel\n            if isinstance(self.cancel, dict):\n                d[\"cancel\"] = ToastAction(**self.cancel)\n        if \"onDismiss\" in d:\n            d[\"onDismiss\"] = format.format_queue_events(\n                self.on_dismiss, _toast_callback_signature\n            )\n        if \"onAutoClose\" in d:\n            d[\"onAutoClose\"] = format.format_queue_events(\n                self.on_auto_close, _toast_callback_signature\n            )\n        return d\n\n\nclass Toaster(Component):\n    \"\"\"A Toaster Component for displaying toast notifications.\"\"\"\n\n    library: str | None = \"sonner@2.0.7\"\n\n    tag = \"Toaster\"\n\n    # the theme of the toast\n    theme: Var[str] = resolved_color_mode\n\n    # whether to show rich colors\n    rich_colors: Var[bool] = LiteralVar.create(True)\n\n    # whether to expand the toast\n    expand: Var[bool] = LiteralVar.create(True)\n\n    # the number of toasts that are currently visible\n    visible_toasts: Var[int]\n\n    # the position of the toast\n    position: Var[LiteralPosition] = LiteralVar.create(\"bottom-right\")\n\n    # whether to show the close button\n    close_button: Var[bool] = LiteralVar.create(False)\n\n    # offset of the toast\n    offset: Var[str]\n\n    # directionality of the toast (default: ltr)\n    dir: Var[str]\n\n    # Keyboard shortcut that will move focus to the toaster area.\n    hotkey: Var[str]\n\n    # Dark toasts in light mode and vice versa.\n    invert: Var[bool]\n\n    # These will act as default options for all toasts. See toast() for all available options.\n    toast_options: Var[ToastProps]\n\n    # Gap between toasts when expanded\n    gap: Var[int]\n\n    # Changes the default loading icon\n    loading_icon: Var[Icon]\n\n    # Pauses toast timers when the page is hidden, e.g., when the tab is backgrounded, the browser is minimized, or the OS is locked.\n    pause_when_page_is_hidden: Var[bool]\n\n    def add_hooks(self) -> list[Var | str]:\n        \"\"\"Add hooks for the toaster component.\n\n        Returns:\n            The hooks for the toaster component.\n        \"\"\"\n        if self.library is None:\n            return []\n        hook = Var(\n            _js_expr=f\"{toast_ref} = toast\",\n            _var_data=VarData(\n                imports={\n                    \"$/utils/state\": [ImportVar(tag=\"refs\")],\n                    self.library: [ImportVar(tag=\"toast\", install=False)],\n                }\n            ),\n        )\n        return [hook]\n\n    @staticmethod\n    def send_toast(\n        message: str | Var[str] = \"\",\n        level: str | None = None,\n        fallback_to_alert: bool = False,\n        **props,\n    ) -> EventSpec:\n        \"\"\"Send a toast message.\n\n        Args:\n            message: The message to display.\n            level: The level of the toast.\n            fallback_to_alert: Whether to fallback to an alert if the toaster is not created.\n            **props: The options for the toast.\n\n        Returns:\n            The toast event.\n\n        Raises:\n            ValueError: If the Toaster component is not created.\n        \"\"\"\n        toast_command = (\n            ObjectVar.__getattr__(toast_ref.to(dict), level) if level else toast_ref\n        ).to(FunctionVar)\n\n        if isinstance(message, Var):\n            props.setdefault(\"title\", message)\n            message = \"\"\n        elif message == \"\" and \"title\" not in props and \"description\" not in props:\n            msg = \"Toast message or title or description must be provided.\"\n            raise ValueError(msg)\n\n        if props:\n            args = LiteralVar.create(ToastProps(component_name=\"rx.toast\", **props))  # pyright: ignore [reportCallIssue]\n            toast = toast_command.call(message, args)\n        else:\n            toast = toast_command.call(message)\n\n        if fallback_to_alert:\n            toast = ternary_operation(\n                toast_ref.bool(),\n                toast,\n                FunctionVar(\"window.alert\").call(\n                    Var\n                    .create(\n                        message\n                        if isinstance(message, str) and message\n                        else props.get(\"title\", props.get(\"description\", \"\"))\n                    )\n                    .to(str)\n                    .replace(\"<br/>\", \"\\n\")\n                ),\n            )\n\n        return run_script(toast)\n\n    @staticmethod\n    def toast_info(message: str | Var[str] = \"\", **kwargs: Any) -> EventSpec:\n        \"\"\"Display an info toast message.\n\n        Args:\n            message: The message to display.\n            **kwargs: Additional toast props.\n\n        Returns:\n            The toast event.\n        \"\"\"\n        return Toaster.send_toast(message, level=\"info\", **kwargs)\n\n    @staticmethod\n    def toast_warning(message: str | Var[str] = \"\", **kwargs: Any) -> EventSpec:\n        \"\"\"Display a warning toast message.\n\n        Args:\n            message: The message to display.\n            **kwargs: Additional toast props.\n\n        Returns:\n            The toast event.\n        \"\"\"\n        return Toaster.send_toast(message, level=\"warning\", **kwargs)\n\n    @staticmethod\n    def toast_error(message: str | Var[str] = \"\", **kwargs: Any) -> EventSpec:\n        \"\"\"Display an error toast message.\n\n        Args:\n            message: The message to display.\n            **kwargs: Additional toast props.\n\n        Returns:\n            The toast event.\n        \"\"\"\n        return Toaster.send_toast(message, level=\"error\", **kwargs)\n\n    @staticmethod\n    def toast_success(message: str | Var[str] = \"\", **kwargs: Any) -> EventSpec:\n        \"\"\"Display a success toast message.\n\n        Args:\n            message: The message to display.\n            **kwargs: Additional toast props.\n\n        Returns:\n            The toast event.\n        \"\"\"\n        return Toaster.send_toast(message, level=\"success\", **kwargs)\n\n    @staticmethod\n    def toast_loading(message: str | Var[str] = \"\", **kwargs: Any) -> EventSpec:\n        \"\"\"Display a loading toast message.\n\n        Args:\n            message: The message to display.\n            **kwargs: Additional toast props.\n\n        Returns:\n            The toast event.\n        \"\"\"\n        return Toaster.send_toast(message, level=\"loading\", **kwargs)\n\n    @staticmethod\n    def toast_dismiss(id: Var[str] | str | None = None) -> EventSpec:\n        \"\"\"Dismiss a toast.\n\n        Args:\n            id: The id of the toast to dismiss.\n\n        Returns:\n            The toast dismiss event.\n        \"\"\"\n        dismiss_var_data = None\n\n        if isinstance(id, Var):\n            dismiss = f\"{toast_ref}.dismiss({id!s})\"\n            dismiss_var_data = id._get_all_var_data()\n        elif isinstance(id, str):\n            dismiss = f\"{toast_ref}.dismiss('{id}')\"\n        else:\n            dismiss = f\"{toast_ref}.dismiss()\"\n        dismiss_action = Var(\n            _js_expr=dismiss, _var_data=VarData.merge(dismiss_var_data)\n        )\n        return run_script(dismiss_action)\n\n    @classmethod\n    def create(cls, *children: Any, **props: Any) -> Component:\n        \"\"\"Create a toaster component.\n\n        Args:\n            *children: The children of the toaster.\n            **props: The properties of the toaster.\n\n        Returns:\n            The toaster component.\n        \"\"\"\n        return super().create(*children, **props)\n\n\n# TODO: figure out why loading toast stay open forever when using level=\"loading\" in toast()\n\n\nclass ToastNamespace(ComponentNamespace):\n    \"\"\"Namespace for toast components.\"\"\"\n\n    provider = staticmethod(Toaster.create)\n    options = staticmethod(ToastProps)\n    info = staticmethod(Toaster.toast_info)\n    warning = staticmethod(Toaster.toast_warning)\n    error = staticmethod(Toaster.toast_error)\n    success = staticmethod(Toaster.toast_success)\n    loading = staticmethod(Toaster.toast_loading)\n    dismiss = staticmethod(Toaster.toast_dismiss)\n    __call__ = staticmethod(Toaster.send_toast)\n\n\ntoast = ToastNamespace()\n"
  },
  {
    "path": "reflex/components/tags/__init__.py",
    "content": "\"\"\"Representations for React tags.\"\"\"\n\nfrom .cond_tag import CondTag\nfrom .iter_tag import IterTag\nfrom .match_tag import MatchTag\nfrom .tag import Tag\n"
  },
  {
    "path": "reflex/components/tags/cond_tag.py",
    "content": "\"\"\"Tag to conditionally render components.\"\"\"\n\nimport dataclasses\nfrom collections.abc import Iterator, Mapping\nfrom typing import Any\n\nfrom reflex.components.tags.tag import Tag\n\n\n@dataclasses.dataclass(frozen=True, kw_only=True)\nclass CondTag(Tag):\n    \"\"\"A conditional tag.\"\"\"\n\n    # The condition to determine which component to render.\n    cond_state: str\n\n    # The code to render if the condition is true.\n    true_value: Mapping\n\n    # The code to render if the condition is false.\n    false_value: Mapping | None = None\n\n    def __iter__(self) -> Iterator[tuple[str, Any]]:\n        \"\"\"Iterate over the tag's attributes.\n\n        Yields:\n            An iterator over the tag's attributes.\n        \"\"\"\n        yield (\"cond_state\", self.cond_state)\n        yield (\"true_value\", self.true_value)\n        yield (\"false_value\", self.false_value)\n"
  },
  {
    "path": "reflex/components/tags/iter_tag.py",
    "content": "\"\"\"Tag to loop through a list of components.\"\"\"\n\nfrom __future__ import annotations\n\nimport dataclasses\nimport inspect\nfrom collections.abc import Callable, Iterable\nfrom typing import TYPE_CHECKING\n\nfrom reflex.components.tags.tag import Tag\nfrom reflex.utils.types import GenericType\nfrom reflex.vars import LiteralArrayVar, Var, get_unique_variable_name\nfrom reflex.vars.sequence import _determine_value_of_array_index\n\nif TYPE_CHECKING:\n    from reflex.components.component import Component\n\n\n@dataclasses.dataclass(frozen=True)\nclass IterTag(Tag):\n    \"\"\"An iterator tag.\"\"\"\n\n    # The var to iterate over.\n    iterable: Var[Iterable] = dataclasses.field(\n        default_factory=lambda: LiteralArrayVar.create([])\n    )\n\n    # The component render function for each item in the iterable.\n    render_fn: Callable = dataclasses.field(default_factory=lambda: lambda x: x)\n\n    # The name of the arg var.\n    arg_var_name: str = dataclasses.field(default_factory=get_unique_variable_name)\n\n    # The name of the index var.\n    index_var_name: str = dataclasses.field(default_factory=get_unique_variable_name)\n\n    def get_iterable_var_type(self) -> GenericType:\n        \"\"\"Get the type of the iterable var.\n\n        Returns:\n            The type of the iterable var.\n        \"\"\"\n        return _determine_value_of_array_index(self.iterable._var_type)\n\n    def get_index_var(self) -> Var:\n        \"\"\"Get the index var for the tag (with curly braces).\n\n        This is used to reference the index var within the tag.\n\n        Returns:\n            The index var.\n        \"\"\"\n        return Var(\n            _js_expr=self.index_var_name,\n            _var_type=int,\n        ).guess_type()\n\n    def get_arg_var(self) -> Var:\n        \"\"\"Get the arg var for the tag (with curly braces).\n\n        This is used to reference the arg var within the tag.\n\n        Returns:\n            The arg var.\n        \"\"\"\n        return Var(\n            _js_expr=self.arg_var_name,\n            _var_type=self.get_iterable_var_type(),\n        ).guess_type()\n\n    def render_component(self) -> Component:\n        \"\"\"Render the component.\n\n        Returns:\n            The rendered component.\n\n        Raises:\n            ValueError: If the render function takes more than 2 arguments.\n            ValueError: If the render function doesn't return a component.\n        \"\"\"\n        # Import here to avoid circular imports.\n        from reflex.compiler.compiler import _into_component_once\n        from reflex.components.base.fragment import Fragment\n        from reflex.components.core.cond import Cond\n        from reflex.components.core.foreach import Foreach\n\n        # Get the render function arguments.\n        args = inspect.getfullargspec(self.render_fn).args\n        arg = self.get_arg_var()\n        index = self.get_index_var()\n\n        if len(args) == 1:\n            # If the render function doesn't take the index as an argument.\n            component = self.render_fn(arg)\n        else:\n            # If the render function takes the index as an argument.\n            if len(args) != 2:\n                msg = \"The render function must take 2 arguments.\"\n                raise ValueError(msg)\n            component = self.render_fn(arg, index)\n\n        # Nested foreach components or cond must be wrapped in fragments.\n        if isinstance(component, (Foreach, Cond)):\n            component = Fragment.create(component)\n\n        component = _into_component_once(component)\n\n        if component is None:\n            msg = \"The render function must return a component.\"\n            raise ValueError(msg)\n\n        # Set the component key.\n        if component.key is None:\n            component.key = index\n\n        return component\n"
  },
  {
    "path": "reflex/components/tags/match_tag.py",
    "content": "\"\"\"Tag to conditionally match cases.\"\"\"\n\nimport dataclasses\nfrom collections.abc import Iterator, Mapping, Sequence\nfrom typing import Any\n\nfrom reflex.components.tags.tag import Tag\n\n\n@dataclasses.dataclass(frozen=True, kw_only=True)\nclass MatchTag(Tag):\n    \"\"\"A match tag.\"\"\"\n\n    # The condition to determine which case to match.\n    cond: str\n\n    # The list of match cases to be matched.\n    match_cases: Sequence[tuple[Sequence[str], Mapping]]\n\n    # The catchall case to match.\n    default: Any\n\n    def __iter__(self) -> Iterator[tuple[str, Any]]:\n        \"\"\"Iterate over the tag's attributes.\n\n        Yields:\n            An iterator over the tag's attributes.\n        \"\"\"\n        yield (\"cond\", self.cond)\n        yield (\"match_cases\", self.match_cases)\n        yield (\"default\", self.default)\n"
  },
  {
    "path": "reflex/components/tags/tag.py",
    "content": "\"\"\"A React tag.\"\"\"\n\nfrom __future__ import annotations\n\nimport dataclasses\nfrom collections.abc import Iterator, Mapping, Sequence\nfrom typing import Any\n\nfrom reflex.event import EventChain\nfrom reflex.utils import format\nfrom reflex.vars.base import LiteralVar, Var\n\n\ndef render_prop(value: Any) -> Any:\n    \"\"\"Render the prop.\n\n    Args:\n        value: The value to render.\n\n    Returns:\n        The rendered value.\n    \"\"\"\n    from reflex.components.component import BaseComponent\n\n    if isinstance(value, BaseComponent):\n        return value.render()\n    if isinstance(value, Sequence) and not isinstance(value, str):\n        return [render_prop(v) for v in value]\n    if callable(value) and not isinstance(value, Var):\n        return None\n    return value\n\n\n@dataclasses.dataclass(frozen=True)\nclass Tag:\n    \"\"\"A React tag.\"\"\"\n\n    # The name of the tag.\n    name: str = \"\"\n\n    # The props of the tag.\n    props: Mapping[str, Any] = dataclasses.field(default_factory=dict)\n\n    # Special props that aren't key value pairs.\n    special_props: Sequence[Var] = dataclasses.field(default_factory=list)\n\n    # The children components.\n    children: Sequence[Any] = dataclasses.field(default_factory=list)\n\n    def format_props(self) -> list[str]:\n        \"\"\"Format the tag's props.\n\n        Returns:\n            The formatted props list.\n        \"\"\"\n        return format.format_props(*self.special_props, **self.props)\n\n    def set(self, **kwargs: Any):\n        \"\"\"Return a new tag with the given fields set.\n\n        Args:\n            **kwargs: The fields to set.\n\n        Returns:\n            The tag with the fields set.\n        \"\"\"\n        return dataclasses.replace(self, **kwargs)\n\n    def __iter__(self) -> Iterator[tuple[str, Any]]:\n        \"\"\"Iterate over the tag's fields.\n\n        Yields:\n            tuple[str, Any]: The field name and value.\n        \"\"\"\n        for field in dataclasses.fields(self):\n            if field.name == \"props\":\n                yield \"props\", self.format_props()\n            elif field.name != \"special_props\":\n                rendered_value = render_prop(getattr(self, field.name))\n                if rendered_value is not None:\n                    yield field.name, rendered_value\n\n    def add_props(self, **kwargs: Any | None) -> Tag:\n        \"\"\"Return a new tag with the given props added.\n\n        Args:\n            **kwargs: The props to add.\n\n        Returns:\n            The tag with the props added.\n        \"\"\"\n        return dataclasses.replace(\n            self,\n            props={\n                **self.props,\n                **{\n                    format.to_camel_case(name, treat_hyphens_as_underscores=False): (\n                        prop\n                        if isinstance(prop, (EventChain, Mapping))\n                        else LiteralVar.create(prop)\n                    )\n                    for name, prop in kwargs.items()\n                    if self.is_valid_prop(prop)\n                },\n            },\n        )\n\n    def remove_props(self, *args: str) -> Tag:\n        \"\"\"Return a new tag with the given props removed.\n\n        Args:\n            *args: The names of the props to remove.\n\n        Returns:\n            The tag with the props removed.\n        \"\"\"\n        formatted_args = [format.to_camel_case(arg) for arg in args]\n        return dataclasses.replace(\n            self,\n            props={\n                name: value\n                for name, value in self.props.items()\n                if name not in formatted_args\n            },\n        )\n\n    @staticmethod\n    def is_valid_prop(prop: Var | None) -> bool:\n        \"\"\"Check if the prop is valid.\n\n        Args:\n            prop: The prop to check.\n\n        Returns:\n            Whether the prop is valid.\n        \"\"\"\n        return prop is not None and not (isinstance(prop, dict) and len(prop) == 0)\n"
  },
  {
    "path": "reflex/components/tags/tagless.py",
    "content": "\"\"\"A tag with no tag.\"\"\"\n\nimport dataclasses\n\nfrom reflex.components.tags import Tag\nfrom reflex.utils import format\n\n\n@dataclasses.dataclass(frozen=True, kw_only=True)\nclass Tagless(Tag):\n    \"\"\"A tag with no tag.\"\"\"\n\n    # The inner contents of the tag.\n    contents: str\n\n    def __str__(self) -> str:\n        \"\"\"Return the string representation of the tag.\n\n        Returns:\n            The string representation of the tag.\n        \"\"\"\n        out = self.contents\n        space = format.wrap(\" \", \"{\")\n        if len(self.contents) > 0 and self.contents[0] == \" \":\n            out = space + out\n        if len(self.contents) > 0 and self.contents[-1] == \" \":\n            out = out + space\n        return out\n\n    def __iter__(self):\n        \"\"\"Iterate over the tag's fields.\n\n        Yields:\n            tuple[str, Any]: The field name and value.\n        \"\"\"\n        yield \"contents\", self.contents\n"
  },
  {
    "path": "reflex/config.py",
    "content": "\"\"\"The Reflex config.\"\"\"\n\nimport dataclasses\nimport importlib\nimport os\nimport sys\nimport threading\nimport urllib.parse\nfrom collections.abc import Sequence\nfrom importlib.util import find_spec\nfrom pathlib import Path\nfrom types import ModuleType\nfrom typing import TYPE_CHECKING, Annotated, Any, ClassVar, Literal\n\nfrom reflex import constants\nfrom reflex.constants.base import LogLevel\nfrom reflex.environment import EnvironmentVariables as EnvironmentVariables\nfrom reflex.environment import EnvVar as EnvVar\nfrom reflex.environment import (\n    ExistingPath,\n    SequenceOptions,\n    _load_dotenv_from_files,\n    _paths_from_env_files,\n    interpret_env_var_value,\n)\nfrom reflex.environment import env_var as env_var\nfrom reflex.environment import environment as environment\nfrom reflex.plugins import Plugin\nfrom reflex.plugins.sitemap import SitemapPlugin\nfrom reflex.utils import console\nfrom reflex.utils.exceptions import ConfigError\n\nif TYPE_CHECKING:\n    from pyleak.base import LeakAction\n\n\n@dataclasses.dataclass(kw_only=True)\nclass DBConfig:\n    \"\"\"Database config.\"\"\"\n\n    engine: str\n    username: str | None = \"\"\n    password: str | None = \"\"\n    host: str | None = \"\"\n    port: int | None = None\n    database: str\n\n    @classmethod\n    def postgresql(\n        cls,\n        database: str,\n        username: str,\n        password: str | None = None,\n        host: str | None = None,\n        port: int | None = 5432,\n    ) -> \"DBConfig\":\n        \"\"\"Create an instance with postgresql engine.\n\n        Args:\n            database: Database name.\n            username: Database username.\n            password: Database password.\n            host: Database host.\n            port: Database port.\n\n        Returns:\n            DBConfig instance.\n        \"\"\"\n        return cls(\n            engine=\"postgresql\",\n            username=username,\n            password=password,\n            host=host,\n            port=port,\n            database=database,\n        )\n\n    @classmethod\n    def postgresql_psycopg(\n        cls,\n        database: str,\n        username: str,\n        password: str | None = None,\n        host: str | None = None,\n        port: int | None = 5432,\n    ) -> \"DBConfig\":\n        \"\"\"Create an instance with postgresql+psycopg engine.\n\n        Args:\n            database: Database name.\n            username: Database username.\n            password: Database password.\n            host: Database host.\n            port: Database port.\n\n        Returns:\n            DBConfig instance.\n        \"\"\"\n        return cls(\n            engine=\"postgresql+psycopg\",\n            username=username,\n            password=password,\n            host=host,\n            port=port,\n            database=database,\n        )\n\n    @classmethod\n    def sqlite(\n        cls,\n        database: str,\n    ) -> \"DBConfig\":\n        \"\"\"Create an instance with sqlite engine.\n\n        Args:\n            database: Database name.\n\n        Returns:\n            DBConfig instance.\n        \"\"\"\n        return cls(\n            engine=\"sqlite\",\n            database=database,\n        )\n\n    def get_url(self) -> str:\n        \"\"\"Get database URL.\n\n        Returns:\n            The database URL.\n        \"\"\"\n        host = (\n            f\"{self.host}:{self.port}\" if self.host and self.port else self.host or \"\"\n        )\n        username = urllib.parse.quote_plus(self.username) if self.username else \"\"\n        password = urllib.parse.quote_plus(self.password) if self.password else \"\"\n\n        if username:\n            path = f\"{username}:{password}@{host}\" if password else f\"{username}@{host}\"\n        else:\n            path = f\"{host}\"\n\n        return f\"{self.engine}://{path}/{self.database}\"\n\n\n# These vars are not logged because they may contain sensitive information.\n_sensitive_env_vars = {\"DB_URL\", \"ASYNC_DB_URL\", \"REDIS_URL\"}\n\n\n@dataclasses.dataclass(kw_only=True)\nclass BaseConfig:\n    \"\"\"Base config for the Reflex app.\"\"\"\n\n    # The name of the app (should match the name of the app directory).\n    app_name: str\n\n    # The path to the app module.\n    app_module_import: str | None = None\n\n    # The log level to use.\n    loglevel: constants.LogLevel = constants.LogLevel.DEFAULT\n\n    # The port to run the frontend on. NOTE: When running in dev mode, the next available port will be used if this is taken.\n    frontend_port: int | None = None\n\n    # The path to run the frontend on. For example, \"/app\" will run the frontend on http://localhost:3000/app\n    frontend_path: str = \"\"\n\n    # The port to run the backend on. NOTE: When running in dev mode, the next available port will be used if this is taken.\n    backend_port: int | None = None\n\n    # The backend url the frontend will connect to. This must be updated if the backend is hosted elsewhere, or in production.\n    api_url: str = f\"http://localhost:{constants.DefaultPorts.BACKEND_PORT}\"\n\n    # The url the frontend will be hosted on.\n    deploy_url: str | None = f\"http://localhost:{constants.DefaultPorts.FRONTEND_PORT}\"\n\n    # The url the backend will be hosted on.\n    backend_host: str = \"0.0.0.0\"\n\n    # The database url used by rx.Model.\n    db_url: str | None = \"sqlite:///reflex.db\"\n\n    # The async database url used by rx.Model.\n    async_db_url: str | None = None\n\n    # The redis url\n    redis_url: str | None = None\n\n    # Telemetry opt-in.\n    telemetry_enabled: bool = True\n\n    # PyLeak monitoring configuration for detecting event loop blocking and resource leaks.\n    enable_pyleak_monitoring: bool = False\n\n    # Threshold in seconds for detecting event loop blocking operations.\n    pyleak_blocking_threshold: float = 0.1\n\n    # Grace period in seconds for thread leak detection cleanup.\n    pyleak_thread_grace_period: float = 0.2\n\n    # Action to take when PyLeak detects issues\n    pyleak_action: \"LeakAction | None\" = None\n\n    # The bun path\n    bun_path: ExistingPath = constants.Bun.DEFAULT_PATH\n\n    # Timeout to do a production build of a frontend page.\n    static_page_generation_timeout: int = 60\n\n    # Comma separated list of origins that are allowed to connect to the backend API.\n    cors_allowed_origins: Annotated[Sequence[str], SequenceOptions(delimiter=\",\")] = (\n        dataclasses.field(default=(\"*\",))\n    )\n\n    # Allowed hosts for the Vite dev server. Set to True to allow all hosts,\n    # or provide a list of hostnames (e.g. [\"myservice.local\"]) to allow specific ones.\n    # Prevents 403 errors in Docker, Codespaces, reverse proxies, etc.\n    vite_allowed_hosts: bool | list[str] = False\n\n    # Whether to use React strict mode.\n    react_strict_mode: bool = True\n\n    # Additional frontend packages to install.\n    frontend_packages: list[str] = dataclasses.field(default_factory=list)\n\n    # Indicate which type of state manager to use\n    state_manager_mode: constants.StateManagerMode = constants.StateManagerMode.DISK\n\n    # Maximum expiration lock time for redis state manager\n    redis_lock_expiration: int = constants.Expiration.LOCK\n\n    # Maximum lock time before warning for redis state manager.\n    redis_lock_warning_threshold: int = constants.Expiration.LOCK_WARNING_THRESHOLD\n\n    # Token expiration time for redis state manager\n    redis_token_expiration: int = constants.Expiration.TOKEN\n\n    # Attributes that were explicitly set by the user.\n    _non_default_attributes: set[str] = dataclasses.field(\n        default_factory=set, init=False\n    )\n\n    # Path to file containing key-values pairs to override in the environment; Dotenv format.\n    env_file: str | None = None\n\n    # Whether to automatically create setters for state base vars\n    state_auto_setters: bool | None = None\n\n    # Whether to display the sticky \"Built with Reflex\" badge on all pages.\n    show_built_with_reflex: bool | None = None\n\n    # Whether the app is running in the reflex cloud environment.\n    is_reflex_cloud: bool = False\n\n    # Extra overlay function to run after the app is built. Formatted such that `from path_0.path_1... import path[-1]`, and calling it with no arguments would work. For example, \"reflex.components.moment.moment\".\n    extra_overlay_function: str | None = None\n\n    # List of plugins to use in the app.\n    plugins: list[Plugin] = dataclasses.field(default_factory=list)\n\n    # List of plugin types to disable in the app.\n    disable_plugins: list[type[Plugin]] = dataclasses.field(default_factory=list)\n\n    # The transport method for client-server communication.\n    transport: Literal[\"websocket\", \"polling\"] = \"websocket\"\n\n    # Whether to skip plugin checks.\n    _skip_plugins_checks: bool = dataclasses.field(default=False, repr=False)\n\n    _prefixes: ClassVar[list[str]] = [\"REFLEX_\"]\n\n\n_PLUGINS_ENABLED_BY_DEFAULT = [\n    SitemapPlugin,\n]\n\n\n@dataclasses.dataclass(kw_only=True, init=False)\nclass Config(BaseConfig):\n    \"\"\"Configuration class for Reflex applications.\n\n    The config defines runtime settings for your app including server ports, database connections,\n    frontend packages, and deployment settings.\n\n    By default, the config is defined in an `rxconfig.py` file in the root of your app:\n\n    ```python\n    # rxconfig.py\n    import reflex as rx\n\n    config = rx.Config(\n        app_name=\"myapp\",\n        # Server configuration\n        frontend_port=3000,\n        backend_port=8000,\n        # Database\n        db_url=\"postgresql://user:pass@localhost:5432/mydb\",\n        # Additional frontend packages\n        frontend_packages=[\"react-icons\"],\n        # CORS settings for production\n        cors_allowed_origins=[\"https://mydomain.com\"],\n    )\n    ```\n\n    ## Environment Variable Overrides\n\n    Any config value can be overridden by setting an environment variable with the `REFLEX_`\n    prefix and the parameter name in uppercase:\n\n    ```bash\n    REFLEX_DB_URL=\"postgresql://user:pass@localhost/db\" reflex run\n    REFLEX_FRONTEND_PORT=3001 reflex run\n    ```\n\n    ## Key Configuration Areas\n\n    - **App Settings**: `app_name`, `loglevel`, `telemetry_enabled`\n    - **Server**: `frontend_port`, `backend_port`, `api_url`, `cors_allowed_origins`\n    - **Database**: `db_url`, `async_db_url`, `redis_url`\n    - **Frontend**: `frontend_packages`, `react_strict_mode`\n    - **State Management**: `state_manager_mode`, `state_auto_setters`\n    - **Plugins**: `plugins`, `disable_plugins`\n\n    See the [configuration docs](https://reflex.dev/docs/advanced-onboarding/configuration) for complete details on all available options.\n    \"\"\"\n\n    # Track whether the app name has already been validated for this Config instance.\n    _app_name_is_valid: bool = dataclasses.field(default=False, repr=False)\n\n    def _post_init(self, **kwargs):\n        \"\"\"Post-initialization method to set up the config.\n\n        This method is called after the config is initialized. It sets up the\n        environment variables, updates the config from the environment, and\n        replaces default URLs if ports were set.\n\n        Args:\n            **kwargs: The kwargs passed to the Pydantic init method.\n\n        Raises:\n            ConfigError: If some values in the config are invalid.\n        \"\"\"\n        class_fields = self.class_fields()\n        for key, value in kwargs.items():\n            if key not in class_fields:\n                setattr(self, key, value)\n\n        # Clean up this code when we remove plain envvar in 0.8.0\n        env_loglevel = os.environ.get(\"REFLEX_LOGLEVEL\")\n        if env_loglevel is not None:\n            env_loglevel = LogLevel(env_loglevel.lower())\n        if env_loglevel or self.loglevel != LogLevel.DEFAULT:\n            console.set_log_level(env_loglevel or self.loglevel)\n\n        # Update the config from environment variables.\n        env_kwargs = self.update_from_env()\n        for key, env_value in env_kwargs.items():\n            setattr(self, key, env_value)\n\n        # Normalize disable_plugins: convert strings and Plugin subclasses to instances.\n        self._normalize_disable_plugins()\n\n        # Add builtin plugins if not disabled.\n        if not self._skip_plugins_checks:\n            self._add_builtin_plugins()\n\n        #   Update default URLs if ports were set\n        kwargs.update(env_kwargs)\n        self._non_default_attributes = set(kwargs.keys())\n        self._replace_defaults(**kwargs)\n\n        if (\n            self.state_manager_mode == constants.StateManagerMode.REDIS\n            and not self.redis_url\n        ):\n            msg = f\"{self._prefixes[0]}REDIS_URL is required when using the redis state manager.\"\n            raise ConfigError(msg)\n\n    def _normalize_disable_plugins(self):\n        \"\"\"Normalize disable_plugins list entries to Plugin subclasses.\n\n        Handles backward compatibility by converting strings (fully qualified\n        import paths) and Plugin instances to their associated classes.\n        \"\"\"\n        normalized: list[type[Plugin]] = []\n        for entry in self.disable_plugins:\n            if isinstance(entry, type) and issubclass(entry, Plugin):\n                normalized.append(entry)\n            elif isinstance(entry, Plugin):\n                normalized.append(type(entry))\n            elif isinstance(entry, str):\n                console.deprecate(\n                    feature_name=\"Passing strings to disable_plugins\",\n                    reason=\"pass Plugin classes directly instead, e.g. disable_plugins=[SitemapPlugin]\",\n                    deprecation_version=\"0.8.28\",\n                    removal_version=\"0.9.0\",\n                )\n                try:\n                    from reflex.environment import interpret_plugin_class_env\n\n                    normalized.append(\n                        interpret_plugin_class_env(entry, \"disable_plugins\")\n                    )\n                except Exception:\n                    console.warn(\n                        f\"Failed to import plugin from string {entry!r} in disable_plugins. \"\n                        \"Please pass Plugin subclasses directly.\",\n                    )\n            else:\n                console.warn(\n                    f\"reflex.Config.disable_plugins should contain Plugin subclasses, but got {entry!r}.\",\n                )\n        self.disable_plugins = normalized\n\n    def _add_builtin_plugins(self):\n        \"\"\"Add the builtin plugins to the config.\"\"\"\n        for plugin in _PLUGINS_ENABLED_BY_DEFAULT:\n            plugin_name = plugin.__module__ + \".\" + plugin.__qualname__\n            if plugin not in self.disable_plugins:\n                if not any(isinstance(p, plugin) for p in self.plugins):\n                    console.warn(\n                        f\"`{plugin_name}` plugin is enabled by default, but not explicitly added to the config. \"\n                        \"If you want to use it, please add it to the `plugins` list in your config inside of `rxconfig.py`. \"\n                        f\"To disable this plugin, add `{plugin.__name__}` to the `disable_plugins` list.\",\n                    )\n                    self.plugins.append(plugin())\n            else:\n                if any(isinstance(p, plugin) for p in self.plugins):\n                    console.warn(\n                        f\"`{plugin_name}` is disabled in the config, but it is still present in the `plugins` list. \"\n                        \"Please remove it from the `plugins` list in your config inside of `rxconfig.py`.\",\n                    )\n\n        for disabled_plugin in self.disable_plugins:\n            if disabled_plugin not in _PLUGINS_ENABLED_BY_DEFAULT:\n                console.warn(\n                    f\"`{disabled_plugin!r}` is disabled in the config, but it is not a built-in plugin. \"\n                    \"Please remove it from the `disable_plugins` list in your config inside of `rxconfig.py`.\",\n                )\n\n    @classmethod\n    def class_fields(cls) -> set[str]:\n        \"\"\"Get the fields of the config class.\n\n        Returns:\n            The fields of the config class.\n        \"\"\"\n        return {field.name for field in dataclasses.fields(cls)}\n\n    if not TYPE_CHECKING:\n\n        def __init__(self, **kwargs):\n            \"\"\"Initialize the config values.\n\n            Args:\n                **kwargs: The kwargs to pass to the Pydantic init method.\n\n            # noqa: DAR101 self\n            \"\"\"\n            class_fields = self.class_fields()\n            super().__init__(**{k: v for k, v in kwargs.items() if k in class_fields})\n            self._post_init(**kwargs)\n\n    def json(self) -> str:\n        \"\"\"Get the config as a JSON string.\n\n        Returns:\n            The config as a JSON string.\n        \"\"\"\n        import json\n\n        from reflex.utils.serializers import serialize\n\n        return json.dumps(self, default=serialize)\n\n    @property\n    def app_module(self) -> ModuleType | None:\n        \"\"\"Return the app module if `app_module_import` is set.\n\n        Returns:\n            The app module.\n        \"\"\"\n        return (\n            importlib.import_module(self.app_module_import)\n            if self.app_module_import\n            else None\n        )\n\n    @property\n    def module(self) -> str:\n        \"\"\"Get the module name of the app.\n\n        Returns:\n            The module name.\n        \"\"\"\n        if self.app_module_import is not None:\n            return self.app_module_import\n        return self.app_name + \".\" + self.app_name\n\n    def update_from_env(self) -> dict[str, Any]:\n        \"\"\"Update the config values based on set environment variables.\n        If there is a set env_file, it is loaded first.\n\n        Returns:\n            The updated config values.\n        \"\"\"\n        if self.env_file:\n            _load_dotenv_from_files(_paths_from_env_files(self.env_file))\n\n        updated_values = {}\n        # Iterate over the fields.\n        for field in dataclasses.fields(self):\n            # The env var name is the key in uppercase.\n            environment_variable = None\n            for prefix in self._prefixes:\n                if environment_variable := os.environ.get(\n                    f\"{prefix}{field.name.upper()}\"\n                ):\n                    break\n\n            # If the env var is set, override the config value.\n            if environment_variable and environment_variable.strip():\n                # Interpret the value.\n                value = interpret_env_var_value(\n                    environment_variable,\n                    field.type,\n                    field.name,\n                )\n\n                # Set the value.\n                updated_values[field.name] = value\n\n                if field.name.upper() in _sensitive_env_vars:\n                    environment_variable = \"***\"\n\n                if value != getattr(self, field.name):\n                    console.debug(\n                        f\"Overriding config value {field.name} with env var {field.name.upper()}={environment_variable}\",\n                        dedupe=True,\n                    )\n        return updated_values\n\n    def get_event_namespace(self) -> str:\n        \"\"\"Get the path that the backend Websocket server lists on.\n\n        Returns:\n            The namespace for websocket.\n        \"\"\"\n        event_url = constants.Endpoint.EVENT.get_url()\n        return urllib.parse.urlsplit(event_url).path\n\n    def _replace_defaults(self, **kwargs):\n        \"\"\"Replace formatted defaults when the caller provides updates.\n\n        Args:\n            **kwargs: The kwargs passed to the config or from the env.\n        \"\"\"\n        if \"api_url\" not in self._non_default_attributes and \"backend_port\" in kwargs:\n            self.api_url = f\"http://localhost:{kwargs['backend_port']}\"\n\n        if (\n            \"deploy_url\" not in self._non_default_attributes\n            and \"frontend_port\" in kwargs\n        ):\n            self.deploy_url = f\"http://localhost:{kwargs['frontend_port']}\"\n\n        if \"api_url\" not in self._non_default_attributes:\n            # If running in Github Codespaces, override API_URL\n            codespace_name = os.getenv(\"CODESPACE_NAME\")\n            github_codespaces_port_forwarding_domain = os.getenv(\n                \"GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN\"\n            )\n            # If running on Replit.com interactively, override API_URL to ensure we maintain the backend_port\n            replit_dev_domain = os.getenv(\"REPLIT_DEV_DOMAIN\")\n            backend_port = kwargs.get(\"backend_port\", self.backend_port)\n            if codespace_name and github_codespaces_port_forwarding_domain:\n                self.api_url = (\n                    f\"https://{codespace_name}-{kwargs.get('backend_port', self.backend_port)}\"\n                    f\".{github_codespaces_port_forwarding_domain}\"\n                )\n            elif replit_dev_domain and backend_port:\n                self.api_url = f\"https://{replit_dev_domain}:{backend_port}\"\n\n    def _set_persistent(self, **kwargs):\n        \"\"\"Set values in this config and in the environment so they persist into subprocess.\n\n        Args:\n            **kwargs: The kwargs passed to the config.\n        \"\"\"\n        for key, value in kwargs.items():\n            if value is not None:\n                os.environ[self._prefixes[0] + key.upper()] = str(value)\n            setattr(self, key, value)\n        self._non_default_attributes.update(kwargs)\n        self._replace_defaults(**kwargs)\n\n\ndef _get_config() -> Config:\n    \"\"\"Get the app config.\n\n    Returns:\n        The app config.\n    \"\"\"\n    # only import the module if it exists. If a module spec exists then\n    # the module exists.\n    spec = find_spec(constants.Config.MODULE)\n    if not spec:\n        # we need this condition to ensure that a ModuleNotFound error is not thrown when\n        # running unit/integration tests or during `reflex init`.\n        return Config(app_name=\"\", _skip_plugins_checks=True)\n    rxconfig = importlib.import_module(constants.Config.MODULE)\n    return rxconfig.config\n\n\n# Protect sys.path from concurrent modification\n_config_lock = threading.RLock()\n\n\ndef get_config(reload: bool = False) -> Config:\n    \"\"\"Get the app config.\n\n    Args:\n        reload: Re-import the rxconfig module from disk\n\n    Returns:\n        The app config.\n    \"\"\"\n    cached_rxconfig = sys.modules.get(constants.Config.MODULE, None)\n    if cached_rxconfig is not None:\n        if reload:\n            # Remove any cached module when `reload` is requested.\n            del sys.modules[constants.Config.MODULE]\n        else:\n            return cached_rxconfig.config\n\n    with _config_lock:\n        orig_sys_path = sys.path.copy()\n        sys.path.clear()\n        sys.path.append(str(Path.cwd()))\n        try:\n            # Try to import the module with only the current directory in the path.\n            return _get_config()\n        except Exception:\n            # If the module import fails, try to import with the original sys.path.\n            sys.path.extend(orig_sys_path)\n            return _get_config()\n        finally:\n            # Find any entries added to sys.path by rxconfig.py itself.\n            extra_paths = [\n                p for p in sys.path if p not in orig_sys_path and p != str(Path.cwd())\n            ]\n            # Restore the original sys.path.\n            sys.path.clear()\n            sys.path.extend(extra_paths)\n            sys.path.extend(orig_sys_path)\n"
  },
  {
    "path": "reflex/constants/__init__.py",
    "content": "\"\"\"The constants package.\"\"\"\n\nfrom .base import (\n    APP_HARNESS_FLAG,\n    COOKIES,\n    IS_LINUX,\n    IS_MACOS,\n    IS_WINDOWS,\n    LOCAL_STORAGE,\n    POLLING_MAX_HTTP_BUFFER_SIZE,\n    PYTEST_CURRENT_TEST,\n    REFLEX_VAR_CLOSING_TAG,\n    REFLEX_VAR_OPENING_TAG,\n    SESSION_STORAGE,\n    ColorMode,\n    Dirs,\n    Env,\n    LogLevel,\n    Ping,\n    ReactRouter,\n    Reflex,\n    ReflexHostingCLI,\n    Templates,\n)\nfrom .compiler import (\n    NOCOMPILE_FILE,\n    SETTER_PREFIX,\n    CompileContext,\n    CompileVars,\n    ComponentName,\n    Ext,\n    Hooks,\n    Imports,\n    MemoizationDisposition,\n    MemoizationMode,\n    PageNames,\n)\nfrom .config import (\n    ALEMBIC_CONFIG,\n    Config,\n    DefaultPorts,\n    Expiration,\n    GitIgnore,\n    PyprojectToml,\n    RequirementsTxt,\n)\nfrom .custom_components import CustomComponents\nfrom .event import Endpoint, EventTriggers, SocketEvent\nfrom .installer import Bun, Node, PackageJson\nfrom .route import (\n    ROUTE_NOT_FOUND,\n    ROUTER,\n    ROUTER_DATA,\n    ROUTER_DATA_INCLUDE,\n    DefaultPage,\n    Page404,\n    RouteArgType,\n    RouteRegex,\n    RouteVar,\n)\nfrom .state import StateManagerMode\n\n__all__ = [\n    \"ALEMBIC_CONFIG\",\n    \"APP_HARNESS_FLAG\",\n    \"COOKIES\",\n    \"IS_LINUX\",\n    \"IS_MACOS\",\n    \"IS_WINDOWS\",\n    \"LOCAL_STORAGE\",\n    \"NOCOMPILE_FILE\",\n    \"POLLING_MAX_HTTP_BUFFER_SIZE\",\n    \"PYTEST_CURRENT_TEST\",\n    \"REFLEX_VAR_CLOSING_TAG\",\n    \"REFLEX_VAR_OPENING_TAG\",\n    \"ROUTER\",\n    \"ROUTER_DATA\",\n    \"ROUTER_DATA_INCLUDE\",\n    \"ROUTE_NOT_FOUND\",\n    \"SESSION_STORAGE\",\n    \"SETTER_PREFIX\",\n    \"Bun\",\n    \"ColorMode\",\n    \"CompileContext\",\n    \"CompileVars\",\n    \"ComponentName\",\n    \"Config\",\n    \"CustomComponents\",\n    \"DefaultPage\",\n    \"DefaultPorts\",\n    \"Dirs\",\n    \"Endpoint\",\n    \"Env\",\n    \"EventTriggers\",\n    \"Expiration\",\n    \"Ext\",\n    \"GitIgnore\",\n    \"Hooks\",\n    \"Imports\",\n    \"LogLevel\",\n    \"MemoizationDisposition\",\n    \"MemoizationMode\",\n    \"Node\",\n    \"PackageJson\",\n    \"Page404\",\n    \"PageNames\",\n    \"Ping\",\n    \"PyprojectToml\",\n    \"ReactRouter\",\n    \"Reflex\",\n    \"RequirementsTxt\",\n    \"RouteArgType\",\n    \"RouteRegex\",\n    \"RouteVar\",\n    \"SocketEvent\",\n    \"StateManagerMode\",\n    \"Templates\",\n]\n"
  },
  {
    "path": "reflex/constants/base.py",
    "content": "\"\"\"Base file for constants that don't fit any other categories.\"\"\"\n\nfrom __future__ import annotations\n\nimport platform\nfrom enum import Enum\nfrom importlib import metadata\nfrom pathlib import Path\nfrom types import SimpleNamespace\nfrom typing import Literal\n\nfrom platformdirs import PlatformDirs\n\nIS_WINDOWS = platform.system() == \"Windows\"\nIS_MACOS = platform.system() == \"Darwin\"\nIS_LINUX = platform.system() == \"Linux\"\n\n\nclass Dirs(SimpleNamespace):\n    \"\"\"Various directories/paths used by Reflex.\"\"\"\n\n    # The frontend directories in a project.\n    # The web folder where the frontend app is compiled to.\n    WEB = \".web\"\n    # The directory where uploaded files are stored.\n    UPLOADED_FILES = \"uploaded_files\"\n    # The name of the assets directory.\n    APP_ASSETS = \"assets\"\n    # The name of the assets directory for external resources (a subfolder of APP_ASSETS).\n    EXTERNAL_APP_ASSETS = \"external\"\n    # The name of the utils file.\n    UTILS = \"utils\"\n    # The name of the state file.\n    STATE_PATH = UTILS + \"/state\"\n    # The name of the components file.\n    COMPONENTS_PATH = UTILS + \"/components\"\n    # The name of the contexts file.\n    CONTEXTS_PATH = UTILS + \"/context\"\n    # The name of the output directory.\n    BUILD_DIR = \"build\"\n    # The name of the static files directory.\n    STATIC = BUILD_DIR + \"/client\"\n    # The name of the public html directory served at \"/\"\n    PUBLIC = \"public\"\n    # The directory where styles are located.\n    STYLES = \"styles\"\n    # The name of the pages directory.\n    PAGES = \"app\"\n    # The name of the routes directory.\n    ROUTES = \"routes\"\n    # The name of the env json file.\n    ENV_JSON = \"env.json\"\n    # The name of the reflex json file.\n    REFLEX_JSON = \"reflex.json\"\n    # The name of the postcss config file.\n    POSTCSS_JS = \"postcss.config.js\"\n    # The name of the states directory.\n    STATES = \".states\"\n    # Where compilation artifacts for the backend are stored.\n    BACKEND = \"backend\"\n    # JSON-encoded list of page routes that need to be evaluated on the backend.\n    STATEFUL_PAGES = \"stateful_pages.json\"\n    # Marker file indicating that upload component was used in the frontend.\n    UPLOAD_IS_USED = \"upload_is_used\"\n\n\ndef _reflex_version() -> str:\n    \"\"\"Get the Reflex version.\n\n    Returns:\n        The Reflex version.\n    \"\"\"\n    try:\n        return metadata.version(\"reflex\")\n    except metadata.PackageNotFoundError:\n        return \"unknown\"\n\n\nclass Reflex(SimpleNamespace):\n    \"\"\"Base constants concerning Reflex.\"\"\"\n\n    # App names and versions.\n    # The name of the Reflex package.\n    MODULE_NAME = \"reflex\"\n    # The current version of Reflex.\n    VERSION = _reflex_version()\n\n    # The reflex json file.\n    JSON = \"reflex.json\"\n\n    # Files and directories used to init a new project.\n    # The directory to store reflex dependencies.\n    # on windows, we use C:/Users/<username>/AppData/Local/reflex.\n    # on macOS, we use ~/Library/Application Support/reflex.\n    # on linux, we use ~/.local/share/reflex.\n    # If user sets REFLEX_DIR envroment variable use that instead.\n    DIR = PlatformDirs(MODULE_NAME, False).user_data_path\n\n    LOGS_DIR = DIR / \"logs\"\n\n    # The root directory of the reflex library.\n    ROOT_DIR = Path(__file__).parents[2]\n\n    RELEASES_URL = \"https://api.github.com/repos/reflex-dev/templates/releases\"\n\n    # The reflex stylesheet language supported\n    STYLESHEETS_SUPPORTED = [\"css\", \"sass\", \"scss\"]\n\n\nclass ReflexHostingCLI(SimpleNamespace):\n    \"\"\"Base constants concerning Reflex Hosting CLI.\"\"\"\n\n    # The name of the Reflex Hosting CLI package.\n    MODULE_NAME = \"reflex-hosting-cli\"\n\n\nclass Templates(SimpleNamespace):\n    \"\"\"Constants related to Templates.\"\"\"\n\n    # The default template\n    DEFAULT = \"blank\"\n\n    # The AI template\n    AI = \"ai\"\n\n    # The option for the user to choose a remote template.\n    CHOOSE_TEMPLATES = \"choose-templates\"\n\n    # The URL to find reflex templates.\n    REFLEX_TEMPLATES_URL = (\n        \"https://reflex.dev/docs/getting-started/open-source-templates/\"\n    )\n\n    # The reflex.build frontend host\n    REFLEX_BUILD_FRONTEND = \"https://build.reflex.dev\"\n\n    # The reflex.build frontend with referrer\n    REFLEX_BUILD_FRONTEND_WITH_REFERRER = (\n        f\"{REFLEX_BUILD_FRONTEND}/?utm_source=reflex_cli\"\n    )\n\n    class Dirs(SimpleNamespace):\n        \"\"\"Folders used by the template system of Reflex.\"\"\"\n\n        # The template directory used during reflex init.\n        BASE = Reflex.ROOT_DIR / Reflex.MODULE_NAME / \".templates\"\n        # The web subdirectory of the template directory.\n        WEB_TEMPLATE = BASE / \"web\"\n        # Where the code for the templates is stored.\n        CODE = \"code\"\n\n\nclass Javascript(SimpleNamespace):\n    \"\"\"Constants related to Javascript.\"\"\"\n\n    # The node modules directory.\n    NODE_MODULES = \"node_modules\"\n\n\nclass ReactRouter(Javascript):\n    \"\"\"Constants related to React Router.\"\"\"\n\n    # The react router config file\n    CONFIG_FILE = \"react-router.config.js\"\n\n    # The associated Vite config file\n    VITE_CONFIG_FILE = \"vite.config.js\"\n\n    # Regex to check for message displayed when frontend comes up\n    DEV_FRONTEND_LISTENING_REGEX = r\"Local:[\\s]+\"\n\n    # Regex to pattern the route path in the config file\n    # INFO  Accepting connections at http://localhost:3000\n    PROD_FRONTEND_LISTENING_REGEX = r\"Accepting connections at[\\s]+\"\n\n    FRONTEND_LISTENING_REGEX = (\n        rf\"(?:{DEV_FRONTEND_LISTENING_REGEX}|{PROD_FRONTEND_LISTENING_REGEX})(.*)\"\n    )\n\n    SPA_FALLBACK = \"__spa-fallback.html\"\n\n\n# Color mode variables\nclass ColorMode(SimpleNamespace):\n    \"\"\"Constants related to ColorMode.\"\"\"\n\n    NAME = \"rawColorMode\"\n    RESOLVED_NAME = \"resolvedColorMode\"\n    USE = \"useColorMode\"\n    TOGGLE = \"toggleColorMode\"\n    SET = \"setColorMode\"\n\n\nLITERAL_ENV = Literal[\"dev\", \"prod\"]\n\n\n# Env modes\nclass Env(str, Enum):\n    \"\"\"The environment modes.\"\"\"\n\n    DEV = \"dev\"\n    PROD = \"prod\"\n\n\n# Log levels\nclass LogLevel(str, Enum):\n    \"\"\"The log levels.\"\"\"\n\n    DEBUG = \"debug\"\n    DEFAULT = \"default\"\n    INFO = \"info\"\n    WARNING = \"warning\"\n    ERROR = \"error\"\n    CRITICAL = \"critical\"\n\n    @classmethod\n    def from_string(cls, level: str | None) -> LogLevel | None:\n        \"\"\"Convert a string to a log level.\n\n        Args:\n            level: The log level as a string.\n\n        Returns:\n            The log level.\n        \"\"\"\n        if not level:\n            return None\n        try:\n            return LogLevel[level.upper()]\n        except KeyError:\n            return None\n\n    def __le__(self, other: LogLevel) -> bool:\n        \"\"\"Compare log levels.\n\n        Args:\n            other: The other log level.\n\n        Returns:\n            True if the log level is less than or equal to the other log level.\n        \"\"\"\n        levels = list(LogLevel)\n        return levels.index(self) <= levels.index(other)\n\n    def subprocess_level(self):\n        \"\"\"Return the log level for the subprocess.\n\n        Returns:\n            The log level for the subprocess\n        \"\"\"\n        return self if self != LogLevel.DEFAULT else LogLevel.WARNING\n\n\n# Server socket configuration variables\nPOLLING_MAX_HTTP_BUFFER_SIZE = 1000 * 1000\n\n\nclass Ping(SimpleNamespace):\n    \"\"\"PING constants.\"\"\"\n\n    # The 'ping' interval\n    INTERVAL = 25\n    # The 'ping' timeout\n    TIMEOUT = 120\n\n\n# Keys in the client_side_storage dict\nCOOKIES = \"cookies\"\nLOCAL_STORAGE = \"local_storage\"\nSESSION_STORAGE = \"session_storage\"\n\n# Testing variables.\n# Testing os env set by pytest when running a test case.\nPYTEST_CURRENT_TEST = \"PYTEST_CURRENT_TEST\"\nAPP_HARNESS_FLAG = \"APP_HARNESS_FLAG\"\n\nREFLEX_VAR_OPENING_TAG = \"<reflex.Var>\"\nREFLEX_VAR_CLOSING_TAG = \"</reflex.Var>\"\n"
  },
  {
    "path": "reflex/constants/colors.py",
    "content": "\"\"\"The colors used in Reflex are a wrapper around https://www.radix-ui.com/colors.\"\"\"\n\nfrom __future__ import annotations\n\nfrom dataclasses import dataclass\nfrom typing import TYPE_CHECKING, Literal, get_args\n\nif TYPE_CHECKING:\n    from reflex.vars import Var\n\nColorType = Literal[\n    \"gray\",\n    \"mauve\",\n    \"slate\",\n    \"sage\",\n    \"olive\",\n    \"sand\",\n    \"tomato\",\n    \"red\",\n    \"ruby\",\n    \"crimson\",\n    \"pink\",\n    \"plum\",\n    \"purple\",\n    \"violet\",\n    \"iris\",\n    \"indigo\",\n    \"blue\",\n    \"cyan\",\n    \"teal\",\n    \"jade\",\n    \"green\",\n    \"grass\",\n    \"brown\",\n    \"orange\",\n    \"sky\",\n    \"mint\",\n    \"lime\",\n    \"yellow\",\n    \"amber\",\n    \"gold\",\n    \"bronze\",\n    \"accent\",\n    \"black\",\n    \"white\",\n]\n\nCOLORS = frozenset(get_args(ColorType))\n\nShadeType = Literal[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]\nMIN_SHADE_VALUE = 1\nMAX_SHADE_VALUE = 12\n\n\ndef format_color(\n    color: ColorType | Var[str], shade: ShadeType | Var[int], alpha: bool | Var[bool]\n) -> str:\n    \"\"\"Format a color as a CSS color string.\n\n    Args:\n        color: The color to use.\n        shade: The shade of the color to use.\n        alpha: Whether to use the alpha variant of the color.\n\n    Returns:\n        The formatted color.\n    \"\"\"\n    if isinstance(alpha, bool):\n        return f\"var(--{color}-{'a' if alpha else ''}{shade})\"\n\n    from reflex.components.core import cond\n\n    alpha_var = cond(alpha, \"a\", \"\")\n    return f\"var(--{color}-{alpha_var}{shade})\"\n\n\n@dataclass\nclass Color:\n    \"\"\"A color in the Reflex color palette.\"\"\"\n\n    # The color palette to use\n    color: ColorType | Var[str]\n\n    # The shade of the color to use\n    shade: ShadeType | Var[int] = 7\n\n    # Whether to use the alpha variant of the color\n    alpha: bool | Var[bool] = False\n\n    def __format__(self, format_spec: str) -> str:\n        \"\"\"Format the color as a CSS color string.\n\n        Args:\n            format_spec: The format specifier to use.\n\n        Returns:\n            The formatted color.\n        \"\"\"\n        return format_color(self.color, self.shade, self.alpha)\n"
  },
  {
    "path": "reflex/constants/compiler.py",
    "content": "\"\"\"Compiler variables.\"\"\"\n\nimport dataclasses\nimport enum\nfrom enum import Enum\nfrom types import SimpleNamespace\n\nfrom reflex.constants import Dirs\nfrom reflex.utils.imports import ImportVar\n\n# The prefix used to create setters for state vars.\nSETTER_PREFIX = \"set_\"\n\n# The file used to specify no compilation.\nNOCOMPILE_FILE = \"nocompile\"\n\n\nclass Ext(SimpleNamespace):\n    \"\"\"Extension used in Reflex.\"\"\"\n\n    # The extension for JS files.\n    JS = \".js\"\n    # The extension for JSX files.\n    JSX = \".jsx\"\n    # The extension for python files.\n    PY = \".py\"\n    # The extension for css files.\n    CSS = \".css\"\n    # The extension for zip files.\n    ZIP = \".zip\"\n    # The extension for executable files on Windows.\n    EXE = \".exe\"\n    # The extension for markdown files.\n    MD = \".md\"\n\n\nclass CompileVars(SimpleNamespace):\n    \"\"\"The variables used during compilation.\"\"\"\n\n    # The expected variable name where the rx.App is stored.\n    APP = \"app\"\n    # The expected variable name where the API object is stored for deployment.\n    API = \"api\"\n    # The name of the router variable.\n    ROUTER = \"router\"\n    # The name of the socket variable.\n    SOCKET = \"socket\"\n    # The name of the variable to hold API results.\n    RESULT = \"result\"\n    # The name of the final variable.\n    FINAL = \"final\"\n    # The name of the process variable.\n    PROCESSING = \"processing\"\n    # The name of the state variable.\n    STATE = \"state\"\n    # The name of the events variable.\n    EVENTS = \"events\"\n    # The name of the initial hydrate event.\n    HYDRATE = \"hydrate\"\n    # The name of the is_hydrated variable.\n    IS_HYDRATED = \"is_hydrated\"\n    # The name of the function to add events to the queue.\n    ADD_EVENTS = \"addEvents\"\n    # The name of the var storing any connection error.\n    CONNECT_ERROR = \"connectErrors\"\n    # The name of the function for converting a dict to an event.\n    TO_EVENT = \"ReflexEvent\"\n    # The name of the internal on_load event.\n    ON_LOAD_INTERNAL = \"reflex___state____on_load_internal_state.on_load_internal\"\n    # The name of the internal event to update generic state vars.\n    UPDATE_VARS_INTERNAL = (\n        \"reflex___state____update_vars_internal_state.update_vars_internal\"\n    )\n    # The name of the frontend event exception state\n    FRONTEND_EXCEPTION_STATE = \"reflex___state____frontend_event_exception_state\"\n    # The full name of the frontend exception state\n    FRONTEND_EXCEPTION_STATE_FULL = (\n        f\"reflex___state____state.{FRONTEND_EXCEPTION_STATE}\"\n    )\n\n\nclass PageNames(SimpleNamespace):\n    \"\"\"The name of basic pages deployed in the frontend.\"\"\"\n\n    # The name of the index page.\n    INDEX_ROUTE = \"index\"\n    # The name of the app root page.\n    APP_ROOT = \"root.jsx\"\n    # The root stylesheet filename.\n    STYLESHEET_ROOT = \"__reflex_global_styles\"\n    # The name of the document root page.\n    DOCUMENT_ROOT = \"_document.js\"\n    # The name of the theme page.\n    THEME = \"theme\"\n    # The module containing components.\n    COMPONENTS = \"components\"\n    # The module containing shared stateful components\n    STATEFUL_COMPONENTS = \"stateful_components\"\n\n\nclass ComponentName(Enum):\n    \"\"\"Component names.\"\"\"\n\n    BACKEND = \"Backend\"\n    FRONTEND = \"Frontend\"\n\n    def zip(self):\n        \"\"\"Give the zip filename for the component.\n\n        Returns:\n            The lower-case filename with zip extension.\n        \"\"\"\n        return self.value.lower() + Ext.ZIP\n\n\nclass CompileContext(str, Enum):\n    \"\"\"The context in which the compiler is running.\"\"\"\n\n    RUN = \"run\"\n    EXPORT = \"export\"\n    DEPLOY = \"deploy\"\n    UNDEFINED = \"undefined\"\n\n\nclass Imports(SimpleNamespace):\n    \"\"\"Common sets of import vars.\"\"\"\n\n    EVENTS = {\n        \"react\": [ImportVar(tag=\"useContext\")],\n        f\"$/{Dirs.CONTEXTS_PATH}\": [ImportVar(tag=\"EventLoopContext\")],\n        f\"$/{Dirs.STATE_PATH}\": [ImportVar(tag=CompileVars.TO_EVENT)],\n    }\n\n\nclass Hooks(SimpleNamespace):\n    \"\"\"Common sets of hook declarations.\"\"\"\n\n    EVENTS = f\"const [{CompileVars.ADD_EVENTS}, {CompileVars.CONNECT_ERROR}] = useContext(EventLoopContext);\"\n\n    class HookPosition(enum.Enum):\n        \"\"\"The position of the hook in the component.\"\"\"\n\n        INTERNAL = \"internal\"\n        PRE_TRIGGER = \"pre_trigger\"\n        POST_TRIGGER = \"post_trigger\"\n\n\nclass MemoizationDisposition(enum.Enum):\n    \"\"\"The conditions under which a component should be memoized.\"\"\"\n\n    # If the component uses state or events, it should be memoized.\n    STATEFUL = \"stateful\"\n    ALWAYS = \"always\"\n    NEVER = \"never\"\n\n\n@dataclasses.dataclass(frozen=True)\nclass MemoizationMode:\n    \"\"\"The mode for memoizing a Component.\"\"\"\n\n    # The conditions under which the component should be memoized.\n    disposition: MemoizationDisposition = MemoizationDisposition.STATEFUL\n\n    # Whether children of this component should be memoized first.\n    recursive: bool = True\n\n\nDATA_UNDERSCORE = \"data_\"\nDATA_DASH = \"data-\"\nARIA_UNDERSCORE = \"aria_\"\nARIA_DASH = \"aria-\"\n\nSPECIAL_ATTRS = (\n    DATA_UNDERSCORE,\n    DATA_DASH,\n    ARIA_UNDERSCORE,\n    ARIA_DASH,\n)\n\n\nclass SpecialAttributes(enum.Enum):\n    \"\"\"Special attributes for components.\n\n    These are placed in custom_attrs and rendered as-is rather than converting\n    to a style prop.\n    \"\"\"\n\n    @classmethod\n    def is_special(cls, attr: str) -> bool:\n        \"\"\"Check if the attribute is special.\n\n        Args:\n            attr: the attribute to check\n\n        Returns:\n            True if the attribute is special.\n        \"\"\"\n        return attr.startswith(SPECIAL_ATTRS)\n\n\nclass ResetStylesheet(SimpleNamespace):\n    \"\"\"Constants for CSS reset stylesheet.\"\"\"\n\n    # The filename of the CSS reset file.\n    FILENAME = \"__reflex_style_reset.css\"\n"
  },
  {
    "path": "reflex/constants/config.py",
    "content": "\"\"\"Config constants.\"\"\"\n\nfrom pathlib import Path\nfrom types import SimpleNamespace\n\nfrom reflex.constants.base import Dirs, Reflex\n\nfrom .compiler import Ext\n\n# Alembic migrations\nALEMBIC_CONFIG = \"alembic.ini\"\n\n\nclass Config(SimpleNamespace):\n    \"\"\"Config constants.\"\"\"\n\n    # The name of the reflex config module.\n    MODULE = \"rxconfig\"\n    # The python config file.\n    FILE = Path(f\"{MODULE}{Ext.PY}\")\n\n\nclass Expiration(SimpleNamespace):\n    \"\"\"Expiration constants.\"\"\"\n\n    # Token expiration time in seconds\n    TOKEN = 60 * 60\n    # Maximum time in milliseconds that a state can be locked for exclusive access.\n    LOCK = 10000\n    # The PING timeout\n    PING = 120\n    # The maximum time in milliseconds to hold a lock before throwing a warning.\n    LOCK_WARNING_THRESHOLD = 1000\n\n\nclass GitIgnore(SimpleNamespace):\n    \"\"\"Gitignore constants.\"\"\"\n\n    # The gitignore file.\n    FILE = Path(\".gitignore\")\n    # Files to gitignore.\n    DEFAULTS = {\n        Dirs.WEB,\n        Dirs.STATES,\n        \"*.db\",\n        \"__pycache__/\",\n        \"*.py[cod]\",\n        \"assets/external/\",\n    }\n\n\nclass PyprojectToml(SimpleNamespace):\n    \"\"\"Pyproject.toml constants.\"\"\"\n\n    # The pyproject.toml file.\n    FILE = \"pyproject.toml\"\n\n\nclass RequirementsTxt(SimpleNamespace):\n    \"\"\"Requirements.txt constants.\"\"\"\n\n    # The requirements.txt file.\n    FILE = \"requirements.txt\"\n    # The partial text used to form requirement that pins a reflex version\n    DEFAULTS_STUB = f\"{Reflex.MODULE_NAME}==\"\n\n\nclass DefaultPorts(SimpleNamespace):\n    \"\"\"Default port constants.\"\"\"\n\n    FRONTEND_PORT = 3000\n    BACKEND_PORT = 8000\n\n\n# The deployment URL.\nPRODUCTION_BACKEND_URL = \"https://{username}-{app_name}.api.pynecone.app\"\n"
  },
  {
    "path": "reflex/constants/custom_components.py",
    "content": "\"\"\"Constants for the custom components.\"\"\"\n\nfrom __future__ import annotations\n\nfrom pathlib import Path\nfrom types import SimpleNamespace\n\n\nclass CustomComponents(SimpleNamespace):\n    \"\"\"Constants for the custom components.\"\"\"\n\n    # The name of the custom components source directory.\n    SRC_DIR = Path(\"custom_components\")\n    # The name of the custom components pyproject.toml file.\n    PYPROJECT_TOML = Path(\"pyproject.toml\")\n    # The name of the custom components package README file.\n    PACKAGE_README = Path(\"README.md\")\n    # The name of the custom components package .gitignore file.\n    PACKAGE_GITIGNORE = \".gitignore\"\n    # The name of the distribution directory as result of a build.\n    DIST_DIR = \"dist\"\n    # The name of the init file.\n    INIT_FILE = \"__init__.py\"\n    # Suffixes for the distribution files.\n    DISTRIBUTION_FILE_SUFFIXES = [\".tar.gz\", \".whl\"]\n    # The name to the URL of python package repositories.\n    REPO_URLS = {\n        # Note: the trailing slash is required for below URLs.\n        \"pypi\": \"https://upload.pypi.org/legacy/\",\n        \"testpypi\": \"https://test.pypi.org/legacy/\",\n    }\n    # The .gitignore file for the custom component project.\n    FILE = Path(\".gitignore\")\n    # Files to gitignore.\n    DEFAULTS = {\"__pycache__/\", \"*.py[cod]\", \"*.egg-info/\", \"dist/\"}\n"
  },
  {
    "path": "reflex/constants/event.py",
    "content": "\"\"\"Event-related constants.\"\"\"\n\nfrom enum import Enum\nfrom types import SimpleNamespace\n\n\nclass Endpoint(Enum):\n    \"\"\"Endpoints for the reflex backend API.\"\"\"\n\n    PING = \"ping\"\n    EVENT = \"_event\"\n    UPLOAD = \"_upload\"\n    AUTH_CODESPACE = \"auth-codespace\"\n    HEALTH = \"_health\"\n    ALL_ROUTES = \"_all_routes\"\n\n    def __str__(self) -> str:\n        \"\"\"Get the string representation of the endpoint.\n\n        Returns:\n            The path for the endpoint.\n        \"\"\"\n        return f\"/{self.value}\"\n\n    def get_url(self) -> str:\n        \"\"\"Get the URL for the endpoint.\n\n        Returns:\n            The full URL for the endpoint.\n        \"\"\"\n        # Import here to avoid circular imports.\n        from reflex.config import get_config\n\n        # Get the API URL from the config.\n        config = get_config()\n        url = \"\".join([config.api_url, str(self)])\n\n        # The event endpoint is a websocket.\n        if self == Endpoint.EVENT:\n            # Replace the protocol with ws.\n            url = url.replace(\"https://\", \"wss://\").replace(\"http://\", \"ws://\")\n\n        # Return the url.\n        return url\n\n\nclass SocketEvent(SimpleNamespace):\n    \"\"\"Socket events sent by the reflex backend API.\"\"\"\n\n    PING = \"ping\"\n    EVENT = \"event\"\n\n    def __str__(self) -> str:\n        \"\"\"Get the string representation of the event name.\n\n        Returns:\n            The event name string.\n        \"\"\"\n        return str(self.value)\n\n\nclass EventTriggers(SimpleNamespace):\n    \"\"\"All trigger names used in Reflex.\"\"\"\n\n    ON_FOCUS = \"on_focus\"\n    ON_BLUR = \"on_blur\"\n    ON_CANCEL = \"on_cancel\"\n    ON_CLICK = \"on_click\"\n    ON_CHANGE = \"on_change\"\n    ON_CHANGE_END = \"on_change_end\"\n    ON_CHANGE_START = \"on_change_start\"\n    ON_COMPLETE = \"on_complete\"\n    ON_CONTEXT_MENU = \"on_context_menu\"\n    ON_DOUBLE_CLICK = \"on_double_click\"\n    ON_DROP = \"on_drop\"\n    ON_EDIT = \"on_edit\"\n    ON_KEY_DOWN = \"on_key_down\"\n    ON_KEY_UP = \"on_key_up\"\n    ON_MOUSE_DOWN = \"on_mouse_down\"\n    ON_MOUSE_ENTER = \"on_mouse_enter\"\n    ON_MOUSE_LEAVE = \"on_mouse_leave\"\n    ON_MOUSE_MOVE = \"on_mouse_move\"\n    ON_MOUSE_OUT = \"on_mouse_out\"\n    ON_MOUSE_OVER = \"on_mouse_over\"\n    ON_MOUSE_UP = \"on_mouse_up\"\n    ON_OPEN_CHANGE = \"on_open_change\"\n    ON_OPEN_AUTO_FOCUS = \"on_open_auto_focus\"\n    ON_CLOSE_AUTO_FOCUS = \"on_close_auto_focus\"\n    ON_FOCUS_OUTSIDE = \"on_focus_outside\"\n    ON_ESCAPE_KEY_DOWN = \"on_escape_key_down\"\n    ON_POINTER_DOWN_OUTSIDE = \"on_pointer_down_outside\"\n    ON_INTERACT_OUTSIDE = \"on_interact_outside\"\n    ON_SCROLL = \"on_scroll\"\n    ON_SCROLL_END = \"on_scroll_end\"\n    ON_SUBMIT = \"on_submit\"\n    ON_MOUNT = \"on_mount\"\n    ON_UNMOUNT = \"on_unmount\"\n    ON_CLEAR_SERVER_ERRORS = \"on_clear_server_errors\"\n    ON_VALUE_COMMIT = \"on_value_commit\"\n    ON_SELECT = \"on_select\"\n    ON_ANIMATION_START = \"on_animation_start\"\n    ON_ANIMATION_END = \"on_animation_end\"\n"
  },
  {
    "path": "reflex/constants/installer.py",
    "content": "\"\"\"File for constants related to the installation process. (Bun/Node).\"\"\"\n\nfrom __future__ import annotations\n\nimport os\nfrom types import SimpleNamespace\n\nfrom .base import IS_WINDOWS\nfrom .utils import classproperty\n\n\n# Bun config.\nclass Bun(SimpleNamespace):\n    \"\"\"Bun constants.\"\"\"\n\n    # The Bun version.\n    VERSION = \"1.3.10\"\n\n    # Min Bun Version\n    MIN_VERSION = \"1.3.0\"\n\n    # URL to bun install script.\n    INSTALL_URL = \"https://raw.githubusercontent.com/reflex-dev/reflex/main/scripts/bun_install.sh\"\n\n    # URL to windows install script.\n    WINDOWS_INSTALL_URL = (\n        \"https://raw.githubusercontent.com/reflex-dev/reflex/main/scripts/install.ps1\"\n    )\n\n    # Path of the bunfig file\n    CONFIG_PATH = \"bunfig.toml\"\n\n    @classproperty\n    @classmethod\n    def ROOT_PATH(cls):\n        \"\"\"The directory to store the bun.\n\n        Returns:\n            The directory to store the bun.\n        \"\"\"\n        from reflex.environment import environment\n\n        return environment.REFLEX_DIR.get() / \"bun\"\n\n    @classproperty\n    @classmethod\n    def DEFAULT_PATH(cls):\n        \"\"\"Default bun path.\n\n        Returns:\n            The default bun path.\n        \"\"\"\n        return cls.ROOT_PATH / \"bin\" / (\"bun\" if not IS_WINDOWS else \"bun.exe\")\n\n    DEFAULT_CONFIG = \"\"\"\n[install]\nregistry = \"{registry}\"\n\"\"\"\n\n\n# Node / NPM config\nclass Node(SimpleNamespace):\n    \"\"\"Node/ NPM constants.\"\"\"\n\n    # The minimum required node version.\n    MIN_VERSION = \"20.19.0\"\n\n    # Path of the node config file.\n    CONFIG_PATH = \".npmrc\"\n\n    DEFAULT_CONFIG = \"\"\"\nregistry={registry}\nfetch-retries=0\n\"\"\"\n\n\ndef _determine_react_router_version() -> str:\n    default_version = \"7.13.1\"\n    if (version := os.getenv(\"REACT_ROUTER_VERSION\")) and version != default_version:\n        from reflex.utils import console\n\n        console.warn(\n            f\"You have requested react-router@{version} but the supported version is {default_version}, abandon all hope ye who enter here.\"\n        )\n        return version\n    return default_version\n\n\ndef _determine_react_version() -> str:\n    default_version = \"19.2.4\"\n    if (version := os.getenv(\"REACT_VERSION\")) and version != default_version:\n        from reflex.utils import console\n\n        console.warn(\n            f\"You have requested react@{version} but the supported version is {default_version}, abandon all hope ye who enter here.\"\n        )\n        return version\n    return default_version\n\n\nclass PackageJson(SimpleNamespace):\n    \"\"\"Constants used to build the package.json file.\"\"\"\n\n    class Commands(SimpleNamespace):\n        \"\"\"The commands to define in package.json.\"\"\"\n\n        DEV = \"react-router dev --host\"\n        EXPORT = \"react-router build\"\n\n        @staticmethod\n        def get_prod_command(frontend_path: str = \"\") -> str:\n            \"\"\"Get the prod command with the correct 404.html path for the given frontend_path.\n\n            Args:\n                frontend_path: The frontend path prefix (e.g. \"/app\").\n\n            Returns:\n                The sirv command with the correct --single fallback path.\n            \"\"\"\n            stripped = frontend_path.strip(\"/\")\n            fallback = f\"{stripped}/404.html\" if stripped else \"404.html\"\n            return f\"sirv ./build/client --single {fallback} --host\"\n\n    PATH = \"package.json\"\n\n    _react_version = _determine_react_version()\n\n    _react_router_version = _determine_react_router_version()\n\n    @classproperty\n    @classmethod\n    def DEPENDENCIES(cls) -> dict[str, str]:\n        \"\"\"The dependencies to include in package.json.\n\n        Returns:\n            A dictionary of dependencies with their versions.\n        \"\"\"\n        return {\n            \"json5\": \"2.2.3\",\n            \"react-router\": cls._react_router_version,\n            \"react-router-dom\": cls._react_router_version,\n            \"@react-router/node\": cls._react_router_version,\n            \"sirv-cli\": \"3.0.1\",\n            \"react\": cls._react_version,\n            \"react-helmet\": \"6.1.0\",\n            \"react-dom\": cls._react_version,\n            \"isbot\": \"5.1.36\",\n            \"socket.io-client\": \"4.8.3\",\n            \"universal-cookie\": \"7.2.2\",\n        }\n\n    DEV_DEPENDENCIES = {\n        \"@emotion/react\": \"11.14.0\",\n        \"autoprefixer\": \"10.4.27\",\n        \"postcss\": \"8.5.8\",\n        \"postcss-import\": \"16.1.1\",\n        \"@react-router/dev\": _react_router_version,\n        \"@react-router/fs-routes\": _react_router_version,\n        \"vite\": \"8.0.0\",\n    }\n    OVERRIDES = {\n        # This should always match the `react` version in DEPENDENCIES for recharts compatibility.\n        \"react-is\": _react_version,\n        \"cookie\": \"1.1.1\",\n    }\n"
  },
  {
    "path": "reflex/constants/route.py",
    "content": "\"\"\"Route constants.\"\"\"\n\nimport re\nfrom types import SimpleNamespace\n\n\nclass RouteArgType(SimpleNamespace):\n    \"\"\"Type of dynamic route arg extracted from URI route.\"\"\"\n\n    SINGLE = \"arg_single\"\n    LIST = \"arg_list\"\n\n\n# the name of the backend var containing path and client information\nROUTER = \"router\"\nROUTER_DATA = \"router_data\"\n\n\nclass RouteVar(SimpleNamespace):\n    \"\"\"Names of variables used in the router_data dict stored in State.\"\"\"\n\n    CLIENT_IP = \"ip\"\n    CLIENT_TOKEN = \"token\"\n    HEADERS = \"headers\"\n    PATH = \"pathname\"\n    ORIGIN = \"asPath\"\n    SESSION_ID = \"sid\"\n    QUERY = \"query\"\n    COOKIE = \"cookie\"\n\n\n# This subset of router_data is included in chained on_load events.\nROUTER_DATA_INCLUDE = {RouteVar.PATH, RouteVar.ORIGIN, RouteVar.QUERY}\n\n\nclass RouteRegex(SimpleNamespace):\n    \"\"\"Regex used for extracting route args in route.\"\"\"\n\n    _DOT_DOT_DOT = r\"\\.\\.\\.\"\n    _OPENING_BRACKET = r\"\\[\"\n    _CLOSING_BRACKET = r\"\\]\"\n    _ARG_NAME = r\"[a-zA-Z_]\\w*\"\n\n    # The regex for a valid arg name, e.g. \"slug\" in \"[slug]\"\n    _ARG_NAME_PATTERN = re.compile(_ARG_NAME)\n\n    SLUG = re.compile(r\"[a-zA-Z0-9_-]+\")\n    # match a single arg (i.e. \"[slug]\"), returns the name of the arg\n    ARG = re.compile(rf\"{_OPENING_BRACKET}({_ARG_NAME}){_CLOSING_BRACKET}\")\n    # match a single optional arg (i.e. \"[[slug]]\"), returns the name of the arg\n    OPTIONAL_ARG = re.compile(\n        rf\"{_OPENING_BRACKET * 2}({_ARG_NAME}){_CLOSING_BRACKET * 2}\"\n    )\n\n    # match a single non-optional catch-all arg (i.e. \"[...slug]\"), returns the name of the arg\n    STRICT_CATCHALL = re.compile(\n        rf\"{_OPENING_BRACKET}{_DOT_DOT_DOT}({_ARG_NAME}){_CLOSING_BRACKET}\"\n    )\n\n    # match a single optional catch-all arg (i.e. \"[[...slug]]\"), returns the name of the arg\n    OPTIONAL_CATCHALL = re.compile(\n        rf\"{_OPENING_BRACKET * 2}{_DOT_DOT_DOT}({_ARG_NAME}){_CLOSING_BRACKET * 2}\"\n    )\n\n    SPLAT_CATCHALL = \"[[...splat]]\"\n    SINGLE_SEGMENT = \"__SINGLE_SEGMENT__\"\n    DOUBLE_SEGMENT = \"__DOUBLE_SEGMENT__\"\n    DOUBLE_CATCHALL_SEGMENT = \"__DOUBLE_CATCHALL_SEGMENT__\"\n\n\nclass DefaultPage(SimpleNamespace):\n    \"\"\"Default page constants.\"\"\"\n\n    # The default title to show for Reflex apps.\n    TITLE = \"{} | {}\"\n    # The default description to show for Reflex apps.\n    DESCRIPTION = \"\"\n    # The default image to show for Reflex apps.\n    IMAGE = \"favicon.ico\"\n    # The default meta list to show for Reflex apps.\n    META_LIST = []\n\n\n# 404 variables\nclass Page404(SimpleNamespace):\n    \"\"\"Page 404 constants.\"\"\"\n\n    SLUG = \"404\"\n    TITLE = \"404 - Not Found\"\n    IMAGE = \"favicon.ico\"\n    DESCRIPTION = \"The page was not found\"\n\n\nROUTE_NOT_FOUND = \"routeNotFound\"\n"
  },
  {
    "path": "reflex/constants/state.py",
    "content": "\"\"\"State-related constants.\"\"\"\n\nfrom enum import Enum\n\n\nclass StateManagerMode(str, Enum):\n    \"\"\"State manager constants.\"\"\"\n\n    DISK = \"disk\"\n    MEMORY = \"memory\"\n    REDIS = \"redis\"\n\n\n# Used for things like console_log, etc.\nFRONTEND_EVENT_STATE = \"__reflex_internal_frontend_event_state\"\n\nFIELD_MARKER = \"_rx_state_\"\nMEMO_MARKER = \"_rx_memo_\"\nCAMEL_CASE_MEMO_MARKER = \"RxMemo\"\n"
  },
  {
    "path": "reflex/constants/utils.py",
    "content": "\"\"\"Utility functions for constants.\"\"\"\n\nfrom collections.abc import Callable\nfrom typing import Any, Generic, TypeVar\n\nT = TypeVar(\"T\")\nV = TypeVar(\"V\")\n\n\nclass classproperty(Generic[T, V]):\n    \"\"\"A class property decorator.\"\"\"\n\n    def __init__(self, getter: Callable[[type[T]], V]) -> None:\n        \"\"\"Initialize the class property.\n\n        Args:\n            getter: The getter function.\n        \"\"\"\n        self.getter = getattr(getter, \"__func__\", getter)\n\n    def __get__(self, instance: Any, owner: type[T]) -> V:\n        \"\"\"Get the value of the class property.\n\n        Args:\n            instance: The instance of the class.\n            owner: The class itself.\n\n        Returns:\n            The value of the class property.\n        \"\"\"\n        return self.getter(owner)\n"
  },
  {
    "path": "reflex/custom_components/__init__.py",
    "content": "\"\"\"The Reflex custom components.\"\"\"\n"
  },
  {
    "path": "reflex/custom_components/custom_components.py",
    "content": "\"\"\"CLI for creating custom components.\"\"\"\n\nfrom __future__ import annotations\n\nimport os\nimport re\nimport subprocess\nimport sys\nfrom collections import namedtuple\nfrom contextlib import contextmanager\nfrom pathlib import Path\nfrom typing import Any\n\nimport click\n\nfrom reflex import constants\nfrom reflex.constants import CustomComponents\nfrom reflex.utils import console, frontend_skeleton\n\n\ndef _pyproject_toml_template(\n    package_name: str, module_name: str, reflex_version: str\n) -> str:\n    \"\"\"Template for custom components pyproject.toml.\n\n    Args:\n        package_name: The name of the package.\n        module_name: The name of the module.\n        reflex_version: The version of Reflex.\n\n    Returns:\n        Rendered pyproject.toml content as string.\n    \"\"\"\n    return f\"\"\"[build-system]\nrequires = [\"setuptools\", \"wheel\"]\nbuild-backend = \"setuptools.build_meta\"\n\n[project]\nname = \"{package_name}\"\nversion = \"0.0.1\"\ndescription = \"Reflex custom component {module_name}\"\nreadme = \"README.md\"\nlicense = {{ text = \"Apache-2.0\" }}\nrequires-python = \">=3.10\"\nauthors = [{{ name = \"\", email = \"YOUREMAIL@domain.com\" }}]\nkeywords = [\"reflex\",\"reflex-custom-components\"]\n\ndependencies = [\"reflex>={reflex_version}\"]\n\nclassifiers = [\"Development Status :: 4 - Beta\"]\n\n[project.urls]\n\n[project.optional-dependencies]\ndev = [\"build\", \"twine\"]\n\n[tool.setuptools.packages.find]\nwhere = [\"custom_components\"]\n\"\"\"\n\n\ndef _readme_template(module_name: str, package_name: str) -> str:\n    \"\"\"Template for custom components README.\n\n    Args:\n        module_name: The name of the module.\n        package_name: The name of the package.\n\n    Returns:\n        Rendered README.md content as string.\n    \"\"\"\n    return f\"\"\"# {module_name}\n\nA Reflex custom component {module_name}.\n\n## Installation\n\n```bash\npip install {package_name}\n```\n\"\"\"\n\n\ndef _source_template(component_class_name: str, module_name: str) -> str:\n    \"\"\"Template for custom components source.\n\n    Args:\n        component_class_name: The name of the component class.\n        module_name: The name of the module.\n\n    Returns:\n        Rendered custom component source code as string.\n    \"\"\"\n    return rf'''\n\"\"\"Reflex custom component {component_class_name}.\"\"\"\n\n# For wrapping react guide, visit https://reflex.dev/docs/wrapping-react/overview/\n\nimport reflex as rx\n\n# Some libraries you want to wrap may require dynamic imports.\n# This is because they they may not be compatible with Server-Side Rendering (SSR).\n# To handle this in Reflex, all you need to do is subclass `NoSSRComponent` instead.\n# For example:\n# from reflex.components.component import NoSSRComponent\n# class {component_class_name}(NoSSRComponent):\n#     pass\n\n\nclass {component_class_name}(rx.Component):\n    \"\"\"{component_class_name} component.\"\"\"\n\n    # The React library to wrap.\n    library = \"Fill-Me\"\n\n    # The React component tag.\n    tag = \"Fill-Me\"\n\n    # If the tag is the default export from the module, you must set is_default = True.\n    # This is normally used when components don't have curly braces around them when importing.\n    # is_default = True\n\n    # If you are wrapping another components with the same tag as a component in your project\n    # you can use aliases to differentiate between them and avoid naming conflicts.\n    # alias = \"Other{component_class_name}\"\n\n    # The props of the React component.\n    # Note: when Reflex compiles the component to Javascript,\n    # `snake_case` property names are automatically formatted as `camelCase`.\n    # The prop names may be defined in `camelCase` as well.\n    # some_prop: rx.Var[str] = \"some default value\"\n    # some_other_prop: rx.Var[int] = 1\n\n    # By default Reflex will install the library you have specified in the library property.\n    # However, sometimes you may need to install other libraries to use a component.\n    # In this case you can use the lib_dependencies property to specify other libraries to install.\n    # lib_dependencies: list[str] = []\n\n    # Event triggers declaration if any.\n    # Below is equivalent to merging `{{ \"on_change\": lambda e: [e] }}`\n    # onto the default event triggers of parent/base Component.\n    # The function defined for the `on_change` trigger maps event for the javascript\n    # trigger to what will be passed to the backend event handler function.\n    # on_change: rx.EventHandler[lambda e: [e]]\n\n    # To add custom code to your component\n    # def _get_custom_code(self) -> str:\n    #     return \"const customCode = 'customCode';\"\n\n\n{module_name} = {component_class_name}.create\n'''\n\n\ndef _init_template(module_name: str) -> str:\n    \"\"\"Template for custom components __init__.py.\n\n    Args:\n        module_name: The name of the module.\n\n    Returns:\n        Rendered __init__.py content as string.\n    \"\"\"\n    return f\"from .{module_name} import *\"\n\n\ndef _demo_app_template(custom_component_module_dir: str, module_name: str) -> str:\n    \"\"\"Template for custom components demo app.\n\n    Args:\n        custom_component_module_dir: The directory of the custom component module.\n        module_name: The name of the module.\n\n    Returns:\n        Rendered demo app source code as string.\n    \"\"\"\n    return rf'''\n\"\"\"Welcome to Reflex! This file showcases the custom component in a basic app.\"\"\"\n\nfrom rxconfig import config\n\nimport reflex as rx\n\nfrom {custom_component_module_dir} import {module_name}\n\nfilename = f\"{{config.app_name}}/{{config.app_name}}.py\"\n\n\nclass State(rx.State):\n    \"\"\"The app state.\"\"\"\n    pass\n\ndef index() -> rx.Component:\n    return rx.center(\n        rx.theme_panel(),\n        rx.vstack(\n            rx.heading(\"Welcome to Reflex!\", size=\"9\"),\n            rx.text(\n                \"Test your custom component by editing \",\n                rx.code(filename),\n                font_size=\"2em\",\n            ),\n            {module_name}(),\n            align=\"center\",\n            spacing=\"7\",\n        ),\n        height=\"100vh\",\n    )\n\n\n# Add state and page to the app.\napp = rx.App()\napp.add_page(index)\n'''\n\n\ndef set_loglevel(ctx: Any, self: Any, value: str | None):\n    \"\"\"Set the log level.\n\n    Args:\n        ctx: The click context.\n        self: The click command.\n        value: The log level to set.\n    \"\"\"\n    if value is not None:\n        loglevel = constants.LogLevel.from_string(value)\n        console.set_log_level(loglevel)\n\n\n@click.group\ndef custom_components_cli():\n    \"\"\"CLI for creating custom components.\"\"\"\n\n\nloglevel_option = click.option(\n    \"--loglevel\",\n    type=click.Choice(\n        [loglevel.value for loglevel in constants.LogLevel],\n        case_sensitive=False,\n    ),\n    callback=set_loglevel,\n    is_eager=True,\n    expose_value=False,\n    help=\"The log level to use.\",\n)\n\nPOST_CUSTOM_COMPONENTS_GALLERY_TIMEOUT = 15\n\n\n@contextmanager\ndef set_directory(working_directory: str | Path):\n    \"\"\"Context manager that sets the working directory.\n\n    Args:\n        working_directory: The working directory to change to.\n\n    Yields:\n        Yield to the caller to perform operations in the working directory.\n    \"\"\"\n    current_directory = Path.cwd()\n    working_directory = Path(working_directory)\n    try:\n        os.chdir(working_directory)\n        yield\n    finally:\n        os.chdir(current_directory)\n\n\ndef _create_package_config(module_name: str, package_name: str):\n    \"\"\"Create a package config pyproject.toml file.\n\n    Args:\n        module_name: The name of the module.\n        package_name: The name of the package typically constructed with `reflex-` prefix and a meaningful library name.\n    \"\"\"\n    pyproject = Path(CustomComponents.PYPROJECT_TOML)\n    pyproject.write_text(\n        _pyproject_toml_template(\n            module_name=module_name,\n            package_name=package_name,\n            reflex_version=constants.Reflex.VERSION,\n        )\n    )\n\n\ndef _create_readme(module_name: str, package_name: str):\n    \"\"\"Create a package README file.\n\n    Args:\n        module_name: The name of the module.\n        package_name: The name of the python package to be published.\n    \"\"\"\n    readme = Path(CustomComponents.PACKAGE_README)\n    readme.write_text(\n        _readme_template(\n            module_name=module_name,\n            package_name=package_name,\n        )\n    )\n\n\ndef _write_source_and_init_py(\n    custom_component_src_dir: Path,\n    component_class_name: str,\n    module_name: str,\n):\n    \"\"\"Write the source code and init file from templates for the custom component.\n\n    Args:\n        custom_component_src_dir: The name of the custom component source directory.\n        component_class_name: The name of the component class.\n        module_name: The name of the module.\n    \"\"\"\n    module_path = custom_component_src_dir / f\"{module_name}.py\"\n    module_path.write_text(\n        _source_template(\n            component_class_name=component_class_name, module_name=module_name\n        )\n    )\n\n    init_path = custom_component_src_dir / CustomComponents.INIT_FILE\n    init_path.write_text(_init_template(module_name=module_name))\n\n\ndef _populate_demo_app(name_variants: NameVariants):\n    \"\"\"Populate the demo app that imports the custom components.\n\n    Args:\n        name_variants: the tuple including various names such as package name, class name needed for the project.\n    \"\"\"\n    from reflex import constants\n    from reflex.reflex import _init\n\n    demo_app_dir = Path(name_variants.demo_app_dir)\n    demo_app_name = name_variants.demo_app_name\n\n    console.info(f\"Creating app for testing: {demo_app_dir!s}\")\n\n    demo_app_dir.mkdir(exist_ok=True)\n\n    with set_directory(demo_app_dir):\n        # We start with the blank template as basis.\n        _init(name=demo_app_name, template=constants.Templates.DEFAULT)\n        # Then overwrite the app source file with the one we want for testing custom components.\n        # This source file is rendered using template file.\n        demo_file = Path(f\"{demo_app_name}/{demo_app_name}.py\")\n        demo_file.write_text(\n            _demo_app_template(\n                custom_component_module_dir=name_variants.custom_component_module_dir,\n                module_name=name_variants.module_name,\n            )\n        )\n        # Append the custom component package to the requirements.txt file.\n        with Path(f\"{constants.RequirementsTxt.FILE}\").open(mode=\"a\") as f:\n            f.write(f\"{name_variants.package_name}\\n\")\n\n\ndef _get_default_library_name_parts() -> list[str]:\n    \"\"\"Get the default library name. Based on the current directory name, remove any non-alphanumeric characters.\n\n    Returns:\n        The parts of default library name.\n\n    Raises:\n        SystemExit: If the current directory name is not suitable for python projects, and we cannot find a valid library name based off it.\n    \"\"\"\n    current_dir_name = Path.cwd().name\n\n    cleaned_dir_name = re.sub(r\"[^0-9a-zA-Z-_]+\", \"\", current_dir_name).lower()\n    parts = [part for part in re.split(r\"-|_\", cleaned_dir_name) if part]\n    if parts and parts[0] == constants.Reflex.MODULE_NAME:\n        # If the directory name already starts with \"reflex\", remove it from the parts.\n        parts = parts[1:]\n        # If no parts left, cannot find a valid library name, exit.\n        if not parts:\n            # The folder likely has a name not suitable for python paths.\n            console.error(\n                f\"Based on current directory name {current_dir_name}, the library name is {constants.Reflex.MODULE_NAME}. This package already exists. Please use --library-name to specify a different name.\"\n            )\n            raise SystemExit(1)\n    if not parts:\n        # The folder likely has a name not suitable for python paths.\n        console.error(\n            f\"Could not find a valid library name based on the current directory: got {current_dir_name}.\"\n        )\n        raise SystemExit(1)\n    return parts\n\n\nNameVariants = namedtuple(\n    \"NameVariants\",\n    [\n        \"library_name\",\n        \"component_class_name\",\n        \"package_name\",\n        \"module_name\",\n        \"custom_component_module_dir\",\n        \"demo_app_dir\",\n        \"demo_app_name\",\n    ],\n)\n\n\ndef _validate_library_name(library_name: str | None) -> NameVariants:\n    \"\"\"Validate the library name.\n\n    Args:\n        library_name: The name of the library if picked otherwise None.\n\n    Returns:\n        A tuple containing the various names such as package name, class name, etc., needed for the project.\n\n    Raises:\n        SystemExit: If the library name is not suitable for python projects.\n    \"\"\"\n    if library_name is not None and not re.match(\n        r\"^[a-zA-Z-]+[a-zA-Z0-9-]*$\", library_name\n    ):\n        console.error(\n            f\"Please use only alphanumeric characters or dashes: got {library_name}\"\n        )\n        raise SystemExit(1)\n\n    # If not specified, use the current directory name to form the module name.\n    name_parts = (\n        [part.lower() for part in library_name.split(\"-\")]\n        if library_name\n        else _get_default_library_name_parts()\n    )\n    if not library_name:\n        library_name = \"-\".join(name_parts)\n\n    # Component class name is the camel case.\n    component_class_name = \"\".join([part.capitalize() for part in name_parts])\n    console.debug(f\"Component class name: {component_class_name}\")\n\n    # Package name is commonly kebab case.\n    package_name = f\"reflex-{library_name}\"\n    console.debug(f\"Package name: {package_name}\")\n\n    # Module name is the snake case.\n    module_name = \"_\".join(name_parts)\n\n    custom_component_module_dir = Path(f\"reflex_{module_name}\")\n    console.debug(f\"Custom component source directory: {custom_component_module_dir}\")\n\n    # Use the same name for the directory and the app.\n    demo_app_dir = demo_app_name = f\"{module_name}_demo\"\n    console.debug(f\"Demo app directory: {demo_app_dir}\")\n\n    return NameVariants(\n        library_name=library_name,\n        component_class_name=component_class_name,\n        package_name=package_name,\n        module_name=module_name,\n        custom_component_module_dir=custom_component_module_dir,\n        demo_app_dir=demo_app_dir,\n        demo_app_name=demo_app_name,\n    )\n\n\ndef _populate_custom_component_project(name_variants: NameVariants):\n    \"\"\"Populate the custom component source directory. This includes the pyproject.toml, README.md, and the code template for the custom component.\n\n    Args:\n        name_variants: the tuple including various names such as package name, class name needed for the project.\n    \"\"\"\n    console.info(\n        f\"Populating pyproject.toml with package name: {name_variants.package_name}\"\n    )\n    # write pyproject.toml, README.md, etc.\n    _create_package_config(\n        module_name=name_variants.library_name, package_name=name_variants.package_name\n    )\n    _create_readme(\n        module_name=name_variants.library_name, package_name=name_variants.package_name\n    )\n\n    console.info(\n        f\"Initializing the component directory: {CustomComponents.SRC_DIR / name_variants.custom_component_module_dir}\"\n    )\n    CustomComponents.SRC_DIR.mkdir(exist_ok=True)\n    with set_directory(CustomComponents.SRC_DIR):\n        module_dir = Path(name_variants.custom_component_module_dir)\n        module_dir.mkdir(exist_ok=True, parents=True)\n        _write_source_and_init_py(\n            custom_component_src_dir=module_dir,\n            component_class_name=name_variants.component_class_name,\n            module_name=name_variants.module_name,\n        )\n\n\n@custom_components_cli.command(name=\"init\")\n@click.option(\n    \"--library-name\",\n    default=None,\n    help=\"The name of your library. On PyPI, package will be published as `reflex-{library-name}`.\",\n)\n@click.option(\n    \"--install/--no-install\",\n    default=True,\n    help=\"Whether to install package from this local custom component in editable mode.\",\n)\n@loglevel_option\ndef init(\n    library_name: str | None,\n    install: bool,\n):\n    \"\"\"Initialize a custom component.\n\n    Args:\n        library_name: The name of the library.\n        install: Whether to install package from this local custom component in editable mode.\n\n    Raises:\n        SystemExit: If the pyproject.toml already exists.\n    \"\"\"\n    from reflex.utils import exec\n\n    if CustomComponents.PYPROJECT_TOML.exists():\n        console.error(f\"A {CustomComponents.PYPROJECT_TOML} already exists. Aborting.\")\n        raise SystemExit(1)\n\n    # Show system info.\n    exec.output_system_info()\n\n    # Check the name follows the convention if picked.\n    name_variants = _validate_library_name(library_name)\n\n    console.rule(f\"[bold]Initializing {name_variants.package_name} project\")\n\n    _populate_custom_component_project(name_variants)\n\n    _populate_demo_app(name_variants)\n\n    # Initialize the .gitignore.\n    frontend_skeleton.initialize_gitignore(\n        gitignore_file=CustomComponents.FILE, files_to_ignore=CustomComponents.DEFAULTS\n    )\n\n    if install:\n        package_name = name_variants.package_name\n        console.rule(f\"[bold]Installing {package_name} in editable mode.\")\n        if _pip_install_on_demand(package_name=\".\", install_args=[\"-e\"]):\n            console.info(f\"Package {package_name} installed!\")\n        else:\n            raise SystemExit(1)\n\n    console.print(\"[bold]Custom component initialized successfully!\")\n    console.rule(\"[bold]Project Summary\")\n    console.print(\n        f\"[ {CustomComponents.PACKAGE_README} ]: Package description. Please add usage examples.\"\n    )\n    console.print(\n        f\"[ {CustomComponents.PYPROJECT_TOML} ]: Project configuration file. Please fill in details such as your name, email, homepage URL.\"\n    )\n    console.print(\n        f\"[ {CustomComponents.SRC_DIR}/ ]: Custom component code template. Start by editing it with your component implementation.\"\n    )\n    console.print(\n        f\"[ {name_variants.demo_app_dir}/ ]: Demo App. Add more code to this app and test.\"\n    )\n\n\ndef _pip_install_on_demand(\n    package_name: str,\n    install_args: list[str] | None = None,\n) -> bool:\n    \"\"\"Install a package on demand.\n\n    Args:\n        package_name: The name of the package.\n        install_args: The additional arguments for the pip install command.\n\n    Returns:\n        True if the package is installed successfully, False otherwise.\n    \"\"\"\n    install_args = install_args or []\n\n    install_cmds = [\n        sys.executable,\n        \"-m\",\n        \"pip\",\n        \"install\",\n        *install_args,\n        package_name,\n    ]\n    console.debug(f\"Install package: {' '.join(install_cmds)}\")\n    return _run_commands_in_subprocess(install_cmds)\n\n\ndef _run_commands_in_subprocess(cmds: list[str]) -> bool:\n    \"\"\"Run commands in a subprocess.\n\n    Args:\n        cmds: The commands to run.\n\n    Returns:\n        True if the command runs successfully, False otherwise.\n    \"\"\"\n    console.debug(f\"Running command: {' '.join(cmds)}\")\n    try:\n        result = subprocess.run(cmds, capture_output=True, text=True, check=True)\n    except subprocess.CalledProcessError as cpe:\n        console.error(cpe.stdout)\n        console.error(cpe.stderr)\n        return False\n    else:\n        console.debug(result.stdout)\n        return True\n\n\ndef _make_pyi_files():\n    \"\"\"Create pyi files for the custom component.\"\"\"\n    from reflex.utils.pyi_generator import PyiGenerator\n\n    for top_level_dir in Path.cwd().iterdir():\n        if not top_level_dir.is_dir() or top_level_dir.name.startswith(\".\"):\n            continue\n        for dir, _, _ in top_level_dir.walk():\n            if \"__pycache__\" in dir.name:\n                continue\n            PyiGenerator().scan_all([dir])\n\n\ndef _run_build():\n    \"\"\"Run the build command.\n\n    Raises:\n        SystemExit: If the build fails.\n    \"\"\"\n    console.print(\"Building custom component...\")\n\n    _make_pyi_files()\n\n    cmds = [sys.executable, \"-m\", \"build\", \".\"]\n    if _run_commands_in_subprocess(cmds):\n        console.info(\"Custom component built successfully!\")\n    else:\n        raise SystemExit(1)\n\n\n@custom_components_cli.command(name=\"build\")\n@loglevel_option\ndef build():\n    \"\"\"Build a custom component. Must be run from the project root directory where the pyproject.toml is.\"\"\"\n    _run_build()\n\n\ndef _collect_details_for_gallery():\n    \"\"\"Helper to collect details on the custom component to be included in the gallery.\n\n    Raises:\n        SystemExit: If pyproject.toml file is ill-formed or the request to the backend services fails.\n    \"\"\"\n    import httpx\n    from reflex_cli.utils import hosting\n\n    console.rule(\"[bold]Authentication with Reflex Services\")\n    console.print(\"First let's log in to Reflex backend services.\")\n    access_token, _ = hosting.authenticated_token()\n\n    if not access_token:\n        console.error(\n            \"Unable to authenticate with Reflex backend services. Make sure you are logged in.\"\n        )\n        raise SystemExit(1)\n\n    console.rule(\"[bold]Custom Component Information\")\n    params = {}\n\n    package_name = console.ask(\"[ Published python package name ]\")\n    console.print(f\"[ Custom component package name ] : {package_name}\")\n    params[\"package_name\"] = package_name\n\n    post_custom_components_gallery_endpoint = (\n        \"https://gallery-backend.reflex.dev/custom-components/gallery\"\n    )\n\n    # Check the backend services if the user is allowed to update information of this package is already shared.\n    try:\n        console.debug(\n            f\"Checking if user has permission to upsert information for {package_name} by POST.\"\n        )\n        # Send a POST request to achieve two things at once:\n        # 1. Check if the package is already shared by the user. If not, the backend will return 403.\n        # 2. If this package is not shared before, this request records the package name in the backend.\n        response = httpx.post(\n            post_custom_components_gallery_endpoint,\n            headers={\"Authorization\": f\"Bearer {access_token}\"},\n            data=params,\n        )\n        if response.status_code == httpx.codes.FORBIDDEN:\n            console.error(\n                f\"{package_name} is owned by another user. Unable to update the information for it.\"\n            )\n            raise SystemExit(1)\n        response.raise_for_status()\n    except httpx.HTTPError as he:\n        console.error(f\"Unable to complete request due to {he}.\")\n        raise SystemExit(1) from None\n\n    files = []\n    if (image_file_and_extension := _get_file_from_prompt_in_loop()) is not None:\n        files.append((\n            \"files\",\n            (image_file_and_extension[1], image_file_and_extension[0]),\n        ))\n\n    demo_url = None\n    while True:\n        demo_url = (\n            console.ask(\n                \"[ Full URL of deployed demo app, e.g. `https://my-app.reflex.run` ] (enter to skip)\"\n            )\n            or None\n        )\n        if _validate_url_with_protocol_prefix(demo_url):\n            break\n    if demo_url:\n        params[\"demo_url\"] = demo_url\n\n    # Now send the post request to Reflex backend services.\n    try:\n        console.debug(f\"Sending custom component data: {params}\")\n        response = httpx.post(\n            post_custom_components_gallery_endpoint,\n            headers={\"Authorization\": f\"Bearer {access_token}\"},\n            data=params,\n            files=files,\n            timeout=POST_CUSTOM_COMPONENTS_GALLERY_TIMEOUT,\n        )\n        response.raise_for_status()\n\n    except httpx.HTTPError as he:\n        console.error(f\"Unable to complete request due to {he}.\")\n        raise SystemExit(1) from None\n\n    console.info(\"Custom component information successfully shared!\")\n\n\ndef _validate_url_with_protocol_prefix(url: str | None) -> bool:\n    \"\"\"Validate the URL with protocol prefix. Empty string is acceptable.\n\n    Args:\n        url: the URL string to check.\n\n    Returns:\n        Whether the entered URL is acceptable.\n    \"\"\"\n    return not url or (url.startswith((\"http://\", \"https://\")))\n\n\ndef _get_file_from_prompt_in_loop() -> tuple[bytes, str] | None:\n    image_file = file_extension = None\n    while image_file is None:\n        image_path_str = console.ask(\n            \"Upload a preview image of your demo app (enter to skip)\"\n        )\n        if not image_path_str:\n            break\n        image_file_path = Path(image_path_str)\n        if not image_file_path:\n            break\n        if not image_file_path.exists():\n            console.error(f\"File {image_file_path} does not exist.\")\n            continue\n        file_extension = image_file_path.suffix\n        try:\n            image_file = image_file_path.read_bytes()\n        except OSError as ose:\n            console.error(f\"Unable to read the {file_extension} file due to {ose}\")\n            raise SystemExit(1) from None\n        else:\n            return image_file, file_extension\n\n    console.debug(f\"File extension detected: {file_extension}\")\n    return None\n\n\n@custom_components_cli.command(name=\"share\")\n@loglevel_option\ndef share_more_detail():\n    \"\"\"Collect more details on the published package for gallery.\"\"\"\n    _collect_details_for_gallery()\n\n\n@custom_components_cli.command(name=\"install\")\n@loglevel_option\ndef install():\n    \"\"\"Install package from this local custom component in editable mode.\n\n    Raises:\n        SystemExit: If unable to install the current directory in editable mode.\n    \"\"\"\n    if _pip_install_on_demand(package_name=\".\", install_args=[\"-e\"]):\n        console.info(\"Package installed successfully!\")\n    else:\n        raise SystemExit(1)\n"
  },
  {
    "path": "reflex/environment.py",
    "content": "\"\"\"Environment variable management.\"\"\"\n\nfrom __future__ import annotations\n\nimport concurrent.futures\nimport dataclasses\nimport enum\nimport importlib\nimport multiprocessing\nimport os\nimport platform\nfrom collections.abc import Callable, Sequence\nfrom functools import lru_cache\nfrom pathlib import Path\nfrom typing import (\n    TYPE_CHECKING,\n    Annotated,\n    Any,\n    Generic,\n    Literal,\n    TypeVar,\n    get_args,\n    get_origin,\n    get_type_hints,\n)\n\nfrom reflex import constants\nfrom reflex.constants.base import LogLevel\nfrom reflex.plugins import Plugin\nfrom reflex.utils.exceptions import EnvironmentVarValueError\nfrom reflex.utils.types import GenericType, is_union, value_inside_optional\n\n\ndef get_default_value_for_field(field: dataclasses.Field) -> Any:\n    \"\"\"Get the default value for a field.\n\n    Args:\n        field: The field.\n\n    Returns:\n        The default value.\n\n    Raises:\n        ValueError: If no default value is found.\n    \"\"\"\n    if field.default != dataclasses.MISSING:\n        return field.default\n    if field.default_factory != dataclasses.MISSING:\n        return field.default_factory()\n    msg = f\"Missing value for environment variable {field.name} and no default value found\"\n    raise ValueError(msg)\n\n\n# TODO: Change all interpret_.* signatures to value: str, field: dataclasses.Field once we migrate rx.Config to dataclasses\ndef interpret_boolean_env(value: str, field_name: str) -> bool:\n    \"\"\"Interpret a boolean environment variable value.\n\n    Args:\n        value: The environment variable value.\n        field_name: The field name.\n\n    Returns:\n        The interpreted value.\n\n    Raises:\n        EnvironmentVarValueError: If the value is invalid.\n    \"\"\"\n    true_values = [\"true\", \"1\", \"yes\", \"y\"]\n    false_values = [\"false\", \"0\", \"no\", \"n\"]\n\n    if value.lower() in true_values:\n        return True\n    if value.lower() in false_values:\n        return False\n    msg = f\"Invalid boolean value: {value!r} for {field_name}\"\n    raise EnvironmentVarValueError(msg)\n\n\ndef interpret_int_env(value: str, field_name: str) -> int:\n    \"\"\"Interpret an integer environment variable value.\n\n    Args:\n        value: The environment variable value.\n        field_name: The field name.\n\n    Returns:\n        The interpreted value.\n\n    Raises:\n        EnvironmentVarValueError: If the value is invalid.\n    \"\"\"\n    try:\n        return int(value)\n    except ValueError as ve:\n        msg = f\"Invalid integer value: {value!r} for {field_name}\"\n        raise EnvironmentVarValueError(msg) from ve\n\n\ndef interpret_float_env(value: str, field_name: str) -> float:\n    \"\"\"Interpret a float environment variable value.\n\n    Args:\n        value: The environment variable value.\n        field_name: The field name.\n\n    Returns:\n        The interpreted value.\n\n    Raises:\n        EnvironmentVarValueError: If the value is invalid.\n    \"\"\"\n    try:\n        return float(value)\n    except ValueError as ve:\n        msg = f\"Invalid float value: {value!r} for {field_name}\"\n        raise EnvironmentVarValueError(msg) from ve\n\n\ndef interpret_existing_path_env(value: str, field_name: str) -> ExistingPath:\n    \"\"\"Interpret a path environment variable value as an existing path.\n\n    Args:\n        value: The environment variable value.\n        field_name: The field name.\n\n    Returns:\n        The interpreted value.\n\n    Raises:\n        EnvironmentVarValueError: If the path does not exist.\n    \"\"\"\n    path = Path(value)\n    if not path.exists():\n        msg = f\"Path does not exist: {path!r} for {field_name}\"\n        raise EnvironmentVarValueError(msg)\n    return path\n\n\ndef interpret_path_env(value: str, field_name: str) -> Path:\n    \"\"\"Interpret a path environment variable value.\n\n    Args:\n        value: The environment variable value.\n        field_name: The field name.\n\n    Returns:\n        The interpreted value.\n    \"\"\"\n    return Path(value)\n\n\ndef interpret_plugin_class_env(value: str, field_name: str) -> type[Plugin]:\n    \"\"\"Interpret an environment variable value as a Plugin subclass.\n\n    Resolves a fully qualified import path to the Plugin subclass it refers to.\n\n    Args:\n        value: The environment variable value (e.g. \"reflex.plugins.sitemap.SitemapPlugin\").\n        field_name: The field name.\n\n    Returns:\n        The Plugin subclass.\n\n    Raises:\n        EnvironmentVarValueError: If the value is invalid.\n    \"\"\"\n    if \".\" not in value:\n        msg = f\"Invalid plugin value: {value!r} for {field_name}. Plugin name must be in the format 'package.module.PluginName'.\"\n        raise EnvironmentVarValueError(msg)\n\n    import_path, plugin_name = value.rsplit(\".\", 1)\n\n    try:\n        module = importlib.import_module(import_path)\n    except ImportError as e:\n        msg = f\"Failed to import module {import_path!r} for {field_name}: {e}\"\n        raise EnvironmentVarValueError(msg) from e\n\n    try:\n        plugin_class = getattr(module, plugin_name, None)\n    except Exception as e:\n        msg = f\"Failed to get plugin class {plugin_name!r} from module {import_path!r} for {field_name}: {e}\"\n        raise EnvironmentVarValueError(msg) from e\n\n    if not isinstance(plugin_class, type) or not issubclass(plugin_class, Plugin):\n        msg = f\"Invalid plugin class: {plugin_name!r} for {field_name}. Must be a subclass of Plugin.\"\n        raise EnvironmentVarValueError(msg)\n\n    return plugin_class\n\n\ndef interpret_plugin_env(value: str, field_name: str) -> Plugin:\n    \"\"\"Interpret a plugin environment variable value.\n\n    Resolves a fully qualified import path and returns an instance of the Plugin.\n\n    Args:\n        value: The environment variable value (e.g. \"reflex.plugins.sitemap.SitemapPlugin\").\n        field_name: The field name.\n\n    Returns:\n        An instance of the Plugin subclass.\n\n    Raises:\n        EnvironmentVarValueError: If the value is invalid.\n    \"\"\"\n    plugin_class = interpret_plugin_class_env(value, field_name)\n\n    try:\n        return plugin_class()\n    except Exception as e:\n        msg = f\"Failed to instantiate plugin {plugin_class.__name__!r} for {field_name}: {e}\"\n        raise EnvironmentVarValueError(msg) from e\n\n\ndef interpret_enum_env(value: str, field_type: GenericType, field_name: str) -> Any:\n    \"\"\"Interpret an enum environment variable value.\n\n    Args:\n        value: The environment variable value.\n        field_type: The field type.\n        field_name: The field name.\n\n    Returns:\n        The interpreted value.\n\n    Raises:\n        EnvironmentVarValueError: If the value is invalid.\n    \"\"\"\n    try:\n        return field_type(value)\n    except ValueError as ve:\n        msg = f\"Invalid enum value: {value!r} for {field_name}\"\n        raise EnvironmentVarValueError(msg) from ve\n\n\n@dataclasses.dataclass(frozen=True, kw_only=True, slots=True)\nclass SequenceOptions:\n    \"\"\"Options for interpreting Sequence environment variables.\"\"\"\n\n    delimiter: str = \":\"\n    strip: bool = False\n\n\nDEFAULT_SEQUENCE_OPTIONS = SequenceOptions()\n\n\ndef interpret_env_var_value(\n    value: str, field_type: GenericType, field_name: str\n) -> Any:\n    \"\"\"Interpret an environment variable value based on the field type.\n\n    Args:\n        value: The environment variable value.\n        field_type: The field type.\n        field_name: The field name.\n\n    Returns:\n        The interpreted value.\n\n    Raises:\n        ValueError: If the value is invalid.\n        EnvironmentVarValueError: If the value is invalid for the specific type.\n    \"\"\"\n    field_type = value_inside_optional(field_type)\n\n    if is_union(field_type):\n        errors = []\n        for arg in (union_types := get_args(field_type)):\n            try:\n                return interpret_env_var_value(value, arg, field_name)\n            except (ValueError, EnvironmentVarValueError) as e:  # noqa: PERF203\n                errors.append(e)\n        msg = f\"Could not interpret {value!r} for {field_name} as any of {union_types}: {errors}\"\n        raise EnvironmentVarValueError(msg)\n\n    value = value.strip()\n\n    if field_type is bool:\n        return interpret_boolean_env(value, field_name)\n    if field_type is str:\n        return value\n    if field_type is LogLevel:\n        loglevel = LogLevel.from_string(value)\n        if loglevel is None:\n            msg = f\"Invalid log level value: {value} for {field_name}\"\n            raise EnvironmentVarValueError(msg)\n        return loglevel\n    if field_type is int:\n        return interpret_int_env(value, field_name)\n    if field_type is float:\n        return interpret_float_env(value, field_name)\n    if field_type is Path:\n        return interpret_path_env(value, field_name)\n    if field_type is ExistingPath:\n        return interpret_existing_path_env(value, field_name)\n    if field_type is Plugin:\n        return interpret_plugin_env(value, field_name)\n    if get_origin(field_type) is type:\n        type_args = get_args(field_type)\n        if (\n            type_args\n            and isinstance(type_args[0], type)\n            and issubclass(type_args[0], Plugin)\n        ):\n            return interpret_plugin_class_env(value, field_name)\n    if get_origin(field_type) is Literal:\n        literal_values = get_args(field_type)\n        for literal_value in literal_values:\n            if isinstance(literal_value, str) and literal_value == value:\n                return literal_value\n            if isinstance(literal_value, bool):\n                try:\n                    interpreted_bool = interpret_boolean_env(value, field_name)\n                    if interpreted_bool == literal_value:\n                        return interpreted_bool\n                except EnvironmentVarValueError:\n                    continue\n            if isinstance(literal_value, int):\n                try:\n                    interpreted_int = interpret_int_env(value, field_name)\n                    if interpreted_int == literal_value:\n                        return interpreted_int\n                except EnvironmentVarValueError:\n                    continue\n        msg = f\"Invalid literal value: {value!r} for {field_name}, expected one of {literal_values}\"\n        raise EnvironmentVarValueError(msg)\n    # If the field is Annotated with SequenceOptions, extract the options\n    sequence_options = DEFAULT_SEQUENCE_OPTIONS\n    if get_origin(field_type) is Annotated:\n        annotated_args = get_args(field_type)\n        field_type = annotated_args[0]\n        for arg in annotated_args[1:]:\n            if isinstance(arg, SequenceOptions):\n                sequence_options = arg\n                break\n    if get_origin(field_type) in (list, Sequence):\n        items = value.split(sequence_options.delimiter)\n        if sequence_options.strip:\n            items = [item.strip() for item in items]\n        return [\n            interpret_env_var_value(\n                v,\n                get_args(field_type)[0],\n                f\"{field_name}[{i}]\",\n            )\n            for i, v in enumerate(items)\n        ]\n    if isinstance(field_type, type) and issubclass(field_type, enum.Enum):\n        return interpret_enum_env(value, field_type, field_name)\n\n    msg = f\"Invalid type for environment variable {field_name}: {field_type}. This is probably an issue in Reflex.\"\n    raise ValueError(msg)\n\n\nT = TypeVar(\"T\")\n\n\nclass EnvVar(Generic[T]):\n    \"\"\"Environment variable.\"\"\"\n\n    name: str\n    default: Any\n    type_: T\n\n    def __init__(self, name: str, default: Any, type_: T) -> None:\n        \"\"\"Initialize the environment variable.\n\n        Args:\n            name: The environment variable name.\n            default: The default value.\n            type_: The type of the value.\n        \"\"\"\n        self.name = name\n        self.default = default\n        self.type_ = type_\n\n    def interpret(self, value: str) -> T:\n        \"\"\"Interpret the environment variable value.\n\n        Args:\n            value: The environment variable value.\n\n        Returns:\n            The interpreted value.\n        \"\"\"\n        return interpret_env_var_value(value, self.type_, self.name)\n\n    def getenv(self) -> T | None:\n        \"\"\"Get the interpreted environment variable value.\n\n        Returns:\n            The environment variable value.\n        \"\"\"\n        env_value = os.getenv(self.name, None)\n        if env_value and env_value.strip():\n            return self.interpret(env_value)\n        return None\n\n    def is_set(self) -> bool:\n        \"\"\"Check if the environment variable is set.\n\n        Returns:\n            True if the environment variable is set.\n        \"\"\"\n        return bool(os.getenv(self.name, \"\").strip())\n\n    def get(self) -> T:\n        \"\"\"Get the interpreted environment variable value or the default value if not set.\n\n        Returns:\n            The interpreted value.\n        \"\"\"\n        env_value = self.getenv()\n        if env_value is not None:\n            return env_value\n        return self.default\n\n    def set(self, value: T | None) -> None:\n        \"\"\"Set the environment variable. None unsets the variable.\n\n        Args:\n            value: The value to set.\n        \"\"\"\n        if value is None:\n            _ = os.environ.pop(self.name, None)\n        else:\n            if isinstance(value, enum.Enum):\n                value = value.value\n            if isinstance(value, list):\n                str_value = \":\".join(str(v) for v in value)\n            else:\n                str_value = str(value)\n            os.environ[self.name] = str_value\n\n\n@lru_cache\ndef get_type_hints_environment(cls: type) -> dict[str, Any]:\n    \"\"\"Get the type hints for the environment variables.\n\n    Args:\n        cls: The class.\n\n    Returns:\n        The type hints.\n    \"\"\"\n    return get_type_hints(cls)\n\n\nclass env_var:  # noqa: N801 # pyright: ignore [reportRedeclaration]\n    \"\"\"Descriptor for environment variables.\"\"\"\n\n    name: str\n    default: Any\n    internal: bool = False\n\n    def __init__(self, default: Any, internal: bool = False) -> None:\n        \"\"\"Initialize the descriptor.\n\n        Args:\n            default: The default value.\n            internal: Whether the environment variable is reflex internal.\n        \"\"\"\n        self.default = default\n        self.internal = internal\n\n    def __set_name__(self, owner: Any, name: str):\n        \"\"\"Set the name of the descriptor.\n\n        Args:\n            owner: The owner class.\n            name: The name of the descriptor.\n        \"\"\"\n        self.name = name\n\n    def __get__(\n        self, instance: EnvironmentVariables, owner: type[EnvironmentVariables]\n    ):\n        \"\"\"Get the EnvVar instance.\n\n        Args:\n            instance: The instance.\n            owner: The owner class.\n\n        Returns:\n            The EnvVar instance.\n        \"\"\"\n        type_ = get_args(get_type_hints_environment(owner)[self.name])[0]\n        env_name = self.name\n        if self.internal:\n            env_name = f\"__{env_name}\"\n        return EnvVar(name=env_name, default=self.default, type_=type_)\n\n\nif TYPE_CHECKING:\n\n    def env_var(default: Any, internal: bool = False) -> EnvVar:\n        \"\"\"Typing helper for the env_var descriptor.\n\n        Args:\n            default: The default value.\n            internal: Whether the environment variable is reflex internal.\n\n        Returns:\n            The EnvVar instance.\n        \"\"\"\n        return default\n\n\nclass PathExistsFlag:\n    \"\"\"Flag to indicate that a path must exist.\"\"\"\n\n\nExistingPath = Annotated[Path, PathExistsFlag]\n\n\nclass PerformanceMode(enum.Enum):\n    \"\"\"Performance mode for the app.\"\"\"\n\n    WARN = \"warn\"\n    RAISE = \"raise\"\n    OFF = \"off\"\n\n\nclass ExecutorType(enum.Enum):\n    \"\"\"Executor for compiling the frontend.\"\"\"\n\n    THREAD = \"thread\"\n    PROCESS = \"process\"\n    MAIN_THREAD = \"main_thread\"\n\n    @classmethod\n    def get_executor_from_environment(cls):\n        \"\"\"Get the executor based on the environment variables.\n\n        Returns:\n            The executor.\n        \"\"\"\n        from reflex.utils import console\n\n        executor_type = environment.REFLEX_COMPILE_EXECUTOR.get()\n\n        reflex_compile_processes = environment.REFLEX_COMPILE_PROCESSES.get()\n        reflex_compile_threads = environment.REFLEX_COMPILE_THREADS.get()\n        # By default, use the main thread. Unless the user has specified a different executor.\n        # Using a process pool is much faster, but not supported on all platforms. It's gated behind a flag.\n        if executor_type is None:\n            if (\n                platform.system() not in (\"Linux\", \"Darwin\")\n                and reflex_compile_processes is not None\n            ):\n                console.warn(\"Multiprocessing is only supported on Linux and MacOS.\")\n\n            if (\n                platform.system() in (\"Linux\", \"Darwin\")\n                and reflex_compile_processes is not None\n            ):\n                if reflex_compile_processes == 0:\n                    console.warn(\n                        \"Number of processes must be greater than 0. If you want to use the default number of processes, set REFLEX_COMPILE_EXECUTOR to 'process'. Defaulting to None.\"\n                    )\n                    reflex_compile_processes = None\n                elif reflex_compile_processes < 0:\n                    console.warn(\n                        \"Number of processes must be greater than 0. Defaulting to None.\"\n                    )\n                    reflex_compile_processes = None\n                executor_type = ExecutorType.PROCESS\n            elif reflex_compile_threads is not None:\n                if reflex_compile_threads == 0:\n                    console.warn(\n                        \"Number of threads must be greater than 0. If you want to use the default number of threads, set REFLEX_COMPILE_EXECUTOR to 'thread'. Defaulting to None.\"\n                    )\n                    reflex_compile_threads = None\n                elif reflex_compile_threads < 0:\n                    console.warn(\n                        \"Number of threads must be greater than 0. Defaulting to None.\"\n                    )\n                    reflex_compile_threads = None\n                executor_type = ExecutorType.THREAD\n            else:\n                executor_type = ExecutorType.MAIN_THREAD\n\n        match executor_type:\n            case ExecutorType.PROCESS:\n                executor = concurrent.futures.ProcessPoolExecutor(\n                    max_workers=reflex_compile_processes,\n                    mp_context=multiprocessing.get_context(\"fork\"),\n                )\n            case ExecutorType.THREAD:\n                executor = concurrent.futures.ThreadPoolExecutor(\n                    max_workers=reflex_compile_threads\n                )\n            case ExecutorType.MAIN_THREAD:\n                FUTURE_RESULT_TYPE = TypeVar(\"FUTURE_RESULT_TYPE\")\n\n                class MainThreadExecutor:\n                    def __enter__(self):\n                        return self\n\n                    def __exit__(self, *args):\n                        pass\n\n                    def submit(\n                        self, fn: Callable[..., FUTURE_RESULT_TYPE], *args, **kwargs\n                    ) -> concurrent.futures.Future[FUTURE_RESULT_TYPE]:\n                        future_job = concurrent.futures.Future()\n                        future_job.set_result(fn(*args, **kwargs))\n                        return future_job\n\n                executor = MainThreadExecutor()\n\n        return executor\n\n\nclass EnvironmentVariables:\n    \"\"\"Environment variables class to instantiate environment variables.\"\"\"\n\n    # Indicate the current command that was invoked in the reflex CLI.\n    REFLEX_COMPILE_CONTEXT: EnvVar[constants.CompileContext] = env_var(\n        constants.CompileContext.UNDEFINED, internal=True\n    )\n\n    # Whether to use npm over bun to install and run the frontend.\n    REFLEX_USE_NPM: EnvVar[bool] = env_var(False)\n\n    # The npm registry to use.\n    NPM_CONFIG_REGISTRY: EnvVar[str | None] = env_var(None)\n\n    # Whether to use Granian for the backend. By default, the backend uses Uvicorn if available.\n    REFLEX_USE_GRANIAN: EnvVar[bool] = env_var(False)\n\n    # Whether to use the system installed bun. If set to false, bun will be bundled with the app.\n    REFLEX_USE_SYSTEM_BUN: EnvVar[bool] = env_var(False)\n\n    # The working directory for the frontend directory.\n    REFLEX_WEB_WORKDIR: EnvVar[Path] = env_var(Path(constants.Dirs.WEB))\n\n    # The working directory for the states directory.\n    REFLEX_STATES_WORKDIR: EnvVar[Path] = env_var(Path(constants.Dirs.STATES))\n\n    # Path to the alembic config file\n    ALEMBIC_CONFIG: EnvVar[ExistingPath] = env_var(Path(constants.ALEMBIC_CONFIG))\n\n    # Include schemas in alembic migrations.\n    ALEMBIC_INCLUDE_SCHEMAS: EnvVar[bool] = env_var(False)\n\n    # Disable SSL verification for HTTPX requests.\n    SSL_NO_VERIFY: EnvVar[bool] = env_var(False)\n\n    # The directory to store uploaded files.\n    REFLEX_UPLOADED_FILES_DIR: EnvVar[Path] = env_var(\n        Path(constants.Dirs.UPLOADED_FILES)\n    )\n\n    REFLEX_COMPILE_EXECUTOR: EnvVar[ExecutorType | None] = env_var(None)\n\n    # Whether to use separate processes to compile the frontend and how many. If not set, defaults to thread executor.\n    REFLEX_COMPILE_PROCESSES: EnvVar[int | None] = env_var(None)\n\n    # Whether to use separate threads to compile the frontend and how many. Defaults to `min(32, os.cpu_count() + 4)`.\n    REFLEX_COMPILE_THREADS: EnvVar[int | None] = env_var(None)\n\n    # The directory to store reflex dependencies.\n    REFLEX_DIR: EnvVar[Path] = env_var(constants.Reflex.DIR)\n\n    # Whether to print the SQL queries if the log level is INFO or lower.\n    SQLALCHEMY_ECHO: EnvVar[bool] = env_var(False)\n\n    # Whether to check db connections before using them.\n    SQLALCHEMY_POOL_PRE_PING: EnvVar[bool] = env_var(True)\n\n    # The size of the database connection pool.\n    SQLALCHEMY_POOL_SIZE: EnvVar[int] = env_var(5)\n\n    # The maximum overflow size of the database connection pool.\n    SQLALCHEMY_MAX_OVERFLOW: EnvVar[int] = env_var(10)\n\n    # Recycle connections after this many seconds.\n    SQLALCHEMY_POOL_RECYCLE: EnvVar[int] = env_var(-1)\n\n    # The timeout for acquiring a connection from the pool.\n    SQLALCHEMY_POOL_TIMEOUT: EnvVar[int] = env_var(30)\n\n    # Whether to ignore the redis config error. Some redis servers only allow out-of-band configuration.\n    REFLEX_IGNORE_REDIS_CONFIG_ERROR: EnvVar[bool] = env_var(False)\n\n    # Whether to skip purging the web directory in dev mode.\n    REFLEX_PERSIST_WEB_DIR: EnvVar[bool] = env_var(False)\n\n    # This env var stores the execution mode of the app\n    REFLEX_ENV_MODE: EnvVar[constants.Env] = env_var(constants.Env.DEV)\n\n    # Whether to run the backend only. Exclusive with REFLEX_FRONTEND_ONLY.\n    REFLEX_BACKEND_ONLY: EnvVar[bool] = env_var(False)\n\n    # Whether to run the frontend only. Exclusive with REFLEX_BACKEND_ONLY.\n    REFLEX_FRONTEND_ONLY: EnvVar[bool] = env_var(False)\n\n    # The port to run the frontend on.\n    REFLEX_FRONTEND_PORT: EnvVar[int | None] = env_var(None)\n\n    # The port to run the backend on.\n    REFLEX_BACKEND_PORT: EnvVar[int | None] = env_var(None)\n\n    # If this env var is set to \"yes\", App.compile will be a no-op\n    REFLEX_SKIP_COMPILE: EnvVar[bool] = env_var(False, internal=True)\n\n    # Whether to run app harness tests in headless mode.\n    APP_HARNESS_HEADLESS: EnvVar[bool] = env_var(False)\n\n    # Which app harness driver to use.\n    APP_HARNESS_DRIVER: EnvVar[str] = env_var(\"Chrome\")\n\n    # Arguments to pass to the app harness driver.\n    APP_HARNESS_DRIVER_ARGS: EnvVar[str] = env_var(\"\")\n\n    # Whether to check for outdated package versions.\n    REFLEX_CHECK_LATEST_VERSION: EnvVar[bool] = env_var(True)\n\n    # In which performance mode to run the app.\n    REFLEX_PERF_MODE: EnvVar[PerformanceMode] = env_var(PerformanceMode.WARN)\n\n    # The maximum size of the reflex state in kilobytes.\n    REFLEX_STATE_SIZE_LIMIT: EnvVar[int] = env_var(1000)\n\n    # Whether to use the turbopack bundler.\n    REFLEX_USE_TURBOPACK: EnvVar[bool] = env_var(False)\n\n    # Additional paths to include in the hot reload. Separated by a colon.\n    REFLEX_HOT_RELOAD_INCLUDE_PATHS: EnvVar[list[Path]] = env_var([])\n\n    # Paths to exclude from the hot reload. Takes precedence over include paths. Separated by a colon.\n    REFLEX_HOT_RELOAD_EXCLUDE_PATHS: EnvVar[list[Path]] = env_var([])\n\n    # Enables different behavior for when the backend would do a cold start if it was inactive.\n    REFLEX_DOES_BACKEND_COLD_START: EnvVar[bool] = env_var(False)\n\n    # The timeout for the backend to do a cold start in seconds.\n    REFLEX_BACKEND_COLD_START_TIMEOUT: EnvVar[int] = env_var(10)\n\n    # Used by flexgen to enumerate the pages.\n    REFLEX_ADD_ALL_ROUTES_ENDPOINT: EnvVar[bool] = env_var(False)\n\n    # The address to bind the HTTP client to. You can set this to \"::\" to enable IPv6.\n    REFLEX_HTTP_CLIENT_BIND_ADDRESS: EnvVar[str | None] = env_var(None)\n\n    # Maximum size of the message in the websocket server in bytes.\n    REFLEX_SOCKET_MAX_HTTP_BUFFER_SIZE: EnvVar[int] = env_var(\n        constants.POLLING_MAX_HTTP_BUFFER_SIZE\n    )\n\n    # The interval to send a ping to the websocket server in seconds.\n    REFLEX_SOCKET_INTERVAL: EnvVar[int] = env_var(constants.Ping.INTERVAL)\n\n    # The timeout to wait for a pong from the websocket server in seconds.\n    REFLEX_SOCKET_TIMEOUT: EnvVar[int] = env_var(constants.Ping.TIMEOUT)\n\n    # Whether to run Granian in a spawn process. This enables Reflex to pick up on environment variable changes between hot reloads.\n    REFLEX_STRICT_HOT_RELOAD: EnvVar[bool] = env_var(False)\n\n    # The path to the reflex log file. If not set, the log file will be stored in the reflex user directory.\n    REFLEX_LOG_FILE: EnvVar[Path | None] = env_var(None)\n\n    # Enable full logging of debug messages to reflex user directory.\n    REFLEX_ENABLE_FULL_LOGGING: EnvVar[bool] = env_var(False)\n\n    # Whether to enable hot module replacement\n    VITE_HMR: EnvVar[bool] = env_var(True)\n\n    # Whether to force a full reload on changes.\n    VITE_FORCE_FULL_RELOAD: EnvVar[bool] = env_var(False)\n\n    # Whether to enable Rolldown's experimental HMR.\n    VITE_EXPERIMENTAL_HMR: EnvVar[bool] = env_var(False)\n\n    # Whether to generate sourcemaps for the frontend.\n    VITE_SOURCEMAP: EnvVar[Literal[False, True, \"inline\", \"hidden\"]] = env_var(False)  # noqa: RUF038\n\n    # Whether to enable SSR for the frontend.\n    REFLEX_SSR: EnvVar[bool] = env_var(True)\n\n    # Whether to mount the compiled frontend app in the backend server in production.\n    REFLEX_MOUNT_FRONTEND_COMPILED_APP: EnvVar[bool] = env_var(False, internal=True)\n\n    # How long to delay writing updated states to disk. (Higher values mean less writes, but more chance of lost data.)\n    REFLEX_STATE_MANAGER_DISK_DEBOUNCE_SECONDS: EnvVar[float] = env_var(2.0)\n\n    # How long to wait between automatic reload on frontend error to avoid reload loops.\n    REFLEX_AUTO_RELOAD_COOLDOWN_TIME_MS: EnvVar[int] = env_var(10_000)\n\n    # Whether to enable debug logging for the redis state manager.\n    REFLEX_STATE_MANAGER_REDIS_DEBUG: EnvVar[bool] = env_var(False)\n\n    # Whether to opportunistically hold the redis lock to allow fast in-memory access while uncontended.\n    REFLEX_OPLOCK_ENABLED: EnvVar[bool] = env_var(False)\n\n    # How long to opportunistically hold the redis lock in milliseconds (must be less than the token expiration).\n    REFLEX_OPLOCK_HOLD_TIME_MS: EnvVar[int] = env_var(0)\n\n\nenvironment = EnvironmentVariables()\n\ntry:\n    from dotenv import load_dotenv\nexcept ImportError:\n    load_dotenv = None\n\n\ndef _paths_from_env_files(env_files: str) -> list[Path]:\n    \"\"\"Convert a string of paths separated by os.pathsep into a list of Path objects.\n\n    Args:\n        env_files: The string of paths.\n\n    Returns:\n        A list of Path objects.\n    \"\"\"\n    # load env files in reverse order\n    return list(\n        reversed([\n            Path(path)\n            for path_element in env_files.split(os.pathsep)\n            if (path := path_element.strip())\n        ])\n    )\n\n\ndef _load_dotenv_from_files(files: list[Path]):\n    \"\"\"Load environment variables from a list of files.\n\n    Args:\n        files: A list of Path objects representing the environment variable files.\n    \"\"\"\n    from reflex.utils import console\n\n    if not files:\n        return\n\n    if load_dotenv is None:\n        console.error(\n            \"\"\"The `python-dotenv` package is required to load environment variables from a file. Run `pip install \"python-dotenv>=1.1.0\"`.\"\"\"\n        )\n        return\n\n    for env_file in files:\n        if env_file.exists():\n            load_dotenv(env_file, override=True)\n\n\ndef _paths_from_environment() -> list[Path]:\n    \"\"\"Get the paths from the REFLEX_ENV_FILE environment variable.\n\n    Returns:\n        A list of Path objects.\n    \"\"\"\n    env_files = os.environ.get(\"REFLEX_ENV_FILE\")\n    if not env_files:\n        return []\n\n    return _paths_from_env_files(env_files)\n\n\ndef _load_dotenv_from_env():\n    \"\"\"Load environment variables from paths specified in REFLEX_ENV_FILE.\"\"\"\n    _load_dotenv_from_files(_paths_from_environment())\n\n\n# Load the env files at import time if they are set in the ENV_FILE environment variable.\n_load_dotenv_from_env()\n"
  },
  {
    "path": "reflex/event.py",
    "content": "\"\"\"Define event classes to connect the frontend and backend.\"\"\"\n\nimport dataclasses\nimport inspect\nimport sys\nimport types\nfrom base64 import b64encode\nfrom collections.abc import Callable, Mapping, Sequence\nfrom functools import lru_cache, partial\nfrom typing import (\n    TYPE_CHECKING,\n    Annotated,\n    Any,\n    Generic,\n    Literal,\n    NoReturn,\n    Protocol,\n    TypeVar,\n    get_args,\n    get_origin,\n    get_type_hints,\n    overload,\n)\n\nfrom typing_extensions import Self, TypeAliasType, TypedDict, TypeVarTuple, Unpack\n\nfrom reflex import constants\nfrom reflex.components.field import BaseField\nfrom reflex.constants.compiler import CompileVars, Hooks, Imports\nfrom reflex.constants.state import FRONTEND_EVENT_STATE\nfrom reflex.utils import format\nfrom reflex.utils.decorator import once\nfrom reflex.utils.exceptions import (\n    EventFnArgMismatchError,\n    EventHandlerArgTypeMismatchError,\n    MissingAnnotationError,\n)\nfrom reflex.utils.types import (\n    ArgsSpec,\n    GenericType,\n    Unset,\n    safe_issubclass,\n    typehint_issubclass,\n)\nfrom reflex.vars import VarData\nfrom reflex.vars.base import LiteralVar, Var\nfrom reflex.vars.function import (\n    ArgsFunctionOperation,\n    ArgsFunctionOperationBuilder,\n    BuilderFunctionVar,\n    FunctionArgs,\n    FunctionStringVar,\n    FunctionVar,\n    VarOperationCall,\n)\nfrom reflex.vars.object import ObjectVar\n\n\n@dataclasses.dataclass(\n    init=True,\n    frozen=True,\n)\nclass Event:\n    \"\"\"An event that describes any state change in the app.\"\"\"\n\n    # The token to specify the client that the event is for.\n    token: str\n\n    # The event name.\n    name: str\n\n    # The routing data where event occurred\n    router_data: dict[str, Any] = dataclasses.field(default_factory=dict)\n\n    # The event payload.\n    payload: dict[str, Any] = dataclasses.field(default_factory=dict)\n\n    @property\n    def substate_token(self) -> str:\n        \"\"\"Get the substate token for the event.\n\n        Returns:\n            The substate token.\n        \"\"\"\n        substate = self.name.rpartition(\".\")[0]\n        return f\"{self.token}_{substate}\"\n\n\n_EVENT_FIELDS: set[str] = {f.name for f in dataclasses.fields(Event)}\n\nBACKGROUND_TASK_MARKER = \"_reflex_background_task\"\nEVENT_ACTIONS_MARKER = \"_rx_event_actions\"\n\n\n@dataclasses.dataclass(\n    init=True,\n    frozen=True,\n    kw_only=True,\n)\nclass EventActionsMixin:\n    \"\"\"Mixin for DOM event actions.\"\"\"\n\n    # Whether to `preventDefault` or `stopPropagation` on the event.\n    event_actions: dict[str, bool | int] = dataclasses.field(default_factory=dict)\n\n    @property\n    def stop_propagation(self) -> Self:\n        \"\"\"Stop the event from bubbling up the DOM tree.\n\n        Returns:\n            New EventHandler-like with stopPropagation set to True.\n        \"\"\"\n        return dataclasses.replace(\n            self,\n            event_actions={**self.event_actions, \"stopPropagation\": True},\n        )\n\n    @property\n    def prevent_default(self) -> Self:\n        \"\"\"Prevent the default behavior of the event.\n\n        Returns:\n            New EventHandler-like with preventDefault set to True.\n        \"\"\"\n        return dataclasses.replace(\n            self,\n            event_actions={**self.event_actions, \"preventDefault\": True},\n        )\n\n    def throttle(self, limit_ms: int) -> Self:\n        \"\"\"Throttle the event handler.\n\n        Args:\n            limit_ms: The time in milliseconds to throttle the event handler.\n\n        Returns:\n            New EventHandler-like with throttle set to limit_ms.\n        \"\"\"\n        return dataclasses.replace(\n            self,\n            event_actions={**self.event_actions, \"throttle\": limit_ms},\n        )\n\n    def debounce(self, delay_ms: int) -> Self:\n        \"\"\"Debounce the event handler.\n\n        Args:\n            delay_ms: The time in milliseconds to debounce the event handler.\n\n        Returns:\n            New EventHandler-like with debounce set to delay_ms.\n        \"\"\"\n        return dataclasses.replace(\n            self,\n            event_actions={**self.event_actions, \"debounce\": delay_ms},\n        )\n\n    @property\n    def temporal(self) -> Self:\n        \"\"\"Do not queue the event if the backend is down.\n\n        Returns:\n            New EventHandler-like with temporal set to True.\n        \"\"\"\n        return dataclasses.replace(\n            self,\n            event_actions={**self.event_actions, \"temporal\": True},\n        )\n\n\n@dataclasses.dataclass(\n    init=True,\n    frozen=True,\n    kw_only=True,\n)\nclass EventHandler(EventActionsMixin):\n    \"\"\"An event handler responds to an event to update the state.\"\"\"\n\n    # The function to call in response to the event.\n    fn: Any = dataclasses.field(default=None)\n\n    # The full name of the state class this event handler is attached to.\n    # Empty string means this event handler is a server side event.\n    state_full_name: str = dataclasses.field(default=\"\")\n\n    def __hash__(self):\n        \"\"\"Get the hash of the event handler.\n\n        Returns:\n            The hash of the event handler.\n        \"\"\"\n        return hash((tuple(self.event_actions.items()), self.fn, self.state_full_name))\n\n    def get_parameters(self) -> Mapping[str, inspect.Parameter]:\n        \"\"\"Get the parameters of the function.\n\n        Returns:\n            The parameters of the function.\n        \"\"\"\n        if self.fn is None:\n            return {}\n        return inspect.signature(self.fn).parameters\n\n    @property\n    def _parameters(self) -> Mapping[str, inspect.Parameter]:\n        \"\"\"Get the parameters of the function.\n\n        Returns:\n            The parameters of the function.\n        \"\"\"\n        if (parameters := getattr(self, \"__parameters\", None)) is None:\n            parameters = {**self.get_parameters()}\n            object.__setattr__(self, \"__parameters\", parameters)\n        return parameters\n\n    @classmethod\n    def __class_getitem__(cls, args_spec: str) -> Annotated:\n        \"\"\"Get a typed EventHandler.\n\n        Args:\n            args_spec: The args_spec of the EventHandler.\n\n        Returns:\n            The EventHandler class item.\n        \"\"\"\n        return Annotated[cls, args_spec]\n\n    @property\n    def is_background(self) -> bool:\n        \"\"\"Whether the event handler is a background task.\n\n        Returns:\n            True if the event handler is marked as a background task.\n        \"\"\"\n        return getattr(self.fn, BACKGROUND_TASK_MARKER, False)\n\n    def __call__(self, *args: Any, **kwargs: Any) -> \"EventSpec\":\n        \"\"\"Pass arguments to the handler to get an event spec.\n\n        This method configures event handlers that take in arguments.\n\n        Args:\n            *args: The arguments to pass to the handler.\n            **kwargs: The keyword arguments to pass to the handler.\n\n        Returns:\n            The event spec, containing both the function and args.\n\n        Raises:\n            EventHandlerTypeError: If the arguments are invalid.\n        \"\"\"\n        from reflex.utils.exceptions import EventHandlerTypeError\n\n        # Get the function args.\n        fn_args = list(self._parameters)[1:]\n\n        if not isinstance(\n            repeated_arg := next(\n                (kwarg for kwarg in kwargs if kwarg in fn_args[: len(args)]), Unset()\n            ),\n            Unset,\n        ):\n            msg = f\"Event handler {self.fn.__name__} received repeated argument {repeated_arg}.\"\n            raise EventHandlerTypeError(msg)\n\n        if not isinstance(\n            extra_arg := next(\n                (kwarg for kwarg in kwargs if kwarg not in fn_args), Unset()\n            ),\n            Unset,\n        ):\n            msg = (\n                f\"Event handler {self.fn.__name__} received extra argument {extra_arg}.\"\n            )\n            raise EventHandlerTypeError(msg)\n\n        fn_args = fn_args[: len(args)] + list(kwargs)\n\n        fn_args = (Var(_js_expr=arg) for arg in fn_args)\n\n        # Construct the payload.\n        values = []\n        for arg in [*args, *kwargs.values()]:\n            # Special case for file uploads.\n            if isinstance(arg, FileUpload):\n                return arg.as_event_spec(handler=self)\n\n            # Otherwise, convert to JSON.\n            try:\n                values.append(LiteralVar.create(arg))\n            except TypeError as e:\n                msg = f\"Arguments to event handlers must be Vars or JSON-serializable. Got {arg} of type {type(arg)}.\"\n                raise EventHandlerTypeError(msg) from e\n        payload = tuple(zip(fn_args, values, strict=False))\n\n        # Return the event spec.\n        return EventSpec(\n            handler=self, args=payload, event_actions=self.event_actions.copy()\n        )\n\n\n@dataclasses.dataclass(\n    init=True,\n    frozen=True,\n    kw_only=True,\n)\nclass EventSpec(EventActionsMixin):\n    \"\"\"An event specification.\n\n    Whereas an Event object is passed during runtime, a spec is used\n    during compile time to outline the structure of an event.\n    \"\"\"\n\n    # The event handler.\n    handler: EventHandler = dataclasses.field(default=None)  # pyright: ignore [reportAssignmentType]\n\n    # The handler on the client to process event.\n    client_handler_name: str = dataclasses.field(default=\"\")\n\n    # The arguments to pass to the function.\n    args: tuple[tuple[Var, Var], ...] = dataclasses.field(default_factory=tuple)\n\n    def __init__(\n        self,\n        handler: EventHandler,\n        event_actions: dict[str, bool | int] | None = None,\n        client_handler_name: str = \"\",\n        args: tuple[tuple[Var, Var], ...] = (),\n    ):\n        \"\"\"Initialize an EventSpec.\n\n        Args:\n            event_actions: The event actions.\n            handler: The event handler.\n            client_handler_name: The client handler name.\n            args: The arguments to pass to the function.\n        \"\"\"\n        if event_actions is None:\n            event_actions = {}\n        object.__setattr__(self, \"event_actions\", event_actions)\n        object.__setattr__(self, \"handler\", handler)\n        object.__setattr__(self, \"client_handler_name\", client_handler_name)\n        object.__setattr__(self, \"args\", args or ())\n\n    def with_args(self, args: tuple[tuple[Var, Var], ...]) -> \"EventSpec\":\n        \"\"\"Copy the event spec, with updated args.\n\n        Args:\n            args: The new args to pass to the function.\n\n        Returns:\n            A copy of the event spec, with the new args.\n        \"\"\"\n        return type(self)(\n            handler=self.handler,\n            client_handler_name=self.client_handler_name,\n            args=args,\n            event_actions=self.event_actions.copy(),\n        )\n\n    def add_args(self, *args: Var) -> \"EventSpec\":\n        \"\"\"Add arguments to the event spec.\n\n        Args:\n            *args: The arguments to add positionally.\n\n        Returns:\n            The event spec with the new arguments.\n\n        Raises:\n            EventHandlerTypeError: If the arguments are invalid.\n        \"\"\"\n        from reflex.utils.exceptions import EventHandlerTypeError\n\n        # Get the remaining unfilled function args.\n        fn_args = list(self.handler._parameters)[1 + len(self.args) :]\n        fn_args = (Var(_js_expr=arg) for arg in fn_args)\n\n        # Construct the payload.\n        values = []\n        arg = None\n        try:\n            for arg in args:\n                values.append(LiteralVar.create(value=arg))  # noqa: PERF401, RUF100\n        except TypeError as e:\n            msg = f\"Arguments to event handlers must be Vars or JSON-serializable. Got {arg} of type {type(arg)}.\"\n            raise EventHandlerTypeError(msg) from e\n        new_payload = tuple(zip(fn_args, values, strict=False))\n        return self.with_args(self.args + new_payload)\n\n\n@dataclasses.dataclass(\n    frozen=True,\n)\nclass CallableEventSpec(EventSpec):\n    \"\"\"Decorate an EventSpec-returning function to act as both a EventSpec and a function.\n\n    This is used as a compatibility shim for replacing EventSpec objects in the\n    API with functions that return a family of EventSpec.\n    \"\"\"\n\n    fn: Callable[..., EventSpec] | None = None\n\n    def __init__(self, fn: Callable[..., EventSpec] | None = None, **kwargs):\n        \"\"\"Initialize a CallableEventSpec.\n\n        Args:\n            fn: The function to decorate.\n            **kwargs: The kwargs to pass to the EventSpec constructor.\n        \"\"\"\n        if fn is not None:\n            default_event_spec = fn()\n            super().__init__(\n                event_actions=default_event_spec.event_actions,\n                client_handler_name=default_event_spec.client_handler_name,\n                args=default_event_spec.args,\n                handler=default_event_spec.handler,\n                **kwargs,\n            )\n            object.__setattr__(self, \"fn\", fn)\n        else:\n            super().__init__(**kwargs)\n\n    def __call__(self, *args, **kwargs) -> EventSpec:\n        \"\"\"Call the decorated function.\n\n        Args:\n            *args: The args to pass to the function.\n            **kwargs: The kwargs to pass to the function.\n\n        Returns:\n            The EventSpec returned from calling the function.\n\n        Raises:\n            EventHandlerTypeError: If the CallableEventSpec has no associated function.\n        \"\"\"\n        from reflex.utils.exceptions import EventHandlerTypeError\n\n        if self.fn is None:\n            msg = \"CallableEventSpec has no associated function.\"\n            raise EventHandlerTypeError(msg)\n        return self.fn(*args, **kwargs)\n\n\n@dataclasses.dataclass(\n    init=True,\n    frozen=True,\n)\nclass EventChain(EventActionsMixin):\n    \"\"\"Container for a chain of events that will be executed in order.\"\"\"\n\n    events: Sequence[\"EventSpec | EventVar | EventCallback\"] = dataclasses.field(\n        default_factory=list\n    )\n\n    args_spec: Callable | Sequence[Callable] | None = dataclasses.field(default=None)\n\n    invocation: Var | None = dataclasses.field(default=None)\n\n    @classmethod\n    def create(\n        cls,\n        value: \"EventType\",\n        args_spec: ArgsSpec | Sequence[ArgsSpec],\n        key: str | None = None,\n        **event_chain_kwargs,\n    ) -> \"EventChain | Var\":\n        \"\"\"Create an event chain from a variety of input types.\n\n        Args:\n            value: The value to create the event chain from.\n            args_spec: The args_spec of the event trigger being bound.\n            key: The key of the event trigger being bound.\n            **event_chain_kwargs: Additional kwargs to pass to the EventChain constructor.\n\n        Returns:\n            The event chain.\n\n        Raises:\n            ValueError: If the value is not a valid event chain.\n        \"\"\"\n        # If it's an event chain var, return it.\n        if isinstance(value, Var):\n            if isinstance(value, EventChainVar):\n                return value\n            if isinstance(value, EventVar):\n                value = [value]\n            elif safe_issubclass(value._var_type, (EventChain, EventSpec)):\n                return cls.create(\n                    value=value.guess_type(),\n                    args_spec=args_spec,\n                    key=key,\n                    **event_chain_kwargs,\n                )\n            else:\n                msg = f\"Invalid event chain: {value!s} of type {value._var_type}\"\n                raise ValueError(msg)\n        elif isinstance(value, EventChain):\n            # Trust that the caller knows what they're doing passing an EventChain directly\n            return value\n\n        # If the input is a single event handler, wrap it in a list.\n        if isinstance(value, (EventHandler, EventSpec)):\n            value = [value]\n\n        # If the input is a list of event handlers, create an event chain.\n        if isinstance(value, list):\n            events: list[EventSpec | EventVar] = []\n            for v in value:\n                if isinstance(v, (EventHandler, EventSpec)):\n                    # Call the event handler to get the event.\n                    events.append(call_event_handler(v, args_spec, key=key))\n                elif isinstance(v, Callable):\n                    # Call the lambda to get the event chain.\n                    result = call_event_fn(v, args_spec, key=key)\n                    if isinstance(result, Var):\n                        msg = (\n                            f\"Invalid event chain: {v}. Cannot use a Var-returning \"\n                            \"lambda inside an EventChain list.\"\n                        )\n                        raise ValueError(msg)\n                    events.extend(result)\n                elif isinstance(v, EventVar):\n                    events.append(v)\n                else:\n                    msg = f\"Invalid event: {v}\"\n                    raise ValueError(msg)\n\n        # If the input is a callable, create an event chain.\n        elif isinstance(value, Callable):\n            result = call_event_fn(value, args_spec, key=key)\n            if isinstance(result, Var):\n                # Recursively call this function if the lambda returned an EventChain Var.\n                return cls.create(\n                    value=result, args_spec=args_spec, key=key, **event_chain_kwargs\n                )\n            events = [*result]\n\n        # Otherwise, raise an error.\n        else:\n            msg = f\"Invalid event chain: {value}\"\n            raise ValueError(msg)\n\n        # Add args to the event specs if necessary.\n        events = [\n            (e.with_args(get_handler_args(e)) if isinstance(e, EventSpec) else e)\n            for e in events\n        ]\n\n        # Return the event chain.\n        return cls(\n            events=events,\n            args_spec=args_spec,\n            **event_chain_kwargs,\n        )\n\n\n@dataclasses.dataclass(\n    init=True,\n    frozen=True,\n)\nclass JavascriptHTMLInputElement:\n    \"\"\"Interface for a Javascript HTMLInputElement https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement.\"\"\"\n\n    value: str = \"\"\n    checked: bool = False\n\n\n@dataclasses.dataclass(\n    init=True,\n    frozen=True,\n)\nclass JavascriptInputEvent:\n    \"\"\"Interface for a Javascript InputEvent https://developer.mozilla.org/en-US/docs/Web/API/InputEvent.\"\"\"\n\n    target: JavascriptHTMLInputElement = JavascriptHTMLInputElement()\n\n\n@dataclasses.dataclass(\n    init=True,\n    frozen=True,\n)\nclass JavascriptKeyboardEvent:\n    \"\"\"Interface for a Javascript KeyboardEvent https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent.\"\"\"\n\n    key: str = \"\"\n    altKey: bool = False  # noqa: N815\n    ctrlKey: bool = False  # noqa: N815\n    metaKey: bool = False  # noqa: N815\n    shiftKey: bool = False  # noqa: N815\n\n\ndef input_event(e: ObjectVar[JavascriptInputEvent]) -> tuple[Var[str]]:\n    \"\"\"Get the value from an input event.\n\n    Args:\n        e: The input event.\n\n    Returns:\n        The value from the input event.\n    \"\"\"\n    return (e.target.value,)\n\n\ndef int_input_event(e: ObjectVar[JavascriptInputEvent]) -> tuple[Var[int]]:\n    \"\"\"Get the value from an input event as an int.\n\n    Args:\n        e: The input event.\n\n    Returns:\n        The value from the input event as an int.\n    \"\"\"\n    return (Var(\"Number\").to(FunctionVar).call(e.target.value).to(int),)\n\n\ndef float_input_event(e: ObjectVar[JavascriptInputEvent]) -> tuple[Var[float]]:\n    \"\"\"Get the value from an input event as a float.\n\n    Args:\n        e: The input event.\n\n    Returns:\n        The value from the input event as a float.\n    \"\"\"\n    return (Var(\"Number\").to(FunctionVar).call(e.target.value).to(float),)\n\n\ndef checked_input_event(e: ObjectVar[JavascriptInputEvent]) -> tuple[Var[bool]]:\n    \"\"\"Get the checked state from an input event.\n\n    Args:\n        e: The input event.\n\n    Returns:\n        The checked state from the input event.\n    \"\"\"\n    return (e.target.checked,)\n\n\nFORM_DATA = Var(_js_expr=\"form_data\")\n\n\ndef on_submit_event() -> tuple[Var[dict[str, Any]]]:\n    \"\"\"Event handler spec for the on_submit event.\n\n    Returns:\n        The event handler spec.\n    \"\"\"\n    return (FORM_DATA,)\n\n\ndef on_submit_string_event() -> tuple[Var[dict[str, str]]]:\n    \"\"\"Event handler spec for the on_submit event.\n\n    Returns:\n        The event handler spec.\n    \"\"\"\n    return (FORM_DATA,)\n\n\nclass KeyInputInfo(TypedDict):\n    \"\"\"Information about a key input event.\"\"\"\n\n    alt_key: bool\n    ctrl_key: bool\n    meta_key: bool\n    shift_key: bool\n\n\ndef key_event(\n    e: ObjectVar[JavascriptKeyboardEvent],\n) -> tuple[Var[str], Var[KeyInputInfo]]:\n    \"\"\"Get the key from a keyboard event.\n\n    Args:\n        e: The keyboard event.\n\n    Returns:\n        The key from the keyboard event.\n    \"\"\"\n    return (\n        e.key.to(str),\n        Var.create(\n            {\n                \"alt_key\": e.altKey,\n                \"ctrl_key\": e.ctrlKey,\n                \"meta_key\": e.metaKey,\n                \"shift_key\": e.shiftKey,\n            },\n        ).to(KeyInputInfo),\n    )\n\n\n@dataclasses.dataclass(\n    init=True,\n    frozen=True,\n)\nclass JavascriptMouseEvent:\n    \"\"\"Interface for a Javascript MouseEvent https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent.\"\"\"\n\n    button: int = 0\n    buttons: list[int] = dataclasses.field(default_factory=list)\n    clientX: int = 0  # noqa: N815\n    clientY: int = 0  # noqa: N815\n    altKey: bool = False  # noqa: N815\n    ctrlKey: bool = False  # noqa: N815\n    metaKey: bool = False  # noqa: N815\n    shiftKey: bool = False  # noqa: N815\n\n\nclass JavascriptPointerEvent(JavascriptMouseEvent):\n    \"\"\"Interface for a Javascript PointerEvent https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent.\n\n    Inherits from JavascriptMouseEvent.\n    \"\"\"\n\n\nclass MouseEventInfo(TypedDict):\n    \"\"\"Information about a mouse event.\"\"\"\n\n    button: int\n    buttons: int\n    client_x: int\n    client_y: int\n    alt_key: bool\n    ctrl_key: bool\n    meta_key: bool\n    shift_key: bool\n\n\nclass PointerEventInfo(MouseEventInfo):\n    \"\"\"Information about a pointer event.\"\"\"\n\n\ndef pointer_event_spec(\n    e: ObjectVar[JavascriptPointerEvent],\n) -> tuple[Var[PointerEventInfo]]:\n    \"\"\"Get the pointer event information.\n\n    Args:\n        e: The pointer event.\n\n    Returns:\n        The pointer event information.\n    \"\"\"\n    return (\n        Var.create(\n            {\n                \"button\": e.button,\n                \"buttons\": e.buttons,\n                \"client_x\": e.clientX,\n                \"client_y\": e.clientY,\n                \"alt_key\": e.altKey,\n                \"ctrl_key\": e.ctrlKey,\n                \"meta_key\": e.metaKey,\n                \"shift_key\": e.shiftKey,\n            },\n        ).to(PointerEventInfo),\n    )\n\n\ndef no_args_event_spec() -> tuple[()]:\n    \"\"\"Empty event handler.\n\n    Returns:\n        An empty tuple.\n    \"\"\"\n    return ()\n\n\nT = TypeVar(\"T\")\nU = TypeVar(\"U\")\n\n\nclass IdentityEventReturn(Generic[T], Protocol):\n    \"\"\"Protocol for an identity event return.\"\"\"\n\n    def __call__(self, *values: Var[T]) -> tuple[Var[T], ...]:\n        \"\"\"Return the input values.\n\n        Args:\n            *values: The values to return.\n\n        Returns:\n            The input values.\n        \"\"\"\n        return values\n\n\n@overload\ndef passthrough_event_spec(  # pyright: ignore [reportOverlappingOverload]\n    event_type: type[T], /\n) -> Callable[[Var[T]], tuple[Var[T]]]: ...\n\n\n@overload\ndef passthrough_event_spec(\n    event_type_1: type[T], event_type2: type[U], /\n) -> Callable[[Var[T], Var[U]], tuple[Var[T], Var[U]]]: ...\n\n\n@overload\ndef passthrough_event_spec(*event_types: type[T]) -> IdentityEventReturn[T]: ...\n\n\ndef passthrough_event_spec(*event_types: type[T]) -> IdentityEventReturn[T]:  # pyright: ignore [reportInconsistentOverload]\n    \"\"\"A helper function that returns the input event as output.\n\n    Args:\n        *event_types: The types of the events.\n\n    Returns:\n        A function that returns the input event as output.\n    \"\"\"\n\n    def inner(*values: Var[T]) -> tuple[Var[T], ...]:\n        return values\n\n    inner_type = tuple(Var[event_type] for event_type in event_types)\n    return_annotation = tuple[inner_type]\n\n    inner.__signature__ = inspect.signature(inner).replace(  # pyright: ignore [reportFunctionMemberAccess]\n        parameters=[\n            inspect.Parameter(\n                f\"ev_{i}\",\n                kind=inspect.Parameter.POSITIONAL_OR_KEYWORD,\n                annotation=Var[event_type],\n            )\n            for i, event_type in enumerate(event_types)\n        ],\n        return_annotation=return_annotation,\n    )\n    for i, event_type in enumerate(event_types):\n        inner.__annotations__[f\"ev_{i}\"] = Var[event_type]\n    inner.__annotations__[\"return\"] = return_annotation\n\n    return inner\n\n\n@dataclasses.dataclass(\n    init=True,\n    frozen=True,\n)\nclass FileUpload:\n    \"\"\"Class to represent a file upload.\"\"\"\n\n    upload_id: str | None = None\n    on_upload_progress: EventHandler | Callable | None = None\n    extra_headers: dict[str, str] | None = None\n\n    @staticmethod\n    def on_upload_progress_args_spec(_prog: Var[dict[str, int | float | bool]]):\n        \"\"\"Args spec for on_upload_progress event handler.\n\n        Returns:\n            The arg mapping passed to backend event handler\n        \"\"\"\n        return [_prog]\n\n    def as_event_spec(self, handler: EventHandler) -> EventSpec:\n        \"\"\"Get the EventSpec for the file upload.\n\n        Args:\n            handler: The event handler.\n\n        Returns:\n            The event spec for the handler.\n\n        Raises:\n            ValueError: If the on_upload_progress is not a valid event handler.\n        \"\"\"\n        from reflex.components.core.upload import (\n            DEFAULT_UPLOAD_ID,\n            upload_files_context_var_data,\n        )\n\n        upload_id = self.upload_id if self.upload_id is not None else DEFAULT_UPLOAD_ID\n        spec_args = [\n            (\n                Var(_js_expr=\"files\"),\n                Var(\n                    _js_expr=\"filesById\",\n                    _var_type=dict[str, Any],\n                    _var_data=VarData.merge(upload_files_context_var_data),\n                ).to(ObjectVar)[LiteralVar.create(upload_id)],\n            ),\n            (\n                Var(_js_expr=\"upload_id\"),\n                LiteralVar.create(upload_id),\n            ),\n            (\n                Var(_js_expr=\"extra_headers\"),\n                LiteralVar.create(\n                    self.extra_headers if self.extra_headers is not None else {}\n                ),\n            ),\n        ]\n        if self.on_upload_progress is not None:\n            on_upload_progress = self.on_upload_progress\n            if isinstance(on_upload_progress, EventHandler):\n                events = [\n                    call_event_handler(\n                        on_upload_progress,\n                        self.on_upload_progress_args_spec,\n                    ),\n                ]\n            elif isinstance(on_upload_progress, Callable):\n                # Call the lambda to get the event chain.\n                events = call_event_fn(\n                    on_upload_progress, self.on_upload_progress_args_spec\n                )\n            else:\n                msg = f\"{on_upload_progress} is not a valid event handler.\"\n                raise ValueError(msg)\n            if isinstance(events, Var):\n                msg = f\"{on_upload_progress} cannot return a var {events}.\"\n                raise ValueError(msg)\n            on_upload_progress_chain = EventChain(\n                events=[*events],\n                args_spec=self.on_upload_progress_args_spec,\n            )\n            formatted_chain = str(format.format_prop(on_upload_progress_chain))\n            spec_args.append(\n                (\n                    Var(_js_expr=\"on_upload_progress\"),\n                    FunctionStringVar(\n                        formatted_chain.strip(\"{}\"),\n                    ).to(FunctionVar, EventChain),\n                ),\n            )\n        return EventSpec(\n            handler=handler,\n            client_handler_name=\"uploadFiles\",\n            args=tuple(spec_args),\n            event_actions=handler.event_actions.copy(),\n        )\n\n\n# Alias for rx.upload_files\nupload_files = FileUpload\n\n\n# Special server-side events.\ndef server_side(name: str, sig: inspect.Signature, **kwargs) -> EventSpec:\n    \"\"\"A server-side event.\n\n    Args:\n        name: The name of the event.\n        sig: The function signature of the event.\n        **kwargs: The arguments to pass to the event.\n\n    Returns:\n        An event spec for a server-side event.\n    \"\"\"\n\n    def fn():\n        return None\n\n    fn.__qualname__ = name\n    fn.__signature__ = sig  # pyright: ignore [reportFunctionMemberAccess]\n    return EventSpec(\n        handler=EventHandler(fn=fn, state_full_name=FRONTEND_EVENT_STATE),\n        args=tuple(\n            (\n                Var(_js_expr=k),\n                LiteralVar.create(v),\n            )\n            for k, v in kwargs.items()\n        ),\n    )\n\n\n@overload\ndef redirect(\n    path: str | Var[str],\n    *,\n    is_external: Literal[False] = False,\n    replace: bool = False,\n) -> EventSpec: ...\n\n\n@overload\ndef redirect(\n    path: str | Var[str],\n    *,\n    is_external: Literal[True],\n    popup: bool = False,\n) -> EventSpec: ...\n\n\ndef redirect(\n    path: str | Var[str],\n    *,\n    is_external: bool = False,\n    popup: bool = False,\n    replace: bool = False,\n) -> EventSpec:\n    \"\"\"Redirect to a new path.\n\n    Args:\n        path: The path to redirect to.\n        is_external: Whether to open in new tab or not.\n        popup: Whether to open in a new window or not.\n        replace: If True, the current page will not create a new history entry.\n\n    Returns:\n        An event to redirect to the path.\n    \"\"\"\n    return server_side(\n        \"_redirect\",\n        get_fn_signature(redirect),\n        path=path,\n        external=is_external,\n        popup=popup,\n        replace=replace,\n    )\n\n\ndef console_log(message: str | Var[str]) -> EventSpec:\n    \"\"\"Do a console.log on the browser.\n\n    Args:\n        message: The message to log.\n\n    Returns:\n        An event to log the message.\n    \"\"\"\n    return run_script(Var(\"console\").to(dict).log.to(FunctionVar).call(message))\n\n\n@once\ndef noop() -> EventSpec:\n    \"\"\"Do nothing.\n\n    Returns:\n        An event to do nothing.\n    \"\"\"\n    return run_script(Var.create(None))\n\n\ndef back() -> EventSpec:\n    \"\"\"Do a history.back on the browser.\n\n    Returns:\n        An event to go back one page.\n    \"\"\"\n    return run_script(\n        Var(\"window\").to(dict).history.to(dict).back.to(FunctionVar).call()\n    )\n\n\ndef window_alert(message: str | Var[str]) -> EventSpec:\n    \"\"\"Create a window alert on the browser.\n\n    Args:\n        message: The message to alert.\n\n    Returns:\n        An event to alert the message.\n    \"\"\"\n    return run_script(Var(\"window\").to(dict).alert.to(FunctionVar).call(message))\n\n\ndef set_focus(ref: str) -> EventSpec:\n    \"\"\"Set focus to specified ref.\n\n    Args:\n        ref: The ref.\n\n    Returns:\n        An event to set focus on the ref\n    \"\"\"\n    return server_side(\n        \"_set_focus\",\n        get_fn_signature(set_focus),\n        ref=LiteralVar.create(format.format_ref(ref)),\n    )\n\n\ndef blur_focus(ref: str) -> EventSpec:\n    \"\"\"Blur focus of specified ref.\n\n    Args:\n        ref: The ref.\n\n    Returns:\n        An event to blur focus on the ref\n    \"\"\"\n    return server_side(\n        \"_blur_focus\",\n        get_fn_signature(blur_focus),\n        ref=LiteralVar.create(format.format_ref(ref)),\n    )\n\n\ndef scroll_to(elem_id: str, align_to_top: bool | Var[bool] = True) -> EventSpec:\n    \"\"\"Select the id of a html element for scrolling into view.\n\n    Args:\n        elem_id: The id of the element to scroll to.\n        align_to_top: Whether to scroll to the top (True) or bottom (False) of the element.\n\n    Returns:\n        An EventSpec to scroll the page to the selected element.\n    \"\"\"\n    get_element_by_id = FunctionStringVar.create(\"document.getElementById\")\n\n    return run_script(\n        get_element_by_id\n        .call(elem_id)\n        .to(ObjectVar)\n        .scrollIntoView.to(FunctionVar)\n        .call(align_to_top),\n    )\n\n\ndef set_value(ref: str, value: Any) -> EventSpec:\n    \"\"\"Set the value of a ref.\n\n    Args:\n        ref: The ref.\n        value: The value to set.\n\n    Returns:\n        An event to set the ref.\n    \"\"\"\n    return server_side(\n        \"_set_value\",\n        get_fn_signature(set_value),\n        ref=LiteralVar.create(format.format_ref(ref)),\n        value=value,\n    )\n\n\ndef remove_cookie(key: str, options: dict[str, Any] | None = None) -> EventSpec:\n    \"\"\"Remove a cookie on the frontend.\n\n    Args:\n        key: The key identifying the cookie to be removed.\n        options: Support all the cookie options from RFC 6265\n\n    Returns:\n        EventSpec: An event to remove a cookie.\n    \"\"\"\n    options = options or {}\n    options[\"path\"] = options.get(\"path\", \"/\")\n    return server_side(\n        \"_remove_cookie\",\n        get_fn_signature(remove_cookie),\n        key=key,\n        options=options,\n    )\n\n\ndef clear_local_storage() -> EventSpec:\n    \"\"\"Set a value in the local storage on the frontend.\n\n    Returns:\n        EventSpec: An event to clear the local storage.\n    \"\"\"\n    return server_side(\n        \"_clear_local_storage\",\n        get_fn_signature(clear_local_storage),\n    )\n\n\ndef remove_local_storage(key: str) -> EventSpec:\n    \"\"\"Set a value in the local storage on the frontend.\n\n    Args:\n        key: The key identifying the variable in the local storage to remove.\n\n    Returns:\n        EventSpec: An event to remove an item based on the provided key in local storage.\n    \"\"\"\n    return server_side(\n        \"_remove_local_storage\",\n        get_fn_signature(remove_local_storage),\n        key=key,\n    )\n\n\ndef clear_session_storage() -> EventSpec:\n    \"\"\"Set a value in the session storage on the frontend.\n\n    Returns:\n        EventSpec: An event to clear the session storage.\n    \"\"\"\n    return server_side(\n        \"_clear_session_storage\",\n        get_fn_signature(clear_session_storage),\n    )\n\n\ndef remove_session_storage(key: str) -> EventSpec:\n    \"\"\"Set a value in the session storage on the frontend.\n\n    Args:\n        key: The key identifying the variable in the session storage to remove.\n\n    Returns:\n        EventSpec: An event to remove an item based on the provided key in session storage.\n    \"\"\"\n    return server_side(\n        \"_remove_session_storage\",\n        get_fn_signature(remove_session_storage),\n        key=key,\n    )\n\n\ndef set_clipboard(content: str | Var[str]) -> EventSpec:\n    \"\"\"Set the text in content in the clipboard.\n\n    Args:\n        content: The text to add to clipboard.\n\n    Returns:\n        EventSpec: An event to set some content in the clipboard.\n    \"\"\"\n    return run_script(\n        Var(\"navigator\")\n        .to(dict)\n        .clipboard.to(dict)\n        .writeText.to(FunctionVar)\n        .call(content)\n    )\n\n\ndef download(\n    url: str | Var | None = None,\n    filename: str | Var | None = None,\n    data: str | bytes | Var | None = None,\n    mime_type: str | Var | None = None,\n) -> EventSpec:\n    \"\"\"Download the file at a given path or with the specified data.\n\n    Args:\n        url: The URL to the file to download.\n        filename: The name that the file should be saved as after download.\n        data: The data to download.\n        mime_type: The mime type of the data to download.\n\n    Returns:\n        EventSpec: An event to download the associated file.\n\n    Raises:\n        ValueError: If the URL provided is invalid, both URL and data are provided,\n            or the data is not an expected type.\n    \"\"\"\n    from reflex.components.core.cond import cond\n\n    if isinstance(url, str):\n        if not url.startswith(\"/\"):\n            msg = \"The URL argument should start with a /\"\n            raise ValueError(msg)\n\n        # if filename is not provided, infer it from url\n        if filename is None:\n            filename = url.rpartition(\"/\")[-1]\n\n    if filename is None:\n        filename = \"\"\n\n    if data is not None:\n        if url is not None:\n            msg = \"Cannot provide both URL and data to download.\"\n            raise ValueError(msg)\n\n        if isinstance(data, str):\n            if mime_type is None:\n                mime_type = \"text/plain\"\n            # Caller provided a plain text string to download.\n            url = f\"data:{mime_type};base64,\" + b64encode(data.encode(\"utf-8\")).decode(\n                \"utf-8\"\n            )\n        elif isinstance(data, Var):\n            if mime_type is None:\n                mime_type = \"text/plain\"\n            # Need to check on the frontend if the Var already looks like a data: URI.\n\n            is_data_url = (data.js_type() == \"string\") & (\n                data.to(str).startswith(\"data:\")\n            )\n\n            # If it's a data: URI, use it as is, otherwise convert the Var to JSON in a data: URI.\n            url = cond(\n                is_data_url,\n                data.to(str),\n                f\"data:{mime_type},\" + data.to_string(),\n            )\n        elif isinstance(data, bytes):\n            if mime_type is None:\n                mime_type = \"application/octet-stream\"\n            # Caller provided bytes, so base64 encode it as a data: URI.\n            b64_data = b64encode(data).decode(\"utf-8\")\n            url = f\"data:{mime_type};base64,\" + b64_data\n        else:\n            msg = f\"Invalid data type {type(data)} for download. Use `str` or `bytes`.\"\n            raise ValueError(msg)\n\n    return server_side(\n        \"_download\",\n        get_fn_signature(download),\n        url=url,\n        filename=filename,\n    )\n\n\ndef call_script(\n    javascript_code: str | Var[str],\n    callback: \"EventType[Any] | None\" = None,\n) -> EventSpec:\n    \"\"\"Create an event handler that executes arbitrary javascript code.\n\n    Args:\n        javascript_code: The code to execute.\n        callback: EventHandler that will receive the result of evaluating the javascript code.\n\n    Returns:\n        EventSpec: An event that will execute the client side javascript.\n    \"\"\"\n    callback_kwargs = {\"callback\": None}\n    if callback is not None:\n        callback_kwargs = {\n            \"callback\": str(\n                format.format_queue_events(\n                    callback,\n                    args_spec=lambda result: [result],\n                )\n            ),\n        }\n    if isinstance(javascript_code, str):\n        # When there is VarData, include it and eval the JS code inline on the client.\n        javascript_code, original_code = (\n            LiteralVar.create(javascript_code),\n            javascript_code,\n        )\n        if not javascript_code._get_all_var_data():\n            # Without VarData, cast to string and eval the code in the event loop.\n            javascript_code = str(Var(_js_expr=original_code))\n\n    return server_side(\n        \"_call_script\",\n        get_fn_signature(call_script),\n        javascript_code=javascript_code,\n        **callback_kwargs,\n    )\n\n\ndef call_function(\n    javascript_code: str | Var,\n    callback: \"EventType[Any] | None\" = None,\n) -> EventSpec:\n    \"\"\"Create an event handler that executes arbitrary javascript code.\n\n    Args:\n        javascript_code: The code to execute.\n        callback: EventHandler that will receive the result of evaluating the javascript code.\n\n    Returns:\n        EventSpec: An event that will execute the client side javascript.\n    \"\"\"\n    callback_kwargs = {\"callback\": None}\n    if callback is not None:\n        callback_kwargs = {\n            \"callback\": str(\n                format.format_queue_events(\n                    callback,\n                    args_spec=lambda result: [result],\n                ),\n            )\n        }\n\n    javascript_code = (\n        Var(javascript_code) if isinstance(javascript_code, str) else javascript_code\n    )\n\n    return server_side(\n        \"_call_function\",\n        get_fn_signature(call_function),\n        function=javascript_code,\n        **callback_kwargs,\n    )\n\n\ndef run_script(\n    javascript_code: str | Var,\n    callback: \"EventType[Any] | None\" = None,\n) -> EventSpec:\n    \"\"\"Create an event handler that executes arbitrary javascript code.\n\n    Args:\n        javascript_code: The code to execute.\n        callback: EventHandler that will receive the result of evaluating the javascript code.\n\n    Returns:\n        EventSpec: An event that will execute the client side javascript.\n    \"\"\"\n    javascript_code = (\n        Var(javascript_code) if isinstance(javascript_code, str) else javascript_code\n    )\n\n    return call_function(ArgsFunctionOperation.create((), javascript_code), callback)\n\n\ndef get_event(state: \"BaseState\", event: str):\n    \"\"\"Get the event from the given state.\n\n    Args:\n        state: The state.\n        event: The event.\n\n    Returns:\n        The event.\n    \"\"\"\n    return f\"{state.get_name()}.{event}\"\n\n\ndef get_hydrate_event(state: \"BaseState\") -> str:\n    \"\"\"Get the name of the hydrate event for the state.\n\n    Args:\n        state: The state.\n\n    Returns:\n        The name of the hydrate event.\n    \"\"\"\n    return get_event(state, constants.CompileVars.HYDRATE)\n\n\ndef _values_returned_from_event(event_spec_annotations: list[Any]) -> list[Any]:\n    return [\n        event_spec_return_type\n        for event_spec_annotation in event_spec_annotations\n        if (event_spec_return_type := event_spec_annotation.get(\"return\")) is not None\n        and get_origin(event_spec_return_type) is tuple\n    ]\n\n\ndef _check_event_args_subclass_of_callback(\n    callback_params_names: list[str],\n    provided_event_types: list[Any],\n    callback_param_name_to_type: dict[str, Any],\n    callback_name: str = \"\",\n    key: str = \"\",\n):\n    \"\"\"Check if the event handler arguments are subclass of the callback.\n\n    Args:\n        callback_params_names: The names of the callback parameters.\n        provided_event_types: The event types.\n        callback_param_name_to_type: The callback parameter name to type mapping.\n        callback_name: The name of the callback.\n        key: The key.\n\n    Raises:\n        TypeError: If the event handler arguments are invalid.\n        EventHandlerArgTypeMismatchError: If the event handler arguments do not match the callback.\n\n    # noqa: DAR401 delayed_exceptions[]\n    # noqa: DAR402 EventHandlerArgTypeMismatchError\n    \"\"\"\n    from reflex.utils import console\n\n    type_match_found: dict[str, bool] = {}\n    delayed_exceptions: list[EventHandlerArgTypeMismatchError] = []\n\n    for event_spec_index, event_spec_return_type in enumerate(provided_event_types):\n        args = get_args(event_spec_return_type)\n\n        args_types_without_vars = [\n            arg if get_origin(arg) is not Var else get_args(arg)[0] for arg in args\n        ]\n\n        # check that args of event handler are matching the spec if type hints are provided\n        for i, arg in enumerate(callback_params_names[: len(args_types_without_vars)]):\n            if arg not in callback_param_name_to_type:\n                continue\n\n            type_match_found.setdefault(arg, False)\n\n            try:\n                compare_result = typehint_issubclass(\n                    args_types_without_vars[i], callback_param_name_to_type[arg]\n                )\n            except TypeError as te:\n                callback_name_context = f\" of {callback_name}\" if callback_name else \"\"\n                key_context = f\" for {key}\" if key else \"\"\n                msg = f\"Could not compare types {args_types_without_vars[i]} and {callback_param_name_to_type[arg]} for argument {arg}{callback_name_context}{key_context}.\"\n                raise TypeError(msg) from te\n\n            if compare_result:\n                type_match_found[arg] = True\n                continue\n            type_match_found[arg] = False\n            as_annotated_in = (\n                f\" as annotated in {callback_name}\" if callback_name else \"\"\n            )\n            delayed_exceptions.append(\n                EventHandlerArgTypeMismatchError(\n                    f\"Event handler {key} expects {args_types_without_vars[i]} for argument {arg} but got {callback_param_name_to_type[arg]}{as_annotated_in} instead.\"\n                )\n            )\n\n        if all(type_match_found.values()):\n            delayed_exceptions.clear()\n            if event_spec_index:\n                args = get_args(provided_event_types[0])\n\n                args_types_without_vars = [\n                    arg if get_origin(arg) is not Var else get_args(arg)[0]\n                    for arg in args\n                ]\n\n                expect_string = \", \".join(\n                    repr(arg) for arg in args_types_without_vars\n                ).replace(\"[\", \"\\\\[\")\n\n                given_string = \", \".join(\n                    repr(callback_param_name_to_type.get(arg, Any))\n                    for arg in callback_params_names\n                ).replace(\"[\", \"\\\\[\")\n\n                as_annotated_in = (\n                    f\" as annotated in {callback_name}\" if callback_name else \"\"\n                )\n\n                console.warn(\n                    f\"Event handler {key} expects ({expect_string}) -> () but got ({given_string}) -> (){as_annotated_in} instead. \"\n                    f\"This may lead to unexpected behavior but is intentionally ignored for {key}.\"\n                )\n            break\n\n    if delayed_exceptions:\n        raise delayed_exceptions[0]\n\n\ndef call_event_handler(\n    event_callback: EventHandler | EventSpec,\n    event_spec: ArgsSpec | Sequence[ArgsSpec],\n    key: str | None = None,\n) -> EventSpec:\n    \"\"\"Call an event handler to get the event spec.\n\n    This function will inspect the function signature of the event handler.\n    If it takes in an arg, the arg will be passed to the event handler.\n    Otherwise, the event handler will be called with no args.\n\n    Args:\n        event_callback: The event handler.\n        event_spec: The lambda that define the argument(s) to pass to the event handler.\n        key: The key to pass to the event handler.\n\n    Returns:\n        The event spec from calling the event handler.\n    \"\"\"\n    event_spec_args, event_annotations = parse_args_spec(event_spec)\n\n    event_spec_return_types = _values_returned_from_event(event_annotations)\n\n    if isinstance(event_callback, EventSpec):\n        parameters = event_callback.handler._parameters\n\n        check_fn_match_arg_spec(\n            event_callback.handler.fn,\n            parameters,\n            event_spec_args,\n            key,\n            bool(event_callback.handler.state_full_name) + len(event_callback.args),\n            event_callback.handler.fn.__qualname__,\n        )\n\n        event_callback_spec_args = list(parameters)\n\n        try:\n            type_hints_of_provided_callback = get_type_hints(event_callback.handler.fn)\n        except NameError:\n            type_hints_of_provided_callback = {}\n\n        argument_names = [str(arg) for arg, value in event_callback.args]\n\n        _check_event_args_subclass_of_callback(\n            [\n                arg\n                for arg in event_callback_spec_args[\n                    bool(event_callback.handler.state_full_name) :\n                ]\n                if arg not in argument_names\n            ],\n            event_spec_return_types,\n            type_hints_of_provided_callback,\n            event_callback.handler.fn.__qualname__,\n            key or \"\",\n        )\n\n        # Handle partial application of EventSpec args\n        return event_callback.add_args(*event_spec_args)\n\n    parameters = event_callback._parameters\n\n    check_fn_match_arg_spec(\n        event_callback.fn,\n        parameters,\n        event_spec_args,\n        key,\n        bool(event_callback.state_full_name),\n        event_callback.fn.__qualname__,\n    )\n\n    if event_spec_return_types:\n        event_callback_spec_args = list(parameters)\n\n        try:\n            type_hints_of_provided_callback = get_type_hints(event_callback.fn)\n        except NameError:\n            type_hints_of_provided_callback = {}\n\n        _check_event_args_subclass_of_callback(\n            event_callback_spec_args[1:],\n            event_spec_return_types,\n            type_hints_of_provided_callback,\n            event_callback.fn.__qualname__,\n            key or \"\",\n        )\n\n    return event_callback(*event_spec_args)\n\n\ndef unwrap_var_annotation(annotation: GenericType):\n    \"\"\"Unwrap a Var annotation or return it as is if it's not Var[X].\n\n    Args:\n        annotation: The annotation to unwrap.\n\n    Returns:\n        The unwrapped annotation.\n    \"\"\"\n    if get_origin(annotation) in (Var, ObjectVar) and (args := get_args(annotation)):\n        return args[0]\n    return annotation\n\n\ndef resolve_annotation(annotations: dict[str, Any], arg_name: str, spec: ArgsSpec):\n    \"\"\"Resolve the annotation for the given argument name.\n\n    Args:\n        annotations: The annotations.\n        arg_name: The argument name.\n        spec: The specs which the annotations come from.\n\n    Returns:\n        The resolved annotation.\n\n    Raises:\n        MissingAnnotationError: If the annotation is missing for non-lambda methods.\n    \"\"\"\n    annotation = annotations.get(arg_name)\n    if annotation is None:\n        if not isinstance(spec, types.LambdaType):\n            raise MissingAnnotationError(var_name=arg_name)\n        return dict[str, dict]\n    return annotation\n\n\n@lru_cache\ndef parse_args_spec(arg_spec: ArgsSpec | Sequence[ArgsSpec]):\n    \"\"\"Parse the args provided in the ArgsSpec of an event trigger.\n\n    Args:\n        arg_spec: The spec of the args.\n\n    Returns:\n        The parsed args.\n    \"\"\"\n    # if there's multiple, the first is the default\n    if isinstance(arg_spec, Sequence):\n        annotations = [get_type_hints(one_arg_spec) for one_arg_spec in arg_spec]\n        arg_spec = arg_spec[0]\n    else:\n        annotations = [get_type_hints(arg_spec)]\n\n    spec = inspect.getfullargspec(arg_spec)\n\n    return list(\n        arg_spec(*[\n            Var(f\"_{l_arg}\").to(\n                unwrap_var_annotation(\n                    resolve_annotation(annotations[0], l_arg, spec=arg_spec)\n                )\n            )\n            for l_arg in spec.args\n        ])\n    ), annotations\n\n\ndef args_specs_from_fields(\n    fields_dict: Mapping[str, BaseField],\n) -> dict[str, ArgsSpec | Sequence[ArgsSpec]]:\n    \"\"\"Get the event triggers and arg specs from the given fields.\n\n    Args:\n        fields_dict: The fields, keyed by name\n\n    Returns:\n        The args spec for any field annotated as EventHandler.\n    \"\"\"\n    return {\n        name: (\n            metadata[0]\n            if (\n                (metadata := getattr(field.annotated_type, \"__metadata__\", None))\n                is not None\n            )\n            else no_args_event_spec\n        )\n        for name, field in fields_dict.items()\n        if field.type_origin is EventHandler\n    }\n\n\ndef check_fn_match_arg_spec(\n    user_func: Callable,\n    user_func_parameters: Mapping[str, inspect.Parameter],\n    event_spec_args: Sequence[Var],\n    key: str | None = None,\n    number_of_bound_args: int = 0,\n    func_name: str | None = None,\n):\n    \"\"\"Ensures that the function signature matches the passed argument specification\n    or raises an EventFnArgMismatchError if they do not.\n\n    Args:\n        user_func: The function to be validated.\n        user_func_parameters: The parameters of the function to be validated.\n        event_spec_args: The argument specification for the event trigger.\n        key: The key of the event trigger.\n        number_of_bound_args: The number of bound arguments to the function.\n        func_name: The name of the function to be validated.\n\n    Raises:\n        EventFnArgMismatchError: Raised if the number of mandatory arguments do not match\n    \"\"\"\n    user_args = list(user_func_parameters)\n    # Drop the first argument if it's a bound method\n    if inspect.ismethod(user_func) and user_func.__self__ is not None:\n        user_args = user_args[1:]\n\n    user_default_args = [\n        p.default\n        for p in user_func_parameters.values()\n        if p.default is not inspect.Parameter.empty\n    ]\n    number_of_user_args = len(user_args) - number_of_bound_args\n    number_of_user_default_args = len(user_default_args) if user_default_args else 0\n\n    number_of_event_args = len(event_spec_args)\n\n    if number_of_user_args - number_of_user_default_args > number_of_event_args:\n        msg = (\n            f\"Event {key} only provides {number_of_event_args} arguments, but \"\n            f\"{func_name or user_func} requires at least {number_of_user_args - number_of_user_default_args} \"\n            \"arguments to be passed to the event handler.\\n\"\n            \"See https://reflex.dev/docs/events/event-arguments/\"\n        )\n        raise EventFnArgMismatchError(msg)\n\n\ndef call_event_fn(\n    fn: Callable,\n    arg_spec: ArgsSpec | Sequence[ArgsSpec],\n    key: str | None = None,\n) -> list[EventSpec] | Var:\n    \"\"\"Call a function to a list of event specs.\n\n    The function should return a single EventSpec, a list of EventSpecs, or a\n    single Var.\n\n    Args:\n        fn: The function to call.\n        arg_spec: The argument spec for the event trigger.\n        key: The key to pass to the event handler.\n\n    Returns:\n        The event specs from calling the function or a Var.\n\n    Raises:\n        EventHandlerValueError: If the lambda returns an unusable value.\n    \"\"\"\n    # Import here to avoid circular imports.\n    from reflex.event import EventHandler, EventSpec\n    from reflex.utils.exceptions import EventHandlerValueError\n\n    parsed_args, _ = parse_args_spec(arg_spec)\n\n    parameters = inspect.signature(fn).parameters\n\n    # Check that fn signature matches arg_spec\n    check_fn_match_arg_spec(fn, parameters, parsed_args, key=key)\n\n    number_of_fn_args = len(parameters)\n\n    # Call the function with the parsed args.\n    out = fn(*[*parsed_args][:number_of_fn_args])\n\n    # If the function returns a Var, assume it's an EventChain and render it directly.\n    if isinstance(out, Var):\n        return out\n\n    # Convert the output to a list.\n    if not isinstance(out, list):\n        out = [out]\n\n    # Convert any event specs to event specs.\n    events = []\n    for e in out:\n        if isinstance(e, EventHandler):\n            # An un-called EventHandler gets all of the args of the event trigger.\n            e = call_event_handler(e, arg_spec, key=key)\n\n        # Make sure the event spec is valid.\n        if not isinstance(e, EventSpec):\n            msg = f\"Lambda {fn} returned an invalid event spec: {e}.\"\n            raise EventHandlerValueError(msg)\n\n        # Add the event spec to the chain.\n        events.append(e)\n\n    # Return the events.\n    return events\n\n\ndef get_handler_args(\n    event_spec: EventSpec,\n) -> tuple[tuple[Var, Var], ...]:\n    \"\"\"Get the handler args for the given event spec.\n\n    Args:\n        event_spec: The event spec.\n\n    Returns:\n        The handler args.\n    \"\"\"\n    args = event_spec.handler._parameters\n\n    return event_spec.args if len(args) > 1 else ()\n\n\ndef fix_events(\n    events: list[EventSpec | EventHandler] | None,\n    token: str,\n    router_data: dict[str, Any] | None = None,\n) -> list[Event]:\n    \"\"\"Fix a list of events returned by an event handler.\n\n    Args:\n        events: The events to fix.\n        token: The user token.\n        router_data: The optional router data to set in the event.\n\n    Returns:\n        The fixed events.\n\n    Raises:\n        ValueError: If the event type is not what was expected.\n    \"\"\"\n    # If the event handler returns nothing, return an empty list.\n    if events is None:\n        return []\n\n    # If the handler returns a single event, wrap it in a list.\n    if not isinstance(events, list):\n        events = [events]\n\n    # Fix the events created by the handler.\n    out = []\n    for e in events:\n        if callable(e) and getattr(e, \"__name__\", \"\") == \"<lambda>\":\n            # A lambda was returned, assume the user wants to call it with no args.\n            e = e()\n        if isinstance(e, Event):\n            # If the event is already an event, append it to the list.\n            out.append(e)\n            continue\n        if not isinstance(e, (EventHandler, EventSpec)):\n            e = EventHandler(fn=e)\n        # Otherwise, create an event from the event spec.\n        if isinstance(e, EventHandler):\n            e = e()\n        if not isinstance(e, EventSpec):\n            msg = f\"Unexpected event type, {type(e)}.\"\n            raise ValueError(msg)\n        name = format.format_event_handler(e.handler)\n        payload = {k._js_expr: v._decode() for k, v in e.args}\n\n        # Filter router_data to reduce payload size\n        event_router_data = {\n            k: v\n            for k, v in (router_data or {}).items()\n            if k in constants.route.ROUTER_DATA_INCLUDE\n        }\n        # Create an event and append it to the list.\n        out.append(\n            Event(\n                token=token,\n                name=name,\n                payload=payload,\n                router_data=event_router_data,\n            )\n        )\n\n    return out\n\n\ndef get_fn_signature(fn: Callable) -> inspect.Signature:\n    \"\"\"Get the signature of a function.\n\n    Args:\n        fn: The function.\n\n    Returns:\n        The signature of the function.\n    \"\"\"\n    signature = inspect.signature(fn)\n    new_param = inspect.Parameter(\n        FRONTEND_EVENT_STATE, inspect.Parameter.POSITIONAL_OR_KEYWORD, annotation=Any\n    )\n    return signature.replace(parameters=(new_param, *signature.parameters.values()))\n\n\n# These chains can be used for their side effects when no other events are desired.\nstop_propagation = noop().stop_propagation\nprevent_default = noop().prevent_default\n\n\nclass EventVar(ObjectVar, python_types=(EventSpec, EventHandler)):\n    \"\"\"Base class for event vars.\"\"\"\n\n    def bool(self) -> NoReturn:\n        \"\"\"Get the boolean value of the var.\n\n        Raises:\n            TypeError: EventVar cannot be converted to a boolean.\n        \"\"\"\n        msg = f\"Cannot convert {self._js_expr} of type {type(self).__name__} to bool.\"\n        raise TypeError(msg)\n\n\n@dataclasses.dataclass(\n    eq=False,\n    frozen=True,\n    slots=True,\n)\nclass LiteralEventVar(VarOperationCall, LiteralVar, EventVar):\n    \"\"\"A literal event var.\"\"\"\n\n    _var_value: EventSpec = dataclasses.field(default=None)  # pyright: ignore [reportAssignmentType]\n\n    def __hash__(self) -> int:\n        \"\"\"Get the hash of the var.\n\n        Returns:\n            The hash of the var.\n        \"\"\"\n        return hash((type(self).__name__, self._js_expr))\n\n    @classmethod\n    def create(\n        cls,\n        value: EventSpec | EventHandler,\n        _var_data: VarData | None = None,\n    ) -> \"LiteralEventVar\":\n        \"\"\"Create a new LiteralEventVar instance.\n\n        Args:\n            value: The value of the var.\n            _var_data: The data of the var.\n\n        Returns:\n            The created LiteralEventVar instance.\n\n        Raises:\n            EventFnArgMismatchError: If the event handler takes arguments.\n        \"\"\"\n        if isinstance(value, EventHandler):\n\n            def no_args():\n                return ()\n\n            try:\n                value = call_event_handler(value, no_args)\n            except EventFnArgMismatchError:\n                msg = f\"Event handler {value.fn.__qualname__} used inside of a rx.cond() must not take any arguments.\"\n                raise EventFnArgMismatchError(msg) from None\n\n        return cls(\n            _js_expr=\"\",\n            _var_type=EventSpec,\n            _var_data=_var_data,\n            _var_value=value,\n            _func=FunctionStringVar(\"ReflexEvent\"),\n            _args=(\n                # event handler name\n                \".\".join(\n                    filter(\n                        None,\n                        format.get_event_handler_parts(value.handler),\n                    )\n                ),\n                # event handler args\n                {str(name): value for name, value in value.args},\n                # event actions\n                value.event_actions,\n                # client handler name\n                *([value.client_handler_name] if value.client_handler_name else []),\n            ),\n        )\n\n\nclass EventChainVar(BuilderFunctionVar, python_types=EventChain):\n    \"\"\"Base class for event chain vars.\"\"\"\n\n    def bool(self) -> NoReturn:\n        \"\"\"Get the boolean value of the var.\n\n        Raises:\n            TypeError: EventChainVar cannot be converted to a boolean.\n        \"\"\"\n        msg = f\"Cannot convert {self._js_expr} of type {type(self).__name__} to bool.\"\n        raise TypeError(msg)\n\n\n@dataclasses.dataclass(\n    eq=False,\n    frozen=True,\n    slots=True,\n)\n# Note: LiteralVar is second in the inheritance list allowing it act like a\n# CachedVarOperation (ArgsFunctionOperation) and get the _js_expr from the\n# _cached_var_name property.\nclass LiteralEventChainVar(ArgsFunctionOperationBuilder, LiteralVar, EventChainVar):\n    \"\"\"A literal event chain var.\"\"\"\n\n    _var_value: EventChain = dataclasses.field(default=None)  # pyright: ignore [reportAssignmentType]\n\n    def __hash__(self) -> int:\n        \"\"\"Get the hash of the var.\n\n        Returns:\n            The hash of the var.\n        \"\"\"\n        return hash((type(self).__name__, self._js_expr))\n\n    @classmethod\n    def create(\n        cls,\n        value: EventChain,\n        _var_data: VarData | None = None,\n    ) -> \"LiteralEventChainVar\":\n        \"\"\"Create a new LiteralEventChainVar instance.\n\n        Args:\n            value: The value of the var.\n            _var_data: The data of the var.\n\n        Returns:\n            The created LiteralEventChainVar instance.\n\n        Raises:\n            ValueError: If the invocation is not a FunctionVar.\n        \"\"\"\n        arg_spec = (\n            value.args_spec[0]\n            if isinstance(value.args_spec, Sequence)\n            else value.args_spec\n        )\n        sig = inspect.signature(arg_spec)  # pyright: ignore [reportArgumentType]\n        if sig.parameters:\n            arg_def = tuple(f\"_{p}\" for p in sig.parameters)\n            arg_def_expr = LiteralVar.create([Var(_js_expr=arg) for arg in arg_def])\n        else:\n            # add a default argument for addEvents if none were specified in value.args_spec\n            # used to trigger the preventDefault() on the event.\n            arg_def = (\"...args\",)\n            arg_def_expr = Var(_js_expr=\"args\")\n\n        if value.invocation is None:\n            invocation = FunctionStringVar.create(\n                CompileVars.ADD_EVENTS,\n                _var_data=VarData(\n                    imports=Imports.EVENTS,\n                    hooks={Hooks.EVENTS: None},\n                ),\n            )\n        else:\n            invocation = value.invocation\n\n        if invocation is not None and not isinstance(invocation, FunctionVar):\n            msg = f\"EventChain invocation must be a FunctionVar, got {invocation!s} of type {invocation._var_type!s}.\"\n            raise ValueError(msg)\n\n        return cls(\n            _js_expr=\"\",\n            _var_type=EventChain,\n            _var_data=_var_data,\n            _args=FunctionArgs(arg_def),\n            _return_expr=invocation.call(\n                LiteralVar.create([LiteralVar.create(event) for event in value.events]),\n                arg_def_expr,\n                value.event_actions,\n            ),\n            _var_value=value,\n        )\n\n\nP = TypeVarTuple(\"P\")\nQ = TypeVarTuple(\"Q\")\nV = TypeVar(\"V\")\nV2 = TypeVar(\"V2\")\nV3 = TypeVar(\"V3\")\nV4 = TypeVar(\"V4\")\nV5 = TypeVar(\"V5\")\n\n\nclass EventCallback(Generic[Unpack[P]], EventActionsMixin):\n    \"\"\"A descriptor that wraps a function to be used as an event.\"\"\"\n\n    def __init__(self, func: Callable[[Any, Unpack[P]], Any]):\n        \"\"\"Initialize the descriptor with the function to be wrapped.\n\n        Args:\n            func: The function to be wrapped.\n        \"\"\"\n        self.func = func\n\n    @overload\n    def __call__(\n        self: \"EventCallback[Unpack[Q]]\",\n    ) -> \"EventCallback[Unpack[Q]]\": ...\n\n    @overload\n    def __call__(\n        self: \"EventCallback[V, Unpack[Q]]\", value: V | Var[V]\n    ) -> \"EventCallback[Unpack[Q]]\": ...\n\n    @overload\n    def __call__(\n        self: \"EventCallback[V, V2, Unpack[Q]]\",\n        value: V | Var[V],\n        value2: V2 | Var[V2],\n    ) -> \"EventCallback[Unpack[Q]]\": ...\n\n    @overload\n    def __call__(\n        self: \"EventCallback[V, V2, V3, Unpack[Q]]\",\n        value: V | Var[V],\n        value2: V2 | Var[V2],\n        value3: V3 | Var[V3],\n    ) -> \"EventCallback[Unpack[Q]]\": ...\n\n    @overload\n    def __call__(\n        self: \"EventCallback[V, V2, V3, V4, Unpack[Q]]\",\n        value: V | Var[V],\n        value2: V2 | Var[V2],\n        value3: V3 | Var[V3],\n        value4: V4 | Var[V4],\n    ) -> \"EventCallback[Unpack[Q]]\": ...\n\n    def __call__(self, *values) -> \"EventCallback\":  # pyright: ignore [reportInconsistentOverload]\n        \"\"\"Call the function with the values.\n\n        Args:\n            *values: The values to call the function with.\n\n        Returns:\n            The function with the values.\n        \"\"\"\n        return self.func(*values)  # pyright: ignore [reportArgumentType]\n\n    @overload\n    def __get__(\n        self: \"EventCallback[Unpack[P]]\", instance: None, owner: Any\n    ) -> \"EventCallback[Unpack[P]]\": ...\n\n    @overload\n    def __get__(self, instance: Any, owner: Any) -> \"Callable[[Unpack[P]]]\": ...\n\n    def __get__(self, instance: Any, owner: Any) -> Callable:\n        \"\"\"Get the function with the instance bound to it.\n\n        Args:\n            instance: The instance to bind to the function.\n            owner: The owner of the function.\n\n        Returns:\n            The function with the instance bound to it\n        \"\"\"\n        if instance is None:\n            return self.func\n\n        return partial(self.func, instance)\n\n\nclass LambdaEventCallback(Protocol[Unpack[P]]):\n    \"\"\"A protocol for a lambda event callback.\"\"\"\n\n    __code__: types.CodeType\n\n    @overload\n    def __call__(self: \"LambdaEventCallback[()]\") -> Any: ...\n\n    @overload\n    def __call__(self: \"LambdaEventCallback[V]\", value: \"Var[V]\", /) -> Any: ...\n\n    @overload\n    def __call__(\n        self: \"LambdaEventCallback[V, V2]\", value: Var[V], value2: Var[V2], /\n    ) -> Any: ...\n\n    @overload\n    def __call__(\n        self: \"LambdaEventCallback[V, V2, V3]\",\n        value: Var[V],\n        value2: Var[V2],\n        value3: Var[V3],\n        /,\n    ) -> Any: ...\n\n    def __call__(self, *args: Var) -> Any:\n        \"\"\"Call the lambda with the args.\n\n        Args:\n            *args: The args to call the lambda with.\n        \"\"\"\n\n\nARGS = TypeVarTuple(\"ARGS\")\n\n\nLAMBDA_OR_STATE = TypeAliasType(\n    \"LAMBDA_OR_STATE\",\n    LambdaEventCallback[Unpack[ARGS]] | EventCallback[Unpack[ARGS]],\n    type_params=(ARGS,),\n)\n\nItemOrList = V | list[V]\n\nBASIC_EVENT_TYPES = TypeAliasType(\n    \"BASIC_EVENT_TYPES\", EventSpec | EventHandler | Var[Any], type_params=()\n)\n\nIndividualEventType = TypeAliasType(\n    \"IndividualEventType\",\n    LAMBDA_OR_STATE[Unpack[ARGS]] | BASIC_EVENT_TYPES,\n    type_params=(ARGS,),\n)\n\nEventType = TypeAliasType(\n    \"EventType\",\n    ItemOrList[LAMBDA_OR_STATE[Unpack[ARGS]] | BASIC_EVENT_TYPES],\n    type_params=(ARGS,),\n)\n\n\nif TYPE_CHECKING:\n    from reflex.state import BaseState\n\n    BASE_STATE = TypeVar(\"BASE_STATE\", bound=BaseState)\nelse:\n    BASE_STATE = TypeVar(\"BASE_STATE\")\n\n\nclass EventNamespace:\n    \"\"\"A namespace for event related classes.\"\"\"\n\n    # Core Event Classes\n    Event = Event\n    EventActionsMixin = EventActionsMixin\n    EventHandler = EventHandler\n    EventSpec = EventSpec\n    CallableEventSpec = CallableEventSpec\n    EventChain = EventChain\n    EventVar = EventVar\n    LiteralEventVar = LiteralEventVar\n    EventChainVar = EventChainVar\n    LiteralEventChainVar = LiteralEventChainVar\n    EventCallback = EventCallback\n    LambdaEventCallback = LambdaEventCallback\n\n    # Javascript Event Classes\n    JavascriptHTMLInputElement = JavascriptHTMLInputElement\n    JavascriptInputEvent = JavascriptInputEvent\n    JavascriptKeyboardEvent = JavascriptKeyboardEvent\n    JavascriptMouseEvent = JavascriptMouseEvent\n    JavascriptPointerEvent = JavascriptPointerEvent\n\n    # Type Info Classes\n    KeyInputInfo = KeyInputInfo\n    MouseEventInfo = MouseEventInfo\n    PointerEventInfo = PointerEventInfo\n    IdentityEventReturn = IdentityEventReturn\n\n    # File Upload\n    FileUpload = FileUpload\n\n    # Type Aliases\n    EventType = EventType\n    LAMBDA_OR_STATE = LAMBDA_OR_STATE\n    BASIC_EVENT_TYPES = BASIC_EVENT_TYPES\n    IndividualEventType = IndividualEventType\n\n    # Constants\n    BACKGROUND_TASK_MARKER = BACKGROUND_TASK_MARKER\n    EVENT_ACTIONS_MARKER = EVENT_ACTIONS_MARKER\n    _EVENT_FIELDS = _EVENT_FIELDS\n    FORM_DATA = FORM_DATA\n    upload_files = upload_files\n    stop_propagation = stop_propagation\n    prevent_default = prevent_default\n\n    # Private/Internal Functions\n    _values_returned_from_event = staticmethod(_values_returned_from_event)\n    _check_event_args_subclass_of_callback = staticmethod(\n        _check_event_args_subclass_of_callback\n    )\n\n    @overload\n    def __new__(\n        cls,\n        func: None = None,\n        *,\n        background: bool | None = None,\n        stop_propagation: bool | None = None,\n        prevent_default: bool | None = None,\n        throttle: int | None = None,\n        debounce: int | None = None,\n        temporal: bool | None = None,\n    ) -> Callable[\n        [Callable[[BASE_STATE, Unpack[P]], Any]], EventCallback[Unpack[P]]  # pyright: ignore [reportInvalidTypeVarUse]\n    ]: ...\n\n    @overload\n    def __new__(\n        cls,\n        func: Callable[[BASE_STATE, Unpack[P]], Any],\n        *,\n        background: bool | None = None,\n        stop_propagation: bool | None = None,\n        prevent_default: bool | None = None,\n        throttle: int | None = None,\n        debounce: int | None = None,\n        temporal: bool | None = None,\n    ) -> EventCallback[Unpack[P]]: ...\n\n    def __new__(\n        cls,\n        func: Callable[[BASE_STATE, Unpack[P]], Any] | None = None,\n        *,\n        background: bool | None = None,\n        stop_propagation: bool | None = None,\n        prevent_default: bool | None = None,\n        throttle: int | None = None,\n        debounce: int | None = None,\n        temporal: bool | None = None,\n    ) -> (\n        EventCallback[Unpack[P]]\n        | Callable[[Callable[[BASE_STATE, Unpack[P]], Any]], EventCallback[Unpack[P]]]\n    ):\n        \"\"\"Wrap a function to be used as an event.\n\n        Args:\n            func: The function to wrap.\n            background: Whether the event should be run in the background. Defaults to False.\n            stop_propagation: Whether to stop the event from bubbling up the DOM tree.\n            prevent_default: Whether to prevent the default behavior of the event.\n            throttle: Throttle the event handler to limit calls (in milliseconds).\n            debounce: Debounce the event handler to delay calls (in milliseconds).\n            temporal: Whether the event should be dropped when the backend is down.\n\n        Returns:\n            The wrapped function.\n\n        Raises:\n            TypeError: If background is True and the function is not a coroutine or async generator. # noqa: DAR402\n        \"\"\"\n\n        def _build_event_actions():\n            \"\"\"Build event_actions dict from decorator parameters.\n\n            Returns:\n                Dict of event actions to apply, or empty dict if none specified.\n            \"\"\"\n            if not any([\n                stop_propagation,\n                prevent_default,\n                throttle,\n                debounce,\n                temporal,\n            ]):\n                return {}\n\n            event_actions = {}\n            if stop_propagation is not None:\n                event_actions[\"stopPropagation\"] = stop_propagation\n            if prevent_default is not None:\n                event_actions[\"preventDefault\"] = prevent_default\n            if throttle is not None:\n                event_actions[\"throttle\"] = throttle\n            if debounce is not None:\n                event_actions[\"debounce\"] = debounce\n            if temporal is not None:\n                event_actions[\"temporal\"] = temporal\n            return event_actions\n\n        def wrapper(\n            func: Callable[[BASE_STATE, Unpack[P]], T],\n        ) -> EventCallback[Unpack[P]]:\n            if background is True:\n                if not inspect.iscoroutinefunction(\n                    func\n                ) and not inspect.isasyncgenfunction(func):\n                    msg = \"Background task must be async function or generator.\"\n                    raise TypeError(msg)\n                setattr(func, BACKGROUND_TASK_MARKER, True)\n            if getattr(func, \"__name__\", \"\").startswith(\"_\"):\n                msg = \"Event handlers cannot be private.\"\n                raise ValueError(msg)\n\n            qualname: str | None = getattr(func, \"__qualname__\", None)\n\n            if qualname and (\n                len(func_path := qualname.split(\".\")) == 1\n                or func_path[-2] == \"<locals>\"\n            ):\n                from reflex.state import BaseState\n\n                types = get_type_hints(func)\n                state_arg_name = next(iter(inspect.signature(func).parameters), None)\n                state_cls = state_arg_name and types.get(state_arg_name)\n                if state_cls and issubclass(state_cls, BaseState):\n                    name = (\n                        (func.__module__ + \".\" + qualname)\n                        .replace(\".\", \"_\")\n                        .replace(\"<locals>\", \"_\")\n                        .removeprefix(\"_\")\n                    )\n                    object.__setattr__(func, \"__name__\", name)\n                    object.__setattr__(func, \"__qualname__\", name)\n                    state_cls._add_event_handler(name, func)\n                    event_callback = getattr(state_cls, name)\n\n                    # Apply decorator event actions\n                    event_actions = _build_event_actions()\n                    if event_actions:\n                        # Create new EventCallback with updated event_actions\n                        event_callback = dataclasses.replace(\n                            event_callback, event_actions=event_actions\n                        )\n\n                    return event_callback\n\n            # Store decorator event actions on the function for later processing\n            event_actions = _build_event_actions()\n            if event_actions:\n                setattr(func, EVENT_ACTIONS_MARKER, event_actions)\n            return func  # pyright: ignore [reportReturnType]\n\n        if func is not None:\n            return wrapper(func)\n        return wrapper\n\n    get_event = staticmethod(get_event)\n    get_hydrate_event = staticmethod(get_hydrate_event)\n    fix_events = staticmethod(fix_events)\n    call_event_handler = staticmethod(call_event_handler)\n    call_event_fn = staticmethod(call_event_fn)\n    get_handler_args = staticmethod(get_handler_args)\n    check_fn_match_arg_spec = staticmethod(check_fn_match_arg_spec)\n    resolve_annotation = staticmethod(resolve_annotation)\n    parse_args_spec = staticmethod(parse_args_spec)\n    args_specs_from_fields = staticmethod(args_specs_from_fields)\n    unwrap_var_annotation = staticmethod(unwrap_var_annotation)\n    get_fn_signature = staticmethod(get_fn_signature)\n\n    # Event Spec Functions\n    passthrough_event_spec = staticmethod(passthrough_event_spec)\n    input_event = staticmethod(input_event)\n    int_input_event = staticmethod(int_input_event)\n    float_input_event = staticmethod(float_input_event)\n    checked_input_event = staticmethod(checked_input_event)\n    key_event = staticmethod(key_event)\n    pointer_event_spec = staticmethod(pointer_event_spec)\n    no_args_event_spec = staticmethod(no_args_event_spec)\n    on_submit_event = staticmethod(on_submit_event)\n    on_submit_string_event = staticmethod(on_submit_string_event)\n\n    # Server Side Events\n    server_side = staticmethod(server_side)\n    redirect = staticmethod(redirect)\n    console_log = staticmethod(console_log)\n    noop = staticmethod(noop)\n    back = staticmethod(back)\n    window_alert = staticmethod(window_alert)\n    set_focus = staticmethod(set_focus)\n    blur_focus = staticmethod(blur_focus)\n    scroll_to = staticmethod(scroll_to)\n    set_value = staticmethod(set_value)\n    remove_cookie = staticmethod(remove_cookie)\n    clear_local_storage = staticmethod(clear_local_storage)\n    remove_local_storage = staticmethod(remove_local_storage)\n    clear_session_storage = staticmethod(clear_session_storage)\n    remove_session_storage = staticmethod(remove_session_storage)\n    set_clipboard = staticmethod(set_clipboard)\n    download = staticmethod(download)\n    call_script = staticmethod(call_script)\n    call_function = staticmethod(call_function)\n    run_script = staticmethod(run_script)\n    __file__ = __file__\n\n\nevent = EventNamespace\nevent.event = event  # pyright: ignore[reportAttributeAccessIssue]\nsys.modules[__name__] = event  # pyright: ignore[reportArgumentType]\n"
  },
  {
    "path": "reflex/experimental/__init__.py",
    "content": "\"\"\"Namespace for experimental features.\"\"\"\n\nfrom types import SimpleNamespace\n\nfrom reflex.components.datadisplay.shiki_code_block import code_block as code_block\nfrom reflex.utils.console import warn\nfrom reflex.utils.misc import run_in_thread\n\nfrom . import hooks as hooks\nfrom .client_state import ClientStateVar as ClientStateVar\n\n\nclass ExperimentalNamespace(SimpleNamespace):\n    \"\"\"Namespace for experimental features.\"\"\"\n\n    def __getattribute__(self, item: str):\n        \"\"\"Get attribute from the namespace.\n\n        Args:\n            item: attribute name.\n\n        Returns:\n            The attribute.\n        \"\"\"\n        warn(\n            \"`rx._x` contains experimental features and might be removed at any time in the future.\",\n            dedupe=True,\n        )\n        return super().__getattribute__(item)\n\n    @property\n    def run_in_thread(self):\n        \"\"\"Temporary property returning the run_in_thread helper function.\n\n        Remove this property when run_in_thread is fully promoted.\n\n        Returns:\n            The run_in_thread helper function.\n        \"\"\"\n        self.register_component_warning(\"run_in_thread\")\n        return run_in_thread\n\n    @staticmethod\n    def register_component_warning(component_name: str):\n        \"\"\"Add component to emitted warnings and throw a warning if it\n        doesn't exist.\n\n        Args:\n            component_name: name of the component.\n        \"\"\"\n        warn(\n            f\"`rx._x.{component_name}` was promoted to `rx.{component_name}`.\",\n            dedupe=True,\n        )\n\n\n_x = ExperimentalNamespace(\n    client_state=ClientStateVar.create,\n    hooks=hooks,\n    code_block=code_block,\n)\n"
  },
  {
    "path": "reflex/experimental/client_state.py",
    "content": "\"\"\"Handle client side state with `useState`.\"\"\"\n\nfrom __future__ import annotations\n\nimport dataclasses\nimport re\nfrom collections.abc import Callable\nfrom typing import Any\n\nfrom reflex import constants\nfrom reflex.event import EventChain, EventHandler, EventSpec, run_script\nfrom reflex.utils.imports import ImportVar\nfrom reflex.vars import VarData, get_unique_variable_name\nfrom reflex.vars.base import LiteralVar, Var\nfrom reflex.vars.function import ArgsFunctionOperationBuilder, FunctionVar\n\nNoValue = object()\n\n\n_refs_import = {\n    f\"$/{constants.Dirs.STATE_PATH}\": [ImportVar(tag=\"refs\")],\n}\n\n\ndef _client_state_ref(var_name: str) -> str:\n    \"\"\"Get the ref path for a ClientStateVar.\n\n    Args:\n        var_name: The name of the variable.\n\n    Returns:\n        An accessor for ClientStateVar ref as a string.\n    \"\"\"\n    return f\"refs['_client_state_{var_name}']\"\n\n\ndef _client_state_ref_dict(var_name: str) -> str:\n    \"\"\"Get the ref path for a ClientStateVar.\n\n    Args:\n        var_name: The name of the variable.\n\n    Returns:\n        An accessor for ClientStateVar ref as a string.\n    \"\"\"\n    return f\"refs['_client_state_dict_{var_name}']\"\n\n\n@dataclasses.dataclass(\n    eq=False,\n    frozen=True,\n    slots=True,\n)\nclass ClientStateVar(Var):\n    \"\"\"A Var that exists on the client via useState.\"\"\"\n\n    # Track the names of the getters and setters\n    _setter_name: str = dataclasses.field(default=\"\")\n    _getter_name: str = dataclasses.field(default=\"\")\n    _id_name: str = dataclasses.field(default=\"\")\n\n    # Whether to add the var and setter to the global `refs` object for use in any Component.\n    _global_ref: bool = dataclasses.field(default=True)\n\n    def __hash__(self) -> int:\n        \"\"\"Define a hash function for a var.\n\n        Returns:\n            The hash of the var.\n        \"\"\"\n        return hash((\n            self._js_expr,\n            str(self._var_type),\n            self._getter_name,\n            self._setter_name,\n        ))\n\n    @classmethod\n    def create(\n        cls,\n        var_name: str | None = None,\n        default: Any = NoValue,\n        global_ref: bool = True,\n    ) -> ClientStateVar:\n        \"\"\"Create a local_state Var that can be accessed and updated on the client.\n\n        The `ClientStateVar` should be included in the highest parent component\n        that contains the components which will access and manipulate the client\n        state. It has no visual rendering, including it ensures that the\n        `useState` hook is called in the correct scope.\n\n        To render the var in a component, use the `value` property.\n\n        To update the var in a component, use the `set` property or `set_value` method.\n\n        To access the var in an event handler, use the `retrieve` method with\n        `callback` set to the event handler which should receive the value.\n\n        To update the var in an event handler, use the `push` method with the\n        value to update.\n\n        Args:\n            var_name: The name of the variable.\n            default: The default value of the variable.\n            global_ref: Whether the state should be accessible in any Component and on the backend.\n\n        Returns:\n            ClientStateVar\n\n        Raises:\n            ValueError: If the var_name is not a string.\n        \"\"\"\n        if var_name is None:\n            var_name = get_unique_variable_name()\n        id_name = \"id_\" + get_unique_variable_name()\n        if not isinstance(var_name, str):\n            msg = \"var_name must be a string.\"\n            raise ValueError(msg)\n        if default is NoValue:\n            default_var = Var(_js_expr=\"\")\n        elif not isinstance(default, Var):\n            default_var = LiteralVar.create(default)\n        else:\n            default_var = default\n        setter_name = f\"set{var_name.capitalize()}\"\n        hooks: dict[str, VarData | None] = {\n            f\"const {id_name} = useId()\": None,\n            f\"const [{var_name}, {setter_name}] = useState({default_var!s})\": None,\n        }\n        imports = {\n            \"react\": [ImportVar(tag=\"useState\"), ImportVar(tag=\"useId\")],\n        }\n        if global_ref:\n            arg_name = get_unique_variable_name()\n            func = ArgsFunctionOperationBuilder.create(\n                args_names=(arg_name,),\n                return_expr=Var(\"Array.prototype.forEach.call\")\n                .to(FunctionVar)\n                .call(\n                    (\n                        Var(\"Object.values\")\n                        .to(FunctionVar)\n                        .call(Var(_client_state_ref_dict(setter_name)))\n                        .to(list)\n                        .to(list)\n                    )\n                    + Var.create([\n                        Var(f\"(value) => {{ {_client_state_ref(var_name)} = value; }}\")\n                    ]).to(list),\n                    ArgsFunctionOperationBuilder.create(\n                        args_names=(\"setter\",),\n                        return_expr=Var(\"setter\").to(FunctionVar).call(Var(arg_name)),\n                    ),\n                ),\n            )\n\n            hooks[f\"{_client_state_ref(setter_name)} = {func!s}\"] = None\n            hooks[f\"{_client_state_ref(var_name)} ??= {var_name!s}\"] = None\n            hooks[f\"{_client_state_ref_dict(var_name)} ??= {{}}\"] = None\n            hooks[f\"{_client_state_ref_dict(setter_name)} ??= {{}}\"] = None\n            hooks[\n                f\"{_client_state_ref_dict(var_name)}[{id_name}] = {_client_state_ref(var_name)}\"\n            ] = None\n            hooks[\n                f\"{_client_state_ref_dict(setter_name)}[{id_name}] = {setter_name}\"\n            ] = None\n            imports.update(_refs_import)\n        return cls(\n            _js_expr=\"null\",\n            _setter_name=setter_name,\n            _getter_name=var_name,\n            _id_name=id_name,\n            _global_ref=global_ref,\n            _var_type=default_var._var_type,\n            _var_data=VarData.merge(\n                default_var._var_data,\n                VarData(\n                    hooks=hooks,\n                    imports=imports,\n                ),\n            ),\n        )\n\n    @property\n    def value(self) -> Var:\n        \"\"\"Get a placeholder for the Var.\n\n        This property can only be rendered on the frontend.\n\n        To access the value in a backend event handler, see `retrieve`.\n\n        Returns:\n            an accessor for the client state variable.\n        \"\"\"\n        return (\n            Var(\n                _js_expr=(\n                    _client_state_ref_dict(self._getter_name) + f\"[{self._id_name}]\"\n                    if self._global_ref\n                    else self._getter_name\n                ),\n                _var_data=self._var_data,\n            )\n            .to(self._var_type)\n            ._replace(\n                merge_var_data=VarData(imports=_refs_import if self._global_ref else {})\n            )\n        )\n\n    def set_value(self, value: Any = NoValue) -> Var:\n        \"\"\"Set the value of the client state variable.\n\n        This property can only be attached to a frontend event trigger.\n\n        To set a value from a backend event handler, see `push`.\n\n        Args:\n            value: The value to set.\n\n        Returns:\n            A special EventChain Var which will set the value when triggered.\n        \"\"\"\n        var_data = VarData(imports=_refs_import if self._global_ref else {})\n\n        setter = (\n            Var(_client_state_ref(self._setter_name))\n            if self._global_ref\n            else Var(self._setter_name, _var_data=var_data)\n        ).to(FunctionVar)\n\n        if value is not NoValue:\n            # This is a hack to make it work like an EventSpec taking an arg\n            value_var = LiteralVar.create(value)\n            value_str = str(value_var)\n\n            setter = ArgsFunctionOperationBuilder.create(\n                # remove patterns of [\"*\"] from the value_str using regex\n                args_names=(re.sub(r\"(\\?\\.)?\\[\\\".*\\\"\\]\", \"\", value_str),)\n                if value_str.startswith(\"_\")\n                else (),\n                return_expr=setter.call(value_var),\n            )\n\n        return setter.to(FunctionVar, EventChain)\n\n    @property\n    def set(self) -> Var:\n        \"\"\"Set the value of the client state variable.\n\n        This property can only be attached to a frontend event trigger.\n\n        To set a value from a backend event handler, see `push`.\n\n        Returns:\n            A special EventChain Var which will set the value when triggered.\n        \"\"\"\n        return self.set_value()\n\n    def retrieve(self, callback: EventHandler | Callable | None = None) -> EventSpec:\n        \"\"\"Pass the value of the client state variable to a backend EventHandler.\n\n        The event handler must `yield` or `return` the EventSpec to trigger the event.\n\n        Args:\n            callback: The callback to pass the value to.\n\n        Returns:\n            An EventSpec which will retrieve the value when triggered.\n\n        Raises:\n            ValueError: If the ClientStateVar is not global.\n        \"\"\"\n        if not self._global_ref:\n            msg = \"ClientStateVar must be global to retrieve the value.\"\n            raise ValueError(msg)\n        return run_script(_client_state_ref(self._getter_name), callback=callback)\n\n    def push(self, value: Any) -> EventSpec:\n        \"\"\"Push a value to the client state variable from the backend.\n\n        The event handler must `yield` or `return` the EventSpec to trigger the event.\n\n        Args:\n            value: The value to update.\n\n        Returns:\n            An EventSpec which will push the value when triggered.\n\n        Raises:\n            ValueError: If the ClientStateVar is not global.\n        \"\"\"\n        if not self._global_ref:\n            msg = \"ClientStateVar must be global to push the value.\"\n            raise ValueError(msg)\n        value = Var.create(value)\n        return run_script(f\"{_client_state_ref(self._setter_name)}({value})\")\n"
  },
  {
    "path": "reflex/experimental/hooks.py",
    "content": "\"\"\"Add standard Hooks wrapper for React.\"\"\"\n\nfrom __future__ import annotations\n\nfrom reflex.utils.imports import ImportVar\nfrom reflex.vars import VarData\nfrom reflex.vars.base import Var\n\n\ndef _compose_react_imports(tags: list[str]) -> dict[str, list[ImportVar]]:\n    return {\"react\": [ImportVar(tag=tag) for tag in tags]}\n\n\ndef const(name: str | list[str], value: str | Var) -> Var:\n    \"\"\"Create a constant Var.\n\n    Args:\n        name: The name of the constant.\n        value: The value of the constant.\n\n    Returns:\n        The constant Var.\n    \"\"\"\n    if isinstance(name, list):\n        return Var(_js_expr=f\"const [{', '.join(name)}] = {value}\")\n    return Var(_js_expr=f\"const {name} = {value}\")\n\n\ndef useCallback(func: str, deps: list) -> Var:  # noqa: N802\n    \"\"\"Create a useCallback hook with a function and dependencies.\n\n    Args:\n        func: The function to wrap.\n        deps: The dependencies of the function.\n\n    Returns:\n        The useCallback hook.\n    \"\"\"\n    return Var(\n        _js_expr=f\"useCallback({func}, {deps})\" if deps else f\"useCallback({func})\",\n        _var_data=VarData(imports=_compose_react_imports([\"useCallback\"])),\n    )\n\n\ndef useContext(context: str) -> Var:  # noqa: N802\n    \"\"\"Create a useContext hook with a context.\n\n    Args:\n        context: The context to use.\n\n    Returns:\n        The useContext hook.\n    \"\"\"\n    return Var(\n        _js_expr=f\"useContext({context})\",\n        _var_data=VarData(imports=_compose_react_imports([\"useContext\"])),\n    )\n\n\ndef useRef(default: str) -> Var:  # noqa: N802\n    \"\"\"Create a useRef hook with a default value.\n\n    Args:\n        default: The default value of the ref.\n\n    Returns:\n        The useRef hook.\n    \"\"\"\n    return Var(\n        _js_expr=f\"useRef({default})\",\n        _var_data=VarData(imports=_compose_react_imports([\"useRef\"])),\n    )\n\n\ndef useState(var_name: str, default: str | None = None) -> Var:  # noqa: N802\n    \"\"\"Create a useState hook with a variable name and setter name.\n\n    Args:\n        var_name: The name of the variable.\n        default: The default value of the variable.\n\n    Returns:\n        A useState hook.\n    \"\"\"\n    return const(\n        [var_name, f\"set{var_name.capitalize()}\"],\n        Var(\n            _js_expr=f\"useState({default})\",\n            _var_data=VarData(imports=_compose_react_imports([\"useState\"])),\n        ),\n    )\n"
  },
  {
    "path": "reflex/istate/__init__.py",
    "content": "\"\"\"This module will provide interfaces for the state.\"\"\"\n\nimport pickle\nimport sys\nfrom collections.abc import Callable\nfrom typing import Any\n\n# Errors caught during pickling of state\nHANDLED_PICKLE_ERRORS = (\n    pickle.PicklingError,\n    AttributeError,\n    IndexError,\n    TypeError,\n    ValueError,\n)\n\n\ndef _is_picklable(obj: Any, dumps: Callable[[object], bytes]) -> bool:\n    try:\n        dumps(obj)\n    except Exception:\n        return False\n    else:\n        return True\n\n\ndef debug_failed_pickles(obj: object, dumps: Callable[[object], bytes]):\n    \"\"\"Recursively check the picklability of an object and its contents.\n\n    Args:\n        obj: The object to check.\n        dumps: The pickle dump function to use.\n\n    Raises:\n        HANDLED_PICKLE_ERRORS: If the object or any of its contents are not picklable.\n    \"\"\"\n    if _is_picklable(obj, dumps):\n        return\n    if sys.version_info < (3, 11):\n        return\n    if isinstance(obj, dict):\n        for k, v in obj.items():\n            try:\n                debug_failed_pickles(v, dumps)\n            except HANDLED_PICKLE_ERRORS as e:\n                e.add_note(f\"While pickling dict value for key {k!r}\")\n                raise\n            try:\n                debug_failed_pickles(k, dumps)\n            except HANDLED_PICKLE_ERRORS as e:\n                e.add_note(f\"While pickling dict key {k!r}\")\n                raise\n        return\n    if isinstance(obj, (list, tuple)):\n        for i, v in enumerate(obj):\n            try:\n                debug_failed_pickles(v, dumps)\n            except HANDLED_PICKLE_ERRORS as e:  # noqa: PERF203\n                e.add_note(f\"While pickling index {i} of {type(obj).__name__}\")\n                raise\n        return\n    picklable_thing = obj.__getstate__()\n    if picklable_thing is not None:\n        debug_failed_pickles(picklable_thing, dumps)\n    else:\n        try:\n            dumps(obj)\n        except HANDLED_PICKLE_ERRORS as e:\n            e.add_note(f\"While pickling object of type {type(obj).__name__}\")\n            raise\n"
  },
  {
    "path": "reflex/istate/data.py",
    "content": "\"\"\"This module contains the dataclasses representing the router object.\"\"\"\n\nimport dataclasses\nfrom collections.abc import Mapping\nfrom types import MappingProxyType\nfrom typing import TYPE_CHECKING\nfrom urllib.parse import _NetlocResultMixinStr, parse_qsl, urlsplit\n\nfrom reflex import constants\nfrom reflex.utils import console, format\nfrom reflex.utils.serializers import serializer\n\n\n@dataclasses.dataclass(frozen=True, init=False)\nclass _FrozenDictStrStr(Mapping[str, str]):\n    _data: MappingProxyType[str, str]\n\n    def __init__(self, **kwargs):\n        object.__setattr__(\n            self, \"_data\", MappingProxyType(dict(sorted(kwargs.items())))\n        )\n\n    def __getitem__(self, key: str) -> str:\n        return self._data[key]\n\n    def __iter__(self):\n        return iter(self._data)\n\n    def __len__(self):\n        return len(self._data)\n\n    def __hash__(self) -> int:\n        return hash(frozenset(self._data.items()))\n\n    def __getstate__(self) -> object:\n        return dict(self._data)\n\n    def __setstate__(self, state: object) -> None:\n        if not isinstance(state, dict):\n            msg = \"Invalid state for _FrozenDictStrStr\"\n            raise TypeError(msg)\n        object.__setattr__(self, \"_data\", MappingProxyType(state))\n\n\n@dataclasses.dataclass(frozen=True)\nclass _HeaderData:\n    host: str = \"\"\n    origin: str = \"\"\n    upgrade: str = \"\"\n    connection: str = \"\"\n    cookie: str = \"\"\n    pragma: str = \"\"\n    cache_control: str = \"\"\n    user_agent: str = \"\"\n    sec_websocket_version: str = \"\"\n    sec_websocket_key: str = \"\"\n    sec_websocket_extensions: str = \"\"\n    accept_encoding: str = \"\"\n    accept_language: str = \"\"\n    raw_headers: Mapping[str, str] = dataclasses.field(\n        default_factory=_FrozenDictStrStr\n    )\n\n\n_HEADER_DATA_FIELDS = frozenset([\n    field.name for field in dataclasses.fields(_HeaderData)\n])\n\n\n@dataclasses.dataclass(frozen=True)\nclass HeaderData(_HeaderData):\n    \"\"\"An object containing headers data.\"\"\"\n\n    @classmethod\n    def from_router_data(cls, router_data: dict) -> \"HeaderData\":\n        \"\"\"Create a HeaderData object from the given router_data.\n\n        Args:\n            router_data: the router_data dict.\n\n        Returns:\n            A HeaderData object initialized with the provided router_data.\n        \"\"\"\n        return cls(\n            **{\n                snake_case_key: v\n                for k, v in router_data.get(constants.RouteVar.HEADERS, {}).items()\n                if v\n                and (snake_case_key := format.to_snake_case(k)) in _HEADER_DATA_FIELDS\n            },\n            raw_headers=_FrozenDictStrStr(**{\n                k: v\n                for k, v in router_data.get(constants.RouteVar.HEADERS, {}).items()\n                if v\n            }),\n        )\n\n\n@serializer(to=dict)\ndef _serialize_header_data(obj: HeaderData) -> dict:\n    return {k.name: getattr(obj, k.name) for k in dataclasses.fields(obj)}\n\n\n@serializer(to=dict)\ndef serialize_frozen_dict_str_str(obj: _FrozenDictStrStr) -> dict:\n    \"\"\"Serialize a _FrozenDictStrStr object to a dict.\n\n    Args:\n        obj: the _FrozenDictStrStr object.\n\n    Returns:\n        A dict representation of the _FrozenDictStrStr object.\n    \"\"\"\n    return dict(obj._data)\n\n\nclass ReflexURL(str, _NetlocResultMixinStr):\n    \"\"\"A class representing a URL split result.\"\"\"\n\n    if TYPE_CHECKING:\n        scheme: str\n        netloc: str\n        origin: str\n        path: str\n        query: str\n        query_parameters: Mapping[str, str]\n        fragment: str\n\n    def __new__(cls, url: str):\n        \"\"\"Create a new ReflexURL instance.\n\n        Args:\n            url: the URL to split.\n\n        Returns:\n            A new ReflexURL instance.\n        \"\"\"\n        (scheme, netloc, path, query, fragment) = urlsplit(url)\n        obj = super().__new__(cls, url)\n        object.__setattr__(obj, \"scheme\", scheme)\n        object.__setattr__(obj, \"netloc\", netloc)\n        object.__setattr__(obj, \"path\", path)\n        object.__setattr__(obj, \"query\", query)\n        object.__setattr__(obj, \"origin\", f\"{scheme}://{netloc}\")\n        object.__setattr__(\n            obj, \"query_parameters\", _FrozenDictStrStr(**dict(parse_qsl(query)))\n        )\n        object.__setattr__(obj, \"fragment\", fragment)\n        return obj\n\n\n@dataclasses.dataclass(frozen=True)\nclass PageData:\n    \"\"\"An object containing page data.\"\"\"\n\n    host: str = \"\"  # repeated with self.headers.origin (remove or keep the duplicate?)\n    path: str = \"\"\n    raw_path: str = \"\"\n    full_path: str = \"\"\n    full_raw_path: str = \"\"\n    params: dict = dataclasses.field(default_factory=dict)\n\n    @classmethod\n    def from_router_data(cls, router_data: dict) -> \"PageData\":\n        \"\"\"Create a PageData object from the given router_data.\n\n        Args:\n            router_data: the router_data dict.\n\n        Returns:\n            A PageData object initialized with the provided router_data.\n        \"\"\"\n        host = router_data.get(constants.RouteVar.HEADERS, {}).get(\"origin\", \"\")\n        path = router_data.get(constants.RouteVar.PATH, \"\")\n        raw_path = router_data.get(constants.RouteVar.ORIGIN, \"\")\n        return cls(\n            host=host,\n            path=path,\n            raw_path=raw_path,\n            full_path=f\"{host}{path}\",\n            full_raw_path=f\"{host}{raw_path}\",\n            params=router_data.get(constants.RouteVar.QUERY, {}),\n        )\n\n\n@serializer(to=dict)\ndef _serialize_page_data(obj: PageData) -> dict:\n    return {key.name: getattr(obj, key.name) for key in dataclasses.fields(obj)}\n\n\n@dataclasses.dataclass(frozen=True)\nclass SessionData:\n    \"\"\"An object containing session data.\"\"\"\n\n    client_token: str = \"\"\n    client_ip: str = \"\"\n    session_id: str = \"\"\n\n    @classmethod\n    def from_router_data(cls, router_data: dict) -> \"SessionData\":\n        \"\"\"Create a SessionData object from the given router_data.\n\n        Args:\n            router_data: the router_data dict.\n\n        Returns:\n            A SessionData object initialized with the provided router_data.\n        \"\"\"\n        return cls(\n            client_token=router_data.get(constants.RouteVar.CLIENT_TOKEN, \"\"),\n            client_ip=router_data.get(constants.RouteVar.CLIENT_IP, \"\"),\n            session_id=router_data.get(constants.RouteVar.SESSION_ID, \"\"),\n        )\n\n\n@serializer(to=dict)\ndef _serialize_session_data(obj: SessionData) -> dict:\n    return {key.name: getattr(obj, key.name) for key in dataclasses.fields(obj)}\n\n\n@dataclasses.dataclass(frozen=True)\nclass RouterData:\n    \"\"\"An object containing RouterData.\"\"\"\n\n    session: SessionData = dataclasses.field(default_factory=SessionData)\n    headers: HeaderData = dataclasses.field(default_factory=HeaderData)\n    _page: PageData = dataclasses.field(default_factory=PageData)\n    url: ReflexURL = dataclasses.field(default=ReflexURL(\"\"))\n    route_id: str = \"\"\n\n    @property\n    def page(self) -> PageData:\n        \"\"\"Get the page data.\n\n        Returns:\n            The PageData object.\n        \"\"\"\n        console.deprecate(\n            feature_name=\"RouterData.page\",\n            reason=\"Use RouterData.url instead\",\n            deprecation_version=\"0.8.1\",\n            removal_version=\"0.9.0\",\n        )\n        return self._page\n\n    @classmethod\n    def from_router_data(cls, router_data: dict) -> \"RouterData\":\n        \"\"\"Create a RouterData object from the given router_data.\n\n        Args:\n            router_data: the router_data dict.\n\n        Returns:\n            A RouterData object initialized with the provided router_data.\n        \"\"\"\n        return cls(\n            session=SessionData.from_router_data(router_data),\n            headers=HeaderData.from_router_data(router_data),\n            _page=PageData.from_router_data(router_data),\n            url=ReflexURL(\n                router_data.get(constants.RouteVar.HEADERS, {}).get(\"origin\", \"\")\n                + router_data.get(constants.RouteVar.ORIGIN, \"\")\n            ),\n            route_id=router_data.get(constants.RouteVar.PATH, \"\"),\n        )\n\n\n@serializer(to=dict)\ndef serialize_router_data(obj: RouterData) -> dict:\n    \"\"\"Serialize a RouterData object to a dict.\n\n    Args:\n        obj: the RouterData object.\n\n    Returns:\n        A dict representation of the RouterData object.\n    \"\"\"\n    return {\n        \"session\": obj.session,\n        \"headers\": obj.headers,\n        \"page\": obj._page,\n        \"url\": obj.url,\n        \"route_id\": obj.route_id,\n    }\n"
  },
  {
    "path": "reflex/istate/dynamic.py",
    "content": "\"\"\"A container for dynamically generated states.\"\"\"\n\n# This page intentionally left blank.\n"
  },
  {
    "path": "reflex/istate/manager/__init__.py",
    "content": "\"\"\"State manager for managing client states.\"\"\"\n\nimport contextlib\nimport dataclasses\nfrom abc import ABC, abstractmethod\nfrom collections.abc import AsyncIterator\nfrom typing import TypedDict\n\nfrom typing_extensions import ReadOnly, Unpack\n\nfrom reflex import constants\nfrom reflex.config import get_config\nfrom reflex.event import Event\nfrom reflex.state import BaseState\nfrom reflex.utils import console, prerequisites\nfrom reflex.utils.exceptions import InvalidStateManagerModeError\n\n\nclass StateModificationContext(TypedDict, total=False):\n    \"\"\"The context for modifying state.\"\"\"\n\n    event: ReadOnly[Event | None]\n\n\nEmptyContext = StateModificationContext()\n\n\n@dataclasses.dataclass\nclass StateManager(ABC):\n    \"\"\"A class to manage many client states.\"\"\"\n\n    # The state class to use.\n    state: type[BaseState]\n\n    @classmethod\n    def create(cls, state: type[BaseState]):\n        \"\"\"Create a new state manager.\n\n        Args:\n            state: The state class to use.\n\n        Returns:\n            The state manager (either disk, memory or redis).\n\n        Raises:\n            InvalidStateManagerModeError: If the state manager mode is invalid.\n        \"\"\"\n        config = get_config()\n        if prerequisites.parse_redis_url() is not None:\n            config.state_manager_mode = constants.StateManagerMode.REDIS\n        if config.state_manager_mode == constants.StateManagerMode.MEMORY:\n            from reflex.istate.manager.memory import StateManagerMemory\n\n            return StateManagerMemory(state=state)\n        if config.state_manager_mode == constants.StateManagerMode.DISK:\n            from reflex.istate.manager.disk import StateManagerDisk\n\n            return StateManagerDisk(state=state)\n        if config.state_manager_mode == constants.StateManagerMode.REDIS:\n            redis = prerequisites.get_redis()\n            if redis is not None:\n                from reflex.istate.manager.redis import StateManagerRedis\n\n                # make sure expiration values are obtained only from the config object on creation\n                return StateManagerRedis(\n                    state=state,\n                    redis=redis,\n                    token_expiration=config.redis_token_expiration,\n                    lock_expiration=config.redis_lock_expiration,\n                    lock_warning_threshold=config.redis_lock_warning_threshold,\n                )\n        msg = f\"Expected one of: DISK, MEMORY, REDIS, got {config.state_manager_mode}\"\n        raise InvalidStateManagerModeError(msg)\n\n    @abstractmethod\n    async def get_state(self, token: str) -> BaseState:\n        \"\"\"Get the state for a token.\n\n        Args:\n            token: The token to get the state for.\n\n        Returns:\n            The state for the token.\n        \"\"\"\n\n    @abstractmethod\n    async def set_state(\n        self,\n        token: str,\n        state: BaseState,\n        **context: Unpack[StateModificationContext],\n    ):\n        \"\"\"Set the state for a token.\n\n        Args:\n            token: The token to set the state for.\n            state: The state to set.\n            context: The state modification context.\n        \"\"\"\n\n    @abstractmethod\n    @contextlib.asynccontextmanager\n    async def modify_state(\n        self, token: str, **context: Unpack[StateModificationContext]\n    ) -> AsyncIterator[BaseState]:\n        \"\"\"Modify the state for a token while holding exclusive lock.\n\n        Args:\n            token: The token to modify the state for.\n            context: The state modification context.\n\n        Yields:\n            The state for the token.\n        \"\"\"\n        yield self.state()\n\n    @contextlib.asynccontextmanager\n    async def modify_state_with_links(\n        self,\n        token: str,\n        previous_dirty_vars: dict[str, set[str]] | None = None,\n        **context: Unpack[StateModificationContext],\n    ) -> AsyncIterator[BaseState]:\n        \"\"\"Modify the state for a token, including linked substates, while holding exclusive lock.\n\n        Args:\n            token: The token to modify the state for.\n            previous_dirty_vars: The previously dirty vars for linked states.\n            context: The state modification context.\n\n        Yields:\n            The state for the token with linked states patched in.\n        \"\"\"\n        async with self.modify_state(token, **context) as root_state:\n            if getattr(root_state, \"_reflex_internal_links\", None) is not None:\n                from reflex.istate.shared import SharedStateBaseInternal\n\n                shared_state = await root_state.get_state(SharedStateBaseInternal)\n                async with shared_state._modify_linked_states(\n                    previous_dirty_vars=previous_dirty_vars\n                ) as _:\n                    yield root_state\n            else:\n                yield root_state\n\n    async def close(self):  # noqa: B027\n        \"\"\"Close the state manager.\"\"\"\n\n\ndef _default_token_expiration() -> int:\n    \"\"\"Get the default token expiration time.\n\n    Returns:\n        The default token expiration time.\n    \"\"\"\n    return get_config().redis_token_expiration\n\n\ndef reset_disk_state_manager():\n    \"\"\"Reset the disk state manager.\"\"\"\n    console.debug(\"Resetting disk state manager.\")\n    states_directory = prerequisites.get_states_dir()\n    if states_directory.exists():\n        for path in states_directory.iterdir():\n            path.unlink()\n\n\ndef get_state_manager() -> StateManager:\n    \"\"\"Get the state manager for the app that is currently running.\n\n    Returns:\n        The state manager.\n    \"\"\"\n    return prerequisites.get_and_validate_app().app.state_manager\n"
  },
  {
    "path": "reflex/istate/manager/disk.py",
    "content": "\"\"\"A state manager that stores states on disk.\"\"\"\n\nimport asyncio\nimport contextlib\nimport dataclasses\nimport functools\nimport time\nfrom collections.abc import AsyncIterator\nfrom hashlib import md5\nfrom pathlib import Path\n\nfrom typing_extensions import Unpack, override\n\nfrom reflex.environment import environment\nfrom reflex.istate.manager import (\n    StateManager,\n    StateModificationContext,\n    _default_token_expiration,\n)\nfrom reflex.state import BaseState, _split_substate_key, _substate_key\nfrom reflex.utils import console, path_ops, prerequisites\nfrom reflex.utils.misc import run_in_thread\n\n\n@dataclasses.dataclass(frozen=True)\nclass QueueItem:\n    \"\"\"An item in the write queue.\"\"\"\n\n    token: str\n    state: BaseState\n    timestamp: float\n\n\n@dataclasses.dataclass\nclass StateManagerDisk(StateManager):\n    \"\"\"A state manager that stores states on disk.\"\"\"\n\n    # The mapping of client ids to states.\n    states: dict[str, BaseState] = dataclasses.field(default_factory=dict)\n\n    # The mutex ensures the dict of mutexes is updated exclusively\n    _state_manager_lock: asyncio.Lock = dataclasses.field(default=asyncio.Lock())\n\n    # The dict of mutexes for each client\n    _states_locks: dict[str, asyncio.Lock] = dataclasses.field(\n        default_factory=dict,\n        init=False,\n    )\n\n    # The token expiration time (s).\n    token_expiration: int = dataclasses.field(default_factory=_default_token_expiration)\n\n    # Last time a token was touched.\n    _token_last_touched: dict[str, float] = dataclasses.field(\n        default_factory=dict,\n        init=False,\n    )\n\n    # Pending writes\n    _write_queue: dict[str, QueueItem] = dataclasses.field(\n        default_factory=dict,\n        init=False,\n    )\n    _write_queue_task: asyncio.Task | None = None\n    _write_debounce_seconds: float = dataclasses.field(\n        default=environment.REFLEX_STATE_MANAGER_DISK_DEBOUNCE_SECONDS.get()\n    )\n\n    def __post_init__(self):\n        \"\"\"Create a new state manager.\"\"\"\n        path_ops.mkdir(self.states_directory)\n\n        self._purge_expired_states()\n\n    @functools.cached_property\n    def states_directory(self) -> Path:\n        \"\"\"Get the states directory.\n\n        Returns:\n            The states directory.\n        \"\"\"\n        return prerequisites.get_states_dir()\n\n    def _purge_expired_states(self):\n        \"\"\"Purge expired states from the disk.\"\"\"\n        for path in path_ops.ls(self.states_directory):\n            # check path is a pickle file\n            if path.suffix != \".pkl\":\n                continue\n\n            # load last edited field from file\n            last_edited = path.stat().st_mtime\n\n            # check if the file is older than the token expiration time\n            if time.time() - last_edited > self.token_expiration:\n                # remove the file\n                path.unlink()\n\n    def token_path(self, token: str) -> Path:\n        \"\"\"Get the path for a token.\n\n        Args:\n            token: The token to get the path for.\n\n        Returns:\n            The path for the token.\n        \"\"\"\n        return (\n            self.states_directory / f\"{md5(token.encode()).hexdigest()}.pkl\"\n        ).absolute()\n\n    async def load_state(self, token: str) -> BaseState | None:\n        \"\"\"Load a state object based on the provided token.\n\n        Args:\n            token: The token used to identify the state object.\n\n        Returns:\n            The loaded state object or None.\n        \"\"\"\n        token_path = self.token_path(token)\n\n        if token_path.exists():\n            try:\n                with token_path.open(mode=\"rb\") as file:\n                    return BaseState._deserialize(fp=file)\n            except Exception:\n                pass\n        return None\n\n    async def populate_substates(\n        self, client_token: str, state: BaseState, root_state: BaseState\n    ):\n        \"\"\"Populate the substates of a state object.\n\n        Args:\n            client_token: The client token.\n            state: The state object to populate.\n            root_state: The root state object.\n        \"\"\"\n        for substate in state.get_substates():\n            substate_token = _substate_key(client_token, substate)\n\n            fresh_instance = await root_state.get_state(substate)\n            instance = await self.load_state(substate_token)\n            if instance is not None:\n                # Ensure all substates exist, even if they weren't serialized previously.\n                instance.substates = fresh_instance.substates\n            else:\n                instance = fresh_instance\n            state.substates[substate.get_name()] = instance\n            instance.parent_state = state\n\n            await self.populate_substates(client_token, instance, root_state)\n\n    @override\n    async def get_state(\n        self,\n        token: str,\n    ) -> BaseState:\n        \"\"\"Get the state for a token.\n\n        Args:\n            token: The token to get the state for.\n\n        Returns:\n            The state for the token.\n        \"\"\"\n        client_token = _split_substate_key(token)[0]\n        self._token_last_touched[client_token] = time.time()\n        root_state = self.states.get(client_token)\n        if root_state is not None:\n            # Retrieved state from memory.\n            return root_state\n\n        # Deserialize root state from disk.\n        root_state = await self.load_state(_substate_key(client_token, self.state))\n        # Create a new root state tree with all substates instantiated.\n        fresh_root_state = self.state(_reflex_internal_init=True)\n        if root_state is None:\n            root_state = fresh_root_state\n        else:\n            # Ensure all substates exist, even if they were not serialized previously.\n            root_state.substates = fresh_root_state.substates\n        self.states[client_token] = root_state\n        await self.populate_substates(client_token, root_state, root_state)\n        return root_state\n\n    async def set_state_for_substate(self, client_token: str, substate: BaseState):\n        \"\"\"Set the state for a substate.\n\n        Args:\n            client_token: The client token.\n            substate: The substate to set.\n        \"\"\"\n        substate_token = _substate_key(client_token, substate)\n\n        if substate._get_was_touched():\n            substate._was_touched = False  # Reset the touched flag after serializing.\n            pickle_state = substate._serialize()\n            if pickle_state:\n                if not self.states_directory.exists():\n                    self.states_directory.mkdir(parents=True, exist_ok=True)\n                await run_in_thread(\n                    lambda: self.token_path(substate_token).write_bytes(pickle_state),\n                )\n\n        for substate_substate in substate.substates.values():\n            await self.set_state_for_substate(client_token, substate_substate)\n\n    async def _process_write_queue_delay(self):\n        \"\"\"Wait for the debounce period before processing the write queue again.\"\"\"\n        now = time.time()\n        if self._write_queue:\n            # There are still items in the queue, schedule another run.\n            next_write_in = max(\n                0,\n                min(\n                    self._write_debounce_seconds - (now - item.timestamp)\n                    for item in self._write_queue.values()\n                ),\n            )\n            await asyncio.sleep(next_write_in)\n        elif self._write_debounce_seconds > 0:\n            # No items left, wait a bit before checking again.\n            await asyncio.sleep(self._write_debounce_seconds)\n        else:\n            # Debounce is disabled, so sleep until the next token expiration.\n            oldest_token_last_touch = min(\n                self._token_last_touched.values(), default=now\n            )\n            next_expiration_in = self.token_expiration - (now - oldest_token_last_touch)\n            await asyncio.sleep(next_expiration_in)\n\n    async def _process_write_queue(self):\n        \"\"\"Long running task that checks for states to write to disk.\n\n        Raises:\n            asyncio.CancelledError: When the task is cancelled.\n        \"\"\"\n        while True:\n            try:\n                now = time.time()\n                # sort the _write_queue by oldest timestamp and exclude items younger than debounce time\n                items_to_write = sorted(\n                    (\n                        item\n                        for item in self._write_queue.values()\n                        if now - item.timestamp >= self._write_debounce_seconds\n                    ),\n                    key=lambda item: item.timestamp,\n                )\n                for item in items_to_write:\n                    token = item.token\n                    client_token, _ = _split_substate_key(token)\n                    await self.set_state_for_substate(\n                        client_token, self._write_queue.pop(token).state\n                    )\n                # Check for expired states to purge.\n                for token, last_touched in list(self._token_last_touched.items()):\n                    if now - last_touched > self.token_expiration:\n                        self._token_last_touched.pop(token)\n                        self.states.pop(token, None)\n                await run_in_thread(self._purge_expired_states)\n                await self._process_write_queue_delay()\n            except asyncio.CancelledError:  # noqa: PERF203\n                await self._flush_write_queue()\n                raise\n            except Exception as e:\n                console.error(f\"Error processing write queue: {e!r}\")\n                if e.args == (\"cannot schedule new futures after shutdown\",):\n                    # Event loop is shutdown, nothing else we can really do...\n                    return\n                await self._process_write_queue_delay()\n\n    async def _flush_write_queue(self):\n        \"\"\"Flush any remaining items in the write queue to disk.\"\"\"\n        outstanding_items = list(self._write_queue.values())\n        n_outstanding_items = len(outstanding_items)\n        self._write_queue.clear()\n        # When the task is cancelled, write all remaining items to disk.\n        console.debug(\n            f\"StateManagerDisk._flush_write_queue: writing {n_outstanding_items} remaining items to disk\"\n        )\n        for item in outstanding_items:\n            token = item.token\n            client_token, _ = _split_substate_key(token)\n            await self.set_state_for_substate(\n                client_token,\n                item.state,\n            )\n        console.debug(\n            f\"StateManagerDisk._flush_write_queue: Finished writing {n_outstanding_items} items\"\n        )\n\n    async def _schedule_process_write_queue(self):\n        \"\"\"Schedule the write queue processing task if not already running.\"\"\"\n        if self._write_queue_task is None or self._write_queue_task.done():\n            async with self._state_manager_lock:\n                if self._write_queue_task is None or self._write_queue_task.done():\n                    self._write_queue_task = asyncio.create_task(\n                        self._process_write_queue(),\n                        name=\"StateManagerDisk|WriteQueueProcessor\",\n                    )\n                    await asyncio.sleep(0)  # Yield to allow the task to start.\n\n    @override\n    async def set_state(\n        self, token: str, state: BaseState, **context: Unpack[StateModificationContext]\n    ):\n        \"\"\"Set the state for a token.\n\n        Args:\n            token: The token to set the state for.\n            state: The state to set.\n            context: The state modification context.\n        \"\"\"\n        client_token, _ = _split_substate_key(token)\n        if self._write_debounce_seconds > 0:\n            # Deferred write to reduce disk IO overhead.\n            if client_token not in self._write_queue:\n                self._write_queue[client_token] = QueueItem(\n                    token=client_token,\n                    state=state,\n                    timestamp=time.time(),\n                )\n        else:\n            # Immediate write to disk.\n            await self.set_state_for_substate(client_token, state)\n        # Ensure the processing task is scheduled to handle expirations and any deferred writes.\n        await self._schedule_process_write_queue()\n\n    @override\n    @contextlib.asynccontextmanager\n    async def modify_state(\n        self, token: str, **context: Unpack[StateModificationContext]\n    ) -> AsyncIterator[BaseState]:\n        \"\"\"Modify the state for a token while holding exclusive lock.\n\n        Args:\n            token: The token to modify the state for.\n            context: The state modification context.\n\n        Yields:\n            The state for the token.\n        \"\"\"\n        # Disk state manager ignores the substate suffix and always returns the top-level state.\n        client_token, _ = _split_substate_key(token)\n        if client_token not in self._states_locks:\n            async with self._state_manager_lock:\n                if client_token not in self._states_locks:\n                    self._states_locks[client_token] = asyncio.Lock()\n\n        async with self._states_locks[client_token]:\n            state = await self.get_state(token)\n            yield state\n            await self.set_state(token, state, **context)\n\n    async def close(self):\n        \"\"\"Close the state manager, flushing any pending writes to disk.\"\"\"\n        async with self._state_manager_lock:\n            if self._write_queue_task:\n                self._write_queue_task.cancel()\n                with contextlib.suppress(asyncio.CancelledError):\n                    await self._write_queue_task\n                    self._write_queue_task = None\n"
  },
  {
    "path": "reflex/istate/manager/memory.py",
    "content": "\"\"\"A state manager that stores states in memory.\"\"\"\n\nimport asyncio\nimport contextlib\nimport dataclasses\nfrom collections.abc import AsyncIterator\n\nfrom typing_extensions import Unpack, override\n\nfrom reflex.istate.manager import StateManager, StateModificationContext\nfrom reflex.state import BaseState, _split_substate_key\n\n\n@dataclasses.dataclass\nclass StateManagerMemory(StateManager):\n    \"\"\"A state manager that stores states in memory.\"\"\"\n\n    # The mapping of client ids to states.\n    states: dict[str, BaseState] = dataclasses.field(default_factory=dict)\n\n    # The mutex ensures the dict of mutexes is updated exclusively\n    _state_manager_lock: asyncio.Lock = dataclasses.field(default=asyncio.Lock())\n\n    # The dict of mutexes for each client\n    _states_locks: dict[str, asyncio.Lock] = dataclasses.field(\n        default_factory=dict, init=False\n    )\n\n    @override\n    async def get_state(self, token: str) -> BaseState:\n        \"\"\"Get the state for a token.\n\n        Args:\n            token: The token to get the state for.\n\n        Returns:\n            The state for the token.\n        \"\"\"\n        # Memory state manager ignores the substate suffix and always returns the top-level state.\n        token = _split_substate_key(token)[0]\n        if token not in self.states:\n            self.states[token] = self.state(_reflex_internal_init=True)\n        return self.states[token]\n\n    @override\n    async def set_state(\n        self,\n        token: str,\n        state: BaseState,\n        **context: Unpack[StateModificationContext],\n    ):\n        \"\"\"Set the state for a token.\n\n        Args:\n            token: The token to set the state for.\n            state: The state to set.\n            context: The state modification context.\n        \"\"\"\n        token = _split_substate_key(token)[0]\n        self.states[token] = state\n\n    @override\n    @contextlib.asynccontextmanager\n    async def modify_state(\n        self, token: str, **context: Unpack[StateModificationContext]\n    ) -> AsyncIterator[BaseState]:\n        \"\"\"Modify the state for a token while holding exclusive lock.\n\n        Args:\n            token: The token to modify the state for.\n            context: The state modification context.\n\n        Yields:\n            The state for the token.\n        \"\"\"\n        # Memory state manager ignores the substate suffix and always returns the top-level state.\n        token = _split_substate_key(token)[0]\n        if token not in self._states_locks:\n            async with self._state_manager_lock:\n                if token not in self._states_locks:\n                    self._states_locks[token] = asyncio.Lock()\n\n        async with self._states_locks[token]:\n            yield await self.get_state(token)\n"
  },
  {
    "path": "reflex/istate/manager/redis.py",
    "content": "\"\"\"A state manager that stores states in redis.\"\"\"\n\nimport asyncio\nimport contextlib\nimport dataclasses\nimport inspect\nimport os\nimport sys\nimport time\nimport uuid\nfrom collections.abc import AsyncIterator\nfrom typing import TypedDict\n\nfrom redis import ResponseError\nfrom redis.asyncio import Redis\nfrom typing_extensions import Unpack, override\n\nfrom reflex.config import get_config\nfrom reflex.environment import environment\nfrom reflex.istate.manager import (\n    StateManager,\n    StateModificationContext,\n    _default_token_expiration,\n)\nfrom reflex.state import BaseState, _split_substate_key, _substate_key\nfrom reflex.utils import console\nfrom reflex.utils.exceptions import (\n    InvalidLockWarningThresholdError,\n    LockExpiredError,\n    StateSchemaMismatchError,\n)\nfrom reflex.utils.tasks import ensure_task\n\n\ndef _default_lock_expiration() -> int:\n    \"\"\"Get the default lock expiration time.\n\n    Returns:\n        The default lock expiration time.\n    \"\"\"\n    return get_config().redis_lock_expiration\n\n\ndef _default_lock_warning_threshold() -> int:\n    \"\"\"Get the default lock warning threshold.\n\n    Returns:\n        The default lock warning threshold.\n    \"\"\"\n    return get_config().redis_lock_warning_threshold\n\n\ndef _default_oplock_hold_time_ms() -> int:\n    \"\"\"Get the default opportunistic lock hold time.\n\n    Returns:\n        The default opportunistic lock hold time.\n    \"\"\"\n    return environment.REFLEX_OPLOCK_HOLD_TIME_MS.get() or (\n        _default_lock_expiration() // 2\n    )\n\n\n# The lock waiter task should subscribe to lock channel updates within this period.\nLOCK_SUBSCRIBE_TASK_TIMEOUT = 2  # seconds\n\n\nSMR = f\"[SMR:{os.getpid()}]\"\nstart = time.monotonic()\n\n\nclass RedisPubSubMessage(TypedDict):\n    \"\"\"A Redis Pub/Sub message.\"\"\"\n\n    type: str\n    pattern: bytes | None\n    channel: bytes\n    data: bytes | int\n\n\nclass OplockFound(Exception):  # noqa: N818\n    \"\"\"Indicates that an opportunistic lock was found.\"\"\"\n\n\n@dataclasses.dataclass\nclass StateManagerRedis(StateManager):\n    \"\"\"A state manager that stores states in redis.\"\"\"\n\n    # The redis client to use.\n    redis: Redis\n\n    # The token expiration time (s).\n    token_expiration: int = dataclasses.field(default_factory=_default_token_expiration)\n\n    # The maximum time to hold a lock (ms).\n    lock_expiration: int = dataclasses.field(default_factory=_default_lock_expiration)\n\n    # The maximum time to hold a lock (ms) before warning.\n    lock_warning_threshold: int = dataclasses.field(\n        default_factory=_default_lock_warning_threshold\n    )\n\n    # How long to opportunistically hold the redis lock in milliseconds (must be less than the token expiration).\n    oplock_hold_time_ms: int = dataclasses.field(\n        default_factory=_default_oplock_hold_time_ms\n    )\n\n    # The keyspace subscription string when redis is waiting for lock to be released.\n    _redis_notify_keyspace_events: str = dataclasses.field(\n        default=\"K\"  # Enable keyspace notifications (target a particular key)\n        \"$\"  # For String commands (like setting keys)\n        \"s\"  # For Set commands (SADD, SREM, etc)\n        \"g\"  # For generic commands (DEL, EXPIRE, etc)\n        \"x\"  # For expired events\n        \"e\"  # For evicted events (i.e. maxmemory exceeded)\n    )\n\n    # These events indicate that a lock is no longer held.\n    _redis_keyspace_lock_release_events: set[bytes] = dataclasses.field(\n        default_factory=lambda: {\n            b\"del\",\n            b\"expired\",\n            b\"evicted\",\n        }\n    )\n\n    # Whether keyspace notifications have been enabled.\n    _redis_notify_keyspace_events_enabled: bool = dataclasses.field(default=False)\n\n    # The mutex ensures the dict of mutexes is updated exclusively\n    _state_manager_lock: asyncio.Lock = dataclasses.field(\n        default=asyncio.Lock(), init=False\n    )\n\n    # Whether to opportunistically hold locks for fast in-memory access.\n    _oplock_enabled: bool = dataclasses.field(\n        default_factory=environment.REFLEX_OPLOCK_ENABLED.get, init=False\n    )\n\n    # Cached states\n    _cached_states: dict[str, BaseState] = dataclasses.field(\n        default_factory=dict, init=False\n    )\n    _cached_states_locks: dict[str, asyncio.Lock] = dataclasses.field(\n        default_factory=dict, init=False\n    )\n\n    # Local Leases (token -> flush task)\n    _local_leases: dict[str, asyncio.Task] = dataclasses.field(\n        default_factory=dict, init=False\n    )\n    # The unique ID for this state manager, the domain for _local_leases.\n    _instance_id: str = dataclasses.field(default_factory=lambda: str(uuid.uuid4()))\n\n    # Lock waiters for redis per-token lock.\n    _lock_waiters: dict[bytes, list[asyncio.Event]] = dataclasses.field(\n        default_factory=dict,\n        init=False,\n    )\n    _lock_updates_subscribed: asyncio.Event = dataclasses.field(\n        default_factory=asyncio.Event,\n        init=False,\n    )\n    _lock_task: asyncio.Task | None = dataclasses.field(default=None, init=False)\n\n    # Whether debug prints are enabled.\n    _debug_enabled: bool = dataclasses.field(\n        default=environment.REFLEX_STATE_MANAGER_REDIS_DEBUG.get(),\n        init=False,\n    )\n\n    def __post_init__(self):\n        \"\"\"Validate the lock warning threshold.\n\n        Raises:\n            InvalidLockWarningThresholdError: If the lock warning threshold is invalid.\n        \"\"\"\n        if self.lock_warning_threshold >= (lock_expiration := self.lock_expiration):\n            msg = f\"The lock warning threshold({self.lock_warning_threshold}) must be less than the lock expiration time({lock_expiration}).\"\n            raise InvalidLockWarningThresholdError(msg)\n        if self._oplock_enabled and self.oplock_hold_time_ms >= lock_expiration:\n            msg = f\"The opportunistic lock hold time({self.oplock_hold_time_ms}) must be less than the lock expiration time({lock_expiration}).\"\n            raise InvalidLockWarningThresholdError(msg)\n        with contextlib.suppress(RuntimeError):\n            asyncio.get_running_loop()  # Check if we're in an event loop.\n            self._ensure_lock_task()\n\n    def _get_required_state_classes(\n        self,\n        target_state_cls: type[BaseState],\n        subclasses: bool = False,\n        required_state_classes: set[type[BaseState]] | None = None,\n    ) -> set[type[BaseState]]:\n        \"\"\"Recursively determine which states are required to fetch the target state.\n\n        This will always include potentially dirty substates that depend on vars\n        in the target_state_cls.\n\n        Args:\n            target_state_cls: The target state class being fetched.\n            subclasses: Whether to include subclasses of the target state.\n            required_state_classes: Recursive argument tracking state classes that have already been seen.\n\n        Returns:\n            The set of state classes required to fetch the target state.\n        \"\"\"\n        if required_state_classes is None:\n            required_state_classes = set()\n        # Get the substates if requested.\n        if subclasses:\n            for substate in target_state_cls.get_substates():\n                self._get_required_state_classes(\n                    substate,\n                    subclasses=True,\n                    required_state_classes=required_state_classes,\n                )\n        if target_state_cls in required_state_classes:\n            return required_state_classes\n        required_state_classes.add(target_state_cls)\n\n        # Get dependent substates.\n        for pd_substates in target_state_cls._get_potentially_dirty_states():\n            self._get_required_state_classes(\n                pd_substates,\n                subclasses=False,\n                required_state_classes=required_state_classes,\n            )\n\n        # Get the parent state if it exists.\n        if parent_state := target_state_cls.get_parent_state():\n            self._get_required_state_classes(\n                parent_state,\n                subclasses=False,\n                required_state_classes=required_state_classes,\n            )\n        return required_state_classes\n\n    def _get_populated_states(\n        self,\n        target_state: BaseState,\n        populated_states: dict[str, BaseState] | None = None,\n    ) -> dict[str, BaseState]:\n        \"\"\"Recursively determine which states from target_state are already fetched.\n\n        Args:\n            target_state: The state to check for populated states.\n            populated_states: Recursive argument tracking states seen in previous calls.\n\n        Returns:\n            A dictionary of state full name to state instance.\n        \"\"\"\n        if populated_states is None:\n            populated_states = {}\n        if target_state.get_full_name() in populated_states:\n            return populated_states\n        populated_states[target_state.get_full_name()] = target_state\n        for substate in target_state.substates.values():\n            self._get_populated_states(substate, populated_states=populated_states)\n        if target_state.parent_state is not None:\n            self._get_populated_states(\n                target_state.parent_state, populated_states=populated_states\n            )\n        return populated_states\n\n    @override\n    async def get_state(\n        self,\n        token: str,\n        top_level: bool = True,\n        for_state_instance: BaseState | None = None,\n    ) -> BaseState:\n        \"\"\"Get the state for a token.\n\n        Args:\n            token: The token to get the state for.\n            top_level: If true, return an instance of the top-level state (self.state).\n            for_state_instance: If provided, attach the requested states to this existing state tree.\n\n        Returns:\n            The state for the token.\n\n        Raises:\n            RuntimeError: when the state_cls is not specified in the token, or when the parent state for a\n                requested state was not fetched.\n        \"\"\"\n        # Split the actual token from the fully qualified substate name.\n        token, state_path = _split_substate_key(token)\n        if state_path:\n            # Get the State class associated with the given path.\n            requested_state_cls = self.state.get_class_substate(state_path)\n        else:\n            msg = f\"StateManagerRedis requires token to be specified in the form of {{token}}_{{state_full_name}}, but got {token}\"\n            raise RuntimeError(msg)\n\n        # Determine which states we already have.\n        flat_state_tree: dict[str, BaseState] = (\n            self._get_populated_states(for_state_instance) if for_state_instance else {}\n        )\n\n        # Determine which states from the tree need to be fetched.\n        required_state_classes = sorted(\n            self._get_required_state_classes(requested_state_cls, subclasses=True)\n            - {type(s) for s in flat_state_tree.values()},\n            key=lambda x: x.get_full_name(),\n        )\n\n        redis_pipeline = self.redis.pipeline()\n        for state_cls in required_state_classes:\n            redis_pipeline.get(_substate_key(token, state_cls))\n\n        for state_cls, redis_state in zip(\n            required_state_classes,\n            await redis_pipeline.execute(),\n            strict=False,\n        ):\n            state = None\n\n            if redis_state is not None:\n                # Deserialize the substate.\n                with contextlib.suppress(StateSchemaMismatchError):\n                    state = BaseState._deserialize(data=redis_state)\n            if state is None:\n                # Key didn't exist or schema mismatch so create a new instance for this token.\n                state = state_cls(\n                    init_substates=False,\n                    _reflex_internal_init=True,\n                )\n            flat_state_tree[state.get_full_name()] = state\n            if state.get_parent_state() is not None:\n                parent_state_name, _dot, state_name = state.get_full_name().rpartition(\n                    \".\"\n                )\n                parent_state = flat_state_tree.get(parent_state_name)\n                if parent_state is None:\n                    msg = (\n                        f\"Parent state for {state.get_full_name()} was not found \"\n                        \"in the state tree, but should have already been fetched. \"\n                        \"This is a bug\"\n                    )\n                    raise RuntimeError(msg)\n                parent_state.substates[state_name] = state\n                state.parent_state = parent_state\n\n        # To retain compatibility with previous implementation, by default, we return\n        # the top-level state which should always be fetched or already cached.\n        if top_level:\n            return flat_state_tree[self.state.get_full_name()]\n        return flat_state_tree[requested_state_cls.get_full_name()]\n\n    @override\n    async def set_state(\n        self,\n        token: str,\n        state: BaseState,\n        *,\n        lock_id: bytes | None = None,\n        **context: Unpack[StateModificationContext],\n    ):\n        \"\"\"Set the state for a token.\n\n        Args:\n            token: The token to set the state for.\n            state: The state to set.\n            lock_id: If provided, the lock_key must be set to this value to set the state.\n            context: The event context.\n\n        Raises:\n            LockExpiredError: If lock_id is provided and the lock for the token is not held by that ID.\n            RuntimeError: If the state instance doesn't match the state name in the token.\n        \"\"\"\n        # Check that we're holding the lock.\n        if (\n            lock_id is not None\n            and (existing_lock_id := await self.redis.get(self._lock_key(token)))\n            != lock_id\n        ):\n            msg = (\n                f\"Lock expired for token {token} while processing. Consider increasing \"\n                f\"`app.state_manager.lock_expiration` (currently {self.lock_expiration}) \"\n                \"or use `@rx.event(background=True)` decorator for long-running tasks. \"\n                f\"Current lock id: {existing_lock_id!r}, expected lock id: {lock_id!r}.\"\n                + (\n                    f\" Happened in event: {event.name}\"\n                    if (event := context.get(\"event\")) is not None\n                    else \"\"\n                )\n            )\n            raise LockExpiredError(msg)\n\n        client_token, substate_name = _split_substate_key(token)\n\n        if lock_id is not None and client_token not in self._local_leases:\n            time_taken = (\n                self.lock_expiration - (await self.redis.pttl(self._lock_key(token)))\n            ) / 1000\n            if time_taken > self.lock_warning_threshold / 1000:\n                console.warn(\n                    f\"Lock for token {token} was held too long {time_taken=}s, \"\n                    f\"use `@rx.event(background=True)` decorator for long-running tasks.\"\n                    + (\n                        f\" Happened in event: {event.name}\"\n                        if (event := context.get(\"event\")) is not None\n                        else \"\"\n                    ),\n                    dedupe=True,\n                )\n\n        # If the substate name on the token doesn't match the instance name, it cannot have a parent.\n        if state.parent_state is not None and state.get_full_name() != substate_name:\n            msg = f\"Cannot `set_state` with mismatching token {token} and substate {state.get_full_name()}.\"\n            raise RuntimeError(msg)\n\n        # Recursively set_state on all known substates.\n        tasks = [\n            asyncio.create_task(\n                self.set_state(\n                    _substate_key(client_token, substate),\n                    substate,\n                    lock_id=lock_id,\n                    **context,\n                ),\n                name=f\"reflex_set_state|{client_token}|{substate.get_full_name()}\",\n            )\n            for substate in state.substates.values()\n        ]\n        # Persist only the given state (parents or substates are excluded by BaseState.__getstate__).\n        if state._get_was_touched():\n            pickle_state = state._serialize()\n            if pickle_state:\n                await self.redis.set(\n                    _substate_key(client_token, state),\n                    pickle_state,\n                    ex=self.token_expiration,\n                )\n\n        # Wait for substates to be persisted.\n        for t in tasks:\n            await t\n\n    @contextlib.asynccontextmanager\n    async def _try_modify_state(\n        self, token: str, **context: Unpack[StateModificationContext]\n    ) -> AsyncIterator[BaseState | None]:\n        \"\"\"Modify the state for a token while holding exclusive lock.\n\n        Args:\n            token: The token to modify the state for.\n            context: The state modification context.\n\n        Yields:\n            The state for the token or None if we couldn't get the lock.\n        \"\"\"\n        event_name = event.name if (event := context.get(\"event\")) is not None else None\n        if not self._oplock_enabled:\n            # OpLock is disabled, get a fresh lock, write, and release.\n            async with self._lock(token, event_name=event_name) as lock_id:\n                state = await self.get_state(token)\n                yield state\n                await self.set_state(token, state, lock_id=lock_id, **context)\n            return\n\n        # Opportunistically reuse existing lock.\n        async with self._get_state_cached(token) as cached_state:\n            if cached_state is not None:\n                yield cached_state\n                self._notify_next_waiter(self._lock_key(token))\n                return\n\n        # Opportunistic locking is enabled, so try to hold the lock across multiple calls.\n        client_token, _ = _split_substate_key(token)\n        lock_held_ctx = contextlib.AsyncExitStack()\n        try:\n            lock_id = await lock_held_ctx.enter_async_context(\n                self._lock(token, event_name=event_name)\n            )\n        except OplockFound:\n            # While waiting for the lock, another process has acquired it, but we can piggy back.\n            pass\n        else:\n            # Do not create a lease break task when multiple instances are waiting.\n            if (\n                not await self._get_local_lease(client_token)\n                and await self._n_lock_contenders(self._lock_key(token)) > 0\n            ):\n                if self._debug_enabled:\n                    console.debug(\n                        f\"{SMR} [{time.monotonic() - start:.3f}] {client_token} has contention, not leasing\"\n                    )\n                async with lock_held_ctx:\n                    state = await self.get_state(token)\n                    yield state\n                    await self.set_state(token, state, lock_id=lock_id, **context)\n                return\n\n            # Create the lease break task since we got the lock.\n            if (\n                new_lease_task := await self._create_lease_break_task(\n                    token, lock_id, cleanup_ctx=lock_held_ctx, **context\n                )\n            ) is (\n                current_lease_task := await self._get_local_lease(client_token)\n            ) and new_lease_task is not None:\n                if self._debug_enabled:\n                    console.debug(\n                        f\"{SMR} [{time.monotonic() - start:.3f}] {client_token} obtained lock {lock_id.decode()}.\"\n                    )\n            elif current_lease_task is None:\n                # Check if we still have the redis lock, then just try to send this one update and release it.\n                await self._try_extend_lock(self._lock_key(token))\n                if await self.redis.get(self._lock_key(token)) == lock_id:\n                    if self._debug_enabled:\n                        console.debug(\n                            f\"{SMR} [{time.monotonic() - start:.3f}] {client_token} holding lock {lock_id.decode()}, {new_lease_task=} already exited, doing single update...\"\n                        )\n                    async with lock_held_ctx:\n                        state = await self.get_state(token)\n                        yield state\n                        await self.set_state(token, state, lock_id=lock_id, **context)\n                    return\n                elif self._debug_enabled:\n                    console.debug(\n                        f\"{SMR} [{time.monotonic() - start:.3f}] {client_token} lock {lock_id.decode()} expired while waiting for lease task to exit...\"\n                    )\n        # Have to retry getting the state, but now it's probably cached.\n        yield None\n\n    @override\n    @contextlib.asynccontextmanager\n    async def modify_state(\n        self, token: str, **context: Unpack[StateModificationContext]\n    ) -> AsyncIterator[BaseState]:\n        \"\"\"Modify the state for a token while holding exclusive lock.\n\n        Args:\n            token: The token to modify the state for.\n            context: The state modification context.\n\n        Yields:\n            The state for the token.\n        \"\"\"\n        while True:\n            async with self._try_modify_state(token, **context) as state_instance:\n                if state_instance is not None:\n                    yield state_instance\n                    return\n\n    @contextlib.asynccontextmanager\n    async def _get_state_cached(self, token: str) -> AsyncIterator[BaseState | None]:\n        \"\"\"Get the cached state for a token, while holding the local lease lock.\n\n        Args:\n            token: The token to get the cached state for.\n\n        Yields:\n            The cached state for the token, or None if not cached/uncachable.\n\n        Raises:\n            RuntimeError: when the state_cls is not specified in the token.\n        \"\"\"\n        client_token, state_path = _split_substate_key(token)\n        # Opportunistically reuse existing lock.\n        if (\n            client_token in self._local_leases\n            and (state_lock := self._cached_states_locks.get(client_token)) is not None\n        ):\n            async with state_lock:\n                if await self._get_local_lease(client_token) is not None:\n                    if (\n                        cached_state := self._cached_states.get(client_token)\n                    ) is not None:\n                        # Make sure we have the substate cached (or fetch it from redis).\n                        try:\n                            substate = cached_state.get_substate(state_path.split(\".\"))\n                            if len(substate.substates) != len(\n                                type(substate).get_substates()\n                            ):\n                                # If the substate is missing substates, we need to refetch it.\n                                raise ValueError  # noqa: TRY301\n                        except ValueError:\n                            await self.get_state(token, for_state_instance=cached_state)\n                        yield cached_state\n                        return\n                    elif self._debug_enabled:\n                        console.debug(\n                            f\"{SMR} [{time.monotonic() - start:.3f}] {client_token} lease task found, lock held, but no cached state\"\n                        )\n                elif self._debug_enabled:\n                    console.debug(\n                        f\"{SMR} [{time.monotonic() - start:.3f}] {client_token} no active lease task found\"\n                    )\n        yield None\n\n    def _notify_next_waiter(self, key: bytes):\n        \"\"\"Notify the next waiter for a given lock key.\n\n        Args:\n            key: The redis lock key.\n        \"\"\"\n        # Notify the next un-notified waiter, if any.\n        for event in self._lock_waiters.get(key, ()):\n            if not event.is_set():\n                event.set()\n                if self._debug_enabled:\n                    console.debug(\n                        f\"{SMR} [{time.monotonic() - start:.3f}] {key.decode()} NOTIFY 1 / {len(self._lock_waiters[key])} waiters {event=}\"\n                    )\n                break\n\n    async def _create_lease_break_task(\n        self,\n        token: str,\n        lock_id: bytes,\n        cleanup_ctx: contextlib.AsyncExitStack,\n        **context: Unpack[StateModificationContext],\n    ) -> asyncio.Task | None:\n        \"\"\"Create a background task to break the local lease after lock expiration.\n\n        Args:\n            token: The token to create the lease break task for.\n            lock_id: The ID of the lock.\n            cleanup_ctx: Enter this context while running the lease break task.\n            context: The state modification context.\n\n        Returns:\n            The lease break task, or None when there is contention.\n        \"\"\"\n        self._ensure_lock_task()\n\n        client_token, _ = _split_substate_key(token)\n\n        async def do_flush() -> None:\n            if (state_lock := self._cached_states_locks.get(client_token)) is None:\n                # If we lost the lock, we can't write the state, something went wrong.\n                console.warn(\n                    f\"State lock for {client_token} missing while finalizing lease.\"\n                )\n                return\n            async with state_lock:\n                # Write the state to redis while no one else can modify the cached copy.\n                state = self._cached_states.pop(client_token, None)\n                try:\n                    if state:\n                        if self._debug_enabled:\n                            console.debug(\n                                f\"{SMR} [{time.monotonic() - start:.3f}] {client_token} lease breaker {lock_id.decode()} flushing state\"\n                            )\n                        await self.set_state(token, state, lock_id=lock_id, **context)\n                finally:\n                    if (current_lease := self._local_leases.get(client_token)) is task:\n                        self._local_leases.pop(client_token, None)\n                        # TODO: clean up the cached states locks periodically\n                    elif self._debug_enabled:\n                        console.debug(\n                            f\"{SMR} [{time.monotonic() - start:.3f}] {client_token} lease breaker {lock_id.decode()} cleanup of {task=} found different task in _local_leases {current_lease=}.\"\n                        )\n\n        async def lease_breaker():\n            cancelled_error: asyncio.CancelledError | None = None\n            async with cleanup_ctx:\n                lease_break_time = self.oplock_hold_time_ms / 1000\n                if self._debug_enabled:\n                    console.debug(\n                        f\"{SMR} [{time.monotonic() - start:.3f}] {client_token} lease breaker {lock_id.decode()} started, sleeping for {lease_break_time}s\"\n                    )\n                try:\n                    await asyncio.sleep(lease_break_time)\n                except asyncio.CancelledError as err:\n                    cancelled_error = err\n                    # We got cancelled so if someone is holding the lock,\n                    # extend the timeout so they get the full time to complete.\n                    if (\n                        state_lock := self._cached_states_locks[client_token]\n                    ) is not None and state_lock.locked():\n                        await self._try_extend_lock(self._lock_key(token))\n                try:\n                    # Shield the flush from cancellation to ensure it always runs to completion.\n                    await asyncio.shield(do_flush())\n                except Exception as e:\n                    # Propagate exception to the main loop, since we have nowhere to catch it.\n                    if not isinstance(e, asyncio.CancelledError):\n                        asyncio.get_running_loop().call_exception_handler({\n                            \"message\": \"Exception in Redis State Manager lease breaker\",\n                            \"exception\": e,\n                        })\n                    raise\n                finally:\n                    # Re-raise any cancellation error after cleaning up.\n                    if cancelled_error is not None:\n                        raise cancelled_error\n\n        if (state_lock := self._cached_states_locks.get(client_token)) is not None:\n            # We have an existing lock, so lets see if we have an existing lease to cancel.\n            async with state_lock:\n                if (existing_task := self._local_leases.get(client_token)) is not None:\n                    # There's already a lease break task, so cancel it to clear it out.\n                    existing_task.cancel()\n            if existing_task is not None:\n                with contextlib.suppress(asyncio.CancelledError):\n                    await existing_task\n\n        # Now we might need to create a new lock.\n        if (state_lock := self._cached_states_locks.get(client_token)) is None:\n            async with self._state_manager_lock:\n                if (state_lock := self._cached_states_locks.get(client_token)) is None:\n                    state_lock = self._cached_states_locks[client_token] = (\n                        asyncio.Lock()\n                    )\n\n        async with state_lock:\n            # Create the task now if one didn't sneak past us.\n            if (\n                client_token not in self._local_leases\n                and await self._n_lock_contenders(self._lock_key(token)) == 0\n            ):\n                self._local_leases[client_token] = task = asyncio.create_task(\n                    lease_breaker(),\n                    name=f\"reflex_lease_breaker|{client_token}|{lock_id.decode()}\",\n                )\n                # Fetch the requested state into the cache.\n                self._cached_states[client_token] = await self.get_state(token)\n                return task\n        return None\n\n    @staticmethod\n    def _lock_key(token: str) -> bytes:\n        \"\"\"Get the redis key for a token's lock.\n\n        Args:\n            token: The token to get the lock key for.\n\n        Returns:\n            The redis lock key for the token.\n        \"\"\"\n        # All substates share the same lock domain, so ignore any substate path suffix.\n        client_token = _split_substate_key(token)[0]\n        return f\"{client_token}_lock\".encode()\n\n    async def _try_extend_lock(self, lock_key: bytes) -> bool | None:\n        \"\"\"Extends the current lock for another lock_expiration period.\n\n        Does not change ownership of the lock!\n\n        Args:\n            lock_key: The redis key for the lock.\n\n        Returns:\n            True if the lock was extended.\n        \"\"\"\n        return await self.redis.pexpire(lock_key, self.lock_expiration, xx=True)\n\n    async def _try_get_lock(self, lock_key: bytes, lock_id: bytes) -> bool | None:\n        \"\"\"Try to get a redis lock for a token.\n\n        Args:\n            lock_key: The redis key for the lock.\n            lock_id: The ID of the lock.\n\n        Returns:\n            True if the lock was obtained.\n        \"\"\"\n        return await self.redis.set(\n            lock_key,\n            lock_id,\n            px=self.lock_expiration,\n            nx=True,  # only set if it doesn't exist\n        )\n\n    async def _handle_lock_release(self, message: RedisPubSubMessage) -> None:\n        \"\"\"Handle a lock release message from redis.\n\n        Args:\n            message: The redis message.\n        \"\"\"\n        if message[\"data\"] in self._redis_keyspace_lock_release_events:\n            key = message[\"channel\"].split(b\":\", 1)[1]\n            if key in self._lock_waiters:\n                self._notify_next_waiter(key)\n\n    async def _handle_lock_contention(self, message: RedisPubSubMessage) -> None:\n        \"\"\"Handle a lock contention message from redis.\n\n        Args:\n            message: The redis message.\n        \"\"\"\n        # Opportunistic lock contention notification.\n        token = message[\"channel\"].rsplit(b\":\", 1)[1][: -len(b\"_lock_waiters\")].decode()\n        if (\n            message[\"data\"] == b\"sadd\"\n            and (state_lock := self._cached_states_locks.get(token)) is not None\n        ):\n            # Cancel the lease break task to force a lock reacquisition.\n            async with state_lock:\n                if (lease_task := await self._get_local_lease(token)) is not None:\n                    lease_task.cancel()\n                    if self._debug_enabled:\n                        console.debug(\n                            f\"{SMR} [{time.monotonic() - start:.3f}] {token} OPLOCK CONTEND - lease break task cancelled {lease_task=}\"\n                        )\n\n    async def _subscribe_lock_updates(self):\n        \"\"\"Subscribe to redis keyspace notifications for lock updates.\"\"\"\n        await self._enable_keyspace_notifications()\n        redis_db = self.redis.get_connection_kwargs().get(\"db\", 0)\n\n        lock_key_pattern = f\"__keyspace@{redis_db}__:*_lock\"\n        lock_waiter_key_pattern = f\"__keyspace@{redis_db}__:*_lock_waiters\"\n        handlers = {\n            lock_key_pattern: self._handle_lock_release,\n            lock_waiter_key_pattern: self._handle_lock_contention,\n        }\n        async with self.redis.pubsub() as pubsub:\n            await pubsub.psubscribe(**handlers)  # pyright: ignore[reportArgumentType]\n            self._lock_updates_subscribed.set()\n            try:\n                async for _ in pubsub.listen():\n                    pass\n            finally:\n                self._lock_updates_subscribed.clear()\n\n    def _ensure_lock_task(self) -> None:\n        \"\"\"Ensure the lock updates subscriber task is running.\"\"\"\n        ensure_task(\n            owner=self,\n            task_attribute=\"_lock_task\",\n            coro_function=self._subscribe_lock_updates,\n            suppress_exceptions=[Exception],\n        )\n\n    async def _ensure_lock_task_subscribed(self, timeout: float | None = None) -> None:\n        \"\"\"Ensure the lock updates subscriber task is running and subscribed to avoid missing notifications.\n\n        Args:\n            timeout: How long to wait for the subscriber to be subscribed before\n                raising an error. If None, defaults to\n                min(LOCK_SUBSCRIBE_TASK_TIMEOUT, lock_expiration).\n\n        Raises:\n            TimeoutError: If the lock updates subscriber task fails to subscribe in time.\n        \"\"\"\n        if timeout is None:\n            timeout = min(\n                LOCK_SUBSCRIBE_TASK_TIMEOUT,\n                max(self.lock_expiration / 1000, 0),\n            )\n        # Make sure lock waiter task is running.\n        self._ensure_lock_task()\n        # Make sure the lock waiter is subscribed to avoid missing notifications.\n        await asyncio.wait_for(\n            self._lock_updates_subscribed.wait(),\n            timeout=timeout,\n        )\n\n    async def _enable_keyspace_notifications(self):\n        \"\"\"Enable keyspace notifications for the redis server.\n\n        Raises:\n            ResponseError: when the keyspace config cannot be set.\n        \"\"\"\n        if self._redis_notify_keyspace_events_enabled:\n            return\n\n        try:\n            await self.redis.config_set(\n                \"notify-keyspace-events\",\n                self._redis_notify_keyspace_events,\n            )\n        except ResponseError:\n            # Some redis servers only allow out-of-band configuration, so ignore errors here.\n            if not environment.REFLEX_IGNORE_REDIS_CONFIG_ERROR.get():\n                raise\n        self._redis_notify_keyspace_events_enabled = True\n\n    @contextlib.asynccontextmanager\n    async def _lock_waiter(self, lock_key: bytes) -> AsyncIterator[asyncio.Event]:\n        \"\"\"Create a lock waiter for a given lock key.\n\n        Args:\n            lock_key: The redis key for the lock.\n\n        Yields:\n            The event that will be set when the lock is released.\n        \"\"\"\n        lock_released_events = self._lock_waiters.get(lock_key)\n        if lock_released_events is None:\n            # Create a new or get existing set of waiters in manager lock.\n            async with self._state_manager_lock:\n                lock_released_events = self._lock_waiters.setdefault(lock_key, [])\n        lock_released_event = asyncio.Event()\n        lock_released_events.append(lock_released_event)\n        try:\n            yield lock_released_event\n        finally:\n            # Set before removing to signal that we don't care about it anymore.\n            lock_released_event.set()\n            # Clean up the waiter\n            lock_released_events.remove(lock_released_event)\n            if not lock_released_events:\n                # Try to clean up the whole set if empty.\n                async with self._state_manager_lock:\n                    if not lock_released_events:\n                        self._lock_waiters.pop(lock_key, None)\n\n    def _n_lock_waiters(self, lock_key: bytes) -> int:\n        \"\"\"Get the number of local waiters for a given lock key.\n\n        Args:\n            lock_key: The redis key for the lock.\n\n        Returns:\n            The number of waiters for the lock key on this instance.\n        \"\"\"\n        lock_released_events = self._lock_waiters.get(lock_key)\n        if lock_released_events is None:\n            return 0\n        return len(lock_released_events)\n\n    async def _n_lock_contenders(self, lock_key: bytes) -> int:\n        \"\"\"Get the number of contenders for a given lock key.\n\n        Args:\n            lock_key: The redis key for the lock.\n\n        Returns:\n            The number of contenders for the lock key across all instances.\n        \"\"\"\n        res = self.redis.scard(lock_key + b\"_waiters\")\n        if inspect.isawaitable(res):\n            res = await res\n        return res\n\n    @contextlib.asynccontextmanager\n    async def _request_lock_release(\n        self, lock_key: bytes, lock_id: bytes\n    ) -> AsyncIterator[None]:\n        \"\"\"Request the release of a redis lock.\n\n        Args:\n            lock_key: The redis key for the lock.\n            lock_id: The ID of the lock.\n        \"\"\"\n        if not self._oplock_enabled:\n            yield\n            return\n\n        lock_waiter_key = lock_key + b\"_waiters\"\n        pipeline = self.redis.pipeline()\n        # Signal intention to request oplock for this process.\n        pipeline.sadd(lock_waiter_key, self._instance_id)\n        pipeline.pexpire(lock_waiter_key, self.lock_expiration)\n        await pipeline.execute()\n        try:\n            yield  # Waiting for redis/oplock to be acquired.\n        finally:\n            res = self.redis.srem(lock_waiter_key, self._instance_id)\n            if inspect.isawaitable(res):\n                await res\n\n    async def _get_local_lease(\n        self, token: str, raise_when_found: bool = False\n    ) -> asyncio.Task | None:\n        \"\"\"Check if there is a local lease for a token.\n\n        Args:\n            token: The token to check for a local lease.\n            raise_when_found: If true, raise OplockFound when a local lease is found.\n\n        Returns:\n            The local lease task if found, None otherwise.\n\n        Raises:\n            OplockFound: If there is a local lease for the token and raise_when_found is True.\n        \"\"\"\n        if (\n            self._oplock_enabled\n            and (lease_task := self._local_leases.get(token)) is not None\n            and not lease_task.done()\n            and not lease_task.cancelled()\n            and (sys.version_info < (3, 11) or not lease_task.cancelling())\n        ):\n            if raise_when_found:\n                raise OplockFound\n            return lease_task\n        return None\n\n    async def _wait_lock(self, lock_key: bytes, lock_id: bytes) -> None:\n        \"\"\"Wait for a redis lock to be released via pubsub.\n\n        Coroutine will not return until the lock is obtained.\n\n        It _might_ raise OplockFound if another coroutine in this process did\n        get the lock and Oplock is enabled.\n\n        Args:\n            lock_key: The redis key for the lock.\n            lock_id: The ID of the lock.\n        \"\"\"\n        token = lock_key.decode().rsplit(\"_lock\", 1)[0]\n        if (\n            # If there's not a line, try to get the lock immediately.\n            not self._n_lock_waiters(lock_key)\n            and await self._try_get_lock(lock_key, lock_id)\n        ):\n            if self._debug_enabled:\n                console.debug(\n                    f\"{SMR} [{time.monotonic() - start:.3f}] {lock_key.decode()} instaque by {lock_id.decode()}\"\n                )\n            return\n        # Make sure lock waiter task is running.\n        with contextlib.suppress(TimeoutError, asyncio.TimeoutError):\n            await self._ensure_lock_task_subscribed()\n        async with (\n            self._lock_waiter(lock_key) as lock_released_event,\n            self._request_lock_release(lock_key, lock_id),\n        ):\n            while (\n                self._n_lock_waiters(lock_key) > 1 and not lock_released_event.is_set()\n            ) or (\n                # We didn't get the lock so wait for the next release event.\n                lock_released_event.clear() is None\n                and not await self._try_get_lock(lock_key, lock_id)\n            ):\n                # Check if this process got a lease, then we can abandon waiting on the redis lock.\n                await self._get_local_lease(token, raise_when_found=True)\n                if self._debug_enabled:\n                    console.debug(\n                        f\"{SMR} [{time.monotonic() - start:.3f}] {lock_key.decode()} waiting for {lock_id.decode()}\"\n                    )\n                try:\n                    await asyncio.wait_for(\n                        lock_released_event.wait(),\n                        timeout=max(self.lock_expiration / 1000, 0),\n                    )\n                except (TimeoutError, asyncio.TimeoutError):\n                    if self._debug_enabled:\n                        console.debug(\n                            f\"{SMR} [{time.monotonic() - start:.3f}] {lock_key.decode()} wait timeout for {lock_id.decode()}\"\n                        )\n                    lock_released_event.set()  # to re-check the lock\n            if self._debug_enabled:\n                console.debug(\n                    f\"{SMR} [{time.monotonic() - start:.3f}] {lock_key.decode()} acquired by {lock_id.decode()} event={lock_released_event}\"\n                )\n\n    @contextlib.asynccontextmanager\n    async def _lock(\n        self, token: str, event_name: str | None = None\n    ) -> AsyncIterator[bytes]:\n        \"\"\"Obtain a redis lock for a token.\n\n        Args:\n            token: The token to obtain a lock for.\n            event_name: The name of the event associated with the lock.\n\n        Yields:\n            The ID of the lock (to be passed to set_state).\n\n        Raises:\n            LockExpiredError: If the lock has expired while processing the event.\n        \"\"\"\n        lock_key = self._lock_key(token)\n        lock_id = (\n            f\"{event_name}:{uuid.uuid4().hex}\" if event_name else uuid.uuid4().hex\n        ).encode()\n\n        await self._wait_lock(lock_key, lock_id)\n        state_is_locked = True\n\n        try:\n            yield lock_id\n        except LockExpiredError:\n            state_is_locked = False\n            raise\n        finally:\n            if state_is_locked:\n                # only delete our lock\n                deleted_lock_id = await self.redis.getdel(lock_key)\n                if deleted_lock_id == lock_id:\n                    if self._debug_enabled:\n                        console.debug(\n                            f\"{SMR} [{time.monotonic() - start:.3f}] {lock_key.decode()} released by {lock_id.decode()}\"\n                        )\n                elif deleted_lock_id is not None:\n                    # This can happen if the caller never tried to `set_state` before the lock expired and is a pretty bad bug.\n                    console.warn(\n                        f\"{lock_key.decode()} was released by {lock_id.decode()}, but it belonged to {deleted_lock_id.decode()}. This is a bug.\"\n                    )\n                # To avoid race when a waiter is registered after the del message is processed.\n                self._notify_next_waiter(lock_key)\n\n    async def close(self):\n        \"\"\"Explicitly close the redis connection and connection_pool.\n\n        It is necessary in testing scenarios to close between asyncio test cases\n        to avoid having lingering redis connections associated with event loops\n        that will be closed (each test case uses its own event loop).\n\n        Note: Connections will be automatically reopened when needed.\n        \"\"\"\n        try:\n            # Kill the lock task first so waiters don't get lock notifications.\n            if self._lock_task is not None:\n                self._lock_task.cancel()\n                with contextlib.suppress(asyncio.CancelledError):\n                    await self._lock_task\n                self._lock_task = None\n            # Then cancel all outstanding leases and write the cached states to redis.\n            for lease_task in self._local_leases.values():\n                lease_task.cancel()\n            await asyncio.gather(*self._local_leases.values(), return_exceptions=True)\n        finally:\n            await self.redis.aclose(close_connection_pool=True)\n"
  },
  {
    "path": "reflex/istate/proxy.py",
    "content": "\"\"\"A module to hold state proxy classes.\"\"\"\n\nfrom __future__ import annotations\n\nimport asyncio\nimport copy\nimport dataclasses\nimport functools\nimport inspect\nimport json\nimport sys\nfrom collections.abc import Callable, Sequence\nfrom importlib.util import find_spec\nfrom types import MethodType\nfrom typing import TYPE_CHECKING, Any, SupportsIndex, TypeVar\n\nimport wrapt\nfrom typing_extensions import Self\n\nfrom reflex.base import Base\nfrom reflex.event import Event\nfrom reflex.utils import prerequisites\nfrom reflex.utils.exceptions import ImmutableStateError\nfrom reflex.utils.serializers import can_serialize, serialize, serializer\nfrom reflex.vars.base import Var\n\nif TYPE_CHECKING:\n    from reflex.state import BaseState, StateUpdate\n\nT_STATE = TypeVar(\"T_STATE\", bound=\"BaseState\")\nT = TypeVar(\"T\")\n\n\nclass StateProxy(wrapt.ObjectProxy):\n    \"\"\"Proxy of a state instance to control mutability of vars for a background task.\n\n    Since a background task runs against a state instance without holding the\n    state_manager lock for the token, the reference may become stale if the same\n    state is modified by another event handler.\n\n    The proxy object ensures that writes to the state are blocked unless\n    explicitly entering a context which refreshes the state from state_manager\n    and holds the lock for the token until exiting the context. After exiting\n    the context, a StateUpdate may be emitted to the frontend to notify the\n    client of the state change.\n\n    A background task will be passed the `StateProxy` as `self`, so mutability\n    can be safely performed inside an `async with self` block.\n\n        class State(rx.State):\n            counter: int = 0\n\n            @rx.event(background=True)\n            async def bg_increment(self):\n                await asyncio.sleep(1)\n                async with self:\n                    self.counter += 1\n    \"\"\"\n\n    def __init__(\n        self,\n        state_instance: BaseState,\n        event: Event | None = None,\n        parent_state_proxy: StateProxy | None = None,\n    ):\n        \"\"\"Create a proxy for a state instance.\n\n        If `get_state` is used on a StateProxy, the resulting state will be\n        linked to the given state via parent_state_proxy. The first state in the\n        chain is the state that initiated the background task.\n\n        Args:\n            state_instance: The state instance to proxy.\n            event: The event associated with the state modification context.\n            parent_state_proxy: The parent state proxy, for linked mutability and context tracking.\n        \"\"\"\n        from reflex.state import _substate_key\n\n        super().__init__(state_instance)\n        self._self_event = event\n        self._self_app = prerequisites.get_and_validate_app().app\n        self._self_substate_path = tuple(state_instance.get_full_name().split(\".\"))\n        self._self_substate_token = _substate_key(\n            state_instance.router.session.client_token,\n            self._self_substate_path,\n        )\n        self._self_actx = None\n        self._self_mutable = False\n        self._self_actx_lock = asyncio.Lock()\n        self._self_actx_lock_holder = None\n        self._self_parent_state_proxy = parent_state_proxy\n\n    def _is_mutable(self) -> bool:\n        \"\"\"Check if the state is mutable.\n\n        Returns:\n            Whether the state is mutable.\n        \"\"\"\n        if self._self_parent_state_proxy is not None:\n            return self._self_parent_state_proxy._is_mutable() or self._self_mutable\n        return self._self_mutable\n\n    async def __aenter__(self) -> Self:\n        \"\"\"Enter the async context manager protocol.\n\n        Sets mutability to True and enters the `App.modify_state` async context,\n        which refreshes the state from state_manager and holds the lock for the\n        given state token until exiting the context.\n\n        Background tasks should avoid blocking calls while inside the context.\n\n        Returns:\n            This StateProxy instance in mutable mode.\n\n        Raises:\n            ImmutableStateError: If the state is already mutable.\n        \"\"\"\n        if self._self_parent_state_proxy is not None:\n            from reflex.state import State\n\n            parent_state = (\n                await self._self_parent_state_proxy.__aenter__()\n            ).__wrapped__\n            super().__setattr__(\n                \"__wrapped__\",\n                await parent_state.get_state(\n                    State.get_class_substate(self._self_substate_path)\n                ),\n            )\n            return self\n        current_task = asyncio.current_task()\n        if (\n            self._self_actx_lock.locked()\n            and current_task == self._self_actx_lock_holder\n        ):\n            msg = \"The state is already mutable. Do not nest `async with self` blocks.\"\n            raise ImmutableStateError(msg)\n\n        await self._self_actx_lock.acquire()\n        try:\n            self._self_actx_lock_holder = current_task\n            self._self_actx = self._self_app.modify_state(\n                token=self._self_substate_token, background=True, event=self._self_event\n            )\n            mutable_state = await self._self_actx.__aenter__()\n            self._self_mutable = True\n            super().__setattr__(\n                \"__wrapped__\", mutable_state.get_substate(self._self_substate_path)\n            )\n        except (Exception, asyncio.CancelledError):\n            # Restore the proxy to a consistent state since __aexit__ will not be called when __aenter__ raises.\n            await self.__aexit__(*sys.exc_info())\n            raise\n        return self\n\n    async def __aexit__(self, *exc_info: Any) -> None:\n        \"\"\"Exit the async context manager protocol.\n\n        Sets proxy mutability to False and persists any state changes.\n\n        Args:\n            exc_info: The exception info tuple.\n        \"\"\"\n        if self._self_parent_state_proxy is not None:\n            await self._self_parent_state_proxy.__aexit__(*exc_info)\n            return\n        try:\n            if self._self_mutable and self._self_actx is not None:\n                await self._self_actx.__aexit__(*exc_info)\n        finally:\n            self._self_actx = None\n            self._self_mutable = False\n            self._self_actx_lock_holder = None\n            self._self_actx_lock.release()\n\n    def __enter__(self):\n        \"\"\"Enter the regular context manager protocol.\n\n        This is not supported for background tasks, and exists only to raise a more useful exception\n        when the StateProxy is used incorrectly.\n\n        Raises:\n            TypeError: always, because only async contextmanager protocol is supported.\n        \"\"\"\n        msg = \"Background task must use `async with self` to modify state.\"\n        raise TypeError(msg)\n\n    def __exit__(self, *exc_info: Any) -> None:\n        \"\"\"Exit the regular context manager protocol.\n\n        Args:\n            exc_info: The exception info tuple.\n        \"\"\"\n\n    def __getattr__(self, name: str) -> Any:\n        \"\"\"Get the attribute from the underlying state instance.\n\n        Args:\n            name: The name of the attribute.\n\n        Returns:\n            The value of the attribute.\n\n        Raises:\n            ImmutableStateError: If the state is not in mutable mode.\n        \"\"\"\n        if name in [\"substates\", \"parent_state\"] and not self._is_mutable():\n            msg = (\n                \"Background task StateProxy is immutable outside of a context \"\n                \"manager. Use `async with self` to modify state.\"\n            )\n            raise ImmutableStateError(msg)\n\n        value = super().__getattr__(name)  # pyright: ignore[reportAttributeAccessIssue]\n        if not name.startswith(\"_self_\") and isinstance(value, MutableProxy):\n            # ensure mutations to these containers are blocked unless proxy is _mutable\n            return ImmutableMutableProxy(\n                wrapped=value.__wrapped__,\n                state=self,\n                field_name=value._self_field_name,\n            )\n        if isinstance(value, functools.partial) and value.args[0] is self.__wrapped__:\n            # Rebind event handler to the proxy instance\n            value = functools.partial(\n                value.func,\n                self,\n                *value.args[1:],\n                **value.keywords,\n            )\n        if isinstance(value, MethodType) and value.__self__ is self.__wrapped__:\n            # Rebind methods to the proxy instance\n            value = type(value)(value.__func__, self)\n        return value\n\n    def __setattr__(self, name: str, value: Any) -> None:\n        \"\"\"Set the attribute on the underlying state instance.\n\n        If the attribute is internal, set it on the proxy instance instead.\n\n        Args:\n            name: The name of the attribute.\n            value: The value of the attribute.\n\n        Raises:\n            ImmutableStateError: If the state is not in mutable mode.\n        \"\"\"\n        if (\n            name.startswith(\"_self_\")  # wrapper attribute\n            or self._is_mutable()  # lock held\n            # non-persisted state attribute\n            or name in self.__wrapped__.get_skip_vars()\n        ):\n            super().__setattr__(name, value)\n            return\n\n        msg = (\n            \"Background task StateProxy is immutable outside of a context \"\n            \"manager. Use `async with self` to modify state.\"\n        )\n        raise ImmutableStateError(msg)\n\n    def get_substate(self, path: Sequence[str]) -> BaseState:\n        \"\"\"Only allow substate access with lock held.\n\n        Args:\n            path: The path to the substate.\n\n        Returns:\n            The substate.\n\n        Raises:\n            ImmutableStateError: If the state is not in mutable mode.\n        \"\"\"\n        if not self._is_mutable():\n            msg = (\n                \"Background task StateProxy is immutable outside of a context \"\n                \"manager. Use `async with self` to modify state.\"\n            )\n            raise ImmutableStateError(msg)\n        return self.__wrapped__.get_substate(path)\n\n    async def get_state(self, state_cls: type[T_STATE]) -> T_STATE:\n        \"\"\"Get an instance of the state associated with this token.\n\n        Args:\n            state_cls: The class of the state.\n\n        Returns:\n            The state.\n\n        Raises:\n            ImmutableStateError: If the state is not in mutable mode.\n        \"\"\"\n        if not self._is_mutable():\n            msg = (\n                \"Background task StateProxy is immutable outside of a context \"\n                \"manager. Use `async with self` to modify state.\"\n            )\n            raise ImmutableStateError(msg)\n        return type(self)(\n            await self.__wrapped__.get_state(state_cls),\n            event=self._self_event,\n            parent_state_proxy=self,\n        )  # pyright: ignore [reportReturnType]\n\n    async def _as_state_update(self, *args, **kwargs) -> StateUpdate:\n        \"\"\"Temporarily allow mutability to access parent_state.\n\n        Args:\n            *args: The args to pass to the underlying state instance.\n            **kwargs: The kwargs to pass to the underlying state instance.\n\n        Returns:\n            The state update.\n        \"\"\"\n        original_mutable = self._self_mutable\n        self._self_mutable = True\n        try:\n            return await self.__wrapped__._as_state_update(*args, **kwargs)\n        finally:\n            self._self_mutable = original_mutable\n\n\nclass ReadOnlyStateProxy(StateProxy):\n    \"\"\"A read-only proxy for a state.\"\"\"\n\n    def __setattr__(self, name: str, value: Any) -> None:\n        \"\"\"Prevent setting attributes on the state for read-only proxy.\n\n        Args:\n            name: The attribute name.\n            value: The attribute value.\n\n        Raises:\n            NotImplementedError: Always raised when trying to set an attribute on proxied state.\n        \"\"\"\n        if name.startswith(\"_self_\"):\n            # Special case attributes of the proxy itself, not applied to the wrapped object.\n            super().__setattr__(name, value)\n            return\n        msg = \"This is a read-only state proxy.\"\n        raise NotImplementedError(msg)\n\n    def mark_dirty(self):\n        \"\"\"Mark the state as dirty.\n\n        Raises:\n            NotImplementedError: Always raised when trying to mark the proxied state as dirty.\n        \"\"\"\n        msg = \"This is a read-only state proxy.\"\n        raise NotImplementedError(msg)\n\n\nif find_spec(\"pydantic\"):\n    import pydantic\n\n    NEVER_WRAP_BASE_ATTRS = set(Base.__dict__) - {\"set\"} | set(\n        pydantic.BaseModel.__dict__\n    )\nelse:\n    NEVER_WRAP_BASE_ATTRS = {}\n\nMUTABLE_TYPES = (\n    list,\n    dict,\n    set,\n    Base,\n)\n\nif find_spec(\"sqlalchemy\"):\n    from sqlalchemy.orm import DeclarativeBase\n\n    MUTABLE_TYPES += (DeclarativeBase,)\n\nif find_spec(\"pydantic\"):\n    from pydantic import BaseModel as BaseModelV2\n    from pydantic.v1 import BaseModel as BaseModelV1\n\n    MUTABLE_TYPES += (BaseModelV1, BaseModelV2)\n\n\nclass MutableProxy(wrapt.ObjectProxy):\n    \"\"\"A proxy for a mutable object that tracks changes.\"\"\"\n\n    # Hint for finding the base class of the proxy.\n    __base_proxy__ = \"MutableProxy\"\n\n    # Methods on wrapped objects which should mark the state as dirty.\n    __mark_dirty_attrs__ = {\n        \"add\",\n        \"append\",\n        \"clear\",\n        \"difference_update\",\n        \"discard\",\n        \"extend\",\n        \"insert\",\n        \"intersection_update\",\n        \"pop\",\n        \"popitem\",\n        \"remove\",\n        \"reverse\",\n        \"setdefault\",\n        \"sort\",\n        \"symmetric_difference_update\",\n        \"update\",\n    }\n\n    # Methods on wrapped objects might return mutable objects that should be tracked.\n    __wrap_mutable_attrs__ = {\n        \"get\",\n        \"setdefault\",\n    }\n\n    # Dynamically generated classes for tracking dataclass mutations.\n    __dataclass_proxies__: dict[str, type] = {}\n\n    def __new__(cls, wrapped: Any, *args, **kwargs) -> MutableProxy:\n        \"\"\"Create a proxy instance for a mutable object that tracks changes.\n\n        Args:\n            wrapped: The object to proxy.\n            *args: Other args passed to MutableProxy (ignored).\n            **kwargs: Other kwargs passed to MutableProxy (ignored).\n\n        Returns:\n            The proxy instance.\n        \"\"\"\n        if dataclasses.is_dataclass(wrapped):\n            wrapped_cls = type(wrapped)\n            wrapper_cls_name = wrapped_cls.__name__ + cls.__name__\n            # Find the associated class\n            if wrapper_cls_name not in cls.__dataclass_proxies__:\n                # Create a new class that has the __dataclass_fields__ defined\n                cls.__dataclass_proxies__[wrapper_cls_name] = type(\n                    wrapper_cls_name,\n                    (cls,),\n                    {\n                        dataclasses._FIELDS: getattr(  # pyright: ignore [reportAttributeAccessIssue]\n                            wrapped_cls,\n                            dataclasses._FIELDS,  # pyright: ignore [reportAttributeAccessIssue]\n                        ),\n                    },\n                )\n            cls = cls.__dataclass_proxies__[wrapper_cls_name]\n        return super().__new__(cls)  # pyright: ignore[reportArgumentType]\n\n    def __init__(self, wrapped: Any, state: BaseState, field_name: str):\n        \"\"\"Create a proxy for a mutable object that tracks changes.\n\n        Args:\n            wrapped: The object to proxy.\n            state: The state to mark dirty when the object is changed.\n            field_name: The name of the field on the state associated with the\n                wrapped object.\n        \"\"\"\n        super().__init__(wrapped)\n        self._self_state = state\n        self._self_field_name = field_name\n\n    def __repr__(self) -> str:\n        \"\"\"Get the representation of the wrapped object.\n\n        Returns:\n            The representation of the wrapped object.\n        \"\"\"\n        return f\"{type(self).__name__}({self.__wrapped__})\"\n\n    def _mark_dirty(\n        self,\n        wrapped: Callable | None = None,\n        instance: BaseState | None = None,\n        args: tuple = (),\n        kwargs: dict | None = None,\n    ) -> Any:\n        \"\"\"Mark the state as dirty, then call a wrapped function.\n\n        Intended for use with `FunctionWrapper` from the `wrapt` library.\n\n        Args:\n            wrapped: The wrapped function.\n            instance: The instance of the wrapped function.\n            args: The args for the wrapped function.\n            kwargs: The kwargs for the wrapped function.\n\n        Returns:\n            The result of the wrapped function.\n        \"\"\"\n        self._self_state.dirty_vars.add(self._self_field_name)\n        self._self_state._mark_dirty()\n        if wrapped is not None:\n            return wrapped(*args, **(kwargs or {}))\n        return None\n\n    @staticmethod\n    def _is_called_from_dataclasses_internal() -> bool:\n        \"\"\"Check if the current function is called from dataclasses helper.\n\n        Returns:\n            Whether the current function is called from dataclasses internal code.\n        \"\"\"\n        # Walk up the stack a bit to see if we are called from dataclasses\n        # internal code, for example `asdict` or `astuple`.\n        frame = inspect.currentframe()\n        for _ in range(5):\n            # Why not `inspect.stack()` -- this is much faster!\n            if not (frame := frame and frame.f_back):\n                break\n            if inspect.getfile(frame) == dataclasses.__file__:\n                return True\n        return False\n\n    def _wrap_recursive(self, value: Any) -> Any:\n        \"\"\"Wrap a value recursively if it is mutable.\n\n        Args:\n            value: The value to wrap.\n\n        Returns:\n            The wrapped value.\n        \"\"\"\n        # When called from dataclasses internal code, return the unwrapped value\n        if self._is_called_from_dataclasses_internal():\n            return value\n        # If we already have a proxy, unwrap and rewrap to make sure the state\n        # reference is up to date.\n        if isinstance(value, MutableProxy):\n            value = value.__wrapped__\n        # Recursively wrap mutable types.\n        if is_mutable_type(type(value)):\n            base_cls = globals()[self.__base_proxy__]\n            return base_cls(\n                wrapped=value,\n                state=self._self_state,\n                field_name=self._self_field_name,\n            )\n        return value\n\n    def _wrap_recursive_decorator(\n        self, wrapped: Callable, instance: BaseState, args: list, kwargs: dict\n    ) -> Any:\n        \"\"\"Wrap a function that returns a possibly mutable value.\n\n        Intended for use with `FunctionWrapper` from the `wrapt` library.\n\n        Args:\n            wrapped: The wrapped function.\n            instance: The instance of the wrapped function.\n            args: The args for the wrapped function.\n            kwargs: The kwargs for the wrapped function.\n\n        Returns:\n            The result of the wrapped function (possibly wrapped in a MutableProxy).\n        \"\"\"\n        return self._wrap_recursive(wrapped(*args, **kwargs))\n\n    def __getattr__(self, __name: str) -> Any:\n        \"\"\"Get the attribute on the proxied object and return a proxy if mutable.\n\n        Args:\n            __name: The name of the attribute.\n\n        Returns:\n            The attribute value.\n        \"\"\"\n        value = super().__getattr__(__name)  # pyright: ignore[reportAttributeAccessIssue]\n\n        if callable(value):\n            if __name in self.__mark_dirty_attrs__:\n                # Wrap special callables, like \"append\", which should mark state dirty.\n                value = wrapt.FunctionWrapper(value, self._mark_dirty)\n\n            if __name in self.__wrap_mutable_attrs__:\n                # Wrap special methods that may return mutable objects tied to the state.\n                value = wrapt.FunctionWrapper(\n                    value,\n                    self._wrap_recursive_decorator,  # pyright: ignore[reportArgumentType]\n                )\n\n            if (\n                (\n                    not isinstance(self.__wrapped__, Base)\n                    or __name not in NEVER_WRAP_BASE_ATTRS\n                )\n                and (func := getattr(value, \"__func__\", None)) is not None\n                and not inspect.isclass(getattr(value, \"__self__\", None))\n                # skip SQLAlchemy instrumented methods\n                and not getattr(value, \"_sa_instrumented\", False)\n            ):\n                # Rebind `self` to the proxy on methods to capture nested mutations.\n                return functools.partial(func, self)\n\n        if is_mutable_type(type(value)) and __name not in (\n            \"__wrapped__\",\n            \"_self_state\",\n            \"__dict__\",\n        ):\n            # Recursively wrap mutable attribute values retrieved through this proxy.\n            return self._wrap_recursive(value)\n\n        return value\n\n    def __getitem__(self, key: Any) -> Any:\n        \"\"\"Get the item on the proxied object and return a proxy if mutable.\n\n        Args:\n            key: The key of the item.\n\n        Returns:\n            The item value.\n        \"\"\"\n        value = super().__getitem__(key)  # pyright: ignore[reportAttributeAccessIssue]\n        if isinstance(key, slice) and isinstance(value, list):\n            return [self._wrap_recursive(item) for item in value]\n        # Recursively wrap mutable items retrieved through this proxy.\n        return self._wrap_recursive(value)\n\n    def __iter__(self) -> Any:\n        \"\"\"Iterate over the proxied object and return a proxy if mutable.\n\n        Yields:\n            Each item value (possibly wrapped in MutableProxy).\n        \"\"\"\n        for value in super().__iter__():  # pyright: ignore[reportAttributeAccessIssue]\n            # Recursively wrap mutable items retrieved through this proxy.\n            yield self._wrap_recursive(value)\n\n    def __delattr__(self, name: str):\n        \"\"\"Delete the attribute on the proxied object and mark state dirty.\n\n        Args:\n            name: The name of the attribute.\n        \"\"\"\n        self._mark_dirty(super().__delattr__, args=(name,))\n\n    def __delitem__(self, key: str):\n        \"\"\"Delete the item on the proxied object and mark state dirty.\n\n        Args:\n            key: The key of the item.\n        \"\"\"\n        self._mark_dirty(super().__delitem__, args=(key,))  # pyright: ignore[reportAttributeAccessIssue]\n\n    def __setitem__(self, key: str, value: Any):\n        \"\"\"Set the item on the proxied object and mark state dirty.\n\n        Args:\n            key: The key of the item.\n            value: The value of the item.\n        \"\"\"\n        self._mark_dirty(super().__setitem__, args=(key, value))  # pyright: ignore[reportAttributeAccessIssue]\n\n    def __setattr__(self, name: str, value: Any):\n        \"\"\"Set the attribute on the proxied object and mark state dirty.\n\n        If the attribute starts with \"_self_\", then the state is NOT marked\n        dirty as these are internal proxy attributes.\n\n        Args:\n            name: The name of the attribute.\n            value: The value of the attribute.\n        \"\"\"\n        if name.startswith(\"_self_\"):\n            # Special case attributes of the proxy itself, not applied to the wrapped object.\n            super().__setattr__(name, value)\n            return\n        self._mark_dirty(super().__setattr__, args=(name, value))\n\n    def __copy__(self) -> Any:\n        \"\"\"Return a copy of the proxy.\n\n        Returns:\n            A copy of the wrapped object, unconnected to the proxy.\n        \"\"\"\n        return copy.copy(self.__wrapped__)\n\n    def __deepcopy__(self, memo: dict[int, Any] | None = None) -> Any:\n        \"\"\"Return a deepcopy of the proxy.\n\n        Args:\n            memo: The memo dict to use for the deepcopy.\n\n        Returns:\n            A deepcopy of the wrapped object, unconnected to the proxy.\n        \"\"\"\n        return copy.deepcopy(self.__wrapped__, memo=memo)\n\n    def __reduce_ex__(self, protocol_version: SupportsIndex):\n        \"\"\"Serialize the wrapped object for pickle, stripping off the proxy.\n\n        Returns a function that reconstructs to the wrapped object directly,\n        ensuring pickle's memo system correctly tracks object identity.\n\n        Args:\n            protocol_version: The protocol version.\n\n        Returns:\n            Tuple that reconstructs to the wrapped object.\n        \"\"\"\n        return (_unwrap_for_pickle, (self.__wrapped__,))\n\n\ndef _unwrap_for_pickle(obj: T) -> T:\n    \"\"\"Return the object unchanged. Used by MutableProxy.__reduce_ex__.\"\"\"\n    return obj\n\n\n@serializer\ndef serialize_mutable_proxy(mp: MutableProxy):\n    \"\"\"Return the wrapped value of a MutableProxy.\n\n    Args:\n        mp: The MutableProxy to serialize.\n\n    Returns:\n        The wrapped object.\n    \"\"\"\n    obj = mp.__wrapped__\n    if can_serialize(type(obj)):\n        return serialize(obj)\n    return obj\n\n\n_orig_json_encoder_default = json.JSONEncoder.default\n\n\ndef _json_encoder_default_wrapper(self: json.JSONEncoder, o: Any) -> Any:\n    \"\"\"Wrap JSONEncoder.default to handle MutableProxy objects.\n\n    Args:\n        self: the JSONEncoder instance.\n        o: the object to serialize.\n\n    Returns:\n        A JSON-able object.\n    \"\"\"\n    try:\n        return o.__wrapped__\n    except AttributeError:\n        pass\n    return _orig_json_encoder_default(self, o)\n\n\njson.JSONEncoder.default = _json_encoder_default_wrapper\n\n\nclass ImmutableMutableProxy(MutableProxy):\n    \"\"\"A proxy for a mutable object that tracks changes.\n\n    This wrapper comes from StateProxy, and will raise an exception if an attempt is made\n    to modify the wrapped object when the StateProxy is immutable.\n    \"\"\"\n\n    # Ensure that recursively wrapped proxies use ImmutableMutableProxy as base.\n    __base_proxy__ = \"ImmutableMutableProxy\"\n\n    def _mark_dirty(\n        self,\n        wrapped: Callable | None = None,\n        instance: BaseState | None = None,\n        args: tuple = (),\n        kwargs: dict | None = None,\n    ) -> Any:\n        \"\"\"Raise an exception when an attempt is made to modify the object.\n\n        Intended for use with `FunctionWrapper` from the `wrapt` library.\n\n        Args:\n            wrapped: The wrapped function.\n            instance: The instance of the wrapped function.\n            args: The args for the wrapped function.\n            kwargs: The kwargs for the wrapped function.\n\n        Returns:\n            The result of the wrapped function.\n\n        Raises:\n            ImmutableStateError: if the StateProxy is not mutable.\n        \"\"\"\n        if not self._self_state._is_mutable():  # pyright: ignore[reportAttributeAccessIssue]\n            msg = (\n                \"Background task StateProxy is immutable outside of a context \"\n                \"manager. Use `async with self` to modify state.\"\n            )\n            raise ImmutableStateError(msg)\n        return super()._mark_dirty(\n            wrapped=wrapped, instance=instance, args=args, kwargs=kwargs\n        )\n\n\n@functools.lru_cache(maxsize=1024)\ndef is_mutable_type(type_: type) -> bool:\n    \"\"\"Check if a type is mutable and should be wrapped.\n\n    Args:\n        type_: The type to check.\n\n    Returns:\n        Whether the type is mutable and should be wrapped.\n    \"\"\"\n    return issubclass(type_, MUTABLE_TYPES) or (\n        dataclasses.is_dataclass(type_) and not issubclass(type_, Var)\n    )\n"
  },
  {
    "path": "reflex/istate/shared.py",
    "content": "\"\"\"Base classes for shared / linked states.\"\"\"\n\nimport asyncio\nimport contextlib\nfrom collections.abc import AsyncIterator\nfrom typing import Self, TypeVar\n\nfrom reflex.constants import ROUTER_DATA\nfrom reflex.event import Event, get_hydrate_event\nfrom reflex.state import BaseState, State, _override_base_method, _substate_key\nfrom reflex.utils import console\nfrom reflex.utils.exceptions import ReflexRuntimeError\n\nUPDATE_OTHER_CLIENT_TASKS: set[asyncio.Task] = set()\nLINKED_STATE = TypeVar(\"LINKED_STATE\", bound=\"SharedStateBaseInternal\")\n\n\ndef _log_update_client_errors(task: asyncio.Task):\n    \"\"\"Log errors from updating other clients.\n\n    Args:\n        task: The asyncio task to check for errors.\n    \"\"\"\n    try:\n        task.result()\n    except Exception as e:\n        console.warn(f\"Error updating linked client: {e}\")\n    finally:\n        UPDATE_OTHER_CLIENT_TASKS.discard(task)\n\n\ndef _do_update_other_tokens(\n    affected_tokens: set[str],\n    previous_dirty_vars: dict[str, set[str]],\n    state_type: type[BaseState],\n) -> list[asyncio.Task]:\n    \"\"\"Update other clients after a shared state update.\n\n    Submit the updates in separate asyncio tasks to avoid deadlocking.\n\n    Args:\n        affected_tokens: The tokens to update.\n        previous_dirty_vars: The dirty vars to apply to other clients.\n        state_type: The type of the shared state.\n\n    Returns:\n        The list of asyncio tasks created to perform the updates.\n    \"\"\"\n    from reflex.utils.prerequisites import get_app\n\n    app = get_app().app\n\n    async def _update_client(token: str):\n        async with app.modify_state(\n            _substate_key(token, state_type),\n            previous_dirty_vars=previous_dirty_vars,\n        ):\n            pass\n\n    tasks = []\n    for affected_token in affected_tokens:\n        # Don't send updates for disconnected clients.\n        if affected_token not in app.event_namespace._token_manager.token_to_socket:\n            continue\n        # TODO: remove disconnected clients after some time.\n        t = asyncio.create_task(_update_client(affected_token))\n        UPDATE_OTHER_CLIENT_TASKS.add(t)\n        t.add_done_callback(_log_update_client_errors)\n        tasks.append(t)\n    return tasks\n\n\n@contextlib.asynccontextmanager\nasync def _patch_state(\n    original_state: BaseState, linked_state: BaseState, full_delta: bool = False\n):\n    \"\"\"Patch the linked state into the original state's tree, restoring it afterward.\n\n    Args:\n        original_state: The original shared state.\n        linked_state: The linked shared state.\n        full_delta: If True, mark all Vars in linked_state dirty and resolve\n            the delta from the root. This option is used when linking or unlinking\n            to ensure that other computed vars in the tree pick up the newly\n            linked/unlinked values.\n    \"\"\"\n    if (original_parent_state := original_state.parent_state) is None:\n        msg = \"Cannot patch root state as linked state.\"\n        raise ReflexRuntimeError(msg)\n\n    state_name = original_state.get_name()\n    original_parent_state.substates[state_name] = linked_state\n    linked_parent_state = linked_state.parent_state\n    linked_state.parent_state = original_parent_state\n    try:\n        if full_delta:\n            linked_state.dirty_vars.update(linked_state.base_vars)\n            linked_state.dirty_vars.update(linked_state.backend_vars)\n            linked_state.dirty_vars.update(linked_state.computed_vars)\n            linked_state._mark_dirty()\n        # Apply the updates into the existing state tree for rehydrate.\n        root_state = original_state._get_root_state()\n        root_state.dirty_vars.add(\"router\")\n        root_state.dirty_vars.add(ROUTER_DATA)\n        root_state._mark_dirty()\n        await root_state._get_resolved_delta()\n        yield\n    finally:\n        original_parent_state.substates[state_name] = original_state\n        linked_state.parent_state = linked_parent_state\n\n\nclass SharedStateBaseInternal(State):\n    \"\"\"The private base state for all shared states.\"\"\"\n\n    _exit_stack: contextlib.AsyncExitStack | None = None\n    _held_locks: dict[str, dict[type[BaseState], BaseState]] | None = None\n\n    def __getstate__(self):\n        \"\"\"Override redis serialization to remove temporary fields.\n\n        Returns:\n            The state dictionary without temporary fields.\n        \"\"\"\n        s = super().__getstate__()\n        s.pop(\"_previous_dirty_vars\", None)\n        s.pop(\"_exit_stack\", None)\n        s.pop(\"_held_locks\", None)\n        return s\n\n    @_override_base_method\n    def _clean(self):\n        \"\"\"Override BaseState._clean to track the last set of dirty vars.\n\n        This is necessary for applying dirty vars from one event to other linked states.\n        \"\"\"\n        if (\n            previous_dirty_vars := getattr(self, \"_previous_dirty_vars\", None)\n        ) is not None:\n            previous_dirty_vars.clear()\n            previous_dirty_vars.update(self.dirty_vars)\n        super()._clean()\n\n    @_override_base_method\n    def _mark_dirty(self):\n        \"\"\"Override BaseState._mark_dirty to avoid marking certain vars as dirty.\n\n        Since these internal fields are not persisted to redis, they shouldn't cause the\n        state to be considered dirty either.\n        \"\"\"\n        self.dirty_vars.discard(\"_previous_dirty_vars\")\n        self.dirty_vars.discard(\"_exit_stack\")\n        self.dirty_vars.discard(\"_held_locks\")\n        # Only mark dirty if there are still dirty vars, or any substate is dirty\n        if self.dirty_vars or any(\n            substate.dirty_vars for substate in self.substates.values()\n        ):\n            super()._mark_dirty()\n\n    def _rehydrate(self):\n        \"\"\"Get the events to rehydrate the state.\n\n        Returns:\n            The events to rehydrate the state (these should be returned/yielded).\n        \"\"\"\n        return [\n            Event(\n                token=self.router.session.client_token,\n                name=get_hydrate_event(self._get_root_state()),\n            ),\n            State.set_is_hydrated(True),\n        ]\n\n    async def _link_to(self, token: str) -> Self:\n        \"\"\"Link this shared state to a token.\n\n        After linking, subsequent access to this shared state will affect the\n        linked token's state, and cause changes to be propagated to all other\n        clients linked to that token.\n\n        Args:\n            token: The token to link to (Cannot contain underscore characters).\n\n        Returns:\n            The newly linked state.\n\n        Raises:\n            ReflexRuntimeError: If linking fails or token is invalid.\n        \"\"\"\n        if not token:\n            msg = \"Cannot link shared state to empty token.\"\n            raise ReflexRuntimeError(msg)\n        if not isinstance(self, SharedState):\n            msg = \"Can only link SharedState instances.\"\n            raise RuntimeError(msg)\n        if self._linked_to == token:\n            return self  # already linked to this token\n        if self._linked_to and self._linked_to != token:\n            # Disassociate from previous linked token since unlink will not be called.\n            self._linked_from.discard(self.router.session.client_token)\n        # TODO: Change StateManager to accept token + class instead of combining them in a string.\n        if \"_\" in token:\n            msg = f\"Invalid token {token} for linking state {self.get_full_name()}, cannot use underscore (_) in the token name.\"\n            raise ReflexRuntimeError(msg)\n\n        # Associate substate with the given link token.\n        state_name = self.get_full_name()\n        if self._reflex_internal_links is None:\n            self._reflex_internal_links = {}\n        self._reflex_internal_links[state_name] = token\n        return await self._internal_patch_linked_state(token, full_delta=True)\n\n    async def _unlink(self):\n        \"\"\"Unlink this shared state from its linked token.\n\n        Returns:\n            The events to rehydrate the state after unlinking (these should be returned/yielded).\n        \"\"\"\n        from reflex.istate.manager import get_state_manager\n\n        if not isinstance(self, SharedState):\n            msg = \"Can only unlink SharedState instances.\"\n            raise ReflexRuntimeError(msg)\n\n        state_name = self.get_full_name()\n        if (\n            not self._reflex_internal_links\n            or state_name not in self._reflex_internal_links\n        ):\n            msg = f\"State {state_name} is not linked and cannot be unlinked.\"\n            raise ReflexRuntimeError(msg)\n\n        # Break the linkage for future events.\n        self._reflex_internal_links.pop(state_name)\n        self._linked_from.discard(self.router.session.client_token)\n\n        # Patch in the original state, apply updates, then rehydrate.\n        private_root_state = await get_state_manager().get_state(\n            _substate_key(self.router.session.client_token, type(self))\n        )\n        private_state = await private_root_state.get_state(type(self))\n        async with _patch_state(\n            original_state=self,\n            linked_state=private_state,\n            full_delta=True,\n        ):\n            return self._rehydrate()\n\n    async def _internal_patch_linked_state(\n        self, token: str, full_delta: bool = False\n    ) -> Self:\n        \"\"\"Load and replace this state with the linked state for a given token.\n\n        Must be called inside a `_modify_linked_states` context, to ensure locks are\n        released after the event is done processing.\n\n        Args:\n            token: The token of the linked state.\n            full_delta: If True, mark all Vars in linked_state dirty and resolve\n                delta to update cached computed vars\n\n        Returns:\n            The state that was linked into the tree.\n        \"\"\"\n        from reflex.istate.manager import get_state_manager\n\n        if self._exit_stack is None or self._held_locks is None:\n            msg = \"Cannot link shared state outside of _modify_linked_states context.\"\n            raise ReflexRuntimeError(msg)\n\n        # Get the newly linked state and update pointers/delta for subsequent events.\n        if token not in self._held_locks:\n            linked_root_state = await self._exit_stack.enter_async_context(\n                get_state_manager().modify_state(_substate_key(token, type(self)))\n            )\n            self._held_locks.setdefault(token, {})\n        else:\n            linked_root_state = await get_state_manager().get_state(\n                _substate_key(token, type(self))\n            )\n        linked_state = await linked_root_state.get_state(type(self))\n        if not isinstance(linked_state, SharedState):\n            msg = f\"Linked state for token {token} is not a SharedState.\"\n            raise ReflexRuntimeError(msg)\n        # Avoid unnecessary dirtiness of shared state when there are no changes.\n        if type(self) not in self._held_locks[token]:\n            self._held_locks[token][type(self)] = linked_state\n        if self.router.session.client_token not in linked_state._linked_from:\n            linked_state._linked_from.add(self.router.session.client_token)\n        if linked_state._linked_to != token:\n            linked_state._linked_to = token\n        await self._exit_stack.enter_async_context(\n            _patch_state(\n                original_state=self,\n                linked_state=linked_state,\n                full_delta=full_delta,\n            )\n        )\n        return linked_state\n\n    def _held_locks_linked_states(self) -> list[\"SharedState\"]:\n        \"\"\"Get all linked states currently held by this state.\n\n        Returns:\n            The list of linked states currently held.\n        \"\"\"\n        if self._held_locks is None:\n            return []\n        return [\n            linked_state\n            for linked_state_cls_to_instance in self._held_locks.values()\n            for linked_state in linked_state_cls_to_instance.values()\n            if isinstance(linked_state, SharedState)\n        ]\n\n    @contextlib.asynccontextmanager\n    async def _modify_linked_states(\n        self, previous_dirty_vars: dict[str, set[str]] | None = None\n    ) -> AsyncIterator[None]:\n        \"\"\"Take lock, fetch all linked states, and patch them into the current state tree.\n\n        If previous_dirty_vars is NOT provided, then any dirty vars after\n        exiting the context will be applied to all other clients linked to this\n        state's linked token.\n\n        Args:\n            previous_dirty_vars: When apply linked state changes to other\n                tokens, provide mapping of state full_name to set of dirty vars.\n\n        Yields:\n            None.\n        \"\"\"\n        if self._exit_stack is not None:\n            msg = \"Cannot nest _modify_linked_states contexts.\"\n            raise ReflexRuntimeError(msg)\n        if self._reflex_internal_links is None:\n            msg = \"No linked states to modify.\"\n            raise ReflexRuntimeError(msg)\n        self._exit_stack = contextlib.AsyncExitStack()\n        self._held_locks = {}\n        current_dirty_vars: dict[str, set[str]] = {}\n        affected_tokens: set[str] = set()\n        try:\n            # Go through all linked states and patch them in if they are present in the tree\n            for linked_state_name, linked_token in self._reflex_internal_links.items():\n                linked_state_cls: type[SharedState] = (\n                    self.get_root_state().get_class_substate(  # pyright: ignore[reportAssignmentType]\n                        linked_state_name\n                    )\n                )\n                try:\n                    original_state = self._get_state_from_cache(linked_state_cls)\n                except ValueError:\n                    # This state wasn't required for processing the event.\n                    continue\n                linked_state = await original_state._internal_patch_linked_state(\n                    linked_token\n                )\n                if (\n                    previous_dirty_vars\n                    and (dv := previous_dirty_vars.get(linked_state_name)) is not None\n                ):\n                    linked_state.dirty_vars.update(dv)\n                    linked_state._mark_dirty()\n            async with self._exit_stack:\n                yield None\n                # Collect dirty vars and other affected clients that need to be updated.\n                for linked_state in self._held_locks_linked_states():\n                    if linked_state._previous_dirty_vars is not None:\n                        current_dirty_vars[linked_state.get_full_name()] = set(\n                            linked_state._previous_dirty_vars\n                        )\n                    if (\n                        linked_state._get_was_touched()\n                        or linked_state._previous_dirty_vars is not None\n                    ):\n                        affected_tokens.update(\n                            token\n                            for token in linked_state._linked_from\n                            if token != self.router.session.client_token\n                        )\n        finally:\n            self._exit_stack = None\n\n        # Only propagate dirty vars when we are not already propagating from another state.\n        if previous_dirty_vars is None:\n            _do_update_other_tokens(\n                affected_tokens=affected_tokens,\n                previous_dirty_vars=current_dirty_vars,\n                state_type=type(self),\n            )\n\n\nclass SharedState(SharedStateBaseInternal, mixin=True):\n    \"\"\"Mixin for defining new shared states.\"\"\"\n\n    _linked_from: set[str] = set()\n    _linked_to: str = \"\"\n    _previous_dirty_vars: set[str] = set()\n\n    @classmethod\n    def __init_subclass__(cls, **kwargs):\n        \"\"\"Initialize subclass and set up shared state fields.\n\n        Args:\n            **kwargs: The kwargs to pass to the init_subclass method.\n        \"\"\"\n        kwargs[\"mixin\"] = False\n        cls._mixin = False\n        super().__init_subclass__(**kwargs)\n        root_state = cls.get_root_state()\n        if root_state.backend_vars[\"_reflex_internal_links\"] is None:\n            root_state.backend_vars[\"_reflex_internal_links\"] = {}\n        if root_state is State:\n            # Always fetch SharedStateBaseInternal to access\n            # `_modify_linked_states` without having to use `.get_state()` which\n            # pulls in all linked states and substates which may not actually be\n            # accessed for this event.\n            root_state._always_dirty_substates.add(SharedStateBaseInternal.get_name())\n"
  },
  {
    "path": "reflex/istate/storage.py",
    "content": "\"\"\"Client-side storage classes for reflex state variables.\"\"\"\n\nfrom __future__ import annotations\n\nfrom typing import Any\n\nfrom reflex.utils import format\n\n\nclass ClientStorageBase:\n    \"\"\"Base class for client-side storage.\"\"\"\n\n    def options(self) -> dict[str, Any]:\n        \"\"\"Get the options for the storage.\n\n        Returns:\n            All set options for the storage (not None).\n        \"\"\"\n        return {\n            format.to_camel_case(k): v for k, v in vars(self).items() if v is not None\n        }\n\n\nclass Cookie(ClientStorageBase, str):\n    \"\"\"Represents a state Var that is stored as a cookie in the browser.\"\"\"\n\n    name: str | None\n    path: str\n    max_age: int | None\n    domain: str | None\n    secure: bool | None\n    same_site: str\n\n    def __new__(\n        cls,\n        object: Any = \"\",\n        encoding: str | None = None,\n        errors: str | None = None,\n        /,\n        name: str | None = None,\n        path: str = \"/\",\n        max_age: int | None = None,\n        domain: str | None = None,\n        secure: bool | None = None,\n        same_site: str = \"lax\",\n    ):\n        \"\"\"Create a client-side Cookie (str).\n\n        Args:\n            object: The initial object.\n            encoding: The encoding to use.\n            errors: The error handling scheme to use.\n            name: The name of the cookie on the client side.\n            path: Cookie path. Use / as the path if the cookie should be accessible on all pages.\n            max_age: Relative max age of the cookie in seconds from when the client receives it.\n            domain: Domain for the cookie (sub.domain.com or .allsubdomains.com).\n            secure: Is the cookie only accessible through HTTPS?\n            same_site: Whether the cookie is sent with third party requests.\n                One of (true|false|none|lax|strict)\n\n        Returns:\n            The client-side Cookie object.\n\n        Note: expires (absolute Date) is not supported at this time.\n        \"\"\"\n        if encoding or errors:\n            inst = super().__new__(cls, object, encoding or \"utf-8\", errors or \"strict\")\n        else:\n            inst = super().__new__(cls, object)\n        inst.name = name\n        inst.path = path\n        inst.max_age = max_age\n        inst.domain = domain\n        inst.secure = secure\n        inst.same_site = same_site\n        return inst\n\n\nclass LocalStorage(ClientStorageBase, str):\n    \"\"\"Represents a state Var that is stored in localStorage in the browser.\"\"\"\n\n    name: str | None\n    sync: bool = False\n\n    def __new__(\n        cls,\n        object: Any = \"\",\n        encoding: str | None = None,\n        errors: str | None = None,\n        /,\n        name: str | None = None,\n        sync: bool = False,\n    ) -> LocalStorage:\n        \"\"\"Create a client-side localStorage (str).\n\n        Args:\n            object: The initial object.\n            encoding: The encoding to use.\n            errors: The error handling scheme to use.\n            name: The name of the storage key on the client side.\n            sync: Whether changes should be propagated to other tabs.\n\n        Returns:\n            The client-side localStorage object.\n        \"\"\"\n        if encoding or errors:\n            inst = super().__new__(cls, object, encoding or \"utf-8\", errors or \"strict\")\n        else:\n            inst = super().__new__(cls, object)\n        inst.name = name\n        inst.sync = sync\n        return inst\n\n\nclass SessionStorage(ClientStorageBase, str):\n    \"\"\"Represents a state Var that is stored in sessionStorage in the browser.\"\"\"\n\n    name: str | None\n\n    def __new__(\n        cls,\n        object: Any = \"\",\n        encoding: str | None = None,\n        errors: str | None = None,\n        /,\n        name: str | None = None,\n    ) -> SessionStorage:\n        \"\"\"Create a client-side sessionStorage (str).\n\n        Args:\n            object: The initial object.\n            encoding: The encoding to use.\n            errors: The error handling scheme to use\n            name: The name of the storage on the client side\n\n        Returns:\n            The client-side sessionStorage object.\n        \"\"\"\n        if encoding or errors:\n            inst = super().__new__(cls, object, encoding or \"utf-8\", errors or \"strict\")\n        else:\n            inst = super().__new__(cls, object)\n        inst.name = name\n        return inst\n"
  },
  {
    "path": "reflex/istate/wrappers.py",
    "content": "\"\"\"Wrappers for the state manager.\"\"\"\n\nfrom typing import Any\n\nfrom reflex.istate.proxy import ReadOnlyStateProxy\nfrom reflex.state import _split_substate_key, _substate_key, get_state_manager\n\n\nasync def get_state(token: str, state_cls: Any | None = None) -> ReadOnlyStateProxy:\n    \"\"\"Get the instance of a state for a token.\n\n    Args:\n        token: The token for the state.\n        state_cls: The class of the state.\n\n    Returns:\n        A read-only proxy of the state instance.\n    \"\"\"\n    mng = get_state_manager()\n    if state_cls is not None:\n        root_state = await mng.get_state(_substate_key(token, state_cls))\n    else:\n        root_state = await mng.get_state(token)\n        _, state_path = _split_substate_key(token)\n        state_cls = root_state.get_class_substate(tuple(state_path.split(\".\")))\n    instance = await root_state.get_state(state_cls)\n    return ReadOnlyStateProxy(instance)\n"
  },
  {
    "path": "reflex/middleware/__init__.py",
    "content": "\"\"\"Reflex middleware.\"\"\"\n\nfrom .hydrate_middleware import HydrateMiddleware\nfrom .middleware import Middleware\n"
  },
  {
    "path": "reflex/middleware/hydrate_middleware.py",
    "content": "\"\"\"Middleware to hydrate the state.\"\"\"\n\nfrom __future__ import annotations\n\nimport dataclasses\nfrom typing import TYPE_CHECKING\n\nfrom reflex import constants\nfrom reflex.event import Event, get_hydrate_event\nfrom reflex.middleware.middleware import Middleware\nfrom reflex.state import BaseState, StateUpdate, _resolve_delta\n\nif TYPE_CHECKING:\n    from reflex.app import App\n\n\n@dataclasses.dataclass(init=True)\nclass HydrateMiddleware(Middleware):\n    \"\"\"Middleware to handle initial app hydration.\"\"\"\n\n    async def preprocess(\n        self, app: App, state: BaseState, event: Event\n    ) -> StateUpdate | None:\n        \"\"\"Preprocess the event.\n\n        Args:\n            app: The app to apply the middleware to.\n            state: The client state.\n            event: The event to preprocess.\n\n        Returns:\n            An optional delta or list of state updates to return.\n        \"\"\"\n        # If this is not the hydrate event, return None\n        if event.name != get_hydrate_event(state):\n            return None\n\n        # Clear client storage, to respect clearing cookies\n        state._reset_client_storage()\n\n        # Mark state as not hydrated (until on_loads are complete)\n        setattr(state, constants.CompileVars.IS_HYDRATED, False)\n\n        # Get the initial state.\n        delta = await _resolve_delta(state.dict())\n        # since a full dict was captured, clean any dirtiness\n        state._clean()\n\n        # Return the state update.\n        return StateUpdate(delta=delta, events=[])\n"
  },
  {
    "path": "reflex/middleware/middleware.py",
    "content": "\"\"\"Base Reflex middleware.\"\"\"\n\nfrom __future__ import annotations\n\nfrom abc import ABC, abstractmethod\nfrom typing import TYPE_CHECKING\n\nfrom reflex.event import Event\nfrom reflex.state import BaseState, StateUpdate\n\nif TYPE_CHECKING:\n    from reflex.app import App\n\n\nclass Middleware(ABC):\n    \"\"\"Middleware to preprocess and postprocess requests.\"\"\"\n\n    @abstractmethod\n    async def preprocess(\n        self, app: App, state: BaseState, event: Event\n    ) -> StateUpdate | None:\n        \"\"\"Preprocess the event.\n\n        Args:\n            app: The app.\n            state: The client state.\n            event: The event to preprocess.\n\n        Returns:\n            An optional state update to return.\n        \"\"\"\n        return None\n\n    async def postprocess(\n        self, app: App, state: BaseState, event: Event, update: StateUpdate\n    ) -> StateUpdate:\n        \"\"\"Postprocess the event.\n\n        Args:\n            app: The app.\n            state: The client state.\n            event: The event to postprocess.\n            update: The current state update.\n\n        Returns:\n            An optional state to return.\n        \"\"\"\n        return update\n"
  },
  {
    "path": "reflex/model.py",
    "content": "\"\"\"Database built into Reflex.\"\"\"\n\nfrom __future__ import annotations\n\nimport re\nfrom collections import defaultdict\nfrom contextlib import suppress\nfrom importlib.util import find_spec\nfrom typing import TYPE_CHECKING, Any, ClassVar\n\nfrom reflex.config import get_config\nfrom reflex.environment import environment\nfrom reflex.utils import console\nfrom reflex.utils.compat import sqlmodel_field_has_primary_key\nfrom reflex.utils.serializers import serializer\n\nif TYPE_CHECKING:\n    from typing import TypeVar\n\n    import sqlalchemy\n    import sqlmodel\n\n    SQLModelOrSqlAlchemy = (\n        type[sqlmodel.SQLModel] | type[sqlalchemy.orm.DeclarativeBase]\n    )\n\n    SQLModelOrSqlAlchemyT = TypeVar(\"SQLModelOrSqlAlchemyT\", bound=SQLModelOrSqlAlchemy)\n\n\ndef _safe_db_url_for_logging(url: str) -> str:\n    \"\"\"Remove username and password from the database URL for logging.\n\n    Args:\n        url: The database URL.\n\n    Returns:\n        The database URL with the username and password removed.\n    \"\"\"\n    return re.sub(r\"://[^@]+@\", \"://<username>:<password>@\", url)\n\n\ndef _print_db_not_available(*args, **kwargs):\n    msg = (\n        \"Database is not available. Please install the required packages: \"\n        \"`pip install reflex[db]`.\"\n    )\n    raise ImportError(msg)\n\n\nclass _ClassThatErrorsOnInit:\n    def __init__(self, *args, **kwargs):\n        _print_db_not_available(*args, **kwargs)\n\n\nif find_spec(\"sqlalchemy\"):\n    import sqlalchemy\n    import sqlalchemy.exc\n    import sqlalchemy.ext.asyncio\n    import sqlalchemy.orm\n\n    _ENGINE: dict[str, sqlalchemy.engine.Engine] = {}\n    _ASYNC_ENGINE: dict[str, sqlalchemy.ext.asyncio.AsyncEngine] = {}\n\n    def get_engine_args(url: str | None = None) -> dict[str, Any]:\n        \"\"\"Get the database engine arguments.\n\n        Args:\n            url: The database url.\n\n        Returns:\n            The database engine arguments as a dict.\n        \"\"\"\n        kwargs: dict[str, Any] = {\n            # Print the SQL queries if the log level is INFO or lower.\n            \"echo\": environment.SQLALCHEMY_ECHO.get(),\n            # Check connections before returning them.\n            \"pool_pre_ping\": environment.SQLALCHEMY_POOL_PRE_PING.get(),\n            \"pool_size\": environment.SQLALCHEMY_POOL_SIZE.get(),\n            \"max_overflow\": environment.SQLALCHEMY_MAX_OVERFLOW.get(),\n            \"pool_recycle\": environment.SQLALCHEMY_POOL_RECYCLE.get(),\n            \"pool_timeout\": environment.SQLALCHEMY_POOL_TIMEOUT.get(),\n        }\n        conf = get_config()\n        url = url or conf.db_url\n        if url is not None and url.startswith(\"sqlite\"):\n            # Needed for the admin dash on sqlite.\n            kwargs[\"connect_args\"] = {\"check_same_thread\": False}\n        return kwargs\n\n    def get_engine(url: str | None = None) -> sqlalchemy.engine.Engine:\n        \"\"\"Get the database engine.\n\n        Args:\n            url: the DB url to use.\n\n        Returns:\n            The database engine.\n\n        Raises:\n            ValueError: If the database url is None.\n        \"\"\"\n        conf = get_config()\n        url = url or conf.db_url\n        if url is None:\n            msg = \"No database url configured\"\n            raise ValueError(msg)\n\n        global _ENGINE\n        if url in _ENGINE:\n            return _ENGINE[url]\n\n        if not environment.ALEMBIC_CONFIG.get().exists():\n            console.warn(\n                \"Database is not initialized, run [bold]reflex db init[/bold] first.\",\n                dedupe=True,\n            )\n        _ENGINE[url] = sqlalchemy.engine.create_engine(\n            url,\n            **get_engine_args(url),\n        )\n        return _ENGINE[url]\n\n    def get_async_engine(url: str | None) -> sqlalchemy.ext.asyncio.AsyncEngine:\n        \"\"\"Get the async database engine.\n\n        Args:\n            url: The database url.\n\n        Returns:\n            The async database engine.\n\n        Raises:\n            ValueError: If the async database url is None.\n        \"\"\"\n        if url is None:\n            conf = get_config()\n            url = conf.async_db_url\n            if url is not None and conf.db_url is not None:\n                async_db_url_tail = url.partition(\"://\")[2]\n                db_url_tail = conf.db_url.partition(\"://\")[2]\n                if async_db_url_tail != db_url_tail:\n                    console.warn(\n                        f\"async_db_url `{_safe_db_url_for_logging(url)}` \"\n                        \"should reference the same database as \"\n                        f\"db_url `{_safe_db_url_for_logging(conf.db_url)}`.\"\n                    )\n        if url is None:\n            msg = \"No async database url configured\"\n            raise ValueError(msg)\n\n        global _ASYNC_ENGINE\n        if url in _ASYNC_ENGINE:\n            return _ASYNC_ENGINE[url]\n\n        if not environment.ALEMBIC_CONFIG.get().exists():\n            console.warn(\n                \"Database is not initialized, run [bold]reflex db init[/bold] first.\",\n                dedupe=True,\n            )\n        _ASYNC_ENGINE[url] = sqlalchemy.ext.asyncio.create_async_engine(\n            url,\n            **get_engine_args(url),\n        )\n        return _ASYNC_ENGINE[url]\n\n    def sqla_session(url: str | None = None) -> sqlalchemy.orm.Session:\n        \"\"\"Get a bare sqlalchemy session to interact with the database.\n\n        Args:\n            url: The database url.\n\n        Returns:\n            A database session.\n        \"\"\"\n        return sqlalchemy.orm.Session(get_engine(url))\n\n    class ModelRegistry:\n        \"\"\"Registry for all models.\"\"\"\n\n        models: ClassVar[set[SQLModelOrSqlAlchemy]] = set()\n\n        # Cache the metadata to avoid re-creating it.\n        _metadata: ClassVar[sqlalchemy.MetaData | None] = None\n\n        @classmethod\n        def register(cls, model: SQLModelOrSqlAlchemyT) -> SQLModelOrSqlAlchemyT:\n            \"\"\"Register a model. Can be used directly or as a decorator.\n\n            Args:\n                model: The model to register.\n\n            Returns:\n                The model passed in as an argument (Allows decorator usage)\n            \"\"\"\n            cls.models.add(model)\n            return model\n\n        @classmethod\n        def get_models(cls, include_empty: bool = False) -> set[SQLModelOrSqlAlchemy]:\n            \"\"\"Get registered models.\n\n            Args:\n                include_empty: If True, include models with empty metadata.\n\n            Returns:\n                The registered models.\n            \"\"\"\n            if include_empty:\n                return cls.models\n            return {\n                model for model in cls.models if not cls._model_metadata_is_empty(model)\n            }\n\n        @staticmethod\n        def _model_metadata_is_empty(model: SQLModelOrSqlAlchemy) -> bool:\n            \"\"\"Check if the model metadata is empty.\n\n            Args:\n                model: The model to check.\n\n            Returns:\n                True if the model metadata is empty, False otherwise.\n            \"\"\"\n            return len(model.metadata.tables) == 0\n\n        @classmethod\n        def get_metadata(cls) -> sqlalchemy.MetaData:\n            \"\"\"Get the database metadata.\n\n            Returns:\n                The database metadata.\n            \"\"\"\n            if cls._metadata is not None:\n                return cls._metadata\n\n            models = cls.get_models(include_empty=False)\n\n            if len(models) == 1:\n                metadata = next(iter(models)).metadata\n            else:\n                # Merge the metadata from all the models.\n                # This allows mixing bare sqlalchemy models with sqlmodel models in one database.\n                metadata = sqlalchemy.MetaData()\n                for model in cls.get_models():\n                    for table in model.metadata.tables.values():\n                        table.to_metadata(metadata)\n\n            # Cache the metadata\n            cls._metadata = metadata\n\n            return metadata\n\nelse:\n    get_engine_args = _print_db_not_available\n    get_engine = _print_db_not_available\n    get_async_engine = _print_db_not_available\n    sqla_session = _print_db_not_available\n    ModelRegistry = _ClassThatErrorsOnInit  # pyright: ignore [reportAssignmentType]\n\nif find_spec(\"sqlmodel\") and find_spec(\"sqlalchemy\") and find_spec(\"pydantic\"):\n    import alembic.autogenerate\n    import alembic.command\n    import alembic.config\n    import alembic.operations.ops\n    import alembic.runtime.environment\n    import alembic.script\n    import sqlmodel\n    from alembic.runtime.migration import MigrationContext\n    from alembic.script.base import Script\n    from sqlmodel.ext.asyncio.session import AsyncSession\n\n    _AsyncSessionLocal: dict[str | None, sqlalchemy.ext.asyncio.async_sessionmaker] = {}\n\n    def format_revision(\n        rev: Script,\n        current_rev: str | None,\n        current_reached_ref: list[bool],\n    ) -> str:\n        \"\"\"Format a single revision for display.\n\n        Args:\n            rev: The alembic script object\n            current_rev: The currently applied revision ID\n            current_reached_ref: Mutable reference to track if we've reached current revision\n\n        Returns:\n            Formatted string for display\n        \"\"\"\n        current = rev.revision\n        message = rev.doc\n\n        # Determine if this migration is applied\n        if current_rev is None:\n            is_applied = False\n        elif current == current_rev:\n            is_applied = True\n            current_reached_ref[0] = True\n        else:\n            is_applied = not current_reached_ref[0]\n\n        # Show checkmark or X with colors\n        status_icon = \"[green]✓[/green]\" if is_applied else \"[red]✗[/red]\"\n        head_marker = \" (head)\" if rev.is_head else \"\"\n\n        # Format output with message\n        return f\"  [{status_icon}] {current}{head_marker}, {message}\"\n\n    def get_db_status() -> dict[str, bool]:\n        \"\"\"Checks the status of the database connection.\n\n        Attempts to connect to the database and execute a simple query to verify connectivity.\n\n        Returns:\n            The status of the database connection.\n        \"\"\"\n        status = True\n        try:\n            engine = get_engine()\n            with engine.connect() as connection:\n                connection.execute(sqlalchemy.text(\"SELECT 1\"))\n        except Exception as exc:\n            status = False\n            console.error(\n                f\"Database health check failed: {exc} (subsequent errors will not be logged)\",\n                dedupe=True,\n            )\n\n        return {\"db\": status}\n\n    @serializer\n    def serialize_sqlmodel(m: sqlmodel.SQLModel) -> dict[str, Any]:\n        \"\"\"Serialize a SQLModel object to a dictionary.\n\n        Args:\n            m: The SQLModel object to serialize.\n\n        Returns:\n            The serialized object as a dictionary.\n        \"\"\"\n        base_fields = m.model_dump()\n        relationships = {}\n        # SQLModel relationships do not appear in __fields__, but should be included if present.\n        for name in m.__sqlmodel_relationships__:\n            with suppress(\n                sqlalchemy.orm.exc.DetachedInstanceError  # This happens when the relationship was never loaded and the session is closed.\n            ):\n                relationships[name] = getattr(m, name)\n        return {\n            **base_fields,\n            **relationships,\n        }\n\n    class Model(sqlmodel.SQLModel):\n        \"\"\"Base class to define a table in the database.\"\"\"\n\n        # The primary key for the table.\n        id: int | None = sqlmodel.Field(default=None, primary_key=True)\n\n        model_config = {  # pyright: ignore [reportAssignmentType]\n            \"arbitrary_types_allowed\": True,\n            \"use_enum_values\": True,\n            \"extra\": \"allow\",\n        }\n\n        @classmethod\n        def __pydantic_init_subclass__(cls):\n            \"\"\"Drop the default primary key field if any primary key field is defined.\"\"\"\n            non_default_primary_key_fields = [\n                field_name\n                for field_name, field_info in cls.model_fields.items()\n                if field_name != \"id\" and sqlmodel_field_has_primary_key(field_info)\n            ]\n            if non_default_primary_key_fields:\n                cls.model_fields.pop(\"id\", None)\n                console.deprecate(\n                    feature_name=\"Overriding default primary key\",\n                    reason=(\n                        \"Register sqlmodel.SQLModel classes with `@rx.ModelRegistry.register`\"\n                    ),\n                    deprecation_version=\"0.8.15\",\n                    removal_version=\"0.9.0\",\n                )\n            super().__pydantic_init_subclass__()\n\n        @staticmethod\n        def create_all():\n            \"\"\"Create all the tables.\"\"\"\n            engine = get_engine()\n            ModelRegistry.get_metadata().create_all(engine)\n\n        @staticmethod\n        def get_db_engine():\n            \"\"\"Get the database engine.\n\n            Returns:\n                The database engine.\n            \"\"\"\n            return get_engine()\n\n        @staticmethod\n        def _alembic_config():\n            \"\"\"Get the alembic configuration and script_directory.\n\n            Returns:\n                tuple of (config, script_directory)\n            \"\"\"\n            config = alembic.config.Config(environment.ALEMBIC_CONFIG.get())\n            if not config.get_main_option(\"script_location\"):\n                config.set_main_option(\"script_location\", \"version\")\n            return config, alembic.script.ScriptDirectory.from_config(config)\n\n        @staticmethod\n        def _alembic_render_item(\n            type_: str,\n            obj: Any,\n            autogen_context: alembic.autogenerate.api.AutogenContext,\n        ):\n            \"\"\"Alembic render_item hook call.\n\n            This method is called to provide python code for the given obj,\n            but currently it is only used to add `sqlmodel` to the import list\n            when generating migration scripts.\n\n            See https://alembic.sqlalchemy.org/en/latest/api/runtime.html\n\n            Args:\n                type_: One of \"schema\", \"table\", \"column\", \"index\",\n                    \"unique_constraint\", or \"foreign_key_constraint\".\n                obj: The object being rendered.\n                autogen_context: Shared AutogenContext passed to each render_item call.\n\n            Returns:\n                False - Indicating that the default rendering should be used.\n            \"\"\"\n            autogen_context.imports.add(\"import sqlmodel\")\n            return False\n\n        @classmethod\n        def alembic_init(cls):\n            \"\"\"Initialize alembic for the project.\"\"\"\n            alembic.command.init(\n                config=alembic.config.Config(environment.ALEMBIC_CONFIG.get()),\n                directory=str(environment.ALEMBIC_CONFIG.get().parent / \"alembic\"),\n            )\n\n        @classmethod\n        def get_migration_history(cls):\n            \"\"\"Get migration history with current database state.\n\n            Returns:\n                tuple: (current_revision, revisions_list) where revisions_list is in chronological order\n            \"\"\"\n            # Get current revision from database\n            with cls.get_db_engine().connect() as connection:\n                context = MigrationContext.configure(connection)\n                current_rev = context.get_current_revision()\n\n            # Get all revisions from base to head\n            _, script_dir = cls._alembic_config()\n            revisions = list(script_dir.walk_revisions())\n            revisions.reverse()  # Reverse to get chronological order (base first)\n\n            return current_rev, revisions\n\n        @classmethod\n        def alembic_autogenerate(\n            cls,\n            connection: sqlalchemy.engine.Connection,\n            message: str | None = None,\n            write_migration_scripts: bool = True,\n        ) -> bool:\n            \"\"\"Generate migration scripts for alembic-detectable changes.\n\n            Args:\n                connection: SQLAlchemy connection to use when detecting changes.\n                message: Human readable identifier describing the generated revision.\n                write_migration_scripts: If True, write autogenerated revisions to script directory.\n\n            Returns:\n                True when changes have been detected.\n            \"\"\"\n            if not environment.ALEMBIC_CONFIG.get().exists():\n                return False\n\n            config, script_directory = cls._alembic_config()\n            revision_context = alembic.autogenerate.api.RevisionContext(\n                config=config,\n                script_directory=script_directory,\n                command_args=defaultdict(\n                    lambda: None,\n                    autogenerate=True,\n                    head=\"head\",\n                    message=message,\n                ),\n            )\n            writer = alembic.autogenerate.rewriter.Rewriter()\n\n            @writer.rewrites(alembic.operations.ops.AddColumnOp)\n            def render_add_column_with_server_default(\n                context: MigrationContext,\n                revision: str | None,\n                op: Any,\n            ):\n                # Carry the sqlmodel default as server_default so that newly added\n                # columns get the desired default value in existing rows.\n                if op.column.default is not None and op.column.server_default is None:\n                    op.column.server_default = sqlalchemy.DefaultClause(\n                        sqlalchemy.sql.expression.literal(op.column.default.arg),\n                    )\n                return op\n\n            def run_autogenerate(rev: str, context: MigrationContext):\n                revision_context.run_autogenerate(rev, context)\n                return []\n\n            with alembic.runtime.environment.EnvironmentContext(\n                config=config,\n                script=script_directory,\n                fn=run_autogenerate,\n            ) as env:\n                env.configure(\n                    connection=connection,\n                    target_metadata=ModelRegistry.get_metadata(),\n                    render_item=cls._alembic_render_item,\n                    process_revision_directives=writer,\n                    compare_type=False,\n                    include_schemas=environment.ALEMBIC_INCLUDE_SCHEMAS.get(),\n                    render_as_batch=True,  # for sqlite compatibility\n                )\n                env.run_migrations()\n            changes_detected = False\n            if revision_context.generated_revisions:\n                upgrade_ops = revision_context.generated_revisions[-1].upgrade_ops\n                if upgrade_ops is not None:\n                    changes_detected = bool(upgrade_ops.ops)\n            if changes_detected and write_migration_scripts:\n                # Must iterate the generator to actually write the scripts.\n                _ = tuple(revision_context.generate_scripts())\n            return changes_detected\n\n        @classmethod\n        def _alembic_upgrade(\n            cls,\n            connection: sqlalchemy.engine.Connection,\n            to_rev: str = \"head\",\n        ) -> None:\n            \"\"\"Apply alembic migrations up to the given revision.\n\n            Args:\n                connection: SQLAlchemy connection to use when performing upgrade.\n                to_rev: Revision to migrate towards.\n            \"\"\"\n            config, script_directory = cls._alembic_config()\n\n            def run_upgrade(rev: str, context: MigrationContext):\n                return script_directory._upgrade_revs(to_rev, rev)\n\n            with alembic.runtime.environment.EnvironmentContext(\n                config=config,\n                script=script_directory,\n                fn=run_upgrade,\n            ) as env:\n                env.configure(connection=connection)\n                env.run_migrations()\n\n        @classmethod\n        def migrate(cls, autogenerate: bool = False) -> bool | None:\n            \"\"\"Execute alembic migrations for all sqlmodel Model classes.\n\n            If alembic is not installed or has not been initialized for the project,\n            then no action is performed.\n\n            If there are no revisions currently tracked by alembic, then\n            an initial revision will be created based on sqlmodel metadata.\n\n            If models in the app have changed in incompatible ways that alembic\n            cannot automatically generate revisions for, the app may not be able to\n            start up until migration scripts have been corrected by hand.\n\n            Args:\n                autogenerate: If True, generate migration script and use it to upgrade schema\n                    (otherwise, just bring the schema to current \"head\" revision).\n\n            Returns:\n                True - indicating the process was successful.\n                None - indicating the process was skipped.\n            \"\"\"\n            if not environment.ALEMBIC_CONFIG.get().exists():\n                return None\n\n            with cls.get_db_engine().connect() as connection:\n                cls._alembic_upgrade(connection=connection)\n                if autogenerate:\n                    changes_detected = cls.alembic_autogenerate(connection=connection)\n                    if changes_detected:\n                        cls._alembic_upgrade(connection=connection)\n                connection.commit()\n            return True\n\n        @classmethod\n        def select(cls):\n            \"\"\"Select rows from the table.\n\n            Returns:\n                The select statement.\n            \"\"\"\n            return sqlmodel.select(cls)\n\n    ModelRegistry.register(Model)\n\n    def session(url: str | None = None) -> sqlmodel.Session:\n        \"\"\"Get a sqlmodel session to interact with the database.\n\n        Args:\n            url: The database url.\n\n        Returns:\n            A database session.\n        \"\"\"\n        return sqlmodel.Session(get_engine(url))\n\n    def asession(url: str | None = None) -> AsyncSession:\n        \"\"\"Get an async sqlmodel session to interact with the database.\n\n        async with rx.asession() as asession:\n            ...\n\n        Most operations against the `asession` must be awaited.\n\n        Args:\n            url: The database url.\n\n        Returns:\n            An async database session.\n        \"\"\"\n        global _AsyncSessionLocal\n        if url not in _AsyncSessionLocal:\n            _AsyncSessionLocal[url] = sqlalchemy.ext.asyncio.async_sessionmaker(\n                bind=get_async_engine(url),\n                class_=AsyncSession,\n                expire_on_commit=False,\n                autocommit=False,\n                autoflush=False,\n            )\n        return _AsyncSessionLocal[url]()\n\nelse:\n    get_db_status = _print_db_not_available\n    session = _print_db_not_available\n    asession = _print_db_not_available\n    Model = _ClassThatErrorsOnInit  # pyright: ignore [reportAssignmentType]\n"
  },
  {
    "path": "reflex/page.py",
    "content": "\"\"\"The page decorator and associated variables and functions.\"\"\"\n\nfrom __future__ import annotations\n\nimport sys\nfrom collections import defaultdict\nfrom typing import TYPE_CHECKING\n\nif TYPE_CHECKING:\n    from collections.abc import Callable\n    from typing import Any\n\n    from reflex.event import EventType\n\nDECORATED_PAGES: dict[str, list] = defaultdict(list)\n\n\ndef page(\n    route: str | None = None,\n    title: str | None = None,\n    image: str | None = None,\n    description: str | None = None,\n    meta: list[Any] | None = None,\n    script_tags: list[Any] | None = None,\n    on_load: EventType[()] | None = None,\n):\n    \"\"\"Decorate a function as a page.\n\n    rx.App() will automatically call add_page() for any method decorated with page\n    when App.compile is called.\n\n    All defaults are None because they will use the one from add_page().\n\n    Note: the decorated functions still need to be imported.\n\n    Args:\n        route: The route to reach the page.\n        title: The title of the page.\n        image: The favicon of the page.\n        description: The description of the page.\n        meta: Additional meta to add to the page.\n        on_load: The event handler(s) called when the page load.\n        script_tags: scripts to attach to the page\n\n    Returns:\n        The decorated function.\n    \"\"\"\n    from reflex.config import get_config\n\n    def decorator(render_fn: Callable):\n        kwargs = {}\n        if route:\n            kwargs[\"route\"] = route\n        if title:\n            kwargs[\"title\"] = title\n        if image:\n            kwargs[\"image\"] = image\n        if description:\n            kwargs[\"description\"] = description\n        if meta:\n            kwargs[\"meta\"] = meta\n        if script_tags:\n            kwargs[\"script_tags\"] = script_tags\n        if on_load:\n            kwargs[\"on_load\"] = on_load\n\n        DECORATED_PAGES[get_config().app_name].append((render_fn, kwargs))\n\n        return render_fn\n\n    return decorator\n\n\nclass PageNamespace:\n    \"\"\"A namespace for page names.\"\"\"\n\n    DECORATED_PAGES = DECORATED_PAGES\n\n    def __new__(\n        cls,\n        route: str | None = None,\n        title: str | None = None,\n        image: str | None = None,\n        description: str | None = None,\n        meta: list[Any] | None = None,\n        script_tags: list[Any] | None = None,\n        on_load: EventType[()] | None = None,\n    ):\n        \"\"\"Decorate a function as a page.\n\n        rx.App() will automatically call add_page() for any method decorated with page\n        when App.compile is called.\n\n        All defaults are None because they will use the one from add_page().\n\n        Note: the decorated functions still need to be imported.\n\n        Args:\n            route: The route to reach the page.\n            title: The title of the page.\n            image: The favicon of the page.\n            description: The description of the page.\n            meta: Additional meta to add to the page.\n            on_load: The event handler(s) called when the page load.\n            script_tags: scripts to attach to the page\n\n        Returns:\n            The decorated function.\n        \"\"\"\n        return page(\n            route=route,\n            title=title,\n            image=image,\n            description=description,\n            meta=meta,\n            script_tags=script_tags,\n            on_load=on_load,\n        )\n\n    page = staticmethod(page)\n    __file__ = __file__\n\n\npage_namespace = PageNamespace\nsys.modules[__name__] = page_namespace  # pyright: ignore[reportArgumentType]\n"
  },
  {
    "path": "reflex/plugins/__init__.py",
    "content": "\"\"\"Reflex Plugin System.\"\"\"\n\nfrom ._screenshot import ScreenshotPlugin as _ScreenshotPlugin\nfrom .base import CommonContext, Plugin, PreCompileContext\nfrom .sitemap import SitemapPlugin\nfrom .tailwind_v3 import TailwindV3Plugin\nfrom .tailwind_v4 import TailwindV4Plugin\n\n__all__ = [\n    \"CommonContext\",\n    \"Plugin\",\n    \"PreCompileContext\",\n    \"SitemapPlugin\",\n    \"TailwindV3Plugin\",\n    \"TailwindV4Plugin\",\n    \"_ScreenshotPlugin\",\n]\n"
  },
  {
    "path": "reflex/plugins/_screenshot.py",
    "content": "\"\"\"Plugin to enable screenshot functionality.\"\"\"\n\nfrom typing import TYPE_CHECKING\n\nfrom reflex.plugins.base import Plugin as BasePlugin\n\nif TYPE_CHECKING:\n    from starlette.requests import Request\n    from starlette.responses import Response\n    from typing_extensions import Unpack\n\n    from reflex.app import App\n    from reflex.plugins.base import PostCompileContext\n    from reflex.state import BaseState\n\nACTIVE_CONNECTIONS = \"/_active_connections\"\nCLONE_STATE = \"/_clone_state\"\n\n\ndef _deep_copy(state: \"BaseState\") -> \"BaseState\":\n    \"\"\"Create a deep copy of the state.\n\n    Args:\n        state: The state to copy.\n\n    Returns:\n        A deep copy of the state.\n    \"\"\"\n    import copy\n\n    copy_of_state = copy.deepcopy(state)\n\n    def copy_substate(substate: \"BaseState\") -> \"BaseState\":\n        substate_copy = _deep_copy(substate)\n\n        substate_copy.parent_state = copy_of_state\n\n        return substate_copy\n\n    copy_of_state.substates = {\n        substate_name: copy_substate(substate)\n        for substate_name, substate in state.substates.items()\n    }\n\n    return copy_of_state\n\n\nclass ScreenshotPlugin(BasePlugin):\n    \"\"\"Plugin to handle screenshot functionality.\"\"\"\n\n    def post_compile(self, **context: \"Unpack[PostCompileContext]\") -> None:\n        \"\"\"Called after the compilation of the plugin.\n\n        Args:\n            context: The context for the plugin.\n        \"\"\"\n        app = context[\"app\"]\n        self._add_active_connections_endpoint(app)\n        self._add_clone_state_endpoint(app)\n\n    @staticmethod\n    def _add_active_connections_endpoint(app: \"App\") -> None:\n        \"\"\"Add an endpoint to the app that returns the active connections.\n\n        Args:\n            app: The application instance to which the endpoint will be added.\n        \"\"\"\n        if not app._api:\n            return\n\n        def active_connections(_request: \"Request\") -> \"Response\":\n            from starlette.responses import JSONResponse\n\n            if not app.event_namespace:\n                return JSONResponse({})\n\n            return JSONResponse(app.event_namespace.token_to_sid)\n\n        app._api.add_route(\n            ACTIVE_CONNECTIONS,\n            active_connections,\n            methods=[\"GET\"],\n        )\n\n    @staticmethod\n    def _add_clone_state_endpoint(app: \"App\") -> None:\n        \"\"\"Add an endpoint to the app that clones the current state.\n\n        Args:\n            app: The application instance to which the endpoint will be added.\n        \"\"\"\n        if not app._api:\n            return\n\n        async def clone_state(request: \"Request\") -> \"Response\":\n            import uuid\n\n            from starlette.responses import JSONResponse\n\n            from reflex.state import _substate_key\n\n            if not app.event_namespace:\n                return JSONResponse({})\n\n            token_to_clone = await request.json()\n\n            if not isinstance(token_to_clone, str):\n                return JSONResponse(\n                    {\"error\": \"Token to clone must be a string.\"}, status_code=400\n                )\n\n            old_state = await app.state_manager.get_state(token_to_clone)\n\n            new_state = _deep_copy(old_state)\n\n            new_token = uuid.uuid4().hex\n\n            all_states = [new_state]\n\n            found_new = True\n\n            while found_new:\n                found_new = False\n\n                for state in list(all_states):\n                    for substate in state.substates.values():\n                        substate._was_touched = True\n\n                        if substate not in all_states:\n                            all_states.append(substate)\n\n                            found_new = True\n\n            await app.state_manager.set_state(\n                _substate_key(new_token, new_state), new_state\n            )\n\n            return JSONResponse(new_token)\n\n        app._api.add_route(\n            CLONE_STATE,\n            clone_state,\n            methods=[\"POST\"],\n        )\n"
  },
  {
    "path": "reflex/plugins/base.py",
    "content": "\"\"\"Base class for all plugins.\"\"\"\n\nfrom collections.abc import Callable, Sequence\nfrom pathlib import Path\nfrom typing import TYPE_CHECKING, ParamSpec, Protocol, TypedDict\n\nfrom typing_extensions import Unpack\n\nif TYPE_CHECKING:\n    from reflex.app import App, UnevaluatedPage\n\n\nclass CommonContext(TypedDict):\n    \"\"\"Common context for all plugins.\"\"\"\n\n\nP = ParamSpec(\"P\")\n\n\nclass AddTaskProtocol(Protocol):\n    \"\"\"Protocol for adding a task to the pre-compile context.\"\"\"\n\n    def __call__(\n        self,\n        task: Callable[P, list[tuple[str, str]] | tuple[str, str] | None],\n        /,\n        *args: P.args,\n        **kwargs: P.kwargs,\n    ) -> None:\n        \"\"\"Add a task to the pre-compile context.\n\n        Args:\n            task: The task to add.\n            args: The arguments to pass to the task\n            kwargs: The keyword arguments to pass to the task\n        \"\"\"\n\n\nclass PreCompileContext(CommonContext):\n    \"\"\"Context for pre-compile hooks.\"\"\"\n\n    add_save_task: AddTaskProtocol\n    add_modify_task: Callable[[str, Callable[[str], str]], None]\n    unevaluated_pages: Sequence[\"UnevaluatedPage\"]\n\n\nclass PostCompileContext(CommonContext):\n    \"\"\"Context for post-compile hooks.\"\"\"\n\n    app: \"App\"\n\n\nclass Plugin:\n    \"\"\"Base class for all plugins.\"\"\"\n\n    def get_frontend_development_dependencies(\n        self, **context: Unpack[CommonContext]\n    ) -> list[str] | set[str] | tuple[str, ...]:\n        \"\"\"Get the NPM packages required by the plugin for development.\n\n        Args:\n            context: The context for the plugin.\n\n        Returns:\n            A list of packages required by the plugin for development.\n        \"\"\"\n        return []\n\n    def get_frontend_dependencies(\n        self, **context: Unpack[CommonContext]\n    ) -> list[str] | set[str] | tuple[str, ...]:\n        \"\"\"Get the NPM packages required by the plugin.\n\n        Args:\n            context: The context for the plugin.\n\n        Returns:\n            A list of packages required by the plugin.\n        \"\"\"\n        return []\n\n    def get_static_assets(\n        self, **context: Unpack[CommonContext]\n    ) -> Sequence[tuple[Path, str | bytes]]:\n        \"\"\"Get the static assets required by the plugin.\n\n        Args:\n            context: The context for the plugin.\n\n        Returns:\n            A list of static assets required by the plugin.\n        \"\"\"\n        return []\n\n    def get_stylesheet_paths(self, **context: Unpack[CommonContext]) -> Sequence[str]:\n        \"\"\"Get the paths to the stylesheets required by the plugin relative to the styles directory.\n\n        Args:\n            context: The context for the plugin.\n\n        Returns:\n            A list of paths to the stylesheets required by the plugin.\n        \"\"\"\n        return []\n\n    def pre_compile(self, **context: Unpack[PreCompileContext]) -> None:\n        \"\"\"Called before the compilation of the plugin.\n\n        Args:\n            context: The context for the plugin.\n        \"\"\"\n\n    def post_compile(self, **context: Unpack[PostCompileContext]) -> None:\n        \"\"\"Called after the compilation of the plugin.\n\n        Args:\n            context: The context for the plugin.\n        \"\"\"\n\n    def __repr__(self):\n        \"\"\"Return a string representation of the plugin.\n\n        Returns:\n            A string representation of the plugin.\n        \"\"\"\n        return f\"{self.__class__.__name__}()\"\n"
  },
  {
    "path": "reflex/plugins/shared_tailwind.py",
    "content": "\"\"\"Tailwind CSS configuration types for Reflex plugins.\"\"\"\n\nimport dataclasses\nfrom collections.abc import Mapping\nfrom copy import deepcopy\nfrom typing import Any, Literal, TypedDict\n\nfrom typing_extensions import NotRequired, Unpack\n\nfrom .base import Plugin as PluginBase\n\nTailwindPluginImport = TypedDict(\n    \"TailwindPluginImport\",\n    {\n        \"name\": str,\n        \"from\": str,\n    },\n)\n\nTailwindPluginWithCallConfig = TypedDict(\n    \"TailwindPluginWithCallConfig\",\n    {\n        \"name\": str,\n        \"import\": NotRequired[TailwindPluginImport],\n        \"call\": str,\n        \"args\": NotRequired[dict[str, Any]],\n    },\n)\n\nTailwindPluginWithoutCallConfig = TypedDict(\n    \"TailwindPluginWithoutCallConfig\",\n    {\n        \"name\": str,\n        \"import\": NotRequired[TailwindPluginImport],\n    },\n)\n\nTailwindPluginConfig = (\n    TailwindPluginWithCallConfig | TailwindPluginWithoutCallConfig | str\n)\n\n\ndef remove_version_from_plugin(plugin: TailwindPluginConfig) -> TailwindPluginConfig:\n    \"\"\"Remove the version from a plugin name.\n\n    Args:\n        plugin: The plugin to remove the version from.\n\n    Returns:\n        The plugin without the version.\n    \"\"\"\n    from reflex.utils.format import format_library_name\n\n    if isinstance(plugin, str):\n        return format_library_name(plugin)\n\n    if plugin_import := plugin.get(\"import\"):\n        plugin_import[\"from\"] = format_library_name(plugin_import[\"from\"])\n\n    plugin[\"name\"] = format_library_name(plugin[\"name\"])\n\n    return plugin\n\n\nclass TailwindConfig(TypedDict):\n    \"\"\"Tailwind CSS configuration options.\n\n    See: https://tailwindcss.com/docs/configuration\n    \"\"\"\n\n    content: NotRequired[list[str]]\n    important: NotRequired[str | bool]\n    prefix: NotRequired[str]\n    separator: NotRequired[str]\n    presets: NotRequired[list[str]]\n    darkMode: NotRequired[Literal[\"media\", \"class\", \"selector\"]]\n    theme: NotRequired[dict[str, Any]]\n    corePlugins: NotRequired[list[str] | dict[str, bool]]\n    plugins: NotRequired[list[TailwindPluginConfig]]\n\n\ndef tailwind_config_js_template(\n    *, default_content: list[str], **kwargs: Unpack[TailwindConfig]\n):\n    \"\"\"Generate a Tailwind CSS configuration file in JavaScript format.\n\n    Args:\n        default_content: The default content to use if none is provided.\n        **kwargs: The template variables.\n\n    Returns:\n        The Tailwind config template.\n    \"\"\"\n    import json\n\n    # Extract parameters\n    plugins = kwargs.get(\"plugins\", [])\n    presets = kwargs.get(\"presets\", [])\n    content = kwargs.get(\"content\")\n    theme = kwargs.get(\"theme\")\n    dark_mode = kwargs.get(\"darkMode\")\n    core_plugins = kwargs.get(\"corePlugins\")\n    important = kwargs.get(\"important\")\n    prefix = kwargs.get(\"prefix\")\n    separator = kwargs.get(\"separator\")\n\n    # Extract destructured imports from plugin dicts only\n    imports = [\n        plugin[\"import\"]\n        for plugin in plugins\n        if isinstance(plugin, Mapping) and \"import\" in plugin\n    ]\n\n    # Generate import statements for destructured imports\n    import_lines = \"\\n\".join([\n        f\"import {{ {imp['name']} }} from {json.dumps(imp['from'])};\" for imp in imports\n    ])\n\n    # Generate plugin imports\n    plugin_imports = []\n    for i, plugin in enumerate(plugins, 1):\n        if isinstance(plugin, Mapping) and \"call\" not in plugin:\n            plugin_imports.append(\n                f\"import plugin{i} from {json.dumps(plugin['name'])};\"\n            )\n        elif not isinstance(plugin, Mapping):\n            plugin_imports.append(f\"import plugin{i} from {json.dumps(plugin)};\")\n\n    plugin_imports_lines = \"\\n\".join(plugin_imports)\n\n    presets_imports_lines = \"\\n\".join([\n        f\"import preset{i} from {json.dumps(preset)};\"\n        for i, preset in enumerate(presets, 1)\n    ])\n\n    # Generate plugin array\n    plugin_list = []\n    for i, plugin in enumerate(plugins, 1):\n        if isinstance(plugin, Mapping) and \"call\" in plugin:\n            args_part = \"\"\n            if \"args\" in plugin:\n                args_part = json.dumps(plugin[\"args\"])\n            plugin_list.append(f\"{plugin['call']}({args_part})\")\n        else:\n            plugin_list.append(f\"plugin{i}\")\n\n    plugin_use_str = \",\".join(plugin_list)\n\n    return rf\"\"\"\n{import_lines}\n\n{plugin_imports_lines}\n\n{presets_imports_lines}\n\nexport default {{\n    content: {json.dumps(content or default_content)},\n    theme: {json.dumps(theme or {})},\n    {f\"darkMode: {json.dumps(dark_mode)},\" if dark_mode is not None else \"\"}\n    {f\"corePlugins: {json.dumps(core_plugins)},\" if core_plugins is not None else \"\"}\n    {f\"importants: {json.dumps(important)},\" if important is not None else \"\"}\n    {f\"prefix: {json.dumps(prefix)},\" if prefix is not None else \"\"}\n    {f\"separator: {json.dumps(separator)},\" if separator is not None else \"\"}\n    {f\"presets: [{', '.join(f'preset{i}' for i in range(1, len(presets) + 1))}],\" if presets else \"\"}\n    plugins: [{plugin_use_str}]\n}};\n\"\"\"\n\n\n@dataclasses.dataclass\nclass TailwindPlugin(PluginBase):\n    \"\"\"Plugin for Tailwind CSS.\"\"\"\n\n    config: TailwindConfig = dataclasses.field(\n        default_factory=lambda: TailwindConfig(\n            plugins=[\n                \"@tailwindcss/typography@0.5.19\",\n            ],\n        )\n    )\n\n    def get_frontend_development_dependencies(self, **context) -> list[str]:\n        \"\"\"Get the packages required by the plugin.\n\n        Args:\n            **context: The context for the plugin.\n\n        Returns:\n            A list of packages required by the plugin.\n        \"\"\"\n        config = self.get_config()\n\n        return [\n            plugin if isinstance(plugin, str) else plugin.get(\"name\")\n            for plugin in config.get(\"plugins\", [])\n        ] + config.get(\"presets\", [])\n\n    def get_config(self) -> TailwindConfig:\n        \"\"\"Get the Tailwind CSS configuration.\n\n        Returns:\n            The Tailwind CSS configuration.\n        \"\"\"\n        from reflex.config import get_config\n\n        rxconfig_config = getattr(get_config(), \"tailwind\", None)\n\n        if rxconfig_config is not None and rxconfig_config != self.config:\n            from reflex.utils import console\n\n            console.warn(\n                \"It seems you have provided a tailwind configuration in your call to `rx.Config`.\"\n                f\" You should provide the configuration as an argument to `rx.plugins.{self.__class__.__name__}()` instead.\"\n            )\n            return rxconfig_config\n\n        return self.config\n\n    def get_unversioned_config(self) -> TailwindConfig:\n        \"\"\"Get the Tailwind CSS configuration without version-specific adjustments.\n\n        Returns:\n            The Tailwind CSS configuration without version-specific adjustments.\n        \"\"\"\n        from reflex.utils.format import format_library_name\n\n        config = deepcopy(self.get_config())\n        if presets := config.get(\"presets\"):\n            # Somehow, having an empty list of presets breaks Tailwind.\n            # So we only set the presets if there are any.\n            config[\"presets\"] = [format_library_name(preset) for preset in presets]\n        config[\"plugins\"] = [\n            remove_version_from_plugin(plugin) for plugin in config.get(\"plugins\", [])\n        ]\n        return config\n"
  },
  {
    "path": "reflex/plugins/sitemap.py",
    "content": "\"\"\"Sitemap plugin for Reflex.\"\"\"\n\nimport datetime\nfrom collections.abc import Sequence\nfrom pathlib import Path\nfrom types import SimpleNamespace\nfrom typing import TYPE_CHECKING, Literal, TypedDict\nfrom xml.etree.ElementTree import Element, SubElement, indent, tostring\n\nfrom typing_extensions import NotRequired\n\nfrom reflex import constants\n\nfrom .base import Plugin as PluginBase\n\nif TYPE_CHECKING:\n    from reflex.app import UnevaluatedPage\n\nLocation = str\nLastModified = datetime.datetime\nChangeFrequency = Literal[\n    \"always\", \"hourly\", \"daily\", \"weekly\", \"monthly\", \"yearly\", \"never\"\n]\nPriority = float\n\n\nclass SitemapLink(TypedDict):\n    \"\"\"A link in the sitemap.\"\"\"\n\n    loc: Location\n    lastmod: NotRequired[LastModified]\n    changefreq: NotRequired[ChangeFrequency]\n    priority: NotRequired[Priority]\n\n\nclass SitemapLinkConfiguration(TypedDict):\n    \"\"\"Configuration for a sitemap link.\"\"\"\n\n    loc: NotRequired[Location]\n    lastmod: NotRequired[LastModified]\n    changefreq: NotRequired[ChangeFrequency]\n    priority: NotRequired[Priority]\n\n\nclass Constants(SimpleNamespace):\n    \"\"\"Sitemap constants.\"\"\"\n\n    FILE_PATH: Path = Path(constants.Dirs.PUBLIC) / \"sitemap.xml\"\n\n\ndef configuration_with_loc(\n    *, config: SitemapLinkConfiguration, deploy_url: str | None, loc: Location\n) -> SitemapLink:\n    \"\"\"Set the 'loc' field of the configuration.\n\n    Args:\n        config: The configuration dictionary.\n        deploy_url: The deployment URL, if any.\n        loc: The location to set.\n\n    Returns:\n        A SitemapLink dictionary with the 'loc' field set.\n    \"\"\"\n    if deploy_url and not loc.startswith(\"http://\") and not loc.startswith(\"https://\"):\n        loc = f\"{deploy_url.rstrip('/')}/{loc.lstrip('/')}\"\n    link: SitemapLink = {\"loc\": loc}\n    if (lastmod := config.get(\"lastmod\")) is not None:\n        link[\"lastmod\"] = lastmod\n    if (changefreq := config.get(\"changefreq\")) is not None:\n        link[\"changefreq\"] = changefreq\n    if (priority := config.get(\"priority\")) is not None:\n        link[\"priority\"] = min(1.0, max(0.0, priority))\n    return link\n\n\ndef generate_xml(links: Sequence[SitemapLink]) -> str:\n    \"\"\"Generate an XML sitemap from a list of links.\n\n    Args:\n        links: A sequence of SitemapLink dictionaries.\n\n    Returns:\n        A pretty-printed XML string representing the sitemap.\n    \"\"\"\n    urlset = Element(\"urlset\", xmlns=\"https://www.sitemaps.org/schemas/sitemap/0.9\")\n\n    for link in links:\n        url = SubElement(urlset, \"url\")\n\n        loc_element = SubElement(url, \"loc\")\n        loc_element.text = link[\"loc\"]\n\n        if (changefreq := link.get(\"changefreq\")) is not None:\n            changefreq_element = SubElement(url, \"changefreq\")\n            changefreq_element.text = changefreq\n\n        if (lastmod := link.get(\"lastmod\")) is not None:\n            lastmod_element = SubElement(url, \"lastmod\")\n            if isinstance(lastmod, datetime.datetime):\n                lastmod = lastmod.isoformat()\n            lastmod_element.text = lastmod\n\n        if (priority := link.get(\"priority\")) is not None:\n            priority_element = SubElement(url, \"priority\")\n            priority_element.text = str(priority)\n    indent(urlset, \"  \")\n    return tostring(urlset, encoding=\"utf-8\", xml_declaration=True).decode(\"utf-8\")\n\n\ndef is_route_dynamic(route: str) -> bool:\n    \"\"\"Check if a route is dynamic.\n\n    Args:\n        route: The route to check.\n\n    Returns:\n        True if the route is dynamic, False otherwise.\n    \"\"\"\n    return \"[\" in route and \"]\" in route\n\n\ndef generate_links_for_sitemap(\n    unevaluated_pages: Sequence[\"UnevaluatedPage\"],\n) -> list[SitemapLink]:\n    \"\"\"Generate sitemap links from unevaluated pages.\n\n    Args:\n        unevaluated_pages: Sequence of unevaluated pages.\n\n    Returns:\n        A list of SitemapLink dictionaries.\n    \"\"\"\n    from reflex.config import get_config\n    from reflex.utils import console\n\n    deploy_url = get_config().deploy_url\n\n    links: list[SitemapLink] = []\n\n    for page in unevaluated_pages:\n        sitemap_config: SitemapLinkConfiguration | None = page.context.get(\n            \"sitemap\", {}\n        )\n        if sitemap_config is None:\n            continue\n\n        if is_route_dynamic(page.route) or page.route == \"404\":\n            if not sitemap_config:\n                continue\n\n            if (loc := sitemap_config.get(\"loc\")) is None:\n                route_message = (\n                    \"Dynamic route\" if is_route_dynamic(page.route) else \"Route 404\"\n                )\n                console.warn(\n                    route_message\n                    + f\" '{page.route}' does not have a 'loc' in sitemap configuration. Skipping.\"\n                )\n                continue\n\n            sitemap_link = configuration_with_loc(\n                config=sitemap_config, deploy_url=deploy_url, loc=loc\n            )\n\n        elif (loc := sitemap_config.get(\"loc\")) is not None:\n            sitemap_link = configuration_with_loc(\n                config=sitemap_config, deploy_url=deploy_url, loc=loc\n            )\n\n        else:\n            loc = page.route if page.route != \"index\" else \"/\"\n            if not loc.startswith(\"/\"):\n                loc = \"/\" + loc\n            sitemap_link = configuration_with_loc(\n                config=sitemap_config, deploy_url=deploy_url, loc=loc\n            )\n\n        links.append(sitemap_link)\n    return links\n\n\ndef sitemap_task(unevaluated_pages: Sequence[\"UnevaluatedPage\"]) -> tuple[str, str]:\n    \"\"\"Task to generate the sitemap XML file.\n\n    Args:\n        unevaluated_pages: Sequence of unevaluated pages.\n\n    Returns:\n        A tuple containing the file path and the generated XML content.\n    \"\"\"\n    return (\n        str(Constants.FILE_PATH),\n        generate_xml(generate_links_for_sitemap(unevaluated_pages)),\n    )\n\n\nclass SitemapPlugin(PluginBase):\n    \"\"\"Sitemap plugin for Reflex.\"\"\"\n\n    def pre_compile(self, **context):\n        \"\"\"Generate the sitemap XML file before compilation.\n\n        Args:\n            context: The context for the plugin.\n        \"\"\"\n        unevaluated_pages = context.get(\"unevaluated_pages\", [])\n        context[\"add_save_task\"](sitemap_task, unevaluated_pages)\n\n\nPlugin = SitemapPlugin\n"
  },
  {
    "path": "reflex/plugins/tailwind_v3.py",
    "content": "\"\"\"Base class for all plugins.\"\"\"\n\nimport dataclasses\nfrom pathlib import Path\nfrom types import SimpleNamespace\n\nfrom reflex.constants.base import Dirs\nfrom reflex.constants.compiler import Ext, PageNames\nfrom reflex.plugins.shared_tailwind import (\n    TailwindConfig,\n    TailwindPlugin,\n    tailwind_config_js_template,\n)\n\n\nclass Constants(SimpleNamespace):\n    \"\"\"Tailwind constants.\"\"\"\n\n    # The Tailwindcss version\n    VERSION = \"tailwindcss@3.4.19\"\n    # The Tailwind config.\n    CONFIG = \"tailwind.config.js\"\n    # Default Tailwind content paths\n    CONTENT = [f\"./{Dirs.PAGES}/**/*.{{js,ts,jsx,tsx}}\", \"./utils/**/*.{js,ts,jsx,tsx}\"]\n    # Relative tailwind style path to root stylesheet in Dirs.STYLES.\n    ROOT_STYLE_PATH = \"./tailwind.css\"\n\n    # Content of the style content.\n    ROOT_STYLE_CONTENT = \"\"\"\n@import \"tailwindcss/base\";\n\n@import url('{radix_url}');\n\n@tailwind components;\n@tailwind utilities;\n\"\"\"\n\n    # The default tailwind css.\n    TAILWIND_CSS = \"@import url('./tailwind.css');\"\n\n\ndef compile_config(config: TailwindConfig):\n    \"\"\"Compile the Tailwind config.\n\n    Args:\n        config: The Tailwind config.\n\n    Returns:\n        The compiled Tailwind config.\n    \"\"\"\n    return Constants.CONFIG, tailwind_config_js_template(\n        **config,\n        default_content=Constants.CONTENT,\n    )\n\n\ndef compile_root_style():\n    \"\"\"Compile the Tailwind root style.\n\n    Returns:\n        The compiled Tailwind root style.\n    \"\"\"\n    from reflex.compiler.compiler import RADIX_THEMES_STYLESHEET\n\n    return str(\n        Path(Dirs.STYLES) / Constants.ROOT_STYLE_PATH\n    ), Constants.ROOT_STYLE_CONTENT.format(\n        radix_url=RADIX_THEMES_STYLESHEET,\n    )\n\n\ndef _index_of_element_that_has(haystack: list[str], needle: str) -> int | None:\n    return next(\n        (i for i, line in enumerate(haystack) if needle in line),\n        None,\n    )\n\n\ndef add_tailwind_to_postcss_config(postcss_file_content: str) -> str:\n    \"\"\"Add tailwind to the postcss config.\n\n    Args:\n        postcss_file_content: The content of the postcss config file.\n\n    Returns:\n        The modified postcss config file content.\n    \"\"\"\n    from reflex.constants import Dirs\n\n    postcss_file_lines = postcss_file_content.splitlines()\n\n    if _index_of_element_that_has(postcss_file_lines, \"tailwindcss\") is not None:\n        return postcss_file_content\n\n    line_with_postcss_plugins = _index_of_element_that_has(\n        postcss_file_lines, \"plugins\"\n    )\n    if not line_with_postcss_plugins:\n        print(  # noqa: T201\n            f\"Could not find line with 'plugins' in {Dirs.POSTCSS_JS}. \"\n            \"Please make sure the file exists and is valid.\"\n        )\n        return postcss_file_content\n\n    postcss_import_line = _index_of_element_that_has(\n        postcss_file_lines, '\"postcss-import\"'\n    )\n    postcss_file_lines.insert(\n        (postcss_import_line or line_with_postcss_plugins) + 1, \"tailwindcss: {},\"\n    )\n\n    return \"\\n\".join(postcss_file_lines)\n\n\ndef add_tailwind_to_css_file(css_file_content: str) -> str:\n    \"\"\"Add tailwind to the css file.\n\n    Args:\n        css_file_content: The content of the css file.\n\n    Returns:\n        The modified css file content.\n    \"\"\"\n    from reflex.compiler.compiler import RADIX_THEMES_STYLESHEET\n\n    if Constants.TAILWIND_CSS.splitlines()[0] in css_file_content:\n        return css_file_content\n    if RADIX_THEMES_STYLESHEET not in css_file_content:\n        print(  # noqa: T201\n            f\"Could not find line with '{RADIX_THEMES_STYLESHEET}' in {Dirs.STYLES}. \"\n            \"Please make sure the file exists and is valid.\"\n        )\n        return css_file_content\n    return css_file_content.replace(\n        f\"@import url('{RADIX_THEMES_STYLESHEET}');\",\n        Constants.TAILWIND_CSS,\n    )\n\n\n@dataclasses.dataclass\nclass TailwindV3Plugin(TailwindPlugin):\n    \"\"\"Plugin for Tailwind CSS.\"\"\"\n\n    def get_frontend_development_dependencies(self, **context) -> list[str]:\n        \"\"\"Get the packages required by the plugin.\n\n        Args:\n            **context: The context for the plugin.\n\n        Returns:\n            A list of packages required by the plugin.\n        \"\"\"\n        return [\n            *super().get_frontend_development_dependencies(**context),\n            Constants.VERSION,\n        ]\n\n    def pre_compile(self, **context):\n        \"\"\"Pre-compile the plugin.\n\n        Args:\n            context: The context for the plugin.\n        \"\"\"\n        context[\"add_save_task\"](compile_config, self.get_unversioned_config())\n        context[\"add_save_task\"](compile_root_style)\n        context[\"add_modify_task\"](Dirs.POSTCSS_JS, add_tailwind_to_postcss_config)\n        context[\"add_modify_task\"](\n            str(Path(Dirs.STYLES) / (PageNames.STYLESHEET_ROOT + Ext.CSS)),\n            add_tailwind_to_css_file,\n        )\n"
  },
  {
    "path": "reflex/plugins/tailwind_v4.py",
    "content": "\"\"\"Base class for all plugins.\"\"\"\n\nimport dataclasses\nfrom pathlib import Path\nfrom types import SimpleNamespace\n\nfrom reflex.constants.base import Dirs\nfrom reflex.constants.compiler import Ext, PageNames\nfrom reflex.plugins.shared_tailwind import (\n    TailwindConfig,\n    TailwindPlugin,\n    tailwind_config_js_template,\n)\n\n\nclass Constants(SimpleNamespace):\n    \"\"\"Tailwind constants.\"\"\"\n\n    # The Tailwindcss version\n    VERSION = \"tailwindcss@4.2.2\"\n    # The Tailwind config.\n    CONFIG = \"tailwind.config.js\"\n    # Default Tailwind content paths\n    CONTENT = [f\"./{Dirs.PAGES}/**/*.{{js,ts,jsx,tsx}}\", \"./utils/**/*.{js,ts,jsx,tsx}\"]\n    # Relative tailwind style path to root stylesheet in Dirs.STYLES.\n    ROOT_STYLE_PATH = \"./tailwind.css\"\n\n    # Content of the style content.\n    ROOT_STYLE_CONTENT = \"\"\"@layer theme, base, components, utilities;\n@import \"tailwindcss/theme.css\" layer(theme);\n@import \"tailwindcss/preflight.css\" layer(base);\n@import \"{radix_url}\" layer(components);\n@import \"tailwindcss/utilities.css\" layer(utilities);\n@config \"../tailwind.config.js\";\n\"\"\"\n\n    # The default tailwind css.\n    TAILWIND_CSS = \"@import url('./tailwind.css');\"\n\n\ndef compile_config(config: TailwindConfig):\n    \"\"\"Compile the Tailwind config.\n\n    Args:\n        config: The Tailwind config.\n\n    Returns:\n        The compiled Tailwind config.\n    \"\"\"\n    return Constants.CONFIG, tailwind_config_js_template(\n        **config,\n        default_content=Constants.CONTENT,\n    )\n\n\ndef compile_root_style():\n    \"\"\"Compile the Tailwind root style.\n\n    Returns:\n        The compiled Tailwind root style.\n    \"\"\"\n    from reflex.compiler.compiler import RADIX_THEMES_STYLESHEET\n\n    return str(\n        Path(Dirs.STYLES) / Constants.ROOT_STYLE_PATH\n    ), Constants.ROOT_STYLE_CONTENT.format(\n        radix_url=RADIX_THEMES_STYLESHEET,\n    )\n\n\ndef _index_of_element_that_has(haystack: list[str], needle: str) -> int | None:\n    return next(\n        (i for i, line in enumerate(haystack) if needle in line),\n        None,\n    )\n\n\ndef add_tailwind_to_postcss_config(postcss_file_content: str) -> str:\n    \"\"\"Add tailwind to the postcss config.\n\n    Args:\n        postcss_file_content: The content of the postcss config file.\n\n    Returns:\n        The modified postcss config file content.\n    \"\"\"\n    from reflex.constants import Dirs\n\n    postcss_file_lines = postcss_file_content.splitlines()\n\n    line_with_postcss_plugins = _index_of_element_that_has(\n        postcss_file_lines, \"plugins\"\n    )\n    if not line_with_postcss_plugins:\n        print(  # noqa: T201\n            f\"Could not find line with 'plugins' in {Dirs.POSTCSS_JS}. \"\n            \"Please make sure the file exists and is valid.\"\n        )\n        return postcss_file_content\n\n    plugins_to_remove = ['\"postcss-import\"', \"tailwindcss\", \"autoprefixer\"]\n    plugins_to_add = ['\"@tailwindcss/postcss\"']\n\n    for plugin in plugins_to_remove:\n        plugin_index = _index_of_element_that_has(postcss_file_lines, plugin)\n        if plugin_index is not None:\n            postcss_file_lines.pop(plugin_index)\n\n    for plugin in plugins_to_add[::-1]:\n        if not _index_of_element_that_has(postcss_file_lines, plugin):\n            postcss_file_lines.insert(\n                line_with_postcss_plugins + 1, f\"  {plugin}: {{}},\"\n            )\n\n    return \"\\n\".join(postcss_file_lines)\n\n\ndef add_tailwind_to_css_file(css_file_content: str) -> str:\n    \"\"\"Add tailwind to the css file.\n\n    Args:\n        css_file_content: The content of the css file.\n\n    Returns:\n        The modified css file content.\n    \"\"\"\n    from reflex.compiler.compiler import RADIX_THEMES_STYLESHEET\n\n    if Constants.TAILWIND_CSS.splitlines()[0] in css_file_content:\n        return css_file_content\n    if RADIX_THEMES_STYLESHEET not in css_file_content:\n        print(  # noqa: T201\n            f\"Could not find line with '{RADIX_THEMES_STYLESHEET}' in {Dirs.STYLES}. \"\n            \"Please make sure the file exists and is valid.\"\n        )\n        return css_file_content\n    return css_file_content.replace(\n        f\"@import url('{RADIX_THEMES_STYLESHEET}');\",\n        Constants.TAILWIND_CSS,\n    )\n\n\n@dataclasses.dataclass\nclass TailwindV4Plugin(TailwindPlugin):\n    \"\"\"Plugin for Tailwind CSS.\"\"\"\n\n    def get_frontend_development_dependencies(self, **context) -> list[str]:\n        \"\"\"Get the packages required by the plugin.\n\n        Args:\n            **context: The context for the plugin.\n\n        Returns:\n            A list of packages required by the plugin.\n        \"\"\"\n        return [\n            *super().get_frontend_development_dependencies(**context),\n            Constants.VERSION,\n            \"@tailwindcss/postcss@4.2.2\",\n        ]\n\n    def pre_compile(self, **context):\n        \"\"\"Pre-compile the plugin.\n\n        Args:\n            context: The context for the plugin.\n        \"\"\"\n        context[\"add_save_task\"](compile_config, self.get_unversioned_config())\n        context[\"add_save_task\"](compile_root_style)\n        context[\"add_modify_task\"](Dirs.POSTCSS_JS, add_tailwind_to_postcss_config)\n        context[\"add_modify_task\"](\n            str(Path(Dirs.STYLES) / (PageNames.STYLESHEET_ROOT + Ext.CSS)),\n            add_tailwind_to_css_file,\n        )\n"
  },
  {
    "path": "reflex/py.typed",
    "content": ""
  },
  {
    "path": "reflex/reflex.py",
    "content": "\"\"\"Reflex CLI to create, run, and deploy apps.\"\"\"\n\nfrom __future__ import annotations\n\nfrom importlib.util import find_spec\nfrom pathlib import Path\nfrom typing import TYPE_CHECKING\n\nimport click\nfrom reflex_cli.v2.deployments import hosting_cli\n\nfrom reflex import constants\nfrom reflex.config import get_config\nfrom reflex.custom_components.custom_components import custom_components_cli\nfrom reflex.environment import environment\nfrom reflex.utils import console\n\nif TYPE_CHECKING:\n    from reflex_cli.constants.base import LogLevel as HostingLogLevel\n\n    from reflex.constants.base import LITERAL_ENV\n\n\ndef set_loglevel(ctx: click.Context, self: click.Parameter, value: str | None):\n    \"\"\"Set the log level.\n\n    Args:\n        ctx: The click context.\n        self: The click command.\n        value: The log level to set.\n    \"\"\"\n    if value is not None:\n        loglevel = constants.LogLevel.from_string(value)\n        console.set_log_level(loglevel)\n\n\n@click.group\n@click.version_option(constants.Reflex.VERSION, message=\"%(version)s\")\ndef cli():\n    \"\"\"Reflex CLI to create, run, and deploy apps.\"\"\"\n\n\nloglevel_option = click.option(\n    \"--loglevel\",\n    \"--log-level\",\n    \"loglevel\",\n    type=click.Choice(\n        [loglevel.value for loglevel in constants.LogLevel],\n        case_sensitive=False,\n    ),\n    is_eager=True,\n    callback=set_loglevel,\n    expose_value=False,\n    help=\"The log level to use.\",\n)\n\n\ndef _init(\n    name: str,\n    template: str | None = None,\n    ai: bool = False,\n):\n    \"\"\"Initialize a new Reflex app in the given directory.\"\"\"\n    from reflex.utils import exec, frontend_skeleton, prerequisites, templates\n\n    # Show system info\n    exec.output_system_info()\n\n    if ai:\n        from reflex.utils.redir import reflex_build_redirect\n\n        reflex_build_redirect()\n        return\n\n    # Validate the app name.\n    app_name = prerequisites.validate_app_name(name)\n    console.rule(f\"[bold]Initializing {app_name}\")\n\n    # Check prerequisites.\n    prerequisites.check_latest_package_version(constants.Reflex.MODULE_NAME)\n    prerequisites.initialize_reflex_user_directory()\n    prerequisites.ensure_reflex_installation_id()\n\n    # Set up the web project.\n    prerequisites.initialize_frontend_dependencies()\n\n    # Initialize the app.\n    template = templates.initialize_app(app_name, template)\n\n    # Initialize the .gitignore.\n    frontend_skeleton.initialize_gitignore()\n\n    # Initialize the requirements.txt.\n    needs_user_manual_update = frontend_skeleton.initialize_requirements_txt()\n\n    template_msg = f\" using the {template} template\" if template else \"\"\n    # Finish initializing the app.\n    console.success(\n        f\"Initialized {app_name}{template_msg}.\"\n        + (\n            f\" Make sure to add {constants.RequirementsTxt.DEFAULTS_STUB + constants.Reflex.VERSION} to your requirements.txt or pyproject.toml file.\"\n            if needs_user_manual_update\n            else \"\"\n        )\n    )\n\n\n@cli.command()\n@loglevel_option\n@click.option(\n    \"--name\",\n    metavar=\"APP_NAME\",\n    help=\"The name of the app to initialize.\",\n)\n@click.option(\n    \"--template\",\n    help=\"The template to initialize the app with.\",\n)\n@click.option(\n    \"--ai\",\n    is_flag=True,\n    help=\"Use AI to create the initial template. Cannot be used with existing app or `--template` option.\",\n)\ndef init(\n    name: str,\n    template: str | None,\n    ai: bool,\n):\n    \"\"\"Initialize a new Reflex app in the current directory.\"\"\"\n    _init(name, template, ai)\n\n\ndef _run(\n    env: constants.Env = constants.Env.DEV,\n    frontend: bool = True,\n    backend: bool = True,\n    frontend_port: int | None = None,\n    backend_port: int | None = None,\n    backend_host: str | None = None,\n    single_port: bool = False,\n):\n    \"\"\"Run the app in the given directory.\"\"\"\n    import atexit\n\n    from reflex.state import reset_disk_state_manager\n    from reflex.utils import build, exec, prerequisites, processes, telemetry\n    from reflex.utils.exec import should_use_granian\n\n    config = get_config()\n\n    backend_host = backend_host or config.backend_host\n\n    # Set env mode in the environment\n    environment.REFLEX_ENV_MODE.set(env)\n\n    # Show system info\n    exec.output_system_info()\n\n    # If no --frontend-only and no --backend-only, then turn on frontend and backend both\n    frontend, backend = prerequisites.check_running_mode(frontend, backend)\n    if not frontend and backend:\n        _skip_compile()\n\n    prerequisites.assert_in_reflex_dir()\n\n    # Check that the app is initialized.\n    if frontend and prerequisites.needs_reinit():\n        _init(name=config.app_name)\n\n    # Delete the states folder if it exists.\n    reset_disk_state_manager()\n\n    # Find the next available open port if applicable.\n    if frontend:\n        auto_increment_frontend = not bool(frontend_port or config.frontend_port)\n        frontend_port = processes.handle_port(\n            \"frontend\",\n            (\n                frontend_port\n                or config.frontend_port\n                or constants.DefaultPorts.FRONTEND_PORT\n            ),\n            auto_increment=auto_increment_frontend,\n        )\n\n    if single_port:\n        backend_port = frontend_port\n    elif backend:\n        auto_increment_backend = not bool(backend_port or config.backend_port)\n\n        backend_port = processes.handle_port(\n            \"backend\",\n            (\n                backend_port\n                or config.backend_port\n                or constants.DefaultPorts.BACKEND_PORT\n            ),\n            auto_increment=auto_increment_backend,\n        )\n\n    # Apply the new ports to the config.\n    if frontend_port != config.frontend_port:\n        config._set_persistent(frontend_port=frontend_port)\n    if backend_port != config.backend_port:\n        config._set_persistent(backend_port=backend_port)\n\n    # Reload the config to make sure the env vars are persistent.\n    get_config(reload=True)\n\n    console.rule(\"[bold]Starting Reflex App\")\n\n    prerequisites.check_latest_package_version(constants.Reflex.MODULE_NAME)\n\n    # Get the app module.\n    app_task = prerequisites.compile_or_validate_app\n    args = (frontend,)\n    kwargs = {\n        \"check_if_schema_up_to_date\": True,\n        \"prerender_routes\": exec.should_prerender_routes(),\n    }\n\n    # Granian fails if the app is already imported.\n    if should_use_granian():\n        import concurrent.futures\n\n        compile_future = concurrent.futures.ProcessPoolExecutor(max_workers=1).submit(\n            app_task,\n            *args,\n            **kwargs,\n        )\n        return_result = compile_future.result()\n    else:\n        return_result = app_task(*args, **kwargs)\n\n    if not return_result:\n        raise SystemExit(1)\n\n    if env != constants.Env.PROD and env != constants.Env.DEV:\n        msg = f\"Invalid env: {env}. Must be DEV or PROD.\"\n        raise ValueError(msg)\n\n    # Get the frontend and backend commands, based on the environment.\n    if env == constants.Env.DEV:\n        setup_frontend, frontend_cmd, backend_cmd = (\n            build.setup_frontend,\n            exec.run_frontend,\n            exec.run_backend,\n        )\n    elif env == constants.Env.PROD:\n        setup_frontend, frontend_cmd, backend_cmd = (\n            build.setup_frontend_prod,\n            exec.run_frontend_prod,\n            exec.run_backend_prod,\n        )\n\n    # Post a telemetry event.\n    telemetry.send(f\"run-{env.value}\")\n\n    # Display custom message when there is a keyboard interrupt.\n    atexit.register(processes.atexit_handler)\n\n    # Run the frontend and backend together.\n    commands = []\n\n    # Run the frontend on a separate thread.\n    if frontend and not single_port:\n        setup_frontend(Path.cwd())\n        commands.append((frontend_cmd, Path.cwd(), frontend_port, backend))\n\n    # In prod mode, run the backend on a separate thread.\n    if backend and env == constants.Env.PROD:\n        commands.append((\n            backend_cmd,\n            backend_host,\n            backend_port,\n            config.loglevel.subprocess_level(),\n            frontend,\n        ))\n\n    if single_port:\n        setup_frontend(Path.cwd())\n        backend_function, *args = commands[0]\n        exec.notify_app_running()\n        exec.notify_frontend(\n            f\"http://0.0.0.0:{get_config().frontend_port}\", backend_present=True\n        )\n        backend_function(*args, mount_frontend_compiled_app=True)\n    else:\n        # Start the frontend and backend.\n        with processes.run_concurrently_context(*commands):\n            # In dev mode, run the backend on the main thread.\n            if backend and backend_port and env == constants.Env.DEV:\n                backend_cmd(\n                    backend_host,\n                    int(backend_port),\n                    config.loglevel.subprocess_level(),\n                    frontend,\n                )\n                # The windows uvicorn bug workaround\n                # https://github.com/reflex-dev/reflex/issues/2335\n                if constants.IS_WINDOWS and exec.frontend_process:\n                    # Sends SIGTERM in windows\n                    exec.kill(exec.frontend_process.pid)\n\n\n@cli.command()\n@loglevel_option\n@click.option(\n    \"--env\",\n    type=click.Choice([e.value for e in constants.Env], case_sensitive=False),\n    default=constants.Env.DEV.value,\n    help=\"The environment to run the app in.\",\n)\n@click.option(\n    \"--frontend-only\",\n    is_flag=True,\n    show_default=False,\n    help=\"Execute only frontend.\",\n    envvar=environment.REFLEX_FRONTEND_ONLY.name,\n)\n@click.option(\n    \"--backend-only\",\n    is_flag=True,\n    show_default=False,\n    help=\"Execute only backend.\",\n    envvar=environment.REFLEX_BACKEND_ONLY.name,\n)\n@click.option(\n    \"--frontend-port\",\n    type=int,\n    help=\"Specify a different frontend port.\",\n    envvar=environment.REFLEX_FRONTEND_PORT.name,\n)\n@click.option(\n    \"--backend-port\",\n    type=int,\n    help=\"Specify a different backend port.\",\n    envvar=environment.REFLEX_BACKEND_PORT.name,\n)\n@click.option(\n    \"--backend-host\",\n    help=\"Specify the backend host.\",\n)\n@click.option(\n    \"--single-port\",\n    is_flag=True,\n    help=\"Run both frontend and backend on the same port.\",\n    default=False,\n)\ndef run(\n    env: LITERAL_ENV,\n    frontend_only: bool,\n    backend_only: bool,\n    frontend_port: int | None,\n    backend_port: int | None,\n    backend_host: str | None,\n    single_port: bool,\n):\n    \"\"\"Run the app in the current directory.\"\"\"\n    if frontend_only and backend_only:\n        console.error(\"Cannot use both --frontend-only and --backend-only options.\")\n        raise SystemExit(1)\n\n    if single_port:\n        if env != constants.Env.PROD.value:\n            console.error(\"--single-port can only be used with --env=PROD.\")\n            raise click.exceptions.Exit(1)\n        if frontend_only or backend_only:\n            console.error(\n                \"Cannot use --single-port with --frontend-only or --backend-only options.\"\n            )\n            raise click.exceptions.Exit(1)\n        if backend_port and frontend_port and backend_port != frontend_port:\n            console.error(\n                \"When using --single-port, --backend-port and --frontend-port must be the same.\"\n            )\n            raise click.exceptions.Exit(1)\n    elif frontend_port and backend_port and frontend_port == backend_port:\n        single_port = True\n\n    config = get_config()\n\n    frontend_port = frontend_port or config.frontend_port\n    backend_port = backend_port or config.backend_port\n    backend_host = backend_host or config.backend_host\n\n    environment.REFLEX_COMPILE_CONTEXT.set(constants.CompileContext.RUN)\n    environment.REFLEX_BACKEND_ONLY.set(backend_only)\n    environment.REFLEX_FRONTEND_ONLY.set(frontend_only)\n\n    _run(\n        constants.Env.DEV if env == constants.Env.DEV else constants.Env.PROD,\n        frontend_only,\n        backend_only,\n        frontend_port,\n        backend_port,\n        backend_host,\n        single_port,\n    )\n\n\n@cli.command()\n@loglevel_option\n@click.option(\n    \"--dry\",\n    is_flag=True,\n    default=False,\n    help=\"Run the command without making any changes.\",\n)\n@click.option(\n    \"--rich/--no-rich\",\n    default=True,\n    is_flag=True,\n    help=\"Whether to use rich progress bars.\",\n)\ndef compile(dry: bool, rich: bool):\n    \"\"\"Compile the app in the current directory.\"\"\"\n    import time\n\n    from reflex.utils import prerequisites\n\n    # Check the app.\n    if prerequisites.needs_reinit():\n        _init(name=get_config().app_name)\n    get_config(reload=True)\n    starting_time = time.monotonic()\n    prerequisites.get_compiled_app(dry_run=dry, use_rich=rich)\n    elapsed_time = time.monotonic() - starting_time\n    console.success(f\"App compiled successfully in {elapsed_time:.3f} seconds.\")\n\n\n@cli.command()\n@loglevel_option\n@click.option(\n    \"--zip/--no-zip\",\n    default=True,\n    is_flag=True,\n    help=\"Whether to zip the backend and frontend exports.\",\n)\n@click.option(\n    \"--frontend-only\",\n    is_flag=True,\n    show_default=False,\n    envvar=environment.REFLEX_FRONTEND_ONLY.name,\n    help=\"Export only frontend.\",\n)\n@click.option(\n    \"--backend-only\",\n    is_flag=True,\n    show_default=False,\n    envvar=environment.REFLEX_BACKEND_ONLY.name,\n    help=\"Export only backend.\",\n)\n@click.option(\n    \"--zip-dest-dir\",\n    default=str(Path.cwd()),\n    help=\"The directory to export the zip files to.\",\n    show_default=False,\n)\n@click.option(\n    \"--upload-db-file\",\n    is_flag=True,\n    help=\"Whether to exclude sqlite db files when exporting backend.\",\n    hidden=True,\n)\n@click.option(\n    \"--env\",\n    type=click.Choice([e.value for e in constants.Env], case_sensitive=False),\n    default=constants.Env.PROD.value,\n    help=\"The environment to export the app in.\",\n)\n@click.option(\n    \"--exclude-from-backend\",\n    \"backend_excluded_dirs\",\n    multiple=True,\n    type=click.Path(exists=True, path_type=Path, resolve_path=True),\n    help=\"Files or directories to exclude from the backend zip. Can be used multiple times.\",\n)\n@click.option(\n    \"--server-side-rendering/--no-server-side-rendering\",\n    \"--ssr/--no-ssr\",\n    \"ssr\",\n    default=True,\n    is_flag=True,\n    help=\"Whether to enable server side rendering for the frontend.\",\n)\ndef export(\n    zip: bool,\n    frontend_only: bool,\n    backend_only: bool,\n    zip_dest_dir: str,\n    upload_db_file: bool,\n    env: LITERAL_ENV,\n    backend_excluded_dirs: tuple[Path, ...] = (),\n    ssr: bool = True,\n):\n    \"\"\"Export the app to a zip file.\"\"\"\n    from reflex.utils import export as export_utils\n    from reflex.utils import prerequisites\n\n    if not environment.REFLEX_SSR.is_set():\n        environment.REFLEX_SSR.set(ssr)\n    elif environment.REFLEX_SSR.get() != ssr:\n        ssr = environment.REFLEX_SSR.get()\n\n    environment.REFLEX_COMPILE_CONTEXT.set(constants.CompileContext.EXPORT)\n\n    should_frontend_run, should_backend_run = prerequisites.check_running_mode(\n        frontend_only, backend_only\n    )\n\n    config = get_config()\n\n    prerequisites.assert_in_reflex_dir()\n\n    if should_frontend_run and prerequisites.needs_reinit():\n        _init(name=config.app_name)\n\n    export_utils.export(\n        zipping=zip,\n        frontend=should_frontend_run,\n        backend=should_backend_run,\n        zip_dest_dir=zip_dest_dir,\n        upload_db_file=upload_db_file,\n        env=constants.Env.DEV if env == constants.Env.DEV else constants.Env.PROD,\n        loglevel=config.loglevel.subprocess_level(),\n        backend_excluded_dirs=backend_excluded_dirs,\n        prerender_routes=ssr,\n    )\n\n\n@cli.command()\n@loglevel_option\ndef login():\n    \"\"\"Authenticate with experimental Reflex hosting service.\"\"\"\n    from reflex_cli.v2 import cli as hosting_cli\n    from reflex_cli.v2.deployments import check_version\n\n    check_version()\n\n    validated_info = hosting_cli.login()\n    if validated_info is not None:\n        _skip_compile()  # Allow running outside of an app dir\n        from reflex.utils import telemetry\n\n        telemetry.send(\"login\", user_uuid=validated_info.get(\"user_id\"))\n\n\n@cli.command()\n@loglevel_option\ndef logout():\n    \"\"\"Log out of access to Reflex hosting service.\"\"\"\n    from reflex_cli.v2.cli import logout\n    from reflex_cli.v2.deployments import check_version\n\n    check_version()\n\n    logout(_convert_reflex_loglevel_to_reflex_cli_loglevel(get_config().loglevel))\n\n\n@click.group\ndef db_cli():\n    \"\"\"Subcommands for managing the database schema.\"\"\"\n\n\n@click.group\ndef script_cli():\n    \"\"\"Subcommands for running helper scripts.\"\"\"\n\n\ndef _skip_compile():\n    \"\"\"Skip the compile step.\"\"\"\n    environment.REFLEX_SKIP_COMPILE.set(True)\n\n\n@db_cli.command(name=\"init\")\ndef db_init():\n    \"\"\"Create database schema and migration configuration.\"\"\"\n    from reflex import model\n    from reflex.utils import prerequisites\n\n    config = get_config()\n\n    # Check the database url.\n    if config.db_url is None:\n        console.error(\"db_url is not configured, cannot initialize.\")\n        return\n\n    # Check the alembic config.\n    if environment.ALEMBIC_CONFIG.get().exists():\n        console.error(\n            \"Database is already initialized. Use \"\n            \"[bold]reflex db makemigrations[/bold] to create schema change \"\n            \"scripts and [bold]reflex db migrate[/bold] to apply migrations \"\n            \"to a new or existing database.\",\n        )\n        return\n\n    # Initialize the database.\n    _skip_compile()\n    prerequisites.get_compiled_app()\n    model.Model.alembic_init()\n    model.Model.migrate(autogenerate=True)\n\n\n@db_cli.command()\ndef migrate():\n    \"\"\"Create or update database schema from migration scripts.\"\"\"\n    from reflex import model\n    from reflex.utils import prerequisites\n\n    prerequisites.get_app()\n    if not prerequisites.check_db_initialized():\n        return\n    model.Model.migrate()\n    prerequisites.check_schema_up_to_date()\n\n\n@db_cli.command()\ndef status():\n    \"\"\"Check the status of the database schema.\"\"\"\n    from reflex.model import Model, format_revision\n    from reflex.utils import prerequisites\n\n    prerequisites.get_app()\n    if not prerequisites.check_db_initialized():\n        console.info(\n            \"Database is not initialized. Run [bold]reflex db init[/bold] to initialize.\"\n        )\n        return\n\n    # Run alembic check command and display output\n    import reflex.config\n\n    config = reflex.config.get_config()\n    console.print(f\"[bold]\\\\[{config.db_url}][/bold]\")\n\n    # Get migration history using Model method\n    current_rev, revisions = Model.get_migration_history()\n    if current_rev is None and not revisions:\n        return\n\n    current_reached_ref = [current_rev is None]\n\n    # Show migration history in chronological order\n    console.print(\"<base>\")\n    for rev in revisions:\n        # Format and print the revision\n        console.print(format_revision(rev, current_rev, current_reached_ref))\n\n\n@db_cli.command()\n@click.option(\n    \"--message\",\n    help=\"Human readable identifier for the generated revision.\",\n)\ndef makemigrations(message: str | None):\n    \"\"\"Create autogenerated alembic migration scripts.\"\"\"\n    from alembic.util.exc import CommandError\n\n    from reflex import model\n    from reflex.utils import prerequisites\n\n    # TODO see if we can use `get_app()` instead (no compile).  Would _skip_compile still be needed then?\n    _skip_compile()\n    prerequisites.get_compiled_app()\n    if not prerequisites.check_db_initialized():\n        return\n    with model.Model.get_db_engine().connect() as connection:\n        try:\n            model.Model.alembic_autogenerate(connection=connection, message=message)\n        except CommandError as command_error:\n            if \"Target database is not up to date.\" not in str(command_error):\n                raise\n            console.error(\n                f\"{command_error} Run [bold]reflex db migrate[/bold] to update database.\"\n            )\n\n\n@cli.command()\n@loglevel_option\n@click.option(\n    \"--app-name\",\n    help=\"The name of the app to deploy.\",\n)\n@click.option(\n    \"--app-id\",\n    help=\"The ID of the app to deploy.\",\n)\n@click.option(\n    \"-r\",\n    \"--region\",\n    multiple=True,\n    help=\"The regions to deploy to. `reflex cloud regions` For multiple envs, repeat this option, e.g. --region sjc --region iad\",\n)\n@click.option(\n    \"--env\",\n    multiple=True,\n    help=\"The environment variables to set: <key>=<value>. For multiple envs, repeat this option, e.g. --env k1=v2 --env k2=v2.\",\n)\n@click.option(\n    \"--vmtype\",\n    help=\"Vm type id. Run `reflex cloud vmtypes` to get options.\",\n)\n@click.option(\n    \"--hostname\",\n    help=\"The hostname of the frontend.\",\n)\n@click.option(\n    \"--interactive/--no-interactive\",\n    is_flag=True,\n    default=True,\n    help=\"Whether to list configuration options and ask for confirmation.\",\n)\n@click.option(\n    \"--envfile\",\n    help=\"The path to an env file to use. Will override any envs set manually.\",\n)\n@click.option(\n    \"--project\",\n    help=\"project id to deploy to\",\n)\n@click.option(\n    \"--project-name\",\n    help=\"The name of the project to deploy to.\",\n)\n@click.option(\n    \"--token\",\n    help=\"token to use for auth\",\n)\n@click.option(\n    \"--config-path\",\n    \"--config\",\n    help=\"path to the config file\",\n)\n@click.option(\n    \"--exclude-from-backend\",\n    \"backend_excluded_dirs\",\n    multiple=True,\n    type=click.Path(exists=True, path_type=Path, resolve_path=True),\n    help=\"Files or directories to exclude from the backend zip. Can be used multiple times.\",\n)\n@click.option(\n    \"--server-side-rendering/--no-server-side-rendering\",\n    \"--ssr/--no-ssr\",\n    \"ssr\",\n    default=True,\n    is_flag=True,\n    help=\"Whether to enable server side rendering for the frontend.\",\n)\ndef deploy(\n    app_name: str | None,\n    app_id: str | None,\n    region: tuple[str, ...],\n    env: tuple[str],\n    vmtype: str | None,\n    hostname: str | None,\n    interactive: bool,\n    envfile: str | None,\n    project: str | None,\n    project_name: str | None,\n    token: str | None,\n    config_path: str | None,\n    backend_excluded_dirs: tuple[Path, ...] = (),\n    ssr: bool = True,\n):\n    \"\"\"Deploy the app to the Reflex hosting service.\"\"\"\n    from reflex_cli.utils import dependency\n    from reflex_cli.v2 import cli as hosting_cli\n    from reflex_cli.v2.deployments import check_version\n\n    from reflex.utils import export as export_utils\n    from reflex.utils import prerequisites\n\n    config = get_config()\n\n    app_name = app_name or config.app_name\n\n    check_version()\n\n    environment.REFLEX_COMPILE_CONTEXT.set(constants.CompileContext.DEPLOY)\n\n    if not environment.REFLEX_SSR.is_set():\n        environment.REFLEX_SSR.set(ssr)\n    elif environment.REFLEX_SSR.get() != ssr:\n        ssr = environment.REFLEX_SSR.get()\n\n    # Only check requirements if interactive.\n    # There is user interaction for requirements update.\n    if interactive:\n        dependency.check_requirements()\n\n    prerequisites.assert_in_reflex_dir()\n\n    # Check if we are set up.\n    if prerequisites.needs_reinit():\n        _init(name=config.app_name)\n    prerequisites.check_latest_package_version(constants.ReflexHostingCLI.MODULE_NAME)\n\n    hosting_cli.deploy(\n        app_name=app_name,\n        app_id=app_id,\n        export_fn=(\n            lambda zip_dest_dir, api_url, deploy_url, frontend, backend, upload_db, zipping: (\n                export_utils.export(\n                    zip_dest_dir=zip_dest_dir,\n                    api_url=api_url,\n                    deploy_url=deploy_url,\n                    frontend=frontend,\n                    backend=backend,\n                    zipping=zipping,\n                    loglevel=config.loglevel.subprocess_level(),\n                    upload_db_file=upload_db,\n                    backend_excluded_dirs=backend_excluded_dirs,\n                    prerender_routes=ssr,\n                )\n            )\n        ),\n        regions=list(region),\n        envs=list(env),\n        vmtype=vmtype,\n        envfile=envfile,\n        hostname=hostname,\n        interactive=interactive,\n        loglevel=_convert_reflex_loglevel_to_reflex_cli_loglevel(config.loglevel),\n        token=token,\n        project=project,\n        project_name=project_name,\n        **({\"config_path\": config_path} if config_path is not None else {}),\n    )\n\n\n@cli.command()\n@loglevel_option\n@click.argument(\"new_name\")\ndef rename(new_name: str):\n    \"\"\"Rename the app in the current directory.\"\"\"\n    from reflex.utils import prerequisites\n    from reflex.utils.rename import rename_app\n\n    prerequisites.validate_app_name(new_name)\n    rename_app(new_name, get_config().loglevel)\n\n\ndef _convert_reflex_loglevel_to_reflex_cli_loglevel(\n    loglevel: constants.LogLevel,\n) -> HostingLogLevel:\n    \"\"\"Convert a Reflex log level to a Reflex CLI log level.\n\n    Args:\n        loglevel: The Reflex log level to convert.\n\n    Returns:\n        The converted Reflex CLI log level.\n    \"\"\"\n    from reflex_cli.constants.base import LogLevel as HostingLogLevel\n\n    if loglevel == constants.LogLevel.DEBUG:\n        return HostingLogLevel.DEBUG\n    if loglevel == constants.LogLevel.INFO:\n        return HostingLogLevel.INFO\n    if loglevel == constants.LogLevel.WARNING:\n        return HostingLogLevel.WARNING\n    if loglevel == constants.LogLevel.ERROR:\n        return HostingLogLevel.ERROR\n    if loglevel == constants.LogLevel.CRITICAL:\n        return HostingLogLevel.CRITICAL\n    return HostingLogLevel.INFO\n\n\nif find_spec(\"typer\") and find_spec(\"typer.main\"):\n    import typer  # pyright: ignore[reportMissingImports]\n\n    if isinstance(hosting_cli, typer.Typer):\n        hosting_cli_command = typer.main.get_command(hosting_cli)\n    else:\n        hosting_cli_command = hosting_cli\nelse:\n    hosting_cli_command = hosting_cli\n\ncli.add_command(hosting_cli_command, name=\"cloud\")\ncli.add_command(db_cli, name=\"db\")\ncli.add_command(script_cli, name=\"script\")\ncli.add_command(custom_components_cli, name=\"component\")\n\nif __name__ == \"__main__\":\n    cli()\n"
  },
  {
    "path": "reflex/route.py",
    "content": "\"\"\"The route decorator and associated variables and functions.\"\"\"\n\nfrom __future__ import annotations\n\nimport re\nfrom collections.abc import Callable\n\nfrom reflex import constants\nfrom reflex.config import get_config\n\n\ndef verify_route_validity(route: str) -> None:\n    \"\"\"Verify if the route is valid, and throw an error if not.\n\n    Args:\n        route: The route that need to be checked\n\n    Raises:\n        ValueError: If the route is invalid.\n    \"\"\"\n    route_parts = route.removeprefix(\"/\").split(\"/\")\n    for i, part in enumerate(route_parts):\n        if constants.RouteRegex.SLUG.fullmatch(part):\n            continue\n        if not part.startswith(\"[\") or not part.endswith(\"]\"):\n            msg = (\n                f\"Route part `{part}` is not valid. Reflex only supports \"\n                \"alphabetic characters, underscores, and hyphens in route parts. \"\n            )\n            raise ValueError(msg)\n        if part.startswith((\"[[...\", \"[...\")):\n            if part != constants.RouteRegex.SPLAT_CATCHALL:\n                msg = f\"Catchall pattern `{part}` is not valid. Only `{constants.RouteRegex.SPLAT_CATCHALL}` is allowed.\"\n                raise ValueError(msg)\n            if i != len(route_parts) - 1:\n                msg = f\"Catchall pattern `{part}` must be at the end of the route.\"\n                raise ValueError(msg)\n            continue\n        if part.startswith(\"[[\"):\n            if constants.RouteRegex.OPTIONAL_ARG.fullmatch(part):\n                continue\n            msg = (\n                f\"Route part `{part}` with optional argument is not valid. \"\n                \"Reflex only supports optional arguments that start with an alphabetic character or underscore, \"\n                \"followed by alphanumeric characters or underscores.\"\n            )\n            raise ValueError(msg)\n        if not constants.RouteRegex.ARG.fullmatch(part):\n            msg = (\n                f\"Route part `{part}` with argument is not valid. \"\n                \"Reflex only supports argument names that start with an alphabetic character or underscore, \"\n                \"followed by alphanumeric characters or underscores.\"\n            )\n            raise ValueError(msg)\n\n\ndef get_route_args(route: str) -> dict[str, str]:\n    \"\"\"Get the dynamic arguments for the given route.\n\n    Args:\n        route: The route to get the arguments for.\n\n    Returns:\n        The route arguments.\n    \"\"\"\n    args = {}\n\n    def _add_route_arg(arg_name: str, type_: str):\n        if arg_name in args:\n            msg = (\n                f\"Arg name `{arg_name}` is used more than once in the route `{route}`.\"\n            )\n            raise ValueError(msg)\n        args[arg_name] = type_\n\n    # Regex to check for route args.\n    argument_regex = constants.RouteRegex.ARG\n    optional_argument_regex = constants.RouteRegex.OPTIONAL_ARG\n\n    # Iterate over the route parts and check for route args.\n    for part in route.split(\"/\"):\n        if part == constants.RouteRegex.SPLAT_CATCHALL:\n            _add_route_arg(\"splat\", constants.RouteArgType.LIST)\n            break\n\n        optional_argument = optional_argument_regex.match(part)\n        if optional_argument:\n            _add_route_arg(optional_argument.group(1), constants.RouteArgType.SINGLE)\n            continue\n\n        argument = argument_regex.match(part)\n        if argument:\n            _add_route_arg(argument.group(1), constants.RouteArgType.SINGLE)\n            continue\n\n    return args\n\n\ndef replace_brackets_with_keywords(input_string: str) -> str:\n    \"\"\"Replace brackets and everything inside it in a string with a keyword.\n\n    Example:\n        >>> replace_brackets_with_keywords(\"/posts\")\n        '/posts'\n        >>> replace_brackets_with_keywords(\"/posts/[slug]\")\n        '/posts/__SINGLE_SEGMENT__'\n        >>> replace_brackets_with_keywords(\"/posts/[slug]/comments\")\n        '/posts/__SINGLE_SEGMENT__/comments'\n        >>> replace_brackets_with_keywords(\"/posts/[[slug]]\")\n        '/posts/__DOUBLE_SEGMENT__'\n        >>> replace_brackets_with_keywords(\"/posts/[[...splat]]\")\n        '/posts/__DOUBLE_CATCHALL_SEGMENT__'\n\n    Args:\n        input_string: String to replace.\n\n    Returns:\n        new string containing keywords.\n    \"\"\"\n    # Replace [<slug>] with __SINGLE_SEGMENT__\n    return constants.RouteRegex.ARG.sub(\n        constants.RouteRegex.SINGLE_SEGMENT,\n        # Replace [[slug]] with __DOUBLE_SEGMENT__\n        constants.RouteRegex.OPTIONAL_ARG.sub(\n            constants.RouteRegex.DOUBLE_SEGMENT,\n            # Replace [[...splat]] with __DOUBLE_CATCHALL_SEGMENT__\n            input_string.replace(\n                constants.RouteRegex.SPLAT_CATCHALL,\n                constants.RouteRegex.DOUBLE_CATCHALL_SEGMENT,\n            ),\n        ),\n    )\n\n\ndef route_specificity(keyworded_route: str) -> tuple[int, int, int]:\n    \"\"\"Get the specificity of a route with keywords.\n\n    The smaller the number, the more specific the route is.\n\n    Args:\n        keyworded_route: The route with keywords.\n\n    Returns:\n        A tuple containing the counts of double catchall segments,\n        double segments, and single segments in the route.\n    \"\"\"\n    return (\n        keyworded_route.count(constants.RouteRegex.DOUBLE_CATCHALL_SEGMENT),\n        keyworded_route.count(constants.RouteRegex.DOUBLE_SEGMENT),\n        keyworded_route.count(constants.RouteRegex.SINGLE_SEGMENT),\n    )\n\n\ndef get_route_regex(keyworded_route: str) -> re.Pattern:\n    \"\"\"Get the regex pattern for a route with keywords.\n\n    Args:\n        keyworded_route: The route with keywords.\n\n    Returns:\n        A compiled regex pattern for the route.\n    \"\"\"\n    if keyworded_route == \"index\":\n        return re.compile(re.escape(\"/\"))\n    path_parts = keyworded_route.split(\"/\")\n    regex_parts = []\n    for part in path_parts:\n        if part == constants.RouteRegex.SINGLE_SEGMENT:\n            # Match a single segment (/slug)\n            regex_parts.append(r\"/[^/]*\")\n        elif part == constants.RouteRegex.DOUBLE_SEGMENT:\n            # Match a single optional segment (/slug or nothing)\n            regex_parts.append(r\"(/[^/]+)?\")\n        elif part == constants.RouteRegex.DOUBLE_CATCHALL_SEGMENT:\n            regex_parts.append(\".*\")\n        else:\n            regex_parts.append(re.escape(\"/\" + part))\n    # Join the regex parts and compile the regex\n    regex_pattern = \"\".join(regex_parts)\n    regex_pattern = f\"^{regex_pattern}/?$\"\n    return re.compile(regex_pattern)\n\n\ndef get_router(routes: list[str]) -> Callable[[str], str | None]:\n    \"\"\"Get a function that computes the route for a given path.\n\n    Args:\n        routes: A list of routes to match against.\n\n    Returns:\n        A function that takes a path and returns the first matching route,\n        or None if no match is found.\n    \"\"\"\n    keyworded_routes = {\n        replace_brackets_with_keywords(route): route for route in routes\n    }\n    sorted_routes_by_specificity = sorted(\n        keyworded_routes.items(),\n        key=lambda item: route_specificity(item[0]),\n    )\n    regexed_routes = [\n        (get_route_regex(keyworded_route), original_route)\n        for keyworded_route, original_route in sorted_routes_by_specificity\n    ]\n\n    def get_route(path: str) -> str | None:\n        \"\"\"Get the first matching route for a given path.\n\n        Args:\n            path: The path to match against the routes.\n\n        Returns:\n            The first matching route, or None if no match is found.\n        \"\"\"\n        config = get_config()\n        if config.frontend_path:\n            path = path.removeprefix(config.frontend_path)\n        path = \"/\" + path.removeprefix(\"/\").removesuffix(\"/\")\n        if path == \"/index\":\n            path = \"/\"\n        for regex, original_route in regexed_routes:\n            if regex.fullmatch(path):\n                return original_route\n        return None\n\n    return get_route\n"
  },
  {
    "path": "reflex/state.py",
    "content": "\"\"\"Define the reflex state specification.\"\"\"\n\nfrom __future__ import annotations\n\nimport asyncio\nimport builtins\nimport contextlib\nimport copy\nimport dataclasses\nimport datetime\nimport functools\nimport inspect\nimport pickle\nimport re\nimport sys\nimport time\nimport uuid\nimport warnings\nfrom collections.abc import AsyncIterator, Callable, Iterator, Sequence\nfrom enum import Enum\nfrom hashlib import md5\nfrom importlib.util import find_spec\nfrom types import FunctionType\nfrom typing import (\n    TYPE_CHECKING,\n    Any,\n    BinaryIO,\n    ClassVar,\n    ParamSpec,\n    TypeVar,\n    cast,\n    get_type_hints,\n)\n\nfrom rich.markup import escape\nfrom typing_extensions import Self\n\nimport reflex.istate.dynamic\nfrom reflex import constants, event\nfrom reflex.constants.state import FIELD_MARKER\nfrom reflex.environment import PerformanceMode, environment\nfrom reflex.event import (\n    BACKGROUND_TASK_MARKER,\n    EVENT_ACTIONS_MARKER,\n    Event,\n    EventHandler,\n    EventSpec,\n    call_script,\n    fix_events,\n)\nfrom reflex.istate import HANDLED_PICKLE_ERRORS, debug_failed_pickles\nfrom reflex.istate.data import RouterData\nfrom reflex.istate.proxy import ImmutableMutableProxy as ImmutableMutableProxy\nfrom reflex.istate.proxy import MutableProxy, StateProxy, is_mutable_type\nfrom reflex.istate.storage import ClientStorageBase\nfrom reflex.model import Model\nfrom reflex.utils import console, format, prerequisites, types\nfrom reflex.utils.exceptions import (\n    ComputedVarShadowsBaseVarsError,\n    ComputedVarShadowsStateVarError,\n    DynamicComponentInvalidSignatureError,\n    DynamicRouteArgShadowsStateVarError,\n    EventHandlerShadowsBuiltInStateMethodError,\n    ReflexRuntimeError,\n    SetUndefinedStateVarError,\n    StateMismatchError,\n    StateSchemaMismatchError,\n    StateSerializationError,\n    StateTooLargeError,\n    UnretrievableVarValueError,\n)\nfrom reflex.utils.exceptions import ImmutableStateError as ImmutableStateError\nfrom reflex.utils.exec import is_testing_env\nfrom reflex.utils.monitoring import is_pyleak_enabled, monitor_loopblocks\nfrom reflex.utils.types import _isinstance, is_union, value_inside_optional\nfrom reflex.vars import Field, VarData, field\nfrom reflex.vars.base import (\n    ComputedVar,\n    DynamicRouteVar,\n    EvenMoreBasicBaseState,\n    Var,\n    computed_var,\n    dispatch,\n    is_computed_var,\n)\n\nif TYPE_CHECKING:\n    from reflex.components.component import Component\n\n\nDelta = dict[str, Any]\nvar = computed_var\n\n\nif environment.REFLEX_PERF_MODE.get() != PerformanceMode.OFF:\n    # If the state is this large, it's considered a performance issue.\n    TOO_LARGE_SERIALIZED_STATE = environment.REFLEX_STATE_SIZE_LIMIT.get() * 1024\n    # Only warn about each state class size once.\n    _WARNED_ABOUT_STATE_SIZE: set[str] = set()\n\n\n# For BaseState.get_var_value\nVAR_TYPE = TypeVar(\"VAR_TYPE\")\n\n\ndef _no_chain_background_task(state: BaseState, name: str, fn: Callable) -> Callable:\n    \"\"\"Protect against directly chaining a background task from another event handler.\n\n    Args:\n        state: The state instance the background task is bound to.\n        name: The name of the background task.\n        fn: The background task coroutine function / generator.\n\n    Returns:\n        A compatible coroutine function / generator that raises a runtime error.\n\n    Raises:\n        TypeError: If the background task is not async.\n    \"\"\"\n    call = f\"{type(state).__name__}.{name}\"\n    message = (\n        f\"Cannot directly call background task {name!r}, use \"\n        f\"`yield {call}` or `return {call}` instead.\"\n    )\n    if inspect.iscoroutinefunction(fn):\n\n        async def _no_chain_background_task_co(*args, **kwargs):  # noqa: RUF029\n            raise RuntimeError(message)\n\n        return _no_chain_background_task_co\n    if inspect.isasyncgenfunction(fn):\n\n        async def _no_chain_background_task_gen(*args, **kwargs):  # noqa: RUF029\n            yield\n            raise RuntimeError(message)\n\n        return _no_chain_background_task_gen\n\n    msg = f\"{fn} is marked as a background task, but is not async.\"\n    raise TypeError(msg)\n\n\ndef _substate_key(\n    token: str,\n    state_cls_or_name: BaseState | type[BaseState] | str | Sequence[str],\n) -> str:\n    \"\"\"Get the substate key.\n\n    Args:\n        token: The token of the state.\n        state_cls_or_name: The state class/instance or name or sequence of name parts.\n\n    Returns:\n        The substate key.\n    \"\"\"\n    if isinstance(state_cls_or_name, BaseState) or (\n        isinstance(state_cls_or_name, type) and issubclass(state_cls_or_name, BaseState)\n    ):\n        state_cls_or_name = state_cls_or_name.get_full_name()\n    elif isinstance(state_cls_or_name, (list, tuple)):\n        state_cls_or_name = \".\".join(state_cls_or_name)\n    return f\"{token}_{state_cls_or_name}\"\n\n\ndef _split_substate_key(substate_key: str) -> tuple[str, str]:\n    \"\"\"Split the substate key into token and state name.\n\n    Args:\n        substate_key: The substate key.\n\n    Returns:\n        Tuple of token and state name.\n    \"\"\"\n    token, _, state_name = substate_key.partition(\"_\")\n    return token, state_name\n\n\n@dataclasses.dataclass(frozen=True, init=False)\nclass EventHandlerSetVar(EventHandler):\n    \"\"\"A special event handler to wrap setvar functionality.\"\"\"\n\n    state_cls: type[BaseState] = dataclasses.field(init=False)\n\n    def __init__(self, state_cls: type[BaseState]):\n        \"\"\"Initialize the EventHandlerSetVar.\n\n        Args:\n            state_cls: The state class that vars will be set on.\n        \"\"\"\n        super().__init__(\n            fn=type(self).setvar,\n            state_full_name=state_cls.get_full_name(),\n        )\n        object.__setattr__(self, \"state_cls\", state_cls)\n\n    def __hash__(self):\n        \"\"\"Get the hash of the event handler.\n\n        Returns:\n            The hash of the event handler.\n        \"\"\"\n        return hash((\n            tuple(self.event_actions.items()),\n            self.fn,\n            self.state_full_name,\n            self.state_cls,\n        ))\n\n    def setvar(self, var_name: str, value: Any):\n        \"\"\"Set the state variable to the value of the event.\n\n        Note: `self` here will be an instance of the state, not EventHandlerSetVar.\n\n        Args:\n            var_name: The name of the variable to set.\n            value: The value to set the variable to.\n        \"\"\"\n        getattr(self, constants.SETTER_PREFIX + var_name)(value)\n\n    def __call__(self, *args: Any) -> EventSpec:\n        \"\"\"Performs pre-checks and munging on the provided args that will become an EventSpec.\n\n        Args:\n            *args: The event args.\n\n        Returns:\n            The (partial) EventSpec that will be used to create the event to setvar.\n\n        Raises:\n            AttributeError: If the given Var name does not exist on the state.\n            EventHandlerValueError: If the given Var name is not a str\n            NotImplementedError: If the setter for the given Var is async\n        \"\"\"\n        from reflex.config import get_config\n        from reflex.utils.exceptions import EventHandlerValueError\n\n        config = get_config()\n        if config.state_auto_setters is None:\n            console.deprecate(\n                feature_name=\"state_auto_setters defaulting to True\",\n                reason=\"The default value will be changed to False in a future release. Set state_auto_setters explicitly or define setters explicitly. \"\n                f\"Used {self.state_cls.__name__}.setvar without defining it.\",\n                deprecation_version=\"0.8.9\",\n                removal_version=\"0.9.0\",\n                dedupe=True,\n            )\n\n        if args:\n            if not isinstance(args[0], str):\n                msg = f\"Var name must be passed as a string, got {args[0]!r}\"\n                raise EventHandlerValueError(msg)\n\n            handler = getattr(self.state_cls, constants.SETTER_PREFIX + args[0], None)\n\n            # Check that the requested Var setter exists on the State at compile time.\n            if handler is None:\n                msg = f\"Variable `{args[0]}` cannot be set on `{self.state_cls.get_full_name()}`\"\n                raise AttributeError(msg)\n\n            if inspect.iscoroutinefunction(handler.fn):\n                msg = f\"Setter for {args[0]} is async, which is not supported.\"\n                raise NotImplementedError(msg)\n\n        return super().__call__(*args)\n\n\ndef get_var_for_field(cls: type[BaseState], name: str, f: Field) -> Var:\n    \"\"\"Get a Var instance for a state field.\n\n    Args:\n        cls: The state class.\n        name: The name of the field.\n        f: The Field instance.\n\n    Returns:\n        The Var instance.\n    \"\"\"\n    field_name = (\n        format.format_state_name(cls.get_full_name()) + \".\" + name + FIELD_MARKER\n    )\n\n    return dispatch(\n        field_name=field_name,\n        var_data=VarData.from_state(cls, name),\n        result_var_type=f.outer_type_,\n    )\n\n\nasync def _resolve_delta(delta: Delta) -> Delta:\n    \"\"\"Await all coroutines in the delta.\n\n    Args:\n        delta: The delta to process.\n\n    Returns:\n        The same delta dict with all coroutines resolved to their return value.\n    \"\"\"\n    tasks = {}\n    for state_name, state_delta in delta.items():\n        for var_name, value in state_delta.items():\n            if inspect.iscoroutine(value):\n                tasks[state_name, var_name] = asyncio.create_task(\n                    value,\n                    name=f\"reflex_resolve_delta|{state_name}|{var_name}|{time.time()}\",\n                )\n    for (state_name, var_name), task in tasks.items():\n        delta[state_name][var_name] = await task\n    return delta\n\n\nRETURN = TypeVar(\"RETURN\")\nPARAMS = ParamSpec(\"PARAMS\")\n\n\ndef _override_base_method(fn: Callable[PARAMS, RETURN]) -> Callable[PARAMS, RETURN]:\n    \"\"\"Mark a method as overriding a base method.\n\n    Args:\n        fn: The function to mark.\n\n    Returns:\n        The marked function.\n    \"\"\"\n    fn.__override_base_method__ = True  # pyright: ignore[reportFunctionMemberAccess]\n    return fn\n\n\n_deserializers = {\n    int: int,\n    float: float,\n    datetime.datetime: datetime.datetime.fromisoformat,\n    datetime.date: datetime.date.fromisoformat,\n    datetime.time: datetime.time.fromisoformat,\n    uuid.UUID: uuid.UUID,\n}\n\nall_base_state_classes: dict[str, None] = {}\n\nCLASS_VAR_NAMES = frozenset({\n    \"vars\",\n    \"base_vars\",\n    \"computed_vars\",\n    \"inherited_vars\",\n    \"backend_vars\",\n    \"inherited_backend_vars\",\n    \"event_handlers\",\n    \"class_subclasses\",\n    \"_var_dependencies\",\n    \"_always_dirty_computed_vars\",\n    \"_always_dirty_substates\",\n    \"_potentially_dirty_states\",\n})\n\n\nclass BaseState(EvenMoreBasicBaseState):\n    \"\"\"The state of the app.\"\"\"\n\n    # A map from the var name to the var.\n    vars: ClassVar[builtins.dict[str, Var]] = {}\n\n    # The base vars of the class.\n    base_vars: ClassVar[builtins.dict[str, Var]] = {}\n\n    # The computed vars of the class.\n    computed_vars: ClassVar[builtins.dict[str, ComputedVar]] = {}\n\n    # Vars inherited by the parent state.\n    inherited_vars: ClassVar[builtins.dict[str, Var]] = {}\n\n    # Backend base vars that are never sent to the client.\n    backend_vars: ClassVar[builtins.dict[str, Any]] = {}\n\n    # Backend base vars inherited\n    inherited_backend_vars: ClassVar[builtins.dict[str, Any]] = {}\n\n    # The event handlers.\n    event_handlers: ClassVar[builtins.dict[str, EventHandler]] = {}\n\n    # A set of subclassses of this class.\n    class_subclasses: ClassVar[set[type[BaseState]]] = set()\n\n    # Mapping of var name to set of (state_full_name, var_name) that depend on it.\n    _var_dependencies: ClassVar[builtins.dict[str, set[tuple[str, str]]]] = {}\n\n    # Set of vars which always need to be recomputed\n    _always_dirty_computed_vars: ClassVar[set[str]] = set()\n\n    # Set of substates which always need to be recomputed\n    _always_dirty_substates: ClassVar[set[str]] = set()\n\n    # Set of states which might need to be recomputed if vars in this state change.\n    _potentially_dirty_states: ClassVar[set[str]] = set()\n\n    # The parent state.\n    parent_state: BaseState | None = field(default=None, is_var=False)\n\n    # The substates of the state.\n    substates: builtins.dict[str, BaseState] = field(\n        default_factory=builtins.dict, is_var=False\n    )\n\n    # The set of dirty vars.\n    dirty_vars: set[str] = field(default_factory=set, is_var=False)\n\n    # The set of dirty substates.\n    dirty_substates: set[str] = field(default_factory=set, is_var=False)\n\n    # The routing path that triggered the state\n    router_data: builtins.dict[str, Any] = field(\n        default_factory=builtins.dict, is_var=False\n    )\n\n    # Per-instance copy of backend base variable values\n    _backend_vars: builtins.dict[str, Any] = field(\n        default_factory=builtins.dict, is_var=False\n    )\n\n    # The router data for the current page\n    router: Field[RouterData] = field(default_factory=RouterData)\n\n    # Whether the state has ever been touched since instantiation.\n    _was_touched: bool = field(default=False, is_var=False)\n\n    # A special event handler for setting base vars.\n    setvar: ClassVar[EventHandler]\n\n    def __init__(\n        self,\n        parent_state: BaseState | None = None,\n        init_substates: bool = True,\n        _reflex_internal_init: bool = False,\n        **kwargs,\n    ):\n        \"\"\"Initialize the state.\n\n        DO NOT INSTANTIATE STATE CLASSES DIRECTLY! Use StateManager.get_state() instead.\n\n        Args:\n            parent_state: The parent state.\n            init_substates: Whether to initialize the substates in this instance.\n            _reflex_internal_init: A flag to indicate that the state is being initialized by the framework.\n            **kwargs: The kwargs to set as attributes on the state.\n\n        Raises:\n            ReflexRuntimeError: If the state is instantiated directly by end user.\n        \"\"\"\n        from reflex.utils.exceptions import ReflexRuntimeError\n\n        if not _reflex_internal_init and not is_testing_env():\n            msg = (\n                \"State classes should not be instantiated directly in a Reflex app. \"\n                \"See https://reflex.dev/docs/state/ for further information.\"\n            )\n            raise ReflexRuntimeError(msg)\n        if self._mixin:\n            msg = f\"{type(self).__name__} is a state mixin and cannot be instantiated directly.\"\n            raise ReflexRuntimeError(msg)\n        kwargs[\"parent_state\"] = parent_state\n        super().__init__(**kwargs)\n\n        # Setup the substates (for memory state manager only).\n        if init_substates:\n            for substate in self.get_substates():\n                self.substates[substate.get_name()] = substate(\n                    parent_state=self,\n                    _reflex_internal_init=True,\n                )\n\n        # Create a fresh copy of the backend variables for this instance\n        self._backend_vars = copy.deepcopy(self.backend_vars)\n\n    def __repr__(self) -> str:\n        \"\"\"Get the string representation of the state.\n\n        Returns:\n            The string representation of the state.\n        \"\"\"\n        return f\"{type(self).__name__}({self.dict()})\"\n\n    @classmethod\n    def _get_computed_vars(cls) -> list[tuple[str, ComputedVar]]:\n        \"\"\"Helper function to get all computed vars of a instance.\n\n        Returns:\n            A list of computed vars.\n        \"\"\"\n        return [\n            (name, v)\n            for mixin in (*cls._mixins(), cls)\n            for name, v in mixin.__dict__.items()\n            if is_computed_var(v) and name not in cls.inherited_vars\n        ]\n\n    @classmethod\n    def _validate_module_name(cls) -> None:\n        \"\"\"Check if the module name is valid.\n\n        Reflex uses ___ as state name module separator.\n\n        Raises:\n            NameError: If the module name is invalid.\n        \"\"\"\n        if \"___\" in cls.__module__:\n            msg = (\n                \"The module name of a State class cannot contain '___'. \"\n                \"Please rename the module.\"\n            )\n            raise NameError(msg)\n\n    @classmethod\n    def __init_subclass__(cls, mixin: bool = False, **kwargs):\n        \"\"\"Do some magic for the subclass initialization.\n\n        Args:\n            mixin: Whether the subclass is a mixin and should not be initialized.\n            **kwargs: The kwargs to pass to the init_subclass method.\n\n        Raises:\n            StateValueError: If a substate class shadows another.\n        \"\"\"\n        from reflex.utils.exceptions import StateValueError\n\n        super().__init_subclass__(**kwargs)\n\n        if cls._mixin:\n            return\n\n        # Handle locally-defined states for pickling.\n        if \"<locals>\" in cls.__qualname__:\n            cls._handle_local_def()\n\n        # Validate the module name.\n        cls._validate_module_name()\n\n        # Event handlers should not shadow builtin state methods.\n        cls._check_overridden_methods()\n\n        # Computed vars should not shadow builtin state props.\n        cls._check_overridden_basevars()\n\n        # Reset subclass tracking for this class.\n        cls.class_subclasses = set()\n\n        # Reset dirty substate tracking for this class.\n        cls._always_dirty_substates = set()\n        cls._potentially_dirty_states = set()\n\n        # Get the parent vars.\n        parent_state = cls.get_parent_state()\n        if parent_state is not None:\n            cls.inherited_vars = parent_state.vars\n            cls.inherited_backend_vars = parent_state.backend_vars\n\n            # Check if another substate class with the same name has already been defined.\n            if cls.get_name() in {c.get_name() for c in parent_state.class_subclasses}:\n                # This should not happen, since we have added module prefix to state names in #3214\n                msg = (\n                    f\"The substate class '{cls.get_name()}' has been defined multiple times. \"\n                    \"Shadowing substate classes is not allowed.\"\n                )\n                raise StateValueError(msg)\n            # Track this new subclass in the parent state's subclasses set.\n            parent_state.class_subclasses.add(cls)\n\n        # Get computed vars.\n        computed_vars = cls._get_computed_vars()\n        cls._check_overridden_computed_vars()\n\n        new_backend_vars = {\n            name: value if not isinstance(value, Field) else value.default_value()\n            for mixin_cls in (*cls._mixins(), cls)\n            for name, value in list(mixin_cls.__dict__.items())\n            if types.is_backend_base_variable(name, mixin_cls)\n        }\n        # Add annotated backend vars that may not have a default value.\n        new_backend_vars.update({\n            name: cls._get_var_default(name, annotation_value)\n            for mixin_cls in (*cls._mixins(), cls)\n            for name, annotation_value in mixin_cls._get_type_hints().items()\n            if name not in new_backend_vars\n            and types.is_backend_base_variable(name, mixin_cls)\n        })\n\n        cls.backend_vars = {\n            **cls.inherited_backend_vars,\n            **new_backend_vars,\n        }\n\n        # Set the base and computed vars.\n        cls.base_vars = {\n            name: get_var_for_field(cls, name, f)\n            for name, f in cls.get_fields().items()\n            if name not in cls.get_skip_vars() and f.is_var and not name.startswith(\"_\")\n        }\n        cls.computed_vars = {\n            name: v._replace(merge_var_data=VarData.from_state(cls))\n            for name, v in computed_vars\n        }\n        cls.vars = {\n            **cls.inherited_vars,\n            **cls.base_vars,\n            **cls.computed_vars,\n        }\n        cls.event_handlers = {}\n\n        # Setup the base vars at the class level.\n        for name, prop in cls.base_vars.items():\n            cls._init_var(name, prop)\n\n        # Set up the event handlers.\n        events = {\n            name: fn\n            for name, fn in cls.__dict__.items()\n            if cls._item_is_event_handler(name, fn)\n        }\n\n        for mixin_cls in cls._mixins():\n            for name, value in mixin_cls.__dict__.items():\n                if name in cls.inherited_vars:\n                    continue\n                if is_computed_var(value):\n                    fget = cls._copy_fn(value.fget)\n                    newcv = value._replace(fget=fget, _var_data=VarData.from_state(cls))\n                    # cleanup refs to mixin cls in var_data\n                    setattr(cls, name, newcv)\n                    cls.computed_vars[name] = newcv\n                    cls.vars[name] = newcv\n                    continue\n                if events.get(name) is not None:\n                    continue\n                if not cls._item_is_event_handler(name, value):\n                    continue\n                if parent_state is not None and parent_state.event_handlers.get(name):\n                    continue\n                value = cls._copy_fn(value)\n                value.__qualname__ = f\"{cls.__name__}.{name}\"\n                events[name] = value\n\n        # Create the setvar event handler for this state\n        cls._create_setvar()\n\n        for name, fn in events.items():\n            handler = cls._create_event_handler(fn)\n            cls.event_handlers[name] = handler\n            setattr(cls, name, handler)\n\n        # Initialize per-class var dependency tracking.\n        cls._var_dependencies = {}\n        cls._init_var_dependency_dicts()\n\n        all_base_state_classes[cls.get_full_name()] = None\n\n    @classmethod\n    def _add_event_handler(\n        cls,\n        name: str,\n        fn: Callable,\n    ):\n        \"\"\"Add an event handler dynamically to the state.\n\n        Args:\n            name: The name of the event handler.\n            fn: The function to call when the event is triggered.\n        \"\"\"\n        handler = cls._create_event_handler(fn)\n        cls.event_handlers[name] = handler\n        setattr(cls, name, handler)\n\n    @staticmethod\n    def _copy_fn(fn: Callable) -> Callable:\n        \"\"\"Copy a function. Used to copy ComputedVars and EventHandlers from mixins.\n\n        Args:\n            fn: The function to copy.\n\n        Returns:\n            The copied function.\n        \"\"\"\n        newfn = FunctionType(\n            fn.__code__,\n            fn.__globals__,\n            name=fn.__name__,\n            argdefs=fn.__defaults__,\n            closure=fn.__closure__,\n        )\n        newfn.__annotations__ = fn.__annotations__\n        if mark := getattr(fn, BACKGROUND_TASK_MARKER, None):\n            setattr(newfn, BACKGROUND_TASK_MARKER, mark)\n        # Preserve event_actions from @rx.event decorator\n        if event_actions := getattr(fn, EVENT_ACTIONS_MARKER, None):\n            object.__setattr__(newfn, EVENT_ACTIONS_MARKER, event_actions)\n        return newfn\n\n    @staticmethod\n    def _item_is_event_handler(name: str, value: Any) -> bool:\n        \"\"\"Check if the item is an event handler.\n\n        Args:\n            name: The name of the item.\n            value: The value of the item.\n\n        Returns:\n            Whether the item is an event handler.\n        \"\"\"\n        return (\n            not name.startswith(\"_\")\n            and isinstance(value, Callable)\n            and not isinstance(value, EventHandler)\n            and hasattr(value, \"__code__\")\n        )\n\n    @classmethod\n    def _evaluate(cls, f: Callable[[Self], Any], of_type: type | None = None) -> Var:\n        \"\"\"Evaluate a function to a ComputedVar. Experimental.\n\n        Args:\n            f: The function to evaluate.\n            of_type: The type of the ComputedVar. Defaults to Component.\n\n        Returns:\n            The ComputedVar.\n        \"\"\"\n        console.warn(\n            \"The _evaluate method is experimental and may be removed in future versions.\"\n        )\n        from reflex.components.component import Component\n\n        of_type = of_type or Component\n\n        unique_var_name = (\n            (\"dynamic_\" + f.__module__ + \"_\" + f.__qualname__)\n            .replace(\"<\", \"\")\n            .replace(\">\", \"\")\n            .replace(\".\", \"_\")\n        )\n\n        while unique_var_name in cls.vars:\n            unique_var_name += \"_\"\n\n        def computed_var_func(state: Self):\n            result = f(state)\n\n            if not _isinstance(result, of_type, nested=1, treat_var_as_type=False):\n                console.warn(\n                    f\"Inline ComputedVar {f} expected type {escape(str(of_type))}, got {type(result)}. \"\n                    \"You can specify expected type with `of_type` argument.\"\n                )\n\n            return result\n\n        computed_var_func.__name__ = unique_var_name\n\n        computed_var_func_arg = computed_var(return_type=of_type, cache=False)(\n            computed_var_func\n        )\n\n        setattr(cls, unique_var_name, computed_var_func_arg)\n        cls.computed_vars[unique_var_name] = computed_var_func_arg\n        cls.vars[unique_var_name] = computed_var_func_arg\n        cls._update_substate_inherited_vars({unique_var_name: computed_var_func_arg})\n        cls._always_dirty_computed_vars.add(unique_var_name)\n\n        return getattr(cls, unique_var_name)\n\n    @classmethod\n    def _mixins(cls) -> tuple[type[BaseState], ...]:\n        \"\"\"Get the mixin classes of the state.\n\n        Returns:\n            The mixin classes of the state.\n        \"\"\"\n        return tuple(\n            mixin\n            for mixin in cls.__mro__\n            if (\n                mixin is not cls\n                and issubclass(mixin, BaseState)\n                and mixin._mixin is True\n            )\n        )\n\n    @classmethod\n    def _handle_local_def(cls):\n        \"\"\"Handle locally-defined states for pickling.\"\"\"\n        known_names = dir(reflex.istate.dynamic)\n        proposed_name = cls.__name__\n        for ix in range(len(known_names)):\n            if proposed_name not in known_names:\n                break\n            proposed_name = f\"{cls.__name__}_{ix}\"\n        setattr(reflex.istate.dynamic, proposed_name, cls)\n        cls.__original_name__ = cls.__name__\n        cls.__original_module__ = cls.__module__\n        cls.__name__ = cls.__qualname__ = proposed_name\n        cls.__module__ = reflex.istate.dynamic.__name__\n\n    @classmethod\n    @functools.cache\n    def _get_type_hints(cls) -> dict[str, Any]:\n        \"\"\"Get the type hints for this class.\n\n        If the class is dynamic, evaluate the type hints with the original\n        module in the local namespace.\n\n        Returns:\n            The type hints dict.\n        \"\"\"\n        original_module = getattr(cls, \"__original_module__\", None)\n        if original_module is not None:\n            localns = sys.modules[original_module].__dict__\n        else:\n            localns = None\n\n        return get_type_hints(cls, localns=localns)\n\n    @classmethod\n    def _init_var_dependency_dicts(cls):\n        \"\"\"Initialize the var dependency tracking dicts.\n\n        Allows the state to know which vars each ComputedVar depends on and\n        whether a ComputedVar depends on a var in its parent state.\n\n        Additional updates tracking dicts for vars and substates that always\n        need to be recomputed.\n        \"\"\"\n        for cvar_name, cvar in cls.computed_vars.items():\n            if not cvar._cache:\n                # Do not perform dep calculation when cache=False (these are always dirty).\n                continue\n            for state_name, dvar_set in cvar._deps(objclass=cls).items():\n                state_cls = cls.get_root_state().get_class_substate(state_name)\n                for dvar in dvar_set:\n                    defining_state_cls = state_cls\n                    while dvar in {\n                        *defining_state_cls.inherited_vars,\n                        *defining_state_cls.inherited_backend_vars,\n                    }:\n                        parent_state = defining_state_cls.get_parent_state()\n                        if parent_state is not None:\n                            defining_state_cls = parent_state\n                    defining_state_cls._var_dependencies.setdefault(dvar, set()).add((\n                        cls.get_full_name(),\n                        cvar_name,\n                    ))\n                    defining_state_cls._potentially_dirty_states.add(\n                        cls.get_full_name()\n                    )\n\n        # ComputedVar with cache=False always need to be recomputed\n        cls._always_dirty_computed_vars = {\n            cvar_name\n            for cvar_name, cvar in cls.computed_vars.items()\n            if not cvar._cache\n        }\n\n        # Any substate containing a ComputedVar with cache=False always needs to be recomputed\n        if cls._always_dirty_computed_vars:\n            # Tell parent classes that this substate has always dirty computed vars\n            state_name = cls.get_name()\n            parent_state = cls.get_parent_state()\n            while parent_state is not None:\n                parent_state._always_dirty_substates.add(state_name)\n                state_name, parent_state = (\n                    parent_state.get_name(),\n                    parent_state.get_parent_state(),\n                )\n\n        # Reset cached schema value\n        cls._to_schema.cache_clear()\n\n    @classmethod\n    def _check_overridden_methods(cls):\n        \"\"\"Check for shadow methods and raise error if any.\n\n        Raises:\n            EventHandlerShadowsBuiltInStateMethodError: When an event handler shadows an inbuilt state method.\n        \"\"\"\n        overridden_methods = set()\n        state_base_functions = cls._get_base_functions()\n        for name, method in inspect.getmembers(cls, inspect.isfunction):\n            # Check if the method is overridden and not a dunder method\n            if (\n                not name.startswith(\"__\")\n                and method.__name__ in state_base_functions\n                and state_base_functions[method.__name__] != method\n                and not getattr(method, \"__override_base_method__\", False)\n            ):\n                overridden_methods.add(method.__name__)\n\n        for method_name in overridden_methods:\n            msg = f\"The event handler name `{method_name}` shadows a builtin State method; use a different name instead\"\n            raise EventHandlerShadowsBuiltInStateMethodError(msg)\n\n    @classmethod\n    def _check_overridden_basevars(cls):\n        \"\"\"Check for shadow base vars and raise error if any.\n\n        Raises:\n            ComputedVarShadowsBaseVarsError: When a computed var shadows a base var.\n        \"\"\"\n        hints = cls._get_type_hints()\n        for name, computed_var_ in cls._get_computed_vars():\n            if name in hints:\n                msg = f\"The computed var name `{computed_var_._js_expr}` shadows a base var in {cls.__module__}.{cls.__name__}; use a different name instead\"\n                raise ComputedVarShadowsBaseVarsError(msg)\n\n    @classmethod\n    def _check_overridden_computed_vars(cls) -> None:\n        \"\"\"Check for shadow computed vars and raise error if any.\n\n        Raises:\n            ComputedVarShadowsStateVarError: When a computed var shadows another.\n        \"\"\"\n        for name, cv in cls.__dict__.items():\n            if not is_computed_var(cv):\n                continue\n            name = cv._js_expr\n            if name in cls.inherited_vars or name in cls.inherited_backend_vars:\n                msg = f\"The computed var name `{cv._js_expr}` shadows a var in {cls.__module__}.{cls.__name__}; use a different name instead\"\n                raise ComputedVarShadowsStateVarError(msg)\n\n    @classmethod\n    def get_skip_vars(cls) -> set[str]:\n        \"\"\"Get the vars to skip when serializing.\n\n        Returns:\n            The vars to skip when serializing.\n        \"\"\"\n        return (\n            set(cls.inherited_vars)\n            | {\n                \"parent_state\",\n                \"substates\",\n                \"dirty_vars\",\n                \"dirty_substates\",\n                \"router_data\",\n            }\n            | types.RESERVED_BACKEND_VAR_NAMES\n        )\n\n    @classmethod\n    @functools.lru_cache\n    def get_parent_state(cls) -> type[BaseState] | None:\n        \"\"\"Get the parent state.\n\n        Returns:\n            The parent state.\n\n        Raises:\n            ValueError: If more than one parent state is found.\n        \"\"\"\n        parent_states = [\n            base\n            for base in cls.__bases__\n            if issubclass(base, BaseState) and base is not BaseState and not base._mixin\n        ]\n        if len(parent_states) >= 2:\n            msg = f\"Only one parent state of is allowed. Found {parent_states} parents of {cls}.\"\n            raise ValueError(msg)\n        # The first non-mixin state in the mro is our parent.\n        for base in cls.mro()[1:]:\n            if not issubclass(base, BaseState) or base._mixin:\n                continue\n            if base is BaseState:\n                break\n            return base\n        return None  # No known parent\n\n    @classmethod\n    @functools.lru_cache\n    def get_root_state(cls) -> type[BaseState]:\n        \"\"\"Get the root state.\n\n        Returns:\n            The root state.\n        \"\"\"\n        parent_state = cls.get_parent_state()\n        return cls if parent_state is None else parent_state.get_root_state()\n\n    @classmethod\n    def get_substates(cls) -> set[type[BaseState]]:\n        \"\"\"Get the substates of the state.\n\n        Returns:\n            The substates of the state.\n        \"\"\"\n        return cls.class_subclasses\n\n    @classmethod\n    @functools.lru_cache\n    def get_name(cls) -> str:\n        \"\"\"Get the name of the state.\n\n        Returns:\n            The name of the state.\n        \"\"\"\n        module = cls.__module__.replace(\".\", \"___\")\n        return format.to_snake_case(f\"{module}___{cls.__name__}\")\n\n    @classmethod\n    @functools.lru_cache\n    def get_full_name(cls) -> str:\n        \"\"\"Get the full name of the state.\n\n        Returns:\n            The full name of the state.\n        \"\"\"\n        name = cls.get_name()\n        parent_state = cls.get_parent_state()\n        if parent_state is not None:\n            name = parent_state.get_full_name() + \".\" + name\n        return name\n\n    @classmethod\n    @functools.lru_cache\n    def get_class_substate(cls, path: Sequence[str] | str) -> type[BaseState]:\n        \"\"\"Get the class substate.\n\n        Args:\n            path: The path to the substate.\n\n        Returns:\n            The class substate.\n\n        Raises:\n            ValueError: If the substate is not found.\n        \"\"\"\n        if isinstance(path, str):\n            path = tuple(path.split(\".\"))\n\n        if len(path) == 0:\n            return cls\n        if path[0] == cls.get_name():\n            if len(path) == 1:\n                return cls\n            path = path[1:]\n        for substate in cls.get_substates():\n            if path[0] == substate.get_name():\n                return substate.get_class_substate(path[1:])\n        msg = f\"Invalid path: {path}\"\n        raise ValueError(msg)\n\n    @classmethod\n    def get_class_var(cls, path: Sequence[str]) -> Any:\n        \"\"\"Get the class var.\n\n        Args:\n            path: The path to the var.\n\n        Returns:\n            The class var.\n\n        Raises:\n            ValueError: If the path is invalid.\n        \"\"\"\n        path, name = path[:-1], path[-1]\n        substate = cls.get_class_substate(tuple(path))\n        if not hasattr(substate, name):\n            msg = f\"Invalid path: {path}\"\n            raise ValueError(msg)\n        return getattr(substate, name)\n\n    @classmethod\n    def is_user_defined(cls) -> bool:\n        \"\"\"Check if the state is user-defined.\n\n        Returns:\n            True if the state is user-defined, False otherwise.\n        \"\"\"\n        return (\n            not cls.__module__.startswith(\"reflex.\")\n            or cls.__module__ == \"reflex.istate.dynamic\"\n        )\n\n    @classmethod\n    def _init_var(cls, name: str, prop: Var):\n        \"\"\"Initialize a variable.\n\n        Args:\n            name: The name of the variable\n            prop: The variable to initialize\n\n        Raises:\n            VarTypeError: if the variable has an incorrect type\n        \"\"\"\n        from reflex.config import get_config\n        from reflex.utils.exceptions import VarTypeError\n\n        if not types.is_valid_var_type(prop._var_type):\n            msg = (\n                \"State vars must be of a serializable type. \"\n                \"Valid types include strings, numbers, booleans, lists, \"\n                \"dictionaries, dataclasses, datetime objects, and pydantic models. \"\n                f'Found var \"{prop._js_expr}\" with type {prop._var_type}.'\n            )\n            raise VarTypeError(msg)\n        cls._set_var(name, prop)\n        if cls.is_user_defined() and get_config().state_auto_setters is not False:\n            cls._create_setter(name, prop)\n        cls._set_default_value(name, prop)\n\n    @classmethod\n    def add_var(cls, name: str, type_: Any, default_value: Any = None):\n        \"\"\"Add dynamically a variable to the State.\n\n        The variable added this way can be used in the same way as a variable\n        defined statically in the model.\n\n        Args:\n            name: The name of the variable\n            type_: The type of the variable\n            default_value: The default value of the variable\n\n        Raises:\n            NameError: if a variable of this name already exists\n        \"\"\"\n        if name in cls.__fields__:\n            msg = f\"The variable '{name}' already exist. Use a different name\"\n            raise NameError(msg)\n\n        # create the variable based on name and type\n        var = Var(\n            _js_expr=format.format_state_name(cls.get_full_name())\n            + \".\"\n            + name\n            + FIELD_MARKER,\n            _var_type=type_,\n            _var_data=VarData.from_state(cls, name),\n        ).guess_type()\n\n        # add the field dynamically (must be done before _init_var)\n        cls.add_field(name, var, default_value)\n\n        cls._init_var(name, var)\n\n        # update the internal dicts so the new variable is correctly handled\n        cls.base_vars.update({name: var})\n        cls.vars.update({name: var})\n\n        # let substates know about the new variable\n        for substate_class in cls.class_subclasses:\n            substate_class.vars.setdefault(name, var)\n\n        # Reinitialize dependency tracking dicts.\n        cls._init_var_dependency_dicts()\n\n    @classmethod\n    def _set_var(cls, name: str, prop: Var):\n        \"\"\"Set the var as a class member.\n\n        Args:\n            name: The name of the var.\n            prop: The var instance to set.\n        \"\"\"\n        setattr(cls, name, prop)\n\n    @classmethod\n    def _create_event_handler(\n        cls, fn: Any, event_handler_cls: type[EventHandler] = EventHandler\n    ):\n        \"\"\"Create an event handler for the given function.\n\n        Args:\n            fn: The function to create an event handler for.\n            event_handler_cls: The event handler class to use.\n\n        Returns:\n            The event handler.\n        \"\"\"\n        # Check if function has stored event_actions from decorator\n        event_actions = getattr(fn, EVENT_ACTIONS_MARKER, {})\n\n        return event_handler_cls(\n            fn=fn, state_full_name=cls.get_full_name(), event_actions=event_actions\n        )\n\n    @classmethod\n    def _create_setvar(cls):\n        \"\"\"Create the setvar method for the state.\"\"\"\n        cls.setvar = cls.event_handlers[\"setvar\"] = EventHandlerSetVar(state_cls=cls)\n\n    @classmethod\n    def _create_setter(cls, name: str, prop: Var):\n        \"\"\"Create a setter for the var.\n\n        Args:\n            name: The name of the var.\n            prop: The var to create a setter for.\n        \"\"\"\n        from reflex.config import get_config\n\n        config = get_config()\n        create_event_handler_kwargs = {}\n\n        if config.state_auto_setters is None:\n\n            class EventHandlerDeprecatedSetter(EventHandler):\n                def __call__(self, *args, **kwargs):\n                    console.deprecate(\n                        feature_name=\"state_auto_setters defaulting to True\",\n                        reason=\"The default value will be changed to False in a future release. Set state_auto_setters explicitly or define setters explicitly. \"\n                        f\"Used {setter_name} in {cls.__name__} without defining it.\",\n                        deprecation_version=\"0.8.9\",\n                        removal_version=\"0.9.0\",\n                        dedupe=True,\n                    )\n                    return super().__call__(*args, **kwargs)\n\n            create_event_handler_kwargs[\"event_handler_cls\"] = (\n                EventHandlerDeprecatedSetter\n            )\n\n        setter_name = Var._get_setter_name_for_name(name)\n        if setter_name not in cls.__dict__:\n            event_handler = cls._create_event_handler(\n                prop._get_setter(name), **create_event_handler_kwargs\n            )\n            cls.event_handlers[setter_name] = event_handler\n            setattr(cls, setter_name, event_handler)\n\n    @classmethod\n    def _set_default_value(cls, name: str, prop: Var):\n        \"\"\"Set the default value for the var.\n\n        Args:\n            name: The name of the var.\n            prop: The var to set the default value for.\n        \"\"\"\n        # Get the field for the var.\n        field = cls.get_fields()[name]\n\n        if field.default is None and not types.is_optional(prop._var_type):\n            # Ensure frontend uses null coalescing when accessing.\n            object.__setattr__(prop, \"_var_type\", prop._var_type | None)\n\n    @classmethod\n    def _get_var_default(cls, name: str, annotation_value: Any) -> Any:\n        \"\"\"Get the default value of a (backend) var.\n\n        Args:\n            name: The name of the var.\n            annotation_value: The annotation value of the var.\n\n        Returns:\n            The default value of the var or None.\n        \"\"\"\n        try:\n            value = getattr(cls, name)\n            return value if not isinstance(value, Field) else value.default_value()\n        except AttributeError:\n            try:\n                return types.get_default_value_for_type(annotation_value)\n            except TypeError:\n                pass\n        return None\n\n    @staticmethod\n    def _get_base_functions() -> dict[str, FunctionType]:\n        \"\"\"Get all functions of the state class excluding dunder methods.\n\n        Returns:\n            The functions of rx.State class as a dict.\n        \"\"\"\n        return {\n            func[0]: func[1]\n            for func in inspect.getmembers(BaseState, predicate=inspect.isfunction)\n            if not func[0].startswith(\"__\")\n        }\n\n    @classmethod\n    def _update_substate_inherited_vars(cls, vars_to_add: dict[str, Var]):\n        \"\"\"Update the inherited vars of substates recursively when new vars are added.\n\n        Also updates the var dependency tracking dicts after adding vars.\n\n        Args:\n            vars_to_add: names to Var instances to add to substates\n        \"\"\"\n        for substate_class in cls.class_subclasses:\n            for name, var in vars_to_add.items():\n                if types.is_backend_base_variable(name, cls):\n                    substate_class.backend_vars.setdefault(name, var)\n                    substate_class.inherited_backend_vars.setdefault(name, var)\n                else:\n                    substate_class.vars.setdefault(name, var)\n                    substate_class.inherited_vars.setdefault(name, var)\n                substate_class._update_substate_inherited_vars(vars_to_add)\n        # Reinitialize dependency tracking dicts.\n        cls._init_var_dependency_dicts()\n\n    @classmethod\n    def setup_dynamic_args(cls, args: dict[str, str]):\n        \"\"\"Set up args for easy access in renderer.\n\n        Args:\n            args: a dict of args\n        \"\"\"\n        if not args:\n            return\n\n        cls._check_overwritten_dynamic_args(list(args.keys()))\n\n        def argsingle_factory(param: str):\n            def inner_func(self: BaseState) -> str:\n                return self.router._page.params.get(param, \"\")\n\n            inner_func.__name__ = param\n\n            return inner_func\n\n        def arglist_factory(param: str):\n            def inner_func(self: BaseState) -> list[str]:\n                return self.router._page.params.get(param, [])\n\n            inner_func.__name__ = param\n\n            return inner_func\n\n        dynamic_vars = {}\n        for param, value in args.items():\n            if value == constants.RouteArgType.SINGLE:\n                func = argsingle_factory(param)\n            elif value == constants.RouteArgType.LIST:\n                func = arglist_factory(param)\n            else:\n                continue\n            dynamic_vars[param] = DynamicRouteVar(\n                fget=func,\n                auto_deps=False,\n                deps=[\"router\"],\n                _var_data=VarData.from_state(cls, param),\n            )\n            setattr(cls, param, dynamic_vars[param])\n\n        # Update tracking dicts.\n        cls.computed_vars.update(dynamic_vars)\n        cls.vars.update(dynamic_vars)\n        cls._update_substate_inherited_vars(dynamic_vars)\n\n    @classmethod\n    def _check_overwritten_dynamic_args(cls, args: list[str]):\n        \"\"\"Check if dynamic args are shadowing existing vars. Recursively checks all child states.\n\n        Args:\n            args: a dict of args\n\n        Raises:\n            DynamicRouteArgShadowsStateVarError: If a dynamic arg is shadowing an existing var.\n        \"\"\"\n        for arg in args:\n            if (\n                arg in cls.computed_vars\n                and not isinstance(cls.computed_vars[arg], DynamicRouteVar)\n            ) or arg in cls.base_vars:\n                msg = f\"Dynamic route arg '{arg}' is shadowing an existing var in {cls.__module__}.{cls.__name__}\"\n                raise DynamicRouteArgShadowsStateVarError(msg)\n        for substate in cls.get_substates():\n            substate._check_overwritten_dynamic_args(args)\n\n    def _get_attribute(self, name: str) -> Any:\n        \"\"\"Get the state var.\n\n        If the var is inherited, get the var from the parent state.\n\n        Args:\n            name: The name of the var.\n\n        Returns:\n            The value of the var.\n        \"\"\"\n        # Fast path for dunder\n        if name.startswith(\"__\") or name in CLASS_VAR_NAMES:\n            return super().__getattribute__(name)\n\n        # For now, handle router_data updates as a special case.\n        if (\n            name == constants.ROUTER_DATA\n            or name in super().__getattribute__(\"inherited_vars\")\n            or name in super().__getattribute__(\"inherited_backend_vars\")\n        ):\n            parent_state = super().__getattribute__(\"parent_state\")\n            if parent_state is not None:\n                return getattr(parent_state, name)\n\n        # Allow event handlers to be called on the instance directly.\n        event_handlers = super().__getattribute__(\"event_handlers\")\n        if name in event_handlers:\n            handler = event_handlers[name]\n            if handler.is_background:\n                fn = _no_chain_background_task(self, name, handler.fn)\n            else:\n                fn = functools.partial(handler.fn, self)\n            fn.__module__ = handler.fn.__module__\n            fn.__qualname__ = handler.fn.__qualname__\n            return fn\n\n        backend_vars = super().__getattribute__(\"_backend_vars\") or {}\n        if name in backend_vars:\n            value = backend_vars[name]\n        else:\n            value = super().__getattribute__(name)\n\n        if isinstance(value, EventHandler):\n            # The event handler is inherited from a parent, so let the parent convert\n            # it to a callable function.\n            parent_state = super().__getattribute__(\"parent_state\")\n            if parent_state is not None:\n                return getattr(parent_state, name)\n\n        if is_mutable_type(type(value)) and (\n            name in super().__getattribute__(\"base_vars\") or name in backend_vars\n        ):\n            # track changes in mutable containers (list, dict, set, etc)\n            return MutableProxy(wrapped=value, state=self, field_name=name)\n\n        return value\n\n    if not TYPE_CHECKING:\n        __getattribute__ = _get_attribute\n\n    def __setattr__(self, name: str, value: Any):\n        \"\"\"Set the attribute.\n\n        If the attribute is inherited, set the attribute on the parent state.\n\n        Args:\n            name: The name of the attribute.\n            value: The value of the attribute.\n\n        Raises:\n            SetUndefinedStateVarError: If a value of a var is set without first defining it.\n        \"\"\"\n        if name.startswith(\"__\") or name in CLASS_VAR_NAMES:\n            # Fast path for dunder and class vars\n            object.__setattr__(self, name, value)\n            return\n\n        if isinstance(value, MutableProxy):\n            # unwrap proxy objects when assigning back to the state\n            value = value.__wrapped__\n\n        # Set the var on the parent state.\n        if name in self.inherited_vars or name in self.inherited_backend_vars:\n            setattr(self.parent_state, name, value)\n            return\n\n        if name in self.backend_vars:\n            self._backend_vars.__setitem__(name, value)\n            self.dirty_vars.add(name)\n            self._mark_dirty()\n            return\n\n        if (\n            name not in self.vars\n            and name not in self.get_skip_vars()\n            and not name.startswith(\"__\")\n            and not name.startswith(\n                f\"_{getattr(type(self), '__original_name__', type(self).__name__)}__\"\n            )\n        ):\n            msg = (\n                f\"The state variable '{name}' has not been defined in '{type(self).__name__}'. \"\n                f\"All state variables must be declared before they can be set.\"\n            )\n            raise SetUndefinedStateVarError(msg)\n\n        fields = self.get_fields()\n\n        if (field := fields.get(name)) is not None and field.is_var:\n            field_type = field.outer_type_\n            if not _isinstance(value, field_type, nested=1, treat_var_as_type=False):\n                console.error(\n                    f\"Expected field '{type(self).__name__}.{name}' to receive type '{escape(str(field_type))}',\"\n                    f\" but got '{value}' of type '{type(value)}'.\"\n                )\n\n        # Set the attribute.\n        object.__setattr__(self, name, value)\n\n        # Add the var to the dirty list.\n        if name in self.base_vars:\n            self.dirty_vars.add(name)\n            self._mark_dirty()\n\n        # For now, handle router_data updates as a special case\n        if name == constants.ROUTER_DATA:\n            self.dirty_vars.add(name)\n            self._mark_dirty()\n\n    def reset(self):\n        \"\"\"Reset all the base vars to their default values.\"\"\"\n        # Reset the base vars.\n        fields = self.get_fields()\n        for prop_name in self.base_vars:\n            if prop_name == constants.ROUTER:\n                continue  # never reset the router data\n            field = fields[prop_name]\n            if default_factory := field.default_factory:\n                default = default_factory()\n            else:\n                default = copy.deepcopy(field.default)\n            setattr(self, prop_name, default)\n\n        # Reset the backend vars.\n        for prop_name, value in self.backend_vars.items():\n            setattr(self, prop_name, copy.deepcopy(value))\n\n        # Recursively reset the substates.\n        for substate in self.substates.values():\n            substate.reset()\n\n    @classmethod\n    @functools.lru_cache\n    def _is_client_storage(cls, prop_name_or_field: str | Field) -> bool:\n        \"\"\"Check if the var is a client storage var.\n\n        Args:\n            prop_name_or_field: The name of the var or the field itself.\n\n        Returns:\n            Whether the var is a client storage var.\n        \"\"\"\n        if isinstance(prop_name_or_field, str):\n            field = cls.get_fields().get(prop_name_or_field)\n        else:\n            field = prop_name_or_field\n        return field is not None and (\n            isinstance(field.default, ClientStorageBase)\n            or (\n                isinstance(field.type_, type)\n                and issubclass(field.type_, ClientStorageBase)\n            )\n        )\n\n    def _reset_client_storage(self):\n        \"\"\"Reset client storage base vars to their default values.\"\"\"\n        # Client-side storage is reset during hydrate so that clearing cookies\n        # on the browser also resets the values on the backend.\n        fields = self.get_fields()\n        for prop_name in self.base_vars:\n            field = fields[prop_name]\n            if self._is_client_storage(field):\n                setattr(self, prop_name, copy.deepcopy(field.default))\n\n        # Recursively reset the substate client storage.\n        for substate in self.substates.values():\n            substate._reset_client_storage()\n\n    def get_substate(self, path: Sequence[str]) -> BaseState:\n        \"\"\"Get the substate.\n\n        Args:\n            path: The path to the substate.\n\n        Returns:\n            The substate.\n\n        Raises:\n            ValueError: If the substate is not found.\n        \"\"\"\n        if len(path) == 0:\n            return self\n        if path[0] == self.get_name():\n            if len(path) == 1:\n                return self\n            path = path[1:]\n        if path[0] not in self.substates:\n            msg = f\"Invalid path: {path}\"\n            raise ValueError(msg)\n        return self.substates[path[0]].get_substate(path[1:])\n\n    @classmethod\n    def _get_potentially_dirty_states(cls) -> set[type[BaseState]]:\n        \"\"\"Get substates which may have dirty vars due to dependencies.\n\n        Returns:\n            The set of potentially dirty substate classes.\n        \"\"\"\n        return {\n            cls.get_class_substate(substate_name)\n            for substate_name in cls._always_dirty_substates\n        }.union({\n            cls.get_root_state().get_class_substate(substate_name)\n            for substate_name in cls._potentially_dirty_states\n        })\n\n    def _get_root_state(self) -> BaseState:\n        \"\"\"Get the root state of the state tree.\n\n        Returns:\n            The root state of the state tree.\n        \"\"\"\n        parent_state = self\n        while parent_state.parent_state is not None:\n            parent_state = parent_state.parent_state\n        return parent_state\n\n    async def _get_state_from_redis(self, state_cls: type[T_STATE]) -> T_STATE:\n        \"\"\"Get a state instance from redis.\n\n        Args:\n            state_cls: The class of the state.\n\n        Returns:\n            The instance of state_cls associated with this state's client_token.\n\n        Raises:\n            RuntimeError: If redis is not used in this backend process.\n            StateMismatchError: If the state instance is not of the expected type.\n        \"\"\"\n        from reflex.istate.manager.redis import StateManagerRedis\n\n        # Then get the target state and all its substates.\n        state_manager = get_state_manager()\n        if not isinstance(state_manager, StateManagerRedis):\n            msg = (\n                f\"Requested state {state_cls.get_full_name()} is not cached and cannot be accessed without redis. \"\n                \"(All states should already be available -- this is likely a bug).\"\n            )\n            raise RuntimeError(msg)\n        state_in_redis = await state_manager.get_state(\n            token=_substate_key(self.router.session.client_token, state_cls),\n            top_level=False,\n            for_state_instance=self,\n        )\n\n        if not isinstance(state_in_redis, state_cls):\n            msg = f\"Searched for state {state_cls.get_full_name()} but found {state_in_redis}.\"\n            raise StateMismatchError(msg)\n\n        return state_in_redis\n\n    def _get_state_from_cache(self, state_cls: type[T_STATE]) -> T_STATE:\n        \"\"\"Get a state instance from the cache.\n\n        Args:\n            state_cls: The class of the state.\n\n        Returns:\n            The instance of state_cls associated with this state's client_token.\n\n        Raises:\n            StateMismatchError: If the state instance is not of the expected type.\n        \"\"\"\n        root_state = self._get_root_state()\n        substate = root_state.get_substate(state_cls.get_full_name().split(\".\"))\n        if not isinstance(substate, state_cls):\n            msg = (\n                f\"Searched for state {state_cls.get_full_name()} but found {substate}.\"\n            )\n            raise StateMismatchError(msg)\n        return substate\n\n    async def get_state(self, state_cls: type[T_STATE]) -> T_STATE:\n        \"\"\"Get an instance of the state associated with this token.\n\n        Allows for arbitrary access to sibling states from within an event handler.\n\n        Args:\n            state_cls: The class of the state.\n\n        Returns:\n            The instance of state_cls associated with this state's client_token.\n        \"\"\"\n        # Fast case - if this state instance is already cached, get_substate from root state.\n        try:\n            return self._get_state_from_cache(state_cls)\n        except ValueError:\n            pass\n\n        # Slow case - fetch missing parent states from redis.\n        return await self._get_state_from_redis(state_cls)\n\n    async def get_var_value(self, var: Var[VAR_TYPE]) -> VAR_TYPE:\n        \"\"\"Get the value of an rx.Var from another state.\n\n        Args:\n            var: The var to get the value for.\n\n        Returns:\n            The value of the var.\n\n        Raises:\n            UnretrievableVarValueError: If the var does not have a literal value\n                or associated state.\n        \"\"\"\n        # Oopsie case: you didn't give me a Var... so get what you give.\n        if not isinstance(var, Var):\n            return var\n\n        unset = object()\n\n        # Fast case: this is a literal var and the value is known.\n        if (\n            var_value := getattr(var, \"_var_value\", unset)\n        ) is not unset and not isinstance(var_value, Var):\n            return var_value  # pyright: ignore [reportReturnType]\n\n        var_data = var._get_all_var_data()\n        if var_data is None or not var_data.state:\n            msg = f\"Unable to retrieve value for {var._js_expr}: not associated with any state.\"\n            raise UnretrievableVarValueError(msg)\n        # Fastish case: this var belongs to this state\n        if var_data.state == self.get_full_name():\n            return getattr(self, var_data.field_name)\n\n        # Slow case: this var belongs to another state\n        other_state = await self.get_state(\n            self._get_root_state().get_class_substate(var_data.state)\n        )\n        return getattr(other_state, var_data.field_name)\n\n    def _get_event_handler(self, event: Event | str) -> tuple[BaseState, EventHandler]:\n        \"\"\"Get the event handler for the given event.\n\n        Args:\n            event: The event to get the handler for, or a dotted handler name string.\n\n\n        Returns:\n            The event handler.\n\n        Raises:\n            ValueError: If the event handler or substate is not found.\n        \"\"\"\n        # Get the event handler.\n        name = event.name if isinstance(event, Event) else event\n        path = name.split(\".\")\n        path, name = path[:-1], path[-1]\n        substate = self.get_substate(path)\n        if not substate:\n            msg = \"The value of state cannot be None when processing an event.\"\n            raise ValueError(msg)\n        handler = substate.event_handlers[name]\n\n        return substate, handler\n\n    async def _process(self, event: Event) -> AsyncIterator[StateUpdate]:\n        \"\"\"Obtain event info and process event.\n\n        Args:\n            event: The event to process.\n\n        Yields:\n            The state update after processing the event.\n        \"\"\"\n        # Get the event handler.\n        substate, handler = self._get_event_handler(event)\n\n        # For background tasks, proxy the state.\n        if handler.is_background:\n            substate = StateProxy(substate, event)\n\n        # Run the event generator and yield state updates.\n        async for update in self._process_event(\n            handler=handler,\n            state=substate,\n            payload=event.payload,\n        ):\n            yield update\n\n    def _check_valid(self, handler: EventHandler, events: Any) -> Any:\n        \"\"\"Check if the events yielded are valid. They must be EventHandlers or EventSpecs.\n\n        Args:\n            handler: EventHandler.\n            events: The events to be checked.\n\n        Returns:\n            The events as they are if valid.\n\n        Raises:\n            TypeError: If any of the events are not valid.\n        \"\"\"\n\n        def _is_valid_type(events: Any) -> bool:\n            return isinstance(events, (Event, EventHandler, EventSpec))\n\n        if events is None or _is_valid_type(events):\n            return events\n\n        if not (isinstance(events, Sequence) and not isinstance(events, (str, bytes))):\n            events = [events]\n\n        try:\n            if all(_is_valid_type(e) for e in events):\n                return events\n        except TypeError:\n            pass\n\n        coroutines = [e for e in events if inspect.iscoroutine(e)]\n\n        for coroutine in coroutines:\n            coroutine_name = coroutine.__qualname__\n            warnings.filterwarnings(\n                \"ignore\", message=f\"coroutine '{coroutine_name}' was never awaited\"\n            )\n\n        msg = (\n            f\"Your handler {handler.fn.__qualname__} must only return/yield: None, Events or other EventHandlers referenced by their class (i.e. using `type(self)` or other class references).\"\n            f\" Returned events of types {', '.join(map(str, map(type, events)))!s}.\"\n        )\n        raise TypeError(msg)\n\n    async def _as_state_update(\n        self,\n        handler: EventHandler,\n        events: EventSpec | list[EventSpec] | None,\n        final: bool,\n    ) -> StateUpdate:\n        \"\"\"Convert the events to a StateUpdate.\n\n        Fixes the events and checks for validity before converting.\n\n        Args:\n            handler: The handler where the events originated from.\n            events: The events to queue with the update.\n            final: Whether the handler is done processing.\n\n        Returns:\n            The valid StateUpdate containing the events and final flag.\n        \"\"\"\n        # get the delta from the root of the state tree\n        state = self._get_root_state()\n\n        token = self.router.session.client_token\n\n        # Convert valid EventHandler and EventSpec into Event\n        fixed_events = fix_events(self._check_valid(handler, events), token)\n\n        try:\n            # Get the delta after processing the event.\n            delta = await state._get_resolved_delta()\n            state._clean()\n\n            return StateUpdate(\n                delta=delta,\n                events=fixed_events,\n                final=final if not handler.is_background else None,\n            )\n        except Exception as ex:\n            state._clean()\n\n            event_specs = (\n                prerequisites.get_and_validate_app().app.backend_exception_handler(ex)\n            )\n\n            if event_specs is None:\n                return StateUpdate()\n\n            event_specs_correct_type = cast(\n                list[EventSpec | EventHandler] | None,\n                [event_specs] if isinstance(event_specs, EventSpec) else event_specs,\n            )\n            fixed_events = fix_events(\n                event_specs_correct_type,\n                token,\n                router_data=state.router_data,\n            )\n            return StateUpdate(\n                events=fixed_events,\n                final=True,\n            )\n\n    async def _process_event(\n        self,\n        handler: EventHandler,\n        state: BaseState | StateProxy,\n        payload: builtins.dict,\n    ) -> AsyncIterator[StateUpdate]:\n        \"\"\"Process event.\n\n        Args:\n            handler: EventHandler to process.\n            state: State to process the handler.\n            payload: The event payload.\n\n        Yields:\n            StateUpdate object\n\n        Raises:\n            ValueError: If a string value is received for an int or float type and cannot be converted.\n        \"\"\"\n        from reflex.utils import telemetry\n\n        # Get the function to process the event.\n        if is_pyleak_enabled():\n            console.debug(f\"Monitoring leaks for handler: {handler.fn.__qualname__}\")\n            fn = functools.partial(monitor_loopblocks(handler.fn), state)\n        else:\n            fn = functools.partial(handler.fn, state)\n\n        try:\n            type_hints = types.get_type_hints(handler.fn)\n        except Exception:\n            type_hints = {}\n\n        for arg, value in list(payload.items()):\n            hinted_args = type_hints.get(arg, Any)\n            if hinted_args is Any:\n                continue\n            if is_union(hinted_args):\n                if value is None:\n                    continue\n                hinted_args = value_inside_optional(hinted_args)\n            if (\n                isinstance(value, dict)\n                and isinstance(hinted_args, type)\n                and not types.is_generic_alias(hinted_args)  # py3.10\n            ):\n                if issubclass(hinted_args, Model):\n                    # Remove non-fields from the payload\n                    payload[arg] = hinted_args(**{\n                        key: value\n                        for key, value in value.items()\n                        if key in hinted_args.__fields__\n                    })\n                elif dataclasses.is_dataclass(hinted_args):\n                    payload[arg] = hinted_args(**value)\n                elif find_spec(\"pydantic\"):\n                    from pydantic import BaseModel as BaseModelV2\n                    from pydantic.v1 import BaseModel as BaseModelV1\n\n                    if issubclass(hinted_args, BaseModelV1):\n                        payload[arg] = hinted_args.parse_obj(value)\n                    elif issubclass(hinted_args, BaseModelV2):\n                        payload[arg] = hinted_args.model_validate(value)\n            elif isinstance(value, list) and (hinted_args is set or hinted_args is set):\n                payload[arg] = set(value)\n            elif isinstance(value, list) and (\n                hinted_args is tuple or hinted_args is tuple\n            ):\n                payload[arg] = tuple(value)\n            elif isinstance(hinted_args, type) and issubclass(hinted_args, Enum):\n                try:\n                    payload[arg] = hinted_args(value)\n                except ValueError:\n                    msg = f\"Received an invalid enum value ({value}) for {arg} of type {hinted_args}\"\n                    raise ValueError(msg) from None\n            elif (\n                isinstance(value, str)\n                and (deserializer := _deserializers.get(hinted_args)) is not None\n            ):\n                try:\n                    payload[arg] = deserializer(value)\n                except ValueError:\n                    msg = f\"Received a string value ({value}) for {arg} but expected a {hinted_args}\"\n                    raise ValueError(msg) from None\n                else:\n                    console.warn(\n                        f\"Received a string value ({value}) for {arg} but expected a {hinted_args}. A simple conversion was successful.\"\n                    )\n\n        # Wrap the function in a try/except block.\n        try:\n            # Handle async functions.\n            if inspect.iscoroutinefunction(fn.func):\n                events = await fn(**payload)\n\n            # Handle regular functions.\n            else:\n                events = fn(**payload)\n            # Handle async generators.\n            if inspect.isasyncgen(events):\n                async for event in events:\n                    yield await state._as_state_update(handler, event, final=False)\n                yield await state._as_state_update(handler, events=None, final=True)\n\n            # Handle regular generators.\n            elif inspect.isgenerator(events):\n                try:\n                    while True:\n                        yield await state._as_state_update(\n                            handler, next(events), final=False\n                        )\n                except StopIteration as si:\n                    # the \"return\" value of the generator is not available\n                    # in the loop, we must catch StopIteration to access it\n                    if si.value is not None:\n                        yield await state._as_state_update(\n                            handler, si.value, final=False\n                        )\n                yield await state._as_state_update(handler, events=None, final=True)\n\n            # Handle regular event chains.\n            else:\n                yield await state._as_state_update(handler, events, final=True)\n\n        # If an error occurs, throw a window alert.\n        except Exception as ex:\n            telemetry.send_error(ex, context=\"backend\")\n\n            event_specs = (\n                prerequisites.get_and_validate_app().app.backend_exception_handler(ex)\n            )\n\n            yield await state._as_state_update(\n                handler,\n                event_specs,\n                final=True,\n            )\n\n    def _mark_dirty_computed_vars(self) -> None:\n        \"\"\"Mark ComputedVars that need to be recalculated based on dirty_vars.\"\"\"\n        # Append expired computed vars to dirty_vars to trigger recalculation\n        self.dirty_vars.update(self._expired_computed_vars())\n        # Append always dirty computed vars to dirty_vars to trigger recalculation\n        self.dirty_vars.update(self._always_dirty_computed_vars)\n\n        dirty_vars = self.dirty_vars\n        while dirty_vars:\n            calc_vars, dirty_vars = dirty_vars, set()\n            for state_name, cvar in self._dirty_computed_vars(from_vars=calc_vars):\n                if state_name == self.get_full_name():\n                    defining_state = self\n                else:\n                    defining_state = self._get_root_state().get_substate(\n                        tuple(state_name.split(\".\"))\n                    )\n                defining_state.dirty_vars.add(cvar)\n                actual_var = defining_state.computed_vars.get(cvar)\n                if actual_var is not None:\n                    actual_var.mark_dirty(instance=defining_state)\n                if defining_state is self:\n                    dirty_vars.add(cvar)\n                else:\n                    # mark dirty where this var is defined\n                    defining_state._mark_dirty()\n\n    def _expired_computed_vars(self) -> set[str]:\n        \"\"\"Determine ComputedVars that need to be recalculated based on the expiration time.\n\n        Returns:\n            Set of computed vars to include in the delta.\n        \"\"\"\n        return {\n            cvar\n            for cvar, cvar_obj in self.computed_vars.items()\n            if cvar_obj.needs_update(instance=self)\n        }\n\n    def _dirty_computed_vars(\n        self, from_vars: set[str] | None = None, include_backend: bool = True\n    ) -> set[tuple[str, str]]:\n        \"\"\"Determine ComputedVars that need to be recalculated based on the given vars.\n\n        Args:\n            from_vars: find ComputedVar that depend on this set of vars. If unspecified, will use the dirty_vars.\n            include_backend: whether to include backend vars in the calculation.\n\n        Returns:\n            Set of computed vars to include in the delta.\n        \"\"\"\n        return {\n            (state_name, cvar)\n            for dirty_var in from_vars or self.dirty_vars\n            for state_name, cvar in self._var_dependencies.get(dirty_var, set())\n            if include_backend or not self.computed_vars[cvar]._backend\n        }\n\n    def get_delta(self) -> Delta:\n        \"\"\"Get the delta for the state.\n\n        Returns:\n            The delta for the state.\n        \"\"\"\n        delta = {}\n\n        self._mark_dirty_computed_vars()\n        frontend_computed_vars: set[str] = {\n            name for name, cv in self.computed_vars.items() if not cv._backend\n        }\n\n        # Return the dirty vars for this instance, any cached/dependent computed vars,\n        # and always dirty computed vars (cache=False)\n        delta_vars = self.dirty_vars.intersection(self.base_vars).union(\n            self.dirty_vars.intersection(frontend_computed_vars)\n        )\n\n        subdelta: dict[str, Any] = {\n            prop + FIELD_MARKER: self.get_value(prop)\n            for prop in delta_vars\n            if not types.is_backend_base_variable(prop, type(self))\n        }\n\n        if len(subdelta) > 0:\n            delta[self.get_full_name()] = subdelta\n\n        # Recursively find the substate deltas.\n        substates = self.substates\n        for substate in self.dirty_substates.union(self._always_dirty_substates):\n            delta.update(substates[substate].get_delta())\n\n        # Return the delta.\n        return delta\n\n    async def _get_resolved_delta(self) -> Delta:\n        \"\"\"Get the delta for the state after resolving all coroutines.\n\n        Returns:\n            The resolved delta for the state.\n        \"\"\"\n        return await _resolve_delta(self.get_delta())\n\n    def _mark_dirty(self):\n        \"\"\"Mark the substate and all parent states as dirty.\"\"\"\n        state_name = self.get_name()\n        if (\n            self.parent_state is not None\n            and state_name not in self.parent_state.dirty_substates\n        ):\n            self.parent_state.dirty_substates.add(self.get_name())\n            self.parent_state._mark_dirty()\n\n        # have to mark computed vars dirty to allow access to newly computed\n        # values within the same ComputedVar function\n        self._mark_dirty_computed_vars()\n\n    def _update_was_touched(self):\n        \"\"\"Update the _was_touched flag based on dirty_vars.\"\"\"\n        if self.dirty_vars and not self._was_touched:\n            for var in self.dirty_vars:\n                if var in self.base_vars or var in self._backend_vars:\n                    self._was_touched = True\n                    break\n                if var == constants.ROUTER_DATA and self.parent_state is None:\n                    self._was_touched = True\n                    break\n\n    def _get_was_touched(self) -> bool:\n        \"\"\"Check current dirty_vars and flag to determine if state instance was modified.\n\n        If any dirty vars belong to this state, mark _was_touched.\n\n        This flag determines whether this state instance should be persisted to redis.\n\n        Returns:\n            Whether this state instance was ever modified.\n        \"\"\"\n        # Ensure the flag is up to date based on the current dirty_vars\n        self._update_was_touched()\n        return self._was_touched\n\n    def _clean(self):\n        \"\"\"Reset the dirty vars.\"\"\"\n        # Update touched status before cleaning dirty_vars.\n        self._update_was_touched()\n\n        # Recursively clean the substates.\n        for substate in self.dirty_substates:\n            if substate not in self.substates:\n                continue\n            self.substates[substate]._clean()\n\n        # Clean this state.\n        self.dirty_vars = set()\n        self.dirty_substates = set()\n\n    def get_value(self, key: str) -> Any:\n        \"\"\"Get the value of a field (without proxying).\n\n        The returned value will NOT track dirty state updates.\n\n        Args:\n            key: The key of the field.\n\n        Returns:\n            The value of the field.\n\n        Raises:\n            TypeError: If the key is not a string or MutableProxy.\n        \"\"\"\n        if isinstance(key, MutableProxy):\n            # Legacy behavior from v0.7.14: handle non-string keys with deprecation warning\n            from reflex.utils import console\n\n            console.deprecate(\n                feature_name=\"Non-string keys in get_value\",\n                reason=\"Passing non-string keys to get_value is deprecated and will no longer be supported\",\n                deprecation_version=\"0.8.0\",\n                removal_version=\"0.9.0\",\n            )\n\n            return key.__wrapped__\n\n        if isinstance(key, str):\n            return getattr(self, key)\n\n        msg = f\"Invalid key type: {type(key)}. Expected str.\"\n        raise TypeError(msg)\n\n    def dict(\n        self, include_computed: bool = True, initial: bool = False, **kwargs\n    ) -> dict[str, Any]:\n        \"\"\"Convert the object to a dictionary.\n\n        Args:\n            include_computed: Whether to include computed vars.\n            initial: Whether to get the initial value of computed vars.\n            **kwargs: Kwargs to pass to the dict method.\n\n        Returns:\n            The object as a dictionary.\n        \"\"\"\n        if include_computed:\n            self._mark_dirty_computed_vars()\n        base_vars = {\n            prop_name: self.get_value(prop_name) for prop_name in self.base_vars\n        }\n        if initial and include_computed:\n            computed_vars = {\n                # Include initial computed vars.\n                prop_name: (\n                    cv._initial_value\n                    if is_computed_var(cv)\n                    and not isinstance(cv._initial_value, types.Unset)\n                    else self.get_value(prop_name)\n                )\n                for prop_name, cv in self.computed_vars.items()\n                if not cv._backend\n            }\n        elif include_computed:\n            computed_vars = {\n                # Include the computed vars.\n                prop_name: self.get_value(prop_name)\n                for prop_name, cv in self.computed_vars.items()\n                if not cv._backend\n            }\n        else:\n            computed_vars = {}\n        variables = {**base_vars, **computed_vars}\n        d = {\n            self.get_full_name(): {\n                k + FIELD_MARKER: variables[k] for k in sorted(variables)\n            },\n        }\n        for substate_d in [\n            v.dict(include_computed=include_computed, initial=initial, **kwargs)\n            for v in self.substates.values()\n        ]:\n            d.update(substate_d)\n\n        return d\n\n    async def __aenter__(self) -> Self:\n        \"\"\"Enter the async context manager protocol.\n\n        This is a no-op for the State class and mainly used in background-tasks/StateProxy.\n\n        Returns:\n            The unmodified state (self)\n        \"\"\"\n        return self\n\n    async def __aexit__(self, *exc_info: Any) -> None:\n        \"\"\"Exit the async context manager protocol.\n\n        This should not be used for the State class, but exists for\n        type-compatibility with StateProxy.\n\n        Args:\n            exc_info: The exception info tuple.\n        \"\"\"\n\n    def __getstate__(self):\n        \"\"\"Get the state for redis serialization.\n\n        This method is called by pickle to serialize the object.\n\n        It explicitly removes parent_state and substates because those are serialized separately\n        by the StateManagerRedis to allow for better horizontal scaling as state size increases.\n\n        Returns:\n            The state dict for serialization.\n        \"\"\"\n        state = self.__dict__\n        state = state.copy()\n        if state.get(\"parent_state\") is not None:\n            # Do not serialize router data in substates (only the root state).\n            state.pop(\"router\", None)\n            state.pop(\"router_data\", None)\n        # Never serialize parent_state or substates.\n        state.pop(\"parent_state\", None)\n        state.pop(\"substates\", None)\n        state.pop(\"_was_touched\", None)\n        # Remove all inherited vars.\n        for inherited_var_name in self.inherited_vars:\n            state.pop(inherited_var_name, None)\n        return state\n\n    def __setstate__(self, state: dict[str, Any]):\n        \"\"\"Set the state from redis deserialization.\n\n        This method is called by pickle to deserialize the object.\n\n        Args:\n            state: The state dict for deserialization.\n        \"\"\"\n        state[\"parent_state\"] = None\n        state[\"substates\"] = {}\n        for key, value in state.items():\n            object.__setattr__(self, key, value)\n\n    def _check_state_size(\n        self,\n        pickle_state_size: int,\n    ):\n        \"\"\"Print a warning when the state is too large.\n\n        Args:\n            pickle_state_size: The size of the pickled state.\n\n        Raises:\n            StateTooLargeError: If the state is too large.\n        \"\"\"\n        state_full_name = self.get_full_name()\n        if (\n            state_full_name not in _WARNED_ABOUT_STATE_SIZE\n            and pickle_state_size > TOO_LARGE_SERIALIZED_STATE\n            and self.substates\n        ):\n            msg = (\n                f\"State {state_full_name} serializes to {pickle_state_size} bytes \"\n                + \"which may present performance issues. Consider reducing the size of this state.\"\n            )\n            if environment.REFLEX_PERF_MODE.get() == PerformanceMode.WARN:\n                console.warn(msg)\n            elif environment.REFLEX_PERF_MODE.get() == PerformanceMode.RAISE:\n                raise StateTooLargeError(msg)\n            _WARNED_ABOUT_STATE_SIZE.add(state_full_name)\n\n    @classmethod\n    @functools.lru_cache\n    def _to_schema(cls) -> str:\n        \"\"\"Convert a state to a schema.\n\n        Returns:\n            The hash of the schema.\n        \"\"\"\n\n        def _field_tuple(\n            field_name: str,\n        ) -> tuple[str, Any, Any]:\n            model_field = cls.__fields__[field_name]\n            return (\n                field_name,\n                _serialize_type(model_field.type_),\n                (model_field.default if is_serializable(model_field.default) else None),\n            )\n\n        return md5(\n            pickle.dumps(\n                sorted(_field_tuple(field_name) for field_name in cls.base_vars)\n            )\n        ).hexdigest()\n\n    def _serialize(self) -> bytes:\n        \"\"\"Serialize the state for redis.\n\n        Returns:\n            The serialized state.\n\n        Raises:\n            StateSerializationError: If the state cannot be serialized.\n\n        # noqa: DAR401: e\n        # noqa: DAR402: StateSerializationError\n        \"\"\"\n        payload = b\"\"\n        error = \"\"\n        self_schema = self._to_schema()\n        pickle_function = pickle.dumps\n        try:\n            payload = pickle.dumps((self_schema, self))\n        except HANDLED_PICKLE_ERRORS as og_pickle_error:\n            error = (\n                f\"Failed to serialize state {self.get_full_name()} due to unpicklable object. \"\n                \"This state will not be persisted. \"\n            )\n            try:\n                import dill\n\n                pickle_function = dill.dumps\n                payload = dill.dumps((self_schema, self))\n            except ImportError:\n                error += (\n                    f\"Pickle error: {og_pickle_error}. \"\n                    \"Consider `pip install 'dill>=0.3.8'` for more exotic serialization support.\"\n                )\n            except HANDLED_PICKLE_ERRORS as ex:\n                error += f\"Dill was also unable to pickle the state: {ex}\"\n\n        if environment.REFLEX_PERF_MODE.get() != PerformanceMode.OFF:\n            self._check_state_size(len(payload))\n\n        if not payload:\n            e = StateSerializationError(error)\n            if sys.version_info >= (3, 11):\n                try:\n                    debug_failed_pickles(self, pickle_function)\n                except HANDLED_PICKLE_ERRORS as ex:\n                    for note in ex.__notes__:\n                        e.add_note(note)\n            raise e\n\n        return payload\n\n    @classmethod\n    def _deserialize(\n        cls, data: bytes | None = None, fp: BinaryIO | None = None\n    ) -> BaseState:\n        \"\"\"Deserialize the state from redis/disk.\n\n        data and fp are mutually exclusive, but one must be provided.\n\n        Args:\n            data: The serialized state data.\n            fp: The file pointer to the serialized state data.\n\n        Returns:\n            The deserialized state.\n\n        Raises:\n            ValueError: If both data and fp are provided, or neither are provided.\n            StateSchemaMismatchError: If the state schema does not match the expected schema.\n        \"\"\"\n        if data is not None and fp is None:\n            (substate_schema, state) = pickle.loads(data)\n        elif fp is not None and data is None:\n            (substate_schema, state) = pickle.load(fp)\n        else:\n            msg = \"Only one of `data` or `fp` must be provided\"\n            raise ValueError(msg)\n        if substate_schema != state._to_schema():\n            raise StateSchemaMismatchError\n        return state\n\n\ndef _serialize_type(type_: Any) -> str:\n    \"\"\"Serialize a type.\n\n    Args:\n        type_: The type to serialize.\n\n    Returns:\n        The serialized type.\n    \"\"\"\n    if not isinstance(type_, type):\n        return f\"{type_}\"\n    return f\"{type_.__module__}.{type_.__qualname__}\"\n\n\ndef is_serializable(value: Any) -> bool:\n    \"\"\"Check if a value is serializable.\n\n    Args:\n        value: The value to check.\n\n    Returns:\n        Whether the value is serializable.\n    \"\"\"\n    try:\n        return bool(pickle.dumps(value))\n    except Exception:\n        return False\n\n\nT_STATE = TypeVar(\"T_STATE\", bound=BaseState)\n\n\nclass State(BaseState):\n    \"\"\"The app Base State.\"\"\"\n\n    # The hydrated bool.\n    is_hydrated: bool = False\n    # Maps the state full_name to an arbitrary token it is linked to for shared state.\n    _reflex_internal_links: dict[str, str] | None = None\n\n    @_override_base_method\n    async def _get_state_from_redis(self, state_cls: type[T_STATE]) -> T_STATE:\n        \"\"\"Get a state instance from redis with linking support.\n\n        Args:\n            state_cls: The class of the state.\n\n        Returns:\n            The instance of state_cls associated with this state's client_token.\n        \"\"\"\n        state_instance = await super()._get_state_from_redis(state_cls)\n        if (\n            self._reflex_internal_links\n            and (\n                linked_token := self._reflex_internal_links.get(\n                    state_cls.get_full_name()\n                )\n            )\n            is not None\n            and (\n                internal_patch_linked_state := getattr(\n                    state_instance, \"_internal_patch_linked_state\", None\n                )\n            )\n            is not None\n        ):\n            return await internal_patch_linked_state(linked_token)\n        return state_instance\n\n    @event\n    def set_is_hydrated(self, value: bool) -> None:\n        \"\"\"Set the hydrated state.\n\n        Args:\n            value: The hydrated state.\n        \"\"\"\n        self.is_hydrated = value\n\n\nT = TypeVar(\"T\", bound=BaseState)\n\n\ndef dynamic(func: Callable[[T], Component]):\n    \"\"\"Create a dynamically generated components from a state class.\n\n    Args:\n        func: The function to generate the component.\n\n    Returns:\n        The dynamically generated component.\n\n    Raises:\n        DynamicComponentInvalidSignatureError: If the function does not have exactly one parameter or a type hint for the state class.\n    \"\"\"\n    number_of_parameters = len(inspect.signature(func).parameters)\n\n    func_signature = get_type_hints(func)\n\n    if \"return\" in func_signature:\n        func_signature.pop(\"return\")\n\n    values = list(func_signature.values())\n\n    if number_of_parameters != 1:\n        msg = \"The function must have exactly one parameter, which is the state class.\"\n        raise DynamicComponentInvalidSignatureError(msg)\n\n    if len(values) != 1:\n        msg = \"You must provide a type hint for the state class in the function.\"\n        raise DynamicComponentInvalidSignatureError(msg)\n\n    state_class: type[T] = values[0]\n\n    def wrapper() -> Component:\n        from reflex.components.base.fragment import fragment\n\n        return fragment(state_class._evaluate(lambda state: func(state)))\n\n    return wrapper\n\n\n# sessionStorage key holding the ms timestamp of the last reload on error\nLAST_RELOADED_KEY = \"reflex_last_reloaded_on_error\"\n\n\nclass FrontendEventExceptionState(State):\n    \"\"\"Substate for handling frontend exceptions.\"\"\"\n\n    # If the frontend error message contains any of these strings, automatically reload the page.\n    auto_reload_on_errors: ClassVar[list[re.Pattern]] = [\n        re.compile(  # Chrome/Edge\n            re.escape(\"TypeError: Cannot read properties of null\")\n        ),\n        re.compile(re.escape(\"TypeError: null is not an object\")),  # Safari\n        re.compile(r\"TypeError: can't access property \\\".*\\\" of null\"),  # Firefox\n        # Firefox: property access is on a function that returns null.\n        re.compile(\n            re.escape(\"TypeError: can't access property \\\"\")\n            + r\".*\"\n            + re.escape('\", ')\n            + r\".*\"\n            + re.escape(\" is null\")\n        ),\n    ]\n\n    @event\n    def handle_frontend_exception(\n        self, info: str, component_stack: str\n    ) -> Iterator[EventSpec]:\n        \"\"\"Handle frontend exceptions.\n\n        If a frontend exception handler is provided, it will be called.\n        Otherwise, the default frontend exception handler will be called.\n\n        Args:\n            info: The exception information.\n            component_stack: The stack trace of the component where the exception occurred.\n\n        Yields:\n            Optional auto-reload event for certain errors outside cooldown period.\n        \"\"\"\n        # Handle automatic reload for certain errors.\n        if type(self).auto_reload_on_errors and any(\n            error.search(info) for error in type(self).auto_reload_on_errors\n        ):\n            yield call_script(\n                f\"const last_reload = parseInt(window.sessionStorage.getItem('{LAST_RELOADED_KEY}')) || 0;\"\n                f\"if (Date.now() - last_reload > {environment.REFLEX_AUTO_RELOAD_COOLDOWN_TIME_MS.get()})\"\n                \"{\"\n                f\"window.sessionStorage.setItem('{LAST_RELOADED_KEY}', Date.now().toString());\"\n                \"window.location.reload();\"\n                \"}\"\n            )\n        prerequisites.get_and_validate_app().app.frontend_exception_handler(\n            Exception(info)\n        )\n\n\nclass UpdateVarsInternalState(State):\n    \"\"\"Substate for handling internal state var updates.\"\"\"\n\n    async def update_vars_internal(self, vars: dict[str, Any]) -> None:\n        \"\"\"Apply updates to fully qualified state vars.\n\n        The keys in `vars` should be in the form of `{state.get_full_name()}.{var_name}`,\n        and each value will be set on the appropriate substate instance.\n\n        This function is primarily used to apply cookie and local storage\n        updates from the frontend to the appropriate substate.\n\n        Args:\n            vars: The fully qualified vars and values to update.\n        \"\"\"\n        for var, value in vars.items():\n            state_name, _, var_name = var.rpartition(\".\")\n            var_name = var_name.removesuffix(FIELD_MARKER)\n            var_state_cls = State.get_class_substate(state_name)\n            if var_state_cls._is_client_storage(var_name):\n                var_state = await self.get_state(var_state_cls)\n                setattr(var_state, var_name, value)\n\n\nclass OnLoadInternalState(State):\n    \"\"\"Substate for handling on_load event enumeration.\n\n    This is a separate substate to avoid deserializing the entire state tree for every page navigation.\n    \"\"\"\n\n    # Cannot properly annotate this as `App` due to circular import issues.\n    _app_ref: ClassVar[Any] = None\n\n    def on_load_internal(self) -> list[Event | EventSpec | event.EventCallback] | None:\n        \"\"\"Queue on_load handlers for the current page.\n\n        Returns:\n            The list of events to queue for on load handling.\n\n        Raises:\n            TypeError: If the app reference is not of type App.\n        \"\"\"\n        from reflex.app import App\n\n        app = type(self)._app_ref or prerequisites.get_and_validate_app().app\n        if not isinstance(app, App):\n            msg = (\n                f\"Expected app to be of type {App.__name__}, got {type(app).__name__}.\"\n            )\n            raise TypeError(msg)\n        # Cache the app reference for subsequent calls.\n        if type(self)._app_ref is None:\n            type(self)._app_ref = app\n        load_events = app.get_load_events(self.router.url.path)\n        if not load_events:\n            self.is_hydrated = True\n            return None  # Fast path for navigation with no on_load events defined.\n        self.is_hydrated = False\n        return [\n            *fix_events(\n                cast(list[EventSpec | EventHandler], load_events),\n                self.router.session.client_token,\n                router_data=self.router_data,\n            ),\n            State.set_is_hydrated(True),\n        ]\n\n\nclass ComponentState(State, mixin=True):\n    \"\"\"Base class to allow for the creation of a state instance per component.\n\n    This allows for the bundling of UI and state logic into a single class,\n    where each instance has a separate instance of the state.\n\n    Subclass this class and define vars and event handlers in the traditional way.\n    Then define a `get_component` method that returns the UI for the component instance.\n\n    See the full [docs](https://reflex.dev/docs/state-structure/component-state/) for more.\n\n    Basic example:\n    ```python\n    # Subclass ComponentState and define vars and event handlers.\n    class Counter(rx.ComponentState):\n        # Define vars that change.\n        count: int = 0\n\n        # Define event handlers.\n        def increment(self):\n            self.count += 1\n\n        def decrement(self):\n            self.count -= 1\n\n        @classmethod\n        def get_component(cls, **props):\n            # Access the state vars and event handlers using `cls`.\n            return rx.hstack(\n                rx.button(\"Decrement\", on_click=cls.decrement),\n                rx.text(cls.count),\n                rx.button(\"Increment\", on_click=cls.increment),\n                **props,\n            )\n\n    counter = Counter.create()\n    ```\n    \"\"\"\n\n    # The number of components created from this class.\n    _per_component_state_instance_count: ClassVar[int] = 0\n\n    def __init__(self, *args, **kwargs):\n        \"\"\"Do not allow direct initialization of the ComponentState.\n\n        Args:\n            *args: The args to pass to the State init method.\n            **kwargs: The kwargs to pass to the State init method.\n\n        Raises:\n            ReflexRuntimeError: If the ComponentState is initialized directly.\n        \"\"\"\n        if self._mixin:\n            raise ReflexRuntimeError(\n                f\"{ComponentState.__name__} {type(self).__name__} is not meant to be initialized directly. \"\n                + \"Use the `create` method to create a new instance and access the state via the `State` attribute.\"\n            )\n        super().__init__(*args, **kwargs)\n\n    @classmethod\n    def __init_subclass__(cls, mixin: bool = True, **kwargs):\n        \"\"\"Overwrite mixin default to True.\n\n        Args:\n            mixin: Whether the subclass is a mixin and should not be initialized.\n            **kwargs: The kwargs to pass to the init_subclass method.\n        \"\"\"\n        super().__init_subclass__(mixin=mixin, **kwargs)\n\n    @classmethod\n    def get_component(cls, *children, **props) -> Component:\n        \"\"\"Get the component instance.\n\n        Args:\n            children: The children of the component.\n            props: The props of the component.\n\n        Raises:\n            NotImplementedError: if the subclass does not override this method.\n        \"\"\"\n        msg = f\"{cls.__name__} must implement get_component to return the component instance.\"\n        raise NotImplementedError(msg)\n\n    @classmethod\n    def create(cls, *children, **props) -> Component:\n        \"\"\"Create a new instance of the Component.\n\n        Args:\n            children: The children of the component.\n            props: The props of the component.\n\n        Returns:\n            A new instance of the Component with an independent copy of the State.\n        \"\"\"\n        from reflex.compiler.compiler import into_component\n\n        cls._per_component_state_instance_count += 1\n        state_cls_name = f\"{cls.__name__}_n{cls._per_component_state_instance_count}\"\n        component_state = type(\n            state_cls_name,\n            (cls, State),\n            {\"__module__\": reflex.istate.dynamic.__name__},\n            mixin=False,\n        )\n        # Save a reference to the dynamic state for pickle/unpickle.\n        setattr(reflex.istate.dynamic, state_cls_name, component_state)\n        component = component_state.get_component(*children, **props)\n        component = into_component(component)\n        component.State = component_state\n        return component\n\n\n@dataclasses.dataclass(\n    frozen=True,\n)\nclass StateUpdate:\n    \"\"\"A state update sent to the frontend.\"\"\"\n\n    # The state delta.\n    delta: Delta = dataclasses.field(default_factory=dict)\n\n    # Events to be added to the event queue.\n    events: list[Event] = dataclasses.field(default_factory=list)\n\n    # Whether this is the final state update for the event.\n    final: bool | None = True\n\n    def json(self) -> str:\n        \"\"\"Convert the state update to a JSON string.\n\n        Returns:\n            The state update as a JSON string.\n        \"\"\"\n        return format.json_dumps(self)\n\n\ndef code_uses_state_contexts(javascript_code: str) -> bool:\n    \"\"\"Check if the rendered Javascript uses state contexts.\n\n    Args:\n        javascript_code: The Javascript code to check.\n\n    Returns:\n        True if the code attempts to access a member of StateContexts.\n    \"\"\"\n    return bool(\"useContext(StateContexts\" in javascript_code)\n\n\ndef reload_state_module(\n    module: str,\n    state: type[BaseState] = State,\n) -> None:\n    \"\"\"Reset rx.State subclasses to avoid conflict when reloading.\n\n    Args:\n        module: The module to reload.\n        state: Recursive argument for the state class to reload.\n\n    \"\"\"\n    # Reset the _app_ref of OnLoadInternalState to avoid stale references.\n    if state is OnLoadInternalState:\n        state._app_ref = None\n    # Clean out all potentially dirty states of reloaded modules.\n    for pd_state in tuple(state._potentially_dirty_states):\n        with contextlib.suppress(ValueError):\n            if (\n                state.get_root_state().get_class_substate(pd_state).__module__ == module\n                and module is not None\n            ):\n                state._potentially_dirty_states.remove(pd_state)\n    for subclass in tuple(state.class_subclasses):\n        reload_state_module(module=module, state=subclass)\n        if subclass.__module__ == module and module is not None:\n            all_base_state_classes.pop(subclass.get_full_name(), None)\n            state.class_subclasses.remove(subclass)\n            state._always_dirty_substates.discard(subclass.get_name())\n            state._var_dependencies = {}\n            state._init_var_dependency_dicts()\n    state.get_class_substate.cache_clear()\n\n\nfrom reflex.istate.manager import StateManager as StateManager  # noqa: E402\nfrom reflex.istate.manager import get_state_manager as get_state_manager  # noqa: E402\nfrom reflex.istate.manager import (  # noqa: E402\n    reset_disk_state_manager as reset_disk_state_manager,\n)\n"
  },
  {
    "path": "reflex/style.py",
    "content": "\"\"\"Handle styling.\"\"\"\n\nfrom __future__ import annotations\n\nfrom collections.abc import Mapping\nfrom typing import Any, Literal\n\nfrom reflex import constants\nfrom reflex.components.core.breakpoints import Breakpoints, breakpoints_values\nfrom reflex.event import EventChain, EventHandler, EventSpec, run_script\nfrom reflex.utils import format\nfrom reflex.utils.exceptions import ReflexError\nfrom reflex.utils.imports import ImportVar\nfrom reflex.utils.types import typehint_issubclass\nfrom reflex.vars import VarData\nfrom reflex.vars.base import LiteralVar, Var\nfrom reflex.vars.function import FunctionVar\nfrom reflex.vars.object import ObjectVar\n\nSYSTEM_COLOR_MODE: str = \"system\"\nLIGHT_COLOR_MODE: str = \"light\"\nDARK_COLOR_MODE: str = \"dark\"\nLiteralColorMode = Literal[\"system\", \"light\", \"dark\"]\n\n# Reference the global ColorModeContext\ncolor_mode_imports = {\n    f\"$/{constants.Dirs.CONTEXTS_PATH}\": [ImportVar(tag=\"ColorModeContext\")],\n    \"react\": [ImportVar(tag=\"useContext\")],\n}\n\n\ndef _color_mode_var(_js_expr: str, _var_type: type = str) -> Var:\n    \"\"\"Create a Var that destructs the _js_expr from ColorModeContext.\n\n    Args:\n        _js_expr: The name of the variable to get from ColorModeContext.\n        _var_type: The type of the Var.\n\n    Returns:\n        The Var that resolves to the color mode.\n    \"\"\"\n    return Var(\n        _js_expr=_js_expr,\n        _var_type=_var_type,\n        _var_data=VarData(\n            imports=color_mode_imports,\n            hooks={f\"const {{ {_js_expr} }} = useContext(ColorModeContext)\": None},\n        ),\n    ).guess_type()\n\n\ndef set_color_mode(\n    new_color_mode: LiteralColorMode | Var[LiteralColorMode],\n) -> EventSpec:\n    \"\"\"Create an EventSpec Var that sets the color mode to a specific value.\n\n    Note: `set_color_mode` is not a real event and cannot be triggered from a\n    backend event handler.\n\n    Args:\n        new_color_mode: The color mode to set.\n\n    Returns:\n        The EventSpec Var that can be passed to an event trigger.\n    \"\"\"\n    base_setter = _color_mode_var(\n        _js_expr=constants.ColorMode.SET,\n    ).to(FunctionVar)\n\n    return run_script(\n        base_setter.call(new_color_mode),\n    )\n\n\n# Var resolves to the current color mode for the app (\"light\", \"dark\" or \"system\")\ncolor_mode = _color_mode_var(_js_expr=constants.ColorMode.NAME)\n# Var resolves to the resolved color mode for the app (\"light\" or \"dark\")\nresolved_color_mode = _color_mode_var(_js_expr=constants.ColorMode.RESOLVED_NAME)\n# Var resolves to a function invocation that toggles the color mode\ntoggle_color_mode = _color_mode_var(\n    _js_expr=constants.ColorMode.TOGGLE,\n    _var_type=EventChain,\n)\n\nSTYLE_PROP_SHORTHAND_MAPPING = {\n    \"paddingX\": (\"paddingInlineStart\", \"paddingInlineEnd\"),\n    \"paddingY\": (\"paddingTop\", \"paddingBottom\"),\n    \"marginX\": (\"marginInlineStart\", \"marginInlineEnd\"),\n    \"marginY\": (\"marginTop\", \"marginBottom\"),\n    \"bg\": (\"background\",),\n    \"bgColor\": (\"backgroundColor\",),\n    # Radix components derive their font from this CSS var, not inherited from body or class.\n    \"fontFamily\": (\"fontFamily\", \"--default-font-family\"),\n}\n\n\ndef media_query(breakpoint_expr: str):\n    \"\"\"Create a media query selector.\n\n    Args:\n        breakpoint_expr: The CSS expression representing the breakpoint.\n\n    Returns:\n        The media query selector used as a key in emotion css dict.\n    \"\"\"\n    return f\"@media screen and (min-width: {breakpoint_expr})\"\n\n\ndef convert_item(\n    style_item: int | str | Var,\n) -> tuple[str | Var, VarData | None]:\n    \"\"\"Format a single value in a style dictionary.\n\n    Args:\n        style_item: The style item to format.\n\n    Returns:\n        The formatted style item and any associated VarData.\n\n    Raises:\n        ReflexError: If an EventHandler is used as a style value\n    \"\"\"\n    from reflex.components.component import BaseComponent\n\n    if isinstance(style_item, (EventHandler, BaseComponent)):\n        msg = (\n            f\"{type(style_item)} cannot be used as style values. \"\n            \"Please use a Var or a literal value.\"\n        )\n        raise ReflexError(msg)\n\n    if isinstance(style_item, Var):\n        return style_item, style_item._get_all_var_data()\n\n    # Otherwise, convert to Var to collapse VarData encoded in f-string.\n    new_var = LiteralVar.create(style_item)\n    var_data = new_var._get_all_var_data() if new_var is not None else None\n    return new_var, var_data\n\n\ndef convert_list(\n    responsive_list: list[str | dict | Var],\n) -> tuple[list[str | dict[str, Var | list | dict]], VarData | None]:\n    \"\"\"Format a responsive value list.\n\n    Args:\n        responsive_list: The raw responsive value list (one value per breakpoint).\n\n    Returns:\n        The recursively converted responsive value list and any associated VarData.\n    \"\"\"\n    converted_value = []\n    item_var_datas = []\n    for responsive_item in responsive_list:\n        if isinstance(responsive_item, dict):\n            # Recursively format nested style dictionaries.\n            item, item_var_data = convert(responsive_item)\n        else:\n            item, item_var_data = convert_item(responsive_item)\n        converted_value.append(item)\n        item_var_datas.append(item_var_data)\n    return converted_value, VarData.merge(*item_var_datas)\n\n\ndef convert(\n    style_dict: dict[str, Var | dict | list | str],\n) -> tuple[dict[str, str | list | dict], VarData | None]:\n    \"\"\"Format a style dictionary.\n\n    Args:\n        style_dict: The style dictionary to format.\n\n    Returns:\n        The formatted style dictionary.\n    \"\"\"\n    var_data = None  # Track import/hook data from any Vars in the style dict.\n    out = {}\n\n    def update_out_dict(\n        return_value: Var | dict | list | str, keys_to_update: tuple[str, ...]\n    ):\n        for k in keys_to_update:\n            out[k] = return_value\n\n    for key, value in style_dict.items():\n        keys = (\n            format_style_key(key)\n            if not isinstance(value, (dict, ObjectVar, list))\n            or (\n                isinstance(value, Breakpoints)\n                and all(not isinstance(v, dict) for v in value.values())\n            )\n            or (isinstance(value, list) and all(not isinstance(v, dict) for v in value))\n            or (\n                isinstance(value, ObjectVar)\n                and not typehint_issubclass(value._var_type, Mapping)\n            )\n            else (key,)\n        )\n\n        if isinstance(value, Var):\n            return_val = value\n            new_var_data = value._get_all_var_data()\n            update_out_dict(return_val, keys)\n        elif isinstance(value, dict):\n            # Recursively format nested style dictionaries.\n            return_val, new_var_data = convert(value)\n            update_out_dict(return_val, keys)\n        elif isinstance(value, list):\n            # Responsive value is a list of dict or value\n            return_val, new_var_data = convert_list(value)\n            update_out_dict(return_val, keys)\n        else:\n            return_val, new_var_data = convert_item(value)\n            update_out_dict(return_val, keys)\n        # Combine all the collected VarData instances.\n        var_data = VarData.merge(var_data, new_var_data)\n\n    if isinstance(style_dict, Breakpoints):\n        out = Breakpoints(out).factorize()\n\n    return out, var_data\n\n\ndef format_style_key(key: str) -> tuple[str, ...]:\n    \"\"\"Convert style keys to camel case and convert shorthand\n    styles names to their corresponding css names.\n\n    Args:\n        key: The style key to convert.\n\n    Returns:\n        Tuple of css style names corresponding to the key provided.\n    \"\"\"\n    if key.startswith(\"--\"):\n        return (key,)\n    key = format.to_camel_case(key)\n    return STYLE_PROP_SHORTHAND_MAPPING.get(key, (key,))\n\n\nEMPTY_VAR_DATA = VarData()\n\n\nclass Style(dict[str, Any]):\n    \"\"\"A style dictionary.\"\"\"\n\n    def __init__(self, style_dict: dict[str, Any] | None = None, **kwargs):\n        \"\"\"Initialize the style.\n\n        Args:\n            style_dict: The style dictionary.\n            kwargs: Other key value pairs to apply to the dict update.\n        \"\"\"\n        if style_dict:\n            style_dict.update(kwargs)\n        else:\n            style_dict = kwargs\n        if style_dict:\n            style_dict, self._var_data = convert(style_dict)\n        else:\n            self._var_data = EMPTY_VAR_DATA\n        super().__init__(style_dict)\n\n    def update(self, style_dict: dict | None, **kwargs):\n        \"\"\"Update the style.\n\n        Args:\n            style_dict: The style dictionary.\n            kwargs: Other key value pairs to apply to the dict update.\n        \"\"\"\n        if not isinstance(style_dict, Style):\n            converted_dict = type(self)(style_dict)\n        else:\n            converted_dict = style_dict\n        if kwargs:\n            if converted_dict is None:\n                converted_dict = type(self)(kwargs)\n            else:\n                converted_dict.update(kwargs)\n        # Combine our VarData with that of any Vars in the style_dict that was passed.\n        self._var_data = VarData.merge(self._var_data, converted_dict._var_data)\n        super().update(converted_dict)\n\n    def __setitem__(self, key: str, value: Any):\n        \"\"\"Set an item in the style.\n\n        Args:\n            key: The key to set.\n            value: The value to set.\n        \"\"\"\n        # Create a Var to collapse VarData encoded in f-string.\n        var = LiteralVar.create(value)\n        if var is not None:\n            # Carry the imports/hooks when setting a Var as a value.\n            self._var_data = VarData.merge(\n                getattr(self, \"_var_data\", None), var._get_all_var_data()\n            )\n        super().__setitem__(key, value)\n\n    def __or__(self, other: Style | dict) -> Style:\n        \"\"\"Combine two styles.\n\n        Args:\n            other: The other style to combine.\n\n        Returns:\n            The combined style.\n        \"\"\"\n        other_var_data = None\n        if not isinstance(other, Style):\n            other_dict, other_var_data = convert(other)\n        else:\n            other_dict, other_var_data = other, other._var_data\n\n        new_style = Style(super().__or__(other_dict))\n        if self._var_data or other_var_data:\n            new_style._var_data = VarData.merge(self._var_data, other_var_data)\n        return new_style\n\n\ndef _format_emotion_style_pseudo_selector(key: str) -> str:\n    \"\"\"Format a pseudo selector for emotion CSS-in-JS.\n\n    Args:\n        key: Underscore-prefixed or colon-prefixed pseudo selector key (_hover/:hover).\n\n    Returns:\n        A self-referential pseudo selector key (&:hover).\n    \"\"\"\n    prefix = None\n    if key.startswith(\"_\"):\n        prefix = \"&:\"\n        key = key[1:]\n    if key.startswith(\":\"):\n        # Handle pseudo selectors and elements in native format.\n        prefix = \"&\"\n    if prefix is not None:\n        return prefix + format.to_kebab_case(key)\n    return key\n\n\ndef format_as_emotion(style_dict: dict[str, Any]) -> Style | None:\n    \"\"\"Convert the style to an emotion-compatible CSS-in-JS dict.\n\n    Args:\n        style_dict: The style dict to convert.\n\n    Returns:\n        The emotion style dict.\n    \"\"\"\n    var_data = style_dict._var_data if isinstance(style_dict, Style) else None\n\n    emotion_style = Style()\n\n    for orig_key, value in style_dict.items():\n        key = _format_emotion_style_pseudo_selector(orig_key)\n        if isinstance(value, (Breakpoints, list)):\n            if isinstance(value, Breakpoints):\n                mbps = {\n                    media_query(bp): (\n                        bp_value if isinstance(bp_value, dict) else {key: bp_value}\n                    )\n                    for bp, bp_value in value.items()\n                }\n            else:\n                # Apply media queries from responsive value list.\n                mbps = {\n                    media_query([0, *breakpoints_values][bp]): (\n                        bp_value if isinstance(bp_value, dict) else {key: bp_value}\n                    )\n                    for bp, bp_value in enumerate(value)\n                }\n            if key.startswith(\"&:\"):\n                emotion_style[key] = mbps\n            else:\n                for mq, style_sub_dict in mbps.items():\n                    emotion_style.setdefault(mq, {}).update(style_sub_dict)\n        elif isinstance(value, dict):\n            # Recursively format nested style dictionaries.\n            emotion_style[key] = format_as_emotion(value)\n        else:\n            emotion_style[key] = value\n    if emotion_style:\n        if var_data is not None:\n            emotion_style._var_data = VarData.merge(emotion_style._var_data, var_data)\n        return emotion_style\n    return None\n\n\ndef convert_dict_to_style_and_format_emotion(\n    raw_dict: dict[str, Any],\n) -> dict[str, Any] | None:\n    \"\"\"Convert a dict to a style dict and then format as emotion.\n\n    Args:\n        raw_dict: The dict to convert.\n\n    Returns:\n        The emotion dict.\n\n    \"\"\"\n    return format_as_emotion(Style(raw_dict))\n\n\nSTACK_CHILDREN_FULL_WIDTH = {\n    \"& :where(.rx-Stack)\": {\n        \"width\": \"100%\",\n    },\n    \"& :where(.rx-Stack) > :where( \"\n    \"div:not(.rt-Box, .rx-Upload, .rx-Html),\"\n    \"input, select, textarea, table\"\n    \")\": {\n        \"width\": \"100%\",\n        \"flex_shrink\": \"1\",\n    },\n}\n"
  },
  {
    "path": "reflex/testing.py",
    "content": "\"\"\"reflex.testing - tools for testing reflex apps.\"\"\"\n\nfrom __future__ import annotations\n\nimport asyncio\nimport contextlib\nimport dataclasses\nimport functools\nimport inspect\nimport os\nimport platform\nimport re\nimport signal\nimport socket\nimport socketserver\nimport subprocess\nimport sys\nimport textwrap\nimport threading\nimport time\nimport types\nfrom collections.abc import AsyncIterator, Callable, Coroutine, Sequence\nfrom http.server import SimpleHTTPRequestHandler\nfrom importlib.util import find_spec\nfrom pathlib import Path\nfrom typing import TYPE_CHECKING, Any, Literal, TypeVar\n\nimport uvicorn\nfrom typing_extensions import Self\n\nimport reflex\nimport reflex.reflex\nimport reflex.utils.build\nimport reflex.utils.format\nimport reflex.utils.prerequisites\nimport reflex.utils.processes\nfrom reflex.components.component import CustomComponent\nfrom reflex.config import get_config\nfrom reflex.environment import environment\nfrom reflex.istate.manager.disk import StateManagerDisk\nfrom reflex.istate.manager.memory import StateManagerMemory\nfrom reflex.istate.manager.redis import StateManagerRedis\nfrom reflex.state import (\n    BaseState,\n    StateManager,\n    _split_substate_key,\n    reload_state_module,\n)\nfrom reflex.utils import console, js_runtimes\nfrom reflex.utils.export import export\nfrom reflex.utils.token_manager import TokenManager\nfrom reflex.utils.types import ASGIApp\n\ntry:\n    from selenium import webdriver\n    from selenium.webdriver.remote.webdriver import WebDriver\n\n    if TYPE_CHECKING:\n        from selenium.webdriver.common.options import ArgOptions\n        from selenium.webdriver.remote.webelement import WebElement\n\n    has_selenium = True\nexcept ImportError:\n    has_selenium = False\n\n# The timeout (minutes) to check for the port.\nDEFAULT_TIMEOUT = 15\nPOLL_INTERVAL = 0.25\nFRONTEND_POPEN_ARGS = {}\nT = TypeVar(\"T\")\nTimeoutType = int | float | None\nif platform.system() == \"Windows\":\n    FRONTEND_POPEN_ARGS[\"creationflags\"] = subprocess.CREATE_NEW_PROCESS_GROUP  # pyright: ignore [reportAttributeAccessIssue]\n    FRONTEND_POPEN_ARGS[\"shell\"] = True\nelse:\n    FRONTEND_POPEN_ARGS[\"start_new_session\"] = True\n\n\n# borrowed from py3.11\nclass chdir(contextlib.AbstractContextManager):  # noqa: N801\n    \"\"\"Non thread-safe context manager to change the current working directory.\"\"\"\n\n    def __init__(self, path: str | Path):\n        \"\"\"Prepare contextmanager.\n\n        Args:\n            path: the path to change to\n        \"\"\"\n        self.path = path\n        self._old_cwd = []\n\n    def __enter__(self):\n        \"\"\"Save current directory and perform chdir.\"\"\"\n        self._old_cwd.append(Path.cwd())\n        os.chdir(self.path)\n\n    def __exit__(self, *excinfo):\n        \"\"\"Change back to previous directory on stack.\n\n        Args:\n            excinfo: sys.exc_info captured in the context block\n        \"\"\"\n        os.chdir(self._old_cwd.pop())\n\n\n@dataclasses.dataclass\nclass AppHarness:\n    \"\"\"AppHarness executes a reflex app in-process for testing.\"\"\"\n\n    app_name: str\n    app_source: (\n        Callable[[], None] | types.ModuleType | str | functools.partial[Any] | None\n    )\n    app_path: Path\n    app_module_path: Path\n    app_module: types.ModuleType | None = None\n    app_instance: reflex.App | None = None\n    app_asgi: ASGIApp | None = None\n    frontend_process: subprocess.Popen | None = None\n    frontend_url: str | None = None\n    frontend_output_thread: threading.Thread | None = None\n    backend_thread: threading.Thread | None = None\n    backend: uvicorn.Server | None = None\n    state_manager: StateManager | None = None\n    _frontends: list[WebDriver] = dataclasses.field(default_factory=list)\n\n    @classmethod\n    def create(\n        cls,\n        root: Path,\n        app_source: (\n            Callable[[], None] | types.ModuleType | str | functools.partial[Any] | None\n        ) = None,\n        app_name: str | None = None,\n    ) -> Self:\n        \"\"\"Create an AppHarness instance at root.\n\n        Args:\n            root: the directory that will contain the app under test.\n            app_source: if specified, the source code from this function or module is used\n                as the main module for the app. It may also be the raw source code text, as a str.\n                If unspecified, then root must already contain a working reflex app and will be used directly.\n            app_name: provide the name of the app, otherwise will be derived from app_source or root.\n\n        Returns:\n            AppHarness instance\n\n        Raises:\n            ValueError: when app_source is a string and app_name is not provided.\n        \"\"\"\n        if app_name is None:\n            if app_source is None:\n                app_name = root.name\n            elif isinstance(app_source, functools.partial):\n                keywords = app_source.keywords\n                slug_suffix = \"_\".join([str(v) for v in keywords.values()])\n                func_name = app_source.func.__name__\n                app_name = f\"{func_name}_{slug_suffix}\"\n                app_name = re.sub(r\"[^a-zA-Z0-9_]\", \"_\", app_name)\n            elif isinstance(app_source, str):\n                msg = \"app_name must be provided when app_source is a string.\"\n                raise ValueError(msg)\n            else:\n                app_name = app_source.__name__\n\n            app_name = app_name.lower()\n            while \"__\" in app_name:\n                app_name = app_name.replace(\"__\", \"_\")\n        return cls(\n            app_name=app_name,\n            app_source=app_source,\n            app_path=root,\n            app_module_path=root / app_name / f\"{app_name}.py\",\n        )\n\n    def get_state_name(self, state_cls_name: str) -> str:\n        \"\"\"Get the state name for the given state class name.\n\n        Args:\n            state_cls_name: The state class name\n\n        Returns:\n            The state name\n        \"\"\"\n        return reflex.utils.format.to_snake_case(\n            f\"{self.app_name}___{self.app_name}___\" + state_cls_name\n        )\n\n    def get_full_state_name(self, path: list[str]) -> str:\n        \"\"\"Get the full state name for the given state class name.\n\n        Args:\n            path: A list of state class names\n\n        Returns:\n            The full state name\n        \"\"\"\n        # NOTE: using State.get_name() somehow causes trouble here\n        # path = [State.get_name()] + [self.get_state_name(p) for p in path] # noqa: ERA001\n        path = [\"reflex___state____state\"] + [self.get_state_name(p) for p in path]\n        return \".\".join(path)\n\n    def _get_globals_from_signature(self, func: Any) -> dict[str, Any]:\n        \"\"\"Get the globals from a function or module object.\n\n        Args:\n            func: function or module object\n\n        Returns:\n            dict of globals\n        \"\"\"\n        overrides = {}\n        glbs = {}\n        if not callable(func):\n            return glbs\n        if isinstance(func, functools.partial):\n            overrides = func.keywords\n            func = func.func\n        for param in inspect.signature(func).parameters.values():\n            if param.default is not inspect.Parameter.empty:\n                glbs[param.name] = param.default\n        glbs.update(overrides)\n        return glbs\n\n    def _get_source_from_app_source(self, app_source: Any) -> str:\n        \"\"\"Get the source from app_source.\n\n        Args:\n            app_source: function or module or str\n\n        Returns:\n            source code\n        \"\"\"\n        if isinstance(app_source, str):\n            return app_source\n        source = inspect.getsource(app_source)\n        source = re.sub(\n            r\"^\\s*def\\s+\\w+\\s*\\(.*?\\)(\\s+->\\s+\\w+)?:\", \"\", source, flags=re.DOTALL\n        )\n        return textwrap.dedent(source)\n\n    def _initialize_app(self):\n        # disable telemetry reporting for tests\n\n        os.environ[\"REFLEX_TELEMETRY_ENABLED\"] = \"false\"\n        CustomComponent.create().get_component.cache_clear()\n        self.app_path.mkdir(parents=True, exist_ok=True)\n        if self.app_source is not None:\n            app_globals = self._get_globals_from_signature(self.app_source)\n            if isinstance(self.app_source, functools.partial):\n                self.app_source = self.app_source.func\n            # get the source from a function or module object\n            source_code = \"\\n\".join([\n                \"\\n\".join([\n                    self.get_app_global_source(k, v) for k, v in app_globals.items()\n                ]),\n                self._get_source_from_app_source(self.app_source),\n            ])\n            get_config().loglevel = reflex.constants.LogLevel.INFO\n            with chdir(self.app_path):\n                reflex.reflex._init(\n                    name=self.app_name,\n                    template=reflex.constants.Templates.DEFAULT,\n                )\n                self.app_module_path.write_text(source_code)\n        else:\n            # Just initialize the web folder.\n            with chdir(self.app_path):\n                reflex.utils.prerequisites.initialize_frontend_dependencies()\n        with chdir(self.app_path):\n            # ensure config and app are reloaded when testing different app\n            reflex.config.get_config(reload=True)\n            # Ensure the AppHarness test does not skip State assignment due to running via pytest\n            os.environ.pop(reflex.constants.PYTEST_CURRENT_TEST, None)\n            os.environ[reflex.constants.APP_HARNESS_FLAG] = \"true\"\n            # Ensure we actually compile the app during first initialization.\n            self.app_instance, self.app_module = (\n                reflex.utils.prerequisites.get_and_validate_app(\n                    # Do not reload the module for pre-existing apps (only apps generated from source)\n                    reload=self.app_source is not None\n                )\n            )\n            self.app_asgi = self.app_instance()\n        if self.app_instance and self.app_instance._state_manager is not None:\n            if self.app_instance._state is None:\n                msg = \"State is not set.\"\n                raise RuntimeError(msg)\n            if isinstance(self.app_instance._state_manager, StateManagerRedis):\n                # Create our own redis connection for testing.\n                self.state_manager = StateManagerRedis.create(self.app_instance._state)\n            elif isinstance(self.app_instance._state_manager, StateManagerDisk):\n                self.state_manager = StateManagerDisk.create(self.app_instance._state)\n        if self.state_manager is None:\n            self.state_manager = (\n                self.app_instance._state_manager if self.app_instance else None\n            )\n\n    def _reload_state_module(self):\n        \"\"\"Reload the rx.State module to avoid conflict when reloading.\"\"\"\n        reload_state_module(module=f\"{self.app_name}.{self.app_name}\")\n\n    def _get_backend_shutdown_handler(self):\n        if self.backend is None:\n            msg = \"Backend was not initialized.\"\n            raise RuntimeError(msg)\n\n        original_shutdown = self.backend.shutdown\n\n        async def _shutdown(*args, **kwargs) -> None:\n            # ensure redis is closed before event loop\n            if (\n                self.app_instance is not None\n                and self.app_instance._state_manager is not None\n            ):\n                with contextlib.suppress(ValueError):\n                    await self.app_instance._state_manager.close()\n\n            # socketio shutdown handler\n            if self.app_instance is not None and self.app_instance.sio is not None:\n                with contextlib.suppress(TypeError):\n                    await self.app_instance.sio.shutdown()\n\n            # sqlalchemy async engine shutdown handler\n            if find_spec(\"sqlmodel\"):\n                try:\n                    async_engine = reflex.model.get_async_engine(None)\n                except ValueError:\n                    pass\n                else:\n                    await async_engine.dispose()\n\n            await original_shutdown(*args, **kwargs)\n\n        return _shutdown\n\n    def _start_backend(self, port: int = 0):\n        if self.app_asgi is None:\n            msg = \"App was not initialized.\"\n            raise RuntimeError(msg)\n        self.backend = uvicorn.Server(\n            uvicorn.Config(\n                app=self.app_asgi,\n                host=\"127.0.0.1\",\n                port=port,\n            )\n        )\n        self.backend.shutdown = self._get_backend_shutdown_handler()\n        with chdir(self.app_path):\n            print(  # noqa: T201\n                \"Creating backend in a new thread...\"\n            )  # for pytest diagnosis\n            self.backend_thread = threading.Thread(target=self.backend.run)\n        self.backend_thread.start()\n        print(\"Backend started.\")  # for pytest diagnosis #noqa: T201\n\n    async def _reset_backend_state_manager(self):\n        \"\"\"Reset the StateManagerRedis event loop affinity.\n\n        This is necessary when the backend is restarted and the state manager is a\n        StateManagerRedis instance.\n\n        Raises:\n            RuntimeError: when the state manager cannot be reset\n        \"\"\"\n        if (\n            self.app_instance is not None\n            and self.app_instance._state_manager is not None\n        ):\n            with contextlib.suppress(RuntimeError):\n                await self.app_instance._state_manager.close()\n        if (\n            self.app_instance is not None\n            and isinstance(\n                self.app_instance._state_manager,\n                StateManagerRedis,\n            )\n            and self.app_instance._state is not None\n        ):\n            self.app_instance._state_manager = StateManagerRedis.create(\n                state=self.app_instance._state,\n            )\n            if not isinstance(self.app_instance.state_manager, StateManagerRedis):\n                msg = \"Failed to reset state manager.\"\n                raise RuntimeError(msg)\n\n            # Also reset the TokenManager to avoid loop affinity issues\n            if (\n                hasattr(self.app_instance, \"event_namespace\")\n                and self.app_instance.event_namespace is not None\n                and hasattr(self.app_instance.event_namespace, \"_token_manager\")\n            ):\n                # Import here to avoid circular imports\n                from reflex.utils.token_manager import TokenManager\n\n                self.app_instance.event_namespace._token_manager = TokenManager.create()\n\n    def _start_frontend(self):\n        # Set up the frontend.\n        with chdir(self.app_path):\n            config = reflex.config.get_config()\n            print(\"Polling for servers...\")  # for pytest diagnosis #noqa: T201\n            config.api_url = \"http://{}:{}\".format(\n                *self._poll_for_servers(timeout=30).getsockname(),\n            )\n            print(\"Building frontend...\")  # for pytest diagnosis #noqa: T201\n            reflex.utils.build.setup_frontend(self.app_path)\n\n        print(\"Frontend starting...\")  # for pytest diagnosis #noqa: T201\n\n        # Start the frontend.\n        self.frontend_process = reflex.utils.processes.new_process(\n            [\n                *js_runtimes.get_js_package_executor(raise_on_none=True)[0],\n                \"run\",\n                \"dev\",\n            ],\n            cwd=self.app_path / reflex.utils.prerequisites.get_web_dir(),\n            env={\"PORT\": \"0\", \"NO_COLOR\": \"1\"},\n            **FRONTEND_POPEN_ARGS,\n        )\n\n    def _wait_frontend(self):\n        if self.frontend_process is None or self.frontend_process.stdout is None:\n            msg = \"Frontend process has no stdout.\"\n            raise RuntimeError(msg)\n        while self.frontend_url is None:\n            line = self.frontend_process.stdout.readline()\n            if not line:\n                break\n            print(line)  # for pytest diagnosis #noqa: T201\n            m = re.search(reflex.constants.ReactRouter.FRONTEND_LISTENING_REGEX, line)\n            if m is not None:\n                self.frontend_url = m.group(1)\n                config = reflex.config.get_config()\n                config.deploy_url = self.frontend_url\n                break\n        if self.frontend_url is None:\n            msg = \"Frontend did not start\"\n            raise RuntimeError(msg)\n\n        def consume_frontend_output():\n            while True:\n                try:\n                    line = (\n                        self.frontend_process.stdout.readline()  # pyright: ignore [reportOptionalMemberAccess]\n                    )\n                # catch I/O operation on closed file.\n                except ValueError as e:\n                    console.error(str(e))\n                    break\n                if not line:\n                    break\n\n        self.frontend_output_thread = threading.Thread(target=consume_frontend_output)\n        self.frontend_output_thread.start()\n\n    def start(self) -> Self:\n        \"\"\"Start the backend in a new thread and dev frontend as a separate process.\n\n        Returns:\n            self\n        \"\"\"\n        self._initialize_app()\n        self._start_backend()\n        self._start_frontend()\n        self._wait_frontend()\n        return self\n\n    @staticmethod\n    def get_app_global_source(key: str, value: Any):\n        \"\"\"Get the source code of a global object.\n        If value is a function or class we render the actual\n        source of value otherwise we assign value to key.\n\n        Args:\n            key: variable name to assign value to.\n            value: value of the global variable.\n\n        Returns:\n            The rendered app global code.\n        \"\"\"\n        if not isinstance(value, type) and not inspect.isfunction(value):\n            return f\"{key} = {value!r}\"\n        return inspect.getsource(value)\n\n    def __enter__(self) -> Self:\n        \"\"\"Contextmanager protocol for `start()`.\n\n        Returns:\n            Instance of AppHarness after calling start()\n        \"\"\"\n        return self.start()\n\n    def stop(self) -> None:\n        \"\"\"Stop the frontend and backend servers.\"\"\"\n        import psutil\n\n        # Quit browsers first to avoid any lingering events being sent during shutdown.\n        for driver in self._frontends:\n            driver.quit()\n\n        self._reload_state_module()\n\n        if self.backend is not None:\n            self.backend.should_exit = True\n        if self.frontend_process is not None:\n            # https://stackoverflow.com/a/70565806\n            frontend_children = psutil.Process(self.frontend_process.pid).children(\n                recursive=True,\n            )\n            if sys.platform == \"win32\":\n                self.frontend_process.terminate()\n            else:\n                pgrp = os.getpgid(self.frontend_process.pid)\n                os.killpg(pgrp, signal.SIGTERM)\n            # kill any remaining child processes\n            for child in frontend_children:\n                # It's okay if the process is already gone.\n                with contextlib.suppress(psutil.NoSuchProcess):\n                    child.terminate()\n            _, still_alive = psutil.wait_procs(frontend_children, timeout=3)\n            for child in still_alive:\n                # It's okay if the process is already gone.\n                with contextlib.suppress(psutil.NoSuchProcess):\n                    child.kill()\n            # wait for main process to exit\n            self.frontend_process.communicate()\n        if self.backend_thread is not None:\n            self.backend_thread.join()\n        if self.frontend_output_thread is not None:\n            self.frontend_output_thread.join()\n\n    def __exit__(self, *excinfo) -> None:\n        \"\"\"Contextmanager protocol for `stop()`.\n\n        Args:\n            excinfo: sys.exc_info captured in the context block\n        \"\"\"\n        self.stop()\n\n    @staticmethod\n    def _poll_for(\n        target: Callable[[], T],\n        timeout: TimeoutType = None,\n        step: TimeoutType = None,\n    ) -> T | Literal[False]:\n        \"\"\"Generic polling logic.\n\n        Args:\n            target: callable that returns truthy if polling condition is met.\n            timeout: max polling time\n            step: interval between checking target()\n\n        Returns:\n            return value of target() if truthy within timeout\n            False if timeout elapses\n        \"\"\"\n        if timeout is None:\n            timeout = DEFAULT_TIMEOUT\n        if step is None:\n            step = POLL_INTERVAL\n        deadline = time.time() + timeout\n        while time.time() < deadline:\n            with contextlib.suppress(Exception):\n                success = target()\n                if success:\n                    return success\n            time.sleep(step)\n        return False\n\n    @staticmethod\n    async def _poll_for_async(\n        target: Callable[[], Coroutine[None, None, T]],\n        timeout: TimeoutType = None,\n        step: TimeoutType = None,\n    ) -> T | bool:\n        \"\"\"Generic polling logic for async functions.\n\n        Args:\n            target: callable that returns truthy if polling condition is met.\n            timeout: max polling time\n            step: interval between checking target()\n\n        Returns:\n            return value of target() if truthy within timeout\n            False if timeout elapses\n        \"\"\"\n        if timeout is None:\n            timeout = DEFAULT_TIMEOUT\n        if step is None:\n            step = POLL_INTERVAL\n        deadline = time.time() + timeout\n        while time.time() < deadline:\n            success = await target()\n            if success:\n                return success\n            await asyncio.sleep(step)\n        return False\n\n    def _poll_for_servers(self, timeout: TimeoutType = None) -> socket.socket:\n        \"\"\"Poll backend server for listening sockets.\n\n        Args:\n            timeout: how long to wait for listening socket.\n\n        Returns:\n            first active listening socket on the backend\n\n        Raises:\n            RuntimeError: when the backend hasn't started running\n            TimeoutError: when server or sockets are not ready\n        \"\"\"\n        if self.backend is None:\n            msg = \"Backend is not running.\"\n            raise RuntimeError(msg)\n        backend = self.backend\n        # check for servers to be initialized\n        if not self._poll_for(\n            target=lambda: getattr(backend, \"servers\", False),\n            timeout=timeout,\n        ):\n            msg = \"Backend servers are not initialized.\"\n            raise TimeoutError(msg)\n        # check for sockets to be listening\n        if not self._poll_for(\n            target=lambda: getattr(backend.servers[0], \"sockets\", False),\n            timeout=timeout,\n        ):\n            msg = \"Backend is not listening.\"\n            raise TimeoutError(msg)\n        return backend.servers[0].sockets[0]\n\n    def frontend(\n        self,\n        driver_clz: type[WebDriver] | None = None,\n        driver_kwargs: dict[str, Any] | None = None,\n        driver_options: ArgOptions | None = None,\n        driver_option_args: list[str] | None = None,\n        driver_option_capabilities: dict[str, Any] | None = None,\n    ) -> WebDriver:\n        \"\"\"Get a selenium webdriver instance pointed at the app.\n\n        Args:\n            driver_clz: webdriver.Chrome (default), webdriver.Firefox, webdriver.Safari,\n                webdriver.Edge, etc\n            driver_kwargs: additional keyword arguments to pass to the webdriver constructor\n            driver_options: selenium ArgOptions instance to pass to the webdriver constructor\n            driver_option_args: additional arguments for the webdriver options\n            driver_option_capabilities: additional capabilities for the webdriver options\n\n        Returns:\n            Instance of the given webdriver navigated to the frontend url of the app.\n\n        Raises:\n            RuntimeError: when selenium is not importable or frontend is not running\n        \"\"\"\n        if not has_selenium:\n            msg = (\n                \"Frontend functionality requires `selenium` to be installed, \"\n                \"and it could not be imported.\"\n            )\n            raise RuntimeError(msg)\n        if self.frontend_url is None:\n            msg = \"Frontend is not running.\"\n            raise RuntimeError(msg)\n        want_headless = False\n        if environment.APP_HARNESS_HEADLESS.get():\n            want_headless = True\n        if driver_clz is None:\n            requested_driver = environment.APP_HARNESS_DRIVER.get()\n            driver_clz = getattr(webdriver, requested_driver)  # pyright: ignore [reportPossiblyUnboundVariable]\n            if driver_options is None:\n                driver_options = getattr(webdriver, f\"{requested_driver}Options\")()  # pyright: ignore [reportPossiblyUnboundVariable]\n        if driver_clz is webdriver.Chrome:  # pyright: ignore [reportPossiblyUnboundVariable]\n            if driver_options is None:\n                from selenium.webdriver.chrome.options import Options\n\n                driver_options = Options()  # pyright: ignore [reportPossiblyUnboundVariable]\n            driver_options.add_argument(\"--class=AppHarness\")\n            if want_headless:\n                driver_options.add_argument(\"--headless=new\")\n        elif driver_clz is webdriver.Firefox:  # pyright: ignore [reportPossiblyUnboundVariable]\n            if driver_options is None:\n                from selenium.webdriver.firefox.options import Options\n\n                driver_options = Options()  # pyright: ignore [reportPossiblyUnboundVariable]\n            if want_headless:\n                driver_options.add_argument(\"-headless\")\n        elif driver_clz is webdriver.Edge:  # pyright: ignore [reportPossiblyUnboundVariable]\n            if driver_options is None:\n                from selenium.webdriver.edge.options import Options\n\n                driver_options = Options()  # pyright: ignore [reportPossiblyUnboundVariable]\n            if want_headless:\n                driver_options.add_argument(\"headless\")\n        if driver_options is None:\n            msg = f\"Could not determine options for {driver_clz}\"\n            raise RuntimeError(msg)\n        if args := environment.APP_HARNESS_DRIVER_ARGS.get():\n            for arg in args.split(\",\"):\n                driver_options.add_argument(arg)\n        if driver_option_args is not None:\n            for arg in driver_option_args:\n                driver_options.add_argument(arg)\n        if driver_option_capabilities is not None:\n            for key, value in driver_option_capabilities.items():\n                driver_options.set_capability(key, value)\n        if driver_kwargs is None:\n            driver_kwargs = {}\n        driver = driver_clz(options=driver_options, **driver_kwargs)  # pyright: ignore [reportOptionalCall, reportArgumentType]\n        driver.get(self.frontend_url)\n        self._frontends.append(driver)\n        return driver\n\n    async def get_state(self, token: str) -> BaseState:\n        \"\"\"Get the state associated with the given token.\n\n        Args:\n            token: The state token to look up.\n\n        Returns:\n            The state instance associated with the given token\n\n        Raises:\n            RuntimeError: when the app hasn't started running\n        \"\"\"\n        if self.state_manager is None:\n            msg = \"state_manager is not set.\"\n            raise RuntimeError(msg)\n        if self.app_instance is not None and isinstance(\n            self.app_instance.state_manager, StateManagerDisk\n        ):\n            # Song and dance to convince the instance's state manager to flush\n            # (we can't directly await the _other_ loop's Future)\n            await self.app_instance.state_manager._flush_write_queue()\n        if isinstance(self.state_manager, StateManagerDisk):\n            # Force reload the latest state from disk.\n            client_token, _ = _split_substate_key(token)\n            self.state_manager.states.pop(client_token, None)\n        try:\n            return await self.state_manager.get_state(token)\n        finally:\n            await self.state_manager.close()\n\n    async def set_state(self, token: str, **kwargs) -> None:\n        \"\"\"Set the state associated with the given token.\n\n        Args:\n            token: The state token to set.\n            kwargs: Attributes to set on the state.\n\n        Raises:\n            RuntimeError: when the app hasn't started running\n        \"\"\"\n        if self.state_manager is None:\n            msg = \"state_manager is not set.\"\n            raise RuntimeError(msg)\n        state = await self.get_state(token)\n        for key, value in kwargs.items():\n            setattr(state, key, value)\n        try:\n            await self.state_manager.set_state(token, state)\n        finally:\n            if self.app_instance is not None and isinstance(\n                self.app_instance.state_manager, StateManagerDisk\n            ):\n                # Clear the token from the backend's cache so it will be reloaded.\n                client_token, _ = _split_substate_key(token)\n                self.app_instance.state_manager.states.pop(client_token, None)\n            await self.state_manager.close()\n\n    @contextlib.asynccontextmanager\n    async def modify_state(self, token: str) -> AsyncIterator[BaseState]:\n        \"\"\"Modify the state associated with the given token and send update to frontend.\n\n        Args:\n            token: The state token to modify\n\n        Yields:\n            The state instance associated with the given token\n\n        Raises:\n            RuntimeError: when the app hasn't started running\n        \"\"\"\n        if self.state_manager is None:\n            msg = \"state_manager is not set.\"\n            raise RuntimeError(msg)\n        if self.app_instance is None:\n            msg = \"App is not running.\"\n            raise RuntimeError(msg)\n        app_state_manager = self.app_instance.state_manager\n        if isinstance(self.state_manager, (StateManagerRedis, StateManagerDisk)):\n            # Temporarily replace the app's state manager with our own, since\n            # the redis/disk connection is on the backend_thread event loop\n            self.app_instance._state_manager = self.state_manager\n        try:\n            async with self.app_instance.modify_state(token) as state:\n                yield state\n        finally:\n            if isinstance(app_state_manager, StateManagerDisk):\n                # Clear the token from the cache so it will be reloaded.\n                client_token, _ = _split_substate_key(token)\n                app_state_manager.states.pop(client_token, None)\n            await self.state_manager.close()\n            self.app_instance._state_manager = app_state_manager\n\n    def token_manager(self) -> TokenManager:\n        \"\"\"Get the token manager for the app instance.\n\n        Returns:\n            The current token_manager attached to the app's EventNamespace.\n        \"\"\"\n        assert self.app_instance is not None\n        app_event_namespace = self.app_instance.event_namespace\n        assert app_event_namespace is not None\n        app_token_manager = app_event_namespace._token_manager\n        assert app_token_manager is not None\n        return app_token_manager\n\n    def poll_for_content(\n        self,\n        element: WebElement,\n        timeout: TimeoutType = None,\n        exp_not_equal: str = \"\",\n    ) -> str:\n        \"\"\"Poll element.text for change.\n\n        Args:\n            element: selenium webdriver element to check\n            timeout: how long to poll element.text\n            exp_not_equal: exit the polling loop when the element text does not match\n\n        Returns:\n            The element text when the polling loop exited\n\n        Raises:\n            TimeoutError: when the timeout expires before text changes\n        \"\"\"\n        if not self._poll_for(\n            target=lambda: element.text != exp_not_equal,\n            timeout=timeout,\n        ):\n            msg = f\"{element} content remains {exp_not_equal!r} while polling.\"\n            raise TimeoutError(msg)\n        return element.text\n\n    def poll_for_value(\n        self,\n        element: WebElement,\n        timeout: TimeoutType = None,\n        exp_not_equal: str | Sequence[str] = \"\",\n    ) -> str | None:\n        \"\"\"Poll element.get_attribute(\"value\") for change.\n\n        Args:\n            element: selenium webdriver element to check\n            timeout: how long to poll element value attribute\n            exp_not_equal: exit the polling loop when the value does not match\n\n        Returns:\n            The element value when the polling loop exited\n\n        Raises:\n            TimeoutError: when the timeout expires before value changes\n        \"\"\"\n        exp_not_equal = (\n            (exp_not_equal,) if isinstance(exp_not_equal, str) else exp_not_equal\n        )\n        if not self._poll_for(\n            target=lambda: element.get_attribute(\"value\") not in exp_not_equal,\n            timeout=timeout,\n        ):\n            msg = f\"{element} content remains {exp_not_equal!r} while polling.\"\n            raise TimeoutError(msg)\n        return element.get_attribute(\"value\")\n\n    def poll_for_clients(self, timeout: TimeoutType = None) -> dict[str, BaseState]:\n        \"\"\"Poll app state_manager for any connected clients.\n\n        Args:\n            timeout: how long to wait for client states\n\n        Returns:\n            active state instances when the polling loop exited\n\n        Raises:\n            RuntimeError: when the app hasn't started running\n            TimeoutError: when the timeout expires before any states are seen\n            ValueError: when the state_manager is not a memory state manager\n        \"\"\"\n        if self.app_instance is None:\n            msg = \"App is not running.\"\n            raise RuntimeError(msg)\n        state_manager = self.app_instance.state_manager\n        if not isinstance(state_manager, (StateManagerMemory, StateManagerDisk)):\n            msg = \"Only works with memory or disk state manager\"\n            raise ValueError(msg)\n        if not self._poll_for(\n            target=lambda: state_manager.states,\n            timeout=timeout,\n        ):\n            msg = \"No states were observed while polling.\"\n            raise TimeoutError(msg)\n        return state_manager.states\n\n    @staticmethod\n    def poll_for_or_raise_timeout(\n        target: Callable[[], T],\n        timeout: TimeoutType = None,\n        step: TimeoutType = None,\n    ) -> T:\n        \"\"\"Poll target callable for a truthy return value.\n\n        Like `_poll_for`, but raises a `TimeoutError` if the target does not\n        return a truthy value within the timeout.\n\n        Args:\n            target: callable that returns truthy if polling condition is met.\n            timeout: max polling time\n            step: interval between checking target()\n\n        Returns:\n            return value of target() if truthy within timeout\n\n        Raises:\n            TimeoutError: when target does not return a truthy value within timeout\n        \"\"\"\n        result = AppHarness._poll_for(\n            target=target,\n            timeout=timeout,\n            step=step,\n        )\n        if result is False:\n            msg = \"Target did not return a truthy value while polling.\"\n            raise TimeoutError(msg)\n        return result\n\n    @staticmethod\n    def expect(\n        target: Callable[[], T],\n        timeout: TimeoutType = None,\n        step: TimeoutType = None,\n    ):\n        \"\"\"Expect a target callable to return a truthy value within the timeout.\n\n        Args:\n            target: callable that returns truthy if polling condition is met.\n            timeout: max polling time\n            step: interval between checking target()\n        \"\"\"\n        AppHarness.poll_for_or_raise_timeout(\n            target=target,\n            timeout=timeout,\n            step=step,\n        )\n\n\nclass SimpleHTTPRequestHandlerCustomErrors(SimpleHTTPRequestHandler):\n    \"\"\"SimpleHTTPRequestHandler with custom error page handling.\"\"\"\n\n    def __init__(self, *args, error_page_map: dict[int, Path], **kwargs):\n        \"\"\"Initialize the handler.\n\n        Args:\n            error_page_map: map of error code to error page path\n            *args: passed through to superclass\n            **kwargs: passed through to superclass\n        \"\"\"\n        self.error_page_map = error_page_map\n        super().__init__(*args, **kwargs)\n\n    def send_error(\n        self, code: int, message: str | None = None, explain: str | None = None\n    ) -> None:\n        \"\"\"Send the error page for the given error code.\n\n        If the code matches a custom error page, then message and explain are\n        ignored.\n\n        Args:\n            code: the error code\n            message: the error message\n            explain: the error explanation\n        \"\"\"\n        error_page = self.error_page_map.get(code)\n        if error_page:\n            self.send_response(code, message)\n            self.send_header(\"Connection\", \"close\")\n            body = error_page.read_bytes()\n            self.send_header(\"Content-Type\", self.error_content_type)\n            self.send_header(\"Content-Length\", str(len(body)))\n            self.end_headers()\n            self.wfile.write(body)\n        else:\n            super().send_error(code, message, explain)\n\n\nclass Subdir404TCPServer(socketserver.TCPServer):\n    \"\"\"TCPServer for SimpleHTTPRequestHandlerCustomErrors that serves from a subdir.\"\"\"\n\n    def __init__(\n        self,\n        *args,\n        root: Path,\n        error_page_map: dict[int, Path] | None,\n        **kwargs,\n    ):\n        \"\"\"Initialize the server.\n\n        Args:\n            root: the root directory to serve from\n            error_page_map: map of error code to error page path\n            *args: passed through to superclass\n            **kwargs: passed through to superclass\n        \"\"\"\n        self.root = root\n        self.error_page_map = error_page_map or {}\n        super().__init__(*args, **kwargs)\n\n    def finish_request(self, request: socket.socket, client_address: tuple[str, int]):\n        \"\"\"Finish one request by instantiating RequestHandlerClass.\n\n        Args:\n            request: the requesting socket\n            client_address: (host, port) referring to the client's address.\n        \"\"\"\n        self.RequestHandlerClass(\n            request,\n            client_address,\n            self,\n            directory=str(self.root),  # pyright: ignore [reportCallIssue]\n            error_page_map=self.error_page_map,  # pyright: ignore [reportCallIssue]\n        )\n\n\nclass AppHarnessProd(AppHarness):\n    \"\"\"AppHarnessProd executes a reflex app in-process for testing.\n\n    In prod mode, instead of running `react-router dev` the app is exported as static\n    files and served via the builtin python http.server with custom 404 redirect\n    handling. Additionally, the backend runs in multi-worker mode.\n    \"\"\"\n\n    frontend_thread: threading.Thread | None = None\n    frontend_server: Subdir404TCPServer | None = None\n\n    def _run_frontend(self):\n        web_root = (\n            self.app_path\n            / reflex.utils.prerequisites.get_web_dir()\n            / reflex.constants.Dirs.STATIC\n        )\n        error_page_map = {\n            404: web_root / \"404.html\",\n        }\n        with Subdir404TCPServer(\n            (\"\", 0),\n            SimpleHTTPRequestHandlerCustomErrors,\n            root=web_root,\n            error_page_map=error_page_map,\n        ) as self.frontend_server:\n            self.frontend_url = \"http://localhost:{1}\".format(\n                *self.frontend_server.socket.getsockname()\n            )\n            self.frontend_server.serve_forever()\n\n    def _start_frontend(self):\n        # Set up the frontend.\n        with chdir(self.app_path):\n            config = reflex.config.get_config()\n            print(\"Polling for servers...\")  # for pytest diagnosis #noqa: T201\n            config.api_url = \"http://{}:{}\".format(\n                *self._poll_for_servers(timeout=30).getsockname(),\n            )\n            print(\"Building frontend...\")  # for pytest diagnosis #noqa: T201\n\n            get_config().loglevel = reflex.constants.LogLevel.INFO\n\n            reflex.utils.prerequisites.assert_in_reflex_dir()\n\n            if reflex.utils.prerequisites.needs_reinit():\n                reflex.reflex._init(name=get_config().app_name)\n\n            export(\n                zipping=False,\n                frontend=True,\n                backend=False,\n                loglevel=reflex.constants.LogLevel.INFO,\n                env=reflex.constants.Env.PROD,\n            )\n\n        print(\"Frontend starting...\")  # for pytest diagnosis #noqa: T201\n\n        self.frontend_thread = threading.Thread(target=self._run_frontend)\n        self.frontend_thread.start()\n\n    def _wait_frontend(self):\n        self._poll_for(lambda: self.frontend_server is not None)\n        if self.frontend_server is None or not self.frontend_server.socket.fileno():\n            msg = \"Frontend did not start\"\n            raise RuntimeError(msg)\n\n    def _start_backend(self):\n        if self.app_asgi is None:\n            msg = \"App was not initialized.\"\n            raise RuntimeError(msg)\n        environment.REFLEX_SKIP_COMPILE.set(True)\n        self.backend = uvicorn.Server(\n            uvicorn.Config(\n                app=self.app_asgi,\n                host=\"127.0.0.1\",\n                port=0,\n                workers=reflex.utils.processes.get_num_workers(),\n            ),\n        )\n        self.backend.shutdown = self._get_backend_shutdown_handler()\n        print(  # noqa: T201\n            \"Creating backend in a new thread...\"\n        )\n        self.backend_thread = threading.Thread(target=self.backend.run)\n        self.backend_thread.start()\n        print(\"Backend started.\")  # for pytest diagnosis #noqa: T201\n\n    def _poll_for_servers(self, timeout: TimeoutType = None) -> socket.socket:\n        try:\n            return super()._poll_for_servers(timeout)\n        finally:\n            environment.REFLEX_SKIP_COMPILE.set(None)\n\n    def stop(self):\n        \"\"\"Stop the frontend python webserver.\"\"\"\n        super().stop()\n        if self.frontend_server is not None:\n            self.frontend_server.shutdown()\n        if self.frontend_thread is not None:\n            self.frontend_thread.join()\n"
  },
  {
    "path": "reflex/utils/__init__.py",
    "content": "\"\"\"Reflex utilities.\"\"\"\n"
  },
  {
    "path": "reflex/utils/build.py",
    "content": "\"\"\"Building the app and initializing all prerequisites.\"\"\"\n\nfrom __future__ import annotations\n\nimport os\nimport zipfile\nfrom pathlib import Path, PosixPath\n\nfrom rich.progress import MofNCompleteColumn, Progress, TimeElapsedColumn\n\nfrom reflex import constants\nfrom reflex.config import get_config\nfrom reflex.utils import console, js_runtimes, path_ops, prerequisites, processes\nfrom reflex.utils.exec import is_in_app_harness\n\n\ndef set_env_json():\n    \"\"\"Write the upload url to a REFLEX_JSON.\"\"\"\n    path_ops.update_json_file(\n        str(prerequisites.get_web_dir() / constants.Dirs.ENV_JSON),\n        {\n            **{endpoint.name: endpoint.get_url() for endpoint in constants.Endpoint},\n            \"TRANSPORT\": get_config().transport,\n            \"TEST_MODE\": is_in_app_harness(),\n        },\n    )\n\n\ndef _zip(\n    *,\n    component_name: constants.ComponentName,\n    target: Path,\n    root_directory: Path,\n    exclude_venv_directories: bool,\n    include_db_file: bool = False,\n    directory_names_to_exclude: set[str] | None = None,\n    files_to_exclude: set[Path] | None = None,\n    globs_to_include: list[str] | None = None,\n) -> None:\n    \"\"\"Zip utility function.\n\n    Args:\n        component_name: The name of the component: backend or frontend.\n        target: The target zip file.\n        root_directory: The root directory to zip.\n        exclude_venv_directories: Whether to exclude venv directories.\n        include_db_file: Whether to include local sqlite db files.\n        directory_names_to_exclude: The directory names to exclude.\n        files_to_exclude: The files to exclude.\n        globs_to_include: Apply these globs from the root_directory and always include them in the zip.\n\n    \"\"\"\n    target = Path(target)\n    root_directory = Path(root_directory).resolve()\n    directory_names_to_exclude = directory_names_to_exclude or set()\n    files_to_exclude = files_to_exclude or set()\n    files_to_zip: list[Path] = []\n    # Traverse the root directory in a top-down manner. In this traversal order,\n    # we can modify the dirs list in-place to remove directories we don't want to include.\n    for directory_path, subdirectories_names, subfiles_names in os.walk(\n        root_directory, topdown=True, followlinks=True\n    ):\n        directory_path = Path(directory_path).resolve()\n        # Modify the dirs in-place so excluded and hidden directories are skipped in next traversal.\n        subdirectories_names[:] = [\n            subdirectory_name\n            for subdirectory_name in subdirectories_names\n            if subdirectory_name not in directory_names_to_exclude\n            and not any(\n                (directory_path / subdirectory_name).samefile(exclude)\n                for exclude in files_to_exclude\n                if exclude.exists()\n            )\n            and not subdirectory_name.startswith(\".\")\n            and (\n                not exclude_venv_directories\n                or not _looks_like_venv_directory(directory_path / subdirectory_name)\n            )\n        ]\n        # Modify the files in-place so the hidden files and db files are excluded.\n        subfiles_names[:] = [\n            subfile_name\n            for subfile_name in subfiles_names\n            if not subfile_name.startswith(\".\")\n            and (include_db_file or not subfile_name.endswith(\".db\"))\n        ]\n        files_to_zip += [\n            directory_path / subfile_name\n            for subfile_name in subfiles_names\n            if not any(\n                (directory_path / subfile_name).samefile(excluded_file)\n                for excluded_file in files_to_exclude\n                if excluded_file.exists()\n            )\n        ]\n    if globs_to_include:\n        for glob in globs_to_include:\n            files_to_zip += [\n                file\n                for file in root_directory.glob(glob)\n                if file.name not in files_to_exclude\n            ]\n    # Create a progress bar for zipping the component.\n    progress = Progress(\n        *Progress.get_default_columns()[:-1],\n        MofNCompleteColumn(),\n        TimeElapsedColumn(),\n    )\n    task = progress.add_task(\n        f\"Zipping {component_name.value}:\", total=len(files_to_zip)\n    )\n\n    with progress, zipfile.ZipFile(target, \"w\", zipfile.ZIP_DEFLATED) as zipf:\n        for file in files_to_zip:\n            console.debug(f\"{target}: {file}\", progress=progress)\n            progress.advance(task)\n            zipf.write(file, Path(file).relative_to(root_directory))\n\n\ndef zip_app(\n    frontend: bool = True,\n    backend: bool = True,\n    zip_dest_dir: str | Path | None = None,\n    include_db_file: bool = False,\n    backend_excluded_dirs: tuple[Path, ...] = (),\n):\n    \"\"\"Zip up the app.\n\n    Args:\n        frontend: Whether to zip up the frontend app.\n        backend: Whether to zip up the backend app.\n        zip_dest_dir: The directory to export the zip file to.\n        include_db_file: Whether to include the database file.\n        backend_excluded_dirs: A tuple of files or directories to exclude from the backend zip.  Defaults to ().\n    \"\"\"\n    zip_dest_dir = zip_dest_dir or Path.cwd()\n    zip_dest_dir = Path(zip_dest_dir)\n    files_to_exclude = {\n        Path(constants.ComponentName.FRONTEND.zip()).resolve(),\n        Path(constants.ComponentName.BACKEND.zip()).resolve(),\n    }\n\n    if frontend:\n        _zip(\n            component_name=constants.ComponentName.FRONTEND,\n            target=zip_dest_dir / constants.ComponentName.FRONTEND.zip(),\n            root_directory=prerequisites.get_web_dir() / constants.Dirs.STATIC,\n            files_to_exclude=files_to_exclude,\n            exclude_venv_directories=False,\n        )\n\n    if backend:\n        _zip(\n            component_name=constants.ComponentName.BACKEND,\n            target=zip_dest_dir / constants.ComponentName.BACKEND.zip(),\n            root_directory=Path.cwd(),\n            directory_names_to_exclude={\"__pycache__\"},\n            files_to_exclude=files_to_exclude | set(backend_excluded_dirs),\n            exclude_venv_directories=True,\n            include_db_file=include_db_file,\n            globs_to_include=[\n                str(Path(constants.Dirs.WEB) / constants.Dirs.BACKEND / \"*\")\n            ],\n        )\n\n\ndef _duplicate_index_html_to_parent_directory(directory: Path):\n    \"\"\"Duplicate index.html in the child directories to the given directory.\n\n    This makes accessing /route and /route/ work in production.\n\n    Args:\n        directory: The directory to duplicate index.html to.\n    \"\"\"\n    for child in directory.iterdir():\n        if child.is_dir():\n            # If the child directory has an index.html, copy it to the parent directory.\n            index_html = child / \"index.html\"\n            if index_html.exists():\n                target = directory / (child.name + \".html\")\n                if not target.exists():\n                    console.debug(f\"Copying {index_html} to {target}\")\n                    path_ops.cp(index_html, target)\n                else:\n                    console.debug(f\"Skipping {index_html}, already exists at {target}\")\n            # Recursively call this function for the child directory.\n            _duplicate_index_html_to_parent_directory(child)\n\n\ndef build():\n    \"\"\"Build the app for deployment.\n\n    Raises:\n        SystemExit: If the build process fails.\n    \"\"\"\n    wdir = prerequisites.get_web_dir()\n\n    # Clean the static directory if it exists.\n    path_ops.rm(str(wdir / constants.Dirs.BUILD_DIR))\n\n    checkpoints = [\n        \"building client environment for production...\",\n        \"modules transformed\",\n        \"building ssr environment for production...\",\n        \"built in\",\n    ]\n\n    # Start the subprocess with the progress bar.\n    process = processes.new_process(\n        [\n            *js_runtimes.get_js_package_executor(raise_on_none=True)[0],\n            \"run\",\n            \"export\",\n        ],\n        cwd=wdir,\n        shell=constants.IS_WINDOWS,\n        env={\n            **os.environ,\n            \"NO_COLOR\": \"1\",\n        },\n    )\n    processes.show_progress(\"Creating Production Build\", process, checkpoints)\n    process.wait()\n    if process.returncode != 0:\n        console.error(\n            \"Failed to build the frontend. Please run with --loglevel debug for more information.\",\n        )\n        raise SystemExit(1)\n    _duplicate_index_html_to_parent_directory(wdir / constants.Dirs.STATIC)\n\n    spa_fallback = wdir / constants.Dirs.STATIC / constants.ReactRouter.SPA_FALLBACK\n    if not spa_fallback.exists():\n        spa_fallback = wdir / constants.Dirs.STATIC / \"index.html\"\n\n    if spa_fallback.exists():\n        path_ops.cp(\n            spa_fallback,\n            wdir / constants.Dirs.STATIC / \"404.html\",\n        )\n\n    config = get_config()\n\n    if frontend_path := config.frontend_path.strip(\"/\"):\n        frontend_path = PosixPath(frontend_path)\n        first_part = frontend_path.parts[0]\n        for child in list((wdir / constants.Dirs.STATIC).iterdir()):\n            if child.is_dir() and child.name == first_part:\n                continue\n            path_ops.mv(\n                child,\n                wdir / constants.Dirs.STATIC / frontend_path / child.name,\n            )\n\n\ndef setup_frontend(\n    root: Path,\n):\n    \"\"\"Set up the frontend to run the app.\n\n    Args:\n        root: The root path of the project.\n    \"\"\"\n    # Set the environment variables in client (env.json).\n    set_env_json()\n\n    # update the last reflex run time.\n    prerequisites.set_last_reflex_run_time()\n\n\ndef setup_frontend_prod(\n    root: Path,\n):\n    \"\"\"Set up the frontend for prod mode.\n\n    Args:\n        root: The root path of the project.\n    \"\"\"\n    setup_frontend(root)\n    build()\n\n\ndef _looks_like_venv_directory(directory_to_check: str | Path) -> bool:\n    directory_to_check = Path(directory_to_check)\n    return (directory_to_check / \"pyvenv.cfg\").exists()\n"
  },
  {
    "path": "reflex/utils/codespaces.py",
    "content": "\"\"\"Utilities for working with Github Codespaces.\"\"\"\n\nfrom __future__ import annotations\n\nimport os\n\nfrom starlette.requests import Request\nfrom starlette.responses import HTMLResponse\n\nfrom reflex.components.base.script import Script\nfrom reflex.components.component import Component\nfrom reflex.components.core.banner import has_connection_errors\nfrom reflex.components.core.cond import cond\nfrom reflex.constants import Endpoint\nfrom reflex.utils.decorator import once\n\n\n@once\ndef redirect_script() -> str:\n    \"\"\"Get the redirect script for Github Codespaces.\n\n    Returns:\n        The redirect script as a string.\n    \"\"\"\n    return f\"\"\"\nconst thisUrl = new URL(window.location.href);\nconst params = new URLSearchParams(thisUrl.search)\n\nfunction sameHostnameDifferentPort(one, two) {{\n    const hostnameOne = one.hostname;\n    const hostnameTwo = two.hostname;\n    const partsOne = hostnameOne.split(\".\");\n    const partsTwo = hostnameTwo.split(\".\");\n    if (partsOne.length !== partsTwo.length) {{ return false;  }}\n    for (let i = 1; i < partsOne.length; i++) {{\n        if (partsOne[i] !== partsTwo[i]) {{ return false; }}\n    }}\n    const uniqueNameOne = partsOne[0];\n    const uniqueNameTwo = partsTwo[0];\n    const uniqueNamePartsOne = uniqueNameOne.split(\"-\");\n    const uniqueNamePartsTwo = uniqueNameTwo.split(\"-\");\n    if (uniqueNamePartsOne.length !== uniqueNamePartsTwo.length) {{ return false;  }}\n    for (let i = 0; i < uniqueNamePartsOne.length - 1; i++) {{\n        if (uniqueNamePartsOne[i] !== uniqueNamePartsTwo[i]) {{ return false;  }}\n    }}\n    return true;\n}}\n\nfunction doRedirect(url) {{\n    if (!window.sessionStorage.getItem(\"authenticated_github_codespaces\")) {{\n        const a = document.createElement(\"a\");\n        if (params.has(\"redirect_to\")) {{\n            const redirect_to = new URL(params.get(\"redirect_to\"));\n            if (!sameHostnameDifferentPort(thisUrl, redirect_to)) {{\n                console.warn(\"Reflex: Not redirecting to different hostname\");\n                return;\n            }}\n            if (!redirect_to.hostname.endsWith(\".app.github.dev\")) {{\n                console.warn(\"Reflex: Not redirecting to non .app.github.dev hostname\");\n                return;\n            }}\n            a.href = redirect_to.href;\n        }} else if (!window.location.href.startsWith(url)) {{\n            a.href = url + `?redirect_to=${{window.location.href}}`\n        }} else {{\n            return\n        }}\n        a.hidden = true;\n        a.click();\n        a.remove();\n        window.sessionStorage.setItem(\"authenticated_github_codespaces\", \"true\")\n    }}\n}}\ndoRedirect(\"{Endpoint.AUTH_CODESPACE.get_url()}\")\n\"\"\"\n\n\ndef codespaces_port_forwarding_domain() -> str | None:\n    \"\"\"Get the domain for port forwarding in Github Codespaces.\n\n    Returns:\n        The domain for port forwarding in Github Codespaces, or None if not running in Codespaces.\n    \"\"\"\n    return os.getenv(\"GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN\")\n\n\ndef is_running_in_codespaces() -> bool:\n    \"\"\"Check if the app is running in Github Codespaces.\n\n    Returns:\n        True if running in Github Codespaces, False otherwise.\n    \"\"\"\n    return codespaces_port_forwarding_domain() is not None\n\n\ndef codespaces_auto_redirect() -> list[Component]:\n    \"\"\"Get the components for automatically redirecting back to the app after authenticating a codespace port forward.\n\n    Returns:\n        A list containing the conditional redirect component, or empty list.\n    \"\"\"\n    if is_running_in_codespaces():\n        return [cond(has_connection_errors, Script.create(redirect_script()))]\n    return []\n\n\ndef auth_codespace(_request: Request) -> HTMLResponse:\n    \"\"\"Page automatically redirecting back to the app after authenticating a codespace port forward.\n\n    Args:\n        _request: The request object.\n\n    Returns:\n        An HTML response with an embedded script to redirect back to the app.\n    \"\"\"\n    return HTMLResponse(\n        f\"\"\"\n    <html>\n        <head>\n            <title>Reflex Github Codespace Forward Successfully Authenticated</title>\n        </head>\n        <body>\n            <center>\n                <h2>Successfully Authenticated</h2>\n            </center>\n            <script language=\"javascript\">\n                {redirect_script()}\n            </script>\n        </body>\n    </html>\n    \"\"\"\n    )\n"
  },
  {
    "path": "reflex/utils/compat.py",
    "content": "\"\"\"Compatibility hacks and helpers.\"\"\"\n\nimport sys\nfrom collections.abc import Mapping\nfrom importlib.util import find_spec\nfrom typing import TYPE_CHECKING, Any\n\nif TYPE_CHECKING:\n    from pydantic.fields import FieldInfo\n\n\nasync def windows_hot_reload_lifespan_hack():\n    \"\"\"[REF-3164] A hack to fix hot reload on Windows.\n\n    Uvicorn has an issue stopping itself on Windows after detecting changes in\n    the filesystem.\n\n    This workaround repeatedly prints and flushes null characters to stderr,\n    which seems to allow the uvicorn server to exit when the CTRL-C signal is\n    sent from the reloader process.\n\n    Don't ask me why this works, I discovered it by accident - masenf.\n    \"\"\"\n    import asyncio\n    import sys\n\n    try:\n        while True:\n            sys.stderr.write(\"\\0\")\n            sys.stderr.flush()\n            await asyncio.sleep(0.5)\n    except asyncio.CancelledError:\n        pass\n\n\ndef annotations_from_namespace(namespace: Mapping[str, Any]) -> dict[str, Any]:\n    \"\"\"Get the annotations from a class namespace.\n\n    Args:\n        namespace: The class namespace.\n\n    Returns:\n        The (forward-ref) annotations from the class namespace.\n    \"\"\"\n    if sys.version_info >= (3, 14) and \"__annotations__\" not in namespace:\n        from annotationlib import (\n            Format,\n            call_annotate_function,\n            get_annotate_from_class_namespace,\n        )\n\n        if annotate := get_annotate_from_class_namespace(namespace):\n            return call_annotate_function(annotate, format=Format.FORWARDREF)\n    return namespace.get(\"__annotations__\", {})\n\n\nif find_spec(\"pydantic\") and find_spec(\"pydantic.v1\"):\n    from pydantic.v1.main import ModelMetaclass\n\n    class ModelMetaclassLazyAnnotations(ModelMetaclass):\n        \"\"\"Compatibility metaclass to resolve python3.14 style lazy annotations.\"\"\"\n\n        def __new__(mcs, name: str, bases: tuple, namespace: dict, **kwargs):\n            \"\"\"Resolve python3.14 style lazy annotations before passing off to pydantic v1.\n\n            Args:\n                name: The class name.\n                bases: The base classes.\n                namespace: The class namespace.\n                **kwargs: Additional keyword arguments.\n\n            Returns:\n                The created class.\n            \"\"\"\n            namespace[\"__annotations__\"] = annotations_from_namespace(namespace)\n            return super().__new__(mcs, name, bases, namespace, **kwargs)\n\nelse:\n    ModelMetaclassLazyAnnotations = type  # type: ignore[assignment]\n\n\ndef sqlmodel_field_has_primary_key(field_info: \"FieldInfo\") -> bool:\n    \"\"\"Determines if a field is a primary.\n\n    Args:\n        field_info: a rx.model field\n\n    Returns:\n        If field_info is a primary key (Bool)\n    \"\"\"\n    if getattr(field_info, \"primary_key\", None) is True:\n        return True\n    if getattr(field_info, \"sa_column\", None) is None:\n        return False\n    return bool(getattr(field_info.sa_column, \"primary_key\", None))  # pyright: ignore[reportAttributeAccessIssue]\n"
  },
  {
    "path": "reflex/utils/console.py",
    "content": "\"\"\"Functions to communicate to the user via console.\"\"\"\n\nfrom __future__ import annotations\n\nimport contextlib\nimport datetime\nimport inspect\nimport os\nimport shutil\nimport sys\nimport time\nfrom pathlib import Path\nfrom types import FrameType\n\nfrom rich.console import Console\nfrom rich.progress import MofNCompleteColumn, Progress, TaskID, TimeElapsedColumn\nfrom rich.prompt import Prompt\n\nfrom reflex.constants import LogLevel\nfrom reflex.constants.base import Reflex\nfrom reflex.utils.decorator import once\n\n# Console for pretty printing.\n_console = Console(highlight=False)\n_console_stderr = Console(stderr=True, highlight=False)\n\n# The current log level.\n_LOG_LEVEL = LogLevel.INFO\n\n# Deprecated features who's warning has been printed.\n_EMITTED_DEPRECATION_WARNINGS = set()\n\n# Info messages which have been printed.\n_EMITTED_INFO = set()\n\n# Warnings which have been printed.\n_EMITTED_WARNINGS = set()\n\n# Errors which have been printed.\n_EMITTED_ERRORS = set()\n\n# Success messages which have been printed.\n_EMITTED_SUCCESS = set()\n\n# Debug messages which have been printed.\n_EMITTED_DEBUG = set()\n\n# Logs which have been printed.\n_EMITTED_LOGS = set()\n\n# Prints which have been printed.\n_EMITTED_PRINTS = set()\n\n\ndef set_log_level(log_level: LogLevel | None):\n    \"\"\"Set the log level.\n\n    Args:\n        log_level: The log level to set.\n\n    Raises:\n        TypeError: If the log level is a string.\n    \"\"\"\n    if log_level is None:\n        return\n    if not isinstance(log_level, LogLevel):\n        msg = f\"log_level must be a LogLevel enum value, got {log_level} of type {type(log_level)} instead.\"\n        raise TypeError(msg)\n    global _LOG_LEVEL\n    if log_level != _LOG_LEVEL:\n        # Set the loglevel persistenly for subprocesses.\n        os.environ[\"REFLEX_LOGLEVEL\"] = log_level.value\n    _LOG_LEVEL = log_level\n\n\ndef is_debug() -> bool:\n    \"\"\"Check if the log level is debug.\n\n    Returns:\n        True if the log level is debug.\n    \"\"\"\n    return _LOG_LEVEL <= LogLevel.DEBUG\n\n\ndef print(msg: str, *, dedupe: bool = False, **kwargs):\n    \"\"\"Print a message.\n\n    Args:\n        msg: The message to print.\n        dedupe: If True, suppress multiple console logs of print message.\n        kwargs: Keyword arguments to pass to the print function.\n    \"\"\"\n    if dedupe:\n        if msg in _EMITTED_PRINTS:\n            return\n        _EMITTED_PRINTS.add(msg)\n    _console.print(msg, **kwargs)\n\n\ndef _print_stderr(msg: str, *, dedupe: bool = False, **kwargs):\n    \"\"\"Print a message to stderr.\n\n    Args:\n        msg: The message to print.\n        dedupe: If True, suppress multiple console logs of print message.\n        kwargs: Keyword arguments to pass to the print function.\n    \"\"\"\n    if dedupe:\n        if msg in _EMITTED_PRINTS:\n            return\n        _EMITTED_PRINTS.add(msg)\n    _console_stderr.print(msg, **kwargs)\n\n\n@once\ndef log_file_console():\n    \"\"\"Create a console that logs to a file.\n\n    Returns:\n        A Console object that logs to a file.\n    \"\"\"\n    from reflex.environment import environment\n\n    if not (env_log_file := environment.REFLEX_LOG_FILE.get()):\n        subseconds = int((time.time() % 1) * 1000)\n        timestamp = time.strftime(\"%Y-%m-%d_%H-%M-%S\") + f\"_{subseconds:03d}\"\n        log_file = Reflex.DIR / \"logs\" / (timestamp + \".log\")\n        log_file.parent.mkdir(parents=True, exist_ok=True)\n    else:\n        log_file = env_log_file\n    if log_file.exists():\n        log_file.unlink()\n    log_file.touch()\n    return Console(file=log_file.open(\"a\", encoding=\"utf-8\"))\n\n\n@once\ndef should_use_log_file_console() -> bool:\n    \"\"\"Check if the log file console should be used.\n\n    Returns:\n        True if the log file console should be used, False otherwise.\n    \"\"\"\n    from reflex.environment import environment\n\n    return environment.REFLEX_ENABLE_FULL_LOGGING.get()\n\n\ndef print_to_log_file(msg: str, *, dedupe: bool = False, **kwargs):\n    \"\"\"Print a message to the log file.\n\n    Args:\n        msg: The message to print.\n        dedupe: If True, suppress multiple console logs of print message.\n        kwargs: Keyword arguments to pass to the print function.\n    \"\"\"\n    log_file_console().print(f\"[{datetime.datetime.now()}] {msg}\", **kwargs)\n\n\ndef debug(msg: str, *, dedupe: bool = False, **kwargs):\n    \"\"\"Print a debug message.\n\n    Args:\n        msg: The debug message.\n        dedupe: If True, suppress multiple console logs of debug message.\n        kwargs: Keyword arguments to pass to the print function.\n    \"\"\"\n    if is_debug():\n        msg_ = f\"[purple]Debug: {msg}[/purple]\"\n        if dedupe:\n            if msg_ in _EMITTED_DEBUG:\n                return\n            _EMITTED_DEBUG.add(msg_)\n        if progress := kwargs.pop(\"progress\", None):\n            progress.console.print(msg_, **kwargs)\n        else:\n            print(msg_, **kwargs)\n    if should_use_log_file_console() and kwargs.pop(\"progress\", None) is None:\n        print_to_log_file(f\"[purple]Debug: {msg}[/purple]\", **kwargs)\n\n\ndef info(msg: str, *, dedupe: bool = False, **kwargs):\n    \"\"\"Print an info message.\n\n    Args:\n        msg: The info message.\n        dedupe: If True, suppress multiple console logs of info message.\n        kwargs: Keyword arguments to pass to the print function.\n    \"\"\"\n    if _LOG_LEVEL <= LogLevel.INFO:\n        if dedupe:\n            if msg in _EMITTED_INFO:\n                return\n            _EMITTED_INFO.add(msg)\n        print(f\"[cyan]Info: {msg}[/cyan]\", **kwargs)\n    if should_use_log_file_console():\n        print_to_log_file(f\"[cyan]Info: {msg}[/cyan]\", **kwargs)\n\n\ndef success(msg: str, *, dedupe: bool = False, **kwargs):\n    \"\"\"Print a success message.\n\n    Args:\n        msg: The success message.\n        dedupe: If True, suppress multiple console logs of success message.\n        kwargs: Keyword arguments to pass to the print function.\n    \"\"\"\n    if _LOG_LEVEL <= LogLevel.INFO:\n        if dedupe:\n            if msg in _EMITTED_SUCCESS:\n                return\n            _EMITTED_SUCCESS.add(msg)\n        print(f\"[green]Success: {msg}[/green]\", **kwargs)\n    if should_use_log_file_console():\n        print_to_log_file(f\"[green]Success: {msg}[/green]\", **kwargs)\n\n\ndef log(msg: str, *, dedupe: bool = False, **kwargs):\n    \"\"\"Takes a string and logs it to the console.\n\n    Args:\n        msg: The message to log.\n        dedupe: If True, suppress multiple console logs of log message.\n        kwargs: Keyword arguments to pass to the print function.\n    \"\"\"\n    if _LOG_LEVEL <= LogLevel.INFO:\n        if dedupe:\n            if msg in _EMITTED_LOGS:\n                return\n            _EMITTED_LOGS.add(msg)\n        _console.log(msg, **kwargs)\n    if should_use_log_file_console():\n        print_to_log_file(msg, **kwargs)\n\n\ndef rule(title: str, **kwargs):\n    \"\"\"Prints a horizontal rule with a title.\n\n    Args:\n        title: The title of the rule.\n        kwargs: Keyword arguments to pass to the print function.\n    \"\"\"\n    _console.rule(title, **kwargs)\n\n\ndef warn(msg: str, *, dedupe: bool = False, **kwargs):\n    \"\"\"Print a warning message.\n\n    Args:\n        msg: The warning message.\n        dedupe: If True, suppress multiple console logs of warning message.\n        kwargs: Keyword arguments to pass to the print function.\n    \"\"\"\n    if _LOG_LEVEL <= LogLevel.WARNING:\n        if dedupe:\n            if msg in _EMITTED_WARNINGS:\n                return\n            _EMITTED_WARNINGS.add(msg)\n        print(f\"[orange1]Warning: {msg}[/orange1]\", **kwargs)\n    if should_use_log_file_console():\n        print_to_log_file(f\"[orange1]Warning: {msg}[/orange1]\", **kwargs)\n\n\n@once\ndef _exclude_paths_from_frame_info() -> list[Path]:\n    import importlib.util\n\n    import click\n    import granian\n    import socketio\n    import typing_extensions\n\n    import reflex as rx\n\n    # Exclude utility modules that should never be the source of deprecated reflex usage.\n    exclude_modules = [click, rx, typing_extensions, socketio, granian]\n    modules_paths = [file for m in exclude_modules if (file := m.__file__)] + [\n        spec.origin\n        for m in [*sys.builtin_module_names, *sys.stdlib_module_names]\n        if (spec := importlib.util.find_spec(m)) and spec.origin\n    ]\n    exclude_roots = [\n        p.parent.resolve() if (p := Path(file)).name == \"__init__.py\" else p.resolve()\n        for file in modules_paths\n    ]\n    # Specifically exclude the reflex cli module.\n    if reflex_bin := shutil.which(b\"reflex\"):\n        exclude_roots.append(Path(reflex_bin.decode()))\n\n    return exclude_roots\n\n\ndef _get_first_non_framework_frame() -> FrameType | None:\n    exclude_roots = _exclude_paths_from_frame_info()\n\n    frame = inspect.currentframe()\n    while frame := frame and frame.f_back:\n        frame_path = Path(inspect.getfile(frame)).resolve()\n        if not any(frame_path.is_relative_to(root) for root in exclude_roots):\n            break\n    return frame\n\n\ndef deprecate(\n    *,\n    feature_name: str,\n    reason: str,\n    deprecation_version: str,\n    removal_version: str,\n    dedupe: bool = True,\n    **kwargs,\n):\n    \"\"\"Print a deprecation warning.\n\n    Args:\n        feature_name: The feature to deprecate.\n        reason: The reason for deprecation.\n        deprecation_version: The version the feature was deprecated\n        removal_version: The version the deprecated feature will be removed\n        dedupe: If True, suppress multiple console logs of deprecation message.\n        kwargs: Keyword arguments to pass to the print function.\n    \"\"\"\n    dedupe_key = feature_name\n    loc = \"\"\n\n    # See if we can find where the deprecation exists in \"user code\"\n    origin_frame = _get_first_non_framework_frame()\n    if origin_frame is not None:\n        filename = Path(origin_frame.f_code.co_filename)\n        if filename.is_relative_to(Path.cwd()):\n            filename = filename.relative_to(Path.cwd())\n        loc = f\" ({filename}:{origin_frame.f_lineno})\"\n        dedupe_key = f\"{dedupe_key} {loc}\"\n\n    if dedupe_key not in _EMITTED_DEPRECATION_WARNINGS:\n        msg = (\n            f\"{feature_name} has been deprecated in version {deprecation_version}. {reason.rstrip('.').lstrip('. ')}. It will be completely \"\n            f\"removed in {removal_version}.{loc}\"\n        )\n        if _LOG_LEVEL <= LogLevel.WARNING:\n            print(f\"[yellow]DeprecationWarning: {msg}[/yellow]\", **kwargs)\n        if should_use_log_file_console():\n            print_to_log_file(f\"[yellow]DeprecationWarning: {msg}[/yellow]\", **kwargs)\n        if dedupe:\n            _EMITTED_DEPRECATION_WARNINGS.add(dedupe_key)\n\n\ndef error(msg: str, *, dedupe: bool = False, **kwargs):\n    \"\"\"Print an error message.\n\n    Args:\n        msg: The error message.\n        dedupe: If True, suppress multiple console logs of error message.\n        kwargs: Keyword arguments to pass to the print function.\n    \"\"\"\n    if _LOG_LEVEL <= LogLevel.ERROR:\n        if dedupe:\n            if msg in _EMITTED_ERRORS:\n                return\n            _EMITTED_ERRORS.add(msg)\n        _print_stderr(f\"[red]{msg}[/red]\", **kwargs)\n    if should_use_log_file_console():\n        print_to_log_file(f\"[red]{msg}[/red]\", **kwargs)\n\n\ndef ask(\n    question: str,\n    choices: list[str] | None = None,\n    default: str | None = None,\n    show_choices: bool = True,\n) -> str | None:\n    \"\"\"Takes a prompt question and optionally a list of choices\n     and returns the user input.\n\n    Args:\n        question: The question to ask the user.\n        choices: A list of choices to select from.\n        default: The default option selected.\n        show_choices: Whether to show the choices.\n\n    Returns:\n        A string with the user input.\n    \"\"\"\n    return Prompt.ask(\n        question, choices=choices, default=default, show_choices=show_choices\n    )\n\n\ndef progress():\n    \"\"\"Create a new progress bar.\n\n    Returns:\n        A new progress bar.\n    \"\"\"\n    return Progress(\n        *Progress.get_default_columns()[:-1],\n        MofNCompleteColumn(),\n        TimeElapsedColumn(),\n    )\n\n\ndef status(*args, **kwargs):\n    \"\"\"Create a status with a spinner.\n\n    Args:\n        *args: Args to pass to the status.\n        **kwargs: Kwargs to pass to the status.\n\n    Returns:\n        A new status.\n    \"\"\"\n    return _console.status(*args, **kwargs)\n\n\n@contextlib.contextmanager\ndef timing(msg: str):\n    \"\"\"Create a context manager to time a block of code.\n\n    Args:\n        msg: The message to display.\n\n    Yields:\n        None.\n    \"\"\"\n    start = time.time()\n    try:\n        yield\n    finally:\n        debug(f\"[white]\\\\[timing] {msg}: {time.time() - start:.2f}s[/white]\")\n\n\nclass PoorProgress:\n    \"\"\"A poor man's progress bar.\"\"\"\n\n    def __init__(self):\n        \"\"\"Initialize the progress bar.\"\"\"\n        super().__init__()\n        self.tasks = {}\n        self.progress = 0\n        self.total = 0\n\n    def add_task(self, task: str, total: int):\n        \"\"\"Add a task to the progress bar.\n\n        Args:\n            task: The task name.\n            total: The total number of steps for the task.\n\n        Returns:\n            The task ID.\n        \"\"\"\n        self.total += total\n        task_id = TaskID(len(self.tasks))\n        self.tasks[task_id] = {\"total\": total, \"current\": 0}\n        return task_id\n\n    def advance(self, task: TaskID, advance: int = 1):\n        \"\"\"Advance the progress of a task.\n\n        Args:\n            task: The task ID.\n            advance: The number of steps to advance.\n        \"\"\"\n        if task in self.tasks:\n            self.tasks[task][\"current\"] += advance\n            self.progress += advance\n            _console.print(f\"Progress: {self.progress}/{self.total}\")\n\n    def start(self):\n        \"\"\"Start the progress bar.\"\"\"\n\n    def stop(self):\n        \"\"\"Stop the progress bar.\"\"\"\n"
  },
  {
    "path": "reflex/utils/decorator.py",
    "content": "\"\"\"Decorator utilities.\"\"\"\n\nimport functools\nfrom collections.abc import Callable\nfrom pathlib import Path\nfrom typing import ParamSpec, TypeVar, cast\n\nT = TypeVar(\"T\")\n\n\ndef once(f: Callable[[], T]) -> Callable[[], T]:\n    \"\"\"A decorator that calls the function once and caches the result.\n\n    Args:\n        f: The function to call.\n\n    Returns:\n        A function that calls the function once and caches the result.\n    \"\"\"\n    unset = object()\n    value: object | T = unset\n\n    @functools.wraps(f)\n    def wrapper() -> T:\n        nonlocal value\n        value = f() if value is unset else value\n        return value  # pyright: ignore[reportReturnType]\n\n    return wrapper\n\n\ndef once_unless_none(f: Callable[[], T | None]) -> Callable[[], T | None]:\n    \"\"\"A decorator that calls the function once and caches the result unless it is None.\n\n    Args:\n        f: The function to call.\n\n    Returns:\n        A function that calls the function once and caches the result unless it is None.\n    \"\"\"\n    value: T | None = None\n\n    @functools.wraps(f)\n    def wrapper() -> T | None:\n        nonlocal value\n        value = f() if value is None else value\n        return value\n\n    return wrapper\n\n\nP = ParamSpec(\"P\")\n\n\ndef debug(f: Callable[P, T]) -> Callable[P, T]:\n    \"\"\"A decorator that prints the function name, arguments, and result.\n\n    Args:\n        f: The function to call.\n\n    Returns:\n        A function that prints the function name, arguments, and result.\n    \"\"\"\n\n    @functools.wraps(f)\n    def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:\n        result = f(*args, **kwargs)\n        print(  # noqa: T201\n            f\"Calling {f.__name__} with args: {args} and kwargs: {kwargs}, result: {result}\"\n        )\n        return result\n\n    return wrapper\n\n\ndef _write_cached_procedure_file(payload: str, cache_file: Path, value: object):\n    import pickle\n\n    cache_file.parent.mkdir(parents=True, exist_ok=True)\n    cache_file.write_bytes(pickle.dumps((payload, value)))\n\n\ndef _read_cached_procedure_file(cache_file: Path) -> tuple[str | None, object]:\n    import pickle\n\n    if cache_file.exists():\n        with cache_file.open(\"rb\") as f:\n            return pickle.loads(f.read())\n\n    return None, None\n\n\nP = ParamSpec(\"P\")\nPicklable = TypeVar(\"Picklable\")\n\n\ndef cached_procedure(\n    cache_file_path: Callable[[], Path],\n    payload_fn: Callable[P, str],\n) -> Callable[[Callable[P, Picklable]], Callable[P, Picklable]]:\n    \"\"\"Decorator to cache the result of a function based on its arguments.\n\n    Args:\n        cache_file_path: Function that computes the cache file path.\n        payload_fn: Function that computes cache payload from function args.\n\n    Returns:\n        The decorated function.\n    \"\"\"\n\n    def _inner_decorator(func: Callable[P, Picklable]) -> Callable[P, Picklable]:\n        def _inner(*args: P.args, **kwargs: P.kwargs) -> Picklable:\n            cache_file = cache_file_path()\n\n            payload, value = _read_cached_procedure_file(cache_file)\n            new_payload = payload_fn(*args, **kwargs)\n\n            if payload != new_payload:\n                new_value = func(*args, **kwargs)\n                _write_cached_procedure_file(new_payload, cache_file, new_value)\n                return new_value\n\n            from reflex.utils import console\n\n            console.debug(\n                f\"Using cached value for {func.__name__} with payload: {new_payload}\"\n            )\n            return cast(\"Picklable\", value)\n\n        return _inner\n\n    return _inner_decorator\n\n\ndef cache_result_in_disk(\n    cache_file_path: Callable[[], Path],\n) -> Callable[[Callable[[], Picklable]], Callable[[], Picklable]]:\n    \"\"\"Decorator to cache the result of a function on disk.\n\n    Args:\n        cache_file_path: Function that computes the cache file path.\n\n    Returns:\n        The decorated function.\n    \"\"\"\n    return cached_procedure(\n        cache_file_path=cache_file_path, payload_fn=lambda: \"constant\"\n    )\n"
  },
  {
    "path": "reflex/utils/exceptions.py",
    "content": "\"\"\"Custom Exceptions.\"\"\"\n\nfrom __future__ import annotations\n\nfrom typing import TYPE_CHECKING, Any\n\nif TYPE_CHECKING:\n    from reflex.vars import Var\n\n\nclass ReflexError(Exception):\n    \"\"\"Base exception for all Reflex exceptions.\"\"\"\n\n\nclass ConfigError(ReflexError):\n    \"\"\"Custom exception for config related errors.\"\"\"\n\n\nclass InvalidStateManagerModeError(ReflexError, ValueError):\n    \"\"\"Raised when an invalid state manager mode is provided.\"\"\"\n\n\nclass ReflexRuntimeError(ReflexError, RuntimeError):\n    \"\"\"Custom RuntimeError for Reflex.\"\"\"\n\n\nclass UploadTypeError(ReflexError, TypeError):\n    \"\"\"Custom TypeError for upload related errors.\"\"\"\n\n\nclass EnvVarValueError(ReflexError, ValueError):\n    \"\"\"Custom ValueError raised when unable to convert env var to expected type.\"\"\"\n\n\nclass ComponentTypeError(ReflexError, TypeError):\n    \"\"\"Custom TypeError for component related errors.\"\"\"\n\n\nclass ChildrenTypeError(ComponentTypeError):\n    \"\"\"Raised when the children prop of a component is not a valid type.\"\"\"\n\n    def __init__(self, component: str, child: Any):\n        \"\"\"Initialize the exception.\n\n        Args:\n            component: The name of the component.\n            child: The child that caused the error.\n        \"\"\"\n        super().__init__(\n            f\"Component {component} received child {child} of type {type(child)}. \"\n            \"Accepted types are other components, state vars, or primitive Python types (dict excluded).\"\n        )\n\n\nclass EventHandlerTypeError(ReflexError, TypeError):\n    \"\"\"Custom TypeError for event handler related errors.\"\"\"\n\n\nclass EventHandlerValueError(ReflexError, ValueError):\n    \"\"\"Custom ValueError for event handler related errors.\"\"\"\n\n\nclass StateValueError(ReflexError, ValueError):\n    \"\"\"Custom ValueError for state related errors.\"\"\"\n\n\nclass VarNameError(ReflexError, NameError):\n    \"\"\"Custom NameError for when a state var has been shadowed by a substate var.\"\"\"\n\n\nclass VarTypeError(ReflexError, TypeError):\n    \"\"\"Custom TypeError for var related errors.\"\"\"\n\n\nclass VarValueError(ReflexError, ValueError):\n    \"\"\"Custom ValueError for var related errors.\"\"\"\n\n\nclass VarAttributeError(ReflexError, AttributeError):\n    \"\"\"Custom AttributeError for var related errors.\"\"\"\n\n\nclass UntypedVarError(ReflexError, TypeError):\n    \"\"\"Custom TypeError for untyped var errors.\"\"\"\n\n    def __init__(self, var: Var, action: str, doc_link: str = \"\"):\n        \"\"\"Create an UntypedVarError from a var.\n\n        Args:\n            var: The var.\n            action: The action that caused the error.\n            doc_link: The link to the documentation.\n        \"\"\"\n        var_data = var._get_all_var_data()\n        is_state_var = (\n            var_data\n            and var_data.state\n            and var_data.field_name\n            and var_data.state + \".\" + var_data.field_name == str(var)\n        )\n        super().__init__(\n            f\"Cannot {action} on untyped var '{var!s}' of type '{var._var_type!s}'.\"\n            + (\n                \" Please add a type annotation to the var in the state class.\"\n                if is_state_var\n                else \" You can call the var's .to(desired_type) method to convert it to the desired type.\"\n            )\n            + (f\" See {doc_link}\" if doc_link else \"\")\n        )\n\n\nclass UntypedComputedVarError(ReflexError, TypeError):\n    \"\"\"Custom TypeError for untyped computed var errors.\"\"\"\n\n    def __init__(self, var_name: str):\n        \"\"\"Initialize the UntypedComputedVarError.\n\n        Args:\n            var_name: The name of the computed var.\n        \"\"\"\n        super().__init__(f\"Computed var '{var_name}' must have a type annotation.\")\n\n\nclass ComputedVarSignatureError(ReflexError, TypeError):\n    \"\"\"Custom TypeError for computed var signature errors.\"\"\"\n\n    def __init__(self, var_name: str, signature: str):\n        \"\"\"Initialize the ComputedVarSignatureError.\n\n        Args:\n            var_name: The name of the var.\n            signature: The invalid signature.\n        \"\"\"\n        super().__init__(f\"Computed var `{var_name}{signature}` cannot take arguments.\")\n\n\nclass MissingAnnotationError(ReflexError, TypeError):\n    \"\"\"Custom TypeError for missing annotations.\"\"\"\n\n    def __init__(self, var_name: str):\n        \"\"\"Initialize the MissingAnnotationError.\n\n        Args:\n            var_name: The name of the var.\n        \"\"\"\n        super().__init__(f\"Var '{var_name}' must have a type annotation.\")\n\n\nclass UploadValueError(ReflexError, ValueError):\n    \"\"\"Custom ValueError for upload related errors.\"\"\"\n\n\nclass PageValueError(ReflexError, ValueError):\n    \"\"\"Custom ValueError for page related errors.\"\"\"\n\n\nclass RouteValueError(ReflexError, ValueError):\n    \"\"\"Custom ValueError for route related errors.\"\"\"\n\n\nclass VarOperationTypeError(ReflexError, TypeError):\n    \"\"\"Custom TypeError for when unsupported operations are performed on vars.\"\"\"\n\n\nclass VarDependencyError(ReflexError, ValueError):\n    \"\"\"Custom ValueError for when a var depends on a non-existent var.\"\"\"\n\n\nclass InvalidStylePropError(ReflexError, TypeError):\n    \"\"\"Custom Type Error when style props have invalid values.\"\"\"\n\n\nclass ImmutableStateError(ReflexError):\n    \"\"\"Raised when a background task attempts to modify state outside of context.\"\"\"\n\n\nclass LockExpiredError(ReflexError):\n    \"\"\"Raised when the state lock expires while an event is being processed.\"\"\"\n\n\nclass MatchTypeError(ReflexError, TypeError):\n    \"\"\"Raised when the return types of match cases are different.\"\"\"\n\n\nclass EventHandlerArgTypeMismatchError(ReflexError, TypeError):\n    \"\"\"Raised when the annotations of args accepted by an EventHandler differs from the spec of the event trigger.\"\"\"\n\n\nclass EventFnArgMismatchError(ReflexError, TypeError):\n    \"\"\"Raised when the number of args required by an event handler is more than provided by the event trigger.\"\"\"\n\n\nclass DynamicRouteArgShadowsStateVarError(ReflexError, NameError):\n    \"\"\"Raised when a dynamic route arg shadows a state var.\"\"\"\n\n\nclass ComputedVarShadowsStateVarError(ReflexError, NameError):\n    \"\"\"Raised when a computed var shadows a state var.\"\"\"\n\n\nclass ComputedVarShadowsBaseVarsError(ReflexError, NameError):\n    \"\"\"Raised when a computed var shadows a base var.\"\"\"\n\n\nclass EventHandlerShadowsBuiltInStateMethodError(ReflexError, NameError):\n    \"\"\"Raised when an event handler shadows a built-in state method.\"\"\"\n\n\nclass GeneratedCodeHasNoFunctionDefsError(ReflexError):\n    \"\"\"Raised when refactored code generated with flexgen has no functions defined.\"\"\"\n\n\nclass PrimitiveUnserializableToJSONError(ReflexError, ValueError):\n    \"\"\"Raised when a primitive type is unserializable to JSON. Usually with NaN and Infinity.\"\"\"\n\n\nclass InvalidLifespanTaskTypeError(ReflexError, TypeError):\n    \"\"\"Raised when an invalid task type is registered as a lifespan task.\"\"\"\n\n\nclass DynamicComponentMissingLibraryError(ReflexError, ValueError):\n    \"\"\"Raised when a dynamic component is missing a library.\"\"\"\n\n\nclass SetUndefinedStateVarError(ReflexError, AttributeError):\n    \"\"\"Raised when setting the value of a var without first declaring it.\"\"\"\n\n\nclass StateSchemaMismatchError(ReflexError, TypeError):\n    \"\"\"Raised when the serialized schema of a state class does not match the current schema.\"\"\"\n\n\nclass EnvironmentVarValueError(ReflexError, ValueError):\n    \"\"\"Raised when an environment variable is set to an invalid value.\"\"\"\n\n\nclass DynamicComponentInvalidSignatureError(ReflexError, TypeError):\n    \"\"\"Raised when a dynamic component has an invalid signature.\"\"\"\n\n\nclass InvalidPropValueError(ReflexError):\n    \"\"\"Raised when a prop value is invalid.\"\"\"\n\n\nclass StateTooLargeError(ReflexError):\n    \"\"\"Raised when the state is too large to be serialized.\"\"\"\n\n\nclass StateSerializationError(ReflexError):\n    \"\"\"Raised when the state cannot be serialized.\"\"\"\n\n\nclass StateMismatchError(ReflexError, ValueError):\n    \"\"\"Raised when the state retrieved does not match the expected state.\"\"\"\n\n\nclass SystemPackageMissingError(ReflexError):\n    \"\"\"Raised when a system package is missing.\"\"\"\n\n    def __init__(self, package: str):\n        \"\"\"Initialize the SystemPackageMissingError.\n\n        Args:\n            package: The missing package.\n        \"\"\"\n        from reflex.constants import IS_MACOS\n\n        extra = (\n            f\" You can do so by running 'brew install {package}'.\" if IS_MACOS else \"\"\n        )\n        super().__init__(\n            f\"System package '{package}' is missing.\"\n            f\" Please install it through your system package manager.{extra}\"\n        )\n\n\nclass EventDeserializationError(ReflexError, ValueError):\n    \"\"\"Raised when an event cannot be deserialized.\"\"\"\n\n\nclass InvalidLockWarningThresholdError(ReflexError):\n    \"\"\"Raised when an invalid lock warning threshold is provided.\"\"\"\n\n\nclass UnretrievableVarValueError(ReflexError):\n    \"\"\"Raised when the value of a var is not retrievable.\"\"\"\n"
  },
  {
    "path": "reflex/utils/exec.py",
    "content": "\"\"\"Everything regarding execution of the built app.\"\"\"\n\nfrom __future__ import annotations\n\nimport hashlib\nimport importlib.util\nimport json\nimport os\nimport platform\nimport re\nimport subprocess\nimport sys\nfrom collections.abc import Sequence\nfrom pathlib import Path\nfrom typing import Any, NamedTuple, TypedDict\nfrom urllib.parse import urljoin\n\nfrom reflex import constants\nfrom reflex.config import get_config\nfrom reflex.constants.base import LogLevel\nfrom reflex.environment import environment\nfrom reflex.utils import console, path_ops\nfrom reflex.utils.decorator import once\nfrom reflex.utils.misc import get_module_path\nfrom reflex.utils.prerequisites import get_web_dir\n\n# For uvicorn windows bug fix (#2335)\nfrontend_process = None\n\n\ndef get_package_json_and_hash(package_json_path: Path) -> tuple[PackageJson, str]:\n    \"\"\"Get the content of package.json and its hash.\n\n    Args:\n        package_json_path: The path to the package.json file.\n\n    Returns:\n        A tuple containing the content of package.json as a dictionary and its SHA-256 hash.\n    \"\"\"\n    with package_json_path.open(\"r\") as file:\n        json_data = json.load(file)\n\n    # Calculate the hash\n    json_string = json.dumps(json_data, sort_keys=True)\n    hash_object = hashlib.sha256(json_string.encode())\n    return (json_data, hash_object.hexdigest())\n\n\nclass PackageJson(TypedDict):\n    \"\"\"package.json content.\"\"\"\n\n    dependencies: dict[str, str]\n    devDependencies: dict[str, str]\n\n\nclass Change(NamedTuple):\n    \"\"\"A named tuple to represent a change in package dependencies.\"\"\"\n\n    added: set[str]\n    removed: set[str]\n\n\ndef format_change(name: str, change: Change) -> str:\n    \"\"\"Format the change for display.\n\n    Args:\n        name: The name of the change (e.g., \"dependencies\" or \"devDependencies\").\n        change: The Change named tuple containing added and removed packages.\n\n    Returns:\n        A formatted string representing the changes.\n    \"\"\"\n    if not change.added and not change.removed:\n        return \"\"\n    added_str = \", \".join(sorted(change.added))\n    removed_str = \", \".join(sorted(change.removed))\n    change_str = f\"{name}:\\n\"\n    if change.added:\n        change_str += f\"  Added: {added_str}\\n\"\n    if change.removed:\n        change_str += f\"  Removed: {removed_str}\\n\"\n    return change_str.strip()\n\n\ndef get_different_packages(\n    old_package_json_content: PackageJson,\n    new_package_json_content: PackageJson,\n) -> tuple[Change, Change]:\n    \"\"\"Get the packages that are different between two package JSON contents.\n\n    Args:\n        old_package_json_content: The content of the old package JSON.\n        new_package_json_content: The content of the new package JSON.\n\n    Returns:\n        A tuple containing two `Change` named tuples:\n        - The first `Change` contains the changes in the `dependencies` section.\n        - The second `Change` contains the changes in the `devDependencies` section.\n    \"\"\"\n\n    def get_changes(old: dict[str, str], new: dict[str, str]) -> Change:\n        \"\"\"Get the changes between two dictionaries.\n\n        Args:\n            old: The old dictionary of packages.\n            new: The new dictionary of packages.\n\n        Returns:\n            A `Change` named tuple containing the added and removed packages.\n        \"\"\"\n        old_keys = set(old.keys())\n        new_keys = set(new.keys())\n        added = new_keys - old_keys\n        removed = old_keys - new_keys\n        return Change(added=added, removed=removed)\n\n    dependencies_change = get_changes(\n        old_package_json_content.get(\"dependencies\", {}),\n        new_package_json_content.get(\"dependencies\", {}),\n    )\n    dev_dependencies_change = get_changes(\n        old_package_json_content.get(\"devDependencies\", {}),\n        new_package_json_content.get(\"devDependencies\", {}),\n    )\n\n    return dependencies_change, dev_dependencies_change\n\n\ndef kill(proc_pid: int):\n    \"\"\"Kills a process and all its child processes.\n\n    Requires the `psutil` library to be installed.\n\n    Args:\n        proc_pid: The process ID of the process to be killed.\n\n    Example:\n        >>> kill(1234)\n    \"\"\"\n    import psutil\n\n    process = psutil.Process(proc_pid)\n    for proc in process.children(recursive=True):\n        proc.kill()\n    process.kill()\n\n\ndef notify_frontend(url: str, backend_present: bool):\n    \"\"\"Output a string notifying where the frontend is running.\n\n    Args:\n        url: The URL where the frontend is running.\n        backend_present: Whether the backend is present.\n    \"\"\"\n    console.print(\n        f\"App running at: [bold green]{url.rstrip('/')}/[/bold green]{' (Frontend-only mode)' if not backend_present else ''}\"\n    )\n\n\ndef notify_backend():\n    \"\"\"Output a string notifying where the backend is running.\"\"\"\n    console.print(\n        f\"Backend running at: [bold green]http://0.0.0.0:{get_config().backend_port}[/bold green]\"\n    )\n\n\n# run_process_and_launch_url is assumed to be used\n# only to launch the frontend\n# If this is not the case, might have to change the logic\ndef run_process_and_launch_url(\n    run_command: list[str | None], backend_present: bool = True\n):\n    \"\"\"Run the process and launch the URL.\n\n    Args:\n        run_command: The command to run.\n        backend_present: Whether the backend is present.\n    \"\"\"\n    from reflex.utils import processes\n\n    json_file_path = get_web_dir() / constants.PackageJson.PATH\n    last_content, last_hash = get_package_json_and_hash(json_file_path)\n    process = None\n    first_run = True\n\n    while True:\n        if process is None:\n            kwargs: dict[str, Any] = {\n                \"env\": {\n                    **os.environ,\n                    \"NO_COLOR\": \"1\",\n                }\n            }\n            if constants.IS_WINDOWS and backend_present:\n                kwargs[\"creationflags\"] = subprocess.CREATE_NEW_PROCESS_GROUP  # pyright: ignore [reportAttributeAccessIssue]\n            process = processes.new_process(\n                run_command,\n                cwd=get_web_dir(),\n                shell=constants.IS_WINDOWS,\n                **kwargs,\n            )\n            global frontend_process\n            frontend_process = process\n        if process.stdout:\n            for line in processes.stream_logs(\"Starting frontend\", process):\n                new_content, new_hash = get_package_json_and_hash(json_file_path)\n                if new_hash != last_hash:\n                    dependencies_change, dev_dependencies_change = (\n                        get_different_packages(last_content, new_content)\n                    )\n                    last_content, last_hash = new_content, new_hash\n                    console.info(\n                        \"Detected changes in package.json.\\n\"\n                        + format_change(\"Dependencies\", dependencies_change)\n                        + format_change(\"Dev Dependencies\", dev_dependencies_change)\n                    )\n\n                match = re.search(constants.ReactRouter.FRONTEND_LISTENING_REGEX, line)\n                if match:\n                    if first_run:\n                        url = match.group(1)\n                        if get_config().frontend_path != \"\":\n                            url = urljoin(url, get_config().frontend_path)\n\n                        notify_frontend(url, backend_present)\n                        if backend_present:\n                            notify_backend()\n                        first_run = False\n                    else:\n                        console.print(\"Frontend is restarting...\")\n\n        if process is not None:\n            break  # while True\n\n\ndef run_frontend(root: Path, port: str, backend_present: bool = True):\n    \"\"\"Run the frontend.\n\n    Args:\n        root: The root path of the project.\n        port: The port to run the frontend on.\n        backend_present: Whether the backend is present.\n    \"\"\"\n    from reflex.utils import js_runtimes\n\n    # validate dependencies before run\n    js_runtimes.validate_frontend_dependencies(init=False)\n\n    # Run the frontend in development mode.\n    console.rule(\"[bold green]App Running\")\n    os.environ[\"PORT\"] = str(get_config().frontend_port if port is None else port)\n    run_process_and_launch_url(\n        [\n            *js_runtimes.get_js_package_executor(raise_on_none=True)[0],\n            \"run\",\n            \"dev\",\n        ],\n        backend_present,\n    )\n\n\ndef notify_app_running():\n    \"\"\"Notify that the app is running.\"\"\"\n    console.rule(\"[bold green]App Running\")\n\n\ndef run_frontend_prod(root: Path, port: str, backend_present: bool = True):\n    \"\"\"Run the frontend.\n\n    Args:\n        root: The root path of the project (to keep same API as run_frontend).\n        port: The port to run the frontend on.\n        backend_present: Whether the backend is present.\n    \"\"\"\n    from reflex.utils import js_runtimes\n\n    # Set the port.\n    os.environ[\"PORT\"] = str(get_config().frontend_port if port is None else port)\n    # validate dependencies before run\n    js_runtimes.validate_frontend_dependencies(init=False)\n    # Run the frontend in production mode.\n    notify_app_running()\n    run_process_and_launch_url(\n        [*js_runtimes.get_js_package_executor(raise_on_none=True)[0], \"run\", \"prod\"],\n        backend_present,\n    )\n\n\n@once\ndef _warn_user_about_uvicorn():\n    console.warn(\n        \"Using Uvicorn for backend as it is installed. This behavior will change in 0.8.0 to use Granian by default.\"\n    )\n\n\ndef should_use_granian():\n    \"\"\"Whether to use Granian for backend.\n\n    Returns:\n        True if Granian should be used.\n    \"\"\"\n    if environment.REFLEX_USE_GRANIAN.is_set():\n        return environment.REFLEX_USE_GRANIAN.get()\n    if (\n        importlib.util.find_spec(\"uvicorn\") is None\n        or importlib.util.find_spec(\"gunicorn\") is None\n    ):\n        return True\n    _warn_user_about_uvicorn()\n    return False\n\n\ndef get_app_module():\n    \"\"\"Get the app module for the backend.\n\n    Returns:\n        The app module for the backend.\n    \"\"\"\n    return get_config().module\n\n\ndef get_app_instance():\n    \"\"\"Get the app module for the backend.\n\n    Returns:\n        The app module for the backend.\n    \"\"\"\n    return f\"{get_app_module()}:{constants.CompileVars.APP}\"\n\n\ndef get_app_file() -> Path:\n    \"\"\"Get the app file for the backend.\n\n    Returns:\n        The app file for the backend.\n\n    Raises:\n        ImportError: If the app module is not found.\n    \"\"\"\n    current_working_dir = str(Path.cwd())\n    if current_working_dir not in sys.path:\n        # Add the current working directory to sys.path\n        sys.path.insert(0, current_working_dir)\n    app_module = get_app_module()\n    module_path = get_module_path(app_module)\n    if module_path is None:\n        msg = f\"Module {app_module} not found. Make sure the module is installed.\"\n        raise ImportError(msg)\n    return module_path\n\n\ndef get_app_instance_from_file() -> str:\n    \"\"\"Get the app module for the backend.\n\n    Returns:\n        The app module for the backend.\n    \"\"\"\n    return f\"{get_app_file()}:{constants.CompileVars.APP}\"\n\n\ndef run_backend(\n    host: str,\n    port: int,\n    loglevel: constants.LogLevel = constants.LogLevel.ERROR,\n    frontend_present: bool = False,\n):\n    \"\"\"Run the backend.\n\n    Args:\n        host: The app host\n        port: The app port\n        loglevel: The log level.\n        frontend_present: Whether the frontend is present.\n    \"\"\"\n    web_dir = get_web_dir()\n    # Create a .nocompile file to skip compile for backend.\n    if web_dir.exists():\n        (web_dir / constants.NOCOMPILE_FILE).touch()\n\n    if not frontend_present:\n        notify_backend()\n\n    # Run the backend in development mode.\n    if should_use_granian():\n        # We import reflex app because this lets granian cache the module\n        import reflex.app  # noqa: F401\n\n        run_granian_backend(host, port, loglevel)\n    else:\n        run_uvicorn_backend(host, port, loglevel)\n\n\ndef _has_child_file(directory: Path, file_name: str) -> bool:\n    \"\"\"Check if a directory has a child file with the given name.\n\n    Args:\n        directory: The directory to check.\n        file_name: The name of the file to look for.\n\n    Returns:\n        True if the directory has a child file with the given name, False otherwise.\n    \"\"\"\n    return any(child_file.name == file_name for child_file in directory.iterdir())\n\n\ndef get_reload_paths() -> Sequence[Path]:\n    \"\"\"Get the reload paths for the backend.\n\n    Returns:\n        The reload paths for the backend.\n\n    Raises:\n        RuntimeError: If the `__init__.py` file is found in the app root directory.\n    \"\"\"\n    config = get_config()\n    reload_paths = [Path.cwd()]\n    app_module = config.module\n    module_path = get_module_path(app_module)\n    if module_path is not None:\n        module_path = module_path.parent\n\n        while module_path.parent.name and _has_child_file(module_path, \"__init__.py\"):\n            if (\n                _has_child_file(module_path, \"rxconfig.py\")\n                and module_path == Path.cwd()\n            ):\n                init_file = module_path / \"__init__.py\"\n                init_file_content = init_file.read_text()\n                if init_file_content.strip():\n                    msg = \"There should not be an `__init__.py` file in your app root directory\"\n                    raise RuntimeError(msg)\n                console.warn(\n                    \"Removing `__init__.py` file in the app root directory. \"\n                    \"This file can cause issues with module imports. \"\n                )\n                init_file.unlink()\n                break\n\n            # go up a level to find dir without `__init__.py` or with `rxconfig.py`\n            module_path = module_path.parent\n\n        reload_paths = [module_path]\n\n    include_dirs = tuple(\n        map(Path.absolute, environment.REFLEX_HOT_RELOAD_INCLUDE_PATHS.get())\n    )\n    exclude_dirs = tuple(\n        map(Path.absolute, environment.REFLEX_HOT_RELOAD_EXCLUDE_PATHS.get())\n    )\n\n    def is_excluded_by_default(path: Path) -> bool:\n        if path.is_dir():\n            if path.name.startswith(\".\"):\n                # exclude hidden directories\n                return True\n            if path.name.startswith(\"__\"):\n                # ignore things like __pycache__\n                return True\n        return path.name in (\".gitignore\", \"uploaded_files\")\n\n    reload_paths = (\n        tuple(\n            path.absolute()\n            for dir in reload_paths\n            for path in dir.iterdir()\n            if not is_excluded_by_default(path)\n        )\n        + include_dirs\n    )\n\n    if exclude_dirs:\n        reload_paths = tuple(\n            path\n            for path in reload_paths\n            if all(not path.samefile(exclude) for exclude in exclude_dirs)\n        )\n\n    console.debug(f\"Reload paths: {list(map(str, reload_paths))}\")\n\n    return reload_paths\n\n\ndef run_uvicorn_backend(host: str, port: int, loglevel: LogLevel):\n    \"\"\"Run the backend in development mode using Uvicorn.\n\n    Args:\n        host: The app host\n        port: The app port\n        loglevel: The log level.\n    \"\"\"\n    import uvicorn\n\n    uvicorn.run(\n        app=f\"{get_app_instance()}\",\n        factory=True,\n        host=host,\n        port=port,\n        log_level=loglevel.value,\n        reload=True,\n        reload_dirs=list(map(str, get_reload_paths())),\n        reload_delay=0.1,\n    )\n\n\nHOTRELOAD_IGNORE_EXTENSIONS = (\n    \"txt\",\n    \"toml\",\n    \"sqlite\",\n    \"yaml\",\n    \"yml\",\n    \"json\",\n    \"sh\",\n    \"bash\",\n    \"log\",\n    \"db\",\n)\n\nHOTRELOAD_IGNORE_PATTERNS = (\n    *[rf\"^.*\\.{ext}$\" for ext in HOTRELOAD_IGNORE_EXTENSIONS],\n    r\"^[^\\.]*$\",  # Ignore files without an extension\n)\n\n\ndef run_granian_backend(host: str, port: int, loglevel: LogLevel):\n    \"\"\"Run the backend in development mode using Granian.\n\n    Args:\n        host: The app host\n        port: The app port\n        loglevel: The log level.\n    \"\"\"\n    console.debug(\"Using Granian for backend\")\n\n    if environment.REFLEX_STRICT_HOT_RELOAD.get():\n        import multiprocessing\n\n        multiprocessing.set_start_method(\"spawn\", force=True)\n\n    from granian.constants import Interfaces\n    from granian.log import LogLevels\n    from granian.server import Server as Granian\n\n    from reflex.environment import _load_dotenv_from_env\n\n    granian_app = Granian(\n        target=get_app_instance_from_file(),\n        factory=True,\n        address=host,\n        port=port,\n        interface=Interfaces.ASGI,\n        log_level=LogLevels(loglevel.value),\n        reload=True,\n        reload_paths=get_reload_paths(),\n        reload_ignore_worker_failure=True,\n        reload_ignore_patterns=HOTRELOAD_IGNORE_PATTERNS,\n        reload_tick=100,\n        workers_kill_timeout=2,\n    )\n\n    granian_app.on_reload(_load_dotenv_from_env)\n\n    granian_app.serve()\n\n\ndef run_backend_prod(\n    host: str,\n    port: int,\n    loglevel: constants.LogLevel = constants.LogLevel.ERROR,\n    frontend_present: bool = False,\n    mount_frontend_compiled_app: bool = False,\n):\n    \"\"\"Run the backend.\n\n    Args:\n        host: The app host\n        port: The app port\n        loglevel: The log level.\n        frontend_present: Whether the frontend is present.\n        mount_frontend_compiled_app: Whether to mount the compiled frontend app with the backend.\n    \"\"\"\n    if not frontend_present:\n        notify_backend()\n\n    environment.REFLEX_MOUNT_FRONTEND_COMPILED_APP.set(mount_frontend_compiled_app)\n\n    if should_use_granian():\n        run_granian_backend_prod(host, port, loglevel)\n    else:\n        run_uvicorn_backend_prod(host, port, loglevel)\n\n\ndef _get_backend_workers():\n    from reflex.utils import processes\n\n    return processes.get_num_workers()\n\n\ndef run_uvicorn_backend_prod(host: str, port: int, loglevel: LogLevel):\n    \"\"\"Run the backend in production mode using Uvicorn.\n\n    Args:\n        host: The app host\n        port: The app port\n        loglevel: The log level.\n    \"\"\"\n    import os\n    import shlex\n\n    from reflex.utils import processes\n\n    app_module = get_app_instance()\n\n    if constants.IS_WINDOWS:\n        command = [\n            sys.executable,\n            \"-m\",\n            \"uvicorn\",\n            *(\"--host\", host),\n            *(\"--port\", str(port)),\n            *(\"--workers\", str(_get_backend_workers())),\n            \"--factory\",\n            app_module,\n        ]\n    else:\n        # Parse GUNICORN_CMD_ARGS for user overrides\n        env_args = []\n        if gunicorn_cmd_args := os.environ.get(\"GUNICORN_CMD_ARGS\", \"\"):\n            env_args = shlex.split(gunicorn_cmd_args)\n\n        # Our default args, then env args (env args win on conflicts)\n        command = [\n            sys.executable,\n            \"-m\",\n            \"gunicorn\",\n            \"--preload\",\n            *(\"--worker-class\", \"uvicorn.workers.UvicornH11Worker\"),\n            *(\"--threads\", str(_get_backend_workers())),\n            *(\"--bind\", f\"{host}:{port}\"),\n            *env_args,\n            f\"{app_module}()\",\n        ]\n\n    command += [\n        *(\"--log-level\", loglevel.value),\n    ]\n\n    processes.new_process(\n        command,\n        run=True,\n        show_logs=True,\n        env={\n            environment.REFLEX_SKIP_COMPILE.name: \"true\"\n        },  # skip compile for prod backend\n    )\n\n\ndef run_granian_backend_prod(host: str, port: int, loglevel: LogLevel):\n    \"\"\"Run the backend in production mode using Granian.\n\n    Args:\n        host: The app host\n        port: The app port\n        loglevel: The log level.\n    \"\"\"\n    from granian.constants import Interfaces\n\n    from reflex.utils import processes\n\n    command = [\n        sys.executable,\n        \"-m\",\n        \"granian\",\n        *(\"--host\", host),\n        *(\"--port\", str(port)),\n        *(\"--interface\", str(Interfaces.ASGI)),\n        *(\"--factory\", get_app_instance_from_file()),\n    ]\n\n    extra_env = {\n        environment.REFLEX_SKIP_COMPILE.name: \"true\",  # skip compile for prod backend\n    }\n\n    if \"GRANIAN_WORKERS\" not in os.environ:\n        extra_env[\"GRANIAN_WORKERS\"] = str(_get_backend_workers())\n    if \"GRANIAN_LOG_LEVEL\" not in os.environ:\n        extra_env[\"GRANIAN_LOG_LEVEL\"] = \"critical\"\n\n    processes.new_process(\n        command,\n        run=True,\n        show_logs=True,\n        env=extra_env,\n    )\n\n\ndef output_system_info():\n    \"\"\"Show system information if the loglevel is in DEBUG.\"\"\"\n    if console._LOG_LEVEL > constants.LogLevel.DEBUG:\n        return\n\n    from reflex.utils import js_runtimes\n\n    config = get_config()\n    try:\n        config_file = sys.modules[config.__module__].__file__\n    except Exception:\n        config_file = None\n\n    console.rule(\"System Info\")\n    console.debug(f\"Config file: {config_file!r}\")\n    console.debug(f\"Config: {config}\")\n\n    dependencies = [\n        f\"[Reflex {constants.Reflex.VERSION} with Python {platform.python_version()} (PATH: {sys.executable})]\",\n        f\"[Node {js_runtimes.get_node_version()} (Minimum: {constants.Node.MIN_VERSION}) (PATH:{path_ops.get_node_path()})]\",\n    ]\n\n    system = platform.system()\n\n    dependencies.append(\n        f\"[Bun {js_runtimes.get_bun_version()} (Minimum: {constants.Bun.MIN_VERSION}) (PATH: {path_ops.get_bun_path()})]\"\n    )\n\n    if system == \"Linux\":\n        os_version = platform.freedesktop_os_release().get(\"PRETTY_NAME\", \"Unknown\")\n    else:\n        os_version = platform.version()\n\n    dependencies.append(f\"[OS {platform.system()} {os_version}]\")\n\n    for dep in dependencies:\n        console.debug(f\"{dep}\")\n\n    console.debug(\n        f\"Using package installer at: {js_runtimes.get_nodejs_compatible_package_managers(raise_on_none=False)}\"\n    )\n    console.debug(\n        f\"Using package executer at: {js_runtimes.get_js_package_executor(raise_on_none=False)}\"\n    )\n    if system != \"Windows\":\n        console.debug(f\"Unzip path: {path_ops.which('unzip')}\")\n\n\ndef is_testing_env() -> bool:\n    \"\"\"Whether the app is running in a testing environment.\n\n    Returns:\n        True if the app is running in under pytest.\n    \"\"\"\n    return constants.PYTEST_CURRENT_TEST in os.environ\n\n\ndef is_in_app_harness() -> bool:\n    \"\"\"Whether the app is running in the app harness.\n\n    Returns:\n        True if the app is running in the app harness.\n    \"\"\"\n    return constants.APP_HARNESS_FLAG in os.environ\n\n\ndef is_prod_mode() -> bool:\n    \"\"\"Check if the app is running in production mode.\n\n    Returns:\n        True if the app is running in production mode or False if running in dev mode.\n    \"\"\"\n    current_mode = environment.REFLEX_ENV_MODE.get()\n    return current_mode == constants.Env.PROD\n\n\ndef should_prerender_routes() -> bool:\n    \"\"\"Check if the app should prerender routes.\n\n    Returns:\n        True if the app should prerender routes.\n    \"\"\"\n    if not environment.REFLEX_SSR.is_set():\n        return is_prod_mode()\n    return environment.REFLEX_SSR.get()\n\n\ndef get_compile_context() -> constants.CompileContext:\n    \"\"\"Check if the app is compiled for deploy.\n\n    Returns:\n        Whether the app is being compiled for deploy.\n    \"\"\"\n    return environment.REFLEX_COMPILE_CONTEXT.get()\n"
  },
  {
    "path": "reflex/utils/export.py",
    "content": "\"\"\"Export utilities.\"\"\"\n\nfrom pathlib import Path\n\nfrom reflex import constants\nfrom reflex.config import get_config\nfrom reflex.environment import environment\nfrom reflex.utils import build, console, exec, prerequisites, telemetry\n\n\ndef export(\n    zipping: bool = True,\n    frontend: bool = True,\n    backend: bool = True,\n    zip_dest_dir: str = str(Path.cwd()),\n    upload_db_file: bool = False,\n    api_url: str | None = None,\n    deploy_url: str | None = None,\n    env: constants.Env = constants.Env.PROD,\n    loglevel: constants.LogLevel = console._LOG_LEVEL,\n    backend_excluded_dirs: tuple[Path, ...] = (),\n    prerender_routes: bool = True,\n):\n    \"\"\"Export the app to a zip file.\n\n    Args:\n        zipping: Whether to zip the exported app. Defaults to True.\n        frontend: Whether to export the frontend. Defaults to True.\n        backend: Whether to export the backend. Defaults to True.\n        zip_dest_dir: The directory to export the zip file to. Defaults to os.getcwd().\n        upload_db_file: Whether to upload the database file. Defaults to False.\n        api_url: The API URL to use. Defaults to None.\n        deploy_url: The deploy URL to use. Defaults to None.\n        env: The environment to use. Defaults to constants.Env.PROD.\n        loglevel: The log level to use. Defaults to console._LOG_LEVEL.\n        backend_excluded_dirs: A tuple of files or directories to exclude from the backend zip.  Defaults to ().\n        prerender_routes: Whether to prerender the routes. Defaults to True.\n    \"\"\"\n    config = get_config()\n\n    # Set the log level.\n    console.set_log_level(loglevel)\n\n    # Set env mode in the environment\n    environment.REFLEX_ENV_MODE.set(env)\n\n    # Override the config url values if provided.\n    if api_url is not None:\n        config._set_persistent(api_url=str(api_url))\n        console.debug(f\"overriding API URL: {config.api_url}\")\n    if deploy_url is not None:\n        config._set_persistent(deploy_url=str(deploy_url))\n        console.debug(f\"overriding deploy URL: {config.deploy_url}\")\n\n    # Show system info\n    exec.output_system_info()\n\n    # Compile the app in production mode and export it.\n    console.rule(\"[bold]Compiling production app and preparing for export.\")\n\n    if frontend:\n        # Ensure module can be imported and app.compile() is called.\n        prerequisites.get_compiled_app(prerender_routes=prerender_routes)\n        # Set up .web directory and install frontend dependencies.\n        build.setup_frontend(Path.cwd())\n\n    # Build the static app.\n    if frontend:\n        build.build()\n\n    # Zip up the app.\n    if zipping:\n        build.zip_app(\n            frontend=frontend,\n            backend=backend,\n            zip_dest_dir=zip_dest_dir,\n            include_db_file=upload_db_file,\n            backend_excluded_dirs=backend_excluded_dirs,\n        )\n\n    # Post a telemetry event.\n    telemetry.send(\"export\")\n"
  },
  {
    "path": "reflex/utils/format.py",
    "content": "\"\"\"Formatting operations.\"\"\"\n\nfrom __future__ import annotations\n\nimport inspect\nimport json\nimport os\nimport re\nfrom typing import TYPE_CHECKING, Any\n\nfrom reflex import constants\nfrom reflex.constants.state import FRONTEND_EVENT_STATE\nfrom reflex.utils import exceptions\n\nif TYPE_CHECKING:\n    from reflex.components.component import ComponentStyle\n    from reflex.event import ArgsSpec, EventChain, EventHandler, EventSpec, EventType\n\nWRAP_MAP = {\n    \"{\": \"}\",\n    \"(\": \")\",\n    \"[\": \"]\",\n    \"<\": \">\",\n    '\"': '\"',\n    \"'\": \"'\",\n    \"`\": \"`\",\n}\n\n\ndef length_of_largest_common_substring(str1: str, str2: str) -> int:\n    \"\"\"Find the length of the largest common substring between two strings.\n\n    Args:\n        str1: The first string.\n        str2: The second string.\n\n    Returns:\n        The length of the largest common substring.\n    \"\"\"\n    if not str1 or not str2:\n        return 0\n\n    # Create a matrix of size (len(str1) + 1) x (len(str2) + 1)\n    dp = [[0] * (len(str2) + 1) for _ in range(len(str1) + 1)]\n\n    # Variables to keep track of maximum length and ending position\n    max_length = 0\n\n    # Fill the dp matrix\n    for i in range(1, len(str1) + 1):\n        for j in range(1, len(str2) + 1):\n            if str1[i - 1] == str2[j - 1]:\n                dp[i][j] = dp[i - 1][j - 1] + 1\n                if dp[i][j] > max_length:\n                    max_length = dp[i][j]\n\n    return max_length\n\n\ndef get_close_char(open: str, close: str | None = None) -> str:\n    \"\"\"Check if the given character is a valid brace.\n\n    Args:\n        open: The open character.\n        close: The close character if provided.\n\n    Returns:\n        The close character.\n\n    Raises:\n        ValueError: If the open character is not a valid brace.\n    \"\"\"\n    if close is not None:\n        return close\n    if open not in WRAP_MAP:\n        msg = f\"Invalid wrap open: {open}, must be one of {WRAP_MAP.keys()}\"\n        raise ValueError(msg)\n    return WRAP_MAP[open]\n\n\ndef is_wrapped(text: str, open: str, close: str | None = None) -> bool:\n    \"\"\"Check if the given text is wrapped in the given open and close characters.\n\n    \"(a) + (b)\" --> False\n    \"((abc))\"   --> True\n    \"(abc)\"     --> True\n\n    Args:\n        text: The text to check.\n        open: The open character.\n        close: The close character.\n\n    Returns:\n        Whether the text is wrapped.\n    \"\"\"\n    close = get_close_char(open, close)\n    if not (text.startswith(open) and text.endswith(close)):\n        return False\n\n    depth = 0\n    for ch in text[:-1]:\n        if ch == open:\n            depth += 1\n        if ch == close:\n            depth -= 1\n        if depth == 0:  # it shouldn't close before the end\n            return False\n    return True\n\n\ndef wrap(\n    text: str,\n    open: str,\n    close: str | None = None,\n    check_first: bool = True,\n    num: int = 1,\n) -> str:\n    \"\"\"Wrap the given text in the given open and close characters.\n\n    Args:\n        text: The text to wrap.\n        open: The open character.\n        close: The close character.\n        check_first: Whether to check if the text is already wrapped.\n        num: The number of times to wrap the text.\n\n    Returns:\n        The wrapped text.\n    \"\"\"\n    close = get_close_char(open, close)\n\n    # If desired, check if the text is already wrapped in braces.\n    if check_first and is_wrapped(text=text, open=open, close=close):\n        return text\n\n    # Wrap the text in braces.\n    return f\"{open * num}{text}{close * num}\"\n\n\ndef indent(text: str, indent_level: int = 2) -> str:\n    \"\"\"Indent the given text by the given indent level.\n\n    Args:\n        text: The text to indent.\n        indent_level: The indent level.\n\n    Returns:\n        The indented text.\n    \"\"\"\n    lines = text.splitlines()\n    if len(lines) < 2:\n        return text\n    return os.linesep.join(f\"{' ' * indent_level}{line}\" for line in lines) + os.linesep\n\n\ndef to_snake_case(text: str) -> str:\n    \"\"\"Convert a string to snake case.\n\n    The words in the text are converted to lowercase and\n    separated by underscores.\n\n    Args:\n        text: The string to convert.\n\n    Returns:\n        The snake case string.\n    \"\"\"\n    s1 = re.sub(r\"(.)([A-Z][a-z]+)\", r\"\\1_\\2\", text)\n    return re.sub(r\"([a-z0-9])([A-Z])\", r\"\\1_\\2\", s1).lower().replace(\"-\", \"_\")\n\n\ndef to_camel_case(text: str, treat_hyphens_as_underscores: bool = True) -> str:\n    \"\"\"Convert a string to camel case.\n\n    The first word in the text is converted to lowercase and\n    the rest of the words are converted to title case, removing underscores.\n\n    Args:\n        text: The string to convert.\n        treat_hyphens_as_underscores: Whether to allow hyphens in the string.\n\n    Returns:\n        The camel case string.\n    \"\"\"\n    if treat_hyphens_as_underscores:\n        text = text.replace(\"-\", \"_\")\n    words = text.split(\"_\")\n    # Capitalize the first letter of each word except the first one\n    if len(words) == 1:\n        return words[0]\n    return words[0] + \"\".join([w.capitalize() for w in words[1:]])\n\n\ndef to_title_case(text: str, sep: str = \"\") -> str:\n    \"\"\"Convert a string from snake case to title case.\n\n    Args:\n        text: The string to convert.\n        sep: The separator to use to join the words.\n\n    Returns:\n        The title case string.\n    \"\"\"\n    return sep.join(word.title() for word in text.split(\"_\"))\n\n\ndef to_kebab_case(text: str) -> str:\n    \"\"\"Convert a string to kebab case.\n\n    The words in the text are converted to lowercase and\n    separated by hyphens.\n\n    Args:\n        text: The string to convert.\n\n    Returns:\n        The title case string.\n    \"\"\"\n    return to_snake_case(text).replace(\"_\", \"-\")\n\n\ndef make_default_page_title(app_name: str, route: str) -> str:\n    \"\"\"Make a default page title from a route.\n\n    Args:\n        app_name: The name of the app owning the page.\n        route: The route to make the title from.\n\n    Returns:\n        The default page title.\n    \"\"\"\n    route_parts = [\n        part\n        for part in route.split(\"/\")\n        if part and not (part.startswith(\"[\") and part.endswith(\"]\"))\n    ]\n\n    title = constants.DefaultPage.TITLE.format(\n        app_name, route_parts[-1] if route_parts else constants.PageNames.INDEX_ROUTE\n    )\n    return to_title_case(title)\n\n\ndef _escape_js_string(string: str) -> str:\n    \"\"\"Escape the string for use as a JS string literal.\n\n    Args:\n        string: The string to escape.\n\n    Returns:\n        The escaped string.\n    \"\"\"\n\n    # TODO: we may need to re-visit this logic after new Var API is implemented.\n    def escape_outside_segments(segment: str):\n        \"\"\"Escape backticks in segments outside of `${}`.\n\n        Args:\n            segment: The part of the string to escape.\n\n        Returns:\n            The escaped or unescaped segment.\n        \"\"\"\n        if segment.startswith(\"${\") and segment.endswith(\"}\"):\n            # Return the `${}` segment unchanged\n            return segment\n        # Escape backticks in the segment\n        return segment.replace(r\"\\`\", \"`\").replace(\"`\", r\"\\`\")\n\n    # Split the string into parts, keeping the `${}` segments\n    parts = re.split(r\"(\\$\\{.*?\\})\", string)\n    escaped_parts = [escape_outside_segments(part) for part in parts]\n    return \"\".join(escaped_parts)\n\n\ndef _wrap_js_string(string: str) -> str:\n    \"\"\"Wrap string so it looks like {`string`}.\n\n    Args:\n        string: The string to wrap.\n\n    Returns:\n        The wrapped string.\n    \"\"\"\n    string = wrap(string, \"`\")\n    return wrap(string, \"{\")\n\n\ndef format_string(string: str) -> str:\n    \"\"\"Format the given string as a JS string literal..\n\n    Args:\n        string: The string to format.\n\n    Returns:\n        The formatted string.\n    \"\"\"\n    return _wrap_js_string(_escape_js_string(string))\n\n\ndef format_var(var: Var) -> str:\n    \"\"\"Format the given Var as a javascript value.\n\n    Args:\n        var: The Var to format.\n\n    Returns:\n        The formatted Var.\n    \"\"\"\n    return str(var)\n\n\ndef format_route(route: str) -> str:\n    \"\"\"Format the given route.\n\n    Args:\n        route: The route to format.\n\n    Returns:\n        The formatted route.\n    \"\"\"\n    route = route.strip(\"/\")\n\n    # If the route is empty, return the index route.\n    if route == \"\":\n        return constants.PageNames.INDEX_ROUTE\n\n    return route\n\n\ndef format_match(\n    cond: str | Var,\n    match_cases: list[tuple[list[Var], Var]],\n    default: Var,\n) -> str:\n    \"\"\"Format a match expression whose return type is a Var.\n\n    Args:\n        cond: The condition.\n        match_cases: The list of cases to match.\n        default: The default case.\n\n    Returns:\n        The formatted match expression\n\n    \"\"\"\n    switch_code = f\"(() => {{ switch (JSON.stringify({cond})) {{\"\n\n    for case in match_cases:\n        conditions, return_value = case\n\n        case_conditions = \" \".join([\n            f\"case JSON.stringify({condition!s}):\" for condition in conditions\n        ])\n        case_code = f\"{case_conditions}  return ({return_value!s});  break;\"\n        switch_code += case_code\n\n    switch_code += f\"default:  return ({default!s});  break;\"\n    switch_code += \"};})()\"\n\n    return switch_code\n\n\ndef format_prop(\n    prop: Var | EventChain | ComponentStyle | str,\n) -> int | float | str:\n    \"\"\"Format a prop.\n\n    Args:\n        prop: The prop to format.\n\n    Returns:\n        The formatted prop to display within a tag.\n\n    Raises:\n        exceptions.InvalidStylePropError: If the style prop value is not a valid type.\n        TypeError: If the prop is not valid.\n        ValueError: If the prop is not a string.\n    \"\"\"\n    # import here to avoid circular import.\n    from reflex.event import EventChain\n    from reflex.utils import serializers\n    from reflex.vars import Var\n\n    try:\n        # Handle var props.\n        if isinstance(prop, Var):\n            return str(prop)\n\n        # Handle event props.\n        if isinstance(prop, EventChain):\n            return str(Var.create(prop))\n\n        # Handle other types.\n        if isinstance(prop, str):\n            if is_wrapped(prop, \"{\"):\n                return prop\n            return json_dumps(prop)\n\n        # For dictionaries, convert any properties to strings.\n        if isinstance(prop, dict):\n            prop = serializers.serialize_dict(prop)  # pyright: ignore [reportAttributeAccessIssue]\n\n        else:\n            # Dump the prop as JSON.\n            prop = json_dumps(prop)\n    except exceptions.InvalidStylePropError:\n        raise\n    except TypeError as e:\n        msg = f\"Could not format prop: {prop} of type {type(prop)}\"\n        raise TypeError(msg) from e\n\n    # Wrap the variable in braces.\n    if not isinstance(prop, str):\n        msg = f\"Invalid prop: {prop}. Expected a string.\"\n        raise ValueError(msg)\n    return wrap(prop, \"{\", check_first=False)\n\n\ndef format_props(*single_props, **key_value_props) -> list[str]:\n    \"\"\"Format the tag's props.\n\n    Args:\n        single_props: Props that are not key-value pairs.\n        key_value_props: Props that are key-value pairs.\n\n    Returns:\n        The formatted props list.\n    \"\"\"\n    # Format all the props.\n    from reflex.vars import LiteralStringVar, LiteralVar, Var\n\n    return [\n        (str(LiteralStringVar.create(name)) if \"-\" in name else name)\n        + \":\"\n        + str(format_prop(prop if isinstance(prop, Var) else LiteralVar.create(prop)))\n        for name, prop in sorted(key_value_props.items())\n        if prop is not None\n    ] + [(f\"...{LiteralVar.create(prop)!s}\") for prop in single_props]\n\n\ndef get_event_handler_parts(handler: EventHandler) -> tuple[str, str]:\n    \"\"\"Get the state and function name of an event handler.\n\n    Args:\n        handler: The event handler to get the parts of.\n\n    Returns:\n        The state and function name.\n    \"\"\"\n    # Get the class that defines the event handler.\n    parts = handler.fn.__qualname__.split(\".\")\n\n    # Get the state full name\n    state_full_name = handler.state_full_name\n\n    # If there's no enclosing class, just return the function name.\n    if not state_full_name:\n        return (\"\", parts[-1])\n\n    # Get the function name\n    name = parts[-1]\n\n    from reflex.state import State\n\n    if state_full_name == FRONTEND_EVENT_STATE and name not in State.__dict__:\n        return (\"\", to_snake_case(handler.fn.__qualname__))\n\n    return (state_full_name, name)\n\n\ndef format_event_handler(handler: EventHandler) -> str:\n    \"\"\"Format an event handler.\n\n    Args:\n        handler: The event handler to format.\n\n    Returns:\n        The formatted function.\n    \"\"\"\n    state, name = get_event_handler_parts(handler)\n    if state == \"\":\n        return name\n    return f\"{state}.{name}\"\n\n\ndef format_event(event_spec: EventSpec) -> str:\n    \"\"\"Format an event.\n\n    Args:\n        event_spec: The event to format.\n\n    Returns:\n        The compiled event.\n    \"\"\"\n    args = \",\".join([\n        \":\".join((\n            name._js_expr,\n            (\n                wrap(\n                    json.dumps(val._js_expr).strip('\"').replace(\"`\", \"\\\\`\"),\n                    \"`\",\n                )\n                if val._var_is_string\n                else str(val)\n            ),\n        ))\n        for name, val in event_spec.args\n    ])\n    event_args = [\n        wrap(format_event_handler(event_spec.handler), '\"'),\n    ]\n    event_args.append(wrap(args, \"{\"))\n\n    if event_spec.client_handler_name:\n        event_args.append(wrap(event_spec.client_handler_name, '\"'))\n    return f\"ReflexEvent({', '.join(event_args)})\"\n\n\nif TYPE_CHECKING:\n    from reflex.vars import Var\n\n\ndef format_queue_events(\n    events: EventType[Any] | None = None,\n    args_spec: ArgsSpec | None = None,\n) -> Var[EventChain]:\n    \"\"\"Format a list of event handler / event spec as a javascript callback.\n\n    The resulting code can be passed to interfaces that expect a callback\n    function and when triggered it will directly call queueEvents.\n\n    It is intended to be executed in the rx.call_script context, where some\n    existing API needs a callback to trigger a backend event handler.\n\n    Args:\n        events: The events to queue.\n        args_spec: The argument spec for the callback.\n\n    Returns:\n        The compiled javascript callback to queue the given events on the frontend.\n\n    Raises:\n        ValueError: If a lambda function is given which returns a Var.\n    \"\"\"\n    from reflex.event import (\n        EventChain,\n        EventHandler,\n        EventSpec,\n        call_event_fn,\n        call_event_handler,\n    )\n    from reflex.vars import FunctionVar, Var\n\n    if not events:\n        return Var(\"(() => null)\").to(FunctionVar, EventChain)\n\n    # If no spec is provided, the function will take no arguments.\n    def _default_args_spec():\n        return []\n\n    # Construct the arguments that the function accepts.\n    sig = inspect.signature(args_spec or _default_args_spec)\n    if sig.parameters:\n        arg_def = \",\".join(f\"_{p}\" for p in sig.parameters)\n        arg_def = f\"({arg_def})\"\n    else:\n        arg_def = \"()\"\n\n    payloads = []\n    if not isinstance(events, list):\n        events = [events]\n\n    # Process each event/spec/lambda (similar to Component._create_event_chain).\n    for spec in events:\n        specs: list[EventSpec] = []\n        if isinstance(spec, (EventHandler, EventSpec)):\n            specs = [call_event_handler(spec, args_spec or _default_args_spec)]\n        elif isinstance(spec, type(lambda: None)):\n            specs = call_event_fn(spec, args_spec or _default_args_spec)  # pyright: ignore [reportAssignmentType, reportArgumentType]\n            if isinstance(specs, Var):\n                msg = f\"Invalid event spec: {specs}. Expected a list of EventSpecs.\"\n                raise ValueError(msg)\n        payloads.extend(format_event(s) for s in specs)\n\n    # Return the final code snippet, expecting queueEvents, processEvent, and socket to be in scope.\n    # Typically this snippet will _only_ run from within an rx.call_script eval context.\n    return Var(\n        f\"{arg_def} => {{queueEvents([{','.join(payloads)}], {constants.CompileVars.SOCKET}, false, navigate, params);\"\n        f\"processEvent({constants.CompileVars.SOCKET}, navigate, params);}}\",\n    ).to(FunctionVar, EventChain)\n\n\ndef format_query_params(router_data: dict[str, Any]) -> dict[str, str]:\n    \"\"\"Convert back query params name to python-friendly case.\n\n    Args:\n        router_data: the router_data dict containing the query params\n\n    Returns:\n        The reformatted query params\n    \"\"\"\n    params = router_data[constants.RouteVar.QUERY]\n    return {k.replace(\"-\", \"_\"): v for k, v in params.items()}\n\n\ndef format_state_name(state_name: str) -> str:\n    \"\"\"Format a state name, replacing dots with double underscore.\n\n    This allows individual substates to be accessed independently as javascript vars\n    without using dot notation.\n\n    Args:\n        state_name: The state name to format.\n\n    Returns:\n        The formatted state name.\n    \"\"\"\n    return state_name.replace(\".\", \"__\")\n\n\ndef format_ref(ref: str) -> str:\n    \"\"\"Format a ref.\n\n    Args:\n        ref: The ref to format.\n\n    Returns:\n        The formatted ref.\n    \"\"\"\n    # Replace all non-word characters with underscores.\n    clean_ref = re.sub(r\"[^\\w]+\", \"_\", ref)\n    return f\"ref_{clean_ref}\"\n\n\ndef format_library_name(library_fullname: str | dict[str, Any]) -> str:\n    \"\"\"Format the name of a library.\n\n    Args:\n        library_fullname: The library reference, either as a string or a dictionary with a 'name' key.\n\n    Returns:\n        The name without the @version if it was part of the name\n\n    Raises:\n        KeyError: If library_fullname is a dictionary without a 'name' key.\n        TypeError: If library_fullname or its 'name' value is not a string.\n    \"\"\"\n    # If input is a dictionary, extract the 'name' key\n    if isinstance(library_fullname, dict):\n        if \"name\" not in library_fullname:\n            msg = \"Dictionary input must contain a 'name' key\"\n            raise KeyError(msg)\n        library_fullname = library_fullname[\"name\"]\n\n    # Process the library name as a string\n    if not isinstance(library_fullname, str):\n        msg = \"Library name must be a string\"\n        raise TypeError(msg)\n\n    if library_fullname.startswith(\"https://\"):\n        return library_fullname\n\n    lib, at, version = library_fullname.rpartition(\"@\")\n    if not lib:\n        lib = at + version\n\n    return lib\n\n\ndef json_dumps(obj: Any, **kwargs) -> str:\n    \"\"\"Takes an object and returns a jsonified string.\n\n    Args:\n        obj: The object to be serialized.\n        kwargs: Additional keyword arguments to pass to json.dumps.\n\n    Returns:\n        A string\n    \"\"\"\n    from reflex.utils import serializers\n\n    kwargs.setdefault(\"ensure_ascii\", False)\n    kwargs.setdefault(\"default\", serializers.serialize)\n\n    return json.dumps(obj, **kwargs)\n\n\ndef collect_form_dict_names(form_dict: dict[str, Any]) -> dict[str, Any]:\n    \"\"\"Collapse keys with consecutive suffixes into a single list value.\n\n    Separators dash and underscore are removed, unless this would overwrite an existing key.\n\n    Args:\n        form_dict: The dict to collapse.\n\n    Returns:\n        The collapsed dict.\n    \"\"\"\n    ending_digit_regex = re.compile(r\"^(.*?)[_-]?(\\d+)$\")\n    collapsed = {}\n    for k in sorted(form_dict):\n        m = ending_digit_regex.match(k)\n        if m:\n            collapsed.setdefault(m.group(1), []).append(form_dict[k])\n    # collapsing never overwrites valid data from the form_dict\n    collapsed.update(form_dict)\n    return collapsed\n\n\ndef format_array_ref(refs: str, idx: Var | None) -> str:\n    \"\"\"Format a ref accessed by array.\n\n    Args:\n        refs : The ref array to access.\n        idx : The index of the ref in the array.\n\n    Returns:\n        The formatted ref.\n    \"\"\"\n    clean_ref = re.sub(r\"[^\\w]+\", \"_\", refs)\n    if idx is not None:\n        return f\"refs_{clean_ref}[{idx!s}]\"\n    return f\"refs_{clean_ref}\"\n\n\ndef format_data_editor_column(col: str | dict):\n    \"\"\"Format a given column into the proper format.\n\n    Args:\n        col: The column.\n\n    Returns:\n        The formatted column.\n\n    Raises:\n        ValueError: invalid type provided for column.\n    \"\"\"\n    from reflex.vars import Var\n\n    if isinstance(col, str):\n        return {\"title\": col, \"id\": col.lower(), \"type\": \"str\"}\n\n    if isinstance(col, (dict,)):\n        if \"id\" not in col:\n            col[\"id\"] = col[\"title\"].lower()\n        if \"type\" not in col:\n            col[\"type\"] = \"str\"\n        if \"overlayIcon\" not in col:\n            col[\"overlayIcon\"] = None\n        return col\n\n    if isinstance(col, Var):\n        return col\n\n    msg = f\"unexpected type ({(type(col).__name__)}: {col}) for column header in data_editor\"\n    raise ValueError(msg)\n\n\ndef format_data_editor_cell(cell: Any):\n    \"\"\"Format a given data into a renderable cell for data_editor.\n\n    Args:\n        cell: The data to format.\n\n    Returns:\n        The formatted cell.\n    \"\"\"\n    from reflex.vars.base import Var\n\n    return {\n        \"kind\": Var(_js_expr=\"GridCellKind.Text\"),\n        \"data\": cell,\n    }\n"
  },
  {
    "path": "reflex/utils/frontend_skeleton.py",
    "content": "\"\"\"This module provides utility functions to initialize the frontend skeleton.\"\"\"\n\nimport json\nimport random\nimport re\nfrom pathlib import Path\n\nfrom reflex import constants\nfrom reflex.compiler import templates\nfrom reflex.config import Config, get_config\nfrom reflex.environment import environment\nfrom reflex.utils import console, path_ops\nfrom reflex.utils.prerequisites import get_project_hash, get_web_dir\nfrom reflex.utils.registry import get_npm_registry\n\n\ndef initialize_gitignore(\n    gitignore_file: Path = constants.GitIgnore.FILE,\n    files_to_ignore: set[str] | list[str] = constants.GitIgnore.DEFAULTS,\n):\n    \"\"\"Initialize the template .gitignore file.\n\n    Args:\n        gitignore_file: The .gitignore file to create.\n        files_to_ignore: The files to add to the .gitignore file.\n    \"\"\"\n    # Combine with the current ignored files.\n    current_ignore: list[str] = []\n    if gitignore_file.exists():\n        current_ignore = [ln.strip() for ln in gitignore_file.read_text().splitlines()]\n\n    if files_to_ignore == current_ignore:\n        console.debug(f\"{gitignore_file} already up to date.\")\n        return\n    files_to_ignore = [ln for ln in files_to_ignore if ln not in current_ignore]\n    files_to_ignore += current_ignore\n\n    # Write files to the .gitignore file.\n    gitignore_file.touch(exist_ok=True)\n    console.debug(f\"Creating {gitignore_file}\")\n    gitignore_file.write_text(\"\\n\".join(files_to_ignore) + \"\\n\")\n\n\ndef initialize_requirements_txt() -> bool:\n    \"\"\"Initialize the requirements.txt file.\n    If absent and no pyproject.toml file exists, generate one for the user.\n    If the requirements.txt does not have reflex as dependency,\n    generate a requirement pinning current version and append to\n    the requirements.txt file.\n\n    Returns:\n        True if the user has to update the requirements.txt file.\n\n    Raises:\n        SystemExit: If the requirements.txt file cannot be read or written to.\n    \"\"\"\n    requirements_file_path = Path(constants.RequirementsTxt.FILE)\n    if (\n        not requirements_file_path.exists()\n        and Path(constants.PyprojectToml.FILE).exists()\n    ):\n        return True\n\n    requirements_file_path.touch(exist_ok=True)\n\n    for encoding in [None, \"utf-8\"]:\n        try:\n            content = requirements_file_path.read_text(encoding)\n            break\n        except UnicodeDecodeError:\n            continue\n        except Exception as e:\n            console.error(f\"Failed to read {requirements_file_path} due to {e}.\")\n            raise SystemExit(1) from None\n    else:\n        return True\n\n    for line in content.splitlines():\n        if re.match(r\"^reflex[^a-zA-Z0-9]\", line):\n            console.debug(f\"{requirements_file_path} already has reflex as dependency.\")\n            return False\n\n    console.debug(\n        f\"Appending {constants.RequirementsTxt.DEFAULTS_STUB} to {requirements_file_path}\"\n    )\n    with requirements_file_path.open(\"a\", encoding=encoding) as f:\n        f.write(\n            \"\\n\" + constants.RequirementsTxt.DEFAULTS_STUB + constants.Reflex.VERSION\n        )\n\n    return False\n\n\ndef initialize_web_directory():\n    \"\"\"Initialize the web directory on reflex init.\"\"\"\n    console.log(\"Initializing the web directory.\")\n\n    # Reuse the hash if one is already created, so we don't over-write it when running reflex init\n    project_hash = get_project_hash()\n\n    console.debug(f\"Copying {constants.Templates.Dirs.WEB_TEMPLATE} to {get_web_dir()}\")\n    path_ops.copy_tree(constants.Templates.Dirs.WEB_TEMPLATE, str(get_web_dir()))\n\n    console.debug(\"Initializing the web directory.\")\n    initialize_package_json()\n\n    console.debug(\"Initializing the bun config file.\")\n    initialize_bun_config()\n\n    console.debug(\"Initializing the .npmrc file.\")\n    initialize_npmrc()\n\n    console.debug(\"Initializing the public directory.\")\n    path_ops.mkdir(get_web_dir() / constants.Dirs.PUBLIC)\n\n    console.debug(\"Initializing the react-router.config.js file.\")\n    update_react_router_config()\n\n    console.debug(\"Initializing the vite.config.js file.\")\n    initialize_vite_config()\n\n    console.debug(\"Initializing the reflex.json file.\")\n    # Initialize the reflex json file.\n    init_reflex_json(project_hash=project_hash)\n\n\ndef update_react_router_config(prerender_routes: bool = False):\n    \"\"\"Update react-router.config.js config from Reflex config.\n\n    Args:\n        prerender_routes: Whether to enable prerendering of routes.\n    \"\"\"\n    react_router_config_file_path = get_web_dir() / constants.ReactRouter.CONFIG_FILE\n\n    new_react_router_config = _update_react_router_config(\n        get_config(), prerender_routes=prerender_routes\n    )\n\n    # Overwriting the config file triggers a full server reload, so make sure\n    # there is actually a diff.\n    old_react_router_config = (\n        react_router_config_file_path.read_text()\n        if react_router_config_file_path.exists()\n        else \"\"\n    )\n    if old_react_router_config != new_react_router_config:\n        react_router_config_file_path.write_text(new_react_router_config)\n\n\ndef _update_react_router_config(config: Config, prerender_routes: bool = False):\n    basename = \"/\" + (config.frontend_path or \"\").strip(\"/\")\n    if not basename.endswith(\"/\"):\n        basename += \"/\"\n\n    react_router_config = {\n        \"basename\": basename,\n        \"future\": {\n            \"unstable_optimizeDeps\": True,\n        },\n        \"ssr\": False,\n    }\n\n    if prerender_routes:\n        react_router_config[\"prerender\"] = True\n        react_router_config[\"build\"] = constants.Dirs.BUILD_DIR\n\n    return f\"export default {json.dumps(react_router_config)};\"\n\n\ndef _compile_package_json():\n    config = get_config()\n    return templates.package_json_template(\n        scripts={\n            \"dev\": constants.PackageJson.Commands.DEV,\n            \"export\": constants.PackageJson.Commands.EXPORT,\n            \"prod\": constants.PackageJson.Commands.get_prod_command(\n                config.frontend_path\n            ),\n        },\n        dependencies=constants.PackageJson.DEPENDENCIES,\n        dev_dependencies=constants.PackageJson.DEV_DEPENDENCIES,\n        overrides=constants.PackageJson.OVERRIDES,\n    )\n\n\ndef initialize_package_json():\n    \"\"\"Render and write in .web the package.json file.\"\"\"\n    output_path = get_web_dir() / constants.PackageJson.PATH\n    output_path.write_text(_compile_package_json())\n\n\ndef _compile_vite_config(config: Config):\n    # base must have exactly one trailing slash\n    base = \"/\"\n    if frontend_path := config.frontend_path.strip(\"/\"):\n        base += frontend_path + \"/\"\n    return templates.vite_config_template(\n        base=base,\n        hmr=environment.VITE_HMR.get(),\n        force_full_reload=environment.VITE_FORCE_FULL_RELOAD.get(),\n        experimental_hmr=environment.VITE_EXPERIMENTAL_HMR.get(),\n        sourcemap=environment.VITE_SOURCEMAP.get(),\n        allowed_hosts=config.vite_allowed_hosts,\n    )\n\n\ndef initialize_vite_config():\n    \"\"\"Render and write in .web the vite.config.js file using Reflex config.\"\"\"\n    vite_config_file_path = get_web_dir() / constants.ReactRouter.VITE_CONFIG_FILE\n    vite_config_file_path.write_text(_compile_vite_config(get_config()))\n\n\ndef initialize_bun_config():\n    \"\"\"Initialize the bun config file.\"\"\"\n    bun_config_path = get_web_dir() / constants.Bun.CONFIG_PATH\n\n    if (custom_bunfig := Path(constants.Bun.CONFIG_PATH)).exists():\n        bunfig_content = custom_bunfig.read_text()\n        console.info(f\"Copying custom bunfig.toml inside {get_web_dir()} folder\")\n    else:\n        best_registry = get_npm_registry()\n        bunfig_content = constants.Bun.DEFAULT_CONFIG.format(registry=best_registry)\n\n    bun_config_path.write_text(bunfig_content)\n\n\ndef initialize_npmrc():\n    \"\"\"Initialize the .npmrc file.\"\"\"\n    npmrc_path = get_web_dir() / constants.Node.CONFIG_PATH\n\n    if (custom_npmrc := Path(constants.Node.CONFIG_PATH)).exists():\n        npmrc_content = custom_npmrc.read_text()\n        console.info(f\"Copying custom .npmrc inside {get_web_dir()} folder\")\n    else:\n        best_registry = get_npm_registry()\n        npmrc_content = constants.Node.DEFAULT_CONFIG.format(registry=best_registry)\n\n    npmrc_path.write_text(npmrc_content)\n\n\ndef init_reflex_json(project_hash: int | None):\n    \"\"\"Write the hash of the Reflex project to a REFLEX_JSON.\n\n    Reuse the hash if one is already created, therefore do not\n    overwrite it every time we run the reflex init command\n    .\n\n    Args:\n        project_hash: The app hash.\n    \"\"\"\n    if project_hash is not None:\n        console.debug(f\"Project hash is already set to {project_hash}.\")\n    else:\n        # Get a random project hash.\n        project_hash = random.getrandbits(128)\n        console.debug(f\"Setting project hash to {project_hash}.\")\n\n    # Write the hash and version to the reflex json file.\n    reflex_json = {\n        \"version\": constants.Reflex.VERSION,\n        \"project_hash\": project_hash,\n    }\n    path_ops.update_json_file(get_web_dir() / constants.Reflex.JSON, reflex_json)\n"
  },
  {
    "path": "reflex/utils/imports.py",
    "content": "\"\"\"Import operations.\"\"\"\n\nfrom __future__ import annotations\n\nimport dataclasses\nfrom collections import defaultdict\nfrom collections.abc import Mapping, Sequence\n\n\ndef merge_parsed_imports(\n    *imports: ImmutableParsedImportDict,\n) -> ParsedImportDict:\n    \"\"\"Merge multiple parsed import dicts together.\n\n    Args:\n        *imports: The list of import dicts to merge.\n\n    Returns:\n        The merged import dicts.\n    \"\"\"\n    all_imports: defaultdict[str, list[ImportVar]] = defaultdict(list)\n    for import_dict in imports:\n        for lib, fields in import_dict.items():\n            all_imports[lib].extend(fields)\n    return all_imports\n\n\ndef merge_imports(\n    *imports: ImportDict | ParsedImportDict | ParsedImportTuple,\n) -> ParsedImportDict:\n    \"\"\"Merge multiple import dicts together.\n\n    Args:\n        *imports: The list of import dicts to merge.\n\n    Returns:\n        The merged import dicts.\n    \"\"\"\n    all_imports: defaultdict[str, list[ImportVar]] = defaultdict(list)\n    for import_dict in imports:\n        for lib, fields in (\n            import_dict if isinstance(import_dict, tuple) else import_dict.items()\n        ):\n            # If the lib is an absolute path, we need to prefix it with a $\n            lib = (\n                \"$\" + lib\n                if lib.startswith((\"/utils/\", \"/components/\", \"/styles/\", \"/public/\"))\n                else lib\n            )\n            if isinstance(fields, (list, tuple, set)):\n                all_imports[lib].extend(\n                    ImportVar(field) if isinstance(field, str) else field\n                    for field in fields\n                )\n            else:\n                all_imports[lib].append(\n                    ImportVar(fields) if isinstance(fields, str) else fields\n                )\n    return all_imports\n\n\ndef parse_imports(\n    imports: ImmutableImportDict | ImmutableParsedImportDict,\n) -> ParsedImportDict:\n    \"\"\"Parse the import dict into a standard format.\n\n    Args:\n        imports: The import dict to parse.\n\n    Returns:\n        The parsed import dict.\n    \"\"\"\n    return {\n        package: [maybe_tags]\n        if isinstance(maybe_tags, ImportVar)\n        else [ImportVar(tag=maybe_tags)]\n        if isinstance(maybe_tags, str)\n        else [ImportVar(tag=tag) if isinstance(tag, str) else tag for tag in maybe_tags]\n        for package, maybe_tags in imports.items()\n    }\n\n\ndef collapse_imports(\n    imports: ParsedImportDict | ParsedImportTuple,\n) -> ParsedImportDict:\n    \"\"\"Remove all duplicate ImportVar within an ImportDict.\n\n    Args:\n        imports: The import dict to collapse.\n\n    Returns:\n        The collapsed import dict.\n    \"\"\"\n    return {\n        lib: (\n            list(set(import_vars))\n            if isinstance(import_vars, list)\n            else list(import_vars)\n        )\n        for lib, import_vars in (\n            imports if isinstance(imports, tuple) else imports.items()\n        )\n    }\n\n\n@dataclasses.dataclass(frozen=True)\nclass ImportVar:\n    \"\"\"An import var.\"\"\"\n\n    # The name of the import tag.\n    tag: str | None\n\n    # whether the import is default or named.\n    is_default: bool | None = False\n\n    # The tag alias.\n    alias: str | None = None\n\n    # Whether this import need to install the associated lib\n    install: bool | None = True\n\n    # whether this import should be rendered or not\n    render: bool | None = True\n\n    # The path of the package to import from.\n    package_path: str = \"/\"\n\n    @property\n    def name(self) -> str:\n        \"\"\"The name of the import.\n\n        Returns:\n            The name(tag name with alias) of tag.\n        \"\"\"\n        if self.alias:\n            return (\n                self.alias\n                if self.is_default and self.tag != \"*\"\n                else (self.tag + \" as \" + self.alias if self.tag else self.alias)\n            )\n        return self.tag or \"\"\n\n\nImportTypes = str | ImportVar | list[str | ImportVar] | list[ImportVar]\nImmutableImportTypes = str | ImportVar | Sequence[str | ImportVar]\nImportDict = dict[str, ImportTypes]\nImmutableImportDict = Mapping[str, ImmutableImportTypes]\nParsedImportDict = dict[str, list[ImportVar]]\nImmutableParsedImportDict = Mapping[str, Sequence[ImportVar]]\nParsedImportTuple = tuple[tuple[str, tuple[ImportVar, ...]], ...]\n"
  },
  {
    "path": "reflex/utils/js_runtimes.py",
    "content": "\"\"\"This module provides utilities for managing JavaScript runtimes like Node.js and Bun.\"\"\"\n\nimport functools\nimport os\nimport tempfile\nfrom collections.abc import Sequence\nfrom pathlib import Path\n\nfrom packaging import version\n\nfrom reflex import constants\nfrom reflex.config import Config, get_config\nfrom reflex.environment import environment\nfrom reflex.utils import console, net, path_ops, processes\nfrom reflex.utils.decorator import cached_procedure, once\nfrom reflex.utils.exceptions import SystemPackageMissingError\nfrom reflex.utils.prerequisites import get_web_dir, windows_check_onedrive_in_path\n\n\ndef check_node_version() -> bool:\n    \"\"\"Check the version of Node.js.\n\n    Returns:\n        Whether the version of Node.js is valid.\n    \"\"\"\n    current_version = get_node_version()\n    return current_version is not None and current_version >= version.parse(\n        constants.Node.MIN_VERSION\n    )\n\n\ndef _get_version_of_executable(\n    executable_path: Path | None, version_arg: str = \"--version\"\n) -> version.Version | None:\n    \"\"\"Get the version of an executable.\n\n    Args:\n        executable_path: The path to the executable.\n        version_arg: The argument to pass to the executable to get its version.\n\n    Returns:\n        The version of the executable.\n    \"\"\"\n    if executable_path is None:\n        return None\n    try:\n        result = processes.new_process([executable_path, version_arg], run=True)\n        if result.returncode != 0:\n            console.error(\n                f\"Failed to run {executable_path} {version_arg} to get version. Return code: {result.returncode}. Standard error: {result.stderr!r}.\"\n            )\n            return None\n        return version.parse(result.stdout.strip())\n    except (FileNotFoundError, TypeError):\n        return None\n    except version.InvalidVersion as e:\n        console.warn(\n            f\"The detected version of {executable_path} ({e.args[0]}) is not valid. Defaulting to None.\"\n        )\n        return None\n\n\n@once\ndef get_node_version() -> version.Version | None:\n    \"\"\"Get the version of node.\n\n    Returns:\n        The version of node.\n    \"\"\"\n    return _get_version_of_executable(path_ops.get_node_path())\n\n\ndef get_bun_version(bun_path: Path | None = None) -> version.Version | None:\n    \"\"\"Get the version of bun.\n\n    Args:\n        bun_path: The path to the bun executable.\n\n    Returns:\n        The version of bun.\n    \"\"\"\n    return _get_version_of_executable(bun_path or path_ops.get_bun_path())\n\n\ndef npm_escape_hatch() -> bool:\n    \"\"\"If the user sets REFLEX_USE_NPM, prefer npm over bun.\n\n    Returns:\n        If the user has set REFLEX_USE_NPM.\n    \"\"\"\n    return environment.REFLEX_USE_NPM.get()\n\n\ndef prefer_npm_over_bun() -> bool:\n    \"\"\"Check if npm should be preferred over bun.\n\n    Returns:\n        If npm should be preferred over bun.\n    \"\"\"\n    return npm_escape_hatch() or (\n        constants.IS_WINDOWS and windows_check_onedrive_in_path()\n    )\n\n\ndef get_nodejs_compatible_package_managers(\n    raise_on_none: bool = True,\n) -> Sequence[str]:\n    \"\"\"Get the package manager executable for installation. Typically, bun is used for installation.\n\n    Args:\n        raise_on_none: Whether to raise an error if the package manager is not found.\n\n    Returns:\n        The path to the package manager.\n\n    Raises:\n        FileNotFoundError: If the package manager is not found and raise_on_none is True.\n    \"\"\"\n    bun_package_manager = (\n        str(bun_path) if (bun_path := path_ops.get_bun_path()) else None\n    )\n\n    npm_package_manager = (\n        str(npm_path) if (npm_path := path_ops.get_npm_path()) else None\n    )\n\n    if prefer_npm_over_bun():\n        package_managers = [npm_package_manager, bun_package_manager]\n    else:\n        package_managers = [bun_package_manager, npm_package_manager]\n\n    package_managers = list(filter(None, package_managers))\n\n    if not package_managers and raise_on_none:\n        msg = \"Bun or npm not found. You might need to rerun `reflex init` or install either.\"\n        raise FileNotFoundError(msg)\n\n    return package_managers\n\n\ndef is_outdated_nodejs_installed():\n    \"\"\"Check if the installed Node.js version is outdated.\n\n    Returns:\n        If the installed Node.js version is outdated.\n    \"\"\"\n    current_version = get_node_version()\n    if current_version is not None and current_version < version.parse(\n        constants.Node.MIN_VERSION\n    ):\n        console.warn(\n            f\"Your version ({current_version}) of Node.js is out of date. Upgrade to {constants.Node.MIN_VERSION} or higher.\"\n        )\n        return True\n    return False\n\n\ndef get_js_package_executor(raise_on_none: bool = False) -> Sequence[Sequence[str]]:\n    \"\"\"Get the paths to package managers for running commands. Ordered by preference.\n    This is currently identical to get_install_package_managers, but may change in the future.\n\n    Args:\n        raise_on_none: Whether to raise an error if no package managers is not found.\n\n    Returns:\n        The paths to the package managers as a list of lists, where each list is the command to run and its arguments.\n\n    Raises:\n        FileNotFoundError: If no package managers are found and raise_on_none is True.\n    \"\"\"\n    bun_package_manager = (\n        [str(bun_path)] + ([\"--bun\"] if is_outdated_nodejs_installed() else [])\n        if (bun_path := path_ops.get_bun_path())\n        else None\n    )\n\n    npm_package_manager = (\n        [str(npm_path)] if (npm_path := path_ops.get_npm_path()) else None\n    )\n\n    if prefer_npm_over_bun():\n        package_managers = [npm_package_manager, bun_package_manager]\n    else:\n        package_managers = [bun_package_manager, npm_package_manager]\n\n    package_managers = list(filter(None, package_managers))\n\n    if not package_managers and raise_on_none:\n        msg = \"Bun or npm not found. You might need to rerun `reflex init` or install either.\"\n        raise FileNotFoundError(msg)\n\n    return package_managers\n\n\ndef download_and_run(url: str, *args, show_status: bool = False, **env):\n    \"\"\"Download and run a script.\n\n    Args:\n        url: The url of the script.\n        args: The arguments to pass to the script.\n        show_status: Whether to show the status of the script.\n        env: The environment variables to use.\n\n    Raises:\n        SystemExit: If the script fails to download.\n    \"\"\"\n    import httpx\n\n    # Download the script\n    console.debug(f\"Downloading {url}\")\n    try:\n        response = net.get(url)\n        response.raise_for_status()\n    except httpx.HTTPError as e:\n        console.error(\n            f\"Failed to download bun install script. You can install or update bun manually from https://bun.com \\n{e}\"\n        )\n        raise SystemExit(1) from None\n\n    # Save the script to a temporary file.\n    with tempfile.NamedTemporaryFile() as tempfile_file:\n        script = Path(tempfile_file.name)\n\n        script.write_text(response.text)\n\n        # Run the script.\n        env = {**os.environ, **env}\n        process = processes.new_process([\"bash\", str(script), *args], env=env)\n        show = processes.show_status if show_status else processes.show_logs\n        show(f\"Installing {url}\", process)\n\n\ndef install_bun():\n    \"\"\"Install bun onto the user's system.\n\n    Raises:\n        SystemPackageMissingError: If \"unzip\" is missing.\n        SystemExit: If REFLEX_USE_NPM is set but Node.js is not installed.\n    \"\"\"\n    if npm_escape_hatch():\n        if get_node_version() is not None:\n            console.info(\n                \"Skipping bun installation as REFLEX_USE_NPM is set. Using npm instead.\"\n            )\n            return\n        console.error(\n            \"REFLEX_USE_NPM is set, but Node.js is not installed. Please install Node.js to use npm.\"\n        )\n        raise SystemExit(1)\n\n    bun_path = path_ops.get_bun_path()\n\n    # Skip if bun is already installed.\n    if (\n        bun_path\n        and (current_version := get_bun_version(bun_path=bun_path))\n        and current_version >= version.parse(constants.Bun.MIN_VERSION)\n    ):\n        console.debug(\"Skipping bun installation as it is already installed.\")\n        return\n\n    if bun_path and path_ops.use_system_bun():\n        validate_bun(bun_path=bun_path)\n        return\n\n    if constants.IS_WINDOWS:\n        processes.new_process(\n            [\n                \"powershell\",\n                \"-c\",\n                f\"irm {constants.Bun.WINDOWS_INSTALL_URL}|iex\",\n            ],\n            env={\n                \"BUN_INSTALL\": str(constants.Bun.ROOT_PATH),\n                \"BUN_VERSION\": constants.Bun.VERSION,\n            },\n            shell=True,\n            run=True,\n            show_logs=console.is_debug(),\n        )\n    else:\n        if path_ops.which(\"unzip\") is None:\n            msg = \"unzip\"\n            raise SystemPackageMissingError(msg)\n\n        # Run the bun install script.\n        download_and_run(\n            constants.Bun.INSTALL_URL,\n            f\"bun-v{constants.Bun.VERSION}\",\n            BUN_INSTALL=str(constants.Bun.ROOT_PATH),\n            BUN_VERSION=str(constants.Bun.VERSION),\n        )\n\n\ndef validate_bun(bun_path: Path | None = None):\n    \"\"\"Validate bun if a custom bun path is specified to ensure the bun version meets requirements.\n\n    Args:\n        bun_path: The path to the bun executable. If None, the default bun path is used.\n\n    Raises:\n        SystemExit: If custom specified bun does not exist or does not meet requirements.\n    \"\"\"\n    bun_path = bun_path or path_ops.get_bun_path()\n\n    if bun_path is None:\n        return\n\n    if not path_ops.samefile(bun_path, constants.Bun.DEFAULT_PATH):\n        console.info(f\"Using custom Bun path: {bun_path}\")\n        bun_version = get_bun_version(bun_path=bun_path)\n        if bun_version is None:\n            console.error(\n                \"Failed to obtain bun version. Make sure the specified bun path in your config is correct.\"\n            )\n            raise SystemExit(1)\n        if bun_version < version.parse(constants.Bun.MIN_VERSION):\n            console.warn(\n                f\"Reflex requires bun version {constants.Bun.MIN_VERSION} or higher to run, but the detected version is \"\n                f\"{bun_version}. If you have specified a custom bun path in your config, make sure to provide one \"\n                f\"that satisfies the minimum version requirement. You can upgrade bun by running [bold]bun upgrade[/bold].\"\n            )\n\n\ndef validate_frontend_dependencies(init: bool = True):\n    \"\"\"Validate frontend dependencies to ensure they meet requirements.\n\n    Args:\n        init: whether running `reflex init`\n\n    Raises:\n        SystemExit: If the package manager is invalid.\n    \"\"\"\n    if not init:\n        try:\n            get_js_package_executor(raise_on_none=True)\n        except FileNotFoundError as e:\n            console.error(f\"Failed to find a valid package manager due to {e}.\")\n            raise SystemExit(1) from None\n\n    if prefer_npm_over_bun() and not check_node_version():\n        node_version = get_node_version()\n        console.error(\n            f\"Reflex requires node version {constants.Node.MIN_VERSION} or higher to run, but the detected version is {node_version}\",\n        )\n        raise SystemExit(1)\n\n\ndef remove_existing_bun_installation():\n    \"\"\"Remove existing bun installation.\"\"\"\n    console.debug(\"Removing existing bun installation.\")\n    if Path(get_config().bun_path).exists():\n        path_ops.rm(constants.Bun.ROOT_PATH)\n\n\n@cached_procedure(\n    cache_file_path=lambda: get_web_dir() / \"reflex.install_frontend_packages.cached\",\n    payload_fn=lambda packages, config: f\"{sorted(packages)!r},{config.json()}\",\n)\ndef install_frontend_packages(packages: set[str], config: Config):\n    \"\"\"Installs the base and custom frontend packages.\n\n    Args:\n        packages: A list of package names to be installed.\n        config: The config object.\n\n    Example:\n        >>> install_frontend_packages([\"react\", \"react-dom\"], get_config())\n    \"\"\"\n    install_package_managers = get_nodejs_compatible_package_managers(\n        raise_on_none=True\n    )\n\n    env = (\n        {\n            \"NODE_TLS_REJECT_UNAUTHORIZED\": \"0\",\n        }\n        if environment.SSL_NO_VERIFY.get()\n        else {}\n    )\n\n    primary_package_manager = install_package_managers[0]\n    fallbacks = install_package_managers[1:]\n\n    run_package_manager = functools.partial(\n        processes.run_process_with_fallbacks,\n        fallbacks=fallbacks,\n        analytics_enabled=True,\n        cwd=get_web_dir(),\n        shell=constants.IS_WINDOWS,\n        env=env,\n    )\n\n    run_package_manager(\n        [primary_package_manager, \"install\", \"--legacy-peer-deps\"],\n        show_status_message=\"Installing base frontend packages\",\n    )\n\n    development_deps: set[str] = set()\n    for plugin in config.plugins:\n        development_deps.update(plugin.get_frontend_development_dependencies())\n        packages.update(plugin.get_frontend_dependencies())\n\n    if development_deps:\n        run_package_manager(\n            [\n                primary_package_manager,\n                \"add\",\n                \"--legacy-peer-deps\",\n                \"-d\",\n                *development_deps,\n            ],\n            show_status_message=\"Installing frontend development dependencies\",\n        )\n\n    # Install custom packages defined in frontend_packages\n    if packages:\n        run_package_manager(\n            [primary_package_manager, \"add\", \"--legacy-peer-deps\", *packages],\n            show_status_message=\"Installing frontend packages from config and components\",\n        )\n"
  },
  {
    "path": "reflex/utils/lazy_loader.py",
    "content": "\"\"\"Module to implement lazy loading in reflex.\n\nBSD 3-Clause License\n\nCopyright (c) 2022--2023, Scientific Python project All rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\n    Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n\n    Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n\n    Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\"\"\"\n\nfrom __future__ import annotations\n\nimport copy\nimport importlib\nimport os\nimport sys\n\n\ndef attach(\n    package_name: str,\n    submodules: set[str] | None = None,\n    submod_attrs: dict[str, list[str]] | None = None,\n    **extra_mappings,\n):\n    \"\"\"Replaces a package's __getattr__, __dir__, and __all__ attributes using lazy.attach.\n    The lazy loader __getattr__ doesn't support tuples as list values. We needed to add\n    this functionality (tuples) in Reflex to support 'import as _' statements. This function\n    reformats the submod_attrs dictionary to flatten the module list before passing it to\n    lazy_loader.\n\n    Args:\n        package_name: name of the package.\n        submodules : List of submodules to attach.\n        submod_attrs : Dictionary of submodule -> list of attributes / functions.\n                    These attributes are imported as they are used.\n        extra_mappings: Additional mappings to resolve lazily.\n\n    Returns:\n        __getattr__, __dir__, __all__\n    \"\"\"\n    submod_attrs = copy.deepcopy(submod_attrs)\n    if submod_attrs:\n        for k, v in submod_attrs.items():\n            # when flattening the list, only keep the alias in the tuple(mod[1])\n            submod_attrs[k] = [\n                mod if not isinstance(mod, tuple) else mod[1] for mod in v\n            ]\n\n    if submod_attrs is None:\n        submod_attrs = {}\n\n    submodules = set(submodules) if submodules is not None else set()\n\n    attr_to_modules = {\n        attr: mod for mod, attrs in submod_attrs.items() for attr in attrs\n    }\n\n    __all__ = sorted([*(submodules | attr_to_modules.keys()), *(extra_mappings or [])])\n\n    def __getattr__(name: str):  # noqa: N807\n        if name in extra_mappings:\n            submod_path, attr = extra_mappings[name].rsplit(\".\", 1)\n            submod = importlib.import_module(submod_path)\n            return getattr(submod, attr)\n        if name in submodules:\n            return importlib.import_module(f\"{package_name}.{name}\")\n        if name in attr_to_modules:\n            submod_path = f\"{package_name}.{attr_to_modules[name]}\"\n            submod = importlib.import_module(submod_path)\n            attr = getattr(submod, name)\n\n            # If the attribute lives in a file (module) with the same\n            # name as the attribute, ensure that the attribute and *not*\n            # the module is accessible on the package.\n            if name == attr_to_modules[name]:\n                pkg = sys.modules[package_name]\n                pkg.__dict__[name] = attr\n\n            return attr\n        msg = f\"No {package_name} attribute {name}\"\n        raise AttributeError(msg)\n\n    def __dir__():  # noqa: N807\n        return __all__\n\n    if os.environ.get(\"EAGER_IMPORT\", \"\"):\n        for attr in set(attr_to_modules.keys()) | submodules:\n            __getattr__(attr)\n\n    return __getattr__, __dir__, list(__all__)\n"
  },
  {
    "path": "reflex/utils/misc.py",
    "content": "\"\"\"Miscellaneous functions for the experimental package.\"\"\"\n\nimport asyncio\nimport contextlib\nimport inspect\nimport sys\nimport threading\nfrom collections.abc import Callable\nfrom pathlib import Path\nfrom typing import Any\n\n\ndef get_module_path(module_name: str) -> Path | None:\n    \"\"\"Check if a module exists and return its path.\n\n    This function searches for a module by navigating through the module hierarchy\n    in each path of sys.path, checking for both .py files and packages with __init__.py.\n\n    Args:\n        module_name: The name of the module to search for (e.g., \"package.submodule\").\n\n    Returns:\n        The path to the module file if found, None otherwise.\n    \"\"\"\n    parts = module_name.split(\".\")\n\n    # Check each path in sys.path\n    for path in sys.path:\n        current_path = Path(path)\n\n        # Navigate through the module hierarchy\n        for i, part in enumerate(parts):\n            potential_file = current_path / (part + \".py\")\n            potential_dir = current_path / part\n\n            if potential_file.is_file():\n                # We encountered a file, but we can't continue deeper\n                if i == len(parts) - 1:\n                    return potential_file\n                return None  # Can't continue deeper\n            if potential_dir.is_dir():\n                # It's a package, so we can continue deeper\n                current_path = potential_dir\n            else:\n                break  # Path doesn't exist, break out of the loop\n        else:\n            return current_path / \"__init__.py\"  # Made it through all parts\n\n    return None\n\n\nasync def run_in_thread(func: Callable) -> Any:\n    \"\"\"Run a function in a separate thread.\n\n    To not block the UI event queue, run_in_thread must be inside inside a rx.event(background=True) decorated method.\n\n    Args:\n        func: The non-async function to run.\n\n    Returns:\n        Any: The return value of the function.\n\n    Raises:\n        ValueError: If the function is an async function.\n    \"\"\"\n    if inspect.iscoroutinefunction(func):\n        msg = \"func must be a non-async function\"\n        raise ValueError(msg)\n    return await asyncio.get_event_loop().run_in_executor(None, func)\n\n\n# Global lock for thread-safe sys.path manipulation\n_sys_path_lock = threading.RLock()\n\n\n@contextlib.contextmanager\ndef with_cwd_in_syspath():\n    \"\"\"Temporarily add current working directory to sys.path in a thread-safe manner.\n\n    This context manager temporarily prepends the current working directory to sys.path,\n    ensuring that modules in the current directory can be imported. The original sys.path\n    is restored when exiting the context.\n\n    Yields:\n        None\n    \"\"\"\n    with _sys_path_lock:\n        orig_sys_path = sys.path.copy()\n        sys.path.insert(0, str(Path.cwd()))\n        try:\n            yield\n        finally:\n            sys.path[:] = orig_sys_path\n\n\ndef preload_color_theme():\n    \"\"\"Create a script component that preloads the color theme to prevent FOUC.\n\n    This script runs immediately in the document head before React hydration,\n    reading the saved theme from localStorage and applying the correct CSS classes\n    to prevent flash of unstyled content.\n\n    Returns:\n        Script: A script component to add to App.head_components\n    \"\"\"\n    from reflex.components.el.elements.scripts import Script\n\n    # Create direct inline script content (like next-themes dangerouslySetInnerHTML)\n    script_content = \"\"\"\n// Only run in browser environment, not during SSR\nif (typeof document !== 'undefined') {\n    try {\n        const theme = localStorage.getItem(\"theme\") || \"system\";\n        const systemPreference = window.matchMedia(\"(prefers-color-scheme: dark)\").matches ? \"dark\" : \"light\";\n        const resolvedTheme = theme === \"system\" ? systemPreference : theme;\n\n        // Apply theme immediately - blocks until complete\n        // Use classList to avoid overwriting other classes\n        document.documentElement.classList.remove(\"light\", \"dark\");\n        document.documentElement.classList.add(resolvedTheme);\n        document.documentElement.style.colorScheme = resolvedTheme;\n\n    } catch (e) {\n        // Fallback to system preference on any error (resolve \"system\" to actual theme)\n        const fallbackTheme = window.matchMedia(\"(prefers-color-scheme: dark)\").matches ? \"dark\" : \"light\";\n        document.documentElement.classList.remove(\"light\", \"dark\");\n        document.documentElement.classList.add(fallbackTheme);\n        document.documentElement.style.colorScheme = fallbackTheme;\n    }\n}\n\"\"\"\n\n    return Script.create(script_content)\n"
  },
  {
    "path": "reflex/utils/monitoring.py",
    "content": "\"\"\"PyLeak integration for monitoring event loop blocking and resource leaks in Reflex applications.\"\"\"\n\nimport contextlib\nimport functools\nimport inspect\nimport threading\nfrom collections.abc import AsyncGenerator, Awaitable, Callable, Generator\nfrom typing import TypeVar, overload\n\nfrom reflex.config import get_config\n\ntry:\n    from pyleak import no_event_loop_blocking, no_task_leaks, no_thread_leaks\n    from pyleak.base import LeakAction\n\n    PYLEAK_AVAILABLE = True\nexcept ImportError:\n    PYLEAK_AVAILABLE = False\n    no_event_loop_blocking = no_task_leaks = no_thread_leaks = None  # pyright: ignore[reportAssignmentType]\n    LeakAction = None  # pyright: ignore[reportAssignmentType]\n\n\n# Thread-local storage to track if monitoring is already active\n_thread_local = threading.local()\n\n\ndef is_pyleak_enabled() -> bool:\n    \"\"\"Check if PyLeak monitoring is enabled and available.\n\n    Returns:\n        True if PyLeak monitoring is enabled in config and PyLeak is available.\n    \"\"\"\n    if not PYLEAK_AVAILABLE:\n        return False\n    config = get_config()\n    return config.enable_pyleak_monitoring\n\n\n@contextlib.contextmanager\ndef monitor_sync():\n    \"\"\"Sync context manager for PyLeak monitoring.\n\n    Yields:\n        None: Context for monitoring sync operations.\n    \"\"\"\n    if not is_pyleak_enabled():\n        yield\n        return\n\n    # Check if monitoring is already active in this thread\n    if getattr(_thread_local, \"monitoring_active\", False):\n        yield\n        return\n\n    config = get_config()\n    action = config.pyleak_action or LeakAction.WARN  # pyright: ignore[reportOptionalMemberAccess]\n\n    # Mark monitoring as active\n    _thread_local.monitoring_active = True\n    try:\n        with contextlib.ExitStack() as stack:\n            # Thread leak detection has issues with background tasks (no_thread_leaks)\n            stack.enter_context(\n                no_event_loop_blocking(  # pyright: ignore[reportOptionalCall]\n                    action=action,\n                    threshold=config.pyleak_blocking_threshold,\n                )\n            )\n            yield\n    finally:\n        _thread_local.monitoring_active = False\n\n\n@contextlib.asynccontextmanager\nasync def monitor_async():\n    \"\"\"Async context manager for PyLeak monitoring.\n\n    Yields:\n        None: Context for monitoring async operations.\n    \"\"\"\n    if not is_pyleak_enabled():\n        yield\n        return\n\n    # Check if monitoring is already active in this thread\n    if getattr(_thread_local, \"monitoring_active\", False):\n        yield\n        return\n\n    config = get_config()\n    action = config.pyleak_action or LeakAction.WARN  # pyright: ignore[reportOptionalMemberAccess]\n\n    # Mark monitoring as active\n    _thread_local.monitoring_active = True\n    try:\n        async with contextlib.AsyncExitStack() as stack:\n            # Thread leak detection has issues with background tasks (no_thread_leaks)\n            # Re-add thread leak later.\n\n            # Block detection for event loops\n            stack.enter_context(\n                no_event_loop_blocking(  # pyright: ignore[reportOptionalCall]\n                    action=action,\n                    threshold=config.pyleak_blocking_threshold,\n                )\n            )\n            # Task leak detection has issues with background tasks (no_task_leaks)\n\n            yield\n    finally:\n        _thread_local.monitoring_active = False\n\n\nYieldType = TypeVar(\"YieldType\")\nSendType = TypeVar(\"SendType\")\nReturnType = TypeVar(\"ReturnType\")\n\n\n@overload\ndef monitor_loopblocks(\n    func: Callable[..., AsyncGenerator[YieldType, ReturnType]],\n) -> Callable[..., AsyncGenerator[YieldType, ReturnType]]: ...\n\n\n@overload\ndef monitor_loopblocks(\n    func: Callable[..., Generator[YieldType, SendType, ReturnType]],\n) -> Callable[..., Generator[YieldType, SendType, ReturnType]]: ...\n\n\n@overload\ndef monitor_loopblocks(\n    func: Callable[..., Awaitable[ReturnType]],\n) -> Callable[..., Awaitable[ReturnType]]: ...\n\n\ndef monitor_loopblocks(func: Callable) -> Callable:\n    \"\"\"Framework decorator using the monitoring module's context manager.\n\n    Args:\n        func: The function to be monitored for leaks.\n\n    Returns:\n        Decorator function that applies PyLeak monitoring to sync/async functions.\n    \"\"\"\n    if inspect.isasyncgenfunction(func):\n\n        @functools.wraps(func)\n        async def async_gen_wrapper(*args, **kwargs):\n            async with monitor_async():\n                async for item in func(*args, **kwargs):\n                    yield item\n\n        return async_gen_wrapper\n\n    if inspect.iscoroutinefunction(func):\n\n        @functools.wraps(func)\n        async def async_wrapper(*args, **kwargs):\n            async with monitor_async():\n                return await func(*args, **kwargs)\n\n        return async_wrapper\n\n    if inspect.isgeneratorfunction(func):\n\n        @functools.wraps(func)\n        def gen_wrapper(*args, **kwargs):\n            with monitor_sync():\n                yield from func(*args, **kwargs)\n\n        return gen_wrapper\n\n    @functools.wraps(func)\n    def sync_wrapper(*args, **kwargs):\n        with monitor_sync():\n            return func(*args, **kwargs)\n\n    return sync_wrapper  # pyright: ignore[reportReturnType]\n"
  },
  {
    "path": "reflex/utils/net.py",
    "content": "\"\"\"Helpers for downloading files from the network.\"\"\"\n\nimport functools\nimport time\nfrom collections.abc import Callable\nfrom typing import ParamSpec, TypeVar\n\nfrom reflex.utils.decorator import once\nfrom reflex.utils.types import Unset\n\nfrom . import console\n\n\ndef _httpx_verify_kwarg() -> bool:\n    \"\"\"Get the value of the HTTPX verify keyword argument.\n\n    Returns:\n        True if SSL verification is enabled, False otherwise\n    \"\"\"\n    from reflex.environment import environment\n\n    return not environment.SSL_NO_VERIFY.get()\n\n\n_P = ParamSpec(\"_P\")\n_T = TypeVar(\"_T\")\n\n\ndef _wrap_https_func(\n    func: Callable[_P, _T],\n) -> Callable[_P, _T]:\n    \"\"\"Wrap an HTTPS function with logging.\n\n    Args:\n        func: The function to wrap.\n\n    Returns:\n        The wrapped function.\n    \"\"\"\n\n    @functools.wraps(func)\n    def wrapper(*args: _P.args, **kwargs: _P.kwargs) -> _T:\n        import httpx\n\n        url = args[0]\n        console.debug(f\"Sending HTTPS request to {args[0]}\")\n        initial_time = time.time()\n        try:\n            response = func(*args, **kwargs)\n        except httpx.ConnectError as err:\n            if \"CERTIFICATE_VERIFY_FAILED\" in str(err):\n                # If the error is a certificate verification error, recommend mitigating steps.\n                console.error(\n                    f\"Certificate verification failed for {url}. Set environment variable SSL_CERT_FILE to the \"\n                    \"path of the certificate file or SSL_NO_VERIFY=1 to disable verification.\"\n                )\n            raise\n        else:\n            console.debug(\n                f\"Received response from {url} in {time.time() - initial_time:.3f} seconds\"\n            )\n            return response\n\n    return wrapper\n\n\ndef _wrap_https_lazy_func(\n    func: Callable[[], Callable[_P, _T]],\n) -> Callable[_P, _T]:\n    \"\"\"Wrap an HTTPS function with logging.\n\n    Args:\n        func: The function to wrap.\n\n    Returns:\n        The wrapped function.\n    \"\"\"\n    unset = Unset()\n    f: Callable[_P, _T] | Unset = unset\n\n    def wrapper(*args: _P.args, **kwargs: _P.kwargs) -> _T:\n        nonlocal f\n        if isinstance(f, Unset):\n            f = _wrap_https_func(func())\n            functools.update_wrapper(wrapper, f)\n        return f(*args, **kwargs)\n\n    return wrapper\n\n\ndef _is_ipv4_supported() -> bool:\n    \"\"\"Determine if the system supports IPv4.\n\n    Returns:\n        True if the system supports IPv4, False otherwise.\n    \"\"\"\n    import httpx\n\n    try:\n        httpx.head(\"http://1.1.1.1\", timeout=3)\n    except httpx.RequestError:\n        return False\n    else:\n        return True\n\n\ndef _is_ipv6_supported() -> bool:\n    \"\"\"Determine if the system supports IPv6.\n\n    Returns:\n        True if the system supports IPv6, False otherwise.\n    \"\"\"\n    import httpx\n\n    try:\n        httpx.head(\"http://[2606:4700:4700::1111]\", timeout=3)\n    except httpx.RequestError:\n        return False\n    else:\n        return True\n\n\ndef _should_use_ipv6() -> bool:\n    \"\"\"Determine if the system supports IPv6.\n\n    Returns:\n        True if the system supports IPv6, False otherwise.\n    \"\"\"\n    return not _is_ipv4_supported() and _is_ipv6_supported()\n\n\ndef _httpx_local_address_kwarg() -> str:\n    \"\"\"Get the value of the HTTPX local_address keyword argument.\n\n    Returns:\n        The local address to bind to\n    \"\"\"\n    from reflex.environment import environment\n\n    return environment.REFLEX_HTTP_CLIENT_BIND_ADDRESS.get() or (\n        \"::\" if _should_use_ipv6() else \"0.0.0.0\"\n    )\n\n\n@once\ndef _httpx_client():\n    \"\"\"Get an HTTPX client.\n\n    Returns:\n        An HTTPX client.\n    \"\"\"\n    import httpx\n    from httpx._utils import get_environment_proxies\n\n    verify_setting = _httpx_verify_kwarg()\n    return httpx.Client(\n        transport=httpx.HTTPTransport(\n            local_address=_httpx_local_address_kwarg(),\n            verify=verify_setting,\n        ),\n        mounts={\n            key: (\n                None\n                if url is None\n                else httpx.HTTPTransport(\n                    proxy=httpx.Proxy(url=url), verify=verify_setting\n                )\n            )\n            for key, url in get_environment_proxies().items()\n        },\n    )\n\n\nget = _wrap_https_lazy_func(lambda: _httpx_client().get)\n"
  },
  {
    "path": "reflex/utils/path_ops.py",
    "content": "\"\"\"Path operations.\"\"\"\n\nfrom __future__ import annotations\n\nimport json\nimport os\nimport re\nimport shutil\nimport stat\nfrom pathlib import Path\n\nfrom reflex.config import get_config\nfrom reflex.environment import environment\n\n# Shorthand for join.\njoin = os.linesep.join\n\n\ndef chmod_rm(path: Path):\n    \"\"\"Remove a file or directory with chmod.\n\n    Args:\n        path: The path to the file or directory.\n    \"\"\"\n    path.chmod(stat.S_IWRITE)\n    if path.is_dir():\n        shutil.rmtree(path)\n    elif path.is_file():\n        path.unlink()\n\n\ndef rm(path: str | Path):\n    \"\"\"Remove a file or directory.\n\n    Args:\n        path: The path to the file or directory.\n    \"\"\"\n    path = Path(path)\n    if path.is_dir():\n        # In Python 3.12, onerror is deprecated in favor of onexc\n        shutil.rmtree(path, onerror=lambda _func, _path, _info: chmod_rm(path))\n    elif path.is_file():\n        path.unlink()\n\n\ndef copy_tree(\n    src: str | Path,\n    dest: str | Path,\n    ignore: tuple[str, ...] | None = None,\n):\n    \"\"\"Copy a directory tree.\n\n    Args:\n        src: The path to the source directory.\n        dest: The path to the destination directory.\n        ignore: Ignoring files and directories that match one of the glob-style patterns provided\n    \"\"\"\n    src = Path(src)\n    dest = Path(dest)\n    if dest.exists():\n        for item in dest.iterdir():\n            rm(item)\n    shutil.copytree(\n        src,\n        dest,\n        ignore=shutil.ignore_patterns(*ignore) if ignore is not None else ignore,\n        dirs_exist_ok=True,\n    )\n\n\ndef cp(\n    src: str | Path,\n    dest: str | Path,\n    overwrite: bool = True,\n    ignore: tuple[str, ...] | None = None,\n) -> bool:\n    \"\"\"Copy a file or directory.\n\n    Args:\n        src: The path to the file or directory.\n        dest: The path to the destination.\n        overwrite: Whether to overwrite the destination.\n        ignore: Ignoring files and directories that match one of the glob-style patterns provided\n\n    Returns:\n        Whether the copy was successful.\n    \"\"\"\n    src, dest = Path(src), Path(dest)\n    if src == dest:\n        return False\n    if not overwrite and dest.exists():\n        return False\n    if src.is_dir():\n        copy_tree(src, dest, ignore)\n    else:\n        shutil.copyfile(src, dest)\n    return True\n\n\ndef mv(src: str | Path, dest: str | Path, overwrite: bool = True) -> bool:\n    \"\"\"Move a file or directory.\n\n    Args:\n        src: The path to the file or directory.\n        dest: The path to the destination.\n        overwrite: Whether to overwrite the destination.\n\n    Returns:\n        Whether the move was successful.\n    \"\"\"\n    src, dest = Path(src), Path(dest)\n    if src == dest:\n        return False\n    if not overwrite and dest.exists():\n        return False\n    rm(dest)\n    shutil.move(src, dest)\n    return True\n\n\ndef mkdir(path: str | Path):\n    \"\"\"Create a directory.\n\n    Args:\n        path: The path to the directory.\n    \"\"\"\n    Path(path).mkdir(parents=True, exist_ok=True)\n\n\ndef ls(path: str | Path) -> list[Path]:\n    \"\"\"List the contents of a directory.\n\n    Args:\n        path: The path to the directory.\n\n    Returns:\n        A list of paths to the contents of the directory.\n    \"\"\"\n    return list(Path(path).iterdir())\n\n\ndef ln(src: str | Path, dest: str | Path, overwrite: bool = False) -> bool:\n    \"\"\"Create a symbolic link.\n\n    Args:\n        src: The path to the file or directory.\n        dest: The path to the destination.\n        overwrite: Whether to overwrite the destination.\n\n    Returns:\n        Whether the link was successful.\n    \"\"\"\n    src, dest = Path(src), Path(dest)\n    if src == dest:\n        return False\n    if not overwrite and (dest.exists() or dest.is_symlink()):\n        return False\n    if src.is_dir():\n        rm(dest)\n        src.symlink_to(dest, target_is_directory=True)\n    else:\n        src.symlink_to(dest)\n    return True\n\n\ndef which(program: str | Path) -> Path | None:\n    \"\"\"Find the path to an executable.\n\n    Args:\n        program: The name of the executable.\n\n    Returns:\n        The path to the executable.\n    \"\"\"\n    which_result = shutil.which(program)\n    return Path(which_result) if which_result else None\n\n\ndef use_system_bun() -> bool:\n    \"\"\"Check if the system bun should be used.\n\n    Returns:\n        Whether the system bun should be used.\n    \"\"\"\n    return environment.REFLEX_USE_SYSTEM_BUN.get()\n\n\ndef get_node_bin_path() -> Path | None:\n    \"\"\"Get the node binary dir path.\n\n    Returns:\n        The path to the node bin folder.\n    \"\"\"\n    return bin_path.parent.absolute() if (bin_path := get_node_path()) else None\n\n\ndef get_node_path() -> Path | None:\n    \"\"\"Get the node binary path.\n\n    Returns:\n        The path to the node binary file.\n    \"\"\"\n    return which(\"node\")\n\n\ndef get_npm_path() -> Path | None:\n    \"\"\"Get npm binary path.\n\n    Returns:\n        The path to the npm binary file.\n    \"\"\"\n    return npm_path.absolute() if (npm_path := which(\"npm\")) else None\n\n\ndef get_bun_path() -> Path | None:\n    \"\"\"Get bun binary path.\n\n    Returns:\n        The path to the bun binary file.\n    \"\"\"\n    bun_path = get_config().bun_path\n    if use_system_bun() or not bun_path.exists():\n        bun_path = which(\"bun\")\n    return bun_path.absolute() if bun_path else None\n\n\ndef update_json_file(file_path: str | Path, update_dict: dict[str, int | str]):\n    \"\"\"Update the contents of a json file.\n\n    Args:\n        file_path: the path to the JSON file.\n        update_dict: object to update json.\n    \"\"\"\n    fp = Path(file_path)\n\n    # Create the parent directory if it doesn't exist.\n    fp.parent.mkdir(parents=True, exist_ok=True)\n\n    # Create the file if it doesn't exist.\n    fp.touch(exist_ok=True)\n\n    # Create an empty json object if file is empty\n    fp.write_text(\"{}\") if fp.stat().st_size == 0 else None\n\n    # Read the existing json object from the file.\n    json_object = {}\n    if fp.stat().st_size:\n        with fp.open() as f:\n            json_object = json.load(f)\n\n    # Update the json object with the new data.\n    json_object.update(update_dict)\n\n    # Write the updated json object to the file\n    with fp.open(\"w\") as f:\n        json.dump(json_object, f, ensure_ascii=False)\n\n\ndef find_replace(directory: str | Path, find: str, replace: str):\n    \"\"\"Recursively find and replace text in files in a directory.\n\n    Args:\n        directory: The directory to search.\n        find: The text to find.\n        replace: The text to replace.\n    \"\"\"\n    directory = Path(directory)\n    for root, _dirs, files in os.walk(directory):\n        for file in files:\n            filepath = Path(root, file)\n            text = filepath.read_text(encoding=\"utf-8\")\n            text = re.sub(find, replace, text)\n            filepath.write_text(text, encoding=\"utf-8\")\n\n\ndef samefile(file1: Path, file2: Path) -> bool:\n    \"\"\"Check if two files are the same.\n\n    Args:\n        file1: The first file.\n        file2: The second file.\n\n    Returns:\n        Whether the files are the same. If either file does not exist, returns False.\n    \"\"\"\n    if file1.exists() and file2.exists():\n        return file1.samefile(file2)\n\n    return False\n\n\ndef update_directory_tree(src: Path, dest: Path):\n    \"\"\"Recursively copies a directory tree from src to dest.\n    Only copies files if the destination file is missing or modified earlier than the source file.\n\n    Args:\n        src: Source directory\n        dest: Destination directory\n\n    Raises:\n        ValueError: If the source is not a directory\n    \"\"\"\n    if not src.is_dir():\n        msg = f\"Source {src} is not a directory\"\n        raise ValueError(msg)\n\n    # Ensure the destination directory exists\n    dest.mkdir(parents=True, exist_ok=True)\n\n    for item in src.iterdir():\n        dest_item = dest / item.name\n\n        if item.is_dir():\n            # Recursively copy subdirectories\n            update_directory_tree(item, dest_item)\n        elif item.is_file() and (\n            not dest_item.exists() or item.stat().st_mtime > dest_item.stat().st_mtime\n        ):\n            # Copy file if it doesn't exist in the destination or is older than the source\n            shutil.copy2(item, dest_item)\n"
  },
  {
    "path": "reflex/utils/prerequisites.py",
    "content": "\"\"\"Everything related to fetching or initializing build prerequisites.\"\"\"\n\nfrom __future__ import annotations\n\nimport contextlib\nimport importlib\nimport importlib.metadata\nimport inspect\nimport json\nimport random\nimport re\nimport sys\nimport typing\nfrom datetime import datetime\nfrom os import getcwd\nfrom pathlib import Path\nfrom types import ModuleType\nfrom typing import NamedTuple\n\nfrom packaging import version\n\nfrom reflex import constants, model\nfrom reflex.config import Config, get_config\nfrom reflex.environment import environment\nfrom reflex.utils import console, net, path_ops\nfrom reflex.utils.decorator import once\nfrom reflex.utils.misc import get_module_path\n\nif typing.TYPE_CHECKING:\n    from redis import Redis as RedisSync\n    from redis.asyncio import Redis\n\n    from reflex.app import App\n\n\nclass AppInfo(NamedTuple):\n    \"\"\"A tuple containing the app instance and module.\"\"\"\n\n    app: App\n    module: ModuleType\n\n\ndef get_web_dir() -> Path:\n    \"\"\"Get the working directory for the frontend.\n\n    Can be overridden with REFLEX_WEB_WORKDIR.\n\n    Returns:\n        The working directory.\n    \"\"\"\n    return environment.REFLEX_WEB_WORKDIR.get()\n\n\ndef get_states_dir() -> Path:\n    \"\"\"Get the working directory for the states.\n\n    Can be overridden with REFLEX_STATES_WORKDIR.\n\n    Returns:\n        The working directory.\n    \"\"\"\n    return environment.REFLEX_STATES_WORKDIR.get()\n\n\ndef get_backend_dir() -> Path:\n    \"\"\"Get the working directory for the backend.\n\n    Returns:\n        The working directory.\n    \"\"\"\n    return get_web_dir() / constants.Dirs.BACKEND\n\n\ndef check_latest_package_version(package_name: str):\n    \"\"\"Check if the latest version of the package is installed.\n\n    Args:\n        package_name: The name of the package.\n    \"\"\"\n    if environment.REFLEX_CHECK_LATEST_VERSION.get() is False:\n        return\n    try:\n        console.debug(f\"Checking for the latest version of {package_name}...\")\n        # Get the latest version from PyPI\n        current_version = importlib.metadata.version(package_name)\n        url = f\"https://pypi.org/pypi/{package_name}/json\"\n        response = net.get(url, timeout=2)\n        latest_version = response.json()[\"info\"][\"version\"]\n        console.debug(f\"Latest version of {package_name}: {latest_version}\")\n        if get_or_set_last_reflex_version_check_datetime():\n            # Versions were already checked and saved in reflex.json, no need to warn again\n            return\n        if version.parse(current_version) < version.parse(latest_version):\n            # Show a warning when the host version is older than PyPI version\n            console.warn(\n                f\"Your version ({current_version}) of {package_name} is out of date. Upgrade to {latest_version} with 'pip install {package_name} --upgrade'\"\n            )\n    except Exception:\n        console.debug(f\"Failed to check for the latest version of {package_name}.\")\n\n\ndef get_or_set_last_reflex_version_check_datetime():\n    \"\"\"Get the last time a check was made for the latest reflex version.\n    This is typically useful for cases where the host reflex version is\n    less than that on Pypi.\n\n    Returns:\n        The last version check datetime.\n    \"\"\"\n    reflex_json_file = get_web_dir() / constants.Reflex.JSON\n    if not reflex_json_file.exists():\n        return None\n    # Open and read the file\n    data = json.loads(reflex_json_file.read_text())\n    last_version_check_datetime = data.get(\"last_version_check_datetime\")\n    if not last_version_check_datetime:\n        data.update({\"last_version_check_datetime\": str(datetime.now())})\n        path_ops.update_json_file(reflex_json_file, data)\n    return last_version_check_datetime\n\n\ndef set_last_reflex_run_time():\n    \"\"\"Set the last Reflex run time.\"\"\"\n    path_ops.update_json_file(\n        get_web_dir() / constants.Reflex.JSON,\n        {\"last_reflex_run_datetime\": str(datetime.now())},\n    )\n\n\n@once\ndef windows_check_onedrive_in_path() -> bool:\n    \"\"\"For windows, check if oneDrive is present in the project dir path.\n\n    Returns:\n        If oneDrive is in the path of the project directory.\n    \"\"\"\n    return \"onedrive\" in str(Path.cwd()).lower()\n\n\ndef _check_app_name(config: Config):\n    \"\"\"Check if the app name is valid and matches the folder structure.\n\n    Args:\n        config: The config object.\n\n    Raises:\n        RuntimeError: If the app name is not set, folder doesn't exist, or doesn't match config.\n        ModuleNotFoundError: If the app_name is not importable (i.e., not a valid Python package, folder structure being wrong).\n    \"\"\"\n    if not config.app_name:\n        msg = (\n            \"Cannot get the app module because `app_name` is not set in rxconfig! \"\n            \"If this error occurs in a reflex test case, ensure that `get_app` is mocked.\"\n        )\n        raise RuntimeError(msg)\n\n    from reflex.utils.misc import with_cwd_in_syspath\n\n    with with_cwd_in_syspath():\n        module_path = get_module_path(config.module)\n        if module_path is None:\n            msg = f\"Module {config.module} not found. \"\n            if config.app_module_import is not None:\n                msg += f\"Ensure app_module_import='{config.app_module_import}' in rxconfig.py matches your folder structure.\"\n            else:\n                msg += f\"Ensure app_name='{config.app_name}' in rxconfig.py matches your folder structure.\"\n            raise ModuleNotFoundError(msg)\n    config._app_name_is_valid = True\n\n\ndef get_app(reload: bool = False) -> ModuleType:\n    \"\"\"Get the app module based on the default config.\n\n    Args:\n        reload: Re-import the app module from disk\n\n    Returns:\n        The app based on the default config.\n\n    Raises:\n        Exception: If an error occurs while getting the app module.\n    \"\"\"\n    from reflex.utils import telemetry\n\n    try:\n        config = get_config()\n\n        # Avoid hitting disk when the app name has already been validated in this process.\n        if not config._app_name_is_valid:\n            _check_app_name(config)\n\n        module = config.module\n        sys.path.insert(0, getcwd())  # noqa: PTH109\n        app = (\n            __import__(module, fromlist=(constants.CompileVars.APP,))\n            if not config.app_module\n            else config.app_module\n        )\n        if reload:\n            from reflex.page import DECORATED_PAGES\n            from reflex.state import reload_state_module\n\n            # Reset rx.State subclasses to avoid conflict when reloading.\n            reload_state_module(module=module)\n\n            DECORATED_PAGES.clear()\n\n            # Reload the app module.\n            importlib.reload(app)\n    except Exception as ex:\n        telemetry.send_error(ex, context=\"frontend\")\n        raise\n    else:\n        return app\n\n\ndef get_and_validate_app(\n    reload: bool = False, check_if_schema_up_to_date: bool = False\n) -> AppInfo:\n    \"\"\"Get the app instance based on the default config and validate it.\n\n    Args:\n        reload: Re-import the app module from disk\n        check_if_schema_up_to_date: If True, check if the schema is up to date.\n\n    Returns:\n        The app instance and the app module.\n\n    Raises:\n        RuntimeError: If the app instance is not an instance of rx.App.\n    \"\"\"\n    from reflex.app import App\n\n    app_module = get_app(reload=reload)\n    app = getattr(app_module, constants.CompileVars.APP)\n    if not isinstance(app, App):\n        msg = \"The app instance in the specified app_module_import in rxconfig must be an instance of rx.App.\"\n        raise RuntimeError(msg)\n\n    if check_if_schema_up_to_date:\n        check_schema_up_to_date()\n\n    return AppInfo(app=app, module=app_module)\n\n\ndef get_compiled_app(\n    reload: bool = False,\n    prerender_routes: bool = False,\n    dry_run: bool = False,\n    check_if_schema_up_to_date: bool = False,\n    use_rich: bool = True,\n) -> ModuleType:\n    \"\"\"Get the app module based on the default config after first compiling it.\n\n    Args:\n        reload: Re-import the app module from disk\n        prerender_routes: Whether to prerender routes.\n        dry_run: If True, do not write the compiled app to disk.\n        check_if_schema_up_to_date: If True, check if the schema is up to date.\n        use_rich: Whether to use rich progress bars.\n\n    Returns:\n        The compiled app based on the default config.\n    \"\"\"\n    app, app_module = get_and_validate_app(\n        reload=reload, check_if_schema_up_to_date=check_if_schema_up_to_date\n    )\n    app._compile(prerender_routes=prerender_routes, dry_run=dry_run, use_rich=use_rich)\n    return app_module\n\n\ndef _can_colorize() -> bool:\n    \"\"\"Check if the output can be colorized.\n\n    Copied from _colorize.can_colorize.\n\n    https://raw.githubusercontent.com/python/cpython/refs/heads/main/Lib/_colorize.py\n\n    Returns:\n        If the output can be colorized\n    \"\"\"\n    import io\n    import os\n\n    def _safe_getenv(k: str, fallback: str | None = None) -> str | None:\n        \"\"\"Exception-safe environment retrieval. See gh-128636.\n\n        Args:\n            k: The environment variable key.\n            fallback: The fallback value if the environment variable is not set.\n\n        Returns:\n            The value of the environment variable or the fallback value.\n        \"\"\"\n        try:\n            return os.environ.get(k, fallback)\n        except Exception:\n            return fallback\n\n    file = sys.stdout\n\n    if not sys.flags.ignore_environment:\n        if _safe_getenv(\"PYTHON_COLORS\") == \"0\":\n            return False\n        if _safe_getenv(\"PYTHON_COLORS\") == \"1\":\n            return True\n    if _safe_getenv(\"NO_COLOR\"):\n        return False\n    if _safe_getenv(\"FORCE_COLOR\"):\n        return True\n    if _safe_getenv(\"TERM\") == \"dumb\":\n        return False\n\n    if not hasattr(file, \"fileno\"):\n        return False\n\n    if sys.platform == \"win32\":\n        try:\n            import nt\n\n            if not nt._supports_virtual_terminal():\n                return False\n        except (ImportError, AttributeError):\n            return False\n\n    try:\n        return os.isatty(file.fileno())\n    except io.UnsupportedOperation:\n        return hasattr(file, \"isatty\") and file.isatty()\n\n\ndef compile_or_validate_app(\n    compile: bool = False,\n    check_if_schema_up_to_date: bool = False,\n    prerender_routes: bool = False,\n) -> bool:\n    \"\"\"Compile or validate the app module based on the default config.\n\n    Args:\n        compile: Whether to compile the app.\n        check_if_schema_up_to_date: If True, check if the schema is up to date.\n        prerender_routes: Whether to prerender routes.\n\n    Returns:\n        True if the app was successfully compiled or validated, False otherwise.\n    \"\"\"\n    try:\n        if compile:\n            get_compiled_app(\n                check_if_schema_up_to_date=check_if_schema_up_to_date,\n                prerender_routes=prerender_routes,\n            )\n        else:\n            get_and_validate_app(check_if_schema_up_to_date=check_if_schema_up_to_date)\n    except Exception as e:\n        import traceback\n\n        try:\n            colorize = _can_colorize()\n            traceback.print_exception(e, colorize=colorize)  # pyright: ignore[reportCallIssue]\n        except Exception:\n            traceback.print_exception(e)\n        return False\n    else:\n        return True\n\n\ndef get_redis() -> Redis | None:\n    \"\"\"Get the asynchronous redis client.\n\n    Returns:\n        The asynchronous redis client.\n    \"\"\"\n    try:\n        from redis.asyncio import Redis\n        from redis.exceptions import RedisError\n    except ImportError:\n        console.debug(\"Redis package not installed.\")\n        return None\n    if (redis_url := parse_redis_url()) is not None:\n        return Redis.from_url(\n            redis_url,\n            retry_on_error=[RedisError],\n        )\n    return None\n\n\ndef get_redis_sync() -> RedisSync | None:\n    \"\"\"Get the synchronous redis client.\n\n    Returns:\n        The synchronous redis client.\n    \"\"\"\n    try:\n        from redis import Redis as RedisSync\n        from redis.exceptions import RedisError\n    except ImportError:\n        console.debug(\"Redis package not installed.\")\n        return None\n    if (redis_url := parse_redis_url()) is not None:\n        return RedisSync.from_url(\n            redis_url,\n            retry_on_error=[RedisError],\n        )\n    return None\n\n\ndef parse_redis_url() -> str | None:\n    \"\"\"Parse the REFLEX_REDIS_URL in config if applicable.\n\n    Returns:\n        If url is non-empty, return the URL as it is.\n\n    Raises:\n        ValueError: If the REFLEX_REDIS_URL is not a supported scheme.\n    \"\"\"\n    config = get_config()\n    if not config.redis_url:\n        return None\n    if not config.redis_url.startswith((\"redis://\", \"rediss://\", \"unix://\")):\n        msg = \"REFLEX_REDIS_URL must start with 'redis://', 'rediss://', or 'unix://'.\"\n        raise ValueError(msg)\n    return config.redis_url\n\n\nasync def get_redis_status() -> dict[str, bool | None]:\n    \"\"\"Checks the status of the Redis connection.\n\n    Attempts to connect to Redis and send a ping command to verify connectivity.\n\n    Returns:\n        The status of the Redis connection.\n    \"\"\"\n    try:\n        status = True\n        redis_client = get_redis()\n        if redis_client is not None:\n            ping_command = redis_client.ping()\n            if inspect.isawaitable(ping_command):\n                await ping_command\n        else:\n            status = None\n    except Exception as exc:\n        status = False\n        console.error(\n            f\"Redis health check failed: {exc} (subsequent errors will not be logged)\",\n            dedupe=True,\n        )\n\n    return {\"redis\": status}\n\n\ndef validate_app_name(app_name: str | None = None) -> str:\n    \"\"\"Validate the app name.\n\n    The default app name is the name of the current directory.\n\n    Args:\n        app_name: the name passed by user during reflex init\n\n    Returns:\n        The app name after validation.\n\n    Raises:\n        SystemExit: if the app directory name is reflex or if the name is not standard for a python package name.\n    \"\"\"\n    app_name = app_name or Path.cwd().name.replace(\"-\", \"_\")\n    # Make sure the app is not named \"reflex\".\n    if app_name.lower() == constants.Reflex.MODULE_NAME:\n        console.error(\n            f\"The app directory cannot be named [bold]{constants.Reflex.MODULE_NAME}[/bold].\"\n        )\n        raise SystemExit(1)\n\n    # Make sure the app name is standard for a python package name.\n    if not re.match(r\"^[a-zA-Z][a-zA-Z0-9_]*$\", app_name):\n        console.error(\n            \"The app directory name must start with a letter and can contain letters, numbers, and underscores.\"\n        )\n        raise SystemExit(1)\n\n    return app_name\n\n\ndef get_project_hash(raise_on_fail: bool = False) -> int | None:\n    \"\"\"Get the project hash from the reflex.json file if the file exists.\n\n    Args:\n        raise_on_fail: Whether to raise an error if the file does not exist.\n\n    Returns:\n        project_hash: The app hash.\n    \"\"\"\n    json_file = get_web_dir() / constants.Reflex.JSON\n    if not json_file.exists() and not raise_on_fail:\n        return None\n    data = json.loads(json_file.read_text())\n    return data.get(\"project_hash\")\n\n\ndef check_running_mode(frontend: bool, backend: bool) -> tuple[bool, bool]:\n    \"\"\"Check if the app is running in frontend or backend mode.\n\n    Args:\n        frontend: Whether to run the frontend of the app.\n        backend: Whether to run the backend of the app.\n\n    Returns:\n        The running modes.\n    \"\"\"\n    if not frontend and not backend:\n        return True, True\n    return frontend, backend\n\n\ndef assert_in_reflex_dir():\n    \"\"\"Assert that the current working directory is the reflex directory.\n\n    Raises:\n        SystemExit: If the current working directory is not the reflex directory.\n    \"\"\"\n    if not constants.Config.FILE.exists():\n        console.error(\n            f\"[cyan]{constants.Config.FILE}[/cyan] not found. Move to the root folder of your project, or run [bold]{constants.Reflex.MODULE_NAME} init[/bold] to start a new project.\"\n        )\n        raise SystemExit(1)\n\n\ndef needs_reinit() -> bool:\n    \"\"\"Check if an app needs to be reinitialized.\n\n    Returns:\n        Whether the app needs to be reinitialized.\n    \"\"\"\n    # Make sure the .reflex directory exists.\n    if not environment.REFLEX_DIR.get().exists():\n        return True\n\n    # Make sure the .web directory exists in frontend mode.\n    if not get_web_dir().exists():\n        return True\n\n    if not _is_app_compiled_with_same_reflex_version():\n        return True\n\n    if constants.IS_WINDOWS:\n        console.warn(\n            \"\"\"Windows Subsystem for Linux (WSL) is recommended for improving initial install times.\"\"\"\n        )\n\n        if windows_check_onedrive_in_path():\n            console.warn(\n                \"Creating project directories in OneDrive may lead to performance issues. For optimal performance, It is recommended to avoid using OneDrive for your reflex app.\"\n            )\n    # No need to reinitialize if the app is already initialized.\n    return False\n\n\ndef _is_app_compiled_with_same_reflex_version() -> bool:\n    json_file = get_web_dir() / constants.Reflex.JSON\n    if not json_file.exists():\n        return False\n    app_version = json.loads(json_file.read_text()).get(\"version\")\n    return app_version == constants.Reflex.VERSION\n\n\ndef ensure_reflex_installation_id() -> int | None:\n    \"\"\"Ensures that a reflex distinct id has been generated and stored in the reflex directory.\n\n    Returns:\n        Distinct id.\n    \"\"\"\n    try:\n        console.debug(\"Ensuring reflex installation id.\")\n        initialize_reflex_user_directory()\n        installation_id_file = environment.REFLEX_DIR.get() / \"installation_id\"\n\n        installation_id = None\n        if installation_id_file.exists():\n            with contextlib.suppress(Exception):\n                installation_id = int(installation_id_file.read_text())\n                # If anything goes wrong at all... just regenerate.\n                # Like what? Examples:\n                #     - file not exists\n                #     - file not readable\n                #     - content not parseable as an int\n\n        if installation_id is None:\n            installation_id = random.getrandbits(128)\n            installation_id_file.write_text(str(installation_id))\n    except Exception as e:\n        console.debug(f\"Failed to ensure reflex installation id: {e}\")\n        return None\n    else:\n        # If we get here, installation_id is definitely set\n        return installation_id\n\n\ndef initialize_reflex_user_directory():\n    \"\"\"Initialize the reflex user directory.\"\"\"\n    console.debug(f\"Creating {environment.REFLEX_DIR.get()}\")\n    # Create the reflex directory.\n    path_ops.mkdir(environment.REFLEX_DIR.get())\n\n\ndef initialize_frontend_dependencies():\n    \"\"\"Initialize all the frontend dependencies.\"\"\"\n    from reflex.utils.frontend_skeleton import initialize_web_directory\n    from reflex.utils.js_runtimes import install_bun, validate_frontend_dependencies\n\n    # validate dependencies before install\n    console.debug(\"Validating frontend dependencies.\")\n    validate_frontend_dependencies()\n    # Install the frontend dependencies.\n    console.debug(\"Installing or validating bun.\")\n    install_bun()\n    # Set up the web directory.\n    initialize_web_directory()\n\n\ndef check_db_used() -> bool:\n    \"\"\"Check if the database is used.\n\n    Returns:\n        True if the database is used.\n    \"\"\"\n    return bool(get_config().db_url)\n\n\ndef check_redis_used() -> bool:\n    \"\"\"Check if Redis is used.\n\n    Returns:\n        True if Redis is used.\n    \"\"\"\n    return bool(get_config().redis_url)\n\n\ndef check_db_initialized() -> bool:\n    \"\"\"Check if the database migrations are initialized.\n\n    Returns:\n        True if alembic is initialized (or if database is not used).\n    \"\"\"\n    if (\n        get_config().db_url is not None\n        and not environment.ALEMBIC_CONFIG.get().exists()\n    ):\n        console.error(\n            \"Database is not initialized. Run [bold]reflex db init[/bold] first.\",\n            dedupe=True,\n        )\n        return False\n    return True\n\n\ndef check_schema_up_to_date():\n    \"\"\"Check if the sqlmodel metadata matches the current database schema.\"\"\"\n    if get_config().db_url is None or not environment.ALEMBIC_CONFIG.get().exists():\n        return\n    with model.Model.get_db_engine().connect() as connection:\n        from alembic.util.exc import CommandError\n\n        try:\n            if model.Model.alembic_autogenerate(\n                connection=connection,\n                write_migration_scripts=False,\n            ):\n                console.error(\n                    \"Detected database schema changes. Run [bold]reflex db makemigrations[/bold] \"\n                    \"to generate migration scripts.\",\n                )\n        except CommandError as command_error:\n            if \"Target database is not up to date.\" in str(command_error):\n                console.error(\n                    f\"{command_error} Run [bold]reflex db migrate[/bold] to update database.\"\n                )\n\n\n@once\ndef get_user_tier():\n    \"\"\"Get the current user's tier.\n\n    Returns:\n        The current user's tier.\n    \"\"\"\n    from reflex_cli.v2.utils import hosting\n\n    authenticated_token = hosting.authenticated_token()\n    return (\n        authenticated_token[1].get(\"tier\", \"\").lower()\n        if authenticated_token[0]\n        else \"anonymous\"\n    )\n"
  },
  {
    "path": "reflex/utils/processes.py",
    "content": "\"\"\"Process operations.\"\"\"\n\nfrom __future__ import annotations\n\nimport collections\nimport contextlib\nimport os\nimport signal\nimport socket\nimport subprocess\nimport sys\nfrom collections.abc import Callable, Generator, Sequence\nfrom concurrent import futures\nfrom contextlib import closing\nfrom pathlib import Path\nfrom typing import Any, Literal, overload\n\nimport rich.markup\nfrom rich.progress import Progress\n\nfrom reflex import constants\nfrom reflex.config import get_config\nfrom reflex.environment import environment\nfrom reflex.utils import console, path_ops, prerequisites\nfrom reflex.utils.registry import get_npm_registry\n\n\ndef kill(pid: int):\n    \"\"\"Kill a process.\n\n    Args:\n        pid: The process ID.\n    \"\"\"\n    os.kill(pid, signal.SIGTERM)\n\n\ndef get_num_workers() -> int:\n    \"\"\"Get the number of backend worker processes.\n\n    Returns:\n        The number of backend worker processes.\n\n    Raises:\n        SystemExit: If unable to connect to Redis.\n    \"\"\"\n    if get_config().transport == \"polling\":\n        return 1\n\n    if (redis_client := prerequisites.get_redis_sync()) is None:\n        return 1\n\n    from redis.exceptions import RedisError\n\n    try:\n        redis_client.ping()\n    except RedisError as re:\n        console.error(f\"Unable to connect to Redis: {re}\")\n        raise SystemExit(1) from None\n    return (os.cpu_count() or 1) * 2 + 1\n\n\ndef _can_bind_at_port(\n    address_family: socket.AddressFamily | int, address: str, port: int\n) -> bool:\n    \"\"\"Check if a given address and port are responsive.\n\n    Args:\n        address_family: The address family (e.g., socket.AF_INET or socket.AF_INET6).\n        address: The address to check.\n        port: The port to check.\n\n    Returns:\n        Whether the address and port are responsive.\n    \"\"\"\n    try:\n        with closing(socket.socket(address_family, socket.SOCK_STREAM)) as sock:\n            if sys.platform != \"win32\":\n                sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n            sock.bind((address, port))\n    except (OverflowError, PermissionError, OSError) as e:\n        console.warn(f\"Unable to bind to {address}:{port} due to: {e}.\")\n        return False\n    return True\n\n\ndef _can_bind_at_any_port(address_family: socket.AddressFamily | int) -> bool:\n    \"\"\"Check if any port is available for binding.\n\n    Args:\n        address_family: The address family (e.g., socket.AF_INET or socket.AF_INET6).\n\n    Returns:\n        Whether any port is available for binding.\n    \"\"\"\n    try:\n        with closing(socket.socket(address_family, socket.SOCK_STREAM)) as sock:\n            sock.bind((\"\", 0))  # Bind to any available port\n            return True\n    except (OverflowError, PermissionError, OSError) as e:\n        console.debug(f\"Unable to bind to any port for {address_family}: {e}\")\n        return False\n\n\ndef is_process_on_port(\n    port: int,\n    address_families: Sequence[socket.AddressFamily | int] = (\n        socket.AF_INET,\n        socket.AF_INET6,\n    ),\n) -> bool:\n    \"\"\"Check if a process is running on the given port.\n\n    Args:\n        port: The port.\n        address_families: The address families to check (default: IPv4 and IPv6).\n\n    Returns:\n        Whether a process is running on the given port.\n    \"\"\"\n    return any(not _can_bind_at_port(family, \"\", port) for family in address_families)\n\n\nMAXIMUM_PORT = 2**16 - 1\n\n\ndef handle_port(service_name: str, port: int, auto_increment: bool) -> int:\n    \"\"\"Change port if the specified port is in use and is not explicitly specified as a CLI arg or config arg.\n    Otherwise tell the user the port is in use and exit the app.\n\n    Args:\n        service_name: The frontend or backend.\n        port: The provided port.\n        auto_increment: Whether to automatically increment the port.\n\n    Returns:\n        The port to run the service on.\n\n    Raises:\n        SystemExit:when the port is in use.\n    \"\"\"\n    console.debug(f\"Checking if {service_name.capitalize()} port: {port} is in use.\")\n\n    families = [\n        address_family\n        for address_family in (socket.AF_INET, socket.AF_INET6)\n        if _can_bind_at_any_port(address_family)\n    ]\n\n    if not families:\n        console.error(\n            f\"Unable to bind to any port for {service_name}. \"\n            \"Please check your network configuration.\"\n        )\n        raise SystemExit(1)\n\n    console.debug(\n        f\"Checking if {service_name.capitalize()} port: {port} is in use for families: {families}.\"\n    )\n\n    if not is_process_on_port(port, families):\n        console.debug(f\"{service_name.capitalize()} port: {port} is not in use.\")\n        return port\n\n    if auto_increment:\n        for new_port in range(port + 1, MAXIMUM_PORT + 1):\n            if not is_process_on_port(new_port, families):\n                console.info(\n                    f\"The {service_name} will run on port [bold underline]{new_port}[/bold underline].\"\n                )\n                return new_port\n            console.debug(\n                f\"{service_name.capitalize()} port: {new_port} is already in use.\"\n            )\n\n        # If we reach here, it means we couldn't find an available port.\n        console.error(f\"Unable to find an available port for {service_name}\")\n    else:\n        console.error(f\"{service_name.capitalize()} port: {port} is already in use.\")\n\n    raise SystemExit(1)\n\n\n@overload\ndef new_process(\n    args: str | list[str] | list[str | None] | list[str | Path | None],\n    run: Literal[False] = False,\n    show_logs: bool = False,\n    **kwargs,\n) -> subprocess.Popen[str]: ...\n\n\n@overload\ndef new_process(\n    args: str | list[str] | list[str | None] | list[str | Path | None],\n    run: Literal[True],\n    show_logs: bool = False,\n    **kwargs,\n) -> subprocess.CompletedProcess[str]: ...\n\n\ndef new_process(\n    args: str | list[str] | list[str | None] | list[str | Path | None],\n    run: bool = False,\n    show_logs: bool = False,\n    **kwargs,\n) -> subprocess.CompletedProcess[str] | subprocess.Popen[str]:\n    \"\"\"Wrapper over subprocess.Popen to unify the launch of child processes.\n\n    Args:\n        args: A string, or a sequence of program arguments.\n        run: Whether to run the process to completion.\n        show_logs: Whether to show the logs of the process.\n        **kwargs: Kwargs to override default wrap values to pass to subprocess.Popen as arguments.\n\n    Returns:\n        Execute a child program in a new process.\n\n    Raises:\n        SystemExit: When attempting to run a command with a None value.\n    \"\"\"\n    # Check for invalid command first.\n    non_empty_args = list(filter(None, args)) if isinstance(args, list) else [args]\n    if isinstance(args, list) and len(non_empty_args) != len(args):\n        console.error(f\"Invalid command: {args}\")\n        raise SystemExit(1)\n\n    path_env: str = os.environ.get(\"PATH\", \"\")\n\n    # Add node_bin_path to the PATH environment variable.\n    if not environment.REFLEX_BACKEND_ONLY.get():\n        node_bin_path = path_ops.get_node_bin_path()\n        if node_bin_path:\n            path_env = os.pathsep.join([str(node_bin_path), path_env])\n\n    env: dict[str, str] = {\n        **os.environ,\n        \"PATH\": path_env,\n        **kwargs.pop(\"env\", {}),\n    }\n\n    kwargs = {\n        \"env\": env,\n        \"stderr\": None if show_logs else subprocess.STDOUT,\n        \"stdout\": None if show_logs else subprocess.PIPE,\n        \"universal_newlines\": True,\n        \"encoding\": \"UTF-8\",\n        \"errors\": \"replace\",  # Avoid UnicodeDecodeError in unknown command output\n        **kwargs,\n    }\n    console.debug(f\"Running command: {non_empty_args}\")\n\n    def subprocess_p_open(args: subprocess._CMD, **kwargs):\n        return subprocess.Popen(args, **kwargs)\n\n    fn: Callable[..., subprocess.CompletedProcess[str] | subprocess.Popen[str]] = (\n        subprocess.run if run else subprocess_p_open\n    )\n    return fn(non_empty_args, **kwargs)\n\n\n@contextlib.contextmanager\ndef run_concurrently_context(\n    *fns: Callable[..., Any] | tuple[Callable[..., Any], ...],\n) -> Generator[list[futures.Future], None, None]:\n    \"\"\"Run functions concurrently in a thread pool.\n\n    Args:\n        *fns: The functions to run.\n\n    Yields:\n        The futures for the functions.\n    \"\"\"\n    # If no functions are provided, yield an empty list and return.\n    if not fns:\n        yield []\n        return\n\n    # Convert the functions to tuples.\n    fns = tuple(fn if isinstance(fn, tuple) else (fn,) for fn in fns)\n\n    # Run the functions concurrently.\n    executor = None\n    try:\n        executor = futures.ThreadPoolExecutor(max_workers=len(fns))\n        # Submit the tasks.\n        tasks = [executor.submit(*fn) for fn in fns]\n\n        # Yield control back to the main thread while tasks are running.\n        yield tasks\n\n        # Get the results in the order completed to check any exceptions.\n        for task in futures.as_completed(tasks):\n            # if task throws something, we let it bubble up immediately\n            task.result()\n    finally:\n        # Shutdown the executor\n        if executor:\n            executor.shutdown(wait=False)\n\n\ndef run_concurrently(*fns: Callable | tuple) -> None:\n    \"\"\"Run functions concurrently in a thread pool.\n\n    Args:\n        *fns: The functions to run.\n    \"\"\"\n    with run_concurrently_context(*fns):\n        pass\n\n\ndef stream_logs(\n    message: str,\n    process: subprocess.Popen,\n    progress: Progress | None = None,\n    suppress_errors: bool = False,\n    analytics_enabled: bool = False,\n    prior_logs: tuple[tuple[str, ...], ...] = (),\n):\n    \"\"\"Stream the logs for a process.\n\n    Args:\n        message: The message to display.\n        process: The process.\n        progress: The ongoing progress bar if one is being used.\n        suppress_errors: If True, do not exit if errors are encountered (for fallback).\n        analytics_enabled: Whether analytics are enabled for this command.\n        prior_logs: The logs of the prior processes that have been run.\n\n    Yields:\n        The lines of the process output.\n\n    Raises:\n        SystemExit: If the process failed.\n        ValueError: If the process stdout pipe is closed, but the process remains running.\n    \"\"\"\n    from reflex.utils import telemetry\n\n    # Store the tail of the logs.\n    logs = collections.deque(maxlen=512)\n    with process:\n        console.debug(message, progress=progress)\n        if process.stdout is None:\n            return\n        try:\n            for line in process.stdout:\n                console.debug(rich.markup.escape(line), end=\"\", progress=progress)\n                logs.append(line)\n                yield line\n        except ValueError:\n            # The stream we were reading has been closed,\n            if process.poll() is None:\n                # But if the process is still running that is weird.\n                raise\n            # If the process exited, break out of the loop for post processing.\n\n    # Check if the process failed (not printing the logs for SIGINT).\n\n    # Windows uvicorn bug\n    # https://github.com/reflex-dev/reflex/issues/2335\n    # 130 is the exit code that react router returns when it is interrupted by a signal.\n    accepted_return_codes = [0, -2, 15, 130] if constants.IS_WINDOWS else [0, -2, 130]\n    if process.returncode not in accepted_return_codes and not suppress_errors:\n        console.error(f\"{message} failed with exit code {process.returncode}\")\n        if \"\".join(logs).count(\"CERT_HAS_EXPIRED\") > 0:\n            bunfig = prerequisites.get_web_dir() / constants.Bun.CONFIG_PATH\n            npm_registry_line = next(\n                (\n                    line\n                    for line in bunfig.read_text().splitlines()\n                    if line.startswith(\"registry\")\n                ),\n                None,\n            )\n            if not npm_registry_line or \"=\" not in npm_registry_line:\n                npm_registry = get_npm_registry()\n            else:\n                npm_registry = npm_registry_line.split(\"=\")[1].strip()\n            console.error(\n                f\"Failed to fetch securely from [bold]{npm_registry}[/bold]. Please check your network connection. \"\n                \"You can try running the command again or changing the registry by setting the \"\n                \"NPM_CONFIG_REGISTRY environment variable. If TLS is the issue, and you know what \"\n                \"you are doing, you can disable it by setting the SSL_NO_VERIFY environment variable.\"\n            )\n            raise SystemExit(1)\n        for set_of_logs in (*prior_logs, tuple(logs)):\n            for line in set_of_logs:\n                console.error(line, end=\"\")\n            console.error(\"\\n\\n\")\n        if analytics_enabled:\n            telemetry.send(\"error\", context=message)\n        console.error(\"Run with [bold]--loglevel debug [/bold] for the full log.\")\n        raise SystemExit(1)\n\n\ndef show_logs(message: str, process: subprocess.Popen):\n    \"\"\"Show the logs for a process.\n\n    Args:\n        message: The message to display.\n        process: The process.\n    \"\"\"\n    for _ in stream_logs(message, process):\n        pass\n\n\ndef show_status(\n    message: str,\n    process: subprocess.Popen,\n    suppress_errors: bool = False,\n    analytics_enabled: bool = False,\n    prior_logs: tuple[tuple[str, ...], ...] = (),\n) -> list[str]:\n    \"\"\"Show the status of a process.\n\n    Args:\n        message: The initial message to display.\n        process: The process.\n        suppress_errors: If True, do not exit if errors are encountered (for fallback).\n        analytics_enabled: Whether analytics are enabled for this command.\n        prior_logs: The logs of the prior processes that have been run.\n\n    Returns:\n        The lines of the process output.\n    \"\"\"\n    lines = []\n\n    with console.status(message) as status:\n        for line in stream_logs(\n            message,\n            process,\n            suppress_errors=suppress_errors,\n            analytics_enabled=analytics_enabled,\n            prior_logs=prior_logs,\n        ):\n            status.update(f\"{message} {line}\")\n            lines.append(line)\n        return lines\n\n\ndef show_progress(message: str, process: subprocess.Popen, checkpoints: list[str]):\n    \"\"\"Show a progress bar for a process.\n\n    Args:\n        message: The message to display.\n        process: The process.\n        checkpoints: The checkpoints to advance the progress bar.\n    \"\"\"\n    # Iterate over the process output.\n    with console.progress() as progress:\n        task = progress.add_task(f\"{message}: \", total=len(checkpoints))\n        for line in stream_logs(message, process, progress=progress):\n            # Check for special strings and update the progress bar.\n            while checkpoints:\n                special_string = checkpoints[0]\n                if special_string in line:\n                    progress.update(task, advance=1)\n                    checkpoints.pop(0)\n                    continue\n                break\n\n\ndef atexit_handler():\n    \"\"\"Display a custom message with the current time when exiting an app.\"\"\"\n    console.log(\"Reflex app stopped.\")\n\n\ndef get_command_with_loglevel(command: list[str]) -> list[str]:\n    \"\"\"Add the right loglevel flag to the designated command.\n     npm uses --loglevel <level>, Bun doesn't use the --loglevel flag and\n     runs in debug mode by default.\n\n    Args:\n        command:The command to add loglevel flag.\n\n    Returns:\n        The updated command list\n    \"\"\"\n    npm_path = path_ops.get_npm_path()\n    npm_path = str(npm_path) if npm_path else None\n\n    if command[0] == npm_path:\n        return [*command, \"--loglevel\", \"silly\"]\n    return command\n\n\ndef run_process_with_fallbacks(\n    args: list[str],\n    *,\n    show_status_message: str,\n    fallbacks: str | Sequence[str] | Sequence[Sequence[str]] | None = None,\n    analytics_enabled: bool = False,\n    prior_logs: tuple[tuple[str, ...], ...] = (),\n    **kwargs,\n):\n    \"\"\"Run subprocess and retry using fallback command if initial command fails.\n\n    Args:\n        args: A string, or a sequence of program arguments.\n        show_status_message: The status message to be displayed in the console.\n        fallbacks: The fallback command to run if the initial command fails.\n        analytics_enabled: Whether analytics are enabled for this command.\n        prior_logs: The logs of the prior processes that have been run.\n        **kwargs: Kwargs to pass to new_process function.\n    \"\"\"\n    process = new_process(get_command_with_loglevel(args), **kwargs)\n    if not fallbacks:\n        # No fallback given, or this _is_ the fallback command.\n        show_status(\n            show_status_message,\n            process,\n            analytics_enabled=analytics_enabled,\n            prior_logs=prior_logs,\n        )\n    else:\n        # Suppress errors for initial command, because we will try to fallback\n        logs = show_status(show_status_message, process, suppress_errors=True)\n\n        current_fallback = fallbacks[0] if not isinstance(fallbacks, str) else fallbacks\n        next_fallbacks = fallbacks[1:] if not isinstance(fallbacks, str) else None\n\n        if process.returncode != 0:\n            # retry with fallback command.\n            fallback_with_args = (\n                [current_fallback, *args[1:]]\n                if isinstance(current_fallback, str)\n                else [*current_fallback, *args[1:]]\n            )\n            console.warn(\n                f\"There was an error running command: {args}. Falling back to: {fallback_with_args}.\"\n            )\n            run_process_with_fallbacks(\n                fallback_with_args,\n                show_status_message=show_status_message,\n                fallbacks=next_fallbacks,\n                analytics_enabled=analytics_enabled,\n                prior_logs=(*prior_logs, tuple(logs)),\n                **kwargs,\n            )\n\n\ndef execute_command_and_return_output(command: str) -> str | None:\n    \"\"\"Execute a command and return the output.\n\n    Args:\n        command: The command to run.\n\n    Returns:\n        The output of the command.\n    \"\"\"\n    try:\n        return subprocess.check_output(command, shell=True).decode().strip()\n    except subprocess.SubprocessError as err:\n        console.error(\n            f\"The command `{command}` failed with error: {err}. This will return None.\"\n        )\n        return None\n"
  },
  {
    "path": "reflex/utils/pyi_generator.py",
    "content": "\"\"\"The pyi generator module.\"\"\"\n\nfrom __future__ import annotations\n\nimport ast\nimport contextlib\nimport importlib\nimport inspect\nimport json\nimport logging\nimport multiprocessing\nimport re\nimport subprocess\nimport sys\nimport typing\nfrom collections.abc import Callable, Iterable, Mapping, Sequence\nfrom concurrent.futures import ProcessPoolExecutor\nfrom functools import cache\nfrom hashlib import md5\nfrom inspect import getfullargspec\nfrom itertools import chain\nfrom pathlib import Path\nfrom types import MappingProxyType, ModuleType, SimpleNamespace, UnionType\nfrom typing import Any, get_args, get_origin\n\nfrom reflex.components.component import Component\nfrom reflex.utils import types as rx_types\nfrom reflex.vars.base import Var\n\nlogger = logging.getLogger(\"pyi_generator\")\n\nPWD = Path.cwd()\n\nPYI_HASHES = \"pyi_hashes.json\"\n\nEXCLUDED_FILES = [\n    \"app.py\",\n    \"component.py\",\n    \"bare.py\",\n    \"foreach.py\",\n    \"cond.py\",\n    \"match.py\",\n    \"multiselect.py\",\n    \"literals.py\",\n]\n\n# These props exist on the base component, but should not be exposed in create methods.\nEXCLUDED_PROPS = [\n    \"alias\",\n    \"children\",\n    \"event_triggers\",\n    \"library\",\n    \"lib_dependencies\",\n    \"tag\",\n    \"is_default\",\n    \"special_props\",\n    \"_is_tag_in_global_scope\",\n    \"_invalid_children\",\n    \"_memoization_mode\",\n    \"_rename_props\",\n    \"_valid_children\",\n    \"_valid_parents\",\n    \"State\",\n]\n\nOVERWRITE_TYPES = {\n    \"style\": \"Sequence[Mapping[str, Any]] | Mapping[str, Any] | Var[Mapping[str, Any]] | Breakpoints | None\",\n}\n\nDEFAULT_TYPING_IMPORTS = {\n    \"Any\",\n    \"Callable\",\n    \"Dict\",\n    # \"List\",\n    \"Sequence\",\n    \"Mapping\",\n    \"Literal\",\n    \"Optional\",\n    \"Union\",\n    \"Annotated\",\n}\n\n# TODO: fix import ordering and unused imports with ruff later\nDEFAULT_IMPORTS = {\n    \"typing\": sorted(DEFAULT_TYPING_IMPORTS),\n    \"reflex.components.core.breakpoints\": [\"Breakpoints\"],\n    \"reflex.event\": [\n        \"EventChain\",\n        \"EventHandler\",\n        \"EventSpec\",\n        \"EventType\",\n        \"KeyInputInfo\",\n        \"PointerEventInfo\",\n    ],\n    \"reflex.style\": [\"Style\"],\n    \"reflex.vars.base\": [\"Var\"],\n}\n\n\ndef _walk_files(path: str | Path):\n    \"\"\"Walk all files in a path.\n    This can be replaced with Path.walk() in python3.12.\n\n    Args:\n        path: The path to walk.\n\n    Yields:\n        The next file in the path.\n    \"\"\"\n    for p in Path(path).iterdir():\n        if p.is_dir():\n            yield from _walk_files(p)\n            continue\n        yield p.resolve()\n\n\ndef _relative_to_pwd(path: Path) -> Path:\n    \"\"\"Get the relative path of a path to the current working directory.\n\n    Args:\n        path: The path to get the relative path for.\n\n    Returns:\n        The relative path.\n    \"\"\"\n    if path.is_absolute():\n        return path.relative_to(PWD)\n    return path\n\n\ndef _get_type_hint(\n    value: Any, type_hint_globals: dict, is_optional: bool = True\n) -> str:\n    \"\"\"Resolve the type hint for value.\n\n    Args:\n        value: The type annotation as a str or actual types/aliases.\n        type_hint_globals: The globals to use to resolving a type hint str.\n        is_optional: Whether the type hint should be wrapped in Optional.\n\n    Returns:\n        The resolved type hint as a str.\n\n    Raises:\n        TypeError: If the value name is not visible in the type hint globals.\n    \"\"\"\n    res = \"\"\n    args = get_args(value)\n\n    if value is type(None) or value is None:\n        return \"None\"\n\n    if rx_types.is_union(value):\n        if type(None) in value.__args__:\n            res_args = [\n                _get_type_hint(arg, type_hint_globals, rx_types.is_optional(arg))\n                for arg in value.__args__\n                if arg is not type(None)\n            ]\n            res_args.sort()\n            if len(res_args) == 1:\n                return f\"{res_args[0]} | None\"\n            res = f\"{' | '.join(res_args)}\"\n            return f\"{res} | None\"\n\n        res_args = [\n            _get_type_hint(arg, type_hint_globals, rx_types.is_optional(arg))\n            for arg in value.__args__\n        ]\n        res_args.sort()\n        return f\"{' | '.join(res_args)}\"\n\n    if args:\n        inner_container_type_args = (\n            sorted(repr(arg) for arg in args)\n            if rx_types.is_literal(value)\n            else [\n                _get_type_hint(arg, type_hint_globals, is_optional=False)\n                for arg in args\n                if arg is not type(None)\n            ]\n        )\n\n        if (\n            value.__module__ not in [\"builtins\", \"__builtins__\"]\n            and value.__name__ not in type_hint_globals\n        ):\n            msg = (\n                f\"{value.__module__ + '.' + value.__name__} is not a default import, \"\n                \"add it to DEFAULT_IMPORTS in pyi_generator.py\"\n            )\n            raise TypeError(msg)\n\n        res = f\"{value.__name__}[{', '.join(inner_container_type_args)}]\"\n\n        if value.__name__ == \"Var\":\n            args = list(\n                chain.from_iterable([\n                    get_args(arg) if rx_types.is_union(arg) else [arg] for arg in args\n                ])\n            )\n\n            # For Var types, Union with the inner args so they can be passed directly.\n            types = [res] + [\n                _get_type_hint(arg, type_hint_globals, is_optional=False)\n                for arg in args\n                if arg is not type(None)\n            ]\n            if len(types) > 1:\n                res = \" | \".join(sorted(types))\n\n    elif isinstance(value, str):\n        ev = eval(value, type_hint_globals)\n        if rx_types.is_optional(ev):\n            return _get_type_hint(ev, type_hint_globals, is_optional=False)\n\n        if rx_types.is_union(ev):\n            res = [\n                _get_type_hint(arg, type_hint_globals, rx_types.is_optional(arg))\n                for arg in ev.__args__\n            ]\n            return f\"{' | '.join(res)}\"\n        res = (\n            _get_type_hint(ev, type_hint_globals, is_optional=False)\n            if ev.__name__ == \"Var\"\n            else value\n        )\n    elif isinstance(value, list):\n        res = [\n            _get_type_hint(arg, type_hint_globals, rx_types.is_optional(arg))\n            for arg in value\n        ]\n        return f\"[{', '.join(res)}]\"\n    else:\n        res = value.__name__\n    if is_optional and not res.startswith(\"Optional\") and not res.endswith(\"| None\"):\n        res = f\"{res} | None\"\n    return res\n\n\n@cache\ndef _get_source(obj: Any) -> str:\n    \"\"\"Get and cache the source for a Python object.\n\n    Args:\n        obj: The object whose source should be retrieved.\n\n    Returns:\n        The source code for the object.\n    \"\"\"\n    return inspect.getsource(obj)\n\n\n@cache\ndef _get_class_prop_comments(clz: type[Component]) -> Mapping[str, tuple[str, ...]]:\n    \"\"\"Parse and cache prop comments for a component class.\n\n    Args:\n        clz: The class to extract prop comments from.\n\n    Returns:\n        An immutable mapping of prop name to comment lines.\n    \"\"\"\n    props_comments: dict[str, tuple[str, ...]] = {}\n    comments = []\n    for line in _get_source(clz).splitlines():\n        reached_functions = re.search(r\"def \", line)\n        if reached_functions:\n            # We've reached the functions, so stop.\n            break\n\n        if line == \"\":\n            # We hit a blank line, so clear comments to avoid commented out prop appearing in next prop docs.\n            comments.clear()\n            continue\n\n        # Get comments for prop\n        if line.strip().startswith(\"#\"):\n            # Remove noqa from the comments.\n            line = line.partition(\" # noqa\")[0]\n            comments.append(line)\n            continue\n\n        # Check if this line has a prop.\n        match = re.search(r\"\\w+:\", line)\n        if match is None:\n            # This line doesn't have a var, so continue.\n            continue\n\n        # Get the prop.\n        prop = match.group(0).strip(\":\")\n        if comments:\n            props_comments[prop] = tuple(\n                comment.strip().strip(\"#\") for comment in comments\n            )\n        comments.clear()\n\n    return MappingProxyType(props_comments)\n\n\n@cache\ndef _get_full_argspec(func: Callable) -> inspect.FullArgSpec:\n    \"\"\"Get and cache the full argspec for a callable.\n\n    Args:\n        func: The callable to inspect.\n\n    Returns:\n        The full argument specification.\n    \"\"\"\n    return getfullargspec(func)\n\n\n@cache\ndef _get_signature_return_annotation(func: Callable) -> Any:\n    \"\"\"Get and cache a callable's return annotation.\n\n    Args:\n        func: The callable to inspect.\n\n    Returns:\n        The callable's return annotation.\n    \"\"\"\n    return inspect.signature(func).return_annotation\n\n\n@cache\ndef _get_module_star_imports(module_name: str) -> Mapping[str, Any]:\n    \"\"\"Resolve names imported by `from module import *`.\n\n    Args:\n        module_name: The module to inspect.\n\n    Returns:\n        An immutable mapping of imported names to values.\n    \"\"\"\n    module = importlib.import_module(module_name)\n    exported_names = getattr(module, \"__all__\", None)\n    if exported_names is not None:\n        return MappingProxyType({\n            name: getattr(module, name) for name in exported_names\n        })\n    return MappingProxyType({\n        name: value for name, value in vars(module).items() if not name.startswith(\"_\")\n    })\n\n\n@cache\ndef _get_module_selected_imports(\n    module_name: str, imported_names: tuple[str, ...]\n) -> Mapping[str, Any]:\n    \"\"\"Resolve a set of imported names from a module.\n\n    Args:\n        module_name: The module to import from.\n        imported_names: The names to resolve.\n\n    Returns:\n        An immutable mapping of imported names to values.\n    \"\"\"\n    module = importlib.import_module(module_name)\n    return MappingProxyType({name: getattr(module, name) for name in imported_names})\n\n\n@cache\ndef _get_class_annotation_globals(target_class: type) -> Mapping[str, Any]:\n    \"\"\"Get globals needed to resolve class annotations.\n\n    Args:\n        target_class: The class whose annotation globals should be resolved.\n\n    Returns:\n        An immutable mapping of globals for the class MRO.\n    \"\"\"\n    available_vars: dict[str, Any] = {}\n    for module_name in {cls.__module__ for cls in target_class.__mro__}:\n        available_vars.update(sys.modules[module_name].__dict__)\n    return MappingProxyType(available_vars)\n\n\n@cache\ndef _get_class_event_triggers(target_class: type) -> frozenset[str]:\n    \"\"\"Get and cache event trigger names for a class.\n\n    Args:\n        target_class: The class to inspect.\n\n    Returns:\n        The event trigger names defined on the class.\n    \"\"\"\n    return frozenset(target_class.get_event_triggers())\n\n\ndef _generate_imports(\n    typing_imports: Iterable[str],\n) -> list[ast.ImportFrom | ast.Import]:\n    \"\"\"Generate the import statements for the stub file.\n\n    Args:\n        typing_imports: The typing imports to include.\n\n    Returns:\n        The list of import statements.\n    \"\"\"\n    return [\n        *[\n            ast.ImportFrom(module=name, names=[ast.alias(name=val) for val in values])  # pyright: ignore [reportCallIssue]\n            for name, values in DEFAULT_IMPORTS.items()\n        ],\n        ast.Import([ast.alias(\"reflex\")]),\n    ]\n\n\ndef _generate_docstrings(clzs: list[type[Component]], props: list[str]) -> str:\n    \"\"\"Generate the docstrings for the create method.\n\n    Args:\n        clzs: The classes to generate docstrings for.\n        props: The props to generate docstrings for.\n\n    Returns:\n        The docstring for the create method.\n    \"\"\"\n    props_comments = {}\n    for clz in clzs:\n        for prop, comment_lines in _get_class_prop_comments(clz).items():\n            if prop in props:\n                props_comments[prop] = list(comment_lines)\n    clz = clzs[0]\n    new_docstring = []\n    for line in (clz.create.__doc__ or \"\").splitlines():\n        if \"**\" in line:\n            indent = line.split(\"**\")[0]\n            new_docstring.extend([\n                f\"{indent}{n}:{' '.join(c)}\" for n, c in props_comments.items()\n            ])\n        new_docstring.append(line)\n    return \"\\n\".join(new_docstring)\n\n\ndef _extract_func_kwargs_as_ast_nodes(\n    func: Callable,\n    type_hint_globals: dict[str, Any],\n) -> list[tuple[ast.arg, ast.Constant | None]]:\n    \"\"\"Get the kwargs already defined on the function.\n\n    Args:\n        func: The function to extract kwargs from.\n        type_hint_globals: The globals to use to resolving a type hint str.\n\n    Returns:\n        The list of kwargs as ast arg nodes.\n    \"\"\"\n    spec = _get_full_argspec(func)\n    kwargs = []\n\n    for kwarg in spec.kwonlyargs:\n        arg = ast.arg(arg=kwarg)\n        if kwarg in spec.annotations:\n            arg.annotation = ast.Name(\n                id=_get_type_hint(spec.annotations[kwarg], type_hint_globals)\n            )\n        default = None\n        if spec.kwonlydefaults is not None and kwarg in spec.kwonlydefaults:\n            default = ast.Constant(value=spec.kwonlydefaults[kwarg])\n        kwargs.append((arg, default))\n    return kwargs\n\n\ndef _extract_class_props_as_ast_nodes(\n    func: Callable,\n    clzs: list[type],\n    type_hint_globals: dict[str, Any],\n    extract_real_default: bool = False,\n) -> list[tuple[ast.arg, ast.Constant | None]]:\n    \"\"\"Get the props defined on the class and all parents.\n\n    Args:\n        func: The function that kwargs will be added to.\n        clzs: The classes to extract props from.\n        type_hint_globals: The globals to use to resolving a type hint str.\n        extract_real_default: Whether to extract the real default value from the\n            pydantic field definition.\n\n    Returns:\n        The list of props as ast arg nodes\n    \"\"\"\n    spec = _get_full_argspec(func)\n    func_kwonlyargs = set(spec.kwonlyargs)\n    all_props: set[str] = set()\n    kwargs = []\n    for target_class in clzs:\n        event_triggers = _get_class_event_triggers(target_class)\n        # Import from the target class to ensure type hints are resolvable.\n        type_hint_globals.update(_get_module_star_imports(target_class.__module__))\n        annotation_globals = {\n            **type_hint_globals,\n            **_get_class_annotation_globals(target_class),\n        }\n        for name, value in target_class.__annotations__.items():\n            if (\n                name in func_kwonlyargs\n                or name in EXCLUDED_PROPS\n                or name in all_props\n                or name in event_triggers\n                or (isinstance(value, str) and \"ClassVar\" in value)\n            ):\n                continue\n            all_props.add(name)\n\n            default = None\n            if extract_real_default:\n                # TODO: This is not currently working since the default is not type compatible\n                #       with the annotation in some cases.\n                with contextlib.suppress(AttributeError, KeyError):\n                    # Try to get default from pydantic field definition.\n                    default = target_class.__fields__[name].default\n                    if isinstance(default, Var):\n                        default = default._decode()\n\n            kwargs.append((\n                ast.arg(\n                    arg=name,\n                    annotation=ast.Name(\n                        id=OVERWRITE_TYPES.get(\n                            name,\n                            _get_type_hint(\n                                value,\n                                annotation_globals,\n                            ),\n                        )\n                    ),\n                ),\n                ast.Constant(value=default),  # pyright: ignore [reportArgumentType]\n            ))\n    return kwargs\n\n\ndef type_to_ast(typ: Any, cls: type) -> ast.expr:\n    \"\"\"Converts any type annotation into its AST representation.\n    Handles nested generic types, unions, etc.\n\n    Args:\n        typ: The type annotation to convert.\n        cls: The class where the type annotation is used.\n\n    Returns:\n        The AST representation of the type annotation.\n    \"\"\"\n    if typ is type(None) or typ is None:\n        return ast.Name(id=\"None\")\n\n    origin = get_origin(typ)\n    if origin is typing.Literal:\n        return ast.Subscript(\n            value=ast.Name(id=\"Literal\"),\n            slice=ast.Tuple(\n                elts=[ast.Constant(value=val) for val in get_args(typ)], ctx=ast.Load()\n            ),\n            ctx=ast.Load(),\n        )\n    if origin is UnionType:\n        origin = typing.Union\n\n    # Handle plain types (int, str, custom classes, etc.)\n    if origin is None:\n        if hasattr(typ, \"__name__\"):\n            if typ.__module__.startswith(\"reflex.\"):\n                typ_parts = typ.__module__.split(\".\")\n                cls_parts = cls.__module__.split(\".\")\n\n                zipped = list(zip(typ_parts, cls_parts, strict=False))\n\n                if all(a == b for a, b in zipped) and len(typ_parts) == len(cls_parts):\n                    return ast.Name(id=typ.__name__)\n                if (\n                    typ.__module__ in DEFAULT_IMPORTS\n                    and typ.__name__ in DEFAULT_IMPORTS[typ.__module__]\n                ):\n                    return ast.Name(id=typ.__name__)\n                return ast.Name(id=typ.__module__ + \".\" + typ.__name__)\n            return ast.Name(id=typ.__name__)\n        if hasattr(typ, \"_name\"):\n            return ast.Name(id=typ._name)\n        return ast.Name(id=str(typ))\n\n    # Get the base type name (List, Dict, Optional, etc.)\n    base_name = getattr(origin, \"_name\", origin.__name__)\n\n    # Get type arguments\n    args = get_args(typ)\n\n    # Handle empty type arguments\n    if not args:\n        return ast.Name(id=base_name)\n\n    # Convert all type arguments recursively\n    arg_nodes = [type_to_ast(arg, cls) for arg in args]\n\n    # Special case for single-argument types (like list[T] or Optional[T])\n    if len(arg_nodes) == 1:\n        slice_value = arg_nodes[0]\n    else:\n        slice_value = ast.Tuple(elts=arg_nodes, ctx=ast.Load())\n\n    return ast.Subscript(\n        value=ast.Name(id=base_name),\n        slice=slice_value,\n        ctx=ast.Load(),\n    )\n\n\n@cache\ndef _get_parent_imports(func: Callable) -> Mapping[str, tuple[str, ...]]:\n    \"\"\"Get parent imports needed to resolve forwarded type hints.\n\n    Args:\n        func: The callable whose annotations are being analyzed.\n\n    Returns:\n        An immutable mapping of module names to imported symbol names.\n    \"\"\"\n    imports_: dict[str, set[str]] = {\"reflex.vars\": {\"Var\"}}\n    module_dir = set(dir(importlib.import_module(func.__module__)))\n    for type_hint in inspect.get_annotations(func).values():\n        try:\n            match = re.match(r\"\\w+\\[([\\w\\d]+)\\]\", type_hint)\n        except TypeError:\n            continue\n        if match:\n            type_hint = match.group(1)\n            if type_hint in module_dir:\n                imports_.setdefault(func.__module__, set()).add(type_hint)\n    return MappingProxyType({\n        module_name: tuple(sorted(imported_names))\n        for module_name, imported_names in imports_.items()\n    })\n\n\ndef _generate_component_create_functiondef(\n    clz: type[Component],\n    type_hint_globals: dict[str, Any],\n    lineno: int,\n    decorator_list: Sequence[ast.expr] = (ast.Name(id=\"classmethod\"),),\n) -> ast.FunctionDef:\n    \"\"\"Generate the create function definition for a Component.\n\n    Args:\n        clz: The Component class to generate the create functiondef for.\n        type_hint_globals: The globals to use to resolving a type hint str.\n        lineno: The line number to use for the ast nodes.\n        decorator_list: The list of decorators to apply to the create functiondef.\n\n    Returns:\n        The create functiondef node for the ast.\n\n    Raises:\n        TypeError: If clz is not a subclass of Component.\n    \"\"\"\n    if not issubclass(clz, Component):\n        msg = f\"clz must be a subclass of Component, not {clz!r}\"\n        raise TypeError(msg)\n\n    # add the imports needed by get_type_hint later\n    type_hint_globals.update({\n        name: getattr(typing, name) for name in DEFAULT_TYPING_IMPORTS\n    })\n\n    if clz.__module__ != clz.create.__module__:\n        imports_ = _get_parent_imports(clz.create)\n        for name, values in imports_.items():\n            type_hint_globals.update(_get_module_selected_imports(name, values))\n\n    kwargs = _extract_func_kwargs_as_ast_nodes(clz.create, type_hint_globals)\n\n    # kwargs associated with props defined in the class and its parents\n    all_classes = [c for c in clz.__mro__ if issubclass(c, Component)]\n    prop_kwargs = _extract_class_props_as_ast_nodes(\n        clz.create, all_classes, type_hint_globals\n    )\n    all_props = [arg[0].arg for arg in prop_kwargs]\n    kwargs.extend(prop_kwargs)\n\n    def figure_out_return_type(annotation: Any):\n        if isinstance(annotation, type) and issubclass(annotation, inspect._empty):\n            return ast.Name(id=\"EventType[Any]\")\n\n        if not isinstance(annotation, str) and get_origin(annotation) is tuple:\n            arguments = get_args(annotation)\n\n            arguments_without_var = [\n                get_args(argument)[0] if get_origin(argument) == Var else argument\n                for argument in arguments\n            ]\n\n            # Convert each argument type to its AST representation\n            type_args = [type_to_ast(arg, cls=clz) for arg in arguments_without_var]\n\n            # Get all prefixes of the type arguments\n            all_count_args_type = [\n                ast.Name(\n                    f\"EventType[{', '.join([ast.unparse(arg) for arg in type_args[:i]])}]\"\n                )\n                if i > 0\n                else ast.Name(\"EventType[()]\")\n                for i in range(len(type_args) + 1)\n            ]\n\n            # Create EventType using the joined string\n            return ast.Name(id=f\"{' | '.join(map(ast.unparse, all_count_args_type))}\")\n\n        if isinstance(annotation, str) and annotation.lower().startswith(\"tuple[\"):\n            inside_of_tuple = (\n                annotation\n                .removeprefix(\"tuple[\")\n                .removeprefix(\"Tuple[\")\n                .removesuffix(\"]\")\n            )\n\n            if inside_of_tuple == \"()\":\n                return ast.Name(id=\"EventType[()]\")\n\n            arguments = [\"\"]\n\n            bracket_count = 0\n\n            for char in inside_of_tuple:\n                if char == \"[\":\n                    bracket_count += 1\n                elif char == \"]\":\n                    bracket_count -= 1\n\n                if char == \",\" and bracket_count == 0:\n                    arguments.append(\"\")\n                else:\n                    arguments[-1] += char\n\n            arguments = [argument.strip() for argument in arguments]\n\n            arguments_without_var = [\n                argument.removeprefix(\"Var[\").removesuffix(\"]\")\n                if argument.startswith(\"Var[\")\n                else argument\n                for argument in arguments\n            ]\n\n            all_count_args_type = [\n                ast.Name(f\"EventType[{', '.join(arguments_without_var[:i])}]\")\n                if i > 0\n                else ast.Name(\"EventType[()]\")\n                for i in range(len(arguments) + 1)\n            ]\n\n            return ast.Name(id=f\"{' | '.join(map(ast.unparse, all_count_args_type))}\")\n        return ast.Name(id=\"EventType[Any]\")\n\n    event_triggers = clz.get_event_triggers()\n\n    # event handler kwargs\n    kwargs.extend(\n        (\n            ast.arg(\n                arg=trigger,\n                annotation=ast.Subscript(\n                    ast.Name(\"Optional\"),\n                    ast.Name(\n                        id=ast.unparse(\n                            figure_out_return_type(\n                                _get_signature_return_annotation(event_specs)\n                            )\n                            if not isinstance(\n                                event_specs := event_triggers[trigger], Sequence\n                            )\n                            else ast.Subscript(\n                                ast.Name(\"Union\"),\n                                ast.Tuple([\n                                    figure_out_return_type(\n                                        _get_signature_return_annotation(event_spec)\n                                    )\n                                    for event_spec in event_specs\n                                ]),\n                            )\n                        )\n                    ),\n                ),\n            ),\n            ast.Constant(value=None),\n        )\n        for trigger in sorted(event_triggers)\n    )\n\n    logger.debug(f\"Generated {clz.__name__}.create method with {len(kwargs)} kwargs\")\n    create_args = ast.arguments(\n        args=[ast.arg(arg=\"cls\")],\n        posonlyargs=[],\n        vararg=ast.arg(arg=\"children\"),\n        kwonlyargs=[arg[0] for arg in kwargs],\n        kw_defaults=[arg[1] for arg in kwargs],\n        kwarg=ast.arg(arg=\"props\"),\n        defaults=[],\n    )\n\n    return ast.FunctionDef(  # pyright: ignore [reportCallIssue]\n        name=\"create\",\n        args=create_args,\n        body=[\n            ast.Expr(\n                value=ast.Constant(\n                    value=_generate_docstrings(\n                        all_classes, [*all_props, *event_triggers]\n                    )\n                ),\n            ),\n            ast.Expr(\n                value=ast.Constant(value=Ellipsis),\n            ),\n        ],\n        decorator_list=list(decorator_list),\n        lineno=lineno,\n        returns=ast.Constant(value=clz.__name__),\n    )\n\n\ndef _generate_staticmethod_call_functiondef(\n    node: ast.ClassDef,\n    clz: type[Component] | type[SimpleNamespace],\n    type_hint_globals: dict[str, Any],\n) -> ast.FunctionDef | None:\n    fullspec = _get_full_argspec(clz.__call__)\n\n    call_args = ast.arguments(\n        args=[\n            ast.arg(\n                name,\n                annotation=ast.Name(\n                    id=_get_type_hint(\n                        anno := fullspec.annotations[name],\n                        type_hint_globals,\n                        is_optional=rx_types.is_optional(anno),\n                    )\n                ),\n            )\n            for name in fullspec.args\n        ],\n        posonlyargs=[],\n        kwonlyargs=[],\n        kw_defaults=[],\n        kwarg=ast.arg(arg=\"props\"),\n        defaults=(\n            [ast.Constant(value=default) for default in fullspec.defaults]\n            if fullspec.defaults\n            else []\n        ),\n    )\n    return ast.FunctionDef(  # pyright: ignore [reportCallIssue]\n        name=\"__call__\",\n        args=call_args,\n        body=[\n            ast.Expr(value=ast.Constant(value=clz.__call__.__doc__)),\n            ast.Expr(\n                value=ast.Constant(...),\n            ),\n        ],\n        decorator_list=[ast.Name(id=\"staticmethod\")],\n        lineno=node.lineno,\n        returns=ast.Constant(\n            value=_get_type_hint(\n                typing.get_type_hints(clz.__call__).get(\"return\", None),\n                type_hint_globals,\n                is_optional=False,\n            )\n        ),\n    )\n\n\ndef _generate_namespace_call_functiondef(\n    node: ast.ClassDef,\n    clz_name: str,\n    classes: dict[str, type[Component] | type[SimpleNamespace]],\n    type_hint_globals: dict[str, Any],\n) -> ast.FunctionDef | None:\n    \"\"\"Generate the __call__ function definition for a SimpleNamespace.\n\n    Args:\n        node: The existing __call__ classdef parent node from the ast\n        clz_name: The name of the SimpleNamespace class to generate the __call__ functiondef for.\n        classes: Map name to actual class definition.\n        type_hint_globals: The globals to use to resolving a type hint str.\n\n    Returns:\n        The create functiondef node for the ast.\n    \"\"\"\n    # add the imports needed by get_type_hint later\n    type_hint_globals.update({\n        name: getattr(typing, name) for name in DEFAULT_TYPING_IMPORTS\n    })\n\n    clz = classes[clz_name]\n\n    if not hasattr(clz.__call__, \"__self__\"):\n        return _generate_staticmethod_call_functiondef(node, clz, type_hint_globals)\n\n    # Determine which class is wrapped by the namespace __call__ method\n    component_clz = clz.__call__.__self__\n\n    if clz.__call__.__func__.__name__ != \"create\":  # pyright: ignore [reportFunctionMemberAccess]\n        return None\n\n    if not issubclass(component_clz, Component):\n        return None\n\n    definition = _generate_component_create_functiondef(\n        clz=component_clz,\n        type_hint_globals=type_hint_globals,\n        lineno=node.lineno,\n        decorator_list=[],\n    )\n    definition.name = \"__call__\"\n\n    # Turn the definition into a staticmethod\n    del definition.args.args[0]  # remove `cls` arg\n    definition.decorator_list = [ast.Name(id=\"staticmethod\")]\n\n    return definition\n\n\nclass StubGenerator(ast.NodeTransformer):\n    \"\"\"A node transformer that will generate the stubs for a given module.\"\"\"\n\n    def __init__(\n        self,\n        module: ModuleType,\n        classes: dict[str, type[Component | SimpleNamespace]],\n    ):\n        \"\"\"Initialize the stub generator.\n\n        Args:\n            module: The actual module object module to generate stubs for.\n            classes: The actual Component class objects to generate stubs for.\n        \"\"\"\n        super().__init__()\n        # Dict mapping class name to actual class object.\n        self.classes = classes\n        # Track the last class node that was visited.\n        self.current_class = None\n        # These imports will be included in the AST of stub files.\n        self.typing_imports = DEFAULT_TYPING_IMPORTS.copy()\n        # Whether those typing imports have been inserted yet.\n        self.inserted_imports = False\n        # This dict is used when evaluating type hints.\n        self.type_hint_globals = module.__dict__.copy()\n\n    @staticmethod\n    def _remove_docstring(\n        node: ast.Module | ast.ClassDef | ast.FunctionDef,\n    ) -> ast.Module | ast.ClassDef | ast.FunctionDef:\n        \"\"\"Removes any docstring in place.\n\n        Args:\n            node: The node to remove the docstring from.\n\n        Returns:\n            The modified node.\n        \"\"\"\n        if (\n            node.body\n            and isinstance(node.body[0], ast.Expr)\n            and isinstance(node.body[0].value, ast.Constant)\n        ):\n            node.body.pop(0)\n        return node\n\n    def _current_class_is_component(self) -> type[Component] | None:\n        \"\"\"Check if the current class is a Component.\n\n        Returns:\n            Whether the current class is a Component.\n        \"\"\"\n        if (\n            self.current_class is not None\n            and self.current_class in self.classes\n            and issubclass((clz := self.classes[self.current_class]), Component)\n        ):\n            return clz\n        return None\n\n    def visit_Module(self, node: ast.Module) -> ast.Module:\n        \"\"\"Visit a Module node and remove docstring from body.\n\n        Args:\n            node: The Module node to visit.\n\n        Returns:\n            The modified Module node.\n        \"\"\"\n        self.generic_visit(node)\n        return self._remove_docstring(node)  # pyright: ignore [reportReturnType]\n\n    def visit_Import(\n        self, node: ast.Import | ast.ImportFrom\n    ) -> ast.Import | ast.ImportFrom | list[ast.Import | ast.ImportFrom]:\n        \"\"\"Collect import statements from the module.\n\n        If this is the first import statement, insert the typing imports before it.\n\n        Args:\n            node: The import node to visit.\n\n        Returns:\n            The modified import node(s).\n        \"\"\"\n        if not self.inserted_imports:\n            self.inserted_imports = True\n            default_imports = _generate_imports(self.typing_imports)\n            return [*default_imports, node]\n        return node\n\n    def visit_ImportFrom(\n        self, node: ast.ImportFrom\n    ) -> ast.Import | ast.ImportFrom | list[ast.Import | ast.ImportFrom] | None:\n        \"\"\"Visit an ImportFrom node.\n\n        Remove any `from __future__ import *` statements, and hand off to visit_Import.\n\n        Args:\n            node: The ImportFrom node to visit.\n\n        Returns:\n            The modified ImportFrom node.\n        \"\"\"\n        if node.module == \"__future__\":\n            return None  # ignore __future__ imports: https://docs.astral.sh/ruff/rules/future-annotations-in-stub/\n        return self.visit_Import(node)\n\n    def visit_ClassDef(self, node: ast.ClassDef) -> ast.ClassDef:\n        \"\"\"Visit a ClassDef node.\n\n        Remove all assignments in the class body, and add a create functiondef\n        if one does not exist.\n\n        Args:\n            node: The ClassDef node to visit.\n\n        Returns:\n            The modified ClassDef node.\n        \"\"\"\n        self.current_class = node.name\n        self._remove_docstring(node)\n\n        # Define `__call__` as a real function so the docstring appears in the stub.\n        call_definition = None\n        for child in node.body[:]:\n            found_call = False\n            if (\n                isinstance(child, ast.AnnAssign)\n                and isinstance(child.target, ast.Name)\n                and child.target.id.startswith(\"_\")\n            ):\n                node.body.remove(child)\n            if isinstance(child, ast.Assign):\n                for target in child.targets[:]:\n                    if isinstance(target, ast.Name) and target.id == \"__call__\":\n                        child.targets.remove(target)\n                        found_call = True\n                if not found_call:\n                    continue\n                if not child.targets[:]:\n                    node.body.remove(child)\n                call_definition = _generate_namespace_call_functiondef(\n                    node,\n                    self.current_class,\n                    self.classes,\n                    type_hint_globals=self.type_hint_globals,\n                )\n                break\n\n        self.generic_visit(node)  # Visit child nodes.\n\n        if (\n            not any(\n                isinstance(child, ast.FunctionDef) and child.name == \"create\"\n                for child in node.body\n            )\n            and (clz := self._current_class_is_component()) is not None\n        ):\n            # Add a new .create FunctionDef since one does not exist.\n            node.body.append(\n                _generate_component_create_functiondef(\n                    clz=clz,\n                    type_hint_globals=self.type_hint_globals,\n                    lineno=node.lineno,\n                )\n            )\n        if call_definition is not None:\n            node.body.append(call_definition)\n        if not node.body:\n            # We should never return an empty body.\n            node.body.append(ast.Expr(value=ast.Constant(value=Ellipsis)))\n        self.current_class = None\n        return node\n\n    def visit_FunctionDef(self, node: ast.FunctionDef) -> Any:\n        \"\"\"Visit a FunctionDef node.\n\n        Special handling for `.create` functions to add type hints for all props\n        defined on the component class.\n\n        Remove all private functions and blank out the function body of the\n        remaining public functions.\n\n        Args:\n            node: The FunctionDef node to visit.\n\n        Returns:\n            The modified FunctionDef node (or None).\n        \"\"\"\n        if (\n            node.name == \"create\"\n            and self.current_class in self.classes\n            and issubclass((clz := self.classes[self.current_class]), Component)\n        ):\n            node = _generate_component_create_functiondef(\n                clz=clz,\n                type_hint_globals=self.type_hint_globals,\n                lineno=node.lineno,\n                decorator_list=node.decorator_list,\n            )\n        else:\n            if node.name.startswith(\"_\") and node.name != \"__call__\":\n                return None  # remove private methods\n\n            if node.body[-1] != ast.Expr(value=ast.Constant(value=Ellipsis)):\n                # Blank out the function body for public functions.\n                node.body = [ast.Expr(value=ast.Constant(value=Ellipsis))]\n        return node\n\n    def visit_Assign(self, node: ast.Assign) -> ast.Assign | None:\n        \"\"\"Remove non-annotated assignment statements.\n\n        Args:\n            node: The Assign node to visit.\n\n        Returns:\n            The modified Assign node (or None).\n        \"\"\"\n        # Special case for assignments to `typing.Any` as fallback.\n        if (\n            node.value is not None\n            and isinstance(node.value, ast.Name)\n            and node.value.id == \"Any\"\n        ):\n            return node\n\n        if self._current_class_is_component():\n            # Remove annotated assignments in Component classes (props)\n            return None\n\n        # remove dunder method assignments for lazy_loader.attach\n        for target in node.targets:\n            if isinstance(target, ast.Tuple):\n                for name in target.elts:\n                    if isinstance(name, ast.Name) and name.id.startswith(\"_\"):\n                        return None\n\n        return node\n\n    def visit_AnnAssign(self, node: ast.AnnAssign) -> ast.AnnAssign | None:\n        \"\"\"Visit an AnnAssign node (Annotated assignment).\n\n        Remove private target and remove the assignment value in the stub.\n\n        Args:\n            node: The AnnAssign node to visit.\n\n        Returns:\n            The modified AnnAssign node (or None).\n        \"\"\"\n        # skip ClassVars\n        if (\n            isinstance(node.annotation, ast.Subscript)\n            and isinstance(node.annotation.value, ast.Name)\n            and node.annotation.value.id == \"ClassVar\"\n        ):\n            return node\n        if isinstance(node.target, ast.Name) and node.target.id.startswith(\"_\"):\n            return None\n        if self._current_class_is_component():\n            # Remove annotated assignments in Component classes (props)\n            return None\n        # Blank out assignments in type stubs.\n        node.value = None\n        return node\n\n\nclass InitStubGenerator(StubGenerator):\n    \"\"\"A node transformer that will generate the stubs for a given init file.\"\"\"\n\n    def visit_Import(\n        self, node: ast.Import | ast.ImportFrom\n    ) -> ast.Import | ast.ImportFrom | list[ast.Import | ast.ImportFrom]:\n        \"\"\"Collect import statements from the init module.\n\n        Args:\n            node: The import node to visit.\n\n        Returns:\n                The modified import node(s).\n        \"\"\"\n        return [node]\n\n\ndef _path_to_module_name(path: Path) -> str:\n    \"\"\"Convert a file path to a dotted module name.\n\n    Args:\n        path: The file path to convert.\n\n    Returns:\n        The dotted module name.\n    \"\"\"\n    return _relative_to_pwd(path).with_suffix(\"\").as_posix().replace(\"/\", \".\")\n\n\ndef _write_pyi_file(module_path: Path, source: str) -> str:\n    relpath = str(_relative_to_pwd(module_path)).replace(\"\\\\\", \"/\")\n    pyi_content = (\n        \"\\n\".join([\n            f'\"\"\"Stub file for {relpath}\"\"\"',\n            \"# ------------------- DO NOT EDIT ----------------------\",\n            \"# This file was generated by `reflex/utils/pyi_generator.py`!\",\n            \"# ------------------------------------------------------\",\n            \"\",\n        ])\n        + source\n    )\n\n    pyi_path = module_path.with_suffix(\".pyi\")\n    pyi_path.write_text(pyi_content)\n    logger.info(f\"Wrote {relpath}\")\n    return md5(pyi_content.encode()).hexdigest()\n\n\ndef _get_init_lazy_imports(mod: tuple | ModuleType, new_tree: ast.AST):\n    # retrieve the _SUBMODULES and _SUBMOD_ATTRS from an init file if present.\n    sub_mods: set[str] | None = getattr(mod, \"_SUBMODULES\", None)\n    sub_mod_attrs: dict[str, list[str | tuple[str, str]]] | None = getattr(\n        mod, \"_SUBMOD_ATTRS\", None\n    )\n    extra_mappings: dict[str, str] | None = getattr(mod, \"_EXTRA_MAPPINGS\", None)\n\n    if not sub_mods and not sub_mod_attrs and not extra_mappings:\n        return None\n    sub_mods_imports = []\n    sub_mod_attrs_imports = []\n    extra_mappings_imports = []\n\n    if sub_mods:\n        sub_mods_imports = [f\"from . import {mod}\" for mod in sorted(sub_mods)]\n        sub_mods_imports.append(\"\")\n\n    if sub_mod_attrs:\n        flattened_sub_mod_attrs = {\n            imported: module\n            for module, attrs in sub_mod_attrs.items()\n            for imported in attrs\n        }\n        # construct the import statement and handle special cases for aliases\n        sub_mod_attrs_imports = [\n            f\"from .{module} import \"\n            + (\n                (\n                    (imported[0] + \" as \" + imported[1])\n                    if imported[0] != imported[1]\n                    else imported[0]\n                )\n                if isinstance(imported, tuple)\n                else imported\n            )\n            for imported, module in flattened_sub_mod_attrs.items()\n        ]\n        sub_mod_attrs_imports.append(\"\")\n\n    if extra_mappings:\n        for alias, import_path in extra_mappings.items():\n            module_name, import_name = import_path.rsplit(\".\", 1)\n            extra_mappings_imports.append(\n                f\"from {module_name} import {import_name} as {alias}\"\n            )\n\n    text = (\n        \"\\n\"\n        + \"\\n\".join([\n            *sub_mods_imports,\n            *sub_mod_attrs_imports,\n            *extra_mappings_imports,\n        ])\n        + \"\\n\"\n    )\n    text += ast.unparse(new_tree) + \"\\n\\n\"\n    text += f\"__all__ = {getattr(mod, '__all__', [])!r}\\n\"\n    return text\n\n\ndef _scan_file(module_path: Path) -> tuple[str, str] | None:\n    \"\"\"Process a single Python file and generate its .pyi stub.\n\n    Args:\n        module_path: Path to the Python source file.\n\n    Returns:\n        Tuple of (pyi_path, content_hash) or None if no stub needed.\n    \"\"\"\n    module_import = _path_to_module_name(module_path)\n    module = importlib.import_module(module_import)\n    logger.debug(f\"Read {module_path}\")\n    class_names = {\n        name: obj\n        for name, obj in vars(module).items()\n        if isinstance(obj, type)\n        and (\n            rx_types.safe_issubclass(obj, Component)\n            or rx_types.safe_issubclass(obj, SimpleNamespace)\n        )\n        and obj != Component\n        and inspect.getmodule(obj) == module\n    }\n    is_init_file = _relative_to_pwd(module_path).name == \"__init__.py\"\n    if not class_names and not is_init_file:\n        return None\n\n    if is_init_file:\n        new_tree = InitStubGenerator(module, class_names).visit(\n            ast.parse(_get_source(module))\n        )\n        init_imports = _get_init_lazy_imports(module, new_tree)\n        if not init_imports:\n            return None\n        content_hash = _write_pyi_file(module_path, init_imports)\n    else:\n        new_tree = StubGenerator(module, class_names).visit(\n            ast.parse(_get_source(module))\n        )\n        content_hash = _write_pyi_file(module_path, ast.unparse(new_tree))\n    return str(module_path.with_suffix(\".pyi\").resolve()), content_hash\n\n\nclass PyiGenerator:\n    \"\"\"A .pyi file generator that will scan all defined Component in Reflex and\n    generate the appropriate stub.\n    \"\"\"\n\n    modules: list = []\n    root: str = \"\"\n    current_module: Any = {}\n    written_files: list[tuple[str, str]] = []\n\n    def _scan_files(self, files: list[Path]):\n        max_workers = min(multiprocessing.cpu_count() or 1, len(files), 8)\n        use_parallel = (\n            max_workers > 1 and \"fork\" in multiprocessing.get_all_start_methods()\n        )\n\n        if not use_parallel:\n            # Serial fallback: _scan_file handles its own imports.\n            for file in files:\n                result = _scan_file(file)\n                if result is not None:\n                    self.written_files.append(result)\n            return\n\n        # Pre-import all modules sequentially to populate sys.modules\n        # so forked workers inherit the cache and skip redundant imports.\n        importable_files: list[Path] = []\n        for file in files:\n            module_import = _path_to_module_name(file)\n            try:\n                importlib.import_module(module_import)\n                importable_files.append(file)\n            except Exception:\n                logger.exception(f\"Failed to import {module_import}\")\n\n        # Generate stubs in parallel using forked worker processes.\n        ctx = multiprocessing.get_context(\"fork\")\n        with ProcessPoolExecutor(max_workers=max_workers, mp_context=ctx) as executor:\n            self.written_files.extend(\n                r for r in executor.map(_scan_file, importable_files) if r is not None\n            )\n\n    def scan_all(\n        self,\n        targets: list,\n        changed_files: list[Path] | None = None,\n        use_json: bool = False,\n    ):\n        \"\"\"Scan all targets for class inheriting Component and generate the .pyi files.\n\n        Args:\n            targets: the list of file/folders to scan.\n            changed_files (optional): the list of changed files since the last run.\n            use_json: whether to use json to store the hashes.\n        \"\"\"\n        file_targets = []\n        for target in targets:\n            target_path = Path(target)\n            if (\n                target_path.is_file()\n                and target_path.suffix == \".py\"\n                and target_path.name not in EXCLUDED_FILES\n            ):\n                file_targets.append(target_path)\n                continue\n            if not target_path.is_dir():\n                continue\n            for file_path in _walk_files(target_path):\n                relative = _relative_to_pwd(file_path)\n                if relative.name in EXCLUDED_FILES or file_path.suffix != \".py\":\n                    continue\n                if (\n                    changed_files is not None\n                    and _relative_to_pwd(file_path) not in changed_files\n                ):\n                    continue\n                file_targets.append(file_path)\n\n        # check if pyi changed but not the source\n        if changed_files is not None:\n            for changed_file in changed_files:\n                if changed_file.suffix != \".pyi\":\n                    continue\n                py_file_path = changed_file.with_suffix(\".py\")\n                if not py_file_path.exists() and changed_file.exists():\n                    changed_file.unlink()\n                if py_file_path in file_targets:\n                    continue\n                subprocess.run([\"git\", \"checkout\", changed_file])\n\n        self._scan_files(file_targets)\n\n        file_paths, hashes = (\n            [f[0] for f in self.written_files],\n            [f[1] for f in self.written_files],\n        )\n\n        # Fix generated pyi files with ruff.\n        if file_paths:\n            subprocess.run([\"ruff\", \"check\", \"--fix\", *file_paths])\n            subprocess.run([\"ruff\", \"format\", *file_paths])\n\n        if use_json:\n            if file_paths and changed_files is None:\n                file_paths = list(map(Path, file_paths))\n                top_dir = file_paths[0].parent\n                for file_path in file_paths:\n                    file_parent = file_path.parent\n                    while len(file_parent.parts) > len(top_dir.parts):\n                        file_parent = file_parent.parent\n                    while len(top_dir.parts) > len(file_parent.parts):\n                        top_dir = top_dir.parent\n                    while not file_parent.samefile(top_dir):\n                        file_parent = file_parent.parent\n                        top_dir = top_dir.parent\n\n                while (\n                    not top_dir.samefile(top_dir.parent)\n                    and not (top_dir / PYI_HASHES).exists()\n                ):\n                    top_dir = top_dir.parent\n\n                pyi_hashes_file = top_dir / PYI_HASHES\n\n                if pyi_hashes_file.exists():\n                    pyi_hashes_file.write_text(\n                        json.dumps(\n                            dict(\n                                zip(\n                                    [\n                                        f.relative_to(pyi_hashes_file.parent).as_posix()\n                                        for f in file_paths\n                                    ],\n                                    hashes,\n                                    strict=True,\n                                )\n                            ),\n                            indent=2,\n                            sort_keys=True,\n                        )\n                        + \"\\n\",\n                    )\n            elif file_paths:\n                file_paths = list(map(Path, file_paths))\n                pyi_hashes_parent = file_paths[0].parent\n                while (\n                    not pyi_hashes_parent.samefile(pyi_hashes_parent.parent)\n                    and not (pyi_hashes_parent / PYI_HASHES).exists()\n                ):\n                    pyi_hashes_parent = pyi_hashes_parent.parent\n\n                pyi_hashes_file = pyi_hashes_parent / PYI_HASHES\n                if pyi_hashes_file.exists():\n                    pyi_hashes = json.loads(pyi_hashes_file.read_text())\n                    for file_path, hashed_content in zip(\n                        file_paths, hashes, strict=False\n                    ):\n                        formatted_path = file_path.relative_to(\n                            pyi_hashes_parent\n                        ).as_posix()\n                        pyi_hashes[formatted_path] = hashed_content\n\n                    pyi_hashes_file.write_text(\n                        json.dumps(pyi_hashes, indent=2, sort_keys=True) + \"\\n\"\n                    )\n\n\nif __name__ == \"__main__\":\n    import argparse\n\n    parser = argparse.ArgumentParser(description=\"Generate .pyi stub files\")\n    parser.add_argument(\n        \"targets\",\n        nargs=\"*\",\n        default=[\"reflex/components\", \"reflex/experimental\", \"reflex/__init__.py\"],\n        help=\"Target directories/files to process\",\n    )\n    args = parser.parse_args()\n\n    logging.basicConfig(level=logging.INFO)\n    logging.getLogger(\"blib2to3.pgen2.driver\").setLevel(logging.INFO)\n\n    gen = PyiGenerator()\n    gen.scan_all(args.targets, None, use_json=True)\n"
  },
  {
    "path": "reflex/utils/redir.py",
    "content": "\"\"\"Utilities to handle redirection to browser UI.\"\"\"\n\nfrom typing import TYPE_CHECKING\n\nif TYPE_CHECKING:\n    from urllib.parse import SplitResult\n\n\ndef open_browser(target_url: \"SplitResult\") -> None:\n    \"\"\"Open a browser window to target_url.\n\n    Args:\n        target_url: The URL to open in the browser.\n    \"\"\"\n    import webbrowser\n\n    from reflex.utils import console\n\n    if not webbrowser.open(target_url.geturl()):\n        console.warn(\n            f\"Unable to automatically open the browser. Please navigate to {target_url} in your browser.\"\n        )\n    else:\n        simplified_url = target_url._replace(path=\"\", query=\"\", fragment=\"\").geturl()\n        console.info(f\"Opened browser to {simplified_url}\")\n\n\ndef reflex_build_redirect() -> None:\n    \"\"\"Open the browser window to reflex.build.\"\"\"\n    from urllib.parse import urlsplit\n\n    from reflex import constants\n\n    open_browser(urlsplit(constants.Templates.REFLEX_BUILD_FRONTEND_WITH_REFERRER))\n\n\ndef reflex_templates():\n    \"\"\"Open the browser window to reflex.build/templates.\"\"\"\n    from urllib.parse import urlsplit\n\n    from reflex import constants\n\n    open_browser(urlsplit(constants.Templates.REFLEX_TEMPLATES_URL))\n"
  },
  {
    "path": "reflex/utils/registry.py",
    "content": "\"\"\"Utilities for working with registries.\"\"\"\n\nfrom pathlib import Path\n\nfrom reflex.environment import environment\nfrom reflex.utils import console, net\nfrom reflex.utils.decorator import cache_result_in_disk, once\n\n\ndef latency(registry: str) -> int:\n    \"\"\"Get the latency of a registry.\n\n    Args:\n        registry (str): The URL of the registry.\n\n    Returns:\n        int: The latency of the registry in microseconds.\n    \"\"\"\n    import httpx\n\n    try:\n        time_to_respond = net.get(registry, timeout=2).elapsed.microseconds\n    except httpx.HTTPError:\n        console.info(f\"Failed to connect to {registry}.\")\n        return 10_000_000\n    else:\n        console.debug(f\"Latency of {registry}: {time_to_respond}\")\n        return time_to_respond\n\n\ndef average_latency(registry: str, attempts: int = 3) -> int:\n    \"\"\"Get the average latency of a registry.\n\n    Args:\n        registry: The URL of the registry.\n        attempts: The number of attempts to make. Defaults to 10.\n\n    Returns:\n        The average latency of the registry in microseconds.\n    \"\"\"\n    registry_latency = sum(latency(registry) for _ in range(attempts)) // attempts\n    console.debug(f\"Average latency of {registry}: {registry_latency}\")\n    return registry_latency\n\n\ndef _best_registry_file_path() -> Path:\n    \"\"\"Get the file path for the best registry cache.\n\n    Returns:\n        The file path for the best registry cache.\n    \"\"\"\n    return environment.REFLEX_DIR.get() / \"reflex_best_registry.cached\"\n\n\n@cache_result_in_disk(cache_file_path=_best_registry_file_path)\ndef _get_best_registry() -> str:\n    \"\"\"Get the best registry based on latency.\n\n    Returns:\n        The best registry.\n    \"\"\"\n    console.debug(\"Getting best registry...\")\n    registries = [\n        (\"https://registry.npmjs.org\", 1),\n        (\"https://registry.npmmirror.com\", 2),\n    ]\n\n    best_registry = min(registries, key=lambda x: average_latency(x[0]) * x[1])[0]\n    console.debug(f\"Best registry: {best_registry}\")\n    return best_registry\n\n\n@once\ndef get_npm_registry() -> str:\n    \"\"\"Get npm registry. If environment variable is set, use it first.\n\n    Returns:\n        The npm registry.\n    \"\"\"\n    return environment.NPM_CONFIG_REGISTRY.get() or _get_best_registry()\n"
  },
  {
    "path": "reflex/utils/rename.py",
    "content": "\"\"\"This module provides utilities for renaming directories and files in a Reflex app.\"\"\"\n\nimport re\nimport sys\nfrom pathlib import Path\n\nfrom reflex import constants\nfrom reflex.config import get_config\nfrom reflex.utils import console\nfrom reflex.utils.misc import get_module_path\n\n\ndef rename_path_up_tree(full_path: str | Path, old_name: str, new_name: str) -> Path:\n    \"\"\"Rename all instances of `old_name` in the path (file and directories) to `new_name`.\n    The renaming stops when we reach the directory containing `rxconfig.py`.\n\n    Args:\n        full_path: The full path to start renaming from.\n        old_name: The name to be replaced.\n        new_name: The replacement name.\n\n    Returns:\n         The updated path after renaming.\n    \"\"\"\n    current_path = Path(full_path)\n    new_path = None\n\n    while True:\n        directory, base = current_path.parent, current_path.name\n        # Stop renaming when we reach the root dir (which contains rxconfig.py)\n        if current_path.is_dir() and (current_path / \"rxconfig.py\").exists():\n            new_path = current_path\n            break\n\n        if old_name == base.removesuffix(constants.Ext.PY):\n            new_base = base.replace(old_name, new_name)\n            new_path = directory / new_base\n            current_path.rename(new_path)\n            console.debug(f\"Renamed {current_path} -> {new_path}\")\n            current_path = new_path\n        else:\n            new_path = current_path\n\n        # Move up the directory tree\n        current_path = directory\n\n    return new_path\n\n\ndef rename_app(new_app_name: str, loglevel: constants.LogLevel):\n    \"\"\"Rename the app directory.\n\n    Args:\n        new_app_name: The new name for the app.\n        loglevel: The log level to use.\n\n    Raises:\n        SystemExit: If the command is not ran in the root dir or the app module cannot be imported.\n    \"\"\"\n    # Set the log level.\n    console.set_log_level(loglevel)\n\n    if not constants.Config.FILE.exists():\n        console.error(\n            \"No rxconfig.py found. Make sure you are in the root directory of your app.\"\n        )\n        raise SystemExit(1)\n\n    sys.path.insert(0, str(Path.cwd()))\n\n    config = get_config()\n    module_path = get_module_path(config.module)\n    if module_path is None:\n        console.error(f\"Could not find module {config.module}.\")\n        raise SystemExit(1)\n\n    console.info(f\"Renaming app directory to {new_app_name}.\")\n    process_directory(\n        Path.cwd(),\n        config.app_name,\n        new_app_name,\n        exclude_dirs=[constants.Dirs.WEB, constants.Dirs.APP_ASSETS],\n    )\n\n    rename_path_up_tree(module_path, config.app_name, new_app_name)\n\n    console.success(f\"App directory renamed to [bold]{new_app_name}[/bold].\")\n\n\ndef rename_imports_and_app_name(file_path: str | Path, old_name: str, new_name: str):\n    \"\"\"Rename imports the file using string replacement as well as app_name in rxconfig.py.\n\n    Args:\n        file_path: The file to process.\n        old_name: The old name to replace.\n        new_name: The new name to use.\n    \"\"\"\n    file_path = Path(file_path)\n    content = file_path.read_text()\n\n    # Replace `from old_name.` or `from old_name` with `from new_name`\n    content = re.sub(\n        rf\"\\bfrom {re.escape(old_name)}(\\b|\\.|\\s)\",\n        lambda match: f\"from {new_name}{match.group(1)}\",\n        content,\n    )\n\n    # Replace `import old_name` with `import new_name`\n    content = re.sub(\n        rf\"\\bimport {re.escape(old_name)}\\b\",\n        f\"import {new_name}\",\n        content,\n    )\n\n    # Replace `app_name=\"old_name\"` in rx.Config\n    content = re.sub(\n        rf'\\bapp_name\\s*=\\s*[\"\\']{re.escape(old_name)}[\"\\']',\n        f'app_name=\"{new_name}\"',\n        content,\n    )\n\n    # Replace positional argument `\"old_name\"` in rx.Config\n    content = re.sub(\n        rf'\\brx\\.Config\\(\\s*[\"\\']{re.escape(old_name)}[\"\\']',\n        f'rx.Config(\"{new_name}\"',\n        content,\n    )\n\n    file_path.write_text(content)\n\n\ndef process_directory(\n    directory: str | Path,\n    old_name: str,\n    new_name: str,\n    exclude_dirs: list | None = None,\n    extensions: list | None = None,\n):\n    \"\"\"Process files with specified extensions in a directory, excluding specified directories.\n\n    Args:\n        directory: The root directory to process.\n        old_name: The old name to replace.\n        new_name: The new name to use.\n        exclude_dirs: List of directory names to exclude. Defaults to None.\n        extensions: List of file extensions to process.\n    \"\"\"\n    exclude_dirs = exclude_dirs or []\n    extensions = extensions or [\n        constants.Ext.PY,\n        constants.Ext.MD,\n    ]  # include .md files, typically used in reflex-web.\n    extensions_set = {ext.lstrip(\".\") for ext in extensions}\n    directory = Path(directory)\n\n    root_exclude_dirs = {directory / exclude_dir for exclude_dir in exclude_dirs}\n\n    files = (\n        p.resolve()\n        for p in directory.glob(\"**/*\")\n        if p.is_file() and p.suffix.lstrip(\".\") in extensions_set\n    )\n\n    for file_path in files:\n        if not any(\n            file_path.is_relative_to(exclude_dir) for exclude_dir in root_exclude_dirs\n        ):\n            rename_imports_and_app_name(file_path, old_name, new_name)\n"
  },
  {
    "path": "reflex/utils/serializers.py",
    "content": "\"\"\"Serializers used to convert Var types to JSON strings.\"\"\"\n\nfrom __future__ import annotations\n\nimport contextlib\nimport dataclasses\nimport decimal\nimport functools\nimport inspect\nimport json\nimport warnings\nfrom collections.abc import Callable, Mapping, Sequence\nfrom datetime import date, datetime, time, timedelta\nfrom enum import Enum\nfrom importlib.util import find_spec\nfrom pathlib import Path\nfrom typing import Any, Literal, TypeVar, get_type_hints, overload\nfrom uuid import UUID\n\nfrom reflex.base import Base\nfrom reflex.constants.colors import Color\nfrom reflex.utils import console, types\n\n# Mapping from type to a serializer.\n# The serializer should convert the type to a JSON object.\nSerializedType = str | bool | int | float | list | dict | None\n\n\nSerializer = Callable[[Any], SerializedType]\n\n\nSERIALIZERS: dict[type, Serializer] = {}\nSERIALIZER_TYPES: dict[type, type] = {}\n\nSERIALIZED_FUNCTION = TypeVar(\"SERIALIZED_FUNCTION\", bound=Serializer)\n\n\n@overload\ndef serializer(\n    fn: None = None,\n    to: type[SerializedType] | None = None,\n    overwrite: bool | None = None,\n) -> Callable[[SERIALIZED_FUNCTION], SERIALIZED_FUNCTION]: ...\n\n\n@overload\ndef serializer(\n    fn: SERIALIZED_FUNCTION,\n    to: type[SerializedType] | None = None,\n    overwrite: bool | None = None,\n) -> SERIALIZED_FUNCTION: ...\n\n\ndef serializer(\n    fn: SERIALIZED_FUNCTION | None = None,\n    to: Any = None,\n    overwrite: bool | None = None,\n) -> SERIALIZED_FUNCTION | Callable[[SERIALIZED_FUNCTION], SERIALIZED_FUNCTION]:\n    \"\"\"Decorator to add a serializer for a given type.\n\n    Args:\n        fn: The function to decorate.\n        to: The type returned by the serializer. If this is `str`, then any Var created from this type will be treated as a string.\n        overwrite: Whether to overwrite the existing serializer.\n\n    Returns:\n        The decorated function.\n    \"\"\"\n\n    def wrapper(fn: SERIALIZED_FUNCTION) -> SERIALIZED_FUNCTION:\n        # Check the type hints to get the type of the argument.\n        type_hints = get_type_hints(fn)\n        args = [arg for arg in type_hints if arg != \"return\"]\n\n        # Make sure the function takes a single argument.\n        if len(args) != 1:\n            msg = \"Serializer must take a single argument.\"\n            raise ValueError(msg)\n\n        # Get the type of the argument.\n        type_ = type_hints[args[0]]\n\n        # Make sure the type is not already registered.\n        registered_fn = SERIALIZERS.get(type_)\n        if registered_fn is not None and registered_fn != fn and overwrite is not True:\n            message = f\"Overwriting serializer for type {type_} from {registered_fn.__module__}:{registered_fn.__qualname__} to {fn.__module__}:{fn.__qualname__}.\"\n            if overwrite is False:\n                raise ValueError(message)\n            caller_frame = next(\n                filter(\n                    lambda frame: frame.filename != __file__,\n                    inspect.getouterframes(inspect.currentframe()),\n                ),\n                None,\n            )\n            file_info = (\n                f\"(at {caller_frame.filename}:{caller_frame.lineno})\"\n                if caller_frame\n                else \"\"\n            )\n            console.warn(\n                f\"{message} Call rx.serializer with `overwrite=True` if this is intentional. {file_info}\"\n            )\n\n        to_type = to or type_hints.get(\"return\")\n\n        # Apply type transformation if requested\n        if to_type:\n            SERIALIZER_TYPES[type_] = to_type\n            get_serializer_type.cache_clear()\n\n        # Register the serializer.\n        SERIALIZERS[type_] = fn\n        get_serializer.cache_clear()\n\n        # Return the function.\n        return fn\n\n    if fn is not None:\n        return wrapper(fn)\n    return wrapper\n\n\n@overload\ndef serialize(\n    value: Any, get_type: Literal[True]\n) -> tuple[SerializedType | None, types.GenericType | None]: ...\n\n\n@overload\ndef serialize(value: Any, get_type: Literal[False]) -> SerializedType | None: ...\n\n\n@overload\ndef serialize(value: Any) -> SerializedType | None: ...\n\n\ndef serialize(\n    value: Any, get_type: bool = False\n) -> SerializedType | tuple[SerializedType | None, types.GenericType | None] | None:\n    \"\"\"Serialize the value to a JSON string.\n\n    Args:\n        value: The value to serialize.\n        get_type: Whether to return the type of the serialized value.\n\n    Returns:\n        The serialized value, or None if a serializer is not found.\n    \"\"\"\n    # Get the serializer for the type.\n    serializer = get_serializer(type(value))\n\n    # If there is no serializer, return None.\n    if serializer is None:\n        if dataclasses.is_dataclass(value) and not isinstance(value, type):\n            return {k.name: getattr(value, k.name) for k in dataclasses.fields(value)}\n\n        if get_type:\n            return None, None\n        return None\n\n    # Serialize the value.\n    serialized = serializer(value)\n\n    # Return the serialized value and the type.\n    if get_type:\n        return serialized, get_serializer_type(type(value))\n    return serialized\n\n\n@functools.lru_cache\ndef get_serializer(type_: type) -> Serializer | None:\n    \"\"\"Get the serializer for the type.\n\n    Args:\n        type_: The type to get the serializer for.\n\n    Returns:\n        The serializer for the type, or None if there is no serializer.\n    \"\"\"\n    # First, check if the type is registered.\n    serializer = SERIALIZERS.get(type_)\n    if serializer is not None:\n        return serializer\n\n    # If the type is not registered, check if it is a subclass of a registered type.\n    for registered_type, serializer in reversed(SERIALIZERS.items()):\n        if issubclass(type_, registered_type):\n            return serializer\n\n    # If there is no serializer, return None.\n    return None\n\n\n@functools.lru_cache\ndef get_serializer_type(type_: type) -> type | None:\n    \"\"\"Get the converted type for the type after serializing.\n\n    Args:\n        type_: The type to get the serializer type for.\n\n    Returns:\n        The serialized type for the type, or None if there is no type conversion registered.\n    \"\"\"\n    # First, check if the type is registered.\n    serializer = SERIALIZER_TYPES.get(type_)\n    if serializer is not None:\n        return serializer\n\n    # If the type is not registered, check if it is a subclass of a registered type.\n    for registered_type, serializer in reversed(SERIALIZER_TYPES.items()):\n        if issubclass(type_, registered_type):\n            return serializer\n\n    # If there is no serializer, return None.\n    return None\n\n\ndef has_serializer(type_: type, into_type: type | None = None) -> bool:\n    \"\"\"Check if there is a serializer for the type.\n\n    Args:\n        type_: The type to check.\n        into_type: The type to serialize into.\n\n    Returns:\n        Whether there is a serializer for the type.\n    \"\"\"\n    serializer_for_type = get_serializer(type_)\n    return serializer_for_type is not None and (\n        into_type is None or get_serializer_type(type_) == into_type\n    )\n\n\ndef can_serialize(type_: type, into_type: type | None = None) -> bool:\n    \"\"\"Check if there is a serializer for the type.\n\n    Args:\n        type_: The type to check.\n        into_type: The type to serialize into.\n\n    Returns:\n        Whether there is a serializer for the type.\n    \"\"\"\n    return (\n        isinstance(type_, type)\n        and dataclasses.is_dataclass(type_)\n        and (into_type is None or into_type is dict)\n    ) or has_serializer(type_, into_type)\n\n\n@serializer(to=str)\ndef serialize_type(value: type) -> str:\n    \"\"\"Serialize a python type.\n\n    Args:\n        value: the type to serialize.\n\n    Returns:\n        The serialized type.\n    \"\"\"\n    return value.__name__\n\n\n@serializer(to=dict)\ndef serialize_base(value: Base) -> dict:\n    \"\"\"Serialize a Base instance.\n\n    Args:\n        value : The Base to serialize.\n\n    Returns:\n        The serialized Base.\n    \"\"\"\n    from reflex.vars.base import Var\n\n    return {\n        k: v for k, v in value.dict().items() if isinstance(v, Var) or not callable(v)\n    }\n\n\nif find_spec(\"pydantic\"):\n    from pydantic import BaseModel as BaseModelV2\n    from pydantic.v1 import BaseModel as BaseModelV1\n\n    @serializer(to=dict)\n    def serialize_base_model_v1(model: BaseModelV1) -> dict:\n        \"\"\"Serialize a pydantic v1 BaseModel instance.\n\n        Args:\n            model: The BaseModel to serialize.\n\n        Returns:\n            The serialized BaseModel.\n        \"\"\"\n        return model.dict()\n\n    if BaseModelV1 is not BaseModelV2:\n\n        @serializer(to=dict)\n        def serialize_base_model_v2(model: BaseModelV2) -> dict:\n            \"\"\"Serialize a pydantic v2 BaseModel instance.\n\n            Args:\n                model: The BaseModel to serialize.\n\n            Returns:\n                The serialized BaseModel.\n            \"\"\"\n            return model.model_dump()\n\n\n@serializer\ndef serialize_set(value: set) -> list:\n    \"\"\"Serialize a set to a JSON serializable list.\n\n    Args:\n        value: The set to serialize.\n\n    Returns:\n        The serialized list.\n    \"\"\"\n    return list(value)\n\n\n@serializer\ndef serialize_sequence(value: Sequence) -> list:\n    \"\"\"Serialize a sequence to a JSON serializable list.\n\n    Args:\n        value: The sequence to serialize.\n\n    Returns:\n        The serialized list.\n    \"\"\"\n    return list(value)\n\n\n@serializer(to=dict)\ndef serialize_mapping(value: Mapping) -> dict:\n    \"\"\"Serialize a mapping type to a dictionary.\n\n    Args:\n        value: The mapping instance to serialize.\n\n    Returns:\n        A new dictionary containing the same key-value pairs as the input mapping.\n    \"\"\"\n    return {**value}\n\n\n@serializer(to=str)\ndef serialize_datetime(dt: date | datetime | time | timedelta) -> str:\n    \"\"\"Serialize a datetime to a JSON string.\n\n    Args:\n        dt: The datetime to serialize.\n\n    Returns:\n        The serialized datetime.\n    \"\"\"\n    return str(dt)\n\n\n@serializer(to=str)\ndef serialize_path(path: Path) -> str:\n    \"\"\"Serialize a pathlib.Path to a JSON string.\n\n    Args:\n        path: The path to serialize.\n\n    Returns:\n        The serialized path.\n    \"\"\"\n    return str(path.as_posix())\n\n\n@serializer\ndef serialize_enum(en: Enum) -> str:\n    \"\"\"Serialize a enum to a JSON string.\n\n    Args:\n        en: The enum to serialize.\n\n    Returns:\n        The serialized enum.\n    \"\"\"\n    return en.value\n\n\n@serializer(to=str)\ndef serialize_uuid(uuid: UUID) -> str:\n    \"\"\"Serialize a UUID to a JSON string.\n\n    Args:\n        uuid: The UUID to serialize.\n\n    Returns:\n        The serialized UUID.\n    \"\"\"\n    return str(uuid)\n\n\n@serializer(to=float)\ndef serialize_decimal(value: decimal.Decimal) -> float:\n    \"\"\"Serialize a Decimal to a float.\n\n    Args:\n        value: The Decimal to serialize.\n\n    Returns:\n        The serialized Decimal as a float.\n    \"\"\"\n    return float(value)\n\n\n@serializer(to=str)\ndef serialize_color(color: Color) -> str:\n    \"\"\"Serialize a color.\n\n    Args:\n        color: The color to serialize.\n\n    Returns:\n        The serialized color.\n    \"\"\"\n    return color.__format__(\"\")\n\n\nwith contextlib.suppress(ImportError):\n    from pandas import DataFrame\n\n    def format_dataframe_values(df: DataFrame) -> list[list[Any]]:\n        \"\"\"Format dataframe values to a list of lists.\n\n        Args:\n            df: The dataframe to format.\n\n        Returns:\n            The dataframe as a list of lists.\n        \"\"\"\n        return [\n            [str(d) if isinstance(d, (list, tuple)) else d for d in data]\n            for data in list(df.to_numpy().tolist())\n        ]\n\n    @serializer\n    def serialize_dataframe(df: DataFrame) -> dict:\n        \"\"\"Serialize a pandas dataframe.\n\n        Args:\n            df: The dataframe to serialize.\n\n        Returns:\n            The serialized dataframe.\n        \"\"\"\n        return {\n            \"columns\": df.columns.tolist(),\n            \"data\": format_dataframe_values(df),\n        }\n\n\nwith contextlib.suppress(ImportError):\n    from plotly.graph_objects import Figure, layout\n    from plotly.io import to_json\n\n    @serializer\n    def serialize_figure(figure: Figure) -> dict:\n        \"\"\"Serialize a plotly figure.\n\n        Args:\n            figure: The figure to serialize.\n\n        Returns:\n            The serialized figure.\n        \"\"\"\n        return json.loads(str(to_json(figure)))\n\n    @serializer\n    def serialize_template(template: layout.Template) -> dict:\n        \"\"\"Serialize a plotly template.\n\n        Args:\n            template: The template to serialize.\n\n        Returns:\n            The serialized template.\n        \"\"\"\n        return {\n            \"data\": json.loads(str(to_json(template.data))),\n            \"layout\": json.loads(str(to_json(template.layout))),\n        }\n\n\nwith contextlib.suppress(ImportError):\n    import base64\n    import io\n\n    from PIL.Image import MIME\n    from PIL.Image import Image as Img\n\n    @serializer\n    def serialize_image(image: Img) -> str:\n        \"\"\"Serialize a plotly figure.\n\n        Args:\n            image: The image to serialize.\n\n        Returns:\n            The serialized image.\n        \"\"\"\n        buff = io.BytesIO()\n        image_format = getattr(image, \"format\", None) or \"PNG\"\n        image.save(buff, format=image_format)\n        image_bytes = buff.getvalue()\n        base64_image = base64.b64encode(image_bytes).decode(\"utf-8\")\n        try:\n            # Newer method to get the mime type, but does not always work.\n            mime_type = image.get_format_mimetype()  # pyright: ignore [reportAttributeAccessIssue]\n        except AttributeError:\n            try:\n                # Fallback method\n                mime_type = MIME[image_format]\n            except KeyError:\n                # Unknown mime_type: warn and return image/png and hope the browser can sort it out.\n                warnings.warn(  # noqa: B028\n                    f\"Unknown mime type for {image} {image_format}. Defaulting to image/png\"\n                )\n                mime_type = \"image/png\"\n\n        return f\"data:{mime_type};base64,{base64_image}\"\n"
  },
  {
    "path": "reflex/utils/tasks.py",
    "content": "\"\"\"Helpers for managing asyncio tasks.\"\"\"\n\nimport asyncio\nimport time\nfrom collections.abc import Callable, Coroutine\nfrom typing import Any\n\nfrom reflex.utils import console\n\n\nasync def _run_forever(\n    coro_function: Callable[..., Coroutine],\n    *args: Any,\n    suppress_exceptions: list[type[BaseException]],\n    exception_delay: float,\n    exception_limit: int,\n    exception_limit_window: float,\n    **kwargs: Any,\n):\n    \"\"\"Wrapper to continuously run a coroutine function, suppressing certain exceptions.\n\n    Args:\n        coro_function: The coroutine function to run.\n        *args: The arguments to pass to the coroutine function.\n        suppress_exceptions: The exceptions to suppress.\n        exception_delay: The delay between retries when an exception is suppressed.\n        exception_limit: The maximum number of suppressed exceptions within the limit window before raising.\n        exception_limit_window: The time window in seconds for counting suppressed exceptions.\n        **kwargs: The keyword arguments to pass to the coroutine function.\n    \"\"\"\n    last_regular_loop_start = 0\n    exception_count = 0\n\n    while True:\n        # Reset the exception count when the limit window has elapsed since the last non-exception loop started.\n        if last_regular_loop_start + exception_limit_window < time.monotonic():\n            exception_count = 0\n        if not exception_count:\n            last_regular_loop_start = time.monotonic()\n        try:\n            await coro_function(*args, **kwargs)\n        except (asyncio.CancelledError, RuntimeError):\n            raise\n        except Exception as e:\n            if any(isinstance(e, ex) for ex in suppress_exceptions):\n                exception_count += 1\n                if exception_count >= exception_limit:\n                    console.error(\n                        f\"{coro_function.__name__}: task exceeded exception limit {exception_limit} within {exception_limit_window}s: {e}\"\n                    )\n                    raise\n                console.error(f\"{coro_function.__name__}: task error suppressed: {e}\")\n                await asyncio.sleep(exception_delay)\n                continue\n            raise\n\n\ndef ensure_task(\n    owner: Any,\n    task_attribute: str,\n    coro_function: Callable[..., Coroutine],\n    *args: Any,\n    suppress_exceptions: list[type[BaseException]] | None = None,\n    exception_delay: float = 1.0,\n    exception_limit: int = 5,\n    exception_limit_window: float = 60.0,\n    **kwargs: Any,\n) -> asyncio.Task:\n    \"\"\"Ensure that a task is running for the given coroutine function.\n\n    Note: if the task is already running, args and kwargs are ignored.\n\n    Args:\n        owner: The owner of the task.\n        task_attribute: The attribute name to store/retrieve the task from the owner object.\n        coro_function: The coroutine function to run as a task.\n        suppress_exceptions: The exceptions to log and continue when running the coroutine.\n        exception_delay: The delay between retries when an exception is suppressed.\n        exception_limit: The maximum number of suppressed exceptions within the limit window before raising.\n        exception_limit_window: The time window in seconds for counting suppressed exceptions.\n        *args: The arguments to pass to the coroutine function.\n        **kwargs: The keyword arguments to pass to the coroutine function.\n\n    Returns:\n        The asyncio task running the coroutine function.\n    \"\"\"\n    if suppress_exceptions is None:\n        suppress_exceptions = []\n    if RuntimeError in suppress_exceptions:\n        msg = \"Cannot suppress RuntimeError exceptions which may be raised by asyncio machinery.\"\n        raise RuntimeError(msg)\n\n    task = getattr(owner, task_attribute, None)\n    if task is None or task.done():\n        asyncio.get_running_loop()  # Ensure we're in an event loop.\n        task = asyncio.create_task(\n            _run_forever(\n                coro_function,\n                *args,\n                suppress_exceptions=suppress_exceptions,\n                exception_delay=exception_delay,\n                exception_limit=exception_limit,\n                exception_limit_window=exception_limit_window,\n                **kwargs,\n            ),\n            name=f\"reflex_ensure_task|{type(owner).__name__}.{task_attribute}={coro_function.__name__}|{time.time()}\",\n        )\n        setattr(owner, task_attribute, task)\n    return task\n"
  },
  {
    "path": "reflex/utils/telemetry.py",
    "content": "\"\"\"Anonymous telemetry for Reflex.\"\"\"\n\nimport asyncio\nimport dataclasses\nimport importlib.metadata\nimport json\nimport multiprocessing\nimport platform\nimport warnings\nfrom contextlib import suppress\nfrom datetime import datetime, timezone\nfrom typing import TypedDict\n\nfrom reflex import constants\nfrom reflex.environment import environment\nfrom reflex.utils import console, processes\nfrom reflex.utils.decorator import once, once_unless_none\nfrom reflex.utils.exceptions import ReflexError\nfrom reflex.utils.js_runtimes import get_bun_version, get_node_version\nfrom reflex.utils.prerequisites import ensure_reflex_installation_id, get_project_hash\n\nUTC = timezone.utc\nPOSTHOG_API_URL: str = \"https://app.posthog.com/capture/\"\n\n\n@dataclasses.dataclass(frozen=True)\nclass CpuInfo:\n    \"\"\"Model to save cpu info.\"\"\"\n\n    manufacturer_id: str | None\n    model_name: str | None\n    address_width: int | None\n\n\ndef format_address_width(address_width: str | None) -> int | None:\n    \"\"\"Cast address width to an int.\n\n    Args:\n        address_width: The address width.\n\n    Returns:\n        Address width int\n    \"\"\"\n    try:\n        return int(address_width) if address_width else None\n    except ValueError:\n        return None\n\n\ndef _retrieve_cpu_info() -> CpuInfo | None:\n    \"\"\"Retrieve the CPU info of the host.\n\n    Returns:\n        The CPU info.\n    \"\"\"\n    platform_os = platform.system()\n    cpuinfo = {}\n    try:\n        if platform_os == \"Windows\":\n            cmd = 'powershell -Command \"Get-CimInstance Win32_Processor | Select-Object -First 1 | Select-Object AddressWidth,Manufacturer,Name | ConvertTo-Json\"'\n            output = processes.execute_command_and_return_output(cmd)\n            if output:\n                cpu_data = json.loads(output)\n                cpuinfo[\"address_width\"] = cpu_data[\"AddressWidth\"]\n                cpuinfo[\"manufacturer_id\"] = cpu_data[\"Manufacturer\"]\n                cpuinfo[\"model_name\"] = cpu_data[\"Name\"]\n        elif platform_os == \"Linux\":\n            output = processes.execute_command_and_return_output(\"lscpu\")\n            if output:\n                lines = output.split(\"\\n\")\n                for line in lines:\n                    if \"Architecture\" in line:\n                        cpuinfo[\"address_width\"] = (\n                            64 if line.split(\":\")[1].strip() == \"x86_64\" else 32\n                        )\n                    if \"Vendor ID:\" in line:\n                        cpuinfo[\"manufacturer_id\"] = line.split(\":\")[1].strip()\n                    if \"Model name\" in line:\n                        cpuinfo[\"model_name\"] = line.split(\":\")[1].strip()\n        elif platform_os == \"Darwin\":\n            cpuinfo[\"address_width\"] = format_address_width(\n                processes.execute_command_and_return_output(\"getconf LONG_BIT\")\n            )\n            cpuinfo[\"manufacturer_id\"] = processes.execute_command_and_return_output(\n                \"sysctl -n machdep.cpu.brand_string\"\n            )\n            cpuinfo[\"model_name\"] = processes.execute_command_and_return_output(\n                \"uname -m\"\n            )\n    except Exception as err:\n        console.error(f\"Failed to retrieve CPU info. {err}\")\n        return None\n\n    return (\n        CpuInfo(\n            manufacturer_id=cpuinfo.get(\"manufacturer_id\"),\n            model_name=cpuinfo.get(\"model_name\"),\n            address_width=cpuinfo.get(\"address_width\"),\n        )\n        if cpuinfo\n        else None\n    )\n\n\n@once\ndef get_cpu_info() -> CpuInfo | None:\n    \"\"\"Get the CPU info of the underlining host.\n\n    Returns:\n        The CPU info.\n    \"\"\"\n    cpu_info_file = environment.REFLEX_DIR.get() / \"cpu_info.json\"\n    if cpu_info_file.exists() and (cpu_info := json.loads(cpu_info_file.read_text())):\n        return CpuInfo(**cpu_info)\n    cpu_info = _retrieve_cpu_info()\n    if cpu_info:\n        cpu_info_file.parent.mkdir(parents=True, exist_ok=True)\n        cpu_info_file.write_text(json.dumps(dataclasses.asdict(cpu_info)))\n    return cpu_info\n\n\ndef get_os() -> str:\n    \"\"\"Get the operating system.\n\n    Returns:\n        The operating system.\n    \"\"\"\n    return platform.system()\n\n\ndef get_detailed_platform_str() -> str:\n    \"\"\"Get the detailed os/platform string.\n\n    Returns:\n        The platform string\n    \"\"\"\n    return platform.platform()\n\n\ndef get_python_version() -> str:\n    \"\"\"Get the Python version.\n\n    Returns:\n        The Python version.\n    \"\"\"\n    # Remove the \"+\" from the version string in case user is using a pre-release version.\n    return platform.python_version().rstrip(\"+\")\n\n\ndef get_reflex_version() -> str:\n    \"\"\"Get the Reflex version.\n\n    Returns:\n        The Reflex version.\n    \"\"\"\n    return constants.Reflex.VERSION\n\n\ndef get_cpu_count() -> int:\n    \"\"\"Get the number of CPUs.\n\n    Returns:\n        The number of CPUs.\n    \"\"\"\n    return multiprocessing.cpu_count()\n\n\ndef get_reflex_enterprise_version() -> str | None:\n    \"\"\"Get the version of reflex-enterprise if installed.\n\n    Returns:\n        The version string if installed, None if not installed.\n    \"\"\"\n    try:\n        return importlib.metadata.version(\"reflex-enterprise\")\n    except importlib.metadata.PackageNotFoundError:\n        return None\n\n\ndef _raise_on_missing_project_hash() -> bool:\n    \"\"\"Check if an error should be raised when project hash is missing.\n\n    When running reflex with --backend-only, or doing database migration\n    operations, there is no requirement for a .web directory, so the reflex.json\n    file may not exist, and this should not be considered an error.\n\n    Returns:\n        False when compilation should be skipped (i.e. no .web directory is required).\n        Otherwise return True.\n    \"\"\"\n    return not environment.REFLEX_SKIP_COMPILE.get()\n\n\nclass _Properties(TypedDict):\n    \"\"\"Properties type for telemetry.\"\"\"\n\n    distinct_id: int\n    distinct_app_id: int\n    user_os: str\n    user_os_detail: str\n    reflex_version: str\n    python_version: str\n    node_version: str | None\n    bun_version: str | None\n    reflex_enterprise_version: str | None\n    cpu_count: int\n    cpu_info: dict\n\n\nclass _DefaultEvent(TypedDict):\n    \"\"\"Default event type for telemetry.\"\"\"\n\n    api_key: str\n    properties: _Properties\n\n\nclass _Event(_DefaultEvent):\n    \"\"\"Event type for telemetry.\"\"\"\n\n    event: str\n    timestamp: str\n\n\ndef _get_event_defaults() -> _DefaultEvent | None:\n    \"\"\"Get the default event data.\n\n    Returns:\n        The default event data.\n    \"\"\"\n    installation_id = ensure_reflex_installation_id()\n    project_hash = get_project_hash(raise_on_fail=_raise_on_missing_project_hash())\n\n    if installation_id is None or project_hash is None:\n        console.debug(\n            f\"Could not get installation_id or project_hash: {installation_id}, {project_hash}\"\n        )\n        return None\n\n    cpuinfo = get_cpu_info()\n\n    return {\n        \"api_key\": \"phc_JoMo0fOyi0GQAooY3UyO9k0hebGkMyFJrrCw1Gt5SGb\",\n        \"properties\": {\n            \"distinct_id\": installation_id,\n            \"distinct_app_id\": project_hash,\n            \"user_os\": get_os(),\n            \"user_os_detail\": get_detailed_platform_str(),\n            \"reflex_version\": get_reflex_version(),\n            \"python_version\": get_python_version(),\n            \"node_version\": (\n                str(node_version) if (node_version := get_node_version()) else None\n            ),\n            \"bun_version\": (\n                str(bun_version) if (bun_version := get_bun_version()) else None\n            ),\n            \"reflex_enterprise_version\": get_reflex_enterprise_version(),\n            \"cpu_count\": get_cpu_count(),\n            \"cpu_info\": dataclasses.asdict(cpuinfo) if cpuinfo else {},\n        },\n    }\n\n\n@once_unless_none\ndef get_event_defaults() -> _DefaultEvent | None:\n    \"\"\"Get the default event data.\n\n    Returns:\n        The default event data.\n    \"\"\"\n    return _get_event_defaults()\n\n\ndef _prepare_event(event: str, **kwargs) -> _Event | None:\n    \"\"\"Prepare the event to be sent to the PostHog server.\n\n    Args:\n        event: The event name.\n        kwargs: Additional data to send with the event.\n\n    Returns:\n        The event data.\n    \"\"\"\n    event_data = get_event_defaults()\n    if not event_data:\n        return None\n\n    additional_keys = [\"template\", \"context\", \"detail\", \"user_uuid\"]\n\n    properties = event_data[\"properties\"]\n\n    for key in additional_keys:\n        if key in properties or key not in kwargs:\n            continue\n\n        properties[key] = kwargs[key]\n\n    stamp = datetime.now(UTC).isoformat()\n\n    return {\n        \"api_key\": event_data[\"api_key\"],\n        \"event\": event,\n        \"properties\": properties,\n        \"timestamp\": stamp,\n    }\n\n\ndef _send_event(event_data: _Event) -> bool:\n    import httpx\n\n    try:\n        httpx.post(POSTHOG_API_URL, json=event_data)\n    except Exception:\n        return False\n    else:\n        return True\n\n\ndef _send(event: str, telemetry_enabled: bool | None, **kwargs) -> bool:\n    from reflex.config import get_config\n\n    # Get the telemetry_enabled from the config if it is not specified.\n    if telemetry_enabled is None:\n        telemetry_enabled = get_config().telemetry_enabled\n\n    # Return if telemetry is disabled.\n    if not telemetry_enabled:\n        return False\n\n    with suppress(Exception):\n        event_data = _prepare_event(event, **kwargs)\n        if not event_data:\n            return False\n        return _send_event(event_data)\n    return False\n\n\nbackground_tasks = set()\n\n\ndef send(event: str, telemetry_enabled: bool | None = None, **kwargs):\n    \"\"\"Send anonymous telemetry for Reflex.\n\n    Args:\n        event: The event name.\n        telemetry_enabled: Whether to send the telemetry (If None, get from config).\n        kwargs: Additional data to send with the event.\n    \"\"\"\n\n    async def async_send(event: str, telemetry_enabled: bool | None, **kwargs):  # noqa: RUF029\n        return _send(event, telemetry_enabled, **kwargs)\n\n    try:\n        # Within an event loop context, send the event asynchronously.\n        task = asyncio.create_task(\n            async_send(event, telemetry_enabled, **kwargs),\n            name=f\"reflex_send_telemetry_event|{event}\",\n        )\n        background_tasks.add(task)\n        task.add_done_callback(background_tasks.discard)\n    except RuntimeError:\n        # If there is no event loop, send the event synchronously.\n        warnings.filterwarnings(\"ignore\", category=RuntimeWarning)\n        _send(event, telemetry_enabled, **kwargs)\n\n\ndef send_error(error: Exception, context: str):\n    \"\"\"Send an error event.\n\n    Args:\n        error: The error to send.\n        context: The context of the error (e.g. \"frontend\" or \"backend\")\n    \"\"\"\n    if isinstance(error, ReflexError):\n        send(\"error\", detail=type(error).__name__, context=context)\n"
  },
  {
    "path": "reflex/utils/templates.py",
    "content": "\"\"\"This module provides utilities for managing Reflex app templates.\"\"\"\n\nimport dataclasses\nimport shutil\nimport tempfile\nimport zipfile\nfrom pathlib import Path\nfrom urllib.parse import urlparse\n\nfrom reflex import constants\nfrom reflex.config import get_config\nfrom reflex.utils import console, net, path_ops, redir\n\n\n@dataclasses.dataclass(frozen=True)\nclass Template:\n    \"\"\"A template for a Reflex app.\"\"\"\n\n    name: str\n    description: str\n    code_url: str\n\n\ndef create_config(app_name: str):\n    \"\"\"Create a new rxconfig file.\n\n    Args:\n        app_name: The name of the app.\n    \"\"\"\n    # Import here to avoid circular imports.\n    from reflex.compiler import templates\n\n    console.debug(f\"Creating {constants.Config.FILE}\")\n    constants.Config.FILE.write_text(templates.rxconfig_template(app_name=app_name))\n\n\ndef initialize_app_directory(\n    app_name: str,\n    template_name: str = constants.Templates.DEFAULT,\n    template_code_dir_name: str | None = None,\n    template_dir: Path | None = None,\n):\n    \"\"\"Initialize the app directory on reflex init.\n\n    Args:\n        app_name: The name of the app.\n        template_name: The name of the template to use.\n        template_code_dir_name: The name of the code directory in the template.\n        template_dir: The directory of the template source files.\n\n    Raises:\n        SystemExit: If template_name, template_code_dir_name, template_dir combination is not supported.\n    \"\"\"\n    console.log(\"Initializing the app directory.\")\n\n    # By default, use the blank template from local assets.\n    if template_name == constants.Templates.DEFAULT:\n        if template_code_dir_name is not None or template_dir is not None:\n            console.error(\n                f\"Only {template_name=} should be provided, got {template_code_dir_name=}, {template_dir=}.\"\n            )\n            raise SystemExit(1)\n        template_code_dir_name = constants.Templates.Dirs.CODE\n        template_dir = Path(constants.Templates.Dirs.BASE, \"apps\", template_name)\n    else:\n        if template_code_dir_name is None or template_dir is None:\n            console.error(\n                f\"For `{template_name}` template, `template_code_dir_name` and `template_dir` should both be provided.\"\n            )\n            raise SystemExit(1)\n\n    console.debug(f\"Using {template_name=} {template_dir=} {template_code_dir_name=}.\")\n\n    # Remove __pycache__ dirs in template directory and current directory.\n    for pycache_dir in [\n        *template_dir.glob(\"**/__pycache__\"),\n        *Path.cwd().glob(\"**/__pycache__\"),\n    ]:\n        shutil.rmtree(pycache_dir, ignore_errors=True)\n\n    for file in template_dir.iterdir():\n        # Copy the file to current directory but keep the name the same.\n        path_ops.cp(str(file), file.name)\n\n    # Rename the template app to the app name.\n    path_ops.mv(template_code_dir_name, app_name)\n    path_ops.mv(\n        Path(app_name) / (template_name + constants.Ext.PY),\n        Path(app_name) / (app_name + constants.Ext.PY),\n    )\n\n    # Fix up the imports.\n    path_ops.find_replace(\n        app_name,\n        f\"from {template_name}\",\n        f\"from {app_name}\",\n    )\n\n\ndef initialize_default_app(app_name: str):\n    \"\"\"Initialize the default app.\n\n    Args:\n        app_name: The name of the app.\n    \"\"\"\n    create_config(app_name)\n    initialize_app_directory(app_name)\n\n\ndef create_config_init_app_from_remote_template(app_name: str, template_url: str):\n    \"\"\"Create new rxconfig and initialize app using a remote template.\n\n    Args:\n        app_name: The name of the app.\n        template_url: The path to the template source code as a zip file.\n\n    Raises:\n        SystemExit: If any download, file operations fail or unexpected zip file format.\n\n    \"\"\"\n    import httpx\n\n    # Create a temp directory for the zip download.\n    try:\n        temp_dir = tempfile.mkdtemp()\n    except OSError as ose:\n        console.error(f\"Failed to create temp directory for download: {ose}\")\n        raise SystemExit(1) from None\n\n    # Use httpx GET with redirects to download the zip file.\n    zip_file_path: Path = Path(temp_dir) / \"template.zip\"\n    try:\n        # Note: following redirects can be risky. We only allow this for reflex built templates at the moment.\n        response = net.get(template_url, follow_redirects=True)\n        console.debug(f\"Server responded download request: {response}\")\n        response.raise_for_status()\n    except httpx.HTTPError as he:\n        console.error(f\"Failed to download the template: {he}\")\n        raise SystemExit(1) from None\n    try:\n        zip_file_path.write_bytes(response.content)\n        console.debug(f\"Downloaded the zip to {zip_file_path}\")\n    except OSError as ose:\n        console.error(f\"Unable to write the downloaded zip to disk {ose}\")\n        raise SystemExit(1) from None\n\n    # Create a temp directory for the zip extraction.\n    try:\n        unzip_dir = Path(tempfile.mkdtemp())\n    except OSError as ose:\n        console.error(f\"Failed to create temp directory for extracting zip: {ose}\")\n        raise SystemExit(1) from None\n\n    try:\n        zipfile.ZipFile(zip_file_path).extractall(path=unzip_dir)\n        # The zip file downloaded from github looks like:\n        # repo-name-branch/**/*, so we need to remove the top level directory.\n    except Exception as uze:\n        console.error(f\"Failed to unzip the template: {uze}\")\n        raise SystemExit(1) from None\n\n    if len(subdirs := list(unzip_dir.iterdir())) != 1:\n        console.error(f\"Expected one directory in the zip, found {subdirs}\")\n        raise SystemExit(1)\n\n    template_dir = unzip_dir / subdirs[0]\n    console.debug(f\"Template folder is located at {template_dir}\")\n\n    # Move the rxconfig file here first.\n    path_ops.mv(str(template_dir / constants.Config.FILE), constants.Config.FILE)\n    new_config = get_config(reload=True)\n\n    # Get the template app's name from rxconfig in case it is different than\n    # the source code repo name on github.\n    template_name = new_config.app_name\n\n    create_config(app_name)\n    initialize_app_directory(\n        app_name,\n        template_name=template_name,\n        template_code_dir_name=template_name,\n        template_dir=template_dir,\n    )\n    req_file = Path(\"requirements.txt\")\n    if req_file.exists() and len(req_file.read_text().splitlines()) > 1:\n        console.info(\n            \"Run `pip install -r requirements.txt` to install the required python packages for this template.\"\n        )\n    #  Clean up the temp directories.\n    shutil.rmtree(temp_dir)\n    shutil.rmtree(unzip_dir)\n\n\ndef validate_and_create_app_using_remote_template(\n    app_name: str, template: str, templates: dict[str, Template]\n):\n    \"\"\"Validate and create an app using a remote template.\n\n    Args:\n        app_name: The name of the app.\n        template: The name of the template.\n        templates: The available templates.\n\n    Raises:\n        SystemExit: If the template is not found.\n    \"\"\"\n    # If user selects a template, it needs to exist.\n    if template in templates:\n        from reflex_cli.v2.utils import hosting\n\n        authenticated_token = hosting.authenticated_token()\n        if not authenticated_token or not authenticated_token[0]:\n            console.print(\n                f\"Please use `reflex login` to access the '{template}' template.\"\n            )\n            raise SystemExit(3)\n\n        template_url = templates[template].code_url\n    else:\n        template_parsed_url = urlparse(template)\n        # Check if the template is a github repo.\n        if template_parsed_url.hostname == \"github.com\":\n            path = template_parsed_url.path.strip(\"/\").removesuffix(\".git\")\n            template_url = f\"https://github.com/{path}/archive/main.zip\"\n        else:\n            console.error(f\"Template `{template}` not found or invalid.\")\n            raise SystemExit(1)\n\n    if template_url is None:\n        return\n\n    create_config_init_app_from_remote_template(\n        app_name=app_name, template_url=template_url\n    )\n\n\ndef fetch_app_templates(version: str) -> dict[str, Template]:\n    \"\"\"Fetch a dict of templates from the templates repo using github API.\n\n    Args:\n        version: The version of the templates to fetch.\n\n    Returns:\n        The dict of templates.\n    \"\"\"\n\n    def get_release_by_tag(tag: str) -> dict | None:\n        url = f\"{constants.Reflex.RELEASES_URL}/tags/v{tag}\"\n        response = net.get(url)\n        if response.status_code == 404:\n            return None\n        response.raise_for_status()\n        return response.json()\n\n    release = get_release_by_tag(version)\n    if release is None:\n        console.warn(f\"No templates known for version {version}\")\n        return {}\n\n    asset_map = {\n        a[\"name\"]: a[\"browser_download_url\"] for a in release.get(\"assets\", [])\n    }\n\n    templates_url = asset_map.get(\"templates.json\")\n    if not templates_url:\n        console.warn(f\"Templates metadata not found for version {version}\")\n        return {}\n\n    templates_data = (\n        net.get(templates_url, follow_redirects=True).json().get(\"templates\", [])\n    )\n\n    known_fields = {f.name for f in dataclasses.fields(Template)}\n\n    filtered_templates = {}\n    for template in templates_data:\n        code_url = (\n            \"\"\n            if template[\"name\"] == \"blank\"\n            else asset_map.get(f\"{template['name']}.zip\")\n        )\n        if template[\"hidden\"] or code_url is None:\n            continue\n        filtered_templates[template[\"name\"]] = Template(\n            **{k: v for k, v in template.items() if k in known_fields},\n            code_url=code_url,\n        )\n    return filtered_templates\n\n\ndef fetch_remote_templates(\n    template: str,\n) -> tuple[str, dict[str, Template]]:\n    \"\"\"Fetch the available remote templates.\n\n    Args:\n        template: The name of the template.\n\n    Returns:\n        The selected template and the available templates.\n    \"\"\"\n    available_templates = {}\n\n    try:\n        # Get the available templates\n        available_templates = fetch_app_templates(constants.Reflex.VERSION)\n    except Exception as e:\n        console.warn(\"Failed to fetch templates. Falling back to default template.\")\n        console.debug(f\"Error while fetching templates: {e}\")\n        template = constants.Templates.DEFAULT\n\n    return template, available_templates\n\n\ndef prompt_for_template_options(templates: list[Template]) -> str:\n    \"\"\"Prompt the user to specify a template.\n\n    Args:\n        templates: The templates to choose from.\n\n    Returns:\n        The template name the user selects.\n\n    Raises:\n        SystemExit: If the user does not select a template.\n    \"\"\"\n    # Show the user the URLs of each template to preview.\n    console.print(\"\\nGet started with a template:\")\n\n    # Prompt the user to select a template.\n    for index, template in enumerate(templates):\n        console.print(f\"({index}) {template.description}\")\n\n    template = console.ask(\n        \"Which template would you like to use?\",\n        choices=[str(i) for i in range(len(templates))],\n        show_choices=False,\n        default=\"0\",\n    )\n\n    if not template:\n        console.error(\"No template selected.\")\n        raise SystemExit(1)\n\n    try:\n        template_index = int(template)\n    except ValueError:\n        console.error(\"Invalid template selected.\")\n        raise SystemExit(1) from None\n\n    if template_index < 0 or template_index >= len(templates):\n        console.error(\"Invalid template selected.\")\n        raise SystemExit(1)\n\n    # Return the template.\n    return templates[template_index].name\n\n\ndef initialize_app(app_name: str, template: str | None = None) -> str | None:\n    \"\"\"Initialize the app either from a remote template or a blank app. If the config file exists, it is considered as reinit.\n\n    Args:\n        app_name: The name of the app.\n        template: The name of the template to use.\n\n    Returns:\n        The name of the template.\n\n    Raises:\n        SystemExit: If the template is not valid or unspecified.\n    \"\"\"\n    # Local imports to avoid circular imports.\n    from reflex.utils import telemetry\n\n    # Check if the app is already initialized.\n    if constants.Config.FILE.exists():\n        telemetry.send(\"reinit\")\n        return None\n\n    templates: dict[str, Template] = {}\n\n    # Don't fetch app templates if the user directly asked for DEFAULT.\n    if template is not None and template != constants.Templates.DEFAULT:\n        template, templates = fetch_remote_templates(template)\n\n    if template is None:\n        template = prompt_for_template_options(get_init_cli_prompt_options())\n\n        if template == constants.Templates.CHOOSE_TEMPLATES:\n            redir.reflex_templates()\n            raise SystemExit(0)\n\n    if template == constants.Templates.AI:\n        redir.reflex_build_redirect()\n        raise SystemExit(0)\n\n    # If the blank template is selected, create a blank app.\n    if template == constants.Templates.DEFAULT:\n        # Default app creation behavior: a blank app.\n        initialize_default_app(app_name)\n    else:\n        validate_and_create_app_using_remote_template(\n            app_name=app_name, template=template, templates=templates\n        )\n\n    telemetry.send(\"init\", template=template)\n\n    return template\n\n\ndef get_init_cli_prompt_options() -> list[Template]:\n    \"\"\"Get the CLI options for initializing a Reflex app.\n\n    Returns:\n        The CLI options.\n    \"\"\"\n    return [\n        Template(\n            name=constants.Templates.DEFAULT,\n            description=\"A blank Reflex app.\",\n            code_url=\"\",\n        ),\n        Template(\n            name=constants.Templates.CHOOSE_TEMPLATES,\n            description=\"Premade templates built by the Reflex team.\",\n            code_url=\"\",\n        ),\n        Template(\n            name=constants.Templates.AI,\n            description=\"[bold]Try our AI builder.\",\n            code_url=\"\",\n        ),\n    ]\n"
  },
  {
    "path": "reflex/utils/token_manager.py",
    "content": "\"\"\"Token manager for handling client token to session ID mappings.\"\"\"\n\nfrom __future__ import annotations\n\nimport asyncio\nimport dataclasses\nimport pickle\nimport uuid\nfrom abc import ABC, abstractmethod\nfrom collections.abc import AsyncIterator, Callable, Coroutine\nfrom types import MappingProxyType\nfrom typing import TYPE_CHECKING, ClassVar\n\nfrom reflex.istate.manager.redis import StateManagerRedis\nfrom reflex.state import BaseState, StateUpdate\nfrom reflex.utils import console, prerequisites\nfrom reflex.utils.tasks import ensure_task\n\nif TYPE_CHECKING:\n    from redis.asyncio import Redis\n\n\ndef _get_new_token() -> str:\n    \"\"\"Generate a new unique token.\n\n    Returns:\n        A new UUID4 token string.\n    \"\"\"\n    return str(uuid.uuid4())\n\n\n@dataclasses.dataclass(frozen=True, kw_only=True)\nclass SocketRecord:\n    \"\"\"Record for a connected socket client.\"\"\"\n\n    instance_id: str\n    sid: str\n\n\n@dataclasses.dataclass(frozen=True, kw_only=True)\nclass LostAndFoundRecord:\n    \"\"\"Record for a StateUpdate for a token with its socket on another instance.\"\"\"\n\n    token: str\n    update: StateUpdate\n\n\nclass TokenManager(ABC):\n    \"\"\"Abstract base class for managing client token to session ID mappings.\"\"\"\n\n    def __init__(self):\n        \"\"\"Initialize the token manager with local dictionaries.\"\"\"\n        # Each process has an instance_id to identify its own sockets.\n        self.instance_id: str = _get_new_token()\n        # Keep a mapping between client token and socket ID.\n        self.token_to_socket: dict[str, SocketRecord] = {}\n        # Keep a mapping between socket ID and client token.\n        self.sid_to_token: dict[str, str] = {}\n\n    @property\n    def token_to_sid(self) -> MappingProxyType[str, str]:\n        \"\"\"Read-only compatibility property for token_to_socket mapping.\n\n        Returns:\n            The token to session ID mapping.\n        \"\"\"\n        return MappingProxyType({\n            token: sr.sid for token, sr in self.token_to_socket.items()\n        })\n\n    async def enumerate_tokens(self) -> AsyncIterator[str]:\n        \"\"\"Iterate over all tokens in the system.\n\n        Yields:\n            All client tokens known to the TokenManager.\n        \"\"\"\n        for token in self.token_to_socket:\n            yield token\n\n    @abstractmethod\n    async def link_token_to_sid(self, token: str, sid: str) -> str | None:\n        \"\"\"Link a token to a session ID.\n\n        Args:\n            token: The client token.\n            sid: The Socket.IO session ID.\n\n        Returns:\n            New token if duplicate detected and new token generated, None otherwise.\n        \"\"\"\n\n    @abstractmethod\n    async def disconnect_token(self, token: str, sid: str) -> None:\n        \"\"\"Clean up token mapping when client disconnects.\n\n        Args:\n            token: The client token.\n            sid: The Socket.IO session ID.\n        \"\"\"\n\n    @classmethod\n    def create(cls) -> TokenManager:\n        \"\"\"Factory method to create appropriate TokenManager implementation.\n\n        Returns:\n            RedisTokenManager if Redis is available, LocalTokenManager otherwise.\n        \"\"\"\n        if prerequisites.check_redis_used():\n            redis_client = prerequisites.get_redis()\n            if redis_client is not None:\n                return RedisTokenManager(redis_client)\n\n        return LocalTokenManager()\n\n    async def disconnect_all(self):\n        \"\"\"Disconnect all tracked tokens when the server is going down.\"\"\"\n        token_sid_pairs: set[tuple[str, str]] = {\n            (token, sr.sid) for token, sr in self.token_to_socket.items()\n        }\n        token_sid_pairs.update(\n            ((token, sid) for sid, token in self.sid_to_token.items())\n        )\n        # Perform the disconnection logic here\n        for token, sid in token_sid_pairs:\n            await self.disconnect_token(token, sid)\n\n\nclass LocalTokenManager(TokenManager):\n    \"\"\"Token manager using local in-memory dictionaries (single worker).\"\"\"\n\n    def __init__(self):\n        \"\"\"Initialize the local token manager.\"\"\"\n        super().__init__()\n\n    async def link_token_to_sid(self, token: str, sid: str) -> str | None:\n        \"\"\"Link a token to a session ID.\n\n        Args:\n            token: The client token.\n            sid: The Socket.IO session ID.\n\n        Returns:\n            New token if duplicate detected and new token generated, None otherwise.\n        \"\"\"\n        # Check if token is already mapped to a different SID (duplicate tab)\n        if (\n            socket_record := self.token_to_socket.get(token)\n        ) is not None and sid != socket_record.sid:\n            new_token = _get_new_token()\n            self.token_to_socket[new_token] = SocketRecord(\n                instance_id=self.instance_id, sid=sid\n            )\n            self.sid_to_token[sid] = new_token\n            return new_token\n\n        # Normal case - link token to SID\n        self.token_to_socket[token] = SocketRecord(\n            instance_id=self.instance_id, sid=sid\n        )\n        self.sid_to_token[sid] = token\n        return None\n\n    async def disconnect_token(self, token: str, sid: str) -> None:\n        \"\"\"Clean up token mapping when client disconnects.\n\n        Args:\n            token: The client token.\n            sid: The Socket.IO session ID.\n        \"\"\"\n        # Clean up both mappings\n        self.token_to_socket.pop(token, None)\n        self.sid_to_token.pop(sid, None)\n\n\nclass RedisTokenManager(LocalTokenManager):\n    \"\"\"Token manager using Redis for distributed multi-worker support.\n\n    Inherits local dict logic from LocalTokenManager and adds Redis layer\n    for cross-worker duplicate detection.\n    \"\"\"\n\n    _token_socket_record_prefix: ClassVar[str] = \"token_manager_socket_record_\"\n\n    def __init__(self, redis: Redis):\n        \"\"\"Initialize the Redis token manager.\n\n        Args:\n            redis: The Redis client instance.\n        \"\"\"\n        # Initialize parent's local dicts\n        super().__init__()\n\n        self.redis = redis\n\n        # Get token expiration from config (default 1 hour)\n        from reflex.config import get_config\n\n        config = get_config()\n        self.token_expiration = config.redis_token_expiration\n\n        # Pub/sub tasks for handling sockets owned by other instances.\n        self._socket_record_task: asyncio.Task | None = None\n        self._lost_and_found_task: asyncio.Task | None = None\n\n    def _get_redis_key(self, token: str) -> str:\n        \"\"\"Get Redis key for token mapping.\n\n        Args:\n            token: The client token.\n\n        Returns:\n            Redis key following Reflex conventions: token_manager_socket_record_{token}\n        \"\"\"\n        return f\"{self._token_socket_record_prefix}{token}\"\n\n    async def enumerate_tokens(self) -> AsyncIterator[str]:\n        \"\"\"Iterate over all tokens in the system.\n\n        Yields:\n            All client tokens known to the RedisTokenManager.\n        \"\"\"\n        cursor = 0\n        while scan_result := await self.redis.scan(\n            cursor=cursor, match=self._get_redis_key(\"*\")\n        ):\n            cursor = int(scan_result[0])\n            for key in scan_result[1]:\n                yield key.decode().replace(self._token_socket_record_prefix, \"\")\n            if not cursor:\n                break\n\n    async def _handle_socket_record_del(\n        self, token: str, expired: bool = False\n    ) -> None:\n        \"\"\"Handle deletion of a socket record from Redis.\n\n        Args:\n            token: The client token whose record was deleted.\n            expired: Whether the deletion was due to expiration.\n        \"\"\"\n        if (\n            socket_record := self.token_to_socket.pop(token, None)\n        ) is not None and socket_record.instance_id == self.instance_id:\n            self.sid_to_token.pop(socket_record.sid, None)\n            if expired:\n                # Keep the record alive as long as this process is alive and not deleted.\n                await self.link_token_to_sid(token, socket_record.sid)\n\n    async def _subscribe_socket_record_updates(self) -> None:\n        \"\"\"Subscribe to Redis keyspace notifications for socket record updates.\"\"\"\n        await StateManagerRedis(\n            state=BaseState, redis=self.redis\n        )._enable_keyspace_notifications()\n        redis_db = self.redis.get_connection_kwargs().get(\"db\", 0)\n\n        async with self.redis.pubsub() as pubsub:\n            await pubsub.psubscribe(\n                f\"__keyspace@{redis_db}__:{self._get_redis_key('*')}\"\n            )\n            async for message in pubsub.listen():\n                if message[\"type\"] == \"pmessage\":\n                    key = message[\"channel\"].split(b\":\", 1)[1].decode()\n                    token = key.replace(self._token_socket_record_prefix, \"\")\n\n                    if token not in self.token_to_socket:\n                        # We don't know about this token, skip\n                        continue\n\n                    event = message[\"data\"].decode()\n                    if event in (\"del\", \"expired\", \"evicted\"):\n                        await self._handle_socket_record_del(\n                            token,\n                            expired=(event == \"expired\"),\n                        )\n                    elif event == \"set\":\n                        await self._get_token_owner(token, refresh=True)\n\n    def _ensure_socket_record_task(self) -> None:\n        \"\"\"Ensure the socket record updates subscriber task is running.\"\"\"\n        ensure_task(\n            owner=self,\n            task_attribute=\"_socket_record_task\",\n            coro_function=self._subscribe_socket_record_updates,\n            suppress_exceptions=[Exception],\n        )\n\n    async def link_token_to_sid(self, token: str, sid: str) -> str | None:\n        \"\"\"Link a token to a session ID with Redis-based duplicate detection.\n\n        Args:\n            token: The client token.\n            sid: The Socket.IO session ID.\n\n        Returns:\n            New token if duplicate detected and new token generated, None otherwise.\n        \"\"\"\n        # Fast local check first (handles reconnections)\n        if (\n            socket_record := self.token_to_socket.get(token)\n        ) is not None and sid == socket_record.sid:\n            return None  # Same token, same SID = reconnection, no Redis check needed\n\n        # Make sure the update subscriber is running\n        self._ensure_socket_record_task()\n\n        # Check Redis for cross-worker duplicates\n        redis_key = self._get_redis_key(token)\n\n        try:\n            token_exists_in_redis = await self.redis.exists(redis_key)\n        except Exception as e:\n            console.error(f\"Redis error checking token existence: {e}\")\n            return await super().link_token_to_sid(token, sid)\n\n        new_token = None\n        if token_exists_in_redis:\n            # Duplicate exists somewhere - generate new token\n            token = new_token = _get_new_token()\n            redis_key = self._get_redis_key(new_token)\n\n        # Store in local dicts\n        socket_record = self.token_to_socket[token] = SocketRecord(\n            instance_id=self.instance_id, sid=sid\n        )\n        self.sid_to_token[sid] = token\n\n        # Store in Redis if possible\n        try:\n            await self.redis.set(\n                redis_key,\n                pickle.dumps(socket_record),\n                ex=self.token_expiration,\n            )\n        except Exception as e:\n            console.error(f\"Redis error storing token: {e}\")\n        # Return the new token if one was generated\n        return new_token\n\n    async def disconnect_token(self, token: str, sid: str) -> None:\n        \"\"\"Clean up token mapping when client disconnects.\n\n        Args:\n            token: The client token.\n            sid: The Socket.IO session ID.\n        \"\"\"\n        # Only clean up if we own it locally (fast ownership check)\n        if (\n            (socket_record := self.token_to_socket.get(token)) is not None\n            and socket_record.sid == sid\n            and socket_record.instance_id == self.instance_id\n        ):\n            # Clean up Redis\n            redis_key = self._get_redis_key(token)\n            try:\n                await self.redis.delete(redis_key)\n            except Exception as e:\n                console.error(f\"Redis error deleting token: {e}\")\n\n            # Clean up local dicts (always do this)\n            await super().disconnect_token(token, sid)\n\n    @staticmethod\n    def _get_lost_and_found_key(instance_id: str) -> str:\n        \"\"\"Get the Redis key for lost and found deltas for an instance.\n\n        Args:\n            instance_id: The instance ID.\n\n        Returns:\n            The Redis key for lost and found deltas.\n        \"\"\"\n        return f\"token_manager_lost_and_found_{instance_id}\"\n\n    async def _subscribe_lost_and_found_updates(\n        self,\n        emit_update: Callable[[StateUpdate, str], Coroutine[None, None, None]],\n    ) -> None:\n        \"\"\"Subscribe to Redis channel notifications for lost and found deltas.\n\n        Args:\n            emit_update: The function to emit state updates.\n        \"\"\"\n        async with self.redis.pubsub() as pubsub:\n            await pubsub.psubscribe(\n                f\"channel:{self._get_lost_and_found_key(self.instance_id)}\"\n            )\n            async for message in pubsub.listen():\n                if message[\"type\"] == \"pmessage\":\n                    record = pickle.loads(message[\"data\"])\n                    await emit_update(record.update, record.token)\n\n    def ensure_lost_and_found_task(\n        self,\n        emit_update: Callable[[StateUpdate, str], Coroutine[None, None, None]],\n    ) -> None:\n        \"\"\"Ensure the lost and found subscriber task is running.\n\n        Args:\n            emit_update: The function to emit state updates.\n        \"\"\"\n        ensure_task(\n            owner=self,\n            task_attribute=\"_lost_and_found_task\",\n            coro_function=self._subscribe_lost_and_found_updates,\n            suppress_exceptions=[Exception],\n            emit_update=emit_update,\n        )\n\n    async def _get_token_owner(self, token: str, refresh: bool = False) -> str | None:\n        \"\"\"Get the instance ID of the owner of a token.\n\n        Args:\n            token: The client token.\n            refresh: Whether to fetch the latest record from Redis.\n\n        Returns:\n            The instance ID of the owner, or None if not found.\n        \"\"\"\n        if (\n            not refresh\n            and (socket_record := self.token_to_socket.get(token)) is not None\n        ):\n            return socket_record.instance_id\n\n        redis_key = self._get_redis_key(token)\n        try:\n            record_pkl = await self.redis.get(redis_key)\n            if record_pkl:\n                socket_record = pickle.loads(record_pkl)\n                self.token_to_socket[token] = socket_record\n                self.sid_to_token[socket_record.sid] = token\n                return socket_record.instance_id\n            console.warn(f\"Redis token owner not found for token {token}\")\n        except Exception as e:\n            console.error(f\"Redis error getting token owner: {e}\")\n        return None\n\n    async def emit_lost_and_found(\n        self,\n        token: str,\n        update: StateUpdate,\n    ) -> bool:\n        \"\"\"Emit a lost and found delta to Redis.\n\n        Args:\n            token: The client token.\n            update: The state update.\n\n        Returns:\n            True if the delta was published, False otherwise.\n        \"\"\"\n        # See where this update belongs\n        owner_instance_id = await self._get_token_owner(token)\n        if owner_instance_id is None:\n            return False\n        record = LostAndFoundRecord(token=token, update=update)\n        try:\n            await self.redis.publish(\n                f\"channel:{self._get_lost_and_found_key(owner_instance_id)}\",\n                pickle.dumps(record),\n            )\n        except Exception as e:\n            console.error(f\"Redis error publishing lost and found delta: {e}\")\n        else:\n            return True\n        return False\n"
  },
  {
    "path": "reflex/utils/types.py",
    "content": "\"\"\"Contains custom types and methods to check types.\"\"\"\n\nfrom __future__ import annotations\n\nimport dataclasses\nimport sys\nimport types\nfrom collections.abc import Callable, Iterable, Mapping, Sequence\nfrom enum import Enum\nfrom functools import cached_property, lru_cache\nfrom importlib.util import find_spec\nfrom types import GenericAlias\nfrom typing import (  # noqa: UP035\n    TYPE_CHECKING,\n    Any,\n    Awaitable,\n    ClassVar,\n    Dict,\n    ForwardRef,\n    List,\n    Literal,\n    MutableMapping,\n    NoReturn,\n    Protocol,\n    Tuple,\n    TypeVar,\n    Union,\n    _eval_type,  # pyright: ignore [reportAttributeAccessIssue]\n    _GenericAlias,  # pyright: ignore [reportAttributeAccessIssue]\n    _SpecialGenericAlias,  # pyright: ignore [reportAttributeAccessIssue]\n    get_args,\n    is_typeddict,\n)\nfrom typing import get_origin as get_origin_og\nfrom typing import get_type_hints as get_type_hints_og\n\nfrom typing_extensions import Self as Self\nfrom typing_extensions import override as override\n\nimport reflex\nfrom reflex import constants\nfrom reflex.base import Base\nfrom reflex.components.core.breakpoints import Breakpoints\nfrom reflex.utils import console\n\n# Potential GenericAlias types for isinstance checks.\nGenericAliasTypes = (_GenericAlias, GenericAlias, _SpecialGenericAlias)\n\n# Potential Union types for isinstance checks.\nUnionTypes = (Union, types.UnionType)\n\n# Union of generic types.\nGenericType = type | _GenericAlias\n\n# Valid state var types.\nPrimitiveTypes = (int, float, bool, str, list, dict, set, tuple)\nStateVarTypes = (*PrimitiveTypes, Base, type(None))\n\nif TYPE_CHECKING:\n    from reflex.state import BaseState\n    from reflex.vars.base import Var\n\nVAR1 = TypeVar(\"VAR1\", bound=\"Var\")\nVAR2 = TypeVar(\"VAR2\", bound=\"Var\")\nVAR3 = TypeVar(\"VAR3\", bound=\"Var\")\nVAR4 = TypeVar(\"VAR4\", bound=\"Var\")\nVAR5 = TypeVar(\"VAR5\", bound=\"Var\")\nVAR6 = TypeVar(\"VAR6\", bound=\"Var\")\nVAR7 = TypeVar(\"VAR7\", bound=\"Var\")\n\n\nclass _ArgsSpec0(Protocol):\n    def __call__(self) -> Sequence[Var]: ...\n\n\nclass _ArgsSpec1(Protocol):\n    def __call__(self, var1: VAR1, /) -> Sequence[Var]: ...  # pyright: ignore [reportInvalidTypeVarUse]\n\n\nclass _ArgsSpec2(Protocol):\n    def __call__(self, var1: VAR1, var2: VAR2, /) -> Sequence[Var]: ...  # pyright: ignore [reportInvalidTypeVarUse]\n\n\nclass _ArgsSpec3(Protocol):\n    def __call__(self, var1: VAR1, var2: VAR2, var3: VAR3, /) -> Sequence[Var]: ...  # pyright: ignore [reportInvalidTypeVarUse]\n\n\nclass _ArgsSpec4(Protocol):\n    def __call__(\n        self,\n        var1: VAR1,  # pyright: ignore [reportInvalidTypeVarUse]\n        var2: VAR2,  # pyright: ignore [reportInvalidTypeVarUse]\n        var3: VAR3,  # pyright: ignore [reportInvalidTypeVarUse]\n        var4: VAR4,  # pyright: ignore [reportInvalidTypeVarUse]\n        /,\n    ) -> Sequence[Var]: ...\n\n\nclass _ArgsSpec5(Protocol):\n    def __call__(\n        self,\n        var1: VAR1,  # pyright: ignore [reportInvalidTypeVarUse]\n        var2: VAR2,  # pyright: ignore [reportInvalidTypeVarUse]\n        var3: VAR3,  # pyright: ignore [reportInvalidTypeVarUse]\n        var4: VAR4,  # pyright: ignore [reportInvalidTypeVarUse]\n        var5: VAR5,  # pyright: ignore [reportInvalidTypeVarUse]\n        /,\n    ) -> Sequence[Var]: ...\n\n\nclass _ArgsSpec6(Protocol):\n    def __call__(\n        self,\n        var1: VAR1,  # pyright: ignore [reportInvalidTypeVarUse]\n        var2: VAR2,  # pyright: ignore [reportInvalidTypeVarUse]\n        var3: VAR3,  # pyright: ignore [reportInvalidTypeVarUse]\n        var4: VAR4,  # pyright: ignore [reportInvalidTypeVarUse]\n        var5: VAR5,  # pyright: ignore [reportInvalidTypeVarUse]\n        var6: VAR6,  # pyright: ignore [reportInvalidTypeVarUse]\n        /,\n    ) -> Sequence[Var]: ...\n\n\nclass _ArgsSpec7(Protocol):\n    def __call__(\n        self,\n        var1: VAR1,  # pyright: ignore [reportInvalidTypeVarUse]\n        var2: VAR2,  # pyright: ignore [reportInvalidTypeVarUse]\n        var3: VAR3,  # pyright: ignore [reportInvalidTypeVarUse]\n        var4: VAR4,  # pyright: ignore [reportInvalidTypeVarUse]\n        var5: VAR5,  # pyright: ignore [reportInvalidTypeVarUse]\n        var6: VAR6,  # pyright: ignore [reportInvalidTypeVarUse]\n        var7: VAR7,  # pyright: ignore [reportInvalidTypeVarUse]\n        /,\n    ) -> Sequence[Var]: ...\n\n\nArgsSpec = (\n    _ArgsSpec0\n    | _ArgsSpec1\n    | _ArgsSpec2\n    | _ArgsSpec3\n    | _ArgsSpec4\n    | _ArgsSpec5\n    | _ArgsSpec6\n    | _ArgsSpec7\n)\n\nScope = MutableMapping[str, Any]\nMessage = MutableMapping[str, Any]\n\nReceive = Callable[[], Awaitable[Message]]\nSend = Callable[[Message], Awaitable[None]]\n\nASGIApp = Callable[[Scope, Receive, Send], Awaitable[None]]\n\nPrimitiveToAnnotation = {\n    list: List,  # noqa: UP006\n    tuple: Tuple,  # noqa: UP006\n    dict: Dict,  # noqa: UP006\n}\n\nRESERVED_BACKEND_VAR_NAMES = {\"_abc_impl\", \"_backend_vars\", \"_was_touched\", \"_mixin\"}\n\n\nclass Unset:\n    \"\"\"A class to represent an unset value.\n\n    This is used to differentiate between a value that is not set and a value that is set to None.\n    \"\"\"\n\n    def __repr__(self) -> str:\n        \"\"\"Return the string representation of the class.\n\n        Returns:\n            The string representation of the class.\n        \"\"\"\n        return \"Unset\"\n\n    def __bool__(self) -> bool:\n        \"\"\"Return False when the class is used in a boolean context.\n\n        Returns:\n            False\n        \"\"\"\n        return False\n\n\n@lru_cache\ndef _get_origin_cached(tp: Any):\n    return get_origin_og(tp)\n\n\ndef get_origin(tp: Any):\n    \"\"\"Get the origin of a class.\n\n    Args:\n        tp: The class to get the origin of.\n\n    Returns:\n        The origin of the class.\n    \"\"\"\n    return (\n        origin\n        if (origin := getattr(tp, \"__origin__\", None)) is not None\n        else _get_origin_cached(tp)\n    )\n\n\n@lru_cache\ndef is_generic_alias(cls: GenericType) -> bool:\n    \"\"\"Check whether the class is a generic alias.\n\n    Args:\n        cls: The class to check.\n\n    Returns:\n        Whether the class is a generic alias.\n    \"\"\"\n    return isinstance(cls, GenericAliasTypes)\n\n\n@lru_cache\ndef get_type_hints(obj: Any) -> dict[str, Any]:\n    \"\"\"Get the type hints of a class.\n\n    Args:\n        obj: The class to get the type hints of.\n\n    Returns:\n        The type hints of the class.\n    \"\"\"\n    return get_type_hints_og(obj)\n\n\ndef _unionize(args: list[GenericType]) -> GenericType:\n    if not args:\n        return Any  # pyright: ignore [reportReturnType]\n    if len(args) == 1:\n        return args[0]\n    return Union[tuple(args)]  # noqa: UP007\n\n\ndef unionize(*args: GenericType) -> type:\n    \"\"\"Unionize the types.\n\n    Args:\n        args: The types to unionize.\n\n    Returns:\n        The unionized types.\n    \"\"\"\n    return _unionize([arg for arg in args if arg is not NoReturn])\n\n\ndef is_none(cls: GenericType) -> bool:\n    \"\"\"Check if a class is None.\n\n    Args:\n        cls: The class to check.\n\n    Returns:\n        Whether the class is None.\n    \"\"\"\n    return cls is type(None) or cls is None\n\n\ndef is_union(cls: GenericType) -> bool:\n    \"\"\"Check if a class is a Union.\n\n    Args:\n        cls: The class to check.\n\n    Returns:\n        Whether the class is a Union.\n    \"\"\"\n    origin = getattr(cls, \"__origin__\", None)\n    if origin is Union:\n        return True\n    return origin is None and isinstance(cls, types.UnionType)\n\n\ndef is_literal(cls: GenericType) -> bool:\n    \"\"\"Check if a class is a Literal.\n\n    Args:\n        cls: The class to check.\n\n    Returns:\n        Whether the class is a literal.\n    \"\"\"\n    return getattr(cls, \"__origin__\", None) is Literal\n\n\n@lru_cache\ndef has_args(cls: type) -> bool:\n    \"\"\"Check if the class has generic parameters.\n\n    Args:\n        cls: The class to check.\n\n    Returns:\n        Whether the class has generic\n    \"\"\"\n    if get_args(cls):\n        return True\n\n    # Check if the class inherits from a generic class (using __orig_bases__)\n    if hasattr(cls, \"__orig_bases__\"):\n        for base in cls.__orig_bases__:\n            if get_args(base):\n                return True\n\n    return False\n\n\ndef is_optional(cls: GenericType) -> bool:\n    \"\"\"Check if a class is an Optional.\n\n    Args:\n        cls: The class to check.\n\n    Returns:\n        Whether the class is an Optional.\n    \"\"\"\n    return (\n        cls is None\n        or cls is type(None)\n        or (is_union(cls) and type(None) in get_args(cls))\n    )\n\n\ndef is_classvar(a_type: Any) -> bool:\n    \"\"\"Check if a type is a ClassVar.\n\n    Args:\n        a_type: The type to check.\n\n    Returns:\n        Whether the type is a ClassVar.\n    \"\"\"\n    return (\n        a_type is ClassVar\n        or (type(a_type) is _GenericAlias and a_type.__origin__ is ClassVar)\n        or (\n            type(a_type) is ForwardRef and a_type.__forward_arg__.startswith(\"ClassVar\")\n        )\n    )\n\n\ndef value_inside_optional(cls: GenericType) -> GenericType:\n    \"\"\"Get the value inside an Optional type or the original type.\n\n    Args:\n        cls: The class to check.\n\n    Returns:\n        The value inside the Optional type or the original type.\n    \"\"\"\n    if is_union(cls) and len(args := get_args(cls)) >= 2 and type(None) in args:\n        if len(args) == 2:\n            return args[0] if args[1] is type(None) else args[1]\n        return unionize(*[arg for arg in args if arg is not type(None)])\n    return cls\n\n\ndef get_field_type(cls: GenericType, field_name: str) -> GenericType | None:\n    \"\"\"Get the type of a field in a class.\n\n    Args:\n        cls: The class to check.\n        field_name: The name of the field to check.\n\n    Returns:\n        The type of the field, if it exists, else None.\n    \"\"\"\n    if (fields := getattr(cls, \"_fields\", None)) is not None and field_name in fields:\n        return fields[field_name].annotated_type\n    if (\n        hasattr(cls, \"__fields__\")\n        and field_name in cls.__fields__\n        and hasattr(cls.__fields__[field_name], \"annotation\")\n        and not isinstance(cls.__fields__[field_name].annotation, (str, ForwardRef))\n    ):\n        return cls.__fields__[field_name].annotation\n    type_hints = get_type_hints(cls)\n    return type_hints.get(field_name, None)\n\n\nPROPERTY_CLASSES = (property,)\nif find_spec(\"sqlalchemy\") and find_spec(\"sqlalchemy.ext\"):\n    from sqlalchemy.ext.hybrid import hybrid_property\n\n    PROPERTY_CLASSES += (hybrid_property,)\n\n\ndef get_property_hint(attr: Any | None) -> GenericType | None:\n    \"\"\"Check if an attribute is a property and return its type hint.\n\n    Args:\n        attr: The descriptor to check.\n\n    Returns:\n        The type hint of the property, if it is a property, else None.\n    \"\"\"\n    if not isinstance(attr, PROPERTY_CLASSES):\n        return None\n    hints = get_type_hints(attr.fget)\n    return hints.get(\"return\", None)\n\n\ndef get_attribute_access_type(cls: GenericType, name: str) -> GenericType | None:\n    \"\"\"Check if an attribute can be accessed on the cls and return its type.\n\n    Supports pydantic models, unions, and annotated attributes on rx.Model.\n\n    Args:\n        cls: The class to check.\n        name: The name of the attribute to check.\n\n    Returns:\n        The type of the attribute, if accessible, or None\n    \"\"\"\n    try:\n        attr = getattr(cls, name, None)\n    except NotImplementedError:\n        attr = None\n\n    if hint := get_property_hint(attr):\n        return hint\n\n    if hasattr(cls, \"__fields__\") and name in cls.__fields__:\n        # pydantic models\n        return get_field_type(cls, name)\n    if find_spec(\"sqlalchemy\") and find_spec(\"sqlalchemy.orm\"):\n        import sqlalchemy\n        from sqlalchemy.ext.associationproxy import AssociationProxyInstance\n        from sqlalchemy.orm import (\n            DeclarativeBase,\n            Mapped,\n            QueryableAttribute,\n            Relationship,\n        )\n\n        from reflex.model import Model\n\n        if find_spec(\"sqlmodel\"):\n            from sqlmodel import SQLModel\n\n            sqlmodel_types = (Model, SQLModel)\n        else:\n            sqlmodel_types = (Model,)\n\n        if isinstance(cls, type) and issubclass(cls, DeclarativeBase):\n            insp = sqlalchemy.inspect(cls)\n            if name in insp.columns:\n                # check for list types\n                column = insp.columns[name]\n                column_type = column.type\n                try:\n                    type_ = insp.columns[name].type.python_type\n                except NotImplementedError:\n                    type_ = None\n                if type_ is not None:\n                    if hasattr(column_type, \"item_type\"):\n                        try:\n                            item_type = column_type.item_type.python_type  # pyright: ignore [reportAttributeAccessIssue]\n                        except NotImplementedError:\n                            item_type = None\n                        if item_type is not None:\n                            if type_ in PrimitiveToAnnotation:\n                                type_ = PrimitiveToAnnotation[type_]\n                            type_ = type_[item_type]  # pyright: ignore [reportIndexIssue]\n                    if hasattr(column, \"nullable\") and column.nullable:\n                        type_ = type_ | None\n                    return type_\n            if name in insp.all_orm_descriptors:\n                descriptor = insp.all_orm_descriptors[name]\n                if hint := get_property_hint(descriptor):\n                    return hint\n                if isinstance(descriptor, QueryableAttribute):\n                    prop = descriptor.property\n                    if isinstance(prop, Relationship):\n                        type_ = prop.mapper.class_\n                        # TODO: check for nullable?\n                        return list[type_] if prop.uselist else type_ | None\n                if isinstance(attr, AssociationProxyInstance):\n                    return list[\n                        get_attribute_access_type(\n                            attr.target_class,\n                            attr.remote_attr.key,  # pyright: ignore [reportAttributeAccessIssue]\n                        )\n                    ]\n        elif (\n            isinstance(cls, type)\n            and not is_generic_alias(cls)\n            and issubclass(cls, sqlmodel_types)\n        ):\n            # Check in the annotations directly (for sqlmodel.Relationship)\n            hints = get_type_hints(cls)  # pyright: ignore [reportArgumentType]\n            if name in hints:\n                type_ = hints[name]\n                type_origin = get_origin(type_)\n                if isinstance(type_origin, type) and issubclass(type_origin, Mapped):\n                    return get_args(type_)[0]  # SQLAlchemy v2\n                if find_spec(\"pydantic\"):\n                    from pydantic.v1.fields import ModelField\n\n                    if isinstance(type_, ModelField):\n                        return type_.type_  # SQLAlchemy v1.4\n                return type_\n    if is_union(cls):\n        # Check in each arg of the annotation.\n        return unionize(\n            *(get_attribute_access_type(arg, name) for arg in get_args(cls))\n        )\n    if isinstance(cls, type):\n        # Bare class\n        exceptions = NameError\n        try:\n            hints = get_type_hints(cls)  # pyright: ignore [reportArgumentType]\n            if name in hints:\n                return hints[name]\n        except exceptions as e:\n            console.warn(f\"Failed to resolve ForwardRefs for {cls}.{name} due to {e}\")\n    return None  # Attribute is not accessible.\n\n\n@lru_cache\ndef get_base_class(cls: GenericType) -> type:\n    \"\"\"Get the base class of a class.\n\n    Args:\n        cls: The class.\n\n    Returns:\n        The base class of the class.\n\n    Raises:\n        TypeError: If a literal has multiple types.\n    \"\"\"\n    if is_literal(cls):\n        # only literals of the same type are supported.\n        arg_type = type(get_args(cls)[0])\n        if not all(type(arg) is arg_type for arg in get_args(cls)):\n            msg = \"only literals of the same type are supported\"\n            raise TypeError(msg)\n        return type(get_args(cls)[0])\n\n    if is_union(cls):\n        return tuple(get_base_class(arg) for arg in get_args(cls))  # pyright: ignore [reportReturnType]\n\n    return get_base_class(cls.__origin__) if is_generic_alias(cls) else cls\n\n\ndef _breakpoints_satisfies_typing(cls_check: GenericType, instance: Any) -> bool:\n    \"\"\"Check if the breakpoints instance satisfies the typing.\n\n    Args:\n        cls_check: The class to check against.\n        instance: The instance to check.\n\n    Returns:\n        Whether the breakpoints instance satisfies the typing.\n    \"\"\"\n    cls_check_base = get_base_class(cls_check)\n\n    if cls_check_base == Breakpoints:\n        _, expected_type = get_args(cls_check)\n        if is_literal(expected_type):\n            for value in instance.values():\n                if not isinstance(value, str) or value not in get_args(expected_type):\n                    return False\n        return True\n    if isinstance(cls_check_base, tuple):\n        # union type, so check all types\n        return any(\n            _breakpoints_satisfies_typing(type_to_check, instance)\n            for type_to_check in get_args(cls_check)\n        )\n    if cls_check_base == reflex.vars.Var and \"__args__\" in cls_check.__dict__:\n        return _breakpoints_satisfies_typing(get_args(cls_check)[0], instance)\n\n    return False\n\n\ndef _issubclass(cls: GenericType, cls_check: GenericType, instance: Any = None) -> bool:\n    \"\"\"Check if a class is a subclass of another class.\n\n    Args:\n        cls: The class to check.\n        cls_check: The class to check against.\n        instance: An instance of cls to aid in checking generics.\n\n    Returns:\n        Whether the class is a subclass of the other class.\n\n    Raises:\n        TypeError: If the base class is not valid for issubclass.\n    \"\"\"\n    # Special check for Any.\n    if cls_check == Any:\n        return True\n    if cls in [Any, Callable, None]:\n        return False\n\n    # Get the base classes.\n    cls_base = get_base_class(cls)\n    cls_check_base = get_base_class(cls_check)\n\n    # The class we're checking should not be a union.\n    if isinstance(cls_base, tuple):\n        return False\n\n    # Check that fields of breakpoints match the expected values.\n    if isinstance(instance, Breakpoints):\n        return _breakpoints_satisfies_typing(cls_check, instance)\n\n    if isinstance(cls_check_base, tuple):\n        cls_check_base = tuple(\n            cls_check_one if not is_typeddict(cls_check_one) else dict\n            for cls_check_one in cls_check_base\n        )\n    if is_typeddict(cls_check_base):\n        cls_check_base = dict\n\n    # Check if the types match.\n    try:\n        return cls_check_base == Any or issubclass(cls_base, cls_check_base)\n    except TypeError as te:\n        # These errors typically arise from bad annotations and are hard to\n        # debug without knowing the type that we tried to compare.\n        msg = f\"Invalid type for issubclass: {cls_base}\"\n        raise TypeError(msg) from te\n\n\ndef does_obj_satisfy_typed_dict(\n    obj: Any,\n    cls: GenericType,\n    *,\n    nested: int = 0,\n    treat_var_as_type: bool = True,\n    treat_mutable_obj_as_immutable: bool = False,\n) -> bool:\n    \"\"\"Check if an object satisfies a typed dict.\n\n    Args:\n        obj: The object to check.\n        cls: The typed dict to check against.\n        nested: How many levels deep to check.\n        treat_var_as_type: Whether to treat Var as the type it represents, i.e. _var_type.\n        treat_mutable_obj_as_immutable: Whether to treat mutable objects as immutable. Useful if a component declares a mutable object as a prop, but the value is not expected to change.\n\n    Returns:\n        Whether the object satisfies the typed dict.\n    \"\"\"\n    if not isinstance(obj, Mapping):\n        return False\n\n    key_names_to_values = get_type_hints(cls)\n    required_keys: frozenset[str] = getattr(cls, \"__required_keys__\", frozenset())\n    is_closed = getattr(cls, \"__closed__\", False)\n    extra_items_type = getattr(cls, \"__extra_items__\", Any)\n\n    for key, value in obj.items():\n        if is_closed and key not in key_names_to_values:\n            return False\n        if nested:\n            if key in key_names_to_values:\n                expected_type = key_names_to_values[key]\n                if not _isinstance(\n                    value,\n                    expected_type,\n                    nested=nested - 1,\n                    treat_var_as_type=treat_var_as_type,\n                    treat_mutable_obj_as_immutable=treat_mutable_obj_as_immutable,\n                ):\n                    return False\n            else:\n                if not _isinstance(\n                    value,\n                    extra_items_type,\n                    nested=nested - 1,\n                    treat_var_as_type=treat_var_as_type,\n                    treat_mutable_obj_as_immutable=treat_mutable_obj_as_immutable,\n                ):\n                    return False\n\n    # required keys are all present\n    return required_keys.issubset(frozenset(obj))\n\n\ndef _isinstance(\n    obj: Any,\n    cls: GenericType,\n    *,\n    nested: int = 0,\n    treat_var_as_type: bool = True,\n    treat_mutable_obj_as_immutable: bool = False,\n) -> bool:\n    \"\"\"Check if an object is an instance of a class.\n\n    Args:\n        obj: The object to check.\n        cls: The class to check against.\n        nested: How many levels deep to check.\n        treat_var_as_type: Whether to treat Var as the type it represents, i.e. _var_type.\n        treat_mutable_obj_as_immutable: Whether to treat mutable objects as immutable. Useful if a component declares a mutable object as a prop, but the value is not expected to change.\n\n    Returns:\n        Whether the object is an instance of the class.\n    \"\"\"\n    if cls is Any:\n        return True\n\n    from reflex.vars import LiteralVar, Var\n\n    if cls is Var:\n        return isinstance(obj, Var)\n    if isinstance(obj, LiteralVar):\n        return treat_var_as_type and _isinstance(\n            obj._var_value, cls, nested=nested, treat_var_as_type=True\n        )\n    if isinstance(obj, Var):\n        return treat_var_as_type and typehint_issubclass(\n            obj._var_type,\n            cls,\n            treat_mutable_superclasss_as_immutable=treat_mutable_obj_as_immutable,\n            treat_literals_as_union_of_types=True,\n            treat_any_as_subtype_of_everything=True,\n        )\n\n    if cls is None or cls is type(None):\n        return obj is None\n\n    if cls is not None and is_union(cls):\n        return any(\n            _isinstance(obj, arg, nested=nested, treat_var_as_type=treat_var_as_type)\n            for arg in get_args(cls)\n        )\n\n    if is_literal(cls):\n        return obj in get_args(cls)\n\n    origin = get_origin(cls)\n\n    if origin is None:\n        # cls is a typed dict\n        if is_typeddict(cls):\n            if nested:\n                return does_obj_satisfy_typed_dict(\n                    obj,\n                    cls,\n                    nested=nested - 1,\n                    treat_var_as_type=treat_var_as_type,\n                    treat_mutable_obj_as_immutable=treat_mutable_obj_as_immutable,\n                )\n            return isinstance(obj, dict)\n\n        # cls is a float\n        if cls is float:\n            return isinstance(obj, (float, int))\n\n        # cls is a simple class\n        return isinstance(obj, cls)\n\n    args = get_args(cls)\n\n    if not args:\n        if treat_mutable_obj_as_immutable:\n            if origin is dict:\n                origin = Mapping\n            elif origin is list or origin is set:\n                origin = Sequence\n        # cls is a simple generic class\n        return isinstance(obj, origin)\n\n    if origin is Var and args:\n        # cls is a Var\n        return _isinstance(\n            obj,\n            args[0],\n            nested=nested,\n            treat_var_as_type=treat_var_as_type,\n            treat_mutable_obj_as_immutable=treat_mutable_obj_as_immutable,\n        )\n\n    if nested > 0 and args:\n        if origin is list:\n            expected_class = Sequence if treat_mutable_obj_as_immutable else list\n            return isinstance(obj, expected_class) and all(\n                _isinstance(\n                    item,\n                    args[0],\n                    nested=nested - 1,\n                    treat_var_as_type=treat_var_as_type,\n                )\n                for item in obj\n            )\n        if origin is tuple:\n            if args[-1] is Ellipsis:\n                return isinstance(obj, tuple) and all(\n                    _isinstance(\n                        item,\n                        args[0],\n                        nested=nested - 1,\n                        treat_var_as_type=treat_var_as_type,\n                    )\n                    for item in obj\n                )\n            return (\n                isinstance(obj, tuple)\n                and len(obj) == len(args)\n                and all(\n                    _isinstance(\n                        item,\n                        arg,\n                        nested=nested - 1,\n                        treat_var_as_type=treat_var_as_type,\n                    )\n                    for item, arg in zip(obj, args, strict=True)\n                )\n            )\n        if origin in (dict, Mapping, Breakpoints):\n            expected_class = (\n                dict\n                if origin is dict and not treat_mutable_obj_as_immutable\n                else Mapping\n            )\n            return isinstance(obj, expected_class) and all(\n                _isinstance(\n                    key, args[0], nested=nested - 1, treat_var_as_type=treat_var_as_type\n                )\n                and _isinstance(\n                    value,\n                    args[1],\n                    nested=nested - 1,\n                    treat_var_as_type=treat_var_as_type,\n                )\n                for key, value in obj.items()\n            )\n        if origin is set:\n            expected_class = Sequence if treat_mutable_obj_as_immutable else set\n            return isinstance(obj, expected_class) and all(\n                _isinstance(\n                    item,\n                    args[0],\n                    nested=nested - 1,\n                    treat_var_as_type=treat_var_as_type,\n                )\n                for item in obj\n            )\n\n    if args:\n        from reflex.vars import Field\n\n        if origin is Field:\n            return _isinstance(\n                obj, args[0], nested=nested, treat_var_as_type=treat_var_as_type\n            )\n\n    return isinstance(obj, get_base_class(cls))\n\n\ndef is_dataframe(value: type) -> bool:\n    \"\"\"Check if the given value is a dataframe.\n\n    Args:\n        value: The value to check.\n\n    Returns:\n        Whether the value is a dataframe.\n    \"\"\"\n    if is_generic_alias(value) or value == Any:\n        return False\n    return value.__name__ == \"DataFrame\"\n\n\ndef is_valid_var_type(type_: type) -> bool:\n    \"\"\"Check if the given type is a valid prop type.\n\n    Args:\n        type_: The type to check.\n\n    Returns:\n        Whether the type is a valid prop type.\n    \"\"\"\n    from reflex.utils import serializers\n\n    if is_union(type_):\n        return all(is_valid_var_type(arg) for arg in get_args(type_))\n\n    if is_literal(type_):\n        types = {type(value) for value in get_args(type_)}\n        return all(is_valid_var_type(type_) for type_ in types)\n\n    type_ = origin if (origin := get_origin(type_)) is not None else type_\n\n    return (\n        issubclass(type_, StateVarTypes)\n        or serializers.has_serializer(type_)\n        or dataclasses.is_dataclass(type_)\n    )\n\n\ndef is_backend_base_variable(name: str, cls: type[BaseState]) -> bool:\n    \"\"\"Check if this variable name correspond to a backend variable.\n\n    Args:\n        name: The name of the variable to check\n        cls: The class of the variable to check (must be a BaseState subclass)\n\n    Returns:\n        bool: The result of the check\n    \"\"\"\n    if name in RESERVED_BACKEND_VAR_NAMES:\n        return False\n\n    if not name.startswith(\"_\"):\n        return False\n\n    if name.startswith(\"__\"):\n        return False\n\n    if name.startswith(f\"_{cls.__name__}__\"):\n        return False\n\n    hints = cls._get_type_hints()\n    if name in hints:\n        hint = get_origin(hints[name])\n        if hint == ClassVar:\n            return False\n\n    if name in cls.inherited_backend_vars:\n        return False\n\n    from reflex.vars.base import is_computed_var\n\n    if name in cls.__dict__:\n        value = cls.__dict__[name]\n        if type(value) is classmethod:\n            return False\n        if callable(value):\n            return False\n\n        if isinstance(\n            value,\n            (\n                types.FunctionType,\n                property,\n                cached_property,\n            ),\n        ) or is_computed_var(value):\n            return False\n\n    return True\n\n\ndef check_type_in_allowed_types(value_type: type, allowed_types: Iterable) -> bool:\n    \"\"\"Check that a value type is found in a list of allowed types.\n\n    Args:\n        value_type: Type of value.\n        allowed_types: Iterable of allowed types.\n\n    Returns:\n        If the type is found in the allowed types.\n    \"\"\"\n    return get_base_class(value_type) in allowed_types\n\n\ndef check_prop_in_allowed_types(prop: Any, allowed_types: Iterable) -> bool:\n    \"\"\"Check that a prop value is in a list of allowed types.\n    Does the check in a way that works regardless if it's a raw value or a state Var.\n\n    Args:\n        prop: The prop to check.\n        allowed_types: The list of allowed types.\n\n    Returns:\n        If the prop type match one of the allowed_types.\n    \"\"\"\n    from reflex.vars import Var\n\n    type_ = prop._var_type if isinstance(prop, Var) else type(prop)\n    return type_ in allowed_types\n\n\ndef is_encoded_fstring(value: Any) -> bool:\n    \"\"\"Check if a value is an encoded Var f-string.\n\n    Args:\n        value: The value string to check.\n\n    Returns:\n        Whether the value is an f-string\n    \"\"\"\n    return isinstance(value, str) and constants.REFLEX_VAR_OPENING_TAG in value\n\n\ndef validate_literal(key: str, value: Any, expected_type: type, comp_name: str):\n    \"\"\"Check that a value is a valid literal.\n\n    Args:\n        key: The prop name.\n        value: The prop value to validate.\n        expected_type: The expected type(literal type).\n        comp_name: Name of the component.\n\n    Raises:\n        ValueError: When the value is not a valid literal.\n    \"\"\"\n    from reflex.vars import Var\n\n    if (\n        is_literal(expected_type)\n        and not isinstance(value, Var)  # validating vars is not supported yet.\n        and not is_encoded_fstring(value)  # f-strings are not supported.\n        and value not in expected_type.__args__\n    ):\n        allowed_values = expected_type.__args__\n        if value not in allowed_values:\n            allowed_value_str = \",\".join([\n                str(v) if not isinstance(v, str) else f\"'{v}'\" for v in allowed_values\n            ])\n            value_str = f\"'{value}'\" if isinstance(value, str) else value\n            msg = f\"prop value for {key!s} of the `{comp_name}` component should be one of the following: {allowed_value_str}. Got {value_str} instead\"\n            raise ValueError(msg)\n\n\ndef safe_issubclass(cls: Any, cls_check: Any | tuple[Any, ...]):\n    \"\"\"Check if a class is a subclass of another class. Returns False if internal error occurs.\n\n    Args:\n        cls: The class to check.\n        cls_check: The class to check against.\n\n    Returns:\n        Whether the class is a subclass of the other class.\n    \"\"\"\n    try:\n        return issubclass(cls, cls_check)\n    except TypeError:\n        return False\n\n\ndef typehint_issubclass(\n    possible_subclass: Any,\n    possible_superclass: Any,\n    *,\n    treat_mutable_superclasss_as_immutable: bool = False,\n    treat_literals_as_union_of_types: bool = True,\n    treat_any_as_subtype_of_everything: bool = False,\n) -> bool:\n    \"\"\"Check if a type hint is a subclass of another type hint.\n\n    Args:\n        possible_subclass: The type hint to check.\n        possible_superclass: The type hint to check against.\n        treat_mutable_superclasss_as_immutable: Whether to treat target classes as immutable.\n        treat_literals_as_union_of_types: Whether to treat literals as a union of their types.\n        treat_any_as_subtype_of_everything: Whether to treat Any as a subtype of everything. This is the default behavior in Python.\n\n    Returns:\n        Whether the type hint is a subclass of the other type hint.\n    \"\"\"\n    if possible_subclass is possible_superclass or possible_superclass is Any:\n        return True\n    if possible_subclass is Any:\n        return treat_any_as_subtype_of_everything\n    if possible_subclass is NoReturn:\n        return True\n\n    provided_type_origin = get_origin(possible_subclass)\n    accepted_type_origin = get_origin(possible_superclass)\n\n    if provided_type_origin is None and accepted_type_origin is None:\n        # In this case, we are dealing with a non-generic type, so we can use issubclass\n        return issubclass(possible_subclass, possible_superclass)\n\n    if treat_literals_as_union_of_types and is_literal(possible_superclass):\n        args = get_args(possible_superclass)\n        return any(\n            typehint_issubclass(\n                possible_subclass,\n                type(arg),\n                treat_mutable_superclasss_as_immutable=treat_mutable_superclasss_as_immutable,\n                treat_literals_as_union_of_types=treat_literals_as_union_of_types,\n                treat_any_as_subtype_of_everything=treat_any_as_subtype_of_everything,\n            )\n            for arg in args\n        )\n\n    if is_literal(possible_subclass):\n        args = get_args(possible_subclass)\n        return all(\n            _isinstance(\n                arg,\n                possible_superclass,\n                treat_mutable_obj_as_immutable=treat_mutable_superclasss_as_immutable,\n                nested=2,\n            )\n            for arg in args\n        )\n\n    provided_type_origin = (\n        Union if provided_type_origin is types.UnionType else provided_type_origin\n    )\n    accepted_type_origin = (\n        Union if accepted_type_origin is types.UnionType else accepted_type_origin\n    )\n\n    # Get type arguments (e.g., [float, int] for dict[float, int])\n    provided_args = get_args(possible_subclass)\n    accepted_args = get_args(possible_superclass)\n\n    if accepted_type_origin is Union:\n        if provided_type_origin is not Union:\n            return any(\n                typehint_issubclass(\n                    possible_subclass,\n                    accepted_arg,\n                    treat_mutable_superclasss_as_immutable=treat_mutable_superclasss_as_immutable,\n                    treat_literals_as_union_of_types=treat_literals_as_union_of_types,\n                    treat_any_as_subtype_of_everything=treat_any_as_subtype_of_everything,\n                )\n                for accepted_arg in accepted_args\n            )\n        return all(\n            any(\n                typehint_issubclass(\n                    provided_arg,\n                    accepted_arg,\n                    treat_mutable_superclasss_as_immutable=treat_mutable_superclasss_as_immutable,\n                    treat_literals_as_union_of_types=treat_literals_as_union_of_types,\n                    treat_any_as_subtype_of_everything=treat_any_as_subtype_of_everything,\n                )\n                for accepted_arg in accepted_args\n            )\n            for provided_arg in provided_args\n        )\n    if provided_type_origin is Union:\n        return all(\n            typehint_issubclass(\n                provided_arg,\n                possible_superclass,\n                treat_mutable_superclasss_as_immutable=treat_mutable_superclasss_as_immutable,\n                treat_literals_as_union_of_types=treat_literals_as_union_of_types,\n                treat_any_as_subtype_of_everything=treat_any_as_subtype_of_everything,\n            )\n            for provided_arg in provided_args\n        )\n\n    provided_type_origin = provided_type_origin or possible_subclass\n    accepted_type_origin = accepted_type_origin or possible_superclass\n\n    if treat_mutable_superclasss_as_immutable:\n        if accepted_type_origin is dict:\n            accepted_type_origin = Mapping\n        elif accepted_type_origin is list or accepted_type_origin is set:\n            accepted_type_origin = Sequence\n\n    # Check if the origin of both types is the same (e.g., list for list[int])\n    if not safe_issubclass(\n        provided_type_origin or possible_subclass,\n        accepted_type_origin or possible_superclass,\n    ):\n        return False\n\n    # Ensure all specific types are compatible with accepted types\n    # Note this is not necessarily correct, as it doesn't check against contravariance and covariance\n    # It also ignores when the length of the arguments is different\n    return all(\n        typehint_issubclass(\n            provided_arg,\n            accepted_arg,\n            treat_mutable_superclasss_as_immutable=treat_mutable_superclasss_as_immutable,\n            treat_literals_as_union_of_types=treat_literals_as_union_of_types,\n            treat_any_as_subtype_of_everything=treat_any_as_subtype_of_everything,\n        )\n        for provided_arg, accepted_arg in zip(\n            provided_args, accepted_args, strict=False\n        )\n        if accepted_arg is not Any\n    )\n\n\ndef resolve_annotations(\n    raw_annotations: Mapping[str, type[Any]], module_name: str | None\n) -> dict[str, type[Any]]:\n    \"\"\"Partially taken from typing.get_type_hints.\n\n    Resolve string or ForwardRef annotations into type objects if possible.\n\n    Args:\n        raw_annotations: The raw annotations to resolve.\n        module_name: The name of the module.\n\n    Returns:\n        The resolved annotations.\n    \"\"\"\n    module = sys.modules.get(module_name, None) if module_name is not None else None\n\n    base_globals: dict[str, Any] | None = (\n        module.__dict__ if module is not None else None\n    )\n\n    annotations = {}\n    for name, value in raw_annotations.items():\n        if isinstance(value, str):\n            if sys.version_info == (3, 10, 0):\n                value = ForwardRef(value, is_argument=False)\n            else:\n                value = ForwardRef(value, is_argument=False, is_class=True)\n        try:\n            if sys.version_info >= (3, 13):\n                value = _eval_type(value, base_globals, None, type_params=())\n            else:\n                value = _eval_type(value, base_globals, None)\n        except NameError:\n            # this is ok, it can be fixed with update_forward_refs\n            pass\n        annotations[name] = value\n    return annotations\n\n\nTYPES_THAT_HAS_DEFAULT_VALUE = (int, float, tuple, list, set, dict, str)\n\n\ndef get_default_value_for_type(t: GenericType) -> Any:\n    \"\"\"Get the default value of the var.\n\n    Args:\n        t: The type of the var.\n\n    Returns:\n        The default value of the var, if it has one, else None.\n\n    Raises:\n        ImportError: If the var is a dataframe and pandas is not installed.\n    \"\"\"\n    if is_optional(t):\n        return None\n\n    origin = get_origin(t) if is_generic_alias(t) else t\n    if origin is Literal:\n        args = get_args(t)\n        return args[0] if args else None\n    if safe_issubclass(origin, TYPES_THAT_HAS_DEFAULT_VALUE):\n        return origin()\n    if safe_issubclass(origin, Mapping):\n        return {}\n    if is_dataframe(origin):\n        try:\n            import pandas as pd\n\n            return pd.DataFrame()\n        except ImportError as e:\n            msg = \"Please install pandas to use dataframes in your app.\"\n            raise ImportError(msg) from e\n    return None\n\n\nIMMUTABLE_TYPES = (\n    int,\n    float,\n    bool,\n    str,\n    bytes,\n    frozenset,\n    tuple,\n    type(None),\n    Enum,\n)\n\n\ndef is_immutable(i: Any) -> bool:\n    \"\"\"Check if a value is immutable.\n\n    Args:\n        i: The value to check.\n\n    Returns:\n        Whether the value is immutable.\n    \"\"\"\n    return isinstance(i, IMMUTABLE_TYPES)\n"
  },
  {
    "path": "reflex/vars/__init__.py",
    "content": "\"\"\"Immutable-Based Var System.\"\"\"\n\nfrom .base import (\n    BaseStateMeta,\n    EvenMoreBasicBaseState,\n    Field,\n    LiteralVar,\n    Var,\n    VarData,\n    field,\n    get_unique_variable_name,\n    get_uuid_string_var,\n    var_operation,\n    var_operation_return,\n)\nfrom .color import ColorVar, LiteralColorVar\nfrom .datetime import DateTimeVar\nfrom .function import FunctionStringVar, FunctionVar, VarOperationCall\nfrom .number import BooleanVar, LiteralBooleanVar, LiteralNumberVar, NumberVar\nfrom .object import LiteralObjectVar, ObjectVar\nfrom .sequence import (\n    ArrayVar,\n    ConcatVarOperation,\n    LiteralArrayVar,\n    LiteralStringVar,\n    StringVar,\n)\n\n__all__ = [\n    \"ArrayVar\",\n    \"BaseStateMeta\",\n    \"BooleanVar\",\n    \"ColorVar\",\n    \"ConcatVarOperation\",\n    \"DateTimeVar\",\n    \"EvenMoreBasicBaseState\",\n    \"Field\",\n    \"FunctionStringVar\",\n    \"FunctionVar\",\n    \"LiteralArrayVar\",\n    \"LiteralBooleanVar\",\n    \"LiteralColorVar\",\n    \"LiteralNumberVar\",\n    \"LiteralObjectVar\",\n    \"LiteralStringVar\",\n    \"LiteralVar\",\n    \"NumberVar\",\n    \"ObjectVar\",\n    \"StringVar\",\n    \"Var\",\n    \"VarData\",\n    \"VarOperationCall\",\n    \"field\",\n    \"get_unique_variable_name\",\n    \"get_uuid_string_var\",\n    \"var_operation\",\n    \"var_operation_return\",\n]\n"
  },
  {
    "path": "reflex/vars/base.py",
    "content": "\"\"\"Collection of base classes.\"\"\"\n\nfrom __future__ import annotations\n\nimport contextlib\nimport copy\nimport dataclasses\nimport datetime\nimport functools\nimport inspect\nimport json\nimport re\nimport string\nimport uuid\nimport warnings\nfrom abc import ABCMeta\nfrom collections.abc import Callable, Coroutine, Iterable, Mapping, Sequence\nfrom dataclasses import _MISSING_TYPE, MISSING\nfrom decimal import Decimal\nfrom types import CodeType, FunctionType\nfrom typing import (\n    TYPE_CHECKING,\n    Annotated,\n    Any,\n    ClassVar,\n    Generic,\n    Literal,\n    NoReturn,\n    ParamSpec,\n    Protocol,\n    TypeGuard,\n    TypeVar,\n    cast,\n    get_args,\n    get_type_hints,\n    overload,\n)\n\nfrom rich.markup import escape\nfrom typing_extensions import dataclass_transform, override\n\nfrom reflex import constants\nfrom reflex.constants.compiler import Hooks\nfrom reflex.constants.state import FIELD_MARKER\nfrom reflex.utils import console, exceptions, imports, serializers, types\nfrom reflex.utils.compat import annotations_from_namespace\nfrom reflex.utils.decorator import once\nfrom reflex.utils.exceptions import (\n    ComputedVarSignatureError,\n    UntypedComputedVarError,\n    VarAttributeError,\n    VarDependencyError,\n    VarTypeError,\n)\nfrom reflex.utils.format import format_state_name\nfrom reflex.utils.imports import (\n    ImmutableImportDict,\n    ImmutableParsedImportDict,\n    ImportDict,\n    ImportVar,\n    ParsedImportTuple,\n    parse_imports,\n)\nfrom reflex.utils.types import (\n    GenericType,\n    Self,\n    _isinstance,\n    get_origin,\n    has_args,\n    safe_issubclass,\n    unionize,\n)\n\nif TYPE_CHECKING:\n    from reflex.components.component import BaseComponent\n    from reflex.constants.colors import Color\n    from reflex.state import BaseState\n\n    from .color import LiteralColorVar\n    from .number import BooleanVar, LiteralBooleanVar, LiteralNumberVar, NumberVar\n    from .object import LiteralObjectVar, ObjectVar\n    from .sequence import ArrayVar, LiteralArrayVar, LiteralStringVar, StringVar\n\n\nVAR_TYPE = TypeVar(\"VAR_TYPE\", covariant=True)\nOTHER_VAR_TYPE = TypeVar(\"OTHER_VAR_TYPE\")\nSTRING_T = TypeVar(\"STRING_T\", bound=str)\nSEQUENCE_TYPE = TypeVar(\"SEQUENCE_TYPE\", bound=Sequence)\n\nwarnings.filterwarnings(\"ignore\", message=\"fields may not start with an underscore\")\n\n_PYDANTIC_VALIDATE_VALUES = \"__pydantic_validate_values__\"\n\n\ndef _pydantic_validator(*args, **kwargs):\n    return None\n\n\n@dataclasses.dataclass(\n    eq=False,\n    frozen=True,\n)\nclass VarSubclassEntry:\n    \"\"\"Entry for a Var subclass.\"\"\"\n\n    var_subclass: type[Var]\n    to_var_subclass: type[ToOperation]\n    python_types: tuple[GenericType, ...]\n\n\n_var_subclasses: list[VarSubclassEntry] = []\n_var_literal_subclasses: list[tuple[type[LiteralVar], VarSubclassEntry]] = []\n\n\n@dataclasses.dataclass(\n    eq=True,\n    frozen=True,\n)\nclass VarData:\n    \"\"\"Metadata associated with a x.\"\"\"\n\n    # The name of the enclosing state.\n    state: str = dataclasses.field(default=\"\")\n\n    # The name of the field in the state.\n    field_name: str = dataclasses.field(default=\"\")\n\n    # Imports needed to render this var\n    imports: ParsedImportTuple = dataclasses.field(default_factory=tuple)\n\n    # Hooks that need to be present in the component to render this var\n    hooks: tuple[str, ...] = dataclasses.field(default_factory=tuple)\n\n    # Dependencies of the var\n    deps: tuple[Var, ...] = dataclasses.field(default_factory=tuple)\n\n    # Position of the hook in the component\n    position: Hooks.HookPosition | None = None\n\n    # Components that are part of this var\n    components: tuple[BaseComponent, ...] = dataclasses.field(default_factory=tuple)\n\n    def __init__(\n        self,\n        state: str = \"\",\n        field_name: str = \"\",\n        imports: ImmutableImportDict | ImmutableParsedImportDict | None = None,\n        hooks: Mapping[str, VarData | None] | Sequence[str] | str | None = None,\n        deps: list[Var] | None = None,\n        position: Hooks.HookPosition | None = None,\n        components: Iterable[BaseComponent] | None = None,\n    ):\n        \"\"\"Initialize the var data.\n\n        Args:\n            state: The name of the enclosing state.\n            field_name: The name of the field in the state.\n            imports: Imports needed to render this var.\n            hooks: Hooks that need to be present in the component to render this var.\n            deps: Dependencies of the var for useCallback.\n            position: Position of the hook in the component.\n            components: Components that are part of this var.\n        \"\"\"\n        if isinstance(hooks, str):\n            hooks = [hooks]\n        if not isinstance(hooks, dict):\n            hooks = dict.fromkeys(hooks or [])\n        immutable_imports: ParsedImportTuple = tuple(\n            (k, tuple(v)) for k, v in parse_imports(imports or {}).items()\n        )\n        object.__setattr__(self, \"state\", state)\n        object.__setattr__(self, \"field_name\", field_name)\n        object.__setattr__(self, \"imports\", immutable_imports)\n        object.__setattr__(self, \"hooks\", tuple(hooks or {}))\n        object.__setattr__(self, \"deps\", tuple(deps or []))\n        object.__setattr__(self, \"position\", position or None)\n        object.__setattr__(self, \"components\", tuple(components or []))\n\n        if hooks and any(hooks.values()):\n            # Merge our dependencies first, so they can be referenced.\n            merged_var_data = VarData.merge(*hooks.values(), self)\n            if merged_var_data is not None:\n                object.__setattr__(self, \"state\", merged_var_data.state)\n                object.__setattr__(self, \"field_name\", merged_var_data.field_name)\n                object.__setattr__(self, \"imports\", merged_var_data.imports)\n                object.__setattr__(self, \"hooks\", merged_var_data.hooks)\n                object.__setattr__(self, \"deps\", merged_var_data.deps)\n                object.__setattr__(self, \"position\", merged_var_data.position)\n                object.__setattr__(self, \"components\", merged_var_data.components)\n\n    def old_school_imports(self) -> ImportDict:\n        \"\"\"Return the imports as a mutable dict.\n\n        Returns:\n            The imports as a mutable dict.\n        \"\"\"\n        return {k: list(v) for k, v in self.imports}\n\n    def merge(*all: VarData | None) -> VarData | None:\n        \"\"\"Merge multiple var data objects.\n\n        Args:\n            *all: The var data objects to merge.\n\n        Returns:\n            The merged var data object.\n\n        Raises:\n            ReflexError: If trying to merge VarData with different positions.\n\n        # noqa: DAR102 *all\n        \"\"\"\n        all_var_datas = list(filter(None, all))\n\n        if not all_var_datas:\n            return None\n\n        if len(all_var_datas) == 1:\n            return all_var_datas[0]\n\n        # Get the first non-empty field name or default to empty string.\n        field_name = next(\n            (var_data.field_name for var_data in all_var_datas if var_data.field_name),\n            \"\",\n        )\n\n        # Get the first non-empty state or default to empty string.\n        state = next(\n            (var_data.state for var_data in all_var_datas if var_data.state), \"\"\n        )\n\n        hooks: dict[str, VarData | None] = {\n            hook: None for var_data in all_var_datas for hook in var_data.hooks\n        }\n\n        imports_ = imports.merge_imports(\n            *(var_data.imports for var_data in all_var_datas)\n        )\n\n        deps = [dep for var_data in all_var_datas for dep in var_data.deps]\n\n        positions = list(\n            dict.fromkeys(\n                var_data.position\n                for var_data in all_var_datas\n                if var_data.position is not None\n            )\n        )\n        if positions:\n            if len(positions) > 1:\n                msg = f\"Cannot merge var data with different positions: {positions}\"\n                raise exceptions.ReflexError(msg)\n            position = positions[0]\n        else:\n            position = None\n\n        components = tuple(\n            component for var_data in all_var_datas for component in var_data.components\n        )\n\n        return VarData(\n            state=state,\n            field_name=field_name,\n            imports=imports_,\n            hooks=hooks,\n            deps=deps,\n            position=position,\n            components=components,\n        )\n\n    def __bool__(self) -> bool:\n        \"\"\"Check if the var data is non-empty.\n\n        Returns:\n            True if any field is set to a non-default value.\n        \"\"\"\n        return bool(\n            self.state\n            or self.imports\n            or self.hooks\n            or self.field_name\n            or self.deps\n            or self.position\n            or self.components\n        )\n\n    @classmethod\n    def from_state(cls, state: type[BaseState] | str, field_name: str = \"\") -> VarData:\n        \"\"\"Set the state of the var.\n\n        Args:\n            state: The state to set or the full name of the state.\n            field_name: The name of the field in the state. Optional.\n\n        Returns:\n            The var with the set state.\n        \"\"\"\n        from reflex.utils import format\n\n        state_name = state if isinstance(state, str) else state.get_full_name()\n        return VarData(\n            state=state_name,\n            field_name=field_name,\n            hooks={\n                \"const {0} = useContext(StateContexts.{0})\".format(\n                    format.format_state_name(state_name)\n                ): None\n            },\n            imports={\n                f\"$/{constants.Dirs.CONTEXTS_PATH}\": [ImportVar(tag=\"StateContexts\")],\n                \"react\": [ImportVar(tag=\"useContext\")],\n            },\n        )\n\n\ndef _decode_var_immutable(value: str) -> tuple[VarData | None, str]:\n    \"\"\"Decode the state name from a formatted var.\n\n    Args:\n        value: The value to extract the state name from.\n\n    Returns:\n        The extracted state name and the value without the state name.\n    \"\"\"\n    var_datas = []\n    if isinstance(value, str):\n        # fast path if there is no encoded VarData\n        if constants.REFLEX_VAR_OPENING_TAG not in value:\n            return None, value\n\n        offset = 0\n\n        # Find all tags.\n        while m := _decode_var_pattern.search(value):\n            start, end = m.span()\n            value = value[:start] + value[end:]\n\n            serialized_data = m.group(1)\n\n            if serialized_data.isnumeric() or (\n                serialized_data[0] == \"-\" and serialized_data[1:].isnumeric()\n            ):\n                # This is a global immutable var.\n                var = _global_vars[int(serialized_data)]\n                var_data = var._get_all_var_data()\n\n                if var_data is not None:\n                    var_datas.append(var_data)\n            offset += end - start\n\n    return VarData.merge(*var_datas) if var_datas else None, value\n\n\ndef can_use_in_object_var(cls: GenericType) -> bool:\n    \"\"\"Check if the class can be used in an ObjectVar.\n\n    Args:\n        cls: The class to check.\n\n    Returns:\n        Whether the class can be used in an ObjectVar.\n    \"\"\"\n    if types.is_union(cls):\n        return all(can_use_in_object_var(t) for t in types.get_args(cls))\n    return (\n        isinstance(cls, type)\n        and not safe_issubclass(cls, Var)\n        and serializers.can_serialize(cls, dict)\n    )\n\n\nclass MetaclassVar(type):\n    \"\"\"Metaclass for the Var class.\"\"\"\n\n    def __setattr__(cls, name: str, value: Any):\n        \"\"\"Set an attribute on the class.\n\n        Args:\n            name: The name of the attribute.\n            value: The value of the attribute.\n        \"\"\"\n        super().__setattr__(\n            name, value if name != _PYDANTIC_VALIDATE_VALUES else _pydantic_validator\n        )\n\n\n@dataclasses.dataclass(\n    eq=False,\n    frozen=True,\n)\nclass Var(Generic[VAR_TYPE], metaclass=MetaclassVar):\n    \"\"\"Base class for immutable vars.\"\"\"\n\n    # The name of the var.\n    _js_expr: str = dataclasses.field()\n\n    # The type of the var.\n    _var_type: types.GenericType = dataclasses.field(default=Any)\n\n    # Extra metadata associated with the Var\n    _var_data: VarData | None = dataclasses.field(default=None)\n\n    def __str__(self) -> str:\n        \"\"\"String representation of the var. Guaranteed to be a valid Javascript expression.\n\n        Returns:\n            The name of the var.\n        \"\"\"\n        return self._js_expr\n\n    @property\n    def _var_is_local(self) -> bool:\n        \"\"\"Whether this is a local javascript variable.\n\n        Returns:\n            False\n        \"\"\"\n        return False\n\n    @property\n    def _var_is_string(self) -> bool:\n        \"\"\"Whether the var is a string literal.\n\n        Returns:\n            False\n        \"\"\"\n        return False\n\n    def __init_subclass__(\n        cls,\n        python_types: tuple[GenericType, ...] | GenericType = types.Unset(),\n        default_type: GenericType = types.Unset(),\n        **kwargs,\n    ):\n        \"\"\"Initialize the subclass.\n\n        Args:\n            python_types: The python types that the var represents.\n            default_type: The default type of the var. Defaults to the first python type.\n            **kwargs: Additional keyword arguments.\n        \"\"\"\n        super().__init_subclass__(**kwargs)\n\n        if python_types or default_type:\n            python_types = (\n                (python_types if isinstance(python_types, tuple) else (python_types,))\n                if python_types\n                else ()\n            )\n\n            default_type = default_type or (python_types[0] if python_types else Any)\n\n            @dataclasses.dataclass(\n                eq=False,\n                frozen=True,\n                slots=True,\n            )\n            class ToVarOperation(ToOperation, cls):\n                \"\"\"Base class of converting a var to another var type.\"\"\"\n\n                _original: Var = dataclasses.field(\n                    default=Var(_js_expr=\"null\", _var_type=None),\n                )\n\n                _default_var_type: ClassVar[GenericType] = default_type\n\n            new_to_var_operation_name = f\"{cls.__name__.removesuffix('Var')}CastedVar\"\n            ToVarOperation.__qualname__ = (\n                ToVarOperation.__qualname__.removesuffix(ToVarOperation.__name__)\n                + new_to_var_operation_name\n            )\n            ToVarOperation.__name__ = new_to_var_operation_name\n\n            _var_subclasses.append(VarSubclassEntry(cls, ToVarOperation, python_types))\n\n    def __post_init__(self):\n        \"\"\"Post-initialize the var.\n\n        Raises:\n            TypeError: If _js_expr is not a string.\n        \"\"\"\n        if not isinstance(self._js_expr, str):\n            msg = f\"Expected _js_expr to be a string, got value {self._js_expr!r} of type {type(self._js_expr).__name__}\"\n            raise TypeError(msg)\n\n        if self._var_data is not None and not isinstance(self._var_data, VarData):\n            msg = f\"Expected _var_data to be a VarData, got value {self._var_data!r} of type {type(self._var_data).__name__}\"\n            raise TypeError(msg)\n\n        # Decode any inline Var markup and apply it to the instance\n        var_data_, js_expr_ = _decode_var_immutable(self._js_expr)\n\n        if var_data_ or js_expr_ != self._js_expr:\n            self.__init__(\n                _js_expr=js_expr_,\n                _var_type=self._var_type,\n                _var_data=VarData.merge(self._var_data, var_data_),\n            )\n\n    def __hash__(self) -> int:\n        \"\"\"Define a hash function for the var.\n\n        Returns:\n            The hash of the var.\n        \"\"\"\n        return hash((self._js_expr, self._var_type, self._var_data))\n\n    def _get_all_var_data(self) -> VarData | None:\n        \"\"\"Get all VarData associated with the Var.\n\n        Returns:\n            The VarData of the components and all of its children.\n        \"\"\"\n        return self._var_data\n\n    def __deepcopy__(self, memo: dict[int, Any]) -> Self:\n        \"\"\"Deepcopy the var.\n\n        Args:\n            memo: The memo dictionary to use for the deepcopy.\n\n        Returns:\n            A deepcopy of the var.\n        \"\"\"\n        return self\n\n    def equals(self, other: Var) -> bool:\n        \"\"\"Check if two vars are equal.\n\n        Args:\n            other: The other var to compare.\n\n        Returns:\n            Whether the vars are equal.\n        \"\"\"\n        return (\n            self._js_expr == other._js_expr\n            and self._var_type == other._var_type\n            and self._get_all_var_data() == other._get_all_var_data()\n        )\n\n    @overload\n    def _replace(\n        self,\n        _var_type: type[OTHER_VAR_TYPE],\n        merge_var_data: VarData | None = None,\n        **kwargs: Any,\n    ) -> Var[OTHER_VAR_TYPE]: ...\n\n    @overload\n    def _replace(\n        self,\n        _var_type: GenericType | None = None,\n        merge_var_data: VarData | None = None,\n        **kwargs: Any,\n    ) -> Self: ...\n\n    def _replace(\n        self,\n        _var_type: GenericType | None = None,\n        merge_var_data: VarData | None = None,\n        **kwargs: Any,\n    ) -> Self | Var:\n        \"\"\"Make a copy of this Var with updated fields.\n\n        Args:\n            _var_type: The new type of the Var.\n            merge_var_data: VarData to merge into the existing VarData.\n            **kwargs: Var fields to update.\n\n        Returns:\n            A new Var with the updated fields overwriting the corresponding fields in this Var.\n\n        Raises:\n            TypeError: If _var_is_local, _var_is_string, or _var_full_name_needs_state_prefix is not None.\n        \"\"\"\n        if kwargs.get(\"_var_is_local\", False) is not False:\n            msg = \"The _var_is_local argument is not supported for Var.\"\n            raise TypeError(msg)\n\n        if kwargs.get(\"_var_is_string\", False) is not False:\n            msg = \"The _var_is_string argument is not supported for Var.\"\n            raise TypeError(msg)\n\n        if kwargs.get(\"_var_full_name_needs_state_prefix\", False) is not False:\n            msg = \"The _var_full_name_needs_state_prefix argument is not supported for Var.\"\n            raise TypeError(msg)\n        value_with_replaced = dataclasses.replace(\n            self,\n            _var_type=_var_type or self._var_type,\n            _var_data=VarData.merge(\n                kwargs.get(\"_var_data\", self._var_data), merge_var_data\n            ),\n            **kwargs,\n        )\n\n        if (js_expr := kwargs.get(\"_js_expr\")) is not None:\n            object.__setattr__(value_with_replaced, \"_js_expr\", js_expr)\n\n        return value_with_replaced\n\n    @overload\n    @classmethod\n    def create(  # pyright: ignore[reportOverlappingOverload]\n        cls,\n        value: NoReturn,\n        _var_data: VarData | None = None,\n    ) -> Var[Any]: ...\n\n    @overload\n    @classmethod\n    def create(  # pyright: ignore[reportOverlappingOverload]\n        cls,\n        value: bool,\n        _var_data: VarData | None = None,\n    ) -> LiteralBooleanVar: ...\n\n    @overload\n    @classmethod\n    def create(\n        cls,\n        value: int,\n        _var_data: VarData | None = None,\n    ) -> LiteralNumberVar[int]: ...\n\n    @overload\n    @classmethod\n    def create(\n        cls,\n        value: float,\n        _var_data: VarData | None = None,\n    ) -> LiteralNumberVar[float]: ...\n\n    @overload\n    @classmethod\n    def create(\n        cls,\n        value: Decimal,\n        _var_data: VarData | None = None,\n    ) -> LiteralNumberVar[Decimal]: ...\n\n    @overload\n    @classmethod\n    def create(  # pyright: ignore [reportOverlappingOverload]\n        cls,\n        value: Color,\n        _var_data: VarData | None = None,\n    ) -> LiteralColorVar: ...\n\n    @overload\n    @classmethod\n    def create(  # pyright: ignore [reportOverlappingOverload]\n        cls,\n        value: str,\n        _var_data: VarData | None = None,\n    ) -> LiteralStringVar: ...\n\n    @overload\n    @classmethod\n    def create(  # pyright: ignore [reportOverlappingOverload]\n        cls,\n        value: STRING_T,\n        _var_data: VarData | None = None,\n    ) -> StringVar[STRING_T]: ...\n\n    @overload\n    @classmethod\n    def create(  # pyright: ignore[reportOverlappingOverload]\n        cls,\n        value: None,\n        _var_data: VarData | None = None,\n    ) -> LiteralNoneVar: ...\n\n    @overload\n    @classmethod\n    def create(\n        cls,\n        value: MAPPING_TYPE,\n        _var_data: VarData | None = None,\n    ) -> LiteralObjectVar[MAPPING_TYPE]: ...\n\n    @overload\n    @classmethod\n    def create(\n        cls,\n        value: SEQUENCE_TYPE,\n        _var_data: VarData | None = None,\n    ) -> LiteralArrayVar[SEQUENCE_TYPE]: ...\n\n    @overload\n    @classmethod\n    def create(\n        cls,\n        value: OTHER_VAR_TYPE,\n        _var_data: VarData | None = None,\n    ) -> Var[OTHER_VAR_TYPE]: ...\n\n    @classmethod\n    def create(\n        cls,\n        value: OTHER_VAR_TYPE,\n        _var_data: VarData | None = None,\n    ) -> Var[OTHER_VAR_TYPE]:\n        \"\"\"Create a var from a value.\n\n        Args:\n            value: The value to create the var from.\n            _var_data: Additional hooks and imports associated with the Var.\n\n        Returns:\n            The var.\n        \"\"\"\n        # If the value is already a var, do nothing.\n        if isinstance(value, Var):\n            return value\n\n        return LiteralVar.create(value, _var_data=_var_data)\n\n    def __format__(self, format_spec: str) -> str:\n        \"\"\"Format the var into a Javascript equivalent to an f-string.\n\n        Args:\n            format_spec: The format specifier (Ignored for now).\n\n        Returns:\n            The formatted var.\n        \"\"\"\n        hashed_var = hash(self)\n\n        _global_vars[hashed_var] = self\n\n        # Encode the _var_data into the formatted output for tracking purposes.\n        return f\"{constants.REFLEX_VAR_OPENING_TAG}{hashed_var}{constants.REFLEX_VAR_CLOSING_TAG}{self._js_expr}\"\n\n    @overload\n    def to(self, output: type[str]) -> StringVar: ...  # pyright: ignore[reportOverlappingOverload]\n\n    @overload\n    def to(self, output: type[bool]) -> BooleanVar: ...\n\n    @overload\n    def to(self, output: type[int]) -> NumberVar[int]: ...\n\n    @overload\n    def to(self, output: type[float]) -> NumberVar[float]: ...\n\n    @overload\n    def to(self, output: type[Decimal]) -> NumberVar[Decimal]: ...\n\n    @overload\n    def to(\n        self,\n        output: type[SEQUENCE_TYPE],\n    ) -> ArrayVar[SEQUENCE_TYPE]: ...\n\n    @overload\n    def to(\n        self,\n        output: type[MAPPING_TYPE],\n    ) -> ObjectVar[MAPPING_TYPE]: ...\n\n    @overload\n    def to(\n        self, output: type[ObjectVar], var_type: type[VAR_INSIDE]\n    ) -> ObjectVar[VAR_INSIDE]: ...\n\n    @overload\n    def to(\n        self, output: type[ObjectVar], var_type: None = None\n    ) -> ObjectVar[VAR_TYPE]: ...\n\n    @overload\n    def to(self, output: VAR_SUBCLASS, var_type: None = None) -> VAR_SUBCLASS: ...\n\n    @overload\n    def to(\n        self,\n        output: type[OUTPUT] | types.GenericType,\n        var_type: types.GenericType | None = None,\n    ) -> OUTPUT: ...\n\n    def to(\n        self,\n        output: type[OUTPUT] | types.GenericType,\n        var_type: types.GenericType | None = None,\n    ) -> Var:\n        \"\"\"Convert the var to a different type.\n\n        Args:\n            output: The output type.\n            var_type: The type of the var.\n\n        Returns:\n            The converted var.\n        \"\"\"\n        from .object import ObjectVar\n\n        fixed_output_type = get_origin(output) or output\n\n        # If the first argument is a python type, we map it to the corresponding Var type.\n        for var_subclass in _var_subclasses[::-1]:\n            if fixed_output_type in var_subclass.python_types or safe_issubclass(\n                fixed_output_type, var_subclass.python_types\n            ):\n                return self.to(var_subclass.var_subclass, output)\n\n        if fixed_output_type is None:\n            return get_to_operation(NoneVar).create(self)  # pyright: ignore [reportReturnType]\n\n        # Handle fixed_output_type being Base or a dataclass.\n        if can_use_in_object_var(output):\n            return self.to(ObjectVar, output)\n\n        if isinstance(output, type):\n            for var_subclass in _var_subclasses[::-1]:\n                if safe_issubclass(output, var_subclass.var_subclass):\n                    current_var_type = self._var_type\n                    if current_var_type is Any:\n                        new_var_type = var_type\n                    else:\n                        new_var_type = var_type or current_var_type\n                    return var_subclass.to_var_subclass.create(  # pyright: ignore [reportReturnType]\n                        value=self, _var_type=new_var_type\n                    )\n\n            # If we can't determine the first argument, we just replace the _var_type.\n            if not safe_issubclass(output, Var) or var_type is None:\n                return dataclasses.replace(\n                    self,\n                    _var_type=output,\n                )\n\n        # We couldn't determine the output type to be any other Var type, so we replace the _var_type.\n        if var_type is not None:\n            return dataclasses.replace(\n                self,\n                _var_type=var_type,\n            )\n\n        return self\n\n    @overload\n    def guess_type(self: Var[NoReturn]) -> Var[Any]: ...  # pyright: ignore [reportOverlappingOverload]\n\n    @overload\n    def guess_type(self: Var[str]) -> StringVar: ...\n\n    @overload\n    def guess_type(self: Var[bool]) -> BooleanVar: ...\n\n    @overload\n    def guess_type(self: Var[int] | Var[float] | Var[int | float]) -> NumberVar: ...\n\n    @overload\n    def guess_type(self: Var[BASE_TYPE]) -> ObjectVar[BASE_TYPE]: ...\n\n    @overload\n    def guess_type(self) -> Self: ...\n\n    def guess_type(self) -> Var:\n        \"\"\"Guesses the type of the variable based on its `_var_type` attribute.\n\n        Returns:\n            Var: The guessed type of the variable.\n\n        Raises:\n            TypeError: If the type is not supported for guessing.\n        \"\"\"\n        from .object import ObjectVar\n\n        var_type = self._var_type\n        if var_type is None:\n            return self.to(None)\n        if var_type is NoReturn:\n            return self.to(Any)\n\n        var_type = types.value_inside_optional(var_type)\n\n        if var_type is Any:\n            return self\n\n        fixed_type = get_origin(var_type) or var_type\n\n        if fixed_type in types.UnionTypes:\n            inner_types = get_args(var_type)\n            non_optional_inner_types = [\n                types.value_inside_optional(inner_type) for inner_type in inner_types\n            ]\n            fixed_inner_types = [\n                get_origin(inner_type) or inner_type\n                for inner_type in non_optional_inner_types\n            ]\n\n            for var_subclass in _var_subclasses[::-1]:\n                if all(\n                    safe_issubclass(t, var_subclass.python_types)\n                    for t in fixed_inner_types\n                ):\n                    return self.to(var_subclass.var_subclass, self._var_type)\n\n            if can_use_in_object_var(var_type):\n                return self.to(ObjectVar, self._var_type)\n\n            return self\n\n        if fixed_type is Literal:\n            args = get_args(var_type)\n            fixed_type = unionize(*(type(arg) for arg in args))\n\n        if not isinstance(fixed_type, type):\n            msg = f\"Unsupported type {var_type} for guess_type.\"\n            raise TypeError(msg)\n\n        if fixed_type is None:\n            return self.to(None)\n\n        for var_subclass in _var_subclasses[::-1]:\n            if safe_issubclass(fixed_type, var_subclass.python_types):\n                return self.to(var_subclass.var_subclass, self._var_type)\n\n        if can_use_in_object_var(fixed_type):\n            return self.to(ObjectVar, self._var_type)\n\n        return self\n\n    @staticmethod\n    def _get_setter_name_for_name(\n        name: str,\n    ) -> str:\n        \"\"\"Get the name of the var's generated setter function.\n\n        Args:\n            name: The name of the var.\n\n        Returns:\n            The name of the setter function.\n        \"\"\"\n        return constants.SETTER_PREFIX + name\n\n    def _get_setter(self, name: str) -> Callable[[BaseState, Any], None]:\n        \"\"\"Get the var's setter function.\n\n        Args:\n            name: The name of the var.\n\n        Returns:\n            A function that that creates a setter for the var.\n        \"\"\"\n        setter_name = Var._get_setter_name_for_name(name)\n\n        def setter(state: Any, value: Any):\n            \"\"\"Get the setter for the var.\n\n            Args:\n                state: The state within which we add the setter function.\n                value: The value to set.\n            \"\"\"\n            if self._var_type in [int, float]:\n                try:\n                    value = self._var_type(value)\n                    setattr(state, name, value)\n                except ValueError:\n                    console.debug(\n                        f\"{type(state).__name__}.{self._js_expr}: Failed conversion of {value!s} to '{self._var_type.__name__}'. Value not set.\",\n                    )\n            else:\n                setattr(state, name, value)\n\n        setter.__annotations__[\"value\"] = self._var_type\n\n        setter.__qualname__ = setter_name\n\n        return setter\n\n    def _var_set_state(self, state: type[BaseState] | str) -> Self:\n        \"\"\"Set the state of the var.\n\n        Args:\n            state: The state to set.\n\n        Returns:\n            The var with the state set.\n        \"\"\"\n        formatted_state_name = (\n            state\n            if isinstance(state, str)\n            else format_state_name(state.get_full_name())\n        )\n\n        return StateOperation.create(  # pyright: ignore [reportReturnType]\n            formatted_state_name,\n            self,\n            _var_data=VarData.merge(\n                VarData.from_state(state, self._js_expr), self._var_data\n            ),\n        ).guess_type()\n\n    def __eq__(self, other: Var | Any) -> BooleanVar:\n        \"\"\"Check if the current variable is equal to the given variable.\n\n        Args:\n            other (Var | Any): The variable to compare with.\n\n        Returns:\n            BooleanVar: A BooleanVar object representing the result of the equality check.\n        \"\"\"\n        from .number import equal_operation\n\n        return equal_operation(self, other)\n\n    def __ne__(self, other: Var | Any) -> BooleanVar:\n        \"\"\"Check if the current object is not equal to the given object.\n\n        Parameters:\n            other (Var | Any): The object to compare with.\n\n        Returns:\n            BooleanVar: A BooleanVar object representing the result of the comparison.\n        \"\"\"\n        from .number import equal_operation\n\n        return ~equal_operation(self, other)\n\n    def bool(self) -> BooleanVar:\n        \"\"\"Convert the var to a boolean.\n\n        Returns:\n            The boolean var.\n        \"\"\"\n        from .number import boolify\n\n        return boolify(self)\n\n    def is_none(self) -> BooleanVar:\n        \"\"\"Check if the var is None.\n\n        Returns:\n            A BooleanVar object representing the result of the check.\n        \"\"\"\n        from .number import is_not_none_operation\n\n        return ~is_not_none_operation(self)\n\n    def is_not_none(self) -> BooleanVar:\n        \"\"\"Check if the var is not None.\n\n        Returns:\n            A BooleanVar object representing the result of the check.\n        \"\"\"\n        from .number import is_not_none_operation\n\n        return is_not_none_operation(self)\n\n    def __and__(\n        self, other: Var[OTHER_VAR_TYPE] | Any\n    ) -> Var[VAR_TYPE | OTHER_VAR_TYPE]:\n        \"\"\"Perform a logical AND operation on the current instance and another variable.\n\n        Args:\n            other: The variable to perform the logical AND operation with.\n\n        Returns:\n            A `BooleanVar` object representing the result of the logical AND operation.\n        \"\"\"\n        return and_operation(self, other)\n\n    def __rand__(\n        self, other: Var[OTHER_VAR_TYPE] | Any\n    ) -> Var[VAR_TYPE | OTHER_VAR_TYPE]:\n        \"\"\"Perform a logical AND operation on the current instance and another variable.\n\n        Args:\n            other: The variable to perform the logical AND operation with.\n\n        Returns:\n            A `BooleanVar` object representing the result of the logical AND operation.\n        \"\"\"\n        return and_operation(other, self)\n\n    def __or__(\n        self, other: Var[OTHER_VAR_TYPE] | Any\n    ) -> Var[VAR_TYPE | OTHER_VAR_TYPE]:\n        \"\"\"Perform a logical OR operation on the current instance and another variable.\n\n        Args:\n            other: The variable to perform the logical OR operation with.\n\n        Returns:\n            A `BooleanVar` object representing the result of the logical OR operation.\n        \"\"\"\n        return or_operation(self, other)\n\n    def __ror__(\n        self, other: Var[OTHER_VAR_TYPE] | Any\n    ) -> Var[VAR_TYPE | OTHER_VAR_TYPE]:\n        \"\"\"Perform a logical OR operation on the current instance and another variable.\n\n        Args:\n            other: The variable to perform the logical OR operation with.\n\n        Returns:\n            A `BooleanVar` object representing the result of the logical OR operation.\n        \"\"\"\n        return or_operation(other, self)\n\n    def __invert__(self) -> BooleanVar:\n        \"\"\"Perform a logical NOT operation on the current instance.\n\n        Returns:\n            A `BooleanVar` object representing the result of the logical NOT operation.\n        \"\"\"\n        return ~self.bool()\n\n    def to_string(self, use_json: bool = True) -> StringVar:\n        \"\"\"Convert the var to a string.\n\n        Args:\n            use_json: Whether to use JSON stringify. If False, uses Object.prototype.toString.\n\n        Returns:\n            The string var.\n        \"\"\"\n        from .function import JSON_STRINGIFY, PROTOTYPE_TO_STRING\n        from .sequence import StringVar\n\n        return (\n            JSON_STRINGIFY.call(self).to(StringVar)\n            if use_json\n            else PROTOTYPE_TO_STRING.call(self).to(StringVar)\n        )\n\n    def _as_ref(self) -> Var:\n        \"\"\"Get a reference to the var.\n\n        Returns:\n            The reference to the var.\n        \"\"\"\n        return Var(\n            _js_expr=f\"refs[{Var.create(str(self))}]\",\n            _var_data=VarData(\n                imports={\n                    f\"$/{constants.Dirs.STATE_PATH}\": [imports.ImportVar(tag=\"refs\")]\n                }\n            ),\n        ).to(str)\n\n    def js_type(self) -> StringVar:\n        \"\"\"Returns the javascript type of the object.\n\n        This method uses the `typeof` function from the `FunctionStringVar` class\n        to determine the type of the object.\n\n        Returns:\n            StringVar: A string variable representing the type of the object.\n        \"\"\"\n        from .function import FunctionStringVar\n        from .sequence import StringVar\n\n        type_of = FunctionStringVar(\"typeof\")\n        return type_of.call(self).to(StringVar)\n\n    def _without_data(self):\n        \"\"\"Create a copy of the var without the data.\n\n        Returns:\n            The var without the data.\n        \"\"\"\n        return dataclasses.replace(self, _var_data=None)\n\n    def _decode(self) -> Any:\n        \"\"\"Decode Var as a python value.\n\n        Note that Var with state set cannot be decoded python-side and will be\n        returned as full_name.\n\n        Returns:\n            The decoded value or the Var name.\n        \"\"\"\n        if isinstance(self, LiteralVar):\n            return self._var_value\n        try:\n            return json.loads(str(self))\n        except ValueError:\n            return str(self)\n\n    @property\n    def _var_state(self) -> str:\n        \"\"\"Compat method for getting the state.\n\n        Returns:\n            The state name associated with the var.\n        \"\"\"\n        var_data = self._get_all_var_data()\n        return var_data.state if var_data else \"\"\n\n    @overload\n    @classmethod\n    def range(cls, stop: int | NumberVar, /) -> ArrayVar[Sequence[int]]: ...\n\n    @overload\n    @classmethod\n    def range(\n        cls,\n        start: int | NumberVar,\n        end: int | NumberVar,\n        step: int | NumberVar = 1,\n        /,\n    ) -> ArrayVar[Sequence[int]]: ...\n\n    @classmethod\n    def range(\n        cls,\n        first_endpoint: int | NumberVar,\n        second_endpoint: int | NumberVar | None = None,\n        step: int | NumberVar | None = None,\n    ) -> ArrayVar[Sequence[int]]:\n        \"\"\"Create a range of numbers.\n\n        Args:\n            first_endpoint: The end of the range if second_endpoint is not provided, otherwise the start of the range.\n            second_endpoint: The end of the range.\n            step: The step of the range.\n\n        Returns:\n            The range of numbers.\n        \"\"\"\n        from .sequence import ArrayVar\n\n        return ArrayVar.range(first_endpoint, second_endpoint, step)\n\n    if not TYPE_CHECKING:\n\n        def __getitem__(self, key: Any) -> Var:\n            \"\"\"Get the item from the var.\n\n            Args:\n                key: The key to get.\n\n            Raises:\n                UntypedVarError: If the var type is Any.\n                TypeError: If the var type is Any.\n\n            # noqa: DAR101 self\n            \"\"\"\n            if self._var_type is Any:\n                raise exceptions.UntypedVarError(\n                    self,\n                    f\"access the item '{key}'\",\n                )\n            msg = f\"Var of type {self._var_type} does not support item access.\"\n            raise TypeError(msg)\n\n        def __getattr__(self, name: str):\n            \"\"\"Get an attribute of the var.\n\n            Args:\n                name: The name of the attribute.\n\n            Raises:\n                VarAttributeError: If the attribute does not exist.\n                UntypedVarError: If the var type is Any.\n                TypeError: If the var type is Any.\n\n            # noqa: DAR101 self\n            \"\"\"\n            if name.startswith(\"_\"):\n                msg = f\"Attribute {name} not found.\"\n                raise VarAttributeError(msg)\n\n            if name == \"contains\":\n                msg = f\"Var of type {self._var_type} does not support contains check.\"\n                raise TypeError(msg)\n            if name == \"reverse\":\n                msg = \"Cannot reverse non-list var.\"\n                raise TypeError(msg)\n\n            if self._var_type is Any:\n                raise exceptions.UntypedVarError(\n                    self,\n                    f\"access the attribute '{name}'\",\n                )\n\n            msg = f\"The State var {escape(self._js_expr)} of type {escape(str(self._var_type))} has no attribute '{name}' or may have been annotated wrongly.\"\n            raise VarAttributeError(msg)\n\n        def __bool__(self) -> bool:\n            \"\"\"Raise exception if using Var in a boolean context.\n\n            Raises:\n                VarTypeError: when attempting to bool-ify the Var.\n\n            # noqa: DAR101 self\n            \"\"\"\n            msg = (\n                f\"Cannot convert Var {str(self)!r} to bool for use with `if`, `and`, `or`, and `not`. \"\n                \"Instead use `rx.cond` and bitwise operators `&` (and), `|` (or), `~` (invert).\"\n            )\n            raise VarTypeError(msg)\n\n        def __iter__(self) -> Any:\n            \"\"\"Raise exception if using Var in an iterable context.\n\n            Raises:\n                VarTypeError: when attempting to iterate over the Var.\n\n            # noqa: DAR101 self\n            \"\"\"\n            msg = f\"Cannot iterate over Var {str(self)!r}. Instead use `rx.foreach`.\"\n            raise VarTypeError(msg)\n\n        def __contains__(self, _: Any) -> Var:\n            \"\"\"Override the 'in' operator to alert the user that it is not supported.\n\n            Raises:\n                VarTypeError: the operation is not supported\n\n            # noqa: DAR101 self\n            \"\"\"\n            msg = (\n                \"'in' operator not supported for Var types, use Var.contains() instead.\"\n            )\n            raise VarTypeError(msg)\n\n\nOUTPUT = TypeVar(\"OUTPUT\", bound=Var)\n\nVAR_SUBCLASS = TypeVar(\"VAR_SUBCLASS\", bound=Var)\nVAR_INSIDE = TypeVar(\"VAR_INSIDE\")\n\n\nclass ToOperation:\n    \"\"\"A var operation that converts a var to another type.\"\"\"\n\n    def __getattr__(self, name: str) -> Any:\n        \"\"\"Get an attribute of the var.\n\n        Args:\n            name: The name of the attribute.\n\n        Returns:\n            The attribute of the var.\n        \"\"\"\n        from .object import ObjectVar\n\n        if isinstance(self, ObjectVar) and name != \"_js_expr\":\n            return ObjectVar.__getattr__(self, name)\n        return getattr(self._original, name)\n\n    def __post_init__(self):\n        \"\"\"Post initialization.\"\"\"\n        object.__delattr__(self, \"_js_expr\")\n\n    def __hash__(self) -> int:\n        \"\"\"Calculate the hash value of the object.\n\n        Returns:\n            int: The hash value of the object.\n        \"\"\"\n        return hash(self._original)\n\n    def _get_all_var_data(self) -> VarData | None:\n        \"\"\"Get all the var data.\n\n        Returns:\n            The var data.\n        \"\"\"\n        return VarData.merge(\n            self._original._get_all_var_data(),\n            self._var_data,\n        )\n\n    @classmethod\n    def create(\n        cls,\n        value: Var,\n        _var_type: GenericType | None = None,\n        _var_data: VarData | None = None,\n    ):\n        \"\"\"Create a ToOperation.\n\n        Args:\n            value: The value of the var.\n            _var_type: The type of the Var.\n            _var_data: Additional hooks and imports associated with the Var.\n\n        Returns:\n            The ToOperation.\n        \"\"\"\n        return cls(\n            _js_expr=\"\",  # pyright: ignore [reportCallIssue]\n            _var_data=_var_data,  # pyright: ignore [reportCallIssue]\n            _var_type=_var_type or cls._default_var_type,  # pyright: ignore [reportCallIssue, reportAttributeAccessIssue]\n            _original=value,  # pyright: ignore [reportCallIssue]\n        )\n\n\nclass LiteralVar(Var):\n    \"\"\"Base class for immutable literal vars.\"\"\"\n\n    def __init_subclass__(cls, **kwargs):\n        \"\"\"Initialize the subclass.\n\n        Args:\n            **kwargs: Additional keyword arguments.\n\n        Raises:\n            TypeError: If the LiteralVar subclass does not have a corresponding Var subclass.\n        \"\"\"\n        super().__init_subclass__(**kwargs)\n\n        bases = cls.__bases__\n\n        bases_normalized = [\n            base if isinstance(base, type) else get_origin(base) for base in bases\n        ]\n\n        possible_bases = [\n            base\n            for base in bases_normalized\n            if safe_issubclass(base, Var) and base != LiteralVar\n        ]\n\n        if not possible_bases:\n            msg = f\"LiteralVar subclass {cls} must have a base class that is a subclass of Var and not LiteralVar.\"\n            raise TypeError(msg)\n\n        var_subclasses = [\n            var_subclass\n            for var_subclass in _var_subclasses\n            if var_subclass.var_subclass in possible_bases\n        ]\n\n        if not var_subclasses:\n            msg = f\"LiteralVar {cls} must have a base class annotated with `python_types`.\"\n            raise TypeError(msg)\n\n        if len(var_subclasses) != 1:\n            msg = f\"LiteralVar {cls} must have exactly one base class annotated with `python_types`.\"\n            raise TypeError(msg)\n\n        var_subclass = var_subclasses[0]\n\n        # Remove the old subclass, happens because __init_subclass__ is called twice\n        # for each subclass. This is because of __slots__ in dataclasses.\n        for var_literal_subclass in list(_var_literal_subclasses):\n            if var_literal_subclass[1] is var_subclass:\n                _var_literal_subclasses.remove(var_literal_subclass)\n\n        _var_literal_subclasses.append((cls, var_subclass))\n\n    @classmethod\n    def _create_literal_var(\n        cls,\n        value: Any,\n        _var_data: VarData | None = None,\n    ) -> Var:\n        \"\"\"Create a var from a value.\n\n        Args:\n            value: The value to create the var from.\n            _var_data: Additional hooks and imports associated with the Var.\n\n        Returns:\n            The var.\n\n        Raises:\n            TypeError: If the value is not a supported type for LiteralVar.\n        \"\"\"\n        from .object import LiteralObjectVar\n        from .sequence import ArrayVar, LiteralStringVar\n\n        if isinstance(value, Var):\n            if _var_data is None:\n                return value\n            return value._replace(merge_var_data=_var_data)\n\n        for literal_subclass, var_subclass in _var_literal_subclasses[::-1]:\n            if isinstance(value, var_subclass.python_types):\n                return literal_subclass.create(value, _var_data=_var_data)\n\n        if (\n            (as_var_method := getattr(value, \"_as_var\", None)) is not None\n            and callable(as_var_method)\n            and isinstance((resulting_var := as_var_method()), Var)\n        ):\n            return resulting_var\n\n        from reflex.event import EventHandler\n        from reflex.utils.format import get_event_handler_parts\n\n        if isinstance(value, EventHandler):\n            return Var(_js_expr=\".\".join(filter(None, get_event_handler_parts(value))))\n\n        serialized_value = serializers.serialize(value)\n        if serialized_value is not None:\n            if isinstance(serialized_value, Mapping):\n                return LiteralObjectVar.create(\n                    serialized_value,\n                    _var_type=type(value),\n                    _var_data=_var_data,\n                )\n            if isinstance(serialized_value, str):\n                return LiteralStringVar.create(\n                    serialized_value, _var_type=type(value), _var_data=_var_data\n                )\n            return LiteralVar.create(serialized_value, _var_data=_var_data)\n\n        if dataclasses.is_dataclass(value) and not isinstance(value, type):\n            return LiteralObjectVar.create(\n                {\n                    k.name: (None if callable(v := getattr(value, k.name)) else v)\n                    for k in dataclasses.fields(value)\n                },\n                _var_type=type(value),\n                _var_data=_var_data,\n            )\n\n        if isinstance(value, range):\n            return ArrayVar.range(value.start, value.stop, value.step)\n\n        msg = f\"Unsupported type {type(value)} for LiteralVar. Tried to create a LiteralVar from {value}.\"\n        raise TypeError(msg)\n\n    if not TYPE_CHECKING:\n        create = _create_literal_var\n\n    def __post_init__(self):\n        \"\"\"Post-initialize the var.\"\"\"\n\n    @classmethod\n    def _get_all_var_data_without_creating_var(\n        cls,\n        value: Any,\n    ) -> VarData | None:\n        return cls.create(value)._get_all_var_data()\n\n    @classmethod\n    def _get_all_var_data_without_creating_var_dispatch(\n        cls,\n        value: Any,\n    ) -> VarData | None:\n        \"\"\"Get all the var data without creating a var.\n\n        Args:\n            value: The value to get the var data from.\n\n        Returns:\n            The var data or None.\n\n        Raises:\n            TypeError: If the value is not a supported type for LiteralVar.\n        \"\"\"\n        from .object import LiteralObjectVar\n        from .sequence import LiteralStringVar\n\n        if isinstance(value, Var):\n            return value._get_all_var_data()\n\n        for literal_subclass, var_subclass in _var_literal_subclasses[::-1]:\n            if isinstance(value, var_subclass.python_types):\n                return literal_subclass._get_all_var_data_without_creating_var(value)\n\n        if (\n            (as_var_method := getattr(value, \"_as_var\", None)) is not None\n            and callable(as_var_method)\n            and isinstance((resulting_var := as_var_method()), Var)\n        ):\n            return resulting_var._get_all_var_data()\n\n        from reflex.event import EventHandler\n        from reflex.utils.format import get_event_handler_parts\n\n        if isinstance(value, EventHandler):\n            return Var(\n                _js_expr=\".\".join(filter(None, get_event_handler_parts(value)))\n            )._get_all_var_data()\n\n        serialized_value = serializers.serialize(value)\n        if serialized_value is not None:\n            if isinstance(serialized_value, Mapping):\n                return LiteralObjectVar._get_all_var_data_without_creating_var(\n                    serialized_value\n                )\n            if isinstance(serialized_value, str):\n                return LiteralStringVar._get_all_var_data_without_creating_var(\n                    serialized_value\n                )\n            return LiteralVar._get_all_var_data_without_creating_var_dispatch(\n                serialized_value\n            )\n\n        if dataclasses.is_dataclass(value) and not isinstance(value, type):\n            return LiteralObjectVar._get_all_var_data_without_creating_var({\n                k.name: (None if callable(v := getattr(value, k.name)) else v)\n                for k in dataclasses.fields(value)\n            })\n\n        if isinstance(value, range):\n            return None\n\n        msg = f\"Unsupported type {type(value)} for LiteralVar. Tried to create a LiteralVar from {value}.\"\n        raise TypeError(msg)\n\n    @property\n    def _var_value(self) -> Any:\n        msg = \"LiteralVar subclasses must implement the _var_value property.\"\n        raise NotImplementedError(msg)\n\n    def json(self) -> str:\n        \"\"\"Serialize the var to a JSON string.\n\n        Raises:\n            NotImplementedError: If the method is not implemented.\n        \"\"\"\n        msg = \"LiteralVar subclasses must implement the json method.\"\n        raise NotImplementedError(msg)\n\n\n@serializers.serializer\ndef serialize_literal(value: LiteralVar):\n    \"\"\"Serialize a Literal type.\n\n    Args:\n        value: The Literal to serialize.\n\n    Returns:\n        The serialized Literal.\n    \"\"\"\n    return value._var_value\n\n\ndef get_python_literal(value: LiteralVar | Any) -> Any | None:\n    \"\"\"Get the Python literal value.\n\n    Args:\n        value: The value to get the Python literal value of.\n\n    Returns:\n        The Python literal value.\n    \"\"\"\n    if isinstance(value, LiteralVar):\n        return value._var_value\n    if isinstance(value, Var):\n        return None\n    return value\n\n\nP = ParamSpec(\"P\")\nT = TypeVar(\"T\")\n\n\n# NoReturn is used to match CustomVarOperationReturn with no type hint.\n@overload\ndef var_operation(  # pyright: ignore [reportOverlappingOverload]\n    func: Callable[P, CustomVarOperationReturn[NoReturn]],\n) -> Callable[P, Var]: ...\n\n\n@overload\ndef var_operation(\n    func: Callable[P, CustomVarOperationReturn[None]],\n) -> Callable[P, NoneVar]: ...\n\n\n@overload\ndef var_operation(  # pyright: ignore [reportOverlappingOverload]\n    func: Callable[P, CustomVarOperationReturn[bool]]\n    | Callable[P, CustomVarOperationReturn[bool | None]],\n) -> Callable[P, BooleanVar]: ...\n\n\nNUMBER_T = TypeVar(\"NUMBER_T\", int, float, int | float)\n\n\n@overload\ndef var_operation(\n    func: Callable[P, CustomVarOperationReturn[NUMBER_T]]\n    | Callable[P, CustomVarOperationReturn[NUMBER_T | None]],\n) -> Callable[P, NumberVar[NUMBER_T]]: ...\n\n\n@overload\ndef var_operation(\n    func: Callable[P, CustomVarOperationReturn[str]]\n    | Callable[P, CustomVarOperationReturn[str | None]],\n) -> Callable[P, StringVar]: ...\n\n\nLIST_T = TypeVar(\"LIST_T\", bound=Sequence)\n\n\n@overload\ndef var_operation(\n    func: Callable[P, CustomVarOperationReturn[LIST_T]]\n    | Callable[P, CustomVarOperationReturn[LIST_T | None]],\n) -> Callable[P, ArrayVar[LIST_T]]: ...\n\n\nOBJECT_TYPE = TypeVar(\"OBJECT_TYPE\", bound=Mapping)\n\n\n@overload\ndef var_operation(\n    func: Callable[P, CustomVarOperationReturn[OBJECT_TYPE]]\n    | Callable[P, CustomVarOperationReturn[OBJECT_TYPE | None]],\n) -> Callable[P, ObjectVar[OBJECT_TYPE]]: ...\n\n\n@overload\ndef var_operation(\n    func: Callable[P, CustomVarOperationReturn[T]]\n    | Callable[P, CustomVarOperationReturn[T | None]],\n) -> Callable[P, Var[T]]: ...\n\n\ndef var_operation(  # pyright: ignore [reportInconsistentOverload]\n    func: Callable[P, CustomVarOperationReturn[T]],\n) -> Callable[P, Var[T]]:\n    \"\"\"Decorator for creating a var operation.\n\n    Example:\n    ```python\n    @var_operation\n    def add(a: NumberVar, b: NumberVar):\n        return custom_var_operation(f\"{a} + {b}\")\n    ```\n\n    Args:\n        func: The function to decorate.\n\n    Returns:\n        The decorated function.\n    \"\"\"\n    func_args = list(inspect.signature(func).parameters)\n\n    @functools.wraps(func)\n    def wrapper(*args: P.args, **kwargs: P.kwargs) -> Var[T]:\n        args_vars = {\n            func_args[i]: (LiteralVar.create(arg) if not isinstance(arg, Var) else arg)\n            for i, arg in enumerate(args)\n        }\n        kwargs_vars = {\n            key: LiteralVar.create(value) if not isinstance(value, Var) else value\n            for key, value in kwargs.items()\n        }\n\n        return CustomVarOperation.create(\n            name=func.__name__,\n            args=tuple(list(args_vars.items()) + list(kwargs_vars.items())),\n            return_var=func(*args_vars.values(), **kwargs_vars),  # pyright: ignore [reportCallIssue, reportReturnType]\n        ).guess_type()\n\n    return wrapper\n\n\ndef figure_out_type(value: Any) -> types.GenericType:\n    \"\"\"Figure out the type of the value.\n\n    Args:\n        value: The value to figure out the type of.\n\n    Returns:\n        The type of the value.\n    \"\"\"\n    if isinstance(value, (list, set, tuple, Mapping, Var)):\n        if isinstance(value, Var):\n            return value._var_type\n        if has_args(value_type := type(value)):\n            return value_type\n        if isinstance(value, list):\n            if not value:\n                return Sequence[NoReturn]\n            return Sequence[unionize(*{figure_out_type(v) for v in value[:100]})]\n        if isinstance(value, set):\n            return set[unionize(*{figure_out_type(v) for v in value})]\n        if isinstance(value, tuple):\n            if not value:\n                return tuple[NoReturn, ...]\n            if len(value) <= 5:\n                return tuple[tuple(figure_out_type(v) for v in value)]\n            return tuple[unionize(*{figure_out_type(v) for v in value[:100]}), ...]\n        if isinstance(value, Mapping):\n            if not value:\n                return Mapping[NoReturn, NoReturn]\n            return Mapping[\n                unionize(*{figure_out_type(k) for k in list(value.keys())[:100]}),\n                unionize(*{figure_out_type(v) for v in list(value.values())[:100]}),\n            ]\n    return type(value)\n\n\nGLOBAL_CACHE = {}\n\n\nclass cached_property:  # noqa: N801\n    \"\"\"A cached property that caches the result of the function.\"\"\"\n\n    def __init__(self, func: Callable):\n        \"\"\"Initialize the cached_property.\n\n        Args:\n            func: The function to cache.\n        \"\"\"\n        self._func = func\n        self._attrname = None\n\n    def __set_name__(self, owner: Any, name: str):\n        \"\"\"Set the name of the cached property.\n\n        Args:\n            owner: The owner of the cached property.\n            name: The name of the cached property.\n\n        Raises:\n            TypeError: If the cached property is assigned to two different names.\n        \"\"\"\n        if self._attrname is None:\n            self._attrname = name\n\n            original_del = getattr(owner, \"__del__\", None)\n\n            def delete_property(this: Any):\n                \"\"\"Delete the cached property.\n\n                Args:\n                    this: The object to delete the cached property from.\n                \"\"\"\n                cached_field_name = \"_reflex_cache_\" + name\n                try:\n                    unique_id = object.__getattribute__(this, cached_field_name)\n                except AttributeError:\n                    if original_del is not None:\n                        original_del(this)\n                    return\n                GLOBAL_CACHE.pop(unique_id, None)\n\n                if original_del is not None:\n                    original_del(this)\n\n            owner.__del__ = delete_property\n\n        elif name != self._attrname:\n            msg = (\n                \"Cannot assign the same cached_property to two different names \"\n                f\"({self._attrname!r} and {name!r}).\"\n            )\n            raise TypeError(msg)\n\n    def __get__(self, instance: Any, owner: type | None = None):\n        \"\"\"Get the cached property.\n\n        Args:\n            instance: The instance to get the cached property from.\n            owner: The owner of the cached property.\n\n        Returns:\n            The cached property.\n\n        Raises:\n            TypeError: If the class does not have __set_name__.\n        \"\"\"\n        if self._attrname is None:\n            msg = \"Cannot use cached_property on a class without __set_name__.\"\n            raise TypeError(msg)\n        cached_field_name = \"_reflex_cache_\" + self._attrname\n        try:\n            unique_id = object.__getattribute__(instance, cached_field_name)\n        except AttributeError:\n            unique_id = uuid.uuid4().int\n            object.__setattr__(instance, cached_field_name, unique_id)\n        if unique_id not in GLOBAL_CACHE:\n            GLOBAL_CACHE[unique_id] = self._func(instance)\n        return GLOBAL_CACHE[unique_id]\n\n\ncached_property_no_lock = cached_property\n\n\nclass VarProtocol(Protocol):\n    \"\"\"A protocol for Var.\"\"\"\n\n    __dataclass_fields__: ClassVar[dict[str, dataclasses.Field[Any]]]\n\n    @property\n    def _js_expr(self) -> str: ...\n\n    @property\n    def _var_type(self) -> types.GenericType: ...\n\n    @property\n    def _var_data(self) -> VarData: ...\n\n\nclass CachedVarOperation:\n    \"\"\"Base class for cached var operations to lower boilerplate code.\"\"\"\n\n    def __post_init__(self):\n        \"\"\"Post-initialize the CachedVarOperation.\"\"\"\n        object.__delattr__(self, \"_js_expr\")\n\n    def __getattr__(self, name: str) -> Any:\n        \"\"\"Get an attribute of the var.\n\n        Args:\n            name: The name of the attribute.\n\n        Returns:\n            The attribute.\n        \"\"\"\n        if name == \"_js_expr\":\n            return self._cached_var_name\n\n        parent_classes = inspect.getmro(type(self))\n\n        next_class = parent_classes[parent_classes.index(CachedVarOperation) + 1]\n\n        return next_class.__getattr__(self, name)\n\n    def _get_all_var_data(self) -> VarData | None:\n        \"\"\"Get all VarData associated with the Var.\n\n        Returns:\n            The VarData of the components and all of its children.\n        \"\"\"\n        return self._cached_get_all_var_data\n\n    @cached_property_no_lock\n    def _cached_get_all_var_data(self: VarProtocol) -> VarData | None:\n        \"\"\"Get the cached VarData.\n\n        Returns:\n            The cached VarData.\n        \"\"\"\n        return VarData.merge(\n            *(\n                value._get_all_var_data() if isinstance(value, Var) else None\n                for value in (\n                    getattr(self, field.name) for field in dataclasses.fields(self)\n                )\n            ),\n            self._var_data,\n        )\n\n    def __hash__(self: DataclassInstance) -> int:\n        \"\"\"Calculate the hash of the object.\n\n        Returns:\n            The hash of the object.\n        \"\"\"\n        return hash((\n            type(self).__name__,\n            *[\n                getattr(self, field.name)\n                for field in dataclasses.fields(self)\n                if field.name not in [\"_js_expr\", \"_var_data\", \"_var_type\"]\n            ],\n        ))\n\n\ndef and_operation(\n    a: Var[VAR_TYPE] | Any, b: Var[OTHER_VAR_TYPE] | Any\n) -> Var[VAR_TYPE | OTHER_VAR_TYPE]:\n    \"\"\"Perform a logical AND operation on two variables.\n\n    Args:\n        a: The first variable.\n        b: The second variable.\n\n    Returns:\n        The result of the logical AND operation.\n    \"\"\"\n    return _and_operation(a, b)\n\n\n@var_operation\ndef _and_operation(a: Var, b: Var):\n    \"\"\"Perform a logical AND operation on two variables.\n\n    Args:\n        a: The first variable.\n        b: The second variable.\n\n    Returns:\n        The result of the logical AND operation.\n    \"\"\"\n    return var_operation_return(\n        js_expression=f\"({a} && {b})\",\n        var_type=unionize(a._var_type, b._var_type),\n    )\n\n\ndef or_operation(\n    a: Var[VAR_TYPE] | Any, b: Var[OTHER_VAR_TYPE] | Any\n) -> Var[VAR_TYPE | OTHER_VAR_TYPE]:\n    \"\"\"Perform a logical OR operation on two variables.\n\n    Args:\n        a: The first variable.\n        b: The second variable.\n\n    Returns:\n        The result of the logical OR operation.\n    \"\"\"\n    return _or_operation(a, b)\n\n\n@var_operation\ndef _or_operation(a: Var, b: Var):\n    \"\"\"Perform a logical OR operation on two variables.\n\n    Args:\n        a: The first variable.\n        b: The second variable.\n\n    Returns:\n        The result of the logical OR operation.\n    \"\"\"\n    return var_operation_return(\n        js_expression=f\"({a} || {b})\",\n        var_type=unionize(a._var_type, b._var_type),\n    )\n\n\nRETURN_TYPE = TypeVar(\"RETURN_TYPE\")\n\nDICT_KEY = TypeVar(\"DICT_KEY\")\nDICT_VAL = TypeVar(\"DICT_VAL\")\n\nLIST_INSIDE = TypeVar(\"LIST_INSIDE\")\n\n\nclass FakeComputedVarBaseClass(property):\n    \"\"\"A fake base class for ComputedVar to avoid inheriting from property.\"\"\"\n\n    __pydantic_run_validation__ = False\n\n\ndef is_computed_var(obj: Any) -> TypeGuard[ComputedVar]:\n    \"\"\"Check if the object is a ComputedVar.\n\n    Args:\n        obj: The object to check.\n\n    Returns:\n        Whether the object is a ComputedVar.\n    \"\"\"\n    return isinstance(obj, FakeComputedVarBaseClass)\n\n\n@dataclasses.dataclass(\n    eq=False,\n    frozen=True,\n    slots=True,\n)\nclass ComputedVar(Var[RETURN_TYPE]):\n    \"\"\"A field with computed getters.\"\"\"\n\n    # Whether to track dependencies and cache computed values\n    _cache: bool = dataclasses.field(default=False)\n\n    # Whether the computed var is a backend var\n    _backend: bool = dataclasses.field(default=False)\n\n    # The initial value of the computed var\n    _initial_value: RETURN_TYPE | types.Unset = dataclasses.field(default=types.Unset())\n\n    # Explicit var dependencies to track\n    _static_deps: dict[str | None, set[str]] = dataclasses.field(default_factory=dict)\n\n    # Whether var dependencies should be auto-determined\n    _auto_deps: bool = dataclasses.field(default=True)\n\n    # Interval at which the computed var should be updated\n    _update_interval: datetime.timedelta | None = dataclasses.field(default=None)\n\n    _fget: Callable[[BaseState], RETURN_TYPE] = dataclasses.field(\n        default_factory=lambda: lambda _: None\n    )  # pyright: ignore [reportAssignmentType]\n\n    _name: str = dataclasses.field(default=\"\")\n\n    def __init__(\n        self,\n        fget: Callable[[BASE_STATE], RETURN_TYPE],\n        initial_value: RETURN_TYPE | types.Unset = types.Unset(),\n        cache: bool = True,\n        deps: list[str | Var] | None = None,\n        auto_deps: bool = True,\n        interval: int | datetime.timedelta | None = None,\n        backend: bool | None = None,\n        **kwargs,\n    ):\n        \"\"\"Initialize a ComputedVar.\n\n        Args:\n            fget: The getter function.\n            initial_value: The initial value of the computed var.\n            cache: Whether to cache the computed value.\n            deps: Explicit var dependencies to track.\n            auto_deps: Whether var dependencies should be auto-determined.\n            interval: Interval at which the computed var should be updated.\n            backend: Whether the computed var is a backend var.\n            **kwargs: additional attributes to set on the instance\n\n        Raises:\n            TypeError: If the computed var dependencies are not Var instances or var names.\n            UntypedComputedVarError: If the computed var is untyped.\n        \"\"\"\n        hint = kwargs.pop(\"return_type\", None) or get_type_hints(fget).get(\n            \"return\", Any\n        )\n\n        if hint is Any:\n            raise UntypedComputedVarError(var_name=fget.__name__)\n        is_using_fget_name = \"_js_expr\" not in kwargs\n        js_expr = kwargs.pop(\"_js_expr\", fget.__name__ + FIELD_MARKER)\n        kwargs.setdefault(\"_var_type\", hint)\n\n        Var.__init__(\n            self,\n            _js_expr=js_expr,\n            _var_type=kwargs.pop(\"_var_type\"),\n            _var_data=kwargs.pop(\n                \"_var_data\",\n                VarData(field_name=fget.__name__) if is_using_fget_name else None,\n            ),\n        )\n\n        if kwargs:\n            msg = f\"Unexpected keyword arguments: {tuple(kwargs)}\"\n            raise TypeError(msg)\n\n        if backend is None:\n            backend = fget.__name__.startswith(\"_\")\n\n        object.__setattr__(self, \"_backend\", backend)\n        object.__setattr__(self, \"_initial_value\", initial_value)\n        object.__setattr__(self, \"_cache\", cache)\n        object.__setattr__(self, \"_name\", fget.__name__)\n\n        if isinstance(interval, int):\n            interval = datetime.timedelta(seconds=interval)\n\n        object.__setattr__(self, \"_update_interval\", interval)\n\n        object.__setattr__(\n            self,\n            \"_static_deps\",\n            self._calculate_static_deps(deps),\n        )\n        object.__setattr__(self, \"_auto_deps\", auto_deps)\n\n        object.__setattr__(self, \"_fget\", fget)\n\n    def _calculate_static_deps(\n        self,\n        deps: list[str | Var] | dict[str | None, set[str]] | None = None,\n    ) -> dict[str | None, set[str]]:\n        \"\"\"Calculate the static dependencies of the computed var from user input or existing dependencies.\n\n        Args:\n            deps: The user input dependencies or existing dependencies.\n\n        Returns:\n            The static dependencies.\n        \"\"\"\n        if isinstance(deps, dict):\n            # Assume a dict is coming from _replace, so no special processing.\n            return deps\n        static_deps = {}\n        if deps is not None:\n            for dep in deps:\n                static_deps = self._add_static_dep(dep, static_deps)\n        return static_deps\n\n    def _add_static_dep(\n        self, dep: str | Var, deps: dict[str | None, set[str]] | None = None\n    ) -> dict[str | None, set[str]]:\n        \"\"\"Add a static dependency to the computed var or existing dependency set.\n\n        Args:\n            dep: The dependency to add.\n            deps: The existing dependency set.\n\n        Returns:\n            The updated dependency set.\n\n        Raises:\n            TypeError: If the computed var dependencies are not Var instances or var names.\n        \"\"\"\n        if deps is None:\n            deps = self._static_deps\n        if isinstance(dep, Var):\n            state_name = (\n                all_var_data.state\n                if (all_var_data := dep._get_all_var_data()) and all_var_data.state\n                else None\n            )\n            if all_var_data is not None:\n                var_name = all_var_data.field_name\n            else:\n                var_name = dep._js_expr\n            deps.setdefault(state_name, set()).add(var_name)\n        elif isinstance(dep, str) and dep != \"\":\n            deps.setdefault(None, set()).add(dep)\n        else:\n            msg = \"ComputedVar dependencies must be Var instances or var names (non-empty strings).\"\n            raise TypeError(msg)\n        return deps\n\n    @override\n    def _replace(\n        self,\n        merge_var_data: VarData | None = None,\n        **kwargs: Any,\n    ) -> Self:\n        \"\"\"Replace the attributes of the ComputedVar.\n\n        Args:\n            merge_var_data: VarData to merge into the existing VarData.\n            **kwargs: Var fields to update.\n\n        Returns:\n            The new ComputedVar instance.\n\n        Raises:\n            TypeError: If kwargs contains keys that are not allowed.\n        \"\"\"\n        if \"deps\" in kwargs:\n            kwargs[\"deps\"] = self._calculate_static_deps(kwargs[\"deps\"])\n        field_values = {\n            \"fget\": kwargs.pop(\"fget\", self._fget),\n            \"initial_value\": kwargs.pop(\"initial_value\", self._initial_value),\n            \"cache\": kwargs.pop(\"cache\", self._cache),\n            \"deps\": kwargs.pop(\"deps\", copy.copy(self._static_deps)),\n            \"auto_deps\": kwargs.pop(\"auto_deps\", self._auto_deps),\n            \"interval\": kwargs.pop(\"interval\", self._update_interval),\n            \"backend\": kwargs.pop(\"backend\", self._backend),\n            \"_js_expr\": kwargs.pop(\"_js_expr\", self._js_expr),\n            \"_var_type\": kwargs.pop(\"_var_type\", self._var_type),\n            \"_var_data\": kwargs.pop(\n                \"_var_data\", VarData.merge(self._var_data, merge_var_data)\n            ),\n            \"return_type\": kwargs.pop(\"return_type\", self._var_type),\n        }\n\n        if kwargs:\n            unexpected_kwargs = \", \".join(kwargs.keys())\n            msg = f\"Unexpected keyword arguments: {unexpected_kwargs}\"\n            raise TypeError(msg)\n\n        return type(self)(**field_values)\n\n    @property\n    def _cache_attr(self) -> str:\n        \"\"\"Get the attribute used to cache the value on the instance.\n\n        Returns:\n            An attribute name.\n        \"\"\"\n        return f\"__cached_{self._js_expr}\"\n\n    @property\n    def _last_updated_attr(self) -> str:\n        \"\"\"Get the attribute used to store the last updated timestamp.\n\n        Returns:\n            An attribute name.\n        \"\"\"\n        return f\"__last_updated_{self._js_expr}\"\n\n    def needs_update(self, instance: BaseState) -> bool:\n        \"\"\"Check if the computed var needs to be updated.\n\n        Args:\n            instance: The state instance that the computed var is attached to.\n\n        Returns:\n            True if the computed var needs to be updated, False otherwise.\n        \"\"\"\n        if self._update_interval is None:\n            return False\n        last_updated = getattr(instance, self._last_updated_attr, None)\n        if last_updated is None:\n            return True\n        return datetime.datetime.now() - last_updated > self._update_interval\n\n    @overload\n    def __get__(\n        self: ComputedVar[bool],\n        instance: None,\n        owner: type,\n    ) -> BooleanVar: ...\n\n    @overload\n    def __get__(\n        self: ComputedVar[int] | ComputedVar[float],\n        instance: None,\n        owner: type,\n    ) -> NumberVar: ...\n\n    @overload\n    def __get__(\n        self: ComputedVar[str],\n        instance: None,\n        owner: type,\n    ) -> StringVar: ...\n\n    @overload\n    def __get__(\n        self: ComputedVar[MAPPING_TYPE],\n        instance: None,\n        owner: type,\n    ) -> ObjectVar[MAPPING_TYPE]: ...\n\n    @overload\n    def __get__(\n        self: ComputedVar[list[LIST_INSIDE]],\n        instance: None,\n        owner: type,\n    ) -> ArrayVar[list[LIST_INSIDE]]: ...\n\n    @overload\n    def __get__(\n        self: ComputedVar[tuple[LIST_INSIDE, ...]],\n        instance: None,\n        owner: type,\n    ) -> ArrayVar[tuple[LIST_INSIDE, ...]]: ...\n\n    @overload\n    def __get__(\n        self: ComputedVar[BASE_TYPE],\n        instance: None,\n        owner: type,\n    ) -> ObjectVar[BASE_TYPE]: ...\n\n    @overload\n    def __get__(\n        self: ComputedVar[SQLA_TYPE],\n        instance: None,\n        owner: type,\n    ) -> ObjectVar[SQLA_TYPE]: ...\n\n    if TYPE_CHECKING:\n\n        @overload\n        def __get__(\n            self: ComputedVar[DATACLASS_TYPE], instance: None, owner: Any\n        ) -> ObjectVar[DATACLASS_TYPE]: ...\n\n    @overload\n    def __get__(self, instance: None, owner: type) -> ComputedVar[RETURN_TYPE]: ...\n\n    @overload\n    def __get__(self, instance: BaseState, owner: type) -> RETURN_TYPE: ...\n\n    def __get__(self, instance: BaseState | None, owner: type):\n        \"\"\"Get the ComputedVar value.\n\n        If the value is already cached on the instance, return the cached value.\n\n        Args:\n            instance: the instance of the class accessing this computed var.\n            owner: the class that this descriptor is attached to.\n\n        Returns:\n            The value of the var for the given instance.\n        \"\"\"\n        if instance is None:\n            state_where_defined = owner\n            while self._name in state_where_defined.inherited_vars:\n                state_where_defined = state_where_defined.get_parent_state()\n\n            field_name = (\n                format_state_name(state_where_defined.get_full_name())\n                + \".\"\n                + self._js_expr\n            )\n\n            return dispatch(\n                field_name,\n                var_data=VarData.from_state(state_where_defined, self._name),\n                result_var_type=self._var_type,\n                existing_var=self,\n            )\n\n        if not self._cache:\n            value = self.fget(instance)\n        else:\n            # handle caching\n            if not hasattr(instance, self._cache_attr) or self.needs_update(instance):\n                # Set cache attr on state instance.\n                setattr(instance, self._cache_attr, self.fget(instance))\n                # Ensure the computed var gets serialized to redis.\n                instance._was_touched = True\n                # Set the last updated timestamp on the state instance.\n                setattr(instance, self._last_updated_attr, datetime.datetime.now())\n            value = getattr(instance, self._cache_attr)\n\n        self._check_deprecated_return_type(instance, value)\n\n        return value\n\n    def _check_deprecated_return_type(self, instance: BaseState, value: Any) -> None:\n        if not _isinstance(value, self._var_type, nested=1, treat_var_as_type=False):\n            console.error(\n                f\"Computed var '{type(instance).__name__}.{self._name}' must return\"\n                f\" a value of type '{escape(str(self._var_type))}', got '{value!s}' of type {type(value)}.\"\n            )\n\n    def _deps(\n        self,\n        objclass: type[BaseState],\n        obj: FunctionType | CodeType | None = None,\n    ) -> dict[str, set[str]]:\n        \"\"\"Determine var dependencies of this ComputedVar.\n\n        Save references to attributes accessed on \"self\" or other fetched states.\n\n        Recursively called when the function makes a method call on \"self\" or\n        define comprehensions or nested functions that may reference \"self\".\n\n        Args:\n            objclass: the class obj this ComputedVar is attached to.\n            obj: the object to disassemble (defaults to the fget function).\n\n        Returns:\n            A dictionary mapping state names to the set of variable names\n            accessed by the given obj.\n        \"\"\"\n        from .dep_tracking import DependencyTracker\n\n        d = {}\n        if self._static_deps:\n            d.update(self._static_deps)\n            # None is a placeholder for the current state class.\n            if None in d:\n                d[objclass.get_full_name()] = d.pop(None)\n\n        if not self._auto_deps:\n            return d\n\n        if obj is None:\n            fget = self._fget\n            if fget is not None:\n                obj = cast(FunctionType, fget)\n            else:\n                return d\n\n        try:\n            return DependencyTracker(\n                func=obj, state_cls=objclass, dependencies=d\n            ).dependencies\n        except Exception as e:\n            console.warn(\n                \"Failed to automatically determine dependencies for computed var \"\n                f\"{objclass.__name__}.{self._name}: {e}. \"\n                \"Set auto_deps=False and provide accurate deps=['var1', 'var2'] to suppress this warning.\"\n            )\n            return d\n\n    def mark_dirty(self, instance: BaseState) -> None:\n        \"\"\"Mark this ComputedVar as dirty.\n\n        Args:\n            instance: the state instance that needs to recompute the value.\n        \"\"\"\n        with contextlib.suppress(AttributeError):\n            delattr(instance, self._cache_attr)\n\n    def add_dependency(self, objclass: type[BaseState], dep: Var):\n        \"\"\"Explicitly add a dependency to the ComputedVar.\n\n        After adding the dependency, when the `dep` changes, this computed var\n        will be marked dirty.\n\n        Args:\n            objclass: The class obj this ComputedVar is attached to.\n            dep: The dependency to add.\n\n        Raises:\n            VarDependencyError: If the dependency is not a Var instance with a\n                state and field name\n        \"\"\"\n        if all_var_data := dep._get_all_var_data():\n            state_name = all_var_data.state\n            if state_name:\n                var_name = all_var_data.field_name\n                if var_name:\n                    self._static_deps.setdefault(state_name, set()).add(var_name)\n                    target_state_class = objclass.get_root_state().get_class_substate(\n                        state_name\n                    )\n                    target_state_class._var_dependencies.setdefault(\n                        var_name, set()\n                    ).add((\n                        objclass.get_full_name(),\n                        self._name,\n                    ))\n                    target_state_class._potentially_dirty_states.add(\n                        objclass.get_full_name()\n                    )\n                    return\n        msg = (\n            \"ComputedVar dependencies must be Var instances with a state and \"\n            f\"field name, got {dep!r}.\"\n        )\n        raise VarDependencyError(msg)\n\n    def _determine_var_type(self) -> type:\n        \"\"\"Get the type of the var.\n\n        Returns:\n            The type of the var.\n        \"\"\"\n        hints = get_type_hints(self._fget)\n        if \"return\" in hints:\n            return hints[\"return\"]\n        return Any  # pyright: ignore [reportReturnType]\n\n    @property\n    def __class__(self) -> type:\n        \"\"\"Get the class of the var.\n\n        Returns:\n            The class of the var.\n        \"\"\"\n        return FakeComputedVarBaseClass\n\n    @property\n    def fget(self) -> Callable[[BaseState], RETURN_TYPE]:\n        \"\"\"Get the getter function.\n\n        Returns:\n            The getter function.\n        \"\"\"\n        return self._fget\n\n\nclass DynamicRouteVar(ComputedVar[str | list[str]]):\n    \"\"\"A ComputedVar that represents a dynamic route.\"\"\"\n\n\nasync def _default_async_computed_var(_self: BaseState) -> Any:  # noqa: RUF029\n    return None\n\n\n@dataclasses.dataclass(\n    eq=False,\n    frozen=True,\n    init=False,\n    slots=True,\n)\nclass AsyncComputedVar(ComputedVar[RETURN_TYPE]):\n    \"\"\"A computed var that wraps a coroutinefunction.\"\"\"\n\n    _fget: Callable[[BaseState], Coroutine[None, None, RETURN_TYPE]] = (\n        dataclasses.field(default=_default_async_computed_var)\n    )\n\n    @overload\n    def __get__(\n        self: AsyncComputedVar[bool],\n        instance: None,\n        owner: type,\n    ) -> BooleanVar: ...\n\n    @overload\n    def __get__(\n        self: AsyncComputedVar[int] | ComputedVar[float],\n        instance: None,\n        owner: type,\n    ) -> NumberVar: ...\n\n    @overload\n    def __get__(\n        self: AsyncComputedVar[str],\n        instance: None,\n        owner: type,\n    ) -> StringVar: ...\n\n    @overload\n    def __get__(\n        self: AsyncComputedVar[MAPPING_TYPE],\n        instance: None,\n        owner: type,\n    ) -> ObjectVar[MAPPING_TYPE]: ...\n\n    @overload\n    def __get__(\n        self: AsyncComputedVar[list[LIST_INSIDE]],\n        instance: None,\n        owner: type,\n    ) -> ArrayVar[list[LIST_INSIDE]]: ...\n\n    @overload\n    def __get__(\n        self: AsyncComputedVar[tuple[LIST_INSIDE, ...]],\n        instance: None,\n        owner: type,\n    ) -> ArrayVar[tuple[LIST_INSIDE, ...]]: ...\n\n    @overload\n    def __get__(\n        self: AsyncComputedVar[BASE_TYPE],\n        instance: None,\n        owner: type,\n    ) -> ObjectVar[BASE_TYPE]: ...\n\n    @overload\n    def __get__(\n        self: AsyncComputedVar[SQLA_TYPE],\n        instance: None,\n        owner: type,\n    ) -> ObjectVar[SQLA_TYPE]: ...\n\n    if TYPE_CHECKING:\n\n        @overload\n        def __get__(\n            self: AsyncComputedVar[DATACLASS_TYPE], instance: None, owner: Any\n        ) -> ObjectVar[DATACLASS_TYPE]: ...\n\n    @overload\n    def __get__(self, instance: None, owner: type) -> AsyncComputedVar[RETURN_TYPE]: ...\n\n    @overload\n    def __get__(\n        self, instance: BaseState, owner: type\n    ) -> Coroutine[None, None, RETURN_TYPE]: ...\n\n    def __get__(\n        self, instance: BaseState | None, owner\n    ) -> Var | Coroutine[None, None, RETURN_TYPE]:\n        \"\"\"Get the ComputedVar value.\n\n        If the value is already cached on the instance, return the cached value.\n\n        Args:\n            instance: the instance of the class accessing this computed var.\n            owner: the class that this descriptor is attached to.\n\n        Returns:\n            The value of the var for the given instance.\n        \"\"\"\n        if instance is None:\n            return super(AsyncComputedVar, self).__get__(instance, owner)\n\n        if not self._cache:\n\n            async def _awaitable_result(instance: BaseState = instance) -> RETURN_TYPE:\n                value = await self.fget(instance)\n                self._check_deprecated_return_type(instance, value)\n                return value\n\n            return _awaitable_result()\n\n        # handle caching\n        async def _awaitable_result(instance: BaseState = instance) -> RETURN_TYPE:\n            if not hasattr(instance, self._cache_attr) or self.needs_update(instance):\n                # Set cache attr on state instance.\n                setattr(instance, self._cache_attr, await self.fget(instance))\n                # Ensure the computed var gets serialized to redis.\n                instance._was_touched = True\n                # Set the last updated timestamp on the state instance.\n                setattr(instance, self._last_updated_attr, datetime.datetime.now())\n            value = getattr(instance, self._cache_attr)\n            self._check_deprecated_return_type(instance, value)\n            return value\n\n        return _awaitable_result()\n\n    @property\n    def fget(self) -> Callable[[BaseState], Coroutine[None, None, RETURN_TYPE]]:\n        \"\"\"Get the getter function.\n\n        Returns:\n            The getter function.\n        \"\"\"\n        return self._fget\n\n\nif TYPE_CHECKING:\n    BASE_STATE = TypeVar(\"BASE_STATE\", bound=BaseState)\n\n\nclass _ComputedVarDecorator(Protocol):\n    \"\"\"A protocol for the ComputedVar decorator.\"\"\"\n\n    @overload\n    def __call__(\n        self,\n        fget: Callable[[BASE_STATE], Coroutine[Any, Any, RETURN_TYPE]],\n    ) -> AsyncComputedVar[RETURN_TYPE]: ...\n\n    @overload\n    def __call__(\n        self,\n        fget: Callable[[BASE_STATE], RETURN_TYPE],\n    ) -> ComputedVar[RETURN_TYPE]: ...\n\n    def __call__(\n        self,\n        fget: Callable[[BASE_STATE], Any],\n    ) -> ComputedVar[Any]: ...\n\n\n@overload\ndef computed_var(\n    fget: None = None,\n    initial_value: Any | types.Unset = types.Unset(),\n    cache: bool = True,\n    deps: list[str | Var] | None = None,\n    auto_deps: bool = True,\n    interval: datetime.timedelta | int | None = None,\n    backend: bool | None = None,\n    **kwargs,\n) -> _ComputedVarDecorator: ...\n\n\n@overload\ndef computed_var(\n    fget: Callable[[BASE_STATE], Coroutine[Any, Any, RETURN_TYPE]],\n    initial_value: RETURN_TYPE | types.Unset = types.Unset(),\n    cache: bool = True,\n    deps: list[str | Var] | None = None,\n    auto_deps: bool = True,\n    interval: datetime.timedelta | int | None = None,\n    backend: bool | None = None,\n    **kwargs,\n) -> AsyncComputedVar[RETURN_TYPE]: ...\n\n\n@overload\ndef computed_var(\n    fget: Callable[[BASE_STATE], RETURN_TYPE],\n    initial_value: RETURN_TYPE | types.Unset = types.Unset(),\n    cache: bool = True,\n    deps: list[str | Var] | None = None,\n    auto_deps: bool = True,\n    interval: datetime.timedelta | int | None = None,\n    backend: bool | None = None,\n    **kwargs,\n) -> ComputedVar[RETURN_TYPE]: ...\n\n\ndef computed_var(\n    fget: Callable[[BASE_STATE], Any] | None = None,\n    initial_value: Any | types.Unset = types.Unset(),\n    cache: bool = True,\n    deps: list[str | Var] | None = None,\n    auto_deps: bool = True,\n    interval: datetime.timedelta | int | None = None,\n    backend: bool | None = None,\n    **kwargs,\n) -> ComputedVar | Callable[[Callable[[BASE_STATE], Any]], ComputedVar]:\n    \"\"\"A ComputedVar decorator with or without kwargs.\n\n    Args:\n        fget: The getter function.\n        initial_value: The initial value of the computed var.\n        cache: Whether to cache the computed value.\n        deps: Explicit var dependencies to track.\n        auto_deps: Whether var dependencies should be auto-determined.\n        interval: Interval at which the computed var should be updated.\n        backend: Whether the computed var is a backend var.\n        **kwargs: additional attributes to set on the instance\n\n    Returns:\n        A ComputedVar instance.\n\n    Raises:\n        ValueError: If caching is disabled and an update interval is set.\n        VarDependencyError: If user supplies dependencies without caching.\n        ComputedVarSignatureError: If the getter function has more than one argument.\n    \"\"\"\n    if cache is False and interval is not None:\n        msg = \"Cannot set update interval without caching.\"\n        raise ValueError(msg)\n\n    if cache is False and (deps is not None or auto_deps is False):\n        msg = \"Cannot track dependencies without caching.\"\n        raise VarDependencyError(msg)\n\n    if fget is not None:\n        sign = inspect.signature(fget)\n        if len(sign.parameters) != 1:\n            raise ComputedVarSignatureError(fget.__name__, signature=str(sign))\n\n        if inspect.iscoroutinefunction(fget):\n            computed_var_cls = AsyncComputedVar\n        else:\n            computed_var_cls = ComputedVar\n        return computed_var_cls(\n            fget,\n            initial_value=initial_value,\n            cache=cache,\n            deps=deps,\n            auto_deps=auto_deps,\n            interval=interval,\n            backend=backend,\n            **kwargs,\n        )\n\n    def wrapper(fget: Callable[[BASE_STATE], Any]) -> ComputedVar:\n        if inspect.iscoroutinefunction(fget):\n            computed_var_cls = AsyncComputedVar\n        else:\n            computed_var_cls = ComputedVar\n        return computed_var_cls(\n            fget,\n            initial_value=initial_value,\n            cache=cache,\n            deps=deps,\n            auto_deps=auto_deps,\n            interval=interval,\n            backend=backend,\n            **kwargs,\n        )\n\n    return wrapper\n\n\nRETURN = TypeVar(\"RETURN\")\n\n\nclass CustomVarOperationReturn(Var[RETURN]):\n    \"\"\"Base class for custom var operations.\"\"\"\n\n    @classmethod\n    def create(\n        cls,\n        js_expression: str,\n        _var_type: type[RETURN] | None = None,\n        _var_data: VarData | None = None,\n    ) -> CustomVarOperationReturn[RETURN]:\n        \"\"\"Create a CustomVarOperation.\n\n        Args:\n            js_expression: The JavaScript expression to evaluate.\n            _var_type: The type of the var.\n            _var_data: Additional hooks and imports associated with the Var.\n\n        Returns:\n            The CustomVarOperation.\n        \"\"\"\n        return CustomVarOperationReturn(\n            _js_expr=js_expression,\n            _var_type=_var_type or Any,\n            _var_data=_var_data,\n        )\n\n\ndef var_operation_return(\n    js_expression: str,\n    var_type: type[RETURN] | GenericType | None = None,\n    var_data: VarData | None = None,\n) -> CustomVarOperationReturn[RETURN]:\n    \"\"\"Shortcut for creating a CustomVarOperationReturn.\n\n    Args:\n        js_expression: The JavaScript expression to evaluate.\n        var_type: The type of the var.\n        var_data: Additional hooks and imports associated with the Var.\n\n    Returns:\n        The CustomVarOperationReturn.\n    \"\"\"\n    return CustomVarOperationReturn.create(\n        js_expression,\n        var_type,\n        var_data,\n    )\n\n\n@dataclasses.dataclass(\n    eq=False,\n    frozen=True,\n    slots=True,\n)\nclass CustomVarOperation(CachedVarOperation, Var[T]):\n    \"\"\"Base class for custom var operations.\"\"\"\n\n    _name: str = dataclasses.field(default=\"\")\n\n    _args: tuple[tuple[str, Var], ...] = dataclasses.field(default_factory=tuple)\n\n    _return: CustomVarOperationReturn[T] = dataclasses.field(\n        default_factory=lambda: CustomVarOperationReturn.create(\"\")\n    )\n\n    @cached_property_no_lock\n    def _cached_var_name(self) -> str:\n        \"\"\"Get the cached var name.\n\n        Returns:\n            The cached var name.\n        \"\"\"\n        return str(self._return)\n\n    @cached_property_no_lock\n    def _cached_get_all_var_data(self) -> VarData | None:\n        \"\"\"Get the cached VarData.\n\n        Returns:\n            The cached VarData.\n        \"\"\"\n        return VarData.merge(\n            *(arg[1]._get_all_var_data() for arg in self._args),\n            self._return._get_all_var_data(),\n            self._var_data,\n        )\n\n    @classmethod\n    def create(\n        cls,\n        name: str,\n        args: tuple[tuple[str, Var], ...],\n        return_var: CustomVarOperationReturn[T],\n        _var_data: VarData | None = None,\n    ) -> CustomVarOperation[T]:\n        \"\"\"Create a CustomVarOperation.\n\n        Args:\n            name: The name of the operation.\n            args: The arguments to the operation.\n            return_var: The return var.\n            _var_data: Additional hooks and imports associated with the Var.\n\n        Returns:\n            The CustomVarOperation.\n        \"\"\"\n        return CustomVarOperation(\n            _js_expr=\"\",\n            _var_type=return_var._var_type,\n            _var_data=_var_data,\n            _name=name,\n            _args=args,\n            _return=return_var,\n        )\n\n\nclass NoneVar(Var[None], python_types=type(None)):\n    \"\"\"A var representing None.\"\"\"\n\n\n@dataclasses.dataclass(\n    eq=False,\n    frozen=True,\n    slots=True,\n)\nclass LiteralNoneVar(LiteralVar, NoneVar):\n    \"\"\"A var representing None.\"\"\"\n\n    _var_value: None = None\n\n    def json(self) -> str:\n        \"\"\"Serialize the var to a JSON string.\n\n        Returns:\n            The JSON string.\n        \"\"\"\n        return \"null\"\n\n    @classmethod\n    def _get_all_var_data_without_creating_var(cls, value: None) -> VarData | None:\n        return None\n\n    @classmethod\n    def create(\n        cls,\n        value: None = None,\n        _var_data: VarData | None = None,\n    ) -> LiteralNoneVar:\n        \"\"\"Create a var from a value.\n\n        Args:\n            value: The value of the var. Must be None. Existed for compatibility with LiteralVar.\n            _var_data: Additional hooks and imports associated with the Var.\n\n        Returns:\n            The var.\n        \"\"\"\n        return LiteralNoneVar(\n            _js_expr=\"null\",\n            _var_type=None,\n            _var_data=_var_data,\n        )\n\n\ndef get_to_operation(var_subclass: type[Var]) -> type[ToOperation]:\n    \"\"\"Get the ToOperation class for a given Var subclass.\n\n    Args:\n        var_subclass: The Var subclass.\n\n    Returns:\n        The ToOperation class.\n\n    Raises:\n        ValueError: If the ToOperation class cannot be found.\n    \"\"\"\n    possible_classes = [\n        saved_var_subclass.to_var_subclass\n        for saved_var_subclass in _var_subclasses\n        if saved_var_subclass.var_subclass is var_subclass\n    ]\n    if not possible_classes:\n        msg = f\"Could not find ToOperation for {var_subclass}.\"\n        raise ValueError(msg)\n    return possible_classes[0]\n\n\n@dataclasses.dataclass(\n    eq=False,\n    frozen=True,\n    slots=True,\n)\nclass StateOperation(CachedVarOperation, Var):\n    \"\"\"A var operation that accesses a field on an object.\"\"\"\n\n    _state_name: str = dataclasses.field(default=\"\")\n    _field: Var = dataclasses.field(default_factory=lambda: LiteralNoneVar.create())\n\n    @cached_property_no_lock\n    def _cached_var_name(self) -> str:\n        \"\"\"Get the cached var name.\n\n        Returns:\n            The cached var name.\n        \"\"\"\n        return f\"{self._state_name!s}.{self._field!s}\"\n\n    def __getattr__(self, name: str) -> Any:\n        \"\"\"Get an attribute of the var.\n\n        Args:\n            name: The name of the attribute.\n\n        Returns:\n            The attribute.\n        \"\"\"\n        if name == \"_js_expr\":\n            return self._cached_var_name\n\n        return getattr(self._field, name)\n\n    @classmethod\n    def create(\n        cls,\n        state_name: str,\n        field: Var,\n        _var_data: VarData | None = None,\n    ) -> StateOperation:\n        \"\"\"Create a DotOperation.\n\n        Args:\n            state_name: The name of the state.\n            field: The field of the state.\n            _var_data: Additional hooks and imports associated with the Var.\n\n        Returns:\n            The DotOperation.\n        \"\"\"\n        return StateOperation(\n            _js_expr=\"\",\n            _var_type=field._var_type,\n            _var_data=_var_data,\n            _state_name=state_name,\n            _field=field,\n        )\n\n\ndef get_uuid_string_var() -> Var:\n    \"\"\"Return a Var that generates a single memoized UUID via .web/utils/state.js.\n\n    useMemo with an empty dependency array ensures that the generated UUID is\n    consistent across re-renders of the component.\n\n    Returns:\n        A Var that generates a UUID at runtime.\n    \"\"\"\n    from reflex.utils.imports import ImportVar\n    from reflex.vars import Var\n\n    unique_uuid_var = get_unique_variable_name()\n    unique_uuid_var_data = VarData(\n        imports={\n            f\"$/{constants.Dirs.STATE_PATH}\": ImportVar(tag=\"generateUUID\"),\n            \"react\": \"useMemo\",\n        },\n        hooks={f\"const {unique_uuid_var} = useMemo(generateUUID, [])\": None},\n    )\n\n    return Var(\n        _js_expr=unique_uuid_var,\n        _var_type=str,\n        _var_data=unique_uuid_var_data,\n    )\n\n\n# Set of unique variable names.\nUSED_VARIABLES = set()\n\n\n@once\ndef _rng():\n    import random\n\n    return random.Random(42)\n\n\ndef get_unique_variable_name() -> str:\n    \"\"\"Get a unique variable name.\n\n    Returns:\n        The unique variable name.\n    \"\"\"\n    name = \"\".join([_rng().choice(string.ascii_lowercase) for _ in range(8)])\n    if name not in USED_VARIABLES:\n        USED_VARIABLES.add(name)\n        return name\n    return get_unique_variable_name()\n\n\n# Compile regex for finding reflex var tags.\n_decode_var_pattern_re = (\n    rf\"{constants.REFLEX_VAR_OPENING_TAG}(.*?){constants.REFLEX_VAR_CLOSING_TAG}\"\n)\n_decode_var_pattern = re.compile(_decode_var_pattern_re, flags=re.DOTALL)\n\n# Defined global immutable vars.\n_global_vars: dict[int, Var] = {}\n\n\ndispatchers: dict[GenericType, Callable[[Var], Var]] = {}\n\n\ndef transform(fn: Callable[[Var], Var]) -> Callable[[Var], Var]:\n    \"\"\"Register a function to transform a Var.\n\n    Args:\n        fn: The function to register.\n\n    Returns:\n        The decorator.\n\n    Raises:\n        TypeError: If the return type of the function is not a Var.\n        TypeError: If the Var return type does not have a generic type.\n        ValueError: If a function for the generic type is already registered.\n    \"\"\"\n    types = get_type_hints(fn)\n    return_type = types[\"return\"]\n\n    origin = get_origin(return_type)\n\n    if origin is not Var:\n        msg = f\"Expected return type of {fn.__name__} to be a Var, got {origin}.\"\n        raise TypeError(msg)\n\n    generic_args = get_args(return_type)\n\n    if not generic_args:\n        msg = f\"Expected Var return type of {fn.__name__} to have a generic type.\"\n        raise TypeError(msg)\n\n    generic_type = get_origin(generic_args[0]) or generic_args[0]\n\n    if generic_type in dispatchers:\n        msg = f\"Function for {generic_type} already registered.\"\n        raise ValueError(msg)\n\n    dispatchers[generic_type] = fn\n\n    return fn\n\n\ndef dispatch(\n    field_name: str,\n    var_data: VarData,\n    result_var_type: GenericType,\n    existing_var: Var | None = None,\n) -> Var:\n    \"\"\"Dispatch a Var to the appropriate transformation function.\n\n    Args:\n        field_name: The name of the field.\n        var_data: The VarData associated with the Var.\n        result_var_type: The type of the Var.\n        existing_var: The existing Var to transform. Optional.\n\n    Returns:\n        The transformed Var.\n\n    Raises:\n        TypeError: If the return type of the function is not a Var.\n        TypeError: If the Var return type does not have a generic type.\n        TypeError: If the first argument of the function is not a Var.\n        TypeError: If the first argument of the function does not have a generic type\n    \"\"\"\n    result_origin_var_type = get_origin(result_var_type) or result_var_type\n\n    if result_origin_var_type in dispatchers:\n        fn = dispatchers[result_origin_var_type]\n        fn_types = get_type_hints(fn)\n        fn_first_arg_type = fn_types.get(\n            next(iter(inspect.signature(fn).parameters.values())).name, Any\n        )\n\n        fn_return = fn_types.get(\"return\", Any)\n\n        fn_return_origin = get_origin(fn_return) or fn_return\n\n        if fn_return_origin is not Var:\n            msg = f\"Expected return type of {fn.__name__} to be a Var, got {fn_return}.\"\n            raise TypeError(msg)\n\n        fn_return_generic_args = get_args(fn_return)\n\n        if not fn_return_generic_args:\n            msg = f\"Expected generic type of {fn_return} to be a type.\"\n            raise TypeError(msg)\n\n        arg_origin = get_origin(fn_first_arg_type) or fn_first_arg_type\n\n        if arg_origin is not Var:\n            msg = f\"Expected first argument of {fn.__name__} to be a Var, got {fn_first_arg_type}.\"\n            raise TypeError(msg)\n\n        arg_generic_args = get_args(fn_first_arg_type)\n\n        if not arg_generic_args:\n            msg = f\"Expected generic type of {fn_first_arg_type} to be a type.\"\n            raise TypeError(msg)\n\n        fn_return_type = fn_return_generic_args[0]\n\n        var = (\n            Var(\n                field_name,\n                _var_data=var_data,\n                _var_type=fn_return_type,\n            ).guess_type()\n            if existing_var is None\n            else existing_var._replace(\n                _var_type=fn_return_type,\n                _var_data=var_data,\n                _js_expr=field_name,\n            ).guess_type()\n        )\n\n        return fn(var)\n\n    if existing_var is not None:\n        return existing_var._replace(\n            _js_expr=field_name,\n            _var_data=var_data,\n            _var_type=result_var_type,\n        ).guess_type()\n    return Var(\n        field_name,\n        _var_data=var_data,\n        _var_type=result_var_type,\n    ).guess_type()\n\n\nif TYPE_CHECKING:\n    from _typeshed import DataclassInstance\n    from sqlalchemy.orm import DeclarativeBase\n\n    from reflex.base import Base\n\n    SQLA_TYPE = TypeVar(\"SQLA_TYPE\", bound=DeclarativeBase | None)\n    BASE_TYPE = TypeVar(\"BASE_TYPE\", bound=Base | None)\n    DATACLASS_TYPE = TypeVar(\"DATACLASS_TYPE\", bound=DataclassInstance | None)\n    MAPPING_TYPE = TypeVar(\"MAPPING_TYPE\", bound=Mapping | None)\n    V = TypeVar(\"V\")\n\n\nFIELD_TYPE = TypeVar(\"FIELD_TYPE\")\n\n\nclass Field(Generic[FIELD_TYPE]):\n    \"\"\"A field for a state.\"\"\"\n\n    if TYPE_CHECKING:\n        type_: GenericType\n        default: FIELD_TYPE | _MISSING_TYPE\n        default_factory: Callable[[], FIELD_TYPE] | None\n\n    def __init__(\n        self,\n        default: FIELD_TYPE | _MISSING_TYPE = MISSING,\n        default_factory: Callable[[], FIELD_TYPE] | None = None,\n        is_var: bool = True,\n        annotated_type: GenericType  # pyright: ignore [reportRedeclaration]\n        | _MISSING_TYPE = MISSING,\n    ) -> None:\n        \"\"\"Initialize the field.\n\n        Args:\n            default: The default value for the field.\n            default_factory: The default factory for the field.\n            is_var: Whether the field is a Var.\n            annotated_type: The annotated type for the field.\n        \"\"\"\n        self.default = default\n        self.default_factory = default_factory\n        self.is_var = is_var\n        if annotated_type is not MISSING:\n            type_origin = get_origin(annotated_type) or annotated_type\n            if type_origin is Field and (\n                args := getattr(annotated_type, \"__args__\", None)\n            ):\n                annotated_type: GenericType = args[0]\n                type_origin = get_origin(annotated_type) or annotated_type\n\n            if self.default is MISSING and self.default_factory is None:\n                default_value = types.get_default_value_for_type(annotated_type)\n                if default_value is None and not types.is_optional(annotated_type):\n                    annotated_type = annotated_type | None\n                if types.is_immutable(default_value):\n                    self.default = default_value\n                else:\n                    self.default_factory = functools.partial(\n                        copy.deepcopy, default_value\n                    )\n            self.outer_type_ = self.annotated_type = annotated_type\n\n            if type_origin is Annotated:\n                type_origin = annotated_type.__origin__  # pyright: ignore [reportAttributeAccessIssue]\n\n            self.type_ = self.type_origin = type_origin\n        else:\n            self.outer_type_ = self.annotated_type = self.type_ = self.type_origin = Any\n\n    def default_value(self) -> FIELD_TYPE:\n        \"\"\"Get the default value for the field.\n\n        Returns:\n            The default value for the field.\n\n        Raises:\n            ValueError: If no default value or factory is provided.\n        \"\"\"\n        if self.default is not MISSING:\n            return self.default\n        if self.default_factory is not None:\n            return self.default_factory()\n        msg = \"No default value or factory provided.\"\n        raise ValueError(msg)\n\n    def __repr__(self) -> str:\n        \"\"\"Represent the field in a readable format.\n\n        Returns:\n            The string representation of the field.\n        \"\"\"\n        annotated_type_str = (\n            f\", annotated_type={self.annotated_type!r}\"\n            if self.annotated_type is not MISSING\n            else \"\"\n        )\n        if self.default is not MISSING:\n            return f\"Field(default={self.default!r}, is_var={self.is_var}{annotated_type_str})\"\n        return f\"Field(default_factory={self.default_factory!r}, is_var={self.is_var}{annotated_type_str})\"\n\n    if TYPE_CHECKING:\n\n        def __set__(self, instance: Any, value: FIELD_TYPE):\n            \"\"\"Set the Var.\n\n            Args:\n                instance: The instance of the class setting the Var.\n                value: The value to set the Var to.\n\n            # noqa: DAR101 self\n            \"\"\"\n\n    @overload\n    def __get__(self: Field[None], instance: None, owner: Any) -> NoneVar: ...\n\n    @overload\n    def __get__(\n        self: Field[bool] | Field[bool | None], instance: None, owner: Any\n    ) -> BooleanVar: ...\n\n    @overload\n    def __get__(\n        self: Field[int] | Field[int | None],\n        instance: None,\n        owner: Any,\n    ) -> NumberVar[int]: ...\n\n    @overload\n    def __get__(\n        self: Field[float]\n        | Field[int | float]\n        | Field[float | None]\n        | Field[int | float | None],\n        instance: None,\n        owner: Any,\n    ) -> NumberVar: ...\n\n    @overload\n    def __get__(\n        self: Field[str] | Field[str | None], instance: None, owner: Any\n    ) -> StringVar: ...\n\n    @overload\n    def __get__(\n        self: Field[list[V]]\n        | Field[set[V]]\n        | Field[list[V] | None]\n        | Field[set[V] | None],\n        instance: None,\n        owner: Any,\n    ) -> ArrayVar[Sequence[V]]: ...\n\n    @overload\n    def __get__(\n        self: Field[SEQUENCE_TYPE] | Field[SEQUENCE_TYPE | None],\n        instance: None,\n        owner: Any,\n    ) -> ArrayVar[SEQUENCE_TYPE]: ...\n\n    @overload\n    def __get__(\n        self: Field[MAPPING_TYPE] | Field[MAPPING_TYPE | None],\n        instance: None,\n        owner: Any,\n    ) -> ObjectVar[MAPPING_TYPE]: ...\n\n    @overload\n    def __get__(\n        self: Field[BASE_TYPE] | Field[BASE_TYPE | None], instance: None, owner: Any\n    ) -> ObjectVar[BASE_TYPE]: ...\n\n    @overload\n    def __get__(\n        self: Field[SQLA_TYPE] | Field[SQLA_TYPE | None], instance: None, owner: Any\n    ) -> ObjectVar[SQLA_TYPE]: ...\n\n    if TYPE_CHECKING:\n\n        @overload\n        def __get__(\n            self: Field[DATACLASS_TYPE] | Field[DATACLASS_TYPE | None],\n            instance: None,\n            owner: Any,\n        ) -> ObjectVar[DATACLASS_TYPE]: ...\n\n    @overload\n    def __get__(self, instance: None, owner: Any) -> Var[FIELD_TYPE]: ...\n\n    @overload\n    def __get__(self, instance: Any, owner: Any) -> FIELD_TYPE: ...\n\n    def __get__(self, instance: Any, owner: Any):  # pyright: ignore [reportInconsistentOverload]\n        \"\"\"Get the Var.\n\n        Args:\n            instance: The instance of the class accessing the Var.\n            owner: The class that the Var is attached to.\n        \"\"\"\n\n\n@overload\ndef field(\n    default: FIELD_TYPE | _MISSING_TYPE = MISSING,\n    *,\n    is_var: Literal[False],\n    default_factory: Callable[[], FIELD_TYPE] | None = None,\n) -> FIELD_TYPE: ...\n\n\n@overload\ndef field(\n    default: FIELD_TYPE | _MISSING_TYPE = MISSING,\n    *,\n    default_factory: Callable[[], FIELD_TYPE] | None = None,\n    is_var: Literal[True] = True,\n) -> Field[FIELD_TYPE]: ...\n\n\ndef field(\n    default: FIELD_TYPE | _MISSING_TYPE = MISSING,\n    *,\n    default_factory: Callable[[], FIELD_TYPE] | None = None,\n    is_var: bool = True,\n) -> Field[FIELD_TYPE] | FIELD_TYPE:\n    \"\"\"Create a field for a state.\n\n    Args:\n        default: The default value for the field.\n        default_factory: The default factory for the field.\n        is_var: Whether the field is a Var.\n\n    Returns:\n        The field for the state.\n\n    Raises:\n        ValueError: If both default and default_factory are specified.\n    \"\"\"\n    if default is not MISSING and default_factory is not None:\n        msg = \"cannot specify both default and default_factory\"\n        raise ValueError(msg)\n    if default is not MISSING and not types.is_immutable(default):\n        console.warn(\n            \"Mutable default values are not recommended. \"\n            \"Use default_factory instead to avoid unexpected behavior.\"\n        )\n        return Field(\n            default_factory=functools.partial(copy.deepcopy, default),\n            is_var=is_var,\n        )\n    return Field(\n        default=default,\n        default_factory=default_factory,\n        is_var=is_var,\n    )\n\n\n@dataclass_transform(kw_only_default=True, field_specifiers=(field,))\nclass BaseStateMeta(ABCMeta):\n    \"\"\"Meta class for BaseState.\"\"\"\n\n    if TYPE_CHECKING:\n        __inherited_fields__: Mapping[str, Field]\n        __own_fields__: dict[str, Field]\n        __fields__: dict[str, Field]\n\n        # Whether this state class is a mixin and should not be instantiated.\n        _mixin: bool = False\n\n    def __new__(\n        cls,\n        name: str,\n        bases: tuple[type, ...],\n        namespace: dict[str, Any],\n        mixin: bool = False,\n    ) -> type:\n        \"\"\"Create a new class.\n\n        Args:\n            name: The name of the class.\n            bases: The bases of the class.\n            namespace: The namespace of the class.\n            mixin: Whether the class is a mixin and should not be instantiated.\n\n        Returns:\n            The new class.\n        \"\"\"\n        state_bases = [\n            base for base in bases if issubclass(base, EvenMoreBasicBaseState)\n        ]\n        mixin = mixin or (\n            bool(state_bases) and all(base._mixin for base in state_bases)\n        )\n        # Add the field to the class\n        inherited_fields: dict[str, Field] = {}\n        own_fields: dict[str, Field] = {}\n        resolved_annotations = types.resolve_annotations(\n            annotations_from_namespace(namespace), namespace[\"__module__\"]\n        )\n\n        for base in bases[::-1]:\n            if hasattr(base, \"__inherited_fields__\"):\n                inherited_fields.update(base.__inherited_fields__)\n        for base in bases[::-1]:\n            if hasattr(base, \"__own_fields__\"):\n                inherited_fields.update(base.__own_fields__)\n\n        for key, value in [\n            (key, value)\n            for key, value in namespace.items()\n            if key not in resolved_annotations\n        ]:\n            if isinstance(value, Field):\n                if value.annotated_type is not Any:\n                    new_value = value\n                elif value.default is not MISSING:\n                    new_value = Field(\n                        default=value.default,\n                        is_var=value.is_var,\n                        annotated_type=figure_out_type(value.default),\n                    )\n                else:\n                    new_value = Field(\n                        default_factory=value.default_factory,\n                        is_var=value.is_var,\n                        annotated_type=Any,\n                    )\n            elif (\n                not key.startswith(\"__\")\n                and not callable(value)\n                and not isinstance(value, (staticmethod, classmethod, property, Var))\n            ):\n                if types.is_immutable(value):\n                    new_value = Field(\n                        default=value,\n                        annotated_type=figure_out_type(value),\n                    )\n                else:\n                    new_value = Field(\n                        default_factory=functools.partial(copy.deepcopy, value),\n                        annotated_type=figure_out_type(value),\n                    )\n            else:\n                continue\n\n            own_fields[key] = new_value\n\n        for key, annotation in resolved_annotations.items():\n            value = namespace.get(key, MISSING)\n\n            if types.is_classvar(annotation):\n                # If the annotation is a classvar, skip it.\n                continue\n\n            if value is MISSING:\n                value = Field(\n                    annotated_type=annotation,\n                )\n            elif not isinstance(value, Field):\n                if types.is_immutable(value):\n                    value = Field(\n                        default=value,\n                        annotated_type=annotation,\n                    )\n                else:\n                    value = Field(\n                        default_factory=functools.partial(copy.deepcopy, value),\n                        annotated_type=annotation,\n                    )\n            else:\n                value = Field(\n                    default=value.default,\n                    default_factory=value.default_factory,\n                    is_var=value.is_var,\n                    annotated_type=annotation,\n                )\n\n            own_fields[key] = value\n\n        namespace[\"__own_fields__\"] = own_fields\n        namespace[\"__inherited_fields__\"] = inherited_fields\n        namespace[\"__fields__\"] = inherited_fields | own_fields\n        namespace[\"_mixin\"] = mixin\n        return super().__new__(cls, name, bases, namespace)\n\n\nclass EvenMoreBasicBaseState(metaclass=BaseStateMeta):\n    \"\"\"A simplified base state class that provides basic functionality.\"\"\"\n\n    def __init__(\n        self,\n        **kwargs,\n    ):\n        \"\"\"Initialize the state with the given kwargs.\n\n        Args:\n            **kwargs: The kwargs to pass to the state.\n        \"\"\"\n        super().__init__()\n        for key, value in kwargs.items():\n            object.__setattr__(self, key, value)\n        for name, value in type(self).get_fields().items():\n            if name not in kwargs:\n                default_value = value.default_value()\n                object.__setattr__(self, name, default_value)\n\n    def set(self, **kwargs):\n        \"\"\"Mutate the state by setting the given kwargs. Returns the state.\n\n        Args:\n            **kwargs: The kwargs to set.\n\n        Returns:\n            The state with the fields set to the given kwargs.\n        \"\"\"\n        for key, value in kwargs.items():\n            setattr(self, key, value)\n        return self\n\n    @classmethod\n    def get_fields(cls) -> Mapping[str, Field]:\n        \"\"\"Get the fields of the component.\n\n        Returns:\n            The fields of the component.\n        \"\"\"\n        return cls.__fields__\n\n    @classmethod\n    def add_field(cls, name: str, var: Var, default_value: Any):\n        \"\"\"Add a field to the class after class definition.\n\n        Used by State.add_var() to correctly handle the new variable.\n\n        Args:\n            name: The name of the field to add.\n            var: The variable to add a field for.\n            default_value: The default value of the field.\n        \"\"\"\n        if types.is_immutable(default_value):\n            new_field = Field(\n                default=default_value,\n                annotated_type=var._var_type,\n            )\n        else:\n            new_field = Field(\n                default_factory=functools.partial(copy.deepcopy, default_value),\n                annotated_type=var._var_type,\n            )\n        cls.__fields__[name] = new_field\n"
  },
  {
    "path": "reflex/vars/color.py",
    "content": "\"\"\"Vars for colors.\"\"\"\n\nimport dataclasses\n\nfrom reflex.constants.colors import Color\nfrom reflex.vars.base import (\n    CachedVarOperation,\n    LiteralVar,\n    Var,\n    VarData,\n    cached_property_no_lock,\n    get_python_literal,\n)\nfrom reflex.vars.number import ternary_operation\nfrom reflex.vars.sequence import ConcatVarOperation, LiteralStringVar, StringVar\n\n\nclass ColorVar(StringVar[Color], python_types=Color):\n    \"\"\"Base class for immutable color vars.\"\"\"\n\n\n@dataclasses.dataclass(\n    eq=False,\n    frozen=True,\n    slots=True,\n)\nclass LiteralColorVar(CachedVarOperation, LiteralVar, ColorVar):\n    \"\"\"Base class for immutable literal color vars.\"\"\"\n\n    _var_value: Color = dataclasses.field(default_factory=lambda: Color(color=\"black\"))\n\n    @classmethod\n    def _get_all_var_data_without_creating_var(\n        cls,\n        value: Color,\n    ) -> VarData | None:\n        return VarData.merge(\n            LiteralStringVar._get_all_var_data_without_creating_var(value.color)\n            if isinstance(value.color, str)\n            else value.color._get_all_var_data(),\n            value.alpha._get_all_var_data()\n            if not isinstance(value.alpha, bool)\n            else None,\n            value.shade._get_all_var_data()\n            if not isinstance(value.shade, int)\n            else None,\n        )\n\n    @classmethod\n    def create(\n        cls,\n        value: Color,\n        _var_type: type[Color] | None = None,\n        _var_data: VarData | None = None,\n    ) -> ColorVar:\n        \"\"\"Create a var from a string value.\n\n        Args:\n            value: The value to create the var from.\n            _var_type: The type of the var.\n            _var_data: Additional hooks and imports associated with the Var.\n\n        Returns:\n            The var.\n        \"\"\"\n        return cls(\n            _js_expr=\"\",\n            _var_type=_var_type or Color,\n            _var_data=_var_data,\n            _var_value=value,\n        )\n\n    def __hash__(self) -> int:\n        \"\"\"Get the hash of the var.\n\n        Returns:\n            The hash of the var.\n        \"\"\"\n        return hash((\n            self.__class__.__name__,\n            self._var_value.color,\n            self._var_value.alpha,\n            self._var_value.shade,\n        ))\n\n    @cached_property_no_lock\n    def _cached_var_name(self) -> str:\n        \"\"\"The name of the var.\n\n        Returns:\n            The name of the var.\n        \"\"\"\n        alpha = self._var_value.alpha\n        alpha = (\n            ternary_operation(\n                alpha,\n                LiteralStringVar.create(\"a\"),\n                LiteralStringVar.create(\"\"),\n            )\n            if isinstance(alpha, Var)\n            else LiteralStringVar.create(\"a\" if alpha else \"\")\n        )\n\n        shade = self._var_value.shade\n        shade = (\n            shade.to_string(use_json=False)\n            if isinstance(shade, Var)\n            else LiteralStringVar.create(str(shade))\n        )\n        return str(\n            ConcatVarOperation.create(\n                LiteralStringVar.create(\"var(--\"),\n                self._var_value.color,\n                LiteralStringVar.create(\"-\"),\n                alpha,\n                shade,\n                LiteralStringVar.create(\")\"),\n            )\n        )\n\n    @cached_property_no_lock\n    def _cached_get_all_var_data(self) -> VarData | None:\n        \"\"\"Get all the var data.\n\n        Returns:\n            The var data.\n        \"\"\"\n        return VarData.merge(\n            LiteralStringVar._get_all_var_data_without_creating_var(\n                self._var_value.color\n            )\n            if isinstance(self._var_value.color, str)\n            else self._var_value.color._get_all_var_data(),\n            self._var_value.alpha._get_all_var_data()\n            if not isinstance(self._var_value.alpha, bool)\n            else None,\n            self._var_value.shade._get_all_var_data()\n            if not isinstance(self._var_value.shade, int)\n            else None,\n            self._var_data,\n        )\n\n    def json(self) -> str:\n        \"\"\"Get the JSON representation of the var.\n\n        Returns:\n            The JSON representation of the var.\n\n        Raises:\n            TypeError: If the color is not a valid color.\n        \"\"\"\n        color, alpha, shade = map(\n            get_python_literal,\n            (self._var_value.color, self._var_value.alpha, self._var_value.shade),\n        )\n        if color is None or alpha is None or shade is None:\n            msg = \"Cannot serialize color that contains non-literal vars.\"\n            raise TypeError(msg)\n        if (\n            not isinstance(color, str)\n            or not isinstance(alpha, bool)\n            or not isinstance(shade, int)\n        ):\n            msg = \"Color is not a valid color.\"\n            raise TypeError(msg)\n        return f\"var(--{color}-{'a' if alpha else ''}{shade})\"\n"
  },
  {
    "path": "reflex/vars/datetime.py",
    "content": "\"\"\"Immutable datetime and date vars.\"\"\"\n\nfrom __future__ import annotations\n\nimport dataclasses\nfrom datetime import date, datetime\nfrom typing import Any, TypeVar\n\nfrom reflex.utils.exceptions import VarTypeError\nfrom reflex.vars.number import BooleanVar\n\nfrom .base import (\n    CustomVarOperationReturn,\n    LiteralVar,\n    Var,\n    VarData,\n    var_operation,\n    var_operation_return,\n)\n\nDATETIME_T = TypeVar(\"DATETIME_T\", datetime, date)\n\ndatetime_types = datetime | date\n\n\ndef raise_var_type_error():\n    \"\"\"Raise a VarTypeError.\n\n    Raises:\n        VarTypeError: Cannot compare a datetime object with a non-datetime object.\n    \"\"\"\n    msg = \"Cannot compare a datetime object with a non-datetime object.\"\n    raise VarTypeError(msg)\n\n\nclass DateTimeVar(Var[DATETIME_T], python_types=(datetime, date)):\n    \"\"\"A variable that holds a datetime or date object.\"\"\"\n\n    def __lt__(self, other: datetime_types | DateTimeVar) -> BooleanVar:\n        \"\"\"Less than comparison.\n\n        Args:\n            other: The other datetime to compare.\n\n        Returns:\n            The result of the comparison.\n        \"\"\"\n        if not isinstance(other, DATETIME_TYPES):\n            raise_var_type_error()\n        return date_lt_operation(self, other)\n\n    def __le__(self, other: datetime_types | DateTimeVar) -> BooleanVar:\n        \"\"\"Less than or equal comparison.\n\n        Args:\n            other: The other datetime to compare.\n\n        Returns:\n            The result of the comparison.\n        \"\"\"\n        if not isinstance(other, DATETIME_TYPES):\n            raise_var_type_error()\n        return date_le_operation(self, other)\n\n    def __gt__(self, other: datetime_types | DateTimeVar) -> BooleanVar:\n        \"\"\"Greater than comparison.\n\n        Args:\n            other: The other datetime to compare.\n\n        Returns:\n            The result of the comparison.\n        \"\"\"\n        if not isinstance(other, DATETIME_TYPES):\n            raise_var_type_error()\n        return date_gt_operation(self, other)\n\n    def __ge__(self, other: datetime_types | DateTimeVar) -> BooleanVar:\n        \"\"\"Greater than or equal comparison.\n\n        Args:\n            other: The other datetime to compare.\n\n        Returns:\n            The result of the comparison.\n        \"\"\"\n        if not isinstance(other, DATETIME_TYPES):\n            raise_var_type_error()\n        return date_ge_operation(self, other)\n\n\n@var_operation\ndef date_gt_operation(lhs: DateTimeVar | Any, rhs: DateTimeVar | Any):\n    \"\"\"Greater than comparison.\n\n    Args:\n        lhs: The left-hand side of the operation.\n        rhs: The right-hand side of the operation.\n\n    Returns:\n        The result of the operation.\n    \"\"\"\n    return date_compare_operation(rhs, lhs, strict=True)\n\n\n@var_operation\ndef date_lt_operation(lhs: DateTimeVar | Any, rhs: DateTimeVar | Any):\n    \"\"\"Less than comparison.\n\n    Args:\n        lhs: The left-hand side of the operation.\n        rhs: The right-hand side of the operation.\n\n    Returns:\n        The result of the operation.\n    \"\"\"\n    return date_compare_operation(lhs, rhs, strict=True)\n\n\n@var_operation\ndef date_le_operation(lhs: DateTimeVar | Any, rhs: DateTimeVar | Any):\n    \"\"\"Less than or equal comparison.\n\n    Args:\n        lhs: The left-hand side of the operation.\n        rhs: The right-hand side of the operation.\n\n    Returns:\n        The result of the operation.\n    \"\"\"\n    return date_compare_operation(lhs, rhs)\n\n\n@var_operation\ndef date_ge_operation(lhs: DateTimeVar | Any, rhs: DateTimeVar | Any):\n    \"\"\"Greater than or equal comparison.\n\n    Args:\n        lhs: The left-hand side of the operation.\n        rhs: The right-hand side of the operation.\n\n    Returns:\n        The result of the operation.\n    \"\"\"\n    return date_compare_operation(rhs, lhs)\n\n\ndef date_compare_operation(\n    lhs: DateTimeVar[DATETIME_T] | Any,\n    rhs: DateTimeVar[DATETIME_T] | Any,\n    strict: bool = False,\n) -> CustomVarOperationReturn[bool]:\n    \"\"\"Check if the value is less than the other value.\n\n    Args:\n        lhs: The left-hand side of the operation.\n        rhs: The right-hand side of the operation.\n        strict: Whether to use strict comparison.\n\n    Returns:\n        The result of the operation.\n    \"\"\"\n    return var_operation_return(\n        f\"({lhs} {'<' if strict else '<='} {rhs})\",\n        bool,\n    )\n\n\n@dataclasses.dataclass(\n    eq=False,\n    frozen=True,\n    slots=True,\n)\nclass LiteralDatetimeVar(LiteralVar, DateTimeVar):\n    \"\"\"Base class for immutable datetime and date vars.\"\"\"\n\n    _var_value: date = dataclasses.field(default=datetime.now())\n\n    @classmethod\n    def _get_all_var_data_without_creating_var(cls, value: date) -> VarData | None:\n        return None\n\n    @classmethod\n    def create(cls, value: date, _var_data: VarData | None = None):\n        \"\"\"Create a new instance of the class.\n\n        Args:\n            value: The value to set.\n\n        Returns:\n            LiteralDatetimeVar: The new instance of the class.\n        \"\"\"\n        js_expr = f'\"{value!s}\"'\n        return cls(\n            _js_expr=js_expr,\n            _var_type=type(value),\n            _var_value=value,\n            _var_data=_var_data,\n        )\n\n\nDATETIME_TYPES = (datetime, date, DateTimeVar)\n"
  },
  {
    "path": "reflex/vars/dep_tracking.py",
    "content": "\"\"\"Collection of base classes.\"\"\"\n\nfrom __future__ import annotations\n\nimport contextlib\nimport dataclasses\nimport dis\nimport enum\nimport importlib\nimport inspect\nimport sys\nfrom types import CellType, CodeType, FunctionType, ModuleType\nfrom typing import TYPE_CHECKING, Any, ClassVar, cast\n\nfrom reflex.utils.exceptions import VarValueError\n\nif TYPE_CHECKING:\n    from reflex.state import BaseState\n\n    from .base import Var\n\n\nCellEmpty = object()\n\n\ndef get_cell_value(cell: CellType) -> Any:\n    \"\"\"Get the value of a cell object.\n\n    Args:\n        cell: The cell object to get the value from. (func.__closure__ objects)\n\n    Returns:\n        The value from the cell or CellEmpty if a ValueError is raised.\n    \"\"\"\n    try:\n        return cell.cell_contents\n    except ValueError:\n        return CellEmpty\n\n\nclass ScanStatus(enum.Enum):\n    \"\"\"State of the dis instruction scanning loop.\"\"\"\n\n    SCANNING = enum.auto()\n    GETTING_ATTR = enum.auto()\n    GETTING_STATE = enum.auto()\n    GETTING_STATE_POST_AWAIT = enum.auto()\n    GETTING_VAR = enum.auto()\n    GETTING_IMPORT = enum.auto()\n\n\nclass UntrackedLocalVarError(VarValueError):\n    \"\"\"Raised when a local variable is referenced, but it is not tracked in the current scope.\"\"\"\n\n\ndef assert_base_state(\n    local_value: Any,\n    local_name: str | None = None,\n) -> type[BaseState]:\n    \"\"\"Assert that a local variable is a BaseState subclass.\n\n    Args:\n        local_value: The value of the local variable to check.\n        local_name: The name of the local variable to check.\n\n    Returns:\n        The local variable value if it is a BaseState subclass.\n\n    Raises:\n        VarValueError: If the object is not a BaseState subclass.\n    \"\"\"\n    from reflex.state import BaseState\n\n    if not isinstance(local_value, type) or not issubclass(local_value, BaseState):\n        msg = f\"Cannot determine dependencies in fetched state {local_name!r}: {local_value!r} is not a BaseState.\"\n        raise VarValueError(msg)\n    return local_value\n\n\n@dataclasses.dataclass\nclass DependencyTracker:\n    \"\"\"State machine for identifying state attributes that are accessed by a function.\"\"\"\n\n    func: FunctionType | CodeType = dataclasses.field()\n    state_cls: type[BaseState] = dataclasses.field()\n\n    dependencies: dict[str, set[str]] = dataclasses.field(default_factory=dict)\n\n    scan_status: ScanStatus = dataclasses.field(default=ScanStatus.SCANNING)\n    top_of_stack: str | None = dataclasses.field(default=None)\n\n    tracked_locals: dict[str, type[BaseState] | ModuleType] = dataclasses.field(\n        default_factory=dict\n    )\n\n    _getting_state_class: type[BaseState] | ModuleType | None = dataclasses.field(\n        default=None\n    )\n    _get_var_value_positions: dis.Positions | None = dataclasses.field(default=None)\n    _last_import_name: str | None = dataclasses.field(default=None)\n\n    INVALID_NAMES: ClassVar[list[str]] = [\"parent_state\", \"substates\", \"get_substate\"]\n\n    def __post_init__(self):\n        \"\"\"After initializing, populate the dependencies dict.\"\"\"\n        with contextlib.suppress(AttributeError):\n            # unbox functools.partial\n            self.func = cast(FunctionType, self.func.func)  # pyright: ignore[reportAttributeAccessIssue]\n        with contextlib.suppress(AttributeError):\n            # unbox EventHandler\n            self.func = cast(FunctionType, self.func.fn)  # pyright: ignore[reportAttributeAccessIssue,reportFunctionMemberAccess]\n\n        if isinstance(self.func, FunctionType):\n            with contextlib.suppress(AttributeError, IndexError):\n                # the first argument to the function is the name of \"self\" arg\n                self.tracked_locals[self.func.__code__.co_varnames[0]] = self.state_cls\n\n        self._populate_dependencies()\n\n    def _merge_deps(self, tracker: DependencyTracker) -> None:\n        \"\"\"Merge dependencies from another DependencyTracker.\n\n        Args:\n            tracker: The DependencyTracker to merge dependencies from.\n        \"\"\"\n        for state_name, dep_name in tracker.dependencies.items():\n            self.dependencies.setdefault(state_name, set()).update(dep_name)\n\n    def get_tracked_local(self, local_name: str) -> type[BaseState] | ModuleType:\n        \"\"\"Get the value of a local name tracked in the current function scope.\n\n        Args:\n            local_name: The name of the local variable to fetch.\n\n        Returns:\n            The value of local name tracked in the current scope (a referenced\n            BaseState subclass or imported module).\n\n        Raises:\n            UntrackedLocalVarError: If the local variable is not being tracked.\n        \"\"\"\n        try:\n            local_value = self.tracked_locals[local_name]\n        except KeyError as ke:\n            msg = f\"{local_name!r} is not tracked in the current scope.\"\n            raise UntrackedLocalVarError(msg) from ke\n        return local_value\n\n    def load_attr_or_method(self, instruction: dis.Instruction) -> None:\n        \"\"\"Handle loading an attribute or method from the object on top of the stack.\n\n        This method directly tracks attributes and recursively merges\n        dependencies from analyzing the dependencies of any methods called.\n\n        Args:\n            instruction: The dis instruction to process.\n\n        Raises:\n            VarValueError: if the attribute is an disallowed name or attribute\n                does not reference a BaseState.\n        \"\"\"\n        from .base import ComputedVar\n\n        if instruction.argval in self.INVALID_NAMES:\n            msg = f\"Cached var {self!s} cannot access arbitrary state via `{instruction.argval}`.\"\n            raise VarValueError(msg)\n        if instruction.argval == \"get_state\":\n            # Special case: arbitrary state access requested.\n            self.scan_status = ScanStatus.GETTING_STATE\n            return\n        if instruction.argval == \"get_var_value\":\n            # Special case: arbitrary var access requested.\n            if sys.version_info >= (3, 11):\n                self._get_var_value_positions = instruction.positions\n            self.scan_status = ScanStatus.GETTING_VAR\n            return\n\n        # Reset status back to SCANNING after attribute is accessed.\n        self.scan_status = ScanStatus.SCANNING\n        if not self.top_of_stack:\n            return\n        target_obj = self.get_tracked_local(self.top_of_stack)\n        try:\n            target_state = assert_base_state(target_obj, local_name=self.top_of_stack)\n        except VarValueError:\n            # If the target state is not a BaseState, we cannot track dependencies on it.\n            return\n        try:\n            ref_obj = getattr(target_state, instruction.argval)\n        except AttributeError:\n            # Not found on this state class, maybe it is a dynamic attribute that will be picked up later.\n            ref_obj = None\n\n        if isinstance(ref_obj, property) and not isinstance(ref_obj, ComputedVar):\n            # recurse into property fget functions\n            ref_obj = ref_obj.fget\n        if callable(ref_obj):\n            # recurse into callable attributes\n            self._merge_deps(\n                type(self)(func=cast(FunctionType, ref_obj), state_cls=target_state)\n            )\n        elif (\n            instruction.argval in target_state.backend_vars\n            or instruction.argval in target_state.vars\n        ):\n            # var access\n            self.dependencies.setdefault(target_state.get_full_name(), set()).add(\n                instruction.argval\n            )\n\n    def _get_globals(self) -> dict[str, Any]:\n        \"\"\"Get the globals of the function.\n\n        Returns:\n            The var names and values in the globals of the function.\n        \"\"\"\n        if isinstance(self.func, CodeType):\n            return {}\n        return self.func.__globals__  # pyright: ignore[reportAttributeAccessIssue]\n\n    def _get_closure(self) -> dict[str, Any]:\n        \"\"\"Get the closure of the function, with unbound values omitted.\n\n        Returns:\n            The var names and values in the closure of the function.\n        \"\"\"\n        if isinstance(self.func, CodeType):\n            return {}\n        return {\n            var_name: get_cell_value(cell)\n            for var_name, cell in zip(\n                self.func.__code__.co_freevars,  # pyright: ignore[reportAttributeAccessIssue]\n                self.func.__closure__ or (),\n                strict=False,\n            )\n            if get_cell_value(cell) is not CellEmpty\n        }\n\n    def handle_getting_state(self, instruction: dis.Instruction) -> None:\n        \"\"\"Handle bytecode analysis when `get_state` was called in the function.\n\n        If the wrapped function is getting an arbitrary state and saving it to a\n        local variable, this method associates the local variable name with the\n        state class in self.tracked_locals.\n\n        When an attribute/method is accessed on a tracked local, it will be\n        associated with this state.\n\n        Args:\n            instruction: The dis instruction to process.\n\n        Raises:\n            VarValueError: if the state class cannot be determined from the instruction.\n        \"\"\"\n        if isinstance(self.func, CodeType):\n            msg = \"Dependency detection cannot identify get_state class from a code object.\"\n            raise VarValueError(msg)\n        if instruction.opname in (\"LOAD_FAST\", \"LOAD_FAST_BORROW\"):\n            self._getting_state_class = self.get_tracked_local(\n                local_name=instruction.argval,\n            )\n        elif instruction.opname == \"LOAD_GLOBAL\":\n            # Special case: referencing state class from global scope.\n            try:\n                self._getting_state_class = self._get_globals()[instruction.argval]\n            except (ValueError, KeyError) as ve:\n                msg = f\"Cached var {self!s} cannot access arbitrary state `{instruction.argval}`, not found in globals.\"\n                raise VarValueError(msg) from ve\n        elif instruction.opname == \"LOAD_DEREF\":\n            # Special case: referencing state class from closure.\n            try:\n                self._getting_state_class = self._get_closure()[instruction.argval]\n            except (ValueError, KeyError) as ve:\n                msg = f\"Cached var {self!s} cannot access arbitrary state `{instruction.argval}`, is it defined yet?\"\n                raise VarValueError(msg) from ve\n        elif instruction.opname in (\"LOAD_ATTR\", \"LOAD_METHOD\"):\n            self._getting_state_class = getattr(\n                self._getting_state_class,\n                instruction.argval,\n            )\n        elif instruction.opname == \"GET_AWAITABLE\":\n            # Now inside the `await` machinery, subsequent instructions\n            # operate on the result of the `get_state` call.\n            self.scan_status = ScanStatus.GETTING_STATE_POST_AWAIT\n            if self._getting_state_class is not None:\n                self.top_of_stack = \"_\"\n                self.tracked_locals[self.top_of_stack] = self._getting_state_class\n                self._getting_state_class = None\n\n    def handle_getting_state_post_await(self, instruction: dis.Instruction) -> None:\n        \"\"\"Handle bytecode analysis after `get_state` was called in the function.\n\n        This function is called _after_ awaiting self.get_state to capture the\n        local variable holding the state instance or directly record access to\n        attributes accessed on the result of get_state.\n\n        Args:\n            instruction: The dis instruction to process.\n\n        Raises:\n            VarValueError: if the state class cannot be determined from the instruction.\n        \"\"\"\n        if instruction.opname == \"STORE_FAST\" and self.top_of_stack:\n            # Storing the result of get_state in a local variable.\n            self.tracked_locals[instruction.argval] = self.tracked_locals.pop(\n                self.top_of_stack\n            )\n            self.top_of_stack = None\n            self.scan_status = ScanStatus.SCANNING\n        elif instruction.opname in (\"LOAD_ATTR\", \"LOAD_METHOD\"):\n            # Attribute access on an inline `get_state`, not assigned to a variable.\n            self.load_attr_or_method(instruction)\n\n    def _eval_var(self, positions: dis.Positions) -> Var:\n        \"\"\"Evaluate instructions from the wrapped function to get the Var object.\n\n        Args:\n            positions: The disassembly positions of the get_var_value call.\n\n        Returns:\n            The Var object.\n\n        Raises:\n            VarValueError: if the source code for the var cannot be determined.\n        \"\"\"\n        # Get the original source code and eval it to get the Var.\n        module = inspect.getmodule(self.func)\n        if module is None or self._get_var_value_positions is None:\n            msg = f\"Cannot determine the source code for the var in {self.func!r}.\"\n            raise VarValueError(msg)\n        start_line = self._get_var_value_positions.end_lineno\n        start_column = self._get_var_value_positions.end_col_offset\n        end_line = positions.end_lineno\n        end_column = positions.end_col_offset\n        if (\n            start_line is None\n            or start_column is None\n            or end_line is None\n            or end_column is None\n        ):\n            msg = f\"Cannot determine the source code for the var in {self.func!r}.\"\n            raise VarValueError(msg)\n        source = inspect.getsource(module).splitlines(True)[start_line - 1 : end_line]\n        # Create a python source string snippet.\n        if len(source) > 1:\n            snipped_source = \"\".join([\n                *source[0][start_column:],\n                *source[1:-1],\n                *source[-1][:end_column],\n            ])\n        else:\n            snipped_source = source[0][start_column:end_column]\n        # Evaluate the string in the context of the function's globals, closure and tracked local scope.\n        return eval(\n            f\"({snipped_source})\",\n            self._get_globals(),\n            {**self._get_closure(), **self.tracked_locals},\n        )\n\n    def handle_getting_var(self, instruction: dis.Instruction) -> None:\n        \"\"\"Handle bytecode analysis when `get_var_value` was called in the function.\n\n        This only really works if the expression passed to `get_var_value` is\n        evaluable in the function's global scope or closure, so getting the var\n        value from a var saved in a local variable or in the class instance is\n        not possible.\n\n        Args:\n            instruction: The dis instruction to process.\n\n        Raises:\n            VarValueError: if the source code for the var cannot be determined.\n        \"\"\"\n        if instruction.opname == \"CALL\":\n            if instruction.positions is None:\n                msg = f\"Cannot determine the source code for the var in {self.func!r}.\"\n                raise VarValueError(msg)\n            the_var = self._eval_var(instruction.positions)\n            the_var_data = the_var._get_all_var_data()\n            if the_var_data is None:\n                msg = f\"Cannot determine the source code for the var in {self.func!r}.\"\n                raise VarValueError(msg)\n            self.dependencies.setdefault(the_var_data.state, set()).add(\n                the_var_data.field_name\n            )\n            self.scan_status = ScanStatus.SCANNING\n\n    def _populate_dependencies(self) -> None:\n        \"\"\"Update self.dependencies based on the disassembly of self.func.\n\n        Save references to attributes accessed on \"self\" or other fetched states.\n\n        Recursively called when the function makes a method call on \"self\" or\n        define comprehensions or nested functions that may reference \"self\".\n        \"\"\"\n        for instruction in dis.get_instructions(self.func):\n            if self.scan_status == ScanStatus.GETTING_STATE:\n                self.handle_getting_state(instruction)\n            elif self.scan_status == ScanStatus.GETTING_STATE_POST_AWAIT:\n                self.handle_getting_state_post_await(instruction)\n            elif self.scan_status == ScanStatus.GETTING_VAR:\n                self.handle_getting_var(instruction)\n            elif (\n                instruction.opname\n                in (\n                    \"LOAD_FAST\",\n                    \"LOAD_DEREF\",\n                    \"LOAD_FAST_BORROW\",\n                    \"LOAD_FAST_CHECK\",\n                    \"LOAD_FAST_AND_CLEAR\",\n                )\n                and instruction.argval in self.tracked_locals\n            ):\n                # bytecode loaded the class instance to the top of stack, next load instruction\n                # is referencing an attribute on self\n                self.top_of_stack = instruction.argval\n                self.scan_status = ScanStatus.GETTING_ATTR\n            elif (\n                instruction.opname\n                in (\n                    \"LOAD_FAST_LOAD_FAST\",\n                    \"LOAD_FAST_BORROW_LOAD_FAST_BORROW\",\n                    \"STORE_FAST_LOAD_FAST\",\n                )\n                and instruction.argval[-1] in self.tracked_locals\n            ):\n                # Double LOAD_FAST family instructions load multiple values onto the stack,\n                # the last value in the argval list is the top of the stack.\n                self.top_of_stack = instruction.argval[-1]\n                self.scan_status = ScanStatus.GETTING_ATTR\n            elif self.scan_status == ScanStatus.GETTING_ATTR and instruction.opname in (\n                \"LOAD_ATTR\",\n                \"LOAD_METHOD\",\n            ):\n                self.load_attr_or_method(instruction)\n                self.top_of_stack = None\n            elif instruction.opname == \"LOAD_CONST\" and isinstance(\n                instruction.argval, CodeType\n            ):\n                # recurse into nested functions / comprehensions, which can reference\n                # instance attributes from the outer scope\n                self._merge_deps(\n                    type(self)(\n                        func=instruction.argval,\n                        state_cls=self.state_cls,\n                        tracked_locals=self.tracked_locals,\n                    )\n                )\n            elif instruction.opname == \"IMPORT_NAME\" and instruction.argval is not None:\n                self.scan_status = ScanStatus.GETTING_IMPORT\n                self._last_import_name = instruction.argval\n                importlib.import_module(instruction.argval)\n                top_module_name = instruction.argval.split(\".\")[0]\n                self.tracked_locals[instruction.argval] = sys.modules[top_module_name]\n                self.top_of_stack = instruction.argval\n            elif instruction.opname == \"IMPORT_FROM\":\n                if not self._last_import_name:\n                    msg = f\"Cannot find package associated with import {instruction.argval} in {self.func!r}.\"\n                    raise VarValueError(msg)\n                if instruction.argval in self._last_import_name.split(\".\"):\n                    # `import ... as ...` case:\n                    # import from interim package, update tracked_locals for the last imported name.\n                    self.tracked_locals[self._last_import_name] = getattr(\n                        self.tracked_locals[self._last_import_name], instruction.argval\n                    )\n                    continue\n                # Importing a name from a package/module.\n                if self._last_import_name is not None and self.top_of_stack:\n                    # The full import name does NOT end up in scope for a `from ... import`.\n                    self.tracked_locals.pop(self._last_import_name)\n                self.tracked_locals[instruction.argval] = getattr(\n                    importlib.import_module(self._last_import_name),\n                    instruction.argval,\n                )\n                # If we see a STORE_FAST, we can assign the top of stack to an aliased name.\n                self.top_of_stack = instruction.argval\n            elif (\n                self.scan_status == ScanStatus.GETTING_IMPORT\n                and instruction.opname == \"STORE_FAST\"\n                and self.top_of_stack is not None\n            ):\n                self.tracked_locals[instruction.argval] = self.tracked_locals.pop(\n                    self.top_of_stack\n                )\n                self.top_of_stack = None\n"
  },
  {
    "path": "reflex/vars/function.py",
    "content": "\"\"\"Immutable function vars.\"\"\"\n\nfrom __future__ import annotations\n\nimport dataclasses\nfrom collections.abc import Callable, Sequence\nfrom typing import Any, Concatenate, Generic, ParamSpec, Protocol, TypeVar, overload\n\nfrom reflex.utils import format\nfrom reflex.utils.types import GenericType\n\nfrom .base import CachedVarOperation, LiteralVar, Var, VarData, cached_property_no_lock\n\nP = ParamSpec(\"P\")\nV1 = TypeVar(\"V1\")\nV2 = TypeVar(\"V2\")\nV3 = TypeVar(\"V3\")\nV4 = TypeVar(\"V4\")\nV5 = TypeVar(\"V5\")\nV6 = TypeVar(\"V6\")\nR = TypeVar(\"R\")\n\n\nclass ReflexCallable(Protocol[P, R]):\n    \"\"\"Protocol for a callable.\"\"\"\n\n    __call__: Callable[P, R]\n\n\nCALLABLE_TYPE = TypeVar(\"CALLABLE_TYPE\", bound=ReflexCallable, covariant=True)\nOTHER_CALLABLE_TYPE = TypeVar(\n    \"OTHER_CALLABLE_TYPE\", bound=ReflexCallable, covariant=True\n)\n\n\nclass FunctionVar(Var[CALLABLE_TYPE], default_type=ReflexCallable[Any, Any]):\n    \"\"\"Base class for immutable function vars.\"\"\"\n\n    @overload\n    def partial(self) -> FunctionVar[CALLABLE_TYPE]: ...\n\n    @overload\n    def partial(\n        self: FunctionVar[ReflexCallable[Concatenate[V1, P], R]],\n        arg1: V1 | Var[V1],\n    ) -> FunctionVar[ReflexCallable[P, R]]: ...\n\n    @overload\n    def partial(\n        self: FunctionVar[ReflexCallable[Concatenate[V1, V2, P], R]],\n        arg1: V1 | Var[V1],\n        arg2: V2 | Var[V2],\n    ) -> FunctionVar[ReflexCallable[P, R]]: ...\n\n    @overload\n    def partial(\n        self: FunctionVar[ReflexCallable[Concatenate[V1, V2, V3, P], R]],\n        arg1: V1 | Var[V1],\n        arg2: V2 | Var[V2],\n        arg3: V3 | Var[V3],\n    ) -> FunctionVar[ReflexCallable[P, R]]: ...\n\n    @overload\n    def partial(\n        self: FunctionVar[ReflexCallable[Concatenate[V1, V2, V3, V4, P], R]],\n        arg1: V1 | Var[V1],\n        arg2: V2 | Var[V2],\n        arg3: V3 | Var[V3],\n        arg4: V4 | Var[V4],\n    ) -> FunctionVar[ReflexCallable[P, R]]: ...\n\n    @overload\n    def partial(\n        self: FunctionVar[ReflexCallable[Concatenate[V1, V2, V3, V4, V5, P], R]],\n        arg1: V1 | Var[V1],\n        arg2: V2 | Var[V2],\n        arg3: V3 | Var[V3],\n        arg4: V4 | Var[V4],\n        arg5: V5 | Var[V5],\n    ) -> FunctionVar[ReflexCallable[P, R]]: ...\n\n    @overload\n    def partial(\n        self: FunctionVar[ReflexCallable[Concatenate[V1, V2, V3, V4, V5, V6, P], R]],\n        arg1: V1 | Var[V1],\n        arg2: V2 | Var[V2],\n        arg3: V3 | Var[V3],\n        arg4: V4 | Var[V4],\n        arg5: V5 | Var[V5],\n        arg6: V6 | Var[V6],\n    ) -> FunctionVar[ReflexCallable[P, R]]: ...\n\n    @overload\n    def partial(\n        self: FunctionVar[ReflexCallable[P, R]], *args: Var | Any\n    ) -> FunctionVar[ReflexCallable[P, R]]: ...\n\n    @overload\n    def partial(self, *args: Var | Any) -> FunctionVar: ...\n\n    def partial(self, *args: Var | Any) -> FunctionVar:  # pyright: ignore [reportInconsistentOverload]\n        \"\"\"Partially apply the function with the given arguments.\n\n        Args:\n            *args: The arguments to partially apply the function with.\n\n        Returns:\n            The partially applied function.\n        \"\"\"\n        if not args:\n            return ArgsFunctionOperation.create((), self)\n        return ArgsFunctionOperation.create(\n            (\"...args\",),\n            VarOperationCall.create(self, *args, Var(_js_expr=\"...args\")),\n        )\n\n    @overload\n    def call(\n        self: FunctionVar[ReflexCallable[[V1], R]], arg1: V1 | Var[V1]\n    ) -> VarOperationCall[[V1], R]: ...\n\n    @overload\n    def call(\n        self: FunctionVar[ReflexCallable[[V1, V2], R]],\n        arg1: V1 | Var[V1],\n        arg2: V2 | Var[V2],\n    ) -> VarOperationCall[[V1, V2], R]: ...\n\n    @overload\n    def call(\n        self: FunctionVar[ReflexCallable[[V1, V2, V3], R]],\n        arg1: V1 | Var[V1],\n        arg2: V2 | Var[V2],\n        arg3: V3 | Var[V3],\n    ) -> VarOperationCall[[V1, V2, V3], R]: ...\n\n    @overload\n    def call(\n        self: FunctionVar[ReflexCallable[[V1, V2, V3, V4], R]],\n        arg1: V1 | Var[V1],\n        arg2: V2 | Var[V2],\n        arg3: V3 | Var[V3],\n        arg4: V4 | Var[V4],\n    ) -> VarOperationCall[[V1, V2, V3, V4], R]: ...\n\n    @overload\n    def call(\n        self: FunctionVar[ReflexCallable[[V1, V2, V3, V4, V5], R]],\n        arg1: V1 | Var[V1],\n        arg2: V2 | Var[V2],\n        arg3: V3 | Var[V3],\n        arg4: V4 | Var[V4],\n        arg5: V5 | Var[V5],\n    ) -> VarOperationCall[[V1, V2, V3, V4, V5], R]: ...\n\n    @overload\n    def call(\n        self: FunctionVar[ReflexCallable[[V1, V2, V3, V4, V5, V6], R]],\n        arg1: V1 | Var[V1],\n        arg2: V2 | Var[V2],\n        arg3: V3 | Var[V3],\n        arg4: V4 | Var[V4],\n        arg5: V5 | Var[V5],\n        arg6: V6 | Var[V6],\n    ) -> VarOperationCall[[V1, V2, V3, V4, V5, V6], R]: ...\n\n    @overload\n    def call(\n        self: FunctionVar[ReflexCallable[P, R]], *args: Var | Any\n    ) -> VarOperationCall[P, R]: ...\n\n    @overload\n    def call(self, *args: Var | Any) -> Var: ...\n\n    def call(self, *args: Var | Any) -> Var:  # pyright: ignore [reportInconsistentOverload]\n        \"\"\"Call the function with the given arguments.\n\n        Args:\n            *args: The arguments to call the function with.\n\n        Returns:\n            The function call operation.\n        \"\"\"\n        return VarOperationCall.create(self, *args).guess_type()\n\n    __call__ = call\n\n\nclass BuilderFunctionVar(\n    FunctionVar[CALLABLE_TYPE], default_type=ReflexCallable[Any, Any]\n):\n    \"\"\"Base class for immutable function vars with the builder pattern.\"\"\"\n\n    __call__ = FunctionVar.partial\n\n\nclass FunctionStringVar(FunctionVar[CALLABLE_TYPE]):\n    \"\"\"Base class for immutable function vars from a string.\"\"\"\n\n    @classmethod\n    def create(\n        cls,\n        func: str,\n        _var_type: type[OTHER_CALLABLE_TYPE] = ReflexCallable[Any, Any],\n        _var_data: VarData | None = None,\n    ) -> FunctionStringVar[OTHER_CALLABLE_TYPE]:\n        \"\"\"Create a new function var from a string.\n\n        Args:\n            func: The function to call.\n            _var_type: The type of the Var.\n            _var_data: Additional hooks and imports associated with the Var.\n\n        Returns:\n            The function var.\n        \"\"\"\n        return FunctionStringVar(\n            _js_expr=func,\n            _var_type=_var_type,\n            _var_data=_var_data,\n        )\n\n\n@dataclasses.dataclass(\n    eq=False,\n    frozen=True,\n    slots=True,\n)\nclass VarOperationCall(Generic[P, R], CachedVarOperation, Var[R]):\n    \"\"\"Base class for immutable vars that are the result of a function call.\"\"\"\n\n    _func: FunctionVar[ReflexCallable[P, R]] | None = dataclasses.field(default=None)\n    _args: tuple[Var | Any, ...] = dataclasses.field(default_factory=tuple)\n\n    @cached_property_no_lock\n    def _cached_var_name(self) -> str:\n        \"\"\"The name of the var.\n\n        Returns:\n            The name of the var.\n        \"\"\"\n        return f\"({self._func!s}({', '.join([str(LiteralVar.create(arg)) for arg in self._args])}))\"\n\n    @cached_property_no_lock\n    def _cached_get_all_var_data(self) -> VarData | None:\n        \"\"\"Get all the var data associated with the var.\n\n        Returns:\n            All the var data associated with the var.\n        \"\"\"\n        return VarData.merge(\n            self._func._get_all_var_data() if self._func is not None else None,\n            *[LiteralVar.create(arg)._get_all_var_data() for arg in self._args],\n            self._var_data,\n        )\n\n    @classmethod\n    def create(\n        cls,\n        func: FunctionVar[ReflexCallable[P, R]],\n        *args: Var | Any,\n        _var_type: GenericType = Any,\n        _var_data: VarData | None = None,\n    ) -> VarOperationCall:\n        \"\"\"Create a new function call var.\n\n        Args:\n            func: The function to call.\n            *args: The arguments to call the function with.\n            _var_type: The type of the Var.\n            _var_data: Additional hooks and imports associated with the Var.\n\n        Returns:\n            The function call var.\n        \"\"\"\n        function_return_type = (\n            func._var_type.__args__[1]\n            if getattr(func._var_type, \"__args__\", None)\n            else Any\n        )\n        var_type = _var_type if _var_type is not Any else function_return_type\n        return cls(\n            _js_expr=\"\",\n            _var_type=var_type,\n            _var_data=_var_data,\n            _func=func,\n            _args=args,\n        )\n\n\n@dataclasses.dataclass(frozen=True)\nclass DestructuredArg:\n    \"\"\"Class for destructured arguments.\"\"\"\n\n    fields: tuple[str, ...] = ()\n    rest: str | None = None\n\n    def to_javascript(self) -> str:\n        \"\"\"Convert the destructured argument to JavaScript.\n\n        Returns:\n            The destructured argument in JavaScript.\n        \"\"\"\n        return format.wrap(\n            \", \".join(self.fields) + (f\", ...{self.rest}\" if self.rest else \"\"),\n            \"{\",\n            \"}\",\n        )\n\n\n@dataclasses.dataclass(\n    frozen=True,\n)\nclass FunctionArgs:\n    \"\"\"Class for function arguments.\"\"\"\n\n    args: tuple[str | DestructuredArg, ...] = ()\n    rest: str | None = None\n\n\ndef format_args_function_operation(\n    args: FunctionArgs, return_expr: Var | Any, explicit_return: bool\n) -> str:\n    \"\"\"Format an args function operation.\n\n    Args:\n        args: The function arguments.\n        return_expr: The return expression.\n        explicit_return: Whether to use explicit return syntax.\n\n    Returns:\n        The formatted args function operation.\n    \"\"\"\n    arg_names_str = \", \".join([\n        arg if isinstance(arg, str) else arg.to_javascript() for arg in args.args\n    ]) + (f\", ...{args.rest}\" if args.rest else \"\")\n\n    return_expr_str = str(LiteralVar.create(return_expr))\n\n    # Wrap return expression in curly braces if explicit return syntax is used.\n    return_expr_str_wrapped = (\n        format.wrap(return_expr_str, \"{\", \"}\") if explicit_return else return_expr_str\n    )\n\n    return f\"(({arg_names_str}) => {return_expr_str_wrapped})\"\n\n\n@dataclasses.dataclass(\n    eq=False,\n    frozen=True,\n    slots=True,\n)\nclass ArgsFunctionOperation(CachedVarOperation, FunctionVar):\n    \"\"\"Base class for immutable function defined via arguments and return expression.\"\"\"\n\n    _args: FunctionArgs = dataclasses.field(default_factory=FunctionArgs)\n    _return_expr: Var | Any = dataclasses.field(default=None)\n    _explicit_return: bool = dataclasses.field(default=False)\n\n    @cached_property_no_lock\n    def _cached_var_name(self) -> str:\n        \"\"\"The name of the var.\n\n        Returns:\n            The name of the var.\n        \"\"\"\n        return format_args_function_operation(\n            self._args, self._return_expr, self._explicit_return\n        )\n\n    @classmethod\n    def create(\n        cls,\n        args_names: Sequence[str | DestructuredArg],\n        return_expr: Var | Any,\n        rest: str | None = None,\n        explicit_return: bool = False,\n        _var_type: GenericType = Callable,\n        _var_data: VarData | None = None,\n    ):\n        \"\"\"Create a new function var.\n\n        Args:\n            args_names: The names of the arguments.\n            return_expr: The return expression of the function.\n            rest: The name of the rest argument.\n            explicit_return: Whether to use explicit return syntax.\n            _var_type: The type of the Var.\n            _var_data: Additional hooks and imports associated with the Var.\n\n        Returns:\n            The function var.\n        \"\"\"\n        return_expr = Var.create(return_expr)\n        return cls(\n            _js_expr=\"\",\n            _var_type=_var_type,\n            _var_data=_var_data,\n            _args=FunctionArgs(args=tuple(args_names), rest=rest),\n            _return_expr=return_expr,\n            _explicit_return=explicit_return,\n        )\n\n\n@dataclasses.dataclass(\n    eq=False,\n    frozen=True,\n    slots=True,\n)\nclass ArgsFunctionOperationBuilder(CachedVarOperation, BuilderFunctionVar):\n    \"\"\"Base class for immutable function defined via arguments and return expression with the builder pattern.\"\"\"\n\n    _args: FunctionArgs = dataclasses.field(default_factory=FunctionArgs)\n    _return_expr: Var | Any = dataclasses.field(default=None)\n    _explicit_return: bool = dataclasses.field(default=False)\n\n    @cached_property_no_lock\n    def _cached_var_name(self) -> str:\n        \"\"\"The name of the var.\n\n        Returns:\n            The name of the var.\n        \"\"\"\n        return format_args_function_operation(\n            self._args, self._return_expr, self._explicit_return\n        )\n\n    @classmethod\n    def create(\n        cls,\n        args_names: Sequence[str | DestructuredArg],\n        return_expr: Var | Any,\n        rest: str | None = None,\n        explicit_return: bool = False,\n        _var_type: GenericType = Callable,\n        _var_data: VarData | None = None,\n    ):\n        \"\"\"Create a new function var.\n\n        Args:\n            args_names: The names of the arguments.\n            return_expr: The return expression of the function.\n            rest: The name of the rest argument.\n            explicit_return: Whether to use explicit return syntax.\n            _var_type: The type of the Var.\n            _var_data: Additional hooks and imports associated with the Var.\n\n        Returns:\n            The function var.\n        \"\"\"\n        return_expr = Var.create(return_expr)\n        return cls(\n            _js_expr=\"\",\n            _var_type=_var_type,\n            _var_data=_var_data,\n            _args=FunctionArgs(args=tuple(args_names), rest=rest),\n            _return_expr=return_expr,\n            _explicit_return=explicit_return,\n        )\n\n\nJSON_STRINGIFY = FunctionStringVar.create(\n    \"JSON.stringify\", _var_type=ReflexCallable[[Any], str]\n)\nARRAY_ISARRAY = FunctionStringVar.create(\n    \"Array.isArray\", _var_type=ReflexCallable[[Any], bool]\n)\nPROTOTYPE_TO_STRING = FunctionStringVar.create(\n    \"((__to_string) => __to_string.toString())\",\n    _var_type=ReflexCallable[[Any], str],\n)\n"
  },
  {
    "path": "reflex/vars/number.py",
    "content": "\"\"\"Immutable number vars.\"\"\"\n\nfrom __future__ import annotations\n\nimport dataclasses\nimport decimal\nimport json\nimport math\nfrom collections.abc import Callable\nfrom typing import TYPE_CHECKING, Any, NoReturn, TypeVar, overload\n\nfrom typing_extensions import TypeVar as TypeVarExt\n\nfrom reflex.constants.base import Dirs\nfrom reflex.utils.exceptions import (\n    PrimitiveUnserializableToJSONError,\n    VarTypeError,\n    VarValueError,\n)\nfrom reflex.utils.imports import ImportDict, ImportVar\nfrom reflex.utils.types import safe_issubclass\n\nfrom .base import (\n    CustomVarOperationReturn,\n    LiteralVar,\n    Var,\n    VarData,\n    unionize,\n    var_operation,\n    var_operation_return,\n)\n\nNUMBER_T = TypeVarExt(\n    \"NUMBER_T\",\n    bound=(int | float | decimal.Decimal),\n    default=(int | float | decimal.Decimal),\n    covariant=True,\n)\n\nif TYPE_CHECKING:\n    from .sequence import ArrayVar\n\n\ndef raise_unsupported_operand_types(\n    operator: str, operands_types: tuple[type, ...]\n) -> NoReturn:\n    \"\"\"Raise an unsupported operand types error.\n\n    Args:\n        operator: The operator.\n        operands_types: The types of the operands.\n\n    Raises:\n        VarTypeError: The operand types are unsupported.\n    \"\"\"\n    msg = f\"Unsupported Operand type(s) for {operator}: {', '.join(t.__name__ for t in operands_types)}\"\n    raise VarTypeError(msg)\n\n\nclass NumberVar(Var[NUMBER_T], python_types=(int, float, decimal.Decimal)):\n    \"\"\"Base class for immutable number vars.\"\"\"\n\n    def __add__(self, other: number_types) -> NumberVar:\n        \"\"\"Add two numbers.\n\n        Args:\n            other: The other number.\n\n        Returns:\n            The number addition operation.\n        \"\"\"\n        if not isinstance(other, NUMBER_TYPES):\n            raise_unsupported_operand_types(\"+\", (type(self), type(other)))\n        return number_add_operation(self, +other)\n\n    def __radd__(self, other: number_types) -> NumberVar:\n        \"\"\"Add two numbers.\n\n        Args:\n            other: The other number.\n\n        Returns:\n            The number addition operation.\n        \"\"\"\n        if not isinstance(other, NUMBER_TYPES):\n            raise_unsupported_operand_types(\"+\", (type(other), type(self)))\n        return number_add_operation(+other, self)\n\n    def __sub__(self, other: number_types) -> NumberVar:\n        \"\"\"Subtract two numbers.\n\n        Args:\n            other: The other number.\n\n        Returns:\n            The number subtraction operation.\n        \"\"\"\n        if not isinstance(other, NUMBER_TYPES):\n            raise_unsupported_operand_types(\"-\", (type(self), type(other)))\n\n        return number_subtract_operation(self, +other)\n\n    def __rsub__(self, other: number_types) -> NumberVar:\n        \"\"\"Subtract two numbers.\n\n        Args:\n            other: The other number.\n\n        Returns:\n            The number subtraction operation.\n        \"\"\"\n        if not isinstance(other, NUMBER_TYPES):\n            raise_unsupported_operand_types(\"-\", (type(other), type(self)))\n\n        return number_subtract_operation(+other, self)\n\n    def __abs__(self):\n        \"\"\"Get the absolute value of the number.\n\n        Returns:\n            The number absolute operation.\n        \"\"\"\n        return number_abs_operation(self)\n\n    @overload\n    def __mul__(self, other: number_types | boolean_types) -> NumberVar: ...\n\n    @overload\n    def __mul__(self, other: list | tuple | set | ArrayVar) -> ArrayVar: ...\n\n    def __mul__(self, other: Any):\n        \"\"\"Multiply two numbers.\n\n        Args:\n            other: The other number.\n\n        Returns:\n            The number multiplication operation.\n        \"\"\"\n        from .sequence import ArrayVar, LiteralArrayVar\n\n        if isinstance(other, (list, tuple, ArrayVar)):\n            if isinstance(other, ArrayVar):\n                return other * self\n            return LiteralArrayVar.create(other) * self\n\n        if not isinstance(other, NUMBER_TYPES):\n            raise_unsupported_operand_types(\"*\", (type(self), type(other)))\n\n        return number_multiply_operation(self, +other)\n\n    @overload\n    def __rmul__(self, other: number_types | boolean_types) -> NumberVar: ...\n\n    @overload\n    def __rmul__(self, other: list | tuple | set | ArrayVar) -> ArrayVar: ...\n\n    def __rmul__(self, other: Any):\n        \"\"\"Multiply two numbers.\n\n        Args:\n            other: The other number.\n\n        Returns:\n            The number multiplication operation.\n        \"\"\"\n        from .sequence import ArrayVar, LiteralArrayVar\n\n        if isinstance(other, (list, tuple, ArrayVar)):\n            if isinstance(other, ArrayVar):\n                return other * self\n            return LiteralArrayVar.create(other) * self\n\n        if not isinstance(other, NUMBER_TYPES):\n            raise_unsupported_operand_types(\"*\", (type(other), type(self)))\n\n        return number_multiply_operation(+other, self)\n\n    def __truediv__(self, other: number_types) -> NumberVar:\n        \"\"\"Divide two numbers.\n\n        Args:\n            other: The other number.\n\n        Returns:\n            The number true division operation.\n        \"\"\"\n        if not isinstance(other, NUMBER_TYPES):\n            raise_unsupported_operand_types(\"/\", (type(self), type(other)))\n\n        return number_true_division_operation(self, +other)\n\n    def __rtruediv__(self, other: number_types) -> NumberVar:\n        \"\"\"Divide two numbers.\n\n        Args:\n            other: The other number.\n\n        Returns:\n            The number true division operation.\n        \"\"\"\n        if not isinstance(other, NUMBER_TYPES):\n            raise_unsupported_operand_types(\"/\", (type(other), type(self)))\n\n        return number_true_division_operation(+other, self)\n\n    def __floordiv__(self, other: number_types) -> NumberVar:\n        \"\"\"Floor divide two numbers.\n\n        Args:\n            other: The other number.\n\n        Returns:\n            The number floor division operation.\n        \"\"\"\n        if not isinstance(other, NUMBER_TYPES):\n            raise_unsupported_operand_types(\"//\", (type(self), type(other)))\n\n        return number_floor_division_operation(self, +other)\n\n    def __rfloordiv__(self, other: number_types) -> NumberVar:\n        \"\"\"Floor divide two numbers.\n\n        Args:\n            other: The other number.\n\n        Returns:\n            The number floor division operation.\n        \"\"\"\n        if not isinstance(other, NUMBER_TYPES):\n            raise_unsupported_operand_types(\"//\", (type(other), type(self)))\n\n        return number_floor_division_operation(+other, self)\n\n    def __mod__(self, other: number_types) -> NumberVar:\n        \"\"\"Modulo two numbers.\n\n        Args:\n            other: The other number.\n\n        Returns:\n            The number modulo operation.\n        \"\"\"\n        if not isinstance(other, NUMBER_TYPES):\n            raise_unsupported_operand_types(\"%\", (type(self), type(other)))\n\n        return number_modulo_operation(self, +other)\n\n    def __rmod__(self, other: number_types) -> NumberVar:\n        \"\"\"Modulo two numbers.\n\n        Args:\n            other: The other number.\n\n        Returns:\n            The number modulo operation.\n        \"\"\"\n        if not isinstance(other, NUMBER_TYPES):\n            raise_unsupported_operand_types(\"%\", (type(other), type(self)))\n\n        return number_modulo_operation(+other, self)\n\n    def __pow__(self, other: number_types) -> NumberVar:\n        \"\"\"Exponentiate two numbers.\n\n        Args:\n            other: The other number.\n\n        Returns:\n            The number exponent operation.\n        \"\"\"\n        if not isinstance(other, NUMBER_TYPES):\n            raise_unsupported_operand_types(\"**\", (type(self), type(other)))\n\n        return number_exponent_operation(self, +other)\n\n    def __rpow__(self, other: number_types) -> NumberVar:\n        \"\"\"Exponentiate two numbers.\n\n        Args:\n            other: The other number.\n\n        Returns:\n            The number exponent operation.\n        \"\"\"\n        if not isinstance(other, NUMBER_TYPES):\n            raise_unsupported_operand_types(\"**\", (type(other), type(self)))\n\n        return number_exponent_operation(+other, self)\n\n    def __neg__(self) -> NumberVar:\n        \"\"\"Negate the number.\n\n        Returns:\n            The number negation operation.\n        \"\"\"\n        return number_negate_operation(self)  # pyright: ignore [reportReturnType]\n\n    def __invert__(self):\n        \"\"\"Boolean NOT the number.\n\n        Returns:\n            The boolean NOT operation.\n        \"\"\"\n        return boolean_not_operation(self.bool())\n\n    def __pos__(self) -> NumberVar:\n        \"\"\"Positive the number.\n\n        Returns:\n            The number.\n        \"\"\"\n        return self\n\n    def __round__(self, ndigits: int | NumberVar = 0) -> NumberVar:\n        \"\"\"Round the number.\n\n        Args:\n            ndigits: The number of digits to round.\n\n        Returns:\n            The number round operation.\n        \"\"\"\n        if not isinstance(ndigits, NUMBER_TYPES):\n            raise_unsupported_operand_types(\"round\", (type(self), type(ndigits)))\n\n        return number_round_operation(self, +ndigits)\n\n    def __ceil__(self):\n        \"\"\"Ceil the number.\n\n        Returns:\n            The number ceil operation.\n        \"\"\"\n        return number_ceil_operation(self)\n\n    def __floor__(self):\n        \"\"\"Floor the number.\n\n        Returns:\n            The number floor operation.\n        \"\"\"\n        return number_floor_operation(self)\n\n    def __trunc__(self):\n        \"\"\"Trunc the number.\n\n        Returns:\n            The number trunc operation.\n        \"\"\"\n        return number_trunc_operation(self)\n\n    def __lt__(self, other: number_types) -> BooleanVar:\n        \"\"\"Less than comparison.\n\n        Args:\n            other: The other number.\n\n        Returns:\n            The result of the comparison.\n        \"\"\"\n        if not isinstance(other, NUMBER_TYPES):\n            raise_unsupported_operand_types(\"<\", (type(self), type(other)))\n        return less_than_operation(+self, +other)\n\n    def __le__(self, other: number_types) -> BooleanVar:\n        \"\"\"Less than or equal comparison.\n\n        Args:\n            other: The other number.\n\n        Returns:\n            The result of the comparison.\n        \"\"\"\n        if not isinstance(other, NUMBER_TYPES):\n            raise_unsupported_operand_types(\"<=\", (type(self), type(other)))\n        return less_than_or_equal_operation(+self, +other)\n\n    def __eq__(self, other: Any):\n        \"\"\"Equal comparison.\n\n        Args:\n            other: The other number.\n\n        Returns:\n            The result of the comparison.\n        \"\"\"\n        if isinstance(other, NUMBER_TYPES):\n            return equal_operation(+self, +other)\n        return equal_operation(self, other)\n\n    def __ne__(self, other: Any):\n        \"\"\"Not equal comparison.\n\n        Args:\n            other: The other number.\n\n        Returns:\n            The result of the comparison.\n        \"\"\"\n        if isinstance(other, NUMBER_TYPES):\n            return not_equal_operation(+self, +other)\n        return not_equal_operation(self, other)\n\n    def __gt__(self, other: number_types) -> BooleanVar:\n        \"\"\"Greater than comparison.\n\n        Args:\n            other: The other number.\n\n        Returns:\n            The result of the comparison.\n        \"\"\"\n        if not isinstance(other, NUMBER_TYPES):\n            raise_unsupported_operand_types(\">\", (type(self), type(other)))\n        return greater_than_operation(+self, +other)\n\n    def __ge__(self, other: number_types) -> BooleanVar:\n        \"\"\"Greater than or equal comparison.\n\n        Args:\n            other: The other number.\n\n        Returns:\n            The result of the comparison.\n        \"\"\"\n        if not isinstance(other, NUMBER_TYPES):\n            raise_unsupported_operand_types(\">=\", (type(self), type(other)))\n        return greater_than_or_equal_operation(+self, +other)\n\n    def _is_strict_float(self) -> bool:\n        \"\"\"Check if the number is a float.\n\n        Returns:\n            bool: True if the number is a float.\n        \"\"\"\n        return safe_issubclass(self._var_type, float)\n\n    def _is_strict_int(self) -> bool:\n        \"\"\"Check if the number is an int.\n\n        Returns:\n            bool: True if the number is an int.\n        \"\"\"\n        return safe_issubclass(self._var_type, int)\n\n    def __format__(self, format_spec: str) -> str:\n        \"\"\"Format the number.\n\n        Args:\n            format_spec: The format specifier.\n\n        Returns:\n            The formatted number.\n\n        Raises:\n            VarValueError: If the format specifier is not supported.\n        \"\"\"\n        from .sequence import (\n            get_decimal_string_operation,\n            get_decimal_string_separator_operation,\n        )\n\n        separator = \"\"\n\n        if format_spec and format_spec[:1] == \",\":\n            separator = \",\"\n            format_spec = format_spec[1:]\n        elif format_spec and format_spec[:1] == \"_\":\n            separator = \"_\"\n            format_spec = format_spec[1:]\n\n        if (\n            format_spec\n            and format_spec[-1] == \"f\"\n            and format_spec[0] == \".\"\n            and format_spec[1:-1].isdigit()\n        ):\n            how_many_decimals = int(format_spec[1:-1])\n            return f\"{get_decimal_string_operation(self, Var.create(how_many_decimals), Var.create(separator))}\"\n\n        if not format_spec and separator:\n            return (\n                f\"{get_decimal_string_separator_operation(self, Var.create(separator))}\"\n            )\n\n        if format_spec:\n            msg = (\n                f\"Unknown format code '{format_spec}' for object of type 'NumberVar'. It is only supported to use ',', '_', and '.f' for float numbers.\"\n                \"If possible, use computed variables instead: https://reflex.dev/docs/vars/computed-vars/\"\n            )\n            raise VarValueError(msg)\n\n        return super().__format__(format_spec)\n\n\ndef binary_number_operation(\n    func: Callable[[NumberVar, NumberVar], str],\n) -> Callable[[number_types, number_types], NumberVar]:\n    \"\"\"Decorator to create a binary number operation.\n\n    Args:\n        func: The binary number operation function.\n\n    Returns:\n        The binary number operation.\n    \"\"\"\n\n    @var_operation\n    def operation(lhs: NumberVar, rhs: NumberVar):\n        return var_operation_return(\n            js_expression=func(lhs, rhs),\n            var_type=unionize(lhs._var_type, rhs._var_type),\n        )\n\n    def wrapper(lhs: number_types, rhs: number_types) -> NumberVar:\n        \"\"\"Create the binary number operation.\n\n        Args:\n            lhs: The first number.\n            rhs: The second number.\n\n        Returns:\n            The binary number operation.\n        \"\"\"\n        return operation(lhs, rhs)  # pyright: ignore [reportReturnType, reportArgumentType]\n\n    return wrapper\n\n\n@binary_number_operation\ndef number_add_operation(lhs: NumberVar, rhs: NumberVar):\n    \"\"\"Add two numbers.\n\n    Args:\n        lhs: The first number.\n        rhs: The second number.\n\n    Returns:\n        The number addition operation.\n    \"\"\"\n    return f\"({lhs} + {rhs})\"\n\n\n@binary_number_operation\ndef number_subtract_operation(lhs: NumberVar, rhs: NumberVar):\n    \"\"\"Subtract two numbers.\n\n    Args:\n        lhs: The first number.\n        rhs: The second number.\n\n    Returns:\n        The number subtraction operation.\n    \"\"\"\n    return f\"({lhs} - {rhs})\"\n\n\n@var_operation\ndef number_abs_operation(value: NumberVar):\n    \"\"\"Get the absolute value of the number.\n\n    Args:\n        value: The number.\n\n    Returns:\n        The number absolute operation.\n    \"\"\"\n    return var_operation_return(\n        js_expression=f\"Math.abs({value})\", var_type=value._var_type\n    )\n\n\n@binary_number_operation\ndef number_multiply_operation(lhs: NumberVar, rhs: NumberVar):\n    \"\"\"Multiply two numbers.\n\n    Args:\n        lhs: The first number.\n        rhs: The second number.\n\n    Returns:\n        The number multiplication operation.\n    \"\"\"\n    return f\"({lhs} * {rhs})\"\n\n\n@var_operation\ndef number_negate_operation(\n    value: NumberVar[NUMBER_T],\n) -> CustomVarOperationReturn[NUMBER_T]:\n    \"\"\"Negate the number.\n\n    Args:\n        value: The number.\n\n    Returns:\n        The number negation operation.\n    \"\"\"\n    return var_operation_return(js_expression=f\"-({value})\", var_type=value._var_type)\n\n\n@binary_number_operation\ndef number_true_division_operation(lhs: NumberVar, rhs: NumberVar):\n    \"\"\"Divide two numbers.\n\n    Args:\n        lhs: The first number.\n        rhs: The second number.\n\n    Returns:\n        The number true division operation.\n    \"\"\"\n    return f\"({lhs} / {rhs})\"\n\n\n@binary_number_operation\ndef number_floor_division_operation(lhs: NumberVar, rhs: NumberVar):\n    \"\"\"Floor divide two numbers.\n\n    Args:\n        lhs: The first number.\n        rhs: The second number.\n\n    Returns:\n        The number floor division operation.\n    \"\"\"\n    return f\"Math.floor({lhs} / {rhs})\"\n\n\n@binary_number_operation\ndef number_modulo_operation(lhs: NumberVar, rhs: NumberVar):\n    \"\"\"Modulo two numbers.\n\n    Args:\n        lhs: The first number.\n        rhs: The second number.\n\n    Returns:\n        The number modulo operation.\n    \"\"\"\n    return f\"({lhs} % {rhs})\"\n\n\n@binary_number_operation\ndef number_exponent_operation(lhs: NumberVar, rhs: NumberVar):\n    \"\"\"Exponentiate two numbers.\n\n    Args:\n        lhs: The first number.\n        rhs: The second number.\n\n    Returns:\n        The number exponent operation.\n    \"\"\"\n    return f\"({lhs} ** {rhs})\"\n\n\n@var_operation\ndef number_round_operation(value: NumberVar, ndigits: NumberVar | int):\n    \"\"\"Round the number.\n\n    Args:\n        value: The number.\n        ndigits: The number of digits.\n\n    Returns:\n        The number round operation.\n    \"\"\"\n    if (isinstance(ndigits, LiteralNumberVar) and ndigits._var_value == 0) or (\n        isinstance(ndigits, int) and ndigits == 0\n    ):\n        return var_operation_return(js_expression=f\"Math.round({value})\", var_type=int)\n    return var_operation_return(\n        js_expression=f\"(+{value}.toFixed({ndigits}))\", var_type=float\n    )\n\n\n@var_operation\ndef number_ceil_operation(value: NumberVar):\n    \"\"\"Ceil the number.\n\n    Args:\n        value: The number.\n\n    Returns:\n        The number ceil operation.\n    \"\"\"\n    return var_operation_return(js_expression=f\"Math.ceil({value})\", var_type=int)\n\n\n@var_operation\ndef number_floor_operation(value: NumberVar):\n    \"\"\"Floor the number.\n\n    Args:\n        value: The number.\n\n    Returns:\n        The number floor operation.\n    \"\"\"\n    return var_operation_return(js_expression=f\"Math.floor({value})\", var_type=int)\n\n\n@var_operation\ndef number_trunc_operation(value: NumberVar):\n    \"\"\"Trunc the number.\n\n    Args:\n        value: The number.\n\n    Returns:\n        The number trunc operation.\n    \"\"\"\n    return var_operation_return(js_expression=f\"Math.trunc({value})\", var_type=int)\n\n\nclass BooleanVar(NumberVar[bool], python_types=bool):\n    \"\"\"Base class for immutable boolean vars.\"\"\"\n\n    def __invert__(self):\n        \"\"\"NOT the boolean.\n\n        Returns:\n            The boolean NOT operation.\n        \"\"\"\n        return boolean_not_operation(self)\n\n    def __int__(self):\n        \"\"\"Convert the boolean to an int.\n\n        Returns:\n            The boolean to int operation.\n        \"\"\"\n        return boolean_to_number_operation(self)\n\n    def __pos__(self):\n        \"\"\"Convert the boolean to an int.\n\n        Returns:\n            The boolean to int operation.\n        \"\"\"\n        return boolean_to_number_operation(self)\n\n    def bool(self) -> BooleanVar:\n        \"\"\"Boolean conversion.\n\n        Returns:\n            The boolean value of the boolean.\n        \"\"\"\n        return self\n\n    def __lt__(self, other: Any):\n        \"\"\"Less than comparison.\n\n        Args:\n            other: The other boolean.\n\n        Returns:\n            The result of the comparison.\n        \"\"\"\n        return +self < other\n\n    def __le__(self, other: Any):\n        \"\"\"Less than or equal comparison.\n\n        Args:\n            other: The other boolean.\n\n        Returns:\n            The result of the comparison.\n        \"\"\"\n        return +self <= other\n\n    def __gt__(self, other: Any):\n        \"\"\"Greater than comparison.\n\n        Args:\n            other: The other boolean.\n\n        Returns:\n            The result of the comparison.\n        \"\"\"\n        return +self > other\n\n    def __ge__(self, other: Any):\n        \"\"\"Greater than or equal comparison.\n\n        Args:\n            other: The other boolean.\n\n        Returns:\n            The result of the comparison.\n        \"\"\"\n        return +self >= other\n\n\n@var_operation\ndef boolean_to_number_operation(value: BooleanVar):\n    \"\"\"Convert the boolean to a number.\n\n    Args:\n        value: The boolean.\n\n    Returns:\n        The boolean to number operation.\n    \"\"\"\n    return var_operation_return(js_expression=f\"Number({value})\", var_type=int)\n\n\ndef comparison_operator(\n    func: Callable[[Var, Var], str],\n) -> Callable[[Var | Any, Var | Any], BooleanVar]:\n    \"\"\"Decorator to create a comparison operation.\n\n    Args:\n        func: The comparison operation function.\n\n    Returns:\n        The comparison operation.\n    \"\"\"\n\n    @var_operation\n    def operation(lhs: Var, rhs: Var):\n        return var_operation_return(\n            js_expression=func(lhs, rhs),\n            var_type=bool,\n        )\n\n    def wrapper(lhs: Var | Any, rhs: Var | Any) -> BooleanVar:\n        \"\"\"Create the comparison operation.\n\n        Args:\n            lhs: The first value.\n            rhs: The second value.\n\n        Returns:\n            The comparison operation.\n        \"\"\"\n        return operation(lhs, rhs)\n\n    return wrapper\n\n\n@comparison_operator\ndef greater_than_operation(lhs: Var, rhs: Var):\n    \"\"\"Greater than comparison.\n\n    Args:\n        lhs: The first value.\n        rhs: The second value.\n\n    Returns:\n        The result of the comparison.\n    \"\"\"\n    return f\"({lhs} > {rhs})\"\n\n\n@comparison_operator\ndef greater_than_or_equal_operation(lhs: Var, rhs: Var):\n    \"\"\"Greater than or equal comparison.\n\n    Args:\n        lhs: The first value.\n        rhs: The second value.\n\n    Returns:\n        The result of the comparison.\n    \"\"\"\n    return f\"({lhs} >= {rhs})\"\n\n\n@comparison_operator\ndef less_than_operation(lhs: Var, rhs: Var):\n    \"\"\"Less than comparison.\n\n    Args:\n        lhs: The first value.\n        rhs: The second value.\n\n    Returns:\n        The result of the comparison.\n    \"\"\"\n    return f\"({lhs} < {rhs})\"\n\n\n@comparison_operator\ndef less_than_or_equal_operation(lhs: Var, rhs: Var):\n    \"\"\"Less than or equal comparison.\n\n    Args:\n        lhs: The first value.\n        rhs: The second value.\n\n    Returns:\n        The result of the comparison.\n    \"\"\"\n    return f\"({lhs} <= {rhs})\"\n\n\n@comparison_operator\ndef equal_operation(lhs: Var, rhs: Var):\n    \"\"\"Equal comparison.\n\n    Args:\n        lhs: The first value.\n        rhs: The second value.\n\n    Returns:\n        The result of the comparison.\n    \"\"\"\n    return f\"({lhs}?.valueOf?.() === {rhs}?.valueOf?.())\"\n\n\n@comparison_operator\ndef not_equal_operation(lhs: Var, rhs: Var):\n    \"\"\"Not equal comparison.\n\n    Args:\n        lhs: The first value.\n        rhs: The second value.\n\n    Returns:\n        The result of the comparison.\n    \"\"\"\n    return f\"({lhs}?.valueOf?.() !== {rhs}?.valueOf?.())\"\n\n\n@var_operation\ndef boolean_not_operation(value: BooleanVar):\n    \"\"\"Boolean NOT the boolean.\n\n    Args:\n        value: The boolean.\n\n    Returns:\n        The boolean NOT operation.\n    \"\"\"\n    return var_operation_return(js_expression=f\"!({value})\", var_type=bool)\n\n\n@dataclasses.dataclass(\n    eq=False,\n    frozen=True,\n    slots=True,\n)\nclass LiteralNumberVar(LiteralVar, NumberVar[NUMBER_T]):\n    \"\"\"Base class for immutable literal number vars.\"\"\"\n\n    _var_value: float | int | decimal.Decimal = dataclasses.field(default=0)\n\n    def json(self) -> str:\n        \"\"\"Get the JSON representation of the var.\n\n        Returns:\n            The JSON representation of the var.\n\n        Raises:\n            PrimitiveUnserializableToJSONError: If the var is unserializable to JSON.\n        \"\"\"\n        if isinstance(self._var_value, decimal.Decimal):\n            return json.dumps(float(self._var_value))\n        if math.isinf(self._var_value) or math.isnan(self._var_value):\n            msg = f\"No valid JSON representation for {self}\"\n            raise PrimitiveUnserializableToJSONError(msg)\n        return json.dumps(self._var_value)\n\n    def __hash__(self) -> int:\n        \"\"\"Calculate the hash value of the object.\n\n        Returns:\n            int: The hash value of the object.\n        \"\"\"\n        return hash((type(self).__name__, self._var_value))\n\n    @classmethod\n    def _get_all_var_data_without_creating_var(\n        cls, value: float | int | decimal.Decimal\n    ) -> VarData | None:\n        \"\"\"Get all the var data without creating the var.\n\n        Args:\n            value: The value of the var.\n\n        Returns:\n            The var data.\n        \"\"\"\n        return None\n\n    @classmethod\n    def create(\n        cls, value: float | int | decimal.Decimal, _var_data: VarData | None = None\n    ):\n        \"\"\"Create the number var.\n\n        Args:\n            value: The value of the var.\n            _var_data: Additional hooks and imports associated with the Var.\n\n        Returns:\n            The number var.\n        \"\"\"\n        if math.isinf(value):\n            js_expr = \"Infinity\" if value > 0 else \"-Infinity\"\n        elif math.isnan(value):\n            js_expr = \"NaN\"\n        else:\n            js_expr = str(value)\n\n        return cls(\n            _js_expr=js_expr,\n            _var_type=type(value),\n            _var_data=_var_data,\n            _var_value=value,\n        )\n\n\n@dataclasses.dataclass(\n    eq=False,\n    frozen=True,\n    slots=True,\n)\nclass LiteralBooleanVar(LiteralVar, BooleanVar):\n    \"\"\"Base class for immutable literal boolean vars.\"\"\"\n\n    _var_value: bool = dataclasses.field(default=False)\n\n    def json(self) -> str:\n        \"\"\"Get the JSON representation of the var.\n\n        Returns:\n            The JSON representation of the var.\n        \"\"\"\n        return \"true\" if self._var_value else \"false\"\n\n    def __hash__(self) -> int:\n        \"\"\"Calculate the hash value of the object.\n\n        Returns:\n            int: The hash value of the object.\n        \"\"\"\n        return hash((type(self).__name__, self._var_value))\n\n    @classmethod\n    def _get_all_var_data_without_creating_var(cls, value: bool) -> VarData | None:\n        \"\"\"Get all the var data without creating the var.\n\n        Args:\n            value: The value of the var.\n\n        Returns:\n            The var data.\n        \"\"\"\n        return None\n\n    @classmethod\n    def create(cls, value: bool, _var_data: VarData | None = None):\n        \"\"\"Create the boolean var.\n\n        Args:\n            value: The value of the var.\n            _var_data: Additional hooks and imports associated with the Var.\n\n        Returns:\n            The boolean var.\n        \"\"\"\n        return cls(\n            _js_expr=\"true\" if value else \"false\",\n            _var_type=bool,\n            _var_data=_var_data,\n            _var_value=value,\n        )\n\n\nnumber_types = NumberVar | int | float | decimal.Decimal\nboolean_types = BooleanVar | bool\n\n\n_IS_TRUE_IMPORT: ImportDict = {\n    f\"$/{Dirs.STATE_PATH}\": [ImportVar(tag=\"isTrue\")],\n}\n\n_IS_NOT_NULL_OR_UNDEFINED_IMPORT: ImportDict = {\n    f\"$/{Dirs.STATE_PATH}\": [ImportVar(tag=\"isNotNullOrUndefined\")],\n}\n\n\n@var_operation\ndef boolify(value: Var):\n    \"\"\"Convert the value to a boolean.\n\n    Args:\n        value: The value.\n\n    Returns:\n        The boolean value.\n    \"\"\"\n    return var_operation_return(\n        js_expression=f\"isTrue({value})\",\n        var_type=bool,\n        var_data=VarData(imports=_IS_TRUE_IMPORT),\n    )\n\n\n@var_operation\ndef is_not_none_operation(value: Var):\n    \"\"\"Check if the value is not None.\n\n    Args:\n        value: The value.\n\n    Returns:\n        The boolean value.\n    \"\"\"\n    return var_operation_return(\n        js_expression=f\"isNotNullOrUndefined({value})\",\n        var_type=bool,\n        var_data=VarData(imports=_IS_NOT_NULL_OR_UNDEFINED_IMPORT),\n    )\n\n\nT = TypeVar(\"T\")\nU = TypeVar(\"U\")\n\n\n@var_operation\ndef ternary_operation(\n    condition: Var[bool], if_true: Var[T], if_false: Var[U]\n) -> CustomVarOperationReturn[T | U]:\n    \"\"\"Create a ternary operation.\n\n    Args:\n        condition: The condition.\n        if_true: The value if the condition is true.\n        if_false: The value if the condition is false.\n\n    Returns:\n        The ternary operation.\n    \"\"\"\n    type_value: type[T] | type[U] = unionize(if_true._var_type, if_false._var_type)\n    value: CustomVarOperationReturn[T | U] = var_operation_return(\n        js_expression=f\"({condition} ? {if_true} : {if_false})\",\n        var_type=type_value,\n    )\n    return value\n\n\nNUMBER_TYPES = (int, float, decimal.Decimal, NumberVar)\n"
  },
  {
    "path": "reflex/vars/object.py",
    "content": "\"\"\"Classes for immutable object vars.\"\"\"\n\nfrom __future__ import annotations\n\nimport collections.abc\nimport dataclasses\nimport typing\nfrom collections.abc import Mapping\nfrom importlib.util import find_spec\nfrom typing import (\n    Any,\n    NoReturn,\n    TypeVar,\n    get_args,\n    get_type_hints,\n    is_typeddict,\n    overload,\n)\n\nfrom rich.markup import escape\n\nfrom reflex.utils import types\nfrom reflex.utils.exceptions import VarAttributeError\nfrom reflex.utils.types import (\n    GenericType,\n    get_attribute_access_type,\n    get_origin,\n    safe_issubclass,\n    unionize,\n)\n\nfrom .base import (\n    CachedVarOperation,\n    LiteralVar,\n    Var,\n    VarData,\n    cached_property_no_lock,\n    figure_out_type,\n    var_operation,\n    var_operation_return,\n)\nfrom .number import BooleanVar, NumberVar, raise_unsupported_operand_types\nfrom .sequence import ArrayVar, LiteralArrayVar, StringVar\n\nOBJECT_TYPE = TypeVar(\"OBJECT_TYPE\", covariant=True)\n\nKEY_TYPE = TypeVar(\"KEY_TYPE\")\nVALUE_TYPE = TypeVar(\"VALUE_TYPE\")\n\nARRAY_INNER_TYPE = TypeVar(\"ARRAY_INNER_TYPE\")\n\nOTHER_KEY_TYPE = TypeVar(\"OTHER_KEY_TYPE\")\n\n\ndef _determine_value_type(var_type: GenericType):\n    origin_var_type = get_origin(var_type) or var_type\n\n    if origin_var_type in types.UnionTypes:\n        return unionize(*[\n            _determine_value_type(arg)\n            for arg in get_args(var_type)\n            if arg is not type(None)\n        ])\n\n    if is_typeddict(origin_var_type) or dataclasses.is_dataclass(origin_var_type):\n        annotations = get_type_hints(origin_var_type)\n        return unionize(*annotations.values())\n\n    if origin_var_type in [dict, Mapping, collections.abc.Mapping]:\n        args = get_args(var_type)\n        return args[1] if args else Any\n\n    return Any\n\n\nPYTHON_TYPES = (Mapping,)\nif find_spec(\"pydantic\"):\n    import pydantic\n    import pydantic.v1\n\n    PYTHON_TYPES += (pydantic.BaseModel, pydantic.v1.BaseModel)\n\n\nclass ObjectVar(Var[OBJECT_TYPE], python_types=PYTHON_TYPES):\n    \"\"\"Base class for immutable object vars.\"\"\"\n\n    def _key_type(self) -> type:\n        \"\"\"Get the type of the keys of the object.\n\n        Returns:\n            The type of the keys of the object.\n        \"\"\"\n        return str\n\n    @overload\n    def _value_type(\n        self: ObjectVar[Mapping[Any, VALUE_TYPE]],\n    ) -> type[VALUE_TYPE]: ...\n\n    @overload\n    def _value_type(self) -> GenericType: ...\n\n    def _value_type(self) -> GenericType:\n        \"\"\"Get the type of the values of the object.\n\n        Returns:\n            The type of the values of the object.\n        \"\"\"\n        return _determine_value_type(self._var_type)\n\n    def keys(self) -> ArrayVar[list[str]]:\n        \"\"\"Get the keys of the object.\n\n        Returns:\n            The keys of the object.\n        \"\"\"\n        return object_keys_operation(self)\n\n    @overload\n    def values(\n        self: ObjectVar[Mapping[Any, VALUE_TYPE]],\n    ) -> ArrayVar[list[VALUE_TYPE]]: ...\n\n    @overload\n    def values(self) -> ArrayVar: ...\n\n    def values(self) -> ArrayVar:\n        \"\"\"Get the values of the object.\n\n        Returns:\n            The values of the object.\n        \"\"\"\n        return object_values_operation(self)\n\n    @overload\n    def entries(\n        self: ObjectVar[Mapping[Any, VALUE_TYPE]],\n    ) -> ArrayVar[list[tuple[str, VALUE_TYPE]]]: ...\n\n    @overload\n    def entries(self) -> ArrayVar: ...\n\n    def entries(self) -> ArrayVar:\n        \"\"\"Get the entries of the object.\n\n        Returns:\n            The entries of the object.\n        \"\"\"\n        return object_entries_operation(self)\n\n    items = entries\n\n    def length(self) -> NumberVar[int]:\n        \"\"\"Get the length of the object.\n\n        Returns:\n            The length of the object.\n        \"\"\"\n        return self.keys().length()\n\n    def merge(self, other: ObjectVar):\n        \"\"\"Merge two objects.\n\n        Args:\n            other: The other object to merge.\n\n        Returns:\n            The merged object.\n        \"\"\"\n        return object_merge_operation(self, other)\n\n    # NoReturn is used here to catch when key value is Any\n    @overload\n    def __getitem__(  # pyright: ignore [reportOverlappingOverload]\n        self: ObjectVar[Mapping[Any, NoReturn]],\n        key: Var | Any,\n    ) -> Var: ...\n\n    @overload\n    def __getitem__(\n        self: (ObjectVar[Mapping[Any, bool]]),\n        key: Var | Any,\n    ) -> BooleanVar: ...\n\n    @overload\n    def __getitem__(\n        self: (\n            ObjectVar[Mapping[Any, int]]\n            | ObjectVar[Mapping[Any, float]]\n            | ObjectVar[Mapping[Any, int | float]]\n        ),\n        key: Var | Any,\n    ) -> NumberVar: ...\n\n    @overload\n    def __getitem__(\n        self: ObjectVar[Mapping[Any, str]],\n        key: Var | Any,\n    ) -> StringVar: ...\n\n    @overload\n    def __getitem__(\n        self: ObjectVar[Mapping[Any, list[ARRAY_INNER_TYPE]]],\n        key: Var | Any,\n    ) -> ArrayVar[list[ARRAY_INNER_TYPE]]: ...\n\n    @overload\n    def __getitem__(\n        self: ObjectVar[Mapping[Any, tuple[ARRAY_INNER_TYPE, ...]]],\n        key: Var | Any,\n    ) -> ArrayVar[tuple[ARRAY_INNER_TYPE, ...]]: ...\n\n    @overload\n    def __getitem__(\n        self: ObjectVar[Mapping[Any, Mapping[OTHER_KEY_TYPE, VALUE_TYPE]]],\n        key: Var | Any,\n    ) -> ObjectVar[Mapping[OTHER_KEY_TYPE, VALUE_TYPE]]: ...\n\n    @overload\n    def __getitem__(\n        self: ObjectVar[Mapping[Any, VALUE_TYPE]],\n        key: Var | Any,\n    ) -> Var[VALUE_TYPE]: ...\n\n    def __getitem__(self, key: Var | Any) -> Var:\n        \"\"\"Get an item from the object.\n\n        Args:\n            key: The key to get from the object.\n\n        Returns:\n            The item from the object.\n        \"\"\"\n        from .sequence import LiteralStringVar\n\n        if not isinstance(key, (StringVar, str, int, NumberVar)) or (\n            isinstance(key, NumberVar) and key._is_strict_float()\n        ):\n            raise_unsupported_operand_types(\"[]\", (type(self), type(key)))\n        if isinstance(key, str) and isinstance(Var.create(key), LiteralStringVar):\n            return self.__getattr__(key)\n        return ObjectItemOperation.create(self, key).guess_type()\n\n    def get(self, key: Var | Any, default: Var | Any | None = None) -> Var:\n        \"\"\"Get an item from the object.\n\n        Args:\n            key: The key to get from the object.\n            default: The default value if the key is not found.\n\n        Returns:\n            The item from the object.\n        \"\"\"\n        from reflex.components.core.cond import cond\n\n        if default is None:\n            default = Var.create(None)\n\n        value = self.__getitem__(key)  # pyright: ignore[reportUnknownVariableType,reportAttributeAccessIssue,reportUnknownMemberType]\n\n        return cond(  # pyright: ignore[reportUnknownVariableType]\n            value,\n            value,\n            default,\n        )\n\n    # NoReturn is used here to catch when key value is Any\n    @overload\n    def __getattr__(  # pyright: ignore [reportOverlappingOverload]\n        self: ObjectVar[Mapping[Any, NoReturn]],\n        name: str,\n    ) -> Var: ...\n\n    @overload\n    def __getattr__(\n        self: (\n            ObjectVar[Mapping[Any, int]]\n            | ObjectVar[Mapping[Any, float]]\n            | ObjectVar[Mapping[Any, int | float]]\n        ),\n        name: str,\n    ) -> NumberVar: ...\n\n    @overload\n    def __getattr__(\n        self: ObjectVar[Mapping[Any, str]],\n        name: str,\n    ) -> StringVar: ...\n\n    @overload\n    def __getattr__(\n        self: ObjectVar[Mapping[Any, list[ARRAY_INNER_TYPE]]],\n        name: str,\n    ) -> ArrayVar[list[ARRAY_INNER_TYPE]]: ...\n\n    @overload\n    def __getattr__(\n        self: ObjectVar[Mapping[Any, tuple[ARRAY_INNER_TYPE, ...]]],\n        name: str,\n    ) -> ArrayVar[tuple[ARRAY_INNER_TYPE, ...]]: ...\n\n    @overload\n    def __getattr__(\n        self: ObjectVar[Mapping[Any, Mapping[OTHER_KEY_TYPE, VALUE_TYPE]]],\n        name: str,\n    ) -> ObjectVar[Mapping[OTHER_KEY_TYPE, VALUE_TYPE]]: ...\n\n    @overload\n    def __getattr__(\n        self: ObjectVar,\n        name: str,\n    ) -> ObjectItemOperation: ...\n\n    def __getattr__(self, name: str) -> Var:\n        \"\"\"Get an attribute of the var.\n\n        Args:\n            name: The name of the attribute.\n\n        Returns:\n            The attribute of the var.\n\n        Raises:\n            VarAttributeError: The State var has no such attribute or may have been annotated wrongly.\n        \"\"\"\n        if name.startswith(\"__\") and name.endswith(\"__\"):\n            return getattr(super(type(self), self), name)\n\n        var_type = self._var_type\n\n        var_type = types.value_inside_optional(var_type)\n\n        fixed_type = get_origin(var_type) or var_type\n\n        if (\n            is_typeddict(fixed_type)\n            or (\n                isinstance(fixed_type, type)\n                and not safe_issubclass(fixed_type, Mapping)\n            )\n            or (fixed_type in types.UnionTypes)\n        ):\n            attribute_type = get_attribute_access_type(var_type, name)\n            if attribute_type is None:\n                msg = (\n                    f\"The State var `{self!s}` of type {escape(str(self._var_type))} has no attribute '{name}' or may have been annotated \"\n                    f\"wrongly.\"\n                )\n                raise VarAttributeError(msg)\n            return ObjectItemOperation.create(self, name, attribute_type).guess_type()\n        return ObjectItemOperation.create(self, name).guess_type()\n\n    def contains(self, key: Var | Any) -> BooleanVar:\n        \"\"\"Check if the object contains a key.\n\n        Args:\n            key: The key to check.\n\n        Returns:\n            The result of the check.\n        \"\"\"\n        return object_has_own_property_operation(self, key)\n\n\n@dataclasses.dataclass(\n    eq=False,\n    frozen=True,\n    slots=True,\n)\nclass LiteralObjectVar(CachedVarOperation, ObjectVar[OBJECT_TYPE], LiteralVar):\n    \"\"\"Base class for immutable literal object vars.\"\"\"\n\n    _var_value: Mapping[Var | Any, Var | Any] = dataclasses.field(default_factory=dict)\n\n    def _key_type(self) -> type:\n        \"\"\"Get the type of the keys of the object.\n\n        Returns:\n            The type of the keys of the object.\n        \"\"\"\n        args_list = typing.get_args(self._var_type)\n        return args_list[0] if args_list else Any  # pyright: ignore [reportReturnType]\n\n    def _value_type(self) -> type:\n        \"\"\"Get the type of the values of the object.\n\n        Returns:\n            The type of the values of the object.\n        \"\"\"\n        args_list = typing.get_args(self._var_type)\n        return args_list[1] if args_list else Any  # pyright: ignore [reportReturnType]\n\n    @cached_property_no_lock\n    def _cached_var_name(self) -> str:\n        \"\"\"The name of the var.\n\n        Returns:\n            The name of the var.\n        \"\"\"\n        return (\n            \"({ \"\n            + \", \".join([\n                f\"[{LiteralVar.create(key)!s}] : {LiteralVar.create(value)!s}\"\n                for key, value in self._var_value.items()\n            ])\n            + \" })\"\n        )\n\n    def json(self) -> str:\n        \"\"\"Get the JSON representation of the object.\n\n        Returns:\n            The JSON representation of the object.\n\n        Raises:\n            TypeError: The keys and values of the object must be literal vars to get the JSON representation\n        \"\"\"\n        keys_and_values = []\n        for key, value in self._var_value.items():\n            key = LiteralVar.create(key)\n            value = LiteralVar.create(value)\n            if not isinstance(key, LiteralVar) or not isinstance(value, LiteralVar):\n                msg = \"The keys and values of the object must be literal vars to get the JSON representation.\"\n                raise TypeError(msg)\n            keys_and_values.append(f\"{key.json()}:{value.json()}\")\n        return \"{\" + \", \".join(keys_and_values) + \"}\"\n\n    def __hash__(self) -> int:\n        \"\"\"Get the hash of the var.\n\n        Returns:\n            The hash of the var.\n        \"\"\"\n        return hash((type(self).__name__, self._js_expr))\n\n    @classmethod\n    def _get_all_var_data_without_creating_var(\n        cls,\n        value: Mapping,\n    ) -> VarData | None:\n        \"\"\"Get all the var data without creating a var.\n\n        Args:\n            value: The value to get the var data from.\n\n        Returns:\n            The var data.\n        \"\"\"\n        return VarData.merge(\n            LiteralArrayVar._get_all_var_data_without_creating_var(value),\n            LiteralArrayVar._get_all_var_data_without_creating_var(value.values()),\n        )\n\n    @cached_property_no_lock\n    def _cached_get_all_var_data(self) -> VarData | None:\n        \"\"\"Get all the var data.\n\n        Returns:\n            The var data.\n        \"\"\"\n        return VarData.merge(\n            LiteralArrayVar._get_all_var_data_without_creating_var(self._var_value),\n            LiteralArrayVar._get_all_var_data_without_creating_var(\n                self._var_value.values()\n            ),\n            self._var_data,\n        )\n\n    @classmethod\n    def create(\n        cls,\n        _var_value: Mapping,\n        _var_type: type[OBJECT_TYPE] | None = None,\n        _var_data: VarData | None = None,\n    ) -> LiteralObjectVar[OBJECT_TYPE]:\n        \"\"\"Create the literal object var.\n\n        Args:\n            _var_value: The value of the var.\n            _var_type: The type of the var.\n            _var_data: Additional hooks and imports associated with the Var.\n\n        Returns:\n            The literal object var.\n\n        Raises:\n            TypeError: If the value is not a mapping type or a dataclass.\n        \"\"\"\n        if not isinstance(_var_value, collections.abc.Mapping):\n            from reflex.utils.serializers import serialize\n\n            serialized = serialize(_var_value, get_type=False)\n            if not isinstance(serialized, collections.abc.Mapping):\n                msg = f\"Expected a mapping type or a dataclass, got {_var_value!r} of type {type(_var_value).__name__}.\"\n                raise TypeError(msg)\n\n            return LiteralObjectVar(\n                _js_expr=\"\",\n                _var_type=(type(_var_value) if _var_type is None else _var_type),\n                _var_data=_var_data,\n                _var_value=serialized,\n            )\n\n        return LiteralObjectVar(\n            _js_expr=\"\",\n            _var_type=(figure_out_type(_var_value) if _var_type is None else _var_type),\n            _var_data=_var_data,\n            _var_value=_var_value,\n        )\n\n\n@var_operation\ndef object_keys_operation(value: ObjectVar):\n    \"\"\"Get the keys of an object.\n\n    Args:\n        value: The object to get the keys from.\n\n    Returns:\n        The keys of the object.\n    \"\"\"\n    return var_operation_return(\n        js_expression=f\"Object.keys({value} ?? {{}})\",\n        var_type=list[str],\n    )\n\n\n@var_operation\ndef object_values_operation(value: ObjectVar):\n    \"\"\"Get the values of an object.\n\n    Args:\n        value: The object to get the values from.\n\n    Returns:\n        The values of the object.\n    \"\"\"\n    return var_operation_return(\n        js_expression=f\"Object.values({value} ?? {{}})\",\n        var_type=list[value._value_type()],\n    )\n\n\n@var_operation\ndef object_entries_operation(value: ObjectVar):\n    \"\"\"Get the entries of an object.\n\n    Args:\n        value: The object to get the entries from.\n\n    Returns:\n        The entries of the object.\n    \"\"\"\n    return var_operation_return(\n        js_expression=f\"Object.entries({value} ?? {{}})\",\n        var_type=list[tuple[str, value._value_type()]],\n    )\n\n\n@var_operation\ndef object_merge_operation(lhs: ObjectVar, rhs: ObjectVar):\n    \"\"\"Merge two objects.\n\n    Args:\n        lhs: The first object to merge.\n        rhs: The second object to merge.\n\n    Returns:\n        The merged object.\n    \"\"\"\n    return var_operation_return(\n        js_expression=f\"({{...{lhs}, ...{rhs}}})\",\n        var_type=Mapping[\n            lhs._key_type() | rhs._key_type(),\n            lhs._value_type() | rhs._value_type(),\n        ],\n    )\n\n\n@dataclasses.dataclass(\n    eq=False,\n    frozen=True,\n    slots=True,\n)\nclass ObjectItemOperation(CachedVarOperation, Var):\n    \"\"\"Operation to get an item from an object.\"\"\"\n\n    _object: ObjectVar = dataclasses.field(\n        default_factory=lambda: LiteralObjectVar.create({})\n    )\n    _key: Var | Any = dataclasses.field(default_factory=lambda: LiteralVar.create(None))\n\n    @cached_property_no_lock\n    def _cached_var_name(self) -> str:\n        \"\"\"The name of the operation.\n\n        Returns:\n            The name of the operation.\n        \"\"\"\n        return f\"{self._object!s}?.[{self._key!s}]\"\n\n    @classmethod\n    def create(\n        cls,\n        object: ObjectVar,\n        key: Var | Any,\n        _var_type: GenericType | None = None,\n        _var_data: VarData | None = None,\n    ) -> ObjectItemOperation:\n        \"\"\"Create the object item operation.\n\n        Args:\n            object: The object to get the item from.\n            key: The key to get from the object.\n            _var_type: The type of the item.\n            _var_data: Additional hooks and imports associated with the operation.\n\n        Returns:\n            The object item operation.\n        \"\"\"\n        return cls(\n            _js_expr=\"\",\n            _var_type=object._value_type() if _var_type is None else _var_type,\n            _var_data=_var_data,\n            _object=object,\n            _key=key if isinstance(key, Var) else LiteralVar.create(key),\n        )\n\n\n@var_operation\ndef object_has_own_property_operation(object: ObjectVar, key: Var):\n    \"\"\"Check if an object has a key.\n\n    Args:\n        object: The object to check.\n        key: The key to check.\n\n    Returns:\n        The result of the check.\n    \"\"\"\n    return var_operation_return(\n        js_expression=f\"{object}.hasOwnProperty({key})\",\n        var_type=bool,\n    )\n"
  },
  {
    "path": "reflex/vars/sequence.py",
    "content": "\"\"\"Collection of string classes and utilities.\"\"\"\n\nfrom __future__ import annotations\n\nimport collections.abc\nimport dataclasses\nimport decimal\nimport inspect\nimport json\nimport re\nfrom collections.abc import Iterable, Mapping, Sequence\nfrom typing import TYPE_CHECKING, Any, Literal, TypeVar, get_args, overload\n\nfrom typing_extensions import TypeVar as TypingExtensionsTypeVar\n\nfrom reflex import constants\nfrom reflex.constants.base import REFLEX_VAR_OPENING_TAG\nfrom reflex.utils import types\nfrom reflex.utils.exceptions import VarTypeError\nfrom reflex.utils.types import GenericType, get_origin\n\nfrom .base import (\n    CachedVarOperation,\n    CustomVarOperationReturn,\n    LiteralVar,\n    Var,\n    VarData,\n    _global_vars,\n    cached_property_no_lock,\n    figure_out_type,\n    get_unique_variable_name,\n    unionize,\n    var_operation,\n    var_operation_return,\n)\nfrom .number import (\n    BooleanVar,\n    LiteralNumberVar,\n    NumberVar,\n    raise_unsupported_operand_types,\n)\n\nif TYPE_CHECKING:\n    from .base import BASE_TYPE, DATACLASS_TYPE, SQLA_TYPE\n    from .function import FunctionVar\n    from .object import ObjectVar\n\nARRAY_VAR_TYPE = TypeVar(\"ARRAY_VAR_TYPE\", bound=Sequence, covariant=True)\nOTHER_ARRAY_VAR_TYPE = TypeVar(\"OTHER_ARRAY_VAR_TYPE\", bound=Sequence, covariant=True)\nMAPPING_VAR_TYPE = TypeVar(\"MAPPING_VAR_TYPE\", bound=Mapping, covariant=True)\n\nOTHER_TUPLE = TypeVar(\"OTHER_TUPLE\")\n\nINNER_ARRAY_VAR = TypeVar(\"INNER_ARRAY_VAR\")\n\n\nKEY_TYPE = TypeVar(\"KEY_TYPE\")\nVALUE_TYPE = TypeVar(\"VALUE_TYPE\")\n\n\nclass ArrayVar(Var[ARRAY_VAR_TYPE], python_types=(Sequence, set)):\n    \"\"\"Base class for immutable array vars.\"\"\"\n\n    def join(self, sep: StringVar | str = \"\") -> StringVar:\n        \"\"\"Join the elements of the array.\n\n        Args:\n            sep: The separator between elements.\n\n        Returns:\n            The joined elements.\n        \"\"\"\n        if not isinstance(sep, (StringVar, str)):\n            raise_unsupported_operand_types(\"join\", (type(self), type(sep)))\n        if (\n            isinstance(self, LiteralArrayVar)\n            and (\n                len(\n                    args := [\n                        x\n                        for x in self._var_value\n                        if isinstance(x, (LiteralStringVar, str))\n                    ]\n                )\n                == len(self._var_value)\n            )\n            and isinstance(sep, (LiteralStringVar, str))\n        ):\n            sep_str = sep._var_value if isinstance(sep, LiteralStringVar) else sep\n            return LiteralStringVar.create(\n                sep_str.join(\n                    i._var_value if isinstance(i, LiteralStringVar) else i for i in args\n                )\n            )\n        return array_join_operation(self, sep)\n\n    def reverse(self) -> ArrayVar[ARRAY_VAR_TYPE]:\n        \"\"\"Reverse the array.\n\n        Returns:\n            The reversed array.\n        \"\"\"\n        return array_reverse_operation(self)\n\n    def __add__(self, other: ArrayVar[ARRAY_VAR_TYPE]) -> ArrayVar[ARRAY_VAR_TYPE]:\n        \"\"\"Concatenate two arrays.\n\n        Parameters:\n            other: The other array to concatenate.\n\n        Returns:\n            ArrayConcatOperation: The concatenation of the two arrays.\n        \"\"\"\n        if not isinstance(other, ArrayVar):\n            raise_unsupported_operand_types(\"+\", (type(self), type(other)))\n\n        return array_concat_operation(self, other)\n\n    @overload\n    def __getitem__(self, i: slice) -> ArrayVar[ARRAY_VAR_TYPE]: ...\n\n    @overload\n    def __getitem__(\n        self: (\n            ArrayVar[tuple[int, OTHER_TUPLE]]\n            | ArrayVar[tuple[float, OTHER_TUPLE]]\n            | ArrayVar[tuple[int | float, OTHER_TUPLE]]\n        ),\n        i: Literal[0, -2],\n    ) -> NumberVar: ...\n\n    @overload\n    def __getitem__(\n        self: ArrayVar[tuple[Any, bool]], i: Literal[1, -1]\n    ) -> BooleanVar: ...\n\n    @overload\n    def __getitem__(\n        self: (\n            ArrayVar[tuple[Any, int]]\n            | ArrayVar[tuple[Any, float]]\n            | ArrayVar[tuple[Any, int | float]]\n        ),\n        i: Literal[1, -1],\n    ) -> NumberVar: ...\n\n    @overload\n    def __getitem__(  # pyright: ignore [reportOverlappingOverload]\n        self: ArrayVar[tuple[str, Any]], i: Literal[0, -2]\n    ) -> StringVar: ...\n\n    @overload\n    def __getitem__(\n        self: ArrayVar[tuple[Any, str]], i: Literal[1, -1]\n    ) -> StringVar: ...\n\n    @overload\n    def __getitem__(\n        self: ArrayVar[tuple[bool, Any]], i: Literal[0, -2]\n    ) -> BooleanVar: ...\n\n    @overload\n    def __getitem__(\n        self: ArrayVar[Sequence[bool]], i: int | NumberVar\n    ) -> BooleanVar: ...\n\n    @overload\n    def __getitem__(\n        self: (\n            ArrayVar[Sequence[int]]\n            | ArrayVar[Sequence[float]]\n            | ArrayVar[Sequence[int | float]]\n        ),\n        i: int | NumberVar,\n    ) -> NumberVar: ...\n\n    @overload\n    def __getitem__(self: ArrayVar[Sequence[str]], i: int | NumberVar) -> StringVar: ...\n\n    @overload\n    def __getitem__(\n        self: ArrayVar[Sequence[OTHER_ARRAY_VAR_TYPE]],\n        i: int | NumberVar,\n    ) -> ArrayVar[OTHER_ARRAY_VAR_TYPE]: ...\n\n    @overload\n    def __getitem__(\n        self: ArrayVar[Sequence[MAPPING_VAR_TYPE]],\n        i: int | NumberVar,\n    ) -> ObjectVar[MAPPING_VAR_TYPE]: ...\n\n    @overload\n    def __getitem__(\n        self: ArrayVar[Sequence[BASE_TYPE]],\n        i: int | NumberVar,\n    ) -> ObjectVar[BASE_TYPE]: ...\n\n    @overload\n    def __getitem__(\n        self: ArrayVar[Sequence[SQLA_TYPE]],\n        i: int | NumberVar,\n    ) -> ObjectVar[SQLA_TYPE]: ...\n\n    @overload\n    def __getitem__(\n        self: ArrayVar[Sequence[DATACLASS_TYPE]],\n        i: int | NumberVar,\n    ) -> ObjectVar[DATACLASS_TYPE]: ...\n\n    @overload\n    def __getitem__(self, i: int | NumberVar) -> Var: ...\n\n    def __getitem__(self, i: Any) -> ArrayVar[ARRAY_VAR_TYPE] | Var:\n        \"\"\"Get a slice of the array.\n\n        Args:\n            i: The slice.\n\n        Returns:\n            The array slice operation.\n        \"\"\"\n        if isinstance(i, slice):\n            return ArraySliceOperation.create(self, i)\n        if not isinstance(i, (int, NumberVar)) or (\n            isinstance(i, NumberVar) and i._is_strict_float()\n        ):\n            raise_unsupported_operand_types(\"[]\", (type(self), type(i)))\n        return array_item_operation(self, i)\n\n    def length(self) -> NumberVar[int]:\n        \"\"\"Get the length of the array.\n\n        Returns:\n            The length of the array.\n        \"\"\"\n        return array_length_operation(self)\n\n    @overload\n    @classmethod\n    def range(cls, stop: int | NumberVar, /) -> ArrayVar[list[int]]: ...\n\n    @overload\n    @classmethod\n    def range(\n        cls,\n        start: int | NumberVar,\n        end: int | NumberVar,\n        step: int | NumberVar = 1,\n        /,\n    ) -> ArrayVar[list[int]]: ...\n\n    @overload\n    @classmethod\n    def range(\n        cls,\n        first_endpoint: int | NumberVar,\n        second_endpoint: int | NumberVar | None = None,\n        step: int | NumberVar | None = None,\n    ) -> ArrayVar[list[int]]: ...\n\n    @classmethod\n    def range(\n        cls,\n        first_endpoint: int | NumberVar,\n        second_endpoint: int | NumberVar | None = None,\n        step: int | NumberVar | None = None,\n    ) -> ArrayVar[list[int]]:\n        \"\"\"Create a range of numbers.\n\n        Args:\n            first_endpoint: The end of the range if second_endpoint is not provided, otherwise the start of the range.\n            second_endpoint: The end of the range.\n            step: The step of the range.\n\n        Returns:\n            The range of numbers.\n        \"\"\"\n        if any(\n            not isinstance(i, (int, NumberVar))\n            for i in (first_endpoint, second_endpoint, step)\n            if i is not None\n        ):\n            raise_unsupported_operand_types(\n                \"range\", (type(first_endpoint), type(second_endpoint), type(step))\n            )\n        if second_endpoint is None:\n            start = 0\n            end = first_endpoint\n        else:\n            start = first_endpoint\n            end = second_endpoint\n\n        return array_range_operation(start, end, step or 1)\n\n    @overload\n    def contains(self, other: Any) -> BooleanVar: ...\n\n    @overload\n    def contains(self, other: Any, field: StringVar | str) -> BooleanVar: ...\n\n    def contains(self, other: Any, field: Any = None) -> BooleanVar:\n        \"\"\"Check if the array contains an element.\n\n        Args:\n            other: The element to check for.\n            field: The field to check.\n\n        Returns:\n            The array contains operation.\n        \"\"\"\n        if field is not None:\n            if not isinstance(field, (StringVar, str)):\n                raise_unsupported_operand_types(\"contains\", (type(self), type(field)))\n            return array_contains_field_operation(self, other, field)\n        return array_contains_operation(self, other)\n\n    def pluck(self, field: StringVar | str) -> ArrayVar:\n        \"\"\"Pluck a field from the array.\n\n        Args:\n            field: The field to pluck from the array.\n\n        Returns:\n            The array pluck operation.\n        \"\"\"\n        return array_pluck_operation(self, field)\n\n    def __mul__(self, other: NumberVar | int) -> ArrayVar[ARRAY_VAR_TYPE]:\n        \"\"\"Multiply the sequence by a number or integer.\n\n        Parameters:\n            other: The number or integer to multiply the sequence by.\n\n        Returns:\n            ArrayVar[ARRAY_VAR_TYPE]: The result of multiplying the sequence by the given number or integer.\n        \"\"\"\n        if not isinstance(other, (NumberVar, int)) or (\n            isinstance(other, NumberVar) and other._is_strict_float()\n        ):\n            raise_unsupported_operand_types(\"*\", (type(self), type(other)))\n\n        return repeat_array_operation(self, other)\n\n    __rmul__ = __mul__\n\n    @overload\n    def __lt__(self, other: ArrayVar[ARRAY_VAR_TYPE]) -> BooleanVar: ...\n\n    @overload\n    def __lt__(self, other: list | tuple) -> BooleanVar: ...\n\n    def __lt__(self, other: Any):\n        \"\"\"Check if the array is less than another array.\n\n        Args:\n            other: The other array.\n\n        Returns:\n            The array less than operation.\n        \"\"\"\n        if not isinstance(other, (ArrayVar, list, tuple)):\n            raise_unsupported_operand_types(\"<\", (type(self), type(other)))\n\n        return array_lt_operation(self, other)\n\n    @overload\n    def __gt__(self, other: ArrayVar[ARRAY_VAR_TYPE]) -> BooleanVar: ...\n\n    @overload\n    def __gt__(self, other: list | tuple) -> BooleanVar: ...\n\n    def __gt__(self, other: Any):\n        \"\"\"Check if the array is greater than another array.\n\n        Args:\n            other: The other array.\n\n        Returns:\n            The array greater than operation.\n        \"\"\"\n        if not isinstance(other, (ArrayVar, list, tuple)):\n            raise_unsupported_operand_types(\">\", (type(self), type(other)))\n\n        return array_gt_operation(self, other)\n\n    @overload\n    def __le__(self, other: ArrayVar[ARRAY_VAR_TYPE]) -> BooleanVar: ...\n\n    @overload\n    def __le__(self, other: list | tuple) -> BooleanVar: ...\n\n    def __le__(self, other: Any):\n        \"\"\"Check if the array is less than or equal to another array.\n\n        Args:\n            other: The other array.\n\n        Returns:\n            The array less than or equal operation.\n        \"\"\"\n        if not isinstance(other, (ArrayVar, list, tuple)):\n            raise_unsupported_operand_types(\"<=\", (type(self), type(other)))\n\n        return array_le_operation(self, other)\n\n    @overload\n    def __ge__(self, other: ArrayVar[ARRAY_VAR_TYPE]) -> BooleanVar: ...\n\n    @overload\n    def __ge__(self, other: list | tuple) -> BooleanVar: ...\n\n    def __ge__(self, other: Any):\n        \"\"\"Check if the array is greater than or equal to another array.\n\n        Args:\n            other: The other array.\n\n        Returns:\n            The array greater than or equal operation.\n        \"\"\"\n        if not isinstance(other, (ArrayVar, list, tuple)):\n            raise_unsupported_operand_types(\">=\", (type(self), type(other)))\n\n        return array_ge_operation(self, other)\n\n    def foreach(self, fn: Any):\n        \"\"\"Apply a function to each element of the array.\n\n        Args:\n            fn: The function to apply.\n\n        Returns:\n            The array after applying the function.\n\n        Raises:\n            VarTypeError: If the function takes more than one argument.\n        \"\"\"\n        from .function import ArgsFunctionOperation\n\n        if not callable(fn):\n            raise_unsupported_operand_types(\"foreach\", (type(self), type(fn)))\n        # get the number of arguments of the function\n        num_args = len(inspect.signature(fn).parameters)\n        if num_args > 1:\n            msg = \"The function passed to foreach should take at most one argument.\"\n            raise VarTypeError(msg)\n\n        if num_args == 0:\n            return_value = fn()\n            function_var = ArgsFunctionOperation.create((), return_value)\n        else:\n            # generic number var\n            number_var = Var(\"\").to(NumberVar, int)\n\n            first_arg_type = self[number_var]._var_type\n\n            arg_name = get_unique_variable_name()\n\n            # get first argument type\n            first_arg = Var(\n                _js_expr=arg_name,\n                _var_type=first_arg_type,\n            ).guess_type()\n\n            function_var = ArgsFunctionOperation.create(\n                (arg_name,),\n                Var.create(fn(first_arg)),\n            )\n\n        return map_array_operation(self, function_var)\n\n\n@dataclasses.dataclass(\n    eq=False,\n    frozen=True,\n    slots=True,\n)\nclass LiteralArrayVar(CachedVarOperation, LiteralVar, ArrayVar[ARRAY_VAR_TYPE]):\n    \"\"\"Base class for immutable literal array vars.\"\"\"\n\n    _var_value: Sequence[Var | Any] = dataclasses.field(default=())\n\n    @cached_property_no_lock\n    def _cached_var_name(self) -> str:\n        \"\"\"The name of the var.\n\n        Returns:\n            The name of the var.\n        \"\"\"\n        return (\n            \"[\"\n            + \", \".join([\n                str(LiteralVar.create(element)) for element in self._var_value\n            ])\n            + \"]\"\n        )\n\n    @classmethod\n    def _get_all_var_data_without_creating_var(cls, value: Iterable) -> VarData | None:\n        \"\"\"Get all the VarData associated with the Var without creating a Var.\n\n        Args:\n            value: The value to get the VarData for.\n\n        Returns:\n            The VarData associated with the Var.\n        \"\"\"\n        return VarData.merge(*[\n            LiteralVar._get_all_var_data_without_creating_var_dispatch(element)\n            for element in value\n        ])\n\n    @cached_property_no_lock\n    def _cached_get_all_var_data(self) -> VarData | None:\n        \"\"\"Get all the VarData associated with the Var.\n\n        Returns:\n            The VarData associated with the Var.\n        \"\"\"\n        return VarData.merge(\n            *[\n                LiteralVar._get_all_var_data_without_creating_var_dispatch(element)\n                for element in self._var_value\n            ],\n            self._var_data,\n        )\n\n    def __hash__(self) -> int:\n        \"\"\"Get the hash of the var.\n\n        Returns:\n            The hash of the var.\n        \"\"\"\n        return hash((self.__class__.__name__, self._js_expr))\n\n    def json(self) -> str:\n        \"\"\"Get the JSON representation of the var.\n\n        Returns:\n            The JSON representation of the var.\n\n        Raises:\n            TypeError: If the array elements are not of type LiteralVar.\n        \"\"\"\n        elements = []\n        for element in self._var_value:\n            element_var = LiteralVar.create(element)\n            if not isinstance(element_var, LiteralVar):\n                msg = f\"Array elements must be of type LiteralVar, not {type(element_var)}\"\n                raise TypeError(msg)\n            elements.append(element_var.json())\n\n        return \"[\" + \", \".join(elements) + \"]\"\n\n    @classmethod\n    def create(\n        cls,\n        value: OTHER_ARRAY_VAR_TYPE,\n        _var_type: type[OTHER_ARRAY_VAR_TYPE] | None = None,\n        _var_data: VarData | None = None,\n    ) -> LiteralArrayVar[OTHER_ARRAY_VAR_TYPE]:\n        \"\"\"Create a var from a string value.\n\n        Args:\n            value: The value to create the var from.\n            _var_type: The type of the var.\n            _var_data: Additional hooks and imports associated with the Var.\n\n        Returns:\n            The var.\n        \"\"\"\n        return LiteralArrayVar(\n            _js_expr=\"\",\n            _var_type=figure_out_type(value) if _var_type is None else _var_type,\n            _var_data=_var_data,\n            _var_value=value,\n        )\n\n\nSTRING_TYPE = TypingExtensionsTypeVar(\"STRING_TYPE\", default=str)\n\n\nclass StringVar(Var[STRING_TYPE], python_types=str):\n    \"\"\"Base class for immutable string vars.\"\"\"\n\n    def __add__(self, other: StringVar | str) -> ConcatVarOperation:\n        \"\"\"Concatenate two strings.\n\n        Args:\n            other: The other string.\n\n        Returns:\n            The string concatenation operation.\n        \"\"\"\n        if not isinstance(other, (StringVar, str)):\n            raise_unsupported_operand_types(\"+\", (type(self), type(other)))\n\n        return ConcatVarOperation.create(self, other)\n\n    def __radd__(self, other: StringVar | str) -> ConcatVarOperation:\n        \"\"\"Concatenate two strings.\n\n        Args:\n            other: The other string.\n\n        Returns:\n            The string concatenation operation.\n        \"\"\"\n        if not isinstance(other, (StringVar, str)):\n            raise_unsupported_operand_types(\"+\", (type(other), type(self)))\n\n        return ConcatVarOperation.create(other, self)\n\n    def __mul__(self, other: NumberVar | int) -> StringVar:\n        \"\"\"Multiply the sequence by a number or an integer.\n\n        Args:\n            other: The number or integer to multiply the sequence by.\n\n        Returns:\n            StringVar: The resulting sequence after multiplication.\n        \"\"\"\n        if not isinstance(other, (NumberVar, int)):\n            raise_unsupported_operand_types(\"*\", (type(self), type(other)))\n\n        return (self.split() * other).join()\n\n    def __rmul__(self, other: NumberVar | int) -> StringVar:\n        \"\"\"Multiply the sequence by a number or an integer.\n\n        Args:\n            other: The number or integer to multiply the sequence by.\n\n        Returns:\n            StringVar: The resulting sequence after multiplication.\n        \"\"\"\n        if not isinstance(other, (NumberVar, int)):\n            raise_unsupported_operand_types(\"*\", (type(other), type(self)))\n\n        return (self.split() * other).join()\n\n    @overload\n    def __getitem__(self, i: slice) -> StringVar: ...\n\n    @overload\n    def __getitem__(self, i: int | NumberVar) -> StringVar: ...\n\n    def __getitem__(self, i: Any) -> StringVar:\n        \"\"\"Get a slice of the string.\n\n        Args:\n            i: The slice.\n\n        Returns:\n            The string slice operation.\n        \"\"\"\n        if isinstance(i, slice):\n            return self.split()[i].join()\n        if not isinstance(i, (int, NumberVar)) or (\n            isinstance(i, NumberVar) and i._is_strict_float()\n        ):\n            raise_unsupported_operand_types(\"[]\", (type(self), type(i)))\n        return string_item_operation(self, i)\n\n    def length(self) -> NumberVar:\n        \"\"\"Get the length of the string.\n\n        Returns:\n            The string length operation.\n        \"\"\"\n        return self.split().length()\n\n    def lower(self) -> StringVar:\n        \"\"\"Convert the string to lowercase.\n\n        Returns:\n            The string lower operation.\n        \"\"\"\n        return string_lower_operation(self)\n\n    def upper(self) -> StringVar:\n        \"\"\"Convert the string to uppercase.\n\n        Returns:\n            The string upper operation.\n        \"\"\"\n        return string_upper_operation(self)\n\n    def title(self) -> StringVar:\n        \"\"\"Convert the string to title case.\n\n        Returns:\n            The string title operation.\n        \"\"\"\n        return string_title_operation(self)\n\n    def capitalize(self) -> StringVar:\n        \"\"\"Capitalize the string.\n\n        Returns:\n            The string capitalize operation.\n        \"\"\"\n        return string_capitalize_operation(self)\n\n    def strip(self) -> StringVar:\n        \"\"\"Strip the string.\n\n        Returns:\n            The string strip operation.\n        \"\"\"\n        return string_strip_operation(self)\n\n    def reversed(self) -> StringVar:\n        \"\"\"Reverse the string.\n\n        Returns:\n            The string reverse operation.\n        \"\"\"\n        return self.split().reverse().join()\n\n    def contains(\n        self, other: StringVar | str, field: StringVar | str | None = None\n    ) -> BooleanVar:\n        \"\"\"Check if the string contains another string.\n\n        Args:\n            other: The other string.\n            field: The field to check.\n\n        Returns:\n            The string contains operation.\n        \"\"\"\n        if not isinstance(other, (StringVar, str)):\n            raise_unsupported_operand_types(\"contains\", (type(self), type(other)))\n        if field is not None:\n            if not isinstance(field, (StringVar, str)):\n                raise_unsupported_operand_types(\"contains\", (type(self), type(field)))\n            return string_contains_field_operation(self, other, field)\n        return string_contains_operation(self, other)\n\n    def split(self, separator: StringVar | str = \"\") -> ArrayVar[list[str]]:\n        \"\"\"Split the string.\n\n        Args:\n            separator: The separator.\n\n        Returns:\n            The string split operation.\n        \"\"\"\n        if not isinstance(separator, (StringVar, str)):\n            raise_unsupported_operand_types(\"split\", (type(self), type(separator)))\n        return string_split_operation(self, separator)\n\n    def startswith(self, prefix: StringVar | str) -> BooleanVar:\n        \"\"\"Check if the string starts with a prefix.\n\n        Args:\n            prefix: The prefix.\n\n        Returns:\n            The string starts with operation.\n        \"\"\"\n        if not isinstance(prefix, (StringVar, str)):\n            raise_unsupported_operand_types(\"startswith\", (type(self), type(prefix)))\n        return string_starts_with_operation(self, prefix)\n\n    def endswith(self, suffix: StringVar | str) -> BooleanVar:\n        \"\"\"Check if the string ends with a suffix.\n\n        Args:\n            suffix: The suffix.\n\n        Returns:\n            The string ends with operation.\n        \"\"\"\n        if not isinstance(suffix, (StringVar, str)):\n            raise_unsupported_operand_types(\"endswith\", (type(self), type(suffix)))\n        return string_ends_with_operation(self, suffix)\n\n    def __lt__(self, other: StringVar | str) -> BooleanVar:\n        \"\"\"Check if the string is less than another string.\n\n        Args:\n            other: The other string.\n\n        Returns:\n            The string less than operation.\n        \"\"\"\n        if not isinstance(other, (StringVar, str)):\n            raise_unsupported_operand_types(\"<\", (type(self), type(other)))\n\n        return string_lt_operation(self, other)\n\n    def __gt__(self, other: StringVar | str) -> BooleanVar:\n        \"\"\"Check if the string is greater than another string.\n\n        Args:\n            other: The other string.\n\n        Returns:\n            The string greater than operation.\n        \"\"\"\n        if not isinstance(other, (StringVar, str)):\n            raise_unsupported_operand_types(\">\", (type(self), type(other)))\n\n        return string_gt_operation(self, other)\n\n    def __le__(self, other: StringVar | str) -> BooleanVar:\n        \"\"\"Check if the string is less than or equal to another string.\n\n        Args:\n            other: The other string.\n\n        Returns:\n            The string less than or equal operation.\n        \"\"\"\n        if not isinstance(other, (StringVar, str)):\n            raise_unsupported_operand_types(\"<=\", (type(self), type(other)))\n\n        return string_le_operation(self, other)\n\n    def __ge__(self, other: StringVar | str) -> BooleanVar:\n        \"\"\"Check if the string is greater than or equal to another string.\n\n        Args:\n            other: The other string.\n\n        Returns:\n            The string greater than or equal operation.\n        \"\"\"\n        if not isinstance(other, (StringVar, str)):\n            raise_unsupported_operand_types(\">=\", (type(self), type(other)))\n\n        return string_ge_operation(self, other)\n\n    @overload\n    def replace(  # pyright: ignore [reportOverlappingOverload]\n        self, search_value: StringVar | str, new_value: StringVar | str\n    ) -> StringVar: ...\n\n    @overload\n    def replace(\n        self, search_value: Any, new_value: Any\n    ) -> CustomVarOperationReturn[StringVar]: ...\n\n    def replace(self, search_value: Any, new_value: Any) -> StringVar:  # pyright: ignore [reportInconsistentOverload]\n        \"\"\"Replace a string with a value.\n\n        Args:\n            search_value: The string to search.\n            new_value: The value to be replaced with.\n\n        Returns:\n            The string replace operation.\n        \"\"\"\n        if not isinstance(search_value, (StringVar, str)):\n            raise_unsupported_operand_types(\"replace\", (type(self), type(search_value)))\n        if not isinstance(new_value, (StringVar, str)):\n            raise_unsupported_operand_types(\"replace\", (type(self), type(new_value)))\n\n        return string_replace_operation(self, search_value, new_value)\n\n\n@var_operation\ndef string_lt_operation(lhs: StringVar[Any] | str, rhs: StringVar[Any] | str):\n    \"\"\"Check if a string is less than another string.\n\n    Args:\n        lhs: The left-hand side string.\n        rhs: The right-hand side string.\n\n    Returns:\n        The string less than operation.\n    \"\"\"\n    return var_operation_return(js_expression=f\"{lhs} < {rhs}\", var_type=bool)\n\n\n@var_operation\ndef string_gt_operation(lhs: StringVar[Any] | str, rhs: StringVar[Any] | str):\n    \"\"\"Check if a string is greater than another string.\n\n    Args:\n        lhs: The left-hand side string.\n        rhs: The right-hand side string.\n\n    Returns:\n        The string greater than operation.\n    \"\"\"\n    return var_operation_return(js_expression=f\"{lhs} > {rhs}\", var_type=bool)\n\n\n@var_operation\ndef string_le_operation(lhs: StringVar[Any] | str, rhs: StringVar[Any] | str):\n    \"\"\"Check if a string is less than or equal to another string.\n\n    Args:\n        lhs: The left-hand side string.\n        rhs: The right-hand side string.\n\n    Returns:\n        The string less than or equal operation.\n    \"\"\"\n    return var_operation_return(js_expression=f\"{lhs} <= {rhs}\", var_type=bool)\n\n\n@var_operation\ndef string_ge_operation(lhs: StringVar[Any] | str, rhs: StringVar[Any] | str):\n    \"\"\"Check if a string is greater than or equal to another string.\n\n    Args:\n        lhs: The left-hand side string.\n        rhs: The right-hand side string.\n\n    Returns:\n        The string greater than or equal operation.\n    \"\"\"\n    return var_operation_return(js_expression=f\"{lhs} >= {rhs}\", var_type=bool)\n\n\n@var_operation\ndef string_lower_operation(string: StringVar[Any]):\n    \"\"\"Convert a string to lowercase.\n\n    Args:\n        string: The string to convert.\n\n    Returns:\n        The lowercase string.\n    \"\"\"\n    return var_operation_return(js_expression=f\"{string}.toLowerCase()\", var_type=str)\n\n\n@var_operation\ndef string_upper_operation(string: StringVar[Any]):\n    \"\"\"Convert a string to uppercase.\n\n    Args:\n        string: The string to convert.\n\n    Returns:\n        The uppercase string.\n    \"\"\"\n    return var_operation_return(js_expression=f\"{string}.toUpperCase()\", var_type=str)\n\n\n@var_operation\ndef string_title_operation(string: StringVar[Any]):\n    \"\"\"Convert a string to title case.\n\n    Args:\n        string: The string to convert.\n\n    Returns:\n        The title case string.\n    \"\"\"\n    return var_operation_return(\n        js_expression=f\"{string}.split(' ').map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(' ')\",\n        var_type=str,\n    )\n\n\n@var_operation\ndef string_capitalize_operation(string: StringVar[Any]):\n    \"\"\"Capitalize a string.\n\n    Args:\n        string: The string to capitalize.\n\n    Returns:\n        The capitalized string.\n    \"\"\"\n    return var_operation_return(\n        js_expression=f\"(((s) => s.charAt(0).toUpperCase() + s.slice(1).toLowerCase())({string}))\",\n        var_type=str,\n    )\n\n\n@var_operation\ndef string_strip_operation(string: StringVar[Any]):\n    \"\"\"Strip a string.\n\n    Args:\n        string: The string to strip.\n\n    Returns:\n        The stripped string.\n    \"\"\"\n    return var_operation_return(js_expression=f\"{string}.trim()\", var_type=str)\n\n\n@var_operation\ndef string_contains_field_operation(\n    haystack: StringVar[Any], needle: StringVar[Any] | str, field: StringVar[Any] | str\n):\n    \"\"\"Check if a string contains another string.\n\n    Args:\n        haystack: The haystack.\n        needle: The needle.\n        field: The field to check.\n\n    Returns:\n        The string contains operation.\n    \"\"\"\n    return var_operation_return(\n        js_expression=f\"{haystack}.some(obj => obj[{field}] === {needle})\",\n        var_type=bool,\n    )\n\n\n@var_operation\ndef string_contains_operation(haystack: StringVar[Any], needle: StringVar[Any] | str):\n    \"\"\"Check if a string contains another string.\n\n    Args:\n        haystack: The haystack.\n        needle: The needle.\n\n    Returns:\n        The string contains operation.\n    \"\"\"\n    return var_operation_return(\n        js_expression=f\"{haystack}.includes({needle})\", var_type=bool\n    )\n\n\n@var_operation\ndef string_starts_with_operation(\n    full_string: StringVar[Any], prefix: StringVar[Any] | str\n):\n    \"\"\"Check if a string starts with a prefix.\n\n    Args:\n        full_string: The full string.\n        prefix: The prefix.\n\n    Returns:\n        Whether the string starts with the prefix.\n    \"\"\"\n    return var_operation_return(\n        js_expression=f\"{full_string}.startsWith({prefix})\", var_type=bool\n    )\n\n\n@var_operation\ndef string_ends_with_operation(\n    full_string: StringVar[Any], suffix: StringVar[Any] | str\n):\n    \"\"\"Check if a string ends with a suffix.\n\n    Args:\n        full_string: The full string.\n        suffix: The suffix.\n\n    Returns:\n        Whether the string ends with the suffix.\n    \"\"\"\n    return var_operation_return(\n        js_expression=f\"{full_string}.endsWith({suffix})\", var_type=bool\n    )\n\n\n@var_operation\ndef string_item_operation(string: StringVar[Any], index: NumberVar | int):\n    \"\"\"Get an item from a string.\n\n    Args:\n        string: The string.\n        index: The index of the item.\n\n    Returns:\n        The item from the string.\n    \"\"\"\n    return var_operation_return(js_expression=f\"{string}?.at?.({index})\", var_type=str)\n\n\n@var_operation\ndef array_join_operation(array: ArrayVar, sep: StringVar[Any] | str = \"\"):\n    \"\"\"Join the elements of an array.\n\n    Args:\n        array: The array.\n        sep: The separator.\n\n    Returns:\n        The joined elements.\n    \"\"\"\n    return var_operation_return(js_expression=f\"{array}.join({sep})\", var_type=str)\n\n\n@var_operation\ndef string_replace_operation(\n    string: StringVar[Any], search_value: StringVar | str, new_value: StringVar | str\n):\n    \"\"\"Replace a string with a value.\n\n    Args:\n        string: The string.\n        search_value: The string to search.\n        new_value: The value to be replaced with.\n\n    Returns:\n        The string replace operation.\n    \"\"\"\n    return var_operation_return(\n        js_expression=f\"{string}.replaceAll({search_value}, {new_value})\",\n        var_type=str,\n    )\n\n\n@var_operation\ndef get_decimal_string_separator_operation(value: NumberVar, separator: StringVar):\n    \"\"\"Get the decimal string separator.\n\n    Args:\n        value: The number.\n        separator: The separator.\n\n    Returns:\n        The decimal string separator.\n    \"\"\"\n    return var_operation_return(\n        js_expression=f\"({value}.toLocaleString('en-US').replaceAll(',', {separator}))\",\n        var_type=str,\n    )\n\n\n@var_operation\ndef get_decimal_string_operation(\n    value: NumberVar, decimals: NumberVar, separator: StringVar\n):\n    \"\"\"Get the decimal string of the number.\n\n    Args:\n        value: The number.\n        decimals: The number of decimals.\n        separator: The separator.\n\n    Returns:\n        The decimal string of the number.\n    \"\"\"\n    return var_operation_return(\n        js_expression=f\"({value}.toLocaleString('en-US', ((decimals) => ({{minimumFractionDigits: decimals, maximumFractionDigits: decimals}}))({decimals})).replaceAll(',', {separator}))\",\n        var_type=str,\n    )\n\n\n# Compile regex for finding reflex var tags.\n_decode_var_pattern_re = (\n    rf\"{constants.REFLEX_VAR_OPENING_TAG}(.*?){constants.REFLEX_VAR_CLOSING_TAG}\"\n)\n_decode_var_pattern = re.compile(_decode_var_pattern_re, flags=re.DOTALL)\n\n\n@dataclasses.dataclass(\n    eq=False,\n    frozen=True,\n    slots=True,\n)\nclass LiteralStringVar(LiteralVar, StringVar[str]):\n    \"\"\"Base class for immutable literal string vars.\"\"\"\n\n    _var_value: str = dataclasses.field(default=\"\")\n\n    @classmethod\n    def _get_all_var_data_without_creating_var(cls, value: str) -> VarData | None:\n        \"\"\"Get all the VarData associated with the Var without creating a Var.\n\n        Args:\n            value: The value to get the VarData for.\n\n        Returns:\n            The VarData associated with the Var.\n        \"\"\"\n        if REFLEX_VAR_OPENING_TAG not in value:\n            return None\n        return cls.create(value)._get_all_var_data()\n\n    @classmethod\n    def create(\n        cls,\n        value: str,\n        _var_type: GenericType | None = None,\n        _var_data: VarData | None = None,\n    ) -> StringVar:\n        \"\"\"Create a var from a string value.\n\n        Args:\n            value: The value to create the var from.\n            _var_type: The type of the var.\n            _var_data: Additional hooks and imports associated with the Var.\n\n        Returns:\n            The var.\n        \"\"\"\n        # Determine var type in case the value is inherited from str.\n        _var_type = _var_type or type(value) or str\n\n        if REFLEX_VAR_OPENING_TAG in value:\n            strings_and_vals: list[Var | str] = []\n            offset = 0\n\n            # Find all tags\n            while m := _decode_var_pattern.search(value):\n                start, end = m.span()\n\n                strings_and_vals.append(value[:start])\n\n                serialized_data = m.group(1)\n\n                if serialized_data.isnumeric() or (\n                    serialized_data[0] == \"-\" and serialized_data[1:].isnumeric()\n                ):\n                    # This is a global immutable var.\n                    var = _global_vars[int(serialized_data)]\n                    strings_and_vals.append(var)\n                    value = value[(end + len(var._js_expr)) :]\n\n                offset += end - start\n\n            strings_and_vals.append(value)\n\n            filtered_strings_and_vals = [\n                s for s in strings_and_vals if isinstance(s, Var) or s\n            ]\n            if len(filtered_strings_and_vals) == 1:\n                only_string = filtered_strings_and_vals[0]\n                if isinstance(only_string, str):\n                    return LiteralVar.create(only_string).to(StringVar, _var_type)\n                return only_string.to(StringVar, only_string._var_type)\n\n            if len(\n                literal_strings := [\n                    s\n                    for s in filtered_strings_and_vals\n                    if isinstance(s, (str, LiteralStringVar))\n                ]\n            ) == len(filtered_strings_and_vals):\n                return LiteralStringVar.create(\n                    \"\".join(\n                        s._var_value if isinstance(s, LiteralStringVar) else s\n                        for s in literal_strings\n                    ),\n                    _var_type=_var_type,\n                    _var_data=VarData.merge(\n                        _var_data,\n                        *(\n                            s._get_all_var_data()\n                            for s in filtered_strings_and_vals\n                            if isinstance(s, Var)\n                        ),\n                    ),\n                )\n\n            concat_result = ConcatVarOperation.create(\n                *filtered_strings_and_vals,\n                _var_data=_var_data,\n            )\n\n            return (\n                concat_result\n                if _var_type is str\n                else concat_result.to(StringVar, _var_type)\n            )\n\n        return LiteralStringVar(\n            _js_expr=json.dumps(value),\n            _var_type=_var_type,\n            _var_data=_var_data,\n            _var_value=value,\n        )\n\n    def __hash__(self) -> int:\n        \"\"\"Get the hash of the var.\n\n        Returns:\n            The hash of the var.\n        \"\"\"\n        return hash((type(self).__name__, self._var_value))\n\n    def json(self) -> str:\n        \"\"\"Get the JSON representation of the var.\n\n        Returns:\n            The JSON representation of the var.\n        \"\"\"\n        return json.dumps(self._var_value)\n\n\n@dataclasses.dataclass(\n    eq=False,\n    frozen=True,\n    slots=True,\n)\nclass ConcatVarOperation(CachedVarOperation, StringVar[str]):\n    \"\"\"Representing a concatenation of literal string vars.\"\"\"\n\n    _var_value: tuple[Var, ...] = dataclasses.field(default_factory=tuple)\n\n    @cached_property_no_lock\n    def _cached_var_name(self) -> str:\n        \"\"\"The name of the var.\n\n        Returns:\n            The name of the var.\n        \"\"\"\n        list_of_strs: list[str | Var] = []\n        last_string = \"\"\n        for var in self._var_value:\n            if isinstance(var, LiteralStringVar):\n                last_string += var._var_value\n            else:\n                if last_string:\n                    list_of_strs.append(last_string)\n                    last_string = \"\"\n                list_of_strs.append(var)\n\n        if last_string:\n            list_of_strs.append(last_string)\n\n        list_of_strs_filtered = [\n            str(LiteralVar.create(s)) for s in list_of_strs if isinstance(s, Var) or s\n        ]\n\n        if len(list_of_strs_filtered) == 1:\n            return list_of_strs_filtered[0]\n\n        return \"(\" + \"+\".join(list_of_strs_filtered) + \")\"\n\n    @cached_property_no_lock\n    def _cached_get_all_var_data(self) -> VarData | None:\n        \"\"\"Get all the VarData asVarDatae Var.\n\n        Returns:\n            The VarData associated with the Var.\n        \"\"\"\n        return VarData.merge(\n            *[\n                var._get_all_var_data()\n                for var in self._var_value\n                if isinstance(var, Var)\n            ],\n            self._var_data,\n        )\n\n    @classmethod\n    def create(\n        cls,\n        *value: Var | str,\n        _var_data: VarData | None = None,\n    ) -> ConcatVarOperation:\n        \"\"\"Create a var from a string value.\n\n        Args:\n            *value: The values to concatenate.\n            _var_data: Additional hooks and imports associated with the Var.\n\n        Returns:\n            The var.\n        \"\"\"\n        return cls(\n            _js_expr=\"\",\n            _var_type=str,\n            _var_data=_var_data,\n            _var_value=tuple(map(LiteralVar.create, value)),\n        )\n\n\n@var_operation\ndef string_split_operation(string: StringVar[Any], sep: StringVar | str = \"\"):\n    \"\"\"Split a string.\n\n    Args:\n        string: The string to split.\n        sep: The separator.\n\n    Returns:\n        The split string.\n    \"\"\"\n    return var_operation_return(\n        js_expression=f\"{string}.split({sep})\", var_type=list[str]\n    )\n\n\n@dataclasses.dataclass(\n    eq=False,\n    frozen=True,\n    slots=True,\n)\nclass ArraySliceOperation(CachedVarOperation, ArrayVar):\n    \"\"\"Base class for immutable string vars that are the result of a string slice operation.\"\"\"\n\n    _array: ArrayVar = dataclasses.field(\n        default_factory=lambda: LiteralArrayVar.create([])\n    )\n    _start: NumberVar | int = dataclasses.field(default_factory=lambda: 0)\n    _stop: NumberVar | int = dataclasses.field(default_factory=lambda: 0)\n    _step: NumberVar | int = dataclasses.field(default_factory=lambda: 1)\n\n    @cached_property_no_lock\n    def _cached_var_name(self) -> str:\n        \"\"\"The name of the var.\n\n        Returns:\n            The name of the var.\n\n        Raises:\n            ValueError: If the slice step is zero.\n        \"\"\"\n        start, end, step = self._start, self._stop, self._step\n\n        normalized_start = (\n            LiteralVar.create(start) if start is not None else Var(_js_expr=\"undefined\")\n        )\n        normalized_end = (\n            LiteralVar.create(end) if end is not None else Var(_js_expr=\"undefined\")\n        )\n        if step is None:\n            return f\"{self._array!s}.slice({normalized_start!s}, {normalized_end!s})\"\n        if not isinstance(step, Var):\n            if step < 0:\n                actual_start = end + 1 if end is not None else 0\n                actual_end = start + 1 if start is not None else self._array.length()\n                return str(self._array[actual_start:actual_end].reverse()[::-step])\n            if step == 0:\n                msg = \"slice step cannot be zero\"\n                raise ValueError(msg)\n            return f\"{self._array!s}.slice({normalized_start!s}, {normalized_end!s}).filter((_, i) => i % {step!s} === 0)\"\n\n        actual_start_reverse = end + 1 if end is not None else 0\n        actual_end_reverse = start + 1 if start is not None else self._array.length()\n\n        return f\"{self.step!s} > 0 ? {self._array!s}.slice({normalized_start!s}, {normalized_end!s}).filter((_, i) => i % {step!s} === 0) : {self._array!s}.slice({actual_start_reverse!s}, {actual_end_reverse!s}).reverse().filter((_, i) => i % {-step!s} === 0)\"\n\n    @classmethod\n    def create(\n        cls,\n        array: ArrayVar,\n        slice: slice,\n        _var_data: VarData | None = None,\n    ) -> ArraySliceOperation:\n        \"\"\"Create a var from a string value.\n\n        Args:\n            array: The array.\n            slice: The slice.\n            _var_data: Additional hooks and imports associated with the Var.\n\n        Returns:\n            The var.\n        \"\"\"\n        return cls(\n            _js_expr=\"\",\n            _var_type=array._var_type,\n            _var_data=_var_data,\n            _array=array,\n            _start=slice.start,\n            _stop=slice.stop,\n            _step=slice.step,\n        )\n\n\n@var_operation\ndef array_pluck_operation(\n    array: ArrayVar[ARRAY_VAR_TYPE],\n    field: StringVar | str,\n) -> CustomVarOperationReturn[ARRAY_VAR_TYPE]:\n    \"\"\"Pluck a field from an array of objects.\n\n    Args:\n        array: The array to pluck from.\n        field: The field to pluck from the objects in the array.\n\n    Returns:\n        The reversed array.\n    \"\"\"\n    return var_operation_return(\n        js_expression=f\"{array}.map(e=>e?.[{field}])\",\n        var_type=array._var_type,\n    )\n\n\n@var_operation\ndef array_reverse_operation(\n    array: ArrayVar[ARRAY_VAR_TYPE],\n) -> CustomVarOperationReturn[ARRAY_VAR_TYPE]:\n    \"\"\"Reverse an array.\n\n    Args:\n        array: The array to reverse.\n\n    Returns:\n        The reversed array.\n    \"\"\"\n    return var_operation_return(\n        js_expression=f\"{array}.slice().reverse()\",\n        var_type=array._var_type,\n    )\n\n\n@var_operation\ndef array_lt_operation(lhs: ArrayVar | list | tuple, rhs: ArrayVar | list | tuple):\n    \"\"\"Check if an array is less than another array.\n\n    Args:\n        lhs: The left-hand side array.\n        rhs: The right-hand side array.\n\n    Returns:\n        The array less than operation.\n    \"\"\"\n    return var_operation_return(js_expression=f\"{lhs} < {rhs}\", var_type=bool)\n\n\n@var_operation\ndef array_gt_operation(lhs: ArrayVar | list | tuple, rhs: ArrayVar | list | tuple):\n    \"\"\"Check if an array is greater than another array.\n\n    Args:\n        lhs: The left-hand side array.\n        rhs: The right-hand side array.\n\n    Returns:\n        The array greater than operation.\n    \"\"\"\n    return var_operation_return(js_expression=f\"{lhs} > {rhs}\", var_type=bool)\n\n\n@var_operation\ndef array_le_operation(lhs: ArrayVar | list | tuple, rhs: ArrayVar | list | tuple):\n    \"\"\"Check if an array is less than or equal to another array.\n\n    Args:\n        lhs: The left-hand side array.\n        rhs: The right-hand side array.\n\n    Returns:\n        The array less than or equal operation.\n    \"\"\"\n    return var_operation_return(js_expression=f\"{lhs} <= {rhs}\", var_type=bool)\n\n\n@var_operation\ndef array_ge_operation(lhs: ArrayVar | list | tuple, rhs: ArrayVar | list | tuple):\n    \"\"\"Check if an array is greater than or equal to another array.\n\n    Args:\n        lhs: The left-hand side array.\n        rhs: The right-hand side array.\n\n    Returns:\n        The array greater than or equal operation.\n    \"\"\"\n    return var_operation_return(js_expression=f\"{lhs} >= {rhs}\", var_type=bool)\n\n\n@var_operation\ndef array_length_operation(array: ArrayVar):\n    \"\"\"Get the length of an array.\n\n    Args:\n        array: The array.\n\n    Returns:\n        The length of the array.\n    \"\"\"\n    return var_operation_return(\n        js_expression=f\"{array}.length\",\n        var_type=int,\n    )\n\n\ndef is_tuple_type(t: GenericType) -> bool:\n    \"\"\"Check if a type is a tuple type.\n\n    Args:\n        t: The type to check.\n\n    Returns:\n        Whether the type is a tuple type.\n    \"\"\"\n    return get_origin(t) is tuple\n\n\ndef _determine_value_of_array_index(\n    var_type: GenericType, index: int | float | decimal.Decimal | None = None\n):\n    \"\"\"Determine the value of an array index.\n\n    Args:\n        var_type: The type of the array.\n        index: The index of the array.\n\n    Returns:\n        The value of the array index.\n    \"\"\"\n    origin_var_type = get_origin(var_type) or var_type\n    if origin_var_type in types.UnionTypes:\n        return unionize(*[\n            _determine_value_of_array_index(t, index)\n            for t in get_args(var_type)\n            if t is not type(None)\n        ])\n    if origin_var_type is range:\n        return int\n    if origin_var_type in [\n        Sequence,\n        Iterable,\n        list,\n        set,\n        collections.abc.Sequence,\n        collections.abc.Iterable,\n    ]:\n        args = get_args(var_type)\n        return args[0] if args else Any\n    if origin_var_type is tuple:\n        args = get_args(var_type)\n        if len(args) == 2 and args[1] is ...:\n            return args[0]\n        return (\n            args[int(index) % len(args)]\n            if args and index is not None\n            else (unionize(*args) if args else Any)\n        )\n    return Any\n\n\n@var_operation\ndef array_item_operation(array: ArrayVar, index: NumberVar | int):\n    \"\"\"Get an item from an array.\n\n    Args:\n        array: The array.\n        index: The index of the item.\n\n    Returns:\n        The item from the array.\n    \"\"\"\n    element_type = _determine_value_of_array_index(\n        array._var_type,\n        (\n            index\n            if isinstance(index, int)\n            else (index._var_value if isinstance(index, LiteralNumberVar) else None)\n        ),\n    )\n\n    return var_operation_return(\n        js_expression=f\"{array!s}?.at?.({index!s})\",\n        var_type=element_type,\n    )\n\n\n@var_operation\ndef array_range_operation(\n    start: NumberVar | int, stop: NumberVar | int, step: NumberVar | int\n):\n    \"\"\"Create a range of numbers.\n\n    Args:\n        start: The start of the range.\n        stop: The end of the range.\n        step: The step of the range.\n\n    Returns:\n        The range of numbers.\n    \"\"\"\n    return var_operation_return(\n        js_expression=f\"Array.from({{ length: Math.ceil(({stop!s} - {start!s}) / {step!s}) }}, (_, i) => {start!s} + i * {step!s})\",\n        var_type=list[int],\n    )\n\n\n@var_operation\ndef array_contains_field_operation(\n    haystack: ArrayVar, needle: Any | Var, field: StringVar | str\n):\n    \"\"\"Check if an array contains an element.\n\n    Args:\n        haystack: The array to check.\n        needle: The element to check for.\n        field: The field to check.\n\n    Returns:\n        The array contains operation.\n    \"\"\"\n    return var_operation_return(\n        js_expression=f\"{haystack}.some(obj => obj[{field}] === {needle})\",\n        var_type=bool,\n    )\n\n\n@var_operation\ndef array_contains_operation(\n    haystack: ArrayVar, needle: Any | Var\n) -> CustomVarOperationReturn[bool]:\n    \"\"\"Check if an array contains an element.\n\n    Args:\n        haystack: The array to check.\n        needle: The element to check for.\n\n    Returns:\n        The array contains operation.\n    \"\"\"\n    return var_operation_return(\n        js_expression=f\"{haystack}.includes({needle})\",\n        var_type=bool,\n    )\n\n\n@var_operation\ndef repeat_array_operation(\n    array: ArrayVar[ARRAY_VAR_TYPE], count: NumberVar | int\n) -> CustomVarOperationReturn[ARRAY_VAR_TYPE]:\n    \"\"\"Repeat an array a number of times.\n\n    Args:\n        array: The array to repeat.\n        count: The number of times to repeat the array.\n\n    Returns:\n        The repeated array.\n    \"\"\"\n    return var_operation_return(\n        js_expression=f\"Array.from({{ length: {count} }}).flatMap(() => {array})\",\n        var_type=array._var_type,\n    )\n\n\n@var_operation\ndef map_array_operation(\n    array: ArrayVar[ARRAY_VAR_TYPE],\n    function: FunctionVar,\n) -> CustomVarOperationReturn[list[Any]]:\n    \"\"\"Map a function over an array.\n\n    Args:\n        array: The array.\n        function: The function to map.\n\n    Returns:\n        The mapped array.\n    \"\"\"\n    return var_operation_return(\n        js_expression=f\"{array}.map({function})\", var_type=list[Any]\n    )\n\n\n@var_operation\ndef array_concat_operation(\n    lhs: ArrayVar[ARRAY_VAR_TYPE], rhs: ArrayVar[ARRAY_VAR_TYPE]\n) -> CustomVarOperationReturn[ARRAY_VAR_TYPE]:\n    \"\"\"Concatenate two arrays.\n\n    Args:\n        lhs: The left-hand side array.\n        rhs: The right-hand side array.\n\n    Returns:\n        The concatenated array.\n    \"\"\"\n    return var_operation_return(\n        js_expression=f\"[...{lhs}, ...{rhs}]\",\n        var_type=lhs._var_type | rhs._var_type,\n    )\n\n\nclass RangeVar(ArrayVar[Sequence[int]], python_types=range):\n    \"\"\"Base class for immutable range vars.\"\"\"\n\n\n@dataclasses.dataclass(\n    eq=False,\n    frozen=True,\n    slots=True,\n)\nclass LiteralRangeVar(CachedVarOperation, LiteralVar, RangeVar):\n    \"\"\"Base class for immutable literal range vars.\"\"\"\n\n    _var_value: range = dataclasses.field(default_factory=lambda: range(0))\n\n    @classmethod\n    def create(\n        cls,\n        value: range,\n        _var_type: type[range] | None = None,\n        _var_data: VarData | None = None,\n    ) -> RangeVar:\n        \"\"\"Create a var from a string value.\n\n        Args:\n            value: The value to create the var from.\n            _var_type: The type of the var.\n            _var_data: Additional hooks and imports associated with the Var.\n\n        Returns:\n            The var.\n        \"\"\"\n        return cls(\n            _js_expr=\"\",\n            _var_type=_var_type or range,\n            _var_data=_var_data,\n            _var_value=value,\n        )\n\n    def __hash__(self) -> int:\n        \"\"\"Get the hash of the var.\n\n        Returns:\n            The hash of the var.\n        \"\"\"\n        return hash((\n            self.__class__.__name__,\n            self._var_value.start,\n            self._var_value.stop,\n            self._var_value.step,\n        ))\n\n    @cached_property_no_lock\n    def _cached_var_name(self) -> str:\n        \"\"\"The name of the var.\n\n        Returns:\n            The name of the var.\n        \"\"\"\n        return f\"Array.from({{ length: Math.ceil(({self._var_value.stop!s} - {self._var_value.start!s}) / {self._var_value.step!s}) }}, (_, i) => {self._var_value.start!s} + i * {self._var_value.step!s})\"\n\n    @cached_property_no_lock\n    def _cached_get_all_var_data(self) -> VarData | None:\n        \"\"\"Get all the var data.\n\n        Returns:\n            The var data.\n        \"\"\"\n        return self._var_data\n\n    def json(self) -> str:\n        \"\"\"Get the JSON representation of the var.\n\n        Returns:\n            The JSON representation of the var.\n        \"\"\"\n        return json.dumps(\n            list(self._var_value),\n        )\n"
  },
  {
    "path": "scripts/__init__.py",
    "content": "\"\"\"Utility scripts for the project.\"\"\"\n"
  },
  {
    "path": "scripts/bun_install.sh",
    "content": "#!/usr/bin/env bash\nset -euo pipefail\n\nplatform=$(uname -ms)\n\nif [[ ${OS:-} = Windows_NT ]]; then\n  if [[ $platform != MINGW64* ]]; then\n    powershell -c \"irm bun.com/install.ps1|iex\"\n    exit $?\n  fi\nfi\n\n# Reset\nColor_Off=''\n\n# Regular Colors\nRed=''\nGreen=''\nDim='' # White\n\n# Bold\nBold_White=''\nBold_Green=''\n\nif [[ -t 1 ]]; then\n    # Reset\n    Color_Off='\\033[0m' # Text Reset\n\n    # Regular Colors\n    Red='\\033[0;31m'   # Red\n    Green='\\033[0;32m' # Green\n    Dim='\\033[0;2m'    # White\n\n    # Bold\n    Bold_Green='\\033[1;32m' # Bold Green\n    Bold_White='\\033[1m'    # Bold White\nfi\n\nerror() {\n    echo -e \"${Red}error${Color_Off}:\" \"$@\" >&2\n    exit 1\n}\n\ninfo() {\n    echo -e \"${Dim}$@ ${Color_Off}\"\n}\n\ninfo_bold() {\n    echo -e \"${Bold_White}$@ ${Color_Off}\"\n}\n\nsuccess() {\n    echo -e \"${Green}$@ ${Color_Off}\"\n}\n\ncommand -v unzip >/dev/null ||\n    error 'unzip is required to install bun'\n\nif [[ $# -gt 2 ]]; then\n    error 'Too many arguments, only 2 are allowed. The first can be a specific tag of bun to install. (e.g. \"bun-v0.1.4\") The second can be a build variant of bun to install. (e.g. \"debug-info\")'\nfi\n\ncase $platform in\n'Darwin x86_64')\n    target=darwin-x64\n    ;;\n'Darwin arm64')\n    target=darwin-aarch64\n    ;;\n'Linux aarch64' | 'Linux arm64')\n    target=linux-aarch64\n    ;;\n'MINGW64'*)\n    target=windows-x64\n    ;;\n'Linux x86_64' | *)\n    target=linux-x64\n    ;;\nesac\n\ncase \"$target\" in\n'linux'*)\n    if [ -f /etc/alpine-release ]; then\n        target=\"$target-musl\"\n    fi\n    ;;\nesac\n\nif [[ $target = darwin-x64 ]]; then\n    # Is this process running in Rosetta?\n    # redirect stderr to devnull to avoid error message when not running in Rosetta\n    if [[ $(sysctl -n sysctl.proc_translated 2>/dev/null) = 1 ]]; then\n        target=darwin-aarch64\n        info \"Your shell is running in Rosetta 2. Downloading bun for $target instead\"\n    fi\nfi\n\nGITHUB=${GITHUB-\"https://github.com\"}\n\ngithub_repo=\"$GITHUB/oven-sh/bun\"\n\n# If AVX2 isn't supported, use the -baseline build\ncase \"$target\" in\n'darwin-x64'*)\n    if [[ $(sysctl -a | grep machdep.cpu | grep AVX2) == '' ]]; then\n        target=\"$target-baseline\"\n    fi\n    ;;\n'linux-x64'*)\n    # If AVX2 isn't supported, use the -baseline build\n    if [[ $(cat /proc/cpuinfo | grep avx2) = '' ]]; then\n        target=\"$target-baseline\"\n    fi\n    ;;\nesac\n\nexe_name=bun\n\nif [[ $# = 2 && $2 = debug-info ]]; then\n    target=$target-profile\n    exe_name=bun-profile\n    info \"You requested a debug build of bun. More information will be shown if a crash occurs.\"\nfi\n\nbun_version=BUN_VERSION\n\nif [[ $# = 0 ]]; then\n    bun_uri=$github_repo/releases/download/bun-v$bun_version/bun-$target.zip\nelse\n    bun_uri=$github_repo/releases/download/$1/bun-$target.zip\nfi\n\ninstall_env=BUN_INSTALL\nbin_env=\\$$install_env/bin\n\ninstall_dir=${!install_env:-$HOME/.bun}\nbin_dir=$install_dir/bin\nexe=$bin_dir/bun\n\nif [[ ! -d $bin_dir ]]; then\n    mkdir -p \"$bin_dir\" ||\n        error \"Failed to create install directory \\\"$bin_dir\\\"\"\nfi\n\ncurl --fail --location --progress-bar --output \"$exe.zip\" \"$bun_uri\" ||\n    error \"Failed to download bun from \\\"$bun_uri\\\"\"\n\nunzip -oqd \"$bin_dir\" \"$exe.zip\" ||\n    error 'Failed to extract bun'\n\nmv \"$bin_dir/bun-$target/$exe_name\" \"$exe\" ||\n    error 'Failed to move extracted bun to destination'\n\nchmod +x \"$exe\" ||\n    error 'Failed to set permissions on bun executable'\n\nrm -r \"$bin_dir/bun-$target\" \"$exe.zip\"\n\ntildify() {\n    if [[ $1 = $HOME/* ]]; then\n        local replacement=\\~/\n\n        echo \"${1/$HOME\\//$replacement}\"\n    else\n        echo \"$1\"\n    fi\n}\n\nsuccess \"bun was installed successfully to $Bold_Green$(tildify \"$exe\")\"\n\nif command -v bun >/dev/null; then\n    # Install completions, but we don't care if it fails\n    IS_BUN_AUTO_UPDATE=true $exe completions &>/dev/null || :\n\n    echo \"Run 'bun --help' to get started\"\n    exit\nfi\n\nrefresh_command=''\n\ntilde_bin_dir=$(tildify \"$bin_dir\")\nquoted_install_dir=\\\"${install_dir//\\\"/\\\\\\\"}\\\"\n\nif [[ $quoted_install_dir = \\\"$HOME/* ]]; then\n    quoted_install_dir=${quoted_install_dir/$HOME\\//\\$HOME/}\nfi\n\necho\n\ncase $(basename \"$SHELL\") in\nfish)\n    # Install completions, but we don't care if it fails\n    IS_BUN_AUTO_UPDATE=true SHELL=fish $exe completions &>/dev/null || :\n\n    commands=(\n        \"set --export $install_env $quoted_install_dir\"\n        \"set --export PATH $bin_env \\$PATH\"\n    )\n\n    fish_config=$HOME/.config/fish/config.fish\n    tilde_fish_config=$(tildify \"$fish_config\")\n\n    if [[ -w $fish_config ]]; then\n        {\n            echo -e '\\n# bun'\n\n            for command in \"${commands[@]}\"; do\n                echo \"$command\"\n            done\n        } >>\"$fish_config\"\n\n        info \"Added \\\"$tilde_bin_dir\\\" to \\$PATH in \\\"$tilde_fish_config\\\"\"\n\n        refresh_command=\"source $tilde_fish_config\"\n    else\n        echo \"Manually add the directory to $tilde_fish_config (or similar):\"\n\n        for command in \"${commands[@]}\"; do\n            info_bold \"  $command\"\n        done\n    fi\n    ;;\nzsh)\n    # Install completions, but we don't care if it fails\n    IS_BUN_AUTO_UPDATE=true SHELL=zsh $exe completions &>/dev/null || :\n\n    commands=(\n        \"export $install_env=$quoted_install_dir\"\n        \"export PATH=\\\"$bin_env:\\$PATH\\\"\"\n    )\n\n    zsh_config=$HOME/.zshrc\n    tilde_zsh_config=$(tildify \"$zsh_config\")\n\n    if [[ -w $zsh_config ]]; then\n        {\n            echo -e '\\n# bun'\n\n            for command in \"${commands[@]}\"; do\n                echo \"$command\"\n            done\n        } >>\"$zsh_config\"\n\n        info \"Added \\\"$tilde_bin_dir\\\" to \\$PATH in \\\"$tilde_zsh_config\\\"\"\n\n        refresh_command=\"exec $SHELL\"\n    else\n        echo \"Manually add the directory to $tilde_zsh_config (or similar):\"\n\n        for command in \"${commands[@]}\"; do\n            info_bold \"  $command\"\n        done\n    fi\n    ;;\nbash)\n    # Install completions, but we don't care if it fails\n    IS_BUN_AUTO_UPDATE=true SHELL=bash $exe completions &>/dev/null || :\n\n    commands=(\n        \"export $install_env=$quoted_install_dir\"\n        \"export PATH=\\\"$bin_env:\\$PATH\\\"\"\n    )\n\n    bash_configs=(\n        \"$HOME/.bashrc\"\n        \"$HOME/.bash_profile\"\n    )\n\n    if [[ ${XDG_CONFIG_HOME:-} ]]; then\n        bash_configs+=(\n            \"$XDG_CONFIG_HOME/.bash_profile\"\n            \"$XDG_CONFIG_HOME/.bashrc\"\n            \"$XDG_CONFIG_HOME/bash_profile\"\n            \"$XDG_CONFIG_HOME/bashrc\"\n        )\n    fi\n\n    set_manually=true\n    for bash_config in \"${bash_configs[@]}\"; do\n        tilde_bash_config=$(tildify \"$bash_config\")\n\n        if [[ -w $bash_config ]]; then\n            {\n                echo -e '\\n# bun'\n\n                for command in \"${commands[@]}\"; do\n                    echo \"$command\"\n                done\n            } >>\"$bash_config\"\n\n            info \"Added \\\"$tilde_bin_dir\\\" to \\$PATH in \\\"$tilde_bash_config\\\"\"\n\n            refresh_command=\"source $bash_config\"\n            set_manually=false\n            break\n        fi\n    done\n\n    if [[ $set_manually = true ]]; then\n        echo \"Manually add the directory to $tilde_bash_config (or similar):\"\n\n        for command in \"${commands[@]}\"; do\n            info_bold \"  $command\"\n        done\n    fi\n    ;;\n*)\n    echo 'Manually add the directory to ~/.bashrc (or similar):'\n    info_bold \"  export $install_env=$quoted_install_dir\"\n    info_bold \"  export PATH=\\\"$bin_env:\\$PATH\\\"\"\n    ;;\nesac\n\necho\ninfo \"To get started, run:\"\necho\n\nif [[ $refresh_command ]]; then\n    info_bold \"  $refresh_command\"\nfi\n\ninfo_bold \"  bun --help\"\n"
  },
  {
    "path": "scripts/darglint_test.bat",
    "content": "@echo off\ncd ..\n\necho \"start darglint\"\n\necho \"reflex folder\"\nfor /R reflex %%f in (*.py) do (\n    echo %%f\n    echo %%f|findstr /r \"^.*reflex\\\\rx\\.py$\"\n    if errorlevel 1 (\n        uv run darglint %%f\n    )\n)\n\necho \"tests folder\"\nfor /R tests %%f in (*.py) do (\n    echo %%f\n    uv run darglint %%f\n)\n\necho \"darglint finished\"\npause\n"
  },
  {
    "path": "scripts/hatch_build.py",
    "content": "\"\"\"Custom build hook for Hatch.\"\"\"\n\nimport importlib.util\nimport pathlib\nimport subprocess\nimport sys\nfrom typing import Any\n\nfrom hatchling.builders.hooks.plugin.interface import BuildHookInterface\n\n\nclass CustomBuilder(BuildHookInterface):\n    \"\"\"Custom build hook for Hatch.\"\"\"\n\n    PLUGIN_NAME = \"custom\"\n\n    def marker(self) -> pathlib.Path:\n        \"\"\"Get the marker file path.\n\n        Returns:\n            The marker file path.\n        \"\"\"\n        return (\n            pathlib.Path(self.directory)\n            / f\".reflex-{self.metadata.version}.pyi_generated\"\n        )\n\n    def initialize(self, version: str, build_data: dict[str, Any]) -> None:\n        \"\"\"Initialize the build hook.\n\n        Args:\n            version: The version being built.\n            build_data: Additional build data.\n        \"\"\"\n        if self.marker().exists():\n            return\n\n        if importlib.util.find_spec(\"pre_commit\") and importlib.util.find_spec(\"toml\"):\n            import json\n\n            import toml\n            import yaml\n\n            reflex_dir = pathlib.Path(__file__).parent.parent\n            pre_commit_config = json.loads(\n                json.dumps(\n                    toml.load(reflex_dir / \"pyproject.toml\")[\"tool\"][\"pre-commit\"]\n                )\n            )\n            (reflex_dir / \".pre-commit-config.yaml\").write_text(\n                yaml.dump(pre_commit_config), encoding=\"utf-8\"\n            )\n\n        if not (pathlib.Path(self.root) / \"scripts\").exists():\n            return\n\n        for file in (pathlib.Path(self.root) / \"reflex\").rglob(\"**/*.pyi\"):\n            file.unlink(missing_ok=True)\n\n        subprocess.run(\n            [sys.executable, \"-m\", \"reflex.utils.pyi_generator\"],\n            check=True,\n        )\n        self.marker().touch()\n"
  },
  {
    "path": "scripts/install.ps1",
    "content": "#!/usr/bin/env pwsh\nparam(\n  # Forces installing the baseline build regardless of what CPU you are actually using.\n  [Switch]$ForceBaseline = $false,\n  # Skips adding the bun.exe directory to the user's %PATH%\n  [Switch]$NoPathUpdate = $false,\n  # Skips adding the bun to the list of installed programs\n  [Switch]$NoRegisterInstallation = $false,\n  # Skips installing powershell completions to your profile\n  [Switch]$NoCompletions = $false,\n\n  # Debugging: Always download with 'Invoke-RestMethod' instead of 'curl.exe'\n  [Switch]$DownloadWithoutCurl = $false\n);\n$Version = if ($env:BUN_VERSION) { $env:BUN_VERSION } else { \"latest\" }\n# filter out 32 bit + ARM\nif (-not ((Get-CimInstance Win32_ComputerSystem)).SystemType -match \"x64-based\") {\n  Write-Output \"Install Failed:\"\n  Write-Output \"Bun for Windows is currently only available for x86 64-bit Windows.`n\"\n  return 1\n}\n\n# This corresponds to .win10_rs5 in build.zig\n$MinBuild = 17763;\n$MinBuildName = \"Windows 10 1809 / Windows Server 2019\"\n\n$WinVer = [System.Environment]::OSVersion.Version\nif ($WinVer.Major -lt 10 -or ($WinVer.Major -eq 10 -and $WinVer.Build -lt $MinBuild)) {\n  Write-Warning \"Bun requires at ${MinBuildName} or newer.`n`nThe install will still continue but it may not work.`n\"\n  return 1\n}\n\n$ErrorActionPreference = \"Stop\"\n\n# These three environment functions are roughly copied from https://github.com/prefix-dev/pixi/pull/692\n# They are used instead of `SetEnvironmentVariable` because of unwanted variable expansions.\nfunction Publish-Env {\n  if (-not (\"Win32.NativeMethods\" -as [Type])) {\n    Add-Type -Namespace Win32 -Name NativeMethods -MemberDefinition @\"\n[DllImport(\"user32.dll\", SetLastError = true, CharSet = CharSet.Auto)]\npublic static extern IntPtr SendMessageTimeout(\n    IntPtr hWnd, uint Msg, UIntPtr wParam, string lParam,\n    uint fuFlags, uint uTimeout, out UIntPtr lpdwResult);\n\"@\n  }\n  $HWND_BROADCAST = [IntPtr] 0xffff\n  $WM_SETTINGCHANGE = 0x1a\n  $result = [UIntPtr]::Zero\n  [Win32.NativeMethods]::SendMessageTimeout($HWND_BROADCAST,\n    $WM_SETTINGCHANGE,\n    [UIntPtr]::Zero,\n    \"Environment\",\n    2,\n    5000,\n    [ref] $result\n  ) | Out-Null\n}\n\nfunction Write-Env {\n  param([String]$Key, [String]$Value)\n\n  $RegisterKey = Get-Item -Path 'HKCU:'\n\n  $EnvRegisterKey = $RegisterKey.OpenSubKey('Environment', $true)\n  if ($null -eq $Value) {\n    $EnvRegisterKey.DeleteValue($Key)\n  } else {\n    $RegistryValueKind = if ($Value.Contains('%')) {\n      [Microsoft.Win32.RegistryValueKind]::ExpandString\n    } elseif ($EnvRegisterKey.GetValue($Key)) {\n      $EnvRegisterKey.GetValueKind($Key)\n    } else {\n      [Microsoft.Win32.RegistryValueKind]::String\n    }\n    $EnvRegisterKey.SetValue($Key, $Value, $RegistryValueKind)\n  }\n\n  Publish-Env\n}\n\nfunction Get-Env {\n  param([String] $Key)\n\n  $RegisterKey = Get-Item -Path 'HKCU:'\n  $EnvRegisterKey = $RegisterKey.OpenSubKey('Environment')\n  $EnvRegisterKey.GetValue($Key, $null, [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames)\n}\n\n# The installation of bun is it's own function so that in the unlikely case the $IsBaseline check fails, we can do a recursive call.\n# There are also lots of sanity checks out of fear of anti-virus software or other weird Windows things happening.\nfunction Install-Bun {\n  param(\n    [string]$Version,\n    [bool]$ForceBaseline = $False\n  );\n\n  # if a semver is given, we need to adjust it to this format: bun-v0.0.0\n  if ($Version -match \"^\\d+\\.\\d+\\.\\d+$\") {\n    $Version = \"bun-v$Version\"\n  }\n  elseif ($Version -match \"^v\\d+\\.\\d+\\.\\d+$\") {\n    $Version = \"bun-$Version\"\n  }\n\n  $Arch = \"x64\"\n  $IsBaseline = $ForceBaseline\n  if (!$IsBaseline) {\n    $IsBaseline = !( `\n      Add-Type -MemberDefinition '[DllImport(\"kernel32.dll\")] public static extern bool IsProcessorFeaturePresent(int ProcessorFeature);' `\n        -Name 'Kernel32' -Namespace 'Win32' -PassThru `\n    )::IsProcessorFeaturePresent(40);\n  }\n\n  $BunRoot = if ($env:BUN_INSTALL) { $env:BUN_INSTALL } else { \"${Home}\\.bun\" }\n  $BunBin = mkdir -Force \"${BunRoot}\\bin\"\n\n  try {\n    Remove-Item \"${BunBin}\\bun.exe\" -Force\n  } catch [System.Management.Automation.ItemNotFoundException] {\n    # ignore\n  } catch [System.UnauthorizedAccessException] {\n    $openProcesses = Get-Process -Name bun | Where-Object { $_.Path -eq \"${BunBin}\\bun.exe\" }\n    if ($openProcesses.Count -gt 0) {\n      Write-Output \"Install Failed - An older installation exists and is open. Please close open Bun processes and try again.\"\n      return 1\n    }\n    Write-Output \"Install Failed - An unknown error occurred while trying to remove the existing installation\"\n    Write-Output $_\n    return 1\n  } catch {\n    Write-Output \"Install Failed - An unknown error occurred while trying to remove the existing installation\"\n    Write-Output $_\n    return 1\n  }\n\n  $Target = \"bun-windows-$Arch\"\n  if ($IsBaseline) {\n    $Target = \"bun-windows-$Arch-baseline\"\n  }\n  $BaseURL = \"https://github.com/oven-sh/bun/releases\"\n  $URL = \"$BaseURL/$(if ($Version -eq \"latest\") { \"latest/download\" } else { \"download/$Version\" })/$Target.zip\"\n\n  $ZipPath = \"${BunBin}\\$Target.zip\"\n\n  $DisplayVersion = $(\n    if ($Version -eq \"latest\") { \"Bun\" }\n    elseif ($Version -eq \"canary\") { \"Bun Canary\" }\n    elseif ($Version -match \"^bun-v\\d+\\.\\d+\\.\\d+$\") { \"Bun $($Version.Substring(4))\" }\n    else { \"Bun tag='${Version}'\" }\n  )\n\n  $null = mkdir -Force $BunBin\n  Remove-Item -Force $ZipPath -ErrorAction SilentlyContinue\n\n  # curl.exe is faster than PowerShell 5's 'Invoke-WebRequest'\n  # note: 'curl' is an alias to 'Invoke-WebRequest'. so the exe suffix is required\n  if (-not $DownloadWithoutCurl) {\n    curl.exe \"-#SfLo\" \"$ZipPath\" \"$URL\" \n  }\n  if ($DownloadWithoutCurl -or ($LASTEXITCODE -ne 0)) {\n    Write-Warning \"The command 'curl.exe $URL -o $ZipPath' exited with code ${LASTEXITCODE}`nTrying an alternative download method...\"\n    try {\n      # Use Invoke-RestMethod instead of Invoke-WebRequest because Invoke-WebRequest breaks on\n      # some machines, see \n      Invoke-RestMethod -Uri $URL -OutFile $ZipPath\n    } catch {\n      Write-Output \"Install Failed - could not download $URL\"\n      Write-Output \"The command 'Invoke-RestMethod $URL -OutFile $ZipPath' exited with code ${LASTEXITCODE}`n\"\n      return 1\n    }\n  }\n\n  if (!(Test-Path $ZipPath)) {\n    Write-Output \"Install Failed - could not download $URL\"\n    Write-Output \"The file '$ZipPath' does not exist. Did an antivirus delete it?`n\"\n    return 1\n  }\n\n  try {\n    $lastProgressPreference = $global:ProgressPreference\n    $global:ProgressPreference = 'SilentlyContinue';\n    Expand-Archive \"$ZipPath\" \"$BunBin\" -Force\n    $global:ProgressPreference = $lastProgressPreference\n    if (!(Test-Path \"${BunBin}\\$Target\\bun.exe\")) {\n      throw \"The file '${BunBin}\\$Target\\bun.exe' does not exist. Download is corrupt or intercepted Antivirus?`n\"\n    }\n  } catch {\n    Write-Output \"Install Failed - could not unzip $ZipPath\"\n    Write-Error $_\n    return 1\n  }\n\n  Move-Item \"${BunBin}\\$Target\\bun.exe\" \"${BunBin}\\bun.exe\" -Force\n\n  Remove-Item \"${BunBin}\\$Target\" -Recurse -Force\n  Remove-Item $ZipPath -Force\n\n  $BunRevision = \"$(& \"${BunBin}\\bun.exe\" --revision)\"\n  if ($LASTEXITCODE -eq 1073741795) { # STATUS_ILLEGAL_INSTRUCTION\n    if ($IsBaseline) {\n      Write-Output \"Install Failed - bun.exe (baseline) is not compatible with your CPU.`n\"\n      Write-Output \"Please open a GitHub issue with your CPU model:`nhttps://github.com/oven-sh/bun/issues/new/choose`n\"\n      return 1\n    }\n\n    Write-Output \"Install Failed - bun.exe is not compatible with your CPU. This should have been detected before downloading.`n\"\n    Write-Output \"Attempting to download bun.exe (baseline) instead.`n\"\n\n    Install-Bun -Version $Version -ForceBaseline $True\n    return 1\n  }\n  # '-1073741515' was spotted in the wild, but not clearly documented as a status code:\n  # https://discord.com/channels/876711213126520882/1149339379446325248/1205194965383250081\n  # http://community.sqlbackupandftp.com/t/error-1073741515-solved/1305\n  if (($LASTEXITCODE -eq 3221225781) -or ($LASTEXITCODE -eq -1073741515)) # STATUS_DLL_NOT_FOUND\n  { \n    # TODO: as of July 2024, Bun has no external dependencies.\n    # I want to keep this error message in for a few months to ensure that\n    # if someone somehow runs into this, it can be reported.\n    Write-Output \"Install Failed - You are missing a DLL required to run bun.exe\"\n    Write-Output \"This can be solved by installing the Visual C++ Redistributable from Microsoft:`nSee https://learn.microsoft.com/cpp/windows/latest-supported-vc-redist`nDirect Download -> https://aka.ms/vs/17/release/vc_redist.x64.exe`n`n\"\n    Write-Output \"The error above should be unreachable as Bun does not depend on this library. Please comment in https://github.com/oven-sh/bun/issues/8598 or open a new issue.`n`n\"\n    Write-Output \"The command '${BunBin}\\bun.exe --revision' exited with code ${LASTEXITCODE}`n\"\n    return 1\n  }\n  if ($LASTEXITCODE -ne 0) {\n    Write-Output \"Install Failed - could not verify bun.exe\"\n    Write-Output \"The command '${BunBin}\\bun.exe --revision' exited with code ${LASTEXITCODE}`n\"\n    return 1\n  }\n\n  try {\n    $env:IS_BUN_AUTO_UPDATE = \"1\"\n    # TODO: When powershell completions are added, make this switch actually do something\n    if ($NoCompletions) {\n      $env:BUN_NO_INSTALL_COMPLETIONS = \"1\"\n    }\n    # This completions script in general will install some extra stuff, mainly the `bunx` link.\n    # It also installs completions.\n    $output = \"$(& \"${BunBin}\\bun.exe\" completions 2>&1)\"\n    if ($LASTEXITCODE -ne 0) {\n      Write-Output $output\n      Write-Output \"Install Failed - could not finalize installation\"\n      Write-Output \"The command '${BunBin}\\bun.exe completions' exited with code ${LASTEXITCODE}`n\"\n      return 1\n    }\n  } catch {\n    # it is possible on powershell 5 that an error happens, but it is probably fine?\n  }\n  $env:IS_BUN_AUTO_UPDATE = $null\n  $env:BUN_NO_INSTALL_COMPLETIONS = $null\n\n  $DisplayVersion = if ($BunRevision -like \"*-canary.*\") {\n    \"${BunRevision}\"\n  } else {\n    \"$(& \"${BunBin}\\bun.exe\" --version)\"\n  }\n\n  $C_RESET = [char]27 + \"[0m\"\n  $C_GREEN = [char]27 + \"[1;32m\"\n\n  Write-Output \"${C_GREEN}Bun ${DisplayVersion} was installed successfully!${C_RESET}\"\n  Write-Output \"The binary is located at ${BunBin}\\bun.exe`n\"\n\n  $hasExistingOther = $false;\n  try {\n    $existing = Get-Command bun -ErrorAction\n    if ($existing.Source -ne \"${BunBin}\\bun.exe\") {\n      Write-Warning \"Note: Another bun.exe is already in %PATH% at $($existing.Source)`nTyping 'bun' in your terminal will not use what was just installed.`n\"\n      $hasExistingOther = $true;\n    }\n  } catch {}\n\n  if (-not $NoRegisterInstallation) {\n    $rootKey = $null\n    try {\n      $RegistryKey = \"HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Bun\"  \n      $rootKey = New-Item -Path $RegistryKey -Force\n      New-ItemProperty -Path $RegistryKey -Name \"DisplayName\" -Value \"Bun\" -PropertyType String -Force | Out-Null\n      New-ItemProperty -Path $RegistryKey -Name \"InstallLocation\" -Value \"${BunRoot}\" -PropertyType String -Force | Out-Null\n      New-ItemProperty -Path $RegistryKey -Name \"DisplayIcon\" -Value $BunBin\\bun.exe -PropertyType String -Force | Out-Null\n      New-ItemProperty -Path $RegistryKey -Name \"UninstallString\" -Value \"powershell -c `\"& `'$BunRoot\\uninstall.ps1`' -PauseOnError`\" -ExecutionPolicy Bypass\" -PropertyType String -Force | Out-Null\n    } catch {\n      if ($rootKey -ne $null) {\n        Remove-Item -Path $RegistryKey -Force\n      }\n    }\n  }\n\n  if(!$hasExistingOther) {\n    # Only try adding to path if there isn't already a bun.exe in the path\n    $Path = (Get-Env -Key \"Path\") -split ';'\n    if ($Path -notcontains $BunBin) {\n      if (-not $NoPathUpdate) {\n        $Path += $BunBin\n        Write-Env -Key 'Path' -Value ($Path -join ';')\n        $env:PATH = $Path;\n      } else {\n        Write-Output \"Skipping adding '${BunBin}' to the user's %PATH%`n\"\n      }\n    }\n\n    Write-Output \"To get started, restart your terminal/editor, then type `\"bun`\"`n\"\n  }\n\n  $LASTEXITCODE = 0;\n}\n\nInstall-Bun -Version $Version -ForceBaseline $ForceBaseline\n"
  },
  {
    "path": "scripts/integration.sh",
    "content": "#!/bin/bash\n\n# Change directory to the first argument passed to the script\nproject_dir=$1\nshift\npushd \"$project_dir\" || exit 1\necho \"Changed directory to $project_dir\"\n\n# So we get stdout / stderr from Python ASAP. Without this, delays can be very long (e.g. on Windows, Github Actions)\nexport PYTHONUNBUFFERED=1\n\nenv_mode=$1\nshift\ncheck_ports=${1:-3000 8000}\nshift\n\n# Start the server in the background\nexport REFLEX_TELEMETRY_ENABLED=false\nreflex run --loglevel debug --env \"$env_mode\" \"$@\" & pid=$!\n\n# Within the context of this bash, $pid_in_bash is what we need to pass to \"kill\" on exit\n# This is true on all platforms.\npid_in_bash=$pid\ntrap \"kill -INT $pid_in_bash ||:\" EXIT\n\necho \"Started server with PID $pid\"\n\n# Assume we run from the root of the repo\npopd\n\n# In Windows, our Python script below needs to work with the WINPID\nif [ -f /proc/$pid/winpid ]; then\n  pid=$(cat /proc/$pid/winpid)\n  echo \"Windows detected, passing winpid $pid to port waiter\"\nfi\n\npython scripts/wait_for_listening_port.py $check_ports --timeout=900 --server-pid \"$pid\"\n"
  },
  {
    "path": "scripts/make_pyi.py",
    "content": "\"\"\"The pyi generator module.\"\"\"\n\nimport logging\nimport subprocess\nimport sys\nfrom pathlib import Path\n\nfrom reflex.utils.pyi_generator import PyiGenerator, _relative_to_pwd\n\nlogger = logging.getLogger(\"pyi_generator\")\n\nLAST_RUN_COMMIT_SHA_FILE = Path(\".pyi_generator_last_run\").resolve()\nGENERATOR_FILE = Path(__file__).resolve()\nGENERATOR_DIFF_FILE = Path(\".pyi_generator_diff\").resolve()\nDEFAULT_TARGETS = [\"reflex/components\", \"reflex/experimental\", \"reflex/__init__.py\"]\n\n\ndef _git_diff(args: list[str]) -> str:\n    \"\"\"Run a git diff command.\n\n    Args:\n        args: The args to pass to git diff.\n\n    Returns:\n        The output of the git diff command.\n    \"\"\"\n    cmd = [\"git\", \"diff\", \"--no-color\", *args]\n    return subprocess.run(cmd, capture_output=True, encoding=\"utf-8\").stdout\n\n\ndef _git_changed_files(args: list[str] | None = None) -> list[Path]:\n    \"\"\"Get the list of changed files for a git diff command.\n\n    Args:\n        args: The args to pass to git diff.\n\n    Returns:\n        The list of changed files.\n    \"\"\"\n    if not args:\n        args = []\n\n    if \"--name-only\" not in args:\n        args.insert(0, \"--name-only\")\n\n    diff = _git_diff(args).splitlines()\n    return [Path(file.strip()) for file in diff]\n\n\ndef _get_changed_files() -> list[Path] | None:\n    \"\"\"Get the list of changed files since the last run of the generator.\n\n    Returns:\n        The list of changed files, or None if all files should be regenerated.\n    \"\"\"\n    try:\n        last_run_commit_sha = LAST_RUN_COMMIT_SHA_FILE.read_text().strip()\n    except FileNotFoundError:\n        logger.info(\n            \"make_pyi.py last run could not be determined, regenerating all .pyi files\"\n        )\n        return None\n    changed_files = _git_changed_files([f\"{last_run_commit_sha}..HEAD\"])\n    # get all unstaged changes\n    changed_files.extend(_git_changed_files())\n    if _relative_to_pwd(GENERATOR_FILE) not in changed_files:\n        return changed_files\n    logger.info(\"make_pyi.py has changed, checking diff now\")\n    diff = \"\".join(_git_diff([GENERATOR_FILE.as_posix()]).splitlines()[2:])\n\n    try:\n        last_diff = GENERATOR_DIFF_FILE.read_text()\n        if diff != last_diff:\n            logger.info(\"make_pyi.py has changed, regenerating all .pyi files\")\n            changed_files = None\n        else:\n            logger.info(\"make_pyi.py has not changed, only regenerating changed files\")\n    except FileNotFoundError:\n        logger.info(\n            \"make_pyi.py diff could not be determined, regenerating all .pyi files\"\n        )\n        changed_files = None\n\n    GENERATOR_DIFF_FILE.write_text(diff)\n\n    return changed_files\n\n\nif __name__ == \"__main__\":\n    logging.basicConfig(level=logging.DEBUG)\n    logging.getLogger(\"blib2to3.pgen2.driver\").setLevel(logging.INFO)\n\n    targets = (\n        [arg for arg in sys.argv[1:] if not arg.startswith(\"tests\")]\n        if len(sys.argv) > 1\n        else DEFAULT_TARGETS\n    )\n\n    # Only include targets that have a prefix in the default target list\n    targets = [\n        target\n        for target in targets\n        if any(str(target).startswith(prefix) for prefix in DEFAULT_TARGETS)\n    ]\n\n    logger.info(f\"Running .pyi generator for {targets}\")\n\n    changed_files = _get_changed_files()\n    if changed_files is None:\n        logger.info(\"Changed files could not be detected, regenerating all .pyi files\")\n    else:\n        logger.info(f\"Detected changed files: {changed_files}\")\n\n    gen = PyiGenerator()\n    gen.scan_all(targets, changed_files, use_json=True)\n\n    current_commit_sha = subprocess.run(\n        [\"git\", \"rev-parse\", \"HEAD\"], capture_output=True, encoding=\"utf-8\"\n    ).stdout.strip()\n    LAST_RUN_COMMIT_SHA_FILE.write_text(current_commit_sha)\n"
  },
  {
    "path": "scripts/wait_for_listening_port.py",
    "content": "\"\"\"Script to wait for ports to start listening.\n\nReplaces logic previously implemented in a shell script that needed\ntools that are not available on Windows.\n\"\"\"\n\nimport argparse\nimport socket\nimport time\nfrom concurrent.futures import ThreadPoolExecutor, as_completed\n\n\ndef _pid_exists(pid: int):\n    # Note: For windows, the pid here is really the \"winpid\".\n    import psutil\n\n    return psutil.pid_exists(pid)\n\n\ndef _wait_for_port(port: int, server_pid: int, timeout: float) -> tuple[bool, str]:\n    start = time.time()\n    print(f\"Waiting for up to {timeout} seconds for port {port} to start listening.\")  # noqa: T201\n    while True:\n        if not _pid_exists(server_pid):\n            return False, f\"Server PID {server_pid} is not running.\"\n        try:\n            socket.create_connection((\"localhost\", port), timeout=0.5)\n            return True, f\"Port {port} is listening after {time.time() - start} seconds\"\n        except Exception:\n            if time.time() - start > timeout:\n                return (\n                    False,\n                    f\"Port {port} still not listening after {timeout} seconds.\",\n                )\n            time.sleep(5)\n\n\ndef main():\n    \"\"\"Wait for ports to start listening.\"\"\"\n    parser = argparse.ArgumentParser(description=\"Wait for ports to start listening.\")\n    parser.add_argument(\"port\", type=int, nargs=\"+\")\n    parser.add_argument(\"--timeout\", type=int, required=True)\n    parser.add_argument(\"--server-pid\", type=int)\n    args = parser.parse_args()\n    executor = ThreadPoolExecutor(max_workers=len(args.port))\n    futures = [\n        executor.submit(_wait_for_port, p, args.server_pid, args.timeout)\n        for p in args.port\n    ]\n    for f in as_completed(futures):\n        ok, msg = f.result()\n        if ok:\n            print(f\"OK: {msg}\")  # noqa: T201\n        else:\n            print(f\"FAIL: {msg}\")  # noqa: T201\n            exit(1)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "tests/__init__.py",
    "content": "\"\"\"Root directory for tests.\"\"\"\n\nimport os\n\nfrom reflex import constants\n"
  },
  {
    "path": "tests/benchmarks/__init__.py",
    "content": ""
  },
  {
    "path": "tests/benchmarks/conftest.py",
    "content": "from .fixtures import evaluated_page, unevaluated_page\n\n__all__ = [\"evaluated_page\", \"unevaluated_page\"]\n"
  },
  {
    "path": "tests/benchmarks/fixtures.py",
    "content": "from dataclasses import dataclass\nfrom typing import cast\n\nimport pytest\nfrom pydantic import BaseModel\n\nimport reflex as rx\n\n\nclass SideBarState(rx.State):\n    \"\"\"State for the side bar.\"\"\"\n\n    current_page: rx.Field[str] = rx.field(\"/\")\n\n\n@dataclass(frozen=True)\nclass SideBarPage:\n    \"\"\"A page in the side bar.\"\"\"\n\n    title: str\n    href: str\n\n\n@dataclass(frozen=True)\nclass SideBarSection:\n    \"\"\"A section in the side bar.\"\"\"\n\n    name: str\n    icon: str\n    pages: tuple[SideBarPage, ...]\n\n\n@dataclass(frozen=True)\nclass Category:\n    \"\"\"A category in the side bar.\"\"\"\n\n    name: str\n    href: str\n    sections: tuple[SideBarSection, ...]\n\n\nSIDE_BAR = (\n    Category(\n        name=\"General\",\n        href=\"/\",\n        sections=(\n            SideBarSection(\n                name=\"Home\",\n                icon=\"home\",\n                pages=(\n                    SideBarPage(title=\"Home\", href=\"/\"),\n                    SideBarPage(title=\"Contact\", href=\"/contact\"),\n                ),\n            ),\n            SideBarSection(\n                name=\"About\",\n                icon=\"info\",\n                pages=(\n                    SideBarPage(title=\"About\", href=\"/about\"),\n                    SideBarPage(title=\"FAQ\", href=\"/faq\"),\n                ),\n            ),\n        ),\n    ),\n    Category(\n        name=\"Projects\",\n        href=\"/projects\",\n        sections=(\n            SideBarSection(\n                name=\"Python\",\n                icon=\"worm\",\n                pages=(\n                    SideBarPage(title=\"Python\", href=\"/projects/python\"),\n                    SideBarPage(title=\"Django\", href=\"/projects/django\"),\n                    SideBarPage(title=\"Flask\", href=\"/projects/flask\"),\n                    SideBarPage(title=\"FastAPI\", href=\"/projects/fastapi\"),\n                    SideBarPage(title=\"Pyramid\", href=\"/projects/pyramid\"),\n                    SideBarPage(title=\"Tornado\", href=\"/projects/tornado\"),\n                    SideBarPage(title=\"TurboGears\", href=\"/projects/turbogears\"),\n                    SideBarPage(title=\"Web2py\", href=\"/projects/web2py\"),\n                    SideBarPage(title=\"Zope\", href=\"/projects/zope\"),\n                    SideBarPage(title=\"Plone\", href=\"/projects/plone\"),\n                    SideBarPage(title=\"Quixote\", href=\"/projects/quixote\"),\n                    SideBarPage(title=\"Bottle\", href=\"/projects/bottle\"),\n                    SideBarPage(title=\"CherryPy\", href=\"/projects/cherrypy\"),\n                    SideBarPage(title=\"Falcon\", href=\"/projects/falcon\"),\n                    SideBarPage(title=\"Sanic\", href=\"/projects/sanic\"),\n                    SideBarPage(title=\"Starlette\", href=\"/projects/starlette\"),\n                ),\n            ),\n            SideBarSection(\n                name=\"JavaScript\",\n                icon=\"banana\",\n                pages=(\n                    SideBarPage(title=\"JavaScript\", href=\"/projects/javascript\"),\n                    SideBarPage(title=\"Angular\", href=\"/projects/angular\"),\n                    SideBarPage(title=\"React\", href=\"/projects/react\"),\n                    SideBarPage(title=\"Vue\", href=\"/projects/vue\"),\n                    SideBarPage(title=\"Ember\", href=\"/projects/ember\"),\n                    SideBarPage(title=\"Backbone\", href=\"/projects/backbone\"),\n                    SideBarPage(title=\"Meteor\", href=\"/projects/meteor\"),\n                    SideBarPage(title=\"Svelte\", href=\"/projects/svelte\"),\n                    SideBarPage(title=\"Preact\", href=\"/projects/preact\"),\n                    SideBarPage(title=\"Mithril\", href=\"/projects/mithril\"),\n                    SideBarPage(title=\"Aurelia\", href=\"/projects/aurelia\"),\n                    SideBarPage(title=\"Polymer\", href=\"/projects/polymer\"),\n                    SideBarPage(title=\"Knockout\", href=\"/projects/knockout\"),\n                    SideBarPage(title=\"Dojo\", href=\"/projects/dojo\"),\n                    SideBarPage(title=\"Riot\", href=\"/projects/riot\"),\n                    SideBarPage(title=\"Alpine\", href=\"/projects/alpine\"),\n                    SideBarPage(title=\"Stimulus\", href=\"/projects/stimulus\"),\n                    SideBarPage(title=\"Marko\", href=\"/projects/marko\"),\n                    SideBarPage(title=\"Sapper\", href=\"/projects/sapper\"),\n                    SideBarPage(title=\"Nuxt\", href=\"/projects/nuxt\"),\n                    SideBarPage(title=\"Next\", href=\"/projects/next\"),\n                    SideBarPage(title=\"Gatsby\", href=\"/projects/gatsby\"),\n                    SideBarPage(title=\"Gridsome\", href=\"/projects/gridsome\"),\n                    SideBarPage(title=\"Nest\", href=\"/projects/nest\"),\n                    SideBarPage(title=\"Express\", href=\"/projects/express\"),\n                    SideBarPage(title=\"Koa\", href=\"/projects/koa\"),\n                    SideBarPage(title=\"Hapi\", href=\"/projects/hapi\"),\n                    SideBarPage(title=\"LoopBack\", href=\"/projects/loopback\"),\n                    SideBarPage(title=\"Feathers\", href=\"/projects/feathers\"),\n                    SideBarPage(title=\"Sails\", href=\"/projects/sails\"),\n                    SideBarPage(title=\"Adonis\", href=\"/projects/adonis\"),\n                    SideBarPage(title=\"Meteor\", href=\"/projects/meteor\"),\n                    SideBarPage(title=\"Derby\", href=\"/projects/derby\"),\n                    SideBarPage(title=\"Socket.IO\", href=\"/projects/socketio\"),\n                ),\n            ),\n        ),\n    ),\n)\n\n\ndef side_bar_page(page: SideBarPage):\n    return rx.box(\n        rx.link(\n            page.title,\n            href=page.href,\n        )\n    )\n\n\ndef side_bar_section(section: SideBarSection):\n    return rx.accordion.item(\n        rx.accordion.header(\n            rx.accordion.trigger(\n                rx.hstack(\n                    rx.hstack(\n                        rx.icon(section.icon),\n                        section.name,\n                        align=\"center\",\n                    ),\n                    rx.accordion.icon(),\n                    width=\"100%\",\n                    justify=\"between\",\n                )\n            )\n        ),\n        rx.accordion.content(\n            rx.vstack(\n                *map(side_bar_page, section.pages),\n            ),\n            border_inline_start=\"1px solid\",\n            padding_inline_start=\"1em\",\n            margin_inline_start=\"1.5em\",\n        ),\n        value=section.name,\n        width=\"100%\",\n        variant=\"ghost\",\n    )\n\n\ndef side_bar_category(category: Category):\n    selected_section = cast(\n        rx.Var,\n        rx.match(\n            SideBarState.current_page,\n            *[\n                (\n                    section.name,\n                    section.name,\n                )\n                for section in category.sections\n            ],\n            None,\n        ),\n    )\n    return rx.vstack(\n        rx.heading(\n            rx.link(\n                category.name,\n                href=category.href,\n            ),\n            size=\"5\",\n        ),\n        rx.accordion.root(\n            *map(side_bar_section, category.sections),\n            default_value=selected_section.to(str),\n            variant=\"ghost\",\n            width=\"100%\",\n            collapsible=True,\n            type=\"multiple\",\n        ),\n        width=\"100%\",\n    )\n\n\ndef side_bar():\n    return rx.vstack(\n        *map(side_bar_category, SIDE_BAR),\n        width=\"fit-content\",\n    )\n\n\nclass NestedElement(BaseModel):\n    \"\"\"A nested element.\"\"\"\n\n    identifier: str\n    value: list[int]\n\n\nclass BenchmarkState(rx.State):\n    \"\"\"State for the benchmark.\"\"\"\n\n    counter: rx.Field[int] = rx.field(17)\n\n    current_key: rx.Field[str] = rx.field(\"key_2\")\n\n    @rx.event\n    def increment(self):\n        \"\"\"Increment the counter.\"\"\"\n        self.counter = self.counter + 1\n\n    @rx.event\n    def decrement(self):\n        \"\"\"Decrement the counter.\"\"\"\n        self.counter = self.counter - 1\n\n    @rx.var\n    def elements(self) -> list[int]:\n        \"\"\"List of elements.\n\n        Returns:\n            List of elements.\n        \"\"\"\n        if self.counter < 0:\n            return list(range(0))\n        return list(range(self.counter))\n\n    @rx.var\n    def nested_elements(self) -> list[NestedElement]:\n        \"\"\"List of nested elements.\n\n        Returns:\n            List of nested elements.\n        \"\"\"\n        return [\n            NestedElement(\n                identifier=str(i),\n                value=list(range(i)),\n            )\n            for i in range(self.counter)\n        ]\n\n    @rx.var\n    def show_odd(self) -> bool:\n        \"\"\"Check if the counter is odd.\n\n        Returns:\n            True if the counter is odd, False otherwise.\n        \"\"\"\n        return self.counter % 2 == 1\n\n    @rx.var\n    def show_even(self) -> bool:\n        \"\"\"Check if the counter is even.\n\n        Returns:\n            True if the counter is even, False otherwise.\n        \"\"\"\n        return self.counter % 2 == 0\n\n\nLOREM_IPSUM = \"Lorem ipsum dolor sit amet, dolor ut dolore pariatur aliqua enim tempor sed. Labore excepteur sed exercitation. Ullamco aliquip lorem sunt enim in incididunt. Magna anim officia sint cillum labore. Ut eu non dolore minim nostrud magna eu, aute ex in incididunt irure eu. Fugiat et magna magna est excepteur eiusmod minim. Quis eiusmod et non pariatur dolor veniam incididunt, eiusmod irure enim sed dolor lorem pariatur do. Occaecat duis irure excepteur dolore. Proident ut laborum pariatur sit sit, nisi nostrud voluptate magna commodo laborum esse velit. Voluptate non minim deserunt adipiscing irure deserunt cupidatat. Laboris veniam commodo incididunt veniam lorem occaecat, fugiat ipsum dolor cupidatat. Ea officia sed eu excepteur culpa adipiscing, tempor consectetur ullamco eu. Anim ex proident nulla sunt culpa, voluptate veniam proident est adipiscing sint elit velit. Laboris adipiscing est culpa cillum magna. Sit veniam nulla nulla, aliqua eiusmod commodo lorem cupidatat commodo occaecat. Fugiat cillum dolor incididunt mollit eiusmod sint. Non lorem dolore labore excepteur minim laborum sed. Irure nisi do lorem nulla sunt commodo, deserunt quis mollit consectetur minim et esse est, proident nostrud officia enim sed reprehenderit. Magna cillum consequat aute reprehenderit duis sunt ullamco. Labore qui mollit voluptate. Duis dolor sint aute amet aliquip officia, est non mollit tempor enim quis fugiat, eu do culpa consectetur magna. Do ullamco aliqua voluptate culpa excepteur reprehenderit reprehenderit. Occaecat nulla sit est magna. Deserunt ea voluptate veniam cillum. Amet cupidatat duis est tempor fugiat ex eu, officia est sunt consectetur labore esse exercitation. Nisi cupidatat irure est nisi. Officia amet eu veniam reprehenderit. In amet incididunt tempor commodo ea labore. Mollit dolor aliquip excepteur, voluptate aute occaecat id officia proident. Ullamco est amet tempor. Proident aliquip proident mollit do aliquip ipsum, culpa quis aute id irure. Velit excepteur cillum cillum ut cupidatat. Occaecat qui elit esse nulla minim. Consequat velit id ad pariatur tempor. Eiusmod deserunt aliqua ex sed quis non. Dolor sint commodo ex in deserunt nostrud excepteur, pariatur ex aliqua anim adipiscing amet proident. Laboris eu laborum magna lorem ipsum fugiat velit.\"\n\n\ndef _complicated_page():\n    return rx.hstack(\n        side_bar(),\n        rx.box(\n            rx.heading(\"Complicated Page\", size=\"1\"),\n            rx.text(LOREM_IPSUM),\n        ),\n    )\n\n\ndef _counter():\n    return (\n        rx.text(BenchmarkState.counter),\n        rx.button(\"Increment\", on_click=BenchmarkState.increment),\n        rx.button(\"Decrement\", on_click=BenchmarkState.decrement),\n        rx.cond(\n            BenchmarkState.counter < 0,\n            rx.text(\"Counter is negative\"),\n            rx.fragment(\n                rx.cond(\n                    BenchmarkState.show_odd,\n                    rx.text(\"Counter is odd\"),\n                ),\n                rx.cond(\n                    BenchmarkState.show_even,\n                    rx.text(\"Counter is even\"),\n                ),\n            ),\n        ),\n    )\n\n\ndef _show_key():\n    return rx.match(\n        BenchmarkState.current_key,\n        (\n            \"key_1\",\n            rx.text(\"Key 1\"),\n        ),\n        (\n            \"key_2\",\n            rx.text(\"Key 2\"),\n        ),\n        (\n            \"key_3\",\n            rx.text(\"Key 3\"),\n        ),\n        rx.text(\"Key not found\"),\n    )\n\n\ndef _simple_foreach():\n    return rx.foreach(\n        BenchmarkState.elements,\n        lambda elem: rx.text(elem),\n    )\n\n\ndef _render_nested_element(elem: NestedElement, idx):\n    return (\n        rx.text(f\"{idx} {elem.identifier}\"),\n        rx.foreach(elem.value, lambda value: rx.text(value)),\n    )\n\n\ndef _nested_foreach():\n    return rx.foreach(\n        BenchmarkState.nested_elements,\n        _render_nested_element,\n    )\n\n\ndef _stateful_page():\n    return rx.hstack(\n        _counter(),\n        _show_key(),\n        _simple_foreach(),\n        _nested_foreach(),\n    )\n\n\n@pytest.fixture(params=[_complicated_page, _stateful_page])\ndef unevaluated_page(request: pytest.FixtureRequest):\n    return request.param\n\n\n@pytest.fixture(params=[_complicated_page, _stateful_page])\ndef evaluated_page(request: pytest.FixtureRequest):\n    return request.param()\n"
  },
  {
    "path": "tests/benchmarks/test_compilation.py",
    "content": "from pytest_codspeed import BenchmarkFixture\n\nfrom reflex.compiler.compiler import _compile_page, _compile_stateful_components\nfrom reflex.components.component import Component\n\n\ndef import_templates():\n    # Importing the templates module to avoid the import time in the benchmark\n    import reflex.compiler.templates  # noqa: F401\n\n\ndef test_compile_page(evaluated_page: Component, benchmark: BenchmarkFixture):\n    import_templates()\n\n    benchmark(lambda: _compile_page(evaluated_page))\n\n\ndef test_compile_stateful(evaluated_page: Component, benchmark: BenchmarkFixture):\n    import_templates()\n\n    benchmark(lambda: _compile_stateful_components([evaluated_page]))\n\n\ndef test_get_all_imports(evaluated_page: Component, benchmark: BenchmarkFixture):\n    benchmark(lambda: evaluated_page._get_all_imports())\n"
  },
  {
    "path": "tests/benchmarks/test_evaluate.py",
    "content": "from collections.abc import Callable\n\nfrom pytest_codspeed import BenchmarkFixture\n\nfrom reflex.components.component import Component\n\n\ndef test_evaluate_page(\n    unevaluated_page: Callable[[], Component], benchmark: BenchmarkFixture\n):\n    benchmark(unevaluated_page)\n"
  },
  {
    "path": "tests/integration/__init__.py",
    "content": "\"\"\"Package for integration tests.\"\"\"\n"
  },
  {
    "path": "tests/integration/conftest.py",
    "content": "\"\"\"Shared conftest for all integration tests.\"\"\"\n\nimport pytest\nfrom pytest_mock import MockerFixture\n\nimport reflex.app\nfrom reflex.testing import AppHarness, AppHarnessProd\n\n\n@pytest.fixture(\n    scope=\"session\", params=[AppHarness, AppHarnessProd], ids=[\"dev\", \"prod\"]\n)\ndef app_harness_env(request):\n    \"\"\"Parametrize the AppHarness class to use for the test, either dev or prod.\n\n    Args:\n        request: The pytest fixture request object.\n\n    Returns:\n        The AppHarness class to use for the test.\n    \"\"\"\n    return request.param\n\n\n@pytest.fixture(autouse=True)\ndef raise_console_error(request, mocker: MockerFixture):\n    \"\"\"Spy on calls to `console.error` used by the framework.\n\n    Help catch spurious error conditions that might otherwise go unnoticed.\n\n    If a test is marked with `ignore_console_error`, the spy will be ignored\n    after the test.\n\n    Args:\n        request: The pytest request object.\n        mocker: The pytest mocker object.\n\n    Yields:\n        control to the test function.\n    \"\"\"\n    spy = mocker.spy(reflex.app.console, \"error\")\n    yield\n    if \"ignore_console_error\" not in request.keywords:\n        spy.assert_not_called()\n"
  },
  {
    "path": "tests/integration/init-test/Dockerfile",
    "content": "FROM python:3.10\n\nARG USERNAME=kerrigan\nRUN useradd -m $USERNAME\nRUN apt-get update && apt-get install -y redis && rm -rf /var/lib/apt/lists/*\nUSER $USERNAME\n\nWORKDIR /home/$USERNAME\n"
  },
  {
    "path": "tests/integration/init-test/in_docker_test_script.sh",
    "content": "#!/usr/bin/env bash\n\nset -euxo pipefail\n\nSCRIPTPATH=\"$( cd -- \"$(dirname \"$0\")\" >/dev/null 2>&1 ; pwd -P )\"\nexport REFLEX_TELEMETRY_ENABLED=false\n\nfunction do_export () {\n    template=$1\n    mkdir ~/\"$template\"\n    cd ~/\"$template\"\n    rm -rf ~/.local/share/reflex ~/\"$template\"/.web\n    reflex init --template \"$template\"\n    reflex export --loglevel debug\n    (\n        cd \"$SCRIPTPATH/../../..\"\n        scripts/integration.sh ~/\"$template\" dev\n        pkill -9 -f 'node|python3' || true\n        sleep 10\n        REFLEX_REDIS_URL=redis://localhost scripts/integration.sh ~/\"$template\" prod\n        pkill -9 -f 'node|python3' || true\n        sleep 10\n    )\n}\n\necho \"Preparing test project dir\"\npython3 -m venv ~/venv\nsource ~/venv/bin/activate\npip install -U pip\n\necho \"Installing reflex from local repo code\"\ncp -r /reflex-repo ~/reflex-repo\npip install ~/reflex-repo\npip install psutil\n\nredis-server &\n\necho \"Running reflex init in test project dir\"\ndo_export blank\n"
  },
  {
    "path": "tests/integration/shared/state.py",
    "content": "\"\"\"Simple module which contains one reusable reflex state class.\"\"\"\n\nimport reflex as rx\n\n\nclass SharedState(rx.State):\n    \"\"\"Shared state class for reflexers using libraries.\"\"\"\n"
  },
  {
    "path": "tests/integration/test_background_task.py",
    "content": "\"\"\"Test @rx.event(background=True) task functionality.\"\"\"\n\nfrom collections.abc import Generator\n\nimport pytest\nfrom selenium.webdriver.common.by import By\n\nfrom reflex.testing import DEFAULT_TIMEOUT, AppHarness, WebDriver\n\n\ndef BackgroundTask():\n    \"\"\"Test that background tasks work as expected.\"\"\"\n    import asyncio\n\n    import pytest\n\n    import reflex as rx\n    from reflex.state import ImmutableStateError\n\n    class State(rx.State):\n        counter: int = 0\n        _task_id: int = 0\n        iterations: rx.Field[int] = rx.field(10)\n\n        @rx.event\n        def set_iterations(self, value: str):\n            self.iterations = int(value)\n\n        @rx.var\n        async def counter_async_cv(self) -> int:\n            \"\"\"This exists solely as an integration test for background tasks triggering async var updates.\n\n            Returns:\n                The current value of the counter.\n            \"\"\"\n            return self.counter\n\n        @rx.event(background=True)\n        async def handle_event(self):\n            async with self:\n                self._task_id += 1\n            for _ix in range(int(self.iterations)):\n                async with self:\n                    self.counter += 1\n                await asyncio.sleep(0.005)\n\n        @rx.event(background=True)\n        async def handle_event_yield_only(self):\n            async with self:\n                self._task_id += 1\n            for ix in range(int(self.iterations)):\n                if ix % 2 == 0:\n                    yield State.increment_arbitrary(1)\n                else:\n                    yield State.increment()\n                await asyncio.sleep(0.005)\n\n        @rx.event(background=True)\n        async def fast_yielding(self):\n            for _ in range(1000):\n                yield State.increment()\n\n        @rx.event\n        def increment(self):\n            self.counter += 1\n\n        @rx.event(background=True)\n        async def increment_arbitrary(self, amount: int):\n            async with self:\n                self.counter += int(amount)\n\n        @rx.event\n        def reset_counter(self):\n            self.counter = 0\n\n        @rx.event\n        async def blocking_pause(self):\n            await asyncio.sleep(0.02)\n\n        @rx.event(background=True)\n        async def non_blocking_pause(self):\n            await asyncio.sleep(0.02)\n\n        async def racy_task(self):\n            async with self:\n                self._task_id += 1\n            for _ix in range(int(self.iterations)):\n                async with self:\n                    self.counter += 1\n                await asyncio.sleep(0.005)\n\n        @rx.event(background=True)\n        async def handle_racy_event(self):\n            await asyncio.gather(\n                self.racy_task(), self.racy_task(), self.racy_task(), self.racy_task()\n            )\n\n        @rx.event(background=True)\n        async def nested_async_with_self(self):\n            async with self:\n                self.counter += 1\n                with pytest.raises(ImmutableStateError):\n                    async with self:\n                        self.counter += 1\n\n        async def triple_count(self):\n            third_state = await self.get_state(ThirdState)\n            await third_state._triple_count()\n\n        @rx.event(background=True)\n        async def yield_in_async_with_self(self):\n            async with self:\n                self.counter += 1\n                yield\n                self.counter += 1\n\n        @rx.event(background=True)\n        async def disconnect_reconnect_background(self):\n            async with self:\n                self.counter += 1\n            yield rx.call_script(\"socket.disconnect()\")\n            await asyncio.sleep(0.5)\n            async with self:\n                self.counter += 1\n\n    class OtherState(rx.State):\n        @rx.event(background=True)\n        async def get_other_state(self):\n            async with self:\n                state = await self.get_state(State)\n                state.counter += 1\n                await state.triple_count()\n            with pytest.raises(ImmutableStateError):\n                await state.triple_count()\n            with pytest.raises(ImmutableStateError):\n                state.counter += 1\n            async with state:\n                state.counter += 1\n                await state.triple_count()\n\n    class ThirdState(rx.State):\n        async def _triple_count(self):\n            state = await self.get_state(State)\n            state.counter *= 3\n\n    def index() -> rx.Component:\n        return rx.vstack(\n            rx.input(\n                id=\"token\", value=State.router.session.client_token, is_read_only=True\n            ),\n            rx.input(\n                id=\"sid\", value=State.router.session.session_id, is_read_only=True\n            ),\n            rx.hstack(\n                rx.heading(State.counter, id=\"counter\"),\n                rx.text(State.counter_async_cv, size=\"1\", id=\"counter-async-cv\"),\n            ),\n            rx.input(\n                id=\"iterations\",\n                placeholder=\"Iterations\",\n                value=State.iterations.to_string(),\n                on_change=State.set_iterations,\n            ),\n            rx.button(\n                \"Delayed Increment\",\n                on_click=State.handle_event,\n                id=\"delayed-increment\",\n            ),\n            rx.button(\n                \"Yield Increment\",\n                on_click=State.handle_event_yield_only,\n                id=\"yield-increment\",\n            ),\n            rx.button(\"Increment 1\", on_click=State.increment, id=\"increment\"),\n            rx.button(\n                \"Blocking Pause\",\n                on_click=State.blocking_pause,\n                id=\"blocking-pause\",\n            ),\n            rx.button(\n                \"Non-Blocking Pause\",\n                on_click=State.non_blocking_pause,\n                id=\"non-blocking-pause\",\n            ),\n            rx.button(\n                \"Racy Increment (x4)\",\n                on_click=State.handle_racy_event,\n                id=\"racy-increment\",\n            ),\n            rx.button(\n                \"Nested Async with Self\",\n                on_click=State.nested_async_with_self,\n                id=\"nested-async-with-self\",\n            ),\n            rx.button(\n                \"Increment from OtherState\",\n                on_click=OtherState.get_other_state,\n                id=\"increment-from-other-state\",\n            ),\n            rx.button(\n                \"Yield in Async with Self\",\n                on_click=State.yield_in_async_with_self,\n                id=\"yield-in-async-with-self\",\n            ),\n            rx.button(\n                \"Disconnect / Reconnect Background\",\n                on_click=State.disconnect_reconnect_background,\n                id=\"disconnect-reconnect-background\",\n            ),\n            rx.button(\n                \"Fast Yielding\",\n                on_click=State.fast_yielding,\n                id=\"fast-yielding\",\n            ),\n            rx.button(\"Reset\", on_click=State.reset_counter, id=\"reset\"),\n        )\n\n    app = rx.App()\n    app.add_page(index)\n\n\n@pytest.fixture(scope=\"module\")\ndef background_task(\n    tmp_path_factory,\n) -> Generator[AppHarness, None, None]:\n    \"\"\"Start BackgroundTask app at tmp_path via AppHarness.\n\n    Args:\n        tmp_path_factory: pytest tmp_path_factory fixture\n\n    Yields:\n        running AppHarness instance\n    \"\"\"\n    with AppHarness.create(\n        root=tmp_path_factory.mktemp(\"background_task\"),\n        app_source=BackgroundTask,\n    ) as harness:\n        yield harness\n\n\n@pytest.fixture\ndef driver(background_task: AppHarness) -> Generator[WebDriver, None, None]:\n    \"\"\"Get an instance of the browser open to the background_task app.\n\n    Args:\n        background_task: harness for BackgroundTask app\n\n    Yields:\n        WebDriver instance.\n    \"\"\"\n    assert background_task.app_instance is not None, \"app is not running\"\n    driver = background_task.frontend()\n    try:\n        yield driver\n    finally:\n        driver.quit()\n\n\n@pytest.fixture\ndef token(background_task: AppHarness, driver: WebDriver) -> str:\n    \"\"\"Get a function that returns the active token.\n\n    Args:\n        background_task: harness for BackgroundTask app.\n        driver: WebDriver instance.\n\n    Returns:\n        The token for the connected client\n    \"\"\"\n    assert background_task.app_instance is not None\n\n    token_input = AppHarness.poll_for_or_raise_timeout(\n        lambda: driver.find_element(By.ID, \"token\")\n    )\n\n    # wait for the backend connection to send the token\n    token = background_task.poll_for_value(token_input, timeout=DEFAULT_TIMEOUT * 2)\n    assert token is not None\n\n    return token\n\n\ndef test_background_task(\n    background_task: AppHarness,\n    driver: WebDriver,\n    token: str,\n):\n    \"\"\"Test that background tasks work as expected.\n\n    Args:\n        background_task: harness for BackgroundTask app.\n        driver: WebDriver instance.\n        token: The token for the connected client.\n    \"\"\"\n    assert background_task.app_instance is not None\n\n    # get a reference to all buttons\n    delayed_increment_button = driver.find_element(By.ID, \"delayed-increment\")\n    yield_increment_button = driver.find_element(By.ID, \"yield-increment\")\n    increment_button = driver.find_element(By.ID, \"increment\")\n    blocking_pause_button = driver.find_element(By.ID, \"blocking-pause\")\n    non_blocking_pause_button = driver.find_element(By.ID, \"non-blocking-pause\")\n    racy_increment_button = driver.find_element(By.ID, \"racy-increment\")\n    driver.find_element(By.ID, \"reset\")\n\n    # get a reference to the counter\n    counter = driver.find_element(By.ID, \"counter\")\n    counter_async_cv = driver.find_element(By.ID, \"counter-async-cv\")\n\n    # get a reference to the iterations input\n    iterations_input = driver.find_element(By.ID, \"iterations\")\n\n    # kick off background tasks\n    iterations_input.clear()\n    iterations_input.send_keys(\"50\")\n    delayed_increment_button.click()\n    blocking_pause_button.click()\n    delayed_increment_button.click()\n    for _ in range(10):\n        increment_button.click()\n    blocking_pause_button.click()\n    delayed_increment_button.click()\n    delayed_increment_button.click()\n    yield_increment_button.click()\n    racy_increment_button.click()\n    non_blocking_pause_button.click()\n    yield_increment_button.click()\n    blocking_pause_button.click()\n    yield_increment_button.click()\n    for _ in range(10):\n        increment_button.click()\n    yield_increment_button.click()\n    blocking_pause_button.click()\n    AppHarness.expect(lambda: counter.text == \"620\", timeout=40)\n    AppHarness.expect(lambda: counter_async_cv.text == \"620\", timeout=40)\n    # all tasks should have exited and cleaned up\n    AppHarness.expect(\n        lambda: not background_task.app_instance._background_tasks  # pyright: ignore [reportOptionalMemberAccess]\n    )\n\n\ndef test_nested_async_with_self(\n    background_task: AppHarness,\n    driver: WebDriver,\n    token: str,\n):\n    \"\"\"Test that nested async with self in the same coroutine raises Exception.\n\n    Args:\n        background_task: harness for BackgroundTask app.\n        driver: WebDriver instance.\n        token: The token for the connected client.\n    \"\"\"\n    assert background_task.app_instance is not None\n\n    # get a reference to all buttons\n    nested_async_with_self_button = driver.find_element(By.ID, \"nested-async-with-self\")\n    increment_button = driver.find_element(By.ID, \"increment\")\n\n    # get a reference to the counter\n    counter = driver.find_element(By.ID, \"counter\")\n    AppHarness.expect(lambda: counter.text == \"0\", timeout=5)\n\n    nested_async_with_self_button.click()\n    AppHarness.expect(lambda: counter.text == \"1\", timeout=5)\n\n    increment_button.click()\n    AppHarness.expect(lambda: counter.text == \"2\", timeout=5)\n\n\ndef test_get_state(\n    background_task: AppHarness,\n    driver: WebDriver,\n    token: str,\n):\n    \"\"\"Test that get_state returns a state bound to the correct StateProxy.\n\n    Args:\n        background_task: harness for BackgroundTask app.\n        driver: WebDriver instance.\n        token: The token for the connected client.\n    \"\"\"\n    assert background_task.app_instance is not None\n\n    # get a reference to all buttons\n    other_state_button = driver.find_element(By.ID, \"increment-from-other-state\")\n    increment_button = driver.find_element(By.ID, \"increment\")\n\n    # get a reference to the counter\n    counter = driver.find_element(By.ID, \"counter\")\n    AppHarness.expect(lambda: counter.text == \"0\", timeout=5)\n\n    other_state_button.click()\n    AppHarness.expect(lambda: counter.text == \"12\", timeout=5)\n\n    increment_button.click()\n    AppHarness.expect(lambda: counter.text == \"13\", timeout=5)\n\n\ndef test_yield_in_async_with_self(\n    background_task: AppHarness,\n    driver: WebDriver,\n    token: str,\n):\n    \"\"\"Test that yielding inside async with self does not disable mutability.\n\n    Args:\n        background_task: harness for BackgroundTask app.\n        driver: WebDriver instance.\n        token: The token for the connected client.\n    \"\"\"\n    assert background_task.app_instance is not None\n\n    # get a reference to all buttons\n    yield_in_async_with_self_button = driver.find_element(\n        By.ID, \"yield-in-async-with-self\"\n    )\n\n    # get a reference to the counter\n    counter = driver.find_element(By.ID, \"counter\")\n    AppHarness.expect(lambda: counter.text == \"0\", timeout=5)\n\n    yield_in_async_with_self_button.click()\n    AppHarness.expect(lambda: counter.text == \"2\", timeout=5)\n\n\n@pytest.mark.parametrize(\n    \"button_id\",\n    [\n        \"disconnect-reconnect-background\",\n    ],\n)\ndef test_disconnect_reconnect(\n    background_task: AppHarness,\n    driver: WebDriver,\n    token: str,\n    button_id: str,\n):\n    \"\"\"Test that disconnecting and reconnecting works as expected.\n\n    Args:\n        background_task: harness for BackgroundTask app.\n        driver: WebDriver instance.\n        token: The token for the connected client.\n        button_id: The ID of the button to click.\n    \"\"\"\n    counter = driver.find_element(By.ID, \"counter\")\n    button = driver.find_element(By.ID, button_id)\n    increment_button = driver.find_element(By.ID, \"increment\")\n    sid_input = driver.find_element(By.ID, \"sid\")\n    sid = background_task.poll_for_value(sid_input, timeout=5)\n    assert sid is not None\n\n    AppHarness.expect(lambda: counter.text == \"0\", timeout=5)\n    button.click()\n    AppHarness.expect(lambda: counter.text == \"1\", timeout=5)\n    increment_button.click()\n    # should get a new sid after the reconnect\n    assert (\n        background_task.poll_for_value(sid_input, timeout=5, exp_not_equal=sid) != sid\n    )\n    # Final update should come through on the new websocket connection\n    AppHarness.expect(lambda: counter.text == \"3\", timeout=5)\n\n\ndef test_fast_yielding(\n    background_task: AppHarness,\n    driver: WebDriver,\n    token: str,\n) -> None:\n    \"\"\"Test that fast yielding works as expected.\n\n    Args:\n        background_task: harness for BackgroundTask app.\n        driver: WebDriver instance.\n        token: The token for the connected client.\n    \"\"\"\n    assert background_task.app_instance is not None\n\n    # get a reference to all buttons\n    fast_yielding_button = driver.find_element(By.ID, \"fast-yielding\")\n\n    # get a reference to the counter\n    counter = driver.find_element(By.ID, \"counter\")\n    assert background_task._poll_for(lambda: counter.text == \"0\", timeout=5)\n\n    fast_yielding_button.click()\n    assert background_task._poll_for(lambda: counter.text == \"1000\", timeout=50)\n"
  },
  {
    "path": "tests/integration/test_call_script.py",
    "content": "\"\"\"Integration tests for client side storage.\"\"\"\n\nfrom __future__ import annotations\n\nfrom collections.abc import Generator\n\nimport pytest\nfrom selenium.webdriver.common.by import By\nfrom selenium.webdriver.remote.webdriver import WebDriver\n\nfrom reflex.testing import AppHarness\n\nfrom .utils import SessionStorage\n\n\ndef CallScript():\n    \"\"\"A test app for browser javascript integration.\"\"\"\n    from pathlib import Path\n\n    import reflex as rx\n\n    inline_scripts = \"\"\"\n    let inline_counter = 0\n    function inline1() {\n        inline_counter += 1\n        return \"inline1\"\n    }\n    function inline2() {\n        inline_counter += 1\n        console.log(\"inline2\")\n    }\n    function inline3() {\n        inline_counter += 1\n        return {inline3: 42, a: [1, 2, 3], s: 'js', o: {a: 1, b: 2}}\n    }\n    async function inline4() {\n        inline_counter += 1\n        return \"async inline4\"\n    }\n    \"\"\"\n\n    external_scripts = inline_scripts.replace(\"inline\", \"external\")\n\n    class CallScriptState(rx.State):\n        results: rx.Field[list[str | dict | list | None]] = rx.field([])\n        inline_counter: rx.Field[int] = rx.field(0)\n        external_counter: rx.Field[int] = rx.field(0)\n        value: str = \"Initial\"\n        last_result: rx.Field[int] = rx.field(0)\n\n        @rx.event\n        def call_script_callback(self, result):\n            self.results.append(result)\n\n        @rx.event\n        def call_script_callback_other_arg(self, result, other_arg):\n            self.results.append([other_arg, result])\n\n        @rx.event\n        def call_scripts_inline_yield(self):\n            yield rx.call_script(\"inline1()\")\n            yield rx.call_script(\"inline2()\")\n            yield rx.call_script(\"inline3()\")\n            yield rx.call_script(\"inline4()\")\n\n        @rx.event\n        def call_script_inline_return(self):\n            return rx.call_script(\"inline2()\")\n\n        @rx.event\n        def call_scripts_inline_yield_callback(self):\n            yield rx.call_script(\n                \"inline1()\", callback=CallScriptState.call_script_callback\n            )\n            yield rx.call_script(\n                \"inline2()\", callback=CallScriptState.call_script_callback\n            )\n            yield rx.call_script(\n                \"inline3()\", callback=CallScriptState.call_script_callback\n            )\n            yield rx.call_script(\n                \"inline4()\", callback=CallScriptState.call_script_callback\n            )\n\n        @rx.event\n        def call_script_inline_return_callback(self):\n            return rx.call_script(\n                \"inline3()\", callback=CallScriptState.call_script_callback\n            )\n\n        @rx.event\n        def call_script_inline_return_lambda(self):\n            return rx.call_script(\n                \"inline2()\",\n                callback=lambda result: CallScriptState.call_script_callback_other_arg(\n                    result, \"lambda\"\n                ),\n            )\n\n        @rx.event\n        def get_inline_counter(self):\n            return rx.call_script(\n                \"inline_counter\",\n                callback=CallScriptState.setvar(\"inline_counter\"),\n            )\n\n        @rx.event\n        def call_scripts_external_yield(self):\n            yield rx.call_script(\"external1()\")\n            yield rx.call_script(\"external2()\")\n            yield rx.call_script(\"external3()\")\n            yield rx.call_script(\"external4()\")\n\n        @rx.event\n        def call_script_external_return(self):\n            return rx.call_script(\"external2()\")\n\n        @rx.event\n        def call_scripts_external_yield_callback(self):\n            yield rx.call_script(\n                \"external1()\", callback=CallScriptState.call_script_callback\n            )\n            yield rx.call_script(\n                \"external2()\", callback=CallScriptState.call_script_callback\n            )\n            yield rx.call_script(\n                \"external3()\", callback=CallScriptState.call_script_callback\n            )\n            yield rx.call_script(\n                \"external4()\", callback=CallScriptState.call_script_callback\n            )\n\n        @rx.event\n        def call_script_external_return_callback(self):\n            return rx.call_script(\n                \"external3()\", callback=CallScriptState.call_script_callback\n            )\n\n        @rx.event\n        def call_script_external_return_lambda(self):\n            return rx.call_script(\n                \"external2()\",\n                callback=lambda result: CallScriptState.call_script_callback_other_arg(\n                    result, \"lambda\"\n                ),\n            )\n\n        @rx.event\n        def get_external_counter(self):\n            return rx.call_script(\n                \"external_counter\",\n                callback=CallScriptState.setvar(\"external_counter\"),\n            )\n\n        @rx.event\n        def call_with_var_f_string(self):\n            return rx.call_script(\n                f\"{rx.Var('inline_counter')} + {rx.Var('external_counter')}\",\n                callback=CallScriptState.setvar(\"last_result\"),\n            )\n\n        @rx.event\n        def call_with_var_str_cast(self):\n            return rx.call_script(\n                f\"{rx.Var('inline_counter')!s} + {rx.Var('external_counter')!s}\",\n                callback=CallScriptState.setvar(\"last_result\"),\n            )\n\n        @rx.event\n        def call_with_var_f_string_wrapped(self):\n            return rx.call_script(\n                rx.Var(f\"{rx.Var('inline_counter')} + {rx.Var('external_counter')}\"),\n                callback=CallScriptState.setvar(\"last_result\"),\n            )\n\n        @rx.event\n        def call_with_var_str_cast_wrapped(self):\n            return rx.call_script(\n                rx.Var(\n                    f\"{rx.Var('inline_counter')!s} + {rx.Var('external_counter')!s}\"\n                ),\n                callback=CallScriptState.setvar(\"last_result\"),\n            )\n\n        @rx.event\n        def set_inline_counter(self, value: str):\n            self.inline_counter = int(value)\n\n        @rx.event\n        def set_external_counter(self, value: str):\n            self.external_counter = int(value)\n\n        @rx.event\n        def set_last_result(self, value: str):\n            self.last_result = int(value)\n\n        @rx.event\n        def set_value(self, value: str):\n            self.value = value\n\n        @rx.event\n        def reset_(self):\n            yield rx.call_script(\"inline_counter = 0; external_counter = 0\")\n            self.reset()\n\n    app = rx.App()\n    Path(\"assets/external.js\").write_text(external_scripts)\n\n    @app.add_page\n    def index():\n        return rx.vstack(\n            rx.input(\n                value=CallScriptState.inline_counter.to_string(),\n                id=\"inline_counter\",\n                read_only=True,\n            ),\n            rx.input(\n                value=CallScriptState.external_counter.to_string(),\n                id=\"external_counter\",\n                read_only=True,\n            ),\n            rx.text_area(\n                value=CallScriptState.results.to_string(),\n                id=\"results\",\n                read_only=True,\n            ),\n            rx.script(inline_scripts),\n            rx.script(src=\"/external.js\"),\n            rx.button(\n                \"call_scripts_inline_yield\",\n                on_click=CallScriptState.call_scripts_inline_yield,\n                id=\"inline_yield\",\n            ),\n            rx.button(\n                \"call_script_inline_return\",\n                on_click=CallScriptState.call_script_inline_return,\n                id=\"inline_return\",\n            ),\n            rx.button(\n                \"call_scripts_inline_yield_callback\",\n                on_click=CallScriptState.call_scripts_inline_yield_callback,\n                id=\"inline_yield_callback\",\n            ),\n            rx.button(\n                \"call_script_inline_return_callback\",\n                on_click=CallScriptState.call_script_inline_return_callback,\n                id=\"inline_return_callback\",\n            ),\n            rx.button(\n                \"call_script_inline_return_lambda\",\n                on_click=CallScriptState.call_script_inline_return_lambda,\n                id=\"inline_return_lambda\",\n            ),\n            rx.button(\n                \"call_scripts_external_yield\",\n                on_click=CallScriptState.call_scripts_external_yield,\n                id=\"external_yield\",\n            ),\n            rx.button(\n                \"call_script_external_return\",\n                on_click=CallScriptState.call_script_external_return,\n                id=\"external_return\",\n            ),\n            rx.button(\n                \"call_scripts_external_yield_callback\",\n                on_click=CallScriptState.call_scripts_external_yield_callback,\n                id=\"external_yield_callback\",\n            ),\n            rx.button(\n                \"call_script_external_return_callback\",\n                on_click=CallScriptState.call_script_external_return_callback,\n                id=\"external_return_callback\",\n            ),\n            rx.button(\n                \"call_script_external_return_lambda\",\n                on_click=CallScriptState.call_script_external_return_lambda,\n                id=\"external_return_lambda\",\n            ),\n            rx.button(\n                \"Update Inline Counter\",\n                on_click=CallScriptState.get_inline_counter,\n                id=\"update_inline_counter\",\n            ),\n            rx.button(\n                \"Update External Counter\",\n                on_click=CallScriptState.get_external_counter,\n                id=\"update_external_counter\",\n            ),\n            rx.button(\n                CallScriptState.value,\n                on_click=rx.call_script(\n                    \"'updated'\",\n                    callback=CallScriptState.setvar(\"value\"),\n                ),\n                id=\"update_value\",\n            ),\n            rx.button(\"Reset\", id=\"reset\", on_click=CallScriptState.reset_),\n            rx.input(\n                value=CallScriptState.last_result.to_string(),\n                id=\"last_result\",\n                read_only=True,\n                on_click=CallScriptState.setvar(\"last_result\", 0),\n            ),\n            rx.button(\n                \"call_with_var_f_string\",\n                on_click=CallScriptState.call_with_var_f_string,\n                id=\"call_with_var_f_string\",\n            ),\n            rx.button(\n                \"call_with_var_str_cast\",\n                on_click=CallScriptState.call_with_var_str_cast,\n                id=\"call_with_var_str_cast\",\n            ),\n            rx.button(\n                \"call_with_var_f_string_wrapped\",\n                on_click=CallScriptState.call_with_var_f_string_wrapped,\n                id=\"call_with_var_f_string_wrapped\",\n            ),\n            rx.button(\n                \"call_with_var_str_cast_wrapped\",\n                on_click=CallScriptState.call_with_var_str_cast_wrapped,\n                id=\"call_with_var_str_cast_wrapped\",\n            ),\n            rx.button(\n                \"call_with_var_f_string_inline\",\n                on_click=rx.call_script(\n                    f\"{rx.Var('inline_counter')} + {CallScriptState.last_result}\",\n                    callback=CallScriptState.setvar(\"last_result\"),\n                ),\n                id=\"call_with_var_f_string_inline\",\n            ),\n            rx.button(\n                \"call_with_var_str_cast_inline\",\n                on_click=rx.call_script(\n                    f\"{rx.Var('inline_counter')!s} + {rx.Var('external_counter')!s}\",\n                    callback=CallScriptState.setvar(\"last_result\"),\n                ),\n                id=\"call_with_var_str_cast_inline\",\n            ),\n            rx.button(\n                \"call_with_var_f_string_wrapped_inline\",\n                on_click=rx.call_script(\n                    rx.Var(\n                        f\"{rx.Var('inline_counter')} + {CallScriptState.last_result}\"\n                    ),\n                    callback=CallScriptState.setvar(\"last_result\"),\n                ),\n                id=\"call_with_var_f_string_wrapped_inline\",\n            ),\n            rx.button(\n                \"call_with_var_str_cast_wrapped_inline\",\n                on_click=rx.call_script(\n                    rx.Var(\n                        f\"{rx.Var('inline_counter')!s} + {rx.Var('external_counter')!s}\"\n                    ),\n                    callback=CallScriptState.setvar(\"last_result\"),\n                ),\n                id=\"call_with_var_str_cast_wrapped_inline\",\n            ),\n        )\n\n\n@pytest.fixture(scope=\"module\")\ndef call_script(tmp_path_factory) -> Generator[AppHarness, None, None]:\n    \"\"\"Start CallScript app at tmp_path via AppHarness.\n\n    Args:\n        tmp_path_factory: pytest tmp_path_factory fixture\n\n    Yields:\n        running AppHarness instance\n    \"\"\"\n    with AppHarness.create(\n        root=tmp_path_factory.mktemp(\"call_script\"),\n        app_source=CallScript,\n    ) as harness:\n        yield harness\n\n\n@pytest.fixture\ndef driver(call_script: AppHarness) -> Generator[WebDriver, None, None]:\n    \"\"\"Get an instance of the browser open to the call_script app.\n\n    Args:\n        call_script: harness for CallScript app\n\n    Yields:\n        WebDriver instance.\n    \"\"\"\n    assert call_script.app_instance is not None, \"app is not running\"\n    driver = call_script.frontend()\n    try:\n        yield driver\n    finally:\n        driver.quit()\n\n\ndef assert_token(driver: WebDriver) -> str:\n    \"\"\"Get the token associated with backend state.\n\n    Args:\n        driver: WebDriver instance.\n\n    Returns:\n        The token visible in the driver browser.\n    \"\"\"\n    ss = SessionStorage(driver)\n    assert AppHarness._poll_for(lambda: ss.get(\"token\") is not None), \"token not found\"\n    assert AppHarness._poll_for(\n        lambda: driver.execute_script(\"return typeof external4 !== 'undefined'\")\n    ), \"scripts not loaded\"\n    return ss.get(\"token\")\n\n\n@pytest.mark.parametrize(\"script\", [\"inline\", \"external\"])\ndef test_call_script(\n    call_script: AppHarness,\n    driver: WebDriver,\n    script: str,\n):\n    \"\"\"Test calling javascript functions from python.\n\n    Args:\n        call_script: harness for CallScript app.\n        driver: WebDriver instance.\n        script: The type of script to test.\n    \"\"\"\n    assert_token(driver)\n    reset_button = driver.find_element(By.ID, \"reset\")\n    update_counter_button = driver.find_element(By.ID, f\"update_{script}_counter\")\n    counter = driver.find_element(By.ID, f\"{script}_counter\")\n    results = driver.find_element(By.ID, \"results\")\n    yield_button = driver.find_element(By.ID, f\"{script}_yield\")\n    return_button = driver.find_element(By.ID, f\"{script}_return\")\n    yield_callback_button = driver.find_element(By.ID, f\"{script}_yield_callback\")\n    return_callback_button = driver.find_element(By.ID, f\"{script}_return_callback\")\n    return_lambda_button = driver.find_element(By.ID, f\"{script}_return_lambda\")\n\n    yield_button.click()\n    update_counter_button.click()\n    assert call_script.poll_for_value(counter, exp_not_equal=\"0\") == \"4\"\n    reset_button.click()\n    assert call_script.poll_for_value(counter, exp_not_equal=\"4\") == \"0\"\n    return_button.click()\n    update_counter_button.click()\n    assert call_script.poll_for_value(counter, exp_not_equal=\"0\") == \"1\"\n    reset_button.click()\n    assert call_script.poll_for_value(counter, exp_not_equal=\"1\") == \"0\"\n\n    yield_callback_button.click()\n    update_counter_button.click()\n    assert call_script.poll_for_value(counter, exp_not_equal=\"0\") == \"4\"\n    assert (\n        call_script.poll_for_value(results, exp_not_equal=\"[]\")\n        == f'[\"{script}1\",null,{{\"{script}3\":42,\"a\":[1,2,3],\"s\":\"js\",\"o\":{{\"a\":1,\"b\":2}}}},\"async {script}4\"]'\n    )\n    reset_button.click()\n    assert call_script.poll_for_value(counter, exp_not_equal=\"4\") == \"0\"\n\n    return_callback_button.click()\n    update_counter_button.click()\n    assert call_script.poll_for_value(counter, exp_not_equal=\"0\") == \"1\"\n    assert (\n        call_script.poll_for_value(results, exp_not_equal=\"[]\")\n        == f'[{{\"{script}3\":42,\"a\":[1,2,3],\"s\":\"js\",\"o\":{{\"a\":1,\"b\":2}}}}]'\n    )\n    reset_button.click()\n    assert call_script.poll_for_value(counter, exp_not_equal=\"1\") == \"0\"\n\n    return_lambda_button.click()\n    update_counter_button.click()\n    assert call_script.poll_for_value(counter, exp_not_equal=\"0\") == \"1\"\n    assert (\n        call_script.poll_for_value(results, exp_not_equal=\"[]\") == '[[\"lambda\",null]]'\n    )\n    reset_button.click()\n    assert call_script.poll_for_value(counter, exp_not_equal=\"1\") == \"0\"\n\n    # Check that triggering script from event trigger calls callback\n    update_value_button = driver.find_element(By.ID, \"update_value\")\n    update_value_button.click()\n\n    assert (\n        call_script.poll_for_content(update_value_button, exp_not_equal=\"Initial\")\n        == \"updated\"\n    )\n\n\ndef test_call_script_w_var(\n    call_script: AppHarness,\n    driver: WebDriver,\n):\n    \"\"\"Test evaluating javascript expressions containing Vars.\n\n    Args:\n        call_script: harness for CallScript app.\n        driver: WebDriver instance.\n    \"\"\"\n    assert_token(driver)\n    last_result = driver.find_element(By.ID, \"last_result\")\n    assert last_result.get_attribute(\"value\") == \"0\"\n\n    inline_return_button = driver.find_element(By.ID, \"inline_return\")\n\n    call_with_var_f_string_button = driver.find_element(By.ID, \"call_with_var_f_string\")\n    call_with_var_str_cast_button = driver.find_element(By.ID, \"call_with_var_str_cast\")\n    call_with_var_f_string_wrapped_button = driver.find_element(\n        By.ID, \"call_with_var_f_string_wrapped\"\n    )\n    call_with_var_str_cast_wrapped_button = driver.find_element(\n        By.ID, \"call_with_var_str_cast_wrapped\"\n    )\n    call_with_var_f_string_inline_button = driver.find_element(\n        By.ID, \"call_with_var_f_string_inline\"\n    )\n    call_with_var_str_cast_inline_button = driver.find_element(\n        By.ID, \"call_with_var_str_cast_inline\"\n    )\n    call_with_var_f_string_wrapped_inline_button = driver.find_element(\n        By.ID, \"call_with_var_f_string_wrapped_inline\"\n    )\n    call_with_var_str_cast_wrapped_inline_button = driver.find_element(\n        By.ID, \"call_with_var_str_cast_wrapped_inline\"\n    )\n\n    inline_return_button.click()\n    call_with_var_f_string_button.click()\n    assert call_script.poll_for_value(last_result, exp_not_equal=(\"\", \"0\")) == \"1\"\n\n    inline_return_button.click()\n    call_with_var_str_cast_button.click()\n    assert call_script.poll_for_value(last_result, exp_not_equal=\"1\") == \"2\"\n\n    inline_return_button.click()\n    call_with_var_f_string_wrapped_button.click()\n    assert call_script.poll_for_value(last_result, exp_not_equal=\"2\") == \"3\"\n\n    inline_return_button.click()\n    call_with_var_str_cast_wrapped_button.click()\n    assert call_script.poll_for_value(last_result, exp_not_equal=\"3\") == \"4\"\n\n    inline_return_button.click()\n    call_with_var_f_string_inline_button.click()\n    assert call_script.poll_for_value(last_result, exp_not_equal=\"4\") == \"9\"\n\n    inline_return_button.click()\n    call_with_var_str_cast_inline_button.click()\n    assert call_script.poll_for_value(last_result, exp_not_equal=\"9\") == \"6\"\n\n    inline_return_button.click()\n    call_with_var_f_string_wrapped_inline_button.click()\n    assert call_script.poll_for_value(last_result, exp_not_equal=\"6\") == \"13\"\n\n    inline_return_button.click()\n    call_with_var_str_cast_wrapped_inline_button.click()\n    assert call_script.poll_for_value(last_result, exp_not_equal=\"13\") == \"8\"\n"
  },
  {
    "path": "tests/integration/test_client_storage.py",
    "content": "\"\"\"Integration tests for client side storage.\"\"\"\n\nfrom __future__ import annotations\n\nimport asyncio\nfrom collections.abc import Generator\n\nimport pytest\nfrom selenium.webdriver.common.by import By\nfrom selenium.webdriver.firefox.webdriver import WebDriver as Firefox\nfrom selenium.webdriver.remote.webdriver import WebDriver\n\nfrom reflex.constants.state import FIELD_MARKER\nfrom reflex.istate.manager.disk import StateManagerDisk\nfrom reflex.istate.manager.memory import StateManagerMemory\nfrom reflex.istate.manager.redis import StateManagerRedis\nfrom reflex.state import State, _substate_key\nfrom reflex.testing import AppHarness\n\nfrom . import utils\n\n\ndef ClientSide():\n    \"\"\"App for testing client-side state.\"\"\"\n    import reflex as rx\n\n    class ClientSideState(rx.State):\n        state_var: str = \"\"\n        input_value: str = \"\"\n\n        @rx.event\n        def set_state_var(self, value: str):\n            self.state_var = value\n\n        @rx.event\n        def set_input_value(self, value: str):\n            self.input_value = value\n\n    class ClientSideSubState(ClientSideState):\n        # cookies with default settings\n        c1: str = rx.Cookie()\n        c2: str = rx.Cookie(\"c2 default\")\n\n        # cookies with custom settings\n        c3: str = rx.Cookie(max_age=2)  # expires after 2 second\n        c4: str = rx.Cookie(same_site=\"strict\")\n        c5: str = rx.Cookie(path=\"/foo/\")  # only accessible on `/foo/`\n        c6: str = rx.Cookie(name=\"c6\")\n        c7: str = rx.Cookie(\"c7 default\")\n\n        # local storage with default settings\n        l1: str = rx.LocalStorage()\n        l2: str = rx.LocalStorage(\"l2 default\")\n\n        # local storage with custom settings\n        l3: str = rx.LocalStorage(name=\"l3\")\n        l4: str = rx.LocalStorage(\"l4 default\")\n\n        # Sync'd local storage\n        l5: str = rx.LocalStorage(sync=True)\n        l6: str = rx.LocalStorage(sync=True, name=\"l6\")\n\n        # Session storage\n        s1: str = rx.SessionStorage()\n        s2: str = rx.SessionStorage(\"s2 default\")\n        s3: str = rx.SessionStorage(name=\"s3\")\n\n        def set_l6(self, my_param: str):\n            self.l6 = my_param\n\n        @rx.event\n        def set_var(self):\n            setattr(self, self.state_var, self.input_value)\n            self.state_var = self.input_value = \"\"\n\n    class ClientSideSubSubState(ClientSideSubState):\n        c1s: str = rx.Cookie()\n        l1s: str = rx.LocalStorage()\n        s1s: str = rx.SessionStorage()\n\n        @rx.event\n        def set_var(self):\n            setattr(self, self.state_var, self.input_value)\n            self.state_var = self.input_value = \"\"\n\n    def index():\n        return rx.fragment(\n            rx.input(\n                value=ClientSideState.router.session.client_token,\n                read_only=True,\n                id=\"token\",\n            ),\n            rx.input(\n                placeholder=\"state var\",\n                value=ClientSideState.state_var,\n                on_change=ClientSideState.setvar(\"state_var\"),\n                id=\"state_var\",\n            ),\n            rx.input(\n                placeholder=\"input value\",\n                value=ClientSideState.input_value,\n                on_change=ClientSideState.setvar(\"input_value\"),\n                id=\"input_value\",\n            ),\n            rx.button(\n                \"Set ClientSideSubState\",\n                on_click=ClientSideSubState.set_var,\n                id=\"set_sub_state\",\n            ),\n            rx.button(\n                \"Set ClientSideSubSubState\",\n                on_click=ClientSideSubSubState.set_var,\n                id=\"set_sub_sub_state\",\n            ),\n            rx.box(ClientSideSubState.c1, id=\"c1\"),\n            rx.box(ClientSideSubState.c2, id=\"c2\"),\n            rx.box(ClientSideSubState.c3, id=\"c3\"),\n            rx.box(ClientSideSubState.c4, id=\"c4\"),\n            rx.box(ClientSideSubState.c5, id=\"c5\"),\n            rx.box(ClientSideSubState.c6, id=\"c6\"),\n            rx.box(ClientSideSubState.c7, id=\"c7\"),\n            rx.box(ClientSideSubState.l1, id=\"l1\"),\n            rx.box(ClientSideSubState.l2, id=\"l2\"),\n            rx.box(ClientSideSubState.l3, id=\"l3\"),\n            rx.box(ClientSideSubState.l4, id=\"l4\"),\n            rx.box(ClientSideSubState.l5, id=\"l5\"),\n            rx.box(ClientSideSubState.l6, id=\"l6\"),\n            rx.box(ClientSideSubState.s1, id=\"s1\"),\n            rx.box(ClientSideSubState.s2, id=\"s2\"),\n            rx.box(ClientSideSubState.s3, id=\"s3\"),\n            rx.box(ClientSideSubSubState.c1s, id=\"c1s\"),\n            rx.box(ClientSideSubSubState.l1s, id=\"l1s\"),\n            rx.box(ClientSideSubSubState.s1s, id=\"s1s\"),\n        )\n\n    app = rx.App()\n    app.add_page(index)\n    app.add_page(index, route=\"/foo\")\n\n\n@pytest.fixture(scope=\"module\")\ndef client_side(tmp_path_factory) -> Generator[AppHarness, None, None]:\n    \"\"\"Start ClientSide app at tmp_path via AppHarness.\n\n    Args:\n        tmp_path_factory: pytest tmp_path_factory fixture\n\n    Yields:\n        running AppHarness instance\n    \"\"\"\n    with AppHarness.create(\n        root=tmp_path_factory.mktemp(\"client_side\"),\n        app_source=ClientSide,\n    ) as harness:\n        yield harness\n\n\n@pytest.fixture\ndef driver(client_side: AppHarness) -> Generator[WebDriver, None, None]:\n    \"\"\"Get an instance of the browser open to the client_side app.\n\n    Args:\n        client_side: harness for ClientSide app\n\n    Yields:\n        WebDriver instance.\n    \"\"\"\n    assert client_side.app_instance is not None, \"app is not running\"\n    driver = client_side.frontend()\n    try:\n        yield driver\n    finally:\n        driver.quit()\n\n\n@pytest.fixture\ndef local_storage(driver: WebDriver) -> Generator[utils.LocalStorage, None, None]:\n    \"\"\"Get an instance of the local storage helper.\n\n    Args:\n        driver: WebDriver instance.\n\n    Yields:\n        Local storage helper.\n    \"\"\"\n    ls = utils.LocalStorage(driver)\n    yield ls\n    ls.clear()\n\n\n@pytest.fixture\ndef session_storage(driver: WebDriver) -> Generator[utils.SessionStorage, None, None]:\n    \"\"\"Get an instance of the session storage helper.\n\n    Args:\n        driver: WebDriver instance.\n\n    Yields:\n        Session storage helper.\n    \"\"\"\n    ss = utils.SessionStorage(driver)\n    yield ss\n    ss.clear()\n\n\n@pytest.fixture(autouse=True)\ndef delete_all_cookies(driver: WebDriver) -> Generator[None, None, None]:\n    \"\"\"Delete all cookies after each test.\n\n    Args:\n        driver: WebDriver instance.\n\n    Yields:\n        None\n    \"\"\"\n    yield\n    driver.delete_all_cookies()\n\n\ndef cookie_info_map(driver: WebDriver) -> dict[str, dict[str, str]]:\n    \"\"\"Get a map of cookie names to cookie info.\n\n    Args:\n        driver: WebDriver instance.\n\n    Returns:\n        A map of cookie names to cookie info.\n    \"\"\"\n    return {cookie_info[\"name\"]: cookie_info for cookie_info in driver.get_cookies()}\n\n\n@pytest.mark.asyncio\nasync def test_client_side_state(\n    client_side: AppHarness,\n    driver: WebDriver,\n    local_storage: utils.LocalStorage,\n    session_storage: utils.SessionStorage,\n):\n    \"\"\"Test client side state.\n\n    Args:\n        client_side: harness for ClientSide app.\n        driver: WebDriver instance.\n        local_storage: Local storage helper.\n        session_storage: Session storage helper.\n    \"\"\"\n    app = client_side.app_instance\n    assert app is not None\n    assert client_side.frontend_url is not None\n\n    def poll_for_token():\n        token_input = AppHarness.poll_for_or_raise_timeout(\n            lambda: driver.find_element(By.ID, \"token\")\n        )\n\n        # wait for the backend connection to send the token\n        token = client_side.poll_for_value(token_input)\n        assert token is not None\n        return token\n\n    def set_sub(var: str, value: str):\n        # Get a reference to the cookie manipulation form.\n        state_var_input = driver.find_element(By.ID, \"state_var\")\n        input_value_input = driver.find_element(By.ID, \"input_value\")\n        set_sub_state_button = driver.find_element(By.ID, \"set_sub_state\")\n        AppHarness.expect(lambda: state_var_input.get_attribute(\"value\") == \"\")\n        AppHarness.expect(lambda: input_value_input.get_attribute(\"value\") == \"\")\n\n        # Set the values.\n        state_var_input.send_keys(var)\n        input_value_input.send_keys(value)\n        set_sub_state_button.click()\n\n    def set_sub_sub(var: str, value: str):\n        # Get a reference to the cookie manipulation form.\n        state_var_input = driver.find_element(By.ID, \"state_var\")\n        input_value_input = driver.find_element(By.ID, \"input_value\")\n        set_sub_sub_state_button = driver.find_element(By.ID, \"set_sub_sub_state\")\n        AppHarness.expect(lambda: state_var_input.get_attribute(\"value\") == \"\")\n        AppHarness.expect(lambda: input_value_input.get_attribute(\"value\") == \"\")\n\n        # Set the values.\n        state_var_input.send_keys(var)\n        input_value_input.send_keys(value)\n        set_sub_sub_state_button.click()\n\n    token = poll_for_token()\n\n    # get a reference to all cookie and local storage elements\n    c1 = driver.find_element(By.ID, \"c1\")\n    c2 = driver.find_element(By.ID, \"c2\")\n    c3 = driver.find_element(By.ID, \"c3\")\n    c4 = driver.find_element(By.ID, \"c4\")\n    c5 = driver.find_element(By.ID, \"c5\")\n    c6 = driver.find_element(By.ID, \"c6\")\n    c7 = driver.find_element(By.ID, \"c7\")\n    l1 = driver.find_element(By.ID, \"l1\")\n    l2 = driver.find_element(By.ID, \"l2\")\n    l3 = driver.find_element(By.ID, \"l3\")\n    l4 = driver.find_element(By.ID, \"l4\")\n    s1 = driver.find_element(By.ID, \"s1\")\n    s2 = driver.find_element(By.ID, \"s2\")\n    s3 = driver.find_element(By.ID, \"s3\")\n    c1s = driver.find_element(By.ID, \"c1s\")\n    l1s = driver.find_element(By.ID, \"l1s\")\n    s1s = driver.find_element(By.ID, \"s1s\")\n\n    # assert on defaults where present\n    assert c1.text == \"\"\n    assert c2.text == \"c2 default\"\n    assert c3.text == \"\"\n    assert c4.text == \"\"\n    assert c5.text == \"\"\n    assert c6.text == \"\"\n    assert c7.text == \"c7 default\"\n    assert l1.text == \"\"\n    assert l2.text == \"l2 default\"\n    assert l3.text == \"\"\n    assert l4.text == \"l4 default\"\n    assert s1.text == \"\"\n    assert s2.text == \"s2 default\"\n    assert s3.text == \"\"\n    assert c1s.text == \"\"\n    assert l1s.text == \"\"\n    assert s1s.text == \"\"\n\n    # no cookies should be set yet!\n    assert not driver.get_cookies()\n    local_storage_items = local_storage.items()\n    local_storage_items.pop(\"last_compiled_theme\", None)\n    local_storage_items.pop(\"theme\", None)\n    assert not local_storage_items\n\n    # set some cookies and local storage values\n    set_sub(\"c1\", \"c1 value\")\n    set_sub(\"c2\", \"c2 value\")\n    set_sub(\"c4\", \"c4 value\")\n    set_sub(\"c5\", \"c5 value\")\n    set_sub(\"c6\", \"c6 throwaway value\")\n    set_sub(\"c6\", \"c6 value\")\n    set_sub(\"c7\", \"c7 value\")\n    set_sub(\"l1\", \"l1 value\")\n    set_sub(\"l2\", \"l2 value\")\n    set_sub(\"l3\", \"l3 value\")\n    set_sub(\"l4\", \"l4 value\")\n    set_sub(\"s1\", \"s1 value\")\n    set_sub(\"s2\", \"s2 value\")\n    set_sub(\"s3\", \"s3 value\")\n    set_sub_sub(\"c1s\", \"c1s value\")\n    set_sub_sub(\"l1s\", \"l1s value\")\n    set_sub_sub(\"s1s\", \"s1s value\")\n\n    state_name = client_side.get_full_state_name([\"_client_side_state\"])\n    sub_state_name = client_side.get_full_state_name([\n        \"_client_side_state\",\n        \"_client_side_sub_state\",\n    ])\n    sub_sub_state_name = client_side.get_full_state_name([\n        \"_client_side_state\",\n        \"_client_side_sub_state\",\n        \"_client_side_sub_sub_state\",\n    ])\n\n    exp_cookies = {\n        f\"{sub_state_name}.c1\" + FIELD_MARKER: {\n            \"domain\": \"localhost\",\n            \"httpOnly\": False,\n            \"name\": f\"{sub_state_name}.c1\" + FIELD_MARKER,\n            \"path\": \"/\",\n            \"sameSite\": \"Lax\",\n            \"secure\": False,\n            \"value\": \"c1%20value\",\n        },\n        f\"{sub_state_name}.c2\" + FIELD_MARKER: {\n            \"domain\": \"localhost\",\n            \"httpOnly\": False,\n            \"name\": f\"{sub_state_name}.c2\" + FIELD_MARKER,\n            \"path\": \"/\",\n            \"sameSite\": \"Lax\",\n            \"secure\": False,\n            \"value\": \"c2%20value\",\n        },\n        f\"{sub_state_name}.c4\" + FIELD_MARKER: {\n            \"domain\": \"localhost\",\n            \"httpOnly\": False,\n            \"name\": f\"{sub_state_name}.c4\" + FIELD_MARKER,\n            \"path\": \"/\",\n            \"sameSite\": \"Strict\",\n            \"secure\": False,\n            \"value\": \"c4%20value\",\n        },\n        \"c6\": {\n            \"domain\": \"localhost\",\n            \"httpOnly\": False,\n            \"name\": \"c6\",\n            \"path\": \"/\",\n            \"sameSite\": \"Lax\",\n            \"secure\": False,\n            \"value\": \"c6%20value\",\n        },\n        f\"{sub_state_name}.c7\" + FIELD_MARKER: {\n            \"domain\": \"localhost\",\n            \"httpOnly\": False,\n            \"name\": f\"{sub_state_name}.c7\" + FIELD_MARKER,\n            \"path\": \"/\",\n            \"sameSite\": \"Lax\",\n            \"secure\": False,\n            \"value\": \"c7%20value\",\n        },\n        f\"{sub_sub_state_name}.c1s\" + FIELD_MARKER: {\n            \"domain\": \"localhost\",\n            \"httpOnly\": False,\n            \"name\": f\"{sub_sub_state_name}.c1s\" + FIELD_MARKER,\n            \"path\": \"/\",\n            \"sameSite\": \"Lax\",\n            \"secure\": False,\n            \"value\": \"c1s%20value\",\n        },\n    }\n    AppHarness.expect(\n        lambda: all(cookie_key in cookie_info_map(driver) for cookie_key in exp_cookies)\n    )\n    cookies = cookie_info_map(driver)\n    for exp_cookie_key, exp_cookie_data in exp_cookies.items():\n        assert cookies.pop(exp_cookie_key) == exp_cookie_data\n    # assert all cookies have been popped for this page\n    assert not cookies\n\n    # Test cookie with expiry by itself to avoid timing flakiness\n    set_sub(\"c3\", \"c3 value\")\n    AppHarness.expect(\n        lambda: f\"{sub_state_name}.c3\" + FIELD_MARKER in cookie_info_map(driver)\n    )\n    c3_cookie = cookie_info_map(driver)[f\"{sub_state_name}.c3\" + FIELD_MARKER]\n    assert c3_cookie.pop(\"expiry\") is not None\n    assert c3_cookie == {\n        \"domain\": \"localhost\",\n        \"httpOnly\": False,\n        \"name\": f\"{sub_state_name}.c3\" + FIELD_MARKER,\n        \"path\": \"/\",\n        \"sameSite\": \"Lax\",\n        \"secure\": False,\n        \"value\": \"c3%20value\",\n    }\n    await asyncio.sleep(2)  # wait for c3 to expire\n    if not isinstance(driver, Firefox):\n        # Note: Firefox does not remove expired cookies Bug 576347\n        assert f\"{sub_state_name}.c3\" + FIELD_MARKER not in cookie_info_map(driver)\n\n    local_storage_items = local_storage.items()\n    local_storage_items.pop(\"last_compiled_theme\", None)\n    local_storage_items.pop(\"theme\", None)\n    assert local_storage_items.pop(f\"{sub_state_name}.l1\" + FIELD_MARKER) == \"l1 value\"\n    assert local_storage_items.pop(f\"{sub_state_name}.l2\" + FIELD_MARKER) == \"l2 value\"\n    assert local_storage_items.pop(\"l3\") == \"l3 value\"\n    assert local_storage_items.pop(f\"{sub_state_name}.l4\" + FIELD_MARKER) == \"l4 value\"\n    assert (\n        local_storage_items.pop(f\"{sub_sub_state_name}.l1s\" + FIELD_MARKER)\n        == \"l1s value\"\n    )\n    assert not local_storage_items\n\n    session_storage_items = session_storage.items()\n    session_storage_items.pop(\"token\", None)\n    assert (\n        session_storage_items.pop(f\"{sub_state_name}.s1\" + FIELD_MARKER) == \"s1 value\"\n    )\n    assert (\n        session_storage_items.pop(f\"{sub_state_name}.s2\" + FIELD_MARKER) == \"s2 value\"\n    )\n    assert session_storage_items.pop(\"s3\") == \"s3 value\"\n    assert (\n        session_storage_items.pop(f\"{sub_sub_state_name}.s1s\" + FIELD_MARKER)\n        == \"s1s value\"\n    )\n    assert not session_storage_items\n\n    assert c1.text == \"c1 value\"\n    assert c2.text == \"c2 value\"\n    assert c3.text == \"c3 value\"\n    assert c4.text == \"c4 value\"\n    assert c5.text == \"c5 value\"\n    assert c6.text == \"c6 value\"\n    assert c7.text == \"c7 value\"\n    assert l1.text == \"l1 value\"\n    assert l2.text == \"l2 value\"\n    assert l3.text == \"l3 value\"\n    assert l4.text == \"l4 value\"\n    assert s1.text == \"s1 value\"\n    assert s2.text == \"s2 value\"\n    assert s3.text == \"s3 value\"\n    assert c1s.text == \"c1s value\"\n    assert l1s.text == \"l1s value\"\n    assert s1s.text == \"s1s value\"\n\n    # navigate to the /foo route\n    with utils.poll_for_navigation(driver):\n        driver.get(client_side.frontend_url.removesuffix(\"/\") + \"/foo/\")\n\n    # get new references to all cookie and local storage elements\n    c1 = AppHarness.poll_for_or_raise_timeout(lambda: driver.find_element(By.ID, \"c1\"))\n    c2 = driver.find_element(By.ID, \"c2\")\n    c3 = driver.find_element(By.ID, \"c3\")\n    c4 = driver.find_element(By.ID, \"c4\")\n    c5 = driver.find_element(By.ID, \"c5\")\n    c6 = driver.find_element(By.ID, \"c6\")\n    c7 = driver.find_element(By.ID, \"c7\")\n    l1 = driver.find_element(By.ID, \"l1\")\n    l2 = driver.find_element(By.ID, \"l2\")\n    l3 = driver.find_element(By.ID, \"l3\")\n    l4 = driver.find_element(By.ID, \"l4\")\n    s1 = driver.find_element(By.ID, \"s1\")\n    s2 = driver.find_element(By.ID, \"s2\")\n    s3 = driver.find_element(By.ID, \"s3\")\n    c1s = driver.find_element(By.ID, \"c1s\")\n    l1s = driver.find_element(By.ID, \"l1s\")\n    s1s = driver.find_element(By.ID, \"s1s\")\n\n    assert c1.text == \"c1 value\"\n    assert c2.text == \"c2 value\"\n    assert c3.text == \"\"  # cookie expired so value removed from state\n    assert c4.text == \"c4 value\"\n    assert c5.text == \"c5 value\"\n    assert c6.text == \"c6 value\"\n    assert c7.text == \"c7 value\"\n    assert l1.text == \"l1 value\"\n    assert l2.text == \"l2 value\"\n    assert l3.text == \"l3 value\"\n    assert l4.text == \"l4 value\"\n    assert s1.text == \"s1 value\"\n    assert s2.text == \"s2 value\"\n    assert s3.text == \"s3 value\"\n    assert c1s.text == \"c1s value\"\n    assert l1s.text == \"l1s value\"\n    assert s1s.text == \"s1s value\"\n\n    # reset the backend state to force refresh from client storage\n    async with client_side.modify_state(f\"{token}_{state_name}\") as state:\n        state.reset()\n    driver.refresh()\n\n    # wait for the backend connection to send the token (again)\n    token_input = AppHarness.poll_for_or_raise_timeout(\n        lambda: driver.find_element(By.ID, \"token\")\n    )\n    assert token_input\n    token = client_side.poll_for_value(token_input)\n    assert token is not None\n\n    # get new references to all cookie and local storage elements (again)\n    c1 = driver.find_element(By.ID, \"c1\")\n    c2 = driver.find_element(By.ID, \"c2\")\n    c3 = driver.find_element(By.ID, \"c3\")\n    c4 = driver.find_element(By.ID, \"c4\")\n    c5 = driver.find_element(By.ID, \"c5\")\n    c6 = driver.find_element(By.ID, \"c6\")\n    c7 = driver.find_element(By.ID, \"c7\")\n    l1 = driver.find_element(By.ID, \"l1\")\n    l2 = driver.find_element(By.ID, \"l2\")\n    l3 = driver.find_element(By.ID, \"l3\")\n    l4 = driver.find_element(By.ID, \"l4\")\n    s1 = driver.find_element(By.ID, \"s1\")\n    s2 = driver.find_element(By.ID, \"s2\")\n    s3 = driver.find_element(By.ID, \"s3\")\n    c1s = driver.find_element(By.ID, \"c1s\")\n    l1s = driver.find_element(By.ID, \"l1s\")\n    s1s = driver.find_element(By.ID, \"s1s\")\n\n    assert c1.text == \"c1 value\"\n    assert c2.text == \"c2 value\"\n    assert c3.text == \"\"  # temporary cookie expired after reset state!\n    assert c4.text == \"c4 value\"\n    assert c5.text == \"c5 value\"\n    assert c6.text == \"c6 value\"\n    assert c7.text == \"c7 value\"\n    assert l1.text == \"l1 value\"\n    assert l2.text == \"l2 value\"\n    assert l3.text == \"l3 value\"\n    assert l4.text == \"l4 value\"\n    assert s1.text == \"s1 value\"\n    assert s2.text == \"s2 value\"\n    assert s3.text == \"s3 value\"\n    assert c1s.text == \"c1s value\"\n    assert l1s.text == \"l1s value\"\n    assert s1s.text == \"s1s value\"\n\n    # make sure c5 cookie shows up on the `/foo` route\n    AppHarness.expect(\n        lambda: f\"{sub_state_name}.c5\" + FIELD_MARKER in cookie_info_map(driver)\n    )\n    assert cookie_info_map(driver)[f\"{sub_state_name}.c5\" + FIELD_MARKER] == {\n        \"domain\": \"localhost\",\n        \"httpOnly\": False,\n        \"name\": f\"{sub_state_name}.c5\" + FIELD_MARKER,\n        \"path\": \"/foo/\",\n        \"sameSite\": \"Lax\",\n        \"secure\": False,\n        \"value\": \"c5%20value\",\n    }\n\n    # Open a new tab to check that sync'd local storage is working\n    main_tab = driver.window_handles[0]\n    driver.switch_to.new_window(\"window\")\n    driver.get(client_side.frontend_url)\n\n    # New tab should have a different state token.\n    assert poll_for_token() != token\n\n    # Set values and check them in the new tab.\n    set_sub(\"l5\", \"l5 value\")\n    set_sub(\"l6\", \"l6 value\")\n    l5 = driver.find_element(By.ID, \"l5\")\n    l6 = driver.find_element(By.ID, \"l6\")\n    AppHarness.expect(lambda: l6.text == \"l6 value\")\n    assert l5.text == \"l5 value\"\n\n    # Set session storage values in the new tab\n    set_sub(\"s1\", \"other tab s1\")\n    s1 = driver.find_element(By.ID, \"s1\")\n    s2 = driver.find_element(By.ID, \"s2\")\n    s3 = driver.find_element(By.ID, \"s3\")\n    AppHarness.expect(lambda: s1.text == \"other tab s1\")\n    assert s2.text == \"s2 default\"\n    assert s3.text == \"\"\n\n    # Switch back to main window.\n    driver.switch_to.window(main_tab)\n\n    # The values should have updated automatically.\n    l5 = driver.find_element(By.ID, \"l5\")\n    l6 = driver.find_element(By.ID, \"l6\")\n    AppHarness.expect(lambda: l6.text == \"l6 value\")\n    assert l5.text == \"l5 value\"\n\n    s1 = driver.find_element(By.ID, \"s1\")\n    s2 = driver.find_element(By.ID, \"s2\")\n    s3 = driver.find_element(By.ID, \"s3\")\n    AppHarness.expect(lambda: s1.text == \"s1 value\")\n    assert s2.text == \"s2 value\"\n    assert s3.text == \"s3 value\"\n\n    # Simulate state expiration\n    if isinstance(client_side.state_manager, StateManagerRedis):\n        await client_side.state_manager.redis.delete(\n            _substate_key(token, State.get_full_name())\n        )\n        await client_side.state_manager.redis.delete(_substate_key(token, state_name))\n        await client_side.state_manager.redis.delete(\n            _substate_key(token, sub_state_name)\n        )\n        await client_side.state_manager.redis.delete(\n            _substate_key(token, sub_sub_state_name)\n        )\n    elif isinstance(client_side.state_manager, (StateManagerMemory, StateManagerDisk)):\n        del client_side.state_manager.states[token]\n    if (\n        client_side.app_instance is not None\n        and (app_state_manager := client_side.app_instance.state_manager) is not None\n        and isinstance(app_state_manager, StateManagerDisk)\n    ):\n        # Purge the backend's disk manager\n        app_state_manager.states.pop(token, None)\n        app_state_manager._write_queue.pop(token, None)\n        og_token_expiration = app_state_manager.token_expiration\n        app_state_manager.token_expiration = 0\n        app_state_manager._purge_expired_states()\n        app_state_manager.token_expiration = og_token_expiration\n\n    # Ensure the state is gone (not hydrated)\n    async def poll_for_not_hydrated():\n        state = await client_side.get_state(_substate_key(token or \"\", state_name))\n        assert isinstance(state, State)\n        return not state.is_hydrated\n\n    assert await AppHarness._poll_for_async(poll_for_not_hydrated)\n\n    # Trigger event to get a new instance of the state since the old was expired.\n    set_sub(\"c1\", \"c1 post expire\")\n\n    # get new references to all cookie and local storage elements (again)\n    c1 = driver.find_element(By.ID, \"c1\")\n    c2 = driver.find_element(By.ID, \"c2\")\n    c3 = driver.find_element(By.ID, \"c3\")\n    c4 = driver.find_element(By.ID, \"c4\")\n    c5 = driver.find_element(By.ID, \"c5\")\n    c6 = driver.find_element(By.ID, \"c6\")\n    c7 = driver.find_element(By.ID, \"c7\")\n    l1 = driver.find_element(By.ID, \"l1\")\n    l2 = driver.find_element(By.ID, \"l2\")\n    l3 = driver.find_element(By.ID, \"l3\")\n    l4 = driver.find_element(By.ID, \"l4\")\n    s1 = driver.find_element(By.ID, \"s1\")\n    s2 = driver.find_element(By.ID, \"s2\")\n    s3 = driver.find_element(By.ID, \"s3\")\n    c1s = driver.find_element(By.ID, \"c1s\")\n    l1s = driver.find_element(By.ID, \"l1s\")\n    s1s = driver.find_element(By.ID, \"s1s\")\n\n    assert c1.text == \"c1 post expire\"\n    assert c2.text == \"c2 value\"\n    assert c3.text == \"\"  # temporary cookie expired after reset state!\n    assert c4.text == \"c4 value\"\n    assert c5.text == \"c5 value\"\n    assert c6.text == \"c6 value\"\n    assert c7.text == \"c7 value\"\n    assert l1.text == \"l1 value\"\n    assert l2.text == \"l2 value\"\n    assert l3.text == \"l3 value\"\n    assert l4.text == \"l4 value\"\n    assert s1.text == \"s1 value\"\n    assert s2.text == \"s2 value\"\n    assert s3.text == \"s3 value\"\n    assert c1s.text == \"c1s value\"\n    assert l1s.text == \"l1s value\"\n    assert s1s.text == \"s1s value\"\n\n    # Get the backend state and ensure the values are still set\n    async def get_sub_state():\n        root_state = await client_side.get_state(\n            _substate_key(token or \"\", sub_state_name)\n        )\n        state = root_state.substates[client_side.get_state_name(\"_client_side_state\")]\n        return state.substates[client_side.get_state_name(\"_client_side_sub_state\")]\n\n    async def poll_for_c1_set():\n        sub_state = await get_sub_state()\n        return sub_state.c1 == \"c1 post expire\"  # pyright: ignore[reportAttributeAccessIssue]\n\n    assert await AppHarness._poll_for_async(poll_for_c1_set)\n    sub_state = await get_sub_state()\n    assert sub_state.c1 == \"c1 post expire\"  # pyright: ignore[reportAttributeAccessIssue]\n    assert sub_state.c2 == \"c2 value\"  # pyright: ignore[reportAttributeAccessIssue]\n    assert sub_state.c3 == \"\"  # pyright: ignore[reportAttributeAccessIssue]\n    assert sub_state.c4 == \"c4 value\"  # pyright: ignore[reportAttributeAccessIssue]\n    assert sub_state.c5 == \"c5 value\"  # pyright: ignore[reportAttributeAccessIssue]\n    assert sub_state.c6 == \"c6 value\"  # pyright: ignore[reportAttributeAccessIssue]\n    assert sub_state.c7 == \"c7 value\"  # pyright: ignore[reportAttributeAccessIssue]\n    assert sub_state.l1 == \"l1 value\"  # pyright: ignore[reportAttributeAccessIssue]\n    assert sub_state.l2 == \"l2 value\"  # pyright: ignore[reportAttributeAccessIssue]\n    assert sub_state.l3 == \"l3 value\"  # pyright: ignore[reportAttributeAccessIssue]\n    assert sub_state.l4 == \"l4 value\"  # pyright: ignore[reportAttributeAccessIssue]\n    assert sub_state.s1 == \"s1 value\"  # pyright: ignore[reportAttributeAccessIssue]\n    assert sub_state.s2 == \"s2 value\"  # pyright: ignore[reportAttributeAccessIssue]\n    assert sub_state.s3 == \"s3 value\"  # pyright: ignore[reportAttributeAccessIssue]\n    sub_sub_state = sub_state.substates[\n        client_side.get_state_name(\"_client_side_sub_sub_state\")\n    ]\n    assert sub_sub_state.c1s == \"c1s value\"  # pyright: ignore[reportAttributeAccessIssue]\n    assert sub_sub_state.l1s == \"l1s value\"  # pyright: ignore[reportAttributeAccessIssue]\n    assert sub_sub_state.s1s == \"s1s value\"  # pyright: ignore[reportAttributeAccessIssue]\n\n    # clear the cookie jar and local storage, ensure state reset to default\n    driver.delete_all_cookies()\n    local_storage.clear()\n\n    # refresh the page to trigger re-hydrate\n    driver.refresh()\n\n    # wait for the backend connection to send the token (again)\n    token_input = AppHarness.poll_for_or_raise_timeout(\n        lambda: driver.find_element(By.ID, \"token\")\n    )\n    token = client_side.poll_for_value(token_input)\n    assert token is not None\n\n    # all values should be back to their defaults\n    c1 = driver.find_element(By.ID, \"c1\")\n    c2 = driver.find_element(By.ID, \"c2\")\n    c3 = driver.find_element(By.ID, \"c3\")\n    c4 = driver.find_element(By.ID, \"c4\")\n    c5 = driver.find_element(By.ID, \"c5\")\n    c6 = driver.find_element(By.ID, \"c6\")\n    c7 = driver.find_element(By.ID, \"c7\")\n    l1 = driver.find_element(By.ID, \"l1\")\n    l2 = driver.find_element(By.ID, \"l2\")\n    l3 = driver.find_element(By.ID, \"l3\")\n    l4 = driver.find_element(By.ID, \"l4\")\n    c1s = driver.find_element(By.ID, \"c1s\")\n    l1s = driver.find_element(By.ID, \"l1s\")\n\n    # assert on defaults where present\n    assert c1.text == \"\"\n    assert c2.text == \"c2 default\"\n    assert c3.text == \"\"\n    assert c4.text == \"\"\n    assert c5.text == \"\"\n    assert c6.text == \"\"\n    assert c7.text == \"c7 default\"\n    assert l1.text == \"\"\n    assert l2.text == \"l2 default\"\n    assert l3.text == \"\"\n    assert l4.text == \"l4 default\"\n    assert c1s.text == \"\"\n    assert l1s.text == \"\"\n\n\ndef test_json_cookie_values(\n    client_side: AppHarness,\n    driver: WebDriver,\n):\n    \"\"\"Test that JSON-formatted cookie values are preserved as strings.\n\n    Args:\n        client_side: harness for ClientSide app.\n        driver: WebDriver instance.\n    \"\"\"\n    app = client_side.app_instance\n    assert app is not None\n    assert client_side.frontend_url is not None\n\n    def poll_for_token():\n        token_input = AppHarness.poll_for_or_raise_timeout(\n            lambda: driver.find_element(By.ID, \"token\")\n        )\n        token = client_side.poll_for_value(token_input)\n        assert token is not None\n        return token\n\n    def set_sub(var: str, value: str):\n        state_var_input = driver.find_element(By.ID, \"state_var\")\n        input_value_input = driver.find_element(By.ID, \"input_value\")\n        set_sub_state_button = driver.find_element(By.ID, \"set_sub_state\")\n        AppHarness.expect(lambda: state_var_input.get_attribute(\"value\") == \"\")\n        AppHarness.expect(lambda: input_value_input.get_attribute(\"value\") == \"\")\n\n        state_var_input.send_keys(var)\n        input_value_input.send_keys(value)\n        set_sub_state_button.click()\n\n    def _assert_json_cookie_with_refresh(cookie_id: str, json_value: str):\n        \"\"\"Helper function to test JSON cookie values with browser refresh.\n\n        Args:\n            cookie_id: ID of the cookie element to manipulate.\n            json_value: JSON string to set as the cookie value.\n        \"\"\"\n        poll_for_token()\n        element = driver.find_element(By.ID, cookie_id)\n        set_sub(cookie_id, json_value)\n        AppHarness.expect(lambda: element.text == json_value)\n\n        driver.refresh()\n        poll_for_token()\n        element = driver.find_element(By.ID, cookie_id)\n        AppHarness.expect(lambda: element.text == json_value)\n\n    json_dict = '{\"access_token\": \"redacted\", \"refresh_token\": \"redacted\", \"created_at\": 1234567890, \"expires_in\": 3600}'\n    _assert_json_cookie_with_refresh(\"c1\", json_dict)\n\n    json_array = '[\"item1\", \"item2\", \"item3\"]'\n    _assert_json_cookie_with_refresh(\"c2\", json_array)\n\n    complex_json = '{\"user\": {\"id\": 123, \"name\": \"test\"}, \"settings\": {\"theme\": \"dark\", \"notifications\": true}, \"data\": [1, 2, 3]}'\n    _assert_json_cookie_with_refresh(\"c1\", complex_json)\n\n    json_with_escapes = (\n        '{\"message\": \"Hello \\\\\"world\\\\\"\", \"path\": \"/api/v1\", \"count\": 42}'\n    )\n    _assert_json_cookie_with_refresh(\"c2\", json_with_escapes)\n\n    empty_json_obj = \"{}\"\n    _assert_json_cookie_with_refresh(\"c1\", empty_json_obj)\n\n    empty_json_array = \"[]\"\n    _assert_json_cookie_with_refresh(\"c2\", empty_json_array)\n"
  },
  {
    "path": "tests/integration/test_component_state.py",
    "content": "\"\"\"Test that per-component state scaffold works and operates independently.\"\"\"\n\nfrom collections.abc import Generator\n\nimport pytest\nfrom selenium.webdriver.common.by import By\n\nfrom reflex.state import State, _substate_key\nfrom reflex.testing import AppHarness\n\nfrom . import utils\n\n\ndef ComponentStateApp():\n    \"\"\"App using per component state.\"\"\"\n    from typing import Generic, TypeVar\n\n    import reflex as rx\n\n    E = TypeVar(\"E\")\n\n    class MultiCounter(rx.ComponentState, Generic[E]):\n        \"\"\"ComponentState style.\"\"\"\n\n        count: int = 0\n        _be: E\n        _be_int: int\n        _be_str: str = \"42\"\n\n        @rx.event\n        def increment(self):\n            self.count += 1\n            self._be = self.count  # pyright: ignore [reportAttributeAccessIssue]\n\n        @classmethod\n        def get_component(cls, *children, **props):\n            return rx.vstack(\n                *children,\n                rx.heading(cls.count, id=f\"count-{props.get('id', 'default')}\"),\n                rx.button(\n                    \"Increment\",\n                    on_click=cls.increment,\n                    id=f\"button-{props.get('id', 'default')}\",\n                ),\n                **props,\n            )\n\n    def multi_counter_func(id: str = \"default\") -> rx.Component:\n        \"\"\"Local-substate style.\n\n        Args:\n            id: identifier for this instance\n\n        Returns:\n            A new instance of the component with its own state.\n        \"\"\"\n\n        class _Counter(rx.State):\n            count: int = 0\n\n            @rx.event\n            def increment(self):\n                self.count += 1\n\n        return rx.vstack(\n            rx.heading(_Counter.count, id=f\"count-{id}\"),\n            rx.button(\n                \"Increment\",\n                on_click=_Counter.increment,\n                id=f\"button-{id}\",\n            ),\n            State=_Counter,\n        )\n\n    app = rx.App()  # noqa: F841\n\n    @rx.page()\n    def index():\n        mc_a = MultiCounter.create(id=\"a\")\n        mc_b = MultiCounter.create(id=\"b\")\n        mc_c = multi_counter_func(id=\"c\")\n        mc_d = multi_counter_func(id=\"d\")\n        assert mc_a.State != mc_b.State\n        assert mc_c.State != mc_d.State\n        return rx.vstack(\n            mc_a,\n            mc_b,\n            mc_c,\n            mc_d,\n            rx.button(\n                \"Inc A\",\n                on_click=mc_a.State.increment,  # pyright: ignore [reportAttributeAccessIssue, reportOptionalMemberAccess]\n                id=\"inc-a\",\n            ),\n            rx.text(\n                mc_a.State.get_name() if mc_a.State is not None else \"\",\n                id=\"a_state_name\",\n            ),\n            rx.text(\n                mc_b.State.get_name() if mc_b.State is not None else \"\",\n                id=\"b_state_name\",\n            ),\n        )\n\n\n@pytest.fixture\ndef component_state_app(tmp_path) -> Generator[AppHarness, None, None]:\n    \"\"\"Start ComponentStateApp app at tmp_path via AppHarness.\n\n    Args:\n        tmp_path: pytest tmp_path fixture\n\n    Yields:\n        running AppHarness instance\n    \"\"\"\n    with AppHarness.create(\n        root=tmp_path,\n        app_source=ComponentStateApp,\n    ) as harness:\n        yield harness\n\n\n@pytest.mark.asyncio\nasync def test_component_state_app(component_state_app: AppHarness):\n    \"\"\"Increment counters independently.\n\n    Args:\n        component_state_app: harness for ComponentStateApp app\n    \"\"\"\n    assert component_state_app.app_instance is not None, \"app is not running\"\n    driver = component_state_app.frontend()\n\n    ss = utils.SessionStorage(driver)\n    assert AppHarness._poll_for(lambda: ss.get(\"token\") is not None), \"token not found\"\n    root_state_token = _substate_key(ss.get(\"token\"), State)\n\n    count_a = driver.find_element(By.ID, \"count-a\")\n    count_b = driver.find_element(By.ID, \"count-b\")\n    button_a = driver.find_element(By.ID, \"button-a\")\n    button_b = driver.find_element(By.ID, \"button-b\")\n    button_inc_a = driver.find_element(By.ID, \"inc-a\")\n\n    # Check that backend vars in mixins are okay\n    a_state_name = driver.find_element(By.ID, \"a_state_name\").text\n    b_state_name = driver.find_element(By.ID, \"b_state_name\").text\n    root_state = await component_state_app.get_state(root_state_token)\n    a_state = root_state.substates[a_state_name]\n    b_state = root_state.substates[b_state_name]\n    assert a_state._backend_vars == a_state.backend_vars\n    assert a_state._backend_vars == b_state._backend_vars\n    assert a_state._backend_vars[\"_be\"] is None\n    assert a_state._backend_vars[\"_be_int\"] == 0\n    assert a_state._backend_vars[\"_be_str\"] == \"42\"\n\n    assert count_a.text == \"0\"\n\n    button_a.click()\n    assert component_state_app.poll_for_content(count_a, exp_not_equal=\"0\") == \"1\"\n\n    button_a.click()\n    assert component_state_app.poll_for_content(count_a, exp_not_equal=\"1\") == \"2\"\n\n    button_inc_a.click()\n    assert component_state_app.poll_for_content(count_a, exp_not_equal=\"2\") == \"3\"\n\n    root_state = await component_state_app.get_state(root_state_token)\n    a_state = root_state.substates[a_state_name]\n    b_state = root_state.substates[b_state_name]\n    assert a_state._backend_vars != a_state.backend_vars\n    assert a_state._be == a_state._backend_vars[\"_be\"] == 3  # pyright: ignore[reportAttributeAccessIssue]\n    assert b_state._be is None  # pyright: ignore[reportAttributeAccessIssue]\n    assert b_state._backend_vars[\"_be\"] is None\n\n    assert count_b.text == \"0\"\n\n    button_b.click()\n    assert component_state_app.poll_for_content(count_b, exp_not_equal=\"0\") == \"1\"\n\n    button_b.click()\n    assert component_state_app.poll_for_content(count_b, exp_not_equal=\"1\") == \"2\"\n\n    root_state = await component_state_app.get_state(root_state_token)\n    a_state = root_state.substates[a_state_name]\n    b_state = root_state.substates[b_state_name]\n    assert b_state._backend_vars != b_state.backend_vars\n    assert b_state._be == b_state._backend_vars[\"_be\"] == 2  # pyright: ignore[reportAttributeAccessIssue]\n\n    # Check locally-defined substate style\n    count_c = driver.find_element(By.ID, \"count-c\")\n    count_d = driver.find_element(By.ID, \"count-d\")\n    button_c = driver.find_element(By.ID, \"button-c\")\n    button_d = driver.find_element(By.ID, \"button-d\")\n\n    assert component_state_app.poll_for_content(count_c, exp_not_equal=\"\") == \"0\"\n    assert component_state_app.poll_for_content(count_d, exp_not_equal=\"\") == \"0\"\n    button_c.click()\n    assert component_state_app.poll_for_content(count_c, exp_not_equal=\"0\") == \"1\"\n    assert component_state_app.poll_for_content(count_d, exp_not_equal=\"\") == \"0\"\n    button_c.click()\n    assert component_state_app.poll_for_content(count_c, exp_not_equal=\"1\") == \"2\"\n    assert component_state_app.poll_for_content(count_d, exp_not_equal=\"\") == \"0\"\n    button_d.click()\n    assert component_state_app.poll_for_content(count_c, exp_not_equal=\"1\") == \"2\"\n    assert component_state_app.poll_for_content(count_d, exp_not_equal=\"0\") == \"1\"\n"
  },
  {
    "path": "tests/integration/test_computed_vars.py",
    "content": "\"\"\"Test computed vars.\"\"\"\n\nfrom __future__ import annotations\n\nimport asyncio\nfrom collections.abc import Generator\n\nimport pytest\nfrom selenium.webdriver.common.by import By\n\nfrom reflex.testing import DEFAULT_TIMEOUT, AppHarness, WebDriver\n\n\ndef ComputedVars():\n    \"\"\"Test app for computed vars.\"\"\"\n    import reflex as rx\n\n    class StateMixin(rx.State, mixin=True):\n        pass\n\n    class State(StateMixin, rx.State):\n        count: int = 0\n\n        # cached var with dep on count\n        @rx.var(interval=15)\n        def count1(self) -> int:\n            return self.count\n\n        # cached backend var with dep on count\n        @rx.var(interval=15, backend=True)\n        def count1_backend(self) -> int:\n            return self.count\n\n        # same as above but implicit backend with `_` prefix\n        @rx.var(interval=15)\n        def _count1_backend(self) -> int:\n            return self.count\n\n        # explicit disabled auto_deps\n        @rx.var(interval=15, auto_deps=False)\n        def count3(self) -> int:\n            # this will not add deps, because auto_deps is False\n            print(self.count1)\n\n            return self.count\n\n        # explicit dependency on count var\n        @rx.var(deps=[\"count\"], auto_deps=False)\n        def depends_on_count(self) -> int:\n            return self.count\n\n        # explicit dependency on count1 var\n        @rx.var(deps=[count1], auto_deps=False)\n        def depends_on_count1(self) -> int:\n            return self.count\n\n        @rx.var(\n            deps=[count3],\n            auto_deps=False,\n        )\n        def depends_on_count3(self) -> int:\n            return self.count\n\n        # special floats should be properly decoded on the frontend\n        @rx.var(cache=True, initial_value=[])\n        def special_floats(self) -> list[float]:\n            return [42.9, float(\"nan\"), float(\"inf\"), float(\"-inf\")]\n\n        @rx.event\n        def increment(self):\n            self.count += 1\n\n        @rx.event\n        def mark_dirty(self):\n            self._mark_dirty()\n\n    assert State.backend_vars == {\"_reflex_internal_links\": None}\n\n    def index() -> rx.Component:\n        return rx.center(\n            rx.vstack(\n                rx.input(\n                    id=\"token\",\n                    value=State.router.session.client_token,\n                    is_read_only=True,\n                ),\n                rx.button(\"Increment\", on_click=State.increment, id=\"increment\"),\n                rx.button(\"Do nothing\", on_click=State.mark_dirty, id=\"mark_dirty\"),\n                rx.text(\"count:\"),\n                rx.text(State.count, id=\"count\"),\n                rx.text(\"count1:\"),\n                rx.text(State.count1, id=\"count1\"),\n                rx.text(\"count1_backend:\"),\n                rx.text(State.count1_backend, id=\"count1_backend\"),\n                rx.text(\"_count1_backend:\"),\n                rx.text(State._count1_backend, id=\"_count1_backend\"),\n                rx.text(\"count3:\"),\n                rx.text(State.count3, id=\"count3\"),\n                rx.text(\"depends_on_count:\"),\n                rx.text(\n                    State.depends_on_count,\n                    id=\"depends_on_count\",\n                ),\n                rx.text(\"depends_on_count1:\"),\n                rx.text(\n                    State.depends_on_count1,\n                    id=\"depends_on_count1\",\n                ),\n                rx.text(\"depends_on_count3:\"),\n                rx.text(\n                    State.depends_on_count3,\n                    id=\"depends_on_count3\",\n                ),\n                rx.text(\"special_floats:\"),\n                rx.text(\n                    State.special_floats.join(\", \"),\n                    id=\"special_floats\",\n                ),\n            ),\n        )\n\n    app = rx.App()\n    app.add_page(index)\n\n\n@pytest.fixture(scope=\"module\")\ndef computed_vars(\n    tmp_path_factory: pytest.TempPathFactory,\n) -> Generator[AppHarness, None, None]:\n    \"\"\"Start ComputedVars app at tmp_path via AppHarness.\n\n    Args:\n        tmp_path_factory: pytest tmp_path_factory fixture\n\n    Yields:\n        running AppHarness instance\n    \"\"\"\n    with AppHarness.create(\n        root=tmp_path_factory.mktemp(\"computed_vars\"),\n        app_source=ComputedVars,\n    ) as harness:\n        yield harness\n\n\n@pytest.fixture\ndef driver(computed_vars: AppHarness) -> Generator[WebDriver, None, None]:\n    \"\"\"Get an instance of the browser open to the computed_vars app.\n\n    Args:\n        computed_vars: harness for ComputedVars app\n\n    Yields:\n        WebDriver instance.\n    \"\"\"\n    assert computed_vars.app_instance is not None, \"app is not running\"\n    driver = computed_vars.frontend()\n    try:\n        yield driver\n    finally:\n        driver.quit()\n\n\n@pytest.fixture\ndef token(computed_vars: AppHarness, driver: WebDriver) -> str:\n    \"\"\"Get a function that returns the active token.\n\n    Args:\n        computed_vars: harness for ComputedVars app.\n        driver: WebDriver instance.\n\n    Returns:\n        The token for the connected client\n    \"\"\"\n    assert computed_vars.app_instance is not None\n    token_input = AppHarness.poll_for_or_raise_timeout(\n        lambda: driver.find_element(By.ID, \"token\")\n    )\n\n    # wait for the backend connection to send the token\n    token = computed_vars.poll_for_value(token_input, timeout=DEFAULT_TIMEOUT * 2)\n    assert token is not None\n\n    return token\n\n\n@pytest.mark.asyncio\nasync def test_computed_vars(\n    computed_vars: AppHarness,\n    driver: WebDriver,\n    token: str,\n):\n    \"\"\"Test that computed vars are working as expected.\n\n    Args:\n        computed_vars: harness for ComputedVars app.\n        driver: WebDriver instance.\n        token: The token for the connected client.\n    \"\"\"\n    assert computed_vars.app_instance is not None\n\n    state_name = computed_vars.get_state_name(\"_state\")\n    full_state_name = computed_vars.get_full_state_name([\"_state\"])\n    token = f\"{token}_{full_state_name}\"\n    state = (await computed_vars.get_state(token)).substates[state_name]\n    assert state is not None\n    assert state.count1_backend == 0  # pyright: ignore[reportAttributeAccessIssue]\n    assert state._count1_backend == 0  # pyright: ignore[reportAttributeAccessIssue]\n\n    # test that backend var is not rendered\n    count1_backend = driver.find_element(By.ID, \"count1_backend\")\n    assert count1_backend\n    assert count1_backend.text == \"\"\n    count1_backend_ = driver.find_element(By.ID, \"_count1_backend\")\n    assert count1_backend_\n    assert count1_backend_.text == \"\"\n\n    count = driver.find_element(By.ID, \"count\")\n    assert count\n    assert count.text == \"0\"\n\n    count1 = driver.find_element(By.ID, \"count1\")\n    assert count1\n    assert count1.text == \"0\"\n\n    count3 = driver.find_element(By.ID, \"count3\")\n    assert count3\n    assert count3.text == \"0\"\n\n    depends_on_count = driver.find_element(By.ID, \"depends_on_count\")\n    assert depends_on_count\n    assert depends_on_count.text == \"0\"\n\n    depends_on_count1 = driver.find_element(By.ID, \"depends_on_count1\")\n    assert depends_on_count1\n    assert depends_on_count1.text == \"0\"\n\n    depends_on_count3 = driver.find_element(By.ID, \"depends_on_count3\")\n    assert depends_on_count3\n    assert depends_on_count3.text == \"0\"\n\n    special_floats = driver.find_element(By.ID, \"special_floats\")\n    assert special_floats\n    assert special_floats.text == \"42.9, NaN, Infinity, -Infinity\"\n\n    increment = driver.find_element(By.ID, \"increment\")\n    assert increment.is_enabled()\n\n    mark_dirty = driver.find_element(By.ID, \"mark_dirty\")\n    assert mark_dirty.is_enabled()\n\n    mark_dirty.click()\n\n    increment.click()\n    assert computed_vars.poll_for_content(count, timeout=2, exp_not_equal=\"0\") == \"1\"\n    assert computed_vars.poll_for_content(count1, timeout=2, exp_not_equal=\"0\") == \"1\"\n    assert (\n        computed_vars.poll_for_content(depends_on_count, timeout=2, exp_not_equal=\"0\")\n        == \"1\"\n    )\n    state = (await computed_vars.get_state(token)).substates[state_name]\n    assert state is not None\n    assert state.count1_backend == 1  # pyright: ignore[reportAttributeAccessIssue]\n    assert count1_backend.text == \"\"\n    assert state._count1_backend == 1  # pyright: ignore[reportAttributeAccessIssue]\n    assert count1_backend_.text == \"\"\n\n    mark_dirty.click()\n    with pytest.raises(TimeoutError):\n        _ = computed_vars.poll_for_content(count3, timeout=5, exp_not_equal=\"0\")\n\n    await asyncio.sleep(10)\n    assert count3.text == \"0\"\n    assert depends_on_count3.text == \"0\"\n    mark_dirty.click()\n    assert computed_vars.poll_for_content(count3, timeout=2, exp_not_equal=\"0\") == \"1\"\n    assert depends_on_count3.text == \"1\"\n"
  },
  {
    "path": "tests/integration/test_connection_banner.py",
    "content": "\"\"\"Test case for displaying the connection banner when the websocket drops.\"\"\"\n\nimport pickle\nfrom collections.abc import Generator\n\nimport pytest\nfrom selenium.common.exceptions import NoSuchElementException\nfrom selenium.webdriver.common.by import By\n\nfrom reflex import constants\nfrom reflex.environment import environment\nfrom reflex.istate.manager.redis import StateManagerRedis\nfrom reflex.testing import AppHarness, WebDriver\nfrom reflex.utils.token_manager import RedisTokenManager, SocketRecord\n\nfrom .utils import SessionStorage\n\n\ndef ConnectionBanner():\n    \"\"\"App with a connection banner.\"\"\"\n    import asyncio\n\n    import reflex as rx\n\n    class State(rx.State):\n        foo: int = 0\n\n        @rx.event\n        def set_foo(self, foo: int):\n            self.foo = foo\n\n        @rx.event\n        async def delay(self):\n            await asyncio.sleep(5)\n\n    def index():\n        return rx.vstack(\n            rx.text(\"Hello World\"),\n            rx.input(value=State.foo, read_only=True, id=\"counter\"),\n            rx.button(\n                \"Increment\",\n                id=\"increment\",\n                on_click=State.set_foo(State.foo + 1),\n            ),\n            rx.button(\"Delay\", id=\"delay\", on_click=State.delay),\n        )\n\n    app = rx.App()\n    app.add_page(index)\n\n\n@pytest.fixture(\n    params=[constants.CompileContext.RUN, constants.CompileContext.DEPLOY],\n    ids=[\"compile_context_run\", \"compile_context_deploy\"],\n)\ndef simulate_compile_context(request) -> constants.CompileContext:\n    \"\"\"Fixture to simulate reflex cloud deployment.\n\n    Args:\n        request: pytest request fixture.\n\n    Returns:\n        The context to run the app with.\n    \"\"\"\n    return request.param\n\n\n@pytest.fixture\ndef connection_banner(\n    tmp_path,\n    simulate_compile_context: constants.CompileContext,\n) -> Generator[AppHarness, None, None]:\n    \"\"\"Start ConnectionBanner app at tmp_path via AppHarness.\n\n    Args:\n        tmp_path: pytest tmp_path fixture\n        simulate_compile_context: Which context to run the app with.\n\n    Yields:\n        running AppHarness instance\n    \"\"\"\n    environment.REFLEX_COMPILE_CONTEXT.set(simulate_compile_context)\n\n    with AppHarness.create(\n        root=tmp_path,\n        app_source=ConnectionBanner,\n        app_name=(\n            \"connection_banner_reflex_cloud\"\n            if simulate_compile_context == constants.CompileContext.DEPLOY\n            else \"connection_banner\"\n        ),\n    ) as harness:\n        yield harness\n\n\nCONNECTION_ERROR_XPATH = \"//*[ contains(text(), 'Cannot connect to server') ]\"\n\n\ndef has_error_modal(driver: WebDriver) -> bool:\n    \"\"\"Check if the connection error modal is displayed.\n\n    Args:\n        driver: Selenium webdriver instance.\n\n    Returns:\n        True if the modal is displayed, False otherwise.\n    \"\"\"\n    try:\n        driver.find_element(By.XPATH, CONNECTION_ERROR_XPATH)\n    except NoSuchElementException:\n        return False\n    else:\n        return True\n\n\ndef has_cloud_banner(driver: WebDriver) -> bool:\n    \"\"\"Check if the cloud banner is displayed.\n\n    Args:\n        driver: Selenium webdriver instance.\n\n    Returns:\n        True if the banner is displayed, False otherwise.\n    \"\"\"\n    try:\n        driver.find_element(By.XPATH, \"//*[ contains(text(), 'This app is paused') ]\")\n    except NoSuchElementException:\n        return False\n    else:\n        return True\n\n\ndef _assert_token(connection_banner, driver) -> str:\n    \"\"\"Poll for backend to be up.\n\n    Args:\n        connection_banner: AppHarness instance.\n        driver: Selenium webdriver instance.\n\n    Returns:\n        The token if found, raises an assertion error otherwise.\n    \"\"\"\n    ss = SessionStorage(driver)\n    assert connection_banner._poll_for(lambda: ss.get(\"token\") is not None), (\n        \"token not found\"\n    )\n    return ss.get(\"token\")\n\n\n@pytest.mark.asyncio\nasync def test_connection_banner(connection_banner: AppHarness):\n    \"\"\"Test that the connection banner is displayed when the websocket drops.\n\n    Args:\n        connection_banner: AppHarness instance.\n    \"\"\"\n    assert connection_banner.app_instance is not None\n    assert connection_banner.backend is not None\n    driver = connection_banner.frontend()\n\n    token = _assert_token(connection_banner, driver)\n    AppHarness.expect(lambda: not has_error_modal(driver))\n\n    # Check that the token association was established.\n    app_token_manager = connection_banner.token_manager()\n    assert token in app_token_manager.token_to_sid\n    sid_before = app_token_manager.token_to_sid[token]\n    if isinstance(connection_banner.state_manager, StateManagerRedis):\n        assert isinstance(app_token_manager, RedisTokenManager)\n        assert await connection_banner.state_manager.redis.get(\n            app_token_manager._get_redis_key(token)\n        ) == pickle.dumps(\n            SocketRecord(instance_id=app_token_manager.instance_id, sid=sid_before)\n        )\n\n    delay_button = driver.find_element(By.ID, \"delay\")\n    increment_button = driver.find_element(By.ID, \"increment\")\n    counter_element = driver.find_element(By.ID, \"counter\")\n\n    # Increment the counter\n    increment_button.click()\n    assert connection_banner.poll_for_value(counter_element, exp_not_equal=\"0\") == \"1\"\n\n    # Start an long event before killing the backend, to mark event_processing=true\n    delay_button.click()\n\n    # Get the backend port\n    backend_port = connection_banner._poll_for_servers().getsockname()[1]\n\n    # Kill the backend\n    connection_banner.backend.should_exit = True\n    if connection_banner.backend_thread is not None:\n        connection_banner.backend_thread.join()\n\n    # Error modal should now be displayed\n    AppHarness.expect(lambda: has_error_modal(driver))\n\n    # The token association should have been removed when the server exited.\n    assert token not in app_token_manager.token_to_sid\n    if isinstance(connection_banner.state_manager, StateManagerRedis):\n        assert isinstance(app_token_manager, RedisTokenManager)\n        assert (\n            await connection_banner.state_manager.redis.get(\n                app_token_manager._get_redis_key(token)\n            )\n            is None\n        )\n\n    # Increment the counter with backend down\n    increment_button.click()\n    assert connection_banner.poll_for_value(counter_element, exp_not_equal=\"0\") == \"1\"\n\n    # Bring the backend back up\n    connection_banner._start_backend(port=backend_port)\n\n    # Create a new StateManager to avoid async loop affinity issues w/ redis\n    await connection_banner._reset_backend_state_manager()\n\n    # Banner should be gone now\n    AppHarness.expect(lambda: not has_error_modal(driver))\n\n    # After reconnecting, the token association should be re-established.\n    app_token_manager = connection_banner.token_manager()\n    # Make sure the new connection has a different websocket sid.\n    sid_after = app_token_manager.token_to_sid[token]\n    assert sid_before != sid_after\n    if isinstance(connection_banner.state_manager, StateManagerRedis):\n        assert isinstance(app_token_manager, RedisTokenManager)\n        assert await connection_banner.state_manager.redis.get(\n            app_token_manager._get_redis_key(token)\n        ) == pickle.dumps(\n            SocketRecord(instance_id=app_token_manager.instance_id, sid=sid_after)\n        )\n\n    # Count should have incremented after coming back up\n    assert connection_banner.poll_for_value(counter_element, exp_not_equal=\"1\") == \"2\"\n\n\ndef test_cloud_banner(\n    connection_banner: AppHarness, simulate_compile_context: constants.CompileContext\n):\n    \"\"\"Test that the connection banner is displayed when the websocket drops.\n\n    Args:\n        connection_banner: AppHarness instance.\n        simulate_compile_context: Which context to set for the app.\n    \"\"\"\n    assert connection_banner.app_instance is not None\n    assert connection_banner.backend is not None\n    driver = connection_banner.frontend()\n\n    driver.add_cookie({\"name\": \"backend-enabled\", \"value\": \"truly\"})\n    driver.refresh()\n    _assert_token(connection_banner, driver)\n    AppHarness.expect(lambda: not has_cloud_banner(driver))\n\n    driver.add_cookie({\"name\": \"backend-enabled\", \"value\": \"false\"})\n    driver.refresh()\n    if simulate_compile_context == constants.CompileContext.DEPLOY:\n        AppHarness.expect(lambda: has_cloud_banner(driver))\n    else:\n        _assert_token(connection_banner, driver)\n        AppHarness.expect(lambda: not has_cloud_banner(driver))\n\n    driver.delete_cookie(\"backend-enabled\")\n    driver.refresh()\n    _assert_token(connection_banner, driver)\n    AppHarness.expect(lambda: not has_cloud_banner(driver))\n"
  },
  {
    "path": "tests/integration/test_deploy_url.py",
    "content": "\"\"\"Integration tests for deploy_url.\"\"\"\n\nfrom __future__ import annotations\n\nfrom collections.abc import Generator\n\nimport pytest\nfrom selenium.webdriver.common.by import By\nfrom selenium.webdriver.remote.webdriver import WebDriver\nfrom selenium.webdriver.support.ui import WebDriverWait\n\nfrom reflex.testing import AppHarness\n\n\ndef DeployUrlSample() -> None:\n    \"\"\"Sample app for testing config deploy_url is correct (in tests).\"\"\"\n    import reflex as rx\n\n    class State(rx.State):\n        @rx.event\n        def goto_self(self):\n            if (deploy_url := rx.config.get_config().deploy_url) is not None:\n                return rx.redirect(deploy_url)\n            return None\n\n    def index():\n        return rx.fragment(\n            rx.button(\"GOTO SELF\", on_click=State.goto_self, id=\"goto_self\")\n        )\n\n    app = rx.App()\n    app.add_page(index)\n\n\n@pytest.fixture(scope=\"module\")\ndef deploy_url_sample(\n    tmp_path_factory: pytest.TempPathFactory,\n) -> Generator[AppHarness, None, None]:\n    \"\"\"AppHarness fixture for testing deploy_url.\n\n    Args:\n        tmp_path_factory: pytest fixture for creating temporary directories.\n\n    Yields:\n        AppHarness: An AppHarness instance.\n    \"\"\"\n    with AppHarness.create(\n        root=tmp_path_factory.mktemp(\"deploy_url_sample\"),\n        app_source=DeployUrlSample,\n    ) as harness:\n        yield harness\n\n\n@pytest.fixture\ndef driver(deploy_url_sample: AppHarness) -> Generator[WebDriver, None, None]:\n    \"\"\"WebDriver fixture for testing deploy_url.\n\n    Args:\n        deploy_url_sample: AppHarness fixture for testing deploy_url.\n\n    Yields:\n        WebDriver: A WebDriver instance.\n    \"\"\"\n    assert deploy_url_sample.app_instance is not None, \"app is not running\"\n    driver = deploy_url_sample.frontend()\n    try:\n        yield driver\n    finally:\n        driver.quit()\n\n\ndef test_deploy_url(deploy_url_sample: AppHarness, driver: WebDriver) -> None:\n    \"\"\"Test deploy_url is correct.\n\n    Args:\n        deploy_url_sample: AppHarness fixture for testing deploy_url.\n        driver: WebDriver fixture for testing deploy_url.\n    \"\"\"\n    import reflex as rx\n\n    deploy_url = rx.config.get_config().deploy_url\n    assert deploy_url is not None\n    assert deploy_url != \"http://localhost:3000\"\n    assert deploy_url == deploy_url_sample.frontend_url\n    driver.get(deploy_url)\n    assert driver.current_url.removesuffix(\"/\") == deploy_url.removesuffix(\"/\")\n\n\ndef test_deploy_url_in_app(deploy_url_sample: AppHarness, driver: WebDriver) -> None:\n    \"\"\"Test deploy_url is correct in app.\n\n    Args:\n        deploy_url_sample: AppHarness fixture for testing deploy_url.\n        driver: WebDriver fixture for testing deploy_url.\n    \"\"\"\n    driver.implicitly_wait(10)\n    driver.find_element(By.ID, \"goto_self\").click()\n\n    WebDriverWait(driver, 10).until(\n        lambda driver: (\n            deploy_url_sample.frontend_url\n            and driver.current_url.removesuffix(\"/\")\n            == deploy_url_sample.frontend_url.removesuffix(\"/\")\n        )\n    )\n"
  },
  {
    "path": "tests/integration/test_dynamic_components.py",
    "content": "\"\"\"Integration tests for var operations.\"\"\"\n\nfrom collections.abc import Generator\nfrom typing import TypeVar\n\nimport pytest\nfrom selenium.webdriver.common.by import By\n\nfrom reflex.testing import AppHarness\n\n# pyright: reportOptionalMemberAccess=false, reportGeneralTypeIssues=false, reportUnknownMemberType=false\n\n\ndef DynamicComponents():\n    \"\"\"App with var operations.\"\"\"\n    import reflex as rx\n\n    class DynamicComponentsState(rx.State):\n        value: int = 10\n\n        button: rx.Component = rx.button(\n            \"Click me\",\n            custom_attrs={\n                \"id\": \"button\",\n            },\n        )\n\n        @rx.event\n        def got_clicked(self):\n            self.button = rx.button(\n                \"Clicked\",\n                custom_attrs={\n                    \"id\": \"button\",\n                },\n            )\n\n        @rx.var\n        def client_token_component(self) -> rx.Component:\n            return rx.vstack(\n                rx.el.input(\n                    custom_attrs={\n                        \"id\": \"token\",\n                    },\n                    value=self.router.session.client_token,\n                    is_read_only=True,\n                ),\n                rx.button(\n                    \"Update\",\n                    custom_attrs={\n                        \"id\": \"update\",\n                    },\n                    on_click=DynamicComponentsState.got_clicked,\n                ),\n            )\n\n    app = rx.App()\n\n    def factorial(n: int) -> int:\n        if n == 0:\n            return 1\n        return n * factorial(n - 1)\n\n    @app.add_page\n    def index():\n        return rx.vstack(\n            DynamicComponentsState.client_token_component,\n            DynamicComponentsState.button,\n            rx.text(\n                DynamicComponentsState._evaluate(\n                    lambda state: factorial(state.value), of_type=int\n                ),\n                id=\"factorial\",\n            ),\n        )\n\n\n@pytest.fixture(scope=\"module\")\ndef dynamic_components(tmp_path_factory) -> Generator[AppHarness, None, None]:\n    \"\"\"Start VarOperations app at tmp_path via AppHarness.\n\n    Args:\n        tmp_path_factory: pytest tmp_path_factory fixture\n\n    Yields:\n        running AppHarness instance\n    \"\"\"\n    with AppHarness.create(\n        root=tmp_path_factory.mktemp(\"dynamic_components\"),\n        app_source=DynamicComponents,\n    ) as harness:\n        assert harness.app_instance is not None, \"app is not running\"\n        yield harness\n\n\nT = TypeVar(\"T\")\n\n\n@pytest.fixture\ndef driver(dynamic_components: AppHarness):\n    \"\"\"Get an instance of the browser open to the dynamic components app.\n\n    Args:\n        dynamic_components: AppHarness for the dynamic components\n\n    Yields:\n        WebDriver instance.\n    \"\"\"\n    driver = dynamic_components.frontend()\n    try:\n        token_input = AppHarness.poll_for_or_raise_timeout(\n            lambda: driver.find_element(By.ID, \"token\")\n        )\n        # wait for the backend connection to send the token\n        token = dynamic_components.poll_for_value(token_input)\n        assert token is not None\n\n        yield driver\n    finally:\n        driver.quit()\n\n\ndef test_dynamic_components(driver, dynamic_components: AppHarness):\n    \"\"\"Test that the var operations produce the right results.\n\n    Args:\n        driver: selenium WebDriver open to the app\n        dynamic_components: AppHarness for the dynamic components\n    \"\"\"\n    button = AppHarness.poll_for_or_raise_timeout(\n        lambda: driver.find_element(By.ID, \"button\")\n    )\n    assert button.text == \"Click me\"\n\n    update_button = driver.find_element(By.ID, \"update\")\n    assert update_button\n    update_button.click()\n\n    assert (\n        dynamic_components.poll_for_content(button, exp_not_equal=\"Click me\")\n        == \"Clicked\"\n    )\n\n    factorial = AppHarness.poll_for_or_raise_timeout(\n        lambda: driver.find_element(By.ID, \"factorial\")\n    )\n    assert factorial.text == \"3628800\"\n"
  },
  {
    "path": "tests/integration/test_dynamic_routes.py",
    "content": "\"\"\"Integration tests for dynamic route page behavior.\"\"\"\n\nfrom __future__ import annotations\n\nimport asyncio\nfrom collections.abc import Callable, Coroutine, Generator\nfrom urllib.parse import urlsplit\n\nimport pytest\nfrom selenium.webdriver.common.by import By\n\nfrom reflex.testing import AppHarness, WebDriver\n\nfrom .utils import poll_for_navigation\n\n\ndef DynamicRoute():\n    \"\"\"App for testing dynamic routes.\"\"\"\n    import reflex as rx\n\n    class DynamicState(rx.State):\n        order: list[str] = []\n\n        @rx.event\n        def on_load(self):\n            page_data = f\"{self.router.page.path}-{self.page_id or 'no page id'}\"  # pyright: ignore[reportAttributeAccessIssue]\n            print(f\"on_load: {page_data}\")\n            self.order.append(page_data)\n\n        @rx.event\n        def on_load_redir(self):\n            query_params = self.router.page.params\n            page_data = f\"on_load_redir-{query_params}\"\n            print(f\"on_load_redir: {page_data}\")\n            self.order.append(page_data)\n            return rx.redirect(f\"/page/{query_params['page_id']}\")\n\n        @rx.event\n        def on_load_static(self):\n            print(\"on_load_static\")\n            self.order.append(\"on-load-static\")\n\n        @rx.var\n        def next_page(self) -> str:\n            try:\n                return str(int(self.page_id) + 1)  # pyright: ignore[reportAttributeAccessIssue]\n            except ValueError:\n                return \"0\"\n\n    def index():\n        return rx.fragment(\n            rx.input(\n                value=DynamicState.router.session.client_token,\n                read_only=True,\n                id=\"token\",\n            ),\n            rx.input(value=rx.State.page_id, read_only=True, id=\"page_id\"),  # pyright: ignore [reportAttributeAccessIssue]\n            rx.input(\n                value=DynamicState.router.page.raw_path,\n                read_only=True,\n                id=\"raw_path\",\n            ),\n            rx.link(\"index\", href=\"/\", id=\"link_index\"),\n            rx.link(\"page_X\", href=\"/static/x\", id=\"link_page_x\"),\n            rx.link(\n                \"next\",\n                href=\"/page/\" + DynamicState.next_page,\n                id=\"link_page_next\",\n            ),\n            rx.link(\"missing\", href=\"/missing\", id=\"link_missing\"),\n            rx.list(  # pyright: ignore [reportAttributeAccessIssue]\n                rx.foreach(\n                    DynamicState.order,  # pyright: ignore [reportAttributeAccessIssue]\n                    lambda i: rx.list_item(rx.text(i)),\n                ),\n            ),\n        )\n\n    class ArgState(rx.State):\n        \"\"\"The app state.\"\"\"\n\n        @rx.var(cache=False)\n        def arg(self) -> int:\n            return int(self.arg_str or 0)  # pyright: ignore[reportAttributeAccessIssue]\n\n    class ArgSubState(ArgState):\n        @rx.var\n        def cached_arg(self) -> int:\n            return self.arg\n\n        @rx.var\n        def cached_arg_str(self) -> str:\n            return self.arg_str  # pyright: ignore[reportAttributeAccessIssue]\n\n    @rx.page(route=\"/arg/[arg_str]\")\n    def arg() -> rx.Component:\n        return rx.vstack(\n            rx.input(\n                value=DynamicState.router.session.client_token,\n                read_only=True,\n                id=\"token\",\n            ),\n            rx.data_list.root(\n                rx.data_list.item(\n                    rx.data_list.label(\"rx.State.arg_str (dynamic)\"),\n                    rx.data_list.value(rx.State.arg_str, id=\"state-arg_str\"),  # pyright: ignore [reportAttributeAccessIssue]\n                ),\n                rx.data_list.item(\n                    rx.data_list.label(\"ArgState.arg_str (dynamic) (inherited)\"),\n                    rx.data_list.value(ArgState.arg_str, id=\"argstate-arg_str\"),  # pyright: ignore [reportAttributeAccessIssue]\n                ),\n                rx.data_list.item(\n                    rx.data_list.label(\"ArgState.arg\"),\n                    rx.data_list.value(ArgState.arg, id=\"argstate-arg\"),\n                ),\n                rx.data_list.item(\n                    rx.data_list.label(\"ArgSubState.arg_str (dynamic) (inherited)\"),\n                    rx.data_list.value(ArgSubState.arg_str, id=\"argsubstate-arg_str\"),  # pyright: ignore [reportAttributeAccessIssue]\n                ),\n                rx.data_list.item(\n                    rx.data_list.label(\"ArgSubState.arg (inherited)\"),\n                    rx.data_list.value(ArgSubState.arg, id=\"argsubstate-arg\"),\n                ),\n                rx.data_list.item(\n                    rx.data_list.label(\"ArgSubState.cached_arg\"),\n                    rx.data_list.value(\n                        ArgSubState.cached_arg, id=\"argsubstate-cached_arg\"\n                    ),\n                ),\n                rx.data_list.item(\n                    rx.data_list.label(\"ArgSubState.cached_arg_str\"),\n                    rx.data_list.value(\n                        ArgSubState.cached_arg_str, id=\"argsubstate-cached_arg_str\"\n                    ),\n                ),\n            ),\n            rx.link(\"+\", href=f\"/arg/{ArgState.arg + 1}\", id=\"next-page\"),\n            align=\"center\",\n            height=\"100vh\",\n        )\n\n    @rx.page(route=\"/redirect-page/[page_id]\", on_load=DynamicState.on_load_redir)\n    def redirect_page():\n        return rx.fragment(rx.text(\"redirecting...\"))\n\n    app = rx.App()\n    app.add_page(index, route=\"/page/[page_id]\", on_load=DynamicState.on_load)\n    app.add_page(index, route=\"/page/static\", on_load=DynamicState.on_load_static)\n    app.add_page(index, route=\"/static/x\", on_load=DynamicState.on_load)\n    app.add_page(index)\n    app.add_page(route=\"/404\", on_load=DynamicState.on_load)\n\n\n@pytest.fixture(scope=\"module\")\ndef dynamic_route(\n    app_harness_env: type[AppHarness], tmp_path_factory\n) -> Generator[AppHarness, None, None]:\n    \"\"\"Start DynamicRoute app at tmp_path via AppHarness.\n\n    Args:\n        app_harness_env: either AppHarness (dev) or AppHarnessProd (prod)\n        tmp_path_factory: pytest tmp_path_factory fixture\n\n    Yields:\n        running AppHarness instance\n    \"\"\"\n    with app_harness_env.create(\n        root=tmp_path_factory.mktemp(\"dynamic_route\"),\n        app_name=f\"dynamicroute_{app_harness_env.__name__.lower()}\",\n        app_source=DynamicRoute,\n    ) as harness:\n        yield harness\n\n\n@pytest.fixture\ndef driver(dynamic_route: AppHarness) -> Generator[WebDriver, None, None]:\n    \"\"\"Get an instance of the browser open to the dynamic_route app.\n\n    Args:\n        dynamic_route: harness for DynamicRoute app\n\n    Yields:\n        WebDriver instance.\n    \"\"\"\n    assert dynamic_route.app_instance is not None, \"app is not running\"\n    driver = dynamic_route.frontend()\n    # TODO: drop after flakiness is resolved\n    driver.implicitly_wait(30)\n    try:\n        yield driver\n    finally:\n        driver.quit()\n\n\n@pytest.fixture\ndef token(dynamic_route: AppHarness, driver: WebDriver) -> str:\n    \"\"\"Get the token associated with backend state.\n\n    Args:\n        dynamic_route: harness for DynamicRoute app.\n        driver: WebDriver instance.\n\n    Returns:\n        The token visible in the driver browser.\n    \"\"\"\n    assert dynamic_route.app_instance is not None\n    token_input = AppHarness.poll_for_or_raise_timeout(\n        lambda: driver.find_element(By.ID, \"token\")\n    )\n\n    # wait for the backend connection to send the token\n    token = dynamic_route.poll_for_value(token_input)\n    assert token is not None\n\n    return token\n\n\n@pytest.fixture\ndef poll_for_order(\n    dynamic_route: AppHarness, token: str\n) -> Callable[[list[str]], Coroutine[None, None, None]]:\n    \"\"\"Poll for the order list to match the expected order.\n\n    Args:\n        dynamic_route: harness for DynamicRoute app.\n        token: The token visible in the driver browser.\n\n    Returns:\n        An async function that polls for the order list to match the expected order.\n    \"\"\"\n    dynamic_state_name = dynamic_route.get_state_name(\"_dynamic_state\")\n    dynamic_state_full_name = dynamic_route.get_full_state_name([\"_dynamic_state\"])\n\n    async def _poll_for_order(exp_order: list[str]):\n        async def _backend_state():\n            return await dynamic_route.get_state(f\"{token}_{dynamic_state_full_name}\")\n\n        async def _check():\n            return (await _backend_state()).substates[\n                dynamic_state_name\n            ].order == exp_order  # pyright: ignore[reportAttributeAccessIssue]\n\n        await AppHarness._poll_for_async(_check, timeout=10)\n        assert (\n            list((await _backend_state()).substates[dynamic_state_name].order)  # pyright: ignore[reportAttributeAccessIssue]\n            == exp_order\n        )\n\n    return _poll_for_order\n\n\n@pytest.mark.asyncio\nasync def test_on_load_navigate(\n    dynamic_route: AppHarness,\n    driver: WebDriver,\n    token: str,\n    poll_for_order: Callable[[list[str]], Coroutine[None, None, None]],\n):\n    \"\"\"Click links to navigate between dynamic pages with on_load event.\n\n    Args:\n        dynamic_route: harness for DynamicRoute app.\n        driver: WebDriver instance.\n        token: The token visible in the driver browser.\n        poll_for_order: function that polls for the order list to match the expected order.\n    \"\"\"\n    dynamic_state_full_name = dynamic_route.get_full_state_name([\"_dynamic_state\"])\n    assert dynamic_route.app_instance is not None\n    link = driver.find_element(By.ID, \"link_page_next\")\n    assert link\n\n    exp_order = [f\"/page/[page_id]-{ix}\" for ix in range(10)]\n    # click the link a few times\n    for ix in range(10):\n        # wait for navigation, then assert on url\n        with poll_for_navigation(driver):\n            link.click()\n        assert urlsplit(driver.current_url).path == f\"/page/{ix}\"\n\n        link = AppHarness.poll_for_or_raise_timeout(\n            lambda: driver.find_element(By.ID, \"link_page_next\")\n        )\n        page_id_input = driver.find_element(By.ID, \"page_id\")\n        raw_path_input = driver.find_element(By.ID, \"raw_path\")\n\n        assert link\n        assert page_id_input\n\n        assert dynamic_route.poll_for_value(\n            page_id_input, exp_not_equal=str(ix - 1)\n        ) == str(ix)\n        assert dynamic_route.poll_for_value(raw_path_input) == f\"/page/{ix}\"\n    await poll_for_order(exp_order)\n\n    frontend_url = dynamic_route.frontend_url\n    assert frontend_url\n    frontend_url = frontend_url.removesuffix(\"/\")\n\n    # manually load the next page to trigger client side routing in prod mode\n    exp_order += [\"/page/[page_id]-10\"]\n    with poll_for_navigation(driver):\n        driver.get(f\"{frontend_url}/page/10\")\n    await poll_for_order(exp_order)\n\n    # make sure internal nav still hydrates after redirect\n    exp_order += [\"/page/[page_id]-11\"]\n    link = driver.find_element(By.ID, \"link_page_next\")\n    with poll_for_navigation(driver):\n        link.click()\n    await poll_for_order(exp_order)\n\n    # load same page with a query param and make sure it passes through\n    exp_order += [\"/page/[page_id]-11\"]\n    with poll_for_navigation(driver):\n        driver.get(f\"{driver.current_url}?foo=bar\")\n    await poll_for_order(exp_order)\n    assert (\n        await dynamic_route.get_state(f\"{token}_{dynamic_state_full_name}\")\n    ).router.page.params[\"foo\"] == \"bar\"\n\n    # hit a 404 and ensure we still hydrate\n    exp_order += [\"/404-no page id\"]\n    with poll_for_navigation(driver):\n        driver.get(f\"{frontend_url}/missing\")\n    await poll_for_order(exp_order)\n\n    # browser nav should still trigger hydration\n    exp_order += [\"/page/[page_id]-11\"]\n    with poll_for_navigation(driver):\n        driver.back()\n    await poll_for_order(exp_order)\n\n    # next/link to a 404 and ensure we still hydrate\n    exp_order += [\"/404-no page id\"]\n    link = driver.find_element(By.ID, \"link_missing\")\n    with poll_for_navigation(driver):\n        link.click()\n    await poll_for_order(exp_order)\n\n    # hit a page that redirects back to dynamic page\n    exp_order += [\"on_load_redir-{'foo': 'bar', 'page_id': '0'}\", \"/page/[page_id]-0\"]\n    with poll_for_navigation(driver):\n        driver.get(f\"{frontend_url}/redirect-page/0/?foo=bar\")\n    await poll_for_order(exp_order)\n    # should have redirected back to page 0\n    assert urlsplit(driver.current_url).path.removesuffix(\"/\") == \"/page/0\"\n\n    # hit a static route that would also match the dynamic route\n    exp_order += [\"on-load-static\"]\n    with poll_for_navigation(driver):\n        driver.get(f\"{frontend_url}/page/static\")\n    await poll_for_order(exp_order)\n\n\n@pytest.mark.asyncio\nasync def test_on_load_navigate_non_dynamic(\n    dynamic_route: AppHarness,\n    driver: WebDriver,\n    poll_for_order: Callable[[list[str]], Coroutine[None, None, None]],\n):\n    \"\"\"Click links to navigate between static pages with on_load event.\n\n    Args:\n        dynamic_route: harness for DynamicRoute app.\n        driver: WebDriver instance.\n        poll_for_order: function that polls for the order list to match the expected order.\n    \"\"\"\n    assert dynamic_route.app_instance is not None\n    link = driver.find_element(By.ID, \"link_page_x\")\n    assert link\n\n    with poll_for_navigation(driver):\n        link.click()\n    assert urlsplit(driver.current_url).path.removesuffix(\"/\") == \"/static/x\"\n    await poll_for_order([\"/static/x-no page id\"])\n\n    # go back to the index and navigate back to the static route\n    link = driver.find_element(By.ID, \"link_index\")\n    with poll_for_navigation(driver):\n        link.click()\n    assert urlsplit(driver.current_url).path.removesuffix(\"/\") == \"\"\n\n    link = driver.find_element(By.ID, \"link_page_x\")\n    with poll_for_navigation(driver):\n        link.click()\n    assert urlsplit(driver.current_url).path.removesuffix(\"/\") == \"/static/x\"\n    await poll_for_order([\"/static/x-no page id\", \"/static/x-no page id\"])\n\n    for _ in range(3):\n        link = driver.find_element(By.ID, \"link_page_x\")\n        link.click()\n        assert urlsplit(driver.current_url).path.removesuffix(\"/\") == \"/static/x\"\n    await poll_for_order([\"/static/x-no page id\"] * 5)\n\n\n@pytest.mark.asyncio\nasync def test_render_dynamic_arg(\n    dynamic_route: AppHarness,\n    driver: WebDriver,\n    token: str,\n):\n    \"\"\"Assert that dynamic arg var is rendered correctly in different contexts.\n\n    Args:\n        dynamic_route: harness for DynamicRoute app.\n        driver: WebDriver instance.\n        token: The token visible in the driver browser.\n    \"\"\"\n    assert dynamic_route.app_instance is not None\n    frontend_url = dynamic_route.frontend_url\n    assert frontend_url\n\n    with poll_for_navigation(driver):\n        driver.get(f\"{frontend_url.removesuffix('/')}/arg/0\")\n\n    # TODO: drop after flakiness is resolved\n    await asyncio.sleep(3)\n\n    def assert_content(expected: str, expect_not: str):\n        ids = [\n            \"state-arg_str\",\n            \"argstate-arg\",\n            \"argstate-arg_str\",\n            \"argsubstate-arg_str\",\n            \"argsubstate-arg\",\n            \"argsubstate-cached_arg\",\n            \"argsubstate-cached_arg_str\",\n        ]\n        for id in ids:\n            el = driver.find_element(By.ID, id)\n            assert el\n            assert (\n                dynamic_route.poll_for_content(el, timeout=30, exp_not_equal=expect_not)\n                == expected\n            )\n\n    assert_content(\"0\", \"\")\n    next_page_link = driver.find_element(By.ID, \"next-page\")\n    assert next_page_link\n    with poll_for_navigation(driver):\n        next_page_link.click()\n    assert (\n        driver.current_url.removesuffix(\"/\")\n        == f\"{frontend_url.removesuffix('/')}/arg/1\"\n    )\n    assert_content(\"1\", \"0\")\n    next_page_link = driver.find_element(By.ID, \"next-page\")\n    assert next_page_link\n    with poll_for_navigation(driver):\n        next_page_link.click()\n    assert (\n        driver.current_url.removesuffix(\"/\")\n        == f\"{frontend_url.removesuffix('/')}/arg/2\"\n    )\n    assert_content(\"2\", \"1\")\n"
  },
  {
    "path": "tests/integration/test_event_actions.py",
    "content": "\"\"\"Ensure stopPropagation and preventDefault work as expected.\"\"\"\n\nfrom __future__ import annotations\n\nimport asyncio\nimport time\nfrom collections.abc import Callable, Coroutine, Generator\n\nimport pytest\nfrom selenium.webdriver.common.by import By\nfrom selenium.webdriver.common.keys import Keys\nfrom selenium.webdriver.support import expected_conditions as EC\nfrom selenium.webdriver.support.wait import WebDriverWait\n\nfrom reflex.state import BaseState\nfrom reflex.testing import AppHarness, WebDriver\n\n\ndef TestEventAction():\n    \"\"\"App for testing event_actions.\"\"\"\n    from typing import Any\n\n    import reflex as rx\n\n    class EventActionState(rx.State):\n        order: list[str]\n\n        def on_click(self, ev):\n            self.order.append(f\"on_click:{ev}\")\n\n        @rx.event\n        def on_click2(self):\n            self.order.append(\"on_click2\")\n\n        def on_click_throttle(self):\n            self.order.append(\"on_click_throttle\")\n\n        def on_click_debounce(self):\n            self.order.append(\"on_click_debounce\")\n\n        @rx.event\n        def on_submit(self, form_data: dict[str, Any]):\n            self.order.append(\"on_submit\")\n\n    class EventFiringComponent(rx.Component):\n        \"\"\"A component that fires onClick event without passing DOM event.\"\"\"\n\n        tag = \"EventFiringComponent\"\n\n        def _get_custom_code(self) -> str | None:\n            return \"\"\"\n                function EventFiringComponent(props) {\n                    return jsx(\n                        \"div\",\n                        {\"id\":props.id,\"onClick\":(e) => props.onClick(\"foo\")},\n                        \"Event Firing Component\",\n                    )\n                }\"\"\"\n\n        @classmethod\n        def get_event_triggers(cls):\n            return {\"on_click\": rx.event.no_args_event_spec}\n\n    def index():\n        return rx.vstack(\n            rx.input(\n                value=EventActionState.router.session.client_token,\n                is_read_only=True,\n                id=\"token\",\n            ),\n            rx.button(\"No events\", id=\"btn-no-events\"),\n            rx.button(\n                \"Stop Prop Only\",\n                id=\"btn-stop-prop-only\",\n                on_click=rx.stop_propagation,\n            ),\n            rx.button(\n                \"Click event\",\n                on_click=EventActionState.on_click(\"no_event_actions\"),  # pyright: ignore [reportCallIssue]\n                id=\"btn-click-event\",\n            ),\n            rx.button(\n                \"Click stop propagation\",\n                on_click=EventActionState.on_click(\"stop_propagation\").stop_propagation,  # pyright: ignore [reportCallIssue]\n                id=\"btn-click-stop-propagation\",\n            ),\n            rx.button(\n                \"Click stop propagation2\",\n                on_click=EventActionState.on_click2.stop_propagation,\n                id=\"btn-click-stop-propagation2\",\n            ),\n            rx.button(\n                \"Click event 2\",\n                on_click=EventActionState.on_click2,\n                id=\"btn-click-event2\",\n            ),\n            rx.link(\n                \"Link\",\n                href=\"?link\",\n                on_click=EventActionState.on_click(\"link_no_event_actions\"),  # pyright: ignore [reportCallIssue]\n                id=\"link\",\n            ),\n            rx.link(\n                \"Link Stop Propagation\",\n                href=\"?link-stop-propagation\",\n                on_click=EventActionState.on_click(  # pyright: ignore [reportCallIssue]\n                    \"link_stop_propagation\"\n                ).stop_propagation,\n                id=\"link-stop-propagation\",\n            ),\n            rx.link(\n                \"Link Prevent Default Only\",\n                href=\"/invalid\",\n                on_click=rx.prevent_default,\n                id=\"link-prevent-default-only\",\n            ),\n            rx.link(\n                \"Link Prevent Default\",\n                href=\"/invalid\",\n                on_click=EventActionState.on_click(  # pyright: ignore [reportCallIssue]\n                    \"link_prevent_default\"\n                ).prevent_default,\n                id=\"link-prevent-default\",\n            ),\n            rx.link(\n                \"Link Both\",\n                href=\"/invalid\",\n                on_click=EventActionState.on_click(  # pyright: ignore [reportCallIssue]\n                    \"link_both\"\n                ).stop_propagation.prevent_default,\n                id=\"link-stop-propagation-prevent-default\",\n            ),\n            EventFiringComponent.create(\n                id=\"custom-stop-propagation\",\n                on_click=EventActionState.on_click(  # pyright: ignore [reportCallIssue]\n                    \"custom-stop-propagation\"\n                ).stop_propagation,\n            ),\n            EventFiringComponent.create(\n                id=\"custom-prevent-default\",\n                on_click=EventActionState.on_click(  # pyright: ignore [reportCallIssue]\n                    \"custom-prevent-default\"\n                ).prevent_default,\n            ),\n            rx.button(\n                \"Throttle\",\n                id=\"btn-throttle\",\n                on_click=lambda: (\n                    EventActionState.on_click_throttle.throttle(  # pyright: ignore [reportFunctionMemberAccess]\n                        200\n                    ).stop_propagation\n                ),\n            ),\n            rx.button(\n                \"Debounce\",\n                id=\"btn-debounce\",\n                on_click=EventActionState.on_click_debounce.debounce(  # pyright: ignore [reportFunctionMemberAccess]\n                    200\n                ).stop_propagation,\n            ),\n            rx.list(  # pyright: ignore [reportAttributeAccessIssue]\n                rx.foreach(\n                    EventActionState.order,\n                    rx.list_item,\n                ),\n            ),\n            on_click=EventActionState.on_click(\"outer\"),  # pyright: ignore [reportCallIssue]\n        ), rx.form(\n            rx.dialog.root(\n                rx.dialog.trigger(\n                    rx.button(\"Open Dialog\", type=\"button\", id=\"btn-dialog\"),\n                    on_click=rx.stop_propagation,\n                ),\n                rx.dialog.content(\n                    rx.dialog.close(\n                        rx.form(\n                            rx.button(\"Submit\", id=\"btn-submit\"),\n                            on_submit=EventActionState.on_submit.stop_propagation,  # pyright: ignore [reportCallIssue]\n                        ),\n                    ),\n                ),\n            ),\n            on_submit=EventActionState.on_submit,  # pyright: ignore [reportCallIssue]\n        )\n\n    app = rx.App()\n    app.add_page(index)\n\n\n@pytest.fixture(scope=\"module\")\ndef event_action(tmp_path_factory) -> Generator[AppHarness, None, None]:\n    \"\"\"Start TestEventAction app at tmp_path via AppHarness.\n\n    Args:\n        tmp_path_factory: pytest tmp_path_factory fixture\n\n    Yields:\n        running AppHarness instance\n    \"\"\"\n    with AppHarness.create(\n        root=tmp_path_factory.mktemp(\"event_action\"),\n        app_source=TestEventAction,\n    ) as harness:\n        yield harness\n\n\n@pytest.fixture\ndef driver(event_action: AppHarness) -> Generator[WebDriver, None, None]:\n    \"\"\"Get an instance of the browser open to the event_action app.\n\n    Args:\n        event_action: harness for TestEventAction app\n\n    Yields:\n        WebDriver instance.\n    \"\"\"\n    assert event_action.app_instance is not None, \"app is not running\"\n    driver = event_action.frontend()\n    try:\n        yield driver\n    finally:\n        driver.quit()\n\n\n@pytest.fixture\ndef token(event_action: AppHarness, driver: WebDriver) -> str:\n    \"\"\"Get the token associated with backend state.\n\n    Args:\n        event_action: harness for TestEventAction app.\n        driver: WebDriver instance.\n\n    Returns:\n        The token visible in the driver browser.\n    \"\"\"\n    assert event_action.app_instance is not None\n    token_input = AppHarness.poll_for_or_raise_timeout(\n        lambda: driver.find_element(By.ID, \"token\")\n    )\n\n    # wait for the backend connection to send the token\n    token = event_action.poll_for_value(token_input)\n    assert token is not None\n\n    return token\n\n\nasync def _backend_state(app: AppHarness, token: str) -> BaseState:\n    state_name = app.get_state_name(\"_event_action_state\")\n    state_full_name = app.get_full_state_name([\"_event_action_state\"])\n    return (await app.get_state(f\"{token}_{state_full_name}\")).substates[state_name]\n\n\n@pytest.fixture\ndef poll_for_order(\n    event_action: AppHarness, token: str\n) -> Callable[[list[str]], Coroutine[None, None, None]]:\n    \"\"\"Poll for the order list to match the expected order.\n\n    Args:\n        event_action: harness for TestEventAction app.\n        token: The token visible in the driver browser.\n\n    Returns:\n        An async function that polls for the order list to match the expected order.\n    \"\"\"\n\n    async def _poll_for_order(exp_order: list[str]):\n        async def _check():\n            return (await _backend_state(event_action, token)).order == exp_order  # pyright: ignore[reportAttributeAccessIssue]\n\n        await AppHarness._poll_for_async(_check)\n        assert (await _backend_state(event_action, token)).order == exp_order  # pyright: ignore[reportAttributeAccessIssue]\n\n    return _poll_for_order\n\n\n@pytest.mark.parametrize(\n    (\"element_id\", \"exp_order\"),\n    [\n        (\"btn-no-events\", [\"on_click:outer\"]),\n        (\"btn-stop-prop-only\", []),\n        (\"btn-click-event\", [\"on_click:no_event_actions\", \"on_click:outer\"]),\n        (\"btn-click-stop-propagation\", [\"on_click:stop_propagation\"]),\n        (\"btn-click-stop-propagation2\", [\"on_click2\"]),\n        (\"btn-click-event2\", [\"on_click2\", \"on_click:outer\"]),\n        (\"link\", [\"on_click:link_no_event_actions\", \"on_click:outer\"]),\n        (\"link-stop-propagation\", [\"on_click:link_stop_propagation\"]),\n        (\"link-prevent-default\", [\"on_click:link_prevent_default\", \"on_click:outer\"]),\n        (\"link-prevent-default-only\", [\"on_click:outer\"]),\n        (\"link-stop-propagation-prevent-default\", [\"on_click:link_both\"]),\n        (\n            \"custom-stop-propagation\",\n            [\"on_click:custom-stop-propagation\", \"on_click:outer\"],\n        ),\n        (\n            \"custom-prevent-default\",\n            [\"on_click:custom-prevent-default\", \"on_click:outer\"],\n        ),\n    ],\n)\n@pytest.mark.usefixtures(\"token\")\n@pytest.mark.asyncio\nasync def test_event_actions(\n    driver: WebDriver,\n    poll_for_order: Callable[[list[str]], Coroutine[None, None, None]],\n    element_id: str,\n    exp_order: list[str],\n):\n    \"\"\"Click links and buttons and assert on fired events.\n\n    Args:\n        driver: WebDriver instance.\n        poll_for_order: function that polls for the order list to match the expected order.\n        element_id: The id of the element to click.\n        exp_order: The expected order of events.\n    \"\"\"\n    el = driver.find_element(By.ID, element_id)\n    assert el\n\n    prev_url = driver.current_url\n\n    el.click()\n    if \"on_click:outer\" not in exp_order:\n        # really make sure the outer event is not fired\n        await asyncio.sleep(0.5)\n    await poll_for_order(exp_order)\n\n    if element_id.startswith(\"link\") and \"prevent-default\" not in element_id:\n        assert driver.current_url != prev_url\n    else:\n        assert driver.current_url == prev_url\n\n\n@pytest.mark.asyncio\nasync def test_event_actions_throttle_debounce(\n    event_action: AppHarness,\n    driver: WebDriver,\n    token: str,\n):\n    \"\"\"Click buttons with debounce and throttle and assert on fired events.\n\n    Args:\n        event_action: harness for TestEventAction app.\n        driver: WebDriver instance.\n        token: The client_token associated with the driver browser.\n    \"\"\"\n    btn_throttle = driver.find_element(By.ID, \"btn-throttle\")\n    assert btn_throttle\n    btn_debounce = driver.find_element(By.ID, \"btn-debounce\")\n    assert btn_debounce\n\n    exp_events = 10\n    throttle_duration = exp_events * 0.2  # 200ms throttle\n    throttle_start = time.time()\n    while time.time() - throttle_start < throttle_duration:\n        btn_throttle.click()\n        btn_debounce.click()\n\n    # Wait until the debounce event shows up\n    async def _debounce_received():\n        state = await _backend_state(event_action, token)\n        return state.order and state.order[-1] == \"on_click_debounce\"  # pyright: ignore[reportAttributeAccessIssue]\n\n    await AppHarness._poll_for_async(_debounce_received)\n\n    # This test is inherently racy, so ensure the `on_click_throttle` event is fired approximately the expected number of times.\n    final_event_order = (await _backend_state(event_action, token)).order  # pyright: ignore[reportAttributeAccessIssue]\n    n_on_click_throttle_received = final_event_order.count(\"on_click_throttle\")\n    print(\n        f\"Expected ~{exp_events} on_click_throttle events, received {n_on_click_throttle_received}\"\n    )\n    assert exp_events - 2 <= n_on_click_throttle_received <= exp_events + 1\n    assert final_event_order == [\"on_click_throttle\"] * n_on_click_throttle_received + [\n        \"on_click_debounce\"\n    ]\n\n\n@pytest.mark.usefixtures(\"token\")\n@pytest.mark.asyncio\nasync def test_event_actions_dialog_form_in_form(\n    driver: WebDriver,\n    poll_for_order: Callable[[list[str]], Coroutine[None, None, None]],\n):\n    \"\"\"Click links and buttons and assert on fired events.\n\n    Args:\n        driver: WebDriver instance.\n        poll_for_order: function that polls for the order list to match the expected order.\n    \"\"\"\n    open_dialog_id = \"btn-dialog\"\n    submit_button_id = \"btn-submit\"\n    wait = WebDriverWait(driver, 10)\n\n    driver.find_element(By.ID, open_dialog_id).click()\n    el = wait.until(EC.element_to_be_clickable((By.ID, submit_button_id)))\n    el.click()  # pyright: ignore[reportAttributeAccessIssue]\n    el.send_keys(Keys.ESCAPE)  # pyright: ignore[reportAttributeAccessIssue]\n\n    btn_no_events = wait.until(EC.element_to_be_clickable((By.ID, \"btn-no-events\")))\n    btn_no_events.location_once_scrolled_into_view\n    btn_no_events.click()\n    await poll_for_order([\"on_submit\", \"on_click:outer\"])\n"
  },
  {
    "path": "tests/integration/test_event_chain.py",
    "content": "\"\"\"Ensure that Event Chains are properly queued and handled between frontend and backend.\"\"\"\n\nfrom __future__ import annotations\n\nimport os\nfrom collections.abc import Generator\n\nimport pytest\nfrom selenium.webdriver.common.by import By\n\nfrom reflex.testing import AppHarness, WebDriver\n\nMANY_EVENTS = 50\n\n\ndef EventChain():\n    \"\"\"App with chained event handlers.\"\"\"\n    import asyncio\n    import time\n\n    import reflex as rx\n\n    # repeated here since the outer global isn't exported into the App module\n    MANY_EVENTS = 50\n\n    class State(rx.State):\n        event_order: list[str] = []\n        interim_value: str = \"\"\n\n        @rx.event\n        def event_no_args(self):\n            self.event_order.append(\"event_no_args\")\n\n        @rx.event\n        def event_arg(self, arg):\n            self.event_order.append(f\"event_arg:{arg}\")\n\n        @rx.event\n        def event_arg_repr_type(self, arg):\n            self.event_order.append(f\"event_arg_repr:{arg!r}_{type(arg).__name__}\")\n\n        @rx.event\n        def event_nested_1(self):\n            self.event_order.append(\"event_nested_1\")\n            yield State.event_nested_2\n            yield State.event_arg(\"nested_1\")\n\n        @rx.event\n        def event_nested_2(self):\n            self.event_order.append(\"event_nested_2\")\n            yield State.event_nested_3\n            yield rx.console_log(\"event_nested_2\")\n            yield State.event_arg(\"nested_2\")\n\n        @rx.event\n        def event_nested_3(self):\n            self.event_order.append(\"event_nested_3\")\n            yield State.event_no_args\n            yield State.event_arg(\"nested_3\")\n\n        @rx.event\n        def on_load_return_chain(self):\n            self.event_order.append(\"on_load_return_chain\")\n            return [State.event_arg(1), State.event_arg(2), State.event_arg(3)]\n\n        @rx.event\n        def on_load_yield_chain(self):\n            self.event_order.append(\"on_load_yield_chain\")\n            yield State.event_arg(4)\n            yield State.event_arg(5)\n            yield State.event_arg(6)\n\n        @rx.event\n        def click_return_event(self):\n            self.event_order.append(\"click_return_event\")\n            return State.event_no_args\n\n        @rx.event\n        def click_return_events(self):\n            self.event_order.append(\"click_return_events\")\n            return [\n                State.event_arg(7),\n                rx.console_log(\"click_return_events\"),\n                State.event_arg(8),\n                State.event_arg(9),\n            ]\n\n        @rx.event\n        def click_yield_chain(self):\n            self.event_order.append(\"click_yield_chain:0\")\n            yield State.event_arg(10)\n            self.event_order.append(\"click_yield_chain:1\")\n            yield rx.console_log(\"click_yield_chain\")\n            yield State.event_arg(11)\n            self.event_order.append(\"click_yield_chain:2\")\n            yield State.event_arg(12)\n            self.event_order.append(\"click_yield_chain:3\")\n\n        @rx.event\n        def click_yield_many_events(self):\n            self.event_order.append(\"click_yield_many_events\")\n            for ix in range(MANY_EVENTS):\n                yield State.event_arg(ix)\n                yield rx.console_log(f\"many_events_{ix}\")\n            self.event_order.append(\"click_yield_many_events_done\")\n\n        @rx.event\n        def click_yield_nested(self):\n            self.event_order.append(\"click_yield_nested\")\n            yield State.event_nested_1\n            yield State.event_arg(\"yield_nested\")\n\n        @rx.event\n        def redirect_return_chain(self):\n            self.event_order.append(\"redirect_return_chain\")\n            yield rx.redirect(\"/on-load-return-chain\")\n\n        @rx.event\n        def redirect_yield_chain(self):\n            self.event_order.append(\"redirect_yield_chain\")\n            yield rx.redirect(\"/on-load-yield-chain\")\n\n        @rx.event\n        def click_return_int_type(self):\n            self.event_order.append(\"click_return_int_type\")\n            return State.event_arg_repr_type(1)\n\n        @rx.event\n        def click_return_dict_type(self):\n            self.event_order.append(\"click_return_dict_type\")\n            return State.event_arg_repr_type({\"a\": 1})\n\n        @rx.event\n        async def click_yield_interim_value_async(self):\n            self.interim_value = \"interim\"\n            yield\n            await asyncio.sleep(0.5)\n            self.interim_value = \"final\"\n\n        @rx.event\n        def click_yield_interim_value(self):\n            self.interim_value = \"interim\"\n            yield\n            time.sleep(0.5)\n            self.interim_value = \"final\"\n\n    app = rx.App()\n\n    token_input = rx.input(\n        value=State.router.session.client_token, is_read_only=True, id=\"token\"\n    )\n\n    @app.add_page\n    def index():\n        return rx.fragment(\n            token_input,\n            rx.input(value=State.interim_value, is_read_only=True, id=\"interim_value\"),\n            rx.button(\n                \"Return Event\",\n                id=\"return_event\",\n                on_click=State.click_return_event,\n            ),\n            rx.button(\n                \"Return Events\",\n                id=\"return_events\",\n                on_click=State.click_return_events,\n            ),\n            rx.button(\n                \"Yield Chain\",\n                id=\"yield_chain\",\n                on_click=State.click_yield_chain,\n            ),\n            rx.button(\n                \"Yield Many events\",\n                id=\"yield_many_events\",\n                on_click=State.click_yield_many_events,\n            ),\n            rx.button(\n                \"Yield Nested\",\n                id=\"yield_nested\",\n                on_click=State.click_yield_nested,\n            ),\n            rx.button(\n                \"Redirect Yield Chain\",\n                id=\"redirect_yield_chain\",\n                on_click=State.redirect_yield_chain,\n            ),\n            rx.button(\n                \"Redirect Return Chain\",\n                id=\"redirect_return_chain\",\n                on_click=State.redirect_return_chain,\n            ),\n            rx.button(\n                \"Click Int Type\",\n                id=\"click_int_type\",\n                on_click=lambda: State.event_arg_repr_type(1),\n            ),\n            rx.button(\n                \"Click Dict Type\",\n                id=\"click_dict_type\",\n                on_click=lambda: State.event_arg_repr_type({\"a\": 1}),\n            ),\n            rx.button(\n                \"Return Chain Int Type\",\n                id=\"return_int_type\",\n                on_click=State.click_return_int_type,\n            ),\n            rx.button(\n                \"Return Chain Dict Type\",\n                id=\"return_dict_type\",\n                on_click=State.click_return_dict_type,\n            ),\n            rx.button(\n                \"Click Yield Interim Value (Async)\",\n                id=\"click_yield_interim_value_async\",\n                on_click=State.click_yield_interim_value_async,\n            ),\n            rx.button(\n                \"Click Yield Interim Value\",\n                id=\"click_yield_interim_value\",\n                on_click=State.click_yield_interim_value,\n            ),\n        )\n\n    def on_load_return_chain():\n        return rx.fragment(\n            rx.text(\"return\"),\n            token_input,\n        )\n\n    def on_load_yield_chain():\n        return rx.fragment(\n            rx.text(\"yield\"),\n            token_input,\n        )\n\n    def on_mount_return_chain():\n        return rx.fragment(\n            rx.text(\n                \"return\",\n                on_mount=State.on_load_return_chain,\n                on_unmount=lambda: State.event_arg(\"unmount\"),\n            ),\n            token_input,\n            rx.button(\"Unmount\", on_click=rx.redirect(\"/\"), id=\"unmount\"),\n        )\n\n    def on_mount_yield_chain():\n        return rx.fragment(\n            rx.text(\n                \"yield\",\n                on_mount=[\n                    State.on_load_yield_chain,\n                    lambda: State.event_arg(\"mount\"),\n                ],\n                on_unmount=State.event_no_args,\n            ),\n            token_input,\n            rx.button(\"Unmount\", on_click=rx.redirect(\"/\"), id=\"unmount\"),\n        )\n\n    app.add_page(on_load_return_chain, on_load=State.on_load_return_chain)\n    app.add_page(on_load_yield_chain, on_load=State.on_load_yield_chain)\n    app.add_page(on_mount_return_chain)\n    app.add_page(on_mount_yield_chain)\n\n\n@pytest.fixture(scope=\"module\")\ndef event_chain(tmp_path_factory) -> Generator[AppHarness, None, None]:\n    \"\"\"Start EventChain app at tmp_path via AppHarness.\n\n    Args:\n        tmp_path_factory: pytest tmp_path_factory fixture\n\n    Yields:\n        running AppHarness instance\n    \"\"\"\n    os.environ[\"REFLEX_REACT_STRICT_MODE\"] = \"0\"\n    with AppHarness.create(\n        root=tmp_path_factory.mktemp(\"event_chain\"),\n        app_source=EventChain,\n    ) as harness:\n        yield harness\n\n\n@pytest.fixture\ndef driver(event_chain: AppHarness) -> Generator[WebDriver, None, None]:\n    \"\"\"Get an instance of the browser open to the event_chain app.\n\n    Args:\n        event_chain: harness for EventChain app\n\n    Yields:\n        WebDriver instance.\n    \"\"\"\n    assert event_chain.app_instance is not None, \"app is not running\"\n    driver = event_chain.frontend()\n    try:\n        yield driver\n    finally:\n        driver.quit()\n\n\n@pytest.fixture(scope=\"module\")\ndef event_chain_strict(tmp_path_factory) -> Generator[AppHarness, None, None]:\n    \"\"\"Start EventChain app at tmp_path via AppHarness.\n\n    Args:\n        tmp_path_factory: pytest tmp_path_factory fixture\n\n    Yields:\n        running AppHarness instance\n    \"\"\"\n    os.environ[\"REFLEX_REACT_STRICT_MODE\"] = \"1\"\n    with AppHarness.create(\n        root=tmp_path_factory.mktemp(\"event_chain_strict\"),\n        app_source=EventChain,\n    ) as harness:\n        yield harness\n\n\n@pytest.fixture\ndef driver_strict(event_chain_strict: AppHarness) -> Generator[WebDriver, None, None]:\n    \"\"\"Get an instance of the browser open to the event_chain_strict app.\n\n    Args:\n        event_chain_strict: harness for EventChain app\n\n    Yields:\n        WebDriver instance.\n    \"\"\"\n    assert event_chain_strict.app_instance is not None, \"app is not running\"\n    driver = event_chain_strict.frontend()\n    try:\n        yield driver\n    finally:\n        driver.quit()\n\n\ndef assert_token(event_chain: AppHarness, driver: WebDriver) -> str:\n    \"\"\"Get the token associated with backend state.\n\n    Args:\n        event_chain: harness for EventChain app.\n        driver: WebDriver instance.\n\n    Returns:\n        The token visible in the driver browser.\n    \"\"\"\n    assert event_chain.app_instance is not None\n    token_input = AppHarness.poll_for_or_raise_timeout(\n        lambda: driver.find_element(By.ID, \"token\")\n    )\n\n    # wait for the backend connection to send the token\n    token = event_chain.poll_for_value(token_input)\n    assert token is not None\n\n    state_name = event_chain.get_full_state_name([\"_state\"])\n    return f\"{token}_{state_name}\"\n\n\n@pytest.mark.parametrize(\n    (\"button_id\", \"exp_event_order\"),\n    [\n        (\"return_event\", [\"click_return_event\", \"event_no_args\"]),\n        (\n            \"return_events\",\n            [\"click_return_events\", \"event_arg:7\", \"event_arg:8\", \"event_arg:9\"],\n        ),\n        (\n            \"yield_chain\",\n            [\n                \"click_yield_chain:0\",\n                \"click_yield_chain:1\",\n                \"click_yield_chain:2\",\n                \"click_yield_chain:3\",\n                \"event_arg:10\",\n                \"event_arg:11\",\n                \"event_arg:12\",\n            ],\n        ),\n        (\n            \"yield_many_events\",\n            [\n                \"click_yield_many_events\",\n                \"click_yield_many_events_done\",\n                *[f\"event_arg:{ix}\" for ix in range(MANY_EVENTS)],\n            ],\n        ),\n        (\n            \"yield_nested\",\n            [\n                \"click_yield_nested\",\n                \"event_nested_1\",\n                \"event_arg:yield_nested\",\n                \"event_nested_2\",\n                \"event_arg:nested_1\",\n                \"event_nested_3\",\n                \"event_arg:nested_2\",\n                \"event_no_args\",\n                \"event_arg:nested_3\",\n            ],\n        ),\n        (\n            \"redirect_return_chain\",\n            [\n                \"redirect_return_chain\",\n                \"on_load_return_chain\",\n                \"event_arg:1\",\n                \"event_arg:2\",\n                \"event_arg:3\",\n            ],\n        ),\n        (\n            \"redirect_yield_chain\",\n            [\n                \"redirect_yield_chain\",\n                \"on_load_yield_chain\",\n                \"event_arg:4\",\n                \"event_arg:5\",\n                \"event_arg:6\",\n            ],\n        ),\n        (\n            \"click_int_type\",\n            [\"event_arg_repr:1_int\"],\n        ),\n        (\n            \"click_dict_type\",\n            [\"event_arg_repr:{'a': 1}_dict\"],\n        ),\n        (\n            \"return_int_type\",\n            [\"click_return_int_type\", \"event_arg_repr:1_int\"],\n        ),\n        (\n            \"return_dict_type\",\n            [\"click_return_dict_type\", \"event_arg_repr:{'a': 1}_dict\"],\n        ),\n    ],\n)\n@pytest.mark.asyncio\nasync def test_event_chain_click(\n    event_chain: AppHarness,\n    driver: WebDriver,\n    button_id: str,\n    exp_event_order: list[str],\n):\n    \"\"\"Click the button, assert that the events are handled in the correct order.\n\n    Args:\n        event_chain: AppHarness for the event_chain app\n        driver: selenium WebDriver open to the app\n        button_id: the ID of the button to click\n        exp_event_order: the expected events recorded in the State\n    \"\"\"\n    token = assert_token(event_chain, driver)\n    state_name = event_chain.get_state_name(\"_state\")\n    btn = driver.find_element(By.ID, button_id)\n    btn.click()\n\n    async def _has_all_events():\n        return len(\n            (await event_chain.get_state(token)).substates[state_name].event_order  # pyright: ignore[reportAttributeAccessIssue]\n        ) == len(exp_event_order)\n\n    await AppHarness._poll_for_async(_has_all_events)\n    event_order = (await event_chain.get_state(token)).substates[state_name].event_order  # pyright: ignore[reportAttributeAccessIssue]\n    assert event_order == exp_event_order\n\n\n@pytest.mark.parametrize(\n    (\"uri\", \"exp_event_order\"),\n    [\n        (\n            \"/on-load-return-chain\",\n            [\n                \"on_load_return_chain\",\n                \"event_arg:1\",\n                \"event_arg:2\",\n                \"event_arg:3\",\n            ],\n        ),\n        (\n            \"/on-load-yield-chain\",\n            [\n                \"on_load_yield_chain\",\n                \"event_arg:4\",\n                \"event_arg:5\",\n                \"event_arg:6\",\n            ],\n        ),\n    ],\n)\n@pytest.mark.asyncio\nasync def test_event_chain_on_load(\n    event_chain: AppHarness,\n    driver: WebDriver,\n    uri: str,\n    exp_event_order: list[str],\n):\n    \"\"\"Load the URI, assert that the events are handled in the correct order.\n\n    Args:\n        event_chain: AppHarness for the event_chain app\n        driver: selenium WebDriver open to the app\n        uri: the page to load\n        exp_event_order: the expected events recorded in the State\n    \"\"\"\n    assert event_chain.frontend_url is not None\n    driver.get(event_chain.frontend_url.removesuffix(\"/\") + uri)\n    token = assert_token(event_chain, driver)\n    state_name = event_chain.get_state_name(\"_state\")\n\n    async def _has_all_events():\n        return len(\n            (await event_chain.get_state(token)).substates[state_name].event_order  # pyright: ignore[reportAttributeAccessIssue]\n        ) == len(exp_event_order)\n\n    await AppHarness._poll_for_async(_has_all_events)\n    backend_state = (await event_chain.get_state(token)).substates[state_name]\n    assert backend_state.event_order == exp_event_order  # pyright: ignore[reportAttributeAccessIssue]\n    assert backend_state.is_hydrated is True  # pyright: ignore[reportAttributeAccessIssue]\n\n\n@pytest.mark.parametrize(\n    (\"uri\", \"exp_event_order\"),\n    [\n        (\n            \"/on-mount-return-chain\",\n            [\n                \"on_load_return_chain\",\n                \"event_arg:1\",\n                \"event_arg:2\",\n                \"event_arg:3\",\n                \"event_arg:unmount\",\n            ],\n        ),\n        (\n            \"/on-mount-yield-chain\",\n            [\n                \"on_load_yield_chain\",\n                \"event_arg:mount\",\n                \"event_arg:4\",\n                \"event_arg:5\",\n                \"event_arg:6\",\n                \"event_no_args\",\n            ],\n        ),\n    ],\n)\n@pytest.mark.asyncio\nasync def test_event_chain_on_mount(\n    event_chain: AppHarness,\n    driver: WebDriver,\n    uri: str,\n    exp_event_order: list[str],\n):\n    \"\"\"Load the URI, assert that the events are handled in the correct order.\n\n    These pages use `on_mount` and `on_unmount`, which get fired twice in dev mode\n    due to react StrictMode being used.\n\n    In prod mode, these events are only fired once.\n\n    Args:\n        event_chain: AppHarness for the event_chain app\n        driver: selenium WebDriver open to the app\n        uri: the page to load\n        exp_event_order: the expected events recorded in the State\n    \"\"\"\n    assert event_chain.frontend_url is not None\n    driver.get(event_chain.frontend_url.removesuffix(\"/\") + uri)\n\n    unmount_button = AppHarness.poll_for_or_raise_timeout(\n        lambda: driver.find_element(By.ID, \"unmount\")\n    )\n    token = assert_token(event_chain, driver)\n    state_name = event_chain.get_state_name(\"_state\")\n    unmount_button.click()\n\n    async def _has_all_events():\n        return len(\n            (await event_chain.get_state(token)).substates[state_name].event_order  # pyright: ignore[reportAttributeAccessIssue]\n        ) == len(exp_event_order)\n\n    await AppHarness._poll_for_async(_has_all_events)\n    event_order = (await event_chain.get_state(token)).substates[state_name].event_order  # pyright: ignore[reportAttributeAccessIssue]\n    assert list(event_order) == exp_event_order\n\n\n@pytest.mark.parametrize(\n    (\"uri\", \"exp_event_order\"),\n    [\n        (\n            \"/on-mount-return-chain\",\n            [\n                \"on_load_return_chain\",\n                \"event_arg:unmount\",\n                \"on_load_return_chain\",\n                \"event_arg:1\",\n                \"event_arg:2\",\n                \"event_arg:3\",\n                \"event_arg:1\",\n                \"event_arg:2\",\n                \"event_arg:3\",\n                \"event_arg:unmount\",\n            ],\n        ),\n        (\n            \"/on-mount-yield-chain\",\n            [\n                \"on_load_yield_chain\",\n                \"event_arg:mount\",\n                \"event_no_args\",\n                \"on_load_yield_chain\",\n                \"event_arg:mount\",\n                \"event_arg:4\",\n                \"event_arg:5\",\n                \"event_arg:6\",\n                \"event_arg:4\",\n                \"event_arg:5\",\n                \"event_arg:6\",\n                \"event_no_args\",\n            ],\n        ),\n    ],\n)\n@pytest.mark.asyncio\nasync def test_event_chain_on_mount_strict(\n    event_chain_strict: AppHarness,\n    driver_strict: WebDriver,\n    uri: str,\n    exp_event_order: list[str],\n):\n    \"\"\"Run the test_event_chain_on_mount test with strict mode enabled.\n\n    Args:\n        event_chain_strict: AppHarness for the event_chain app with strict mode enabled\n        driver_strict: selenium WebDriver open to the app with strict mode enabled\n        uri: the page to load\n        exp_event_order: the expected events recorded in the State\n    \"\"\"\n    await test_event_chain_on_mount(\n        event_chain=event_chain_strict,\n        driver=driver_strict,\n        uri=uri,\n        exp_event_order=exp_event_order,\n    )\n\n\n@pytest.mark.parametrize(\n    \"button_id\",\n    [\n        \"click_yield_interim_value_async\",\n        \"click_yield_interim_value\",\n    ],\n)\ndef test_yield_state_update(event_chain: AppHarness, driver: WebDriver, button_id: str):\n    \"\"\"Click the button, assert that the interim value is set, then final value is set.\n\n    Args:\n        event_chain: AppHarness for the event_chain app\n        driver: selenium WebDriver open to the app\n        button_id: the ID of the button to click\n    \"\"\"\n    assert_token(event_chain, driver)\n    interim_value_input = driver.find_element(By.ID, \"interim_value\")\n\n    btn = driver.find_element(By.ID, button_id)\n    btn.click()\n    assert (\n        event_chain.poll_for_value(interim_value_input, exp_not_equal=\"\") == \"interim\"\n    )\n    assert (\n        event_chain.poll_for_value(interim_value_input, exp_not_equal=\"interim\")\n        == \"final\"\n    )\n"
  },
  {
    "path": "tests/integration/test_exception_handlers.py",
    "content": "\"\"\"Integration tests for event exception handlers.\"\"\"\n\nfrom __future__ import annotations\n\nimport time\nfrom collections.abc import Generator\n\nimport pytest\nfrom selenium.webdriver.common.by import By\nfrom selenium.webdriver.remote.webdriver import WebDriver\nfrom selenium.webdriver.support import expected_conditions as EC\nfrom selenium.webdriver.support.ui import WebDriverWait\n\nfrom reflex.testing import AppHarness, AppHarnessProd\n\npytestmark = [pytest.mark.ignore_console_error]\n\n\ndef TestApp():\n    \"\"\"A test app for event exception handler integration.\"\"\"\n    import reflex as rx\n\n    class TestAppConfig(rx.Config):\n        \"\"\"Config for the TestApp app.\"\"\"\n\n    class TestAppState(rx.State):\n        \"\"\"State for the TestApp app.\"\"\"\n\n        react_error: bool = False\n\n        @rx.event\n        def set_react_error(self, value: bool):\n            self.react_error = value\n\n        def divide_by_number(self, number: int):\n            \"\"\"Divide by number and print the result.\n\n            Args:\n                number: number to divide by\n\n            \"\"\"\n            print(1 / number)\n\n    app = rx.App()\n\n    @app.add_page\n    def index():\n        return rx.vstack(\n            rx.button(\n                \"induce_frontend_error\",\n                on_click=rx.call_script(\"induce_frontend_error()\"),\n                id=\"induce-frontend-error-btn\",\n            ),\n            rx.button(\n                \"induce_backend_error\",\n                on_click=lambda: TestAppState.divide_by_number(0),  # pyright: ignore [reportCallIssue]\n                id=\"induce-backend-error-btn\",\n            ),\n            rx.button(\n                \"induce_react_error\",\n                on_click=TestAppState.set_react_error(True),\n                id=\"induce-react-error-btn\",\n            ),\n            rx.box(\n                rx.cond(\n                    TestAppState.react_error,\n                    rx.Var.create({\"invalid\": \"cannot have object as child\"}),\n                    \"\",\n                ),\n            ),\n        )\n\n\n@pytest.fixture(scope=\"module\")\ndef test_app(\n    app_harness_env: type[AppHarness], tmp_path_factory\n) -> Generator[AppHarness, None, None]:\n    \"\"\"Start TestApp app at tmp_path via AppHarness.\n\n    Args:\n        app_harness_env: either AppHarness (dev) or AppHarnessProd (prod)\n        tmp_path_factory: pytest tmp_path_factory fixture\n\n    Yields:\n        running AppHarness instance\n\n    \"\"\"\n    with app_harness_env.create(\n        root=tmp_path_factory.mktemp(\"test_app\"),\n        app_name=f\"testapp_{app_harness_env.__name__.lower()}\",\n        app_source=TestApp,\n    ) as harness:\n        yield harness\n\n\n@pytest.fixture\ndef driver(test_app: AppHarness) -> Generator[WebDriver, None, None]:\n    \"\"\"Get an instance of the browser open to the test_app app.\n\n    Args:\n        test_app: harness for TestApp app\n\n    Yields:\n        WebDriver instance.\n\n    \"\"\"\n    assert test_app.app_instance is not None, \"app is not running\"\n    driver = test_app.frontend()\n    try:\n        yield driver\n    finally:\n        driver.quit()\n\n\ndef test_frontend_exception_handler_during_runtime(\n    driver: WebDriver,\n    capsys: pytest.CaptureFixture[str],\n):\n    \"\"\"Test calling frontend exception handler during runtime.\n\n    We send an event containing a call to a non-existent function in the frontend.\n    This should trigger the default frontend exception handler.\n\n    Args:\n        driver: WebDriver instance.\n        capsys: pytest fixture for capturing stdout and stderr.\n\n    \"\"\"\n    reset_button = WebDriverWait(driver, 20).until(\n        EC.element_to_be_clickable((By.ID, \"induce-frontend-error-btn\"))\n    )\n\n    reset_button.click()\n\n    # Wait for the error to be logged\n    time.sleep(2)\n\n    captured_default_handler_output = capsys.readouterr()\n    assert \"induce_frontend_error\" in captured_default_handler_output.err\n    assert \"ReferenceError\" in captured_default_handler_output.err\n\n\ndef test_backend_exception_handler_during_runtime(\n    driver: WebDriver,\n    capsys: pytest.CaptureFixture[str],\n):\n    \"\"\"Test calling backend exception handler during runtime.\n\n    We invoke TestAppState.divide_by_zero to induce backend error.\n    This should trigger the default backend exception handler.\n\n    Args:\n        driver: WebDriver instance.\n        capsys: pytest fixture for capturing stdout and stderr.\n\n    \"\"\"\n    reset_button = WebDriverWait(driver, 20).until(\n        EC.element_to_be_clickable((By.ID, \"induce-backend-error-btn\"))\n    )\n\n    reset_button.click()\n\n    # Wait for the error to be logged\n    time.sleep(2)\n\n    captured_default_handler_output = capsys.readouterr()\n    assert \"divide_by_number\" in captured_default_handler_output.err\n    assert \"ZeroDivisionError\" in captured_default_handler_output.err\n\n\ndef test_frontend_exception_handler_with_react(\n    test_app: AppHarness,\n    driver: WebDriver,\n    capsys: pytest.CaptureFixture[str],\n):\n    \"\"\"Test calling frontend exception handler during runtime.\n\n    Render an object as a react child, which is invalid.\n\n    Args:\n        test_app: harness for TestApp app\n        driver: WebDriver instance.\n        capsys: pytest fixture for capturing stdout and stderr.\n\n    \"\"\"\n    reset_button = WebDriverWait(driver, 20).until(\n        EC.element_to_be_clickable((By.ID, \"induce-react-error-btn\"))\n    )\n\n    reset_button.click()\n\n    # Wait for the error to be logged\n    time.sleep(2)\n\n    captured_default_handler_output = capsys.readouterr()\n    if isinstance(test_app, AppHarnessProd):\n        assert \"Error: Minified React error #31\" in captured_default_handler_output.err\n    else:\n        assert (\n            \"Error: Objects are not valid as a React child (found: object with keys \\n{invalid})\"\n            in captured_default_handler_output.err\n        )\n"
  },
  {
    "path": "tests/integration/test_extra_overlay_function.py",
    "content": "\"\"\"Test case for adding an overlay component defined in the rxconfig.\"\"\"\n\nfrom collections.abc import Generator\n\nimport pytest\nfrom selenium.webdriver.common.by import By\n\nfrom reflex.testing import AppHarness, WebDriver\n\n\ndef ExtraOverlay():\n    import reflex as rx\n\n    def index():\n        return rx.vstack(\n            rx.el.input(\n                id=\"token\",\n                value=rx.State.router.session.client_token,\n                is_read_only=True,\n            ),\n            rx.text(\n                \"Hello World\",\n            ),\n        )\n\n    app = rx.App()\n    rx.config.get_config().extra_overlay_function = (\n        \"reflex.components.radix.themes.components.button\"\n    )\n    app.add_page(index)\n\n\n@pytest.fixture(scope=\"module\")\ndef extra_overlay(tmp_path_factory) -> Generator[AppHarness, None, None]:\n    \"\"\"Start ExtraOverlay app at tmp_path via AppHarness.\n\n    Args:\n        tmp_path_factory: pytest tmp_path_factory fixture\n\n    Yields:\n        running AppHarness instance\n    \"\"\"\n    with AppHarness.create(\n        root=tmp_path_factory.mktemp(\"extra_overlay\"),\n        app_source=ExtraOverlay,\n    ) as harness:\n        assert harness.app_instance is not None, \"app is not running\"\n        yield harness\n\n\n@pytest.fixture\ndef driver(extra_overlay: AppHarness):\n    \"\"\"Get an instance of the browser open to the extra overlay app.\n\n    Args:\n        extra_overlay: harness for the ExtraOverlay app.\n\n    Yields:\n        WebDriver instance.\n    \"\"\"\n    driver = extra_overlay.frontend()\n    try:\n        token_input = AppHarness.poll_for_or_raise_timeout(\n            lambda: driver.find_element(By.ID, \"token\")\n        )\n        # wait for the backend connection to send the token\n        token = extra_overlay.poll_for_value(token_input)\n        assert token is not None\n\n        yield driver\n    finally:\n        driver.quit()\n\n\ndef test_extra_overlay(driver: WebDriver, extra_overlay: AppHarness):\n    \"\"\"Test the ExtraOverlay app.\n\n    Args:\n        driver: WebDriver instance.\n        extra_overlay: harness for the ExtraOverlay app.\n    \"\"\"\n    # Check that the text is displayed.\n    text = driver.find_element(By.XPATH, \"//*[contains(text(), 'Hello World')]\")\n    assert text\n    assert text.text == \"Hello World\"\n\n    button = driver.find_element(By.TAG_NAME, \"button\")\n    assert button\n    assert not button.text\n"
  },
  {
    "path": "tests/integration/test_form_submit.py",
    "content": "\"\"\"Integration tests for forms.\"\"\"\n\nimport asyncio\nimport functools\nfrom collections.abc import Generator\n\nimport pytest\nfrom selenium.webdriver.common.by import By\nfrom selenium.webdriver.common.keys import Keys\n\nfrom reflex.testing import AppHarness\nfrom reflex.utils import format\n\n\ndef FormSubmit(form_component):\n    \"\"\"App with a form using on_submit.\n\n    Args:\n        form_component: The str name of the form component to use.\n    \"\"\"\n    import reflex as rx\n\n    class FormState(rx.State):\n        form_data: dict = {}\n\n        var_options: list[str] = [\"option3\", \"option4\"]\n\n        def form_submit(self, form_data: dict):\n            self.form_data = form_data\n\n    app = rx.App()\n\n    @app.add_page\n    def index():\n        return rx.vstack(\n            rx.input(\n                value=FormState.router.session.client_token,\n                is_read_only=True,\n                id=\"token\",\n            ),\n            eval(form_component)(\n                rx.vstack(\n                    rx.input(id=\"name_input\"),\n                    rx.checkbox(id=\"bool_input\"),\n                    rx.switch(id=\"bool_input2\"),\n                    rx.checkbox(id=\"bool_input3\"),\n                    rx.switch(id=\"bool_input4\"),\n                    rx.slider(id=\"slider_input\", default_value=[50], width=\"100%\"),\n                    rx.radio([\"option1\", \"option2\"], id=\"radio_input\"),\n                    rx.radio(FormState.var_options, id=\"radio_input_var\"),\n                    rx.select(\n                        [\"option1\", \"option2\"],\n                        name=\"select_input\",\n                        default_value=\"option1\",\n                    ),\n                    rx.select(FormState.var_options, id=\"select_input_var\"),\n                    rx.text_area(id=\"text_area_input\"),\n                    rx.input(\n                        id=\"debounce_input\",\n                        debounce_timeout=0,\n                        on_change=rx.console_log,\n                    ),\n                    rx.button(\"Submit\", type_=\"submit\"),\n                ),\n                on_submit=FormState.form_submit,\n                custom_attrs={\"action\": \"/invalid\"},\n            ),\n            rx.spacer(),\n            height=\"100vh\",\n        )\n\n\ndef FormSubmitName(form_component):\n    \"\"\"App with a form using on_submit.\n\n    Args:\n        form_component: The str name of the form component to use.\n    \"\"\"\n    import reflex as rx\n\n    class FormState(rx.State):\n        form_data: dict = {}\n        val: str = \"foo\"\n        options: list[str] = [\"option1\", \"option2\"]\n\n        def form_submit(self, form_data: dict):\n            self.form_data = form_data\n\n    app = rx.App()\n\n    @app.add_page\n    def index():\n        return rx.vstack(\n            rx.input(\n                value=FormState.router.session.client_token,\n                is_read_only=True,\n                id=\"token\",\n            ),\n            eval(form_component)(\n                rx.vstack(\n                    rx.input(name=\"name_input\"),\n                    rx.checkbox(name=\"bool_input\"),\n                    rx.switch(name=\"bool_input2\"),\n                    rx.checkbox(name=\"bool_input3\"),\n                    rx.switch(name=\"bool_input4\"),\n                    rx.slider(name=\"slider_input\", default_value=[50], width=\"100%\"),\n                    rx.radio(FormState.options, name=\"radio_input\"),\n                    rx.select(\n                        FormState.options,\n                        name=\"select_input\",\n                        default_value=FormState.options[0],\n                    ),\n                    rx.text_area(name=\"text_area_input\"),\n                    rx.input(\n                        name=\"debounce_input\",\n                        debounce_timeout=0,\n                        on_change=rx.console_log,\n                    ),\n                    rx.button(\"Submit\", type_=\"submit\"),\n                    rx.icon_button(rx.icon(tag=\"plus\")),\n                ),\n                on_submit=FormState.form_submit,\n                custom_attrs={\"action\": \"/invalid\"},\n            ),\n            rx.spacer(),\n            height=\"100vh\",\n        )\n\n\n@pytest.fixture(\n    scope=\"module\",\n    params=[\n        functools.partial(FormSubmit, form_component=\"rx.form.root\"),\n        functools.partial(FormSubmitName, form_component=\"rx.form.root\"),\n        functools.partial(FormSubmit, form_component=\"rx.el.form\"),\n        functools.partial(FormSubmitName, form_component=\"rx.el.form\"),\n    ],\n    ids=[\n        \"id-radix\",\n        \"name-radix\",\n        \"id-html\",\n        \"name-html\",\n    ],\n)\ndef form_submit(request, tmp_path_factory) -> Generator[AppHarness, None, None]:\n    \"\"\"Start FormSubmit app at tmp_path via AppHarness.\n\n    Args:\n        request: pytest request fixture\n        tmp_path_factory: pytest tmp_path_factory fixture\n\n    Yields:\n        running AppHarness instance\n    \"\"\"\n    param_id = request._pyfuncitem.callspec.id.replace(\"-\", \"_\")\n    with AppHarness.create(\n        root=tmp_path_factory.mktemp(\"form_submit\"),\n        app_source=request.param,\n        app_name=request.param.func.__name__ + f\"_{param_id}\",\n    ) as harness:\n        assert harness.app_instance is not None, \"app is not running\"\n        yield harness\n\n\n@pytest.fixture\ndef driver(form_submit: AppHarness):\n    \"\"\"GEt an instance of the browser open to the form_submit app.\n\n    Args:\n        form_submit: harness for ServerSideEvent app\n\n    Yields:\n        WebDriver instance.\n    \"\"\"\n    driver = form_submit.frontend()\n    try:\n        yield driver\n    finally:\n        driver.quit()\n\n\n@pytest.mark.asyncio\nasync def test_submit(driver, form_submit: AppHarness):\n    \"\"\"Fill a form with various different output, submit it to backend and verify\n    the output.\n\n    Args:\n        driver: selenium WebDriver open to the app\n        form_submit: harness for FormSubmit app\n    \"\"\"\n    assert form_submit.app_instance is not None, \"app is not running\"\n    by = By.ID if form_submit.app_source is FormSubmit else By.NAME\n\n    # get a reference to the connected client\n    token_input = AppHarness.poll_for_or_raise_timeout(\n        lambda: driver.find_element(By.ID, \"token\")\n    )\n\n    # wait for the backend connection to send the token\n    token = form_submit.poll_for_value(token_input)\n    assert token\n\n    name_input = driver.find_element(by, \"name_input\")\n    name_input.send_keys(\"foo\")\n\n    checkbox_input = driver.find_element(By.XPATH, \"//button[@role='checkbox']\")\n    checkbox_input.click()\n\n    switch_input = driver.find_element(By.XPATH, \"//button[@role='switch']\")\n    switch_input.click()\n\n    radio_buttons = driver.find_elements(By.XPATH, \"//button[@role='radio']\")\n    radio_buttons[1].click()\n\n    textarea_input = driver.find_element(By.TAG_NAME, \"textarea\")\n    textarea_input.send_keys(\"Some\", Keys.ENTER, \"Text\")\n\n    debounce_input = driver.find_element(by, \"debounce_input\")\n    debounce_input.send_keys(\"bar baz\")\n\n    await asyncio.sleep(1)\n\n    prev_url = driver.current_url\n\n    submit_input = driver.find_element(By.CLASS_NAME, \"rt-Button\")\n    submit_input.click()\n\n    state_name = form_submit.get_state_name(\"_form_state\")\n    full_state_name = form_submit.get_full_state_name([\"_form_state\"])\n\n    async def get_form_data():\n        return (\n            (await form_submit.get_state(f\"{token}_{full_state_name}\"))\n            .substates[state_name]\n            .form_data  # pyright: ignore[reportAttributeAccessIssue]\n        )\n\n    # wait for the form data to arrive at the backend\n    form_data = await AppHarness._poll_for_async(get_form_data)\n    assert isinstance(form_data, dict)\n\n    form_data = format.collect_form_dict_names(form_data)\n\n    print(form_data)\n\n    assert form_data[\"name_input\"] == \"foo\"\n    assert form_data[\"bool_input\"]\n    assert form_data[\"bool_input2\"]\n    assert not form_data.get(\"bool_input3\", False)\n    assert not form_data.get(\"bool_input4\", False)\n\n    assert form_data[\"slider_input\"] == \"50\"\n    assert form_data[\"radio_input\"] == \"option2\"\n    assert form_data[\"select_input\"] == \"option1\"\n    assert form_data[\"text_area_input\"] == \"Some\\nText\"\n    assert form_data[\"debounce_input\"] == \"bar baz\"\n\n    # submitting the form should NOT change the url (preventDefault on_submit event)\n    assert driver.current_url == prev_url\n"
  },
  {
    "path": "tests/integration/test_icon.py",
    "content": "\"\"\"Integration tests for the Icon component.\"\"\"\n\nfrom collections.abc import Generator\n\nimport pytest\nfrom selenium.webdriver.common.by import By\n\nfrom reflex.components.lucide.icon import LUCIDE_ICON_LIST\nfrom reflex.testing import AppHarness, WebDriver\n\n\ndef Icons():\n    import reflex as rx\n    from reflex.components.lucide.icon import LUCIDE_ICON_LIST\n\n    app = rx.App()\n\n    class State(rx.State):\n        \"\"\"State for the Icons app.\"\"\"\n\n        dynamic_icon: str = \"airplay\"\n\n    @app.add_page\n    def index():\n        return rx.vstack(\n            rx.el.input(\n                custom_attrs={\n                    \"id\": \"token\",\n                },\n                value=State.router.session.client_token,\n                is_read_only=True,\n            ),\n            rx.el.div(\n                rx.icon(State.dynamic_icon),\n                id=\"dynamic_icon\",\n            ),\n            *[\n                rx.el.div(\n                    rx.icon(icon_name),\n                    id=icon_name,\n                )\n                for icon_name in LUCIDE_ICON_LIST\n            ],\n        )\n\n\n@pytest.fixture(scope=\"module\")\ndef icons(\n    tmp_path_factory, app_harness_env: type[AppHarness]\n) -> Generator[AppHarness, None, None]:\n    \"\"\"Start Icons app at tmp_path via AppHarness.\n\n    Args:\n        tmp_path_factory: pytest tmp_path_factory fixture\n        app_harness_env: The AppHarness environment to use\n\n    Yields:\n        running AppHarness instance\n    \"\"\"\n    with app_harness_env.create(\n        root=tmp_path_factory.mktemp(\"icons\"),\n        app_source=Icons,\n    ) as harness:\n        assert harness.app_instance is not None, \"app is not running\"\n        yield harness\n\n\n@pytest.fixture\ndef driver(icons: AppHarness):\n    \"\"\"Get an instance of the browser open to the dynamic components app.\n\n    Args:\n        icons: AppHarness for the dynamic components\n\n    Yields:\n        WebDriver instance.\n    \"\"\"\n    driver = icons.frontend()\n    try:\n        token_input = AppHarness.poll_for_or_raise_timeout(\n            lambda: driver.find_element(By.ID, \"token\")\n        )\n        # wait for the backend connection to send the token\n        token = icons.poll_for_value(token_input)\n        assert token is not None\n\n        yield driver\n    finally:\n        driver.quit()\n\n\ndef test_icons(driver: WebDriver, icons: AppHarness):\n    \"\"\"Test that the var operations produce the right results.\n\n    Args:\n        driver: selenium WebDriver open to the app\n        icons: AppHarness for the dynamic components\n    \"\"\"\n    for icon_name in [*LUCIDE_ICON_LIST, \"dynamic_icon\"]:\n        AppHarness.expect(\n            lambda icon_name=icon_name: driver.find_element(\n                By.ID, icon_name\n            ).find_element(By.TAG_NAME, \"svg\")\n        )\n"
  },
  {
    "path": "tests/integration/test_input.py",
    "content": "\"\"\"Integration tests for text input and related components.\"\"\"\n\nfrom collections.abc import Generator\n\nimport pytest\nfrom selenium.webdriver.common.by import By\nfrom selenium.webdriver.common.keys import Keys\n\nfrom reflex.testing import AppHarness\n\n\ndef FullyControlledInput():\n    \"\"\"App using a fully controlled input with implicit debounce wrapper.\"\"\"\n    import reflex as rx\n\n    class State(rx.State):\n        text: str = \"initial\"\n\n        @rx.event\n        def set_text(self, text: str):\n            self.text = text\n\n    app = rx.App()\n\n    @app.add_page\n    def index():\n        return rx.fragment(\n            rx.input(\n                value=State.router.session.client_token, is_read_only=True, id=\"token\"\n            ),\n            rx.input(\n                id=\"debounce_input_input\",\n                on_change=State.set_text,\n                value=State.text,\n            ),\n            rx.input(value=State.text, id=\"value_input\", is_read_only=True),\n            rx.input(on_change=State.set_text, id=\"on_change_input\"),\n            rx.el.input(\n                value=State.text,\n                id=\"plain_value_input\",\n                disabled=True,\n                _disabled={\"width\": \"42px\"},\n            ),\n            rx.input(default_value=\"default\", id=\"default_input\"),\n            rx.el.input(\n                type=\"text\", default_value=\"default plain\", id=\"plain_default_input\"\n            ),\n            rx.checkbox(default_checked=True, id=\"default_checkbox\"),\n            rx.el.input(\n                type=\"checkbox\", default_checked=True, id=\"plain_default_checkbox\"\n            ),\n            rx.button(\n                \"CLEAR\", on_click=rx.set_value(\"on_change_input\", \"\"), id=\"clear\"\n            ),\n        )\n\n\n@pytest.fixture\ndef fully_controlled_input(tmp_path) -> Generator[AppHarness, None, None]:\n    \"\"\"Start FullyControlledInput app at tmp_path via AppHarness.\n\n    Args:\n        tmp_path: pytest tmp_path fixture\n\n    Yields:\n        running AppHarness instance\n    \"\"\"\n    with AppHarness.create(\n        root=tmp_path,\n        app_source=FullyControlledInput,\n    ) as harness:\n        yield harness\n\n\n@pytest.mark.asyncio\nasync def test_fully_controlled_input(fully_controlled_input: AppHarness):\n    \"\"\"Type text after moving cursor. Update text on backend.\n\n    Args:\n        fully_controlled_input: harness for FullyControlledInput app\n    \"\"\"\n    assert fully_controlled_input.app_instance is not None, \"app is not running\"\n    driver = fully_controlled_input.frontend()\n\n    # get a reference to the connected client\n    token_input = AppHarness.poll_for_or_raise_timeout(\n        lambda: driver.find_element(By.ID, \"token\")\n    )\n\n    # wait for the backend connection to send the token\n    token = fully_controlled_input.poll_for_value(token_input)\n    assert token\n\n    state_name = fully_controlled_input.get_state_name(\"_state\")\n    full_state_name = fully_controlled_input.get_full_state_name([\"_state\"])\n\n    async def get_state_text():\n        state = await fully_controlled_input.get_state(f\"{token}_{full_state_name}\")\n        return state.substates[state_name].text  # pyright: ignore[reportAttributeAccessIssue]\n\n    # ensure defaults are set correctly\n    assert (\n        fully_controlled_input.poll_for_value(\n            driver.find_element(By.ID, \"default_input\")\n        )\n        == \"default\"\n    )\n    assert (\n        fully_controlled_input.poll_for_value(\n            driver.find_element(By.ID, \"plain_default_input\")\n        )\n        == \"default plain\"\n    )\n    assert (\n        fully_controlled_input.poll_for_value(\n            driver.find_element(By.ID, \"default_checkbox\")\n        )\n        == \"on\"\n    )\n    assert (\n        fully_controlled_input.poll_for_value(\n            driver.find_element(By.ID, \"plain_default_checkbox\")\n        )\n        == \"on\"\n    )\n\n    # find the input and wait for it to have the initial state value\n    debounce_input = driver.find_element(By.ID, \"debounce_input_input\")\n    value_input = driver.find_element(By.ID, \"value_input\")\n    on_change_input = driver.find_element(By.ID, \"on_change_input\")\n    plain_value_input = driver.find_element(By.ID, \"plain_value_input\")\n    clear_button = driver.find_element(By.ID, \"clear\")\n    assert fully_controlled_input.poll_for_value(debounce_input) == \"initial\"\n    assert fully_controlled_input.poll_for_value(value_input) == \"initial\"\n    assert fully_controlled_input.poll_for_value(plain_value_input) == \"initial\"\n    assert plain_value_input.value_of_css_property(\"width\") == \"42px\"\n\n    # move cursor to home, then to the right and type characters\n    debounce_input.send_keys(*([Keys.ARROW_LEFT] * len(\"initial\")), Keys.ARROW_RIGHT)\n    debounce_input.send_keys(\"foo\")\n    AppHarness.expect(\n        lambda: fully_controlled_input.poll_for_value(value_input) == \"ifoonitial\"\n    )\n    assert debounce_input.get_attribute(\"value\") == \"ifoonitial\"\n    assert await get_state_text() == \"ifoonitial\"\n    assert fully_controlled_input.poll_for_value(plain_value_input) == \"ifoonitial\"\n\n    # clear the input on the backend\n    async with fully_controlled_input.modify_state(\n        f\"{token}_{full_state_name}\"\n    ) as state:\n        state.substates[state_name].text = \"\"\n    assert await get_state_text() == \"\"\n    assert (\n        fully_controlled_input.poll_for_value(\n            debounce_input, exp_not_equal=\"ifoonitial\"\n        )\n        == \"\"\n    )\n\n    # type more characters\n    debounce_input.send_keys(\"getting testing done\")\n    AppHarness.expect(\n        lambda: (\n            fully_controlled_input.poll_for_value(value_input) == \"getting testing done\"\n        )\n    )\n    assert debounce_input.get_attribute(\"value\") == \"getting testing done\"\n    assert await get_state_text() == \"getting testing done\"\n    assert (\n        fully_controlled_input.poll_for_value(plain_value_input)\n        == \"getting testing done\"\n    )\n\n    # type into the on_change input\n    on_change_input.send_keys(\"overwrite the state\")\n    AppHarness.expect(\n        lambda: (\n            fully_controlled_input.poll_for_value(value_input) == \"overwrite the state\"\n        )\n    )\n    assert debounce_input.get_attribute(\"value\") == \"overwrite the state\"\n    assert on_change_input.get_attribute(\"value\") == \"overwrite the state\"\n    assert await get_state_text() == \"overwrite the state\"\n    assert (\n        fully_controlled_input.poll_for_value(plain_value_input)\n        == \"overwrite the state\"\n    )\n\n    clear_button.click()\n    AppHarness.expect(lambda: on_change_input.get_attribute(\"value\") == \"\")\n    # potential bug: clearing the on_change field doesn't itself trigger on_change\n    # assert backend_state.text == \"\" #noqa: ERA001\n    # assert debounce_input.get_attribute(\"value\") == \"\" #noqa: ERA001\n    # assert value_input.get_attribute(\"value\") == \"\" #noqa: ERA001\n"
  },
  {
    "path": "tests/integration/test_large_state.py",
    "content": "\"\"\"Test large state.\"\"\"\n\nimport time\n\nimport pytest\nfrom selenium.webdriver.common.by import By\n\nfrom reflex.testing import AppHarness, WebDriver\n\n\ndef _large_state_app_template(var_count: int) -> str:\n    var_part = \"\\n\".join(\n        f'    var{i}: str = \"{i}\" * 10000' for i in range(1, var_count)\n    )\n    return f\"\"\"\nimport reflex as rx\n\nclass State(rx.State):\n    var0: int = 0\n    {var_part}\n\n    def increment_var0(self):\n        self.var0 += 1\n\n\ndef index() -> rx.Component:\n    return rx.box(rx.button(State.var0, on_click=State.increment_var0, id=\"button\"))\n\napp = rx.App()\napp.add_page(index)\n\"\"\"\n\n\ndef get_driver(large_state) -> WebDriver:\n    \"\"\"Get an instance of the browser open to the large_state app.\n\n    Args:\n        large_state: harness for LargeState app\n\n    Returns:\n        WebDriver instance.\n    \"\"\"\n    assert large_state.app_instance is not None, \"app is not running\"\n    return large_state.frontend()\n\n\n@pytest.mark.parametrize(\"var_count\", [1, 10, 100, 1000, 10000])\ndef test_large_state(var_count: int, tmp_path_factory, benchmark):\n    \"\"\"Measure how long it takes for button click => state update to round trip.\n\n    Args:\n        var_count: number of variables to store in the state\n        tmp_path_factory: pytest fixture\n        benchmark: pytest fixture\n\n    Raises:\n        TimeoutError: if the state doesn't update within 30 seconds\n    \"\"\"\n    large_state_rendered = _large_state_app_template(var_count)\n\n    with AppHarness.create(\n        root=tmp_path_factory.mktemp(\"large_state\"),\n        app_source=large_state_rendered,\n        app_name=\"large_state\",\n    ) as large_state:\n        driver = get_driver(large_state)\n        try:\n            assert large_state.app_instance is not None\n            button = AppHarness.poll_for_or_raise_timeout(\n                lambda: driver.find_element(By.ID, \"button\")\n            )\n\n            t = time.time()\n            while button.text != \"0\":\n                time.sleep(0.1)\n                if time.time() - t > 30.0:\n                    msg = \"Timeout waiting for initial state\"\n                    raise TimeoutError(msg)\n\n            times_clicked = 0\n\n            def round_trip(clicks: int, timeout: float):\n                t = time.time()\n                for _ in range(clicks):\n                    button.click()\n                nonlocal times_clicked\n                times_clicked += clicks\n                while button.text != str(times_clicked):\n                    time.sleep(0.005)\n                    if time.time() - t > timeout:\n                        msg = \"Timeout waiting for state update\"\n                        raise TimeoutError(msg)\n\n            benchmark(round_trip, clicks=10, timeout=30.0)\n        finally:\n            driver.quit()\n"
  },
  {
    "path": "tests/integration/test_lifespan.py",
    "content": "\"\"\"Test cases for the Starlette lifespan integration.\"\"\"\n\nimport functools\nfrom collections.abc import Generator\n\nimport pytest\nfrom selenium.webdriver.common.by import By\n\nfrom reflex.testing import AppHarness\n\nfrom .utils import SessionStorage\n\npytest.importorskip(\"fastapi\")\n\n\ndef LifespanApp(\n    mount_cached_fastapi: bool = False, mount_api_transformer: bool = False\n) -> None:\n    \"\"\"App with lifespan tasks and context.\n\n    Args:\n        mount_cached_fastapi: Whether to mount the cached FastAPI app.\n        mount_api_transformer: Whether to mount the API transformer.\n    \"\"\"\n    import asyncio\n    from contextlib import asynccontextmanager\n\n    import reflex as rx\n\n    lifespan_task_global = 0\n    lifespan_context_global = 0\n\n    @asynccontextmanager\n    async def lifespan_context(app, inc: int = 1):  # noqa: RUF029\n        global lifespan_context_global\n        print(f\"Lifespan context entered: {app}.\")\n        lifespan_context_global += inc  # pyright: ignore[reportUnboundVariable]\n        try:\n            yield\n        finally:\n            print(\"Lifespan context exited.\")\n            lifespan_context_global += inc\n\n    async def lifespan_task(inc: int = 1):\n        global lifespan_task_global\n        print(\"Lifespan global started.\")\n        try:\n            while True:\n                lifespan_task_global += inc  # pyright: ignore[reportUnboundVariable, reportPossiblyUnboundVariable]\n                await asyncio.sleep(0.1)\n        except asyncio.CancelledError as ce:\n            print(f\"Lifespan global cancelled: {ce}.\")\n            lifespan_task_global = 0\n\n    class LifespanState(rx.State):\n        interval: int = 100\n\n        @rx.event\n        def set_interval(self, interval: int):\n            self.interval = interval\n\n        @rx.var(cache=False)\n        def task_global(self) -> int:\n            return lifespan_task_global\n\n        @rx.var(cache=False)\n        def context_global(self) -> int:\n            return lifespan_context_global\n\n        @rx.event\n        def tick(self, date):\n            pass\n\n    def index():\n        return rx.vstack(\n            rx.text(LifespanState.task_global, id=\"task_global\"),\n            rx.text(LifespanState.context_global, id=\"context_global\"),\n            rx.button(\n                rx.moment(\n                    interval=LifespanState.interval, on_change=LifespanState.tick\n                ),\n                on_click=LifespanState.set_interval(\n                    rx.cond(LifespanState.interval, 0, 100)\n                ),\n                id=\"toggle-tick\",\n            ),\n        )\n\n    from fastapi import FastAPI\n\n    app = rx.App(api_transformer=FastAPI() if mount_api_transformer else None)\n\n    if mount_cached_fastapi:\n        assert app._api is not None\n\n    app.register_lifespan_task(lifespan_task)\n    app.register_lifespan_task(lifespan_context, inc=2)\n    app.add_page(index)\n\n\n@pytest.fixture(\n    scope=\"session\",\n    params=[False, True],\n    ids=[\"no_api_transformer\", \"mount_api_transformer\"],\n)\ndef mount_api_transformer(request: pytest.FixtureRequest) -> bool:\n    \"\"\"Whether to use api_transformer in the app.\n\n    Args:\n        request: pytest fixture request object\n\n    Returns:\n        bool: Whether to use api_transformer\n    \"\"\"\n    return request.param\n\n\n@pytest.fixture(\n    scope=\"session\", params=[False, True], ids=[\"no_fastapi\", \"mount_cached_fastapi\"]\n)\ndef mount_cached_fastapi(request: pytest.FixtureRequest) -> bool:\n    \"\"\"Whether to use cached FastAPI in the app (app.api).\n\n    Args:\n        request: pytest fixture request object\n\n    Returns:\n        Whether to use cached FastAPI\n    \"\"\"\n    return request.param\n\n\n@pytest.fixture(scope=\"session\")\ndef lifespan_app(\n    tmp_path_factory: pytest.TempPathFactory,\n    app_harness_env: type[AppHarness],\n    mount_api_transformer: bool,\n    mount_cached_fastapi: bool,\n) -> Generator[AppHarness, None, None]:\n    \"\"\"Start LifespanApp app at tmp_path via AppHarness.\n\n    Args:\n        tmp_path_factory: pytest tmp_path_factory fixture\n        app_harness_env: AppHarness environment\n        mount_api_transformer: Whether to mount the API transformer.\n        mount_cached_fastapi: Whether to mount the cached FastAPI app.\n\n    Yields:\n        running AppHarness instance\n    \"\"\"\n    with app_harness_env.create(\n        root=tmp_path_factory.mktemp(\"lifespan_app\"),\n        app_source=functools.partial(\n            LifespanApp,\n            mount_cached_fastapi=mount_cached_fastapi,\n            mount_api_transformer=mount_api_transformer,\n        ),\n        app_name=f\"lifespanapp_fastapi{mount_cached_fastapi}_transformer{mount_api_transformer}\",\n    ) as harness:\n        yield harness\n\n\ndef test_lifespan(lifespan_app: AppHarness):\n    \"\"\"Test the lifespan integration.\n\n    Args:\n        lifespan_app: harness for LifespanApp app\n    \"\"\"\n    assert lifespan_app.app_module is not None, \"app module is not found\"\n    assert lifespan_app.app_instance is not None, \"app is not running\"\n    driver = lifespan_app.frontend()\n\n    ss = SessionStorage(driver)\n    assert AppHarness._poll_for(lambda: ss.get(\"token\") is not None), \"token not found\"\n\n    context_global = driver.find_element(By.ID, \"context_global\")\n    task_global = driver.find_element(By.ID, \"task_global\")\n\n    assert lifespan_app.poll_for_content(context_global, exp_not_equal=\"0\") == \"2\"\n    assert lifespan_app.app_module.lifespan_context_global == 2\n\n    original_task_global_text = task_global.text\n    original_task_global_value = int(original_task_global_text)\n    lifespan_app.poll_for_content(task_global, exp_not_equal=original_task_global_text)\n    driver.find_element(By.ID, \"toggle-tick\").click()  # avoid teardown errors\n    assert lifespan_app.app_module.lifespan_task_global > original_task_global_value\n    assert int(task_global.text) > original_task_global_value\n\n    # Kill the backend\n    assert lifespan_app.backend is not None\n    lifespan_app.backend.should_exit = True\n    if lifespan_app.backend_thread is not None:\n        lifespan_app.backend_thread.join()\n\n    # Check that the lifespan tasks have been cancelled\n    assert lifespan_app.app_module.lifespan_task_global == 0\n    assert lifespan_app.app_module.lifespan_context_global == 4\n"
  },
  {
    "path": "tests/integration/test_linked_state.py",
    "content": "\"\"\"Test linked state.\"\"\"\n\nfrom __future__ import annotations\n\nimport uuid\nfrom collections.abc import Callable, Generator\n\nimport pytest\nfrom selenium.webdriver.common.by import By\nfrom selenium.webdriver.common.keys import Keys\n\nfrom reflex.testing import AppHarness, WebDriver\n\nfrom . import utils\n\n\ndef LinkedStateApp():\n    \"\"\"Test that linked state works as expected.\"\"\"\n    import uuid\n    from typing import Any\n\n    import reflex as rx\n\n    class SharedState(rx.SharedState):\n        _who: str = \"world\"\n        n_changes: int = 0\n        counter: int = 0\n\n        @rx.event\n        def set_counter(self, value: int) -> None:\n            self.counter = value\n\n        @rx.event\n        def set_who(self, who: str) -> None:\n            self._who = who\n            self.n_changes += 1\n\n        @rx.event\n        async def link_to(self, token: str):\n            await self._link_to(token)\n\n        @rx.event\n        async def link_to_and_increment(self):\n            linked_state = await self._link_to(f\"arbitrary-token-{uuid.uuid4()}\")\n            linked_state.counter += 1\n\n        @rx.event\n        async def unlink(self):\n            return await self._unlink()\n\n        @rx.event\n        async def on_load_link_default(self):\n            linked_state = await self._link_to(self.room or \"default\")  # pyright: ignore[reportAttributeAccessIssue]\n            if self.room:  # pyright: ignore[reportAttributeAccessIssue]\n                assert linked_state._linked_to == self.room  # pyright: ignore[reportAttributeAccessIssue]\n            else:\n                assert linked_state._linked_to == \"default\"\n\n        @rx.event\n        async def handle_submit(self, form_data: dict[str, Any]):\n            if \"who\" in form_data:\n                self.set_who(form_data[\"who\"])\n            if \"token\" in form_data:\n                await self.link_to(form_data[\"token\"])\n\n    class PrivateState(rx.State):\n        @rx.var\n        async def greeting(self) -> str:\n            ss = await self.get_state(SharedState)\n            return f\"Hello, {ss._who}!\"\n\n        @rx.var\n        async def linked_to(self) -> str:\n            ss = await self.get_state(SharedState)\n            return ss._linked_to\n\n        @rx.event(background=True)\n        async def bump_counter_bg(self):\n            for _ in range(5):\n                async with self:\n                    ss = await self.get_state(SharedState)\n                    ss.counter += 1\n            async with self:\n                ss = await self.get_state(SharedState)\n            for _ in range(5):\n                async with ss:\n                    ss.counter += 1\n\n        @rx.event\n        async def bump_counter_yield(self):\n            ss = await self.get_state(SharedState)\n            for _ in range(5):\n                ss.counter += 1\n                yield\n\n    def index() -> rx.Component:\n        return rx.vstack(\n            rx.text(\n                SharedState.n_changes,\n                id=\"n-changes\",\n            ),\n            rx.text(\n                PrivateState.greeting,\n                id=\"greeting\",\n            ),\n            rx.form(\n                rx.input(name=\"who\", id=\"who-input\"),\n                rx.button(\"Set Who\"),\n                on_submit=SharedState.handle_submit,\n                reset_on_submit=True,\n            ),\n            rx.text(PrivateState.linked_to, id=\"linked-to\"),\n            rx.button(\"Unlink\", id=\"unlink-button\", on_click=SharedState.unlink),\n            rx.form(\n                rx.input(name=\"token\", id=\"token-input\"),\n                rx.button(\"Link To Token\"),\n                on_submit=SharedState.handle_submit,\n                reset_on_submit=True,\n            ),\n            rx.button(\n                SharedState.counter,\n                id=\"counter-button\",\n                on_click=SharedState.set_counter(SharedState.counter + 1),\n                on_context_menu=SharedState.set_counter(\n                    SharedState.counter - 1\n                ).prevent_default,\n            ),\n            rx.button(\n                \"Bump Counter in Background\",\n                on_click=PrivateState.bump_counter_bg,\n                id=\"bg-button\",\n            ),\n            rx.button(\n                \"Bump Counter with Yield\",\n                on_click=PrivateState.bump_counter_yield,\n                id=\"yield-button\",\n            ),\n            rx.button(\n                \"Link to arbitrary token and Increment n_changes\",\n                on_click=SharedState.link_to_and_increment,\n                id=\"link-increment-button\",\n            ),\n        )\n\n    app = rx.App()\n    app.add_page(index, route=\"/room/[room]\", on_load=SharedState.on_load_link_default)\n    app.add_page(index)\n\n\n@pytest.fixture\ndef linked_state(\n    tmp_path_factory,\n) -> Generator[AppHarness, None, None]:\n    \"\"\"Start LinkedStateApp at tmp_path via AppHarness.\n\n    Args:\n        tmp_path_factory: pytest tmp_path_factory fixture\n\n    Yields:\n        running AppHarness instance\n\n    \"\"\"\n    with AppHarness.create(\n        root=tmp_path_factory.mktemp(\"linked_state\"),\n        app_source=LinkedStateApp,\n    ) as harness:\n        yield harness\n\n\n@pytest.fixture\ndef tab_factory(\n    linked_state: AppHarness,\n) -> Generator[Callable[[], WebDriver], None, None]:\n    \"\"\"Get an instance of the browser open to the linked_state app.\n\n    Args:\n        linked_state: harness for LinkedStateApp\n\n    Yields:\n        WebDriver instance.\n\n    \"\"\"\n    assert linked_state.app_instance is not None, \"app is not running\"\n\n    drivers = []\n\n    def driver() -> WebDriver:\n        d = linked_state.frontend()\n        drivers.append(d)\n        return d\n\n    try:\n        yield driver\n    finally:\n        for d in drivers:\n            d.quit()\n\n\ndef test_linked_state(\n    linked_state: AppHarness,\n    tab_factory: Callable[[], WebDriver],\n):\n    \"\"\"Test that multiple tabs can link to and share state.\n\n    Args:\n        linked_state: harness for LinkedStateApp.\n        tab_factory: factory to create WebDriver instances.\n\n    \"\"\"\n    assert linked_state.app_instance is not None\n\n    tab1 = tab_factory()\n    tab2 = tab_factory()\n    ss = utils.SessionStorage(tab1)\n    assert AppHarness._poll_for(lambda: ss.get(\"token\") is not None), \"token not found\"\n    n_changes_1 = tab1.find_element(By.ID, \"n-changes\")\n    greeting_1 = tab1.find_element(By.ID, \"greeting\")\n    ss = utils.SessionStorage(tab2)\n    assert AppHarness._poll_for(lambda: ss.get(\"token\") is not None), \"token not found\"\n    n_changes_2 = tab2.find_element(By.ID, \"n-changes\")\n    greeting_2 = tab2.find_element(By.ID, \"greeting\")\n\n    # Initial state\n    assert n_changes_1.text == \"0\"\n    assert greeting_1.text == \"Hello, world!\"\n    assert n_changes_2.text == \"0\"\n    assert greeting_2.text == \"Hello, world!\"\n\n    # Change state in tab 1\n    tab1.find_element(By.ID, \"who-input\").send_keys(\"Alice\", Keys.ENTER)\n    assert linked_state.poll_for_content(n_changes_1, exp_not_equal=\"0\") == \"1\"\n    assert (\n        linked_state.poll_for_content(greeting_1, exp_not_equal=\"Hello, world!\")\n        == \"Hello, Alice!\"\n    )\n\n    # Change state in tab 2\n    tab2.find_element(By.ID, \"who-input\").send_keys(\"Bob\", Keys.ENTER)\n    assert linked_state.poll_for_content(n_changes_2, exp_not_equal=\"0\") == \"1\"\n    assert (\n        linked_state.poll_for_content(greeting_2, exp_not_equal=\"Hello, world!\")\n        == \"Hello, Bob!\"\n    )\n\n    # Link both tabs to the same token, \"shared-foo\"\n    shared_token = f\"shared-foo-{uuid.uuid4()}\"\n    for tab in (tab1, tab2):\n        tab.find_element(By.ID, \"token-input\").send_keys(shared_token, Keys.ENTER)\n    assert linked_state.poll_for_content(n_changes_1, exp_not_equal=\"1\") == \"0\"\n    assert (\n        linked_state.poll_for_content(greeting_1, exp_not_equal=\"Hello, Alice!\")\n        == \"Hello, world!\"\n    )\n    assert linked_state.poll_for_content(n_changes_2, exp_not_equal=\"1\") == \"0\"\n    assert (\n        linked_state.poll_for_content(greeting_2, exp_not_equal=\"Hello, Bob!\")\n        == \"Hello, world!\"\n    )\n\n    # Set a new value in tab 1, should reflect in tab 2\n    tab1.find_element(By.ID, \"who-input\").send_keys(\"Charlie\", Keys.ENTER)\n    assert linked_state.poll_for_content(n_changes_1, exp_not_equal=\"0\") == \"1\"\n    assert (\n        linked_state.poll_for_content(greeting_1, exp_not_equal=\"Hello, world!\")\n        == \"Hello, Charlie!\"\n    )\n    assert linked_state.poll_for_content(n_changes_2, exp_not_equal=\"0\") == \"1\"\n    assert (\n        linked_state.poll_for_content(greeting_2, exp_not_equal=\"Hello, world!\")\n        == \"Hello, Charlie!\"\n    )\n\n    # Bump the counter in tab 2, should reflect in tab 1\n    counter_button_1 = tab1.find_element(By.ID, \"counter-button\")\n    counter_button_2 = tab2.find_element(By.ID, \"counter-button\")\n    assert counter_button_1.text == \"0\"\n    assert counter_button_2.text == \"0\"\n    counter_button_2.click()\n    assert linked_state.poll_for_content(counter_button_1, exp_not_equal=\"0\") == \"1\"\n    assert linked_state.poll_for_content(counter_button_2, exp_not_equal=\"0\") == \"1\"\n    counter_button_1.click()\n    assert linked_state.poll_for_content(counter_button_1, exp_not_equal=\"1\") == \"2\"\n    assert linked_state.poll_for_content(counter_button_2, exp_not_equal=\"1\") == \"2\"\n    counter_button_2.click()\n    assert linked_state.poll_for_content(counter_button_1, exp_not_equal=\"2\") == \"3\"\n    assert linked_state.poll_for_content(counter_button_2, exp_not_equal=\"2\") == \"3\"\n\n    # Unlink tab 2, should revert to previous private values\n    tab2.find_element(By.ID, \"unlink-button\").click()\n    assert n_changes_2.text == \"1\"\n    assert (\n        linked_state.poll_for_content(greeting_2, exp_not_equal=\"Hello, Charlie!\")\n        == \"Hello, Bob!\"\n    )\n    assert linked_state.poll_for_content(counter_button_2, exp_not_equal=\"3\") == \"0\"\n\n    # Relink tab 2, should go back to shared values\n    tab2.find_element(By.ID, \"token-input\").send_keys(shared_token, Keys.ENTER)\n    assert n_changes_2.text == \"1\"\n    assert (\n        linked_state.poll_for_content(greeting_2, exp_not_equal=\"Hello, Bob!\")\n        == \"Hello, Charlie!\"\n    )\n    assert linked_state.poll_for_content(counter_button_2, exp_not_equal=\"0\") == \"3\"\n\n    # Unlink tab 1, change the shared value in tab 2, and relink tab 1\n    tab1.find_element(By.ID, \"unlink-button\").click()\n    assert n_changes_1.text == \"1\"\n    assert (\n        linked_state.poll_for_content(greeting_1, exp_not_equal=\"Hello, Charlie!\")\n        == \"Hello, Alice!\"\n    )\n    tab2.find_element(By.ID, \"who-input\").send_keys(\"Diana\", Keys.ENTER)\n    assert linked_state.poll_for_content(n_changes_2, exp_not_equal=\"1\") == \"2\"\n    assert (\n        linked_state.poll_for_content(greeting_2, exp_not_equal=\"Hello, Charlie!\")\n        == \"Hello, Diana!\"\n    )\n    assert counter_button_2.text == \"3\"\n    assert n_changes_1.text == \"1\"\n    assert greeting_1.text == \"Hello, Alice!\"\n    tab1.find_element(By.ID, \"token-input\").send_keys(shared_token, Keys.ENTER)\n    assert linked_state.poll_for_content(n_changes_1, exp_not_equal=\"1\") == \"2\"\n    assert (\n        linked_state.poll_for_content(greeting_1, exp_not_equal=\"Hello, Alice!\")\n        == \"Hello, Diana!\"\n    )\n    assert linked_state.poll_for_content(counter_button_1, exp_not_equal=\"0\") == \"3\"\n\n    # Open a third tab linked to the shared token on_load\n    tab3 = tab_factory()\n    tab3.get(f\"{linked_state.frontend_url}room/{shared_token}\")\n    ss = utils.SessionStorage(tab3)\n    assert AppHarness._poll_for(lambda: ss.get(\"token\") is not None), \"token not found\"\n    n_changes_3 = AppHarness._poll_for(lambda: tab3.find_element(By.ID, \"n-changes\"))\n    assert n_changes_3\n    greeting_3 = tab3.find_element(By.ID, \"greeting\")\n    counter_button_3 = tab3.find_element(By.ID, \"counter-button\")\n    assert linked_state.poll_for_content(n_changes_3, exp_not_equal=\"0\") == \"2\"\n    assert (\n        linked_state.poll_for_content(greeting_3, exp_not_equal=\"Hello, world!\")\n        == \"Hello, Diana!\"\n    )\n    assert linked_state.poll_for_content(counter_button_3, exp_not_equal=\"0\") == \"3\"\n    assert tab3.find_element(By.ID, \"linked-to\").text == shared_token\n\n    # Trigger a background task in all shared states, assert on final value\n    tab1.find_element(By.ID, \"bg-button\").click()\n    tab2.find_element(By.ID, \"bg-button\").click()\n    tab3.find_element(By.ID, \"bg-button\").click()\n    assert AppHarness._poll_for(lambda: counter_button_1.text == \"33\")\n    assert AppHarness._poll_for(lambda: counter_button_2.text == \"33\")\n    assert AppHarness._poll_for(lambda: counter_button_3.text == \"33\")\n\n    # Trigger a yield-based task in all shared states, assert on final value\n    tab1.find_element(By.ID, \"yield-button\").click()\n    tab2.find_element(By.ID, \"yield-button\").click()\n    tab3.find_element(By.ID, \"yield-button\").click()\n    assert AppHarness._poll_for(lambda: counter_button_1.text == \"48\")\n    assert AppHarness._poll_for(lambda: counter_button_2.text == \"48\")\n    assert AppHarness._poll_for(lambda: counter_button_3.text == \"48\")\n\n    # Link to a new token when we're already linked\n    new_shared_token = f\"shared-bar-{uuid.uuid4()}\"\n    tab1.find_element(By.ID, \"token-input\").send_keys(new_shared_token, Keys.ENTER)\n    assert linked_state.poll_for_content(n_changes_1, exp_not_equal=\"2\") == \"0\"\n    assert (\n        linked_state.poll_for_content(greeting_1, exp_not_equal=\"Hello, Diana!\")\n        == \"Hello, world!\"\n    )\n    assert linked_state.poll_for_content(counter_button_1, exp_not_equal=\"48\") == \"0\"\n    counter_button_1.click()\n    assert linked_state.poll_for_content(counter_button_1, exp_not_equal=\"0\") == \"1\"\n    counter_button_1.click()\n    assert linked_state.poll_for_content(counter_button_1, exp_not_equal=\"1\") == \"2\"\n    counter_button_1.click()\n    assert linked_state.poll_for_content(counter_button_1, exp_not_equal=\"2\") == \"3\"\n    # Ensure other tabs are unaffected\n    assert n_changes_2.text == \"2\"\n    assert greeting_2.text == \"Hello, Diana!\"\n    assert counter_button_2.text == \"48\"\n    assert n_changes_3.text == \"2\"\n    assert greeting_3.text == \"Hello, Diana!\"\n    assert counter_button_3.text == \"48\"\n\n    # Link to a new state and increment the counter in the same event\n    tab1.find_element(By.ID, \"link-increment-button\").click()\n    assert linked_state.poll_for_content(counter_button_1, exp_not_equal=\"3\") == \"1\"\n"
  },
  {
    "path": "tests/integration/test_login_flow.py",
    "content": "\"\"\"Integration tests for client side storage.\"\"\"\n\nfrom __future__ import annotations\n\nfrom collections.abc import Generator\n\nimport pytest\nfrom selenium.common.exceptions import NoSuchElementException\nfrom selenium.webdriver.common.by import By\nfrom selenium.webdriver.remote.webdriver import WebDriver\n\nfrom reflex.constants.state import FIELD_MARKER\nfrom reflex.testing import AppHarness\n\nfrom . import utils\n\n\ndef LoginSample():\n    \"\"\"Sample app for testing login/logout with LocalStorage var.\"\"\"\n    import reflex as rx\n\n    class State(rx.State):\n        auth_token: str = rx.LocalStorage(\"\")\n\n        @rx.event\n        def set_auth_token(self, token: str):\n            self.auth_token = token\n\n        @rx.event\n        def logout(self):\n            self.set_auth_token(\"\")\n\n        @rx.event\n        def login(self):\n            self.set_auth_token(\"12345\")\n            yield rx.redirect(\"/\")\n\n    def index():\n        return rx.cond(  # pyright: ignore [reportCallIssue]\n            State.is_hydrated & State.auth_token,  # pyright: ignore [reportOperatorIssue]\n            rx.vstack(\n                rx.heading(State.auth_token, id=\"auth-token\"),\n                rx.button(\"Logout\", on_click=State.logout, id=\"logout\"),\n            ),\n            rx.button(\"Login\", on_click=rx.redirect(\"/login\"), id=\"login\"),\n        )\n\n    def login():\n        return rx.vstack(\n            rx.button(\"Do it\", on_click=State.login, id=\"doit\"),\n        )\n\n    app = rx.App()\n    app.add_page(index)\n    app.add_page(login)\n\n\n@pytest.fixture(scope=\"module\")\ndef login_sample(tmp_path_factory) -> Generator[AppHarness, None, None]:\n    \"\"\"Start LoginSample app at tmp_path via AppHarness.\n\n    Args:\n        tmp_path_factory: pytest tmp_path_factory fixture\n\n    Yields:\n        running AppHarness instance\n    \"\"\"\n    with AppHarness.create(\n        root=tmp_path_factory.mktemp(\"login_sample\"),\n        app_source=LoginSample,\n    ) as harness:\n        yield harness\n\n\n@pytest.fixture\ndef driver(login_sample: AppHarness) -> Generator[WebDriver, None, None]:\n    \"\"\"Get an instance of the browser open to the login_sample app.\n\n    Args:\n        login_sample: harness for LoginSample app\n\n    Yields:\n        WebDriver instance.\n    \"\"\"\n    assert login_sample.app_instance is not None, \"app is not running\"\n    driver = login_sample.frontend()\n    try:\n        yield driver\n    finally:\n        driver.quit()\n\n\n@pytest.fixture\ndef local_storage(driver: WebDriver) -> Generator[utils.LocalStorage, None, None]:\n    \"\"\"Get an instance of the local storage helper.\n\n    Args:\n        driver: WebDriver instance.\n\n    Yields:\n        Local storage helper.\n    \"\"\"\n    ls = utils.LocalStorage(driver)\n    yield ls\n    ls.clear()\n\n\ndef test_login_flow(\n    login_sample: AppHarness, driver: WebDriver, local_storage: utils.LocalStorage\n):\n    \"\"\"Test login flow.\n\n    Args:\n        login_sample: harness for LoginSample app.\n        driver: WebDriver instance.\n        local_storage: Local storage helper.\n    \"\"\"\n    assert login_sample.frontend_url is not None\n    local_storage.clear()\n\n    login_button = AppHarness.poll_for_or_raise_timeout(\n        lambda: driver.find_element(By.ID, \"login\")\n    )\n    with pytest.raises(NoSuchElementException):\n        driver.find_element(By.ID, \"auth-token\")\n\n    login_sample.poll_for_content(login_button)\n    with utils.poll_for_navigation(driver):\n        login_button.click()\n    assert driver.current_url.endswith(\"/login\")\n\n    do_it_button = driver.find_element(By.ID, \"doit\")\n    with utils.poll_for_navigation(driver):\n        do_it_button.click()\n    assert driver.current_url == login_sample.frontend_url\n\n    def check_auth_token_header():\n        try:\n            auth_token_header = driver.find_element(By.ID, \"auth-token\")\n        except NoSuchElementException:\n            return False\n        return auth_token_header.text\n\n    assert AppHarness.poll_for_or_raise_timeout(check_auth_token_header) == \"12345\"\n\n    logout_button = driver.find_element(By.ID, \"logout\")\n    logout_button.click()\n\n    state_name = login_sample.get_full_state_name([\"_state\"])\n    AppHarness.expect(\n        lambda: local_storage[f\"{state_name}.auth_token\" + FIELD_MARKER] == \"\"\n    )\n    with pytest.raises(NoSuchElementException):\n        driver.find_element(By.ID, \"auth-token\")\n"
  },
  {
    "path": "tests/integration/test_media.py",
    "content": "\"\"\"Integration tests for media components.\"\"\"\n\nfrom collections.abc import Generator\n\nimport pytest\nfrom selenium.webdriver.common.by import By\n\nfrom reflex.testing import AppHarness\n\n\ndef MediaApp():\n    \"\"\"Reflex app with generated images.\"\"\"\n    import io\n\n    import httpx\n    from PIL import Image\n\n    import reflex as rx\n\n    class State(rx.State):\n        def _blue(self, format=None) -> Image.Image:\n            img = Image.new(\"RGB\", (200, 200), \"blue\")\n            if format is not None:\n                img.format = format\n            return img\n\n        @rx.var\n        def img_default(self) -> Image.Image:\n            return self._blue()\n\n        @rx.var\n        def img_bmp(self) -> Image.Image:\n            return self._blue(format=\"BMP\")\n\n        @rx.var\n        def img_jpg(self) -> Image.Image:\n            return self._blue(format=\"JPEG\")\n\n        @rx.var\n        def img_png(self) -> Image.Image:\n            return self._blue(format=\"PNG\")\n\n        @rx.var\n        def img_gif(self) -> Image.Image:\n            return self._blue(format=\"GIF\")\n\n        @rx.var\n        def img_webp(self) -> Image.Image:\n            return self._blue(format=\"WEBP\")\n\n        @rx.var\n        def img_from_url(self) -> Image.Image:\n            img_url = \"https://picsum.photos/id/1/200/300\"\n            img_resp = httpx.get(img_url, follow_redirects=True)\n            img_bytes = img_resp.content\n            return Image.open(io.BytesIO(img_bytes))\n\n    app = rx.App()\n\n    @app.add_page\n    def index():\n        return rx.vstack(\n            rx.input(\n                value=State.router.session.client_token,\n                read_only=True,\n                id=\"token\",\n            ),\n            rx.image(src=State.img_default, alt=\"Default image\", id=\"default\"),\n            rx.image(src=State.img_bmp, alt=\"BMP image\", id=\"bmp\"),\n            rx.image(src=State.img_jpg, alt=\"JPG image\", id=\"jpg\"),\n            rx.image(src=State.img_png, alt=\"PNG image\", id=\"png\"),\n            rx.image(src=State.img_gif, alt=\"GIF image\", id=\"gif\"),\n            rx.image(src=State.img_webp, alt=\"WEBP image\", id=\"webp\"),\n            rx.image(src=State.img_from_url, alt=\"Image from URL\", id=\"from_url\"),\n        )\n\n\n@pytest.fixture\ndef media_app(tmp_path) -> Generator[AppHarness, None, None]:\n    \"\"\"Start MediaApp app at tmp_path via AppHarness.\n\n    Args:\n        tmp_path: pytest tmp_path fixture\n\n    Yields:\n        running AppHarness instance\n    \"\"\"\n    with AppHarness.create(\n        root=tmp_path,\n        app_source=MediaApp,\n    ) as harness:\n        yield harness\n\n\ndef test_media_app(media_app: AppHarness):\n    \"\"\"Display images, ensure the data uri mime type is correct and images load.\n\n    Args:\n        media_app: harness for MediaApp app\n    \"\"\"\n    assert media_app.app_instance is not None, \"app is not running\"\n    driver = media_app.frontend()\n\n    # wait for the backend connection to send the token\n    token_input = AppHarness.poll_for_or_raise_timeout(\n        lambda: driver.find_element(By.ID, \"token\")\n    )\n    token = media_app.poll_for_value(token_input)\n    assert token\n\n    # check out the images\n    default_img = driver.find_element(By.ID, \"default\")\n    bmp_img = driver.find_element(By.ID, \"bmp\")\n    jpg_img = driver.find_element(By.ID, \"jpg\")\n    png_img = driver.find_element(By.ID, \"png\")\n    gif_img = driver.find_element(By.ID, \"gif\")\n    webp_img = driver.find_element(By.ID, \"webp\")\n    from_url_img = driver.find_element(By.ID, \"from_url\")\n\n    def check_image_loaded(img, check_width=\" == 200\", check_height=\" == 200\"):\n        return driver.execute_script(\n            \"console.log(arguments); return arguments[1].complete \"\n            '&& typeof arguments[1].naturalWidth != \"undefined\" '\n            f\"&& arguments[1].naturalWidth {check_width} \",\n            '&& typeof arguments[1].naturalHeight != \"undefined\" '\n            f\"&& arguments[1].naturalHeight {check_height} \",\n            img,\n        )\n\n    default_img_src = default_img.get_attribute(\"src\")\n    assert default_img_src is not None\n    assert default_img_src.startswith(\"data:image/png;base64\")\n    assert check_image_loaded(default_img)\n\n    bmp_img_src = bmp_img.get_attribute(\"src\")\n    assert bmp_img_src is not None\n    assert bmp_img_src.startswith(\"data:image/bmp;base64\")\n    assert check_image_loaded(bmp_img)\n\n    jpg_img_src = jpg_img.get_attribute(\"src\")\n    assert jpg_img_src is not None\n    assert jpg_img_src.startswith(\"data:image/jpeg;base64\")\n    assert check_image_loaded(jpg_img)\n\n    png_img_src = png_img.get_attribute(\"src\")\n    assert png_img_src is not None\n    assert png_img_src.startswith(\"data:image/png;base64\")\n    assert check_image_loaded(png_img)\n\n    gif_img_src = gif_img.get_attribute(\"src\")\n    assert gif_img_src is not None\n    assert gif_img_src.startswith(\"data:image/gif;base64\")\n    assert check_image_loaded(gif_img)\n\n    webp_img_src = webp_img.get_attribute(\"src\")\n    assert webp_img_src is not None\n    assert webp_img_src.startswith(\"data:image/webp;base64\")\n    assert check_image_loaded(webp_img)\n\n    from_url_img_src = from_url_img.get_attribute(\"src\")\n    assert from_url_img_src is not None\n    assert from_url_img_src.startswith(\"data:image/jpeg;base64\")\n    assert check_image_loaded(\n        from_url_img,\n        check_width=\" == 200\",\n        check_height=\" == 300\",\n    )\n"
  },
  {
    "path": "tests/integration/test_memo.py",
    "content": "\"\"\"Integration tests for rx.memo components.\"\"\"\n\nfrom collections.abc import Generator\n\nimport pytest\nfrom selenium.webdriver.common.by import By\n\nfrom reflex.testing import AppHarness\n\n\ndef MemoApp():\n    \"\"\"Reflex app with memo components.\"\"\"\n    import reflex as rx\n\n    class FooComponent(rx.Fragment):\n        def add_custom_code(self) -> list[str]:\n            return [\n                \"const foo = 'bar'\",\n            ]\n\n    @rx.memo\n    def foo_component(t: str):\n        return FooComponent.create(t, rx.Var(\"foo\"))\n\n    @rx.memo\n    def foo_component2(t: str):\n        return FooComponent.create(t, rx.Var(\"foo\"))\n\n    class MemoState(rx.State):\n        last_value: str = \"\"\n\n        @rx.event\n        def set_last_value(self, value: str):\n            self.last_value = value\n\n    @rx.memo\n    def my_memoed_component(\n        some_value: str,\n        event: rx.EventHandler[rx.event.passthrough_event_spec(str)],\n    ) -> rx.Component:\n        return rx.vstack(\n            rx.button(some_value, id=\"memo-button\", on_click=event(some_value)),\n            rx.input(id=\"memo-input\", on_change=event),\n        )\n\n    def index() -> rx.Component:\n        return rx.vstack(\n            rx.vstack(\n                foo_component(t=\"foo\"), foo_component2(t=\"bar\"), id=\"memo-custom-code\"\n            ),\n            rx.text(MemoState.last_value, id=\"memo-last-value\"),\n            my_memoed_component(\n                some_value=\"memod_some_value\", event=MemoState.set_last_value\n            ),\n        )\n\n    app = rx.App()\n    app.add_page(index)\n\n\n@pytest.fixture\ndef memo_app(tmp_path) -> Generator[AppHarness, None, None]:\n    \"\"\"Start MemoApp app at tmp_path via AppHarness.\n\n    Args:\n        tmp_path: pytest tmp_path fixture\n\n    Yields:\n        running AppHarness instance\n    \"\"\"\n    with AppHarness.create(\n        root=tmp_path,\n        app_source=MemoApp,\n    ) as harness:\n        yield harness\n\n\ndef test_memo_app(memo_app: AppHarness):\n    \"\"\"Render various memo'd components and assert on the output.\n\n    Args:\n        memo_app: harness for MemoApp app\n    \"\"\"\n    assert memo_app.app_instance is not None, \"app is not running\"\n    driver = memo_app.frontend()\n\n    # check that the output matches\n    memo_custom_code_stack = AppHarness.poll_for_or_raise_timeout(\n        lambda: driver.find_element(By.ID, \"memo-custom-code\")\n    )\n    assert (\n        memo_app.poll_for_content(memo_custom_code_stack, exp_not_equal=\"\")\n        == \"foobarbarbar\"\n    )\n    assert memo_custom_code_stack.text == \"foobarbarbar\"\n\n    # click the button to trigger partial event application\n    button = driver.find_element(By.ID, \"memo-button\")\n    button.click()\n    last_value = driver.find_element(By.ID, \"memo-last-value\")\n    assert memo_app.poll_for_content(last_value, exp_not_equal=\"\") == \"memod_some_value\"\n\n    # enter text to trigger passed argument to event handler\n    textbox = driver.find_element(By.ID, \"memo-input\")\n    textbox.send_keys(\"new_value\")\n    AppHarness.expect(lambda: memo_app.poll_for_content(last_value) == \"new_value\")\n"
  },
  {
    "path": "tests/integration/test_navigation.py",
    "content": "\"\"\"Integration tests for links and related components.\"\"\"\n\nfrom collections.abc import Generator\nfrom urllib.parse import urlsplit\n\nimport pytest\nfrom selenium.webdriver.common.by import By\n\nfrom reflex.testing import AppHarness\n\nfrom .utils import SessionStorage, poll_for_navigation\n\n\ndef NavigationApp():\n    \"\"\"Reflex app with links for navigation.\"\"\"\n    import reflex as rx\n\n    class State(rx.State):\n        is_external: bool = True\n\n    app = rx.App()\n\n    @app.add_page\n    def index():\n        return rx.fragment(\n            rx.link(\"Internal\", href=\"/internal\", id=\"internal\"),\n            rx.link(\n                \"External\",\n                href=\"/internal\",\n                is_external=State.is_external,\n                id=\"external\",\n            ),\n            rx.link(\n                \"External Target\", href=\"/internal\", target=\"_blank\", id=\"external2\"\n            ),\n        )\n\n    @rx.page(route=\"/internal\")\n    def internal():\n        return rx.text(\"Internal\")\n\n\n@pytest.fixture\ndef navigation_app(tmp_path) -> Generator[AppHarness, None, None]:\n    \"\"\"Start NavigationApp app at tmp_path via AppHarness.\n\n    Args:\n        tmp_path: pytest tmp_path fixture\n\n    Yields:\n        running AppHarness instance\n    \"\"\"\n    with AppHarness.create(\n        root=tmp_path,\n        app_source=NavigationApp,\n    ) as harness:\n        yield harness\n\n\ndef test_navigation_app(navigation_app: AppHarness):\n    \"\"\"Type text after moving cursor. Update text on backend.\n\n    Args:\n        navigation_app: harness for NavigationApp app\n    \"\"\"\n    assert navigation_app.app_instance is not None, \"app is not running\"\n    driver = navigation_app.frontend()\n\n    ss = SessionStorage(driver)\n    assert AppHarness._poll_for(lambda: ss.get(\"token\") is not None), \"token not found\"\n\n    internal_link = driver.find_element(By.ID, \"internal\")\n\n    with poll_for_navigation(driver):\n        internal_link.click()\n    assert urlsplit(driver.current_url).path == \"/internal\"\n    with poll_for_navigation(driver):\n        driver.back()\n\n    external_link = AppHarness.poll_for_or_raise_timeout(\n        lambda: driver.find_element(By.ID, \"external\")\n    )\n    external2_link = driver.find_element(By.ID, \"external2\")\n\n    external_link.click()\n    # Expect a new tab to open\n    AppHarness.expect(lambda: len(driver.window_handles) == 2)\n\n    # Switch back to the main tab\n    driver.switch_to.window(driver.window_handles[0])\n\n    external2_link.click()\n    # Expect another new tab to open\n    AppHarness.expect(lambda: len(driver.window_handles) == 3)\n"
  },
  {
    "path": "tests/integration/test_server_side_event.py",
    "content": "\"\"\"Integration tests for special server side events.\"\"\"\n\nimport time\nfrom collections.abc import Generator\n\nimport pytest\nfrom selenium.webdriver.common.by import By\n\nfrom reflex.testing import AppHarness\n\n\ndef ServerSideEvent():\n    \"\"\"App with inputs set via event handlers and set_value.\"\"\"\n    import reflex as rx\n\n    class SSState(rx.State):\n        @rx.event\n        def set_value_yield(self):\n            yield rx.set_value(\"a\", \"\")\n            yield rx.set_value(\"b\", \"\")\n            yield rx.set_value(\"c\", \"\")\n\n        @rx.event\n        def set_value_yield_return(self):\n            yield rx.set_value(\"a\", \"\")\n            yield rx.set_value(\"b\", \"\")\n            return rx.set_value(\"c\", \"\")  # noqa: B901\n\n        @rx.event\n        def set_value_return(self):\n            return [\n                rx.set_value(\"a\", \"\"),\n                rx.set_value(\"b\", \"\"),\n                rx.set_value(\"c\", \"\"),\n            ]\n\n        @rx.event\n        def set_value_return_c(self):\n            return rx.set_value(\"c\", \"\")\n\n    app = rx.App()\n\n    @app.add_page\n    def index():\n        return rx.fragment(\n            rx.input(\n                id=\"token\", value=SSState.router.session.client_token, is_read_only=True\n            ),\n            rx.input(default_value=\"a\", id=\"a\"),\n            rx.input(default_value=\"b\", id=\"b\"),\n            rx.input(default_value=\"c\", id=\"c\"),\n            rx.button(\n                \"Clear Immediate\",\n                id=\"clear_immediate\",\n                on_click=[\n                    rx.set_value(\"a\", \"\"),\n                    rx.set_value(\"b\", \"\"),\n                    rx.set_value(\"c\", \"\"),\n                ],\n            ),\n            rx.button(\n                \"Clear Chained Yield\",\n                id=\"clear_chained_yield\",\n                on_click=SSState.set_value_yield,\n            ),\n            rx.button(\n                \"Clear Chained Yield+Return\",\n                id=\"clear_chained_yield_return\",\n                on_click=SSState.set_value_yield_return,\n            ),\n            rx.button(\n                \"Clear Chained Return\",\n                id=\"clear_chained_return\",\n                on_click=SSState.set_value_return,\n            ),\n            rx.button(\n                \"Clear C Return\",\n                id=\"clear_return_c\",\n                on_click=SSState.set_value_return_c,\n            ),\n        )\n\n\n@pytest.fixture(scope=\"module\")\ndef server_side_event(tmp_path_factory) -> Generator[AppHarness, None, None]:\n    \"\"\"Start ServerSideEvent app at tmp_path via AppHarness.\n\n    Args:\n        tmp_path_factory: pytest tmp_path_factory fixture\n\n    Yields:\n        running AppHarness instance\n    \"\"\"\n    with AppHarness.create(\n        root=tmp_path_factory.mktemp(\"server_side_event\"),\n        app_source=ServerSideEvent,\n    ) as harness:\n        yield harness\n\n\n@pytest.fixture\ndef driver(server_side_event: AppHarness):\n    \"\"\"Get an instance of the browser open to the server_side_event app.\n\n    Args:\n        server_side_event: harness for ServerSideEvent app\n\n    Yields:\n        WebDriver instance.\n    \"\"\"\n    assert server_side_event.app_instance is not None, \"app is not running\"\n    driver = server_side_event.frontend()\n    try:\n        token_input = AppHarness.poll_for_or_raise_timeout(\n            lambda: driver.find_element(By.ID, \"token\")\n        )\n        # wait for the backend connection to send the token\n        token = server_side_event.poll_for_value(token_input)\n        assert token is not None\n\n        yield driver\n    finally:\n        driver.quit()\n\n\n@pytest.mark.parametrize(\n    \"button_id\",\n    [\n        \"clear_immediate\",\n        \"clear_chained_yield\",\n        \"clear_chained_yield_return\",\n        \"clear_chained_return\",\n    ],\n)\ndef test_set_value(driver, button_id: str):\n    \"\"\"Call set_value as an event chain, via yielding, via yielding with return.\n\n    Args:\n        driver: selenium WebDriver open to the app\n        button_id: id of the button to click (parametrized)\n    \"\"\"\n    input_a = driver.find_element(By.ID, \"a\")\n    input_b = driver.find_element(By.ID, \"b\")\n    input_c = driver.find_element(By.ID, \"c\")\n    btn = driver.find_element(By.ID, button_id)\n\n    assert input_a\n    assert input_b\n    assert input_c\n    assert btn\n\n    assert input_a.get_attribute(\"value\") == \"a\"\n    assert input_b.get_attribute(\"value\") == \"b\"\n    assert input_c.get_attribute(\"value\") == \"c\"\n    btn.click()\n    time.sleep(0.2)\n    assert input_a.get_attribute(\"value\") == \"\"\n    assert input_b.get_attribute(\"value\") == \"\"\n    assert input_c.get_attribute(\"value\") == \"\"\n\n\ndef test_set_value_return_c(driver):\n    \"\"\"Call set_value returning single event.\n\n    Args:\n        driver: selenium WebDriver open to the app\n    \"\"\"\n    input_a = driver.find_element(By.ID, \"a\")\n    input_b = driver.find_element(By.ID, \"b\")\n    input_c = driver.find_element(By.ID, \"c\")\n    btn = driver.find_element(By.ID, \"clear_return_c\")\n\n    assert input_a\n    assert input_b\n    assert input_c\n    assert btn\n\n    assert input_a.get_attribute(\"value\") == \"a\"\n    assert input_b.get_attribute(\"value\") == \"b\"\n    assert input_c.get_attribute(\"value\") == \"c\"\n    btn.click()\n    time.sleep(0.2)\n    assert input_a.get_attribute(\"value\") == \"a\"\n    assert input_b.get_attribute(\"value\") == \"b\"\n    assert input_c.get_attribute(\"value\") == \"\"\n"
  },
  {
    "path": "tests/integration/test_shared_state.py",
    "content": "\"\"\"Test shared state.\"\"\"\n\nfrom __future__ import annotations\n\nfrom collections.abc import Generator\n\nimport pytest\n\nfrom reflex.testing import AppHarness, WebDriver\n\n\ndef SharedStateApp():\n    \"\"\"Test that shared state works as expected.\"\"\"\n    import reflex as rx\n    from tests.integration.shared.state import SharedState\n\n    class State(SharedState):\n        pass\n\n    def index() -> rx.Component:\n        return rx.vstack()\n\n    app = rx.App()\n    app.add_page(index)\n\n\n@pytest.fixture\ndef shared_state(\n    tmp_path_factory,\n) -> Generator[AppHarness, None, None]:\n    \"\"\"Start SharedStateApp at tmp_path via AppHarness.\n\n    Args:\n        tmp_path_factory: pytest tmp_path_factory fixture\n\n    Yields:\n        running AppHarness instance\n\n    \"\"\"\n    with AppHarness.create(\n        root=tmp_path_factory.mktemp(\"shared_state\"),\n        app_source=SharedStateApp,\n    ) as harness:\n        yield harness\n\n\n@pytest.fixture\ndef driver(shared_state: AppHarness) -> Generator[WebDriver, None, None]:\n    \"\"\"Get an instance of the browser open to the shared_state app.\n\n    Args:\n        shared_state: harness for SharedStateApp\n\n    Yields:\n        WebDriver instance.\n\n    \"\"\"\n    assert shared_state.app_instance is not None, \"app is not running\"\n    driver = shared_state.frontend()\n    try:\n        yield driver\n    finally:\n        driver.quit()\n\n\ndef test_shared_state(\n    shared_state: AppHarness,\n    driver: WebDriver,\n):\n    \"\"\"Test that 2 AppHarness instances can share a state (f.e. from a library).\n\n    Args:\n        shared_state: harness for SharedStateApp.\n        driver: WebDriver instance.\n\n    \"\"\"\n    assert shared_state.app_instance is not None\n"
  },
  {
    "path": "tests/integration/test_state_inheritance.py",
    "content": "\"\"\"Test state inheritance.\"\"\"\n\nfrom __future__ import annotations\n\nfrom collections.abc import Generator\nfrom contextlib import suppress\n\nimport pytest\nfrom selenium.common.exceptions import NoAlertPresentException\nfrom selenium.webdriver.common.alert import Alert\nfrom selenium.webdriver.common.by import By\n\nfrom reflex.testing import DEFAULT_TIMEOUT, AppHarness, WebDriver\n\n\ndef get_alert_or_none(driver: WebDriver) -> Alert | None:\n    \"\"\"Switch to an alert if present.\n\n    Args:\n        driver: WebDriver instance.\n\n    Returns:\n        The alert if present, otherwise None.\n    \"\"\"\n    with suppress(NoAlertPresentException):\n        return driver.switch_to.alert\n\n\ndef raises_alert(driver: WebDriver, element: str) -> None:\n    \"\"\"Click an element and check that an alert is raised.\n\n    Args:\n        driver: WebDriver instance.\n        element: The element to click.\n    \"\"\"\n    btn = driver.find_element(By.ID, element)\n    btn.click()\n    alert = AppHarness.poll_for_or_raise_timeout(lambda: get_alert_or_none(driver))\n    assert isinstance(alert, Alert)\n    assert alert.text == \"clicked\"\n    alert.accept()\n\n\ndef StateInheritance():\n    \"\"\"Test that state inheritance works as expected.\"\"\"\n    import reflex as rx\n\n    class ChildMixin(rx.State, mixin=True):\n        child_mixin: str = \"child_mixin\"\n\n        @rx.var\n        def computed_child_mixin(self) -> str:\n            return \"computed_child_mixin\"\n\n    class Mixin(ChildMixin, mixin=True):\n        mixin: str = \"mixin\"\n\n        @rx.var\n        def computed_mixin(self) -> str:\n            return \"computed_mixin\"\n\n        @rx.event\n        def on_click_mixin(self):\n            return rx.call_script(\"alert('clicked')\")\n\n    class OtherMixin(rx.State, mixin=True):\n        other_mixin: str = \"other_mixin\"\n        other_mixin_clicks: int = 0\n\n        @rx.var\n        def computed_other_mixin(self) -> str:\n            return self.other_mixin\n\n        @rx.event\n        def on_click_other_mixin(self):\n            self.other_mixin_clicks += 1\n            self.other_mixin = (\n                f\"{type(self).__name__}.clicked.{self.other_mixin_clicks}\"\n            )\n\n    class Base1(Mixin, rx.State):\n        _base1: str = \"_base1\"\n        base1: str = \"base1\"\n\n        @rx.var\n        def computed_basevar(self) -> str:\n            return \"computed_basevar1\"\n\n        @rx.var\n        def computed_backend_vars_base1(self) -> str:\n            return self._base1\n\n    class Base2(rx.State):\n        _base2: str = \"_base2\"\n        base2: str = \"base2\"\n\n        @rx.var\n        def computed_basevar(self) -> str:\n            return \"computed_basevar2\"\n\n        @rx.var\n        def computed_backend_vars_base2(self) -> str:\n            return self._base2\n\n    class Child1(Base1, OtherMixin):\n        pass\n\n    class Child2(Base2, Mixin, OtherMixin):\n        pass\n\n    class Child3(Child2):\n        _child3: str = \"_child3\"\n        child3: str = \"child3\"\n\n        @rx.var\n        def computed_childvar(self) -> str:\n            return \"computed_childvar\"\n\n        @rx.var\n        def computed_backend_vars_child3(self) -> str:\n            return f\"{self._base2}.{self._child3}\"\n\n    def index() -> rx.Component:\n        return rx.vstack(\n            rx.input(\n                id=\"token\", value=Base1.router.session.client_token, is_read_only=True\n            ),\n            # Base 1 (Mixin, ChildMixin)\n            rx.heading(Base1.computed_mixin, id=\"base1-computed_mixin\"),\n            rx.heading(Base1.computed_basevar, id=\"base1-computed_basevar\"),\n            rx.heading(Base1.computed_child_mixin, id=\"base1-computed-child-mixin\"),\n            rx.heading(Base1.base1, id=\"base1-base1\"),\n            rx.heading(Base1.child_mixin, id=\"base1-child-mixin\"),\n            rx.button(\n                \"Base1.on_click_mixin\",\n                on_click=Base1.on_click_mixin,\n                id=\"base1-mixin-btn\",\n            ),\n            rx.heading(\n                Base1.computed_backend_vars_base1, id=\"base1-computed_backend_vars\"\n            ),\n            # Base 2 (no mixins)\n            rx.heading(Base2.computed_basevar, id=\"base2-computed_basevar\"),\n            rx.heading(Base2.base2, id=\"base2-base2\"),\n            rx.heading(\n                Base2.computed_backend_vars_base2, id=\"base2-computed_backend_vars\"\n            ),\n            # Child 1 (Mixin, ChildMixin, OtherMixin)\n            rx.heading(Child1.computed_basevar, id=\"child1-computed_basevar\"),\n            rx.heading(Child1.computed_mixin, id=\"child1-computed_mixin\"),\n            rx.heading(Child1.computed_other_mixin, id=\"child1-other-mixin\"),\n            rx.heading(Child1.computed_child_mixin, id=\"child1-computed-child-mixin\"),\n            rx.heading(Child1.base1, id=\"child1-base1\"),\n            rx.heading(Child1.other_mixin, id=\"child1-other_mixin\"),\n            rx.heading(Child1.child_mixin, id=\"child1-child-mixin\"),\n            rx.button(\n                \"Child1.on_click_other_mixin\",\n                on_click=Child1.on_click_other_mixin,\n                id=\"child1-other-mixin-btn\",\n            ),\n            # Child 2 (Mixin, ChildMixin, OtherMixin)\n            rx.heading(Child2.computed_basevar, id=\"child2-computed_basevar\"),\n            rx.heading(Child2.computed_mixin, id=\"child2-computed_mixin\"),\n            rx.heading(Child2.computed_other_mixin, id=\"child2-other-mixin\"),\n            rx.heading(Child2.computed_child_mixin, id=\"child2-computed-child-mixin\"),\n            rx.heading(Child2.base2, id=\"child2-base2\"),\n            rx.heading(Child2.other_mixin, id=\"child2-other_mixin\"),\n            rx.heading(Child2.child_mixin, id=\"child2-child-mixin\"),\n            rx.button(\n                \"Child2.on_click_mixin\",\n                on_click=Child2.on_click_mixin,\n                id=\"child2-mixin-btn\",\n            ),\n            rx.button(\n                \"Child2.on_click_other_mixin\",\n                on_click=Child2.on_click_other_mixin,\n                id=\"child2-other-mixin-btn\",\n            ),\n            # Child 3 (Mixin, ChildMixin, OtherMixin)\n            rx.heading(Child3.computed_basevar, id=\"child3-computed_basevar\"),\n            rx.heading(Child3.computed_mixin, id=\"child3-computed_mixin\"),\n            rx.heading(Child3.computed_other_mixin, id=\"child3-other-mixin\"),\n            rx.heading(Child3.computed_childvar, id=\"child3-computed_childvar\"),\n            rx.heading(Child3.computed_child_mixin, id=\"child3-computed-child-mixin\"),\n            rx.heading(Child3.child3, id=\"child3-child3\"),\n            rx.heading(Child3.base2, id=\"child3-base2\"),\n            rx.heading(Child3.other_mixin, id=\"child3-other_mixin\"),\n            rx.heading(Child3.child_mixin, id=\"child3-child-mixin\"),\n            rx.button(\n                \"Child3.on_click_mixin\",\n                on_click=Child3.on_click_mixin,\n                id=\"child3-mixin-btn\",\n            ),\n            rx.button(\n                \"Child3.on_click_other_mixin\",\n                on_click=Child3.on_click_other_mixin,\n                id=\"child3-other-mixin-btn\",\n            ),\n            rx.heading(\n                Child3.computed_backend_vars_child3, id=\"child3-computed_backend_vars\"\n            ),\n        )\n\n    app = rx.App()\n    app.add_page(index)\n\n\n@pytest.fixture(scope=\"module\")\ndef state_inheritance(\n    tmp_path_factory,\n) -> Generator[AppHarness, None, None]:\n    \"\"\"Start StateInheritance app at tmp_path via AppHarness.\n\n    Args:\n        tmp_path_factory: pytest tmp_path_factory fixture\n\n    Yields:\n        running AppHarness instance\n    \"\"\"\n    with AppHarness.create(\n        root=tmp_path_factory.mktemp(\"state_inheritance\"),\n        app_source=StateInheritance,\n    ) as harness:\n        yield harness\n\n\n@pytest.fixture\ndef driver(state_inheritance: AppHarness) -> Generator[WebDriver, None, None]:\n    \"\"\"Get an instance of the browser open to the state_inheritance app.\n\n    Args:\n        state_inheritance: harness for StateInheritance app\n\n    Yields:\n        WebDriver instance.\n    \"\"\"\n    assert state_inheritance.app_instance is not None, \"app is not running\"\n    driver = state_inheritance.frontend()\n    try:\n        yield driver\n    finally:\n        driver.quit()\n\n\n@pytest.fixture\ndef token(state_inheritance: AppHarness, driver: WebDriver) -> str:\n    \"\"\"Get a function that returns the active token.\n\n    Args:\n        state_inheritance: harness for StateInheritance app.\n        driver: WebDriver instance.\n\n    Returns:\n        The token for the connected client\n    \"\"\"\n    assert state_inheritance.app_instance is not None\n    token_input = AppHarness.poll_for_or_raise_timeout(\n        lambda: driver.find_element(By.ID, \"token\")\n    )\n\n    # wait for the backend connection to send the token\n    token = state_inheritance.poll_for_value(token_input, timeout=DEFAULT_TIMEOUT * 2)\n    assert token is not None\n\n    return token\n\n\ndef test_state_inheritance(\n    state_inheritance: AppHarness,\n    driver: WebDriver,\n    token: str,\n):\n    \"\"\"Test that background tasks work as expected.\n\n    Args:\n        state_inheritance: harness for StateInheritance app.\n        driver: WebDriver instance.\n        token: The token for the connected client.\n    \"\"\"\n    assert state_inheritance.app_instance is not None\n\n    # Initial State values Test\n    # Base 1\n    base1_mixin = driver.find_element(By.ID, \"base1-computed_mixin\")\n    assert base1_mixin.text == \"computed_mixin\"\n\n    base1_computed_basevar = driver.find_element(By.ID, \"base1-computed_basevar\")\n    assert base1_computed_basevar.text == \"computed_basevar1\"\n\n    base1_computed_child_mixin = driver.find_element(\n        By.ID, \"base1-computed-child-mixin\"\n    )\n    assert base1_computed_child_mixin.text == \"computed_child_mixin\"\n\n    base1_base1 = driver.find_element(By.ID, \"base1-base1\")\n    assert base1_base1.text == \"base1\"\n\n    base1_computed_backend_vars = driver.find_element(\n        By.ID, \"base1-computed_backend_vars\"\n    )\n    assert base1_computed_backend_vars.text == \"_base1\"\n\n    base1_child_mixin = driver.find_element(By.ID, \"base1-child-mixin\")\n    assert base1_child_mixin.text == \"child_mixin\"\n\n    # Base 2\n    base2_computed_basevar = driver.find_element(By.ID, \"base2-computed_basevar\")\n    assert base2_computed_basevar.text == \"computed_basevar2\"\n\n    base2_base2 = driver.find_element(By.ID, \"base2-base2\")\n    assert base2_base2.text == \"base2\"\n\n    base2_computed_backend_vars = driver.find_element(\n        By.ID, \"base2-computed_backend_vars\"\n    )\n    assert base2_computed_backend_vars.text == \"_base2\"\n\n    # Child 1\n    child1_computed_basevar = driver.find_element(By.ID, \"child1-computed_basevar\")\n    assert child1_computed_basevar.text == \"computed_basevar1\"\n\n    child1_mixin = driver.find_element(By.ID, \"child1-computed_mixin\")\n    assert child1_mixin.text == \"computed_mixin\"\n\n    child1_computed_other_mixin = driver.find_element(By.ID, \"child1-other-mixin\")\n    assert child1_computed_other_mixin.text == \"other_mixin\"\n\n    child1_computed_child_mixin = driver.find_element(\n        By.ID, \"child1-computed-child-mixin\"\n    )\n    assert child1_computed_child_mixin.text == \"computed_child_mixin\"\n\n    child1_base1 = driver.find_element(By.ID, \"child1-base1\")\n    assert child1_base1.text == \"base1\"\n\n    child1_other_mixin = driver.find_element(By.ID, \"child1-other_mixin\")\n    assert child1_other_mixin.text == \"other_mixin\"\n\n    child1_child_mixin = driver.find_element(By.ID, \"child1-child-mixin\")\n    assert child1_child_mixin.text == \"child_mixin\"\n\n    # Child 2\n    child2_computed_basevar = driver.find_element(By.ID, \"child2-computed_basevar\")\n    assert child2_computed_basevar.text == \"computed_basevar2\"\n\n    child2_mixin = driver.find_element(By.ID, \"child2-computed_mixin\")\n    assert child2_mixin.text == \"computed_mixin\"\n\n    child2_computed_other_mixin = driver.find_element(By.ID, \"child2-other-mixin\")\n    assert child2_computed_other_mixin.text == \"other_mixin\"\n\n    child2_computed_child_mixin = driver.find_element(\n        By.ID, \"child2-computed-child-mixin\"\n    )\n    assert child2_computed_child_mixin.text == \"computed_child_mixin\"\n\n    child2_base2 = driver.find_element(By.ID, \"child2-base2\")\n    assert child2_base2.text == \"base2\"\n\n    child2_other_mixin = driver.find_element(By.ID, \"child2-other_mixin\")\n    assert child2_other_mixin.text == \"other_mixin\"\n\n    child2_child_mixin = driver.find_element(By.ID, \"child2-child-mixin\")\n    assert child2_child_mixin.text == \"child_mixin\"\n\n    # Child 3\n    child3_computed_basevar = driver.find_element(By.ID, \"child3-computed_basevar\")\n    assert child3_computed_basevar.text == \"computed_basevar2\"\n\n    child3_mixin = driver.find_element(By.ID, \"child3-computed_mixin\")\n    assert child3_mixin.text == \"computed_mixin\"\n\n    child3_computed_other_mixin = driver.find_element(By.ID, \"child3-other-mixin\")\n    assert child3_computed_other_mixin.text == \"other_mixin\"\n\n    child3_computed_childvar = driver.find_element(By.ID, \"child3-computed_childvar\")\n    assert child3_computed_childvar.text == \"computed_childvar\"\n\n    child3_computed_child_mixin = driver.find_element(\n        By.ID, \"child3-computed-child-mixin\"\n    )\n    assert child3_computed_child_mixin.text == \"computed_child_mixin\"\n\n    child3_child3 = driver.find_element(By.ID, \"child3-child3\")\n    assert child3_child3.text == \"child3\"\n\n    child3_base2 = driver.find_element(By.ID, \"child3-base2\")\n    assert child3_base2.text == \"base2\"\n\n    child3_other_mixin = driver.find_element(By.ID, \"child3-other_mixin\")\n    assert child3_other_mixin.text == \"other_mixin\"\n\n    child3_child_mixin = driver.find_element(By.ID, \"child3-child-mixin\")\n    assert child3_child_mixin.text == \"child_mixin\"\n\n    child3_computed_backend_vars = driver.find_element(\n        By.ID, \"child3-computed_backend_vars\"\n    )\n    assert child3_computed_backend_vars.text == \"_base2._child3\"\n\n    # Event Handler Tests\n    raises_alert(driver, \"base1-mixin-btn\")\n    raises_alert(driver, \"child2-mixin-btn\")\n    raises_alert(driver, \"child3-mixin-btn\")\n\n    child1_other_mixin_btn = driver.find_element(By.ID, \"child1-other-mixin-btn\")\n    child1_other_mixin_btn.click()\n    child1_other_mixin_value = state_inheritance.poll_for_content(\n        child1_other_mixin, exp_not_equal=\"other_mixin\"\n    )\n    child1_computed_mixin_value = state_inheritance.poll_for_content(\n        child1_computed_other_mixin, exp_not_equal=\"other_mixin\"\n    )\n    assert child1_other_mixin_value == \"Child1.clicked.1\"\n    assert child1_computed_mixin_value == \"Child1.clicked.1\"\n\n    child2_other_mixin_btn = driver.find_element(By.ID, \"child2-other-mixin-btn\")\n    child2_other_mixin_btn.click()\n    child2_other_mixin_value = state_inheritance.poll_for_content(\n        child2_other_mixin, exp_not_equal=\"other_mixin\"\n    )\n    child2_computed_mixin_value = state_inheritance.poll_for_content(\n        child2_computed_other_mixin, exp_not_equal=\"other_mixin\"\n    )\n    child3_other_mixin_value = state_inheritance.poll_for_content(\n        child3_other_mixin, exp_not_equal=\"other_mixin\"\n    )\n    child3_computed_mixin_value = state_inheritance.poll_for_content(\n        child3_computed_other_mixin, exp_not_equal=\"other_mixin\"\n    )\n    assert child2_other_mixin_value == \"Child2.clicked.1\"\n    assert child2_computed_mixin_value == \"Child2.clicked.1\"\n    assert child3_other_mixin_value == \"Child2.clicked.1\"\n    assert child3_computed_mixin_value == \"Child2.clicked.1\"\n\n    child3_other_mixin_btn = driver.find_element(By.ID, \"child3-other-mixin-btn\")\n    child3_other_mixin_btn.click()\n    child2_other_mixin_value = state_inheritance.poll_for_content(\n        child2_other_mixin, exp_not_equal=\"Child2.clicked.1\"\n    )\n    child2_computed_mixin_value = state_inheritance.poll_for_content(\n        child2_computed_other_mixin, exp_not_equal=\"Child2.clicked.1\"\n    )\n    child3_other_mixin_value = state_inheritance.poll_for_content(\n        child3_other_mixin, exp_not_equal=\"Child2.clicked.1\"\n    )\n    child3_computed_mixin_value = state_inheritance.poll_for_content(\n        child3_computed_other_mixin, exp_not_equal=\"Child2.clicked.1\"\n    )\n    assert child2_other_mixin_value == \"Child2.clicked.2\"\n    assert child2_computed_mixin_value == \"Child2.clicked.2\"\n    assert child3_other_mixin.text == \"Child2.clicked.2\"\n    assert child3_computed_other_mixin.text == \"Child2.clicked.2\"\n"
  },
  {
    "path": "tests/integration/test_tailwind.py",
    "content": "\"\"\"Test case for disabling tailwind in the config.\"\"\"\n\nimport functools\nfrom collections.abc import Generator\n\nimport pytest\nfrom selenium.webdriver.common.by import By\n\nfrom reflex.testing import AppHarness\n\nPARAGRAPH_TEXT = \"Tailwind Is Cool\"\nPARAGRAPH_CLASS_NAME = \"text-red-500\"\nTEXT_RED_500_COLOR_v3 = [\"rgba(239, 68, 68, 1)\", \"rgb(239, 68, 68)\"]\nTEXT_RED_500_COLOR_v4 = [\"oklch(0.637 0.237 25.331)\"]\n\n\ndef TailwindApp(\n    tailwind_version: int = 0,\n    paragraph_text: str = PARAGRAPH_TEXT,\n    paragraph_class_name: str = PARAGRAPH_CLASS_NAME,\n):\n    \"\"\"App with tailwind optionally disabled.\n\n    Args:\n        tailwind_version: Tailwind version to use. If 0, tailwind is disabled.\n        paragraph_text: Text for the paragraph.\n        paragraph_class_name: Tailwind class_name for the paragraph.\n    \"\"\"\n    from pathlib import Path\n\n    import reflex as rx\n\n    class UnusedState(rx.State):\n        pass\n\n    def index():\n        return rx.el.div(\n            rx.text(paragraph_text, class_name=paragraph_class_name),\n            rx.el.p(paragraph_text, class_name=paragraph_class_name),\n            rx.text(paragraph_text, as_=\"p\", class_name=paragraph_class_name),\n            rx.el.div(\"Test external stylesheet\", class_name=\"external\"),\n            id=\"p-content\",\n        )\n\n    assets = Path(__file__).resolve().parent.parent / \"assets\"\n    assets.mkdir(exist_ok=True)\n    stylesheet = assets / \"test_styles.css\"\n    stylesheet.write_text(\".external { color: rgba(0, 0, 255, 0.5) }\")\n    app = rx.App(\n        style={\"font_family\": \"monospace\"},\n        stylesheets=[stylesheet.name],\n        enable_state=False,\n    )\n    app.add_page(index)\n    if not tailwind_version:\n        config = rx.config.get_config()\n        config.plugins = []\n    elif tailwind_version == 3:\n        config = rx.config.get_config()\n        config.plugins = [rx.plugins.TailwindV3Plugin()]\n    elif tailwind_version == 4:\n        config = rx.config.get_config()\n        config.plugins = [rx.plugins.TailwindV4Plugin()]\n\n\n@pytest.fixture(\n    params=[0, 3, 4], ids=[\"tailwind_disabled\", \"tailwind_v3\", \"tailwind_v4\"]\n)\ndef tailwind_version(request) -> int:\n    \"\"\"Tailwind version fixture.\n\n    Args:\n        request: pytest request fixture.\n\n    Returns:\n        Tailwind version to use. 0 for disabled, 3 for v3, 4 for v4.\n    \"\"\"\n    return request.param\n\n\n@pytest.fixture\ndef tailwind_app(tmp_path, tailwind_version) -> Generator[AppHarness, None, None]:\n    \"\"\"Start TailwindApp app at tmp_path via AppHarness with tailwind disabled via config.\n\n    Args:\n        tmp_path: pytest tmp_path fixture\n        tailwind_version: Whether tailwind is disabled for the app.\n\n    Yields:\n        running AppHarness instance\n    \"\"\"\n    with AppHarness.create(\n        root=tmp_path,\n        app_source=functools.partial(TailwindApp, tailwind_version=tailwind_version),\n        app_name=\"tailwind_\"\n        + (\"disabled\" if tailwind_version == 0 else str(tailwind_version)),\n    ) as harness:\n        yield harness\n\n\ndef test_tailwind_app(tailwind_app: AppHarness, tailwind_version: bool):\n    \"\"\"Test that the app can compile without tailwind.\n\n    Args:\n        tailwind_app: AppHarness instance.\n        tailwind_version: Tailwind version to use. If 0, tailwind is disabled.\n    \"\"\"\n    assert tailwind_app.app_instance is not None\n    assert tailwind_app.backend is not None\n\n    driver = tailwind_app.frontend()\n\n    # Assert the app is stateless.\n    with pytest.raises(ValueError) as errctx:\n        _ = tailwind_app.app_instance.state_manager\n    errctx.match(\"The state manager has not been initialized.\")\n\n    # Assert content is visible (and not some error)\n    content = AppHarness.poll_for_or_raise_timeout(\n        lambda: driver.find_element(By.ID, \"p-content\")\n    )\n    paragraphs = content.find_elements(By.TAG_NAME, \"p\")\n    assert len(paragraphs) == 3\n    for p in paragraphs:\n        assert tailwind_app.poll_for_content(p, exp_not_equal=\"\") == PARAGRAPH_TEXT\n        assert p.value_of_css_property(\"font-family\") == \"monospace\"\n        if not tailwind_version:\n            # expect default color, not \"text-red-500\" from tailwind utility class\n            assert p.value_of_css_property(\"color\") not in TEXT_RED_500_COLOR_v3\n        elif tailwind_version == 3:\n            # expect \"text-red-500\" from tailwind utility class\n            assert p.value_of_css_property(\"color\") in TEXT_RED_500_COLOR_v3\n        elif tailwind_version == 4:\n            # expect \"text-red-500\" from tailwind utility class\n            assert p.value_of_css_property(\"color\") in TEXT_RED_500_COLOR_v4\n\n    # Assert external stylesheet is applying rules\n    external = driver.find_elements(By.CLASS_NAME, \"external\")\n    assert len(external) == 1\n    for ext_div in external:\n        assert ext_div.value_of_css_property(\"color\") == \"rgba(0, 0, 255, 0.5)\"\n"
  },
  {
    "path": "tests/integration/test_upload.py",
    "content": "\"\"\"Integration tests for file upload.\"\"\"\n\nfrom __future__ import annotations\n\nimport asyncio\nimport time\nfrom collections.abc import Generator\nfrom pathlib import Path\nfrom urllib.parse import urlsplit\n\nimport pytest\nfrom selenium.webdriver.common.by import By\n\nfrom reflex.constants.event import Endpoint\nfrom reflex.testing import AppHarness, WebDriver\n\nfrom .utils import poll_for_navigation\n\n\ndef UploadFile():\n    \"\"\"App for testing dynamic routes.\"\"\"\n    import reflex as rx\n\n    LARGE_DATA = \"DUMMY\" * 1024 * 512\n\n    class UploadState(rx.State):\n        _file_data: dict[str, str] = {}\n        event_order: rx.Field[list[str]] = rx.field([])\n        progress_dicts: rx.Field[list[dict]] = rx.field([])\n        disabled: rx.Field[bool] = rx.field(False)\n        large_data: rx.Field[str] = rx.field(\"\")\n        quaternary_names: rx.Field[list[str]] = rx.field([])\n\n        @rx.event\n        async def handle_upload(self, files: list[rx.UploadFile]):\n            for file in files:\n                upload_data = await file.read()\n                self._file_data[file.name or \"\"] = upload_data.decode(\"utf-8\")\n\n        @rx.event\n        async def handle_upload_secondary(self, files: list[rx.UploadFile]):\n            for file in files:\n                upload_data = await file.read()\n                self._file_data[file.name or \"\"] = upload_data.decode(\"utf-8\")\n                self.large_data = LARGE_DATA\n                yield UploadState.chain_event\n\n        @rx.event\n        def upload_progress(self, progress):\n            assert progress\n            self.event_order.append(\"upload_progress\")\n            self.progress_dicts.append(progress)\n\n        @rx.event\n        def chain_event(self):\n            assert self.large_data == LARGE_DATA\n            self.large_data = \"\"\n            self.event_order.append(\"chain_event\")\n\n        @rx.event\n        async def handle_upload_tertiary(self, files: list[rx.UploadFile]):\n            for file in files:\n                (rx.get_upload_dir() / (file.name or \"INVALID\")).write_bytes(\n                    await file.read()\n                )\n\n        @rx.event\n        async def handle_upload_quaternary(self, files: list[rx.UploadFile]):\n            self.quaternary_names = [file.name for file in files if file.name]\n\n        @rx.event\n        def do_download(self):\n            return rx.download(rx.get_upload_url(\"test.txt\"))\n\n    def index():\n        return rx.vstack(\n            rx.input(\n                value=UploadState.router.session.client_token,\n                read_only=True,\n                id=\"token\",\n            ),\n            rx.heading(\"Default Upload\"),\n            rx.upload.root(\n                rx.vstack(\n                    rx.button(\"Select File\"),\n                    rx.text(\"Drag and drop files here or click to select files\"),\n                ),\n                disabled=UploadState.disabled,\n            ),\n            rx.button(\n                \"Upload\",\n                on_click=lambda: UploadState.handle_upload(rx.upload_files()),  # pyright: ignore [reportArgumentType]\n                id=\"upload_button\",\n            ),\n            rx.box(\n                rx.foreach(\n                    rx.selected_files(),\n                    lambda f: rx.text(f, as_=\"p\"),\n                ),\n                id=\"selected_files\",\n            ),\n            rx.button(\n                \"Clear\",\n                on_click=rx.clear_selected_files,\n                id=\"clear_button\",\n            ),\n            rx.heading(\"Secondary Upload\"),\n            rx.upload.root(\n                rx.vstack(\n                    rx.button(\"Select File\"),\n                    rx.text(\"Drag and drop files here or click to select files\"),\n                ),\n                id=\"secondary\",\n            ),\n            rx.button(\n                \"Upload\",\n                on_click=UploadState.handle_upload_secondary(\n                    rx.upload_files(  # pyright: ignore [reportArgumentType]\n                        upload_id=\"secondary\",\n                        on_upload_progress=UploadState.upload_progress,\n                    ),\n                ),\n                id=\"upload_button_secondary\",\n            ),\n            rx.box(\n                rx.foreach(\n                    rx.selected_files(\"secondary\"),\n                    lambda f: rx.text(f, as_=\"p\"),\n                ),\n                id=\"selected_files_secondary\",\n            ),\n            rx.button(\n                \"Clear\",\n                on_click=rx.clear_selected_files(\"secondary\"),\n                id=\"clear_button_secondary\",\n            ),\n            rx.vstack(\n                rx.foreach(\n                    UploadState.progress_dicts,\n                    lambda d: rx.text(d.to_string()),\n                )\n            ),\n            rx.button(\n                \"Cancel\",\n                on_click=rx.cancel_upload(\"secondary\"),\n                id=\"cancel_button_secondary\",\n            ),\n            rx.heading(\"Tertiary Upload/Download\"),\n            rx.upload.root(\n                rx.vstack(\n                    rx.button(\"Select File\"),\n                    rx.text(\"Drag and drop files here or click to select files\"),\n                ),\n                id=\"tertiary\",\n            ),\n            rx.button(\n                \"Upload\",\n                on_click=UploadState.handle_upload_tertiary(\n                    rx.upload_files(  # pyright: ignore [reportArgumentType]\n                        upload_id=\"tertiary\",\n                    ),\n                ),\n                id=\"upload_button_tertiary\",\n            ),\n            rx.button(\n                \"Download - Frontend\",\n                on_click=rx.download(rx.get_upload_url(\"test.txt\")),\n                id=\"download-frontend\",\n            ),\n            rx.button(\n                \"Download - Backend\",\n                on_click=UploadState.do_download,\n                id=\"download-backend\",\n            ),\n            rx.upload.root(\n                rx.vstack(\n                    rx.button(\"Select File\"),\n                    rx.text(\"Drag and drop files here or click to select files\"),\n                ),\n                on_drop=UploadState.handle_upload_quaternary(\n                    rx.upload_files(  # pyright: ignore [reportArgumentType]\n                        upload_id=\"quaternary\",\n                    ),\n                ),\n                id=\"quaternary\",\n            ),\n            rx.text(\n                UploadState.quaternary_names.to_string(),\n                id=\"quaternary_files\",\n            ),\n            rx.text(UploadState.event_order.to_string(), id=\"event-order\"),\n        )\n\n    app = rx.App()\n    app.add_page(index)\n\n\n@pytest.fixture(scope=\"module\")\ndef upload_file(tmp_path_factory) -> Generator[AppHarness, None, None]:\n    \"\"\"Start UploadFile app at tmp_path via AppHarness.\n\n    Args:\n        tmp_path_factory: pytest tmp_path_factory fixture\n\n    Yields:\n        running AppHarness instance\n    \"\"\"\n    with AppHarness.create(\n        root=tmp_path_factory.mktemp(\"upload_file\"),\n        app_source=UploadFile,\n    ) as harness:\n        yield harness\n\n\n@pytest.fixture\ndef driver(upload_file: AppHarness):\n    \"\"\"Get an instance of the browser open to the upload_file app.\n\n    Args:\n        upload_file: harness for DynamicRoute app\n\n    Yields:\n        WebDriver instance.\n    \"\"\"\n    assert upload_file.app_instance is not None, \"app is not running\"\n    driver = upload_file.frontend()\n    try:\n        yield driver\n    finally:\n        driver.quit()\n\n\ndef poll_for_token(driver: WebDriver, upload_file: AppHarness) -> str:\n    \"\"\"Poll for the token input to be populated.\n\n    Args:\n        driver: WebDriver instance.\n        upload_file: harness for UploadFile app.\n\n    Returns:\n        token value\n    \"\"\"\n    token_input = AppHarness.poll_for_or_raise_timeout(\n        lambda: driver.find_element(By.ID, \"token\")\n    )\n    # wait for the backend connection to send the token\n    token = upload_file.poll_for_value(token_input)\n    assert token is not None\n    return token\n\n\n@pytest.mark.parametrize(\"secondary\", [False, True])\n@pytest.mark.asyncio\nasync def test_upload_file(\n    tmp_path, upload_file: AppHarness, driver: WebDriver, secondary: bool\n):\n    \"\"\"Submit a file upload and check that it arrived on the backend.\n\n    Args:\n        tmp_path: pytest tmp_path fixture\n        upload_file: harness for UploadFile app.\n        driver: WebDriver instance.\n        secondary: whether to use the secondary upload form\n    \"\"\"\n    assert upload_file.app_instance is not None\n    token = poll_for_token(driver, upload_file)\n    full_state_name = upload_file.get_full_state_name([\"_upload_state\"])\n    state_name = upload_file.get_state_name(\"_upload_state\")\n    substate_token = f\"{token}_{full_state_name}\"\n\n    suffix = \"_secondary\" if secondary else \"\"\n\n    upload_box = driver.find_elements(By.XPATH, \"//input[@type='file']\")[\n        1 if secondary else 0\n    ]\n    assert upload_box\n    upload_button = driver.find_element(By.ID, f\"upload_button{suffix}\")\n    assert upload_button\n\n    exp_name = \"test.txt\"\n    exp_contents = \"test file contents!\"\n    target_file = tmp_path / exp_name\n    target_file.write_text(exp_contents)\n\n    upload_box.send_keys(str(target_file))\n    upload_button.click()\n\n    # check that the selected files are displayed\n    selected_files = driver.find_element(By.ID, f\"selected_files{suffix}\")\n    assert Path(selected_files.text).name == Path(exp_name).name\n\n    if secondary:\n        event_order_displayed = driver.find_element(By.ID, \"event-order\")\n        AppHarness.expect(lambda: \"chain_event\" in event_order_displayed.text)\n\n        state = await upload_file.get_state(substate_token)\n        # only the secondary form tracks progress and chain events\n        assert state.substates[state_name].event_order.count(\"upload_progress\") == 1  # pyright: ignore[reportAttributeAccessIssue]\n        assert state.substates[state_name].event_order.count(\"chain_event\") == 1  # pyright: ignore[reportAttributeAccessIssue]\n\n    # look up the backend state and assert on uploaded contents\n    async def get_file_data():\n        return (\n            (await upload_file.get_state(substate_token))\n            .substates[state_name]\n            ._file_data  # pyright: ignore[reportAttributeAccessIssue]\n        )\n\n    file_data = await AppHarness._poll_for_async(get_file_data)\n    assert isinstance(file_data, dict)\n    normalized_file_data = {Path(k).name: v for k, v in file_data.items()}\n    assert normalized_file_data[Path(exp_name).name] == exp_contents\n\n\n@pytest.mark.asyncio\nasync def test_upload_file_multiple(tmp_path, upload_file: AppHarness, driver):\n    \"\"\"Submit several file uploads and check that they arrived on the backend.\n\n    Args:\n        tmp_path: pytest tmp_path fixture\n        upload_file: harness for UploadFile app.\n        driver: WebDriver instance.\n    \"\"\"\n    assert upload_file.app_instance is not None\n    token = poll_for_token(driver, upload_file)\n    full_state_name = upload_file.get_full_state_name([\"_upload_state\"])\n    state_name = upload_file.get_state_name(\"_upload_state\")\n    substate_token = f\"{token}_{full_state_name}\"\n\n    upload_box = driver.find_element(By.XPATH, \"//input[@type='file']\")\n    assert upload_box\n    upload_button = driver.find_element(By.ID, \"upload_button\")\n    assert upload_button\n\n    exp_files = {\n        \"test1.txt\": \"test file contents!\",\n        \"test2.txt\": \"this is test file number 2!\",\n        \"reflex.txt\": \"reflex is awesome!\",\n    }\n    for exp_name, exp_contents in exp_files.items():\n        target_file = tmp_path / exp_name\n        target_file.write_text(exp_contents)\n        upload_box.send_keys(str(target_file))\n\n    await asyncio.sleep(0.2)\n\n    # check that the selected files are displayed\n    selected_files = driver.find_element(By.ID, \"selected_files\")\n    assert [Path(name).name for name in selected_files.text.split(\"\\n\")] == [\n        Path(name).name for name in exp_files\n    ]\n\n    # do the upload\n    upload_button.click()\n\n    # look up the backend state and assert on uploaded contents\n    async def get_file_data():\n        return (\n            (await upload_file.get_state(substate_token))\n            .substates[state_name]\n            ._file_data  # pyright: ignore[reportAttributeAccessIssue]\n        )\n\n    file_data = await AppHarness._poll_for_async(get_file_data)\n    assert isinstance(file_data, dict)\n    normalized_file_data = {Path(k).name: v for k, v in file_data.items()}\n    for exp_name, exp_contents in exp_files.items():\n        assert normalized_file_data[Path(exp_name).name] == exp_contents\n\n\n@pytest.mark.parametrize(\"secondary\", [False, True])\ndef test_clear_files(\n    tmp_path, upload_file: AppHarness, driver: WebDriver, secondary: bool\n):\n    \"\"\"Select then clear several file uploads and check that they are cleared.\n\n    Args:\n        tmp_path: pytest tmp_path fixture\n        upload_file: harness for UploadFile app.\n        driver: WebDriver instance.\n        secondary: whether to use the secondary upload form.\n    \"\"\"\n    assert upload_file.app_instance is not None\n    poll_for_token(driver, upload_file)\n\n    suffix = \"_secondary\" if secondary else \"\"\n\n    upload_box = driver.find_elements(By.XPATH, \"//input[@type='file']\")[\n        1 if secondary else 0\n    ]\n    assert upload_box\n    upload_button = driver.find_element(By.ID, f\"upload_button{suffix}\")\n    assert upload_button\n\n    exp_files = {\n        \"test1.txt\": \"test file contents!\",\n        \"test2.txt\": \"this is test file number 2!\",\n        \"reflex.txt\": \"reflex is awesome!\",\n    }\n    for exp_name, exp_contents in exp_files.items():\n        target_file = tmp_path / exp_name\n        target_file.write_text(exp_contents)\n        upload_box.send_keys(str(target_file))\n\n    time.sleep(0.2)\n\n    # check that the selected files are displayed\n    selected_files = driver.find_element(By.ID, f\"selected_files{suffix}\")\n    assert [Path(name).name for name in selected_files.text.split(\"\\n\")] == [\n        Path(name).name for name in exp_files\n    ]\n\n    clear_button = driver.find_element(By.ID, f\"clear_button{suffix}\")\n    assert clear_button\n    clear_button.click()\n\n    # check that the selected files are cleared\n    selected_files = driver.find_element(By.ID, f\"selected_files{suffix}\")\n    assert selected_files.text == \"\"\n\n\n# TODO: drag and drop directory\n# https://gist.github.com/florentbr/349b1ab024ca9f3de56e6bf8af2ac69e\n\n\n@pytest.mark.asyncio\nasync def test_cancel_upload(tmp_path, upload_file: AppHarness, driver: WebDriver):\n    \"\"\"Submit a large file upload and cancel it.\n\n    Args:\n        tmp_path: pytest tmp_path fixture\n        upload_file: harness for UploadFile app.\n        driver: WebDriver instance.\n    \"\"\"\n    assert upload_file.app_instance is not None\n    driver.execute_cdp_cmd(\"Network.enable\", {})\n    driver.execute_cdp_cmd(\n        \"Network.emulateNetworkConditions\",\n        {\n            \"offline\": False,\n            \"downloadThroughput\": 1024 * 1024 / 8,  # 1 Mbps\n            \"uploadThroughput\": 1024 * 1024 / 8,  # 1 Mbps\n            \"latency\": 200,  # 200ms\n        },\n    )\n    token = poll_for_token(driver, upload_file)\n    state_name = upload_file.get_state_name(\"_upload_state\")\n    state_full_name = upload_file.get_full_state_name([\"_upload_state\"])\n    substate_token = f\"{token}_{state_full_name}\"\n\n    upload_box = driver.find_elements(By.XPATH, \"//input[@type='file']\")[1]\n    upload_button = driver.find_element(By.ID, \"upload_button_secondary\")\n    cancel_button = driver.find_element(By.ID, \"cancel_button_secondary\")\n\n    exp_name = \"large.txt\"\n    target_file = tmp_path / exp_name\n    with target_file.open(\"wb\") as f:\n        f.seek(1024 * 1024)  # 1 MB file, should upload in ~8 seconds\n        f.write(b\"0\")\n\n    upload_box.send_keys(str(target_file))\n    upload_button.click()\n    await asyncio.sleep(1)\n    cancel_button.click()\n\n    # Wait a bit for the upload to get cancelled.\n    await asyncio.sleep(12)\n\n    # Get interim progress dicts saved in the on_upload_progress handler.\n    async def _progress_dicts():\n        state = await upload_file.get_state(substate_token)\n        return state.substates[state_name].progress_dicts  # pyright: ignore[reportAttributeAccessIssue]\n\n    # We should have _some_ progress\n    assert await AppHarness._poll_for_async(_progress_dicts)\n\n    # But there should never be a final progress record for a cancelled upload.\n    for p in await _progress_dicts():\n        assert p[\"progress\"] != 1\n\n    state = await upload_file.get_state(substate_token)\n    file_data = state.substates[state_name]._file_data  # pyright: ignore[reportAttributeAccessIssue]\n    assert isinstance(file_data, dict)\n    normalized_file_data = {Path(k).name: v for k, v in file_data.items()}\n    assert Path(exp_name).name not in normalized_file_data\n\n    target_file.unlink()\n\n\ndef test_upload_download_file(\n    tmp_path,\n    upload_file: AppHarness,\n    driver: WebDriver,\n):\n    \"\"\"Submit a file upload and then fetch it with rx.download.\n\n    This checks the special case `getBackendURL` logic in the _download event\n    handler in state.js.\n\n    Args:\n        tmp_path: pytest tmp_path fixture\n        upload_file: harness for UploadFile app.\n        driver: WebDriver instance.\n    \"\"\"\n    assert upload_file.app_instance is not None\n    poll_for_token(driver, upload_file)\n\n    upload_box = driver.find_elements(By.XPATH, \"//input[@type='file']\")[2]\n    assert upload_box\n    upload_button = driver.find_element(By.ID, \"upload_button_tertiary\")\n    assert upload_button\n\n    exp_name = \"test.txt\"\n    exp_contents = \"test file contents!\"\n    target_file = tmp_path / exp_name\n    target_file.write_text(exp_contents)\n\n    upload_box.send_keys(str(target_file))\n    upload_button.click()\n\n    # Download via event embedded in frontend code.\n    download_frontend = driver.find_element(By.ID, \"download-frontend\")\n    with poll_for_navigation(driver):\n        download_frontend.click()\n    assert urlsplit(driver.current_url).path == f\"/{Endpoint.UPLOAD.value}/test.txt\"\n    assert driver.find_element(by=By.TAG_NAME, value=\"body\").text == exp_contents\n\n    # Go back and wait for the app to reload.\n    with poll_for_navigation(driver):\n        driver.back()\n    poll_for_token(driver, upload_file)\n\n    # Download via backend event handler.\n    download_backend = driver.find_element(By.ID, \"download-backend\")\n    with poll_for_navigation(driver):\n        download_backend.click()\n    assert urlsplit(driver.current_url).path == f\"/{Endpoint.UPLOAD.value}/test.txt\"\n    assert driver.find_element(by=By.TAG_NAME, value=\"body\").text == exp_contents\n\n\n@pytest.mark.asyncio\nasync def test_on_drop(\n    tmp_path,\n    upload_file: AppHarness,\n    driver: WebDriver,\n):\n    \"\"\"Test the on_drop event handler.\n\n    Args:\n        tmp_path: pytest tmp_path fixture\n        upload_file: harness for UploadFile app.\n        driver: WebDriver instance.\n    \"\"\"\n    assert upload_file.app_instance is not None\n    token = poll_for_token(driver, upload_file)\n    full_state_name = upload_file.get_full_state_name([\"_upload_state\"])\n    state_name = upload_file.get_state_name(\"_upload_state\")\n    substate_token = f\"{token}_{full_state_name}\"\n\n    upload_box = driver.find_elements(By.XPATH, \"//input[@type='file']\")[\n        3\n    ]  # quaternary upload\n    assert upload_box\n\n    exp_name = \"drop_test.txt\"\n    exp_contents = \"dropped file contents!\"\n    target_file = tmp_path / exp_name\n    target_file.write_text(exp_contents)\n\n    # Simulate file drop by directly setting the file input\n    upload_box.send_keys(str(target_file))\n\n    # Wait for the on_drop event to be processed\n    await asyncio.sleep(0.5)\n\n    async def exp_name_in_quaternary():\n        state = await upload_file.get_state(substate_token)\n        return exp_name in state.substates[state_name].quaternary_names  # pyright: ignore[reportAttributeAccessIssue]\n\n    # Poll until the file names appear in the display\n    await AppHarness._poll_for_async(exp_name_in_quaternary)\n\n    # Verify through state that the file names were captured correctly\n    state = await upload_file.get_state(substate_token)\n    assert exp_name in state.substates[state_name].quaternary_names  # pyright: ignore[reportAttributeAccessIssue]\n"
  },
  {
    "path": "tests/integration/test_urls.py",
    "content": "\"\"\"Integration tests for all urls in Reflex.\"\"\"\n\nimport os\nimport re\nfrom pathlib import Path\n\nimport pytest\nimport requests\n\n\ndef check_urls(repo_dir: Path):\n    \"\"\"Check that all URLs in the repo are valid and secure.\n\n    Args:\n        repo_dir: The directory of the repo.\n\n    Returns:\n        A list of errors.\n    \"\"\"\n    url_pattern = re.compile(r'http[s]?://reflex\\.dev[^\\s\")]*')\n    errors = []\n\n    for root, _dirs, files in os.walk(repo_dir):\n        root = Path(root)\n        if root.stem == \"__pycache__\":\n            continue\n\n        for file_name in files:\n            if not file_name.endswith(\".py\") and not file_name.endswith(\".md\"):\n                continue\n\n            file_path = root / file_name\n            try:\n                for line in file_path.read_text().splitlines():\n                    urls = url_pattern.findall(line)\n                    for url in set(urls):\n                        if url.startswith(\"http://\"):\n                            errors.append(\n                                f\"Found insecure HTTP URL: {url} in {file_path}\"\n                            )\n                        url = url.strip('\"\\n')\n                        try:\n                            response = requests.head(\n                                url, allow_redirects=True, timeout=5\n                            )\n                            response.raise_for_status()\n                        except requests.RequestException as e:\n                            errors.append(\n                                f\"Error accessing URL: {url} in {file_path} | Error: {e}, , Check your path ends with a /\"\n                            )\n            except Exception as e:\n                errors.append(f\"Error reading file: {file_path} | Error: {e}\")\n\n    return errors\n\n\n@pytest.mark.parametrize(\n    \"repo_dir\",\n    [Path(__file__).resolve().parent.parent / \"reflex\"],\n)\ndef test_find_and_check_urls(repo_dir: Path):\n    \"\"\"Test that all URLs in the repo are valid and secure.\n\n    Args:\n        repo_dir: The directory of the repo.\n    \"\"\"\n    errors = check_urls(repo_dir)\n    assert not errors, \"\\n\".join(errors)\n"
  },
  {
    "path": "tests/integration/test_var_operations.py",
    "content": "\"\"\"Integration tests for var operations.\"\"\"\n\nfrom collections.abc import Generator\n\nimport pytest\nfrom selenium.webdriver.common.by import By\n\nfrom reflex.testing import AppHarness\n\n\ndef VarOperations():\n    \"\"\"App with var operations.\"\"\"\n    from typing import TypedDict\n\n    import reflex as rx\n    from reflex.vars.base import LiteralVar\n    from reflex.vars.sequence import ArrayVar\n\n    class Object(rx.Base):\n        name: str = \"hello\"\n        optional_none: str | None = None\n        optional_str: str | None = \"hello\"\n\n    class Person(TypedDict):\n        name: str\n        age: int\n\n    class VarOperationState(rx.State):\n        int_var1: rx.Field[int] = rx.field(10)\n        int_var2: rx.Field[int] = rx.field(5)\n        int_var3: rx.Field[int] = rx.field(7)\n        float_var1: rx.Field[float] = rx.field(10.5)\n        float_var2: rx.Field[float] = rx.field(5.5)\n        long_float: rx.Field[float] = rx.field(13212312312.1231231)\n        list1: rx.Field[list] = rx.field([1, 2])\n        list2: rx.Field[list] = rx.field([3, 4])\n        list3: rx.Field[list] = rx.field([\"first\", \"second\", \"third\"])\n        list4: rx.Field[list] = rx.field([Object(name=\"obj_1\"), Object(name=\"obj_2\")])\n        optional_list: rx.Field[list | None] = rx.field(None)\n        optional_dict: rx.Field[dict[str, str] | None] = rx.field(None)\n        optional_list_value: rx.Field[list[str] | None] = rx.field([\"red\", \"yellow\"])\n        optional_dict_value: rx.Field[dict[str, str] | None] = rx.field({\"name\": \"red\"})\n        str_var1: rx.Field[str] = rx.field(\"first\")\n        str_var2: rx.Field[str] = rx.field(\"second\")\n        str_var3: rx.Field[str] = rx.field(\"ThIrD\")\n        str_var4: rx.Field[str] = rx.field(\"a long string\")\n        dict1: rx.Field[dict[int, int]] = rx.field({1: 2})\n        dict2: rx.Field[dict[int, int]] = rx.field({3: 4})\n        html_str: rx.Field[str] = rx.field(\"<div>hello</div>\")\n        people: rx.Field[list[Person]] = rx.field([\n            {\"name\": \"Alice\", \"age\": 30},\n            {\"name\": \"Bob\", \"age\": 25},\n        ])\n        obj: rx.Field[Object] = rx.field(Object())\n\n    app = rx.App()\n\n    @rx.memo\n    def memo_comp(list1: list[int], int_var1: int, id: str):\n        return rx.text(list1, int_var1, id=id)\n\n    @rx.memo\n    def memo_comp_nested(int_var2: int, id: str):\n        return memo_comp(list1=[3, 4], int_var1=int_var2, id=id)\n\n    @app.add_page\n    def index():\n        return rx.vstack(\n            None,  # Testing that None doesn't break everything\n            rx.el.input(\n                id=\"token\",\n                value=VarOperationState.router.session.client_token,\n                is_read_only=True,\n            ),\n            # INT INT\n            rx.text(\n                VarOperationState.int_var1 + VarOperationState.int_var2,\n                id=\"int_add_int\",\n            ),\n            rx.text(\n                VarOperationState.int_var1 * VarOperationState.int_var2,\n                id=\"int_mult_int\",\n            ),\n            rx.text(\n                VarOperationState.int_var1 - VarOperationState.int_var2,\n                id=\"int_sub_int\",\n            ),\n            rx.text(\n                VarOperationState.int_var1**VarOperationState.int_var2,\n                id=\"int_exp_int\",\n            ),\n            rx.text(\n                VarOperationState.int_var1 / VarOperationState.int_var2,\n                id=\"int_div_int\",\n            ),\n            rx.text(\n                VarOperationState.int_var1 // VarOperationState.int_var3,\n                id=\"int_floor_int\",\n            ),\n            rx.text(\n                VarOperationState.int_var1 % VarOperationState.int_var2,\n                id=\"int_mod_int\",\n            ),\n            rx.text(\n                VarOperationState.int_var1 | VarOperationState.int_var2,\n                id=\"int_or_int\",\n            ),\n            rx.text(\n                (VarOperationState.int_var1 > VarOperationState.int_var2).to_string(),\n                id=\"int_gt_int\",\n            ),\n            rx.text(\n                (VarOperationState.int_var1 < VarOperationState.int_var2).to_string(),\n                id=\"int_lt_int\",\n            ),\n            rx.text(\n                (VarOperationState.int_var1 >= VarOperationState.int_var2).to_string(),\n                id=\"int_gte_int\",\n            ),\n            rx.text(\n                (VarOperationState.int_var1 <= VarOperationState.int_var2).to_string(),\n                id=\"int_lte_int\",\n            ),\n            rx.text(\n                VarOperationState.int_var1 & VarOperationState.int_var2,\n                id=\"int_and_int\",\n            ),\n            rx.text(\n                (VarOperationState.int_var1 | VarOperationState.int_var2).to_string(),\n                id=\"int_or_int\",\n            ),\n            rx.text(\n                (VarOperationState.int_var1 == VarOperationState.int_var2).to_string(),\n                id=\"int_eq_int\",\n            ),\n            rx.text(\n                (VarOperationState.int_var1 != VarOperationState.int_var2).to_string(),\n                id=\"int_neq_int\",\n            ),\n            # INT FLOAT OR FLOAT INT\n            rx.text(\n                VarOperationState.float_var1 + VarOperationState.int_var2,\n                id=\"float_add_int\",\n            ),\n            rx.text(\n                VarOperationState.float_var1 * VarOperationState.int_var2,\n                id=\"float_mult_int\",\n            ),\n            rx.text(\n                VarOperationState.float_var1 - VarOperationState.int_var2,\n                id=\"float_sub_int\",\n            ),\n            rx.text(\n                VarOperationState.float_var1**VarOperationState.int_var2,\n                id=\"float_exp_int\",\n            ),\n            rx.text(\n                VarOperationState.float_var1 / VarOperationState.int_var2,\n                id=\"float_div_int\",\n            ),\n            rx.text(\n                VarOperationState.float_var1 // VarOperationState.int_var3,\n                id=\"float_floor_int\",\n            ),\n            rx.text(\n                VarOperationState.float_var1 % VarOperationState.int_var2,\n                id=\"float_mod_int\",\n            ),\n            rx.text(\n                (VarOperationState.float_var1 > VarOperationState.int_var2).to_string(),\n                id=\"float_gt_int\",\n            ),\n            rx.text(\n                (VarOperationState.float_var1 < VarOperationState.int_var2).to_string(),\n                id=\"float_lt_int\",\n            ),\n            rx.text(\n                (\n                    VarOperationState.float_var1 >= VarOperationState.int_var2\n                ).to_string(),\n                id=\"float_gte_int\",\n            ),\n            rx.text(\n                (\n                    VarOperationState.float_var1 <= VarOperationState.int_var2\n                ).to_string(),\n                id=\"float_lte_int\",\n            ),\n            rx.text(\n                (\n                    VarOperationState.float_var1 == VarOperationState.int_var2\n                ).to_string(),\n                id=\"float_eq_int\",\n            ),\n            rx.text(\n                (\n                    VarOperationState.float_var1 != VarOperationState.int_var2\n                ).to_string(),\n                id=\"float_neq_int\",\n            ),\n            rx.text(\n                (VarOperationState.float_var1 & VarOperationState.int_var2).to_string(),\n                id=\"float_and_int\",\n            ),\n            rx.text(\n                (VarOperationState.float_var1 | VarOperationState.int_var2).to_string(),\n                id=\"float_or_int\",\n            ),\n            # INT, DICT\n            rx.text(\n                (VarOperationState.int_var1 | VarOperationState.dict1).to_string(),\n                id=\"int_or_dict\",\n            ),\n            rx.text(\n                (VarOperationState.int_var1 & VarOperationState.dict1).to_string(),\n                id=\"int_and_dict\",\n            ),\n            rx.text(\n                (VarOperationState.int_var1 == VarOperationState.dict1).to_string(),\n                id=\"int_eq_dict\",\n            ),\n            rx.text(\n                (VarOperationState.int_var1 != VarOperationState.dict1).to_string(),\n                id=\"int_neq_dict\",\n            ),\n            # FLOAT FLOAT\n            rx.text(\n                VarOperationState.float_var1 + VarOperationState.float_var2,\n                id=\"float_add_float\",\n            ),\n            rx.text(\n                VarOperationState.float_var1 * VarOperationState.float_var2,\n                id=\"float_mult_float\",\n            ),\n            rx.text(\n                VarOperationState.float_var1 - VarOperationState.float_var2,\n                id=\"float_sub_float\",\n            ),\n            rx.text(\n                VarOperationState.float_var1**VarOperationState.float_var2,\n                id=\"float_exp_float\",\n            ),\n            rx.text(\n                VarOperationState.float_var1 / VarOperationState.float_var2,\n                id=\"float_div_float\",\n            ),\n            rx.text(\n                VarOperationState.float_var1 // VarOperationState.float_var2,\n                id=\"float_floor_float\",\n            ),\n            rx.text(\n                VarOperationState.float_var1 % VarOperationState.float_var2,\n                id=\"float_mod_float\",\n            ),\n            rx.text(\n                (\n                    VarOperationState.float_var1 > VarOperationState.float_var2\n                ).to_string(),\n                id=\"float_gt_float\",\n            ),\n            rx.text(\n                (\n                    VarOperationState.float_var1 < VarOperationState.float_var2\n                ).to_string(),\n                id=\"float_lt_float\",\n            ),\n            rx.text(\n                (\n                    VarOperationState.float_var1 >= VarOperationState.float_var2\n                ).to_string(),\n                id=\"float_gte_float\",\n            ),\n            rx.text(\n                (\n                    VarOperationState.float_var1 <= VarOperationState.float_var2\n                ).to_string(),\n                id=\"float_lte_float\",\n            ),\n            rx.text(\n                (\n                    VarOperationState.float_var1 == VarOperationState.float_var2\n                ).to_string(),\n                id=\"float_eq_float\",\n            ),\n            rx.text(\n                (\n                    VarOperationState.float_var1 != VarOperationState.float_var2\n                ).to_string(),\n                id=\"float_neq_float\",\n            ),\n            rx.text(\n                (\n                    VarOperationState.float_var1 & VarOperationState.float_var2\n                ).to_string(),\n                id=\"float_and_float\",\n            ),\n            rx.text(\n                (\n                    VarOperationState.float_var1 | VarOperationState.float_var2\n                ).to_string(),\n                id=\"float_or_float\",\n            ),\n            # FLOAT STR\n            rx.text(\n                VarOperationState.float_var1 | VarOperationState.str_var1,\n                id=\"float_or_str\",\n            ),\n            rx.text(\n                VarOperationState.float_var1 & VarOperationState.str_var1,\n                id=\"float_and_str\",\n            ),\n            rx.text(\n                (\n                    VarOperationState.float_var1 == VarOperationState.str_var1\n                ).to_string(),\n                id=\"float_eq_str\",\n            ),\n            rx.text(\n                (\n                    VarOperationState.float_var1 != VarOperationState.str_var1\n                ).to_string(),\n                id=\"float_neq_str\",\n            ),\n            # FLOAT LIST\n            rx.text(\n                (VarOperationState.float_var1 | VarOperationState.list1).to_string(),\n                id=\"float_or_list\",\n            ),\n            rx.text(\n                (VarOperationState.float_var1 & VarOperationState.list1).to_string(),\n                id=\"float_and_list\",\n            ),\n            rx.text(\n                (VarOperationState.float_var1 == VarOperationState.list1).to_string(),\n                id=\"float_eq_list\",\n            ),\n            rx.text(\n                (VarOperationState.float_var1 != VarOperationState.list1).to_string(),\n                id=\"float_neq_list\",\n            ),\n            # FLOAT DICT\n            rx.text(\n                (VarOperationState.float_var1 | VarOperationState.dict1).to_string(),\n                id=\"float_or_dict\",\n            ),\n            rx.text(\n                (VarOperationState.float_var1 & VarOperationState.dict1).to_string(),\n                id=\"float_and_dict\",\n            ),\n            rx.text(\n                (VarOperationState.float_var1 == VarOperationState.dict1).to_string(),\n                id=\"float_eq_dict\",\n            ),\n            rx.text(\n                (VarOperationState.float_var1 != VarOperationState.dict1).to_string(),\n                id=\"float_neq_dict\",\n            ),\n            # STR STR\n            rx.text(\n                VarOperationState.str_var1 + VarOperationState.str_var2,\n                id=\"str_add_str\",\n            ),\n            rx.text(\n                (VarOperationState.str_var1 > VarOperationState.str_var2).to_string(),\n                id=\"str_gt_str\",\n            ),\n            rx.text(\n                (VarOperationState.str_var1 < VarOperationState.str_var2).to_string(),\n                id=\"str_lt_str\",\n            ),\n            rx.text(\n                (VarOperationState.str_var1 >= VarOperationState.str_var2).to_string(),\n                id=\"str_gte_str\",\n            ),\n            rx.text(\n                (VarOperationState.str_var1 <= VarOperationState.str_var2).to_string(),\n                id=\"str_lte_str\",\n            ),\n            rx.text(\n                (\n                    VarOperationState.float_var1 == VarOperationState.float_var2\n                ).to_string(),\n                id=\"str_eq_str\",\n            ),\n            rx.text(\n                (\n                    VarOperationState.float_var1 != VarOperationState.float_var2\n                ).to_string(),\n                id=\"str_neq_str\",\n            ),\n            rx.text(\n                VarOperationState.str_var1.contains(\"fir\").to_string(),\n                id=\"str_contains\",\n            ),\n            rx.text(\n                VarOperationState.str_var1 | VarOperationState.str_var1,\n                id=\"str_or_str\",\n            ),\n            rx.text(\n                VarOperationState.str_var1 & VarOperationState.str_var2,\n                id=\"str_and_str\",\n            ),\n            # STR, INT\n            rx.text(\n                VarOperationState.str_var1 * VarOperationState.int_var2,\n                id=\"str_mult_int\",\n            ),\n            rx.text(\n                VarOperationState.str_var1 & VarOperationState.int_var2,\n                id=\"str_and_int\",\n            ),\n            rx.text(\n                VarOperationState.str_var1 | VarOperationState.int_var2,\n                id=\"str_or_int\",\n            ),\n            rx.text(\n                (VarOperationState.str_var1 == VarOperationState.int_var1).to_string(),\n                id=\"str_eq_int\",\n            ),\n            rx.text(\n                (VarOperationState.str_var1 != VarOperationState.int_var1).to_string(),\n                id=\"str_neq_int\",\n            ),\n            # STR, LIST\n            rx.text(\n                VarOperationState.str_var1 | VarOperationState.list1,\n                id=\"str_or_list\",\n            ),\n            rx.text(\n                (VarOperationState.str_var1 & VarOperationState.list1).to_string(),\n                id=\"str_and_list\",\n            ),\n            rx.text(\n                (VarOperationState.str_var1 == VarOperationState.list1).to_string(),\n                id=\"str_eq_list\",\n            ),\n            rx.text(\n                (VarOperationState.str_var1 != VarOperationState.list1).to_string(),\n                id=\"str_neq_list\",\n            ),\n            # STR, DICT\n            rx.text(\n                VarOperationState.str_var1 | VarOperationState.dict1,\n                id=\"str_or_dict\",\n            ),\n            rx.text(\n                (VarOperationState.str_var1 & VarOperationState.dict1).to_string(),\n                id=\"str_and_dict\",\n            ),\n            rx.text(\n                (VarOperationState.str_var1 == VarOperationState.dict1).to_string(),\n                id=\"str_eq_dict\",\n            ),\n            rx.text(\n                (VarOperationState.str_var1 != VarOperationState.dict1).to_string(),\n                id=\"str_neq_dict\",\n            ),\n            # LIST, LIST\n            rx.text(\n                (VarOperationState.list1 + VarOperationState.list2).to_string(),\n                id=\"list_add_list\",\n            ),\n            rx.text(\n                (VarOperationState.list1 & VarOperationState.list2).to_string(),\n                id=\"list_and_list\",\n            ),\n            rx.text(\n                (VarOperationState.list1 | VarOperationState.list2).to_string(),\n                id=\"list_or_list\",\n            ),\n            rx.text(\n                (VarOperationState.list1 > VarOperationState.list2).to_string(),\n                id=\"list_gt_list\",\n            ),\n            rx.text(\n                (VarOperationState.list1 < VarOperationState.list2).to_string(),\n                id=\"list_lt_list\",\n            ),\n            rx.text(\n                (VarOperationState.list1 >= VarOperationState.list2).to_string(),\n                id=\"list_gte_list\",\n            ),\n            rx.text(\n                (VarOperationState.list1 <= VarOperationState.list2).to_string(),\n                id=\"list_lte_list\",\n            ),\n            rx.text(\n                (VarOperationState.list1 == VarOperationState.list2).to_string(),\n                id=\"list_eq_list\",\n            ),\n            rx.text(\n                (VarOperationState.list1 != VarOperationState.list2).to_string(),\n                id=\"list_neq_list\",\n            ),\n            rx.text(\n                VarOperationState.list1.contains(1).to_string(),\n                id=\"list_contains\",\n            ),\n            rx.text(VarOperationState.list4.pluck(\"name\").to_string(), id=\"list_pluck\"),\n            rx.text(VarOperationState.list1.reverse().to_string(), id=\"list_reverse\"),\n            # LIST, INT\n            rx.text(\n                (VarOperationState.list1 * VarOperationState.int_var2).to_string(),\n                id=\"list_mult_int\",\n            ),\n            rx.text(\n                (VarOperationState.list1 | VarOperationState.int_var1).to_string(),\n                id=\"list_or_int\",\n            ),\n            rx.text(\n                (VarOperationState.list1 & VarOperationState.int_var1).to_string(),\n                id=\"list_and_int\",\n            ),\n            rx.text(\n                (VarOperationState.list1 == VarOperationState.int_var1).to_string(),\n                id=\"list_eq_int\",\n            ),\n            rx.text(\n                (VarOperationState.list1 != VarOperationState.int_var1).to_string(),\n                id=\"list_neq_int\",\n            ),\n            # LIST, DICT\n            rx.text(\n                (VarOperationState.list1 | VarOperationState.dict1).to_string(),\n                id=\"list_or_dict\",\n            ),\n            rx.text(\n                (VarOperationState.list1 & VarOperationState.dict1).to_string(),\n                id=\"list_and_dict\",\n            ),\n            rx.text(\n                (VarOperationState.list1 == VarOperationState.dict1).to_string(),\n                id=\"list_eq_dict\",\n            ),\n            rx.text(\n                (VarOperationState.list1 != VarOperationState.dict1).to_string(),\n                id=\"list_neq_dict\",\n            ),\n            # DICT, DICT\n            rx.text(\n                (VarOperationState.dict1 | VarOperationState.dict2).to_string(),\n                id=\"dict_or_dict\",\n            ),\n            rx.text(\n                (VarOperationState.dict1 & VarOperationState.dict2).to_string(),\n                id=\"dict_and_dict\",\n            ),\n            rx.text(\n                (VarOperationState.dict1 == VarOperationState.dict2).to_string(),\n                id=\"dict_eq_dict\",\n            ),\n            rx.text(\n                (VarOperationState.dict1 != VarOperationState.dict2).to_string(),\n                id=\"dict_neq_dict\",\n            ),\n            rx.text(\n                VarOperationState.dict1.contains(1).to_string(),\n                id=\"dict_contains\",\n            ),\n            rx.text(VarOperationState.str_var3.lower(), id=\"str_lower\"),\n            rx.text(VarOperationState.str_var3.upper(), id=\"str_upper\"),\n            rx.text(VarOperationState.str_var4.split(\" \").to_string(), id=\"str_split\"),\n            rx.text(VarOperationState.list3.join(\"\"), id=\"list_join\"),\n            rx.text(VarOperationState.list3.join(\",\"), id=\"list_join_comma\"),\n            # Index from an op var\n            rx.text(\n                VarOperationState.list3[VarOperationState.int_var1 % 3],\n                id=\"list_index_mod\",\n            ),\n            rx.html(\n                VarOperationState.html_str,\n                id=\"html_str\",\n            ),\n            rx.el.mark(\"second\"),\n            rx.text(ArrayVar.range(2, 5).join(\",\"), id=\"list_join_range1\"),\n            rx.text(ArrayVar.range(2, 10, 2).join(\",\"), id=\"list_join_range2\"),\n            rx.text(ArrayVar.range(5, 0, -1).join(\",\"), id=\"list_join_range3\"),\n            rx.text(ArrayVar.range(0, 3).join(\",\"), id=\"list_join_range4\"),\n            rx.box(\n                # Test that foreach works with various non-array inputs without throwing\n                rx.foreach(\n                    rx.Var(\"undefined\").to(list),\n                    rx.text.span,\n                ),\n                rx.foreach(\n                    rx.Var(\"null\").to(list),\n                    rx.text.span,\n                ),\n                rx.foreach(\n                    rx.Var(\"({})\").to(list),\n                    rx.text.span,\n                ),\n                rx.foreach(\n                    rx.Var(\"2\").to(list),\n                    rx.text.span,\n                ),\n                rx.foreach(\n                    rx.Var(\"false\").to(list),\n                    rx.text.span,\n                ),\n            ),\n            rx.box(\n                rx.foreach(\n                    ArrayVar.range(0, 2),\n                    lambda x: rx.text(VarOperationState.list1[x], as_=\"p\"),\n                ),\n                id=\"foreach_list_arg\",\n            ),\n            rx.box(\n                rx.foreach(\n                    ArrayVar.range(0, 2),\n                    lambda x, ix: rx.text(VarOperationState.list1[ix], as_=\"p\"),\n                ),\n                id=\"foreach_list_ix\",\n            ),\n            rx.box(\n                rx.foreach(\n                    LiteralVar.create(list(range(3))).to(ArrayVar, list[int]),\n                    lambda x: rx.foreach(\n                        ArrayVar.range(x),\n                        lambda y: rx.text(VarOperationState.list1[y], as_=\"p\"),\n                    ),\n                ),\n                id=\"foreach_list_nested\",\n            ),\n            rx.box(\n                rx.foreach(\n                    ArrayVar.range(0, 2),\n                    lambda x: VarOperationState.list1[x],\n                ),\n                id=\"foreach_list_arg2\",\n            ),\n            memo_comp(\n                list1=VarOperationState.list1,\n                int_var1=VarOperationState.int_var1,\n                id=\"memo_comp\",\n            ),\n            memo_comp_nested(\n                int_var2=VarOperationState.int_var2,\n                id=\"memo_comp_nested\",\n            ),\n            # length\n            rx.box(\n                rx.text(VarOperationState.list3.length()),\n                id=\"list_length\",\n            ),\n            rx.box(\n                rx.text(VarOperationState.obj.length()),\n                id=\"obj_length\",\n            ),\n            # foreach in a match\n            rx.box(\n                rx.match(\n                    VarOperationState.list3.length(),\n                    (0, rx.text(\"No choices\")),\n                    (1, rx.text(\"One choice\")),\n                    rx.foreach(VarOperationState.list3, lambda choice: rx.text(choice)),\n                ),\n                id=\"foreach_in_match\",\n            ),\n            # Literal range var in a foreach\n            rx.box(rx.foreach(range(42, 80, 27), rx.text.span), id=\"range_in_foreach1\"),\n            rx.box(rx.foreach(range(42, 80, 3), rx.text.span), id=\"range_in_foreach2\"),\n            rx.box(rx.foreach(range(42, 20, -6), rx.text.span), id=\"range_in_foreach3\"),\n            rx.box(rx.foreach(range(42, 43, 5), rx.text.span), id=\"range_in_foreach4\"),\n            # Literal dict in a foreach\n            rx.box(rx.foreach({\"a\": 1, \"b\": 2}, rx.text.span), id=\"dict_in_foreach1\"),\n            # State Var dict in a foreach\n            rx.box(\n                rx.foreach(VarOperationState.dict1, rx.text.span),\n                id=\"dict_in_foreach2\",\n            ),\n            rx.box(\n                rx.foreach(\n                    VarOperationState.dict1.merge(VarOperationState.dict2),\n                    rx.text.span,\n                ),\n                id=\"dict_in_foreach3\",\n            ),\n            rx.box(\n                rx.foreach(\"abcdef\", lambda x: rx.text.span(x + \" \")),\n                id=\"str_in_foreach\",\n            ),\n            rx.box(\n                rx.foreach(VarOperationState.str_var1, lambda x: rx.text.span(x + \" \")),\n                id=\"str_var_in_foreach\",\n            ),\n            rx.box(\n                rx.foreach(\n                    VarOperationState.people,\n                    lambda person: rx.text.span(\n                        \"Hello \" + person[\"name\"], person[\"age\"] + 3\n                    ),\n                ),\n                id=\"typed_dict_in_foreach\",\n            ),\n            rx.box(\n                rx.foreach(VarOperationState.optional_list, rx.text.span),\n                id=\"optional_list\",\n            ),\n            rx.box(\n                rx.foreach(VarOperationState.optional_dict, rx.text.span),\n                id=\"optional_dict\",\n            ),\n            rx.box(\n                rx.foreach(VarOperationState.optional_list_value, rx.text.span),\n                id=\"optional_list_value\",\n            ),\n            rx.box(\n                rx.foreach(VarOperationState.optional_dict_value, rx.text.span),\n                id=\"optional_dict_value\",\n            ),\n            rx.box(\n                rx.text.span(f\"{rx.Var.create(13212312312.1231231)}\"),\n                id=\"float_format\",\n            ),\n            rx.box(\n                rx.text.span(f\"{rx.Var.create(13212312312.1231231):.0f}\"),\n                id=\"float_format_0f\",\n            ),\n            rx.box(\n                rx.text.span(f\"{rx.Var.create(13212312312.1231231):.1f}\"),\n                id=\"float_format_1f\",\n            ),\n            rx.box(\n                rx.text.span(f\"{rx.Var.create(13212312312.1231231):.2f}\"),\n                id=\"float_format_2f\",\n            ),\n            rx.box(\n                rx.text.span(f\"{rx.Var.create(13212312312.1231231):,}\"),\n                id=\"float_format_comma\",\n            ),\n            rx.box(\n                rx.text.span(f\"{rx.Var.create(13212312312.1231231):_}\"),\n                id=\"float_format_underscore\",\n            ),\n            rx.box(\n                rx.text.span(f\"{rx.Var.create(13212312312.1231231):,.0f}\"),\n                id=\"float_format_comma_0f\",\n            ),\n            rx.box(\n                rx.text.span(f\"{rx.Var.create(13212312312.1231231):,.1f}\"),\n                id=\"float_format_comma_1f\",\n            ),\n            rx.box(\n                rx.text.span(f\"{rx.Var.create(13212312312.1231231):,.2f}\"),\n                id=\"float_format_comma_2f\",\n            ),\n            rx.box(\n                rx.text.span(f\"{rx.Var.create(13212312312.1231231):_.0f}\"),\n                id=\"float_format_underscore_0f\",\n            ),\n            rx.box(\n                rx.text.span(f\"{rx.Var.create(13212312312.1231231):_.1f}\"),\n                id=\"float_format_underscore_1f\",\n            ),\n            rx.box(\n                rx.text.span(f\"{rx.Var.create(13212312312.1231231):_.2f}\"),\n                id=\"float_format_underscore_2f\",\n            ),\n            # ObjectVar\n            rx.box(\n                rx.text.span(VarOperationState.obj.name),\n                id=\"obj_name\",\n            ),\n            rx.box(\n                rx.text.span(VarOperationState.obj.optional_none),\n                id=\"obj_optional_none\",\n            ),\n            rx.box(\n                rx.text.span(VarOperationState.obj.optional_str),\n                id=\"obj_optional_str\",\n            ),\n            rx.box(\n                rx.text.span(VarOperationState.obj.get(\"optional_none\")),\n                id=\"obj_optional_none_get_none\",\n            ),\n            rx.box(\n                rx.text.span(VarOperationState.obj.get(\"optional_none\", \"foo\")),\n                id=\"obj_optional_none_get_foo\",\n            ),\n            rx.box(\n                rx.text.span(round(VarOperationState.long_float)),\n                id=\"float_round\",\n            ),\n            rx.box(\n                rx.text.span(round(VarOperationState.long_float, 2)),\n                id=\"float_round_2\",\n            ),\n        )\n\n\n@pytest.fixture(scope=\"module\")\ndef var_operations(tmp_path_factory) -> Generator[AppHarness, None, None]:\n    \"\"\"Start VarOperations app at tmp_path via AppHarness.\n\n    Args:\n        tmp_path_factory: pytest tmp_path_factory fixture\n\n    Yields:\n        running AppHarness instance\n    \"\"\"\n    with AppHarness.create(\n        root=tmp_path_factory.mktemp(\"var_operations\"),\n        app_source=VarOperations,\n    ) as harness:\n        assert harness.app_instance is not None, \"app is not running\"\n        yield harness\n\n\n@pytest.fixture\ndef driver(var_operations: AppHarness):\n    \"\"\"Get an instance of the browser open to the var operations app.\n\n    Args:\n        var_operations: harness for VarOperations app\n\n    Yields:\n        WebDriver instance.\n    \"\"\"\n    driver = var_operations.frontend()\n    try:\n        token_input = AppHarness.poll_for_or_raise_timeout(\n            lambda: driver.find_element(By.ID, \"token\")\n        )\n        # wait for the backend connection to send the token\n        token = var_operations.poll_for_value(token_input)\n        assert token is not None\n\n        yield driver\n    finally:\n        driver.quit()\n\n\ndef test_var_operations(driver, var_operations: AppHarness):\n    \"\"\"Test that the var operations produce the right results.\n\n    Args:\n        driver: selenium WebDriver open to the app\n        var_operations: AppHarness for the var operations app\n    \"\"\"\n    tests = [\n        # int, int\n        (\"int_add_int\", \"15\"),\n        (\"int_mult_int\", \"50\"),\n        (\"int_sub_int\", \"5\"),\n        (\"int_exp_int\", \"100000\"),\n        (\"int_div_int\", \"2\"),\n        (\"int_floor_int\", \"1\"),\n        (\"int_mod_int\", \"0\"),\n        (\"int_gt_int\", \"true\"),\n        (\"int_lt_int\", \"false\"),\n        (\"int_gte_int\", \"true\"),\n        (\"int_lte_int\", \"false\"),\n        (\"int_and_int\", \"5\"),\n        (\"int_or_int\", \"10\"),\n        (\"int_eq_int\", \"false\"),\n        (\"int_neq_int\", \"true\"),\n        # int, float\n        (\"float_add_int\", \"15.5\"),\n        (\"float_mult_int\", \"52.5\"),\n        (\"float_sub_int\", \"5.5\"),\n        (\"float_exp_int\", \"127628.15625\"),\n        (\"float_div_int\", \"2.1\"),\n        (\"float_floor_int\", \"1\"),\n        (\"float_mod_int\", \"0.5\"),\n        (\"float_gt_int\", \"true\"),\n        (\"float_lt_int\", \"false\"),\n        (\"float_gte_int\", \"true\"),\n        (\"float_lte_int\", \"false\"),\n        (\"float_eq_int\", \"false\"),\n        (\"float_neq_int\", \"true\"),\n        (\"float_and_int\", \"5\"),\n        (\"float_or_int\", \"10.5\"),\n        # int, dict\n        (\"int_or_dict\", \"10\"),\n        (\"int_and_dict\", '{\"1\":2}'),\n        (\"int_eq_dict\", \"false\"),\n        (\"int_neq_dict\", \"true\"),\n        # float, float\n        (\"float_add_float\", \"16\"),\n        (\"float_mult_float\", \"57.75\"),\n        (\"float_sub_float\", \"5\"),\n        (\"float_exp_float\", \"413562.49323606625\"),\n        (\"float_div_float\", \"1.9090909090909092\"),\n        (\"float_floor_float\", \"1\"),\n        (\"float_mod_float\", \"5\"),\n        (\"float_gt_float\", \"true\"),\n        (\"float_lt_float\", \"false\"),\n        (\"float_gte_float\", \"true\"),\n        (\"float_lte_float\", \"false\"),\n        (\"float_eq_float\", \"false\"),\n        (\"float_neq_float\", \"true\"),\n        (\"float_and_float\", \"5.5\"),\n        (\"float_or_float\", \"10.5\"),\n        # float, str\n        (\"float_or_str\", \"10.5\"),\n        (\"float_and_str\", \"first\"),\n        (\"float_eq_str\", \"false\"),\n        (\"float_neq_str\", \"true\"),\n        # float, list\n        (\"float_or_list\", \"10.5\"),\n        (\"float_and_list\", \"[1,2]\"),\n        (\"float_eq_list\", \"false\"),\n        (\"float_neq_list\", \"true\"),\n        # float, dict\n        (\"float_or_dict\", \"10.5\"),\n        (\"float_and_dict\", '{\"1\":2}'),\n        (\"float_eq_dict\", \"false\"),\n        (\"float_neq_dict\", \"true\"),\n        # str, str\n        (\"str_add_str\", \"firstsecond\"),\n        (\"str_gt_str\", \"false\"),\n        (\"str_lt_str\", \"true\"),\n        (\"str_gte_str\", \"false\"),\n        (\"str_lte_str\", \"true\"),\n        (\"str_eq_str\", \"false\"),\n        (\"str_neq_str\", \"true\"),\n        (\"str_and_str\", \"second\"),\n        (\"str_or_str\", \"first\"),\n        (\"str_contains\", \"true\"),\n        (\"str_lower\", \"third\"),\n        (\"str_upper\", \"THIRD\"),\n        (\"str_split\", '[\"a\",\"long\",\"string\"]'),\n        # str, int\n        (\"str_mult_int\", \"firstfirstfirstfirstfirst\"),\n        (\"str_and_int\", \"5\"),\n        (\"str_or_int\", \"first\"),\n        (\"str_eq_int\", \"false\"),\n        (\"str_neq_int\", \"true\"),\n        # str, list\n        (\"str_and_list\", \"[1,2]\"),\n        (\"str_or_list\", \"first\"),\n        (\"str_eq_list\", \"false\"),\n        (\"str_neq_list\", \"true\"),\n        # str, dict\n        (\"str_or_dict\", \"first\"),\n        (\"str_and_dict\", '{\"1\":2}'),\n        (\"str_eq_dict\", \"false\"),\n        (\"str_neq_dict\", \"true\"),\n        # list, list\n        (\"list_add_list\", \"[1,2,3,4]\"),\n        (\"list_gt_list\", \"false\"),\n        (\"list_lt_list\", \"true\"),\n        (\"list_gte_list\", \"false\"),\n        (\"list_lte_list\", \"true\"),\n        (\"list_eq_list\", \"false\"),\n        (\"list_neq_list\", \"true\"),\n        (\"list_and_list\", \"[3,4]\"),\n        (\"list_or_list\", \"[1,2]\"),\n        (\"list_contains\", \"true\"),\n        (\"list_pluck\", '[\"obj_1\",\"obj_2\"]'),\n        (\"list_reverse\", \"[2,1]\"),\n        (\"list_join\", \"firstsecondthird\"),\n        (\"list_join_comma\", \"first,second,third\"),\n        (\"list_join_range1\", \"2,3,4\"),\n        (\"list_join_range2\", \"2,4,6,8\"),\n        (\"list_join_range3\", \"5,4,3,2,1\"),\n        (\"list_join_range4\", \"0,1,2\"),\n        # list, int\n        (\"list_mult_int\", \"[1,2,1,2,1,2,1,2,1,2]\"),\n        (\"list_or_int\", \"[1,2]\"),\n        (\"list_and_int\", \"10\"),\n        (\"list_eq_int\", \"false\"),\n        (\"list_neq_int\", \"true\"),\n        # list, dict\n        (\"list_and_dict\", '{\"1\":2}'),\n        (\"list_or_dict\", \"[1,2]\"),\n        (\"list_eq_dict\", \"false\"),\n        (\"list_neq_dict\", \"true\"),\n        # dict, dict\n        (\"dict_or_dict\", '{\"1\":2}'),\n        (\"dict_and_dict\", '{\"3\":4}'),\n        (\"dict_eq_dict\", \"false\"),\n        (\"dict_neq_dict\", \"true\"),\n        (\"dict_contains\", \"true\"),\n        # index from an op var\n        (\"list_index_mod\", \"second\"),\n        # html component with var\n        (\"html_str\", \"hello\"),\n        # index into list with foreach\n        (\"foreach_list_arg\", \"1\\n2\"),\n        (\"foreach_list_ix\", \"1\\n2\"),\n        (\"foreach_list_nested\", \"1\\n1\\n2\"),\n        (\"foreach_list_arg2\", \"12\"),\n        # rx.memo component with state\n        (\"memo_comp\", \"1210\"),\n        (\"memo_comp_nested\", \"345\"),\n        # length\n        (\"list_length\", \"3\"),\n        (\"obj_length\", \"3\"),\n        # foreach in a match\n        (\"foreach_in_match\", \"first\\nsecond\\nthird\"),\n        # literal range in a foreach\n        (\"range_in_foreach1\", \"4269\"),\n        (\"range_in_foreach2\", \"42454851545760636669727578\"),\n        (\"range_in_foreach3\", \"42363024\"),\n        (\"range_in_foreach4\", \"42\"),\n        (\"dict_in_foreach1\", \"a1b2\"),\n        (\"dict_in_foreach2\", \"12\"),\n        (\"dict_in_foreach3\", \"1234\"),\n        (\"str_in_foreach\", \"a b c d e f\"),\n        (\"str_var_in_foreach\", \"f i r s t\"),\n        (\"typed_dict_in_foreach\", \"Hello Alice33Hello Bob28\"),\n        # fstring operations\n        (\"float_format\", \"13212312312.123123\"),\n        (\"float_format_0f\", \"13212312312\"),\n        (\"float_format_1f\", \"13212312312.1\"),\n        (\"float_format_2f\", \"13212312312.12\"),\n        (\"float_format_comma\", \"13,212,312,312.123\"),\n        (\"float_format_underscore\", \"13_212_312_312.123\"),\n        (\"float_format_comma_0f\", \"13,212,312,312\"),\n        (\"float_format_comma_1f\", \"13,212,312,312.1\"),\n        (\"float_format_comma_2f\", \"13,212,312,312.12\"),\n        (\"float_format_underscore_0f\", \"13_212_312_312\"),\n        (\"float_format_underscore_1f\", \"13_212_312_312.1\"),\n        (\"float_format_underscore_2f\", \"13_212_312_312.12\"),\n        (\"obj_name\", \"hello\"),\n        (\"obj_optional_none\", \"\"),\n        (\"obj_optional_str\", \"hello\"),\n        (\"obj_optional_none_get_none\", \"\"),\n        (\"obj_optional_none_get_foo\", \"foo\"),\n        (\"float_round\", \"13212312312\"),\n        (\"float_round_2\", \"13212312312.12\"),\n    ]\n\n    for tag, expected in tests:\n        existing = driver.find_element(By.ID, tag).text\n        assert existing == expected, (\n            f\"Failed on {tag}, expected {expected} but got {existing}\"\n        )\n\n    # Highlight component with var query (does not plumb ID)\n    assert driver.find_element(By.TAG_NAME, \"mark\").text == \"second\"\n"
  },
  {
    "path": "tests/integration/tests_playwright/test_appearance.py",
    "content": "from collections.abc import Generator\n\nimport pytest\nfrom playwright.sync_api import Page, expect\n\nfrom reflex.testing import AppHarness\n\n\ndef DefaultLightModeApp():\n    import reflex as rx\n    from reflex.style import color_mode\n\n    app = rx.App(theme=rx.theme(appearance=\"light\"))\n\n    @app.add_page\n    def index():\n        return rx.text(color_mode)\n\n\ndef DefaultDarkModeApp():\n    import reflex as rx\n    from reflex.style import color_mode\n\n    app = rx.App(theme=rx.theme(appearance=\"dark\"))\n\n    @app.add_page\n    def index():\n        return rx.text(color_mode)\n\n\ndef DefaultSystemModeApp():\n    import reflex as rx\n    from reflex.style import color_mode\n\n    app = rx.App()\n\n    @app.add_page\n    def index():\n        return rx.text(color_mode)\n\n\ndef ColorToggleApp():\n    import reflex as rx\n    from reflex.style import color_mode, resolved_color_mode, set_color_mode\n\n    app = rx.App(theme=rx.theme(appearance=\"light\"))\n\n    @app.add_page\n    def index():\n        return rx.box(\n            rx.segmented_control.root(\n                rx.segmented_control.item(\n                    rx.icon(tag=\"monitor\", size=20),\n                    value=\"system\",\n                ),\n                rx.segmented_control.item(\n                    rx.icon(tag=\"sun\", size=20),\n                    value=\"light\",\n                ),\n                rx.segmented_control.item(\n                    rx.icon(tag=\"moon\", size=20),\n                    value=\"dark\",\n                ),\n                on_change=set_color_mode,  # pyright: ignore[reportArgumentType]\n                variant=\"classic\",\n                radius=\"large\",\n                value=color_mode,\n            ),\n            rx.text(color_mode, id=\"current_color_mode\"),\n            rx.text(resolved_color_mode, id=\"resolved_color_mode\"),\n            rx.text(rx.color_mode_cond(\"LightMode\", \"DarkMode\"), id=\"color_mode_cond\"),\n        )\n\n\n@pytest.fixture\ndef light_mode_app(tmp_path_factory) -> Generator[AppHarness, None, None]:\n    \"\"\"Start DefaultLightMode app at tmp_path via AppHarness.\n\n    Args:\n        tmp_path_factory: pytest tmp_path_factory fixture\n\n    Yields:\n        running AppHarness instance\n\n    \"\"\"\n    with AppHarness.create(\n        root=tmp_path_factory.mktemp(\"appearance_app\"),\n        app_source=DefaultLightModeApp,\n    ) as harness:\n        assert harness.app_instance is not None, \"app is not running\"\n        yield harness\n\n\n@pytest.fixture\ndef dark_mode_app(tmp_path_factory) -> Generator[AppHarness, None, None]:\n    \"\"\"Start DefaultDarkMode app at tmp_path via AppHarness.\n\n    Args:\n        tmp_path_factory: pytest tmp_path_factory fixture\n\n    Yields:\n        running AppHarness instance\n\n    \"\"\"\n    with AppHarness.create(\n        root=tmp_path_factory.mktemp(\"appearance_app\"),\n        app_source=DefaultDarkModeApp,\n    ) as harness:\n        assert harness.app_instance is not None, \"app is not running\"\n        yield harness\n\n\n@pytest.fixture\ndef system_mode_app(tmp_path_factory) -> Generator[AppHarness, None, None]:\n    \"\"\"Start DefaultSystemMode app at tmp_path via AppHarness.\n\n    Args:\n        tmp_path_factory: pytest tmp_path_factory fixture\n\n    Yields:\n        running AppHarness instance\n\n    \"\"\"\n    with AppHarness.create(\n        root=tmp_path_factory.mktemp(\"appearance_app\"),\n        app_source=DefaultSystemModeApp,\n    ) as harness:\n        assert harness.app_instance is not None, \"app is not running\"\n        yield harness\n\n\n@pytest.fixture\ndef color_toggle_app(tmp_path_factory) -> Generator[AppHarness, None, None]:\n    \"\"\"Start ColorToggle app at tmp_path via AppHarness.\n\n    Args:\n        tmp_path_factory: pytest tmp_path_factory fixture\n\n    Yields:\n        running AppHarness instance\n\n    \"\"\"\n    with AppHarness.create(\n        root=tmp_path_factory.mktemp(\"appearance_app\"),\n        app_source=ColorToggleApp,\n    ) as harness:\n        assert harness.app_instance is not None, \"app is not running\"\n        yield harness\n\n\ndef test_appearance_light_mode(light_mode_app: AppHarness, page: Page):\n    assert light_mode_app.frontend_url is not None\n    page.goto(light_mode_app.frontend_url)\n\n    expect(page.get_by_text(\"light\")).to_be_visible()\n\n\ndef test_appearance_dark_mode(dark_mode_app: AppHarness, page: Page):\n    assert dark_mode_app.frontend_url is not None\n    page.goto(dark_mode_app.frontend_url)\n\n    expect(page.get_by_text(\"dark\")).to_be_visible()\n\n\ndef test_appearance_system_mode(system_mode_app: AppHarness, page: Page):\n    assert system_mode_app.frontend_url is not None\n    page.goto(system_mode_app.frontend_url)\n\n    expect(page.get_by_text(\"system\")).to_be_visible()\n\n\ndef test_appearance_color_toggle(color_toggle_app: AppHarness, page: Page):\n    assert color_toggle_app.frontend_url is not None\n    page.goto(color_toggle_app.frontend_url)\n\n    # Radio buttons locators.\n    radio_system = page.get_by_role(\"radio\").nth(0)\n    radio_light = page.get_by_role(\"radio\").nth(1)\n    radio_dark = page.get_by_role(\"radio\").nth(2)\n\n    # Text locators to check.\n    current_color_mode = page.locator(\"id=current_color_mode\")\n    resolved_color_mode = page.locator(\"id=resolved_color_mode\")\n    color_mode_cond = page.locator(\"id=color_mode_cond\")\n    root_body = page.locator('div[data-is-root-theme=\"true\"]')\n\n    # Background colors.\n    dark_background = \"rgb(17, 17, 19)\"  # value based on dark native appearance, can change depending on the browser\n    light_background = \"rgb(255, 255, 255)\"\n\n    # check initial state\n    expect(current_color_mode).to_have_text(\"light\")\n    expect(resolved_color_mode).to_have_text(\"light\")\n    expect(color_mode_cond).to_have_text(\"LightMode\")\n    expect(root_body).to_have_css(\"background-color\", light_background)\n\n    # click dark mode\n    radio_dark.click()\n    expect(current_color_mode).to_have_text(\"dark\")\n    expect(resolved_color_mode).to_have_text(\"dark\")\n    expect(color_mode_cond).to_have_text(\"DarkMode\")\n    expect(root_body).to_have_css(\"background-color\", dark_background)\n\n    # click light mode\n    radio_light.click()\n    expect(current_color_mode).to_have_text(\"light\")\n    expect(resolved_color_mode).to_have_text(\"light\")\n    expect(color_mode_cond).to_have_text(\"LightMode\")\n    expect(root_body).to_have_css(\"background-color\", light_background)\n    page.reload()\n    expect(root_body).to_have_css(\"background-color\", light_background)\n\n    # click system mode\n    radio_system.click()\n    expect(current_color_mode).to_have_text(\"system\")\n    expect(resolved_color_mode).to_have_text(\"light\")\n    expect(color_mode_cond).to_have_text(\"LightMode\")\n    expect(root_body).to_have_css(\"background-color\", light_background)\n"
  },
  {
    "path": "tests/integration/tests_playwright/test_datetime_operations.py",
    "content": "from collections.abc import Generator\n\nimport pytest\nfrom playwright.sync_api import Page, expect\n\nfrom reflex.testing import AppHarness\n\n\ndef DatetimeOperationsApp():\n    from datetime import datetime\n\n    import reflex as rx\n\n    class DtOperationsState(rx.State):\n        date1: datetime = datetime(2021, 1, 1)\n        date2: datetime = datetime(2031, 1, 1)\n        date3: datetime = datetime(2021, 1, 1)\n\n    app = rx.App(_state=DtOperationsState)\n\n    @app.add_page\n    def index():\n        return rx.vstack(\n            rx.text(DtOperationsState.date1, id=\"date1\"),\n            rx.text(DtOperationsState.date2, id=\"date2\"),\n            rx.text(DtOperationsState.date3, id=\"date3\"),\n            rx.text(\"Operations between date1 and date2\"),\n            rx.text(DtOperationsState.date1 == DtOperationsState.date2, id=\"1_eq_2\"),\n            rx.text(DtOperationsState.date1 != DtOperationsState.date2, id=\"1_neq_2\"),\n            rx.text(DtOperationsState.date1 < DtOperationsState.date2, id=\"1_lt_2\"),\n            rx.text(DtOperationsState.date1 <= DtOperationsState.date2, id=\"1_le_2\"),\n            rx.text(DtOperationsState.date1 > DtOperationsState.date2, id=\"1_gt_2\"),\n            rx.text(DtOperationsState.date1 >= DtOperationsState.date2, id=\"1_ge_2\"),\n            rx.text(\"Operations between date1 and date3\"),\n            rx.text(DtOperationsState.date1 == DtOperationsState.date3, id=\"1_eq_3\"),\n            rx.text(DtOperationsState.date1 != DtOperationsState.date3, id=\"1_neq_3\"),\n            rx.text(DtOperationsState.date1 < DtOperationsState.date3, id=\"1_lt_3\"),\n            rx.text(DtOperationsState.date1 <= DtOperationsState.date3, id=\"1_le_3\"),\n            rx.text(DtOperationsState.date1 > DtOperationsState.date3, id=\"1_gt_3\"),\n            rx.text(DtOperationsState.date1 >= DtOperationsState.date3, id=\"1_ge_3\"),\n        )\n\n\n@pytest.fixture\ndef datetime_operations_app(tmp_path_factory) -> Generator[AppHarness, None, None]:\n    \"\"\"Start Table app at tmp_path via AppHarness.\n\n    Args:\n        tmp_path_factory: pytest tmp_path_factory fixture\n\n    Yields:\n        running AppHarness instance\n\n    \"\"\"\n    with AppHarness.create(\n        root=tmp_path_factory.mktemp(\"datetime_operations_app\"),\n        app_source=DatetimeOperationsApp,\n    ) as harness:\n        assert harness.app_instance is not None, \"app is not running\"\n        yield harness\n\n\ndef test_datetime_operations(datetime_operations_app: AppHarness, page: Page):\n    assert datetime_operations_app.frontend_url is not None\n\n    page.goto(datetime_operations_app.frontend_url)\n    expect(page).to_have_url(datetime_operations_app.frontend_url)\n    # Check the actual values\n    expect(page.locator(\"id=date1\")).to_have_text(\"2021-01-01 00:00:00\")\n    expect(page.locator(\"id=date2\")).to_have_text(\"2031-01-01 00:00:00\")\n    expect(page.locator(\"id=date3\")).to_have_text(\"2021-01-01 00:00:00\")\n\n    # Check the operations between date1 and date2\n    expect(page.locator(\"id=1_eq_2\")).to_have_text(\"false\")\n    expect(page.locator(\"id=1_neq_2\")).to_have_text(\"true\")\n    expect(page.locator(\"id=1_lt_2\")).to_have_text(\"true\")\n    expect(page.locator(\"id=1_le_2\")).to_have_text(\"true\")\n    expect(page.locator(\"id=1_gt_2\")).to_have_text(\"false\")\n    expect(page.locator(\"id=1_ge_2\")).to_have_text(\"false\")\n\n    # Check the operations between date1 and date3\n    expect(page.locator(\"id=1_eq_3\")).to_have_text(\"true\")\n    expect(page.locator(\"id=1_neq_3\")).to_have_text(\"false\")\n    expect(page.locator(\"id=1_lt_3\")).to_have_text(\"false\")\n    expect(page.locator(\"id=1_le_3\")).to_have_text(\"true\")\n    expect(page.locator(\"id=1_gt_3\")).to_have_text(\"false\")\n    expect(page.locator(\"id=1_ge_3\")).to_have_text(\"true\")\n"
  },
  {
    "path": "tests/integration/tests_playwright/test_link_hover.py",
    "content": "from collections.abc import Generator\n\nimport pytest\nfrom playwright.sync_api import Page, expect\n\nfrom reflex.testing import AppHarness\n\n\ndef LinkApp():\n    import reflex as rx\n\n    app = rx.App()\n\n    def index():\n        return rx.vstack(\n            rx.box(height=\"10em\"),  # spacer, so the link isn't hovered initially\n            rx.link(\n                \"Click me\",\n                href=\"#\",\n                color=\"blue\",\n                _hover=rx.Style({\"color\": \"red\"}),\n            ),\n        )\n\n    app.add_page(index, \"/\")\n\n\n@pytest.fixture\ndef link_app(tmp_path_factory) -> Generator[AppHarness, None, None]:\n    with AppHarness.create(\n        root=tmp_path_factory.mktemp(\"link_app\"),\n        app_source=LinkApp,\n    ) as harness:\n        assert harness.app_instance is not None, \"app is not running\"\n        yield harness\n\n\ndef test_link_hover(link_app: AppHarness, page: Page):\n    assert link_app.frontend_url is not None\n    page.goto(link_app.frontend_url)\n\n    link = page.get_by_role(\"link\")\n    expect(link).to_have_text(\"Click me\")\n    expect(link).to_have_css(\"color\", \"rgb(0, 0, 255)\")\n    link.hover()\n    expect(link).to_have_css(\"color\", \"rgb(255, 0, 0)\")\n"
  },
  {
    "path": "tests/integration/tests_playwright/test_stateless_app.py",
    "content": "\"\"\"Integration tests for a stateless app.\"\"\"\n\nfrom collections.abc import Generator\n\nimport httpx\nimport pytest\nfrom playwright.sync_api import Page, expect\n\nimport reflex as rx\nfrom reflex.testing import AppHarness\n\n\ndef StatelessApp():\n    \"\"\"A stateless app that renders a heading.\"\"\"\n    import reflex as rx\n\n    def index():\n        return rx.heading(\"This is a stateless app\")\n\n    app = rx.App(enable_state=False)\n    app.add_page(index)\n\n\n@pytest.fixture(scope=\"module\")\ndef stateless_app(tmp_path_factory) -> Generator[AppHarness, None, None]:\n    \"\"\"Create a stateless app AppHarness.\n\n    Args:\n        tmp_path_factory: pytest fixture for creating temporary directories.\n\n    Yields:\n        AppHarness: A harness for testing the stateless app.\n    \"\"\"\n    with AppHarness.create(\n        root=tmp_path_factory.mktemp(\"stateless_app\"),\n        app_source=StatelessApp,\n    ) as harness:\n        yield harness\n\n\ndef test_statelessness(stateless_app: AppHarness, page: Page):\n    \"\"\"Test that the stateless app renders a heading but backend/_event is not mounted.\n\n    Args:\n        stateless_app: A harness for testing the stateless app.\n        page: A Playwright page.\n    \"\"\"\n    assert stateless_app.frontend_url is not None\n    assert stateless_app.backend is not None\n    assert stateless_app.backend.started\n\n    res = httpx.get(rx.config.get_config().api_url + \"/_event\")\n    assert res.status_code == 404\n\n    res2 = httpx.get(rx.config.get_config().api_url + \"/ping\")\n    assert res2.status_code == 200\n\n    page.goto(stateless_app.frontend_url)\n    expect(page.get_by_role(\"heading\")).to_have_text(\"This is a stateless app\")\n"
  },
  {
    "path": "tests/integration/tests_playwright/test_table.py",
    "content": "\"\"\"Integration tests for table and related components.\"\"\"\n\nfrom collections.abc import Generator\n\nimport pytest\nfrom playwright.sync_api import Page, expect\n\nfrom reflex.testing import AppHarness\n\nexpected_col_headers = [\"Name\", \"Age\", \"Location\"]\nexpected_row_headers = [\"John\", \"Jane\", \"Joe\"]\nexpected_cells_data = [\n    [\"30\", \"New York\"],\n    [\"31\", \"San Francisco\"],\n    [\"32\", \"Los Angeles\"],\n]\n\n\ndef Table():\n    \"\"\"App using table component.\"\"\"\n    import reflex as rx\n\n    app = rx.App()\n\n    @app.add_page\n    def index():\n        return rx.center(\n            rx.table.root(\n                rx.table.header(\n                    rx.table.row(\n                        rx.table.column_header_cell(\"Name\"),\n                        rx.table.column_header_cell(\"Age\"),\n                        rx.table.column_header_cell(\"Location\"),\n                    ),\n                ),\n                rx.table.body(\n                    rx.table.row(\n                        rx.table.row_header_cell(\"John\"),\n                        rx.table.cell(30),\n                        rx.table.cell(\"New York\"),\n                    ),\n                    rx.table.row(\n                        rx.table.row_header_cell(\"Jane\"),\n                        rx.table.cell(31),\n                        rx.table.cell(\"San Francisco\"),\n                    ),\n                    rx.table.row(\n                        rx.table.row_header_cell(\"Joe\"),\n                        rx.table.cell(32),\n                        rx.table.cell(\"Los Angeles\"),\n                    ),\n                ),\n                width=\"100%\",\n            ),\n        )\n\n\n@pytest.fixture\ndef table_app(tmp_path_factory) -> Generator[AppHarness, None, None]:\n    \"\"\"Start Table app at tmp_path via AppHarness.\n\n    Args:\n        tmp_path_factory: pytest tmp_path_factory fixture\n\n    Yields:\n        running AppHarness instance\n\n    \"\"\"\n    with AppHarness.create(\n        root=tmp_path_factory.mktemp(\"table\"),\n        app_source=Table,\n    ) as harness:\n        assert harness.app_instance is not None, \"app is not running\"\n        yield harness\n\n\ndef test_table(page: Page, table_app: AppHarness):\n    \"\"\"Test that a table component is rendered properly.\n\n    Args:\n        table_app: Harness for Table app\n        page: Playwright page instance\n    \"\"\"\n    assert table_app.frontend_url is not None, \"frontend url is not available\"\n\n    page.goto(table_app.frontend_url)\n    table = page.get_by_role(\"table\")\n\n    # Check column headers\n    expect(table.get_by_role(\"columnheader\")).to_have_count(3)\n    headers = table.get_by_role(\"columnheader\")\n    for header, exp_value in zip(headers.all(), expected_col_headers, strict=True):\n        expect(header).to_have_text(exp_value)\n\n    # Check rows headers\n    rows = table.get_by_role(\"rowheader\")\n    for row, expected_row in zip(rows.all(), expected_row_headers, strict=True):\n        expect(row).to_have_text(expected_row)\n\n    # Check cells\n    rows = table.get_by_role(\"cell\").all_inner_texts()\n    for i, expected_row in enumerate(expected_cells_data):\n        idx = i * 2\n        assert [rows[idx], rows[idx + 1]] == expected_row\n"
  },
  {
    "path": "tests/integration/utils.py",
    "content": "\"\"\"Helper utilities for integration tests.\"\"\"\n\nfrom __future__ import annotations\n\nfrom collections.abc import Generator, Iterator\nfrom contextlib import contextmanager\n\nfrom selenium.webdriver.remote.webdriver import WebDriver\n\nfrom reflex.testing import AppHarness\n\n\n@contextmanager\ndef poll_for_navigation(\n    driver: WebDriver, timeout: int = 5\n) -> Generator[None, None, None]:\n    \"\"\"Wait for driver url to change.\n\n    Use as a contextmanager, and apply the navigation event inside the context\n    block, polling will occur after the context block exits.\n\n    Args:\n        driver: WebDriver instance.\n        timeout: Time to wait for url to change.\n\n    Yields:\n        None\n    \"\"\"\n    prev_url = driver.current_url\n\n    yield\n\n    AppHarness.expect(lambda: prev_url != driver.current_url, timeout=timeout)\n\n\nclass LocalStorage:\n    \"\"\"Class to access local storage.\n\n    https://stackoverflow.com/a/46361900\n    \"\"\"\n\n    storage_key = \"localStorage\"\n\n    def __init__(self, driver: WebDriver):\n        \"\"\"Initialize the class.\n\n        Args:\n            driver: WebDriver instance.\n        \"\"\"\n        self.driver = driver\n\n    def __len__(self) -> int:\n        \"\"\"Get the number of items in local storage.\n\n        Returns:\n            The number of items in local storage.\n        \"\"\"\n        return int(\n            self.driver.execute_script(f\"return window.{self.storage_key}.length;\")\n        )\n\n    def items(self) -> dict[str, str]:\n        \"\"\"Get all items in local storage.\n\n        Returns:\n            A dict mapping keys to values.\n        \"\"\"\n        return self.driver.execute_script(\n            f\"var ls = window.{self.storage_key}, items = {{}}; \"\n            \"for (var i = 0, k; i < ls.length; ++i) \"\n            \"  items[k = ls.key(i)] = ls.getItem(k); \"\n            \"return items; \"\n        )\n\n    def keys(self) -> list[str]:\n        \"\"\"Get all keys in local storage.\n\n        Returns:\n            A list of keys.\n        \"\"\"\n        return self.driver.execute_script(\n            f\"var ls = window.{self.storage_key}, keys = []; \"\n            \"for (var i = 0; i < ls.length; ++i) \"\n            \"  keys[i] = ls.key(i); \"\n            \"return keys; \"\n        )\n\n    def get(self, key) -> str:\n        \"\"\"Get a key from local storage.\n\n        Args:\n            key: The key to get.\n\n        Returns:\n            The value of the key.\n        \"\"\"\n        return self.driver.execute_script(\n            f\"return window.{self.storage_key}.getItem(arguments[0]);\", key\n        )\n\n    def set(self, key, value) -> None:\n        \"\"\"Set a key in local storage.\n\n        Args:\n            key: The key to set.\n            value: The value to set the key to.\n        \"\"\"\n        self.driver.execute_script(\n            f\"window.{self.storage_key}.setItem(arguments[0], arguments[1]);\",\n            key,\n            value,\n        )\n\n    def has(self, key) -> bool:\n        \"\"\"Check if key is in local storage.\n\n        Args:\n            key: The key to check.\n\n        Returns:\n            True if key is in local storage, False otherwise.\n        \"\"\"\n        return key in self\n\n    def remove(self, key) -> None:\n        \"\"\"Remove a key from local storage.\n\n        Args:\n            key: The key to remove.\n        \"\"\"\n        self.driver.execute_script(\n            f\"window.{self.storage_key}.removeItem(arguments[0]);\", key\n        )\n\n    def clear(self) -> None:\n        \"\"\"Clear all local storage.\"\"\"\n        self.driver.execute_script(f\"window.{self.storage_key}.clear();\")\n\n    def __getitem__(self, key) -> str:\n        \"\"\"Get a key from local storage.\n\n        Args:\n            key: The key to get.\n\n        Returns:\n            The value of the key.\n\n        Raises:\n            KeyError: If key is not in local storage.\n        \"\"\"\n        value = self.get(key)\n        if value is None:\n            raise KeyError(key)\n        return value\n\n    def __setitem__(self, key, value) -> None:\n        \"\"\"Set a key in local storage.\n\n        Args:\n            key: The key to set.\n            value: The value to set the key to.\n        \"\"\"\n        self.set(key, value)\n\n    def __contains__(self, key) -> bool:\n        \"\"\"Check if key is in local storage.\n\n        Args:\n            key: The key to check.\n\n        Returns:\n            True if key is in local storage, False otherwise.\n        \"\"\"\n        return self.has(key)\n\n    def __iter__(self) -> Iterator[str]:\n        \"\"\"Iterate over the keys in local storage.\n\n        Returns:\n            An iterator over the items in local storage.\n        \"\"\"\n        return iter(self.keys())\n\n\nclass SessionStorage(LocalStorage):\n    \"\"\"Class to access session storage.\n\n    https://stackoverflow.com/a/46361900\n    \"\"\"\n\n    storage_key = \"sessionStorage\"\n"
  },
  {
    "path": "tests/test_node_version.py",
    "content": "\"\"\"Test for latest node version being able to run reflex.\"\"\"\n\nfrom __future__ import annotations\n\nfrom collections.abc import Generator\nfrom typing import Any\n\nimport httpx\nimport pytest\nfrom playwright.sync_api import Page, expect\n\nfrom reflex.testing import AppHarness\n\n\ndef TestNodeVersionApp():\n    \"\"\"A test app for node latest version.\"\"\"\n    import reflex as rx\n    from reflex.utils.js_runtimes import get_node_version\n\n    class TestNodeVersionConfig(rx.Config):\n        pass\n\n    class TestNodeVersionState(rx.State):\n        @rx.var\n        def node_version(self) -> str:\n            return str(get_node_version())\n\n    app = rx.App()\n\n    @app.add_page\n    def index():\n        return rx.heading(\"Node Version check v\", TestNodeVersionState.node_version)\n\n\n@pytest.fixture\ndef node_version_app(tmp_path) -> Generator[AppHarness, Any, None]:\n    \"\"\"Fixture to start TestNodeVersionApp app at tmp_path via AppHarness.\n\n    Args:\n        tmp_path: pytest tmp_path fixture\n\n    Yields:\n        running AppHarness instance\n    \"\"\"\n    with AppHarness.create(\n        root=tmp_path,\n        app_source=TestNodeVersionApp,\n    ) as harness:\n        yield harness\n\n\ndef test_node_version(node_version_app: AppHarness, page: Page):\n    \"\"\"Test for latest node version being able to run reflex.\n\n    Args:\n        node_version_app: running AppHarness instance\n        page: playwright page instance\n    \"\"\"\n\n    def get_latest_node_version():\n        response = httpx.get(\"https://nodejs.org/dist/index.json\")\n        versions = response.json()\n\n        # Assuming the first entry in the API response is the most recent version\n        if versions:\n            return versions[0][\"version\"]\n        return None\n\n    assert node_version_app.frontend_url is not None\n    page.goto(node_version_app.frontend_url)\n    expect(page.get_by_role(\"heading\")).to_have_text(\n        f\"Node Version check {get_latest_node_version()}\"\n    )\n"
  },
  {
    "path": "tests/units/__init__.py",
    "content": "\"\"\"Root directory for tests.\"\"\"\n\nimport os\n\nfrom reflex import constants\n"
  },
  {
    "path": "tests/units/assets/custom_script.js",
    "content": "const test = \"inside custom_script.js\";\n"
  },
  {
    "path": "tests/units/assets/test_assets.py",
    "content": "import shutil\nfrom collections.abc import Generator\nfrom pathlib import Path\n\nimport pytest\n\nimport reflex as rx\nimport reflex.constants as constants\nfrom reflex.assets import remove_stale_external_asset_symlinks\n\n\n@pytest.fixture\ndef mock_asset_path(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> Path:\n    \"\"\"Create a mock asset file and patch the current working directory.\n\n    Args:\n        tmp_path: A temporary directory provided by pytest.\n        monkeypatch: A pytest fixture for patching.\n\n    Returns:\n        The path to a tmp cwd that will be used for assets.\n    \"\"\"\n    # Create a temporary directory to act as the current working directory.\n    mock_cwd = tmp_path / \"mock_asset_path\"\n    mock_cwd.mkdir()\n    monkeypatch.chdir(mock_cwd)\n\n    return mock_cwd\n\n\ndef test_shared_asset(mock_asset_path: Path) -> None:\n    \"\"\"Test shared assets.\"\"\"\n    # The asset function copies a file to the app's external assets directory.\n    asset = rx.asset(path=\"custom_script.js\", shared=True, subfolder=\"subfolder\")\n    assert asset == \"/external/test_assets/subfolder/custom_script.js\"\n    result_file = Path(\n        mock_asset_path,\n        \"assets\",\n        \"external\",\n        \"test_assets\",\n        \"subfolder\",\n        \"custom_script.js\",\n    )\n    assert result_file.exists()\n\n    # Running a second time should not raise an error.\n    asset = rx.asset(path=\"custom_script.js\", shared=True, subfolder=\"subfolder\")\n\n    # Test the asset function without a subfolder.\n    asset = rx.asset(path=\"custom_script.js\", shared=True)\n    assert asset == \"/external/test_assets/custom_script.js\"\n    result_file = Path(\n        mock_asset_path, \"assets\", \"external\", \"test_assets\", \"custom_script.js\"\n    )\n    assert result_file.exists()\n\n    # clean up\n    shutil.rmtree(Path(mock_asset_path) / \"assets\" / \"external\")\n\n    with pytest.raises(FileNotFoundError):\n        asset = rx.asset(\"non_existent_file.js\")\n\n    # Nothing is done to assets when file does not exist.\n    assert not Path(mock_asset_path / \"assets\" / \"external\").exists()\n\n\n@pytest.mark.parametrize(\n    (\"path\", \"shared\"),\n    [\n        pytest.param(\"non_existing_file\", True),\n        pytest.param(\"non_existing_file\", False),\n    ],\n)\ndef test_invalid_assets(path: str, shared: bool) -> None:\n    \"\"\"Test that asset raises an error when the file does not exist.\n\n    Args:\n        path: The path to the asset.\n        shared: Whether the asset should be shared.\n    \"\"\"\n    with pytest.raises(FileNotFoundError):\n        _ = rx.asset(path, shared=shared)\n\n\n@pytest.fixture\ndef custom_script_in_asset_dir(mock_asset_path: Path) -> Generator[Path, None, None]:\n    \"\"\"Create a custom_script.js file in the app's assets directory.\n\n    Yields:\n        The path to the custom_script.js file.\n    \"\"\"\n    asset_dir = mock_asset_path / constants.Dirs.APP_ASSETS\n    asset_dir.mkdir(exist_ok=True)\n    path = asset_dir / \"custom_script.js\"\n    path.touch()\n    yield path\n    path.unlink()\n\n\ndef test_local_asset(custom_script_in_asset_dir: Path) -> None:\n    \"\"\"Test that no error is raised if shared is set and both files exist.\n\n    Args:\n        custom_script_in_asset_dir: Fixture that creates a custom_script.js file in the app's assets directory.\n\n    \"\"\"\n    asset = rx.asset(\"custom_script.js\", shared=False)\n    assert asset == \"/custom_script.js\"\n\n\ndef test_remove_stale_external_asset_symlinks(mock_asset_path: Path) -> None:\n    \"\"\"Test that stale symlinks and empty dirs in assets/external/ are cleaned up.\"\"\"\n    external_dir = (\n        mock_asset_path / constants.Dirs.APP_ASSETS / constants.Dirs.EXTERNAL_APP_ASSETS\n    )\n\n    # Set up: create a subdirectory with a broken symlink.\n    stale_dir = external_dir / \"old_module\" / \"subpkg\"\n    stale_dir.mkdir(parents=True, exist_ok=True)\n    stale_symlink = stale_dir / \"missing_file.js\"\n    stale_symlink.symlink_to(\"/nonexistent/path/missing_file.js\")\n    assert stale_symlink.is_symlink()\n    assert not stale_symlink.resolve().exists()\n\n    # Also create a valid symlink that should be preserved.\n    valid_dir = external_dir / \"valid_module\"\n    valid_dir.mkdir(parents=True, exist_ok=True)\n    valid_target = Path(__file__).parent / \"custom_script.js\"\n    valid_symlink = valid_dir / \"custom_script.js\"\n    valid_symlink.symlink_to(valid_target)\n    assert valid_symlink.is_symlink()\n    assert valid_symlink.resolve().exists()\n\n    remove_stale_external_asset_symlinks()\n\n    # Broken symlink and its empty parent dirs should be removed.\n    assert not stale_symlink.exists()\n    assert not stale_symlink.is_symlink()\n    assert not stale_dir.exists()\n    assert not (external_dir / \"old_module\").exists()\n\n    # Valid symlink should be preserved.\n    assert valid_symlink.is_symlink()\n    assert valid_symlink.resolve().exists()\n\n\ndef test_remove_stale_symlinks_no_external_dir(mock_asset_path: Path) -> None:\n    \"\"\"Test that cleanup is a no-op when assets/external/ doesn't exist.\"\"\"\n    external_dir = (\n        mock_asset_path / constants.Dirs.APP_ASSETS / constants.Dirs.EXTERNAL_APP_ASSETS\n    )\n    assert not external_dir.exists()\n    # Should not raise.\n    remove_stale_external_asset_symlinks()\n"
  },
  {
    "path": "tests/units/compiler/__init__.py",
    "content": "\"\"\"Compiler tests.\"\"\"\n"
  },
  {
    "path": "tests/units/compiler/test_compiler.py",
    "content": "import importlib.util\nimport os\nfrom pathlib import Path\n\nimport pytest\nfrom pytest_mock import MockerFixture\n\nfrom reflex import constants\nfrom reflex.compiler import compiler, utils\nfrom reflex.components.base import document\nfrom reflex.components.el.elements.metadata import Link\nfrom reflex.constants.compiler import PageNames\nfrom reflex.utils.imports import ImportVar, ParsedImportDict\nfrom reflex.vars.base import Var\nfrom reflex.vars.sequence import LiteralStringVar\n\n\n@pytest.mark.parametrize(\n    (\"fields\", \"test_default\", \"test_rest\"),\n    [\n        (\n            [ImportVar(tag=\"axios\", is_default=True)],\n            \"axios\",\n            [],\n        ),\n        (\n            [ImportVar(tag=\"foo\"), ImportVar(tag=\"bar\")],\n            \"\",\n            [\"bar\", \"foo\"],\n        ),\n        (\n            [\n                ImportVar(tag=\"axios\", is_default=True),\n                ImportVar(tag=\"foo\"),\n                ImportVar(tag=\"bar\"),\n            ],\n            \"axios\",\n            [\"bar\", \"foo\"],\n        ),\n    ],\n)\ndef test_compile_import_statement(\n    fields: list[ImportVar], test_default: str, test_rest: str\n):\n    \"\"\"Test the compile_import_statement function.\n\n    Args:\n        fields: The fields to import.\n        test_default: The expected output of default library.\n        test_rest: The expected output rest libraries.\n    \"\"\"\n    default, rest = utils.compile_import_statement(fields)\n    assert default == test_default\n    assert sorted(rest) == test_rest\n\n\n@pytest.mark.parametrize(\n    (\"import_dict\", \"test_dicts\"),\n    [\n        ({}, []),\n        (\n            {\"axios\": [ImportVar(tag=\"axios\", is_default=True)]},\n            [{\"lib\": \"axios\", \"default\": \"axios\", \"rest\": []}],\n        ),\n        (\n            {\"axios\": [ImportVar(tag=\"foo\"), ImportVar(tag=\"bar\")]},\n            [{\"lib\": \"axios\", \"default\": \"\", \"rest\": [\"bar\", \"foo\"]}],\n        ),\n        (\n            {\n                \"axios\": [\n                    ImportVar(tag=\"axios\", is_default=True),\n                    ImportVar(tag=\"foo\"),\n                    ImportVar(tag=\"bar\"),\n                ],\n                \"react\": [ImportVar(tag=\"react\", is_default=True)],\n            },\n            [\n                {\"lib\": \"axios\", \"default\": \"axios\", \"rest\": [\"bar\", \"foo\"]},\n                {\"lib\": \"react\", \"default\": \"react\", \"rest\": []},\n            ],\n        ),\n        (\n            {\"\": [ImportVar(tag=\"lib1.js\"), ImportVar(tag=\"lib2.js\")]},\n            [\n                {\"lib\": \"lib1.js\", \"default\": \"\", \"rest\": []},\n                {\"lib\": \"lib2.js\", \"default\": \"\", \"rest\": []},\n            ],\n        ),\n        (\n            {\n                \"\": [ImportVar(tag=\"lib1.js\"), ImportVar(tag=\"lib2.js\")],\n                \"axios\": [ImportVar(tag=\"axios\", is_default=True)],\n            },\n            [\n                {\"lib\": \"lib1.js\", \"default\": \"\", \"rest\": []},\n                {\"lib\": \"lib2.js\", \"default\": \"\", \"rest\": []},\n                {\"lib\": \"axios\", \"default\": \"axios\", \"rest\": []},\n            ],\n        ),\n    ],\n)\ndef test_compile_imports(import_dict: ParsedImportDict, test_dicts: list[dict]):\n    \"\"\"Test the compile_imports function.\n\n    Args:\n        import_dict: The import dictionary.\n        test_dicts: The expected output.\n    \"\"\"\n    imports = utils.compile_imports(import_dict)\n    for one_import_dict, test_dict in zip(imports, test_dicts, strict=True):\n        assert one_import_dict[\"lib\"] == test_dict[\"lib\"]\n        assert one_import_dict[\"default\"] == test_dict[\"default\"]\n        assert (\n            sorted(\n                one_import_dict[\"rest\"],\n                key=lambda i: i if isinstance(i, str) else (i.tag or \"\"),\n            )\n            == test_dict[\"rest\"]\n        )\n\n\ndef test_compile_stylesheets(tmp_path: Path, mocker: MockerFixture):\n    \"\"\"Test that stylesheets compile correctly.\n\n    Args:\n        tmp_path: The test directory.\n        mocker: Pytest mocker object.\n    \"\"\"\n    project = tmp_path / \"test_project\"\n    project.mkdir()\n\n    assets_dir = project / \"assets\"\n    assets_dir.mkdir()\n\n    (assets_dir / \"style.css\").write_text(\n        \"button.rt-Button {\\n\\tborder-radius:unset !important;\\n}\"\n    )\n    mocker.patch(\"reflex.compiler.compiler.Path.cwd\", return_value=project)\n    mocker.patch(\n        \"reflex.compiler.compiler.get_web_dir\",\n        return_value=project / constants.Dirs.WEB,\n    )\n    mocker.patch(\n        \"reflex.compiler.utils.get_web_dir\", return_value=project / constants.Dirs.WEB\n    )\n\n    stylesheets = [\n        \"https://fonts.googleapis.com/css?family=Sofia&effect=neon|outline|emboss|shadow-multiple\",\n        \"https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css\",\n        \"/style.css\",\n        \"https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap-theme.min.css\",\n    ]\n\n    assert compiler.compile_root_stylesheet(stylesheets) == (\n        str(\n            project\n            / constants.Dirs.WEB\n            / \"styles\"\n            / (PageNames.STYLESHEET_ROOT + \".css\")\n        ),\n        (\n            \"@layer __reflex_base;\\n\"\n            \"@import url('./__reflex_style_reset.css');\\n\"\n            \"@import url('@radix-ui/themes/styles.css');\\n\"\n            \"@import url('https://fonts.googleapis.com/css?family=Sofia&effect=neon|outline|emboss|shadow-multiple');\\n\"\n            \"@import url('https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css');\\n\"\n            \"@import url('https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap-theme.min.css');\\n\"\n            \"@import url('./style.css');\"\n        ),\n    )\n\n    assert (project / constants.Dirs.WEB / \"styles\" / \"style.css\").read_text() == (\n        assets_dir / \"style.css\"\n    ).read_text()\n\n\ndef test_compile_stylesheets_scss_sass(tmp_path: Path, mocker: MockerFixture):\n    if importlib.util.find_spec(\"sass\") is None:\n        pytest.skip(\n            'The `libsass` package is required to compile sass/scss stylesheet files. Run `pip install \"libsass>=0.23.0\"`.'\n        )\n    if os.name == \"nt\":\n        pytest.skip(\"Skipping test on Windows\")\n\n    project = tmp_path / \"test_project\"\n    project.mkdir()\n\n    assets_dir = project / \"assets\"\n    assets_dir.mkdir()\n\n    assets_preprocess_dir = assets_dir / \"preprocess\"\n    assets_preprocess_dir.mkdir()\n\n    (assets_dir / \"style.css\").write_text(\n        \"button.rt-Button {\\n\\tborder-radius:unset !important;\\n}\"\n    )\n    (assets_preprocess_dir / \"styles_a.sass\").write_text(\n        \"button.rt-Button\\n\\tborder-radius:unset !important\"\n    )\n    (assets_preprocess_dir / \"styles_b.scss\").write_text(\n        \"button.rt-Button {\\n\\tborder-radius:unset !important;\\n}\"\n    )\n    mocker.patch(\"reflex.compiler.compiler.Path.cwd\", return_value=project)\n    mocker.patch(\n        \"reflex.compiler.compiler.get_web_dir\",\n        return_value=project / constants.Dirs.WEB,\n    )\n    mocker.patch(\n        \"reflex.compiler.utils.get_web_dir\", return_value=project / constants.Dirs.WEB\n    )\n\n    stylesheets = [\n        \"/style.css\",\n        \"/preprocess/styles_a.sass\",\n        \"/preprocess/styles_b.scss\",\n    ]\n\n    assert compiler.compile_root_stylesheet(stylesheets) == (\n        str(\n            project\n            / constants.Dirs.WEB\n            / \"styles\"\n            / (PageNames.STYLESHEET_ROOT + \".css\")\n        ),\n        (\n            \"@layer __reflex_base;\\n\"\n            \"@import url('./__reflex_style_reset.css');\\n\"\n            \"@import url('@radix-ui/themes/styles.css');\\n\"\n            \"@import url('./style.css');\\n\"\n            f\"@import url('./{Path('preprocess') / Path('styles_a.css')!s}');\\n\"\n            f\"@import url('./{Path('preprocess') / Path('styles_b.css')!s}');\"\n        ),\n    )\n\n    stylesheets = [\n        \"/style.css\",\n        \"/preprocess\",  # this is a folder containing \"styles_a.sass\" and \"styles_b.scss\"\n    ]\n\n    assert compiler.compile_root_stylesheet(stylesheets) == (\n        str(\n            project\n            / constants.Dirs.WEB\n            / \"styles\"\n            / (PageNames.STYLESHEET_ROOT + \".css\")\n        ),\n        (\n            \"@layer __reflex_base;\\n\"\n            \"@import url('./__reflex_style_reset.css');\\n\"\n            \"@import url('@radix-ui/themes/styles.css');\\n\"\n            \"@import url('./style.css');\\n\"\n            f\"@import url('./{Path('preprocess') / Path('styles_a.css')!s}');\\n\"\n            f\"@import url('./{Path('preprocess') / Path('styles_b.css')!s}');\"\n        ),\n    )\n\n    assert (project / constants.Dirs.WEB / \"styles\" / \"style.css\").read_text() == (\n        assets_dir / \"style.css\"\n    ).read_text()\n\n    expected_result = \"button.rt-Button{border-radius:unset !important}\\n\"\n    assert (\n        project / constants.Dirs.WEB / \"styles\" / \"preprocess\" / \"styles_a.css\"\n    ).read_text() == expected_result\n    assert (\n        project / constants.Dirs.WEB / \"styles\" / \"preprocess\" / \"styles_b.css\"\n    ).read_text() == expected_result\n\n\ndef test_compile_stylesheets_exclude_tailwind(tmp_path, mocker: MockerFixture):\n    \"\"\"Test that Tailwind is excluded if tailwind config is explicitly set to None.\n\n    Args:\n        tmp_path: The test directory.\n        mocker: Pytest mocker object.\n    \"\"\"\n    project = tmp_path / \"test_project\"\n    project.mkdir()\n\n    assets_dir = project / \"assets\"\n    assets_dir.mkdir()\n    mock = mocker.Mock()\n\n    mocker.patch.object(mock, \"tailwind\", None)\n    mocker.patch.object(mock, \"plugins\", [])\n    mocker.patch(\"reflex.compiler.compiler.get_config\", return_value=mock)\n\n    (assets_dir / \"style.css\").touch()\n    mocker.patch(\"reflex.compiler.compiler.Path.cwd\", return_value=project)\n\n    stylesheets = [\n        \"/style.css\",\n    ]\n\n    assert compiler.compile_root_stylesheet(stylesheets) == (\n        str(Path(\".web\") / \"styles\" / (PageNames.STYLESHEET_ROOT + \".css\")),\n        \"@layer __reflex_base;\\n@import url('./__reflex_style_reset.css');\\n@import url('@radix-ui/themes/styles.css');\\n@import url('./style.css');\",\n    )\n\n\ndef test_compile_stylesheets_no_reset(tmp_path: Path, mocker: MockerFixture):\n    \"\"\"Test that stylesheets compile correctly without reset styles.\n\n    Args:\n        tmp_path: The test directory.\n        mocker: Pytest mocker object.\n    \"\"\"\n    project = tmp_path / \"test_project\"\n    project.mkdir()\n\n    assets_dir = project / \"assets\"\n    assets_dir.mkdir()\n\n    (assets_dir / \"style.css\").write_text(\n        \"button.rt-Button {\\n\\tborder-radius:unset !important;\\n}\"\n    )\n    mocker.patch(\"reflex.compiler.compiler.Path.cwd\", return_value=project)\n    mocker.patch(\n        \"reflex.compiler.compiler.get_web_dir\",\n        return_value=project / constants.Dirs.WEB,\n    )\n    mocker.patch(\n        \"reflex.compiler.utils.get_web_dir\", return_value=project / constants.Dirs.WEB\n    )\n\n    stylesheets = [\"/style.css\"]\n\n    # Test with reset_style=False\n    assert compiler.compile_root_stylesheet(stylesheets, reset_style=False) == (\n        str(\n            project\n            / constants.Dirs.WEB\n            / \"styles\"\n            / (PageNames.STYLESHEET_ROOT + \".css\")\n        ),\n        \"@layer __reflex_base;\\n@import url('@radix-ui/themes/styles.css');\\n@import url('./style.css');\",\n    )\n\n\ndef test_compile_nonexistent_stylesheet(tmp_path, mocker: MockerFixture):\n    \"\"\"Test that an error is thrown for non-existent stylesheets.\n\n    Args:\n        tmp_path: The test directory.\n        mocker: Pytest mocker object.\n    \"\"\"\n    project = tmp_path / \"test_project\"\n    project.mkdir()\n\n    assets_dir = project / \"assets\"\n    assets_dir.mkdir()\n\n    mocker.patch(\"reflex.compiler.compiler.Path.cwd\", return_value=project)\n\n    stylesheets = [\"/style.css\"]\n\n    with pytest.raises(FileNotFoundError):\n        compiler.compile_root_stylesheet(stylesheets)\n\n\ndef test_create_document_root():\n    \"\"\"Test that the document root is created correctly.\"\"\"\n    # Test with no components.\n    root = utils.create_document_root()\n    root.render()\n    assert isinstance(root, utils.Html)\n    assert isinstance(root.children[0], utils.Head)\n    # Default language.\n    lang = root.lang  # pyright: ignore [reportAttributeAccessIssue]\n    assert isinstance(lang, LiteralStringVar)\n    assert lang.equals(Var.create(\"en\"))\n    # No children in head.\n    assert len(root.children[0].children) == 6\n    assert isinstance(root.children[0].children[1], utils.Meta)\n    char_set = root.children[0].children[1].char_set  # pyright: ignore [reportAttributeAccessIssue]\n    assert isinstance(char_set, LiteralStringVar)\n    assert char_set.equals(Var.create(\"utf-8\"))\n    assert isinstance(root.children[0].children[2], utils.Meta)\n    name = root.children[0].children[2].name  # pyright: ignore [reportAttributeAccessIssue]\n    assert isinstance(name, LiteralStringVar)\n    assert name.equals(Var.create(\"viewport\"))\n    assert isinstance(root.children[0].children[3], document.Meta)\n    assert isinstance(root.children[0].children[4], Link)\n    assert isinstance(root.children[0].children[5], document.Links)\n\n\ndef test_create_document_root_with_scripts():\n    # Test with components.\n    comps = [\n        utils.Scripts.create(src=\"foo.js\"),\n        utils.Scripts.create(src=\"bar.js\"),\n    ]\n    root = utils.create_document_root(\n        head_components=comps,\n        html_lang=\"rx\",\n        html_custom_attrs={\"project\": \"reflex\"},\n    )\n    assert isinstance(root, utils.Html)\n    assert len(root.children[0].children) == 8\n    names = [c.tag for c in root.children[0].children]\n    assert names == [\n        \"script\",\n        \"Scripts\",\n        \"Scripts\",\n        \"meta\",\n        \"meta\",\n        \"Meta\",\n        \"link\",\n        \"Links\",\n    ]\n    lang = root.lang  # pyright: ignore [reportAttributeAccessIssue]\n    assert isinstance(lang, LiteralStringVar)\n    assert lang.equals(Var.create(\"rx\"))\n    assert isinstance(root.custom_attrs, dict)\n    assert root.custom_attrs == {\"project\": \"reflex\"}\n\n\ndef test_create_document_root_with_meta_char_set():\n    # Test with components.\n    comps = [\n        utils.Meta.create(char_set=\"cp1252\"),\n    ]\n    root = utils.create_document_root(\n        head_components=comps,\n    )\n    assert isinstance(root, utils.Html)\n    assert len(root.children[0].children) == 6\n    names = [c.tag for c in root.children[0].children]\n    assert names == [\"script\", \"meta\", \"meta\", \"Meta\", \"link\", \"Links\"]\n    assert str(root.children[0].children[1].char_set) == '\"cp1252\"'  # pyright: ignore [reportAttributeAccessIssue]\n\n\ndef test_create_document_root_with_meta_viewport():\n    # Test with components.\n    comps = [\n        utils.Meta.create(http_equiv=\"refresh\", content=\"5\"),\n        utils.Meta.create(name=\"viewport\", content=\"foo\"),\n    ]\n    root = utils.create_document_root(\n        head_components=comps,\n    )\n    assert isinstance(root, utils.Html)\n    assert len(root.children[0].children) == 7\n    names = [c.tag for c in root.children[0].children]\n    assert names == [\"script\", \"meta\", \"meta\", \"meta\", \"Meta\", \"link\", \"Links\"]\n    assert str(root.children[0].children[1].http_equiv) == '\"refresh\"'  # pyright: ignore [reportAttributeAccessIssue]\n    assert str(root.children[0].children[2].name) == '\"viewport\"'  # pyright: ignore [reportAttributeAccessIssue]\n    assert str(root.children[0].children[2].content) == '\"foo\"'  # pyright: ignore [reportAttributeAccessIssue]\n    assert str(root.children[0].children[3].char_set) == '\"utf-8\"'  # pyright: ignore [reportAttributeAccessIssue]\n"
  },
  {
    "path": "tests/units/compiler/test_compiler_utils.py",
    "content": "def TestState(State):\n    pass\n\n\ndef test_compile_state():\n    # TODO: Implement test for compile_state function.\n    pass\n"
  },
  {
    "path": "tests/units/components/__init__.py",
    "content": "\"\"\"Component tests.\"\"\"\n"
  },
  {
    "path": "tests/units/components/base/test_bare.py",
    "content": "import pytest\n\nfrom reflex.components.base.bare import Bare\nfrom reflex.vars.base import Var\n\nSTATE_VAR = Var(_js_expr=\"default_state.name\")\n\n\n@pytest.mark.parametrize(\n    (\"contents\", \"expected\"),\n    [\n        (\"hello\", '\"hello\"'),\n        (\"{}\", '\"{}\"'),\n        (None, '\"\"'),\n        (STATE_VAR, \"default_state.name\"),\n    ],\n)\ndef test_fstrings(contents, expected):\n    \"\"\"Test that fstrings are rendered correctly.\n\n    Args:\n        contents: The contents of the component.\n        expected: The expected output.\n    \"\"\"\n    comp = Bare.create(contents).render()\n    assert comp[\"contents\"] == expected\n"
  },
  {
    "path": "tests/units/components/base/test_link.py",
    "content": "from reflex.components.base.link import RawLink, ScriptTag\n\n\ndef test_raw_link():\n    raw_link = RawLink.create(\"https://example.com\").render()\n    assert raw_link[\"name\"] == '\"link\"'\n    assert raw_link[\"children\"][0][\"contents\"] == '\"https://example.com\"'\n\n\ndef test_script_tag():\n    script_tag = ScriptTag.create(\"console.log('Hello, world!');\").render()\n    assert script_tag[\"name\"] == '\"script\"'\n    assert script_tag[\"children\"][0][\"contents\"] == \"\\\"console.log('Hello, world!');\\\"\"\n"
  },
  {
    "path": "tests/units/components/base/test_script.py",
    "content": "\"\"\"Test that element script renders correctly.\"\"\"\n\nimport pytest\n\nfrom reflex.components.base.script import Script\n\n\ndef test_script_inline():\n    \"\"\"Test inline scripts are rendered as children.\"\"\"\n    component = Script.create(\"let x = 42\")\n    render_dict = component.render()[\"children\"][0]\n    assert render_dict[\"name\"] == '\"script\"'\n    assert len(render_dict[\"children\"]) == 1\n    assert render_dict[\"children\"][0][\"contents\"] == '\"let x = 42\"'\n\n\ndef test_script_src():\n    \"\"\"Test src prop is rendered without children.\"\"\"\n    component = Script.create(src=\"foo.js\")\n    render_dict = component.render()[\"children\"][0]\n    assert render_dict[\"name\"] == '\"script\"'\n    assert not render_dict[\"children\"]\n    assert 'src:\"foo.js\"' in render_dict[\"props\"]\n\n\ndef test_script_neither():\n    \"\"\"Specifying neither children nor src is a ValueError.\"\"\"\n    with pytest.raises(ValueError):\n        Script.create()\n"
  },
  {
    "path": "tests/units/components/core/__init__.py",
    "content": ""
  },
  {
    "path": "tests/units/components/core/test_banner.py",
    "content": "from reflex.components.core.banner import (\n    ConnectionBanner,\n    ConnectionModal,\n    ConnectionPulser,\n    WebsocketTargetURL,\n)\nfrom reflex.components.radix.themes.base import RadixThemesComponent\nfrom reflex.components.radix.themes.typography.text import Text\n\n\ndef test_websocket_target_url():\n    url = WebsocketTargetURL.create()\n    var_data = url._get_all_var_data()\n    assert var_data is not None\n    assert sorted(key for key, _ in var_data.imports) == sorted((\n        \"$/utils/state\",\n        \"$/env.json\",\n    ))\n\n\ndef test_connection_banner():\n    banner = ConnectionBanner.create()\n    imports = banner._get_all_imports(collapse=True)\n    assert sorted(imports) == sorted((\n        \"react\",\n        \"$/utils/context\",\n        \"$/utils/state\",\n        RadixThemesComponent.create().library or \"\",\n        \"$/env.json\",\n    ))\n\n    msg = \"Connection error\"\n    custom_banner = ConnectionBanner.create(Text.create(msg))\n    assert msg in str(custom_banner.render())\n\n\ndef test_connection_modal():\n    modal = ConnectionModal.create()\n    imports = modal._get_all_imports(collapse=True)\n    assert sorted(imports) == sorted((\n        \"react\",\n        \"$/utils/context\",\n        \"$/utils/state\",\n        RadixThemesComponent.create().library or \"\",\n        \"$/env.json\",\n    ))\n\n    msg = \"Connection error\"\n    custom_modal = ConnectionModal.create(Text.create(msg))\n    assert msg in str(custom_modal.render())\n\n\ndef test_connection_pulser():\n    pulser = ConnectionPulser.create()\n    _custom_code = pulser._get_all_custom_code()\n    _imports = pulser._get_all_imports(collapse=True)\n"
  },
  {
    "path": "tests/units/components/core/test_colors.py",
    "content": "import pytest\n\nimport reflex as rx\nfrom reflex.components.datadisplay.code import CodeBlock\nfrom reflex.constants.colors import Color\nfrom reflex.constants.state import FIELD_MARKER\nfrom reflex.vars.base import LiteralVar\n\n\nclass ColorState(rx.State):\n    \"\"\"Test color state.\"\"\"\n\n    color: rx.Field[str] = rx.field(\"mint\")\n    color_part: rx.Field[str] = rx.field(\"tom\")\n    shade: rx.Field[int] = rx.field(4)\n    alpha: rx.Field[bool] = rx.field(False)\n\n\ncolor_state_name = ColorState.get_full_name().replace(\".\", \"__\")\n\n\ndef create_color_var(color):\n    return LiteralVar.create(color)\n\n\ncolor_with_fstring = rx.color(\n    f\"{ColorState.color}\",  # pyright: ignore [reportArgumentType]\n    ColorState.shade,\n)\n\n\n@pytest.mark.parametrize(\n    (\"color\", \"expected\", \"expected_type\"),\n    [\n        (create_color_var(rx.color(\"mint\")), '\"var(--mint-7)\"', Color),\n        (create_color_var(rx.color(\"mint\", 3)), '\"var(--mint-3)\"', Color),\n        (create_color_var(rx.color(\"mint\", 3, True)), '\"var(--mint-a3)\"', Color),\n        (\n            create_color_var(rx.color(ColorState.color, ColorState.shade)),\n            f'(\"var(--\"+{color_state_name!s}.color{FIELD_MARKER}+\"-\"+(((__to_string) => __to_string.toString())({color_state_name!s}.shade{FIELD_MARKER}))+\")\")',\n            Color,\n        ),\n        (\n            create_color_var(\n                rx.color(ColorState.color, ColorState.shade, ColorState.alpha)\n            ),\n            f'(\"var(--\"+{color_state_name!s}.color{FIELD_MARKER}+\"-\"+({color_state_name!s}.alpha{FIELD_MARKER} ? \"a\" : \"\")+(((__to_string) => __to_string.toString())({color_state_name!s}.shade{FIELD_MARKER}))+\")\")',\n            Color,\n        ),\n        (\n            create_color_var(color_with_fstring),\n            f'(\"var(--\"+{color_state_name!s}.color{FIELD_MARKER}+\"-\"+(((__to_string) => __to_string.toString())({color_state_name!s}.shade{FIELD_MARKER}))+\")\")',\n            Color,\n        ),\n        (\n            create_color_var(\n                rx.color(\n                    f\"{ColorState.color_part}ato\",  # pyright: ignore [reportArgumentType]\n                    ColorState.shade,\n                )\n            ),\n            f'(\"var(--\"+({color_state_name!s}.color_part{FIELD_MARKER}+\"ato\")+\"-\"+(((__to_string) => __to_string.toString())({color_state_name!s}.shade{FIELD_MARKER}))+\")\")',\n            Color,\n        ),\n        (\n            create_color_var(f\"{rx.color(ColorState.color, ColorState.shade)}\"),\n            f'(\"var(--\"+{color_state_name!s}.color{FIELD_MARKER}+\"-\"+{color_state_name!s}.shade{FIELD_MARKER}+\")\")',\n            str,\n        ),\n        (\n            create_color_var(f\"{color_with_fstring}\"),\n            f'(\"var(--\"+{color_state_name!s}.color{FIELD_MARKER}+\"-\"+{color_state_name!s}.shade{FIELD_MARKER}+\")\")',\n            str,\n        ),\n    ],\n)\ndef test_color(color, expected, expected_type: type[str] | type[Color]):\n    assert color._var_type is expected_type\n    assert str(color) == expected\n\n\n@pytest.mark.parametrize(\n    (\"cond_var\", \"expected\"),\n    [\n        (\n            rx.cond(True, rx.color(\"mint\"), rx.color(\"tomato\", 5)),\n            '(true ? \"var(--mint-7)\" : \"var(--tomato-5)\")',\n        ),\n        (\n            rx.cond(True, rx.color(ColorState.color), rx.color(ColorState.color, 5)),\n            f'(true ? (\"var(--\"+{color_state_name!s}.color{FIELD_MARKER}+\"-7)\") : (\"var(--\"+{color_state_name!s}.color{FIELD_MARKER}+\"-5)\"))',\n        ),\n        (\n            rx.match(\n                \"condition\",\n                (\"first\", rx.color(\"mint\")),\n                (\"second\", rx.color(\"tomato\", 5)),\n                rx.color(ColorState.color, 2),\n            ),\n            (\n                '(() => { switch (JSON.stringify(\"condition\")) {case JSON.stringify(\"first\"):  return (\"var(--mint-7)\");'\n                '  break;case JSON.stringify(\"second\"):  return (\"var(--tomato-5)\");  break;default:  '\n                f'return ((\"var(--\"+{color_state_name!s}.color{FIELD_MARKER}+\"-2)\"));  break;}};}})()'\n            ),\n        ),\n        (\n            rx.match(\n                \"condition\",\n                (\"first\", rx.color(ColorState.color)),\n                (\"second\", rx.color(ColorState.color, 5)),\n                rx.color(ColorState.color, 2),\n            ),\n            (\n                '(() => { switch (JSON.stringify(\"condition\")) {case JSON.stringify(\"first\"):  '\n                f'return ((\"var(--\"+{color_state_name!s}.color{FIELD_MARKER}+\"-7)\"));  break;case JSON.stringify(\"second\"):  '\n                f'return ((\"var(--\"+{color_state_name!s}.color{FIELD_MARKER}+\"-5)\"));  break;default:  '\n                f'return ((\"var(--\"+{color_state_name!s}.color{FIELD_MARKER}+\"-2)\"));  break;}};}})()'\n            ),\n        ),\n    ],\n)\ndef test_color_with_conditionals(cond_var, expected):\n    assert str(cond_var) == expected\n\n\n@pytest.mark.parametrize(\n    (\"color\", \"expected\"),\n    [\n        (create_color_var(rx.color(\"red\")), '\"var(--red-7)\"'),\n        (create_color_var(rx.color(\"green\", shade=1)), '\"var(--green-1)\"'),\n        (create_color_var(rx.color(\"blue\", alpha=True)), '\"var(--blue-a7)\"'),\n        (\"red\", '\"red\"'),\n        (\"green\", '\"green\"'),\n        (\"blue\", '\"blue\"'),\n    ],\n)\ndef test_radix_color(color, expected):\n    \"\"\"Test that custom_style can accept both string\n    literals and rx.color inputs.\n\n    Args:\n        color (Color): A Color made with rx.color\n        expected (str): The expected custom_style string, radix or literal\n    \"\"\"\n    code_block = CodeBlock.create(\"Hello World\", background_color=color)\n    assert str(code_block.custom_style[\"backgroundColor\"]) == expected  # pyright: ignore [reportAttributeAccessIssue]\n"
  },
  {
    "path": "tests/units/components/core/test_cond.py",
    "content": "import json\nfrom typing import Any\n\nimport pytest\n\nfrom reflex.components.base.fragment import Fragment\nfrom reflex.components.core.cond import Cond, cond\nfrom reflex.components.radix.themes.typography.text import Text\nfrom reflex.constants.state import FIELD_MARKER\nfrom reflex.state import BaseState\nfrom reflex.utils.format import format_state_name\nfrom reflex.vars.base import LiteralVar, Var, computed_var\n\n\n@pytest.fixture\ndef cond_state(request):\n    class CondState(BaseState):\n        value: request.param[\"value_type\"] = request.param[\"value\"]  # pyright: ignore [reportInvalidTypeForm, reportUndefinedVariable] # noqa: F821\n\n    return CondState\n\n\ndef test_f_string_cond_interpolation():\n    # make sure backticks inside interpolation don't get escaped\n    var = LiteralVar.create(f\"x {cond(True, 'a', 'b')}\")\n    assert str(var) == '(\"x \"+(true ? \"a\" : \"b\"))'\n\n\n@pytest.mark.parametrize(\n    \"cond_state\",\n    [\n        pytest.param({\"value_type\": bool, \"value\": True}),\n        pytest.param({\"value_type\": int, \"value\": 0}),\n        pytest.param({\"value_type\": str, \"value\": \"true\"}),\n    ],\n    indirect=True,\n)\ndef test_validate_cond(cond_state: BaseState):\n    \"\"\"Test if cond can be a rx.Var with any values.\n\n    Args:\n        cond_state: A fixture.\n    \"\"\"\n    cond_component = cond(\n        cond_state.value,  # pyright: ignore[reportAttributeAccessIssue]\n        Text.create(\"cond is True\"),\n        Text.create(\"cond is False\"),\n    )\n    cond_dict = cond_component.render() if type(cond_component) is Fragment else {}\n    assert cond_dict[\"name\"] == \"Fragment\"\n\n    [condition] = cond_dict[\"children\"]\n    assert condition[\"cond_state\"] == str(cond_state.value.bool())  # pyright: ignore[reportAttributeAccessIssue]\n\n    # true value\n    true_value = condition[\"true_value\"]\n    assert true_value[\"name\"] == \"Fragment\"\n\n    [true_value_text] = true_value[\"children\"]\n    assert true_value_text[\"name\"] == \"RadixThemesText\"\n    assert true_value_text[\"children\"][0][\"contents\"] == '\"cond is True\"'\n\n    # false value\n    false_value = condition[\"false_value\"]\n    assert false_value[\"name\"] == \"Fragment\"\n\n    [false_value_text] = false_value[\"children\"]\n    assert false_value_text[\"name\"] == \"RadixThemesText\"\n    assert false_value_text[\"children\"][0][\"contents\"] == '\"cond is False\"'\n\n\n@pytest.mark.parametrize(\n    (\"c1\", \"c2\"),\n    [\n        (True, False),\n        (32, 0),\n        (\"hello\", \"\"),\n        (2.3, 0.0),\n        (LiteralVar.create(\"a\"), LiteralVar.create(\"b\")),\n    ],\n)\ndef test_prop_cond(c1: Any, c2: Any):\n    \"\"\"Test if cond can be a prop.\n\n    Args:\n        c1: truth condition value\n        c2: false condition value\n    \"\"\"\n    prop_cond = cond(\n        True,\n        c1,\n        c2,\n    )\n\n    assert isinstance(prop_cond, Var)\n    if not isinstance(c1, Var):\n        c1 = json.dumps(c1)\n    if not isinstance(c2, Var):\n        c2 = json.dumps(c2)\n    assert str(prop_cond) == f\"(true ? {c1!s} : {c2!s})\"\n\n\ndef test_cond_no_mix():\n    \"\"\"Test if cond can mix components and props.\"\"\"\n    cond(True, LiteralVar.create(\"hello\"), Text.create(\"world\"))\n\n\ndef test_cond_no_else():\n    \"\"\"Test if cond can be used without else.\"\"\"\n    # Components should support the use of cond without else\n    comp = cond(True, Text.create(\"hello\"))\n    assert isinstance(comp, Fragment)\n    comp = comp.children[0]\n    assert isinstance(comp, Cond)\n    assert comp.cond._decode() is True\n    assert comp.children[0].render() == Fragment.create(Text.create(\"hello\")).render()  # pyright: ignore [reportOptionalMemberAccess]\n    assert comp.children[1] == Fragment.create()\n\n    # Props do not support the use of cond without else\n    with pytest.raises(ValueError):\n        cond(True, \"hello\")  # pyright: ignore [reportArgumentType]\n\n\ndef test_cond_computed_var():\n    \"\"\"Test if cond works with computed vars.\"\"\"\n\n    class CondStateComputed(BaseState):\n        @computed_var\n        def computed_int(self) -> int:\n            return 0\n\n        @computed_var\n        def computed_str(self) -> str:\n            return \"a string\"\n\n    comp = cond(True, CondStateComputed.computed_int, CondStateComputed.computed_str)\n\n    # TODO: shouldn't this be a ComputedVar?\n    assert isinstance(comp, Var)\n\n    state_name = format_state_name(CondStateComputed.get_full_name())\n    assert (\n        str(comp)\n        == f\"(true ? {state_name}.computed_int{FIELD_MARKER} : {state_name}.computed_str{FIELD_MARKER})\"\n    )\n\n    assert comp._var_type == int | str\n"
  },
  {
    "path": "tests/units/components/core/test_debounce.py",
    "content": "\"\"\"Test that DebounceInput collapses nested forms.\"\"\"\n\nimport pytest\n\nimport reflex as rx\nfrom reflex.components.core.debounce import DEFAULT_DEBOUNCE_TIMEOUT\nfrom reflex.state import BaseState\nfrom reflex.vars.base import LiteralVar, Var\n\n\ndef test_create_no_child():\n    \"\"\"DebounceInput raises RuntimeError if no child is provided.\"\"\"\n    with pytest.raises(RuntimeError):\n        _ = rx.debounce_input()\n\n\ndef test_create_no_child_recursive():\n    \"\"\"DebounceInput raises RuntimeError if no child is provided.\"\"\"\n    with pytest.raises(RuntimeError):\n        _ = rx.debounce_input(rx.debounce_input(rx.debounce_input()))\n\n\ndef test_create_many_child():\n    \"\"\"DebounceInput raises RuntimeError if more than 1 child is provided.\"\"\"\n    with pytest.raises(RuntimeError):\n        _ = rx.debounce_input(\"foo\", \"bar\")\n\n\ndef test_create_no_on_change():\n    \"\"\"DebounceInput raises ValueError if child has no on_change handler.\"\"\"\n    with pytest.raises(ValueError):\n        _ = rx.debounce_input(rx.input())\n\n\nclass S(BaseState):\n    \"\"\"Example state for debounce tests.\"\"\"\n\n    value: str = \"\"\n\n    @rx.event\n    def on_change(self, v: str):\n        \"\"\"Dummy on_change handler.\n\n        Args:\n            v: The changed value.\n        \"\"\"\n\n\ndef test_render_child_props():\n    \"\"\"DebounceInput should render props from child component.\"\"\"\n    tag = rx.debounce_input(\n        rx.input(\n            foo=\"bar\",\n            baz=\"quuc\",\n            value=\"real\",\n            on_change=S.on_change,\n        )\n    )._render()\n    assert \"css\" in tag.props\n    assert isinstance(tag.props[\"css\"], rx.vars.Var)\n    for prop in [\"foo\", \"bar\", \"baz\", \"quuc\"]:\n        assert prop in str(tag.props[\"css\"])\n    assert tag.props[\"value\"].equals(\n        rx.cond(Var.create(\"real\").is_not_none(), \"real\", \"\")\n    )\n    assert len(tag.props[\"onChange\"].events) == 1\n    assert tag.props[\"onChange\"].events[0].handler == S.on_change\n\n\ndef test_render_with_class_name():\n    tag = rx.debounce_input(\n        rx.input(\n            on_change=S.on_change,\n            class_name=\"foo baz\",\n        )\n    )._render()\n    assert isinstance(tag.props[\"className\"], rx.vars.Var)\n    assert \"foo baz\" in str(tag.props[\"className\"])\n\n\ndef test_render_with_ref():\n    tag = rx.debounce_input(\n        rx.input(\n            on_change=S.on_change,\n            id=\"foo_bar\",\n        )\n    )._render()\n    assert isinstance(tag.props[\"inputRef\"], rx.vars.Var)\n    assert \"foo_bar\" in str(tag.props[\"inputRef\"])\n\n\ndef test_render_with_key():\n    tag = rx.debounce_input(\n        rx.input(\n            on_change=S.on_change,\n            key=\"foo_bar\",\n        )\n    )._render()\n    assert isinstance(tag.props[\"key\"], rx.vars.Var)\n    assert \"foo_bar\" in str(tag.props[\"key\"])\n\n\ndef test_render_with_special_props():\n    special_prop = Var(_js_expr=\"{foo_bar}\")\n    tag = rx.debounce_input(\n        rx.input(\n            on_change=S.on_change,\n            special_props=[special_prop],\n        )\n    )._render()\n    assert len(tag.special_props) == 1\n    assert next(iter(tag.special_props)).equals(special_prop)\n\n\ndef test_event_triggers():\n    debounced_input = rx.debounce_input(\n        rx.input(\n            on_change=S.on_change,\n        )\n    )\n    assert tuple(debounced_input.get_event_triggers()) == (\n        *rx.Component.get_event_triggers(),  # default event triggers\n        \"on_change\",\n    )\n\n\ndef test_render_child_props_recursive():\n    \"\"\"DebounceInput should render props from child component.\n\n    If the child component is a DebounceInput, then props will be copied from it\n    recursively.\n    \"\"\"\n    tag = rx.debounce_input(\n        rx.debounce_input(\n            rx.debounce_input(\n                rx.debounce_input(\n                    rx.input(\n                        foo=\"bar\",\n                        baz=\"quuc\",\n                        value=\"real\",\n                        on_change=S.on_change,\n                    ),\n                    value=\"inner\",\n                    debounce_timeout=666,\n                    force_notify_on_blur=False,\n                ),\n                debounce_timeout=42,\n            ),\n            value=\"outer\",\n        ),\n        force_notify_by_enter=False,\n    )._render()\n    assert \"css\" in tag.props\n    assert isinstance(tag.props[\"css\"], rx.vars.Var)\n    for prop in [\"foo\", \"bar\", \"baz\", \"quuc\"]:\n        assert prop in str(tag.props[\"css\"])\n    assert tag.props[\"value\"].equals(LiteralVar.create(\"outer\"))\n    assert tag.props[\"forceNotifyOnBlur\"]._js_expr == \"false\"\n    assert tag.props[\"forceNotifyByEnter\"]._js_expr == \"false\"\n    assert tag.props[\"debounceTimeout\"]._js_expr == \"42\"\n    assert len(tag.props[\"onChange\"].events) == 1\n    assert tag.props[\"onChange\"].events[0].handler == S.on_change\n\n\ndef test_full_control_implicit_debounce():\n    \"\"\"DebounceInput is used when value and on_change are used together.\"\"\"\n    tag = rx.input(\n        value=S.value,\n        on_change=S.on_change,\n    )._render()\n    assert tag.props[\"debounceTimeout\"]._js_expr == str(DEFAULT_DEBOUNCE_TIMEOUT)\n    assert len(tag.props[\"onChange\"].events) == 1\n    assert tag.props[\"onChange\"].events[0].handler == S.on_change\n\n\ndef test_full_control_implicit_debounce_text_area():\n    \"\"\"DebounceInput is used when value and on_change are used together.\"\"\"\n    tag = rx.text_area(\n        value=S.value,\n        on_change=S.on_change,\n    )._render()\n    assert tag.props[\"debounceTimeout\"]._js_expr == str(DEFAULT_DEBOUNCE_TIMEOUT)\n    assert len(tag.props[\"onChange\"].events) == 1\n    assert tag.props[\"onChange\"].events[0].handler == S.on_change\n"
  },
  {
    "path": "tests/units/components/core/test_foreach.py",
    "content": "import pytest\n\nimport reflex as rx\nfrom reflex import el\nfrom reflex.base import Base\nfrom reflex.components.component import Component\nfrom reflex.components.core.foreach import (\n    Foreach,\n    ForeachRenderError,\n    ForeachVarError,\n    foreach,\n)\nfrom reflex.components.radix.themes.layout.box import box\nfrom reflex.components.radix.themes.typography.text import text\nfrom reflex.constants.state import FIELD_MARKER\nfrom reflex.state import BaseState, ComponentState\nfrom reflex.vars.number import NumberVar\nfrom reflex.vars.sequence import ArrayVar\n\n\nclass ForEachTag(Base):\n    \"\"\"A tag for testing the ForEach component.\"\"\"\n\n    name: str = \"\"\n\n\nclass ForEachState(BaseState):\n    \"\"\"A state for testing the ForEach component.\"\"\"\n\n    colors_list: list[str] = [\"red\", \"yellow\"]\n    nested_colors_list: list[list[str]] = [[\"red\", \"yellow\"], [\"blue\", \"green\"]]\n    colors_dict_list: list[dict[str, str]] = [\n        {\n            \"name\": \"red\",\n        },\n        {\"name\": \"yellow\"},\n    ]\n    colors_nested_dict_list: list[dict[str, list[str]]] = [{\"shades\": [\"light-red\"]}]\n    primary_color: dict[str, str] = {\"category\": \"primary\", \"name\": \"red\"}\n    color_with_shades: dict[str, list[str]] = {\n        \"red\": [\"orange\", \"yellow\"],\n        \"yellow\": [\"orange\", \"green\"],\n    }\n    nested_colors_with_shades: dict[str, dict[str, list[dict[str, str]]]] = {\n        \"primary\": {\"red\": [{\"shade\": \"dark\"}]}\n    }\n    color_tuple: tuple[str, str] = (\n        \"red\",\n        \"yellow\",\n    )\n    colors_set: set[str] = {\"red\", \"green\"}\n    bad_annotation_list: list = [[\"red\", \"orange\"], [\"yellow\", \"blue\"]]\n    color_index_tuple: tuple[int, str] = (0, \"red\")\n\n    default_factory_list: rx.Field[list[ForEachTag]] = rx.field(default_factory=list)\n\n    optional_list: rx.Field[list[str] | None] = rx.field(None)\n    optional_list_value: rx.Field[list[str] | None] = rx.field([\"red\", \"yellow\"])\n    optional_dict: rx.Field[dict[str, str] | None] = rx.field(None)\n    optional_dict_value: rx.Field[dict[str, str] | None] = rx.field({\"name\": \"red\"})\n\n\nclass ComponentStateTest(ComponentState):\n    \"\"\"A test component state.\"\"\"\n\n    foo: bool\n\n    @classmethod\n    def get_component(cls, *children, **props) -> Component:\n        \"\"\"Get the component.\n\n        Args:\n            children: The children components.\n            props: The component props.\n\n        Returns:\n            The component.\n        \"\"\"\n        return el.div(*children, **props)\n\n\ndef display_color(color):\n    assert color._var_type is str\n    return box(text(color))\n\n\ndef display_color_name(color):\n    assert color._var_type == dict[str, str]\n    return box(text(color[\"name\"]))\n\n\ndef display_shade(color):\n    assert color._var_type == dict[str, list[str]]\n    return box(text(color[\"shades\"][0]))\n\n\ndef display_primary_colors(color):\n    assert color._var_type == tuple[str, str]\n    return box(text(color[0]), text(color[1]))\n\n\ndef display_color_with_shades(color):\n    assert color._var_type == tuple[str, list[str]]\n    return box(text(color[0]), text(color[1][0]))\n\n\ndef display_nested_color_with_shades(color):\n    assert color._var_type == tuple[str, dict[str, list[dict[str, str]]]]\n    return box(text(color[0]), text(color[1][\"red\"][0][\"shade\"]))\n\n\ndef show_shade(item):\n    return text(item[1][0][\"shade\"])\n\n\ndef display_nested_color_with_shades_v2(color):\n    assert color._var_type == tuple[str, dict[str, list[dict[str, str]]]]\n    return box(text(foreach(color[1], show_shade)))\n\n\ndef display_color_tuple(color):\n    assert color._var_type is str\n    return box(text(color))\n\n\ndef display_colors_set(color):\n    assert color._var_type is str\n    return box(text(color))\n\n\ndef display_nested_list_element(element: ArrayVar[list[str]], index: NumberVar[int]):\n    assert element._var_type == list[str]\n    assert index._var_type is int\n    return box(text(element[index]))\n\n\ndef display_color_index_tuple(color):\n    assert color._var_type == int | str\n    return box(text(color))\n\n\n@pytest.mark.parametrize(\n    (\"state_var\", \"render_fn\", \"render_dict\"),\n    [\n        (\n            ForEachState.colors_list,\n            display_color,\n            {\n                \"iterable_state\": f\"{ForEachState.get_full_name()}.colors_list\"\n                + FIELD_MARKER,\n            },\n        ),\n        (\n            ForEachState.colors_dict_list,\n            display_color_name,\n            {\n                \"iterable_state\": f\"{ForEachState.get_full_name()}.colors_dict_list\"\n                + FIELD_MARKER,\n            },\n        ),\n        (\n            ForEachState.colors_nested_dict_list,\n            display_shade,\n            {\n                \"iterable_state\": f\"{ForEachState.get_full_name()}.colors_nested_dict_list\"\n                + FIELD_MARKER,\n            },\n        ),\n        (\n            ForEachState.primary_color,\n            display_primary_colors,\n            {\n                \"iterable_state\": f\"Object.entries({ForEachState.get_full_name()}.primary_color{FIELD_MARKER} ?? {{}})\",\n            },\n        ),\n        (\n            ForEachState.color_with_shades,\n            display_color_with_shades,\n            {\n                \"iterable_state\": f\"Object.entries({ForEachState.get_full_name()}.color_with_shades{FIELD_MARKER} ?? {{}})\",\n            },\n        ),\n        (\n            ForEachState.nested_colors_with_shades,\n            display_nested_color_with_shades,\n            {\n                \"iterable_state\": f\"Object.entries({ForEachState.get_full_name()}.nested_colors_with_shades{FIELD_MARKER} ?? {{}})\",\n            },\n        ),\n        (\n            ForEachState.nested_colors_with_shades,\n            display_nested_color_with_shades_v2,\n            {\n                \"iterable_state\": f\"Object.entries({ForEachState.get_full_name()}.nested_colors_with_shades{FIELD_MARKER} ?? {{}})\",\n            },\n        ),\n        (\n            ForEachState.color_tuple,\n            display_color_tuple,\n            {\n                \"iterable_state\": f\"{ForEachState.get_full_name()}.color_tuple\"\n                + FIELD_MARKER,\n            },\n        ),\n        (\n            ForEachState.colors_set,\n            display_colors_set,\n            {\n                \"iterable_state\": f\"{ForEachState.get_full_name()}.colors_set\"\n                + FIELD_MARKER,\n            },\n        ),\n        (\n            ForEachState.nested_colors_list,\n            lambda el, i: display_nested_list_element(el, i),\n            {\n                \"iterable_state\": f\"{ForEachState.get_full_name()}.nested_colors_list\"\n                + FIELD_MARKER,\n            },\n        ),\n        (\n            ForEachState.color_index_tuple,\n            display_color_index_tuple,\n            {\n                \"iterable_state\": f\"{ForEachState.get_full_name()}.color_index_tuple\"\n                + FIELD_MARKER,\n            },\n        ),\n    ],\n)\ndef test_foreach_render(state_var, render_fn, render_dict):\n    \"\"\"Test that the foreach component renders without error.\n\n    Args:\n        state_var: the state var.\n        render_fn: The render callable\n        render_dict: return dict on calling `component.render`\n    \"\"\"\n    component = Foreach.create(state_var, render_fn)\n\n    rend = component.render()\n    assert rend[\"iterable_state\"] == render_dict[\"iterable_state\"]\n\n    # Make sure the index vars are unique.\n    arg_index = rend[\"arg_index\"]\n    assert isinstance(arg_index, str)\n\n\ndef test_foreach_bad_annotations():\n    \"\"\"Test that the foreach component raises a ForeachVarError if the iterable is of type Any.\"\"\"\n    with pytest.raises(ForeachVarError):\n        Foreach.create(\n            ForEachState.bad_annotation_list,\n            lambda sublist: Foreach.create(sublist, lambda color: text(color)),\n        )\n\n\ndef test_foreach_no_param_in_signature():\n    \"\"\"Test that the foreach component raises a ForeachRenderError if no parameters are passed.\"\"\"\n    with pytest.raises(ForeachRenderError):\n        Foreach.create(\n            ForEachState.colors_list,\n            lambda: text(\"color\"),\n        )\n\n\ndef test_foreach_too_many_params_in_signature():\n    \"\"\"Test that the foreach component raises a ForeachRenderError if too many parameters are passed.\"\"\"\n    with pytest.raises(ForeachRenderError):\n        Foreach.create(\n            ForEachState.colors_list,\n            lambda color, index, extra: text(color),\n        )\n\n\ndef test_foreach_component_styles():\n    \"\"\"Test that the foreach component works with global component styles.\"\"\"\n    component = el.div(\n        foreach(\n            ForEachState.colors_list,\n            display_color,\n        )\n    )\n    component._add_style_recursive({box: {\"color\": \"red\"}})\n    assert 'css:({ [\"color\"] : \"red\" })' in str(component)\n\n\ndef test_foreach_component_state():\n    \"\"\"Test that using a component state to render in the foreach raises an error.\"\"\"\n    with pytest.raises(TypeError):\n        Foreach.create(\n            ForEachState.colors_list,\n            ComponentStateTest.create,\n        )\n\n\ndef test_foreach_default_factory():\n    \"\"\"Test that the default factory is called.\"\"\"\n    _ = Foreach.create(\n        ForEachState.default_factory_list,\n        lambda tag: text(tag.name),\n    )\n\n\ndef test_optional_list():\n    \"\"\"Test that the foreach component works with optional lists.\"\"\"\n    Foreach.create(\n        ForEachState.optional_list,\n        lambda color: text(color),\n    )\n\n    Foreach.create(\n        ForEachState.optional_list_value,\n        lambda color: text(color),\n    )\n\n    Foreach.create(\n        ForEachState.optional_dict,\n        lambda color: text(color[0], color[1]),\n    )\n\n    Foreach.create(\n        ForEachState.optional_dict_value,\n        lambda color: text(color[0], color[1]),\n    )\n"
  },
  {
    "path": "tests/units/components/core/test_html.py",
    "content": "import pytest\n\nfrom reflex.components.core.html import Html\nfrom reflex.state import State\n\n\ndef test_html_no_children():\n    with pytest.raises(ValueError):\n        _ = Html.create()\n\n\ndef test_html_many_children():\n    with pytest.raises(ValueError):\n        _ = Html.create(\"foo\", \"bar\")\n\n\ndef test_html_create():\n    html = Html.create(\"<p>Hello !</p>\")\n    assert str(html.dangerouslySetInnerHTML) == '({ [\"__html\"] : \"<p>Hello !</p>\" })'  # pyright: ignore [reportAttributeAccessIssue]\n    assert (\n        str(html)\n        == 'jsx(\"div\",{className:\"rx-Html\",dangerouslySetInnerHTML:({ [\"__html\"] : \"<p>Hello !</p>\" })},)'\n    )\n\n\ndef test_html_fstring_create():\n    class TestState(State):\n        \"\"\"The app state.\"\"\"\n\n        myvar: str = \"Blue\"\n\n    html = Html.create(f\"<p>Hello {TestState.myvar}!</p>\")\n\n    html_dangerouslySetInnerHTML = html.dangerouslySetInnerHTML  # pyright: ignore [reportAttributeAccessIssue]\n\n    assert (\n        str(html_dangerouslySetInnerHTML)\n        == f'({{ [\"__html\"] : (\"<p>Hello \"+{TestState.myvar!s}+\"!</p>\") }})'\n    )\n    assert (\n        str(html)\n        == f'jsx(\"div\",{{className:\"rx-Html\",dangerouslySetInnerHTML:{html_dangerouslySetInnerHTML!s}}},)'\n    )\n"
  },
  {
    "path": "tests/units/components/core/test_match.py",
    "content": "import re\n\nimport pytest\n\nimport reflex as rx\nfrom reflex.components.component import Component\nfrom reflex.components.core.match import Match\nfrom reflex.constants.state import FIELD_MARKER\nfrom reflex.state import BaseState\nfrom reflex.utils.exceptions import MatchTypeError\nfrom reflex.vars.base import Var\n\n\nclass MatchState(BaseState):\n    \"\"\"A test state.\"\"\"\n\n    value: int = 0\n    num: int = 5\n    string: str = \"random string\"\n\n\ndef test_match_components():\n    \"\"\"Test matching cases with return values as components.\"\"\"\n    match_case_tuples = (\n        (1, rx.text(\"first value\")),\n        (2, 3, rx.text(\"second value\")),\n        ([1, 2], rx.text(\"third value\")),\n        (\"random\", rx.text(\"fourth value\")),\n        ({\"foo\": \"bar\"}, rx.text(\"fifth value\")),\n        (MatchState.num + 1, rx.text(\"sixth value\")),\n        rx.text(\"default value\"),\n    )\n    match_comp = rx.match(MatchState.value, *match_case_tuples)\n\n    assert isinstance(match_comp, Component)\n    match_dict = match_comp.render()\n    assert match_dict[\"name\"] == \"Fragment\"\n\n    [match_child] = match_dict[\"children\"]\n\n    assert str(match_child[\"cond\"]) == f\"{MatchState.get_name()}.value\" + FIELD_MARKER\n\n    match_cases = match_child[\"match_cases\"]\n    assert len(match_cases) == 6\n    assert match_cases[0][0] == [\"1\"]\n    first_return_value_render = match_cases[0][1]\n    assert first_return_value_render[\"name\"] == \"RadixThemesText\"\n    assert first_return_value_render[\"children\"][0][\"contents\"] == '\"first value\"'\n\n    assert match_cases[1][0] == [\"2\", \"3\"]\n    second_return_value_render = match_cases[1][1]\n    assert second_return_value_render[\"name\"] == \"RadixThemesText\"\n    assert second_return_value_render[\"children\"][0][\"contents\"] == '\"second value\"'\n\n    assert match_cases[2][0] == [\"[1, 2]\"]\n    third_return_value_render = match_cases[2][1]\n    assert third_return_value_render[\"name\"] == \"RadixThemesText\"\n    assert third_return_value_render[\"children\"][0][\"contents\"] == '\"third value\"'\n\n    assert match_cases[3][0] == ['\"random\"']\n    fourth_return_value_render = match_cases[3][1]\n    assert fourth_return_value_render[\"name\"] == \"RadixThemesText\"\n    assert fourth_return_value_render[\"children\"][0][\"contents\"] == '\"fourth value\"'\n\n    assert match_cases[4][0] == ['({ [\"foo\"] : \"bar\" })']\n    fifth_return_value_render = match_cases[4][1]\n    assert fifth_return_value_render[\"name\"] == \"RadixThemesText\"\n    assert fifth_return_value_render[\"children\"][0][\"contents\"] == '\"fifth value\"'\n\n    assert match_cases[5][0] == [f\"({MatchState.get_name()}.num{FIELD_MARKER} + 1)\"]\n    fifth_return_value_render = match_cases[5][1]\n    assert fifth_return_value_render[\"name\"] == \"RadixThemesText\"\n    assert fifth_return_value_render[\"children\"][0][\"contents\"] == '\"sixth value\"'\n\n    default = match_child[\"default\"]\n\n    assert default[\"name\"] == \"RadixThemesText\"\n    assert default[\"children\"][0][\"contents\"] == '\"default value\"'\n\n\n@pytest.mark.parametrize(\n    (\"cases\", \"expected\"),\n    [\n        (\n            (\n                (1, \"first\"),\n                (2, 3, \"second value\"),\n                ([1, 2], \"third-value\"),\n                (\"random\", \"fourth_value\"),\n                ({\"foo\": \"bar\"}, \"fifth value\"),\n                (MatchState.num + 1, \"sixth value\"),\n                (f\"{MatchState.value} - string\", MatchState.string),\n                (MatchState.string, f\"{MatchState.value} - string\"),\n                \"default value\",\n            ),\n            (\n                f'(() => {{ switch (JSON.stringify({MatchState.get_name()}.value{FIELD_MARKER})) {{case JSON.stringify(1):  return (\"first\");  break;case JSON.stringify(2): case JSON.stringify(3):  return '\n                '(\"second value\");  break;case JSON.stringify([1, 2]):  return (\"third-value\");  break;case JSON.stringify(\"random\"):  '\n                'return (\"fourth_value\");  break;case JSON.stringify(({ [\"foo\"] : \"bar\" })):  return (\"fifth value\");  '\n                f'break;case JSON.stringify(({MatchState.get_name()}.num{FIELD_MARKER} + 1)):  return (\"sixth value\");  break;case JSON.stringify(({MatchState.get_name()}.value{FIELD_MARKER}+\" - string\")):  '\n                f'return ({MatchState.get_name()}.string{FIELD_MARKER});  break;case JSON.stringify({MatchState.get_name()}.string{FIELD_MARKER}):  return (({MatchState.get_name()}.value{FIELD_MARKER}+\" - string\"));  break;default:  '\n                'return (\"default value\");  break;};})()'\n            ),\n        ),\n        (\n            (\n                (1, \"first\"),\n                (2, 3, \"second value\"),\n                ([1, 2], \"third-value\"),\n                (\"random\", \"fourth_value\"),\n                ({\"foo\": \"bar\"}, \"fifth value\"),\n                (MatchState.num + 1, \"sixth value\"),\n                (f\"{MatchState.value} - string\", MatchState.string),\n                (MatchState.string, f\"{MatchState.value} - string\"),\n                MatchState.string,\n            ),\n            (\n                f'(() => {{ switch (JSON.stringify({MatchState.get_name()}.value{FIELD_MARKER})) {{case JSON.stringify(1):  return (\"first\");  break;case JSON.stringify(2): case JSON.stringify(3):  return '\n                '(\"second value\");  break;case JSON.stringify([1, 2]):  return (\"third-value\");  break;case JSON.stringify(\"random\"):  '\n                'return (\"fourth_value\");  break;case JSON.stringify(({ [\"foo\"] : \"bar\" })):  return (\"fifth value\");  '\n                f'break;case JSON.stringify(({MatchState.get_name()}.num{FIELD_MARKER} + 1)):  return (\"sixth value\");  break;case JSON.stringify(({MatchState.get_name()}.value{FIELD_MARKER}+\" - string\")):  '\n                f'return ({MatchState.get_name()}.string{FIELD_MARKER});  break;case JSON.stringify({MatchState.get_name()}.string{FIELD_MARKER}):  return (({MatchState.get_name()}.value{FIELD_MARKER}+\" - string\"));  break;default:  '\n                f\"return ({MatchState.get_name()}.string{FIELD_MARKER});  break;}};}})()\"\n            ),\n        ),\n    ],\n)\ndef test_match_vars(cases, expected):\n    \"\"\"Test matching cases with return values as Vars.\n\n    Args:\n        cases: The match cases.\n        expected: The expected var full name.\n    \"\"\"\n    match_comp = Match.create(MatchState.value, *cases)\n    assert isinstance(match_comp, Var)\n    assert str(match_comp) == expected\n\n\ndef test_match_on_component_without_default():\n    \"\"\"Test that matching cases with return values as components returns a Fragment\n    as the default case if not provided.\n    \"\"\"\n    from reflex.components.base.fragment import Fragment\n\n    match_case_tuples = (\n        (1, rx.text(\"first value\")),\n        (2, 3, rx.text(\"second value\")),\n    )\n\n    match_comp = rx.match(MatchState.value, *match_case_tuples)\n    assert isinstance(match_comp, Component)\n    default = match_comp.render()[\"children\"][0][\"default\"]\n\n    assert isinstance(default, dict)\n    assert default[\"name\"] == Fragment.__name__\n\n\ndef test_match_on_var_no_default():\n    \"\"\"Test that an error is thrown when cases with return Values as Var do not have a default case.\"\"\"\n    match_case_tuples = (\n        (1, \"red\"),\n        (2, 3, \"blue\"),\n        ([1, 2], \"green\"),\n    )\n\n    with pytest.raises(\n        ValueError,\n        match=\"For cases with return types as Vars, a default case must be provided\",\n    ):\n        Match.create(MatchState.value, *match_case_tuples)\n\n\n@pytest.mark.parametrize(\n    \"match_case\",\n    [\n        (\n            (1, \"red\"),\n            (2, 3, \"blue\"),\n            \"black\",\n            ([1, 2], \"green\"),\n        ),\n        (\n            (1, rx.text(\"first value\")),\n            (2, 3, rx.text(\"second value\")),\n            ([1, 2], rx.text(\"third value\")),\n            rx.text(\"default value\"),\n            (\"random\", rx.text(\"fourth value\")),\n            ({\"foo\": \"bar\"}, rx.text(\"fifth value\")),\n            (MatchState.num + 1, rx.text(\"sixth value\")),\n        ),\n    ],\n)\ndef test_match_default_not_last_arg(match_case):\n    \"\"\"Test that an error is thrown when the default case is not the last arg.\n\n    Args:\n        match_case: The cases to match.\n    \"\"\"\n    with pytest.raises(\n        ValueError,\n        match=r\"rx\\.match should have tuples of cases and one default case as the last argument\\.\",\n    ):\n        Match.create(MatchState.value, *match_case)\n\n\n@pytest.mark.parametrize(\n    \"match_case\",\n    [\n        (\n            (1, \"red\"),\n            (2, 3, \"blue\"),\n            (\"green\",),\n            \"black\",\n        ),\n        (\n            (1, rx.text(\"first value\")),\n            (2, 3, rx.text(\"second value\")),\n            ([1, 2],),\n            rx.text(\"default value\"),\n        ),\n    ],\n)\ndef test_match_case_tuple_elements(match_case):\n    \"\"\"Test that a match has at least 2 elements(a condition and a return value).\n\n    Args:\n        match_case: The cases to match.\n    \"\"\"\n    with pytest.raises(\n        ValueError,\n        match=r\"A case tuple should have at least a match case element and a return value\\.\",\n    ):\n        Match.create(MatchState.value, *match_case)\n\n\n@pytest.mark.parametrize(\n    (\"cases\", \"error_msg\"),\n    [\n        (\n            (\n                (1, rx.text(\"first value\")),\n                (2, 3, rx.text(\"second value\")),\n                ([1, 2], rx.text(\"third value\")),\n                (\"random\", \"red\"),\n                ({\"foo\": \"bar\"}, \"green\"),\n                (MatchState.num + 1, \"black\"),\n                rx.text(\"default value\"),\n            ),\n            (\n                'Match cases should have the same return types. Case 3 with return value `\"red\"` of type '\n                \"<class 'reflex.vars.sequence.LiteralStringVar'> is not <class 'reflex.components.component.BaseComponent'>\"\n            ),\n        ),\n        (\n            (\n                (\"random\", \"red\"),\n                ({\"foo\": \"bar\"}, \"green\"),\n                (MatchState.num + 1, \"black\"),\n                (1, rx.text(\"first value\")),\n                (2, 3, rx.text(\"second value\")),\n                ([1, 2], rx.text(\"third value\")),\n                rx.text(\"default value\"),\n            ),\n            (\n                'Match cases should have the same return types. Case 3 with return value `jsx(RadixThemesText,{as:\"p\"},\"first value\")` '\n                \"of type <class 'reflex.components.radix.themes.typography.text.Text'> is not <class 'reflex.vars.base.Var'>\"\n            ),\n        ),\n    ],\n)\ndef test_match_different_return_types(cases: tuple, error_msg: str):\n    \"\"\"Test that an error is thrown when the return values are of different types.\n\n    Args:\n        cases: The match cases.\n        error_msg: Expected error message.\n    \"\"\"\n    with pytest.raises(MatchTypeError, match=re.escape(error_msg)):\n        Match.create(MatchState.value, *cases)\n\n\n@pytest.mark.parametrize(\n    \"match_case\",\n    [\n        (\n            (1, \"red\"),\n            (2, 3, \"blue\"),\n            ([1, 2], \"green\"),\n            \"black\",\n            \"white\",\n        ),\n        (\n            (1, rx.text(\"first value\")),\n            (2, 3, rx.text(\"second value\")),\n            ([1, 2], rx.text(\"third value\")),\n            (\"random\", rx.text(\"fourth value\")),\n            ({\"foo\": \"bar\"}, rx.text(\"fifth value\")),\n            (MatchState.num + 1, rx.text(\"sixth value\")),\n            rx.text(\"default value\"),\n            rx.text(\"another default value\"),\n        ),\n    ],\n)\ndef test_match_multiple_default_cases(match_case):\n    \"\"\"Test that there is only one default case.\n\n    Args:\n        match_case: the cases to match.\n    \"\"\"\n    with pytest.raises(\n        ValueError,\n        match=r\"rx\\.match should have tuples of cases and one default case as the last argument\\.\",\n    ):\n        Match.create(MatchState.value, *match_case)\n\n\ndef test_match_no_cond():\n    with pytest.raises(ValueError):\n        _ = Match.create(None)\n"
  },
  {
    "path": "tests/units/components/core/test_responsive.py",
    "content": "from reflex.components.core.responsive import (\n    desktop_only,\n    mobile_and_tablet,\n    mobile_only,\n    tablet_and_desktop,\n    tablet_only,\n)\nfrom reflex.components.radix.themes.layout.box import Box\n\n\ndef test_mobile_only():\n    \"\"\"Test the mobile_only responsive component.\"\"\"\n    component = mobile_only(\"Content\")\n    assert isinstance(component, Box)\n\n\ndef test_tablet_only():\n    \"\"\"Test the tablet_only responsive component.\"\"\"\n    component = tablet_only(\"Content\")\n    assert isinstance(component, Box)\n\n\ndef test_desktop_only():\n    \"\"\"Test the desktop_only responsive component.\"\"\"\n    component = desktop_only(\"Content\")\n    assert isinstance(component, Box)\n\n\ndef test_tablet_and_desktop():\n    \"\"\"Test the tablet_and_desktop responsive component.\"\"\"\n    component = tablet_and_desktop(\"Content\")\n    assert isinstance(component, Box)\n\n\ndef test_mobile_and_tablet():\n    \"\"\"Test the mobile_and_tablet responsive component.\"\"\"\n    component = mobile_and_tablet(\"Content\")\n    assert isinstance(component, Box)\n"
  },
  {
    "path": "tests/units/components/core/test_upload.py",
    "content": "from typing import Any\n\nfrom reflex import event\nfrom reflex.components.core.upload import (\n    StyledUpload,\n    Upload,\n    UploadNamespace,\n    _on_drop_spec,  # pyright: ignore [reportAttributeAccessIssue]\n    cancel_upload,\n    get_upload_url,\n)\nfrom reflex.event import EventSpec\nfrom reflex.state import State\nfrom reflex.vars.base import LiteralVar, Var\n\n\nclass UploadStateTest(State):\n    \"\"\"Test upload state.\"\"\"\n\n    @event\n    def drop_handler(self, files: Any):\n        \"\"\"Handle the drop event.\n\n        Args:\n            files: The files dropped.\n        \"\"\"\n\n    @event\n    def not_drop_handler(self, not_files: Any):\n        \"\"\"Handle the drop event without defining the files argument.\n\n        Args:\n            not_files: The files dropped.\n        \"\"\"\n\n\ndef test_cancel_upload():\n    spec = cancel_upload(\"foo_id\")\n    assert isinstance(spec, EventSpec)\n\n\ndef test_get_upload_url():\n    url = get_upload_url(\"foo_file\")\n    assert isinstance(url, Var)\n\n\ndef test__on_drop_spec():\n    assert isinstance(_on_drop_spec(LiteralVar.create([])), tuple)\n\n\ndef test_upload_create():\n    up_comp_1 = Upload.create()\n    assert isinstance(up_comp_1, Upload)\n    assert up_comp_1.is_used\n\n    # reset is_used\n    Upload.is_used = False\n\n    up_comp_2 = Upload.create(\n        id=\"foo_id\",\n        on_drop=UploadStateTest.drop_handler([]),\n    )\n    assert isinstance(up_comp_2, Upload)\n    assert up_comp_2.is_used\n\n    # reset is_used\n    Upload.is_used = False\n\n    up_comp_3 = Upload.create(\n        id=\"foo_id\",\n        on_drop=UploadStateTest.drop_handler,\n    )\n    assert isinstance(up_comp_3, Upload)\n    assert up_comp_3.is_used\n\n    # reset is_used\n    Upload.is_used = False\n\n    up_comp_4 = Upload.create(\n        id=\"foo_id\",\n        on_drop=UploadStateTest.not_drop_handler([]),\n    )\n    assert isinstance(up_comp_4, Upload)\n    assert up_comp_4.is_used\n\n\ndef test_styled_upload_create():\n    styled_up_comp_1 = StyledUpload.create()\n    assert isinstance(styled_up_comp_1, StyledUpload)\n    assert styled_up_comp_1.is_used\n\n    # reset is_used\n    StyledUpload.is_used = False\n\n    styled_up_comp_2 = StyledUpload.create(\n        id=\"foo_id\",\n        on_drop=UploadStateTest.drop_handler([]),\n    )\n    assert isinstance(styled_up_comp_2, StyledUpload)\n    assert styled_up_comp_2.is_used\n\n    # reset is_used\n    StyledUpload.is_used = False\n\n    styled_up_comp_3 = StyledUpload.create(\n        id=\"foo_id\",\n        on_drop=UploadStateTest.drop_handler,\n    )\n    assert isinstance(styled_up_comp_3, StyledUpload)\n    assert styled_up_comp_3.is_used\n\n    # reset is_used\n    StyledUpload.is_used = False\n\n    styled_up_comp_4 = StyledUpload.create(\n        id=\"foo_id\",\n        on_drop=UploadStateTest.not_drop_handler([]),\n    )\n    assert isinstance(styled_up_comp_4, StyledUpload)\n    assert styled_up_comp_4.is_used\n\n\ndef test_upload_namespace():\n    up_ns = UploadNamespace()\n    assert isinstance(up_ns, UploadNamespace)\n\n    assert isinstance(up_ns(id=\"foo_id\"), StyledUpload)\n    assert isinstance(up_ns.root(id=\"foo_id\"), Upload)\n"
  },
  {
    "path": "tests/units/components/datadisplay/__init__.py",
    "content": "\"\"\"Datadisplay component tests.\"\"\"\n"
  },
  {
    "path": "tests/units/components/datadisplay/conftest.py",
    "content": "\"\"\"Data display component tests fixtures.\"\"\"\n\nimport pandas as pd\nimport pytest\n\nimport reflex as rx\nfrom reflex.state import BaseState\n\n\n@pytest.fixture\ndef data_table_state(request):\n    \"\"\"Get a data table state.\n\n    Args:\n        request: The request.\n\n    Returns:\n        The data table state class.\n    \"\"\"\n\n    class DataTableState(BaseState):\n        data = request.param[\"data\"]\n        columns = [\"column1\", \"column2\"]\n\n    return DataTableState\n\n\n@pytest.fixture\ndef data_table_state2():\n    \"\"\"Get a data table state.\n\n    Returns:\n        The data table state class.\n    \"\"\"\n\n    class DataTableState(BaseState):\n        _data = pd.DataFrame()\n\n        @rx.var\n        def data(self):\n            return self._data\n\n    return DataTableState\n\n\n@pytest.fixture\ndef data_table_state3():\n    \"\"\"Get a data table state.\n\n    Returns:\n        The data table state class.\n    \"\"\"\n\n    class DataTableState(BaseState):\n        _data: list = []\n        _columns: list = [\"col1\", \"col2\"]\n\n        @rx.var\n        def data(self) -> list:\n            return self._data\n\n        @rx.var\n        def columns(self):\n            return self._columns\n\n    return DataTableState\n\n\n@pytest.fixture\ndef data_table_state4():\n    \"\"\"Get a data table state.\n\n    Returns:\n        The data table state class.\n    \"\"\"\n\n    class DataTableState(BaseState):\n        _data: list = []\n        _columns: list[str] = [\"col1\", \"col2\"]\n\n        @rx.var\n        def data(self):\n            return self._data\n\n        @rx.var\n        def columns(self) -> list:\n            return self._columns\n\n    return DataTableState\n"
  },
  {
    "path": "tests/units/components/datadisplay/test_code.py",
    "content": "import pytest\n\nfrom reflex.components.datadisplay.code import CodeBlock, Theme\n\n\n@pytest.mark.parametrize(\n    (\"theme\", \"expected\"),\n    [(Theme.one_light, \"oneLight\"), (Theme.one_dark, \"oneDark\")],\n)\ndef test_code_light_dark_theme(theme, expected):\n    code_block = CodeBlock.create(theme=theme)\n\n    assert code_block.theme._js_expr == expected  # pyright: ignore [reportAttributeAccessIssue]\n"
  },
  {
    "path": "tests/units/components/datadisplay/test_dataeditor.py",
    "content": "from reflex.components.datadisplay.dataeditor import DataEditor\n\n\ndef test_dataeditor():\n    editor_wrapper = DataEditor.create().render()\n    editor = editor_wrapper[\"children\"][0]\n    assert editor_wrapper[\"name\"] == '\"div\"'\n    assert editor_wrapper[\"props\"] == [\n        'css:({ [\"width\"] : \"100%\", [\"height\"] : \"100%\" })'\n    ]\n    assert editor[\"name\"] == \"DataEditor\"\n"
  },
  {
    "path": "tests/units/components/datadisplay/test_datatable.py",
    "content": "import pandas as pd\nimport pytest\n\nimport reflex as rx\nfrom reflex.components.gridjs.datatable import DataTable\nfrom reflex.constants.state import FIELD_MARKER\nfrom reflex.utils import types\nfrom reflex.utils.exceptions import UntypedComputedVarError\nfrom reflex.utils.serializers import serialize, serialize_dataframe\n\n\n@pytest.mark.parametrize(\n    (\"data_table_state\", \"expected\"),\n    [\n        pytest.param(\n            {\n                \"data\": pd.DataFrame(\n                    [[\"foo\", \"bar\"], [\"foo1\", \"bar1\"]],\n                    columns=[\"column1\", \"column2\"],  # pyright: ignore [reportArgumentType]\n                )\n            },\n            \"data\",\n        ),\n        pytest.param({\"data\": [\"foo\", \"bar\"]}, \"\"),\n        pytest.param({\"data\": [[\"foo\", \"bar\"], [\"foo1\", \"bar1\"]]}, \"\"),\n    ],\n    indirect=[\"data_table_state\"],\n)\ndef test_validate_data_table(data_table_state: rx.State, expected):\n    \"\"\"Test the str/render function.\n\n    Args:\n        data_table_state: The state fixture.\n        expected: expected var name.\n\n    \"\"\"\n    if not types.is_dataframe(data_table_state.data._var_type):  # pyright: ignore[reportAttributeAccessIssue]\n        data_table_component = DataTable.create(\n            data=data_table_state.data,  # pyright: ignore[reportAttributeAccessIssue]\n            columns=data_table_state.columns,  # pyright: ignore[reportAttributeAccessIssue]\n        )\n    else:\n        data_table_component = DataTable.create(data=data_table_state.data)  # pyright: ignore[reportAttributeAccessIssue]\n\n    data_table_dict = data_table_component.render()\n\n    # prefix expected with state name\n    state_name = data_table_state.get_name()\n    expected_columns = (\n        f\"{state_name}.{expected}{FIELD_MARKER}.columns\"\n        if expected\n        else state_name + \".columns\" + FIELD_MARKER\n    )\n    expected_data = (\n        f\"{state_name}.{expected}{FIELD_MARKER}.data\"\n        if expected\n        else state_name + \".data\" + FIELD_MARKER\n    )\n\n    assert data_table_dict[\"props\"] == [\n        \"columns:\" + expected_columns,\n        \"data:\" + expected_data,\n    ]\n\n\n@pytest.mark.parametrize(\n    \"props\",\n    [\n        {\"data\": [[\"foo\", \"bar\"], [\"foo1\", \"bar1\"]]},\n        {\n            \"data\": pd.DataFrame([[\"foo\", \"bar\"], [\"foo1\", \"bar1\"]]),\n            \"columns\": [\"column1\", \"column2\"],\n        },\n    ],\n)\ndef test_invalid_props(props):\n    \"\"\"Test if value error is thrown when invalid props are passed.\n\n    Args:\n        props: props to pass in component.\n    \"\"\"\n    with pytest.raises(ValueError):\n        DataTable.create(**props)\n\n\n@pytest.mark.parametrize(\n    (\"fixture\", \"err_msg\", \"is_data_frame\"),\n    [\n        (\n            \"data_table_state2\",\n            \"Computed var 'data' must have a type annotation.\",\n            True,\n        ),\n        (\n            \"data_table_state3\",\n            \"Computed var 'columns' must have a type annotation.\",\n            False,\n        ),\n        (\n            \"data_table_state4\",\n            \"Computed var 'data' must have a type annotation.\",\n            False,\n        ),\n    ],\n)\ndef test_computed_var_without_annotation(fixture, request, err_msg, is_data_frame):\n    \"\"\"Test if value error is thrown when the computed var assigned to the data/column prop is not annotated.\n\n    Args:\n        fixture: the state.\n        request: fixture request.\n        err_msg: expected error message.\n        is_data_frame: whether data field is a pandas dataframe.\n    \"\"\"\n    with pytest.raises(UntypedComputedVarError) as err:\n        if is_data_frame:\n            DataTable.create(data=request.getfixturevalue(fixture).data)\n        else:\n            DataTable.create(\n                data=request.getfixturevalue(fixture).data,\n                columns=request.getfixturevalue(fixture).columns,\n            )\n    assert err.value.args[0] == err_msg\n\n\ndef test_serialize_dataframe():\n    \"\"\"Test if dataframe is serialized correctly.\"\"\"\n    simple_dataframe = pd.DataFrame(\n        [[\"foo\", \"bar\"], [\"foo1\", \"bar1\"]],\n        columns=[\"column1\", \"column2\"],  # pyright: ignore [reportArgumentType]\n    )\n    value = serialize(simple_dataframe)\n    assert value == serialize_dataframe(simple_dataframe)\n    assert isinstance(value, dict)\n    assert tuple(value) == (\"columns\", \"data\")\n"
  },
  {
    "path": "tests/units/components/datadisplay/test_shiki_code.py",
    "content": "import pytest\n\nfrom reflex.components.datadisplay.shiki_code_block import (\n    ShikiBaseTransformers,\n    ShikiCodeBlock,\n    ShikiHighLevelCodeBlock,\n    ShikiJsTransformer,\n)\nfrom reflex.components.el.elements.forms import Button\nfrom reflex.components.lucide.icon import Icon\nfrom reflex.components.radix.themes.layout.box import Box\nfrom reflex.style import Style\nfrom reflex.vars import Var\nfrom reflex.vars.base import LiteralVar\n\n\n@pytest.mark.parametrize(\n    (\"library\", \"fns\", \"expected_output\", \"raises_exception\"),\n    [\n        (\"some_library\", [\"function_one\"], [\"function_one\"], False),\n        (\"some_library\", [123], None, True),\n        (\"some_library\", [], [], False),\n        (\n            \"some_library\",\n            [\"function_one\", \"function_two\"],\n            [\"function_one\", \"function_two\"],\n            False,\n        ),\n        (\"\", [\"function_one\"], [\"function_one\"], False),\n        (\"some_library\", [\"function_one\", 789], None, True),\n        (\"\", [], [], False),\n    ],\n)\ndef test_create_transformer(library, fns, expected_output, raises_exception):\n    if raises_exception:\n        # Ensure ValueError is raised for invalid cases\n        with pytest.raises(ValueError):\n            ShikiCodeBlock.create_transformer(library, fns)\n    else:\n        transformer = ShikiCodeBlock.create_transformer(library, fns)\n        assert isinstance(transformer, ShikiBaseTransformers)\n        assert transformer.library == library\n\n        # Verify that the functions are correctly wrapped in FunctionStringVar\n        function_names = [str(fn) for fn in transformer.fns]\n        assert function_names == expected_output\n\n\n@pytest.mark.parametrize(\n    (\"code_block\", \"children\", \"props\", \"expected_first_child\", \"expected_styles\"),\n    [\n        (\"print('Hello')\", [\"print('Hello')\"], {}, \"print('Hello')\", {}),\n        (\n            \"print('Hello')\",\n            [\"print('Hello')\", \"More content\"],\n            {},\n            \"print('Hello')\",\n            {},\n        ),\n        (\n            \"print('Hello')\",\n            [\"print('Hello')\"],\n            {\n                \"transformers\": [\n                    ShikiBaseTransformers(\n                        library=\"lib\", fns=[], style=Style({\"color\": \"red\"})\n                    )\n                ]\n            },\n            \"print('Hello')\",\n            {\"color\": \"red\"},\n        ),\n        (\n            \"print('Hello')\",\n            [\"print('Hello')\"],\n            {\n                \"transformers\": [\n                    ShikiBaseTransformers(\n                        library=\"lib\", fns=[], style=Style({\"color\": \"red\"})\n                    )\n                ],\n                \"style\": {\"background\": \"blue\"},\n            },\n            \"print('Hello')\",\n            {\"color\": \"red\", \"background\": \"blue\"},\n        ),\n    ],\n)\ndef test_create_shiki_code_block(\n    code_block, children, props, expected_first_child, expected_styles\n):\n    component = ShikiCodeBlock.create(code_block, *children, **props)\n\n    # Test that the created component is a Box\n    assert isinstance(component, Box)\n\n    # Test that the first child is the code\n    code_block_component = component.children[0]\n    assert code_block_component.code._var_value == expected_first_child  # pyright: ignore [reportAttributeAccessIssue]\n\n    applied_styles = component.style\n    for key, value in expected_styles.items():\n        var = Var.create(applied_styles[key])\n        assert isinstance(var, LiteralVar)\n        assert var._var_value == value\n\n\n@pytest.mark.parametrize(\n    (\"children\", \"props\", \"expected_transformers\", \"expected_button_type\"),\n    [\n        ([\"print('Hello')\"], {\"use_transformers\": True}, [ShikiJsTransformer], None),\n        ([\"print('Hello')\"], {\"can_copy\": True}, None, Button),\n        (\n            [\"print('Hello')\"],\n            {\n                \"can_copy\": True,\n                \"copy_button\": Button.create(Icon.create(tag=\"a_arrow_down\")),\n            },\n            None,\n            Button,\n        ),\n    ],\n)\ndef test_create_shiki_high_level_code_block(\n    children, props, expected_transformers, expected_button_type\n):\n    component = ShikiHighLevelCodeBlock.create(*children, **props)\n\n    # Test that the created component is a Box\n    assert isinstance(component, Box)\n\n    # Test that the first child is the code block component\n    code_block_component = component.children[0]\n    assert code_block_component.code._var_value == children[0]  # pyright: ignore [reportAttributeAccessIssue]\n\n    # Check if the transformer is set correctly if expected\n    if expected_transformers:\n        exp_trans_names = [t.__name__ for t in expected_transformers]\n        for transformer in code_block_component.transformers._var_value:  # pyright: ignore [reportAttributeAccessIssue]\n            assert type(transformer).__name__ in exp_trans_names\n\n    # Check if the second child is the copy button if can_copy is True\n    if props.get(\"can_copy\", False):\n        if props.get(\"copy_button\"):\n            assert isinstance(component.children[1], expected_button_type)\n            assert component.children[1] == props[\"copy_button\"]\n        else:\n            assert isinstance(component.children[1], expected_button_type)\n    else:\n        assert len(component.children) == 1\n\n\n@pytest.mark.parametrize(\n    (\"children\", \"props\"),\n    [\n        ([\"print('Hello')\"], {\"theme\": \"dark\"}),\n        ([\"print('Hello')\"], {\"language\": \"javascript\"}),\n    ],\n)\ndef test_shiki_high_level_code_block_theme_language_mapping(children, props):\n    component = ShikiHighLevelCodeBlock.create(*children, **props)\n\n    # Test that the theme is mapped correctly\n    if \"theme\" in props:\n        assert component.children[\n            0\n        ].theme._var_value == ShikiHighLevelCodeBlock._map_themes(props[\"theme\"])  # pyright: ignore [reportAttributeAccessIssue]\n\n    # Test that the language is mapped correctly\n    if \"language\" in props:\n        assert component.children[\n            0\n        ].language._var_value == ShikiHighLevelCodeBlock._map_languages(  # pyright: ignore [reportAttributeAccessIssue]\n            props[\"language\"]\n        )\n"
  },
  {
    "path": "tests/units/components/el/test_svg.py",
    "content": "from reflex.components.el.elements.media import (\n    Circle,\n    Defs,\n    Ellipse,\n    G,\n    Line,\n    LinearGradient,\n    Marker,\n    Path,\n    Polygon,\n    RadialGradient,\n    Rect,\n    Stop,\n    Svg,\n    Text,\n)\n\n\ndef test_circle():\n    circle = Circle.create().render()\n    assert circle[\"name\"] == '\"circle\"'\n\n\ndef test_defs():\n    defs = Defs.create().render()\n    assert defs[\"name\"] == '\"defs\"'\n\n\ndef test_ellipse():\n    ellipse = Ellipse.create().render()\n    assert ellipse[\"name\"] == '\"ellipse\"'\n\n\ndef test_line():\n    line = Line.create().render()\n    assert line[\"name\"] == '\"line\"'\n\n\ndef test_linear_gradient():\n    linear_gradient = LinearGradient.create().render()\n    assert linear_gradient[\"name\"] == '\"linearGradient\"'\n\n\ndef test_path():\n    path = Path.create().render()\n    assert path[\"name\"] == '\"path\"'\n\n\ndef test_polygon():\n    polygon = Polygon.create().render()\n    assert polygon[\"name\"] == '\"polygon\"'\n\n\ndef test_radial_gradient():\n    radial_gradient = RadialGradient.create().render()\n    assert radial_gradient[\"name\"] == '\"radialGradient\"'\n\n\ndef test_rect():\n    rect = Rect.create().render()\n    assert rect[\"name\"] == '\"rect\"'\n\n\ndef test_svg():\n    svg = Svg.create().render()\n    assert svg[\"name\"] == '\"svg\"'\n\n\ndef test_text():\n    text = Text.create().render()\n    assert text[\"name\"] == '\"text\"'\n\n\ndef test_stop():\n    stop = Stop.create().render()\n    assert stop[\"name\"] == '\"stop\"'\n\n\ndef test_marker():\n    marker = Marker.create().render()\n    assert marker[\"name\"] == '\"marker\"'\n\n\ndef test_g():\n    g = G.create().render()\n    assert g[\"name\"] == '\"g\"'\n"
  },
  {
    "path": "tests/units/components/forms/__init__.py",
    "content": ""
  },
  {
    "path": "tests/units/components/forms/test_form.py",
    "content": "from reflex.components.radix.primitives.form import Form\nfrom reflex.event import EventChain, prevent_default\nfrom reflex.vars.base import Var\n\n\ndef test_render_on_submit():\n    \"\"\"Test that on_submit event chain is rendered as a separate function.\"\"\"\n    submit_it = Var(\n        _js_expr=\"submit_it\",\n        _var_type=EventChain,\n    )\n    f = Form.create(on_submit=submit_it)\n    exp_submit_name = f\"handleSubmit_{f.handle_submit_unique_name}\"  # pyright: ignore [reportAttributeAccessIssue]\n    assert f\"onSubmit:{exp_submit_name}\" in f.render()[\"props\"]\n\n\ndef test_render_no_on_submit():\n    \"\"\"A form without on_submit should render a prevent_default handler.\"\"\"\n    f = Form.create()\n    assert isinstance(f.event_triggers[\"on_submit\"], EventChain)\n    assert len(f.event_triggers[\"on_submit\"].events) == 1\n    assert f.event_triggers[\"on_submit\"].events[0] == prevent_default\n"
  },
  {
    "path": "tests/units/components/graphing/__init__.py",
    "content": "\"\"\"Graphing component tests.\"\"\"\n"
  },
  {
    "path": "tests/units/components/graphing/test_plotly.py",
    "content": "import numpy as np\nimport plotly.graph_objects as go\nimport pytest\n\nimport reflex as rx\nfrom reflex.utils.serializers import serialize, serialize_figure\n\n\n@pytest.fixture\ndef plotly_fig() -> go.Figure:\n    \"\"\"Get a plotly figure.\n\n    Returns:\n        A random plotly figure.\n    \"\"\"\n    # Generate random data.\n    rng = np.random.default_rng()\n    data = rng.integers(0, 10, size=(10, 4))\n    trace = go.Scatter(\n        x=list(range(len(data))), y=data[:, 0], mode=\"lines\", name=\"Trace 1\"\n    )\n\n    # Create a graph.\n    return go.Figure(data=[trace])\n\n\ndef test_serialize_plotly(plotly_fig: go.Figure):\n    \"\"\"Test that serializing a plotly figure works.\n\n    Args:\n        plotly_fig: The figure to serialize.\n    \"\"\"\n    value = serialize(plotly_fig)\n    assert isinstance(value, dict)\n    assert value == serialize_figure(plotly_fig)\n\n\ndef test_plotly_config_option(plotly_fig: go.Figure):\n    \"\"\"Test that the plotly component can be created with a config option.\n\n    Args:\n        plotly_fig: The figure to display.\n    \"\"\"\n    # This tests just confirm that the component can be created with a config option.\n    _ = rx.plotly(data=plotly_fig, config={\"showLink\": True})\n"
  },
  {
    "path": "tests/units/components/graphing/test_recharts.py",
    "content": "from reflex.components.recharts.charts import (\n    AreaChart,\n    BarChart,\n    LineChart,\n    PieChart,\n    RadarChart,\n    RadialBarChart,\n    ScatterChart,\n)\nfrom reflex.components.recharts.general import ResponsiveContainer\n\n\ndef test_area_chart():\n    ac = AreaChart.create()\n    assert isinstance(ac, ResponsiveContainer)\n    assert isinstance(ac.children[0], AreaChart)\n\n\ndef test_bar_chart():\n    bc = BarChart.create()\n    assert isinstance(bc, ResponsiveContainer)\n    assert isinstance(bc.children[0], BarChart)\n\n\ndef test_line_chart():\n    lc = LineChart.create()\n    assert isinstance(lc, ResponsiveContainer)\n    assert isinstance(lc.children[0], LineChart)\n\n\ndef test_pie_chart():\n    pc = PieChart.create()\n    assert isinstance(pc, ResponsiveContainer)\n    assert isinstance(pc.children[0], PieChart)\n\n\ndef test_radar_chart():\n    rc = RadarChart.create()\n    assert isinstance(rc, ResponsiveContainer)\n    assert isinstance(rc.children[0], RadarChart)\n\n\ndef test_radial_bar_chart():\n    rbc = RadialBarChart.create()\n    assert isinstance(rbc, ResponsiveContainer)\n    assert isinstance(rbc.children[0], RadialBarChart)\n\n\ndef test_scatter_chart():\n    sc = ScatterChart.create()\n    assert isinstance(sc, ResponsiveContainer)\n    assert isinstance(sc.children[0], ScatterChart)\n"
  },
  {
    "path": "tests/units/components/layout/__init__.py",
    "content": "\"\"\"Layout component tests.\"\"\"\n"
  },
  {
    "path": "tests/units/components/lucide/test_icon.py",
    "content": "import pytest\n\nfrom reflex.components.lucide.icon import (\n    LUCIDE_ICON_LIST,\n    LUCIDE_ICON_MAPPING_OVERRIDE,\n    Icon,\n)\nfrom reflex.utils import format\n\n\n@pytest.mark.parametrize(\"tag\", LUCIDE_ICON_LIST)\ndef test_icon(tag):\n    icon = Icon.create(tag)\n    assert icon.alias == \"Lucide\" + LUCIDE_ICON_MAPPING_OVERRIDE.get(\n        tag, format.to_title_case(tag)\n    )\n\n\ndef test_icon_missing_tag():\n    with pytest.raises(AttributeError):\n        _ = Icon.create()\n\n\ndef test_icon_invalid_tag():\n    invalid = Icon.create(\"invalid-tag\")\n    assert invalid.tag == \"CircleHelp\"\n\n\ndef test_icon_multiple_children():\n    with pytest.raises(AttributeError):\n        _ = Icon.create(\"activity\", \"child1\", \"child2\")\n\n\ndef test_icon_add_style():\n    ic = Icon.create(\"activity\")\n    assert ic.add_style() is None\n"
  },
  {
    "path": "tests/units/components/markdown/__init__.py",
    "content": ""
  },
  {
    "path": "tests/units/components/markdown/test_markdown.py",
    "content": "import pytest\n\nfrom reflex.components.component import Component, memo\nfrom reflex.components.datadisplay.code import CodeBlock\nfrom reflex.components.datadisplay.shiki_code_block import ShikiHighLevelCodeBlock\nfrom reflex.components.markdown.markdown import Markdown, MarkdownComponentMap\nfrom reflex.components.radix.themes.layout.box import Box\nfrom reflex.components.radix.themes.typography.heading import Heading\nfrom reflex.vars.base import Var\n\n\nclass CustomMarkdownComponent(Component, MarkdownComponentMap):\n    \"\"\"A custom markdown component.\"\"\"\n\n    tag = \"CustomMarkdownComponent\"\n    library = \"custom\"\n\n    @classmethod\n    def get_fn_args(cls) -> tuple[str, ...]:\n        \"\"\"Return the function arguments.\n\n        Returns:\n            The function arguments.\n        \"\"\"\n        return (\"custom_node\", \"custom_children\", \"custom_props\")\n\n    @classmethod\n    def get_fn_body(cls) -> Var:\n        \"\"\"Return the function body.\n\n        Returns:\n            The function body.\n        \"\"\"\n        return Var(_js_expr=\"{return custom_node + custom_children + custom_props}\")\n\n\ndef syntax_highlighter_memoized_component(codeblock: type[Component]):\n    @memo\n    def code_block(code: str, language: str):\n        return Box.create(\n            codeblock.create(\n                code,\n                language=language,\n                class_name=\"code-block\",\n                can_copy=True,\n            ),\n            class_name=\"relative mb-4\",\n        )\n\n    def code_block_markdown(*children, **props):\n        return code_block(\n            code=children[0], language=props.pop(\"language\", \"plain\"), **props\n        )\n\n    return code_block_markdown\n\n\n@pytest.mark.parametrize(\n    (\"fn_body\", \"fn_args\", \"explicit_return\", \"expected\"),\n    [\n        (\n            None,\n            None,\n            False,\n            Var(_js_expr=\"(({node, children, ...props}) => undefined)\"),\n        ),\n        (\"return node\", (\"node\",), True, Var(_js_expr=\"(({node}) => {return node})\")),\n        (\n            \"return node + children\",\n            (\"node\", \"children\"),\n            True,\n            Var(_js_expr=\"(({node, children}) => {return node + children})\"),\n        ),\n        (\n            \"return node + props\",\n            (\"node\", \"...props\"),\n            True,\n            Var(_js_expr=\"(({node, ...props}) => {return node + props})\"),\n        ),\n        (\n            \"return node + children + props\",\n            (\"node\", \"children\", \"...props\"),\n            True,\n            Var(\n                _js_expr=\"(({node, children, ...props}) => {return node + children + props})\"\n            ),\n        ),\n    ],\n)\ndef test_create_map_fn_var(fn_body, fn_args, explicit_return, expected):\n    result = MarkdownComponentMap.create_map_fn_var(\n        fn_body=Var(_js_expr=fn_body, _var_type=str) if fn_body else None,\n        fn_args=fn_args,\n        explicit_return=explicit_return,\n    )\n    assert result._js_expr == expected._js_expr\n\n\n@pytest.mark.parametrize(\n    (\"cls\", \"fn_body\", \"fn_args\", \"explicit_return\", \"expected\"),\n    [\n        (\n            MarkdownComponentMap,\n            None,\n            None,\n            False,\n            Var(_js_expr=\"(({node, children, ...props}) => undefined)\"),\n        ),\n        (\n            MarkdownComponentMap,\n            \"return node\",\n            (\"node\",),\n            True,\n            Var(_js_expr=\"(({node}) => {return node})\"),\n        ),\n        (\n            CustomMarkdownComponent,\n            None,\n            None,\n            True,\n            Var(\n                _js_expr=\"(({custom_node, custom_children, custom_props}) => {return custom_node + custom_children + custom_props})\"\n            ),\n        ),\n        (\n            CustomMarkdownComponent,\n            \"return custom_node\",\n            (\"custom_node\",),\n            True,\n            Var(_js_expr=\"(({custom_node}) => {return custom_node})\"),\n        ),\n    ],\n)\ndef test_create_map_fn_var_subclass(cls, fn_body, fn_args, explicit_return, expected):\n    result = cls.create_map_fn_var(\n        fn_body=Var(_js_expr=fn_body, _var_type=int) if fn_body else None,\n        fn_args=fn_args,\n        explicit_return=explicit_return,\n    )\n    assert result._js_expr == expected._js_expr\n\n\n@pytest.mark.parametrize(\n    (\"key\", \"component_map\", \"expected\"),\n    [\n        (\n            \"code\",\n            {},\n            r\"\"\"(({node, children, ...props}) => (jsx(RadixThemesCode,{...props},children)))\"\"\",\n        ),\n        (\n            \"pre\",\n            {\n                \"pre\": lambda value, **props: ShikiHighLevelCodeBlock.create(\n                    value, **props\n                )\n            },\n            r\"\"\"(({node, ...rest}) => { const {node: childNode, className, children: components, ...props} = rest.children.props; const children = String(Array.isArray(components) ? components.join('\\n') : components).replace(/\\n$/, ''); const match = (className || '').match(/language-(?<lang>.*)/); let _language = match ? match[1] : ''; ;             return jsx(RadixThemesBox,{css:({ [\"pre\"] : ({ [\"margin\"] : \"0\", [\"padding\"] : \"24px\", [\"background\"] : \"transparent\", [\"overflowX\"] : \"auto\", [\"borderRadius\"] : \"6px\" }) }),...props},jsx(ShikiCode,{code:children,decorations:[],language:_language,theme:((resolvedColorMode?.valueOf?.() === \"light\"?.valueOf?.()) ? \"one-light\" : \"one-dark-pro\"),transformers:[]},));         })\"\"\",\n        ),\n        (\n            \"h1\",\n            {\n                \"h1\": lambda value: CustomMarkdownComponent.create(\n                    Heading.create(value, as_=\"h1\", size=\"6\", margin_y=\"0.5em\")\n                )\n            },\n            \"\"\"(({custom_node, custom_children, custom_props}) => (jsx(CustomMarkdownComponent,{...props},jsx(RadixThemesHeading,{as:\"h1\",css:({ [\"marginTop\"] : \"0.5em\", [\"marginBottom\"] : \"0.5em\" }),size:\"6\"},children))))\"\"\",\n        ),\n        (\n            \"pre\",\n            {\"pre\": syntax_highlighter_memoized_component(CodeBlock)},\n            r\"\"\"(({node, ...rest}) => { const {node: childNode, className, children: components, ...props} = rest.children.props; const children = String(Array.isArray(components) ? components.join('\\n') : components).replace(/\\n$/, ''); const match = (className || '').match(/language-(?<lang>.*)/); let _language = match ? match[1] : ''; ;             return jsx(CodeBlock,{code:children,language:_language,...props},);         })\"\"\",\n        ),\n        (\n            \"pre\",\n            {\"pre\": syntax_highlighter_memoized_component(ShikiHighLevelCodeBlock)},\n            r\"\"\"(({node, ...rest}) => { const {node: childNode, className, children: components, ...props} = rest.children.props; const children = String(Array.isArray(components) ? components.join('\\n') : components).replace(/\\n$/, ''); const match = (className || '').match(/language-(?<lang>.*)/); let _language = match ? match[1] : ''; ;             return jsx(CodeBlock,{code:children,language:_language,...props},);         })\"\"\",\n        ),\n    ],\n)\ndef test_markdown_format_component(key, component_map, expected):\n    markdown = Markdown.create(\"# header\", component_map=component_map)\n    result = markdown.format_component_map()\n    print(str(result[key]))\n    assert str(result[key]) == expected\n"
  },
  {
    "path": "tests/units/components/media/__init__.py",
    "content": "\"\"\"Media component tests.\"\"\"\n"
  },
  {
    "path": "tests/units/components/media/test_image.py",
    "content": "import numpy as np\nimport PIL\nimport pytest\nfrom PIL.Image import Image as Img\n\nimport reflex as rx\nfrom reflex.utils.serializers import serialize, serialize_image\n\n\n@pytest.fixture\ndef pil_image() -> Img:\n    \"\"\"Get an image.\n\n    Returns:\n        A random PIL image.\n    \"\"\"\n    rng = np.random.default_rng()\n    imarray = rng.random((100, 100, 3)) * 255\n    return PIL.Image.fromarray(imarray.astype(\"uint8\")).convert(\"RGBA\")  # pyright: ignore [reportAttributeAccessIssue]\n\n\ndef test_serialize_image(pil_image: Img):\n    \"\"\"Test that serializing an image works.\n\n    Args:\n        pil_image: The image to serialize.\n    \"\"\"\n    data = serialize(pil_image)\n    assert isinstance(data, str)\n    assert data == serialize_image(pil_image)\n    assert data.startswith(\"data:image/png;base64,\")\n\n\ndef test_set_src_str():\n    \"\"\"Test that setting the src works.\"\"\"\n    image = rx.image(src=\"pic2.jpeg\")\n    assert str(image.src) == '\"pic2.jpeg\"'  # pyright: ignore [reportAttributeAccessIssue]\n"
  },
  {
    "path": "tests/units/components/radix/test_icon_button.py",
    "content": "import pytest\n\nfrom reflex.components.lucide.icon import Icon\nfrom reflex.components.radix.themes.components.icon_button import IconButton\nfrom reflex.style import Style\nfrom reflex.vars.base import LiteralVar\n\n\ndef test_icon_button():\n    ib1 = IconButton.create(\"activity\")\n    assert isinstance(ib1, IconButton)\n\n    ib2 = IconButton.create(Icon.create(\"activity\"))\n    assert isinstance(ib2, IconButton)\n\n    assert isinstance(ib1.add_style(), Style)\n    assert isinstance(ib2.add_style(), Style)\n\n\ndef test_icon_button_no_child():\n    with pytest.raises(ValueError):\n        _ = IconButton.create()\n\n\ndef test_icon_button_size_prop():\n    ib1 = IconButton.create(\"activity\", size=\"2\")\n    assert isinstance(ib1, IconButton)\n\n    ib2 = IconButton.create(\"activity\", size=LiteralVar.create(\"2\"))\n    assert isinstance(ib2, IconButton)\n"
  },
  {
    "path": "tests/units/components/radix/test_layout.py",
    "content": "from reflex.components.radix.themes.layout.base import LayoutComponent\n\n\ndef test_layout_component():\n    lc = LayoutComponent.create()\n    assert isinstance(lc, LayoutComponent)\n"
  },
  {
    "path": "tests/units/components/recharts/test_cartesian.py",
    "content": "from reflex.components.recharts import (\n    Area,\n    Bar,\n    Brush,\n    Line,\n    Scatter,\n    XAxis,\n    YAxis,\n    ZAxis,\n)\n\n\ndef test_xaxis():\n    x_axis = XAxis.create(\"x\").render()\n    assert x_axis[\"name\"] == \"RechartsXAxis\"\n\n\ndef test_yaxis():\n    x_axis = YAxis.create(\"y\").render()\n    assert x_axis[\"name\"] == \"RechartsYAxis\"\n\n\ndef test_zaxis():\n    x_axis = ZAxis.create(\"z\").render()\n    assert x_axis[\"name\"] == \"RechartsZAxis\"\n\n\ndef test_brush():\n    brush = Brush.create().render()\n    assert brush[\"name\"] == \"RechartsBrush\"\n\n\ndef test_area():\n    area = Area.create().render()\n    assert area[\"name\"] == \"RechartsArea\"\n\n\ndef test_bar():\n    bar = Bar.create().render()\n    assert bar[\"name\"] == \"RechartsBar\"\n\n\ndef test_line():\n    line = Line.create().render()\n    assert line[\"name\"] == \"RechartsLine\"\n\n\ndef test_scatter():\n    scatter = Scatter.create().render()\n    assert scatter[\"name\"] == \"RechartsScatter\"\n"
  },
  {
    "path": "tests/units/components/recharts/test_polar.py",
    "content": "from reflex.components.recharts import (\n    Pie,\n    PolarAngleAxis,\n    PolarGrid,\n    PolarRadiusAxis,\n    Radar,\n    RadialBar,\n)\n\n\ndef test_pie():\n    pie = Pie.create().render()\n    assert pie[\"name\"] == \"RechartsPie\"\n\n\ndef test_radar():\n    radar = Radar.create().render()\n    assert radar[\"name\"] == \"RechartsRadar\"\n\n\ndef test_radialbar():\n    radialbar = RadialBar.create().render()\n    assert radialbar[\"name\"] == \"RechartsRadialBar\"\n\n\ndef test_polarangleaxis():\n    polarangleaxis = PolarAngleAxis.create().render()\n    assert polarangleaxis[\"name\"] == \"RechartsPolarAngleAxis\"\n\n\ndef test_polargrid():\n    polargrid = PolarGrid.create().render()\n    assert polargrid[\"name\"] == \"RechartsPolarGrid\"\n\n\ndef test_polarradiusaxis():\n    polarradiusaxis = PolarRadiusAxis.create().render()\n    assert polarradiusaxis[\"name\"] == \"RechartsPolarRadiusAxis\"\n"
  },
  {
    "path": "tests/units/components/test_component.py",
    "content": "from contextlib import nullcontext\nfrom typing import Any, ClassVar\n\nimport pytest\n\nimport reflex as rx\nfrom reflex.base import Base\nfrom reflex.compiler.utils import compile_custom_component\nfrom reflex.components.base.bare import Bare\nfrom reflex.components.base.fragment import Fragment\nfrom reflex.components.component import (\n    CUSTOM_COMPONENTS,\n    Component,\n    CustomComponent,\n    StatefulComponent,\n    custom_component,\n)\nfrom reflex.components.radix.themes.layout.box import Box\nfrom reflex.constants import EventTriggers\nfrom reflex.constants.state import FIELD_MARKER\nfrom reflex.event import (\n    EventChain,\n    EventHandler,\n    JavascriptInputEvent,\n    input_event,\n    no_args_event_spec,\n    parse_args_spec,\n    passthrough_event_spec,\n)\nfrom reflex.state import BaseState\nfrom reflex.style import Style\nfrom reflex.utils import imports\nfrom reflex.utils.exceptions import (\n    ChildrenTypeError,\n    EventFnArgMismatchError,\n    EventHandlerArgTypeMismatchError,\n)\nfrom reflex.utils.imports import ImportDict, ImportVar, ParsedImportDict, parse_imports\nfrom reflex.vars import VarData\nfrom reflex.vars.base import LiteralVar, Var\nfrom reflex.vars.object import ObjectVar\n\n\nclass TestState(BaseState):\n    \"\"\"A test state with various methods for event handling.\"\"\"\n\n    num: int\n\n    @rx.event\n    def do_something(self):\n        \"\"\"A method with no arguments.\"\"\"\n\n    @rx.event\n    def do_something_arg(self, arg):\n        \"\"\"A method with one unspecfied argument.\"\"\"\n\n    @rx.event\n    def do_something_with_bool(self, arg: bool):\n        \"\"\"A method with a boolean argument.\"\"\"\n\n    @rx.event\n    def do_something_with_int(self, arg: int):\n        \"\"\"A method with an integer argument.\"\"\"\n\n    @rx.event\n    def do_something_with_list_int(self, arg: list[int]):\n        \"\"\"A method with a list of integers argument.\"\"\"\n\n    @rx.event\n    def do_something_with_list_str(self, arg: list[str]):\n        \"\"\"A method with a list of strings argument.\"\"\"\n\n    @rx.event\n    def do_something_required_optional(\n        self, required_arg: int, optional_arg: int | None = None\n    ):\n        \"\"\"A method with one required and one optional argument.\"\"\"\n\n\n@pytest.fixture\ndef test_state():\n\n    return TestState\n\n\n@pytest.fixture\ndef component1() -> type[Component]:\n    \"\"\"A test component.\n\n    Returns:\n        A test component.\n    \"\"\"\n\n    class TestComponent1(Component):\n        # A test string prop.\n        text: Var[str]\n\n        # A test number prop.\n        number: Var[int]\n\n        # A test string/number prop.\n        text_or_number: Var[int | str]\n\n        def _get_imports(self) -> ParsedImportDict:\n            return {\"react\": [ImportVar(tag=\"Component\")]}\n\n        def _get_custom_code(self) -> str:\n            return \"console.log('component1')\"\n\n    return TestComponent1\n\n\n@pytest.fixture\ndef component2() -> type[Component]:\n    \"\"\"A test component.\n\n    Returns:\n        A test component.\n    \"\"\"\n\n    def on_prop_event_spec(e0: Any):\n        return [e0]\n\n    class TestComponent2(Component):\n        # A test list prop.\n        arr: Var[list[str]]\n\n        on_prop_event: EventHandler[on_prop_event_spec]\n\n        @classmethod\n        def get_event_triggers(cls) -> dict[str, Any]:\n            \"\"\"Test controlled triggers.\n\n            Returns:\n                Test controlled triggers.\n            \"\"\"\n            return {\n                **super().get_event_triggers(),\n                \"on_open\": passthrough_event_spec(bool),\n                \"on_close\": passthrough_event_spec(bool),\n                \"on_user_visited_count_changed\": passthrough_event_spec(int),\n                \"on_two_args\": passthrough_event_spec(int, int),\n                \"on_user_list_changed\": passthrough_event_spec(list[str]),\n            }\n\n        def _get_imports(self) -> ParsedImportDict:\n            return {\"react-redux\": [ImportVar(tag=\"connect\")]}\n\n        def _get_custom_code(self) -> str:\n            return \"console.log('component2')\"\n\n    return TestComponent2\n\n\n@pytest.fixture\ndef component3() -> type[Component]:\n    \"\"\"A test component with hook defined.\n\n    Returns:\n        A test component.\n    \"\"\"\n\n    class TestComponent3(Component):\n        def _get_hooks(self) -> str:\n            return \"const a = () => true\"\n\n    return TestComponent3\n\n\n@pytest.fixture\ndef component4() -> type[Component]:\n    \"\"\"A test component with hook defined.\n\n    Returns:\n        A test component.\n    \"\"\"\n\n    class TestComponent4(Component):\n        def _get_hooks(self) -> str:\n            return \"const b = () => false\"\n\n    return TestComponent4\n\n\n@pytest.fixture\ndef component5() -> type[Component]:\n    \"\"\"A test component.\n\n    Returns:\n        A test component.\n    \"\"\"\n\n    class TestComponent5(Component):\n        tag = \"RandomComponent\"\n\n        _invalid_children: ClassVar[list[str]] = [\"Text\"]\n\n        _valid_children: ClassVar[list[str]] = [\"Text\"]\n\n        _valid_parents: ClassVar[list[str]] = [\"Text\"]\n\n    return TestComponent5\n\n\n@pytest.fixture\ndef component6() -> type[Component]:\n    \"\"\"A test component.\n\n    Returns:\n        A test component.\n    \"\"\"\n\n    class TestComponent6(Component):\n        tag = \"RandomComponent\"\n\n        _invalid_children: ClassVar[list[str]] = [\"Text\"]\n\n    return TestComponent6\n\n\n@pytest.fixture\ndef component7() -> type[Component]:\n    \"\"\"A test component.\n\n    Returns:\n        A test component.\n    \"\"\"\n\n    class TestComponent7(Component):\n        tag = \"RandomComponent\"\n\n        _valid_children: ClassVar[list[str]] = [\"Text\"]\n\n    return TestComponent7\n\n\n@pytest.fixture\ndef on_click1() -> EventHandler:\n    \"\"\"A sample on click function.\n\n    Returns:\n        A sample on click function.\n    \"\"\"\n\n    def on_click1():\n        pass\n\n    return EventHandler(fn=on_click1)\n\n\n@pytest.fixture\ndef on_click2() -> EventHandler:\n    \"\"\"A sample on click function.\n\n    Returns:\n        A sample on click function.\n    \"\"\"\n\n    def on_click2():\n        pass\n\n    return EventHandler(fn=on_click2)\n\n\n@pytest.fixture\ndef my_component():\n    \"\"\"A test component function.\n\n    Returns:\n        A test component function.\n    \"\"\"\n\n    def my_component(prop1: Var[str], prop2: Var[int]):\n        return Box.create(prop1, prop2)\n\n    return my_component\n\n\ndef test_set_style_attrs(component1):\n    \"\"\"Test that style attributes are set in the dict.\n\n    Args:\n        component1: A test component.\n    \"\"\"\n    component = component1.create(color=\"white\", text_align=\"center\")\n    assert str(component.style[\"color\"]) == '\"white\"'\n    assert str(component.style[\"textAlign\"]) == '\"center\"'\n\n\ndef test_custom_attrs(component1):\n    \"\"\"Test that custom attributes are set in the dict.\n\n    Args:\n        component1: A test component.\n    \"\"\"\n    component = component1.create(custom_attrs={\"attr1\": \"1\", \"attr2\": \"attr2\"})\n    assert component.custom_attrs == {\"attr1\": \"1\", \"attr2\": \"attr2\"}\n\n\ndef test_create_component(component1):\n    \"\"\"Test that the component is created correctly.\n\n    Args:\n        component1: A test component.\n    \"\"\"\n    children = [component1.create() for _ in range(3)]\n    attrs = {\"color\": \"white\", \"text_align\": \"center\"}\n    c = component1.create(*children, **attrs)\n    assert isinstance(c, component1)\n    assert c.children == children\n    assert (\n        str(LiteralVar.create(c.style))\n        == '({ [\"color\"] : \"white\", [\"textAlign\"] : \"center\" })'\n    )\n\n\n@pytest.mark.parametrize(\n    (\"prop_name\", \"var\", \"expected\"),\n    [\n        pytest.param(\n            \"text\",\n            LiteralVar.create(\"hello\"),\n            None,\n            id=\"text\",\n        ),\n        pytest.param(\n            \"text\",\n            Var(_js_expr=\"hello\", _var_type=str | None),\n            None,\n            id=\"text-optional\",\n        ),\n        pytest.param(\n            \"text\",\n            Var(_js_expr=\"hello\", _var_type=str | None),\n            None,\n            id=\"text-union-str-none\",\n        ),\n        pytest.param(\n            \"text\",\n            Var(_js_expr=\"hello\", _var_type=None | str),\n            None,\n            id=\"text-union-none-str\",\n        ),\n        pytest.param(\n            \"text\",\n            LiteralVar.create(1),\n            TypeError,\n            id=\"text-int\",\n        ),\n        pytest.param(\n            \"number\",\n            LiteralVar.create(1),\n            None,\n            id=\"number\",\n        ),\n        pytest.param(\n            \"number\",\n            Var(_js_expr=\"1\", _var_type=int | None),\n            None,\n            id=\"number-optional\",\n        ),\n        pytest.param(\n            \"number\",\n            Var(_js_expr=\"1\", _var_type=int | None),\n            None,\n            id=\"number-union-int-none\",\n        ),\n        pytest.param(\n            \"number\",\n            Var(_js_expr=\"1\", _var_type=None | int),\n            None,\n            id=\"number-union-none-int\",\n        ),\n        pytest.param(\n            \"number\",\n            LiteralVar.create(\"1\"),\n            TypeError,\n            id=\"number-str\",\n        ),\n        pytest.param(\n            \"text_or_number\",\n            LiteralVar.create(\"hello\"),\n            None,\n            id=\"text_or_number-str\",\n        ),\n        pytest.param(\n            \"text_or_number\",\n            LiteralVar.create(1),\n            None,\n            id=\"text_or_number-int\",\n        ),\n        pytest.param(\n            \"text_or_number\",\n            Var(_js_expr=\"hello\", _var_type=str | None),\n            None,\n            id=\"text_or_number-optional-str\",\n        ),\n        pytest.param(\n            \"text_or_number\",\n            Var(_js_expr=\"hello\", _var_type=str | None),\n            None,\n            id=\"text_or_number-union-str-none\",\n        ),\n        pytest.param(\n            \"text_or_number\",\n            Var(_js_expr=\"hello\", _var_type=None | str),\n            None,\n            id=\"text_or_number-union-none-str\",\n        ),\n        pytest.param(\n            \"text_or_number\",\n            Var(_js_expr=\"1\", _var_type=int | None),\n            None,\n            id=\"text_or_number-optional-int\",\n        ),\n        pytest.param(\n            \"text_or_number\",\n            Var(_js_expr=\"1\", _var_type=int | None),\n            None,\n            id=\"text_or_number-union-int-none\",\n        ),\n        pytest.param(\n            \"text_or_number\",\n            Var(_js_expr=\"1\", _var_type=None | int),\n            None,\n            id=\"text_or_number-union-none-int\",\n        ),\n        pytest.param(\n            \"text_or_number\",\n            LiteralVar.create(1.0),\n            TypeError,\n            id=\"text_or_number-float\",\n        ),\n        pytest.param(\n            \"text_or_number\",\n            Var(_js_expr=\"hello\", _var_type=str | int | None),\n            None,\n            id=\"text_or_number-optional-union-str-int\",\n        ),\n    ],\n)\ndef test_create_component_prop_validation(\n    component1: type[Component],\n    prop_name: str,\n    var: Var | str | int,\n    expected: type[Exception],\n):\n    \"\"\"Test that component props are validated correctly.\n\n    Args:\n        component1: A test component.\n        prop_name: The name of the prop.\n        var: The value of the prop.\n        expected: The expected exception.\n    \"\"\"\n    ctx = pytest.raises(expected) if expected else nullcontext()\n    kwargs = {prop_name: var}\n    with ctx:\n        c = component1.create(**kwargs)\n        assert isinstance(c, component1)\n        assert c.children == []\n        assert c.style == {}\n\n\ndef test_add_style(component1, component2):\n    \"\"\"Test adding a style to a component.\n\n    Args:\n        component1: A test component.\n        component2: A test component.\n    \"\"\"\n    style = {\n        component1: Style({\"color\": \"white\"}),\n        component2: Style({\"color\": \"black\"}),\n    }\n    c1 = component1.create()._add_style_recursive(style)\n    c2 = component2.create()._add_style_recursive(style)\n    assert str(c1.style[\"color\"]) == '\"white\"'\n    assert str(c2.style[\"color\"]) == '\"black\"'\n\n\ndef test_add_style_create(component1, component2):\n    \"\"\"Test that adding style works with the create method.\n\n    Args:\n        component1: A test component.\n        component2: A test component.\n    \"\"\"\n    style = {\n        component1.create: Style({\"color\": \"white\"}),\n        component2.create: Style({\"color\": \"black\"}),\n    }\n    c1 = component1.create()._add_style_recursive(style)\n    c2 = component2.create()._add_style_recursive(style)\n    assert str(c1.style[\"color\"]) == '\"white\"'\n    assert str(c2.style[\"color\"]) == '\"black\"'\n\n\ndef test_get_imports(component1, component2):\n    \"\"\"Test getting the imports of a component.\n\n    Args:\n        component1: A test component.\n        component2: A test component.\n    \"\"\"\n    c1 = component1.create()\n    c2 = component2.create(c1)\n    assert c1._get_all_imports() == {\"react\": [ImportVar(tag=\"Component\")]}\n    assert c2._get_all_imports() == {\n        \"react-redux\": [ImportVar(tag=\"connect\")],\n        \"react\": [ImportVar(tag=\"Component\")],\n    }\n\n\ndef test_get_custom_code(component1: Component, component2: Component):\n    \"\"\"Test getting the custom code of a component.\n\n    Args:\n        component1: A test component.\n        component2: A test component.\n    \"\"\"\n    # Check that the code gets compiled correctly.\n    c1 = component1.create()\n    c2 = component2.create()\n    assert c1._get_all_custom_code() == {\"console.log('component1')\": None}\n    assert c2._get_all_custom_code() == {\"console.log('component2')\": None}\n\n    # Check that nesting components compiles both codes.\n    c1 = component1.create(c2)\n    assert c1._get_all_custom_code() == {\n        \"console.log('component1')\": None,\n        \"console.log('component2')\": None,\n    }\n\n    # Check that code is not duplicated.\n    c1 = component1.create(c2, c2, c1, c1)\n    assert c1._get_all_custom_code() == {\n        \"console.log('component1')\": None,\n        \"console.log('component2')\": None,\n    }\n\n\ndef test_get_props(component1, component2):\n    \"\"\"Test that the props are set correctly.\n\n    Args:\n        component1: A test component.\n        component2: A test component.\n    \"\"\"\n    assert set(component1.get_props()) == {\"text\", \"number\", \"text_or_number\"}\n    assert set(component2.get_props()) == {\"arr\", \"on_prop_event\"}\n\n\n@pytest.mark.parametrize(\n    (\"text\", \"number\"),\n    [\n        (\"\", 0),\n        (\"test\", 1),\n        (\"hi\", -13),\n    ],\n)\ndef test_valid_props(component1, text: str, number: int):\n    \"\"\"Test that we can construct a component with valid props.\n\n    Args:\n        component1: A test component.\n        text: A test string.\n        number: A test number.\n    \"\"\"\n    c = component1.create(text=text, number=number)\n    assert c.text._decode() == text\n    assert c.number._decode() == number\n\n\n@pytest.mark.parametrize(\n    (\"text\", \"number\"), [(\"\", \"bad_string\"), (13, 1), (\"test\", [1, 2, 3])]\n)\ndef test_invalid_prop_type(component1, text: str, number: int):\n    \"\"\"Test that an invalid prop type raises an error.\n\n    Args:\n        component1: A test component.\n        text: A test string.\n        number: A test number.\n    \"\"\"\n    # Check that\n    with pytest.raises(TypeError):\n        component1.create(text=text, number=number)\n\n\ndef test_var_props(component1, test_state: type[TestState]):\n    \"\"\"Test that we can set a Var prop.\n\n    Args:\n        component1: A test component.\n        test_state: A test state.\n    \"\"\"\n    c1 = component1.create(text=\"hello\", number=test_state.num)\n    assert c1.number.equals(test_state.num)\n\n\ndef test_get_event_triggers(component1, component2):\n    \"\"\"Test that we can get the triggers of a component.\n\n    Args:\n        component1: A test component.\n        component2: A test component.\n    \"\"\"\n    default_triggers = {\n        EventTriggers.ON_FOCUS,\n        EventTriggers.ON_BLUR,\n        EventTriggers.ON_CLICK,\n        EventTriggers.ON_CONTEXT_MENU,\n        EventTriggers.ON_DOUBLE_CLICK,\n        EventTriggers.ON_MOUSE_DOWN,\n        EventTriggers.ON_MOUSE_ENTER,\n        EventTriggers.ON_MOUSE_LEAVE,\n        EventTriggers.ON_MOUSE_MOVE,\n        EventTriggers.ON_MOUSE_OUT,\n        EventTriggers.ON_MOUSE_OVER,\n        EventTriggers.ON_MOUSE_UP,\n        EventTriggers.ON_SCROLL,\n        EventTriggers.ON_SCROLL_END,\n        EventTriggers.ON_MOUNT,\n        EventTriggers.ON_UNMOUNT,\n    }\n    assert component1.create().get_event_triggers().keys() == default_triggers\n    assert (\n        component2.create().get_event_triggers().keys()\n        == {\n            \"on_open\",\n            \"on_close\",\n            \"on_prop_event\",\n            \"on_user_visited_count_changed\",\n            \"on_two_args\",\n            \"on_user_list_changed\",\n        }\n        | default_triggers\n    )\n\n\n@pytest.fixture\ndef test_component() -> type[Component]:\n    \"\"\"A test component.\n\n    Returns:\n        A test component.\n    \"\"\"\n\n    class TestComponent(Component):\n        pass\n\n    return TestComponent\n\n\n# Write a test case to check if the create method filters out None props\ndef test_create_filters_none_props(test_component):\n    child1 = test_component.create()\n    child2 = test_component.create()\n    props = {\n        \"prop1\": \"value1\",\n        \"prop2\": None,\n        \"prop3\": \"value3\",\n        \"prop4\": None,\n        \"style\": {\"color\": \"white\", \"text-align\": \"center\"},  # Adding a style prop\n    }\n\n    component = test_component.create(child1, child2, **props)\n\n    # Assert that None props are not present in the component's props\n    assert \"prop2\" not in component.get_props()\n    assert \"prop4\" not in component.get_props()\n\n    # Assert that the style prop is present in the component's props\n    assert str(component.style[\"color\"]) == '\"white\"'\n    assert str(component.style[\"textAlign\"]) == '\"center\"'\n\n\n@pytest.mark.parametrize(\n    \"children\",\n    [\n        ({\"foo\": \"bar\"},),\n    ],\n)\ndef test_component_create_unallowed_types(children, test_component):\n    with pytest.raises(ChildrenTypeError):\n        test_component.create(*children)\n\n\n@pytest.mark.parametrize(\n    (\"element\", \"expected\"),\n    [\n        (\n            (rx.text(\"first_text\"),),\n            {\n                \"name\": \"Fragment\",\n                \"props\": [],\n                \"children\": [\n                    {\n                        \"name\": \"RadixThemesText\",\n                        \"props\": ['as:\"p\"'],\n                        \"children\": [\n                            {\n                                \"contents\": '\"first_text\"',\n                            }\n                        ],\n                    }\n                ],\n            },\n        ),\n        (\n            (rx.text(\"first_text\"), rx.text(\"second_text\")),\n            {\n                \"children\": [\n                    {\n                        \"children\": [\n                            {\n                                \"contents\": '\"first_text\"',\n                            }\n                        ],\n                        \"name\": \"RadixThemesText\",\n                        \"props\": ['as:\"p\"'],\n                    },\n                    {\n                        \"children\": [\n                            {\n                                \"contents\": '\"second_text\"',\n                            }\n                        ],\n                        \"name\": \"RadixThemesText\",\n                        \"props\": ['as:\"p\"'],\n                    },\n                ],\n                \"name\": \"Fragment\",\n                \"props\": [],\n            },\n        ),\n        (\n            (rx.text(\"first_text\"), rx.box((rx.text(\"second_text\"),))),\n            {\n                \"children\": [\n                    {\n                        \"children\": [\n                            {\n                                \"contents\": '\"first_text\"',\n                            }\n                        ],\n                        \"name\": \"RadixThemesText\",\n                        \"props\": ['as:\"p\"'],\n                    },\n                    {\n                        \"children\": [\n                            {\n                                \"children\": [\n                                    {\n                                        \"children\": [\n                                            {\n                                                \"contents\": '\"second_text\"',\n                                            }\n                                        ],\n                                        \"name\": \"RadixThemesText\",\n                                        \"props\": ['as:\"p\"'],\n                                    }\n                                ],\n                                \"name\": \"Fragment\",\n                                \"props\": [],\n                            }\n                        ],\n                        \"name\": \"RadixThemesBox\",\n                        \"props\": [],\n                    },\n                ],\n                \"name\": \"Fragment\",\n                \"props\": [],\n            },\n        ),\n    ],\n)\ndef test_component_create_unpack_tuple_child(test_component, element, expected):\n    \"\"\"Test that component in tuples are unwrapped into an rx.Fragment.\n\n    Args:\n        test_component: Component fixture.\n        element: The children to pass to the component.\n        expected: The expected render dict.\n    \"\"\"\n    comp = test_component.create(element)\n\n    assert len(comp.children) == 1\n    fragment_wrapper = comp.children[0]\n    assert isinstance(fragment_wrapper, Fragment)\n    assert fragment_wrapper.render() == expected\n\n\nclass _Obj(Base):\n    custom: int = 0\n\n\nclass C1State(BaseState):\n    \"\"\"State for testing C1 component.\"\"\"\n\n    def mock_handler(self, _e: JavascriptInputEvent, _bravo: dict, _charlie: _Obj):\n        \"\"\"Mock handler.\"\"\"\n\n\ndef test_component_event_trigger_arbitrary_args():\n    \"\"\"Test that we can define arbitrary types for the args of an event trigger.\"\"\"\n\n    def on_foo_spec(\n        _e: ObjectVar[JavascriptInputEvent],\n        alpha: Var[str],\n        bravo: dict[str, Any],\n        charlie: ObjectVar[_Obj],\n    ):\n        return [_e.target.value, bravo[\"nested\"], charlie.custom.to(int) + 42]\n\n    class C1(Component):\n        library = \"/local\"\n        tag = \"C1\"\n\n        @classmethod\n        def get_event_triggers(cls) -> dict[str, Any]:\n            return {\n                **super().get_event_triggers(),\n                \"on_foo\": on_foo_spec,\n            }\n\n    C1.create(on_foo=C1State.mock_handler)\n\n\ndef test_create_custom_component(my_component):\n    \"\"\"Test that we can create a custom component.\n\n    Args:\n        my_component: A test custom component.\n    \"\"\"\n    component = rx.memo(my_component)(prop1=\"test\", prop2=1)\n    assert component.tag == \"MyComponent\"\n    assert set(component.get_props()) == {\"prop1\", \"prop2\"}\n    assert component.tag in CUSTOM_COMPONENTS\n\n\ndef test_custom_component_hash(my_component):\n    \"\"\"Test that the hash of a custom component is correct.\n\n    Args:\n        my_component: A test custom component.\n    \"\"\"\n    component1 = rx.memo(my_component)(prop1=\"test\", prop2=1)\n    component2 = rx.memo(my_component)(prop1=\"test\", prop2=2)\n    assert {component1, component2} == {component1}\n\n\ndef test_custom_component_wrapper():\n    \"\"\"Test that the wrapper of a custom component is correct.\"\"\"\n\n    @custom_component\n    def my_component(width: Var[int], color: Var[str]):\n        return rx.box(\n            width=width,\n            color=color,\n        )\n\n    from reflex.components.radix.themes.typography.text import Text\n\n    ccomponent = my_component(\n        rx.text(\"child\"), width=LiteralVar.create(1), color=LiteralVar.create(\"red\")\n    )\n    assert isinstance(ccomponent, CustomComponent)\n    assert len(ccomponent.children) == 1\n    assert isinstance(ccomponent.children[0], Text)\n\n    component = ccomponent.get_component()\n    assert isinstance(component, Box)\n\n\ndef test_invalid_event_handler_args(component2, test_state: type[TestState]):\n    \"\"\"Test that an invalid event handler raises an error.\n\n    Args:\n        component2: A test component.\n        test_state: A test state.\n    \"\"\"\n    # EventHandler args must match\n    with pytest.raises(EventFnArgMismatchError):\n        component2.create(on_blur=test_state.do_something_arg)\n\n    # EventHandler args must have at least as many default args as the spec.\n    with pytest.raises(EventFnArgMismatchError):\n        component2.create(on_blur=test_state.do_something_required_optional)\n\n    # Multiple EventHandler args: all must match\n    with pytest.raises(EventFnArgMismatchError):\n        component2.create(\n            on_blur=[test_state.do_something_arg, test_state.do_something]\n        )\n\n    # # Event Handler types must match\n    with pytest.raises(EventHandlerArgTypeMismatchError):\n        component2.create(\n            on_user_visited_count_changed=test_state.do_something_with_bool\n        )\n    with pytest.raises(EventHandlerArgTypeMismatchError):\n        component2.create(on_user_list_changed=test_state.do_something_with_int)\n    with pytest.raises(EventHandlerArgTypeMismatchError):\n        component2.create(on_user_list_changed=test_state.do_something_with_list_int)\n    with pytest.raises(EventHandlerArgTypeMismatchError):\n        component2.create(\n            on_user_visited_count_changed=test_state.do_something_with_bool()\n        )\n    with pytest.raises(EventHandlerArgTypeMismatchError):\n        component2.create(on_user_list_changed=test_state.do_something_with_int())\n    with pytest.raises(EventHandlerArgTypeMismatchError):\n        component2.create(on_user_list_changed=test_state.do_something_with_list_int())\n\n    component2.create(\n        on_user_visited_count_changed=test_state.do_something_with_bool(False)\n    )\n    component2.create(on_user_list_changed=test_state.do_something_with_int(23))\n    component2.create(\n        on_user_list_changed=test_state.do_something_with_list_int([2321, 321])\n    )\n\n    component2.create(on_open=test_state.do_something_with_int)\n    component2.create(on_open=test_state.do_something_with_bool)\n    component2.create(on_user_visited_count_changed=test_state.do_something_with_int)\n    component2.create(on_user_list_changed=test_state.do_something_with_list_str)\n\n    # lambda cannot return weird values.\n    with pytest.raises(ValueError):\n        component2.create(on_blur=lambda: 1)\n    with pytest.raises(ValueError):\n        component2.create(on_blur=lambda: [1])\n    with pytest.raises(ValueError):\n        component2.create(\n            on_blur=lambda: (test_state.do_something_arg(1), test_state.do_something)\n        )\n\n    # lambda signature must match event trigger.\n    with pytest.raises(EventFnArgMismatchError):\n        component2.create(on_blur=lambda _: test_state.do_something_arg(1))\n\n    # lambda returning EventHandler must match spec\n    with pytest.raises(EventFnArgMismatchError):\n        component2.create(on_blur=lambda: test_state.do_something_arg)\n\n    # Mixed EventSpec and EventHandler must match spec.\n    with pytest.raises(EventFnArgMismatchError):\n        component2.create(\n            on_blur=lambda: [\n                test_state.do_something_arg(1),\n                test_state.do_something_arg,\n            ]\n        )\n\n\ndef test_valid_event_handler_args(component2, test_state: type[TestState]):\n    \"\"\"Test that an valid event handler args do not raise exception.\n\n    Args:\n        component2: A test component.\n        test_state: A test state.\n    \"\"\"\n    # Uncontrolled event handlers should not take args.\n    component2.create(on_blur=test_state.do_something)\n    component2.create(on_blur=test_state.do_something_arg(1))\n\n    # Does not raise because event handlers are allowed to have less args than the spec.\n    component2.create(on_open=test_state.do_something)\n    component2.create(on_prop_event=test_state.do_something)\n\n    # Does not raise because event handlers can have optional args.\n    component2.create(\n        on_user_visited_count_changed=test_state.do_something_required_optional\n    )\n    component2.create(on_two_args=test_state.do_something_required_optional)\n\n    # Controlled event handlers should take args.\n    component2.create(on_open=test_state.do_something_arg)\n    component2.create(on_prop_event=test_state.do_something_arg)\n\n    # Using a partial event spec bypasses arg validation (ignoring the args).\n    component2.create(on_open=test_state.do_something())\n    component2.create(on_prop_event=test_state.do_something())\n\n    # Multiple EventHandler args: all must match\n    component2.create(on_open=[test_state.do_something_arg, test_state.do_something])\n    component2.create(\n        on_prop_event=[test_state.do_something_arg, test_state.do_something]\n    )\n\n    # lambda returning EventHandler is okay if the spec matches.\n    component2.create(on_blur=lambda: test_state.do_something)\n    component2.create(on_open=lambda _: test_state.do_something_arg)\n    component2.create(on_prop_event=lambda _: test_state.do_something_arg)\n    component2.create(on_open=lambda: test_state.do_something)\n    component2.create(on_prop_event=lambda: test_state.do_something)\n    component2.create(on_open=lambda _: test_state.do_something)\n    component2.create(on_prop_event=lambda _: test_state.do_something)\n\n    # lambda can always return an EventSpec.\n    component2.create(on_blur=lambda: test_state.do_something_arg(1))\n    component2.create(on_open=lambda _: test_state.do_something_arg(1))\n    component2.create(on_prop_event=lambda _: test_state.do_something_arg(1))\n\n    # Return EventSpec and EventHandler (no arg).\n    component2.create(\n        on_blur=lambda: [test_state.do_something_arg(1), test_state.do_something]\n    )\n    component2.create(\n        on_blur=lambda: [test_state.do_something_arg(1), test_state.do_something()]\n    )\n\n    # Return 2 EventSpec.\n    component2.create(\n        on_open=lambda _: [test_state.do_something_arg(1), test_state.do_something()]\n    )\n    component2.create(\n        on_prop_event=lambda _: [\n            test_state.do_something_arg(1),\n            test_state.do_something(),\n        ]\n    )\n\n    # Return EventHandler (1 arg) and EventSpec.\n    component2.create(\n        on_open=lambda _: [test_state.do_something_arg, test_state.do_something()]\n    )\n    component2.create(\n        on_prop_event=lambda _: [test_state.do_something_arg, test_state.do_something()]\n    )\n    component2.create(\n        on_open=lambda _: [test_state.do_something_arg(1), test_state.do_something]\n    )\n    component2.create(\n        on_prop_event=lambda _: [\n            test_state.do_something_arg(1),\n            test_state.do_something,\n        ]\n    )\n\n\ndef test_get_hooks_nested(component1, component2, component3):\n    \"\"\"Test that a component returns hooks from child components.\n\n    Args:\n        component1: test component.\n        component2: another component.\n        component3: component with hooks defined.\n    \"\"\"\n    c = component1.create(\n        component2.create(arr=[]),\n        component3.create(),\n        component3.create(),\n        component3.create(),\n        text=\"a\",\n        number=1,\n    )\n    assert c._get_all_hooks() == component3.create()._get_all_hooks()\n\n\ndef test_get_hooks_nested2(component3, component4):\n    \"\"\"Test that a component returns both when parent and child have hooks.\n\n    Args:\n        component3: component with hooks defined.\n        component4: component with different hooks defined.\n    \"\"\"\n    exp_hooks = {\n        **component3.create()._get_all_hooks(),\n        **component4.create()._get_all_hooks(),\n    }\n    assert component3.create(component4.create())._get_all_hooks() == exp_hooks\n    assert component4.create(component3.create())._get_all_hooks() == exp_hooks\n    assert (\n        component4.create(\n            component3.create(),\n            component4.create(),\n            component3.create(),\n        )._get_all_hooks()\n        == exp_hooks\n    )\n\n\n@pytest.mark.parametrize(\"fixture\", [\"component5\", \"component6\"])\ndef test_unsupported_child_components(fixture, request):\n    \"\"\"Test that a value error is raised when an unsupported component (a child component found in the\n    component's invalid children list) is provided as a child.\n\n    Args:\n        fixture: the test component as a fixture.\n        request: Pytest request.\n    \"\"\"\n    component = request.getfixturevalue(fixture)\n    with pytest.raises(ValueError) as err:\n        comp = component.create(rx.text(\"testing component\"))\n        comp.render()\n    assert (\n        err.value.args[0]\n        == f\"The component `{component.__name__}` cannot have `Text` as a child component\"\n    )\n\n\ndef test_unsupported_parent_components(component5):\n    \"\"\"Test that a value error is raised when an component is not in _valid_parents of one of its children.\n\n    Args:\n        component5: component with valid parent of \"Text\" only\n    \"\"\"\n    with pytest.raises(ValueError) as err:\n        rx.box(component5.create())\n    assert (\n        err.value.args[0]\n        == f\"The component `{component5.__name__}` can only be a child of the components: `{component5._valid_parents[0]}`. Got `Box` instead.\"\n    )\n\n\n@pytest.mark.parametrize(\"fixture\", [\"component5\", \"component7\"])\ndef test_component_with_only_valid_children(fixture, request):\n    \"\"\"Test that a value error is raised when an unsupported component (a child component not found in the\n    component's valid children list) is provided as a child.\n\n    Args:\n        fixture: the test component as a fixture.\n        request: Pytest request.\n    \"\"\"\n    component = request.getfixturevalue(fixture)\n    with pytest.raises(ValueError) as err:\n        comp = component.create(rx.box(\"testing component\"))\n        comp.render()\n    assert (\n        err.value.args[0]\n        == f\"The component `{component.__name__}` only allows the components: `Text` as children. \"\n        f\"Got `Box` instead.\"\n    )\n\n\n@pytest.mark.parametrize(\n    (\"component\", \"rendered\"),\n    [\n        (rx.text(\"hi\"), 'jsx(RadixThemesText,{as:\"p\"},\"hi\")'),\n        (\n            rx.box(rx.heading(\"test\", size=\"3\")),\n            'jsx(RadixThemesBox,{},jsx(RadixThemesHeading,{size:\"3\"},\"test\"))',\n        ),\n    ],\n)\ndef test_format_component(component, rendered):\n    \"\"\"Test that a component is formatted correctly.\n\n    Args:\n        component: The component to format.\n        rendered: The expected rendered component.\n    \"\"\"\n    assert str(component) == rendered\n\n\ndef test_stateful_component(test_state: type[TestState]):\n    \"\"\"Test that a stateful component is created correctly.\n\n    Args:\n        test_state: A test state.\n    \"\"\"\n    text_component = rx.text(test_state.num)\n    stateful_component = StatefulComponent.compile_from(text_component)\n    assert isinstance(stateful_component, StatefulComponent)\n    assert stateful_component.tag is not None\n    assert stateful_component.tag.startswith(\"Text_\")\n    assert stateful_component.references == 1\n    sc2 = StatefulComponent.compile_from(rx.text(test_state.num))\n    assert isinstance(sc2, StatefulComponent)\n    assert stateful_component.references == 2\n    assert sc2.references == 2\n\n\ndef test_stateful_component_memoize_event_trigger(test_state: type[TestState]):\n    \"\"\"Test that a stateful component is created correctly with events.\n\n    Args:\n        test_state: A test state.\n    \"\"\"\n    button_component = rx.button(\"Click me\", on_blur=test_state.do_something)\n    stateful_component = StatefulComponent.compile_from(button_component)\n    assert isinstance(stateful_component, StatefulComponent)\n\n    # No event trigger? No StatefulComponent\n    assert not isinstance(\n        StatefulComponent.compile_from(rx.button(\"Click me\")), StatefulComponent\n    )\n\n\ndef test_stateful_banner():\n    \"\"\"Test that a stateful component is created correctly with events.\"\"\"\n    connection_modal_component = rx.connection_modal()\n    stateful_component = StatefulComponent.compile_from(connection_modal_component)\n    assert isinstance(stateful_component, StatefulComponent)\n\n\nTEST_VAR = LiteralVar.create(\"p\")._replace(\n    merge_var_data=VarData(\n        hooks={\"useTest\": None},\n        imports={\"test\": [ImportVar(tag=\"p\")]},\n        state=\"Test\",\n    )\n)\nFORMATTED_TEST_VAR = LiteralVar.create(f\"foo{TEST_VAR}bar\")\nSTYLE_VAR = TEST_VAR._replace(_js_expr=\"style\")\nEVENT_CHAIN_VAR = TEST_VAR.to(EventChain)\nARG_VAR = Var(_js_expr=\"arg\")\n\nTEST_VAR_DICT_OF_DICT = LiteralVar.create({\"a\": {\"b\": \"p\"}})._replace(\n    merge_var_data=TEST_VAR._var_data\n)\nFORMATTED_TEST_VAR_DICT_OF_DICT = LiteralVar.create({\"a\": {\"b\": \"foopbar\"}})._replace(\n    merge_var_data=TEST_VAR._var_data\n)\n\nTEST_VAR_LIST_OF_LIST = LiteralVar.create([[\"p\"]])._replace(\n    merge_var_data=TEST_VAR._var_data\n)\nFORMATTED_TEST_VAR_LIST_OF_LIST = LiteralVar.create([[\"foopbar\"]])._replace(\n    merge_var_data=TEST_VAR._var_data\n)\n\nTEST_VAR_LIST_OF_LIST_OF_LIST = LiteralVar.create([[[\"p\"]]])._replace(\n    merge_var_data=TEST_VAR._var_data\n)\nFORMATTED_TEST_VAR_LIST_OF_LIST_OF_LIST = LiteralVar.create([[[\"foopbar\"]]])._replace(\n    merge_var_data=TEST_VAR._var_data\n)\n\nTEST_VAR_LIST_OF_DICT = LiteralVar.create([{\"a\": \"p\"}])._replace(\n    merge_var_data=TEST_VAR._var_data\n)\nFORMATTED_TEST_VAR_LIST_OF_DICT = LiteralVar.create([{\"a\": \"foopbar\"}])._replace(\n    merge_var_data=TEST_VAR._var_data\n)\n\n\nclass ComponentNestedVar(Component):\n    \"\"\"A component with nested Var types.\"\"\"\n\n    dict_of_dict: Var[dict[str, dict[str, str]]]\n    list_of_list: Var[list[list[str]]]\n    list_of_list_of_list: Var[list[list[list[str]]]]\n    list_of_dict: Var[list[dict[str, str]]]\n\n\nclass EventState(rx.State):\n    \"\"\"State for testing event handlers with _get_vars.\"\"\"\n\n    v: int = 42\n\n    @rx.event\n    def handler(self):\n        \"\"\"A handler that does nothing.\"\"\"\n\n    def handler2(self, arg):\n        \"\"\"A handler that takes an arg.\n\n        Args:\n            arg: An arg.\n        \"\"\"\n\n\n@pytest.mark.parametrize(\n    (\"component\", \"exp_vars\"),\n    [\n        pytest.param(\n            Bare.create(TEST_VAR),\n            [TEST_VAR],\n            id=\"direct-bare\",\n        ),\n        pytest.param(\n            Bare.create(f\"foo{TEST_VAR}bar\"),\n            [FORMATTED_TEST_VAR],\n            id=\"fstring-bare\",\n        ),\n        pytest.param(\n            rx.text(as_=TEST_VAR),\n            [TEST_VAR],\n            id=\"direct-prop\",\n        ),\n        pytest.param(\n            rx.heading(as_=f\"foo{TEST_VAR}bar\"),\n            [FORMATTED_TEST_VAR],\n            id=\"fstring-prop\",\n        ),\n        pytest.param(\n            rx.fragment(id=TEST_VAR),\n            [TEST_VAR],\n            id=\"direct-id\",\n        ),\n        pytest.param(\n            rx.fragment(id=f\"foo{TEST_VAR}bar\"),\n            [FORMATTED_TEST_VAR],\n            id=\"fstring-id\",\n        ),\n        pytest.param(\n            rx.fragment(key=TEST_VAR),\n            [TEST_VAR],\n            id=\"direct-key\",\n        ),\n        pytest.param(\n            rx.fragment(key=f\"foo{TEST_VAR}bar\"),\n            [FORMATTED_TEST_VAR],\n            id=\"fstring-key\",\n        ),\n        pytest.param(\n            rx.fragment(class_name=TEST_VAR),\n            [TEST_VAR],\n            id=\"direct-class_name\",\n        ),\n        pytest.param(\n            rx.fragment(class_name=f\"foo{TEST_VAR}bar\"),\n            [FORMATTED_TEST_VAR],\n            id=\"fstring-class_name\",\n        ),\n        pytest.param(\n            rx.fragment(class_name=f\"foo{TEST_VAR}bar other-class\"),\n            [LiteralVar.create(f\"{FORMATTED_TEST_VAR} other-class\")],\n            id=\"fstring-dual-class_name\",\n        ),\n        pytest.param(\n            rx.fragment(class_name=[TEST_VAR, \"other-class\"]),\n            [Var.create([TEST_VAR, \"other-class\"]).join(\" \")],\n            id=\"fstring-dual-class_name\",\n        ),\n        pytest.param(\n            rx.fragment(special_props=[TEST_VAR]),\n            [TEST_VAR],\n            id=\"direct-special_props\",\n        ),\n        pytest.param(\n            rx.fragment(special_props=[LiteralVar.create(f\"foo{TEST_VAR}bar\")]),\n            [FORMATTED_TEST_VAR],\n            id=\"fstring-special_props\",\n        ),\n        pytest.param(\n            # custom_attrs cannot accept a Var directly as a value\n            rx.fragment(custom_attrs={\"href\": f\"{TEST_VAR}\"}),\n            [TEST_VAR],\n            id=\"fstring-custom_attrs-nofmt\",\n        ),\n        pytest.param(\n            rx.fragment(custom_attrs={\"href\": f\"foo{TEST_VAR}bar\"}),\n            [FORMATTED_TEST_VAR],\n            id=\"fstring-custom_attrs\",\n        ),\n        pytest.param(\n            rx.fragment(background_color=TEST_VAR),\n            [STYLE_VAR],\n            id=\"direct-background_color\",\n        ),\n        pytest.param(\n            rx.fragment(background_color=f\"foo{TEST_VAR}bar\"),\n            [STYLE_VAR],\n            id=\"fstring-background_color\",\n        ),\n        pytest.param(\n            rx.fragment(style={\"background_color\": TEST_VAR}),\n            [STYLE_VAR],\n            id=\"direct-style-background_color\",\n        ),\n        pytest.param(\n            rx.fragment(style={\"background_color\": f\"foo{TEST_VAR}bar\"}),\n            [STYLE_VAR],\n            id=\"fstring-style-background_color\",\n        ),\n        pytest.param(\n            rx.fragment(on_blur=EVENT_CHAIN_VAR),\n            [EVENT_CHAIN_VAR],\n            id=\"direct-event-chain\",\n        ),\n        pytest.param(\n            rx.fragment(on_blur=EventState.handler),\n            [],\n            id=\"direct-event-handler\",\n        ),\n        pytest.param(\n            rx.fragment(on_blur=EventState.handler2(TEST_VAR)),  # pyright: ignore [reportCallIssue]\n            [ARG_VAR, TEST_VAR],\n            id=\"direct-event-handler-arg\",\n        ),\n        pytest.param(\n            rx.fragment(on_blur=EventState.handler2(EventState.v)),  # pyright: ignore [reportCallIssue]\n            [ARG_VAR, EventState.v],\n            id=\"direct-event-handler-arg2\",\n        ),\n        pytest.param(\n            rx.fragment(on_blur=lambda: EventState.handler2(TEST_VAR)),  # pyright: ignore [reportCallIssue]\n            [ARG_VAR, TEST_VAR],\n            id=\"direct-event-handler-lambda\",\n        ),\n        pytest.param(\n            ComponentNestedVar.create(dict_of_dict={\"a\": {\"b\": TEST_VAR}}),\n            [TEST_VAR_DICT_OF_DICT],\n            id=\"direct-dict_of_dict\",\n        ),\n        pytest.param(\n            ComponentNestedVar.create(dict_of_dict={\"a\": {\"b\": f\"foo{TEST_VAR}bar\"}}),\n            [FORMATTED_TEST_VAR_DICT_OF_DICT],\n            id=\"fstring-dict_of_dict\",\n        ),\n        pytest.param(\n            ComponentNestedVar.create(list_of_list=[[TEST_VAR]]),\n            [TEST_VAR_LIST_OF_LIST],\n            id=\"direct-list_of_list\",\n        ),\n        pytest.param(\n            ComponentNestedVar.create(list_of_list=[[f\"foo{TEST_VAR}bar\"]]),\n            [FORMATTED_TEST_VAR_LIST_OF_LIST],\n            id=\"fstring-list_of_list\",\n        ),\n        pytest.param(\n            ComponentNestedVar.create(list_of_list_of_list=[[[TEST_VAR]]]),\n            [TEST_VAR_LIST_OF_LIST_OF_LIST],\n            id=\"direct-list_of_list_of_list\",\n        ),\n        pytest.param(\n            ComponentNestedVar.create(list_of_list_of_list=[[[f\"foo{TEST_VAR}bar\"]]]),\n            [FORMATTED_TEST_VAR_LIST_OF_LIST_OF_LIST],\n            id=\"fstring-list_of_list_of_list\",\n        ),\n        pytest.param(\n            ComponentNestedVar.create(list_of_dict=[{\"a\": TEST_VAR}]),\n            [TEST_VAR_LIST_OF_DICT],\n            id=\"direct-list_of_dict\",\n        ),\n        pytest.param(\n            ComponentNestedVar.create(list_of_dict=[{\"a\": f\"foo{TEST_VAR}bar\"}]),\n            [FORMATTED_TEST_VAR_LIST_OF_DICT],\n            id=\"fstring-list_of_dict\",\n        ),\n    ],\n)\ndef test_get_vars(component, exp_vars):\n    comp_vars = sorted(component._get_vars(), key=lambda v: v._js_expr)\n    assert len(comp_vars) == len(exp_vars)\n    print(comp_vars, exp_vars)\n    for comp_var, exp_var in zip(\n        comp_vars,\n        sorted(exp_vars, key=lambda v: v._js_expr),\n        strict=True,\n    ):\n        assert comp_var.equals(exp_var)\n\n\ndef test_instantiate_all_components():\n    \"\"\"Test that all components can be instantiated.\"\"\"\n    # These components all have required arguments and cannot be trivially instantiated.\n    untested_components = {\n        \"Card\",\n        \"Cond\",\n        \"DebounceInput\",\n        \"Foreach\",\n        \"FormControl\",\n        \"Html\",\n        \"Icon\",\n        \"Match\",\n        \"Markdown\",\n        \"MultiSelect\",\n        \"Option\",\n        \"Popover\",\n        \"Radio\",\n        \"Script\",\n        \"Tag\",\n        \"Tfoot\",\n        \"Thead\",\n    }\n    component_nested_list = [\n        *rx.RADIX_MAPPING.values(),\n        *rx.COMPONENTS_BASE_MAPPING.values(),\n        *rx.COMPONENTS_CORE_MAPPING.values(),\n    ]\n    for component_name in [\n        comp_name\n        for submodule_list in component_nested_list\n        for comp_name in submodule_list\n    ]:\n        if component_name in untested_components:\n            continue\n        component = getattr(\n            rx,\n            (\n                component_name\n                if not isinstance(component_name, tuple)\n                else component_name[1]\n            ),\n        )\n        if isinstance(component, type) and issubclass(component, Component):\n            component.create()\n\n\nclass InvalidParentComponent(Component):\n    \"\"\"Invalid Parent Component.\"\"\"\n\n\nclass ValidComponent1(Component):\n    \"\"\"Test valid component.\"\"\"\n\n    _valid_children = [\"ValidComponent2\"]\n\n\nclass ValidComponent2(Component):\n    \"\"\"Test valid component.\"\"\"\n\n\nclass ValidComponent3(Component):\n    \"\"\"Test valid component.\"\"\"\n\n    _valid_parents = [\"ValidComponent2\"]\n\n\nclass ValidComponent4(Component):\n    \"\"\"Test valid component.\"\"\"\n\n    _invalid_children = [\"InvalidComponent\"]\n\n\nclass InvalidComponent(Component):\n    \"\"\"Test invalid component.\"\"\"\n\n\nvalid_component1 = ValidComponent1.create\nvalid_component2 = ValidComponent2.create\ninvalid_component = InvalidComponent.create\nvalid_component3 = ValidComponent3.create\ninvalid_parent = InvalidParentComponent.create\nvalid_component4 = ValidComponent4.create\n\n\ndef test_validate_valid_children():\n    valid_component1(valid_component2())\n    valid_component1(\n        rx.fragment(valid_component2()),\n    )\n    valid_component1(\n        rx.fragment(\n            rx.fragment(\n                rx.fragment(valid_component2()),\n            ),\n        ),\n    )\n\n    valid_component1(\n        rx.cond(\n            True,\n            rx.fragment(valid_component2()),\n            rx.fragment(\n                rx.foreach(LiteralVar.create([1, 2, 3]), lambda x: valid_component2(x))\n            ),\n        )\n    )\n\n    valid_component1(\n        rx.cond(\n            True,\n            valid_component2(),\n            rx.fragment(\n                rx.match(\n                    \"condition\",\n                    (\"first\", valid_component2()),\n                    rx.fragment(valid_component2(rx.text(\"default\"))),\n                )\n            ),\n        )\n    )\n\n    valid_component1(\n        rx.match(\n            \"condition\",\n            (\"first\", valid_component2()),\n            (\"second\", \"third\", rx.fragment(valid_component2())),\n            (\n                \"fourth\",\n                rx.cond(True, valid_component2(), rx.fragment(valid_component2())),\n            ),\n            (\n                \"fifth\",\n                \"sixth\",\n                rx.match(\n                    \"nested_condition\",\n                    (\"nested_first\", valid_component2()),\n                    rx.fragment(valid_component2()),\n                ),\n            ),\n        )\n    )\n\n\ndef test_validate_valid_parents():\n    valid_component2(valid_component3())\n    valid_component2(\n        rx.fragment(valid_component3()),\n    )\n    valid_component1(\n        rx.fragment(\n            valid_component2(\n                rx.fragment(valid_component3()),\n            ),\n        ),\n    )\n\n    valid_component2(\n        rx.cond(\n            True,\n            rx.fragment(valid_component3()),\n            rx.fragment(\n                rx.foreach(\n                    LiteralVar.create([1, 2, 3]),\n                    lambda x: valid_component2(valid_component3(x)),\n                )\n            ),\n        )\n    )\n\n    valid_component2(\n        rx.cond(\n            True,\n            valid_component3(),\n            rx.fragment(\n                rx.match(\n                    \"condition\",\n                    (\"first\", valid_component3()),\n                    rx.fragment(valid_component3(rx.text(\"default\"))),\n                )\n            ),\n        )\n    )\n\n    valid_component2(\n        rx.match(\n            \"condition\",\n            (\"first\", valid_component3()),\n            (\"second\", \"third\", rx.fragment(valid_component3())),\n            (\n                \"fourth\",\n                rx.cond(True, valid_component3(), rx.fragment(valid_component3())),\n            ),\n            (\n                \"fifth\",\n                \"sixth\",\n                rx.match(\n                    \"nested_condition\",\n                    (\"nested_first\", valid_component3()),\n                    rx.fragment(valid_component3()),\n                ),\n            ),\n        )\n    )\n\n\ndef test_validate_invalid_children():\n    with pytest.raises(ValueError):\n        valid_component4(invalid_component())\n\n    with pytest.raises(ValueError):\n        valid_component4(\n            rx.fragment(invalid_component()),\n        )\n\n    with pytest.raises(ValueError):\n        rx.el.p(rx.el.p(\"what\"))\n\n    with pytest.raises(ValueError):\n        rx.el.p(rx.el.div(\"what\"))\n\n    with pytest.raises(ValueError):\n        rx.el.button(rx.el.button(\"what\"))\n\n    with pytest.raises(ValueError):\n        rx.el.p(rx.el.ol(rx.el.li(\"what\")))\n\n    with pytest.raises(ValueError):\n        rx.el.p(rx.el.ul(rx.el.li(\"what\")))\n\n    with pytest.raises(ValueError):\n        rx.el.a(rx.el.a(\"what\"))\n\n    with pytest.raises(ValueError):\n        valid_component2(\n            rx.fragment(\n                valid_component4(\n                    rx.fragment(invalid_component()),\n                ),\n            ),\n        )\n\n    with pytest.raises(ValueError):\n        valid_component4(\n            rx.cond(\n                True,\n                rx.fragment(invalid_component()),\n                rx.fragment(\n                    rx.foreach(\n                        LiteralVar.create([1, 2, 3]), lambda x: invalid_component(x)\n                    )\n                ),\n            )\n        )\n\n    with pytest.raises(ValueError):\n        valid_component4(\n            rx.cond(\n                True,\n                invalid_component(),\n                rx.fragment(\n                    rx.match(\n                        \"condition\",\n                        (\"first\", invalid_component()),\n                        rx.fragment(invalid_component(rx.text(\"default\"))),\n                    )\n                ),\n            )\n        )\n\n    with pytest.raises(ValueError):\n        valid_component4(\n            rx.match(\n                \"condition\",\n                (\"first\", invalid_component()),\n                (\"second\", \"third\", rx.fragment(invalid_component())),\n                (\n                    \"fourth\",\n                    rx.cond(True, invalid_component(), rx.fragment(valid_component2())),\n                ),\n                (\n                    \"fifth\",\n                    rx.match(\n                        \"nested_condition\",\n                        (\"nested_first\", invalid_component()),\n                        rx.fragment(invalid_component()),\n                    ),\n                    invalid_component(),\n                ),\n            )\n        )\n\n\ndef test_rename_props():\n    \"\"\"Test that _rename_props works and is inherited.\"\"\"\n\n    class C1(Component):\n        tag = \"C1\"\n\n        prop1: Var[str]\n        prop2: Var[str]\n\n        _rename_props = {\"prop1\": \"renamed_prop1\", \"prop2\": \"renamed_prop2\"}\n\n    class C2(C1):\n        tag = \"C2\"\n\n        prop3: Var[str]\n\n        _rename_props = {\"prop2\": \"subclass_prop2\", \"prop3\": \"renamed_prop3\"}\n\n    c1 = C1.create(prop1=\"prop1_1\", prop2=\"prop2_1\")\n    rendered_c1 = c1.render()\n    assert 'renamed_prop1:\"prop1_1\"' in rendered_c1[\"props\"]\n    assert 'renamed_prop2:\"prop2_1\"' in rendered_c1[\"props\"]\n\n    c2 = C2.create(prop1=\"prop1_2\", prop2=\"prop2_2\", prop3=\"prop3_2\")\n    rendered_c2 = c2.render()\n    assert 'renamed_prop1:\"prop1_2\"' in rendered_c2[\"props\"]\n    assert 'subclass_prop2:\"prop2_2\"' in rendered_c2[\"props\"]\n    assert 'renamed_prop3:\"prop3_2\"' in rendered_c2[\"props\"]\n\n\ndef test_custom_component_get_imports():\n    class Inner(Component):\n        tag = \"Inner\"\n        library = \"inner\"\n\n    class Other(Component):\n        tag = \"Other\"\n        library = \"other\"\n\n    @rx.memo\n    def wrapper():\n        return Inner.create()\n\n    @rx.memo\n    def outer(c: Component):\n        return Other.create(c)\n\n    custom_comp = wrapper()\n\n    # Inner is not imported directly, but it is imported by the custom component.\n    assert \"inner\" not in custom_comp._get_all_imports()\n    assert \"outer\" not in custom_comp._get_all_imports()\n\n    # The imports are only resolved during compilation.\n    custom_comp.get_component()\n    _, imports_inner = compile_custom_component(custom_comp)\n    assert \"inner\" in imports_inner\n    assert \"outer\" not in imports_inner\n\n    outer_comp = outer(c=wrapper())\n\n    # Libraries are not imported directly, but are imported by the custom component.\n    assert \"inner\" not in outer_comp._get_all_imports()\n    assert \"other\" not in outer_comp._get_all_imports()\n\n    # The imports are only resolved during compilation.\n    _, imports_outer = compile_custom_component(outer_comp)\n    assert \"inner\" not in imports_outer\n    assert \"other\" in imports_outer\n\n\ndef test_custom_component_declare_event_handlers_in_fields():\n    class ReferenceComponent(Component):\n        @classmethod\n        def get_event_triggers(cls) -> dict[str, Any]:\n            \"\"\"Test controlled triggers.\n\n            Returns:\n                Test controlled triggers.\n            \"\"\"\n            return {\n                **super().get_event_triggers(),\n                \"on_b\": input_event,\n                \"on_d\": no_args_event_spec,\n                \"on_e\": no_args_event_spec,\n            }\n\n    class TestComponent(Component):\n        on_b: EventHandler[input_event]\n        on_d: EventHandler[no_args_event_spec]\n        on_e: EventHandler\n\n    custom_component = ReferenceComponent.create()\n    test_component = TestComponent.create()\n    custom_triggers = custom_component.get_event_triggers()\n    test_triggers = test_component.get_event_triggers()\n    assert custom_triggers.keys() == test_triggers.keys()\n    for trigger_name in custom_component.get_event_triggers():\n        for v1, v2 in zip(\n            parse_args_spec(test_triggers[trigger_name])[0],\n            parse_args_spec(custom_triggers[trigger_name])[0],\n            strict=True,\n        ):\n            assert v1.equals(v2)\n\n\ndef test_invalid_event_trigger():\n    class TriggerComponent(Component):\n        on_push: Var[bool]\n\n        @classmethod\n        def get_event_triggers(cls) -> dict[str, Any]:\n            \"\"\"Test controlled triggers.\n\n            Returns:\n                Test controlled triggers.\n            \"\"\"\n            return {\n                **super().get_event_triggers(),\n                \"on_a\": no_args_event_spec,\n            }\n\n    trigger_comp = TriggerComponent.create\n\n    # test that these do not throw errors.\n    trigger_comp(on_push=True)\n    trigger_comp(on_a=rx.console_log(\"log\"))\n\n    with pytest.raises(ValueError):\n        trigger_comp(on_b=rx.console_log(\"log\"))\n\n\n@pytest.mark.parametrize(\n    \"tags\",\n    [\n        [\"Component\"],\n        [\"Component\", \"useState\"],\n        [ImportVar(tag=\"Component\")],\n        [ImportVar(tag=\"Component\"), ImportVar(tag=\"useState\")],\n        [\"Component\", ImportVar(tag=\"useState\")],\n    ],\n)\ndef test_component_add_imports(tags):\n    class BaseComponent(Component):\n        def _get_imports(self) -> ImportDict:  # pyright: ignore [reportIncompatibleMethodOverride]\n            return {}\n\n    class Reference(Component):\n        def _get_imports(self) -> ParsedImportDict:\n            return imports.merge_imports(\n                super()._get_imports(),\n                parse_imports({\"react\": tags}),\n                {\"foo\": [ImportVar(tag=\"bar\")]},\n            )\n\n    class TestBase(Component):\n        def add_imports(  # pyright: ignore [reportIncompatibleMethodOverride]\n            self,\n        ) -> dict[str, str | ImportVar | list[str] | list[ImportVar]]:\n            return {\"foo\": \"bar\"}\n\n    class Test(TestBase):\n        def add_imports(\n            self,\n        ) -> dict[str, str | ImportVar | list[str] | list[ImportVar]]:\n            return {\"react\": (tags[0] if len(tags) == 1 else tags)}\n\n    baseline = Reference.create()\n    test = Test.create()\n\n    assert baseline._get_all_imports() == parse_imports({\n        \"react\": tags,\n        \"foo\": [ImportVar(tag=\"bar\")],\n    })\n    assert test._get_all_imports() == baseline._get_all_imports()\n\n\ndef test_component_add_hooks():\n    class BaseComponent(Component):\n        def _get_hooks(self):\n            return \"const hook1 = 42\"\n\n    class ChildComponent1(BaseComponent):\n        pass\n\n    class GrandchildComponent1(ChildComponent1):\n        def add_hooks(self):  # pyright: ignore [reportIncompatibleMethodOverride]\n            return [\n                \"const hook2 = 43\",\n                \"const hook3 = 44\",\n            ]\n\n    class GreatGrandchildComponent1(GrandchildComponent1):\n        def add_hooks(self):\n            return [\n                \"const hook4 = 45\",\n            ]\n\n    class GrandchildComponent2(ChildComponent1):\n        def _get_hooks(self):  # pyright: ignore [reportIncompatibleMethodOverride]\n            return \"const hook5 = 46\"\n\n    class GreatGrandchildComponent2(GrandchildComponent2):\n        def add_hooks(self):  # pyright: ignore [reportIncompatibleMethodOverride]\n            return [\n                \"const hook2 = 43\",\n                \"const hook6 = 47\",\n            ]\n\n    assert list(BaseComponent.create()._get_all_hooks()) == [\"const hook1 = 42\"]\n    assert list(ChildComponent1.create()._get_all_hooks()) == [\"const hook1 = 42\"]\n    assert list(GrandchildComponent1.create()._get_all_hooks()) == [\n        \"const hook1 = 42\",\n        \"const hook2 = 43\",\n        \"const hook3 = 44\",\n    ]\n    assert list(GreatGrandchildComponent1.create()._get_all_hooks()) == [\n        \"const hook1 = 42\",\n        \"const hook2 = 43\",\n        \"const hook3 = 44\",\n        \"const hook4 = 45\",\n    ]\n    assert list(GrandchildComponent2.create()._get_all_hooks()) == [\"const hook5 = 46\"]\n    assert list(GreatGrandchildComponent2.create()._get_all_hooks()) == [\n        \"const hook5 = 46\",\n        \"const hook2 = 43\",\n        \"const hook6 = 47\",\n    ]\n    assert list(\n        BaseComponent.create(\n            GrandchildComponent1.create(GreatGrandchildComponent2.create()),\n            GreatGrandchildComponent1.create(),\n        )._get_all_hooks(),\n    ) == [\n        \"const hook1 = 42\",\n        \"const hook2 = 43\",\n        \"const hook3 = 44\",\n        \"const hook5 = 46\",\n        \"const hook6 = 47\",\n        \"const hook4 = 45\",\n    ]\n    assert list(\n        Fragment.create(\n            GreatGrandchildComponent2.create(),\n            GreatGrandchildComponent1.create(),\n        )._get_all_hooks()\n    ) == [\n        \"const hook5 = 46\",\n        \"const hook2 = 43\",\n        \"const hook6 = 47\",\n        \"const hook1 = 42\",\n        \"const hook3 = 44\",\n        \"const hook4 = 45\",\n    ]\n\n\ndef test_component_add_custom_code():\n    class BaseComponent(Component):\n        def _get_custom_code(self):\n            return \"const custom_code1 = 42\"\n\n    class ChildComponent1(BaseComponent):\n        pass\n\n    class GrandchildComponent1(ChildComponent1):\n        def add_custom_code(self):\n            return [\n                \"const custom_code2 = 43\",\n                \"const custom_code3 = 44\",\n            ]\n\n    class GreatGrandchildComponent1(GrandchildComponent1):\n        def add_custom_code(self):\n            return [\n                \"const custom_code4 = 45\",\n            ]\n\n    class GrandchildComponent2(ChildComponent1):\n        def _get_custom_code(self):  # pyright: ignore [reportIncompatibleMethodOverride]\n            return \"const custom_code5 = 46\"\n\n    class GreatGrandchildComponent2(GrandchildComponent2):\n        def add_custom_code(self):\n            return [\n                \"const custom_code2 = 43\",\n                \"const custom_code6 = 47\",\n            ]\n\n    assert BaseComponent.create()._get_all_custom_code() == {\n        \"const custom_code1 = 42\": None\n    }\n    assert ChildComponent1.create()._get_all_custom_code() == {\n        \"const custom_code1 = 42\": None\n    }\n    assert GrandchildComponent1.create()._get_all_custom_code() == {\n        \"const custom_code1 = 42\": None,\n        \"const custom_code2 = 43\": None,\n        \"const custom_code3 = 44\": None,\n    }\n    assert GreatGrandchildComponent1.create()._get_all_custom_code() == {\n        \"const custom_code1 = 42\": None,\n        \"const custom_code2 = 43\": None,\n        \"const custom_code3 = 44\": None,\n        \"const custom_code4 = 45\": None,\n    }\n    assert GrandchildComponent2.create()._get_all_custom_code() == {\n        \"const custom_code5 = 46\": None\n    }\n    assert GreatGrandchildComponent2.create()._get_all_custom_code() == {\n        \"const custom_code2 = 43\": None,\n        \"const custom_code5 = 46\": None,\n        \"const custom_code6 = 47\": None,\n    }\n    assert BaseComponent.create(\n        GrandchildComponent1.create(GreatGrandchildComponent2.create()),\n        GreatGrandchildComponent1.create(),\n    )._get_all_custom_code() == {\n        \"const custom_code1 = 42\": None,\n        \"const custom_code2 = 43\": None,\n        \"const custom_code3 = 44\": None,\n        \"const custom_code4 = 45\": None,\n        \"const custom_code5 = 46\": None,\n        \"const custom_code6 = 47\": None,\n    }\n    assert Fragment.create(\n        GreatGrandchildComponent2.create(),\n        GreatGrandchildComponent1.create(),\n    )._get_all_custom_code() == {\n        \"const custom_code1 = 42\": None,\n        \"const custom_code2 = 43\": None,\n        \"const custom_code3 = 44\": None,\n        \"const custom_code4 = 45\": None,\n        \"const custom_code5 = 46\": None,\n        \"const custom_code6 = 47\": None,\n    }\n\n\ndef test_component_add_hooks_var():\n    class HookComponent(Component):\n        def add_hooks(self):\n            return [\n                \"const hook3 = useRef(null)\",\n                \"const hook1 = 42\",\n                Var(\n                    _js_expr=\"useEffect(() => () => {}, [])\",\n                    _var_data=VarData(\n                        hooks={\n                            \"const hook2 = 43\": None,\n                            \"const hook3 = useRef(null)\": None,\n                        },\n                        imports={\"react\": [ImportVar(tag=\"useEffect\")]},\n                    ),\n                ),\n                Var(\n                    _js_expr=\"const hook3 = useRef(null)\",\n                    _var_data=VarData(imports={\"react\": [ImportVar(tag=\"useRef\")]}),\n                ),\n            ]\n\n    assert list(HookComponent.create()._get_all_hooks()) == [\n        \"const hook3 = useRef(null)\",\n        \"const hook1 = 42\",\n        \"const hook2 = 43\",\n        \"useEffect(() => () => {}, [])\",\n    ]\n    imports = HookComponent.create()._get_all_imports()\n    assert len(imports) == 1\n    assert \"react\" in imports\n    assert len(imports[\"react\"]) == 2\n    assert ImportVar(tag=\"useRef\") in imports[\"react\"]\n    assert ImportVar(tag=\"useEffect\") in imports[\"react\"]\n\n\ndef test_add_style_embedded_vars(test_state: type[TestState]):\n    \"\"\"Test that add_style works with embedded vars when returning a plain dict.\n\n    Args:\n        test_state: A test state.\n    \"\"\"\n    v0 = LiteralVar.create(\"parent\")._replace(\n        merge_var_data=VarData(hooks={\"useParent\": None}),\n    )\n    v1 = rx.color(\"plum\", 10)\n    v2 = LiteralVar.create(\"text\")._replace(\n        merge_var_data=VarData(hooks={\"useText\": None}),\n    )\n\n    class ParentComponent(Component):\n        def add_style(self):\n            return Style({\n                \"fake_parent\": v0,\n            })\n\n    class StyledComponent(ParentComponent):\n        tag = \"StyledComponent\"\n\n        def add_style(self):  # pyright: ignore [reportIncompatibleMethodOverride]\n            return {\n                \"color\": v1,\n                \"fake\": v2,\n                \"margin\": f\"{test_state.num}%\",\n            }\n\n    page = rx.vstack(StyledComponent.create())\n    page._add_style_recursive(Style())\n\n    assert (\n        f\"const {test_state.get_name()} = useContext(StateContexts.{test_state.get_name()})\"\n        in page._get_all_hooks_internal()\n    )\n    assert \"useText\" in page._get_all_hooks_internal()\n    assert \"useParent\" in page._get_all_hooks_internal()\n    assert (\n        str(page).count(\n            f'css:({{ [\"fakeParent\"] : \"parent\", [\"color\"] : \"var(--plum-10)\", [\"fake\"] : \"text\", [\"margin\"] : ({test_state.get_name()}.num{FIELD_MARKER}+\"%\") }})'\n        )\n        == 1\n    )\n\n\ndef test_add_style_foreach():\n    class StyledComponent(Component):\n        tag = \"StyledComponent\"\n        ix: Var[int]\n\n        def add_style(self):\n            return Style({\"color\": \"red\"})\n\n    page = rx.vstack(rx.foreach(Var.range(3), lambda i: StyledComponent.create(i)))\n    page._add_style_recursive(Style())\n\n    # Expect only a single child of the foreach on the python side\n    assert len(page.children[0].children) == 1\n\n    # Expect the style to be added to the child of the foreach\n    assert 'css:({ [\"color\"] : \"red\" })' in str(page.children[0].children[0])\n\n    # Expect only one instance of this CSS dict in the rendered page\n    assert str(page).count('css:({ [\"color\"] : \"red\" })') == 1\n\n\nclass TriggerState(rx.State):\n    \"\"\"Test state with event handlers.\"\"\"\n\n    @rx.event\n    def do_something(self):\n        \"\"\"Sample event handler.\"\"\"\n\n\n@pytest.mark.parametrize(\n    (\"component\", \"output\"),\n    [\n        (rx.box(rx.text(\"random text\")), False),\n        (\n            rx.box(rx.text(\"random text\", on_blur=rx.console_log(\"log\"))),\n            False,\n        ),\n        (\n            rx.box(\n                rx.text(\"random text\", on_blur=TriggerState.do_something),\n                rx.text(\n                    \"random text\",\n                    on_blur=Var(_js_expr=\"toggleColorMode\").to(EventChain),\n                ),\n            ),\n            True,\n        ),\n        (\n            rx.box(\n                rx.text(\"random text\", on_blur=rx.console_log(\"log\")),\n                rx.text(\n                    \"random text\",\n                    on_blur=Var(_js_expr=\"toggleColorMode\").to(EventChain),\n                ),\n            ),\n            False,\n        ),\n        (\n            rx.box(rx.text(\"random text\", on_blur=TriggerState.do_something)),\n            True,\n        ),\n        (\n            rx.box(\n                rx.text(\n                    \"random text\",\n                    on_blur=[rx.console_log(\"log\"), rx.window_alert(\"alert\")],\n                ),\n            ),\n            False,\n        ),\n        (\n            rx.box(\n                rx.text(\n                    \"random text\",\n                    on_blur=[rx.console_log(\"log\"), TriggerState.do_something],\n                ),\n            ),\n            True,\n        ),\n        (\n            rx.box(\n                rx.text(\n                    \"random text\",\n                    on_blur=lambda: TriggerState.do_something,\n                ),\n            ),\n            True,\n        ),\n    ],\n)\ndef test_has_state_event_triggers(component, output):\n    assert component._has_stateful_event_triggers() == output\n\n\nclass SpecialComponent(Box):\n    \"\"\"A special component with custom attributes.\"\"\"\n\n    data_prop: Var[str]\n    aria_prop: Var[str]\n\n\n@pytest.mark.parametrize(\n    (\"component_kwargs\", \"exp_custom_attrs\", \"exp_style\"),\n    [\n        (\n            {\"data_test\": \"test\", \"aria_test\": \"test\"},\n            {\"data-test\": \"test\", \"aria-test\": \"test\"},\n            {},\n        ),\n        (\n            {\"data-test\": \"test\", \"aria-test\": \"test\"},\n            {\"data-test\": \"test\", \"aria-test\": \"test\"},\n            {},\n        ),\n        (\n            {\"custom_attrs\": {\"data-existing\": \"test\"}, \"data_new\": \"test\"},\n            {\"data-existing\": \"test\", \"data-new\": \"test\"},\n            {},\n        ),\n        (\n            {\"data_test\": \"test\", \"data_prop\": \"prop\"},\n            {\"data-test\": \"test\"},\n            {},\n        ),\n        (\n            {\"aria_test\": \"test\", \"aria_prop\": \"prop\"},\n            {\"aria-test\": \"test\"},\n            {},\n        ),\n    ],\n)\ndef test_special_props(component_kwargs, exp_custom_attrs, exp_style):\n    \"\"\"Test that data_ and aria_ special props are correctly added to the component.\n\n    Args:\n        component_kwargs: The component kwargs.\n        exp_custom_attrs: The expected custom attributes.\n        exp_style: The expected style.\n    \"\"\"\n    component = SpecialComponent.create(**component_kwargs)\n    assert component.custom_attrs == exp_custom_attrs\n    assert component.style == exp_style\n    for prop in SpecialComponent.get_props():\n        if prop in component_kwargs:\n            assert getattr(component, prop)._var_value == component_kwargs[prop]\n\n\ndef test_ref():\n    \"\"\"Test that the ref prop is correctly added to the component.\"\"\"\n    custom_ref = Var(\"custom_ref\")\n    ref_component = rx.box(ref=custom_ref)\n    assert ref_component._render().props[\"ref\"].equals(custom_ref)\n\n    id_component = rx.box(id=\"custom_id\")\n    assert id_component._render().props[\"ref\"].equals(Var(\"ref_custom_id\"))\n\n    assert \"ref\" not in rx.box()._render().props\n"
  },
  {
    "path": "tests/units/components/test_component_future_annotations.py",
    "content": "from __future__ import annotations\n\nfrom typing import Any\n\nfrom reflex.components.component import Component\nfrom reflex.event import EventHandler, input_event, no_args_event_spec\n\n\n# This is a repeat of its namesake in test_component.py.\ndef test_custom_component_declare_event_handlers_in_fields():\n    class ReferenceComponent(Component):\n        @classmethod\n        def get_event_triggers(cls) -> dict[str, Any]:\n            \"\"\"Test controlled triggers.\n\n            Returns:\n                Test controlled triggers.\n            \"\"\"\n            return {\n                **super().get_event_triggers(),\n                \"on_a\": lambda e: [e],\n                \"on_b\": lambda e: [e.target.value],\n                \"on_c\": lambda e: [],\n                \"on_d\": no_args_event_spec,\n            }\n\n    class TestComponent(Component):\n        on_a: EventHandler[lambda e0: [e0]]\n        on_b: EventHandler[input_event]\n        on_c: EventHandler[no_args_event_spec]\n        on_d: EventHandler[no_args_event_spec]\n\n    custom_component = ReferenceComponent.create()\n    test_component = TestComponent.create()\n    assert (\n        custom_component.get_event_triggers().keys()\n        == test_component.get_event_triggers().keys()\n    )\n"
  },
  {
    "path": "tests/units/components/test_component_state.py",
    "content": "\"\"\"Ensure that Components returned by ComponentState.create have independent State classes.\"\"\"\n\nimport pytest\n\nimport reflex as rx\nfrom reflex.components.base.bare import Bare\nfrom reflex.utils.exceptions import ReflexRuntimeError\n\n\ndef test_component_state():\n    \"\"\"Create two components with independent state classes.\"\"\"\n\n    class CS(rx.ComponentState):\n        count: int = 0\n\n        def increment(self):\n            self.count += 1\n\n        @classmethod\n        def get_component(cls, *children, **props):\n            return rx.el.div(\n                *children,\n                **props,\n            )\n\n    cs1, cs2 = CS.create(\"a\", id=\"a\"), CS.create(\"b\", id=\"b\")\n    assert isinstance(cs1, rx.Component)\n    assert isinstance(cs2, rx.Component)\n    assert cs1.State is not None\n    assert cs2.State is not None\n    assert cs1.State != cs2.State\n    assert issubclass(cs1.State, CS)\n    assert issubclass(cs1.State, rx.State)\n    assert issubclass(cs2.State, CS)\n    assert issubclass(cs2.State, rx.State)\n    assert CS._per_component_state_instance_count == 2\n    assert isinstance(cs1.State.increment, rx.event.EventHandler)\n    assert cs1.State.increment != cs2.State.increment\n\n    assert len(cs1.children) == 1\n    assert cs1.children[0].render() == Bare.create(\"a\").render()\n    assert cs1.id == \"a\"\n    assert len(cs2.children) == 1\n    assert cs2.children[0].render() == Bare.create(\"b\").render()\n    assert cs2.id == \"b\"\n\n\ndef test_init_component_state() -> None:\n    \"\"\"Ensure that ComponentState subclasses cannot be instantiated directly.\"\"\"\n\n    class CS(rx.ComponentState):\n        @classmethod\n        def get_component(cls, *children, **props):\n            return rx.el.div()\n\n    with pytest.raises(ReflexRuntimeError):\n        CS()\n\n    class SubCS(CS):\n        pass\n\n    with pytest.raises(ReflexRuntimeError):\n        SubCS()\n"
  },
  {
    "path": "tests/units/components/test_props.py",
    "content": "from __future__ import annotations\n\nimport pytest\n\nfrom reflex.components.props import NoExtrasAllowedProps, PropsBase\nfrom reflex.event import (\n    EventChain,\n    EventHandler,\n    event,\n    no_args_event_spec,\n    passthrough_event_spec,\n)\nfrom reflex.state import State\nfrom reflex.utils.exceptions import InvalidPropValueError\n\n\nclass PropA(NoExtrasAllowedProps):\n    \"\"\"Base prop class.\"\"\"\n\n    foo: str\n    bar: str\n\n\nclass PropB(NoExtrasAllowedProps):\n    \"\"\"Prop class with nested props.\"\"\"\n\n    foobar: str\n    foobaz: PropA\n\n\n@pytest.mark.parametrize(\n    (\"props_class\", \"kwargs\", \"should_raise\"),\n    [\n        (PropA, {\"foo\": \"value\", \"bar\": \"another_value\"}, False),\n        (PropA, {\"fooz\": \"value\", \"bar\": \"another_value\"}, True),\n        (\n            PropB,\n            {\n                \"foobaz\": {\"foo\": \"value\", \"bar\": \"another_value\"},\n                \"foobar\": \"foo_bar_value\",\n            },\n            False,\n        ),\n        (\n            PropB,\n            {\n                \"fooba\": {\"foo\": \"value\", \"bar\": \"another_value\"},\n                \"foobar\": \"foo_bar_value\",\n            },\n            True,\n        ),\n        (\n            PropB,\n            {\n                \"foobaz\": {\"foobar\": \"value\", \"bar\": \"another_value\"},\n                \"foobar\": \"foo_bar_value\",\n            },\n            True,\n        ),\n    ],\n)\ndef test_no_extras_allowed_props(props_class, kwargs, should_raise):\n    if should_raise:\n        with pytest.raises(InvalidPropValueError):\n            props_class(**kwargs)\n    else:\n        props_instance = props_class(**kwargs)\n        assert isinstance(props_instance, props_class)\n\n\n# Test class definitions - reused across tests\nclass MixedCaseProps(PropsBase):\n    \"\"\"Test props with mixed naming conventions.\"\"\"\n\n    # Single word (no case conversion needed)\n    name: str\n    # Already camelCase (should stay unchanged)\n    fontSize: int = 12\n    # snake_case (should convert to camelCase)\n    max_length: int = 100\n    is_active: bool = True\n\n\nclass NestedProps(PropsBase):\n    \"\"\"Test props for nested PropsBase testing.\"\"\"\n\n    user_name: str\n    max_count: int = 10\n\n\nclass ParentProps(PropsBase):\n    \"\"\"Test props containing nested PropsBase objects.\"\"\"\n\n    title: str\n    nested_config: NestedProps\n    is_enabled: bool = True\n\n\nclass OptionalFieldProps(PropsBase):\n    \"\"\"Test props with optional fields to test omission behavior.\"\"\"\n\n    required_field: str\n    optional_snake_case: str | None = None\n    optionalCamelCase: int | None = None\n\n\n@pytest.mark.parametrize(\n    (\"props_class\", \"props_kwargs\", \"expected_dict\"),\n    [\n        # Test single word + snake_case conversion\n        (\n            MixedCaseProps,\n            {\"name\": \"test\", \"max_length\": 50},\n            {\"name\": \"test\", \"fontSize\": 12, \"maxLength\": 50, \"isActive\": True},\n        ),\n        # Test existing camelCase stays unchanged + snake_case converts\n        (\n            MixedCaseProps,\n            {\"name\": \"demo\", \"fontSize\": 16, \"is_active\": False},\n            {\"name\": \"demo\", \"fontSize\": 16, \"maxLength\": 100, \"isActive\": False},\n        ),\n        # Test all different case types together\n        (\n            MixedCaseProps,\n            {\"name\": \"full\", \"fontSize\": 20, \"max_length\": 200, \"is_active\": False},\n            {\"name\": \"full\", \"fontSize\": 20, \"maxLength\": 200, \"isActive\": False},\n        ),\n        # Test nested PropsBase conversion\n        (\n            ParentProps,\n            {\n                \"title\": \"parent\",\n                \"nested_config\": NestedProps(user_name=\"nested_user\", max_count=5),\n            },\n            {\n                \"title\": \"parent\",\n                \"nestedConfig\": {\"userName\": \"nested_user\", \"maxCount\": 5},\n                \"isEnabled\": True,\n            },\n        ),\n        # Test nested with different values\n        (\n            ParentProps,\n            {\n                \"title\": \"test\",\n                \"nested_config\": NestedProps(user_name=\"test_user\"),\n                \"is_enabled\": False,\n            },\n            {\n                \"title\": \"test\",\n                \"nestedConfig\": {\"userName\": \"test_user\", \"maxCount\": 10},\n                \"isEnabled\": False,\n            },\n        ),\n        # Test omitted optional fields appear with None values\n        (\n            OptionalFieldProps,\n            {\"required_field\": \"present\"},\n            {\n                \"requiredField\": \"present\",\n            },\n        ),\n        # Test explicit None values for optional fields\n        (\n            OptionalFieldProps,\n            {\n                \"required_field\": \"test\",\n                \"optional_snake_case\": None,\n                \"optionalCamelCase\": 42,\n            },\n            {\n                \"requiredField\": \"test\",\n                \"optionalCamelCase\": 42,\n            },\n        ),\n    ],\n)\ndef test_props_base_dict_conversion(props_class, props_kwargs, expected_dict):\n    \"\"\"Test that dict() handles different naming conventions correctly for both simple and nested props.\n\n    Args:\n        props_class: The PropsBase class to test.\n        props_kwargs: The keyword arguments to pass to the class constructor.\n        expected_dict: The expected dictionary output with camelCase keys.\n    \"\"\"\n    props = props_class(**props_kwargs)\n    result = props.dict()\n    assert result == expected_dict\n\n\nclass EventProps(PropsBase):\n    \"\"\"Test props with event handler fields.\"\"\"\n\n    on_click: EventHandler[no_args_event_spec]\n    not_start_with_on: EventHandler[passthrough_event_spec(str)]\n\n\ndef test_event_handler_props():\n    class FooState(State):\n        @event\n        def handle_click(self):\n            pass\n\n        @event\n        def handle_input(self, value: str):\n            pass\n\n    props = EventProps(\n        on_click=FooState.handle_click,  # pyright: ignore[reportArgumentType]\n        not_start_with_on=FooState.handle_input,  # pyright: ignore[reportArgumentType]\n    )\n    props_dict = props.dict()\n    assert isinstance(props_dict[\"onClick\"], EventChain)\n    assert isinstance(props_dict[\"notStartWithOn\"], EventChain)\n"
  },
  {
    "path": "tests/units/components/test_tag.py",
    "content": "import pytest\n\nfrom reflex.components.tags import CondTag, Tag, tagless\nfrom reflex.vars.base import LiteralVar, Var\n\n\n@pytest.mark.parametrize(\n    (\"props\", \"test_props\"),\n    [\n        ({}, []),\n        ({\"key-hyphen\": 1}, ['\"key-hyphen\":1']),\n        ({\"key\": 1}, [\"key:1\"]),\n        ({\"key\": \"value\"}, ['key:\"value\"']),\n        ({\"key\": True, \"key2\": \"value2\"}, [\"key:true\", 'key2:\"value2\"']),\n    ],\n)\ndef test_format_props(props: dict[str, Var], test_props: list):\n    \"\"\"Test that the formatted props are correct.\n\n    Args:\n        props: The props to test.\n        test_props: The expected props.\n    \"\"\"\n    tag_props = Tag(props=props).format_props()\n    for i, tag_prop in enumerate(tag_props):\n        assert tag_prop == test_props[i]\n\n\n@pytest.mark.parametrize(\n    (\"prop\", \"valid\"),\n    [\n        (1, True),\n        (3.15, True),\n        (\"string\", True),\n        (False, True),\n        ([], True),\n        ({}, False),\n        (None, False),\n    ],\n)\ndef test_is_valid_prop(prop: Var, valid: bool):\n    \"\"\"Test that the prop is valid.\n\n    Args:\n        prop: The prop to test.\n        valid: The expected validity of the prop.\n    \"\"\"\n    assert Tag.is_valid_prop(prop) == valid\n\n\ndef test_add_props():\n    \"\"\"Test that the props are added.\"\"\"\n    tag = Tag().add_props(key=\"value\", key2=42, invalid=None, invalid2={})\n    assert tag.props[\"key\"].equals(LiteralVar.create(\"value\"))\n    assert tag.props[\"key2\"].equals(LiteralVar.create(42))\n    assert \"invalid\" not in tag.props\n    assert \"invalid2\" not in tag.props\n\n\n@pytest.mark.parametrize(\n    (\"tag\", \"expected\"),\n    [\n        (\n            Tag(),\n            {\n                \"name\": \"\",\n                \"children\": [],\n                \"props\": [],\n            },\n        ),\n        (\n            Tag(name=\"br\"),\n            {\n                \"name\": \"br\",\n                \"children\": [],\n                \"props\": [],\n            },\n        ),\n        (\n            tagless.Tagless(contents=\"hello\"),\n            {\n                \"contents\": \"hello\",\n            },\n        ),\n        (\n            Tag(name=\"box\", props={\"color\": \"red\", \"textAlign\": \"center\"}),\n            {\n                \"name\": \"box\",\n                \"children\": [],\n                \"props\": ['color:\"red\"', 'textAlign:\"center\"'],\n            },\n        ),\n    ],\n)\ndef test_format_tag(tag: Tag, expected: dict):\n    \"\"\"Test that the tag dict is correct.\n\n    Args:\n        tag: The tag to test.\n        expected: The expected tag dictionary.\n    \"\"\"\n    tag_dict = dict(tag)\n    assert tag_dict == expected\n\n\ndef test_format_cond_tag():\n    \"\"\"Test that the cond tag dict is correct.\"\"\"\n    tag = CondTag(\n        cond_state=\"logged_in\",\n        true_value=dict(tagless.Tagless(contents=\"True content\")),\n        false_value=dict(tagless.Tagless(contents=\"False content\")),\n    )\n    tag_dict = dict(tag)\n    cond_state, true_value, false_value = (\n        tag_dict[\"cond_state\"],\n        tag_dict[\"true_value\"],\n        tag_dict[\"false_value\"],\n    )\n    assert cond_state == \"logged_in\"\n\n    assert true_value[\"contents\"] == \"True content\"\n\n    assert false_value[\"contents\"] == \"False content\"\n\n\ndef test_tagless_string_representation():\n    \"\"\"Test that the string representation of a tagless is correct.\"\"\"\n    tag = tagless.Tagless(contents=\"Hello world\")\n    expected_output = \"Hello world\"\n    assert str(tag) == expected_output\n"
  },
  {
    "path": "tests/units/components/typography/__init__.py",
    "content": ""
  },
  {
    "path": "tests/units/components/typography/test_markdown.py",
    "content": "import pytest\n\nimport reflex as rx\nfrom reflex.components.markdown.markdown import Markdown\n\n\n@pytest.mark.parametrize(\n    (\"tag\", \"expected\"),\n    [\n        (\"h1\", \"Heading\"),\n        (\"h2\", \"Heading\"),\n        (\"h3\", \"Heading\"),\n        (\"h4\", \"Heading\"),\n        (\"h5\", \"Heading\"),\n        (\"h6\", \"Heading\"),\n        (\"p\", \"Text\"),\n        (\"ul\", \"ul\"),\n        (\"ol\", \"ol\"),\n        (\"li\", \"li\"),\n        (\"a\", \"Link\"),\n        (\"code\", \"Code\"),\n    ],\n)\ndef test_get_component(tag, expected):\n    \"\"\"Test getting a component from the component map.\n\n    Args:\n        tag: The tag to get.\n        expected: The expected component.\n    \"\"\"\n    md = Markdown.create(\"# Hello\")\n    assert tag in md.component_map  # pyright: ignore [reportAttributeAccessIssue]\n    assert md.get_component(tag).tag == expected\n\n\ndef test_set_component_map():\n    \"\"\"Test setting the component map.\"\"\"\n    component_map = {\n        \"h1\": lambda value: rx.box(rx.heading(value, as_=\"h1\"), padding=\"1em\"),\n        \"p\": lambda value: rx.box(rx.text(value), padding=\"1em\"),\n    }\n    md = Markdown.create(\"# Hello\", component_map=component_map)\n\n    # Check that the new tags have been added.\n    assert md.get_component(\"h1\").tag == \"Box\"\n    assert md.get_component(\"p\").tag == \"Box\"\n\n    # Make sure the old tags are still there.\n    assert md.get_component(\"h2\").tag == \"Heading\"\n"
  },
  {
    "path": "tests/units/conftest.py",
    "content": "\"\"\"Test fixtures.\"\"\"\n\nimport platform\nimport uuid\nfrom collections.abc import Generator\nfrom unittest import mock\n\nimport pytest\n\nfrom reflex.app import App\nfrom reflex.event import EventSpec\nfrom reflex.model import ModelRegistry\nfrom reflex.testing import chdir\nfrom reflex.utils import prerequisites\n\nfrom .states.upload import SubUploadState, UploadState\n\n\n@pytest.fixture\ndef app() -> App:\n    \"\"\"A base app.\n\n    Returns:\n        The app.\n    \"\"\"\n    return App()\n\n\n@pytest.fixture\ndef app_module_mock(monkeypatch) -> mock.Mock:\n    \"\"\"Mock the app module.\n\n    This overwrites prerequisites.get_app to return the mock for the app module.\n\n    To use this in your test, assign `app_module_mock.app = rx.App(...)`.\n\n    Args:\n        monkeypatch: pytest monkeypatch fixture.\n\n    Returns:\n        The mock for the main app module.\n    \"\"\"\n    app_module_mock = mock.Mock()\n    get_app_mock = mock.Mock(return_value=app_module_mock)\n    monkeypatch.setattr(prerequisites, \"get_app\", get_app_mock)\n    return app_module_mock\n\n\n@pytest.fixture\ndef mock_app(app_module_mock: mock.Mock, app: App) -> App:\n    \"\"\"A mocked dummy app per test.\n\n    Args:\n        app_module_mock: The mock for the main app module.\n        app: A default App instance.\n\n    Returns:\n        The mock app instance.\n    \"\"\"\n    app_module_mock.app = app\n    return app\n\n\n@pytest.fixture(scope=\"session\")\ndef windows_platform() -> bool:\n    \"\"\"Check if system is windows.\n\n    Returns:\n        whether system is windows.\n    \"\"\"\n    return platform.system() == \"Windows\"\n\n\n@pytest.fixture\ndef upload_sub_state_event_spec():\n    \"\"\"Create an event Spec for a substate.\n\n    Returns:\n        Event Spec.\n    \"\"\"\n    return EventSpec(handler=SubUploadState.handle_upload, upload=True)  # pyright: ignore [reportCallIssue]\n\n\n@pytest.fixture\ndef upload_event_spec():\n    \"\"\"Create an event Spec for a multi-upload base state.\n\n    Returns:\n        Event Spec.\n    \"\"\"\n    return EventSpec(handler=UploadState.handle_upload1, upload=True)  # pyright: ignore [reportCallIssue]\n\n\n@pytest.fixture\ndef base_config_values() -> dict:\n    \"\"\"Get base config values.\n\n    Returns:\n        Dictionary of base config values\n    \"\"\"\n    return {\"app_name\": \"app\"}\n\n\n@pytest.fixture\ndef base_db_config_values() -> dict:\n    \"\"\"Get base DBConfig values.\n\n    Returns:\n        Dictionary of base db config values\n    \"\"\"\n    return {\"database\": \"db\"}\n\n\n@pytest.fixture\ndef sqlite_db_config_values(base_db_config_values) -> dict:\n    \"\"\"Get sqlite DBConfig values.\n\n    Args:\n        base_db_config_values: Base DBConfig fixture.\n\n    Returns:\n        Dictionary of sqlite DBConfig values\n    \"\"\"\n    base_db_config_values[\"engine\"] = \"sqlite\"\n    return base_db_config_values\n\n\n@pytest.fixture\ndef router_data_headers() -> dict[str, str]:\n    \"\"\"Router data headers.\n\n    Returns:\n        client headers\n    \"\"\"\n    return {\n        \"host\": \"localhost:8000\",\n        \"connection\": \"Upgrade\",\n        \"pragma\": \"no-cache\",\n        \"cache-control\": \"no-cache\",\n        \"user-agent\": \"Mock Agent\",\n        \"upgrade\": \"websocket\",\n        \"origin\": \"http://localhost:3000\",\n        \"sec-websocket-version\": \"13\",\n        \"accept-encoding\": \"gzip, deflate, br\",\n        \"accept-language\": \"en-US,en;q=0.9\",\n        \"cookie\": \"csrftoken=mocktoken; \"\n        \"name=reflex;\"\n        \" list_cookies=%5B%22some%22%2C%20%22random%22%2C%20%22cookies%22%5D;\"\n        \" dict_cookies=%7B%22name%22%3A%20%22reflex%22%7D; val=true\",\n        \"sec-websocket-key\": \"mock-websocket-key\",\n        \"sec-websocket-extensions\": \"permessage-deflate; client_max_window_bits\",\n    }\n\n\n@pytest.fixture\ndef router_data(router_data_headers: dict[str, str]) -> dict[str, str | dict]:\n    \"\"\"Router data.\n\n    Args:\n        router_data_headers: Headers fixture.\n\n    Returns:\n        Dict of router data.\n    \"\"\"\n    return {\n        \"pathname\": \"/\",\n        \"query\": {},\n        \"token\": \"b181904c-3953-4a79-dc18-ae9518c22f05\",\n        \"sid\": \"9fpxSzPb9aFMb4wFAAAH\",\n        \"headers\": router_data_headers,\n        \"ip\": \"127.0.0.1\",\n    }\n\n\n@pytest.fixture\ndef tmp_working_dir(tmp_path):\n    \"\"\"Create a temporary directory and chdir to it.\n\n    After the test executes, chdir back to the original working directory.\n\n    Args:\n        tmp_path: pytest tmp_path fixture creates per-test temp dir\n\n    Yields:\n        subdirectory of tmp_path which is now the current working directory.\n    \"\"\"\n    working_dir = tmp_path / \"working_dir\"\n    working_dir.mkdir()\n    with chdir(working_dir):\n        yield working_dir\n\n\n@pytest.fixture\ndef token() -> str:\n    \"\"\"Create a token.\n\n    Returns:\n        A fresh/unique token string.\n    \"\"\"\n    return str(uuid.uuid4())\n\n\n@pytest.fixture\ndef model_registry() -> Generator[type[ModelRegistry], None, None]:\n    \"\"\"Create a model registry.\n\n    Yields:\n        A fresh model registry.\n    \"\"\"\n    yield ModelRegistry\n    ModelRegistry._metadata = None\n"
  },
  {
    "path": "tests/units/istate/__init__.py",
    "content": ""
  },
  {
    "path": "tests/units/istate/manager/__init__.py",
    "content": ""
  },
  {
    "path": "tests/units/istate/manager/test_redis.py",
    "content": "\"\"\"Tests specific to redis state manager.\"\"\"\n\nimport asyncio\nimport os\nimport time\nimport uuid\nfrom collections.abc import AsyncGenerator\nfrom typing import Any\n\nimport pytest\nimport pytest_asyncio\n\nfrom reflex.istate.manager.redis import StateManagerRedis\nfrom reflex.state import BaseState, _substate_key\nfrom tests.units.mock_redis import mock_redis, real_redis\n\n\nclass RedisTestState(BaseState):\n    \"\"\"A test state for redis state manager tests.\"\"\"\n\n    foo: str = \"bar\"\n    count: int = 0\n\n\nclass SubState1(RedisTestState):\n    \"\"\"A test substate for redis state manager tests.\"\"\"\n\n\nclass SubState2(RedisTestState):\n    \"\"\"A test substate for redis state manager tests.\"\"\"\n\n\n@pytest.fixture\ndef root_state() -> type[RedisTestState]:\n\n    return RedisTestState\n\n\n@pytest_asyncio.fixture(loop_scope=\"function\", scope=\"function\")\nasync def state_manager_redis(\n    root_state: type[RedisTestState],\n) -> AsyncGenerator[StateManagerRedis]:\n    \"\"\"Get a StateManagerRedis with a real or mocked redis client.\n\n    Args:\n        root_state: The root state class.\n\n    Yields:\n        The StateManagerRedis.\n    \"\"\"\n    async with real_redis() as redis:\n        if redis is None:\n            redis = mock_redis()\n        state_manager = StateManagerRedis(state=root_state, redis=redis)\n        test_start = time.monotonic()\n        yield state_manager\n        # None of the tests should have triggered a lock expiration.\n        assert (time.monotonic() - test_start) * 1000 < state_manager.lock_expiration\n\n    await state_manager.close()\n\n\n@pytest.fixture\ndef event_log(state_manager_redis: StateManagerRedis) -> list[dict[str, Any]]:\n    \"\"\"Get the redis event log from the state manager.\n\n    Args:\n        state_manager_redis: The StateManagerRedis.\n\n    Returns:\n        The redis event log.\n    \"\"\"\n    return state_manager_redis.redis._internals[\"event_log\"]  # pyright: ignore[reportAttributeAccessIssue]\n\n\n@pytest.fixture\ndef event_log_on_update(state_manager_redis: StateManagerRedis) -> asyncio.Event:\n    \"\"\"Get the event for new event records being added to the redis event log.\n\n    Test is responsible for calling `.clear` before an operation when it needs\n    to detect a new event added afterward.\n\n    Args:\n        state_manager_redis: The StateManagerRedis.\n\n    Returns:\n        The event that is set when new events are added to the redis event log.\n    \"\"\"\n    return state_manager_redis.redis._internals[\"event_log_on_update\"]  # pyright: ignore[reportAttributeAccessIssue]\n\n\n@pytest.mark.asyncio\nasync def test_basic_get_set(\n    state_manager_redis: StateManagerRedis,\n    root_state: type[RedisTestState],\n):\n    \"\"\"Test basic operations of StateManagerRedis.\n\n    Args:\n        state_manager_redis: The StateManagerRedis to test.\n        root_state: The root state class.\n    \"\"\"\n    state_manager_redis._oplock_enabled = False\n\n    token = str(uuid.uuid4())\n\n    fresh_state = await state_manager_redis.get_state(_substate_key(token, root_state))\n    fresh_state.foo = \"baz\"\n    fresh_state.count = 42\n    await state_manager_redis.set_state(_substate_key(token, root_state), fresh_state)\n\n\nasync def test_modify(\n    state_manager_redis: StateManagerRedis,\n    root_state: type[RedisTestState],\n):\n    \"\"\"Test modifying state with StateManagerRedis.\n\n    Args:\n        state_manager_redis: The StateManagerRedis to test.\n        root_state: The root state class.\n    \"\"\"\n    state_manager_redis._oplock_enabled = False\n\n    token = str(uuid.uuid4())\n\n    # Initial modify should set count to 1\n    async with state_manager_redis.modify_state(\n        _substate_key(token, root_state)\n    ) as new_state:\n        new_state.count = 1\n\n    # Subsequent modify should set count to 2\n    async with state_manager_redis.modify_state(\n        _substate_key(token, root_state)\n    ) as new_state:\n        assert isinstance(new_state, root_state)\n        assert new_state.count == 1\n        new_state.count += 2\n\n    final_state = await state_manager_redis.get_state(_substate_key(token, root_state))\n    assert isinstance(final_state, root_state)\n    assert final_state.count == 3\n\n\nasync def test_modify_oplock(\n    state_manager_redis: StateManagerRedis,\n    root_state: type[RedisTestState],\n    event_log: list[dict[str, Any]],\n    event_log_on_update: asyncio.Event,\n):\n    \"\"\"Test modifying state with StateManagerRedis with optimistic locking.\n\n    Args:\n        state_manager_redis: The StateManagerRedis to test.\n        root_state: The root state class.\n        event_log: The redis event log.\n        event_log_on_update: The event for new event records being added to the redis event log.\n    \"\"\"\n    token = str(uuid.uuid4())\n\n    state_manager_redis._debug_enabled = True\n    state_manager_redis._oplock_enabled = True\n\n    state_manager_2 = StateManagerRedis(\n        state=root_state, redis=state_manager_redis.redis\n    )\n\n    state_manager_2._debug_enabled = True\n    state_manager_2._oplock_enabled = True\n\n    event_log_on_update.clear()\n\n    # Initial modify should set count to 1\n    async with state_manager_redis.modify_state(\n        _substate_key(token, root_state),\n    ) as new_state:\n        new_state.count = 1\n\n    # Initial state manager should be holding a lease\n    lease_task_1 = state_manager_redis._local_leases.get(token)\n    assert lease_task_1 is not None\n    assert not lease_task_1.done()\n\n    # The state should not be locked\n    state_lock_1 = state_manager_redis._cached_states_locks.get(token)\n    assert state_lock_1 is not None\n    assert not state_lock_1.locked()\n\n    await event_log_on_update.wait()\n    lock_events_before = len([\n        ev\n        for ev in event_log\n        if ev[\"channel\"].endswith(b\"lock\") and ev[\"data\"] == b\"set\"\n    ])\n    assert lock_events_before == 1\n\n    # The second modify should NOT trigger another redis lock\n    async with state_manager_redis.modify_state(\n        _substate_key(token, root_state),\n    ) as new_state:\n        new_state.count = 2\n        assert state_lock_1.locked()\n\n    lock_events_after = len([\n        ev\n        for ev in event_log\n        if ev[\"channel\"].endswith(b\"lock\") and ev[\"data\"] == b\"set\"\n    ])\n\n    assert lock_events_before == lock_events_after\n\n    # Contend the lock from another state manager\n    event_log_on_update.clear()\n    async with state_manager_2.modify_state(\n        _substate_key(token, root_state),\n    ) as new_state:\n        new_state.count = 3\n        state_lock_2 = state_manager_2._cached_states_locks.get(token)\n        assert state_lock_2 is not None\n        assert state_lock_2.locked()\n\n    # The second manager should be holding the lease now\n    lease_task_2 = state_manager_2._local_leases.get(token)\n    assert lease_task_2 is not None\n    assert not lease_task_2.done()\n    assert not state_lock_2.locked()\n\n    # Lease task 1 should be cancelled by the time we have modified the state\n    assert lease_task_1.done()\n    assert lease_task_1.cancelled()\n    assert token not in state_manager_redis._local_leases\n    assert token not in state_manager_redis._cached_states\n\n    # There should have been another redis lock taken.\n    await event_log_on_update.wait()\n    lock_events_after_2 = len([\n        ev\n        for ev in event_log\n        if ev[\"channel\"].endswith(b\"lock\") and ev[\"data\"] == b\"set\"\n    ])\n    assert lock_events_after_2 == lock_events_after + 1\n\n    # And there should have been a lock release.\n    unlock_events = len([\n        ev\n        for ev in event_log\n        if ev[\"channel\"].endswith(b\"lock\") and ev[\"data\"] == b\"del\"\n    ])\n    assert unlock_events == 1\n\n    # And a single token set.\n    token_set_events = len([\n        ev\n        for ev in event_log\n        if ev[\"channel\"].endswith(root_state.get_full_name().encode())\n        and ev[\"data\"] == b\"set\"\n    ])\n    assert token_set_events == 1\n\n    # Now close the contender to release its lease.\n    event_log_on_update.clear()\n    await state_manager_2.close()\n    await event_log_on_update.wait()\n\n    # Both locks should have been released.\n    unlock_events = len([\n        ev\n        for ev in event_log\n        if ev[\"channel\"].endswith(b\"lock\") and ev[\"data\"] == b\"del\"\n    ])\n    assert unlock_events == 2\n\n    # And both tokens should have been set.\n    token_set_events = len([\n        ev\n        for ev in event_log\n        if ev[\"channel\"].endswith(root_state.get_full_name().encode())\n        and ev[\"data\"] == b\"set\"\n    ])\n    assert token_set_events == 2\n\n\nasync def test_oplock_contention_queue(\n    state_manager_redis: StateManagerRedis,\n    root_state: type[RedisTestState],\n    event_log: list[dict[str, Any]],\n):\n    \"\"\"Test the oplock contention queue.\n\n    Args:\n        state_manager_redis: The StateManagerRedis to test.\n        root_state: The root state class.\n        event_log: The redis event log.\n    \"\"\"\n    token = str(uuid.uuid4())\n\n    state_manager_redis._debug_enabled = True\n    state_manager_redis._oplock_enabled = True\n\n    state_manager_2 = StateManagerRedis(\n        state=root_state, redis=state_manager_redis.redis\n    )\n\n    state_manager_2._debug_enabled = True\n    state_manager_2._oplock_enabled = True\n\n    modify_started = asyncio.Event()\n    modify_2_started = asyncio.Event()\n    modify_1_continue = asyncio.Event()\n    modify_2_continue = asyncio.Event()\n\n    async def modify_1():\n        async with state_manager_redis.modify_state(\n            _substate_key(token, root_state),\n        ) as new_state:\n            assert isinstance(new_state, root_state)\n            new_state.count += 1\n            modify_started.set()\n            await modify_1_continue.wait()\n\n    async def modify_2():\n        await modify_started.wait()\n        modify_2_started.set()\n        async with state_manager_2.modify_state(\n            _substate_key(token, root_state),\n        ) as new_state:\n            assert isinstance(new_state, root_state)\n            new_state.count += 1\n            await modify_2_continue.wait()\n\n    async def modify_3():\n        await modify_started.wait()\n        modify_2_started.set()\n        async with state_manager_2.modify_state(\n            _substate_key(token, root_state),\n        ) as new_state:\n            assert isinstance(new_state, root_state)\n            new_state.count += 1\n            await modify_2_continue.wait()\n\n    task_1 = asyncio.create_task(modify_1())\n    task_2 = asyncio.create_task(modify_2())\n    task_3 = asyncio.create_task(modify_3())\n\n    await modify_2_started.wait()\n\n    # Let modify 1 complete\n    modify_1_continue.set()\n\n    # Let modify 2 complete\n    modify_2_continue.set()\n\n    await task_1\n    await task_2\n    await task_3\n\n    interim_state = await state_manager_redis.get_state(\n        _substate_key(token, root_state)\n    )\n    assert isinstance(interim_state, root_state)\n    assert interim_state.count == 1\n\n    await state_manager_2.close()\n\n    final_state = await state_manager_redis.get_state(_substate_key(token, root_state))\n    assert isinstance(final_state, root_state)\n    assert final_state.count == 3\n\n    # There should only be two lock acquisitions\n    lock_events = len([\n        ev\n        for ev in event_log\n        if ev[\"channel\"].endswith(b\"lock\") and ev[\"data\"] == b\"set\"\n    ])\n    assert lock_events == 2\n\n\nasync def test_oplock_contention_no_lease(\n    state_manager_redis: StateManagerRedis,\n    root_state: type[RedisTestState],\n    event_log: list[dict[str, Any]],\n):\n    \"\"\"Test the oplock contention queue, when no waiters can share.\n\n    Args:\n        state_manager_redis: The StateManagerRedis to test.\n        root_state: The root state class.\n        event_log: The redis event log.\n    \"\"\"\n    token = str(uuid.uuid4())\n\n    state_manager_redis._debug_enabled = True\n    state_manager_redis._oplock_enabled = True\n\n    state_manager_2 = StateManagerRedis(\n        state=root_state, redis=state_manager_redis.redis\n    )\n\n    state_manager_2._debug_enabled = True\n    state_manager_2._oplock_enabled = True\n\n    state_manager_3 = StateManagerRedis(\n        state=root_state, redis=state_manager_redis.redis\n    )\n    state_manager_3._debug_enabled = True\n    state_manager_3._oplock_enabled = True\n\n    modify_started = asyncio.Event()\n    modify_2_started = asyncio.Event()\n    modify_1_continue = asyncio.Event()\n    modify_2_continue = asyncio.Event()\n\n    async def modify_1():\n        async with state_manager_redis.modify_state(\n            _substate_key(token, root_state),\n        ) as new_state:\n            assert isinstance(new_state, root_state)\n            new_state.count += 1\n            modify_started.set()\n            await modify_1_continue.wait()\n\n    async def modify_2():\n        await modify_started.wait()\n        modify_2_started.set()\n        async with state_manager_2.modify_state(\n            _substate_key(token, root_state),\n        ) as new_state:\n            assert isinstance(new_state, root_state)\n            new_state.count += 1\n            await modify_2_continue.wait()\n\n    async def modify_3():\n        await modify_started.wait()\n        modify_2_started.set()\n        async with state_manager_3.modify_state(\n            _substate_key(token, root_state),\n        ) as new_state:\n            assert isinstance(new_state, root_state)\n            new_state.count += 1\n            await modify_2_continue.wait()\n\n    task_1 = asyncio.create_task(modify_1())\n    task_2 = asyncio.create_task(modify_2())\n    task_3 = asyncio.create_task(modify_3())\n\n    await modify_2_started.wait()\n\n    # Let modify 1 complete\n    modify_1_continue.set()\n\n    # Let modify 2 complete\n    modify_2_continue.set()\n\n    await task_1\n    await task_2\n    await task_3\n\n    # First task should have always gotten a lease\n    assert token in state_manager_redis._cached_states_locks\n\n    # The 2nd or 3rd modify should have _never_ got a lease due to contention\n    if token not in state_manager_2._cached_states_locks:\n        assert await state_manager_3._get_local_lease(token) is not None\n    elif token not in state_manager_3._cached_states_locks:\n        assert await state_manager_2._get_local_lease(token) is not None\n    else:\n        pytest.fail(\"One of the contending state managers should not have a lease.\")\n\n    await state_manager_2.close()\n    await state_manager_3.close()\n\n    final_state = await state_manager_2.get_state(_substate_key(token, root_state))\n    assert isinstance(final_state, root_state)\n    assert final_state.count == 3\n\n    # There should be three lock acquisitions\n    lock_events = len([\n        ev\n        for ev in event_log\n        if ev[\"channel\"].endswith(b\"lock\") and ev[\"data\"] == b\"set\"\n    ])\n    assert lock_events == 3\n\n\n@pytest.mark.parametrize(\"racer_delay\", [None, 0, 0.1])\n@pytest.mark.asyncio\nasync def test_oplock_contention_racers(\n    state_manager_redis: StateManagerRedis,\n    root_state: type[RedisTestState],\n    racer_delay: float | None,\n):\n    \"\"\"Test the oplock contention queue with racers.\n\n    Args:\n        state_manager_redis: The StateManagerRedis to test.\n        root_state: The root state class.\n        racer_delay: The delay before the second racer starts.\n    \"\"\"\n    token = str(uuid.uuid4())\n\n    state_manager_redis._debug_enabled = True\n    state_manager_redis._oplock_enabled = True\n\n    state_manager_2 = StateManagerRedis(\n        state=root_state, redis=state_manager_redis.redis\n    )\n    state_manager_2._debug_enabled = True\n    state_manager_2._oplock_enabled = True\n    lease_1 = None\n    lease_2 = None\n\n    async def modify_1():\n        nonlocal lease_1\n        async with state_manager_redis.modify_state(\n            _substate_key(token, root_state),\n        ) as new_state:\n            lease_1 = await state_manager_redis._get_local_lease(token)\n            assert isinstance(new_state, root_state)\n            new_state.count += 1\n\n    async def modify_2():\n        if racer_delay is not None:\n            await asyncio.sleep(racer_delay)\n        nonlocal lease_2\n        async with state_manager_2.modify_state(\n            _substate_key(token, root_state),\n        ) as new_state:\n            lease_2 = await state_manager_2._get_local_lease(token)\n            assert isinstance(new_state, root_state)\n            new_state.count += 1\n\n    await asyncio.gather(\n        modify_1(),\n        modify_2(),\n    )\n\n    if lease_1 is None or lease_1.cancelled():\n        assert lease_2 is not None\n        assert not lease_2.cancelled()\n    elif lease_2 is None or lease_2.cancelled():\n        assert lease_1 is not None\n        assert not lease_1.cancelled()\n    else:\n        pytest.fail(\n            \"One lease should have been cancelled, other should still be active.\"\n        )\n\n\n@pytest.mark.asyncio\nasync def test_oplock_immediate_cancel(\n    state_manager_redis: StateManagerRedis,\n    root_state: type[RedisTestState],\n    event_log: list[dict[str, Any]],\n):\n    \"\"\"Test that immediate cancellation of modify releases oplock.\n\n    Args:\n        state_manager_redis: The StateManagerRedis to test.\n        root_state: The root state class.\n        event_log: The redis event log.\n    \"\"\"\n    token = str(uuid.uuid4())\n\n    state_manager_redis._debug_enabled = True\n    state_manager_redis._oplock_enabled = True\n\n    async def canceller():\n        while (lease_task := state_manager_redis._local_leases.get(token)) is None:  # noqa: ASYNC110\n            await asyncio.sleep(0)\n        lease_task.cancel()\n\n    task = asyncio.create_task(canceller())\n\n    async with state_manager_redis.modify_state(\n        _substate_key(token, root_state),\n    ) as new_state:\n        assert await state_manager_redis._get_local_lease(token) is None\n        assert isinstance(new_state, root_state)\n        new_state.count += 1\n\n    await task\n\n\n@pytest.mark.asyncio\nasync def test_oplock_fetch_substate(\n    state_manager_redis: StateManagerRedis,\n    root_state: type[RedisTestState],\n    event_log: list[dict[str, Any]],\n):\n    \"\"\"Test fetching substate with oplock enabled and partial state is cached.\n\n    Args:\n        state_manager_redis: The StateManagerRedis to test.\n        root_state: The root state class.\n        event_log: The redis event log.\n    \"\"\"\n    token = str(uuid.uuid4())\n\n    state_manager_redis._debug_enabled = True\n    state_manager_redis._oplock_enabled = True\n\n    async with state_manager_redis.modify_state(\n        _substate_key(token, SubState1),\n    ) as new_state:\n        assert SubState1.get_name() in new_state.substates\n        assert SubState2.get_name() not in new_state.substates\n\n    async with state_manager_redis.modify_state(\n        _substate_key(token, SubState2),\n    ) as new_state:\n        # Both substates should be fetched and cached.\n        assert SubState1.get_name() in new_state.substates\n        assert SubState2.get_name() in new_state.substates\n\n    async with state_manager_redis.modify_state(\n        _substate_key(token, SubState1),\n    ) as new_state:\n        # Both substates should be fetched and cached now.\n        assert SubState1.get_name() in new_state.substates\n        assert SubState2.get_name() in new_state.substates\n\n    # Should have still only been one lock acquisition.\n    lock_events = len([\n        ev\n        for ev in event_log\n        if ev[\"channel\"].endswith(b\"lock\") and ev[\"data\"] == b\"set\"\n    ])\n    assert lock_events == 1\n\n\n@pytest.fixture\ndef short_lock_expiration(\n    state_manager_redis: StateManagerRedis,\n):\n    \"\"\"Get a StateManagerRedis with a short lock expiration for testing.\n\n    Args:\n        state_manager_redis: The base StateManagerRedis.\n\n    Yields:\n        The lock expiration time in milliseconds.\n    \"\"\"\n    lock_expiration = 4000 if os.environ.get(\"CI\") else 300\n    original_expiration = state_manager_redis.lock_expiration\n    state_manager_redis.lock_expiration = lock_expiration\n    yield lock_expiration\n    state_manager_redis.lock_expiration = original_expiration\n\n\n@pytest.mark.asyncio\nasync def test_oplock_hold_oplock_after_cancel(\n    state_manager_redis: StateManagerRedis,\n    root_state: type[RedisTestState],\n    event_log: list[dict[str, Any]],\n    event_log_on_update: asyncio.Event,\n    short_lock_expiration: int,\n):\n    \"\"\"Test that cancelling a modify does not release the oplock prematurely.\n\n    Args:\n        state_manager_redis: The StateManagerRedis to test.\n        root_state: The root state class.\n        event_log: The redis event log.\n        event_log_on_update: The event log update event.\n        short_lock_expiration: The lock expiration time in milliseconds.\n    \"\"\"\n    token = str(uuid.uuid4())\n\n    state_manager_redis._debug_enabled = True\n    state_manager_redis._oplock_enabled = True\n\n    modify_started = asyncio.Event()\n    modify_continue = asyncio.Event()\n    modify_ended = asyncio.Event()\n\n    async def modify():\n        async with state_manager_redis.modify_state(\n            _substate_key(token, root_state),\n        ) as new_state:\n            modify_started.set()\n            assert isinstance(new_state, root_state)\n            new_state.count += 1\n            await modify_continue.wait()\n            modify_ended.set()\n\n    task = asyncio.create_task(modify())\n\n    await modify_started.wait()\n    started = time.monotonic()\n    await asyncio.sleep(short_lock_expiration / 1000 * 0.5)\n    state_lock = state_manager_redis._cached_states_locks.get(token)\n    assert state_lock is not None\n    assert state_lock.locked()\n    lease_task = await state_manager_redis._get_local_lease(token)\n    assert lease_task is not None\n    assert not lease_task.done()\n    lease_task.cancel()\n    # post-cancel wait should get another full lock_expiration.\n    await asyncio.sleep(short_lock_expiration / 1000 * 0.8)\n    assert not lease_task.done()\n    modify_continue.set()\n    await modify_ended.wait()\n    ended = time.monotonic()\n\n    # We should have successfully held the lock for longer than the lock expiration\n    assert (ended - started) * 1000 > short_lock_expiration\n\n    await task\n    with pytest.raises(asyncio.CancelledError):\n        await lease_task\n\n    # Modify the state again, this should get a new lock and lease\n    event_log_on_update.clear()\n    async with state_manager_redis.modify_state(\n        _substate_key(token, root_state),\n    ) as new_state:\n        assert isinstance(new_state, root_state)\n        new_state.count += 1\n\n    # There should have been two redis lock acquisitions.\n    await event_log_on_update.wait()\n    lock_events = len([\n        ev\n        for ev in event_log\n        if ev[\"channel\"].endswith(b\"lock\") and ev[\"data\"] == b\"set\"\n    ])\n    assert lock_events == 2\n\n    await state_manager_redis.close()\n\n    # Both increments should be present.\n    final_state = await state_manager_redis.get_state(_substate_key(token, root_state))\n    assert isinstance(final_state, root_state)\n    assert final_state.count == 2\n"
  },
  {
    "path": "tests/units/istate/test_proxy.py",
    "content": "\"\"\"Tests for MutableProxy pickle behavior.\"\"\"\n\nimport dataclasses\nimport pickle\nfrom asyncio import CancelledError\nfrom contextlib import asynccontextmanager\nfrom unittest.mock import patch\n\nimport pytest\n\nimport reflex as rx\nfrom reflex.istate.proxy import MutableProxy, StateProxy\n\n\n@dataclasses.dataclass\nclass Item:\n    \"\"\"Simple picklable object for testing.\"\"\"\n\n    id: int\n\n\nclass ProxyTestState(rx.State):\n    \"\"\"Test state with a list field.\"\"\"\n\n    items: list[Item] = []\n\n\ndef test_mutable_proxy_pickle_preserves_object_identity():\n    \"\"\"Test that same object referenced directly and via proxy maintains identity.\"\"\"\n    state = ProxyTestState()\n    obj = Item(1)\n\n    data = {\n        \"direct\": [obj],\n        \"proxied\": [MutableProxy(obj, state, \"items\")],\n    }\n\n    unpickled = pickle.loads(pickle.dumps(data))\n\n    assert unpickled[\"direct\"][0].id == 1\n    assert unpickled[\"proxied\"][0].id == 1\n    assert unpickled[\"direct\"][0] is unpickled[\"proxied\"][0]\n\n\n@pytest.mark.usefixtures(\"mock_app\")\n@pytest.mark.asyncio\nasync def test_state_proxy_recovery():\n    \"\"\"Ensure that `async with self` can be re-entered after a lock issue.\"\"\"\n    state = ProxyTestState()\n    state_proxy = StateProxy(state)\n\n    with patch(\"reflex.app.App.modify_state\") as mock_modify_state:\n\n        @asynccontextmanager\n        async def mock_modify_state_context(*args, **kwargs):  # noqa: RUF029\n            msg = \"Simulated lock issue\"\n            raise CancelledError(msg)\n            yield\n\n        mock_modify_state.side_effect = mock_modify_state_context\n\n        with pytest.raises(CancelledError, match=\"Simulated lock issue\"):\n            async with state_proxy:\n                pass\n\n    # After the exception, we should be able to enter the context again without issues\n    async with state_proxy:\n        pass\n"
  },
  {
    "path": "tests/units/middleware/__init__.py",
    "content": ""
  },
  {
    "path": "tests/units/middleware/conftest.py",
    "content": "import pytest\n\nfrom reflex.event import Event\nfrom reflex.state import State\n\n\ndef create_event(name):\n    return Event(\n        token=\"<token>\",\n        name=name,\n        router_data={\n            \"pathname\": \"/\",\n            \"query\": {},\n            \"token\": \"<token>\",\n            \"sid\": \"<sid>\",\n            \"headers\": {},\n            \"ip\": \"127.0.0.1\",\n        },\n        payload={},\n    )\n\n\n@pytest.fixture\ndef event1():\n    return create_event(f\"{State.get_name()}.hydrate\")\n"
  },
  {
    "path": "tests/units/middleware/test_hydrate_middleware.py",
    "content": "from __future__ import annotations\n\nimport pytest\nfrom pytest_mock import MockerFixture\n\nfrom reflex.app import App\nfrom reflex.middleware.hydrate_middleware import HydrateMiddleware\nfrom reflex.state import State, StateUpdate\n\n\nclass TestState(State):\n    \"\"\"A test state with no return in handler.\"\"\"\n\n    __test__ = False\n\n    num: int = 0\n\n    def test_handler(self):\n        \"\"\"Test handler.\"\"\"\n        self.num += 1\n\n\n@pytest.fixture\ndef hydrate_middleware() -> HydrateMiddleware:\n    \"\"\"Fixture creates an instance of HydrateMiddleware per test case.\n\n    Returns:\n        instance of HydrateMiddleware\n    \"\"\"\n    return HydrateMiddleware()\n\n\n@pytest.mark.asyncio\nasync def test_preprocess_no_events(hydrate_middleware, event1, mocker: MockerFixture):\n    \"\"\"Test that app without on_load is processed correctly.\n\n    Args:\n        hydrate_middleware: Instance of HydrateMiddleware\n        event1: An Event.\n        mocker: pytest mock object.\n    \"\"\"\n    mocker.patch(\"reflex.state.State.class_subclasses\", {TestState})\n    state = State()\n    update = await hydrate_middleware.preprocess(\n        app=App(_state=State),\n        event=event1,\n        state=state,\n    )\n    assert isinstance(update, StateUpdate)\n    assert update.delta == state.dict()\n    assert not update.events\n"
  },
  {
    "path": "tests/units/mock_redis.py",
    "content": "\"\"\"Mock implementation of redis for unit testing.\"\"\"\n\nimport asyncio\nimport contextlib\nimport fnmatch\nimport time\nfrom collections.abc import AsyncGenerator, Callable\nfrom typing import Any\nfrom unittest.mock import AsyncMock, Mock\n\nfrom redis.asyncio import Redis\nfrom redis.typing import EncodableT, KeyT\n\nfrom reflex.utils import prerequisites\n\nWRONGTYPE_MESSAGE = \"WRONGTYPE Operation against a key holding the wrong kind of value\"\n\n\ndef mock_redis() -> Redis:\n    \"\"\"Mock the redis client with pubsub support.\n\n    Returns:\n        The mocked redis client.\n    \"\"\"\n    keys: dict[bytes, EncodableT | set[EncodableT]] = {}\n    expire_times: dict[bytes, float] = {}\n    event_log: list[dict[str, bytes]] = []\n    event_log_new_events = asyncio.Event()\n    event_log_on_update = asyncio.Event()\n\n    def _event_log_append_notify(event: dict[str, bytes]) -> None:\n        event_log.append(event)\n        event_log_new_events.set()\n        event_log_on_update.set()\n\n    def _key_bytes(key: KeyT) -> bytes:\n        if isinstance(key, str):\n            return key.encode()\n        if isinstance(key, memoryview):\n            return key.tobytes()\n        return key\n\n    def _keyspace_event(key: KeyT, data: str | bytes):\n        if isinstance(key, str):\n            key = key.encode()\n        if isinstance(data, str):\n            data = data.encode()\n        _event_log_append_notify({\"channel\": b\"__keyspace@1__:\" + key, \"data\": data})\n\n    def _expire_keys():\n        to_delete = []\n        for key, expire_time in expire_times.items():\n            if expire_time <= time.monotonic():\n                to_delete.append(key)\n        for key in to_delete:\n            del keys[key]\n            del expire_times[key]\n            _keyspace_event(key, \"expired\")\n\n    async def mock_get(key: KeyT):  # noqa: RUF029\n        _expire_keys()\n        return keys.get(_key_bytes(key))\n\n    async def mock_set(  # noqa: RUF029\n        key: KeyT,\n        value: EncodableT,\n        ex: int | None = None,\n        px: int | None = None,\n        nx: bool = False,\n    ) -> bool:\n        _expire_keys()\n        key = _key_bytes(key)\n        if nx and key in keys:\n            return False\n        keys[key] = value\n        _keyspace_event(key, \"set\")\n        if ex is not None:\n            expire_times[key] = time.monotonic() + ex\n            _keyspace_event(key, \"expire\")\n        elif px is not None:\n            expire_times[key] = time.monotonic() + (px / 1000)\n            _keyspace_event(key, \"expire\")\n        return True\n\n    async def mock_sadd(key: KeyT, value: EncodableT) -> int:  # noqa: RUF029\n        _expire_keys()\n        key = _key_bytes(key)\n        keyset = keys.setdefault(key, set())\n        if not isinstance(keyset, set):\n            raise TypeError(WRONGTYPE_MESSAGE)\n        before = len(keyset)\n        keyset.add(value)\n        _keyspace_event(key, \"sadd\")\n        return len(keyset) - before\n\n    async def mock_srem(key: KeyT, value: EncodableT) -> int:\n        _expire_keys()\n        keyset = keys.get(_key_bytes(key))\n        if keyset is None:\n            return 0\n        if not isinstance(keyset, set):\n            raise TypeError(WRONGTYPE_MESSAGE)\n        if value in keyset:\n            keyset.remove(value)\n            _keyspace_event(key, \"srem\")\n            if not keyset:\n                await redis_mock.delete(key)\n            return 1\n        return 0\n\n    async def mock_scard(key: KeyT) -> int:  # noqa: RUF029\n        _expire_keys()\n        keyset = keys.get(_key_bytes(key))\n        if keyset is None:\n            return 0\n        if not isinstance(keyset, set):\n            raise TypeError(WRONGTYPE_MESSAGE)\n        return len(keyset)\n\n    async def mock_delete(key: KeyT) -> int:  # noqa: RUF029\n        _expire_keys()\n        key = _key_bytes(key)\n        Unset = object()\n        expire_times.pop(key, None)\n        if keys.pop(key, Unset) is not Unset:\n            _keyspace_event(key, \"del\")\n            return 1\n        return 0\n\n    async def mock_getdel(key: KeyT) -> Any:\n        value = await redis_mock.get(key)\n        await redis_mock.delete(key)\n        return value\n\n    async def mock_pexpire(key: KeyT, px: int, xx: bool = False) -> bool:  # noqa: RUF029\n        _expire_keys()\n        key = _key_bytes(key)\n        if key in keys:\n            if not xx or key in expire_times:\n                expire_times[key] = time.monotonic() + (px / 1000)\n                _keyspace_event(key, \"expire\")\n            return True\n        return False\n\n    def pipeline():\n        pipeline_mock = Mock()\n        results = []\n\n        def get_pipeline(key: KeyT):\n            results.append(redis_mock.get(key=key))\n\n        def set_pipeline(\n            key: KeyT,\n            value: EncodableT,\n            ex: int | None = None,\n            px: int | None = None,\n            nx: bool = False,\n        ):\n            results.append(redis_mock.set(key=key, value=value, ex=ex, px=px, nx=nx))\n\n        def sadd_pipeline(key: KeyT, value: EncodableT):\n            results.append(redis_mock.sadd(key=key, value=value))\n\n        def pexpire_pipeline(key: KeyT, px: int, xx: bool = False):\n            results.append(redis_mock.pexpire(key=key, px=px, xx=xx))\n\n        async def execute():\n            _expire_keys()\n            return await asyncio.gather(*results)\n\n        pipeline_mock.get = get_pipeline\n        pipeline_mock.set = set_pipeline\n        pipeline_mock.sadd = sadd_pipeline\n        pipeline_mock.pexpire = pexpire_pipeline\n        pipeline_mock.execute = execute\n\n        return pipeline_mock\n\n    async def pttl(key: KeyT) -> int:  # noqa: RUF029\n        _expire_keys()\n        return (\n            int(expire_times.get(_key_bytes(key), time.monotonic()) - time.monotonic())\n            * 1000\n        )\n\n    @contextlib.asynccontextmanager\n    async def pubsub():  # noqa: RUF029\n        watch_patterns = {}\n        event_log_pointer = 0\n\n        async def psubscribe(  # noqa: RUF029\n            *patterns: str,\n            **handlers: Callable[[dict[str, bytes]], None],\n        ):\n            nonlocal event_log_pointer, watch_patterns\n            event_log_pointer = len(event_log) - 1\n\n            for pattern in patterns:\n                watch_patterns[pattern] = None\n                _event_log_append_notify({\n                    \"channel\": b\"psubscribe\",\n                    \"data\": pattern.encode(),\n                })\n            for pattern, handler in handlers.items():\n                watch_patterns[pattern] = handler\n                _event_log_append_notify({\n                    \"channel\": b\"psubscribe\",\n                    \"data\": pattern.encode(),\n                })\n\n        async def listen() -> AsyncGenerator[dict[str, Any] | None, None]:\n            nonlocal event_log_pointer\n            while True:\n                if event_log_pointer >= len(event_log):\n                    await event_log_new_events.wait()\n                    event_log_new_events.clear()\n                    continue\n                event = event_log[event_log_pointer]\n                channel_str = event[\"channel\"].decode()\n                event_log_pointer += 1\n                for pattern, handler in watch_patterns.items():\n                    if fnmatch.fnmatch(channel_str, pattern):\n                        if handler is not None:\n                            res = handler(event)\n                            if asyncio.iscoroutine(res):\n                                res = await res\n                            # Yields None to indicate handled\n                            yield None\n                        else:\n                            yield event\n\n        pubsub_mock = AsyncMock()\n        pubsub_mock.psubscribe = psubscribe\n        pubsub_mock.listen = listen\n        yield pubsub_mock\n\n    redis_mock = AsyncMock(spec=Redis)\n    redis_mock.get = mock_get\n    redis_mock.set = mock_set\n    redis_mock.delete = mock_delete\n    redis_mock.getdel = mock_getdel\n    redis_mock.sadd = mock_sadd\n    redis_mock.srem = mock_srem\n    redis_mock.scard = mock_scard\n    redis_mock.pexpire = mock_pexpire\n    redis_mock.pipeline = pipeline\n    redis_mock.pttl = pttl\n    redis_mock.pubsub = pubsub\n    redis_mock.config_set = AsyncMock()\n    redis_mock.get_connection_kwargs = Mock(return_value={\"db\": 1})\n    redis_mock._internals = {\n        \"keys\": keys,\n        \"expire_times\": expire_times,\n        \"event_log\": event_log,\n        \"event_log_on_update\": event_log_on_update,\n    }\n    return redis_mock\n\n\n@contextlib.asynccontextmanager\nasync def real_redis() -> AsyncGenerator[Redis | None]:\n    \"\"\"Get a real redis client for testing.\n\n    Yields:\n        The redis client.\n    \"\"\"\n    redis = prerequisites.get_redis()\n    if redis is None:\n        yield None\n        return\n\n    # Create a pubsub to keep the internal event log for assertions.\n    event_log = []\n    event_log_on_update = asyncio.Event()\n    object.__setattr__(\n        redis,\n        \"_internals\",\n        {\n            \"event_log\": event_log,\n            \"event_log_on_update\": event_log_on_update,\n        },\n    )\n    redis_db = redis.get_connection_kwargs().get(\"db\", 0)\n    pubsub_ready = asyncio.Event()\n\n    async def log_events():\n        async with redis.pubsub() as pubsub:\n            await pubsub.psubscribe(f\"__keyspace@{redis_db}__:*\")\n            pubsub_ready.set()\n            async for message in pubsub.listen():\n                if message is None:\n                    continue\n                event_log.append(message)\n                event_log_on_update.set()\n\n    log_events_task = asyncio.create_task(log_events())\n    await pubsub_ready.wait()\n    try:\n        yield redis\n    finally:\n        log_events_task.cancel()\n        with contextlib.suppress(asyncio.CancelledError):\n            await log_events_task\n"
  },
  {
    "path": "tests/units/plugins/test_sitemap.py",
    "content": "\"\"\"Unit tests for the sitemap plugin.\"\"\"\n\nimport datetime\nfrom unittest.mock import MagicMock, patch\n\nimport reflex as rx\nfrom reflex.app import UnevaluatedPage\nfrom reflex.plugins.sitemap import SitemapLink, generate_links_for_sitemap, generate_xml\n\n\ndef test_generate_xml_empty_links():\n    \"\"\"Test generate_xml with an empty list of links.\"\"\"\n    xml_output = generate_xml([])\n    expected = \"\"\"<?xml version='1.0' encoding='utf-8'?>\n<urlset xmlns=\"https://www.sitemaps.org/schemas/sitemap/0.9\" />\"\"\"\n    assert xml_output == expected\n\n\ndef test_generate_xml_single_link_loc_only():\n    \"\"\"Test generate_xml with a single link having only loc.\"\"\"\n    links: list[SitemapLink] = [{\"loc\": \"https://example.com\"}]\n    xml_output = generate_xml(links)\n    expected = \"\"\"<?xml version='1.0' encoding='utf-8'?>\n<urlset xmlns=\"https://www.sitemaps.org/schemas/sitemap/0.9\">\n  <url>\n    <loc>https://example.com</loc>\n  </url>\n</urlset>\"\"\"\n    assert xml_output == expected\n\n\ndef test_generate_xml_multiple_links_all_fields():\n    \"\"\"Test generate_xml with multiple links having all fields.\"\"\"\n    now = datetime.datetime(2023, 6, 13, 12, 0, 0)\n    links: list[SitemapLink] = [\n        {\n            \"loc\": \"https://example.com/page1\",\n            \"lastmod\": now,\n            \"changefreq\": \"daily\",\n            \"priority\": 0.8,\n        },\n        {\n            \"loc\": \"https://example.com/page2\",\n            \"lastmod\": datetime.datetime(2023, 1, 1, 0, 0, 0),\n            \"changefreq\": \"weekly\",\n            \"priority\": 0.5,\n        },\n    ]\n    xml_output = generate_xml(links)\n    expected = \"\"\"<?xml version='1.0' encoding='utf-8'?>\n<urlset xmlns=\"https://www.sitemaps.org/schemas/sitemap/0.9\">\n  <url>\n    <loc>https://example.com/page1</loc>\n    <changefreq>daily</changefreq>\n    <lastmod>2023-06-13T12:00:00</lastmod>\n    <priority>0.8</priority>\n  </url>\n  <url>\n    <loc>https://example.com/page2</loc>\n    <changefreq>weekly</changefreq>\n    <lastmod>2023-01-01T00:00:00</lastmod>\n    <priority>0.5</priority>\n  </url>\n</urlset>\"\"\"\n    assert xml_output == expected\n\n\n@patch(\"reflex.config.get_config\")\n@patch(\"reflex.utils.console.warn\")\ndef test_generate_links_for_sitemap_static_routes(\n    mock_warn: MagicMock, mock_get_config: MagicMock\n):\n    \"\"\"Test generate_links_for_sitemap with static routes.\n\n    Args:\n        mock_warn: Mock for the console.warn function.\n        mock_get_config: Mock for the get_config function.\n    \"\"\"\n    mock_get_config.return_value.deploy_url = \"https://example.com\"\n\n    def mock_component():\n        return rx.text(\"Test\")\n\n    pages = [\n        UnevaluatedPage(\n            component=mock_component,\n            route=\"index\",\n            title=None,\n            description=None,\n            image=\"favicon.ico\",\n            on_load=None,\n            meta=[],\n            context={},\n        ),\n        UnevaluatedPage(\n            component=mock_component,\n            route=\"about\",\n            title=None,\n            description=None,\n            image=\"favicon.ico\",\n            on_load=None,\n            meta=[],\n            context={},\n        ),\n        UnevaluatedPage(\n            component=mock_component,\n            route=\"contact\",\n            title=None,\n            description=None,\n            image=\"favicon.ico\",\n            on_load=None,\n            meta=[],\n            context={\"sitemap\": {\"priority\": 0.7, \"changefreq\": \"monthly\"}},\n        ),\n    ]\n    links = generate_links_for_sitemap(pages)\n    assert len(links) == 3\n    assert {\"loc\": \"https://example.com/\"} in links\n    assert {\"loc\": \"https://example.com/about\"} in links\n    assert {\n        \"loc\": \"https://example.com/contact\",\n        \"priority\": 0.7,\n        \"changefreq\": \"monthly\",\n    } in links\n    mock_warn.assert_not_called()\n\n\n@patch(\"reflex.config.get_config\")\n@patch(\"reflex.utils.console.warn\")\ndef test_generate_links_for_sitemap_dynamic_routes(\n    mock_warn: MagicMock, mock_get_config: MagicMock\n):\n    \"\"\"Test generate_links_for_sitemap with dynamic routes.\n\n    Args:\n        mock_warn: Mock for the console.warn function.\n        mock_get_config: Mock for the get_config function.\n    \"\"\"\n    mock_get_config.return_value.deploy_url = \"https://sub.example.org\"\n    now = datetime.datetime(2023, 6, 13, 12, 0, 0)\n\n    def mock_component():\n        return rx.text(\"Test\")\n\n    pages = [\n        UnevaluatedPage(\n            component=mock_component,\n            route=\"blog/[id]\",\n            title=None,\n            description=None,\n            image=\"favicon.ico\",\n            on_load=None,\n            meta=[],\n            context={\n                \"sitemap\": {\n                    \"loc\": \"/custom-blog-path\",\n                    \"lastmod\": now,\n                    \"priority\": 0.9,\n                }\n            },\n        ),\n        UnevaluatedPage(\n            component=mock_component,\n            route=\"products/[name]\",\n            title=None,\n            description=None,\n            image=\"favicon.ico\",\n            on_load=None,\n            meta=[],\n            context={},\n        ),  # No sitemap config\n        UnevaluatedPage(\n            component=mock_component,\n            route=\"user/[user_id]/profile\",\n            title=None,\n            description=None,\n            image=\"favicon.ico\",\n            on_load=None,\n            meta=[],\n            context={\"sitemap\": {\"changefreq\": \"yearly\"}},\n        ),  # Has sitemap config but no loc\n    ]\n    links = generate_links_for_sitemap(pages)\n    assert len(links) == 1\n    expected_link = {\n        \"loc\": \"https://sub.example.org/custom-blog-path\",\n        \"lastmod\": now,\n        \"priority\": 0.9,\n    }\n    assert expected_link in links\n    assert mock_warn.call_count == 1\n    mock_warn.assert_any_call(\n        \"Dynamic route 'user/[user_id]/profile' does not have a 'loc' in sitemap configuration. Skipping.\"\n    )\n\n\n@patch(\"reflex.config.get_config\")\n@patch(\"reflex.utils.console.warn\")\ndef test_generate_links_for_sitemap_404_route(\n    mock_warn: MagicMock, mock_get_config: MagicMock\n):\n    \"\"\"Test generate_links_for_sitemap with the 404 route.\n\n    Args:\n        mock_warn: Mock for the console.warn function.\n        mock_get_config: Mock for the get_config function.\n    \"\"\"\n    mock_get_config.return_value.deploy_url = None  # No deploy URL\n\n    def mock_component():\n        return rx.text(\"404\")\n\n    pages = [\n        UnevaluatedPage(\n            component=mock_component,\n            route=\"404\",\n            title=None,\n            description=None,\n            image=\"favicon.ico\",\n            on_load=None,\n            meta=[],\n            context={\"sitemap\": {\"loc\": \"/custom-404\", \"priority\": 0.1}},\n        ),\n        UnevaluatedPage(\n            component=mock_component,\n            route=\"404\",\n            title=None,\n            description=None,\n            image=\"favicon.ico\",\n            on_load=None,\n            meta=[],\n            context={\"sitemap\": {\"priority\": 0.2}},\n        ),  # Has sitemap config but no loc\n    ]\n    links = generate_links_for_sitemap(pages)\n    assert len(links) == 1\n    assert {\"loc\": \"/custom-404\", \"priority\": 0.1} in links\n    mock_warn.assert_called_once_with(\n        \"Route 404 '404' does not have a 'loc' in sitemap configuration. Skipping.\"\n    )\n\n\n@patch(\"reflex.config.get_config\")\ndef test_generate_links_for_sitemap_opt_out(mock_get_config: MagicMock):\n    \"\"\"Test generate_links_for_sitemap with sitemap set to None.\n\n    Args:\n        mock_get_config: Mock for the get_config function.\n    \"\"\"\n    mock_get_config.return_value.deploy_url = None  # No deploy URL\n\n    def mock_component():\n        return rx.text(\"Unlisted\")\n\n    pages = [\n        UnevaluatedPage(\n            component=mock_component,\n            route=\"unlisted\",\n            title=None,\n            description=None,\n            image=\"favicon.ico\",\n            on_load=None,\n            meta=[],\n            context={\"sitemap\": None},\n        ),\n        UnevaluatedPage(\n            component=mock_component,\n            route=\"listed\",\n            title=None,\n            description=None,\n            image=\"favicon.ico\",\n            on_load=None,\n            meta=[],\n            context={},\n        ),\n    ]\n    links = generate_links_for_sitemap(pages)\n    assert len(links) == 1\n    assert {\"loc\": \"/listed\"} in links\n\n\n@patch(\"reflex.config.get_config\")\ndef test_generate_links_for_sitemap_loc_override(mock_get_config: MagicMock):\n    \"\"\"Test generate_links_for_sitemap with loc override in sitemap config.\n\n    Args:\n        mock_get_config: Mock for the get_config function.\n    \"\"\"\n    mock_get_config.return_value.deploy_url = \"http://localhost:3000\"\n\n    def mock_component():\n        return rx.text(\"Test\")\n\n    pages = [\n        UnevaluatedPage(\n            component=mock_component,\n            route=\"features\",\n            title=None,\n            description=None,\n            image=\"favicon.ico\",\n            on_load=None,\n            meta=[],\n            context={\"sitemap\": {\"loc\": \"https://override.com/features_page\"}},\n        ),\n        UnevaluatedPage(\n            component=mock_component,\n            route=\"pricing\",\n            title=None,\n            description=None,\n            image=\"favicon.ico\",\n            on_load=None,\n            meta=[],\n            context={\"sitemap\": {\"loc\": \"/custom_pricing\"}},\n        ),\n    ]\n    links = generate_links_for_sitemap(pages)\n    assert len(links) == 2\n    assert {\"loc\": \"https://override.com/features_page\"} in links\n    assert {\"loc\": \"http://localhost:3000/custom_pricing\"} in links\n\n\n@patch(\"reflex.config.get_config\")\ndef test_generate_links_for_sitemap_priority_clamping(mock_get_config: MagicMock):\n    \"\"\"Test that priority is clamped between 0.0 and 1.0.\n\n    Args:\n        mock_get_config: Mock for the get_config function.\n    \"\"\"\n    mock_get_config.return_value.deploy_url = \"https://example.com\"\n\n    def mock_component():\n        return rx.text(\"Test\")\n\n    pages = [\n        UnevaluatedPage(\n            component=mock_component,\n            route=\"high_prio\",\n            title=None,\n            description=None,\n            image=\"favicon.ico\",\n            on_load=None,\n            meta=[],\n            context={\"sitemap\": {\"priority\": 1.5}},\n        ),\n        UnevaluatedPage(\n            component=mock_component,\n            route=\"low_prio\",\n            title=None,\n            description=None,\n            image=\"favicon.ico\",\n            on_load=None,\n            meta=[],\n            context={\"sitemap\": {\"priority\": -0.5}},\n        ),\n        UnevaluatedPage(\n            component=mock_component,\n            route=\"valid_prio\",\n            title=None,\n            description=None,\n            image=\"favicon.ico\",\n            on_load=None,\n            meta=[],\n            context={\"sitemap\": {\"priority\": 0.5}},\n        ),\n    ]\n    links = generate_links_for_sitemap(pages)\n    expected_links = [\n        {\"loc\": \"https://example.com/high_prio\", \"priority\": 1.0},\n        {\"loc\": \"https://example.com/low_prio\", \"priority\": 0.0},\n        {\"loc\": \"https://example.com/valid_prio\", \"priority\": 0.5},\n    ]\n    for expected_link in expected_links:\n        assert expected_link in links\n\n\n@patch(\"reflex.config.get_config\")\ndef test_generate_links_for_sitemap_no_deploy_url(mock_get_config: MagicMock):\n    \"\"\"Test generate_links_for_sitemap when deploy_url is not set.\n\n    Args:\n        mock_get_config: Mock for the get_config function.\n    \"\"\"\n    mock_get_config.return_value.deploy_url = None\n\n    def mock_component():\n        return rx.text(\"Test\")\n\n    pages = [\n        UnevaluatedPage(\n            component=mock_component,\n            route=\"home\",\n            title=None,\n            description=None,\n            image=\"favicon.ico\",\n            on_load=None,\n            meta=[],\n            context={\"sitemap\": {\"loc\": \"/home\"}},\n        ),\n        UnevaluatedPage(\n            component=mock_component,\n            route=\"about\",\n            title=None,\n            description=None,\n            image=\"favicon.ico\",\n            on_load=None,\n            meta=[],\n            context={},\n        ),  # No loc, should use route\n        UnevaluatedPage(\n            component=mock_component,\n            route=\"index\",\n            title=None,\n            description=None,\n            image=\"favicon.ico\",\n            on_load=None,\n            meta=[],\n            context={},\n        ),  # Special case for index\n    ]\n    links = generate_links_for_sitemap(pages)\n    assert len(links) == 3\n    expected_links = [{\"loc\": \"/home\"}, {\"loc\": \"/about\"}, {\"loc\": \"/\"}]\n    for expected_link in expected_links:\n        assert expected_link in links\n\n\n@patch(\"reflex.config.get_config\")\ndef test_generate_links_for_sitemap_deploy_url_trailing_slash(\n    mock_get_config: MagicMock,\n):\n    \"\"\"Test generate_links_for_sitemap with deploy_url having a trailing slash.\n\n    Args:\n        mock_get_config: Mock for the get_config function.\n    \"\"\"\n    mock_get_config.return_value.deploy_url = \"https://example.com/\"\n\n    def mock_component():\n        return rx.text(\"Test\")\n\n    pages = [\n        UnevaluatedPage(\n            component=mock_component,\n            route=\"testpage\",\n            title=None,\n            description=None,\n            image=\"favicon.ico\",\n            on_load=None,\n            meta=[],\n            context={},\n        ),\n    ]\n    links = generate_links_for_sitemap(pages)\n    assert len(links) == 1\n    assert {\"loc\": \"https://example.com/testpage\"} in links\n\n\n@patch(\"reflex.config.get_config\")\ndef test_generate_links_for_sitemap_loc_leading_slash(mock_get_config: MagicMock):\n    \"\"\"Test generate_links_for_sitemap with loc having a leading slash.\n\n    Args:\n        mock_get_config: Mock for the get_config function.\n    \"\"\"\n    mock_get_config.return_value.deploy_url = \"https://example.com\"\n\n    def mock_component():\n        return rx.text(\"Test\")\n\n    pages = [\n        UnevaluatedPage(\n            component=mock_component,\n            route=\"another\",\n            title=None,\n            description=None,\n            image=\"favicon.ico\",\n            on_load=None,\n            meta=[],\n            context={\"sitemap\": {\"loc\": \"/another\"}},\n        ),\n    ]\n    links = generate_links_for_sitemap(pages)\n    assert len(links) == 1\n    assert {\"loc\": \"https://example.com/another\"} in links\n\n\n@patch(\"reflex.config.get_config\")\ndef test_generate_links_for_sitemap_loc_full_url(mock_get_config: MagicMock):\n    \"\"\"Test generate_links_for_sitemap with loc being a full URL.\n\n    Args:\n        mock_get_config: Mock for the get_config function.\n    \"\"\"\n    mock_get_config.return_value.deploy_url = \"https://example.com\"\n\n    def mock_component():\n        return rx.text(\"Test\")\n\n    pages = [\n        UnevaluatedPage(\n            component=mock_component,\n            route=\"external\",\n            title=None,\n            description=None,\n            image=\"favicon.ico\",\n            on_load=None,\n            meta=[],\n            context={\"sitemap\": {\"loc\": \"http://othersite.com/page\"}},\n        ),\n    ]\n    links = generate_links_for_sitemap(pages)\n    assert len(links) == 1\n    assert {\"loc\": \"http://othersite.com/page\"} in links\n"
  },
  {
    "path": "tests/units/states/__init__.py",
    "content": "\"\"\"Common rx.BaseState subclasses for use in tests.\"\"\"\n\nfrom reflex.state import BaseState\n\n\nclass GenState(BaseState):\n    \"\"\"A state with event handlers that generate multiple updates.\"\"\"\n\n    value: int\n\n    def go(self, c: int):\n        \"\"\"Increment the value c times and update each time.\n\n        Args:\n            c: The number of times to increment.\n\n        Yields:\n            After each increment.\n        \"\"\"\n        for _ in range(c):\n            self.value += 1\n            yield\n"
  },
  {
    "path": "tests/units/states/mutation.py",
    "content": "\"\"\"Test states for mutable vars.\"\"\"\n\nimport reflex as rx\nfrom reflex.state import BaseState\n\n\nclass OtherBase(rx.Base):\n    \"\"\"A Base model with a str field.\"\"\"\n\n    bar: str = \"\"\n\n\nclass CustomVar(rx.Base):\n    \"\"\"A Base model with multiple fields.\"\"\"\n\n    foo: str = \"\"\n    array: list[str] = []\n    hashmap: dict[str, str] = {}\n    test_set: set[str] = set()\n    custom: OtherBase = OtherBase()\n\n\nclass MutableTestState(BaseState):\n    \"\"\"A test state without SQLAlchemy dependencies.\"\"\"\n\n    array: list[str | int | list | dict[str, str]] = [\n        \"value\",\n        [1, 2, 3],\n        {\"key\": \"value\"},\n    ]\n    hashmap: dict[str, list | str | dict[str, str | dict]] = {\n        \"key\": [\"list\", \"of\", \"values\"],\n        \"another_key\": \"another_value\",\n        \"third_key\": {\"key\": \"value\"},\n    }\n    test_set: set[str | int] = {1, 2, 3, 4, \"five\"}\n    custom: CustomVar = CustomVar()\n    _be_custom: CustomVar = CustomVar()\n\n    def reassign_mutables(self):\n        \"\"\"Assign mutable fields to different values.\"\"\"\n        self.array = [\"modified_value\", [1, 2, 3], {\"mod_key\": \"mod_value\"}]\n        self.hashmap = {\n            \"mod_key\": [\"list\", \"of\", \"values\"],\n            \"mod_another_key\": \"another_value\",\n            \"mod_third_key\": {\"key\": \"value\"},\n        }\n        self.test_set = {1, 2, 3, 4, \"five\"}\n\n    def _get_array(self) -> list[str | int | list | dict[str, str]]:\n        return self.array\n"
  },
  {
    "path": "tests/units/states/upload.py",
    "content": "\"\"\"Test states for upload-related tests.\"\"\"\n\nfrom pathlib import Path\n\nimport reflex as rx\nfrom reflex.state import BaseState, State\n\n\nclass UploadBaseState(BaseState):\n    \"\"\"The base state for uploading a file.\"\"\"\n\n\nclass UploadState(BaseState):\n    \"\"\"The base state for uploading a file.\"\"\"\n\n    async def handle_upload1(self, files: list[rx.UploadFile]):\n        \"\"\"Handle the upload of a file.\n\n        Args:\n            files: The uploaded files.\n        \"\"\"\n\n\nclass SubUploadState(UploadBaseState):\n    \"\"\"The test substate.\"\"\"\n\n    img: str\n\n    async def handle_upload(self, files: list[rx.UploadFile]):\n        \"\"\"Handle the upload of a file.\n\n        Args:\n            files: The uploaded files.\n        \"\"\"\n\n\nclass _FileUploadMixin(BaseState, mixin=True):\n    \"\"\"Common fields and handlers for upload state tests.\"\"\"\n\n    img_list: list[str]\n    _tmp_path: Path = Path()\n\n    async def handle_upload2(self, files):\n        \"\"\"Handle the upload of a file.\n\n        Args:\n            files: The uploaded files.\n        \"\"\"\n\n    async def multi_handle_upload(self, files: list[rx.UploadFile]):\n        \"\"\"Handle the upload of a file.\n\n        Args:\n            files: The uploaded files.\n        \"\"\"\n        for file in files:\n            upload_data = await file.read()\n            assert file.name is not None\n            outfile = self._tmp_path / file.name\n\n            # Save the file.\n            outfile.write_bytes(upload_data)\n\n            # Update the img var.\n            self.img_list.append(file.name)\n            yield\n\n    @rx.event(background=True)\n    async def bg_upload(self, files: list[rx.UploadFile]):\n        \"\"\"Background task cannot be upload handler.\n\n        Args:\n            files: The uploaded files.\n        \"\"\"\n\n\nclass FileUploadState(_FileUploadMixin, State):\n    \"\"\"The base state for uploading a file.\"\"\"\n\n\nclass FileStateBase1(State):\n    \"\"\"The base state for a child FileUploadState.\"\"\"\n\n\nclass ChildFileUploadState(_FileUploadMixin, FileStateBase1):\n    \"\"\"The child state for uploading a file.\"\"\"\n\n\nclass FileStateBase2(FileStateBase1):\n    \"\"\"The parent state for a grandchild FileUploadState.\"\"\"\n\n\nclass GrandChildFileUploadState(_FileUploadMixin, FileStateBase2):\n    \"\"\"The child state for uploading a file.\"\"\"\n"
  },
  {
    "path": "tests/units/test_app.py",
    "content": "from __future__ import annotations\n\nimport asyncio\nimport functools\nimport io\nimport json\nimport unittest.mock\nimport uuid\nfrom collections.abc import Generator\nfrom contextlib import nullcontext as does_not_raise\nfrom importlib.util import find_spec\nfrom pathlib import Path\nfrom typing import TYPE_CHECKING, Any, ClassVar\nfrom unittest.mock import AsyncMock\n\nimport pytest\nfrom pytest_mock import MockerFixture\nfrom starlette.applications import Starlette\nfrom starlette.datastructures import FormData, UploadFile\nfrom starlette.responses import StreamingResponse\n\nimport reflex as rx\nfrom reflex import AdminDash, constants\nfrom reflex.app import (\n    App,\n    ComponentCallable,\n    default_overlay_component,\n    process,\n    upload,\n)\nfrom reflex.components import Component\nfrom reflex.components.base.bare import Bare\nfrom reflex.components.base.fragment import Fragment\nfrom reflex.components.core.cond import Cond\nfrom reflex.components.radix.themes.typography.text import Text\nfrom reflex.constants.state import FIELD_MARKER\nfrom reflex.environment import environment\nfrom reflex.event import Event\nfrom reflex.istate.manager.disk import StateManagerDisk\nfrom reflex.istate.manager.memory import StateManagerMemory\nfrom reflex.istate.manager.redis import StateManagerRedis\nfrom reflex.middleware import HydrateMiddleware\nfrom reflex.model import Model\nfrom reflex.state import (\n    BaseState,\n    OnLoadInternalState,\n    RouterData,\n    State,\n    StateUpdate,\n    _substate_key,\n)\nfrom reflex.style import Style\nfrom reflex.utils import console, exceptions, format\nfrom reflex.vars.base import computed_var\n\nfrom .conftest import chdir\nfrom .states import GenState\nfrom .states.upload import (\n    ChildFileUploadState,\n    FileStateBase1,\n    FileUploadState,\n    GrandChildFileUploadState,\n)\n\n\nclass EmptyState(BaseState):\n    \"\"\"An empty state.\"\"\"\n\n\n@pytest.fixture\ndef index_page() -> ComponentCallable:\n    \"\"\"An index page.\n\n    Returns:\n        The index page.\n    \"\"\"\n\n    def index():\n        return rx.box(\"Index\")\n\n    return index\n\n\n@pytest.fixture\ndef about_page() -> ComponentCallable:\n    \"\"\"An about page.\n\n    Returns:\n        The about page.\n    \"\"\"\n\n    def about():\n        return rx.box(\"About\")\n\n    return about\n\n\nclass ATestState(BaseState):\n    \"\"\"A simple state for testing.\"\"\"\n\n    var: int\n\n\n@pytest.fixture\ndef test_state() -> type[BaseState]:\n    \"\"\"A default state.\n\n    Returns:\n        A default state.\n    \"\"\"\n    return ATestState\n\n\n@pytest.fixture\ndef redundant_test_state() -> type[BaseState]:\n    \"\"\"A default state.\n\n    Returns:\n        A default state.\n    \"\"\"\n\n    class RedundantTestState(BaseState):\n        var: int\n\n    return RedundantTestState\n\n\n@pytest.fixture(scope=\"session\")\ndef test_model() -> type[Model]:\n    \"\"\"A default model.\n\n    Returns:\n        A default model.\n    \"\"\"\n\n    class TestModel(Model, table=True):\n        pass\n\n    return TestModel\n\n\n@pytest.fixture(scope=\"session\")\ndef test_model_auth() -> type[Model]:\n    \"\"\"A default model.\n\n    Returns:\n        A default model.\n    \"\"\"\n\n    class TestModelAuth(Model, table=True):\n        \"\"\"A test model with auth.\"\"\"\n\n    return TestModelAuth\n\n\n@pytest.fixture\ndef test_get_engine():\n    \"\"\"A default database engine.\n\n    Returns:\n        A default database engine.\n    \"\"\"\n    import sqlmodel\n\n    enable_admin = True\n    url = \"sqlite:///test.db\"\n    return sqlmodel.create_engine(\n        url,\n        echo=False,\n        connect_args={\"check_same_thread\": False} if enable_admin else {},\n    )\n\n\nif TYPE_CHECKING:\n    from starlette_admin.auth import AuthProvider\n\n\n@pytest.fixture\ndef test_custom_auth_admin() -> type[AuthProvider]:\n    \"\"\"A default auth provider.\n\n    Returns:\n        A default default auth provider.\n    \"\"\"\n    from starlette_admin.auth import AuthProvider\n\n    class TestAuthProvider(AuthProvider):\n        \"\"\"A test auth provider.\"\"\"\n\n        login_path: str = \"/login\"\n        logout_path: str = \"/logout\"\n\n        def login(self):  # pyright: ignore [reportIncompatibleMethodOverride]\n            \"\"\"Login.\"\"\"\n\n        def is_authenticated(self):  # pyright: ignore [reportIncompatibleMethodOverride]\n            \"\"\"Is authenticated.\"\"\"\n\n        def get_admin_user(self):  # pyright: ignore [reportIncompatibleMethodOverride]\n            \"\"\"Get admin user.\"\"\"\n\n        def logout(self):  # pyright: ignore [reportIncompatibleMethodOverride]\n            \"\"\"Logout.\"\"\"\n\n    return TestAuthProvider\n\n\ndef test_default_app(app: App):\n    \"\"\"Test creating an app with no args.\n\n    Args:\n        app: The app to test.\n    \"\"\"\n    assert app._middlewares == [HydrateMiddleware()]\n    assert app.style == Style()\n    assert app.admin_dash is None\n\n\ndef test_multiple_states_error(monkeypatch, test_state, redundant_test_state):\n    \"\"\"Test that an error is thrown when multiple classes subclass rx.BaseState.\n\n    Args:\n        monkeypatch: Pytest monkeypatch object.\n        test_state: A test state subclassing rx.BaseState.\n        redundant_test_state: Another test state subclassing rx.BaseState.\n    \"\"\"\n    monkeypatch.delenv(constants.PYTEST_CURRENT_TEST)\n    with pytest.raises(ValueError):\n        App()\n\n\ndef test_add_page_default_route(app: App, index_page, about_page):\n    \"\"\"Test adding a page to an app.\n\n    Args:\n        app: The app to test.\n        index_page: The index page.\n        about_page: The about page.\n    \"\"\"\n    assert app._pages == {}\n    assert app._unevaluated_pages == {}\n    app.add_page(index_page)\n    app._compile_page(\"index\")\n    assert app._pages.keys() == {\"index\"}\n    app.add_page(about_page)\n    app._compile_page(\"about\")\n    assert app._pages.keys() == {\"index\", \"about\"}\n\n\ndef test_add_page_set_route(app: App, index_page):\n    \"\"\"Test adding a page to an app.\n\n    Args:\n        app: The app to test.\n        index_page: The index page.\n    \"\"\"\n    route = \"/test\"\n    assert app._unevaluated_pages == {}\n    app.add_page(index_page, route=route)\n    app._compile_page(\"test\")\n    assert app._pages.keys() == {\"test\"}\n\n\ndef test_add_page_set_route_dynamic(index_page):\n    \"\"\"Test adding a page with dynamic route variable to an app.\n\n    Args:\n        index_page: The index page.\n    \"\"\"\n    app = App(_state=EmptyState)\n    assert app._state is not None\n    route = \"/test/[dynamic]\"\n    assert app._unevaluated_pages == {}\n    app.add_page(index_page, route=route)\n    app._compile_page(\"test/[dynamic]\")\n    assert app._pages.keys() == {\"test/[dynamic]\"}\n    assert \"dynamic\" in app._state.computed_vars\n    assert app._state.computed_vars[\"dynamic\"]._deps(objclass=EmptyState) == {\n        EmptyState.get_full_name(): {constants.ROUTER},\n    }\n    assert constants.ROUTER in app._state()._var_dependencies\n\n\ndef test_add_page_set_route_nested(app: App, index_page):\n    \"\"\"Test adding a page to an app.\n\n    Args:\n        app: The app to test.\n        index_page: The index page.\n    \"\"\"\n    route = \"test/nested\"\n    assert app._unevaluated_pages == {}\n    app.add_page(index_page, route=route)\n    assert app._unevaluated_pages.keys() == {route}\n\n\ndef test_add_page_invalid_api_route(app: App, index_page):\n    \"\"\"Test adding a page with an invalid route to an app.\n\n    Args:\n        app: The app to test.\n        index_page: The index page.\n    \"\"\"\n    app.add_page(index_page, route=\"api\")\n    app.add_page(index_page, route=\"/api\")\n    app.add_page(index_page, route=\"/api/\")\n    app.add_page(index_page, route=\"api/foo\")\n    app.add_page(index_page, route=\"/api/foo\")\n    # These should be fine\n    app.add_page(index_page, route=\"api2\")\n    app.add_page(index_page, route=\"/foo/api\")\n\n\ndef page1():\n    return rx.fragment()\n\n\ndef page2():\n    return rx.fragment()\n\n\ndef index():\n    return rx.fragment()\n\n\n@pytest.mark.parametrize(\n    (\"first_page\", \"second_page\", \"route\"),\n    [\n        (index, index, None),\n        (page1, page1, None),\n    ],\n)\ndef test_add_the_same_page(\n    mocker: MockerFixture, app: App, first_page, second_page, route\n):\n    app.add_page(first_page, route=route)\n    mock_object = mocker.Mock()\n    mocker.patch.object(\n        console,\n        \"warn\",\n        mock_object,\n    )\n    app.add_page(second_page, route=\"/\" + route.strip(\"/\") if route else None)\n    assert mock_object.call_count == 1\n\n\n@pytest.mark.parametrize(\n    (\"first_page\", \"second_page\", \"route\"),\n    [\n        (lambda: rx.fragment(), lambda: rx.fragment(rx.text(\"second\")), \"/\"),\n        (rx.fragment(rx.text(\"first\")), rx.fragment(rx.text(\"second\")), \"/page1\"),\n        (\n            lambda: rx.fragment(rx.text(\"first\")),\n            rx.fragment(rx.text(\"second\")),\n            \"page3\",\n        ),\n        (page1, page2, \"page1\"),\n    ],\n)\ndef test_add_duplicate_page_route_error(app: App, first_page, second_page, route):\n    app.add_page(first_page, route=route)\n    with pytest.raises(ValueError):\n        app.add_page(second_page, route=\"/\" + route.strip(\"/\") if route else None)\n\n\n@pytest.mark.skipif(\n    not find_spec(\"starlette_admin\")\n    or not find_spec(\"sqlmodel\")\n    or not find_spec(\"pydantic\"),\n    reason=\"starlette_admin not installed or sqlmodel not installed or pydantic not installed\",\n)\ndef test_initialize_with_admin_dashboard(test_model):\n    \"\"\"Test setting the admin dashboard of an app.\n\n    Args:\n        test_model: The default model.\n    \"\"\"\n    app = App(admin_dash=AdminDash(models=[test_model]))\n    assert app.admin_dash is not None\n    assert len(app.admin_dash.models) > 0\n    assert app.admin_dash.models[0] == test_model\n\n\n@pytest.mark.skipif(\n    not find_spec(\"starlette_admin\")\n    or not find_spec(\"sqlmodel\")\n    or not find_spec(\"pydantic\"),\n    reason=\"starlette_admin not installed or sqlmodel not installed or pydantic not installed\",\n)\ndef test_initialize_with_custom_admin_dashboard(\n    test_get_engine,\n    test_custom_auth_admin,\n    test_model_auth,\n):\n    \"\"\"Test setting the custom admin dashboard of an app.\n\n    Args:\n        test_get_engine: The default database engine.\n        test_model_auth: The default model for an auth admin dashboard.\n        test_custom_auth_admin: The custom auth provider.\n    \"\"\"\n    from starlette_admin.contrib.sqla.admin import Admin\n\n    custom_auth_provider = test_custom_auth_admin()\n    custom_admin = Admin(engine=test_get_engine, auth_provider=custom_auth_provider)\n    app = App(admin_dash=AdminDash(models=[test_model_auth], admin=custom_admin))\n    assert app.admin_dash is not None\n    assert app.admin_dash.admin is not None\n    assert len(app.admin_dash.models) > 0\n    assert app.admin_dash.models[0] == test_model_auth\n    assert app.admin_dash.admin.auth_provider == custom_auth_provider\n\n\n@pytest.mark.skipif(\n    not find_spec(\"starlette_admin\")\n    or not find_spec(\"sqlmodel\")\n    or not find_spec(\"pydantic\"),\n    reason=\"starlette_admin not installed or sqlmodel not installed or pydantic not installed\",\n)\ndef test_initialize_admin_dashboard_with_view_overrides(test_model):\n    \"\"\"Test setting the admin dashboard of an app with view class overridden.\n\n    Args:\n        test_model: The default model.\n    \"\"\"\n    from starlette_admin.contrib.sqla.view import ModelView\n\n    class TestModelView(ModelView):\n        pass\n\n    app = App(\n        admin_dash=AdminDash(\n            models=[test_model], view_overrides={test_model: TestModelView}\n        )\n    )\n    assert app.admin_dash is not None\n    assert app.admin_dash.models == [test_model]\n    assert app.admin_dash.view_overrides[test_model] == TestModelView\n\n\n@pytest.mark.asyncio\nasync def test_initialize_with_state(test_state: type[ATestState], token: str):\n    \"\"\"Test setting the state of an app.\n\n    Args:\n        test_state: The default state.\n        token: a Token.\n    \"\"\"\n    app = App(_state=test_state)\n    assert app._state == test_state\n\n    # Get a state for a given token.\n    state = await app.state_manager.get_state(_substate_key(token, test_state))\n    assert isinstance(state, test_state)\n    assert state.var == 0\n\n    await app.state_manager.close()\n\n\n@pytest.mark.asyncio\nasync def test_set_and_get_state(test_state: type[ATestState]):\n    \"\"\"Test setting and getting the state of an app with different tokens.\n\n    Args:\n        test_state: The default state.\n    \"\"\"\n    app = App(_state=test_state)\n\n    # Create two tokens.\n    token1 = str(uuid.uuid4()) + f\"_{test_state.get_full_name()}\"\n    token2 = str(uuid.uuid4()) + f\"_{test_state.get_full_name()}\"\n\n    # Get the default state for each token.\n    state1 = await app.state_manager.get_state(token1)\n    state2 = await app.state_manager.get_state(token2)\n    assert isinstance(state1, test_state)\n    assert isinstance(state2, test_state)\n    assert state1.var == 0\n    assert state2.var == 0\n\n    # Set the vars to different values.\n    state1.var = 1\n    state2.var = 2\n    await app.state_manager.set_state(token1, state1)\n    await app.state_manager.set_state(token2, state2)\n\n    # Get the states again and check the values.\n    state1 = await app.state_manager.get_state(token1)\n    state2 = await app.state_manager.get_state(token2)\n    assert isinstance(state1, test_state)\n    assert isinstance(state2, test_state)\n    assert state1.var == 1\n    assert state2.var == 2\n\n    await app.state_manager.close()\n\n\n@pytest.mark.asyncio\nasync def test_dynamic_var_event(test_state: type[ATestState], token: str):\n    \"\"\"Test that the default handler of a dynamic generated var\n    works as expected.\n\n    Args:\n        test_state: State Fixture.\n        token: a Token.\n    \"\"\"\n    state = test_state()  # pyright: ignore [reportCallIssue]\n    state.add_var(\"int_val\", int, 0)\n    async for result in state._process(\n        Event(\n            token=token,\n            name=f\"{test_state.get_name()}.set_int_val\",\n            router_data={\"pathname\": \"/\", \"query\": {}},\n            payload={\"value\": 50},\n        )\n    ):\n        assert result.delta == {test_state.get_name(): {\"int_val\" + FIELD_MARKER: 50}}\n\n\n@pytest.fixture\ndef list_mutation_state():\n    \"\"\"Create a state with list mutation features.\n\n    Returns:\n        A state with list mutation features.\n    \"\"\"\n\n    class ListMutationTestState(BaseState):\n        \"\"\"A state for testing ReflexList mutation.\"\"\"\n\n        # plain list\n        plain_friends = [\"Tommy\"]\n\n        def make_friend(self):\n            \"\"\"Add a friend to the list.\"\"\"\n            self.plain_friends.append(\"another-fd\")\n\n        def change_first_friend(self):\n            \"\"\"Change the first friend in the list.\"\"\"\n            self.plain_friends[0] = \"Jenny\"\n\n        def unfriend_all_friends(self):\n            \"\"\"Unfriend all friends in the list.\"\"\"\n            self.plain_friends.clear()\n\n        def unfriend_first_friend(self):\n            \"\"\"Unfriend the first friend in the list.\"\"\"\n            del self.plain_friends[0]\n\n        def remove_last_friend(self):\n            \"\"\"Remove the last friend in the list.\"\"\"\n            self.plain_friends.pop()\n\n        def make_friends_with_colleagues(self):\n            \"\"\"Add list of friends to the list.\"\"\"\n            colleagues = [\"Peter\", \"Jimmy\"]\n            self.plain_friends.extend(colleagues)\n\n        def remove_tommy(self):\n            \"\"\"Remove Tommy from the list.\"\"\"\n            self.plain_friends.remove(\"Tommy\")\n\n        # list in dict\n        friends_in_dict = {\"Tommy\": [\"Jenny\"]}\n\n        def remove_jenny_from_tommy(self):\n            \"\"\"Remove Jenny from Tommy's friends list.\"\"\"\n            self.friends_in_dict[\"Tommy\"].remove(\"Jenny\")\n\n        def add_jimmy_to_tommy_friends(self):\n            \"\"\"Add Jimmy to Tommy's friends list.\"\"\"\n            self.friends_in_dict[\"Tommy\"].append(\"Jimmy\")\n\n        def tommy_has_no_fds(self):\n            \"\"\"Clear Tommy's friends list.\"\"\"\n            self.friends_in_dict[\"Tommy\"].clear()\n\n        # nested list\n        friends_in_nested_list = [[\"Tommy\"], [\"Jenny\"]]\n\n        def remove_first_group(self):\n            \"\"\"Remove the first group of friends from the nested list.\"\"\"\n            self.friends_in_nested_list.pop(0)\n\n        def remove_first_person_from_first_group(self):\n            \"\"\"Remove the first person from the first group of friends in the nested list.\"\"\"\n            self.friends_in_nested_list[0].pop(0)\n\n        def add_jimmy_to_second_group(self):\n            \"\"\"Add Jimmy to the second group of friends in the nested list.\"\"\"\n            self.friends_in_nested_list[1].append(\"Jimmy\")\n\n    return ListMutationTestState()\n\n\n@pytest.mark.asyncio\n@pytest.mark.parametrize(\n    \"event_tuples\",\n    [\n        pytest.param(\n            [\n                (\n                    \"make_friend\",\n                    {\"plain_friends\" + FIELD_MARKER: [\"Tommy\", \"another-fd\"]},\n                ),\n                (\n                    \"change_first_friend\",\n                    {\"plain_friends\" + FIELD_MARKER: [\"Jenny\", \"another-fd\"]},\n                ),\n            ],\n            id=\"append then __setitem__\",\n        ),\n        pytest.param(\n            [\n                (\n                    \"unfriend_first_friend\",\n                    {\"plain_friends\" + FIELD_MARKER: []},\n                ),\n                (\n                    \"make_friend\",\n                    {\"plain_friends\" + FIELD_MARKER: [\"another-fd\"]},\n                ),\n            ],\n            id=\"delitem then append\",\n        ),\n        pytest.param(\n            [\n                (\n                    \"make_friends_with_colleagues\",\n                    {\"plain_friends\" + FIELD_MARKER: [\"Tommy\", \"Peter\", \"Jimmy\"]},\n                ),\n                (\n                    \"remove_tommy\",\n                    {\"plain_friends\" + FIELD_MARKER: [\"Peter\", \"Jimmy\"]},\n                ),\n                (\n                    \"remove_last_friend\",\n                    {\"plain_friends\" + FIELD_MARKER: [\"Peter\"]},\n                ),\n                (\n                    \"unfriend_all_friends\",\n                    {\"plain_friends\" + FIELD_MARKER: []},\n                ),\n            ],\n            id=\"extend, remove, pop, clear\",\n        ),\n        pytest.param(\n            [\n                (\n                    \"add_jimmy_to_second_group\",\n                    {\n                        \"friends_in_nested_list\" + FIELD_MARKER: [\n                            [\"Tommy\"],\n                            [\"Jenny\", \"Jimmy\"],\n                        ]\n                    },\n                ),\n                (\n                    \"remove_first_person_from_first_group\",\n                    {\"friends_in_nested_list\" + FIELD_MARKER: [[], [\"Jenny\", \"Jimmy\"]]},\n                ),\n                (\n                    \"remove_first_group\",\n                    {\"friends_in_nested_list\" + FIELD_MARKER: [[\"Jenny\", \"Jimmy\"]]},\n                ),\n            ],\n            id=\"nested list\",\n        ),\n        pytest.param(\n            [\n                (\n                    \"add_jimmy_to_tommy_friends\",\n                    {\"friends_in_dict\" + FIELD_MARKER: {\"Tommy\": [\"Jenny\", \"Jimmy\"]}},\n                ),\n                (\n                    \"remove_jenny_from_tommy\",\n                    {\"friends_in_dict\" + FIELD_MARKER: {\"Tommy\": [\"Jimmy\"]}},\n                ),\n                (\n                    \"tommy_has_no_fds\",\n                    {\"friends_in_dict\" + FIELD_MARKER: {\"Tommy\": []}},\n                ),\n            ],\n            id=\"list in dict\",\n        ),\n    ],\n)\nasync def test_list_mutation_detection__plain_list(\n    event_tuples: list[tuple[str, list[str]]],\n    list_mutation_state: State,\n    token: str,\n):\n    \"\"\"Test list mutation detection\n    when reassignment is not explicitly included in the logic.\n\n    Args:\n        event_tuples: From parametrization.\n        list_mutation_state: A state with list mutation features.\n        token: a Token.\n    \"\"\"\n    for event_name, expected_delta in event_tuples:\n        async for result in list_mutation_state._process(\n            Event(\n                token=token,\n                name=f\"{list_mutation_state.get_name()}.{event_name}\",\n                router_data={\"pathname\": \"/\", \"query\": {}},\n                payload={},\n            )\n        ):\n            # prefix keys in expected_delta with the state name\n            expected_delta = {list_mutation_state.get_name(): expected_delta}\n            assert result.delta == expected_delta\n\n\n@pytest.fixture\ndef dict_mutation_state():\n    \"\"\"Create a state with dict mutation features.\n\n    Returns:\n        A state with dict mutation features.\n    \"\"\"\n\n    class DictMutationTestState(BaseState):\n        \"\"\"A state for testing ReflexDict mutation.\"\"\"\n\n        # plain dict\n        details = {\"name\": \"Tommy\"}\n\n        def add_age(self):\n            \"\"\"Add an age to the dict.\"\"\"\n            self.details.update({\"age\": 20})  # pyright: ignore [reportCallIssue, reportArgumentType]\n\n        def change_name(self):\n            \"\"\"Change the name in the dict.\"\"\"\n            self.details[\"name\"] = \"Jenny\"\n\n        def remove_last_detail(self):\n            \"\"\"Remove the last item in the dict.\"\"\"\n            self.details.popitem()\n\n        def clear_details(self):\n            \"\"\"Clear the dict.\"\"\"\n            self.details.clear()\n\n        def remove_name(self):\n            \"\"\"Remove the name from the dict.\"\"\"\n            del self.details[\"name\"]\n\n        def pop_out_age(self):\n            \"\"\"Pop out the age from the dict.\"\"\"\n            self.details.pop(\"age\")\n\n        # dict in list\n        address = [{\"home\": \"home address\"}, {\"work\": \"work address\"}]\n\n        def remove_home_address(self):\n            \"\"\"Remove the home address from dict in the list.\"\"\"\n            self.address[0].pop(\"home\")\n\n        def add_street_to_home_address(self):\n            \"\"\"Set street key in the dict in the list.\"\"\"\n            self.address[0][\"street\"] = \"street address\"\n\n        # nested dict\n        friend_in_nested_dict = {\"name\": \"Nikhil\", \"friend\": {\"name\": \"Alek\"}}\n\n        def change_friend_name(self):\n            \"\"\"Change the friend's name in the nested dict.\"\"\"\n            self.friend_in_nested_dict[\"friend\"][\"name\"] = \"Tommy\"\n\n        def remove_friend(self):\n            \"\"\"Remove the friend from the nested dict.\"\"\"\n            self.friend_in_nested_dict.pop(\"friend\")\n\n        def add_friend_age(self):\n            \"\"\"Add an age to the friend in the nested dict.\"\"\"\n            self.friend_in_nested_dict[\"friend\"][\"age\"] = 30\n\n    return DictMutationTestState()\n\n\n@pytest.mark.asyncio\n@pytest.mark.parametrize(\n    \"event_tuples\",\n    [\n        pytest.param(\n            [\n                (\n                    \"add_age\",\n                    {\"details\" + FIELD_MARKER: {\"name\": \"Tommy\", \"age\": 20}},\n                ),\n                (\n                    \"change_name\",\n                    {\"details\" + FIELD_MARKER: {\"name\": \"Jenny\", \"age\": 20}},\n                ),\n                (\n                    \"remove_last_detail\",\n                    {\"details\" + FIELD_MARKER: {\"name\": \"Jenny\"}},\n                ),\n            ],\n            id=\"update then __setitem__\",\n        ),\n        pytest.param(\n            [\n                (\n                    \"clear_details\",\n                    {\"details\" + FIELD_MARKER: {}},\n                ),\n                (\n                    \"add_age\",\n                    {\"details\" + FIELD_MARKER: {\"age\": 20}},\n                ),\n            ],\n            id=\"delitem then update\",\n        ),\n        pytest.param(\n            [\n                (\n                    \"add_age\",\n                    {\"details\" + FIELD_MARKER: {\"name\": \"Tommy\", \"age\": 20}},\n                ),\n                (\n                    \"remove_name\",\n                    {\"details\" + FIELD_MARKER: {\"age\": 20}},\n                ),\n                (\n                    \"pop_out_age\",\n                    {\"details\" + FIELD_MARKER: {}},\n                ),\n            ],\n            id=\"add, remove, pop\",\n        ),\n        pytest.param(\n            [\n                (\n                    \"remove_home_address\",\n                    {\"address\" + FIELD_MARKER: [{}, {\"work\": \"work address\"}]},\n                ),\n                (\n                    \"add_street_to_home_address\",\n                    {\n                        \"address\" + FIELD_MARKER: [\n                            {\"street\": \"street address\"},\n                            {\"work\": \"work address\"},\n                        ]\n                    },\n                ),\n            ],\n            id=\"dict in list\",\n        ),\n        pytest.param(\n            [\n                (\n                    \"change_friend_name\",\n                    {\n                        \"friend_in_nested_dict\" + FIELD_MARKER: {\n                            \"name\": \"Nikhil\",\n                            \"friend\": {\"name\": \"Tommy\"},\n                        }\n                    },\n                ),\n                (\n                    \"add_friend_age\",\n                    {\n                        \"friend_in_nested_dict\" + FIELD_MARKER: {\n                            \"name\": \"Nikhil\",\n                            \"friend\": {\"name\": \"Tommy\", \"age\": 30},\n                        }\n                    },\n                ),\n                (\n                    \"remove_friend\",\n                    {\"friend_in_nested_dict\" + FIELD_MARKER: {\"name\": \"Nikhil\"}},\n                ),\n            ],\n            id=\"nested dict\",\n        ),\n    ],\n)\nasync def test_dict_mutation_detection__plain_list(\n    event_tuples: list[tuple[str, list[str]]],\n    dict_mutation_state: State,\n    token: str,\n):\n    \"\"\"Test dict mutation detection\n    when reassignment is not explicitly included in the logic.\n\n    Args:\n        event_tuples: From parametrization.\n        dict_mutation_state: A state with dict mutation features.\n        token: a Token.\n    \"\"\"\n    for event_name, expected_delta in event_tuples:\n        async for result in dict_mutation_state._process(\n            Event(\n                token=token,\n                name=f\"{dict_mutation_state.get_name()}.{event_name}\",\n                router_data={\"pathname\": \"/\", \"query\": {}},\n                payload={},\n            )\n        ):\n            # prefix keys in expected_delta with the state name\n            expected_delta = {dict_mutation_state.get_name(): expected_delta}\n\n            assert result.delta == expected_delta\n\n\n@pytest.mark.asyncio\n@pytest.mark.parametrize(\n    (\"state\", \"delta\"),\n    [\n        (\n            FileUploadState,\n            {\n                FileUploadState.get_full_name(): {\n                    \"img_list\" + FIELD_MARKER: [\"image1.jpg\", \"image2.jpg\"]\n                }\n            },\n        ),\n        (\n            ChildFileUploadState,\n            {\n                ChildFileUploadState.get_full_name(): {\n                    \"img_list\" + FIELD_MARKER: [\"image1.jpg\", \"image2.jpg\"]\n                }\n            },\n        ),\n        (\n            GrandChildFileUploadState,\n            {\n                GrandChildFileUploadState.get_full_name(): {\n                    \"img_list\" + FIELD_MARKER: [\"image1.jpg\", \"image2.jpg\"]\n                }\n            },\n        ),\n    ],\n)\nasync def test_upload_file(tmp_path, state, delta, token: str, mocker: MockerFixture):\n    \"\"\"Test that file upload works correctly.\n\n    Args:\n        tmp_path: Temporary path.\n        state: The state class.\n        delta: Expected delta after processing all files.\n        token: a Token.\n        mocker: pytest mocker object.\n    \"\"\"\n    mocker.patch(\n        \"reflex.state.State.class_subclasses\",\n        {state if state is FileUploadState else FileStateBase1},\n    )\n    # The App state must be the \"root\" of the state tree\n    app = App()\n    app.event_namespace.emit = AsyncMock()  # pyright: ignore [reportOptionalMemberAccess]\n    async with app.modify_state(_substate_key(token, state)) as root_state:\n        root_state.get_substate(state.get_full_name().split(\".\"))._tmp_path = tmp_path\n    data = b\"This is binary data\"\n\n    request_mock = unittest.mock.Mock()\n    request_mock.headers = {\n        \"reflex-client-token\": token,\n        \"reflex-event-handler\": f\"{state.get_full_name()}.multi_handle_upload\",\n    }\n\n    file1 = UploadFile(\n        filename=\"image1.jpg\",\n        file=io.BytesIO(data),\n    )\n    file2 = UploadFile(\n        filename=\"image2.jpg\",\n        file=io.BytesIO(data),\n    )\n\n    async def form():  # noqa: RUF029\n        return FormData([(\"files\", file1), (\"files\", file2)])\n\n    request_mock.form = form\n\n    upload_fn = upload(app)\n    streaming_response = await upload_fn(request_mock)\n    assert isinstance(streaming_response, StreamingResponse)\n    # Handler yields after each file, producing intermediate + final updates.\n    updates = []\n    async for state_update in streaming_response.body_iterator:\n        updates.append(json.loads(str(state_update)))\n    # 2 intermediate yields + 1 final\n    assert len(updates) == 3\n    assert all(not u[\"final\"] for u in updates[:-1])\n    assert updates[-1][\"final\"]\n\n    # The last intermediate update should contain the full cumulative delta.\n    assert updates[1][\"delta\"] == delta\n\n    await app.state_manager.close()\n\n\n@pytest.mark.asyncio\nasync def test_upload_file_keeps_form_open_until_stream_completes(\n    tmp_path,\n    token: str,\n    mocker: MockerFixture,\n):\n    \"\"\"Test that upload files are not eagerly copied into memory.\n\n    Uses two distinct BinaryIO instances, sets _tmp_path via modify_state,\n    and verifies that both file handles remain open during streaming and are\n    closed (along with correct file content) after the stream completes.\n\n    Args:\n        tmp_path: Temporary path.\n        token: A token.\n        mocker: pytest mocker object.\n    \"\"\"\n    mocker.patch(\n        \"reflex.state.State.class_subclasses\",\n        {FileUploadState},\n    )\n    app = App()\n    app.event_namespace.emit = AsyncMock()  # pyright: ignore [reportOptionalMemberAccess]\n\n    # Set _tmp_path via modify_state instead of setting class attribute directly.\n    async with app.modify_state(_substate_key(token, FileUploadState)) as root_state:\n        root_state.get_substate(\n            FileUploadState.get_full_name().split(\".\")\n        )._tmp_path = tmp_path\n\n    request_mock = unittest.mock.Mock()\n    request_mock.headers = {\n        \"reflex-client-token\": token,\n        \"reflex-event-handler\": f\"{FileUploadState.get_full_name()}.multi_handle_upload\",\n    }\n\n    data1 = b\"contents of image one\"\n    data2 = b\"contents of image two\"\n    bio1 = io.BytesIO(data1)\n    bio2 = io.BytesIO(data2)\n    file1 = UploadFile(filename=\"image1.jpg\", file=bio1)\n    file2 = UploadFile(filename=\"image2.jpg\", file=bio2)\n\n    form_data = FormData([(\"files\", file1), (\"files\", file2)])\n    original_close = form_data.close\n    form_close = AsyncMock(side_effect=original_close)\n    form_data.close = form_close\n\n    async def form():  # noqa: RUF029\n        return form_data\n\n    request_mock.form = form\n\n    upload_fn = upload(app)\n    streaming_response = await upload_fn(request_mock)\n\n    assert isinstance(streaming_response, StreamingResponse)\n    # Before streaming starts, nothing should be read or closed.\n    assert form_close.await_count == 0\n    assert not bio1.closed\n    assert not bio2.closed\n\n    # Drive the response through the full ASGI lifecycle so that\n    # _UploadStreamingResponse.__call__ invokes the on_finish callback.\n    scope = {\"type\": \"http\"}\n    done = asyncio.Event()\n\n    async def receive():\n        await done.wait()\n        return {\"type\": \"http.disconnect\"}\n\n    async def send(message):  # noqa: RUF029\n        if message.get(\"type\") == \"http.response.body\" and not message.get(\"body\"):\n            done.set()\n\n    await streaming_response(scope, receive, send)\n\n    # After the ASGI call completes, form_data.close() should have been called,\n    # closing both underlying file handles.\n    assert form_close.await_count == 1\n    assert bio1.closed\n    assert bio2.closed\n\n    # Verify files were written to the tmp dir with the correct content.\n    assert (tmp_path / \"image1.jpg\").read_bytes() == data1\n    assert (tmp_path / \"image2.jpg\").read_bytes() == data2\n\n    await app.state_manager.close()\n\n\n@pytest.mark.asyncio\nasync def test_upload_file_closes_form_on_event_creation_cancellation(\n    token: str,\n    mocker: MockerFixture,\n):\n    \"\"\"Test that cancellation during upload event creation closes form data.\"\"\"\n    mocker.patch(\n        \"reflex.state.State.class_subclasses\",\n        {FileUploadState},\n    )\n    app = App()\n\n    request_mock = unittest.mock.Mock()\n    request_mock.headers = {\n        \"reflex-client-token\": token,\n        \"reflex-event-handler\": f\"{FileUploadState.get_full_name()}.multi_handle_upload\",\n    }\n\n    file1 = UploadFile(filename=\"image1.jpg\", file=io.BytesIO(b\"data\"))\n    form_data = FormData([(\"files\", file1)])\n    original_close = form_data.close\n    form_close = AsyncMock(side_effect=original_close)\n    form_data.close = form_close\n\n    async def form():  # noqa: RUF029\n        return form_data\n\n    async def cancelled_get_state(*_args, **_kwargs):\n        await asyncio.sleep(0)\n        raise asyncio.CancelledError\n\n    request_mock.form = form\n    mocker.patch.object(app.state_manager, \"get_state\", side_effect=cancelled_get_state)\n\n    upload_fn = upload(app)\n    with pytest.raises(asyncio.CancelledError):\n        await upload_fn(request_mock)\n\n    assert form_close.await_count == 1\n    assert file1.file.closed\n\n    await app.state_manager.close()\n\n\n@pytest.mark.asyncio\nasync def test_upload_file_closes_form_if_response_cancelled_before_stream_starts(\n    tmp_path,\n    token: str,\n    mocker: MockerFixture,\n):\n    \"\"\"Test that response cancellation before iteration still closes form data.\"\"\"\n    mocker.patch(\n        \"reflex.state.State.class_subclasses\",\n        {FileUploadState},\n    )\n    app = App()\n    app.event_namespace.emit = AsyncMock()  # pyright: ignore [reportOptionalMemberAccess]\n\n    async with app.modify_state(_substate_key(token, FileUploadState)) as root_state:\n        root_state.get_substate(\n            FileUploadState.get_full_name().split(\".\")\n        )._tmp_path = tmp_path\n\n    request_mock = unittest.mock.Mock()\n    request_mock.headers = {\n        \"reflex-client-token\": token,\n        \"reflex-event-handler\": f\"{FileUploadState.get_full_name()}.multi_handle_upload\",\n    }\n\n    bio = io.BytesIO(b\"contents of image one\")\n    file1 = UploadFile(filename=\"image1.jpg\", file=bio)\n    form_data = FormData([(\"files\", file1)])\n    original_close = form_data.close\n    form_close = AsyncMock(side_effect=original_close)\n    form_data.close = form_close\n\n    async def form():  # noqa: RUF029\n        return form_data\n\n    async def receive():\n        await asyncio.sleep(0)\n        return {\"type\": \"http.disconnect\"}\n\n    async def send(_message):\n        await asyncio.sleep(0)\n        raise asyncio.CancelledError\n\n    request_mock.form = form\n\n    upload_fn = upload(app)\n    streaming_response = await upload_fn(request_mock)\n\n    assert isinstance(streaming_response, StreamingResponse)\n    assert form_close.await_count == 0\n    assert not bio.closed\n\n    with pytest.raises(asyncio.CancelledError):\n        await streaming_response(\n            {\"type\": \"http\", \"asgi\": {\"spec_version\": \"2.4\"}},\n            receive,\n            send,\n        )\n\n    assert form_close.await_count == 1\n    assert bio.closed\n\n    await app.state_manager.close()\n\n\n@pytest.mark.asyncio\n@pytest.mark.parametrize(\n    \"state\",\n    [FileUploadState, ChildFileUploadState, GrandChildFileUploadState],\n)\nasync def test_upload_file_without_annotation(state, tmp_path, token):\n    \"\"\"Test that an error is thrown when there's no param annotated with rx.UploadFile or list[UploadFile].\n\n    Args:\n        state: The state class.\n        tmp_path: Temporary path.\n        token: a Token.\n    \"\"\"\n    app = App(_state=State)\n\n    request_mock = unittest.mock.Mock()\n    request_mock.headers = {\n        \"reflex-client-token\": token,\n        \"reflex-event-handler\": f\"{state.get_full_name()}.handle_upload2\",\n    }\n\n    file1 = UploadFile(filename=\"image1.jpg\", file=io.BytesIO(b\"data\"))\n\n    async def form():  # noqa: RUF029\n        return FormData([(\"files\", file1)])\n\n    request_mock.form = form\n\n    fn = upload(app)\n    with pytest.raises(ValueError) as err:\n        await fn(request_mock)\n    assert (\n        err.value.args[0]\n        == f\"`{state.get_full_name()}.handle_upload2` handler should have a parameter annotated as list[rx.UploadFile]\"\n    )\n\n    await app.state_manager.close()\n\n\n@pytest.mark.asyncio\n@pytest.mark.parametrize(\n    \"state\",\n    [FileUploadState, ChildFileUploadState, GrandChildFileUploadState],\n)\nasync def test_upload_file_background(state, tmp_path, token):\n    \"\"\"Test that an error is thrown handler is a background task.\n\n    Args:\n        state: The state class.\n        tmp_path: Temporary path.\n        token: a Token.\n    \"\"\"\n    app = App(_state=State)\n\n    request_mock = unittest.mock.Mock()\n    request_mock.headers = {\n        \"reflex-client-token\": token,\n        \"reflex-event-handler\": f\"{state.get_full_name()}.bg_upload\",\n    }\n\n    file1 = UploadFile(filename=\"image1.jpg\", file=io.BytesIO(b\"data\"))\n\n    async def form():  # noqa: RUF029\n        return FormData([(\"files\", file1)])\n\n    request_mock.form = form\n\n    fn = upload(app)\n    with pytest.raises(TypeError) as err:\n        await fn(request_mock)\n    assert (\n        err.value.args[0]\n        == f\"@rx.event(background=True) is not supported for upload handler `{state.get_full_name()}.bg_upload`.\"\n    )\n\n    await app.state_manager.close()\n\n\nclass DynamicState(BaseState):\n    \"\"\"State class for testing dynamic route var.\n\n    This is defined at module level because event handlers cannot be addressed\n    correctly when the class is defined as a local.\n\n    There are several counters:\n      * loaded: counts how many times `on_load` was triggered by the hydrate middleware\n      * counter: counts how many times `on_counter` was triggered by a non-navigational event\n          -> these events should NOT trigger reload or recalculation of router_data dependent vars\n      * side_effect_counter: counts how many times a computed var was\n        recalculated when the dynamic route var was dirty\n    \"\"\"\n\n    is_hydrated: bool = False\n    loaded: int = 0\n    counter: int = 0\n    _app_ref: ClassVar[Any] = None\n\n    @rx.event\n    def on_load(self):\n        \"\"\"Event handler for page on_load, should trigger for all navigation events.\"\"\"\n        self.loaded = self.loaded + 1\n\n    @rx.event\n    def on_counter(self):\n        \"\"\"Increment the counter var.\"\"\"\n        self.counter = self.counter + 1\n\n    @computed_var\n    def comp_dynamic(self) -> str:\n        \"\"\"A computed var that depends on the dynamic var.\n\n        Returns:\n            same as self.dynamic\n        \"\"\"\n        return self.dynamic  # pyright: ignore[reportAttributeAccessIssue]\n\n    on_load_internal = OnLoadInternalState.on_load_internal.fn  # pyright: ignore [reportFunctionMemberAccess]\n\n\ndef test_dynamic_arg_shadow(\n    index_page: ComponentCallable,\n    token: str,\n    app_module_mock: unittest.mock.Mock,\n    mocker: MockerFixture,\n):\n    \"\"\"Create app with dynamic route var and try to add a page with a dynamic arg that shadows a state var.\n\n    Args:\n        index_page: The index page.\n        token: a Token.\n        app_module_mock: Mocked app module.\n        mocker: pytest mocker object.\n    \"\"\"\n    DynamicState._app_ref = None\n    arg_name = \"counter\"\n    route = f\"/test/[{arg_name}]\"\n    app = app_module_mock.app = App(_state=DynamicState)\n    assert app._state is not None\n    with pytest.raises(NameError):\n        app.add_page(index_page, route=route, on_load=DynamicState.on_load)\n\n\ndef test_multiple_dynamic_args(\n    index_page: ComponentCallable,\n    token: str,\n    app_module_mock: unittest.mock.Mock,\n    mocker: MockerFixture,\n):\n    \"\"\"Create app with multiple dynamic route vars with the same name.\n\n    Args:\n        index_page: The index page.\n        token: a Token.\n        app_module_mock: Mocked app module.\n        mocker: pytest mocker object.\n    \"\"\"\n    arg_name = \"my_arg\"\n    route = f\"/test/[{arg_name}]\"\n    route2 = f\"/test2/[{arg_name}]\"\n    app = app_module_mock.app = App(_state=EmptyState)\n    app.add_page(index_page, route=route)\n    app.add_page(index_page, route=route2)\n\n\n@pytest.mark.asyncio\nasync def test_dynamic_route_var_route_change_completed_on_load(\n    index_page: ComponentCallable,\n    token: str,\n    app_module_mock: unittest.mock.Mock,\n    mocker: MockerFixture,\n):\n    \"\"\"Create app with dynamic route var, and simulate navigation.\n\n    on_load should fire, allowing any additional vars to be updated before the\n    initial page hydrate.\n\n    Args:\n        index_page: The index page.\n        token: a Token.\n        app_module_mock: Mocked app module.\n        mocker: pytest mocker object.\n    \"\"\"\n    DynamicState._app_ref = None\n    arg_name = \"dynamic\"\n    route = f\"test/[{arg_name}]\"\n    app = app_module_mock.app = App(_state=DynamicState)\n    assert app._state is not None\n    assert arg_name not in app._state.vars\n    app.add_page(index_page, route=route, on_load=DynamicState.on_load)\n    app._compile_page(route)\n    assert arg_name in app._state.vars\n    assert arg_name in app._state.computed_vars\n    assert app._state.computed_vars[arg_name]._deps(objclass=DynamicState) == {\n        DynamicState.get_full_name(): {constants.ROUTER},\n    }\n    assert constants.ROUTER in app._state()._var_dependencies\n\n    substate_token = _substate_key(token, DynamicState)\n    sid = \"mock_sid\"\n    client_ip = \"127.0.0.1\"\n    async with app.state_manager.modify_state(substate_token) as state:\n        state.router_data = {\"simulate\": \"hydrated\"}\n        assert state.dynamic == \"\"  # pyright: ignore[reportAttributeAccessIssue]\n    exp_vals = [\"foo\", \"foobar\", \"baz\"]\n\n    def _event(name, val, **kwargs):\n        return Event(\n            token=kwargs.pop(\"token\", token),\n            name=name,\n            router_data=kwargs.pop(\n                \"router_data\",\n                {\n                    \"pathname\": \"/\" + route,\n                    \"query\": {arg_name: val},\n                    \"asPath\": \"/test/something\",\n                },\n            ),\n            payload=kwargs.pop(\"payload\", {}),\n            **kwargs,\n        )\n\n    def _dynamic_state_event(name, val, **kwargs):\n        return _event(\n            name=format.format_event_handler(getattr(DynamicState, name)),\n            val=val,\n            **kwargs,\n        )\n\n    prev_exp_val = \"\"\n    for exp_index, exp_val in enumerate(exp_vals):\n        on_load_internal = _event(\n            name=f\"{state.get_full_name()}.{constants.CompileVars.ON_LOAD_INTERNAL.rpartition('.')[2]}\",\n            val=exp_val,\n        )\n        exp_router_data = {\n            \"headers\": {},\n            \"ip\": client_ip,\n            \"sid\": sid,\n            \"token\": token,\n            **on_load_internal.router_data,\n        }\n        exp_router = RouterData.from_router_data(exp_router_data)\n        process_coro = process(\n            app,\n            event=on_load_internal,\n            sid=sid,\n            headers={},\n            client_ip=client_ip,\n        )\n        update = await process_coro.__anext__()\n        # route change (on_load_internal) triggers: [call on_load events, call set_is_hydrated(True)]\n        assert update == StateUpdate(\n            delta={\n                state.get_name(): {\n                    arg_name + FIELD_MARKER: exp_val,\n                    f\"comp_{arg_name}\" + FIELD_MARKER: exp_val,\n                    constants.CompileVars.IS_HYDRATED + FIELD_MARKER: False,\n                    \"router\" + FIELD_MARKER: exp_router,\n                }\n            },\n            events=[\n                _dynamic_state_event(\n                    name=\"on_load\",\n                    val=exp_val,\n                ),\n                _event(\n                    name=f\"{State.get_name()}.set_is_hydrated\",\n                    payload={\"value\": True},\n                    val=exp_val,\n                    router_data={},\n                ),\n            ],\n        )\n        if isinstance(app.state_manager, StateManagerRedis):\n            # When redis is used, the state is not updated until the processing is complete\n            state = await app.state_manager.get_state(substate_token)\n            assert state.dynamic == prev_exp_val  # pyright: ignore[reportAttributeAccessIssue]\n\n        # complete the processing\n        with pytest.raises(StopAsyncIteration):\n            await process_coro.__anext__()\n\n        if environment.REFLEX_OPLOCK_ENABLED.get():\n            await app.state_manager.close()\n\n        # check that router data was written to the state_manager store\n        state = await app.state_manager.get_state(substate_token)\n        assert state.dynamic == exp_val  # pyright: ignore[reportAttributeAccessIssue]\n\n        process_coro = process(\n            app,\n            event=_dynamic_state_event(name=\"on_load\", val=exp_val),\n            sid=sid,\n            headers={},\n            client_ip=client_ip,\n        )\n        on_load_update = await process_coro.__anext__()\n        assert on_load_update == StateUpdate(\n            delta={\n                state.get_name(): {\n                    \"loaded\" + FIELD_MARKER: exp_index + 1,\n                },\n            },\n            events=[],\n        )\n        # complete the processing\n        with pytest.raises(StopAsyncIteration):\n            await process_coro.__anext__()\n        process_coro = process(\n            app,\n            event=_dynamic_state_event(\n                name=\"set_is_hydrated\", payload={\"value\": True}, val=exp_val\n            ),\n            sid=sid,\n            headers={},\n            client_ip=client_ip,\n        )\n        on_set_is_hydrated_update = await process_coro.__anext__()\n        assert on_set_is_hydrated_update == StateUpdate(\n            delta={\n                state.get_name(): {\n                    \"is_hydrated\" + FIELD_MARKER: True,\n                },\n            },\n            events=[],\n        )\n        # complete the processing\n        with pytest.raises(StopAsyncIteration):\n            await process_coro.__anext__()\n\n        # a simple state update event should NOT trigger on_load or route var side effects\n        process_coro = process(\n            app,\n            event=_dynamic_state_event(name=\"on_counter\", val=exp_val),\n            sid=sid,\n            headers={},\n            client_ip=client_ip,\n        )\n        update = await process_coro.__anext__()\n        assert update == StateUpdate(\n            delta={\n                state.get_name(): {\n                    \"counter\" + FIELD_MARKER: exp_index + 1,\n                }\n            },\n            events=[],\n        )\n        # complete the processing\n        with pytest.raises(StopAsyncIteration):\n            await process_coro.__anext__()\n\n        prev_exp_val = exp_val\n\n    if environment.REFLEX_OPLOCK_ENABLED.get():\n        await app.state_manager.close()\n    state = await app.state_manager.get_state(substate_token)\n    assert isinstance(state, DynamicState)\n    assert state.loaded == len(exp_vals)\n    assert state.counter == len(exp_vals)\n\n    await app.state_manager.close()\n\n\n@pytest.mark.asyncio\nasync def test_process_events(mocker: MockerFixture, token: str):\n    \"\"\"Test that an event is processed properly and that it is postprocessed\n    n+1 times. Also check that the processing flag of the last stateupdate is set to\n    False.\n\n    Args:\n        mocker: mocker object.\n        token: a Token.\n    \"\"\"\n    router_data = {\n        \"pathname\": \"/\",\n        \"query\": {},\n        \"token\": token,\n        \"sid\": \"mock_sid\",\n        \"headers\": {},\n        \"ip\": \"127.0.0.1\",\n    }\n    app = App(_state=GenState)\n\n    mocker.patch.object(app, \"_postprocess\", AsyncMock())\n    event = Event(\n        token=token,\n        name=f\"{GenState.get_name()}.go\",\n        payload={\"c\": 5},\n        router_data=router_data,\n    )\n    async with app.state_manager.modify_state(event.substate_token) as state:\n        state.router_data = {\"simulate\": \"hydrated\"}\n\n    async for _update in process(app, event, \"mock_sid\", {}, \"127.0.0.1\"):\n        pass\n\n    if environment.REFLEX_OPLOCK_ENABLED.get():\n        await app.state_manager.close()\n\n    gen_state = await app.state_manager.get_state(event.substate_token)\n    assert isinstance(gen_state, GenState)\n    assert gen_state.value == 5\n    assert app._postprocess.call_count == 6  # pyright: ignore [reportAttributeAccessIssue]\n\n    await app.state_manager.close()\n\n\n@pytest.mark.parametrize(\n    (\"state\", \"overlay_component\", \"exp_page_child\"),\n    [\n        (None, default_overlay_component, Fragment),\n        (None, None, None),\n        (None, Text.create(\"foo\"), Text),\n        (State, default_overlay_component, Fragment),\n        (State, None, None),\n        (State, Text.create(\"foo\"), Text),\n        (State, lambda: Text.create(\"foo\"), Text),\n    ],\n)\ndef test_overlay_component(\n    state: type[State] | None,\n    overlay_component: Component | ComponentCallable | None,\n    exp_page_child: type[Component] | None,\n):\n    \"\"\"Test that the overlay component is set correctly.\n\n    Args:\n        state: The state class to pass to App.\n        overlay_component: The overlay_component to pass to App.\n        exp_page_child: The type of the expected child in the page fragment.\n    \"\"\"\n    app = App(_state=state, overlay_component=overlay_component)\n    app._setup_overlay_component()\n    if exp_page_child is None:\n        assert app.overlay_component is None\n    elif isinstance(exp_page_child, Fragment):\n        assert app.overlay_component is not None\n        generated_component = app._generate_component(app.overlay_component)\n        assert isinstance(generated_component, Fragment)\n        assert isinstance(\n            generated_component.children[0],\n            Cond,  # ConnectionModal is a Cond under the hood\n        )\n    else:\n        assert app.overlay_component is not None\n        assert isinstance(\n            app._generate_component(app.overlay_component),\n            exp_page_child,\n        )\n\n    app.add_page(rx.box(\"Index\"), route=\"/test\")\n    # overlay components are wrapped during compile only\n    app._compile_page(\"test\")\n    app._setup_overlay_component()\n    page = app._pages[\"test\"]\n\n    if exp_page_child is not None:\n        assert len(page.children) == 4\n        children_types = (type(child) for child in page.children)\n        assert exp_page_child in children_types  # pyright: ignore [reportOperatorIssue]\n    else:\n        assert len(page.children) == 3\n\n\n@pytest.fixture\ndef compilable_app(tmp_path) -> Generator[tuple[App, Path], None, None]:\n    \"\"\"Fixture for an app that can be compiled.\n\n    Args:\n        tmp_path: Temporary path.\n\n    Yields:\n        Tuple containing (app instance, Path to \".web\" directory)\n\n        The working directory is set to the app dir (parent of .web),\n        allowing app.compile() to be called.\n    \"\"\"\n    app_path = tmp_path / \"app\"\n    web_dir = app_path / \".web\"\n    web_dir.mkdir(parents=True)\n    (web_dir / constants.PackageJson.PATH).touch()\n    (web_dir / constants.Dirs.POSTCSS_JS).touch()\n    (web_dir / constants.Dirs.POSTCSS_JS).write_text(\n        \"\"\"\nmodule.exports = {\n  plugins: {\n    \"postcss-import\": {},\n    autoprefixer: {},\n  },\n};\n\"\"\",\n    )\n    app = App(theme=None)\n    app._get_frontend_packages = unittest.mock.Mock()\n    with chdir(app_path):\n        yield app, web_dir\n\n\n@pytest.mark.parametrize(\n    \"react_strict_mode\",\n    [True, False],\n)\ndef test_app_wrap_compile_theme(\n    react_strict_mode: bool, compilable_app: tuple[App, Path], mocker\n):\n    \"\"\"Test that the radix theme component wraps the app.\n\n    Args:\n        react_strict_mode: Whether to use React Strict Mode.\n        compilable_app: compilable_app fixture.\n        mocker: pytest mocker object.\n    \"\"\"\n    conf = rx.Config(app_name=\"testing\", react_strict_mode=react_strict_mode)\n    mocker.patch(\"reflex.config._get_config\", return_value=conf)\n    app, web_dir = compilable_app\n    mocker.patch(\"reflex.utils.prerequisites.get_web_dir\", return_value=web_dir)\n    app.theme = rx.theme(accent_color=\"plum\")\n    app._compile()\n    app_js_contents = (\n        web_dir / constants.Dirs.PAGES / constants.PageNames.APP_ROOT\n    ).read_text()\n    function_app_definition = app_js_contents[\n        app_js_contents.index(\"function AppWrap\") : app_js_contents.index(\n            \"export function Layout\"\n        )\n    ].strip()\n    expected = (\n        \"function AppWrap({children}) {\\n\"\n        \"const [addEvents, connectErrors] = useContext(EventLoopContext);\\n\\n\\n\\n\"\n        \"return (\"\n        + (\"jsx(StrictMode,{},\" if react_strict_mode else \"\")\n        + \"jsx(ErrorBoundary,{\"\n        \"\"\"fallbackRender:((event_args) => (jsx(\"div\", ({css:({ [\"height\"] : \"100%\", [\"width\"] : \"100%\", [\"position\"] : \"absolute\", [\"backgroundColor\"] : \"#fff\", [\"color\"] : \"#000\", [\"display\"] : \"flex\", [\"alignItems\"] : \"center\", [\"justifyContent\"] : \"center\" })}), (jsx(\"div\", ({css:({ [\"display\"] : \"flex\", [\"flexDirection\"] : \"column\", [\"gap\"] : \"0.5rem\", [\"maxWidth\"] : \"min(80ch, 90vw)\", [\"borderRadius\"] : \"0.25rem\", [\"padding\"] : \"1rem\" })}), (jsx(\"div\", ({css:({ [\"opacity\"] : \"0.5\", [\"display\"] : \"flex\", [\"gap\"] : \"4vmin\", [\"alignItems\"] : \"center\" })}), (jsx(\"svg\", ({className:\"lucide lucide-frown-icon lucide-frown\",fill:\"none\",stroke:\"currentColor\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\",\"stroke-width\":\"2\",viewBox:\"0 0 24 24\",width:\"25vmin\",xmlns:\"http://www.w3.org/2000/svg\"}), (jsx(\"circle\", ({cx:\"12\",cy:\"12\",r:\"10\"}))), (jsx(\"path\", ({d:\"M16 16s-1.5-2-4-2-4 2-4 2\"}))), (jsx(\"line\", ({x1:\"9\",x2:\"9.01\",y1:\"9\",y2:\"9\"}))), (jsx(\"line\", ({x1:\"15\",x2:\"15.01\",y1:\"9\",y2:\"9\"}))))), (jsx(\"h2\", ({css:({ [\"fontSize\"] : \"5vmin\", [\"fontWeight\"] : \"bold\" })}), \"An error occurred while rendering this page.\")))), (jsx(\"p\", ({css:({ [\"opacity\"] : \"0.75\", [\"marginBlock\"] : \"1rem\" })}), \"This is an error with the application itself. Refreshing the page might help.\")), (jsx(\"div\", ({css:({ [\"width\"] : \"100%\", [\"background\"] : \"color-mix(in srgb, currentColor 5%, transparent)\", [\"maxHeight\"] : \"15rem\", [\"overflow\"] : \"auto\", [\"borderRadius\"] : \"0.4rem\" })}), (jsx(\"div\", ({css:({ [\"padding\"] : \"0.5rem\" })}), (jsx(\"pre\", ({css:({ [\"wordBreak\"] : \"break-word\", [\"whiteSpace\"] : \"pre-wrap\" })}), event_args.error.name + \\': \\' + event_args.error.message + \\'\\\\n\\' + event_args.error.stack)))))), (jsx(\"button\", ({css:({ [\"padding\"] : \"0.35rem 1.35rem\", [\"marginBlock\"] : \"0.5rem\", [\"marginInlineStart\"] : \"auto\", [\"background\"] : \"color-mix(in srgb, currentColor 15%, transparent)\", [\"borderRadius\"] : \"0.4rem\", [\"width\"] : \"fit-content\", [\"&:hover\"] : ({ [\"background\"] : \"color-mix(in srgb, currentColor 25%, transparent)\" }), [\"&:active\"] : ({ [\"background\"] : \"color-mix(in srgb, currentColor 35%, transparent)\" }) }),onClick:((_e) => (addEvents([(ReflexEvent(\"_call_function\", ({ [\"function\"] : (() => (navigator?.[\"clipboard\"]?.[\"writeText\"](event_args.error.name + \\': \\' + event_args.error.message + \\'\\\\n\\' + event_args.error.stack))), [\"callback\"] : null }), ({  })))], [_e], ({  }))))}), \"Copy\")), (jsx(\"hr\", ({css:({ [\"borderColor\"] : \"currentColor\", [\"opacity\"] : \"0.25\" })}))), (jsx(ReactRouterLink, ({to:\"https://reflex.dev\"}), (jsx(\"div\", ({css:({ [\"display\"] : \"flex\", [\"alignItems\"] : \"baseline\", [\"justifyContent\"] : \"center\", [\"fontFamily\"] : \"monospace\", [\"--default-font-family\"] : \"monospace\", [\"gap\"] : \"0.5rem\" })}), \"Built with \", (jsx(\"svg\", ({\"aria-label\":\"Reflex\",css:({ [\"fill\"] : \"currentColor\" }),height:\"12\",role:\"img\",width:\"56\",xmlns:\"http://www.w3.org/2000/svg\"}), (jsx(\"path\", ({d:\"M0 11.5999V0.399902H8.96V4.8799H6.72V2.6399H2.24V4.8799H6.72V7.1199H2.24V11.5999H0ZM6.72 11.5999V7.1199H8.96V11.5999H6.72Z\"}))), (jsx(\"path\", ({d:\"M11.2 11.5999V0.399902H17.92V2.6399H13.44V4.8799H17.92V7.1199H13.44V9.3599H17.92V11.5999H11.2Z\"}))), (jsx(\"path\", ({d:\"M20.16 11.5999V0.399902H26.88V2.6399H22.4V4.8799H26.88V7.1199H22.4V11.5999H20.16Z\"}))), (jsx(\"path\", ({d:\"M29.12 11.5999V0.399902H31.36V9.3599H35.84V11.5999H29.12Z\"}))), (jsx(\"path\", ({d:\"M38.08 11.5999V0.399902H44.8V2.6399H40.32V4.8799H44.8V7.1199H40.32V9.3599H44.8V11.5999H38.08Z\"}))), (jsx(\"path\", ({d:\"M47.04 4.8799V0.399902H49.28V4.8799H47.04ZM53.76 4.8799V0.399902H56V4.8799H53.76ZM49.28 7.1199V4.8799H53.76V7.1199H49.28ZM47.04 11.5999V7.1199H49.28V11.5999H47.04ZM53.76 11.5999V7.1199H56V11.5999H53.76Z\"}))), (jsx(\"title\", ({}), \"Reflex\"))))))))))))),\"\"\"\n        \"\"\"onError:((_error, _info) => (addEvents([(ReflexEvent(\"reflex___state____state.reflex___state____frontend_event_exception_state.handle_frontend_exception\", ({ [\"info\"] : ((((_error?.[\"name\"]+\": \")+_error?.[\"message\"])+\"\\\\n\")+_error?.[\"stack\"]), [\"component_stack\"] : _info?.[\"componentStack\"] }), ({  })))], [_error, _info], ({  }))))\"\"\"\n        \"},\"\n        \"jsx(RadixThemesColorModeProvider,{},\"\n        \"jsx(Fragment,{},\"\n        \"jsx(MemoizedToastProvider,{},),\"\n        \"jsx(RadixThemesTheme,{accentColor:\\\"plum\\\",css:{...theme.styles.global[':root'], ...theme.styles.global.body}},\"\n        \"jsx(Fragment,{},\"\n        \"jsx(DefaultOverlayComponents,{},),\"\n        \"jsx(Fragment,{},\"\n        \"children\"\n        \"))))))\" + (\")\" if react_strict_mode else \"\") + \")\"\n        \"\\n}\"\n    )\n    assert expected.split(\",\") == function_app_definition.split(\",\")\n\n\n@pytest.mark.parametrize(\n    \"react_strict_mode\",\n    [True, False],\n)\ndef test_app_wrap_priority(\n    react_strict_mode: bool, compilable_app: tuple[App, Path], mocker\n):\n    \"\"\"Test that the app wrap components are wrapped in the correct order.\n\n    Args:\n        react_strict_mode: Whether to use React Strict Mode.\n        compilable_app: compilable_app fixture.\n        mocker: pytest mocker object.\n    \"\"\"\n    conf = rx.Config(app_name=\"testing\", react_strict_mode=react_strict_mode)\n    mocker.patch(\"reflex.config._get_config\", return_value=conf)\n\n    app, web_dir = compilable_app\n\n    class Fragment1(Component):\n        tag = \"Fragment1\"\n\n        def _get_app_wrap_components(self) -> dict[tuple[int, str], Component]:  # pyright: ignore [reportIncompatibleMethodOverride]\n            return {(99, \"Box\"): rx.box()}\n\n    class Fragment2(Component):\n        tag = \"Fragment2\"\n\n        def _get_app_wrap_components(self) -> dict[tuple[int, str], Component]:  # pyright: ignore [reportIncompatibleMethodOverride]\n            return {(50, \"Text\"): rx.text()}\n\n    class Fragment3(Component):\n        tag = \"Fragment3\"\n\n        def _get_app_wrap_components(self) -> dict[tuple[int, str], Component]:  # pyright: ignore [reportIncompatibleMethodOverride]\n            return {(10, \"Fragment2\"): Fragment2.create()}\n\n    def page():\n        return Fragment1.create(Fragment3.create())\n\n    app.add_page(page)\n    app._compile()\n    app_js_contents = (\n        web_dir / constants.Dirs.PAGES / constants.PageNames.APP_ROOT\n    ).read_text()\n    function_app_definition = app_js_contents[\n        app_js_contents.index(\"function AppWrap\") : app_js_contents.index(\n            \"export function Layout\"\n        )\n    ].strip()\n    expected = (\n        \"function AppWrap({children}) {\\n\"\n        \"const [addEvents, connectErrors] = useContext(EventLoopContext);\\n\\n\\n\\n\"\n        \"return (\"\n        + (\"jsx(StrictMode,{},\" if react_strict_mode else \"\")\n        + \"jsx(RadixThemesBox,{},\"\n        \"jsx(ErrorBoundary,{\"\n        \"\"\"fallbackRender:((event_args) => (jsx(\"div\", ({css:({ [\"height\"] : \"100%\", [\"width\"] : \"100%\", [\"position\"] : \"absolute\", [\"backgroundColor\"] : \"#fff\", [\"color\"] : \"#000\", [\"display\"] : \"flex\", [\"alignItems\"] : \"center\", [\"justifyContent\"] : \"center\" })}), (jsx(\"div\", ({css:({ [\"display\"] : \"flex\", [\"flexDirection\"] : \"column\", [\"gap\"] : \"0.5rem\", [\"maxWidth\"] : \"min(80ch, 90vw)\", [\"borderRadius\"] : \"0.25rem\", [\"padding\"] : \"1rem\" })}), (jsx(\"div\", ({css:({ [\"opacity\"] : \"0.5\", [\"display\"] : \"flex\", [\"gap\"] : \"4vmin\", [\"alignItems\"] : \"center\" })}), (jsx(\"svg\", ({className:\"lucide lucide-frown-icon lucide-frown\",fill:\"none\",stroke:\"currentColor\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\",\"stroke-width\":\"2\",viewBox:\"0 0 24 24\",width:\"25vmin\",xmlns:\"http://www.w3.org/2000/svg\"}), (jsx(\"circle\", ({cx:\"12\",cy:\"12\",r:\"10\"}))), (jsx(\"path\", ({d:\"M16 16s-1.5-2-4-2-4 2-4 2\"}))), (jsx(\"line\", ({x1:\"9\",x2:\"9.01\",y1:\"9\",y2:\"9\"}))), (jsx(\"line\", ({x1:\"15\",x2:\"15.01\",y1:\"9\",y2:\"9\"}))))), (jsx(\"h2\", ({css:({ [\"fontSize\"] : \"5vmin\", [\"fontWeight\"] : \"bold\" })}), \"An error occurred while rendering this page.\")))), (jsx(\"p\", ({css:({ [\"opacity\"] : \"0.75\", [\"marginBlock\"] : \"1rem\" })}), \"This is an error with the application itself. Refreshing the page might help.\")), (jsx(\"div\", ({css:({ [\"width\"] : \"100%\", [\"background\"] : \"color-mix(in srgb, currentColor 5%, transparent)\", [\"maxHeight\"] : \"15rem\", [\"overflow\"] : \"auto\", [\"borderRadius\"] : \"0.4rem\" })}), (jsx(\"div\", ({css:({ [\"padding\"] : \"0.5rem\" })}), (jsx(\"pre\", ({css:({ [\"wordBreak\"] : \"break-word\", [\"whiteSpace\"] : \"pre-wrap\" })}), event_args.error.name + \\': \\' + event_args.error.message + \\'\\\\n\\' + event_args.error.stack)))))), (jsx(\"button\", ({css:({ [\"padding\"] : \"0.35rem 1.35rem\", [\"marginBlock\"] : \"0.5rem\", [\"marginInlineStart\"] : \"auto\", [\"background\"] : \"color-mix(in srgb, currentColor 15%, transparent)\", [\"borderRadius\"] : \"0.4rem\", [\"width\"] : \"fit-content\", [\"&:hover\"] : ({ [\"background\"] : \"color-mix(in srgb, currentColor 25%, transparent)\" }), [\"&:active\"] : ({ [\"background\"] : \"color-mix(in srgb, currentColor 35%, transparent)\" }) }),onClick:((_e) => (addEvents([(ReflexEvent(\"_call_function\", ({ [\"function\"] : (() => (navigator?.[\"clipboard\"]?.[\"writeText\"](event_args.error.name + \\': \\' + event_args.error.message + \\'\\\\n\\' + event_args.error.stack))), [\"callback\"] : null }), ({  })))], [_e], ({  }))))}), \"Copy\")), (jsx(\"hr\", ({css:({ [\"borderColor\"] : \"currentColor\", [\"opacity\"] : \"0.25\" })}))), (jsx(ReactRouterLink, ({to:\"https://reflex.dev\"}), (jsx(\"div\", ({css:({ [\"display\"] : \"flex\", [\"alignItems\"] : \"baseline\", [\"justifyContent\"] : \"center\", [\"fontFamily\"] : \"monospace\", [\"--default-font-family\"] : \"monospace\", [\"gap\"] : \"0.5rem\" })}), \"Built with \", (jsx(\"svg\", ({\"aria-label\":\"Reflex\",css:({ [\"fill\"] : \"currentColor\" }),height:\"12\",role:\"img\",width:\"56\",xmlns:\"http://www.w3.org/2000/svg\"}), (jsx(\"path\", ({d:\"M0 11.5999V0.399902H8.96V4.8799H6.72V2.6399H2.24V4.8799H6.72V7.1199H2.24V11.5999H0ZM6.72 11.5999V7.1199H8.96V11.5999H6.72Z\"}))), (jsx(\"path\", ({d:\"M11.2 11.5999V0.399902H17.92V2.6399H13.44V4.8799H17.92V7.1199H13.44V9.3599H17.92V11.5999H11.2Z\"}))), (jsx(\"path\", ({d:\"M20.16 11.5999V0.399902H26.88V2.6399H22.4V4.8799H26.88V7.1199H22.4V11.5999H20.16Z\"}))), (jsx(\"path\", ({d:\"M29.12 11.5999V0.399902H31.36V9.3599H35.84V11.5999H29.12Z\"}))), (jsx(\"path\", ({d:\"M38.08 11.5999V0.399902H44.8V2.6399H40.32V4.8799H44.8V7.1199H40.32V9.3599H44.8V11.5999H38.08Z\"}))), (jsx(\"path\", ({d:\"M47.04 4.8799V0.399902H49.28V4.8799H47.04ZM53.76 4.8799V0.399902H56V4.8799H53.76ZM49.28 7.1199V4.8799H53.76V7.1199H49.28ZM47.04 11.5999V7.1199H49.28V11.5999H47.04ZM53.76 11.5999V7.1199H56V11.5999H53.76Z\"}))), (jsx(\"title\", ({}), \"Reflex\"))))))))))))),\"\"\"\n        \"\"\"onError:((_error, _info) => (addEvents([(ReflexEvent(\"reflex___state____state.reflex___state____frontend_event_exception_state.handle_frontend_exception\", ({ [\"info\"] : ((((_error?.[\"name\"]+\": \")+_error?.[\"message\"])+\"\\\\n\")+_error?.[\"stack\"]), [\"component_stack\"] : _info?.[\"componentStack\"] }), ({  })))], [_error, _info], ({  }))))\"\"\"\n        \"},\"\n        'jsx(RadixThemesText,{as:\"p\"},'\n        \"jsx(RadixThemesColorModeProvider,{},\"\n        \"jsx(Fragment,{},\"\n        \"jsx(MemoizedToastProvider,{},),\"\n        \"jsx(Fragment2,{},\"\n        \"jsx(Fragment,{},\"\n        \"jsx(DefaultOverlayComponents,{},),\"\n        \"jsx(Fragment,{},\"\n        \"children\"\n        \")))))))\" + (\")\" if react_strict_mode else \"\") + \"))\\n}\"\n    )\n    assert expected.split(\",\") == function_app_definition.split(\",\")\n\n\ndef test_app_state_determination():\n    \"\"\"Test that the stateless status of an app is determined correctly.\"\"\"\n    a1 = App()\n    assert a1._state is not None\n\n    a2 = App(enable_state=False)\n    assert a2._state is None\n\n\ndef test_raise_on_state():\n    \"\"\"Test that the state is set.\"\"\"\n    # state kwargs is deprecated, we just make sure the app is created anyway.\n    app = App(_state=State)\n    assert app._state is not None\n    assert issubclass(app._state, State)\n\n\ndef test_call_app():\n    \"\"\"Test that the app can be called.\"\"\"\n    app = App()\n    app._compile = unittest.mock.Mock()\n    api = app()\n    assert isinstance(api, Starlette)\n\n\ndef test_app_with_optional_endpoints():\n    from reflex.components.core.upload import Upload\n\n    app = App()\n    Upload.is_used = True\n    app._add_optional_endpoints()\n    # TODO: verify the availability of the endpoints in app.api\n\n\ndef test_app_state_manager():\n    app = App(enable_state=False)\n    with pytest.raises(ValueError):\n        app.state_manager\n    app._enable_state()\n    assert app.state_manager is not None\n    assert isinstance(\n        app.state_manager, (StateManagerMemory, StateManagerDisk, StateManagerRedis)\n    )\n\n\ndef test_generate_component():\n    def index():\n        return rx.box(\"Index\")\n\n    def index_mismatch():\n        return rx.match(\n            1,\n            (1, rx.box(\"Index\")),\n            (2, \"About\"),\n            \"Bar\",\n        )\n\n    comp = App._generate_component(index)\n    assert isinstance(comp, Component)\n\n    with pytest.raises(exceptions.MatchTypeError):\n        App._generate_component(index_mismatch)\n\n\ndef test_add_page_component_returning_tuple():\n    \"\"\"Test that a component or render method returning a\n    tuple is unpacked in a Fragment.\n    \"\"\"\n    app = App()\n\n    def index():\n        return rx.text(\"first\"), rx.text(\"second\")\n\n    def page2():\n        return (rx.text(\"third\"),)\n\n    app.add_page(index)\n    app.add_page(page2)\n\n    app._compile_page(\"index\")\n    app._compile_page(\"page2\")\n\n    fragment_wrapper = app._pages[\"index\"].children[0]\n    assert isinstance(fragment_wrapper, Fragment)\n    first_text = fragment_wrapper.children[0]\n    assert isinstance(first_text, Text)\n    assert isinstance(first_text.children[0], Bare)\n    assert str(first_text.children[0].contents) == '\"first\"'\n    second_text = fragment_wrapper.children[1]\n    assert isinstance(second_text, Text)\n    assert isinstance(second_text.children[0], Bare)\n    assert str(second_text.children[0].contents) == '\"second\"'\n\n    # Test page with trailing comma.\n    page2_fragment_wrapper = app._pages[\"page2\"].children[0]\n    assert isinstance(page2_fragment_wrapper, Fragment)\n    third_text = page2_fragment_wrapper.children[0]\n    assert isinstance(third_text, Text)\n    assert isinstance(third_text.children[0], Bare)\n    assert str(third_text.children[0].contents) == '\"third\"'\n\n\ndef test_app_with_valid_var_dependencies(compilable_app: tuple[App, Path]):\n    app, _ = compilable_app\n\n    class ValidDepState(BaseState):\n        base: int = 0\n        _backend: int = 0\n\n        @computed_var()\n        def foo(self) -> str:\n            return \"foo\"\n\n        @computed_var(deps=[\"_backend\", \"base\", foo])\n        def bar(self) -> str:\n            return \"bar\"\n\n    class Child1(ValidDepState):\n        @computed_var(deps=[\"base\", ValidDepState.bar])\n        def other(self) -> str:\n            return \"other\"\n\n    class Child2(ValidDepState):\n        @computed_var(deps=[\"base\", Child1.other])\n        def other(self) -> str:\n            return \"other\"\n\n    app._state = ValidDepState\n    app._compile()\n\n\ndef test_app_with_invalid_var_dependencies(compilable_app: tuple[App, Path]):\n    app, _ = compilable_app\n\n    class InvalidDepState(BaseState):\n        @computed_var(deps=[\"foolksjdf\"])\n        def bar(self) -> str:\n            return \"bar\"\n\n    app._state = InvalidDepState\n    with pytest.raises(exceptions.VarDependencyError):\n        app._compile()\n\n\n# Test custom exception handlers\n\n\ndef valid_custom_handler(exception: Exception, logger: str = \"test\"):\n    print(\"Custom Backend Exception\")\n    print(exception)\n\n\ndef custom_exception_handler_with_wrong_arg_order(\n    logger: str,\n    exception: Exception,  # Should be first\n):\n    print(\"Custom Backend Exception\")\n    print(exception)\n\n\ndef custom_exception_handler_with_wrong_argspec(\n    exception: str,  # Should be Exception\n):\n    print(\"Custom Backend Exception\")\n    print(exception)\n\n\nclass DummyExceptionHandler:\n    \"\"\"Dummy exception handler class.\"\"\"\n\n    def handle(self, exception: Exception):\n        \"\"\"Handle the exception.\n\n        Args:\n            exception: The exception.\n\n        \"\"\"\n        print(\"Custom Backend Exception\")\n        print(exception)\n\n\ncustom_exception_handlers = {\n    \"lambda\": lambda exception: print(\"Custom Exception Handler\", exception),\n    \"wrong_argspec\": custom_exception_handler_with_wrong_argspec,\n    \"wrong_arg_order\": custom_exception_handler_with_wrong_arg_order,\n    \"valid\": valid_custom_handler,\n    \"partial\": functools.partial(valid_custom_handler, logger=\"test\"),\n    \"method\": DummyExceptionHandler().handle,\n}\n\n\n@pytest.mark.parametrize(\n    (\"handler_fn\", \"expected\"),\n    [\n        pytest.param(\n            custom_exception_handlers[\"partial\"],\n            pytest.raises(ValueError),\n            id=\"partial\",\n        ),\n        pytest.param(\n            custom_exception_handlers[\"lambda\"],\n            pytest.raises(ValueError),\n            id=\"lambda\",\n        ),\n        pytest.param(\n            custom_exception_handlers[\"wrong_argspec\"],\n            pytest.raises(ValueError),\n            id=\"wrong_argspec\",\n        ),\n        pytest.param(\n            custom_exception_handlers[\"wrong_arg_order\"],\n            pytest.raises(ValueError),\n            id=\"wrong_arg_order\",\n        ),\n        pytest.param(\n            custom_exception_handlers[\"valid\"],\n            does_not_raise(),\n            id=\"valid_handler\",\n        ),\n        pytest.param(\n            custom_exception_handlers[\"method\"],\n            does_not_raise(),\n            id=\"valid_class_method\",\n        ),\n    ],\n)\ndef test_frontend_exception_handler_validation(handler_fn, expected):\n    \"\"\"Test that the custom frontend exception handler is properly validated.\n\n    Args:\n        handler_fn: The handler function.\n        expected: The expected result.\n\n    \"\"\"\n    with expected:\n        rx.App(frontend_exception_handler=handler_fn)._validate_exception_handlers()\n\n\ndef backend_exception_handler_with_wrong_return_type(exception: Exception) -> int:\n    \"\"\"Custom backend exception handler with wrong return type.\n\n    Args:\n        exception: The exception.\n\n    Returns:\n        int: The wrong return type.\n\n    \"\"\"\n    print(\"Custom Backend Exception\")\n    print(exception)\n\n    return 5\n\n\n@pytest.mark.parametrize(\n    (\"handler_fn\", \"expected\"),\n    [\n        pytest.param(\n            backend_exception_handler_with_wrong_return_type,\n            pytest.raises(ValueError),\n            id=\"wrong_return_type\",\n        ),\n        pytest.param(\n            custom_exception_handlers[\"partial\"],\n            pytest.raises(ValueError),\n            id=\"partial\",\n        ),\n        pytest.param(\n            custom_exception_handlers[\"lambda\"],\n            pytest.raises(ValueError),\n            id=\"lambda\",\n        ),\n        pytest.param(\n            custom_exception_handlers[\"wrong_argspec\"],\n            pytest.raises(ValueError),\n            id=\"wrong_argspec\",\n        ),\n        pytest.param(\n            custom_exception_handlers[\"wrong_arg_order\"],\n            pytest.raises(ValueError),\n            id=\"wrong_arg_order\",\n        ),\n        pytest.param(\n            custom_exception_handlers[\"valid\"],\n            does_not_raise(),\n            id=\"valid_handler\",\n        ),\n        pytest.param(\n            custom_exception_handlers[\"method\"],\n            does_not_raise(),\n            id=\"valid_class_method\",\n        ),\n    ],\n)\ndef test_backend_exception_handler_validation(handler_fn, expected):\n    \"\"\"Test that the custom backend exception handler is properly validated.\n\n    Args:\n        handler_fn: The handler function.\n        expected: The expected result.\n\n    \"\"\"\n    with expected:\n        rx.App(backend_exception_handler=handler_fn)._validate_exception_handlers()\n\n\n@pytest.mark.parametrize(\n    (\"substate\", \"frontend\"),\n    [\n        pytest.param(False, True, id=\"root_state_frontend\"),\n        pytest.param(False, False, id=\"root_state_backend\"),\n        pytest.param(True, True, id=\"substate_frontend\"),\n        pytest.param(True, False, id=\"substate_backend\"),\n    ],\n)\n@pytest.mark.asyncio\nasync def test_app_modify_state_clean(token: str, substate: bool, frontend: bool):\n    \"\"\"Test that modify_state does not leave dirty_vars or dirty_substates.\n\n    Args:\n        token: A client token.\n        substate: Whether to modify a substate.\n        frontend: Whether to modify a frontend or backend var.\n    \"\"\"\n\n    class Base(BaseState):\n        count: int = 0\n        _backend: int = 0\n\n    class Sub(Base):\n        sub_count: int = 0\n        _sub_backend: int = 0\n\n    app = App(_state=Base)\n    app._event_namespace = AsyncMock()\n\n    async with app.modify_state(\n        token=_substate_key(token, Sub.get_name())\n    ) as root_state:\n        sub = root_state.substates[Sub.get_name()]\n        if substate:\n            if frontend:\n                sub.sub_count = 1\n            else:\n                sub._sub_backend = 1\n        else:\n            if frontend:\n                root_state.count = 1\n            else:\n                root_state._backend = 1\n\n    assert not root_state.dirty_vars\n    assert not root_state.dirty_substates\n    if substate:\n        assert sub._was_touched\n        assert not root_state._was_touched\n    else:\n        assert root_state._was_touched\n        assert not sub._was_touched\n\n    if frontend:\n        assert app._event_namespace.emit_update.call_count == 1\n        if substate:\n            exp_delta = {Sub.get_full_name(): {\"sub_count_rx_state_\": 1}}\n        else:\n            exp_delta = {Base.get_full_name(): {\"count_rx_state_\": 1}}\n        assert (\n            app._event_namespace.emit_update.call_args.kwargs[\"update\"].delta\n            == exp_delta\n        )\n    else:\n        assert app._event_namespace.emit_update.call_count == 0\n"
  },
  {
    "path": "tests/units/test_attribute_access_type.py",
    "content": "from __future__ import annotations\n\nfrom typing import List  # noqa: UP035\n\nimport attrs\nimport pytest\n\nimport reflex as rx\nfrom reflex.utils.types import GenericType, get_attribute_access_type\n\npytest.importorskip(\"sqlalchemy\")\npytest.importorskip(\"sqlmodel\")\npytest.importorskip(\"pydantic\")\n\nimport pydantic.v1\nimport sqlalchemy\nimport sqlmodel\nfrom sqlalchemy import JSON, TypeDecorator\nfrom sqlalchemy.ext.hybrid import hybrid_property\nfrom sqlalchemy.orm import (\n    DeclarativeBase,\n    Mapped,\n    MappedAsDataclass,\n    mapped_column,\n    relationship,\n)\n\n\nclass SQLAType(TypeDecorator):\n    \"\"\"SQLAlchemy custom dict type.\"\"\"\n\n    impl = JSON\n\n    @property\n    def python_type(self) -> type[dict[str, str]]:\n        \"\"\"Python type.\n\n        Returns:\n            Python Type of the column.\n        \"\"\"\n        return dict[str, str]\n\n\nclass SQLABase(DeclarativeBase):\n    \"\"\"Base class for bare SQLAlchemy models.\"\"\"\n\n    type_annotation_map = {\n        # do not use lower case dict here!\n        # https://github.com/sqlalchemy/sqlalchemy/issues/9902\n        dict[str, str]: SQLAType,\n    }\n\n\nclass SQLATag(SQLABase):\n    \"\"\"Tag sqlalchemy model.\"\"\"\n\n    __tablename__: str = \"tag\"\n    id: Mapped[int] = mapped_column(primary_key=True)\n    name: Mapped[str] = mapped_column()\n\n\nclass SQLALabel(SQLABase):\n    \"\"\"Label sqlalchemy model.\"\"\"\n\n    __tablename__: str = \"label\"\n    id: Mapped[int] = mapped_column(primary_key=True)\n    test_id: Mapped[int] = mapped_column(sqlalchemy.ForeignKey(\"test.id\"))\n    test: Mapped[SQLAClass] = relationship(back_populates=\"labels\")\n    test_dataclass_id: Mapped[int] = mapped_column(\n        sqlalchemy.ForeignKey(\"test_dataclass.id\")\n    )\n    test_dataclass: Mapped[SQLAClassDataclass] = relationship(back_populates=\"labels\")\n\n\nclass SQLAClass(SQLABase):\n    \"\"\"Test sqlalchemy model.\"\"\"\n\n    __tablename__: str = \"test\"\n    id: Mapped[int] = mapped_column(primary_key=True)\n    count: Mapped[int] = mapped_column()\n    name: Mapped[str] = mapped_column()\n    int_list: Mapped[list[int]] = mapped_column(\n        sqlalchemy.types.ARRAY(item_type=sqlalchemy.INTEGER)\n    )\n    str_list: Mapped[list[str]] = mapped_column(\n        sqlalchemy.types.ARRAY(item_type=sqlalchemy.String)\n    )\n    optional_int: Mapped[int | None] = mapped_column(nullable=True)\n    sqla_tag_id: Mapped[int] = mapped_column(sqlalchemy.ForeignKey(SQLATag.id))\n    sqla_tag: Mapped[SQLATag | None] = relationship()\n    labels: Mapped[list[SQLALabel]] = relationship(back_populates=\"test\")\n    # do not use lower case dict here!\n    # https://github.com/sqlalchemy/sqlalchemy/issues/9902\n    dict_str_str: Mapped[dict[str, str]] = mapped_column()\n\n    @property\n    def str_property(self) -> str:\n        \"\"\"String property.\n\n        Returns:\n            Name attribute\n        \"\"\"\n        return self.name\n\n    @hybrid_property\n    def str_or_int_property(self) -> str | int:\n        \"\"\"String or int property.\n\n        Returns:\n            Name attribute\n        \"\"\"\n        return self.name\n\n    @hybrid_property\n    def first_label(self) -> SQLALabel | None:\n        \"\"\"First label property.\n\n        Returns:\n            First label\n        \"\"\"\n        return self.labels[0] if self.labels else None\n\n\nclass SQLAClassDataclass(MappedAsDataclass, SQLABase):\n    \"\"\"Test sqlalchemy model.\"\"\"\n\n    id: Mapped[int] = mapped_column(primary_key=True)\n    no_default: Mapped[int] = mapped_column(nullable=True)\n    count: Mapped[int] = mapped_column()\n    name: Mapped[str] = mapped_column()\n    int_list: Mapped[list[int]] = mapped_column(\n        sqlalchemy.types.ARRAY(item_type=sqlalchemy.INTEGER)\n    )\n    str_list: Mapped[list[str]] = mapped_column(\n        sqlalchemy.types.ARRAY(item_type=sqlalchemy.String)\n    )\n    optional_int: Mapped[int | None] = mapped_column(nullable=True)\n    sqla_tag_id: Mapped[int] = mapped_column(sqlalchemy.ForeignKey(SQLATag.id))\n    sqla_tag: Mapped[SQLATag | None] = relationship()\n    labels: Mapped[list[SQLALabel]] = relationship(back_populates=\"test_dataclass\")\n    # do not use lower case dict here!\n    # https://github.com/sqlalchemy/sqlalchemy/issues/9902\n    dict_str_str: Mapped[dict[str, str]] = mapped_column()\n    default_factory: Mapped[list[int]] = mapped_column(\n        sqlalchemy.types.ARRAY(item_type=sqlalchemy.INTEGER),\n        default_factory=list,\n    )\n    __tablename__: str = \"test_dataclass\"\n\n    @property\n    def str_property(self) -> str:\n        \"\"\"String property.\n\n        Returns:\n            Name attribute\n        \"\"\"\n        return self.name\n\n    @hybrid_property\n    def str_or_int_property(self) -> str | int:\n        \"\"\"String or int property.\n\n        Returns:\n            Name attribute\n        \"\"\"\n        return self.name\n\n    @hybrid_property\n    def first_label(self) -> SQLALabel | None:\n        \"\"\"First label property.\n\n        Returns:\n            First label\n        \"\"\"\n        return self.labels[0] if self.labels else None\n\n\nclass ModelClass(rx.Model):\n    \"\"\"Test reflex model.\"\"\"\n\n    no_default: int | None = sqlmodel.Field(nullable=True)\n    count: int = 0\n    name: str = \"test\"\n    int_list: list[int] = []\n    str_list: list[str] = []\n    optional_int: int | None = None\n    sqla_tag: SQLATag | None = None\n    labels: list[SQLALabel] = []\n    dict_str_str: dict[str, str] = {}\n    default_factory: list[int] = sqlmodel.Field(default_factory=list)\n\n    @property\n    def str_property(self) -> str:\n        \"\"\"String property.\n\n        Returns:\n            Name attribute\n        \"\"\"\n        return self.name\n\n    @property\n    def str_or_int_property(self) -> str | int:\n        \"\"\"String or int property.\n\n        Returns:\n            Name attribute\n        \"\"\"\n        return self.name\n\n    @property\n    def first_label(self) -> SQLALabel | None:\n        \"\"\"First label property.\n\n        Returns:\n            First label\n        \"\"\"\n        return self.labels[0] if self.labels else None\n\n\nclass BaseClass(rx.Base):\n    \"\"\"Test rx.Base class.\"\"\"\n\n    no_default: int | None = pydantic.v1.Field(required=False)\n    count: int = 0\n    name: str = \"test\"\n    int_list: list[int] = []\n    str_list: list[str] = []\n    optional_int: int | None = None\n    sqla_tag: SQLATag | None = None\n    labels: list[SQLALabel] = []\n    dict_str_str: dict[str, str] = {}\n    default_factory: list[int] = pydantic.v1.Field(default_factory=list)\n\n    @property\n    def str_property(self) -> str:\n        \"\"\"String property.\n\n        Returns:\n            Name attribute\n        \"\"\"\n        return self.name\n\n    @property\n    def str_or_int_property(self) -> str | int:\n        \"\"\"String or int property.\n\n        Returns:\n            Name attribute\n        \"\"\"\n        return self.name\n\n    @property\n    def first_label(self) -> SQLALabel | None:\n        \"\"\"First label property.\n\n        Returns:\n            First label\n        \"\"\"\n        return self.labels[0] if self.labels else None\n\n\nclass BareClass:\n    \"\"\"Bare python class.\"\"\"\n\n    count: int = 0\n    name: str = \"test\"\n    int_list: list[int] = []\n    str_list: list[str] = []\n    optional_int: int | None = None\n    sqla_tag: SQLATag | None = None\n    labels: list[SQLALabel] = []\n    dict_str_str: dict[str, str] = {}\n\n    @property\n    def str_property(self) -> str:\n        \"\"\"String property.\n\n        Returns:\n            Name attribute\n        \"\"\"\n        return self.name\n\n    @property\n    def str_or_int_property(self) -> str | int:\n        \"\"\"String or int property.\n\n        Returns:\n            Name attribute\n        \"\"\"\n        return self.name\n\n    @property\n    def first_label(self) -> SQLALabel | None:\n        \"\"\"First label property.\n\n        Returns:\n            First label\n        \"\"\"\n        return self.labels[0] if self.labels else None\n\n\n@attrs.define\nclass AttrClass:\n    \"\"\"Test attrs class.\"\"\"\n\n    count: int = 0\n    name: str = \"test\"\n    int_list: list[int] = attrs.field(factory=list)\n    str_list: list[str] = attrs.field(factory=list)\n    optional_int: int | None = None\n    sqla_tag: SQLATag | None = None\n    labels: list[SQLALabel] = attrs.field(factory=list)\n    dict_str_str: dict[str, str] = attrs.field(factory=dict)\n    default_factory: list[int] = attrs.field(factory=list)\n\n    @property\n    def str_property(self) -> str:\n        \"\"\"String property.\n\n        Returns:\n            Name attribute\n        \"\"\"\n        return self.name\n\n    @property\n    def str_or_int_property(self) -> str | int:\n        \"\"\"String or int property.\n\n        Returns:\n            Name attribute\n        \"\"\"\n        return self.name\n\n    @property\n    def first_label(self) -> SQLALabel | None:\n        \"\"\"First label property.\n\n        Returns:\n            First label\n        \"\"\"\n        return self.labels[0] if self.labels else None\n\n\n@pytest.mark.parametrize(\n    \"cls\",\n    [\n        SQLAClass,\n        SQLAClassDataclass,\n        BaseClass,\n        BareClass,\n        ModelClass,\n        AttrClass,\n    ],\n)\n@pytest.mark.parametrize(\n    (\"attr\", \"expected\"),\n    [\n        pytest.param(\"count\", int, id=\"int\"),\n        pytest.param(\"name\", str, id=\"str\"),\n        pytest.param(\"int_list\", (list[int], List[int]), id=\"list[int]\"),  # noqa: UP006\n        pytest.param(\"str_list\", (list[str], List[str]), id=\"list[str]\"),  # noqa: UP006\n        pytest.param(\"optional_int\", int | None, id=\"int | None\"),\n        pytest.param(\"sqla_tag\", SQLATag | None, id=\"SQLATag | None\"),\n        pytest.param(\"labels\", list[SQLALabel], id=\"list[SQLALabel]\"),\n        pytest.param(\"dict_str_str\", dict[str, str], id=\"dict[str, str]\"),\n        pytest.param(\"str_property\", str, id=\"str_property\"),\n        pytest.param(\"str_or_int_property\", str | int, id=\"str_or_int_property\"),\n        pytest.param(\"first_label\", SQLALabel | None, id=\"first_label\"),\n    ],\n)\ndef test_get_attribute_access_type(cls: type, attr: str, expected: GenericType) -> None:\n    \"\"\"Test get_attribute_access_type returns the correct type.\n\n    Args:\n        cls: Class to test.\n        attr: Attribute to test.\n        expected: Expected type.\n    \"\"\"\n    if isinstance(expected, tuple):\n        assert get_attribute_access_type(cls, attr) in expected\n    else:\n        assert get_attribute_access_type(cls, attr) == expected\n\n\n@pytest.mark.parametrize(\n    (\"cls\", \"expected\"),\n    [\n        (SQLAClassDataclass, List[int]),  # noqa: UP006\n        (BaseClass, list[int]),\n        (ModelClass, list[int]),\n        (AttrClass, list[int]),\n    ],\n)\ndef test_get_attribute_access_type_default_factory(\n    cls: type, expected: GenericType\n) -> None:\n    \"\"\"Test get_attribute_access_type returns the correct type for default factory fields.\n\n    Args:\n        cls: Class to test.\n        expected: Expected type.\n    \"\"\"\n    assert get_attribute_access_type(cls, \"default_factory\") == expected\n\n\n@pytest.mark.parametrize(\n    \"cls\",\n    [\n        SQLAClassDataclass,\n        BaseClass,\n        ModelClass,\n    ],\n)\ndef test_get_attribute_access_type_no_default(cls: type) -> None:\n    \"\"\"Test get_attribute_access_type returns the correct type for fields with no default which are not required.\n\n    Args:\n        cls: Class to test.\n    \"\"\"\n    assert get_attribute_access_type(cls, \"no_default\") == int | None\n"
  },
  {
    "path": "tests/units/test_base.py",
    "content": "import pytest\n\nfrom reflex.base import Base\n\npytest.importorskip(\"pydantic\")\n\n\n@pytest.fixture\ndef child() -> Base:\n    \"\"\"A child class.\n\n    Returns:\n        A child class.\n    \"\"\"\n\n    class Child(Base):\n        num: float\n        key: str\n\n    return Child(num=3.15, key=\"pi\")\n\n\ndef test_get_fields(child):\n    \"\"\"Test that the fields are set correctly.\n\n    Args:\n        child: A child class.\n    \"\"\"\n    assert child.__fields__.keys() == {\"num\", \"key\"}\n\n\ndef test_json(child):\n    \"\"\"Test converting to json.\n\n    Args:\n        child: A child class.\n    \"\"\"\n    assert child.json().replace(\" \", \"\") == '{\"num\":3.15,\"key\":\"pi\"}'\n\n\n@pytest.fixture\ndef complex_child() -> Base:\n    \"\"\"A child class.\n\n    Returns:\n        A child class.\n    \"\"\"\n\n    class Child(Base):\n        num: float\n        key: str\n        name: str\n        age: int\n        active: bool\n\n    return Child(num=3.15, key=\"pi\", name=\"John Doe\", age=30, active=True)\n\n\ndef test_complex_get_fields(complex_child):\n    \"\"\"Test that the fields are set correctly.\n\n    Args:\n        complex_child: A child class.\n    \"\"\"\n    assert complex_child.__fields__.keys() == {\"num\", \"key\", \"name\", \"age\", \"active\"}\n\n\ndef test_complex_json(complex_child):\n    \"\"\"Test converting to json.\n\n    Args:\n        complex_child: A child class.\n    \"\"\"\n    assert (\n        complex_child.json().replace(\" \", \"\")\n        == '{\"num\":3.15,\"key\":\"pi\",\"name\":\"JohnDoe\",\"age\":30,\"active\":true}'\n    )\n"
  },
  {
    "path": "tests/units/test_config.py",
    "content": "import multiprocessing\nimport os\nfrom pathlib import Path\nfrom typing import Any\n\nimport pytest\nfrom pytest_mock import MockerFixture\n\nimport reflex as rx\nimport reflex.config\nfrom reflex.constants import Endpoint, Env\nfrom reflex.environment import (\n    EnvVar,\n    env_var,\n    environment,\n    interpret_boolean_env,\n    interpret_enum_env,\n    interpret_int_env,\n)\nfrom reflex.plugins import Plugin\nfrom reflex.plugins.sitemap import SitemapPlugin\n\n\ndef test_requires_app_name():\n    \"\"\"Test that a config requires an app_name.\"\"\"\n    with pytest.raises(TypeError):\n        rx.Config()  # pyright: ignore[reportCallIssue]\n\n\ndef test_set_app_name(base_config_values):\n    \"\"\"Test that the app name is set to the value passed in.\n\n    Args:\n        base_config_values: Config values.\n    \"\"\"\n    config = rx.Config(**base_config_values)\n    assert config.app_name == base_config_values[\"app_name\"]\n\n\n@pytest.mark.parametrize(\n    (\"env_var\", \"value\"),\n    [\n        (\"REFLEX_APP_NAME\", \"my_test_app\"),\n        (\"REFLEX_FRONTEND_PORT\", 3001),\n        (\"REFLEX_FRONTEND_PATH\", \"/test\"),\n        (\"REFLEX_BACKEND_PORT\", 8001),\n        (\"REFLEX_API_URL\", \"https://mybackend.com:8000\"),\n        (\"REFLEX_DEPLOY_URL\", \"https://myfrontend.com\"),\n        (\"REFLEX_BACKEND_HOST\", \"127.0.0.1\"),\n        (\"REFLEX_DB_URL\", \"postgresql://user:pass@localhost:5432/db\"),\n        (\"REFLEX_REDIS_URL\", \"redis://localhost:6379\"),\n        (\"REFLEX_TELEMETRY_ENABLED\", False),\n        (\"REFLEX_TELEMETRY_ENABLED\", True),\n    ],\n)\ndef test_update_from_env(\n    base_config_values: dict[str, Any],\n    monkeypatch: pytest.MonkeyPatch,\n    env_var: str,\n    value: Any,\n):\n    \"\"\"Test that environment variables override config values.\n\n    Args:\n        base_config_values: Config values.\n        monkeypatch: The pytest monkeypatch object.\n        env_var: The environment variable name.\n        value: The environment variable value.\n    \"\"\"\n    monkeypatch.setenv(env_var, str(value))\n    assert os.environ.get(env_var) == str(value)\n    config = rx.Config(**base_config_values)\n    # Remove REFLEX_ prefix to get the actual field name\n    field_name = env_var.removeprefix(\"REFLEX_\").lower()\n    assert getattr(config, field_name) == value\n\n\ndef test_update_from_env_path(\n    base_config_values: dict[str, Any],\n    monkeypatch: pytest.MonkeyPatch,\n    tmp_path: Path,\n):\n    \"\"\"Test that environment variables override config values.\n\n    Args:\n        base_config_values: Config values.\n        monkeypatch: The pytest monkeypatch object.\n        tmp_path: The pytest tmp_path fixture object.\n    \"\"\"\n    monkeypatch.setenv(\"REFLEX_BUN_PATH\", \"/test\")\n    assert os.environ.get(\"REFLEX_BUN_PATH\") == \"/test\"\n    with pytest.raises(ValueError):\n        rx.Config(**base_config_values)\n\n    monkeypatch.setenv(\"REFLEX_BUN_PATH\", str(tmp_path))\n    assert os.environ.get(\"REFLEX_BUN_PATH\") == str(tmp_path)\n    config = rx.Config(**base_config_values)\n    assert config.bun_path == tmp_path\n\n\ndef test_update_from_env_cors(\n    base_config_values: dict[str, Any],\n    monkeypatch: pytest.MonkeyPatch,\n    tmp_path: Path,\n):\n    \"\"\"Test that environment variables override config values.\n\n    Args:\n        base_config_values: Config values.\n        monkeypatch: The pytest monkeypatch object.\n        tmp_path: The pytest tmp_path fixture object.\n    \"\"\"\n    config = rx.Config(**base_config_values)\n    assert config.cors_allowed_origins == (\"*\",)\n\n    monkeypatch.setenv(\"REFLEX_CORS_ALLOWED_ORIGINS\", \"\")\n    config = rx.Config(**base_config_values)\n    assert config.cors_allowed_origins == (\"*\",)\n\n    monkeypatch.setenv(\"REFLEX_CORS_ALLOWED_ORIGINS\", \"https://foo.example.com\")\n    config = rx.Config(**base_config_values)\n    assert config.cors_allowed_origins == [\n        \"https://foo.example.com\",\n    ]\n\n    monkeypatch.setenv(\n        \"REFLEX_CORS_ALLOWED_ORIGINS\", \"http://example.com, http://another.com \"\n    )\n    config = rx.Config(**base_config_values)\n    assert config.cors_allowed_origins == [\n        \"http://example.com\",\n        \"http://another.com\",\n    ]\n\n\n@pytest.mark.parametrize(\n    (\"kwargs\", \"expected\"),\n    [\n        (\n            {\"app_name\": \"test_app\", \"api_url\": \"http://example.com\"},\n            f\"{Endpoint.EVENT}\",\n        ),\n        (\n            {\"app_name\": \"test_app\", \"api_url\": \"http://example.com/api\"},\n            f\"/api{Endpoint.EVENT}\",\n        ),\n    ],\n)\ndef test_event_namespace(mocker: MockerFixture, kwargs, expected):\n    \"\"\"Test the event namespace.\n\n    Args:\n        mocker: The pytest mock object.\n        kwargs: The Config kwargs.\n        expected: Expected namespace\n    \"\"\"\n    conf = rx.Config(**kwargs)\n    mocker.patch(\"reflex.config.get_config\", return_value=conf)\n\n    config = reflex.config.get_config()\n    assert conf == config\n    assert config.get_event_namespace() == expected\n\n\nDEFAULT_CONFIG = rx.Config(app_name=\"a\")\n\n\n@pytest.mark.parametrize(\n    (\"config_kwargs\", \"env_vars\", \"set_persistent_vars\", \"exp_config_values\"),\n    [\n        (\n            {},\n            {},\n            {},\n            {\n                \"api_url\": DEFAULT_CONFIG.api_url,\n                \"backend_port\": DEFAULT_CONFIG.backend_port,\n                \"deploy_url\": DEFAULT_CONFIG.deploy_url,\n                \"frontend_port\": DEFAULT_CONFIG.frontend_port,\n            },\n        ),\n        # Ports set in config kwargs\n        (\n            {\"backend_port\": 8001, \"frontend_port\": 3001},\n            {},\n            {},\n            {\n                \"api_url\": \"http://localhost:8001\",\n                \"backend_port\": 8001,\n                \"deploy_url\": \"http://localhost:3001\",\n                \"frontend_port\": 3001,\n            },\n        ),\n        # Ports set in environment take precedence\n        (\n            {\"backend_port\": 8001, \"frontend_port\": 3001},\n            {\"REFLEX_BACKEND_PORT\": 8002},\n            {},\n            {\n                \"api_url\": \"http://localhost:8002\",\n                \"backend_port\": 8002,\n                \"deploy_url\": \"http://localhost:3001\",\n                \"frontend_port\": 3001,\n            },\n        ),\n        # Ports set on the command line take precedence\n        (\n            {\"backend_port\": 8001, \"frontend_port\": 3001},\n            {\"REFLEX_BACKEND_PORT\": 8002},\n            {\"frontend_port\": 3005},\n            {\n                \"api_url\": \"http://localhost:8002\",\n                \"backend_port\": 8002,\n                \"deploy_url\": \"http://localhost:3005\",\n                \"frontend_port\": 3005,\n            },\n        ),\n        # api_url / deploy_url already set should not be overridden\n        (\n            {\"api_url\": \"http://foo.bar:8900\", \"deploy_url\": \"http://foo.bar:3001\"},\n            {\"REFLEX_BACKEND_PORT\": 8002},\n            {\"frontend_port\": 3005},\n            {\n                \"api_url\": \"http://foo.bar:8900\",\n                \"backend_port\": 8002,\n                \"deploy_url\": \"http://foo.bar:3001\",\n                \"frontend_port\": 3005,\n            },\n        ),\n    ],\n)\ndef test_replace_defaults(\n    monkeypatch,\n    config_kwargs,\n    env_vars,\n    set_persistent_vars,\n    exp_config_values,\n):\n    \"\"\"Test that the config replaces defaults with values from the environment.\n\n    Args:\n        monkeypatch: The pytest monkeypatch object.\n        config_kwargs: The config kwargs.\n        env_vars: The environment variables.\n        set_persistent_vars: The values passed to config._set_persistent variables.\n        exp_config_values: The expected config values.\n    \"\"\"\n    mock_os_env = os.environ.copy()\n    monkeypatch.setattr(reflex.config.os, \"environ\", mock_os_env)\n    mock_os_env.update({k: str(v) for k, v in env_vars.items()})\n    c = rx.Config(app_name=\"a\", **config_kwargs)\n    c._set_persistent(**set_persistent_vars)\n    for key, value in exp_config_values.items():\n        assert getattr(c, key) == value\n\n\ndef reflex_dir_constant() -> Path:\n    return environment.REFLEX_DIR.get()\n\n\ndef test_reflex_dir_env_var(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:\n    \"\"\"Test that the REFLEX_DIR environment variable is used to set the Reflex.DIR constant.\n\n    Args:\n        monkeypatch: The pytest monkeypatch object.\n        tmp_path: The pytest tmp_path object.\n    \"\"\"\n    monkeypatch.setenv(\"REFLEX_DIR\", str(tmp_path))\n\n    mp_ctx = multiprocessing.get_context(method=\"spawn\")\n    assert reflex_dir_constant() == tmp_path\n    with mp_ctx.Pool(processes=1) as pool:\n        assert pool.apply(reflex_dir_constant) == tmp_path\n\n\ndef test_interpret_enum_env() -> None:\n    assert interpret_enum_env(Env.PROD.value, Env, \"REFLEX_ENV\") == Env.PROD\n\n\ndef test_interpret_int_env() -> None:\n    assert interpret_int_env(\"3001\", \"FRONTEND_PORT\") == 3001\n\n\n@pytest.mark.parametrize((\"value\", \"expected\"), [(\"true\", True), (\"false\", False)])\ndef test_interpret_bool_env(value: str, expected: bool) -> None:\n    assert interpret_boolean_env(value, \"TELEMETRY_ENABLED\") == expected\n\n\ndef test_env_var():\n    class TestEnv:\n        BLUBB: EnvVar[str] = env_var(\"default\")\n        INTERNAL: EnvVar[str] = env_var(\"default\", internal=True)\n        BOOLEAN: EnvVar[bool] = env_var(False)\n        LIST: EnvVar[list[int]] = env_var([1, 2, 3])\n\n    assert TestEnv.BLUBB.get() == \"default\"\n    assert TestEnv.BLUBB.name == \"BLUBB\"\n    TestEnv.BLUBB.set(\"new\")\n    assert os.environ.get(\"BLUBB\") == \"new\"\n    assert TestEnv.BLUBB.get() == \"new\"\n    TestEnv.BLUBB.set(None)\n    assert \"BLUBB\" not in os.environ\n\n    assert TestEnv.INTERNAL.get() == \"default\"\n    assert TestEnv.INTERNAL.name == \"__INTERNAL\"\n    TestEnv.INTERNAL.set(\"new\")\n    assert os.environ.get(\"__INTERNAL\") == \"new\"\n    assert TestEnv.INTERNAL.get() == \"new\"\n    assert TestEnv.INTERNAL.getenv() == \"new\"\n    TestEnv.INTERNAL.set(None)\n    assert \"__INTERNAL\" not in os.environ\n\n    assert TestEnv.BOOLEAN.get() is False\n    assert TestEnv.BOOLEAN.name == \"BOOLEAN\"\n    TestEnv.BOOLEAN.set(True)\n    assert os.environ.get(\"BOOLEAN\") == \"True\"\n    assert TestEnv.BOOLEAN.get() is True\n    TestEnv.BOOLEAN.set(False)\n    assert os.environ.get(\"BOOLEAN\") == \"False\"\n    assert TestEnv.BOOLEAN.get() is False\n    TestEnv.BOOLEAN.set(None)\n    assert \"BOOLEAN\" not in os.environ\n\n    assert TestEnv.LIST.get() == [1, 2, 3]\n    assert TestEnv.LIST.name == \"LIST\"\n    TestEnv.LIST.set([4, 5, 6])\n    assert os.environ.get(\"LIST\") == \"4:5:6\"\n    assert TestEnv.LIST.get() == [4, 5, 6]\n    TestEnv.LIST.set(None)\n    assert \"LIST\" not in os.environ\n\n\n@pytest.fixture\ndef restore_env():\n    \"\"\"Fixture to restore the environment variables after the test.\n\n    Yields:\n        None: Placeholder for the test to run.\n    \"\"\"\n    original_env = os.environ.copy()\n    yield\n    os.environ.clear()\n    os.environ.update(original_env)\n\n\n@pytest.mark.usefixtures(\"restore_env\")\n@pytest.mark.parametrize(\n    (\"file_map\", \"env_file\", \"exp_env_vars\"),\n    [\n        (\n            {\n                \".env\": \"APP_NAME=my_test_app\\nFRONTEND_PORT=3001\\nBACKEND_PORT=8001\\n\",\n            },\n            \"{path}/.env\",\n            {\n                \"APP_NAME\": \"my_test_app\",\n                \"FRONTEND_PORT\": \"3001\",\n                \"BACKEND_PORT\": \"8001\",\n            },\n        ),\n        (\n            {\n                \".env\": \"FRONTEND_PORT=4001\",\n            },\n            \"{path}/.env{sep}{path}/.env.local\",\n            {\n                \"FRONTEND_PORT\": \"4001\",\n            },\n        ),\n        (\n            {\n                \".env\": \"APP_NAME=my_test_app\\nFRONTEND_PORT=3001\\nBACKEND_PORT=8001\\n\",\n                \".env.local\": \"FRONTEND_PORT=3002\\n\",\n            },\n            \"{path}/.env.local{sep}{path}/.env\",\n            {\n                \"APP_NAME\": \"my_test_app\",\n                \"FRONTEND_PORT\": \"3002\",  # Overrides .env\n                \"BACKEND_PORT\": \"8001\",\n            },\n        ),\n    ],\n)\ndef test_env_file(\n    tmp_path: Path,\n    file_map: dict[str, str],\n    env_file: str,\n    exp_env_vars: dict[str, str],\n) -> None:\n    \"\"\"Test that the env_file method loads environment variables from a file.\n\n    Args:\n        tmp_path: The pytest tmp_path object.\n        file_map: A mapping of file names to their contents.\n        env_file: The path to the environment file to load.\n        exp_env_vars: The expected environment variables after loading the file.\n    \"\"\"\n    for filename, content in file_map.items():\n        (tmp_path / filename).write_text(content)\n\n    _ = rx.Config(\n        app_name=\"test_env_file\",\n        env_file=env_file.format(path=tmp_path, sep=os.pathsep),\n    )\n    for key, value in exp_env_vars.items():\n        assert os.environ.get(key) == value\n\n\nclass TestDisablePlugins:\n    \"\"\"Tests for the disable_plugins config option.\"\"\"\n\n    def test_disable_with_plugin_class(self):\n        \"\"\"Test disabling a plugin by passing the class (type).\"\"\"\n        config = rx.Config(app_name=\"test\", disable_plugins=[SitemapPlugin])\n        assert not any(isinstance(p, SitemapPlugin) for p in config.plugins)\n\n    def test_disable_with_plugin_instance_backward_compat(self):\n        \"\"\"Test disabling a plugin by passing an instance (deprecated).\"\"\"\n        config = rx.Config(app_name=\"test\", disable_plugins=[SitemapPlugin()])  # pyright: ignore[reportArgumentType]\n        assert not any(isinstance(p, SitemapPlugin) for p in config.plugins)\n\n    def test_disable_with_string_backward_compat(self):\n        \"\"\"Test disabling a plugin by passing a string (deprecated).\"\"\"\n        config = rx.Config(\n            app_name=\"test\",\n            disable_plugins=[\"reflex.plugins.sitemap.SitemapPlugin\"],  # pyright: ignore[reportArgumentType]\n        )\n        assert not any(isinstance(p, SitemapPlugin) for p in config.plugins)\n\n    def test_disable_plugins_normalized_to_classes(self):\n        \"\"\"Test that disable_plugins entries are normalized to Plugin subclasses.\"\"\"\n        config = rx.Config(app_name=\"test\", disable_plugins=[SitemapPlugin])\n        assert all(\n            isinstance(dp, type) and issubclass(dp, Plugin)\n            for dp in config.disable_plugins\n        )\n\n    def test_disable_instance_normalized_to_class(self):\n        \"\"\"Test that a Plugin instance in disable_plugins is normalized to its class.\"\"\"\n        config = rx.Config(app_name=\"test\", disable_plugins=[SitemapPlugin()])  # pyright: ignore[reportArgumentType]\n        assert config.disable_plugins == [SitemapPlugin]\n\n    def test_disable_string_normalized_to_class(self):\n        \"\"\"Test that a string in disable_plugins is normalized to the class.\"\"\"\n        config = rx.Config(\n            app_name=\"test\",\n            disable_plugins=[\"reflex.plugins.sitemap.SitemapPlugin\"],  # pyright: ignore[reportArgumentType]\n        )\n        assert config.disable_plugins == [SitemapPlugin]\n\n    def test_disable_and_plugins_conflict_warns(self):\n        \"\"\"Test that a warning is issued when a plugin is both enabled and disabled.\"\"\"\n        config = rx.Config(\n            app_name=\"test\",\n            plugins=[SitemapPlugin()],\n            disable_plugins=[SitemapPlugin],\n        )\n        # Plugin should still be in plugins list (just warned)\n        assert any(isinstance(p, SitemapPlugin) for p in config.plugins)\n\n    def test_no_disable_adds_builtin(self):\n        \"\"\"Test that builtin plugins are added when not disabled.\"\"\"\n        config = rx.Config(app_name=\"test\")\n        assert any(isinstance(p, SitemapPlugin) for p in config.plugins)\n"
  },
  {
    "path": "tests/units/test_db_config.py",
    "content": "import urllib.parse\n\nimport pytest\n\nfrom reflex.config import DBConfig\n\n\n@pytest.mark.parametrize(\n    (\"engine\", \"username\", \"password\", \"host\", \"port\", \"database\", \"expected_url\"),\n    [\n        (\n            \"postgresql\",\n            \"user\",\n            \"pass\",\n            \"localhost\",\n            5432,\n            \"db\",\n            \"postgresql://user:pass@localhost:5432/db\",\n        ),\n        (\n            \"postgresql\",\n            \"user\",\n            \"pass\",\n            \"localhost\",\n            None,\n            \"db\",\n            \"postgresql://user:pass@localhost/db\",\n        ),\n        (\n            \"postgresql\",\n            \"user\",\n            None,\n            \"localhost\",\n            None,\n            \"db\",\n            \"postgresql://user@localhost/db\",\n        ),\n        (\"postgresql\", \"user\", None, None, None, \"db\", \"postgresql://user@/db\"),\n        (\"postgresql\", \"user\", None, None, 5432, \"db\", \"postgresql://user@/db\"),\n        (\n            \"postgresql\",\n            None,\n            None,\n            \"localhost\",\n            5432,\n            \"db\",\n            \"postgresql://localhost:5432/db\",\n        ),\n        (\"sqlite\", None, None, None, None, \"db.sqlite\", \"sqlite:///db.sqlite\"),\n    ],\n)\ndef test_get_url(engine, username, password, host, port, database, expected_url):\n    \"\"\"Test generation of URL.\n\n    Args:\n        engine: Database engine.\n        username: Database username.\n        password: Database password.\n        host: Database host.\n        port: Database port.\n        database: Database name.\n        expected_url: Expected database URL generated.\n    \"\"\"\n    db_config = DBConfig(\n        engine=engine,\n        username=username,\n        password=password,\n        host=host,\n        port=port,\n        database=database,\n    )\n    assert db_config.get_url() == expected_url\n\n\ndef test_url_encode():\n    \"\"\"Test username and password are urlencoded when database URL is generated.\"\"\"\n    username = \"user@user\"\n    password = \"pass@pass\"\n    database = \"db\"\n    username_encoded = urllib.parse.quote_plus(username)\n    password_encoded = urllib.parse.quote_plus(password)\n    engine = \"postgresql\"\n\n    db_config = DBConfig(\n        engine=engine, username=username, password=password, database=database\n    )\n    assert (\n        db_config.get_url()\n        == f\"{engine}://{username_encoded}:{password_encoded}@/{database}\"\n    )\n\n\ndef test_url_encode_database_name():\n    \"\"\"Test database name is not URL encoded.\"\"\"\n    username = \"user\"\n    password = \"pass\"\n    database = \"db@prod\"\n    engine = \"postgresql\"\n\n    db_config = DBConfig(\n        engine=engine, username=username, password=password, database=database\n    )\n    assert db_config.get_url() == f\"{engine}://{username}:{password}@/{database}\"\n\n\ndef test_constructor_sqlite():\n    \"\"\"Test DBConfig.sqlite constructor create the instance correctly.\"\"\"\n    db_config = DBConfig.sqlite(database=\"app.db\")\n    assert db_config.engine == \"sqlite\"\n    assert db_config.username == \"\"\n    assert db_config.password == \"\"\n    assert db_config.host == \"\"\n    assert db_config.port is None\n    assert db_config.database == \"app.db\"\n    assert db_config.get_url() == \"sqlite:///app.db\"\n\n\n@pytest.mark.parametrize(\n    (\"username\", \"password\", \"host\", \"port\", \"database\", \"expected_url\"),\n    [\n        (\n            \"user\",\n            \"pass\",\n            \"localhost\",\n            5432,\n            \"db\",\n            \"postgresql://user:pass@localhost:5432/db\",\n        ),\n        (\"user\", \"\", \"localhost\", None, \"db\", \"postgresql://user@localhost/db\"),\n        (\"user\", \"\", \"\", None, \"db\", \"postgresql://user@/db\"),\n        (\"\", \"\", \"localhost\", 5432, \"db\", \"postgresql://localhost:5432/db\"),\n        (\"\", \"\", \"\", None, \"db\", \"postgresql:///db\"),\n    ],\n)\ndef test_constructor_postgresql(username, password, host, port, database, expected_url):\n    \"\"\"Test DBConfig.postgresql constructor creates the instance correctly.\n\n    Args:\n        username: Database username.\n        password: Database password.\n        host: Database host.\n        port: Database port.\n        database: Database name.\n        expected_url: Expected database URL generated.\n    \"\"\"\n    db_config = DBConfig.postgresql(\n        username=username, password=password, host=host, port=port, database=database\n    )\n    assert db_config.engine == \"postgresql\"\n    assert db_config.username == username\n    assert db_config.password == password\n    assert db_config.host == host\n    assert db_config.port == port\n    assert db_config.database == database\n    assert db_config.get_url() == expected_url\n\n\n@pytest.mark.parametrize(\n    (\"username\", \"password\", \"host\", \"port\", \"database\", \"expected_url\"),\n    [\n        (\n            \"user\",\n            \"pass\",\n            \"localhost\",\n            5432,\n            \"db\",\n            \"postgresql+psycopg://user:pass@localhost:5432/db\",\n        ),\n        (\n            \"user\",\n            \"\",\n            \"localhost\",\n            None,\n            \"db\",\n            \"postgresql+psycopg://user@localhost/db\",\n        ),\n        (\"user\", \"\", \"\", None, \"db\", \"postgresql+psycopg://user@/db\"),\n        (\"\", \"\", \"localhost\", 5432, \"db\", \"postgresql+psycopg://localhost:5432/db\"),\n        (\"\", \"\", \"\", None, \"db\", \"postgresql+psycopg:///db\"),\n    ],\n)\ndef test_constructor_postgresql_psycopg(\n    username, password, host, port, database, expected_url\n):\n    \"\"\"Test DBConfig.postgresql_psycopg constructor creates the instance correctly.\n\n    Args:\n        username: Database username.\n        password: Database password.\n        host: Database host.\n        port: Database port.\n        database: Database name.\n        expected_url: Expected database URL generated.\n    \"\"\"\n    db_config = DBConfig.postgresql_psycopg(\n        username=username, password=password, host=host, port=port, database=database\n    )\n    assert db_config.engine == \"postgresql+psycopg\"\n    assert db_config.username == username\n    assert db_config.password == password\n    assert db_config.host == host\n    assert db_config.port == port\n    assert db_config.database == database\n    assert db_config.get_url() == expected_url\n"
  },
  {
    "path": "tests/units/test_environment.py",
    "content": "\"\"\"Tests for the environment module.\"\"\"\n\nimport enum\nimport os\nimport tempfile\nfrom pathlib import Path\nfrom typing import Annotated\nfrom unittest.mock import patch\n\nimport pytest\n\nfrom reflex import constants\nfrom reflex.environment import (\n    EnvironmentVariables,\n    EnvVar,\n    ExecutorType,\n    ExistingPath,\n    PerformanceMode,\n    SequenceOptions,\n    _load_dotenv_from_files,\n    _paths_from_env_files,\n    _paths_from_environment,\n    env_var,\n    environment,\n    get_default_value_for_field,\n    get_type_hints_environment,\n    interpret_boolean_env,\n    interpret_enum_env,\n    interpret_env_var_value,\n    interpret_existing_path_env,\n    interpret_int_env,\n    interpret_path_env,\n    interpret_plugin_class_env,\n    interpret_plugin_env,\n)\nfrom reflex.plugins import Plugin\nfrom reflex.utils.exceptions import EnvironmentVarValueError\n\n\nclass TestPlugin(Plugin):\n    \"\"\"Test plugin for testing purposes.\"\"\"\n\n\nclass _TestEnum(enum.Enum):\n    \"\"\"Test enum for testing purposes.\"\"\"\n\n    VALUE1 = \"value1\"\n    VALUE2 = \"value2\"\n\n\nclass TestInterpretFunctions:\n    \"\"\"Test the interpret functions.\"\"\"\n\n    def test_interpret_boolean_env_true_values(self):\n        \"\"\"Test boolean interpretation with true values.\"\"\"\n        true_values = [\"true\", \"1\", \"yes\", \"y\", \"TRUE\", \"True\", \"YES\", \"Y\"]\n        for value in true_values:\n            assert interpret_boolean_env(value, \"TEST_FIELD\") is True\n\n    def test_interpret_boolean_env_false_values(self):\n        \"\"\"Test boolean interpretation with false values.\"\"\"\n        false_values = [\"false\", \"0\", \"no\", \"n\", \"FALSE\", \"False\", \"NO\", \"N\"]\n        for value in false_values:\n            assert interpret_boolean_env(value, \"TEST_FIELD\") is False\n\n    def test_interpret_boolean_env_invalid_value(self):\n        \"\"\"Test boolean interpretation with invalid values.\"\"\"\n        with pytest.raises(EnvironmentVarValueError, match=\"Invalid boolean value\"):\n            interpret_boolean_env(\"invalid\", \"TEST_FIELD\")\n\n    def test_interpret_int_env_valid(self):\n        \"\"\"Test integer interpretation with valid values.\"\"\"\n        assert interpret_int_env(\"42\", \"TEST_FIELD\") == 42\n        assert interpret_int_env(\"-10\", \"TEST_FIELD\") == -10\n        assert interpret_int_env(\"0\", \"TEST_FIELD\") == 0\n\n    def test_interpret_int_env_invalid(self):\n        \"\"\"Test integer interpretation with invalid values.\"\"\"\n        with pytest.raises(EnvironmentVarValueError, match=\"Invalid integer value\"):\n            interpret_int_env(\"not_a_number\", \"TEST_FIELD\")\n\n    def test_interpret_path_env(self):\n        \"\"\"Test path interpretation.\"\"\"\n        result = interpret_path_env(\"/some/path\", \"TEST_FIELD\")\n        assert isinstance(result, Path)\n        assert str(result) == str(Path(\"/some/path\"))\n\n    def test_interpret_existing_path_env_valid(self):\n        \"\"\"Test existing path interpretation with valid path.\"\"\"\n        with tempfile.TemporaryDirectory() as temp_dir:\n            result = interpret_existing_path_env(temp_dir, \"TEST_FIELD\")\n            assert isinstance(result, Path)\n            assert result.exists()\n\n    def test_interpret_existing_path_env_invalid(self):\n        \"\"\"Test existing path interpretation with non-existent path.\"\"\"\n        with pytest.raises(EnvironmentVarValueError, match=\"Path does not exist\"):\n            interpret_existing_path_env(\"/non/existent/path\", \"TEST_FIELD\")\n\n    def test_interpret_plugin_env_valid(self):\n        \"\"\"Test plugin interpretation with valid plugin.\"\"\"\n        result = interpret_plugin_env(\n            \"tests.units.test_environment.TestPlugin\", \"TEST_FIELD\"\n        )\n        assert isinstance(result, TestPlugin)\n\n    def test_interpret_plugin_env_invalid_format(self):\n        \"\"\"Test plugin interpretation with invalid format.\"\"\"\n        with pytest.raises(EnvironmentVarValueError, match=\"Invalid plugin value\"):\n            interpret_plugin_env(\"invalid_format\", \"TEST_FIELD\")\n\n    def test_interpret_plugin_env_import_error(self):\n        \"\"\"Test plugin interpretation with import error.\"\"\"\n        with pytest.raises(EnvironmentVarValueError, match=\"Failed to import module\"):\n            interpret_plugin_env(\"non.existent.module.Plugin\", \"TEST_FIELD\")\n\n    def test_interpret_plugin_env_missing_class(self):\n        \"\"\"Test plugin interpretation with missing class.\"\"\"\n        with pytest.raises(EnvironmentVarValueError, match=\"Invalid plugin class\"):\n            interpret_plugin_env(\n                \"tests.units.test_environment.NonExistentPlugin\", \"TEST_FIELD\"\n            )\n\n    def test_interpret_plugin_env_invalid_class(self):\n        \"\"\"Test plugin interpretation with invalid class.\"\"\"\n        with pytest.raises(EnvironmentVarValueError, match=\"Invalid plugin class\"):\n            interpret_plugin_env(\"tests.units.test_environment.TestEnum\", \"TEST_FIELD\")\n\n    def test_interpret_plugin_class_env_valid(self):\n        \"\"\"Test plugin class interpretation returns the class, not an instance.\"\"\"\n        result = interpret_plugin_class_env(\n            \"tests.units.test_environment.TestPlugin\", \"TEST_FIELD\"\n        )\n        assert result is TestPlugin\n\n    def test_interpret_plugin_class_env_invalid_format(self):\n        \"\"\"Test plugin class interpretation with invalid format.\"\"\"\n        with pytest.raises(EnvironmentVarValueError, match=\"Invalid plugin value\"):\n            interpret_plugin_class_env(\"invalid_format\", \"TEST_FIELD\")\n\n    def test_interpret_plugin_class_env_import_error(self):\n        \"\"\"Test plugin class interpretation with import error.\"\"\"\n        with pytest.raises(EnvironmentVarValueError, match=\"Failed to import module\"):\n            interpret_plugin_class_env(\"non.existent.module.Plugin\", \"TEST_FIELD\")\n\n    def test_interpret_plugin_class_env_invalid_class(self):\n        \"\"\"Test plugin class interpretation with invalid class.\"\"\"\n        with pytest.raises(EnvironmentVarValueError, match=\"Invalid plugin class\"):\n            interpret_plugin_class_env(\n                \"tests.units.test_environment.TestEnum\", \"TEST_FIELD\"\n            )\n\n    def test_interpret_enum_env_valid(self):\n        \"\"\"Test enum interpretation with valid values.\"\"\"\n        result = interpret_enum_env(\"value1\", _TestEnum, \"TEST_FIELD\")\n        assert result == _TestEnum.VALUE1\n\n    def test_interpret_enum_env_invalid(self):\n        \"\"\"Test enum interpretation with invalid values.\"\"\"\n        with pytest.raises(EnvironmentVarValueError, match=\"Invalid enum value\"):\n            interpret_enum_env(\"invalid_value\", _TestEnum, \"TEST_FIELD\")\n\n\nclass TestInterpretEnvVarValue:\n    \"\"\"Test the interpret_env_var_value function.\"\"\"\n\n    def test_interpret_string(self):\n        \"\"\"Test string interpretation.\"\"\"\n        result = interpret_env_var_value(\"  test  \", str, \"TEST_FIELD\")\n        assert result == \"test\"\n\n    def test_interpret_boolean(self):\n        \"\"\"Test boolean interpretation.\"\"\"\n        result = interpret_env_var_value(\"true\", bool, \"TEST_FIELD\")\n        assert result is True\n\n    def test_interpret_int(self):\n        \"\"\"Test integer interpretation.\"\"\"\n        result = interpret_env_var_value(\"42\", int, \"TEST_FIELD\")\n        assert result == 42\n\n    def test_interpret_path(self):\n        \"\"\"Test path interpretation.\"\"\"\n        result = interpret_env_var_value(\"/test/path\", Path, \"TEST_FIELD\")\n        assert isinstance(result, Path)\n\n    def test_interpret_existing_path(self):\n        \"\"\"Test existing path interpretation.\"\"\"\n        with tempfile.TemporaryDirectory() as temp_dir:\n            result = interpret_env_var_value(temp_dir, ExistingPath, \"TEST_FIELD\")\n            assert isinstance(result, Path)\n\n    def test_interpret_plugin(self):\n        \"\"\"Test plugin interpretation.\"\"\"\n        result = interpret_env_var_value(\n            \"tests.units.test_environment.TestPlugin\", Plugin, \"TEST_FIELD\"\n        )\n        assert isinstance(result, TestPlugin)\n\n    def test_interpret_plugin_class(self):\n        \"\"\"Test type[Plugin] interpretation returns the class.\"\"\"\n        result = interpret_env_var_value(\n            \"tests.units.test_environment.TestPlugin\",\n            type[Plugin],\n            \"TEST_FIELD\",\n        )\n        assert result is TestPlugin\n\n    def test_interpret_list(self):\n        \"\"\"Test list interpretation.\"\"\"\n        result = interpret_env_var_value(\"1:2:3\", list[int], \"TEST_FIELD\")\n        assert result == [1, 2, 3]\n\n    def test_interpret_annotated_sequence(self):\n        \"\"\"Test annotated sequence interpretation.\"\"\"\n        annotated_type = Annotated[\n            list[str], SequenceOptions(delimiter=\",\", strip=True)\n        ]\n        result = interpret_env_var_value(\"a, b, c \", annotated_type, \"TEST_FIELD\")\n        assert result == [\"a\", \"b\", \"c\"]\n\n    def test_interpret_enum(self):\n        \"\"\"Test enum interpretation.\"\"\"\n        result = interpret_env_var_value(\"value1\", _TestEnum, \"TEST_FIELD\")\n        assert result == _TestEnum.VALUE1\n\n    def test_interpret_union_tries_each_type(self):\n        \"\"\"Test that union types try each type in order.\"\"\"\n        # str matches first\n        assert interpret_env_var_value(\"hello\", int | str, \"TEST_FIELD\") == \"hello\"\n        # int matches first\n        assert interpret_env_var_value(\"42\", int | str, \"TEST_FIELD\") == 42\n        # bool matches before str\n        assert interpret_env_var_value(\"true\", bool | str, \"TEST_FIELD\") is True\n\n    def test_interpret_union_no_match(self):\n        \"\"\"Test that union types raise an error if no type matches.\"\"\"\n        with pytest.raises(EnvironmentVarValueError, match=\"Could not interpret\"):\n            interpret_env_var_value(\"not_a_number\", int | bool, \"TEST_FIELD\")\n\n    def test_interpret_unsupported_type(self):\n        \"\"\"Test unsupported type raises an error.\"\"\"\n        with pytest.raises(ValueError, match=\"Invalid type for environment variable\"):\n            interpret_env_var_value(\"test\", dict, \"TEST_FIELD\")\n\n    def test_interpret_optional_type(self):\n        \"\"\"Test optional type interpretation.\"\"\"\n        # This should work by extracting the inner type\n        result = interpret_env_var_value(\"42\", int | None, \"TEST_FIELD\")\n        assert result == 42\n\n\nclass TestEnvVar:\n    \"\"\"Test the EnvVar class.\"\"\"\n\n    def test_init(self):\n        \"\"\"Test EnvVar initialization.\"\"\"\n        env_var_instance = EnvVar(\"TEST_VAR\", \"default\", str)\n        assert env_var_instance.name == \"TEST_VAR\"\n        assert env_var_instance.default == \"default\"\n        assert env_var_instance.type_ is str\n\n    def test_interpret(self):\n        \"\"\"Test EnvVar interpret method.\"\"\"\n        env_var_instance = EnvVar(\"TEST_VAR\", 0, int)\n        result = env_var_instance.interpret(\"42\")\n        assert result == 42\n\n    def test_getenv_set(self, monkeypatch):\n        \"\"\"Test getenv when environment variable is set.\n\n        Args:\n            monkeypatch: pytest monkeypatch fixture.\n        \"\"\"\n        monkeypatch.setenv(\"TEST_VAR\", \"test_value\")\n        env_var_instance = EnvVar(\"TEST_VAR\", \"default\", str)\n        result = env_var_instance.getenv()\n        assert result == \"test_value\"\n\n    def test_getenv_not_set(self):\n        \"\"\"Test getenv when environment variable is not set.\"\"\"\n        env_var_instance = EnvVar(\"NONEXISTENT_VAR\", \"default\", str)\n        result = env_var_instance.getenv()\n        assert result is None\n\n    def test_getenv_empty_string(self, monkeypatch):\n        \"\"\"Test getenv with empty string value.\n\n        Args:\n            monkeypatch: pytest monkeypatch fixture.\n        \"\"\"\n        monkeypatch.setenv(\"TEST_VAR\", \"\")\n        env_var_instance = EnvVar(\"TEST_VAR\", \"default\", str)\n        result = env_var_instance.getenv()\n        assert result is None\n\n    def test_getenv_whitespace_only(self, monkeypatch):\n        \"\"\"Test getenv with whitespace-only value.\n\n        Args:\n            monkeypatch: pytest monkeypatch fixture.\n        \"\"\"\n        monkeypatch.setenv(\"TEST_VAR\", \"   \")\n        env_var_instance = EnvVar(\"TEST_VAR\", \"default\", str)\n        result = env_var_instance.getenv()\n        assert result is None\n\n    def test_is_set_true(self, monkeypatch):\n        \"\"\"Test is_set when variable is set.\n\n        Args:\n            monkeypatch: pytest monkeypatch fixture.\n        \"\"\"\n        monkeypatch.setenv(\"TEST_VAR\", \"value\")\n        env_var_instance = EnvVar(\"TEST_VAR\", \"default\", str)\n        assert env_var_instance.is_set() is True\n\n    def test_is_set_false(self):\n        \"\"\"Test is_set when variable is not set.\"\"\"\n        env_var_instance = EnvVar(\"NONEXISTENT_VAR\", \"default\", str)\n        assert env_var_instance.is_set() is False\n\n    def test_is_set_empty_string(self, monkeypatch):\n        \"\"\"Test is_set with empty string.\n\n        Args:\n            monkeypatch: pytest monkeypatch fixture.\n        \"\"\"\n        monkeypatch.setenv(\"TEST_VAR\", \"\")\n        env_var_instance = EnvVar(\"TEST_VAR\", \"default\", str)\n        assert env_var_instance.is_set() is False\n\n    def test_get_with_env_value(self, monkeypatch):\n        \"\"\"Test get method when environment variable is set.\n\n        Args:\n            monkeypatch: pytest monkeypatch fixture.\n        \"\"\"\n        monkeypatch.setenv(\"TEST_VAR\", \"env_value\")\n        env_var_instance = EnvVar(\"TEST_VAR\", \"default\", str)\n        result = env_var_instance.get()\n        assert result == \"env_value\"\n\n    def test_get_with_default(self):\n        \"\"\"Test get method when environment variable is not set.\"\"\"\n        env_var_instance = EnvVar(\"NONEXISTENT_VAR\", \"default\", str)\n        result = env_var_instance.get()\n        assert result == \"default\"\n\n    def test_set_string_value(self):\n        \"\"\"Test setting a string value.\"\"\"\n        env_var_instance = EnvVar(\"TEST_VAR\", \"default\", str)\n        env_var_instance.set(\"new_value\")  # type: ignore[arg-type]\n        assert os.environ.get(\"TEST_VAR\") == \"new_value\"\n        # Clean up\n        del os.environ[\"TEST_VAR\"]\n\n    def test_set_none_value(self, monkeypatch):\n        \"\"\"Test setting None value removes the environment variable.\n\n        Args:\n            monkeypatch: pytest monkeypatch fixture.\n        \"\"\"\n        monkeypatch.setenv(\"TEST_VAR\", \"value\")\n        env_var_instance = EnvVar(\"TEST_VAR\", \"default\", str)\n        env_var_instance.set(None)\n        assert \"TEST_VAR\" not in os.environ\n\n    def test_set_enum_value(self):\n        \"\"\"Test setting an enum value.\"\"\"\n        env_var_instance = EnvVar(\"TEST_VAR\", _TestEnum.VALUE1, _TestEnum)\n        env_var_instance.set(_TestEnum.VALUE2)  # type: ignore[arg-type]\n        assert os.environ.get(\"TEST_VAR\") == \"value2\"\n        # Clean up\n        del os.environ[\"TEST_VAR\"]\n\n    def test_set_list_value(self):\n        \"\"\"Test setting a list value.\"\"\"\n        env_var_instance = EnvVar(\"TEST_VAR\", [], list[int])\n        env_var_instance.set([1, 2, 3])  # type: ignore[arg-type]\n        assert os.environ.get(\"TEST_VAR\") == \"1:2:3\"\n        # Clean up\n        del os.environ[\"TEST_VAR\"]\n\n\nclass TestEnvVarDescriptor:\n    \"\"\"Test the env_var descriptor.\"\"\"\n\n    def test_descriptor_get_normal(self):\n        \"\"\"Test getting EnvVar from descriptor.\"\"\"\n\n        class TestEnv:\n            TEST_VAR: EnvVar[str] = env_var(\"default\")\n\n        env_var_instance = TestEnv.TEST_VAR\n        assert isinstance(env_var_instance, EnvVar)\n        assert env_var_instance.name == \"TEST_VAR\"\n        assert env_var_instance.default == \"default\"\n\n    def test_descriptor_get_internal(self):\n        \"\"\"Test getting internal EnvVar from descriptor.\"\"\"\n\n        class TestEnv:\n            INTERNAL_VAR: EnvVar[str] = env_var(\"default\", internal=True)\n\n        env_var_instance = TestEnv.INTERNAL_VAR\n        assert isinstance(env_var_instance, EnvVar)\n        assert env_var_instance.name == \"__INTERNAL_VAR\"\n        assert env_var_instance.default == \"default\"\n\n\nclass TestExecutorType:\n    \"\"\"Test the ExecutorType enum and related functionality.\"\"\"\n\n    def test_executor_type_values(self):\n        \"\"\"Test ExecutorType enum values.\"\"\"\n        assert ExecutorType.THREAD.value == \"thread\"\n        assert ExecutorType.PROCESS.value == \"process\"\n        assert ExecutorType.MAIN_THREAD.value == \"main_thread\"\n\n    def test_get_executor_main_thread_mode(self):\n        \"\"\"Test executor selection in main thread mode.\"\"\"\n        with (\n            patch.object(\n                environment.REFLEX_COMPILE_EXECUTOR,\n                \"get\",\n                return_value=ExecutorType.MAIN_THREAD,\n            ),\n            patch.object(\n                environment.REFLEX_COMPILE_PROCESSES, \"get\", return_value=None\n            ),\n            patch.object(environment.REFLEX_COMPILE_THREADS, \"get\", return_value=None),\n        ):\n            executor = ExecutorType.get_executor_from_environment()\n\n            # Test the main thread executor functionality\n            with executor:\n                future = executor.submit(lambda x: x * 2, 5)\n                assert future.result() == 10\n\n    def test_get_executor_returns_executor(self):\n        \"\"\"Test that get_executor_from_environment returns an executor.\"\"\"\n        # Test with default values - should return some kind of executor\n        executor = ExecutorType.get_executor_from_environment()\n        assert executor is not None\n\n        # Test that we can use it as a context manager\n        with executor:\n            future = executor.submit(lambda: \"test\")\n            assert future.result() == \"test\"\n\n\nclass TestUtilityFunctions:\n    \"\"\"Test utility functions.\"\"\"\n\n    def test_get_type_hints_environment(self):\n        \"\"\"Test get_type_hints_environment function.\"\"\"\n\n        class TestClass:\n            var1: str\n            var2: int\n\n        hints = get_type_hints_environment(TestClass)\n        assert \"var1\" in hints\n        assert \"var2\" in hints\n        assert hints[\"var1\"] is str\n        assert hints[\"var2\"] is int\n\n    def test_paths_from_env_files(self):\n        \"\"\"Test _paths_from_env_files function.\"\"\"\n        env_files = \"/path/one\" + os.pathsep + \"/path/two\" + os.pathsep + \"/path/three\"\n        result = _paths_from_env_files(env_files)\n\n        # Should be reversed order\n        expected = [Path(\"/path/three\"), Path(\"/path/two\"), Path(\"/path/one\")]\n        assert result == expected\n\n    def test_paths_from_env_files_with_spaces(self):\n        \"\"\"Test _paths_from_env_files with spaces.\"\"\"\n        env_files = (\n            \" /path/one \" + os.pathsep + \" /path/two \" + os.pathsep + \" /path/three \"\n        )\n        result = _paths_from_env_files(env_files)\n\n        expected = [Path(\"/path/three\"), Path(\"/path/two\"), Path(\"/path/one\")]\n        assert result == expected\n\n    def test_paths_from_env_files_empty(self):\n        \"\"\"Test _paths_from_env_files with empty string.\"\"\"\n        result = _paths_from_env_files(\"\")\n        assert result == []\n\n    def test_paths_from_environment_set(self, monkeypatch):\n        \"\"\"Test _paths_from_environment when REFLEX_ENV_FILE is set.\n\n        Args:\n            monkeypatch: pytest monkeypatch fixture.\n        \"\"\"\n        monkeypatch.setenv(\"REFLEX_ENV_FILE\", \"/path/one\" + os.pathsep + \"/path/two\")\n        result = _paths_from_environment()\n        expected = [Path(\"/path/two\"), Path(\"/path/one\")]\n        assert result == expected\n\n    def test_paths_from_environment_not_set(self):\n        \"\"\"Test _paths_from_environment when REFLEX_ENV_FILE is not set.\"\"\"\n        # Ensure the env var is not set\n        if \"REFLEX_ENV_FILE\" in os.environ:\n            del os.environ[\"REFLEX_ENV_FILE\"]\n\n        result = _paths_from_environment()\n        assert result == []\n\n    @patch(\"reflex.environment.load_dotenv\")\n    def test_load_dotenv_from_files_with_dotenv(self, mock_load_dotenv):\n        \"\"\"Test _load_dotenv_from_files when dotenv is available.\n\n        Args:\n            mock_load_dotenv: Mock for the load_dotenv function.\n        \"\"\"\n        with tempfile.TemporaryDirectory() as temp_dir:\n            file1 = Path(temp_dir) / \"file1.env\"\n            file2 = Path(temp_dir) / \"file2.env\"\n            file1.touch()\n            file2.touch()\n\n            _load_dotenv_from_files([file1, file2])\n\n            assert mock_load_dotenv.call_count == 2\n            mock_load_dotenv.assert_any_call(file1, override=True)\n            mock_load_dotenv.assert_any_call(file2, override=True)\n\n    @patch(\"reflex.environment.load_dotenv\", None)\n    @patch(\"reflex.utils.console\")\n    def test_load_dotenv_from_files_without_dotenv(self, mock_console):\n        \"\"\"Test _load_dotenv_from_files when dotenv is not available.\n\n        Args:\n            mock_console: Mock for the console object.\n        \"\"\"\n        with tempfile.TemporaryDirectory() as temp_dir:\n            file1 = Path(temp_dir) / \"file1.env\"\n            file1.touch()\n\n            _load_dotenv_from_files([file1])\n            mock_console.error.assert_called_once()\n\n    def test_load_dotenv_from_files_empty_list(self):\n        \"\"\"Test _load_dotenv_from_files with empty file list.\"\"\"\n        # Should not raise any errors\n        _load_dotenv_from_files([])\n\n    @patch(\"reflex.environment.load_dotenv\")\n    def test_load_dotenv_from_files_nonexistent_file(self, mock_load_dotenv):\n        \"\"\"Test _load_dotenv_from_files with non-existent file.\n\n        Args:\n            mock_load_dotenv: Mock for the load_dotenv function.\n        \"\"\"\n        nonexistent_file = Path(\"/non/existent/file.env\")\n        _load_dotenv_from_files([nonexistent_file])\n\n        # Should not call load_dotenv for non-existent files\n        mock_load_dotenv.assert_not_called()\n\n\nclass TestEnvironmentVariables:\n    \"\"\"Test the EnvironmentVariables class and its instances.\"\"\"\n\n    def test_environment_instance_exists(self):\n        \"\"\"Test that the environment instance exists and is properly typed.\"\"\"\n        assert isinstance(environment, EnvironmentVariables)\n\n    def test_environment_variables_have_correct_types(self):\n        \"\"\"Test that environment variables have the correct types.\"\"\"\n        # Test a few key environment variables\n        assert isinstance(environment.REFLEX_USE_NPM, EnvVar)\n        assert isinstance(environment.REFLEX_USE_GRANIAN, EnvVar)\n        assert isinstance(environment.REFLEX_WEB_WORKDIR, EnvVar)\n        assert isinstance(environment.REFLEX_FRONTEND_PORT, EnvVar)\n        assert isinstance(environment.REFLEX_BACKEND_PORT, EnvVar)\n\n    def test_environment_variables_defaults(self):\n        \"\"\"Test that environment variables have the expected defaults.\"\"\"\n        assert environment.REFLEX_USE_NPM.get() is False\n        assert environment.REFLEX_USE_GRANIAN.get() is False\n        assert environment.REFLEX_USE_SYSTEM_BUN.get() is False\n        assert environment.REFLEX_WEB_WORKDIR.get() == Path(constants.Dirs.WEB)\n        assert environment.REFLEX_STATES_WORKDIR.get() == Path(constants.Dirs.STATES)\n\n    def test_internal_environment_variables(self):\n        \"\"\"Test internal environment variables have correct names.\"\"\"\n        assert environment.REFLEX_COMPILE_CONTEXT.name == \"__REFLEX_COMPILE_CONTEXT\"\n        assert environment.REFLEX_SKIP_COMPILE.name == \"__REFLEX_SKIP_COMPILE\"\n\n    def test_performance_mode_enum(self):\n        \"\"\"Test PerformanceMode enum.\"\"\"\n        assert PerformanceMode.WARN.value == \"warn\"\n        assert PerformanceMode.RAISE.value == \"raise\"\n        assert PerformanceMode.OFF.value == \"off\"\n\n        # Test that the default is WARN\n        assert environment.REFLEX_PERF_MODE.get() == PerformanceMode.WARN\n\n\nclass TestGetDefaultValueForField:\n    \"\"\"Test the get_default_value_for_field function.\"\"\"\n\n    def test_get_default_value_for_field_with_default(self):\n        \"\"\"Test field with default value.\"\"\"\n        import dataclasses\n\n        @dataclasses.dataclass\n        class TestClass:\n            field: str = \"default_value\"\n\n        field = dataclasses.fields(TestClass)[0]\n        result = get_default_value_for_field(field)\n        assert result == \"default_value\"\n\n    def test_get_default_value_for_field_with_default_factory(self):\n        \"\"\"Test field with default factory.\"\"\"\n        import dataclasses\n\n        @dataclasses.dataclass\n        class TestClass:\n            field: list = dataclasses.field(default_factory=list)\n\n        field = dataclasses.fields(TestClass)[0]\n        result = get_default_value_for_field(field)\n        assert result == []\n\n    def test_get_default_value_for_field_without_default(self):\n        \"\"\"Test field without default value or factory.\"\"\"\n        import dataclasses\n\n        @dataclasses.dataclass\n        class TestClass:\n            field: str\n\n        field = dataclasses.fields(TestClass)[0]\n        with pytest.raises(ValueError, match=\"Missing value for environment variable\"):\n            get_default_value_for_field(field)\n\n\n@pytest.fixture(autouse=True)\ndef cleanup_env_vars():\n    \"\"\"Clean up test environment variables after each test.\n\n    Yields:\n        None: Fixture yields control back to the test.\n    \"\"\"\n    test_vars = [\n        \"TEST_VAR\",\n        \"NONEXISTENT_VAR\",\n        \"BLUBB\",\n        \"__INTERNAL\",\n        \"BOOLEAN\",\n        \"LIST\",\n        \"__INTERNAL_VAR\",\n    ]\n\n    yield\n\n    for var in test_vars:\n        if var in os.environ:\n            print(var)\n            del os.environ[var]\n"
  },
  {
    "path": "tests/units/test_event.py",
    "content": "import json\nfrom collections.abc import Callable\n\nimport pytest\n\nimport reflex as rx\nfrom reflex.constants.compiler import Hooks, Imports\nfrom reflex.event import (\n    BACKGROUND_TASK_MARKER,\n    Event,\n    EventChain,\n    EventHandler,\n    EventSpec,\n    call_event_handler,\n    event,\n    fix_events,\n)\nfrom reflex.state import BaseState\nfrom reflex.utils import format\nfrom reflex.vars.base import Field, LiteralVar, Var, VarData, field\n\n\ndef make_var(value) -> Var:\n    \"\"\"Make a variable.\n\n    Args:\n        value: The value of the var.\n\n    Returns:\n        The var.\n    \"\"\"\n    return Var(_js_expr=value)\n\n\ndef test_create_event():\n    \"\"\"Test creating an event.\"\"\"\n    event = Event(token=\"token\", name=\"state.do_thing\", payload={\"arg\": \"value\"})\n    assert event.token == \"token\"\n    assert event.name == \"state.do_thing\"\n    assert event.payload == {\"arg\": \"value\"}\n\n\ndef test_call_event_handler():\n    \"\"\"Test that calling an event handler creates an event spec.\"\"\"\n\n    def test_fn():\n        pass\n\n    test_fn.__qualname__ = \"test_fn\"\n\n    def fn_with_args(_, arg1, arg2):\n        pass\n\n    fn_with_args.__qualname__ = \"fn_with_args\"\n\n    handler = EventHandler(fn=test_fn)\n    event_spec = handler()\n\n    assert event_spec.handler == handler\n    assert event_spec.args == ()\n    assert format.format_event(event_spec) == 'ReflexEvent(\"test_fn\", {})'\n\n    handler = EventHandler(fn=fn_with_args)\n    event_spec = handler(make_var(\"first\"), make_var(\"second\"))\n\n    # Test passing vars as args.\n    assert event_spec.handler == handler\n    assert event_spec.args[0][0].equals(Var(_js_expr=\"arg1\"))\n    assert event_spec.args[0][1].equals(Var(_js_expr=\"first\"))\n    assert event_spec.args[1][0].equals(Var(_js_expr=\"arg2\"))\n    assert event_spec.args[1][1].equals(Var(_js_expr=\"second\"))\n    assert (\n        format.format_event(event_spec)\n        == 'ReflexEvent(\"fn_with_args\", {arg1:first,arg2:second})'\n    )\n\n    # Passing args as strings should format differently.\n    event_spec = handler(\"first\", \"second\")\n    assert (\n        format.format_event(event_spec)\n        == 'ReflexEvent(\"fn_with_args\", {arg1:\"first\",arg2:\"second\"})'\n    )\n\n    first, second = 123, \"456\"\n    handler = EventHandler(fn=fn_with_args)\n    event_spec = handler(first, second)\n    assert (\n        format.format_event(event_spec)\n        == 'ReflexEvent(\"fn_with_args\", {arg1:123,arg2:\"456\"})'\n    )\n\n    assert event_spec.handler == handler\n    assert event_spec.args[0][0].equals(Var(_js_expr=\"arg1\"))\n    assert event_spec.args[0][1].equals(LiteralVar.create(first))\n    assert event_spec.args[1][0].equals(Var(_js_expr=\"arg2\"))\n    assert event_spec.args[1][1].equals(LiteralVar.create(second))\n\n    handler = EventHandler(fn=fn_with_args)\n    with pytest.raises(TypeError):\n        handler(test_fn)\n\n\ndef test_call_event_handler_partial():\n    \"\"\"Calling an EventHandler with incomplete args returns an EventSpec that can be extended.\"\"\"\n\n    def fn_with_args(_, arg1, arg2):\n        pass\n\n    fn_with_args.__qualname__ = \"fn_with_args\"\n\n    def spec(a2: Var[str]) -> list[Var[str]]:\n        return [a2]\n\n    handler = EventHandler(fn=fn_with_args, state_full_name=\"BigState\")\n    event_spec = handler(make_var(\"first\"))\n    event_spec2 = call_event_handler(event_spec, spec)\n\n    assert event_spec.handler == handler\n    assert len(event_spec.args) == 1\n    assert event_spec.args[0][0].equals(Var(_js_expr=\"arg1\"))\n    assert event_spec.args[0][1].equals(Var(_js_expr=\"first\"))\n    assert (\n        format.format_event(event_spec)\n        == 'ReflexEvent(\"BigState.fn_with_args\", {arg1:first})'\n    )\n\n    assert event_spec2 is not event_spec\n    assert event_spec2.handler == handler\n    assert len(event_spec2.args) == 2\n    assert event_spec2.args[0][0].equals(Var(_js_expr=\"arg1\"))\n    assert event_spec2.args[0][1].equals(Var(_js_expr=\"first\"))\n    assert event_spec2.args[1][0].equals(Var(_js_expr=\"arg2\"))\n    assert event_spec2.args[1][1].equals(Var(_js_expr=\"_a2\", _var_type=str))\n    assert (\n        format.format_event(event_spec2)\n        == 'ReflexEvent(\"BigState.fn_with_args\", {arg1:first,arg2:_a2})'\n    )\n\n\n@pytest.mark.parametrize(\n    (\"arg1\", \"arg2\"),\n    [\n        (1, 2),\n        (1, \"2\"),\n        ({\"a\": 1}, {\"b\": 2}),\n    ],\n)\ndef test_fix_events(arg1, arg2):\n    \"\"\"Test that chaining an event handler with args formats the payload correctly.\n\n    Args:\n        arg1: The first arg passed to the handler.\n        arg2: The second arg passed to the handler.\n    \"\"\"\n\n    def fn_with_args(_, arg1, arg2):\n        pass\n\n    fn_with_args.__qualname__ = \"fn_with_args\"\n\n    handler = EventHandler(fn=fn_with_args)\n    event_spec = handler(arg1, arg2)\n    event = fix_events([event_spec], token=\"foo\")[0]\n    assert event.name == fn_with_args.__qualname__\n    assert event.token == \"foo\"\n    assert event.payload == {\"arg1\": arg1, \"arg2\": arg2}\n\n\n@pytest.mark.parametrize(\n    (\"input\", \"output\"),\n    [\n        (\n            (path, is_external, replace, popup),\n            f'ReflexEvent(\"_redirect\", {{path:{json.dumps(path) if isinstance(path, str) else path._js_expr},external:{\"true\" if is_external else \"false\"},popup:{\"true\" if popup else \"false\"},replace:{\"true\" if replace else \"false\"}}})',\n        )\n        for path in (\"/path\", Var(_js_expr=\"path\"))\n        for is_external in (None, True, False)\n        for replace in (None, True, False)\n        for popup in (None, True, False)\n    ],\n)\ndef test_event_redirect(input, output):\n    \"\"\"Test the event redirect function.\n\n    Args:\n        input: The input for running the test.\n        output: The expected output to validate the test.\n    \"\"\"\n    path, is_external, replace, popup = input\n    kwargs = {}\n    if is_external is not None:\n        kwargs[\"is_external\"] = is_external\n    if replace is not None:\n        kwargs[\"replace\"] = replace\n    if popup is not None:\n        kwargs[\"popup\"] = popup\n    spec = event.redirect(path, **kwargs)\n    assert isinstance(spec, EventSpec)\n    assert spec.handler.fn.__qualname__ == \"_redirect\"\n    assert format.format_event(spec) == output\n\n\ndef test_event_console_log():\n    \"\"\"Test the event console log function.\"\"\"\n    spec = event.console_log(\"message\")\n    assert isinstance(spec, EventSpec)\n    assert spec.handler.fn.__qualname__ == \"_call_function\"\n    assert spec.args[0][0].equals(Var(_js_expr=\"function\"))\n    assert spec.args[0][1].equals(\n        Var('(() => (console?.[\"log\"](\"message\")))', _var_type=Callable)\n    )\n    assert (\n        format.format_event(spec)\n        == 'ReflexEvent(\"_call_function\", {function:(() => (console?.[\"log\"](\"message\"))),callback:null})'\n    )\n    spec = event.console_log(Var(_js_expr=\"message\"))\n    assert (\n        format.format_event(spec)\n        == 'ReflexEvent(\"_call_function\", {function:(() => (console?.[\"log\"](message))),callback:null})'\n    )\n    spec2 = event.console_log(Var(_js_expr=\"message2\")).add_args(Var(\"throwaway\"))\n    assert (\n        format.format_event(spec2)\n        == 'ReflexEvent(\"_call_function\", {function:(() => (console?.[\"log\"](message2))),callback:null})'\n    )\n\n\ndef test_event_window_alert():\n    \"\"\"Test the event window alert function.\"\"\"\n    spec = event.window_alert(\"message\")\n    assert isinstance(spec, EventSpec)\n    assert spec.handler.fn.__qualname__ == \"_call_function\"\n    assert spec.args[0][0].equals(Var(_js_expr=\"function\"))\n    assert spec.args[0][1].equals(\n        Var('(() => (window?.[\"alert\"](\"message\")))', _var_type=Callable)\n    )\n    assert (\n        format.format_event(spec)\n        == 'ReflexEvent(\"_call_function\", {function:(() => (window?.[\"alert\"](\"message\"))),callback:null})'\n    )\n    spec = event.window_alert(Var(_js_expr=\"message\"))\n    assert (\n        format.format_event(spec)\n        == 'ReflexEvent(\"_call_function\", {function:(() => (window?.[\"alert\"](message))),callback:null})'\n    )\n    spec2 = event.window_alert(Var(_js_expr=\"message2\")).add_args(Var(\"throwaway\"))\n    assert (\n        format.format_event(spec2)\n        == 'ReflexEvent(\"_call_function\", {function:(() => (window?.[\"alert\"](message2))),callback:null})'\n    )\n\n\n@pytest.mark.parametrize(\n    (\"func\", \"qualname\"), [(\"set_focus\", \"_set_focus\"), (\"blur_focus\", \"_blur_focus\")]\n)\ndef test_focus(func: str, qualname: str):\n    \"\"\"Test the event set focus function.\n\n    Args:\n        func: The event function name.\n        qualname: The sig qual name passed to JS.\n    \"\"\"\n    spec = getattr(event, func)(\"input1\")\n    assert isinstance(spec, EventSpec)\n    assert spec.handler.fn.__qualname__ == qualname\n    assert spec.args[0][0].equals(Var(_js_expr=\"ref\"))\n    assert spec.args[0][1].equals(LiteralVar.create(\"ref_input1\"))\n    assert (\n        format.format_event(spec) == f'ReflexEvent(\"{qualname}\", {{ref:\"ref_input1\"}})'\n    )\n    spec = getattr(event, func)(\"input1\")\n    assert (\n        format.format_event(spec) == f'ReflexEvent(\"{qualname}\", {{ref:\"ref_input1\"}})'\n    )\n\n\ndef test_set_value():\n    \"\"\"Test the event window alert function.\"\"\"\n    spec = event.set_value(\"input1\", \"\")\n    assert isinstance(spec, EventSpec)\n    assert spec.handler.fn.__qualname__ == \"_set_value\"\n    assert spec.args[0][0].equals(Var(_js_expr=\"ref\"))\n    assert spec.args[0][1].equals(LiteralVar.create(\"ref_input1\"))\n    assert spec.args[1][0].equals(Var(_js_expr=\"value\"))\n    assert spec.args[1][1].equals(LiteralVar.create(\"\"))\n    assert (\n        format.format_event(spec)\n        == 'ReflexEvent(\"_set_value\", {ref:\"ref_input1\",value:\"\"})'\n    )\n    spec = event.set_value(\"input1\", Var(_js_expr=\"message\"))\n    assert (\n        format.format_event(spec)\n        == 'ReflexEvent(\"_set_value\", {ref:\"ref_input1\",value:message})'\n    )\n\n\ndef test_remove_cookie():\n    \"\"\"Test the event remove_cookie.\"\"\"\n    spec = event.remove_cookie(\"testkey\")\n    assert isinstance(spec, EventSpec)\n    assert spec.handler.fn.__qualname__ == \"_remove_cookie\"\n    assert spec.args[0][0].equals(Var(_js_expr=\"key\"))\n    assert spec.args[0][1].equals(LiteralVar.create(\"testkey\"))\n    assert spec.args[1][0].equals(Var(_js_expr=\"options\"))\n    assert spec.args[1][1].equals(LiteralVar.create({\"path\": \"/\"}))\n    assert (\n        format.format_event(spec)\n        == 'ReflexEvent(\"_remove_cookie\", {key:\"testkey\",options:({ [\"path\"] : \"/\" })})'\n    )\n\n\ndef test_remove_cookie_with_options():\n    \"\"\"Test the event remove_cookie with options.\"\"\"\n    options = {\n        \"path\": \"/foo\",\n        \"domain\": \"example.com\",\n        \"secure\": True,\n        \"sameSite\": \"strict\",\n    }\n    spec = event.remove_cookie(\"testkey\", options)\n    assert isinstance(spec, EventSpec)\n    assert spec.handler.fn.__qualname__ == \"_remove_cookie\"\n    assert spec.args[0][0].equals(Var(_js_expr=\"key\"))\n    assert spec.args[0][1].equals(LiteralVar.create(\"testkey\"))\n    assert spec.args[1][0].equals(Var(_js_expr=\"options\"))\n    assert spec.args[1][1].equals(LiteralVar.create(options))\n    assert (\n        format.format_event(spec)\n        == f'ReflexEvent(\"_remove_cookie\", {{key:\"testkey\",options:{LiteralVar.create(options)!s}}})'\n    )\n\n\ndef test_clear_local_storage():\n    \"\"\"Test the event clear_local_storage.\"\"\"\n    spec = event.clear_local_storage()\n    assert isinstance(spec, EventSpec)\n    assert spec.handler.fn.__qualname__ == \"_clear_local_storage\"\n    assert not spec.args\n    assert format.format_event(spec) == 'ReflexEvent(\"_clear_local_storage\", {})'\n\n\ndef test_remove_local_storage():\n    \"\"\"Test the event remove_local_storage.\"\"\"\n    spec = event.remove_local_storage(\"testkey\")\n    assert isinstance(spec, EventSpec)\n    assert spec.handler.fn.__qualname__ == \"_remove_local_storage\"\n    assert spec.args[0][0].equals(Var(_js_expr=\"key\"))\n    assert spec.args[0][1].equals(LiteralVar.create(\"testkey\"))\n    assert (\n        format.format_event(spec)\n        == 'ReflexEvent(\"_remove_local_storage\", {key:\"testkey\"})'\n    )\n\n\ndef test_event_actions():\n    \"\"\"Test DOM event actions, like stopPropagation and preventDefault.\"\"\"\n    # EventHandler\n    handler = EventHandler(fn=lambda: None)\n    assert not handler.event_actions\n    sp_handler = handler.stop_propagation\n    assert handler is not sp_handler\n    assert sp_handler.event_actions == {\"stopPropagation\": True}\n    pd_handler = handler.prevent_default\n    assert handler is not pd_handler\n    assert pd_handler.event_actions == {\"preventDefault\": True}\n    both_handler = sp_handler.prevent_default\n    assert both_handler is not sp_handler\n    assert both_handler.event_actions == {\n        \"stopPropagation\": True,\n        \"preventDefault\": True,\n    }\n\n    throttle_handler = handler.throttle(300)\n    assert handler is not throttle_handler\n    assert throttle_handler.event_actions == {\"throttle\": 300}\n\n    debounce_handler = handler.debounce(300)\n    assert handler is not debounce_handler\n    assert debounce_handler.event_actions == {\"debounce\": 300}\n\n    all_handler = handler.stop_propagation.prevent_default.throttle(200).debounce(100)\n    assert handler is not all_handler\n    assert all_handler.event_actions == {\n        \"stopPropagation\": True,\n        \"preventDefault\": True,\n        \"throttle\": 200,\n        \"debounce\": 100,\n    }\n\n    assert not handler.event_actions\n\n    # Convert to EventSpec should carry event actions\n    sp_handler2 = handler.stop_propagation.throttle(200)\n    spec = sp_handler2()\n    assert spec.event_actions == {\"stopPropagation\": True, \"throttle\": 200}\n    assert spec.event_actions == sp_handler2.event_actions\n    assert spec.event_actions is not sp_handler2.event_actions\n    # But it should be a copy!\n    assert spec.event_actions is not sp_handler2.event_actions\n    spec2 = spec.prevent_default\n    assert spec is not spec2\n    assert spec2.event_actions == {\n        \"stopPropagation\": True,\n        \"preventDefault\": True,\n        \"throttle\": 200,\n    }\n    assert spec2.event_actions != spec.event_actions\n\n    # The original handler should still not be touched.\n    assert not handler.event_actions\n\n\ndef test_event_actions_on_state():\n    class EventActionState(BaseState):\n        def handler(self):\n            pass\n\n    handler = EventActionState.handler\n    assert isinstance(handler, EventHandler)\n    assert not handler.event_actions\n\n    sp_handler = EventActionState.handler.stop_propagation  # pyright: ignore [reportFunctionMemberAccess]\n    assert sp_handler.event_actions == {\"stopPropagation\": True}\n    # should NOT affect other references to the handler\n    assert not handler.event_actions\n\n\ndef test_event_var_data():\n    class S(BaseState):\n        x: Field[int] = field(0)\n\n        @event\n        def s(self, value: int):\n            pass\n\n        @event\n        def s2(self):\n            pass\n\n    # Handler doesn't have any _var_data because it's just a str\n    handler_var = Var.create(S.s2)\n    assert handler_var._get_all_var_data() is None\n\n    # Ensure spec carries _var_data\n    spec_var = Var.create(S.s(S.x))\n    assert spec_var._get_all_var_data() == S.x._get_all_var_data()\n\n    # Needed to instantiate the EventChain\n    def _args_spec(value: Var[int]) -> tuple[Var[int]]:\n        return (value,)\n\n    # Ensure chain carries _var_data\n    chain_var = Var.create(\n        EventChain(\n            events=[S.s(S.x)],\n            args_spec=_args_spec,\n            invocation=rx.vars.FunctionStringVar.create(\"\"),\n        )\n    )\n    assert chain_var._get_all_var_data() == S.x._get_all_var_data()\n\n    chain_var_data = Var.create(\n        EventChain(\n            events=[],\n            args_spec=_args_spec,\n        )\n    )._get_all_var_data()\n    assert chain_var_data is not None\n\n    assert chain_var_data == VarData(\n        imports=Imports.EVENTS,\n        hooks={Hooks.EVENTS: None},\n    )\n\n\ndef test_event_bound_method() -> None:\n    class S(BaseState):\n        @event\n        def e(self, arg: str):\n            print(arg)\n\n    class Wrapper:\n        def get_handler(self, arg: Var[str]):\n            return S.e(arg)\n\n    w = Wrapper()\n    _ = rx.input(on_change=w.get_handler)\n\n\ndef test_event_decorator_with_event_actions():\n    \"\"\"Test that @rx.event decorator can accept event action parameters.\"\"\"\n\n    class MyTestState(BaseState):\n        # Test individual event actions\n        @event(stop_propagation=True)\n        def handle_stop_prop(self):\n            pass\n\n        @event(prevent_default=True)\n        def handle_prevent_default(self):\n            pass\n\n        @event(throttle=500)\n        def handle_throttle(self):\n            pass\n\n        @event(debounce=300)\n        def handle_debounce(self):\n            pass\n\n        @event(temporal=True)\n        def handle_temporal(self):\n            pass\n\n        # Test multiple event actions combined\n        @event(stop_propagation=True, prevent_default=True, throttle=1000)\n        def handle_multiple(self):\n            pass\n\n        # Test with background parameter (existing functionality)\n        @event(background=True, temporal=True)\n        async def handle_background_temporal(self):\n            pass\n\n        # Test no event actions (existing behavior)\n        @event\n        def handle_no_actions(self):\n            pass\n\n    # Test individual event actions are applied\n    stop_prop_handler = MyTestState.handle_stop_prop\n    assert isinstance(stop_prop_handler, EventHandler)\n    assert stop_prop_handler.event_actions == {\"stopPropagation\": True}\n\n    prevent_default_handler = MyTestState.handle_prevent_default\n    assert prevent_default_handler.event_actions == {\"preventDefault\": True}\n\n    throttle_handler = MyTestState.handle_throttle\n    assert throttle_handler.event_actions == {\"throttle\": 500}\n\n    debounce_handler = MyTestState.handle_debounce\n    assert debounce_handler.event_actions == {\"debounce\": 300}\n\n    temporal_handler = MyTestState.handle_temporal\n    assert temporal_handler.event_actions == {\"temporal\": True}\n\n    # Test multiple event actions are combined correctly\n    multiple_handler = MyTestState.handle_multiple\n    assert multiple_handler.event_actions == {\n        \"stopPropagation\": True,\n        \"preventDefault\": True,\n        \"throttle\": 1000,\n    }\n\n    # Test background + event actions work together\n    bg_temporal_handler = MyTestState.handle_background_temporal\n    assert bg_temporal_handler.event_actions == {\"temporal\": True}\n    assert hasattr(bg_temporal_handler.fn, BACKGROUND_TASK_MARKER)  # pyright: ignore [reportAttributeAccessIssue]\n\n    # Test no event actions (existing behavior preserved)\n    no_actions_handler = MyTestState.handle_no_actions\n    assert no_actions_handler.event_actions == {}\n\n\ndef test_event_decorator_actions_can_be_overridden():\n    \"\"\"Test that decorator event actions can still be overridden by chaining.\"\"\"\n\n    class MyTestState(BaseState):\n        @event(throttle=500, stop_propagation=True)\n        def handle_with_defaults(self):\n            pass\n\n    # Get the handler with default actions\n    handler = MyTestState.handle_with_defaults\n    assert handler.event_actions == {\"throttle\": 500, \"stopPropagation\": True}\n\n    # Chain additional actions - should combine\n    handler_with_prevent_default = handler.prevent_default\n    assert handler_with_prevent_default.event_actions == {\n        \"throttle\": 500,\n        \"stopPropagation\": True,\n        \"preventDefault\": True,\n    }\n\n    # Chain throttle with different value - should override\n    handler_with_new_throttle = handler.throttle(1000)\n    assert handler_with_new_throttle.event_actions == {\n        \"throttle\": 1000,  # New value overrides default\n        \"stopPropagation\": True,\n    }\n\n    # Original handler should be unchanged\n    assert handler.event_actions == {\"throttle\": 500, \"stopPropagation\": True}\n\n\ndef test_event_decorator_with_none_values():\n    \"\"\"Test that None values in decorator don't create event actions.\"\"\"\n\n    class MyTestState(BaseState):\n        @event(stop_propagation=None, prevent_default=None, throttle=None)\n        def handle_all_none(self):\n            pass\n\n        @event(stop_propagation=True, prevent_default=None, throttle=500, debounce=None)\n        def handle_mixed(self):\n            pass\n\n    # All None should result in no event actions\n    all_none_handler = MyTestState.handle_all_none\n    assert all_none_handler.event_actions == {}\n\n    # Only non-None values should be included\n    mixed_handler = MyTestState.handle_mixed\n    assert mixed_handler.event_actions == {\"stopPropagation\": True, \"throttle\": 500}\n\n\ndef test_event_decorator_backward_compatibility():\n    \"\"\"Test that existing code without event action parameters continues to work.\"\"\"\n\n    class MyTestState(BaseState):\n        @event\n        def handle_old_style(self):\n            pass\n\n        @event(background=True)\n        async def handle_old_background(self):\n            pass\n\n    # Old style without parameters should work unchanged\n    old_handler = MyTestState.handle_old_style\n    assert isinstance(old_handler, EventHandler)\n    assert old_handler.event_actions == {}\n    assert not hasattr(old_handler.fn, BACKGROUND_TASK_MARKER)  # pyright: ignore [reportAttributeAccessIssue]\n\n    # Old background parameter should work unchanged\n    bg_handler = MyTestState.handle_old_background\n    assert bg_handler.event_actions == {}\n    assert hasattr(bg_handler.fn, BACKGROUND_TASK_MARKER)  # pyright: ignore [reportAttributeAccessIssue]\n\n\ndef test_event_var_in_rx_cond():\n    \"\"\"Test that EventVar and EventChainVar cannot be used in rx.cond().\"\"\"\n    from reflex.components.core.cond import cond as rx_cond\n\n    class S(BaseState):\n        @event\n        def s(self):\n            pass\n\n    handler_var = Var.create(S.s)\n    with pytest.raises(TypeError) as err:\n        rx_cond(handler_var, rx.text(\"True\"), rx.text(\"False\"))\n    assert \"Cannot convert\" in str(err.value)\n    assert \"to bool\" in str(err.value)\n\n    def _args_spec() -> tuple:\n        return ()\n\n    chain_var = Var.create(\n        EventChain(\n            events=[S.s()],\n            args_spec=_args_spec,\n        )\n    )\n    with pytest.raises(TypeError) as err:\n        rx_cond(chain_var, rx.text(\"True\"), rx.text(\"False\"))\n    assert \"Cannot convert\" in str(err.value)\n    assert \"to bool\" in str(err.value)\n\n\ndef test_decentralized_event_with_args():\n    \"\"\"Test the decentralized event.\"\"\"\n\n    class S(BaseState):\n        field: Field[str] = field(\"\")\n\n    @event\n    def e(s: S, arg: str):\n        s.field = arg\n\n    _ = rx.input(on_change=e(\"foo\"))\n\n\ndef test_decentralized_event_no_args():\n    \"\"\"Test the decentralized event with no args.\"\"\"\n\n    class S(BaseState):\n        field: Field[str] = field(\"\")\n\n    @event\n    def e(s: S):\n        s.field = \"foo\"\n\n    _ = rx.input(on_change=e())\n    _ = rx.input(on_change=e)\n\n\nclass GlobalState(BaseState):\n    \"\"\"Global state for testing decentralized events.\"\"\"\n\n    field: Field[str] = field(\"\")\n\n\n@event\ndef f(s: GlobalState, arg: str):\n    s.field = arg\n\n\ndef test_decentralized_event_global_state():\n    \"\"\"Test the decentralized event with a global state.\"\"\"\n    _ = rx.input(on_change=f(\"foo\"))\n    _ = rx.input(on_change=f)\n"
  },
  {
    "path": "tests/units/test_health_endpoint.py",
    "content": "import json\nfrom importlib.util import find_spec\nfrom unittest.mock import MagicMock, Mock\n\nimport pytest\nfrom pytest_mock import MockerFixture\nfrom redis.exceptions import RedisError\n\nfrom reflex.app import health\nfrom reflex.model import get_db_status\nfrom reflex.utils.prerequisites import get_redis_status\n\npytest.importorskip(\"sqlalchemy\")\n\nimport sqlalchemy.exc\n\n\ndef _get_async_function(func):\n    async def _async_func(*args, **kwargs):  # noqa: RUF029\n        return func(*args, **kwargs)\n\n    return _async_func\n\n\n@pytest.mark.asyncio\n@pytest.mark.parametrize(\n    (\"mock_redis_client\", \"expected_status\"),\n    [\n        # Case 1: Redis client is available and responds to ping\n        (Mock(ping=_get_async_function(lambda: None)), {\"redis\": True}),\n        # Case 2: Redis client raises RedisError\n        (\n            Mock(ping=_get_async_function(lambda: (_ for _ in ()).throw(RedisError))),\n            {\"redis\": False},\n        ),\n        # Case 3: Redis client is not used\n        (None, {\"redis\": None}),\n    ],\n)\nasync def test_get_redis_status(\n    mock_redis_client, expected_status, mocker: MockerFixture\n):\n    # Mock the `get_redis` function to return the mock Redis client\n    mock_get_redis = mocker.patch(\n        \"reflex.utils.prerequisites.get_redis\", return_value=mock_redis_client\n    )\n\n    # Call the function\n    status = await get_redis_status()\n\n    # Verify the result\n    assert status == expected_status\n    mock_get_redis.assert_called_once()\n\n\n@pytest.mark.skipif(\n    not find_spec(\"sqlmodel\") or not find_spec(\"pydantici\"),\n    reason=\"sqlmodel not installed or pydantic is not installed\",\n)\n@pytest.mark.asyncio\n@pytest.mark.parametrize(\n    (\"mock_engine\", \"execute_side_effect\", \"expected_status\"),\n    [\n        # Case 1: Database is accessible\n        (MagicMock(), None, {\"db\": True}),\n        # Case 2: Database connection error (OperationalError)\n        (\n            MagicMock(),\n            sqlalchemy.exc.OperationalError(\"error\", \"error\", \"error\"),  # pyright: ignore[reportArgumentType]\n            {\"db\": False},\n        ),\n    ],\n)\ndef test_get_db_status(\n    mock_engine, execute_side_effect, expected_status, mocker: MockerFixture\n):\n    # Mock get_engine to return the mock_engine\n    mock_get_engine = mocker.patch(\"reflex.model.get_engine\", return_value=mock_engine)\n\n    # Mock the connection and its execute method\n    if mock_engine:\n        mock_connection = mock_engine.connect.return_value.__enter__.return_value\n        if execute_side_effect:\n            # Simulate execute method raising an exception\n            mock_connection.execute.side_effect = execute_side_effect\n        else:\n            # Simulate successful execute call\n            mock_connection.execute.return_value = None\n\n    # Call the function\n    status = get_db_status()\n\n    # Verify the result\n    assert status == expected_status\n    mock_get_engine.assert_called_once()\n\n\n@pytest.mark.skipif(\n    not find_spec(\"sqlmodel\") or not find_spec(\"pydantic\"),\n    reason=\"sqlmodel not installed or pydantic is not installed\",\n)\n@pytest.mark.asyncio\n@pytest.mark.parametrize(\n    (\n        \"db_enabled\",\n        \"redis_enabled\",\n        \"db_status\",\n        \"redis_status\",\n        \"expected_status\",\n        \"expected_code\",\n    ),\n    [\n        # Case 1: Both services are connected\n        (True, True, True, True, {\"status\": True, \"db\": True, \"redis\": True}, 200),\n        # Case 2: Database not connected, Redis connected\n        (True, True, False, True, {\"status\": False, \"db\": False, \"redis\": True}, 503),\n        # Case 3: Database connected, Redis not connected\n        (True, True, True, False, {\"status\": False, \"db\": True, \"redis\": False}, 503),\n        # Case 4: Both services not connected\n        (True, True, False, False, {\"status\": False, \"db\": False, \"redis\": False}, 503),\n        # Case 5: Database Connected, Redis not used\n        (True, False, True, None, {\"status\": True, \"db\": True}, 200),\n        # Case 6: Database not used, Redis Connected\n        (False, True, None, True, {\"status\": True, \"redis\": True}, 200),\n        # Case 7: Both services not used\n        (False, False, None, None, {\"status\": True}, 200),\n    ],\n)\nasync def test_health(\n    db_enabled,\n    redis_enabled,\n    db_status,\n    redis_status,\n    expected_status,\n    expected_code,\n    mocker: MockerFixture,\n):\n    # Mock get_db_status and get_redis_status\n    mocker.patch(\n        \"reflex.utils.prerequisites.check_db_used\",\n        return_value=db_enabled,\n    )\n    mocker.patch(\n        \"reflex.utils.prerequisites.check_redis_used\",\n        return_value=redis_enabled,\n    )\n    mocker.patch(\n        \"reflex.model.get_db_status\",\n        return_value={\"db\": db_status},\n    )\n    mocker.patch(\n        \"reflex.utils.prerequisites.get_redis_status\",\n        return_value={\"redis\": redis_status},\n    )\n\n    request = Mock()\n\n    # Call the async health function\n    response = await health(request)\n\n    # Verify the response content and status code\n    assert response.status_code == expected_code\n    assert isinstance(response.body, bytes)\n    assert json.loads(response.body) == expected_status\n"
  },
  {
    "path": "tests/units/test_model.py",
    "content": "import math\nfrom pathlib import Path\nfrom unittest import mock\n\nimport pytest\n\nimport reflex.constants\nimport reflex.model\nfrom reflex.constants.state import FIELD_MARKER\nfrom reflex.model import Model, ModelRegistry\nfrom reflex.state import BaseState, State\nfrom tests.units.test_state import (\n    mock_app_simple,  # noqa: F401 # for pytest.mark.usefixtures\n)\n\npytest.importorskip(\"alembic\")\npytest.importorskip(\"sqlalchemy\")\npytest.importorskip(\"sqlmodel\")\n\n\n@pytest.fixture\ndef model_default_primary() -> Model:\n    \"\"\"Returns a model object with no defined primary key.\n\n    Returns:\n        Model: Model object.\n    \"\"\"\n\n    class ChildModel(Model):\n        name: str\n\n    return ChildModel(name=\"name\")\n\n\n@pytest.fixture\ndef model_custom_primary() -> Model:\n    \"\"\"Returns a model object with a custom primary key.\n\n    Returns:\n        Model: Model object.\n    \"\"\"\n    import sqlmodel\n\n    class ChildModel(Model):\n        custom_id: int | None = sqlmodel.Field(default=None, primary_key=True)\n        name: str\n\n    return ChildModel(name=\"name\")\n\n\ndef test_default_primary_key(model_default_primary: Model):\n    \"\"\"Test that if a primary key is not defined a default is added.\n\n    Args:\n        model_default_primary: Fixture.\n    \"\"\"\n    assert \"id\" in type(model_default_primary).model_fields\n\n\ndef test_custom_primary_key(model_custom_primary: Model):\n    \"\"\"Test that if a primary key is defined no default key is added.\n\n    Args:\n        model_custom_primary: Fixture.\n    \"\"\"\n    assert \"id\" not in type(model_custom_primary).model_fields\n\n\n@pytest.mark.filterwarnings(\n    \"ignore:This declarative base already contains a class with the same class name\",\n)\ndef test_automigration(\n    tmp_working_dir: Path,\n    monkeypatch: pytest.MonkeyPatch,\n    model_registry: type[ModelRegistry],\n):\n    \"\"\"Test alembic automigration with add and drop table and column.\n\n    Args:\n        tmp_working_dir: directory where database and migrations are stored\n        monkeypatch: pytest fixture to overwrite attributes\n        model_registry: clean reflex ModelRegistry\n    \"\"\"\n    import sqlalchemy.exc\n    import sqlmodel\n\n    alembic_ini = tmp_working_dir / \"alembic.ini\"\n    versions = tmp_working_dir / \"alembic\" / \"versions\"\n    monkeypatch.setattr(reflex.constants, \"ALEMBIC_CONFIG\", str(alembic_ini))\n\n    config_mock = mock.Mock()\n    config_mock.db_url = f\"sqlite:///{tmp_working_dir}/reflex.db\"\n    monkeypatch.setattr(reflex.model, \"get_config\", mock.Mock(return_value=config_mock))\n\n    Model.alembic_init()\n    assert alembic_ini.exists()\n    assert versions.exists()\n\n    # initial table\n    class AlembicThing(Model, table=True):  # pyright: ignore [reportRedeclaration]\n        t1: str\n\n    with Model.get_db_engine().connect() as connection:\n        assert Model.alembic_autogenerate(\n            connection=connection, message=\"Initial Revision\"\n        )\n    assert Model.migrate()\n    version_scripts = list(versions.glob(\"*.py\"))\n    assert len(version_scripts) == 1\n    assert version_scripts[0].name.endswith(\"initial_revision.py\")\n\n    with reflex.model.session() as session:\n        session.add(AlembicThing(id=None, t1=\"foo\"))\n        session.commit()\n\n    model_registry.get_metadata().clear()\n\n    # Create column t2, mark t1 as optional with default\n    class AlembicThing(Model, table=True):  # pyright: ignore [reportRedeclaration]\n        t1: str | None = \"default\"\n        t2: str = \"bar\"\n\n    assert Model.migrate(autogenerate=True)\n    assert len(list(versions.glob(\"*.py\"))) == 2\n\n    with reflex.model.session() as session:\n        session.add(AlembicThing(t2=\"baz\"))\n        session.commit()\n        result = session.exec(sqlmodel.select(AlembicThing)).all()\n        assert len(result) == 2\n        assert result[0].t1 == \"foo\"\n        assert result[0].t2 == \"bar\"\n        assert result[1].t1 == \"default\"\n        assert result[1].t2 == \"baz\"\n\n    model_registry.get_metadata().clear()\n\n    # Drop column t1\n    class AlembicThing(Model, table=True):  # pyright: ignore [reportRedeclaration]\n        t2: str = \"bar\"\n\n    assert Model.migrate(autogenerate=True)\n    assert len(list(versions.glob(\"*.py\"))) == 3\n\n    with reflex.model.session() as session:\n        result = session.exec(sqlmodel.select(AlembicThing)).all()\n        assert len(result) == 2\n        assert result[0].t2 == \"bar\"\n        assert result[1].t2 == \"baz\"\n\n    # Add table\n    class AlembicSecond(Model, table=True):\n        a: int = 42\n        b: float = 4.2\n\n    assert Model.migrate(autogenerate=True)\n    assert len(list(versions.glob(\"*.py\"))) == 4\n\n    with reflex.model.session() as session:\n        session.add(AlembicSecond(id=None))\n        session.commit()\n        result = session.exec(sqlmodel.select(AlembicSecond)).all()\n        assert len(result) == 1\n        assert result[0].a == 42\n        assert math.isclose(result[0].b, 4.2)\n\n    # No-op\n    assert Model.migrate(autogenerate=True)\n    assert len(list(versions.glob(\"*.py\"))) == 4\n\n    # drop table (AlembicSecond)\n    model_registry.get_metadata().clear()\n\n    class AlembicThing(Model, table=True):  # pyright: ignore [reportRedeclaration]\n        t2: str = \"bar\"\n\n    assert Model.migrate(autogenerate=True)\n    assert len(list(versions.glob(\"*.py\"))) == 5\n\n    with reflex.model.session() as session:\n        with pytest.raises(sqlalchemy.exc.OperationalError) as errctx:\n            session.exec(sqlmodel.select(AlembicSecond)).all()\n        assert errctx.match(r\"no such table: alembicsecond\")\n        # first table should still exist\n        result = session.exec(sqlmodel.select(AlembicThing)).all()\n        assert len(result) == 2\n        assert result[0].t2 == \"bar\"\n        assert result[1].t2 == \"baz\"\n\n    model_registry.get_metadata().clear()\n\n    class AlembicThing(Model, table=True):\n        # changing column type not supported by default\n        t2: int = 42\n\n    assert Model.migrate(autogenerate=True)\n    assert len(list(versions.glob(\"*.py\"))) == 5\n\n    # clear all metadata to avoid influencing subsequent tests\n    model_registry.get_metadata().clear()\n\n    # drop remaining tables\n    assert Model.migrate(autogenerate=True)\n    assert len(list(versions.glob(\"*.py\"))) == 6\n\n\nclass ReflexModel(Model):\n    \"\"\"A model for testing.\"\"\"\n\n    foo: str\n\n\nclass UpcastStateWithSqlAlchemy(BaseState):\n    \"\"\"A state for testing upcasting.\"\"\"\n\n    passed: bool = False\n\n    def rx_model(self, m: ReflexModel):  # noqa: D102\n        assert isinstance(m, ReflexModel)\n        self.passed = True\n\n\n@pytest.mark.asyncio\n@pytest.mark.usefixtures(\"mock_app_simple\")\n@pytest.mark.parametrize(\n    (\"handler\", \"payload\"),\n    [\n        (UpcastStateWithSqlAlchemy.rx_model, {\"m\": {\"foo\": \"bar\"}}),\n    ],\n)\nasync def test_upcast_event_handler_arg(handler, payload):\n    \"\"\"Test that upcast event handler args work correctly.\n\n    Args:\n        handler: The handler to test.\n        payload: The payload to test.\n    \"\"\"\n    state = UpcastStateWithSqlAlchemy()\n    async for update in state._process_event(handler, state, payload):\n        assert update.delta == {\n            UpcastStateWithSqlAlchemy.get_full_name(): {\"passed\" + FIELD_MARKER: True}\n        }\n\n\ndef test_no_rebind_mutable_proxy_for_instrumented_functions():\n    \"\"\"Test that we don't rebind mutable proxies for instrumented functions.\"\"\"\n    import sqlalchemy\n    import sqlalchemy.orm\n\n    class SABase(sqlalchemy.orm.MappedAsDataclass, sqlalchemy.orm.DeclarativeBase):\n        pass\n\n    class SAKeyword(SABase):\n        __tablename__ = \"sa_keyword\"\n\n        id: sqlalchemy.orm.Mapped[int] = sqlalchemy.orm.mapped_column(\n            primary_key=True, init=False, default=None\n        )\n        value: sqlalchemy.orm.Mapped[str] = sqlalchemy.orm.mapped_column(default=\"\")\n        obj_id: sqlalchemy.orm.Mapped[int] = sqlalchemy.orm.mapped_column(\n            sqlalchemy.ForeignKey(\"sa_obj.id\"), default=None\n        )\n\n    class SAObj(SABase):\n        __tablename__ = \"sa_obj\"\n\n        id: sqlalchemy.orm.Mapped[int] = sqlalchemy.orm.mapped_column(\n            primary_key=True, init=False, default=None\n        )\n        keywords: sqlalchemy.orm.Mapped[list[SAKeyword]] = sqlalchemy.orm.relationship(\n            lazy=\"selectin\",  # codespell:ignore\n            cascade=\"all, delete\",\n            default_factory=list,\n        )\n\n    class SAState(State):\n        sa_obj: SAObj = SAObj()\n\n    sa_state = SAState()\n    assert \"sa_obj\" not in sa_state.dirty_vars\n    sa_state.sa_obj.keywords.append(SAKeyword(value=\"test\"))\n    assert \"sa_obj\" in sa_state.dirty_vars\n"
  },
  {
    "path": "tests/units/test_page.py",
    "content": "from reflex import text\nfrom reflex.config import get_config\nfrom reflex.page import DECORATED_PAGES, page\n\n\ndef test_page_decorator():\n    def foo_():\n        return text(\"foo\")\n\n    DECORATED_PAGES.clear()\n    assert len(DECORATED_PAGES) == 0\n    decorated_foo_ = page()(foo_)\n    assert decorated_foo_ == foo_\n    assert len(DECORATED_PAGES) == 1\n    page_data = DECORATED_PAGES.get(get_config().app_name, [])[0][1]\n    assert page_data == {}\n    DECORATED_PAGES.clear()\n\n\ndef test_page_decorator_with_kwargs():\n    def foo_():\n        return text(\"foo\")\n\n    def load_foo():\n        return []\n\n    DECORATED_PAGES.clear()\n    assert len(DECORATED_PAGES) == 0\n    decorated_foo_ = page(\n        route=\"foo\",\n        title=\"Foo\",\n        image=\"foo.png\",\n        description=\"Foo description\",\n        meta=[{\"name\": \"keywords\", \"content\": \"foo, test\"}],\n        script_tags=[\"foo-script\"],\n        on_load=load_foo,\n    )(foo_)\n    assert decorated_foo_ == foo_\n    assert len(DECORATED_PAGES) == 1\n    page_data = DECORATED_PAGES.get(get_config().app_name, [])[0][1]\n    assert page_data == {\n        \"description\": \"Foo description\",\n        \"image\": \"foo.png\",\n        \"meta\": [{\"name\": \"keywords\", \"content\": \"foo, test\"}],\n        \"on_load\": load_foo,\n        \"route\": \"foo\",\n        \"script_tags\": [\"foo-script\"],\n        \"title\": \"Foo\",\n    }\n\n    DECORATED_PAGES.clear()\n"
  },
  {
    "path": "tests/units/test_prerequisites.py",
    "content": "import shutil\nimport tempfile\nfrom pathlib import Path\n\nimport pytest\nfrom click.testing import CliRunner\n\nfrom reflex.config import Config\nfrom reflex.constants.installer import PackageJson\nfrom reflex.reflex import cli\nfrom reflex.testing import chdir\nfrom reflex.utils.decorator import cached_procedure\nfrom reflex.utils.frontend_skeleton import (\n    _compile_package_json,\n    _compile_vite_config,\n    _update_react_router_config,\n)\nfrom reflex.utils.rename import rename_imports_and_app_name\nfrom reflex.utils.telemetry import CpuInfo, get_cpu_info\n\nrunner = CliRunner()\n\n\n@pytest.mark.parametrize(\n    (\"config\", \"export\", \"expected_output\"),\n    [\n        (\n            Config(\n                app_name=\"test\",\n            ),\n            False,\n            'export default {\"basename\": \"/\", \"future\": {\"unstable_optimizeDeps\": true}, \"ssr\": false};',\n        ),\n        (\n            Config(\n                app_name=\"test\",\n                static_page_generation_timeout=30,\n            ),\n            False,\n            'export default {\"basename\": \"/\", \"future\": {\"unstable_optimizeDeps\": true}, \"ssr\": false};',\n        ),\n        (\n            Config(\n                app_name=\"test\",\n                frontend_path=\"/test\",\n            ),\n            False,\n            'export default {\"basename\": \"/test/\", \"future\": {\"unstable_optimizeDeps\": true}, \"ssr\": false};',\n        ),\n        (\n            Config(\n                app_name=\"test\",\n            ),\n            True,\n            'export default {\"basename\": \"/\", \"future\": {\"unstable_optimizeDeps\": true}, \"ssr\": false, \"prerender\": true, \"build\": \"build\"};',\n        ),\n    ],\n)\ndef test_update_react_router_config(config, export, expected_output):\n    output = _update_react_router_config(config, prerender_routes=export)\n    assert output == expected_output\n\n\n@pytest.mark.parametrize(\n    (\"config\", \"expected_output\"),\n    [\n        (\n            Config(\n                app_name=\"test\",\n                frontend_path=\"\",\n            ),\n            'assetsDir: \"/assets\".slice(1),',\n        ),\n        (\n            Config(\n                app_name=\"test\",\n                frontend_path=\"/test\",\n            ),\n            'assetsDir: \"/test/assets\".slice(1),',\n        ),\n        (\n            Config(\n                app_name=\"test\",\n                frontend_path=\"/test/\",\n            ),\n            'assetsDir: \"/test/assets\".slice(1),',\n        ),\n    ],\n)\ndef test_initialise_vite_config(config, expected_output):\n    output = _compile_vite_config(config)\n    assert expected_output in output\n\n\n@pytest.mark.parametrize(\n    (\"frontend_path\", \"expected_command\"),\n    [\n        (\"\", \"sirv ./build/client --single 404.html --host\"),\n        (\"/\", \"sirv ./build/client --single 404.html --host\"),\n        (\"/app\", \"sirv ./build/client --single app/404.html --host\"),\n        (\"/app/\", \"sirv ./build/client --single app/404.html --host\"),\n        (\"app\", \"sirv ./build/client --single app/404.html --host\"),\n        (\n            \"/deep/nested/path\",\n            \"sirv ./build/client --single deep/nested/path/404.html --host\",\n        ),\n    ],\n)\ndef test_get_prod_command(frontend_path, expected_command):\n    assert PackageJson.Commands.get_prod_command(frontend_path) == expected_command\n\n\n@pytest.mark.parametrize(\n    (\"config\", \"expected_prod_script\"),\n    [\n        (\n            Config(app_name=\"test\"),\n            \"sirv ./build/client --single 404.html --host\",\n        ),\n        (\n            Config(app_name=\"test\", frontend_path=\"/app\"),\n            \"sirv ./build/client --single app/404.html --host\",\n        ),\n        (\n            Config(app_name=\"test\", frontend_path=\"/deep/nested\"),\n            \"sirv ./build/client --single deep/nested/404.html --host\",\n        ),\n    ],\n)\ndef test_compile_package_json_prod_command(config, expected_prod_script, monkeypatch):\n    monkeypatch.setattr(\"reflex.utils.frontend_skeleton.get_config\", lambda: config)\n    output = _compile_package_json()\n    assert f'\"prod\": \"{expected_prod_script}\"' in output\n\n\ndef test_cached_procedure():\n    call_count = 0\n\n    temp_file = tempfile.mktemp()\n\n    @cached_procedure(\n        cache_file_path=lambda: Path(temp_file), payload_fn=lambda: \"constant\"\n    )\n    def _function_with_no_args():\n        nonlocal call_count\n        call_count += 1\n\n    _function_with_no_args()\n    assert call_count == 1\n    _function_with_no_args()\n    assert call_count == 1\n\n    call_count = 0\n\n    another_temp_file = tempfile.mktemp()\n\n    @cached_procedure(\n        cache_file_path=lambda: Path(another_temp_file),\n        payload_fn=lambda *args, **kwargs: f\"{repr(args), repr(kwargs)}\",\n    )\n    def _function_with_some_args(*args, **kwargs):\n        nonlocal call_count\n        call_count += 1\n\n    _function_with_some_args(1, y=2)\n    assert call_count == 1\n    _function_with_some_args(1, y=2)\n    assert call_count == 1\n    _function_with_some_args(100, y=300)\n    assert call_count == 2\n    _function_with_some_args(100, y=300)\n    assert call_count == 2\n\n    call_count = 0\n\n    @cached_procedure(\n        cache_file_path=lambda: Path(tempfile.mktemp()), payload_fn=lambda: \"constant\"\n    )\n    def _function_with_no_args_fn():\n        nonlocal call_count\n        call_count += 1\n\n    _function_with_no_args_fn()\n    assert call_count == 1\n    _function_with_no_args_fn()\n    assert call_count == 2\n\n\ndef test_get_cpu_info():\n    cpu_info = get_cpu_info()\n    assert cpu_info is not None\n    assert isinstance(cpu_info, CpuInfo)\n    assert cpu_info.model_name is not None\n\n    for attr in (\"manufacturer_id\", \"model_name\", \"address_width\"):\n        value = getattr(cpu_info, attr)\n        assert value.strip() if attr != \"address_width\" else value\n\n\n@pytest.fixture\ndef temp_directory():\n    temp_dir = tempfile.mkdtemp()\n    yield Path(temp_dir)\n    shutil.rmtree(temp_dir)\n\n\n@pytest.mark.parametrize(\n    (\"config_code\", \"expected\"),\n    [\n        (\"rx.Config(app_name='old_name')\", 'rx.Config(app_name=\"new_name\")'),\n        ('rx.Config(app_name=\"old_name\")', 'rx.Config(app_name=\"new_name\")'),\n        (\"rx.Config('old_name')\", 'rx.Config(\"new_name\")'),\n        ('rx.Config(\"old_name\")', 'rx.Config(\"new_name\")'),\n    ],\n)\ndef test_rename_imports_and_app_name(temp_directory, config_code, expected):\n    file_path = temp_directory / \"rxconfig.py\"\n    content = f\"\"\"\nconfig = {config_code}\n\"\"\"\n    file_path.write_text(content)\n\n    rename_imports_and_app_name(file_path, \"old_name\", \"new_name\")\n\n    updated_content = file_path.read_text()\n    expected_content = f\"\"\"\nconfig = {expected}\n\"\"\"\n    assert updated_content == expected_content\n\n\ndef test_regex_edge_cases(temp_directory):\n    file_path = temp_directory / \"example.py\"\n    content = \"\"\"\nfrom old_name.module import something\nimport old_name\nfrom old_name import something_else as alias\nfrom old_name\n\"\"\"\n    file_path.write_text(content)\n\n    rename_imports_and_app_name(file_path, \"old_name\", \"new_name\")\n\n    updated_content = file_path.read_text()\n    expected_content = \"\"\"\nfrom new_name.module import something\nimport new_name\nfrom new_name import something_else as alias\nfrom new_name\n\"\"\"\n    assert updated_content == expected_content\n\n\ndef test_cli_rename_command(temp_directory):\n    foo_dir = temp_directory / \"foo\"\n    foo_dir.mkdir()\n    (foo_dir / \"__init__\").touch()\n    (foo_dir / \".web\").mkdir()\n    (foo_dir / \"assets\").mkdir()\n    (foo_dir / \"foo\").mkdir()\n    (foo_dir / \"foo\" / \"__init__.py\").touch()\n    (foo_dir / \"rxconfig.py\").touch()\n    (foo_dir / \"rxconfig.py\").write_text(\n        \"\"\"\nimport reflex as rx\n\nconfig = rx.Config(\n    app_name=\"foo\",\n)\n\"\"\"\n    )\n    (foo_dir / \"foo\" / \"components\").mkdir()\n    (foo_dir / \"foo\" / \"components\" / \"__init__.py\").touch()\n    (foo_dir / \"foo\" / \"components\" / \"base.py\").touch()\n    (foo_dir / \"foo\" / \"components\" / \"views.py\").touch()\n    (foo_dir / \"foo\" / \"components\" / \"base.py\").write_text(\n        \"\"\"\nimport reflex as rx\nfrom foo.components import views\nfrom foo.components.views import *\nfrom .base import *\n\ndef random_component():\n    return rx.fragment()\n\"\"\"\n    )\n    (foo_dir / \"foo\" / \"foo.py\").touch()\n    (foo_dir / \"foo\" / \"foo.py\").write_text(\n        \"\"\"\nimport reflex as rx\nimport foo.components.base\nfrom foo.components.base import random_component\n\nclass State(rx.State):\n  pass\n\n\ndef index():\n   return rx.text(\"Hello, World!\")\n\napp = rx.App()\napp.add_page(index)\n\"\"\"\n    )\n\n    with chdir(temp_directory / \"foo\"):\n        result = runner.invoke(cli, [\"rename\", \"bar\"])\n\n    assert result.exit_code == 0, result.output\n    assert (foo_dir / \"rxconfig.py\").read_text() == (\n        \"\"\"\nimport reflex as rx\n\nconfig = rx.Config(\n    app_name=\"bar\",\n)\n\"\"\"\n    )\n    assert (foo_dir / \"bar\").exists()\n    assert not (foo_dir / \"foo\").exists()\n    assert (foo_dir / \"bar\" / \"components\" / \"base.py\").read_text() == (\n        \"\"\"\nimport reflex as rx\nfrom bar.components import views\nfrom bar.components.views import *\nfrom .base import *\n\ndef random_component():\n    return rx.fragment()\n\"\"\"\n    )\n    assert (foo_dir / \"bar\" / \"bar.py\").exists()\n    assert not (foo_dir / \"bar\" / \"foo.py\").exists()\n    assert (foo_dir / \"bar\" / \"bar.py\").read_text() == (\n        \"\"\"\nimport reflex as rx\nimport bar.components.base\nfrom bar.components.base import random_component\n\nclass State(rx.State):\n  pass\n\n\ndef index():\n   return rx.text(\"Hello, World!\")\n\napp = rx.App()\napp.add_page(index)\n\"\"\"\n    )\n"
  },
  {
    "path": "tests/units/test_route.py",
    "content": "import pytest\nfrom pytest_mock import MockerFixture\n\nfrom reflex import constants\nfrom reflex.app import App\nfrom reflex.route import get_route_args, verify_route_validity\n\n\n@pytest.mark.parametrize(\n    (\"route_name\", \"expected\"),\n    [\n        (\"/users/[id]\", {\"id\": constants.RouteArgType.SINGLE}),\n        (\n            \"/posts/[postId]/comments/[commentId]\",\n            {\n                \"postId\": constants.RouteArgType.SINGLE,\n                \"commentId\": constants.RouteArgType.SINGLE,\n            },\n        ),\n    ],\n)\ndef test_route_args(route_name, expected):\n    assert get_route_args(route_name) == expected\n\n\n@pytest.mark.parametrize(\n    \"route_name\",\n    [\n        \"/products/[id]/[id]\",\n        \"/posts/[postId]/comments/[postId]\",\n    ],\n)\ndef test_invalid_route_args(route_name):\n    with pytest.raises(ValueError):\n        get_route_args(route_name)\n\n\n@pytest.mark.parametrize(\n    \"route_name\",\n    [\n        \"/products\",\n        \"/products/details\",\n    ],\n)\ndef test_verify_valid_routes(route_name):\n    verify_route_validity(route_name)\n\n\n@pytest.mark.parametrize(\n    \"route_name\",\n    [\n        \"/products/[category]/[...]/details/[version]\",\n        \"[...]\",\n        \"/products/[...]/details/[category]/latest\",\n        \"/blog/[...]/post/[year]/latest\",\n        \"/products/[...]/details/[...]/[category]/[...]/latest\",\n        \"/products/[...]/details/category\",\n    ],\n)\ndef test_verify_invalid_routes(route_name):\n    with pytest.raises(ValueError):\n        verify_route_validity(route_name)\n\n\n@pytest.fixture\ndef app():\n    return App()\n\n\n@pytest.mark.parametrize(\n    (\"route1\", \"route2\"),\n    [\n        (\"/posts/[slug]\", \"/posts/[slug1]\"),\n        (\"/posts/[slug]/info\", \"/posts/[slug1]/info1\"),\n        (\"/posts/[slug]/info/[[slug1]]\", \"/posts/[slug1]/info1/[[slug2]]\"),\n        (\"/posts/[slug]/info/[[slug1]]\", \"/posts/[slug]/info/[[slug2]]\"),\n        (\"/posts/[slug]/info/[[...splat]]\", \"/posts/[slug1]/info/[[...splat]]\"),\n    ],\n)\ndef test_check_routes_conflict_invalid(\n    mocker: MockerFixture, app: App, route1: str, route2: str\n):\n    mocker.patch.object(app, \"_pages\", {route1: []})\n    with pytest.raises(ValueError):\n        app._check_routes_conflict(route2)\n\n\n@pytest.mark.parametrize(\n    (\"route1\", \"route2\"),\n    [\n        (\"/posts/[slug]\", \"/post/[slug1]\"),\n        (\"/posts/[slug]\", \"/post/[slug]\"),\n        (\"/posts/[slug]/info\", \"/posts/[slug]/info1\"),\n        (\"/posts/[slug]/info/[[slug1]]\", \"/posts/[slug]/info1/[[slug1]]\"),\n        (\"/posts/[slug]/info/[[slug1]]\", \"/posts/[slug]/info1/[[slug2]]\"),\n        (\n            \"/posts/[slug]/info/[slug2]/[[slug1]]\",\n            \"/posts/[slug]/info1/[slug2]/[[slug1]]\",\n        ),\n        (\n            \"/posts/[slug]/info/[slug1]/random1/[slug2]/x\",\n            \"/posts/[slug]/info/[slug1]/random/[slug4]/x1\",\n        ),\n        (\"/posts/[slug]/info/[[...splat]]\", \"/posts/[slug]/info1/[[...splat]]\"),\n        (\"/posts/[slug]/info/[...slug1]\", \"/posts/[slug]/info1/[...slug1]\"),\n        (\"/posts/[slug]/info/[...slug1]\", \"/posts/[slug]/info1/[...slug2]\"),\n    ],\n)\ndef test_check_routes_conflict_valid(mocker: MockerFixture, app, route1, route2):\n    mocker.patch.object(app, \"_pages\", {route1: []})\n    # test that running this does not throw an error.\n    app._check_routes_conflict(route2)\n"
  },
  {
    "path": "tests/units/test_sqlalchemy.py",
    "content": "import math\nfrom pathlib import Path\nfrom unittest import mock\n\nimport pytest\n\nimport reflex.constants\nimport reflex.model\nfrom reflex.model import Model, ModelRegistry, sqla_session\nfrom reflex.state import MutableProxy\nfrom reflex.utils.serializers import serializer\n\npytest.importorskip(\"sqlalchemy\")\npytest.importorskip(\"sqlmodel\")\npytest.importorskip(\"alembic\")\npytest.importorskip(\"pydantic\")\n\n# Import SQLAlchemy classes for mutable tests\nfrom sqlalchemy import ARRAY, JSON, String\nfrom sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column\n\nfrom tests.units.states.mutation import MutableTestState\n\n\nclass MutableSQLABase(DeclarativeBase):\n    \"\"\"SQLAlchemy base model for mutable vars.\"\"\"\n\n\nclass MutableSQLAModel(MutableSQLABase):\n    \"\"\"SQLAlchemy model for mutable vars.\"\"\"\n\n    __tablename__: str = \"mutable_test_state\"\n\n    id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)\n    strlist: Mapped[list[str]] = mapped_column(ARRAY(String))\n    hashmap: Mapped[dict[str, str]] = mapped_column(JSON)\n    test_set: Mapped[set[str]] = mapped_column(ARRAY(String))\n\n\n@serializer\ndef serialize_mutable_sqla_model(\n    model: MutableSQLAModel,\n) -> dict[str, list[str] | dict[str, str]]:\n    \"\"\"Serialize the MutableSQLAModel.\n\n    Args:\n        model: The MutableSQLAModel instance to serialize.\n\n    Returns:\n        The serialized model.\n    \"\"\"\n    return {\"strlist\": model.strlist, \"hashmap\": model.hashmap}\n\n\nclass MutableTestStateWithSQLAlchemy(MutableTestState):\n    \"\"\"A test state.\"\"\"\n\n    sqla_model: MutableSQLAModel = MutableSQLAModel(\n        strlist=[\"a\", \"b\", \"c\"],\n        hashmap={\"key\": \"value\"},\n        test_set={\"one\", \"two\", \"three\"},\n    )\n\n    def reassign_mutables(self):\n        \"\"\"Assign mutable fields to different values.\"\"\"\n        super().reassign_mutables()\n        self.sqla_model = MutableSQLAModel(\n            strlist=[\"d\", \"e\", \"f\"],\n            hashmap={\"key\": \"value\"},\n            test_set={\"one\", \"two\", \"three\"},\n        )\n\n\n@pytest.fixture\ndef mutable_state() -> MutableTestStateWithSQLAlchemy:\n    \"\"\"Create a Test state containing mutable types.\n\n    Returns:\n        A state object.\n    \"\"\"\n    return MutableTestStateWithSQLAlchemy()\n\n\ndef test_setattr_of_mutable_types(mutable_state: MutableTestStateWithSQLAlchemy):\n    \"\"\"Test that mutable types are converted to corresponding Reflex wrappers.\n\n    Args:\n        mutable_state: A test state.\n    \"\"\"\n    sqla_model = mutable_state.sqla_model\n\n    assert isinstance(sqla_model, MutableProxy)\n    assert isinstance(sqla_model, MutableSQLAModel)\n    assert isinstance(sqla_model.strlist, MutableProxy)\n    assert isinstance(sqla_model.strlist, list)\n    assert isinstance(sqla_model.hashmap, MutableProxy)\n    assert isinstance(sqla_model.hashmap, dict)\n    assert isinstance(sqla_model.test_set, MutableProxy)\n    assert isinstance(sqla_model.test_set, set)\n\n    mutable_state.reassign_mutables()\n\n    sqla_model = mutable_state.sqla_model\n\n    assert isinstance(sqla_model, MutableProxy)\n    assert isinstance(sqla_model, MutableSQLAModel)\n    assert isinstance(sqla_model.strlist, MutableProxy)\n    assert isinstance(sqla_model.strlist, list)\n    assert isinstance(sqla_model.hashmap, MutableProxy)\n    assert isinstance(sqla_model.hashmap, dict)\n    assert isinstance(sqla_model.test_set, MutableProxy)\n    assert isinstance(sqla_model.test_set, set)\n\n\ndef test_mutable_sqla_model(mutable_state: MutableTestStateWithSQLAlchemy):\n    \"\"\"Test that mutable SQLA models are tracked correctly.\n\n    Args:\n        mutable_state: A test state.\n    \"\"\"\n    assert not mutable_state.dirty_vars\n\n    def assert_sqla_model_dirty():\n        assert mutable_state.dirty_vars == {\"sqla_model\"}\n        mutable_state._clean()\n        assert not mutable_state.dirty_vars\n\n    mutable_state.sqla_model.strlist.append(\"foo\")\n    assert_sqla_model_dirty()\n    mutable_state.sqla_model.hashmap[\"key\"] = \"value\"\n    assert_sqla_model_dirty()\n    mutable_state.sqla_model.test_set.add(\"bar\")\n    assert_sqla_model_dirty()\n\n\n@pytest.mark.filterwarnings(\n    \"ignore:This declarative base already contains a class with the same class name\",\n)\ndef test_automigration(\n    tmp_working_dir: Path,\n    monkeypatch: pytest.MonkeyPatch,\n    model_registry: type[ModelRegistry],\n):\n    \"\"\"Test alembic automigration with add and drop table and column.\n\n    Args:\n        tmp_working_dir: directory where database and migrations are stored\n        monkeypatch: pytest fixture to overwrite attributes\n        model_registry: clean reflex ModelRegistry\n    \"\"\"\n    from sqlalchemy import select\n    from sqlalchemy.exc import OperationalError\n    from sqlalchemy.orm import (\n        DeclarativeBase,\n        Mapped,\n        MappedAsDataclass,\n        declared_attr,\n        mapped_column,\n    )\n\n    alembic_ini = tmp_working_dir / \"alembic.ini\"\n    versions = tmp_working_dir / \"alembic\" / \"versions\"\n    monkeypatch.setattr(reflex.constants, \"ALEMBIC_CONFIG\", str(alembic_ini))\n\n    config_mock = mock.Mock()\n    config_mock.db_url = f\"sqlite:///{tmp_working_dir}/reflex.db\"\n    monkeypatch.setattr(reflex.model, \"get_config\", mock.Mock(return_value=config_mock))\n\n    assert alembic_ini.exists() is False\n    assert versions.exists() is False\n    Model.alembic_init()\n    assert alembic_ini.exists()\n    assert versions.exists()\n\n    class Base(DeclarativeBase):\n        @declared_attr.directive\n        def __tablename__(cls) -> str:\n            return cls.__name__.lower()\n\n    assert model_registry.register(Base)\n\n    class ModelBase(Base, MappedAsDataclass):\n        __abstract__ = True\n        id: Mapped[int | None] = mapped_column(primary_key=True, default=None)\n\n    # initial table\n    class AlembicThing(ModelBase):  # pyright: ignore[reportRedeclaration]\n        t1: Mapped[str] = mapped_column(default=\"\")\n\n    with Model.get_db_engine().connect() as connection:\n        assert Model.alembic_autogenerate(\n            connection=connection, message=\"Initial Revision\"\n        )\n    assert Model.migrate()\n    version_scripts = list(versions.glob(\"*.py\"))\n    assert len(version_scripts) == 1\n    assert version_scripts[0].name.endswith(\"initial_revision.py\")\n\n    with sqla_session() as session:\n        session.add(AlembicThing(t1=\"foo\"))\n        session.commit()\n\n    model_registry.get_metadata().clear()\n\n    # Create column t2, mark t1 as optional with default\n    class AlembicThing(ModelBase):  # pyright: ignore[reportRedeclaration]\n        t1: Mapped[str | None] = mapped_column(default=\"default\")\n        t2: Mapped[str] = mapped_column(default=\"bar\")\n\n    assert Model.migrate(autogenerate=True)\n    assert len(list(versions.glob(\"*.py\"))) == 2\n\n    with sqla_session() as session:\n        session.add(AlembicThing(t2=\"baz\"))\n        session.commit()\n        result = session.scalars(select(AlembicThing)).all()\n        assert len(result) == 2\n        assert result[0].t1 == \"foo\"\n        assert result[0].t2 == \"bar\"\n        assert result[1].t1 == \"default\"\n        assert result[1].t2 == \"baz\"\n\n    model_registry.get_metadata().clear()\n\n    # Drop column t1\n    class AlembicThing(ModelBase):  # pyright: ignore[reportRedeclaration]\n        t2: Mapped[str] = mapped_column(default=\"bar\")\n\n    assert Model.migrate(autogenerate=True)\n    assert len(list(versions.glob(\"*.py\"))) == 3\n\n    with sqla_session() as session:\n        result = session.scalars(select(AlembicThing)).all()\n        assert len(result) == 2\n        assert result[0].t2 == \"bar\"\n        assert result[1].t2 == \"baz\"\n\n    # Add table\n    class AlembicSecond(ModelBase):\n        a: Mapped[int] = mapped_column(default=42)\n        b: Mapped[float] = mapped_column(default=4.2)\n\n    assert Model.migrate(autogenerate=True)\n    assert len(list(versions.glob(\"*.py\"))) == 4\n\n    with reflex.model.session() as session:\n        session.add(AlembicSecond(id=None))\n        session.commit()\n        result = session.scalars(select(AlembicSecond)).all()\n        assert len(result) == 1\n        assert result[0].a == 42\n        assert math.isclose(result[0].b, 4.2)\n\n    # No-op\n    # assert Model.migrate(autogenerate=True) #noqa: ERA001\n    # assert len(list(versions.glob(\"*.py\"))) == 4 #noqa: ERA001\n\n    # drop table (AlembicSecond)\n    model_registry.get_metadata().clear()\n\n    class AlembicThing(ModelBase):  # pyright: ignore[reportRedeclaration]\n        t2: Mapped[str] = mapped_column(default=\"bar\")\n\n    assert Model.migrate(autogenerate=True)\n    assert len(list(versions.glob(\"*.py\"))) == 5\n\n    with reflex.model.session() as session:\n        with pytest.raises(OperationalError) as errctx:\n            _ = session.scalars(select(AlembicSecond)).all()\n        assert errctx.match(r\"no such table: alembicsecond\")\n        # first table should still exist\n        result = session.scalars(select(AlembicThing)).all()\n        assert len(result) == 2\n        assert result[0].t2 == \"bar\"\n        assert result[1].t2 == \"baz\"\n\n    model_registry.get_metadata().clear()\n\n    class AlembicThing(ModelBase):\n        # changing column type not supported by default\n        t2: Mapped[int] = mapped_column(default=42)\n\n    assert Model.migrate(autogenerate=True)\n    assert len(list(versions.glob(\"*.py\"))) == 5\n\n    # clear all metadata to avoid influencing subsequent tests\n    model_registry.get_metadata().clear()\n\n    # drop remaining tables\n    assert Model.migrate(autogenerate=True)\n    assert len(list(versions.glob(\"*.py\"))) == 6\n"
  },
  {
    "path": "tests/units/test_state.py",
    "content": "from __future__ import annotations\n\nimport asyncio\nimport copy\nimport dataclasses\nimport datetime\nimport functools\nimport json\nimport math\nimport os\nimport sys\nimport threading\nfrom collections.abc import AsyncGenerator, Callable\nfrom textwrap import dedent\nfrom typing import Any, ClassVar\nfrom unittest.mock import AsyncMock, Mock\n\nimport pytest\nimport pytest_asyncio\nfrom plotly.graph_objects import Figure\nfrom pytest_mock import MockerFixture\n\nimport reflex as rx\nimport reflex.config\nfrom reflex import constants\nfrom reflex.app import App\nfrom reflex.base import Base\nfrom reflex.constants import CompileVars, RouteVar, SocketEvent\nfrom reflex.constants.state import FIELD_MARKER\nfrom reflex.environment import environment\nfrom reflex.event import Event, EventHandler\nfrom reflex.istate.data import HeaderData, _FrozenDictStrStr\nfrom reflex.istate.manager import StateManager\nfrom reflex.istate.manager.disk import StateManagerDisk\nfrom reflex.istate.manager.memory import StateManagerMemory\nfrom reflex.istate.manager.redis import StateManagerRedis\nfrom reflex.state import (\n    BaseState,\n    ImmutableMutableProxy,\n    ImmutableStateError,\n    MutableProxy,\n    OnLoadInternalState,\n    RouterData,\n    State,\n    StateProxy,\n    StateUpdate,\n    _substate_key,\n)\nfrom reflex.testing import chdir\nfrom reflex.utils import format, prerequisites, types\nfrom reflex.utils.exceptions import (\n    InvalidLockWarningThresholdError,\n    LockExpiredError,\n    ReflexRuntimeError,\n    SetUndefinedStateVarError,\n    StateSerializationError,\n    UnretrievableVarValueError,\n)\nfrom reflex.utils.format import json_dumps\nfrom reflex.utils.token_manager import SocketRecord\nfrom reflex.vars.base import Field, Var, computed_var, field\nfrom tests.units.mock_redis import mock_redis\n\nfrom .states import GenState\n\npytest.importorskip(\"pydantic\")\n\n\nfrom pydantic import BaseModel as BaseModelV2\nfrom pydantic.v1 import BaseModel as BaseModelV1\n\nfrom tests.units.states.mutation import MutableTestState\n\nCI = bool(os.environ.get(\"CI\", False))\nLOCK_EXPIRATION = 2500 if CI else 300\nLOCK_WARNING_THRESHOLD = 1000 if CI else 100\nLOCK_WARN_SLEEP = 1.5 if CI else 0.15\nLOCK_EXPIRE_SLEEP = 2.5 if CI else 0.4\n\n\nformatted_router = {\n    \"route_id\": \"\",\n    \"url\": \"\",\n    \"session\": {\"client_token\": \"\", \"client_ip\": \"\", \"session_id\": \"\"},\n    \"headers\": {\n        \"host\": \"\",\n        \"origin\": \"\",\n        \"upgrade\": \"\",\n        \"connection\": \"\",\n        \"cookie\": \"\",\n        \"pragma\": \"\",\n        \"cache_control\": \"\",\n        \"user_agent\": \"\",\n        \"sec_websocket_version\": \"\",\n        \"sec_websocket_key\": \"\",\n        \"sec_websocket_extensions\": \"\",\n        \"accept_encoding\": \"\",\n        \"accept_language\": \"\",\n        \"raw_headers\": {},\n    },\n    \"page\": {\n        \"host\": \"\",\n        \"path\": \"\",\n        \"raw_path\": \"\",\n        \"full_path\": \"\",\n        \"full_raw_path\": \"\",\n        \"params\": {},\n    },\n}\n\n\nclass Object(Base):\n    \"\"\"A test object fixture.\"\"\"\n\n    prop1: int = 42\n    prop2: str = \"hello\"\n\n\nclass TestMixin(BaseState, mixin=True):\n    \"\"\"A test mixin.\"\"\"\n\n    mixin: rx.Field[str] = rx.field(\"mixin_value\")\n    _mixin_backend: rx.Field[int] = rx.field(default_factory=lambda: 10)\n\n\nclass TestState(TestMixin, BaseState):  # pyright: ignore[reportUnsafeMultipleInheritance]\n    \"\"\"A test state.\"\"\"\n\n    # Set this class as not test one\n    __test__ = False\n\n    num1: rx.Field[int]\n    num2: float = 3.15\n    key: str\n    map_key: str = \"a\"\n    array: list[float] = [1, 2, 3.15]\n    mapping: rx.Field[dict[str, list[int]]] = rx.field({\"a\": [1, 2, 3], \"b\": [4, 5, 6]})\n    obj: Object = Object()\n    complex: dict[int, Object] = {1: Object(), 2: Object()}\n    fig: Figure = Figure()\n    dt: datetime.datetime = datetime.datetime.fromisoformat(\"1989-11-09T18:53:00+01:00\")\n    _backend: int = 0\n    asynctest: int = 0\n\n    @computed_var\n    def sum(self) -> float:\n        \"\"\"Dynamically sum the numbers.\n\n        Returns:\n            The sum of the numbers.\n        \"\"\"\n        return self.num1 + self.num2\n\n    @computed_var\n    def upper(self) -> str:\n        \"\"\"Uppercase the key.\n\n        Returns:\n            The uppercased key.\n        \"\"\"\n        return self.key.upper()\n\n    def do_something(self):\n        \"\"\"Do something.\"\"\"\n\n    async def set_asynctest(self, value: int):\n        \"\"\"Set the asynctest value. Intentionally overwrite the default setter with an async one.\n\n        Args:\n            value: The new value.\n        \"\"\"\n        self.asynctest = value\n\n\nclass ChildState(TestState):\n    \"\"\"A child state fixture.\"\"\"\n\n    value: str\n    count: rx.Field[int] = rx.field(23)\n\n    def change_both(self, value: str, count: int):\n        \"\"\"Change both the value and count.\n\n        Args:\n            value: The new value.\n            count: The new count.\n        \"\"\"\n        self.value = value.upper()\n        self.count = count * 2\n\n\nclass ChildState2(TestState):\n    \"\"\"A child state fixture.\"\"\"\n\n    value: str\n\n\nclass ChildState3(TestState):\n    \"\"\"A child state fixture.\"\"\"\n\n    value: str\n\n\nclass GrandchildState(ChildState):\n    \"\"\"A grandchild state fixture.\"\"\"\n\n    value2: str\n\n    def do_nothing(self):\n        \"\"\"Do something.\"\"\"\n\n\nclass GrandchildState2(ChildState2):\n    \"\"\"A grandchild state fixture.\"\"\"\n\n    @rx.var\n    def cached(self) -> str:\n        \"\"\"A cached var.\n\n        Returns:\n            The value.\n        \"\"\"\n        return self.value\n\n\nclass GrandchildState3(ChildState3):\n    \"\"\"A great grandchild state fixture.\"\"\"\n\n    @rx.var(cache=False)\n    def computed(self) -> str:\n        \"\"\"A computed var.\n\n        Returns:\n            The value.\n        \"\"\"\n        return self.value\n\n\nclass DateTimeState(BaseState):\n    \"\"\"A State with some datetime fields.\"\"\"\n\n    d: datetime.date = datetime.date.fromisoformat(\"1989-11-09\")\n    dt: datetime.datetime = datetime.datetime.fromisoformat(\"1989-11-09T18:53:00+01:00\")\n    t: datetime.time = datetime.time.fromisoformat(\"18:53:00+01:00\")\n    td: datetime.timedelta = datetime.timedelta(days=11, minutes=11)\n\n\n@pytest.fixture\ndef test_state() -> TestState:\n    \"\"\"A state.\n\n    Returns:\n        A test state.\n    \"\"\"\n    return TestState()  # pyright: ignore [reportCallIssue]\n\n\n@pytest.fixture\ndef child_state(test_state) -> ChildState:\n    \"\"\"A child state.\n\n    Args:\n        test_state: A test state.\n\n    Returns:\n        A test child state.\n    \"\"\"\n    child_state = test_state.get_substate([ChildState.get_name()])\n    assert child_state is not None\n    return child_state\n\n\n@pytest.fixture\ndef child_state2(test_state) -> ChildState2:\n    \"\"\"A second child state.\n\n    Args:\n        test_state: A test state.\n\n    Returns:\n        A second test child state.\n    \"\"\"\n    child_state2 = test_state.get_substate([ChildState2.get_name()])\n    assert child_state2 is not None\n    return child_state2\n\n\n@pytest.fixture\ndef grandchild_state(child_state) -> GrandchildState:\n    \"\"\"A state.\n\n    Args:\n        child_state: A child state.\n\n    Returns:\n        A test state.\n    \"\"\"\n    grandchild_state = child_state.get_substate([GrandchildState.get_name()])\n    assert grandchild_state is not None\n    return grandchild_state\n\n\ndef test_base_class_vars(test_state):\n    \"\"\"Test that the class vars are set correctly.\n\n    Args:\n        test_state: A state.\n    \"\"\"\n    fields = test_state.get_fields()\n    cls = type(test_state)\n\n    for field_name in fields:\n        if field_name.startswith(\"_\") or field_name in cls.get_skip_vars():\n            continue\n        prop = getattr(cls, field_name)\n        assert isinstance(prop, Var)\n        assert prop._js_expr.split(\".\")[-1] == field_name + FIELD_MARKER\n\n    assert cls.num1._var_type is int\n    assert cls.num2._var_type is float\n    assert cls.key._var_type is str\n\n\ndef test_computed_class_var(test_state):\n    \"\"\"Test that the class computed vars are set correctly.\n\n    Args:\n        test_state: A state.\n    \"\"\"\n    cls = type(test_state)\n    vars = [(prop._js_expr, prop._var_type) for prop in cls.computed_vars.values()]\n    assert (\"sum\" + FIELD_MARKER, float) in vars\n    assert (\"upper\" + FIELD_MARKER, str) in vars\n\n\ndef test_class_vars(test_state):\n    \"\"\"Test that the class vars are set correctly.\n\n    Args:\n        test_state: A state.\n    \"\"\"\n    cls = type(test_state)\n    assert cls.vars.keys() == {\n        \"router\",\n        \"num1\",\n        \"num2\",\n        \"key\",\n        \"map_key\",\n        \"array\",\n        \"mapping\",\n        \"obj\",\n        \"complex\",\n        \"sum\",\n        \"upper\",\n        \"fig\",\n        \"dt\",\n        \"asynctest\",\n        \"mixin\",\n    }\n\n\ndef test_event_handlers(test_state):\n    \"\"\"Test that event handler is set correctly.\n\n    Args:\n        test_state: A state.\n    \"\"\"\n    expected_keys = (\n        \"do_something\",\n        \"set_array\",\n        \"set_complex\",\n        \"set_fig\",\n        \"set_key\",\n        \"set_mapping\",\n        \"set_num1\",\n        \"set_num2\",\n        \"set_obj\",\n    )\n\n    cls = type(test_state)\n    assert all(key in cls.event_handlers for key in expected_keys)\n\n\ndef test_default_value(test_state: TestState):\n    \"\"\"Test that the default value of a var is correct.\n\n    Args:\n        test_state: A state.\n    \"\"\"\n    assert test_state.num1 == 0\n    assert math.isclose(test_state.num2, 3.15)\n    assert test_state.key == \"\"\n    assert math.isclose(test_state.sum, 3.15)\n    assert test_state.upper == \"\"\n    assert test_state._backend == 0\n    assert test_state.mixin == \"mixin_value\"\n    assert test_state._mixin_backend == 10\n    assert test_state.array == [1, 2, 3.15]\n\n\ndef test_computed_vars(test_state):\n    \"\"\"Test that the computed var is computed correctly.\n\n    Args:\n        test_state: A state.\n    \"\"\"\n    test_state.num1 = 1\n    test_state.num2 = 4\n    assert test_state.sum == 5\n    test_state.key = \"hello world\"\n    assert test_state.upper == \"HELLO WORLD\"\n\n\ndef test_dict(test_state: TestState):\n    \"\"\"Test that the dict representation of a state is correct.\n\n    Args:\n        test_state: A state.\n    \"\"\"\n    substates = {\n        test_state.get_full_name(),\n        ChildState.get_full_name(),\n        GrandchildState.get_full_name(),\n        ChildState2.get_full_name(),\n        GrandchildState2.get_full_name(),\n        ChildState3.get_full_name(),\n        GrandchildState3.get_full_name(),\n    }\n    test_state_dict = test_state.dict()\n    assert set(test_state_dict) == substates\n    assert set(test_state_dict[test_state.get_name()]) == {\n        var + FIELD_MARKER for var in test_state.vars\n    }\n    assert set(test_state.dict(include_computed=False)[test_state.get_name()]) == {\n        var + FIELD_MARKER for var in test_state.base_vars\n    }\n\n\ndef test_default_setters(test_state):\n    \"\"\"Test that we can set default values.\n\n    Args:\n        test_state: A state.\n    \"\"\"\n    for prop_name in test_state.base_vars:\n        # Each base var should have a default setter.\n        assert hasattr(test_state, f\"set_{prop_name}\")\n\n\ndef test_class_indexing_with_vars():\n    \"\"\"Test that we can index into a state var with another var.\"\"\"\n    prop = TestState.array[TestState.num1]  # pyright: ignore [reportCallIssue, reportArgumentType]\n    assert (\n        str(prop)\n        == f\"{TestState.get_name()}.array{FIELD_MARKER}?.at?.({TestState.get_name()}.num1{FIELD_MARKER})\"\n    )\n\n    prop = TestState.mapping[\"a\"][TestState.num1]  # pyright: ignore [reportCallIssue, reportArgumentType]\n    assert (\n        str(prop)\n        == f'{TestState.get_name()}.mapping{FIELD_MARKER}?.[\"a\"]?.at?.({TestState.get_name()}.num1{FIELD_MARKER})'\n    )\n\n    prop = TestState.mapping[TestState.map_key]\n    assert (\n        str(prop)\n        == f\"{TestState.get_name()}.mapping{FIELD_MARKER}?.[{TestState.get_name()}.map_key{FIELD_MARKER}]\"\n    )\n\n\ndef test_class_attributes():\n    \"\"\"Test that we can get class attributes.\"\"\"\n    prop = TestState.obj.prop1\n    assert str(prop) == f'{TestState.get_name()}.obj{FIELD_MARKER}?.[\"prop1\"]'\n\n    prop = TestState.complex[1].prop1\n    assert str(prop) == f'{TestState.get_name()}.complex{FIELD_MARKER}?.[1]?.[\"prop1\"]'\n\n\ndef test_get_parent_state():\n    \"\"\"Test getting the parent state.\"\"\"\n    assert TestState.get_parent_state() is None\n    assert ChildState.get_parent_state() == TestState\n    assert ChildState2.get_parent_state() == TestState\n    assert GrandchildState.get_parent_state() == ChildState\n\n\ndef test_get_substates():\n    \"\"\"Test getting the substates.\"\"\"\n    assert TestState.get_substates() == {ChildState, ChildState2, ChildState3}\n    assert ChildState.get_substates() == {GrandchildState}\n    assert ChildState2.get_substates() == {GrandchildState2}\n    assert GrandchildState.get_substates() == set()\n    assert GrandchildState2.get_substates() == set()\n\n\ndef test_get_name():\n    \"\"\"Test getting the name of a state.\"\"\"\n    assert TestState.get_name() == \"tests___units___test_state____test_state\"\n    assert ChildState.get_name() == \"tests___units___test_state____child_state\"\n    assert ChildState2.get_name() == \"tests___units___test_state____child_state2\"\n    assert (\n        GrandchildState.get_name() == \"tests___units___test_state____grandchild_state\"\n    )\n\n\ndef test_get_full_name():\n    \"\"\"Test getting the full name.\"\"\"\n    assert TestState.get_full_name() == \"tests___units___test_state____test_state\"\n    assert (\n        ChildState.get_full_name()\n        == \"tests___units___test_state____test_state.tests___units___test_state____child_state\"\n    )\n    assert (\n        ChildState2.get_full_name()\n        == \"tests___units___test_state____test_state.tests___units___test_state____child_state2\"\n    )\n    assert (\n        GrandchildState.get_full_name()\n        == \"tests___units___test_state____test_state.tests___units___test_state____child_state.tests___units___test_state____grandchild_state\"\n    )\n\n\ndef test_get_class_substate():\n    \"\"\"Test getting the substate of a class.\"\"\"\n    assert TestState.get_class_substate((ChildState.get_name(),)) == ChildState\n    assert TestState.get_class_substate((ChildState2.get_name(),)) == ChildState2\n    assert (\n        ChildState.get_class_substate((GrandchildState.get_name(),)) == GrandchildState\n    )\n    assert (\n        TestState.get_class_substate((\n            ChildState.get_name(),\n            GrandchildState.get_name(),\n        ))\n        == GrandchildState\n    )\n    with pytest.raises(ValueError):\n        TestState.get_class_substate((\"invalid_child\",))\n    with pytest.raises(ValueError):\n        TestState.get_class_substate((\n            ChildState.get_name(),\n            \"invalid_child\",\n        ))\n\n\ndef test_get_class_var():\n    \"\"\"Test getting the var of a class.\"\"\"\n    assert TestState.get_class_var((\"num1\",)).equals(TestState.num1)\n    assert TestState.get_class_var((\"num2\",)).equals(TestState.num2)\n    assert ChildState.get_class_var((\"value\",)).equals(ChildState.value)\n    assert GrandchildState.get_class_var((\"value2\",)).equals(GrandchildState.value2)\n    assert TestState.get_class_var((ChildState.get_name(), \"value\")).equals(\n        ChildState.value\n    )\n    assert TestState.get_class_var((\n        ChildState.get_name(),\n        GrandchildState.get_name(),\n        \"value2\",\n    )).equals(\n        GrandchildState.value2,\n    )\n    assert ChildState.get_class_var((GrandchildState.get_name(), \"value2\")).equals(\n        GrandchildState.value2,\n    )\n    with pytest.raises(ValueError):\n        TestState.get_class_var((\"invalid_var\",))\n    with pytest.raises(ValueError):\n        TestState.get_class_var((\n            ChildState.get_name(),\n            \"invalid_var\",\n        ))\n\n\ndef test_set_class_var():\n    \"\"\"Test setting the var of a class.\"\"\"\n    with pytest.raises(AttributeError):\n        TestState.num3  # pyright: ignore [reportAttributeAccessIssue]\n    TestState._set_var(\n        \"num3\", Var(_js_expr=\"num3\", _var_type=int)._var_set_state(TestState)\n    )\n    var = TestState.num3  # pyright: ignore [reportAttributeAccessIssue]\n    assert var._js_expr == TestState.get_full_name() + \".num3\"\n    assert var._var_type is int\n    assert var._var_state == TestState.get_full_name()\n\n\ndef test_set_parent_and_substates(test_state, child_state, grandchild_state):\n    \"\"\"Test setting the parent and substates.\n\n    Args:\n        test_state: A state.\n        child_state: A child state.\n        grandchild_state: A grandchild state.\n    \"\"\"\n    assert len(test_state.substates) == 3\n    assert set(test_state.substates) == {\n        ChildState.get_name(),\n        ChildState2.get_name(),\n        ChildState3.get_name(),\n    }\n\n    assert child_state.parent_state == test_state\n    assert len(child_state.substates) == 1\n    assert set(child_state.substates) == {GrandchildState.get_name()}\n\n    assert grandchild_state.parent_state == child_state\n    assert len(grandchild_state.substates) == 0\n\n\ndef test_get_child_attribute(test_state, child_state, child_state2, grandchild_state):\n    \"\"\"Test getting the attribute of a state.\n\n    Args:\n        test_state: A state.\n        child_state: A child state.\n        child_state2: A child state.\n        grandchild_state: A grandchild state.\n    \"\"\"\n    assert test_state.num1 == 0\n    assert child_state.value == \"\"\n    assert child_state2.value == \"\"\n    assert child_state.count == 23\n    assert grandchild_state.value2 == \"\"\n    with pytest.raises(AttributeError):\n        test_state.invalid\n    with pytest.raises(AttributeError):\n        test_state.child_state.invalid\n    with pytest.raises(AttributeError):\n        test_state.child_state.grandchild_state.invalid\n\n\ndef test_set_child_attribute(test_state, child_state, grandchild_state):\n    \"\"\"Test setting the attribute of a state.\n\n    Args:\n        test_state: A state.\n        child_state: A child state.\n        grandchild_state: A grandchild state.\n    \"\"\"\n    test_state.num1 = 10\n    assert test_state.num1 == 10\n    assert child_state.num1 == 10\n    assert grandchild_state.num1 == 10\n\n    grandchild_state.num1 = 5\n    assert test_state.num1 == 5\n    assert child_state.num1 == 5\n    assert grandchild_state.num1 == 5\n\n    child_state.value = \"test\"\n    assert child_state.value == \"test\"\n    assert grandchild_state.value == \"test\"\n\n    grandchild_state.value = \"test2\"\n    assert child_state.value == \"test2\"\n    assert grandchild_state.value == \"test2\"\n\n    grandchild_state.value2 = \"test3\"\n    assert grandchild_state.value2 == \"test3\"\n\n\ndef test_get_substate(test_state, child_state, child_state2, grandchild_state):\n    \"\"\"Test getting the substate of a state.\n\n    Args:\n        test_state: A state.\n        child_state: A child state.\n        child_state2: A child state.\n        grandchild_state: A grandchild state.\n    \"\"\"\n    assert test_state.get_substate((ChildState.get_name(),)) == child_state\n    assert test_state.get_substate((ChildState2.get_name(),)) == child_state2\n    assert (\n        test_state.get_substate((ChildState.get_name(), GrandchildState.get_name()))\n        == grandchild_state\n    )\n    assert child_state.get_substate((GrandchildState.get_name(),)) == grandchild_state\n    with pytest.raises(ValueError):\n        test_state.get_substate((\"invalid\",))\n    with pytest.raises(ValueError):\n        test_state.get_substate((ChildState.get_name(), \"invalid\"))\n    with pytest.raises(ValueError):\n        test_state.get_substate((\n            ChildState.get_name(),\n            GrandchildState.get_name(),\n            \"invalid\",\n        ))\n\n\ndef test_set_dirty_var(test_state):\n    \"\"\"Test changing state vars marks the value as dirty.\n\n    Args:\n        test_state: A state.\n    \"\"\"\n    # Initially there should be no dirty vars.\n    assert test_state.dirty_vars == set()\n\n    # Setting a var should mark it as dirty.\n    test_state.num1 = 1\n    assert test_state.dirty_vars == {\"num1\", \"sum\"}\n\n    # Setting another var should mark it as dirty.\n    test_state.num2 = 2\n    assert test_state.dirty_vars == {\"num1\", \"num2\", \"sum\"}\n\n    # Cleaning the state should remove all dirty vars.\n    test_state._clean()\n    assert test_state.dirty_vars == set()\n\n\ndef test_set_dirty_substate(\n    test_state: TestState,\n    child_state: ChildState,\n    child_state2: ChildState2,\n    grandchild_state: GrandchildState,\n):\n    \"\"\"Test changing substate vars marks the value as dirty.\n\n    Args:\n        test_state: A state.\n        child_state: A child state.\n        child_state2: A child state.\n        grandchild_state: A grandchild state.\n    \"\"\"\n    # Initially there should be no dirty vars.\n    assert test_state.dirty_vars == set()\n    assert child_state.dirty_vars == set()\n    assert child_state2.dirty_vars == set()\n    assert grandchild_state.dirty_vars == set()\n\n    # Setting a var should mark it as dirty.\n    child_state.value = \"test\"\n    assert child_state.dirty_vars == {\"value\"}\n    assert test_state.dirty_substates == {ChildState.get_name()}\n    assert child_state.dirty_substates == set()\n\n    # Cleaning the parent state should remove the dirty substate.\n    test_state._clean()\n    assert test_state.dirty_substates == set()\n    assert child_state.dirty_vars == set()\n\n    # Setting a var on the grandchild should bubble up.\n    grandchild_state.value2 = \"test2\"\n    assert child_state.dirty_substates == {GrandchildState.get_name()}\n    assert test_state.dirty_substates == {ChildState.get_name()}\n\n    # Cleaning the middle state should keep the parent state dirty.\n    child_state._clean()\n    assert test_state.dirty_substates == {ChildState.get_name()}\n    assert child_state.dirty_substates == set()\n    assert grandchild_state.dirty_vars == set()\n\n\ndef test_reset(test_state: TestState, child_state: ChildState):\n    \"\"\"Test resetting the state.\n\n    Args:\n        test_state: A state.\n        child_state: A child state.\n    \"\"\"\n    # Set some values.\n    test_state.num1 = 1\n    test_state.num2 = 2\n    test_state._backend = 3\n    child_state.value = \"test\"\n\n    # Reset the state.\n    test_state.reset()\n\n    # The values should be reset.\n    assert test_state.num1 == 0\n    assert math.isclose(test_state.num2, 3.15)\n    assert test_state._backend == 0\n    assert child_state.value == \"\"\n\n    expected_dirty_vars = {\n        \"num1\",\n        \"num2\",\n        \"obj\",\n        \"upper\",\n        \"complex\",\n        \"fig\",\n        \"key\",\n        \"sum\",\n        \"array\",\n        \"map_key\",\n        \"mapping\",\n        \"dt\",\n        \"_backend\",\n        \"mixin\",\n        \"_mixin_backend\",\n        \"asynctest\",\n    }\n\n    # The dirty vars should be reset.\n    assert test_state.dirty_vars == expected_dirty_vars\n    assert child_state.dirty_vars == {\"count\", \"value\"}\n\n    # The dirty substates should be reset.\n    assert test_state.dirty_substates == {\n        ChildState.get_name(),\n        ChildState2.get_name(),\n        ChildState3.get_name(),\n    }\n\n\n@pytest.mark.asyncio\nasync def test_process_event_simple(test_state):\n    \"\"\"Test processing an event.\n\n    Args:\n        test_state: A state.\n    \"\"\"\n    assert test_state.num1 == 0\n\n    event = Event(token=\"t\", name=\"set_num1\", payload={\"value\": 69})\n    async for update in test_state._process(event):\n        # The event should update the value.\n        assert test_state.num1 == 69\n\n        # The delta should contain the changes, including computed vars.\n        assert update.delta == {\n            TestState.get_full_name(): {\n                \"num1\" + FIELD_MARKER: 69,\n                \"sum\" + FIELD_MARKER: 72.15,\n            },\n            GrandchildState3.get_full_name(): {\"computed\" + FIELD_MARKER: \"\"},\n        }\n        assert update.events == []\n\n\n@pytest.mark.asyncio\nasync def test_process_event_substate(test_state, child_state, grandchild_state):\n    \"\"\"Test processing an event on a substate.\n\n    Args:\n        test_state: A state.\n        child_state: A child state.\n        grandchild_state: A grandchild state.\n    \"\"\"\n    # Events should bubble down to the substate.\n    assert child_state.value == \"\"\n    assert child_state.count == 23\n    event = Event(\n        token=\"t\",\n        name=f\"{ChildState.get_name()}.change_both\",\n        payload={\"value\": \"hi\", \"count\": 12},\n    )\n    async for update in test_state._process(event):\n        assert child_state.value == \"HI\"\n        assert child_state.count == 24\n        assert update.delta == {\n            # TestState.get_full_name(): {\"sum\": 3.14, \"upper\": \"\"},\n            ChildState.get_full_name(): {\n                \"value\" + FIELD_MARKER: \"HI\",\n                \"count\" + FIELD_MARKER: 24,\n            },\n            GrandchildState3.get_full_name(): {\"computed\" + FIELD_MARKER: \"\"},\n        }\n        test_state._clean()\n\n    # Test with the grandchild state.\n    assert grandchild_state.value2 == \"\"\n    event = Event(\n        token=\"t\",\n        name=f\"{GrandchildState.get_full_name()}.set_value2\",\n        payload={\"value\": \"new\"},\n    )\n    async for update in test_state._process(event):\n        assert grandchild_state.value2 == \"new\"\n        assert update.delta == {\n            # TestState.get_full_name(): {\"sum\": 3.14, \"upper\": \"\"},\n            GrandchildState.get_full_name(): {\"value2\" + FIELD_MARKER: \"new\"},\n            GrandchildState3.get_full_name(): {\"computed\" + FIELD_MARKER: \"\"},\n        }\n\n\n@pytest.mark.asyncio\nasync def test_process_event_generator():\n    \"\"\"Test event handlers that generate multiple updates.\"\"\"\n    gen_state = GenState()  # pyright: ignore [reportCallIssue]\n    event = Event(\n        token=\"t\",\n        name=\"go\",\n        payload={\"c\": 5},\n    )\n    gen = gen_state._process(event)\n\n    count = 0\n    async for update in gen:\n        count += 1\n        if count == 6:\n            assert update.delta == {}\n            assert update.final\n        else:\n            assert gen_state.value == count\n            assert update.delta == {\n                GenState.get_full_name(): {\"value\" + FIELD_MARKER: count},\n            }\n            assert not update.final\n\n    assert count == 6\n\n\ndef test_get_client_token(test_state, router_data):\n    \"\"\"Test that the token obtained from the router_data is correct.\n\n    Args:\n        test_state: The test state.\n        router_data: The router data fixture.\n    \"\"\"\n    test_state.router = RouterData.from_router_data(router_data)\n    assert (\n        test_state.router.session.client_token == \"b181904c-3953-4a79-dc18-ae9518c22f05\"\n    )\n\n\ndef test_get_sid(test_state, router_data):\n    \"\"\"Test getting session id.\n\n    Args:\n        test_state: A state.\n        router_data: The router data fixture.\n    \"\"\"\n    test_state.router = RouterData.from_router_data(router_data)\n    assert test_state.router.session.session_id == \"9fpxSzPb9aFMb4wFAAAH\"\n\n\ndef test_get_headers(\n    test_state: TestState,\n    router_data: dict[str, str | dict],\n    router_data_headers: dict[str, str],\n):\n    \"\"\"Test getting client headers.\n\n    Args:\n        test_state: A state.\n        router_data: The router data fixture.\n        router_data_headers: The expected headers.\n    \"\"\"\n    print(router_data_headers)\n    test_state.router = RouterData.from_router_data(router_data)\n    print(test_state.router.headers)\n    assert test_state.router.headers == HeaderData(\n        **{format.to_snake_case(k): v for k, v in router_data_headers.items()},\n        raw_headers=_FrozenDictStrStr(**router_data_headers),\n    )\n\n\ndef test_get_client_ip(test_state, router_data):\n    \"\"\"Test getting client IP.\n\n    Args:\n        test_state: A state.\n        router_data: The router data fixture.\n    \"\"\"\n    test_state.router = RouterData.from_router_data(router_data)\n    assert test_state.router.session.client_ip == \"127.0.0.1\"\n\n\ndef test_get_current_page(test_state):\n    assert test_state.router._page.path == \"\"\n\n    route = \"mypage/subpage\"\n    test_state.router = RouterData.from_router_data({RouteVar.PATH: route})\n    assert test_state.router._page.path == route\n\n\ndef test_get_query_params(test_state):\n    assert test_state.router._page.params == {}\n\n    params = {\"p1\": \"a\", \"p2\": \"b\"}\n    test_state.router = RouterData.from_router_data({RouteVar.QUERY: params})\n    assert dict(test_state.router._page.params) == params\n\n\ndef test_add_var():\n    class DynamicState(BaseState):\n        pass\n\n    ds1 = DynamicState()\n    assert \"dynamic_int\" not in ds1.__dict__\n    assert not hasattr(ds1, \"dynamic_int\")\n    ds1.add_var(\"dynamic_int\", int, 42)\n    # Existing instances get the BaseVar\n    assert ds1.dynamic_int.equals(DynamicState.dynamic_int)  # pyright: ignore [reportAttributeAccessIssue]\n    # New instances get an actual value with the default\n    assert DynamicState().dynamic_int == 42  # pyright: ignore[reportAttributeAccessIssue]\n\n    ds1.add_var(\"dynamic_list\", list[int], [5, 10])\n    assert ds1.dynamic_list.equals(DynamicState.dynamic_list)  # pyright: ignore [reportAttributeAccessIssue]\n    ds2 = DynamicState()\n    assert ds2.dynamic_list == [5, 10]  # pyright: ignore[reportAttributeAccessIssue]\n    ds2.dynamic_list.append(15)  # pyright: ignore[reportAttributeAccessIssue]\n    assert ds2.dynamic_list == [5, 10, 15]  # pyright: ignore[reportAttributeAccessIssue]\n    assert DynamicState().dynamic_list == [5, 10]  # pyright: ignore[reportAttributeAccessIssue]\n\n    ds1.add_var(\"dynamic_dict\", dict[str, int], {\"k1\": 5, \"k2\": 10})\n    assert ds1.dynamic_dict.equals(DynamicState.dynamic_dict)  # pyright: ignore [reportAttributeAccessIssue]\n    assert ds2.dynamic_dict.equals(DynamicState.dynamic_dict)  # pyright: ignore [reportAttributeAccessIssue]\n    assert DynamicState().dynamic_dict == {\"k1\": 5, \"k2\": 10}  # pyright: ignore[reportAttributeAccessIssue]\n\n\ndef test_add_var_default_handlers(test_state):\n    test_state.add_var(\"rand_int\", int, 10)\n    assert \"set_rand_int\" in test_state.event_handlers\n    assert isinstance(test_state.event_handlers[\"set_rand_int\"], EventHandler)\n\n\nclass InterdependentState(BaseState):\n    \"\"\"A state with 3 vars and 3 computed vars.\n\n    x: a variable that no computed var depends on\n    v1: a variable that one computed var directly depends on\n    _v2: a backend variable that one computed var directly depends on\n\n    v1x2: a computed var that depends on v1\n    v2x2: a computed var that depends on backend var _v2\n    v1x2x2: a computed var that depends on computed var v1x2\n    \"\"\"\n\n    x: int = 0\n    v1: int = 0\n    _v2: int = 1\n\n    @rx.var\n    def v1x2(self) -> int:\n        \"\"\"Depends on var v1.\n\n        Returns:\n            Var v1 multiplied by 2\n        \"\"\"\n        return self.v1 * 2\n\n    @rx.var\n    def v2x2(self) -> int:\n        \"\"\"Depends on backend var _v2.\n\n        Returns:\n            backend var _v2 multiplied by 2\n        \"\"\"\n        return self._v2 * 2\n\n    @rx.var(backend=True)\n    def v2x2_backend(self) -> int:\n        \"\"\"Depends on backend var _v2.\n\n        Returns:\n            backend var _v2 multiplied by 2\n        \"\"\"\n        return self._v2 * 2\n\n    @rx.var\n    def v1x2x2(self) -> int:\n        \"\"\"Depends on ComputedVar v1x2.\n\n        Returns:\n            ComputedVar v1x2 multiplied by 2\n        \"\"\"\n        return self.v1x2 * 2\n\n    @rx.var\n    def _v3(self) -> int:\n        \"\"\"Depends on backend var _v2.\n\n        Returns:\n            The value of the backend variable.\n        \"\"\"\n        return self._v2\n\n    @rx.var\n    def v3x2(self) -> int:\n        \"\"\"Depends on ComputedVar _v3.\n\n        Returns:\n            ComputedVar _v3 multiplied by 2\n        \"\"\"\n        return self._v3 * 2\n\n\n@pytest.fixture\ndef interdependent_state() -> BaseState:\n    \"\"\"A state with varying dependency between vars.\n\n    Returns:\n        instance of InterdependentState\n    \"\"\"\n    s = InterdependentState()\n    s.dict()  # prime initial relationships by accessing all ComputedVars\n    return s\n\n\ndef test_interdependent_state_initial_dict() -> None:\n    s = InterdependentState()\n    state_name = s.get_name()\n    d = s.dict(initial=True)[state_name]\n    d.pop(\"router\" + FIELD_MARKER)\n    assert d == {\n        \"x\" + FIELD_MARKER: 0,\n        \"v1\" + FIELD_MARKER: 0,\n        \"v1x2\" + FIELD_MARKER: 0,\n        \"v2x2\" + FIELD_MARKER: 2,\n        \"v1x2x2\" + FIELD_MARKER: 0,\n        \"v3x2\" + FIELD_MARKER: 2,\n    }\n\n\ndef test_not_dirty_computed_var_from_var(\n    interdependent_state: InterdependentState,\n) -> None:\n    \"\"\"Set Var that no ComputedVar depends on, expect no recalculation.\n\n    Args:\n        interdependent_state: A state with varying Var dependencies.\n    \"\"\"\n    interdependent_state.x = 5\n    assert interdependent_state.get_delta() == {\n        interdependent_state.get_full_name(): {\"x\" + FIELD_MARKER: 5},\n    }\n\n\ndef test_dirty_computed_var_from_var(interdependent_state: InterdependentState) -> None:\n    \"\"\"Set Var that ComputedVar depends on, expect recalculation.\n\n    The other ComputedVar depends on the changed ComputedVar and should also be\n    recalculated. No other ComputedVars should be recalculated.\n\n    Args:\n        interdependent_state: A state with varying Var dependencies.\n    \"\"\"\n    interdependent_state.v1 = 1\n    assert interdependent_state.get_delta() == {\n        interdependent_state.get_full_name(): {\n            \"v1\" + FIELD_MARKER: 1,\n            \"v1x2\" + FIELD_MARKER: 2,\n            \"v1x2x2\" + FIELD_MARKER: 4,\n        },\n    }\n\n\ndef test_dirty_computed_var_from_backend_var(\n    interdependent_state: InterdependentState,\n) -> None:\n    \"\"\"Set backend var that ComputedVar depends on, expect recalculation.\n\n    Args:\n        interdependent_state: A state with varying Var dependencies.\n    \"\"\"\n    # Accessing ._v3 returns the immutable var it represents instead of the actual computed var\n    # assert InterdependentState._v3._backend is True\n    interdependent_state._v2 = 2\n    assert interdependent_state.get_delta() == {\n        interdependent_state.get_full_name(): {\n            \"v2x2\" + FIELD_MARKER: 4,\n            \"v3x2\" + FIELD_MARKER: 4,\n        },\n    }\n\n\ndef test_per_state_backend_var(interdependent_state: InterdependentState) -> None:\n    \"\"\"Set backend var on one instance, expect no affect in other instances.\n\n    Args:\n        interdependent_state: A state with varying Var dependencies.\n    \"\"\"\n    s2 = InterdependentState()\n    assert s2._v2 == interdependent_state._v2\n    interdependent_state._v2 = 2\n    assert s2._v2 != interdependent_state._v2\n    s3 = InterdependentState()\n    assert s3._v2 != interdependent_state._v2\n    # both s2 and s3 should still have the default value\n    assert s2._v2 == s3._v2\n    # changing s2._v2 should not affect others\n    s2._v2 = 4\n    assert s2._v2 != interdependent_state._v2\n    assert s2._v2 != s3._v2\n\n\ndef test_child_state():\n    \"\"\"Test that the child state computed vars can reference parent state vars.\"\"\"\n\n    class MainState(BaseState):\n        v: int = 2\n\n    class ChildState(MainState):\n        @computed_var\n        def rendered_var(self) -> int:\n            return self.v\n\n    ms = MainState()\n    cs = ms.substates[ChildState.get_name()]\n    assert ms.v == 2\n    assert isinstance(cs, ChildState)\n    assert cs.v == 2\n    assert cs.rendered_var == 2\n\n\ndef test_conditional_computed_vars():\n    \"\"\"Test that computed vars can have conditionals.\"\"\"\n\n    class MainState(BaseState):\n        flag: bool = False\n        t1: str = \"a\"\n        t2: str = \"b\"\n\n        @computed_var\n        def rendered_var(self) -> str:\n            if self.flag:\n                return self.t1\n            return self.t2\n\n    ms = MainState()\n    # Initially there are no dirty computed vars.\n    assert ms._dirty_computed_vars(from_vars={\"flag\"}) == {\n        (MainState.get_full_name(), \"rendered_var\")\n    }\n    assert ms._dirty_computed_vars(from_vars={\"t2\"}) == {\n        (MainState.get_full_name(), \"rendered_var\")\n    }\n    assert ms._dirty_computed_vars(from_vars={\"t1\"}) == {\n        (MainState.get_full_name(), \"rendered_var\")\n    }\n    assert ms.computed_vars[\"rendered_var\"]._deps(objclass=MainState) == {\n        MainState.get_full_name(): {\"flag\", \"t1\", \"t2\"}\n    }\n\n\ndef test_event_handlers_convert_to_fns(test_state, child_state):\n    \"\"\"Test that when the state is initialized, event handlers are converted to fns.\n\n    Args:\n        test_state: A state with event handlers.\n        child_state: A child state with event handlers.\n    \"\"\"\n    # The class instances should be event handlers.\n    assert isinstance(TestState.do_something, EventHandler)\n    assert isinstance(ChildState.change_both, EventHandler)\n\n    # The object instances should be fns.\n    test_state.do_something()\n\n    child_state.change_both(value=\"goose\", count=9)\n    assert child_state.value == \"GOOSE\"\n    assert child_state.count == 18\n\n\ndef test_event_handlers_call_other_handlers():\n    \"\"\"Test that event handlers can call other event handlers.\"\"\"\n\n    class MainState(BaseState):\n        v: int = 0\n\n        def set_v(self, v: int):\n            self.v = v\n\n        def set_v2(self, v: int):\n            self.set_v(v)\n\n    class SubState(MainState):\n        def set_v3(self, v: int):\n            self.set_v2(v)\n\n    class SubSubState(SubState):\n        def set_v4(self, v: int):\n            self.set_v(v)\n\n    ms = MainState()\n    ms.set_v2(1)\n    assert ms.v == 1\n\n    # ensure handler can be called from substate\n    sub_state = ms.substates[SubState.get_name()]\n    assert isinstance(sub_state, SubState)\n    sub_state.set_v3(2)\n    assert ms.v == 2\n\n    # ensure handler can be called from substate (referencing grandparent handler)\n    sub_sub_state = ms.get_substate(tuple(SubSubState.get_full_name().split(\".\")))\n    assert isinstance(sub_sub_state, SubSubState)\n    sub_sub_state.set_v4(3)\n    assert ms.v == 3\n\n\ndef test_computed_var_cached():\n    \"\"\"Test that a ComputedVar doesn't recalculate when accessed.\"\"\"\n    comp_v_calls = 0\n\n    class ComputedState(BaseState):\n        v: int = 0\n\n        @rx.var\n        def comp_v(self) -> int:\n            nonlocal comp_v_calls\n            comp_v_calls += 1\n            return self.v\n\n    cs = ComputedState()\n    assert cs.dict()[cs.get_full_name()][\"v\" + FIELD_MARKER] == 0\n    assert comp_v_calls == 1\n    assert cs.dict()[cs.get_full_name()][\"comp_v\" + FIELD_MARKER] == 0\n    assert comp_v_calls == 1\n    assert cs.comp_v == 0\n    assert comp_v_calls == 1\n    cs.v = 1\n    assert comp_v_calls == 1\n    assert cs.comp_v == 1\n    assert comp_v_calls == 2\n\n\ndef test_computed_var_cached_depends_on_non_cached():\n    \"\"\"Test that a cached var is recalculated if it depends on non-cached ComputedVar.\"\"\"\n\n    class ComputedState(BaseState):\n        v: int = 0\n\n        @rx.var(cache=False)\n        def no_cache_v(self) -> int:\n            return self.v\n\n        @rx.var\n        def dep_v(self) -> int:\n            return self.no_cache_v\n\n        @rx.var\n        def comp_v(self) -> int:\n            return self.v\n\n    cs = ComputedState()\n    assert cs.dirty_vars == set()\n    assert cs.get_delta() == {\n        cs.get_name(): {\"no_cache_v\" + FIELD_MARKER: 0, \"dep_v\" + FIELD_MARKER: 0}\n    }\n    cs._clean()\n    assert cs.dirty_vars == set()\n    assert cs.get_delta() == {\n        cs.get_name(): {\"no_cache_v\" + FIELD_MARKER: 0, \"dep_v\" + FIELD_MARKER: 0}\n    }\n    cs._clean()\n    assert cs.dirty_vars == set()\n    cs.v = 1\n    assert cs.dirty_vars == {\"v\", \"comp_v\", \"dep_v\", \"no_cache_v\"}\n    assert cs.get_delta() == {\n        cs.get_name(): {\n            \"v\" + FIELD_MARKER: 1,\n            \"no_cache_v\" + FIELD_MARKER: 1,\n            \"dep_v\" + FIELD_MARKER: 1,\n            \"comp_v\" + FIELD_MARKER: 1,\n        }\n    }\n    cs._clean()\n    assert cs.dirty_vars == set()\n    assert cs.get_delta() == {\n        cs.get_name(): {\"no_cache_v\" + FIELD_MARKER: 1, \"dep_v\" + FIELD_MARKER: 1}\n    }\n    cs._clean()\n    assert cs.dirty_vars == set()\n    assert cs.get_delta() == {\n        cs.get_name(): {\"no_cache_v\" + FIELD_MARKER: 1, \"dep_v\" + FIELD_MARKER: 1}\n    }\n    cs._clean()\n    assert cs.dirty_vars == set()\n\n\ndef test_computed_var_depends_on_parent_non_cached():\n    \"\"\"Child state cached var that depends on parent state un cached var is always recalculated.\"\"\"\n    counter = 0\n\n    class ParentState(BaseState):\n        @rx.var(cache=False)\n        def no_cache_v(self) -> int:\n            nonlocal counter\n            counter += 1\n            return counter\n\n    class ChildState(ParentState):\n        @rx.var\n        def dep_v(self) -> int:\n            return self.no_cache_v\n\n    ps = ParentState()\n    cs = ps.substates[ChildState.get_name()]\n\n    assert ps.dirty_vars == set()\n    assert cs.dirty_vars == set()\n\n    dict1 = json.loads(json_dumps(ps.dict()))\n    assert dict1[ps.get_full_name()] == {\n        \"no_cache_v\" + FIELD_MARKER: 1,\n        \"router\" + FIELD_MARKER: formatted_router,\n    }\n    assert dict1[cs.get_full_name()] == {\"dep_v\" + FIELD_MARKER: 2}\n    dict2 = json.loads(json_dumps(ps.dict()))\n    assert dict2[ps.get_full_name()] == {\n        \"no_cache_v\" + FIELD_MARKER: 3,\n        \"router\" + FIELD_MARKER: formatted_router,\n    }\n    assert dict2[cs.get_full_name()] == {\"dep_v\" + FIELD_MARKER: 4}\n    dict3 = json.loads(json_dumps(ps.dict()))\n    assert dict3[ps.get_full_name()] == {\n        \"no_cache_v\" + FIELD_MARKER: 5,\n        \"router\" + FIELD_MARKER: formatted_router,\n    }\n    assert dict3[cs.get_full_name()] == {\"dep_v\" + FIELD_MARKER: 6}\n    assert counter == 6\n\n\n@pytest.mark.parametrize(\"use_partial\", [True, False])\ndef test_cached_var_depends_on_event_handler(use_partial: bool):\n    \"\"\"A cached var that calls an event handler calculates deps correctly.\n\n    Args:\n        use_partial: if true, replace the EventHandler with functools.partial\n    \"\"\"\n    counter = 0\n\n    class HandlerState(BaseState):\n        x: int = 42\n\n        def handler(self):\n            self.x = self.x + 1\n\n        @rx.var\n        def cached_x_side_effect(self) -> int:\n            self.handler()\n            nonlocal counter\n            counter += 1\n            return counter\n\n    if use_partial:\n        HandlerState.handler = functools.partial(HandlerState.handler.fn)  # pyright: ignore [reportFunctionMemberAccess]\n        assert isinstance(HandlerState.handler, functools.partial)\n    else:\n        assert isinstance(HandlerState.handler, EventHandler)\n\n    s = HandlerState()\n    assert (\n        HandlerState.get_full_name(),\n        \"cached_x_side_effect\",\n    ) in s._var_dependencies[\"x\"]\n    assert s.cached_x_side_effect == 1\n    assert s.x == 43\n    s.handler()\n    assert s.cached_x_side_effect == 2\n    assert s.x == 45\n\n\ndef test_computed_var_dependencies():\n    \"\"\"Test that a ComputedVar correctly tracks its dependencies.\"\"\"\n\n    class ComputedState(BaseState):\n        v: int = 0\n        w: int = 0\n        x: int = 0\n        y: list[int] = [1, 2, 3]\n        _z: list[int] = [1, 2, 3]\n\n        @property\n        def testprop(self) -> int:\n            return self.v\n\n        @rx.var\n        def comp_v(self) -> int:\n            \"\"\"Direct access.\n\n            Returns:\n                The value of self.v.\n            \"\"\"\n            return self.v\n\n        @rx.var(backend=True)\n        def comp_v_backend(self) -> int:\n            \"\"\"Direct access backend var.\n\n            Returns:\n                The value of self.v.\n            \"\"\"\n            return self.v\n\n        @rx.var\n        def comp_v_via_property(self) -> int:\n            \"\"\"Access v via property.\n\n            Returns:\n                The value of v via property.\n            \"\"\"\n            return self.testprop\n\n        @rx.var\n        def comp_w(self) -> Callable[[], int]:\n            \"\"\"Nested lambda.\n\n            Returns:\n                A lambda that returns the value of self.w.\n            \"\"\"\n            return lambda: self.w\n\n        @rx.var\n        def comp_x(self) -> Callable[[], int]:\n            \"\"\"Nested function.\n\n            Returns:\n                A function that returns the value of self.x.\n            \"\"\"\n\n            def _():\n                return self.x\n\n            return _\n\n        @rx.var\n        def comp_y(self) -> list[int]:\n            \"\"\"Comprehension iterating over attribute.\n\n            Returns:\n                A list of the values of self.y.\n            \"\"\"\n            return [round(y) for y in self.y]\n\n        @rx.var\n        def comp_z(self) -> list[bool]:\n            \"\"\"Comprehension accesses attribute.\n\n            Returns:\n                A list of whether the values 0-4 are in self._z.\n            \"\"\"\n            return [z in self._z for z in range(5)]\n\n    cs = ComputedState()\n    assert cs._var_dependencies[\"v\"] == {\n        (ComputedState.get_full_name(), \"comp_v\"),\n        (ComputedState.get_full_name(), \"comp_v_backend\"),\n        (ComputedState.get_full_name(), \"comp_v_via_property\"),\n    }\n    assert cs._var_dependencies[\"w\"] == {(ComputedState.get_full_name(), \"comp_w\")}\n    assert cs._var_dependencies[\"x\"] == {(ComputedState.get_full_name(), \"comp_x\")}\n    assert cs._var_dependencies[\"y\"] == {(ComputedState.get_full_name(), \"comp_y\")}\n    assert cs._var_dependencies[\"_z\"] == {(ComputedState.get_full_name(), \"comp_z\")}\n\n\ndef test_backend_method():\n    \"\"\"A method with leading underscore should be callable from event handler.\"\"\"\n\n    class BackendMethodState(BaseState):\n        def _be_method(self):\n            return True\n\n        def handler(self):\n            assert self._be_method()\n\n    bms = BackendMethodState()\n    bms.handler()\n    assert bms._be_method()\n\n\n@pytest.fixture\ndef mutable_state() -> MutableTestState:\n    \"\"\"Create a Test state containing mutable types.\n\n    Returns:\n        A state object.\n    \"\"\"\n    return MutableTestState()\n\n\ndef test_setattr_of_mutable_types(mutable_state: MutableTestState):\n    \"\"\"Test that mutable types are converted to corresponding Reflex wrappers.\n\n    Args:\n        mutable_state: A test state.\n    \"\"\"\n    array = mutable_state.array\n    hashmap = mutable_state.hashmap\n    test_set = mutable_state.test_set\n\n    assert isinstance(array, MutableProxy)\n    assert isinstance(array, list)\n    assert isinstance(array[1], MutableProxy)\n    assert isinstance(array[1], list)\n    assert isinstance(array[2], MutableProxy)\n    assert isinstance(array[2], dict)\n    assert isinstance(array[:], list)\n    assert not isinstance(array[:], MutableProxy)\n    assert isinstance(array[:][1], MutableProxy)\n    assert isinstance(array[:][1], list)\n\n    assert isinstance(hashmap, MutableProxy)\n    assert isinstance(hashmap, dict)\n    assert isinstance(hashmap[\"key\"], MutableProxy)\n    assert isinstance(hashmap[\"key\"], list)\n    assert isinstance(hashmap[\"third_key\"], MutableProxy)\n    assert isinstance(hashmap[\"third_key\"], dict)\n\n    assert isinstance(test_set, MutableProxy)\n    assert isinstance(test_set, set)\n\n    assert isinstance(mutable_state.custom, MutableProxy)\n    assert isinstance(mutable_state.custom.array, MutableProxy)\n    assert isinstance(mutable_state.custom.array, list)\n    assert isinstance(mutable_state.custom.hashmap, MutableProxy)\n    assert isinstance(mutable_state.custom.hashmap, dict)\n    assert isinstance(mutable_state.custom.test_set, MutableProxy)\n    assert isinstance(mutable_state.custom.test_set, set)\n    assert isinstance(mutable_state.custom.custom, MutableProxy)\n\n    mutable_state.reassign_mutables()\n\n    array = mutable_state.array\n    hashmap = mutable_state.hashmap\n    test_set = mutable_state.test_set\n\n    assert isinstance(array, MutableProxy)\n    assert isinstance(array, list)\n    assert isinstance(array[1], MutableProxy)\n    assert isinstance(array[1], list)\n    assert isinstance(array[2], MutableProxy)\n    assert isinstance(array[2], dict)\n\n    assert isinstance(hashmap, MutableProxy)\n    assert isinstance(hashmap, dict)\n    assert isinstance(hashmap[\"mod_key\"], MutableProxy)\n    assert isinstance(hashmap[\"mod_key\"], list)\n    assert isinstance(hashmap[\"mod_third_key\"], MutableProxy)\n    assert isinstance(hashmap[\"mod_third_key\"], dict)\n\n    assert isinstance(test_set, MutableProxy)\n    assert isinstance(test_set, set)\n\n\ndef test_error_on_state_method_shadow():\n    \"\"\"Test that an error is thrown when an event handler shadows a state method.\"\"\"\n    with pytest.raises(NameError) as err:\n\n        class InvalidTest(BaseState):\n            def reset(self):\n                pass\n\n    assert (\n        err.value.args[0]\n        == \"The event handler name `reset` shadows a builtin State method; use a different name instead\"\n    )\n\n\n@pytest.mark.asyncio\nasync def test_state_with_invalid_yield(capsys: pytest.CaptureFixture[str], mock_app):\n    \"\"\"Test that an error is thrown when a state yields an invalid value.\n\n    Args:\n        capsys: Pytest fixture for capture standard streams.\n        mock_app: Mock app fixture.\n    \"\"\"\n\n    class StateWithInvalidYield(BaseState):\n        \"\"\"A state that yields an invalid value.\"\"\"\n\n        def invalid_handler(self):\n            \"\"\"Invalid handler.\n\n            Yields:\n                an invalid value.\n            \"\"\"\n            yield 1\n\n    invalid_state = StateWithInvalidYield()\n    async for update in invalid_state._process(\n        rx.event.Event(token=\"fake_token\", name=\"invalid_handler\")\n    ):\n        assert not update.delta\n        assert update.events == rx.event.fix_events(\n            [\n                rx.toast(\n                    \"An error occurred.\",\n                    level=\"error\",\n                    fallback_to_alert=True,\n                    description=\"TypeError: Your handler test_state_with_invalid_yield.<locals>.StateWithInvalidYield.invalid_handler must only return/yield: None, Events or other EventHandlers referenced by their class (i.e. using `type(self)` or other class references). Returned events of types <class 'int'>..<br/>See logs for details.\",\n                    id=\"backend_error\",\n                    position=\"top-center\",\n                    style={\"width\": \"500px\"},\n                )\n            ],\n            token=\"\",\n        )\n    captured = capsys.readouterr()\n    assert \"must only return/yield: None, Events or other EventHandlers\" in captured.err\n\n\n@pytest_asyncio.fixture(\n    loop_scope=\"function\", scope=\"function\", params=[\"in_process\", \"disk\", \"redis\"]\n)\nasync def state_manager(request) -> AsyncGenerator[StateManager, None]:\n    \"\"\"Instance of state manager parametrized for redis and in-process.\n\n    Args:\n        request: pytest request object.\n\n    Yields:\n        A state manager instance\n    \"\"\"\n    state_manager = StateManager.create(state=TestState)\n    if request.param == \"redis\":\n        if not isinstance(state_manager, StateManagerRedis):\n            state_manager = StateManagerRedis(state=TestState, redis=mock_redis())\n    elif request.param == \"disk\":\n        # explicitly NOT using redis\n        state_manager = StateManagerDisk(state=TestState)\n        assert not state_manager._states_locks\n    else:\n        state_manager = StateManagerMemory(state=TestState)\n        assert not state_manager._states_locks\n\n    yield state_manager\n\n    await state_manager.close()\n\n\n@pytest.fixture\ndef substate_token(state_manager, token) -> str:\n    \"\"\"A token + substate name for looking up in state manager.\n\n    Args:\n        state_manager: A state manager instance.\n        token: A token.\n\n    Returns:\n        Token concatenated with the state_manager's state full_name.\n    \"\"\"\n    return _substate_key(token, state_manager.state)\n\n\n@pytest.mark.asyncio\nasync def test_state_manager_modify_state(\n    state_manager: StateManager, token: str, substate_token: str\n):\n    \"\"\"Test that the state manager can modify a state exclusively.\n\n    Args:\n        state_manager: A state manager instance.\n        token: A token.\n        substate_token: A token + substate name for looking up in state manager.\n    \"\"\"\n    async with state_manager.modify_state(substate_token) as state:\n        if isinstance(state_manager, StateManagerRedis):\n            assert await state_manager.redis.get(f\"{token}_lock\")\n        elif isinstance(state_manager, (StateManagerMemory, StateManagerDisk)):\n            assert token in state_manager._states_locks\n            assert state_manager._states_locks[token].locked()\n        # Should be able to write proxy objects inside mutables\n        assert isinstance(state, TestState)\n        complex_1 = state.complex[1]\n        assert isinstance(complex_1, MutableProxy)\n        state.complex[3] = complex_1\n\n    if environment.REFLEX_OPLOCK_ENABLED.get():\n        await state_manager.close()\n\n    # lock should be dropped after exiting the context\n    if isinstance(state_manager, StateManagerRedis):\n        assert (await state_manager.redis.get(f\"{token}_lock\")) is None\n    elif isinstance(state_manager, (StateManagerMemory, StateManagerDisk)):\n        assert not state_manager._states_locks[token].locked()\n\n        # separate instances should NOT share locks\n        sm2 = type(state_manager)(state=TestState)\n        assert sm2._state_manager_lock is state_manager._state_manager_lock\n        assert not sm2._states_locks\n        if state_manager._states_locks:\n            assert sm2._states_locks != state_manager._states_locks\n\n        await sm2.close()\n\n\n@pytest.mark.asyncio\nasync def test_state_manager_contend(\n    state_manager: StateManager, token: str, substate_token: str\n):\n    \"\"\"Multiple coroutines attempting to access the same state.\n\n    Args:\n        state_manager: A state manager instance.\n        token: A token.\n        substate_token: A token + substate name for looking up in state manager.\n    \"\"\"\n    n_coroutines = 10\n    exp_num1 = 10\n\n    async with state_manager.modify_state(substate_token) as state:\n        state.num1 = 0\n\n    async def _coro():\n        async with state_manager.modify_state(substate_token) as state:\n            await asyncio.sleep(0.01)\n            assert isinstance(state, TestState)\n            state.num1 += 1\n\n    tasks = [asyncio.create_task(_coro()) for _ in range(n_coroutines)]\n\n    for f in asyncio.as_completed(tasks):\n        await f\n\n    if environment.REFLEX_OPLOCK_ENABLED.get():\n        await state_manager.close()\n\n    test_state = await state_manager.get_state(substate_token)\n    assert isinstance(test_state, TestState)\n    assert test_state.num1 == exp_num1\n\n    if isinstance(state_manager, StateManagerRedis):\n        assert (await state_manager.redis.get(f\"{token}_lock\")) is None\n    elif isinstance(state_manager, (StateManagerMemory, StateManagerDisk)):\n        assert token in state_manager._states_locks\n        assert not state_manager._states_locks[token].locked()\n\n\n@pytest_asyncio.fixture(loop_scope=\"function\", scope=\"function\")\nasync def state_manager_redis() -> AsyncGenerator[StateManager, None]:\n    \"\"\"Instance of state manager for redis only.\n\n    Yields:\n        A state manager instance\n    \"\"\"\n    state_manager = StateManager.create(TestState)\n\n    if not isinstance(state_manager, StateManagerRedis):\n        # Create a mocked redis client instead of skipping.\n        state_manager = StateManagerRedis(state=TestState, redis=mock_redis())\n\n    yield state_manager\n\n    await state_manager.close()\n\n\n@pytest.fixture\ndef substate_token_redis(state_manager_redis, token):\n    \"\"\"A token + substate name for looking up in state manager.\n\n    Args:\n        state_manager_redis: A state manager instance.\n        token: A token.\n\n    Returns:\n        Token concatenated with the state_manager's state full_name.\n    \"\"\"\n    return _substate_key(token, state_manager_redis.state)\n\n\n@pytest.mark.asyncio\nasync def test_state_manager_lock_expire(\n    state_manager_redis: StateManagerRedis, token: str, substate_token_redis: str\n):\n    \"\"\"Test that the state manager lock expires and raises exception exiting context.\n\n    Args:\n        state_manager_redis: A state manager instance.\n        token: A token.\n        substate_token_redis: A token + substate name for looking up in state manager.\n    \"\"\"\n    state_manager_redis.lock_expiration = LOCK_EXPIRATION\n    state_manager_redis.lock_warning_threshold = LOCK_WARNING_THRESHOLD\n\n    loop_exception = None\n\n    def loop_exception_handler(loop, context):\n        \"\"\"Catch the LockExpiredError from the event loop.\n\n        Args:\n            loop: The event loop.\n            context: The exception context.\n        \"\"\"\n        nonlocal loop_exception\n        loop_exception = context[\"exception\"]\n\n    asyncio.get_event_loop().set_exception_handler(loop_exception_handler)\n\n    async with state_manager_redis.modify_state(substate_token_redis):\n        await asyncio.sleep(0.01)\n\n    if environment.REFLEX_OPLOCK_ENABLED.get():\n        async with state_manager_redis.modify_state(substate_token_redis):\n            await asyncio.sleep(LOCK_EXPIRE_SLEEP)\n        await asyncio.sleep(LOCK_EXPIRE_SLEEP)\n        assert loop_exception is not None\n        with pytest.raises(LockExpiredError):\n            raise loop_exception\n    else:\n        with pytest.raises(LockExpiredError):\n            async with state_manager_redis.modify_state(substate_token_redis):\n                await asyncio.sleep(LOCK_EXPIRE_SLEEP)\n        assert loop_exception is None\n\n\n@pytest.mark.asyncio\nasync def test_state_manager_lock_expire_contend(\n    state_manager_redis: StateManagerRedis, token: str, substate_token_redis: str\n):\n    \"\"\"Test that the state manager lock expires and queued waiters proceed.\n\n    Args:\n        state_manager_redis: A state manager instance.\n        token: A token.\n        substate_token_redis: A token + substate name for looking up in state manager.\n    \"\"\"\n    exp_num1 = 4252\n    unexp_num1 = 666\n\n    state_manager_redis.lock_expiration = LOCK_EXPIRATION\n    state_manager_redis.lock_warning_threshold = LOCK_WARNING_THRESHOLD\n\n    loop_exception = None\n\n    def loop_exception_handler(loop, context):\n        \"\"\"Catch the LockExpiredError from the event loop.\n\n        Args:\n            loop: The event loop.\n            context: The exception context.\n        \"\"\"\n        nonlocal loop_exception\n        loop_exception = context[\"exception\"]\n\n    asyncio.get_event_loop().set_exception_handler(loop_exception_handler)\n\n    order = []\n    waiter_event = asyncio.Event()\n\n    async def _coro_blocker():\n        async with state_manager_redis.modify_state(substate_token_redis) as state:\n            order.append(\"blocker\")\n            waiter_event.set()\n            await asyncio.sleep(LOCK_EXPIRE_SLEEP)\n            state.num1 = unexp_num1\n\n    async def _coro_waiter():\n        await waiter_event.wait()\n        async with state_manager_redis.modify_state(substate_token_redis) as state:\n            order.append(\"waiter\")\n            state.num1 = exp_num1\n\n    tasks = [\n        asyncio.create_task(_coro_blocker()),\n        asyncio.create_task(_coro_waiter()),\n    ]\n    if environment.REFLEX_OPLOCK_ENABLED.get():\n        await tasks[0]  # Doesn't raise during `modify_state`, only on exit\n        await tasks[1]\n        await asyncio.sleep(LOCK_EXPIRE_SLEEP)\n        assert loop_exception is not None\n        with pytest.raises(LockExpiredError):\n            raise loop_exception\n        # In oplock mode, the blocker block's both updates\n        test_state = await state_manager_redis.get_state(substate_token_redis)\n        assert isinstance(test_state, TestState)\n        assert test_state.num1 == 0\n    else:\n        with pytest.raises(LockExpiredError):\n            await tasks[0]\n        await tasks[1]\n        assert loop_exception is None\n        test_state = await state_manager_redis.get_state(substate_token_redis)\n        assert isinstance(test_state, TestState)\n        assert test_state.num1 == exp_num1\n\n    assert order == [\"blocker\", \"waiter\"]\n\n\n@pytest.mark.asyncio\nasync def test_state_manager_lock_warning_threshold_contend(\n    state_manager_redis: StateManagerRedis,\n    token: str,\n    substate_token_redis: str,\n    mocker: MockerFixture,\n):\n    \"\"\"Test that the state manager triggers a warning when lock contention exceeds the warning threshold.\n\n    Args:\n        state_manager_redis: A state manager instance.\n        token: A token.\n        substate_token_redis: A token + substate name for looking up in state manager.\n        mocker: Pytest mocker object.\n    \"\"\"\n    console_warn = mocker.patch(\"reflex.utils.console.warn\")\n\n    state_manager_redis.lock_expiration = LOCK_EXPIRATION\n    state_manager_redis.lock_warning_threshold = LOCK_WARNING_THRESHOLD\n\n    order = []\n\n    async def _coro_blocker():\n        async with state_manager_redis.modify_state(substate_token_redis):\n            order.append(\"blocker\")\n            await asyncio.sleep(LOCK_WARN_SLEEP)\n\n    tasks = [\n        asyncio.create_task(_coro_blocker()),\n    ]\n\n    await tasks[0]\n    if environment.REFLEX_OPLOCK_ENABLED.get():\n        # When Oplock is enabled, we don't warn when lock is held too long.\n        console_warn.assert_not_called()\n    else:\n        console_warn.assert_called()\n        assert console_warn.call_count == 7\n\n\nclass CopyingAsyncMock(AsyncMock):\n    \"\"\"An AsyncMock, but deepcopy the args and kwargs first.\"\"\"\n\n    def __call__(self, *args, **kwargs):\n        \"\"\"Call the mock.\n\n        Args:\n            args: the arguments passed to the mock\n            kwargs: the keyword arguments passed to the mock\n\n        Returns:\n            The result of the mock call\n        \"\"\"\n        args = copy.deepcopy(args)\n        kwargs = copy.deepcopy(kwargs)\n        return super().__call__(*args, **kwargs)\n\n\n@pytest.fixture\ndef mock_app_simple(monkeypatch) -> rx.App:\n    \"\"\"Simple Mock app fixture.\n\n    Args:\n        monkeypatch: Pytest monkeypatch object.\n\n    Returns:\n        The app, after mocking out prerequisites.get_app()\n    \"\"\"\n    app = App(_state=TestState)\n\n    app_module = Mock()\n\n    setattr(app_module, CompileVars.APP, app)\n    app._state = TestState\n    app.event_namespace.emit = CopyingAsyncMock()  # pyright: ignore [reportOptionalMemberAccess]\n\n    def _mock_get_app(*args, **kwargs):\n        return app_module\n\n    monkeypatch.setattr(prerequisites, \"get_app\", _mock_get_app)\n    return app\n\n\n@pytest.fixture\ndef mock_app(mock_app_simple: rx.App, state_manager: StateManager) -> rx.App:\n    \"\"\"Mock app fixture.\n\n    Args:\n        mock_app_simple: A simple mock app.\n        state_manager: A state manager.\n\n    Returns:\n        The app, after mocking out prerequisites.get_app()\n    \"\"\"\n    mock_app_simple._state_manager = state_manager\n    return mock_app_simple\n\n\n@dataclasses.dataclass\nclass ModelDC:\n    \"\"\"A dataclass.\"\"\"\n\n    foo: str = \"bar\"\n    ls: list[dict] = dataclasses.field(default_factory=list)\n\n    def set_foo(self, val: str):\n        \"\"\"Set the attribute foo.\n\n        Args:\n            val: The value to set.\n        \"\"\"\n        self.foo = val\n\n    def double_foo(self) -> str:\n        \"\"\"Concatenate foo with foo.\n\n        Returns:\n            foo + foo\n        \"\"\"\n        return self.foo + self.foo\n\n    def copy(self, **kwargs) -> ModelDC:\n        \"\"\"Create a copy of the dataclass with updated fields.\n\n        Returns:\n            A new instance of ModelDC with updated fields.\n        \"\"\"\n        return dataclasses.replace(self, **kwargs)\n\n    def append_to_ls(self, item: dict):\n        \"\"\"Append an item to the list attribute ls.\n\n        Args:\n            item: The item to append.\n        \"\"\"\n        self.ls.append(item)\n\n    @classmethod\n    def from_dict(cls, data: dict) -> ModelDC:\n        \"\"\"Create an instance of ModelDC from a dictionary.\n\n        Args:\n            data: The dictionary to create the instance from.\n\n        Returns:\n            An instance of ModelDC.\n        \"\"\"\n        return cls(**data)\n\n\n@pytest.mark.asyncio\nasync def test_state_proxy(\n    grandchild_state: GrandchildState, mock_app: rx.App, token: str\n):\n    \"\"\"Test that the state proxy works.\n\n    Args:\n        grandchild_state: A grandchild state.\n        mock_app: An app that will be returned by `get_app()`\n        token: A token.\n    \"\"\"\n    child_state = grandchild_state.parent_state\n    assert child_state is not None\n    parent_state = child_state.parent_state\n    assert parent_state is not None\n    router_data = RouterData.from_router_data({\n        \"query\": {},\n        \"token\": token,\n        \"sid\": \"test_sid\",\n    })\n    grandchild_state.router = router_data\n    namespace = mock_app.event_namespace\n    assert namespace is not None\n    namespace.sid_to_token[router_data.session.session_id] = token\n    namespace._token_manager.instance_id = \"mock\"\n    namespace._token_manager.token_to_socket[token] = SocketRecord(\n        instance_id=\"mock\", sid=router_data.session.session_id\n    )\n    if isinstance(mock_app.state_manager, (StateManagerMemory, StateManagerDisk)):\n        mock_app.state_manager.states[parent_state.router.session.client_token] = (\n            parent_state\n        )\n    elif isinstance(mock_app.state_manager, StateManagerRedis):\n        pickle_state = parent_state._serialize()\n        if pickle_state:\n            await mock_app.state_manager.redis.set(\n                _substate_key(parent_state.router.session.client_token, parent_state),\n                pickle_state,\n                ex=mock_app.state_manager.token_expiration,\n            )\n\n    sp = StateProxy(grandchild_state)\n    assert sp.__wrapped__ == grandchild_state\n    assert sp._self_substate_path == tuple(grandchild_state.get_full_name().split(\".\"))\n    assert sp._self_app is mock_app\n    assert not sp._self_mutable\n    assert sp._self_actx is None\n\n    # cannot use normal contextmanager protocol\n    with pytest.raises(TypeError), sp:\n        pass\n\n    with pytest.raises(ImmutableStateError):\n        # cannot directly modify state proxy outside of async context\n        sp.value2 = \"16\"\n\n    with pytest.raises(ImmutableStateError):\n        # Cannot get_state\n        await sp.get_state(ChildState)\n\n    with pytest.raises(ImmutableStateError):\n        # Cannot access get_substate\n        sp.get_substate([])\n\n    with pytest.raises(ImmutableStateError):\n        # Cannot access parent state\n        sp.parent_state.get_name()\n\n    with pytest.raises(ImmutableStateError):\n        # Cannot access substates\n        sp.substates[\"\"]\n\n    async with sp:\n        assert sp._self_actx is not None\n        assert sp._self_mutable  # proxy is mutable inside context\n        if isinstance(mock_app.state_manager, (StateManagerMemory, StateManagerDisk)):\n            # For in-process store, only one instance of the state exists\n            assert sp.__wrapped__ is grandchild_state\n        else:\n            # When redis is used, a new+updated instance is assigned to the proxy\n            assert sp.__wrapped__ is not grandchild_state\n        sp.value2 = \"42\"\n    assert not sp._self_mutable  # proxy is not mutable after exiting context\n    assert sp._self_actx is None\n    assert sp.value2 == \"42\"\n\n    if environment.REFLEX_OPLOCK_ENABLED.get():\n        await mock_app.state_manager.close()\n\n    # Get the state from the state manager directly and check that the value is updated\n    gotten_state = await mock_app.state_manager.get_state(\n        _substate_key(grandchild_state.router.session.client_token, grandchild_state)\n    )\n    if isinstance(mock_app.state_manager, (StateManagerMemory, StateManagerDisk)):\n        # For in-process store, only one instance of the state exists\n        assert gotten_state is parent_state\n    else:\n        assert gotten_state is not parent_state\n    gotten_grandchild_state = gotten_state.get_substate(sp._self_substate_path)\n    assert gotten_grandchild_state is not None\n    assert isinstance(gotten_grandchild_state, GrandchildState)\n    assert gotten_grandchild_state.value2 == \"42\"\n\n    # ensure state update was emitted\n    assert mock_app.event_namespace is not None\n    mock_app.event_namespace.emit.assert_called_once()  # pyright: ignore [reportAttributeAccessIssue]\n    mcall = mock_app.event_namespace.emit.mock_calls[0]  # pyright: ignore [reportAttributeAccessIssue]\n    assert mcall.args[0] == str(SocketEvent.EVENT)\n    assert mcall.args[1] == StateUpdate(\n        delta={\n            TestState.get_full_name(): {\"router\" + FIELD_MARKER: router_data},\n            grandchild_state.get_full_name(): {\n                \"value2\" + FIELD_MARKER: \"42\",\n            },\n            GrandchildState3.get_full_name(): {\n                \"computed\" + FIELD_MARKER: \"\",\n            },\n        },\n        final=None,\n    )\n    assert mcall.kwargs[\"to\"] == grandchild_state.router.session.session_id\n\n\nclass BackgroundTaskState(BaseState):\n    \"\"\"A state with a background task.\"\"\"\n\n    order: list[str] = []\n    dict_list: dict[str, list[int]] = {\"foo\": [1, 2, 3]}\n    dc: ModelDC = ModelDC()\n\n    def __init__(self, **kwargs):  # noqa: D107\n        super().__init__(**kwargs)\n        self.router_data = {\"simulate\": \"hydrate\"}\n\n    @rx.var(cache=False)\n    def computed_order(self) -> list[str]:\n        \"\"\"Get the order as a computed var.\n\n        Returns:\n            The value of 'order' var.\n        \"\"\"\n        return self.order\n\n    @rx.event(background=True)\n    async def background_task(self):\n        \"\"\"A background task that updates the state.\"\"\"\n        async with self:\n            assert not self.order\n            self.order.append(\"background_task:start\")\n\n        assert isinstance(self, StateProxy)\n        with pytest.raises(ImmutableStateError):\n            self.order.append(\"bad idea\")\n\n        with pytest.raises(ImmutableStateError):\n            # Cannot manipulate dataclass attributes.\n            self.dc.foo = \"baz\"\n\n        with pytest.raises(ImmutableStateError):\n            # Even nested access to mutables raises an exception.\n            self.dict_list[\"foo\"].append(42)\n\n        with pytest.raises(ImmutableStateError):\n            # Cannot modify dataclass list attribute.\n            self.dc.ls.append({\"foo\": \"bar\"})\n\n        with pytest.raises(ImmutableStateError):\n            # Direct calling another handler that modifies state raises an exception.\n            self.other()\n\n        with pytest.raises(ImmutableStateError):\n            # Calling other methods that modify state raises an exception.\n            self._private_method()\n\n        # wait for some other event to happen\n        while len(self.order) == 1:\n            await asyncio.sleep(0.01)\n            async with self:\n                pass  # update proxy instance\n\n        async with self:\n            # Methods on ImmutableMutableProxy should return their wrapped return value.\n            assert self.dict_list.pop(\"foo\") == [1, 2, 3]\n\n            self.order.append(\"background_task:stop\")\n            self.other()  # direct calling event handlers works in context\n            self._private_method()\n\n    @rx.event(background=True)\n    async def background_task_reset(self):\n        \"\"\"A background task that resets the state.\"\"\"\n        with pytest.raises(ImmutableStateError):\n            # Resetting the state should be explicitly blocked.\n            self.reset()\n\n        async with self:\n            self.order.append(\"foo\")\n            self.reset()\n        assert not self.order\n        async with self:\n            self.order.append(\"reset\")\n\n    @rx.event(background=True)\n    async def background_task_generator(self):\n        \"\"\"A background task generator that does nothing.\n\n        Yields:\n            None\n        \"\"\"\n        yield\n\n    def other(self):\n        \"\"\"Some other event that updates the state.\"\"\"\n        self.order.append(\"other\")\n\n    def _private_method(self):\n        \"\"\"Some private method that updates the state.\"\"\"\n        self.order.append(\"private\")\n\n    async def bad_chain1(self):\n        \"\"\"Test that a background task cannot be chained.\"\"\"\n        await self.background_task()\n\n    async def bad_chain2(self):\n        \"\"\"Test that a background task generator cannot be chained.\"\"\"\n        async for _foo in self.background_task_generator():\n            pass\n\n\n@pytest.mark.asyncio\nasync def test_background_task_no_block(mock_app: rx.App, token: str):\n    \"\"\"Test that a background task does not block other events.\n\n    Args:\n        mock_app: An app that will be returned by `get_app()`\n        token: A token.\n    \"\"\"\n    router_data = {\"query\": {}, \"token\": token}\n    sid = \"test_sid\"\n    namespace = mock_app.event_namespace\n    assert namespace is not None\n    namespace.sid_to_token[sid] = token\n    namespace._token_manager.instance_id = \"mock\"\n    namespace._token_manager.token_to_socket[token] = SocketRecord(\n        instance_id=\"mock\", sid=sid\n    )\n    mock_app.state_manager.state = mock_app._state = BackgroundTaskState\n    async for update in rx.app.process(\n        mock_app,\n        Event(\n            token=token,\n            name=f\"{BackgroundTaskState.get_full_name()}.background_task\",\n            router_data=router_data,\n            payload={},\n        ),\n        sid=sid,\n        headers={},\n        client_ip=\"\",\n    ):\n        # background task returns empty update immediately\n        assert update == StateUpdate()\n\n    # wait for the coroutine to start\n    await asyncio.sleep(0.5 if CI else 0.1)\n    assert len(mock_app._background_tasks) == 1\n\n    # Process another normal event\n    async for update in rx.app.process(\n        mock_app,\n        Event(\n            token=token,\n            name=f\"{BackgroundTaskState.get_full_name()}.other\",\n            router_data=router_data,\n            payload={},\n        ),\n        sid=sid,\n        headers={},\n        client_ip=\"\",\n    ):\n        # other task returns delta\n        assert update == StateUpdate(\n            delta={\n                BackgroundTaskState.get_full_name(): {\n                    \"order\" + FIELD_MARKER: [\n                        \"background_task:start\",\n                        \"other\",\n                    ],\n                    \"computed_order\" + FIELD_MARKER: [\n                        \"background_task:start\",\n                        \"other\",\n                    ],\n                }\n            },\n        )\n\n    # Explicit wait for background tasks\n    for task in tuple(mock_app._background_tasks):\n        await task\n    assert not mock_app._background_tasks\n\n    if environment.REFLEX_OPLOCK_ENABLED.get():\n        await mock_app.state_manager.close()\n\n    exp_order = [\n        \"background_task:start\",\n        \"other\",\n        \"background_task:stop\",\n        \"other\",\n        \"private\",\n    ]\n\n    background_task_state = await mock_app.state_manager.get_state(\n        _substate_key(token, BackgroundTaskState)\n    )\n    assert isinstance(background_task_state, BackgroundTaskState)\n    assert background_task_state.order == exp_order\n    assert mock_app.event_namespace is not None\n    emit_mock = mock_app.event_namespace.emit\n\n    first_ws_message = emit_mock.mock_calls[0].args[1]  # pyright: ignore [reportAttributeAccessIssue]\n    assert (\n        first_ws_message.delta[BackgroundTaskState.get_full_name()].pop(\n            \"router\" + FIELD_MARKER\n        )\n        is not None\n    )\n    assert first_ws_message == StateUpdate(\n        delta={\n            BackgroundTaskState.get_full_name(): {\n                \"order\" + FIELD_MARKER: [\"background_task:start\"],\n                \"computed_order\" + FIELD_MARKER: [\"background_task:start\"],\n            }\n        },\n        events=[],\n        final=None,\n    )\n    for call in emit_mock.mock_calls[1:5]:  # pyright: ignore [reportAttributeAccessIssue]\n        assert call.args[1] == StateUpdate(\n            delta={\n                BackgroundTaskState.get_full_name(): {\n                    \"computed_order\" + FIELD_MARKER: [\"background_task:start\"],\n                }\n            },\n            events=[],\n            final=None,\n        )\n    assert emit_mock.mock_calls[-2].args[1] == StateUpdate(  # pyright: ignore [reportAttributeAccessIssue]\n        delta={\n            BackgroundTaskState.get_full_name(): {\n                \"order\" + FIELD_MARKER: exp_order,\n                \"computed_order\" + FIELD_MARKER: exp_order,\n                \"dict_list\" + FIELD_MARKER: {},\n            }\n        },\n        events=[],\n        final=None,\n    )\n    assert emit_mock.mock_calls[-1].args[1] == StateUpdate(  # pyright: ignore [reportAttributeAccessIssue]\n        delta={\n            BackgroundTaskState.get_full_name(): {\n                \"computed_order\" + FIELD_MARKER: exp_order,\n            },\n        },\n        events=[],\n        final=None,\n    )\n\n\n@pytest.mark.asyncio\nasync def test_background_task_reset(mock_app: rx.App, token: str):\n    \"\"\"Test that a background task calling reset is protected by the state proxy.\n\n    Args:\n        mock_app: An app that will be returned by `get_app()`\n        token: A token.\n    \"\"\"\n    router_data = {\"query\": {}}\n    mock_app.state_manager.state = mock_app._state = BackgroundTaskState\n    async for update in rx.app.process(\n        mock_app,\n        Event(\n            token=token,\n            name=f\"{BackgroundTaskState.get_name()}.background_task_reset\",\n            router_data=router_data,\n            payload={},\n        ),\n        sid=\"\",\n        headers={},\n        client_ip=\"\",\n    ):\n        # background task returns empty update immediately\n        assert update == StateUpdate()\n\n    # Explicit wait for background tasks\n    for task in tuple(mock_app._background_tasks):\n        await task\n    assert not mock_app._background_tasks\n\n    if environment.REFLEX_OPLOCK_ENABLED.get():\n        await mock_app.state_manager.close()\n\n    background_task_state = await mock_app.state_manager.get_state(\n        _substate_key(token, BackgroundTaskState)\n    )\n    assert isinstance(background_task_state, BackgroundTaskState)\n    assert background_task_state.order == [\"reset\"]\n\n\n@pytest.mark.asyncio\nasync def test_background_task_no_chain():\n    \"\"\"Test that a background task cannot be chained.\"\"\"\n    bts = BackgroundTaskState()\n    with pytest.raises(RuntimeError):\n        await bts.bad_chain1()\n    with pytest.raises(RuntimeError):\n        await bts.bad_chain2()\n\n\ndef test_mutable_list(mutable_state: MutableTestState):\n    \"\"\"Test that mutable lists are tracked correctly.\n\n    Args:\n        mutable_state: A test state.\n    \"\"\"\n    assert not mutable_state.dirty_vars\n\n    def assert_array_dirty():\n        assert mutable_state.dirty_vars == {\"array\"}\n        mutable_state._clean()\n        assert not mutable_state.dirty_vars\n\n    # Test all list operations\n    mutable_state.array.append(42)\n    assert_array_dirty()\n    mutable_state.array.extend([1, 2, 3])\n    assert_array_dirty()\n    mutable_state.array.insert(0, 0)\n    assert_array_dirty()\n    mutable_state.array.pop()\n    assert_array_dirty()\n    mutable_state.array.remove(42)\n    assert_array_dirty()\n    mutable_state.array.clear()\n    assert_array_dirty()\n    mutable_state.array += [1, 2, 3]\n    assert_array_dirty()\n    mutable_state.array.reverse()\n    assert_array_dirty()\n    mutable_state.array.sort()  # pyright: ignore[reportCallIssue]\n    assert_array_dirty()\n    mutable_state.array[0] = 666\n    assert_array_dirty()\n    del mutable_state.array[0]\n    assert_array_dirty()\n\n    # Test nested list operations\n    mutable_state.array[0] = [1, 2, 3]\n    assert_array_dirty()\n    mutable_state.array[0].append(4)\n    assert_array_dirty()\n    assert isinstance(mutable_state.array[0], MutableProxy)\n\n    # Test proxy returned from __iter__\n    mutable_state.array = [{}]\n    assert_array_dirty()\n    assert isinstance(mutable_state.array[0], MutableProxy)\n    for item in mutable_state.array:\n        assert isinstance(item, MutableProxy)\n        item[\"foo\"] = \"bar\"  # pyright: ignore[reportArgumentType, reportCallIssue]\n        assert_array_dirty()\n\n\ndef test_mutable_dict(mutable_state: MutableTestState):\n    \"\"\"Test that mutable dicts are tracked correctly.\n\n    Args:\n        mutable_state: A test state.\n    \"\"\"\n    assert not mutable_state.dirty_vars\n\n    def assert_hashmap_dirty():\n        assert mutable_state.dirty_vars == {\"hashmap\"}\n        mutable_state._clean()\n        assert not mutable_state.dirty_vars\n\n    # Test all dict operations\n    mutable_state.hashmap.update({\"new_key\": \"43\"})\n    assert_hashmap_dirty()\n    assert mutable_state.hashmap.setdefault(\"another_key\", \"66\") == \"another_value\"\n    assert_hashmap_dirty()\n    assert mutable_state.hashmap.setdefault(\"setdefault_key\", \"67\") == \"67\"\n    assert_hashmap_dirty()\n    assert mutable_state.hashmap.setdefault(\"setdefault_key\", \"68\") == \"67\"\n    assert_hashmap_dirty()\n    assert mutable_state.hashmap.pop(\"new_key\") == \"43\"\n    assert_hashmap_dirty()\n    mutable_state.hashmap.popitem()\n    assert_hashmap_dirty()\n    mutable_state.hashmap.clear()\n    assert_hashmap_dirty()\n    mutable_state.hashmap[\"new_key\"] = \"42\"\n    assert_hashmap_dirty()\n    del mutable_state.hashmap[\"new_key\"]\n    assert_hashmap_dirty()\n    mutable_state.hashmap |= {\"new_key\": \"44\"}\n    assert_hashmap_dirty()\n\n    # Test nested dict operations\n    mutable_state.hashmap[\"array\"] = []\n    assert_hashmap_dirty()\n    mutable_state.hashmap[\"array\"].append(\"1\")\n    assert_hashmap_dirty()\n    mutable_state.hashmap[\"dict\"] = {}\n    assert_hashmap_dirty()\n    mutable_state.hashmap[\"dict\"][\"key\"] = \"42\"\n    assert_hashmap_dirty()\n    mutable_state.hashmap[\"dict\"][\"dict\"] = {}\n    assert_hashmap_dirty()\n    mutable_state.hashmap[\"dict\"][\"dict\"][\"key\"] = \"43\"\n    assert_hashmap_dirty()\n\n    # Test proxy returned from `setdefault` and `get`\n    mutable_value = mutable_state.hashmap.setdefault(\"setdefault_mutable_key\", [])\n    assert_hashmap_dirty()\n    assert mutable_value == []\n    assert isinstance(mutable_value, MutableProxy)\n    mutable_value.append(\"foo\")\n    assert_hashmap_dirty()\n    mutable_value_other_ref = mutable_state.hashmap.get(\"setdefault_mutable_key\")\n    assert isinstance(mutable_value_other_ref, MutableProxy)\n    assert mutable_value is not mutable_value_other_ref\n    assert mutable_value == mutable_value_other_ref\n    assert not mutable_state.dirty_vars\n    mutable_value_other_ref.append(\"bar\")\n    assert_hashmap_dirty()\n\n    # `pop` should NOT return a proxy, because the returned value is no longer in the dict\n    mutable_value_third_ref = mutable_state.hashmap.pop(\"setdefault_mutable_key\")\n    assert not isinstance(mutable_value_third_ref, MutableProxy)\n    assert_hashmap_dirty()\n    mutable_value_third_ref.append(\"baz\")  # pyright: ignore[reportAttributeAccessIssue]\n    assert not mutable_state.dirty_vars\n    # Unfortunately previous refs still will mark the state dirty... nothing doing about that\n    assert mutable_value.pop()  # pyright: ignore[reportCallIssue]\n    assert_hashmap_dirty()\n\n\ndef test_mutable_set(mutable_state: MutableTestState):\n    \"\"\"Test that mutable sets are tracked correctly.\n\n    Args:\n        mutable_state: A test state.\n    \"\"\"\n    assert not mutable_state.dirty_vars\n\n    def assert_set_dirty():\n        assert mutable_state.dirty_vars == {\"test_set\"}\n        mutable_state._clean()\n        assert not mutable_state.dirty_vars\n\n    # Test all set operations\n    mutable_state.test_set.add(42)\n    assert_set_dirty()\n    mutable_state.test_set.update([1, 2, 3])\n    assert_set_dirty()\n    mutable_state.test_set.remove(42)\n    assert_set_dirty()\n    mutable_state.test_set.discard(3)\n    assert_set_dirty()\n    mutable_state.test_set.pop()\n    assert_set_dirty()\n    mutable_state.test_set.intersection_update([1, 2, 3])\n    assert_set_dirty()\n    mutable_state.test_set.difference_update([99])\n    assert_set_dirty()\n    mutable_state.test_set.symmetric_difference_update([102, 99])\n    assert_set_dirty()\n    mutable_state.test_set |= {1, 2, 3}\n    assert_set_dirty()\n    mutable_state.test_set &= {2, 3, 4}\n    assert_set_dirty()\n    mutable_state.test_set -= {2}\n    assert_set_dirty()\n    mutable_state.test_set ^= {42}\n    assert_set_dirty()\n    mutable_state.test_set.clear()\n    assert_set_dirty()\n\n\ndef test_mutable_custom(mutable_state: MutableTestState):\n    \"\"\"Test that mutable custom types derived from Base are tracked correctly.\n\n    Args:\n        mutable_state: A test state.\n    \"\"\"\n    assert not mutable_state.dirty_vars\n\n    def assert_custom_dirty():\n        assert mutable_state.dirty_vars == {\"custom\"}\n        mutable_state._clean()\n        assert not mutable_state.dirty_vars\n\n    mutable_state.custom.foo = \"bar\"\n    assert_custom_dirty()\n    mutable_state.custom.array.append(\"42\")\n    assert_custom_dirty()\n    mutable_state.custom.hashmap[\"key\"] = \"value\"\n    assert_custom_dirty()\n    mutable_state.custom.test_set.add(\"foo\")\n    assert_custom_dirty()\n    mutable_state.custom.custom.bar = \"baz\"\n    assert_custom_dirty()\n\n\ndef test_mutable_backend(mutable_state: MutableTestState):\n    \"\"\"Test that mutable backend vars are tracked correctly.\n\n    Args:\n        mutable_state: A test state.\n    \"\"\"\n    assert not mutable_state.dirty_vars\n\n    def assert_custom_dirty():\n        assert mutable_state.dirty_vars == {\"_be_custom\"}\n        mutable_state._clean()\n        assert not mutable_state.dirty_vars\n\n    mutable_state._be_custom.foo = \"bar\"\n    assert_custom_dirty()\n    mutable_state._be_custom.array.append(\"baz\")\n    assert_custom_dirty()\n    mutable_state._be_custom.hashmap[\"key\"] = \"value\"\n    assert_custom_dirty()\n    mutable_state._be_custom.test_set.add(\"foo\")\n    assert_custom_dirty()\n    mutable_state._be_custom.custom.bar = \"baz\"\n    assert_custom_dirty()\n\n\n@pytest.mark.parametrize(\n    \"copy_func\",\n    [\n        copy.copy,\n        copy.deepcopy,\n    ],\n)\ndef test_mutable_copy(mutable_state: MutableTestState, copy_func: Callable):\n    \"\"\"Test that mutable types are copied correctly.\n\n    Args:\n        mutable_state: A test state.\n        copy_func: A copy function.\n    \"\"\"\n    ms_copy = copy_func(mutable_state)\n    assert ms_copy is not mutable_state\n    for attr in (\"array\", \"hashmap\", \"test_set\", \"custom\"):\n        assert getattr(ms_copy, attr) == getattr(mutable_state, attr)\n        assert getattr(ms_copy, attr) is not getattr(mutable_state, attr)\n    ms_copy.custom.array.append(42)\n    assert \"custom\" in ms_copy.dirty_vars\n    if copy_func is copy.copy:\n        assert \"custom\" in mutable_state.dirty_vars\n    else:\n        assert not mutable_state.dirty_vars\n\n\n@pytest.mark.parametrize(\n    \"copy_func\",\n    [\n        copy.copy,\n        copy.deepcopy,\n    ],\n)\ndef test_mutable_copy_vars(mutable_state: MutableTestState, copy_func: Callable):\n    \"\"\"Test that mutable types are copied correctly.\n\n    Args:\n        mutable_state: A test state.\n        copy_func: A copy function.\n    \"\"\"\n    for attr in (\"array\", \"hashmap\", \"test_set\", \"custom\"):\n        var_orig = getattr(mutable_state, attr)\n        var_copy = copy_func(var_orig)\n        assert var_orig is not var_copy\n        assert var_orig == var_copy\n        # copied vars should never be proxies, as they by definition are no longer attached to the state.\n        assert not isinstance(var_copy, MutableProxy)\n\n\ndef test_duplicate_substate_class(mocker: MockerFixture):\n    # Neuter pytest escape hatch, because we want to test duplicate detection.\n    mocker.patch(\"reflex.state.is_testing_env\", return_value=False)\n    # Neuter <locals> state handling since these _are_ defined inside a function.\n    mocker.patch(\"reflex.state.BaseState._handle_local_def\", return_value=False)\n    with pytest.raises(ValueError):\n\n        class TestState(BaseState):\n            pass\n\n        class ChildTestState(TestState):  # pyright: ignore [reportRedeclaration]\n            pass\n\n        class ChildTestState(TestState):  # noqa: F811\n            pass\n\n        return TestState\n\n\nclass Foo(Base):\n    \"\"\"A class containing a list of str.\"\"\"\n\n    tags: list[str] = [\"123\", \"456\"]\n\n\ndef test_json_dumps_with_mutables():\n    \"\"\"Test that json.dumps works with Base vars inside mutable types.\"\"\"\n\n    class MutableContainsBase(BaseState):\n        items: list[Foo] = [Foo()]\n\n    dict_val = MutableContainsBase().dict()\n    assert isinstance(\n        dict_val[MutableContainsBase.get_full_name()][\"items\" + FIELD_MARKER][0], Foo\n    )\n    val = json_dumps(dict_val)\n    assert json.loads(val) == {\n        MutableContainsBase.get_full_name(): {\n            f\"items{FIELD_MARKER}\": [{\"tags\": [\"123\", \"456\"]}],\n            f\"router{FIELD_MARKER}\": formatted_router,\n        }\n    }\n\n\ndef test_reset_with_mutables():\n    \"\"\"Calling reset should always reset fields to a copy of the defaults.\"\"\"\n    default = [[0, 0], [0, 1], [1, 1]]\n    copied_default = copy.deepcopy(default)\n\n    class MutableResetState(BaseState):\n        items: list[list[int]] = default\n\n    instance = MutableResetState()\n    assert instance.items.__wrapped__ is not default  # pyright: ignore [reportAttributeAccessIssue]\n    assert instance.items == default == copied_default\n    instance.items.append([3, 3])\n    assert instance.items != default\n    assert instance.items != copied_default\n\n    instance.reset()\n    assert instance.items.__wrapped__ is not default  # pyright: ignore [reportAttributeAccessIssue]\n    assert instance.items == default == copied_default\n    instance.items.append([3, 3])\n    assert instance.items != default\n    assert instance.items != copied_default\n\n    instance.reset()\n    assert instance.items.__wrapped__ is not default  # pyright: ignore [reportAttributeAccessIssue]\n    assert instance.items == default == copied_default\n    instance.items.append([3, 3])\n    assert instance.items != default\n    assert instance.items != copied_default\n\n\nclass Custom1(Base):\n    \"\"\"A custom class with a str field.\"\"\"\n\n    foo: str\n\n    def set_foo(self, val: str):\n        \"\"\"Set the attribute foo.\n\n        Args:\n            val: The value to set.\n        \"\"\"\n        self.foo = val\n\n    def double_foo(self) -> str:\n        \"\"\"Concatenate foo with foo.\n\n        Returns:\n            foo + foo\n        \"\"\"\n        return self.foo + self.foo\n\n\nclass Custom2(Base):\n    \"\"\"A custom class with a Custom1 field.\"\"\"\n\n    c1: Custom1 | None = None\n    c1r: Custom1\n\n    def set_c1r_foo(self, val: str):\n        \"\"\"Set the foo attribute of the c1 field.\n\n        Args:\n            val: The value to set.\n        \"\"\"\n        self.c1r.set_foo(val)\n\n\nclass Custom3(Base):\n    \"\"\"A custom class with a Custom2 field.\"\"\"\n\n    c2: Custom2 | None = None\n    c2r: Custom2\n\n\ndef test_state_union_optional():\n    \"\"\"Test that state can be defined with Union and Optional vars.\"\"\"\n\n    class UnionState(BaseState):\n        int_float: int | float = 0\n        opt_int: int | None\n        c3: Custom3 | None\n        c3i: Custom3  # implicitly required\n        c3r: Custom3 = Custom3(c2r=Custom2(c1r=Custom1(foo=\"\")))\n        custom_union: Custom1 | Custom2 | Custom3 = Custom1(foo=\"\")\n\n    assert str(UnionState.c3.c2) == f'{UnionState.c3!s}?.[\"c2\"]'  # pyright: ignore [reportOptionalMemberAccess]\n    assert str(UnionState.c3.c2.c1) == f'{UnionState.c3!s}?.[\"c2\"]?.[\"c1\"]'  # pyright: ignore [reportOptionalMemberAccess]\n    assert (\n        str(UnionState.c3.c2.c1.foo) == f'{UnionState.c3!s}?.[\"c2\"]?.[\"c1\"]?.[\"foo\"]'  # pyright: ignore [reportOptionalMemberAccess]\n    )\n    assert (\n        str(UnionState.c3.c2.c1r.foo) == f'{UnionState.c3!s}?.[\"c2\"]?.[\"c1r\"]?.[\"foo\"]'  # pyright: ignore [reportOptionalMemberAccess]\n    )\n    assert str(UnionState.c3.c2r.c1) == f'{UnionState.c3!s}?.[\"c2r\"]?.[\"c1\"]'  # pyright: ignore [reportOptionalMemberAccess]\n    assert (\n        str(UnionState.c3.c2r.c1.foo) == f'{UnionState.c3!s}?.[\"c2r\"]?.[\"c1\"]?.[\"foo\"]'  # pyright: ignore [reportOptionalMemberAccess]\n    )\n    assert (\n        str(UnionState.c3.c2r.c1r.foo)  # pyright: ignore [reportOptionalMemberAccess]\n        == f'{UnionState.c3!s}?.[\"c2r\"]?.[\"c1r\"]?.[\"foo\"]'\n    )\n    assert str(UnionState.c3i.c2) == f'{UnionState.c3i!s}?.[\"c2\"]'\n    assert str(UnionState.c3r.c2) == f'{UnionState.c3r!s}?.[\"c2\"]'\n    assert UnionState.custom_union.foo is not None  # pyright: ignore [reportAttributeAccessIssue]\n    assert UnionState.custom_union.c1 is not None  # pyright: ignore [reportAttributeAccessIssue]\n    assert UnionState.custom_union.c1r is not None  # pyright: ignore [reportAttributeAccessIssue]\n    assert UnionState.custom_union.c2 is not None  # pyright: ignore [reportAttributeAccessIssue]\n    assert UnionState.custom_union.c2r is not None  # pyright: ignore [reportAttributeAccessIssue]\n    assert types.is_optional(UnionState.opt_int._var_type)  # pyright: ignore [reportAttributeAccessIssue, reportOptionalMemberAccess]\n    assert types.is_union(UnionState.int_float._var_type)  # pyright: ignore [reportAttributeAccessIssue]\n\n\ndef test_set_base_field_via_setter():\n    \"\"\"When calling a setter on a Base instance, also track changes.\"\"\"\n\n    class BaseFieldSetterState(BaseState):\n        c1: Custom1 = Custom1(foo=\"\")\n        c2: Custom2 = Custom2(c1r=Custom1(foo=\"\"))\n\n    bfss = BaseFieldSetterState()\n    assert \"c1\" not in bfss.dirty_vars\n\n    # Non-mutating function, not dirty\n    bfss.c1.double_foo()\n    assert \"c1\" not in bfss.dirty_vars\n\n    # Mutating function, dirty\n    bfss.c1.set_foo(\"bar\")\n    assert \"c1\" in bfss.dirty_vars\n    bfss.dirty_vars.clear()\n    assert \"c1\" not in bfss.dirty_vars\n\n    # Mutating function from Base, dirty\n    bfss.c1.foo = \"bar\"\n    assert \"c1\" in bfss.dirty_vars\n    bfss.dirty_vars.clear()\n    assert \"c1\" not in bfss.dirty_vars\n\n    # Assert identity of MutableProxy\n    mp = bfss.c1\n    assert isinstance(mp, MutableProxy)\n    mp3 = bfss.c1\n    assert mp is not mp3\n    # Since none of these set calls had values, the state should not be dirty\n    assert not bfss.dirty_vars\n\n    # Chained Mutating function, dirty\n    bfss.c2.set_c1r_foo(\"baz\")\n    assert \"c2\" in bfss.dirty_vars\n\n\ndef exp_is_hydrated(state: BaseState, is_hydrated: bool = True) -> dict[str, Any]:\n    \"\"\"Expected IS_HYDRATED delta that would be emitted by HydrateMiddleware.\n\n    Args:\n        state: the State that is hydrated.\n        is_hydrated: whether the state is hydrated.\n\n    Returns:\n        dict similar to that returned by `State.get_delta` with IS_HYDRATED: is_hydrated\n    \"\"\"\n    return {\n        state.get_full_name(): {CompileVars.IS_HYDRATED + FIELD_MARKER: is_hydrated}\n    }\n\n\nclass OnLoadState(State):\n    \"\"\"A test state with no return in handler.\"\"\"\n\n    num: int = 0\n\n    @rx.event\n    def test_handler(self):\n        \"\"\"Test handler.\"\"\"\n        self.num += 1\n\n\nclass OnLoadState2(State):\n    \"\"\"A test state with return in handler.\"\"\"\n\n    num: int = 0\n    name: str\n\n    def test_handler(self):\n        \"\"\"Test handler that calls another handler.\n\n        Returns:\n            Chain of EventHandlers\n        \"\"\"\n        self.num += 1\n        return self.change_name\n\n    def change_name(self):\n        \"\"\"Test handler to change name.\"\"\"\n        self.name = \"random\"\n\n\nclass OnLoadState3(State):\n    \"\"\"A test state with async handler.\"\"\"\n\n    num: int = 0\n\n    async def test_handler(self):\n        \"\"\"Test handler.\"\"\"\n        self.num += 1\n\n\n@pytest.mark.asyncio\n@pytest.mark.parametrize(\n    (\"test_state\", \"expected\"),\n    [\n        (OnLoadState, {\"on_load_state\": {\"num\": 1}}),\n        (OnLoadState2, {\"on_load_state2\": {\"num\": 1}}),\n        (OnLoadState3, {\"on_load_state3\": {\"num\": 1}}),\n    ],\n)\nasync def test_preprocess(\n    app_module_mock, token, test_state, expected, mocker: MockerFixture\n):\n    \"\"\"Test that a state hydrate event is processed correctly.\n\n    Args:\n        app_module_mock: The app module that will be returned by get_app().\n        token: A token.\n        test_state: State to process event.\n        expected: Expected delta.\n        mocker: pytest mock object.\n    \"\"\"\n    OnLoadInternalState._app_ref = None\n    mocker.patch(\n        \"reflex.state.State.class_subclasses\", {test_state, OnLoadInternalState}\n    )\n    app = app_module_mock.app = App(_state=State)\n\n    def index():\n        return \"hello\"\n\n    app.add_page(index, on_load=test_state.test_handler)\n    app._compile_page(\"index\")\n\n    async with app.state_manager.modify_state(_substate_key(token, State)) as state:\n        state.router_data = {\"simulate\": \"hydrate\"}\n\n    updates = []\n    async for update in rx.app.process(\n        app=app,\n        event=Event(\n            token=token,\n            name=f\"{state.get_name()}.{CompileVars.ON_LOAD_INTERNAL}\",\n            router_data={RouteVar.PATH: \"/\", RouteVar.ORIGIN: \"/\", RouteVar.QUERY: {}},\n        ),\n        sid=\"sid\",\n        headers={},\n        client_ip=\"\",\n    ):\n        assert isinstance(update, StateUpdate)\n        updates.append(update)\n    assert len(updates) == 1\n    assert updates[0].delta[State.get_name()].pop(\"router\" + FIELD_MARKER) is not None\n    assert updates[0].delta == exp_is_hydrated(state, False)\n\n    events = updates[0].events\n    assert len(events) == 2\n    async for update in state._process(events[0]):\n        assert update.delta == {test_state.get_full_name(): {\"num\" + FIELD_MARKER: 1}}\n    async for update in state._process(events[1]):\n        assert update.delta == exp_is_hydrated(state)\n\n    await app.state_manager.close()\n\n\n@pytest.mark.asyncio\nasync def test_preprocess_multiple_load_events(\n    app_module_mock, token, mocker: MockerFixture\n):\n    \"\"\"Test that a state hydrate event for multiple on-load events is processed correctly.\n\n    Args:\n        app_module_mock: The app module that will be returned by get_app().\n        token: A token.\n        mocker: pytest mock object.\n    \"\"\"\n    OnLoadInternalState._app_ref = None\n    mocker.patch(\n        \"reflex.state.State.class_subclasses\", {OnLoadState, OnLoadInternalState}\n    )\n    app = app_module_mock.app = App(_state=State)\n\n    def index():\n        return \"hello\"\n\n    app.add_page(index, on_load=[OnLoadState.test_handler, OnLoadState.test_handler])\n    app._compile_page(\"index\")\n    async with app.state_manager.modify_state(_substate_key(token, State)) as state:\n        state.router_data = {\"simulate\": \"hydrate\"}\n\n    updates = []\n    async for update in rx.app.process(\n        app=app,\n        event=Event(\n            token=token,\n            name=f\"{state.get_full_name()}.{CompileVars.ON_LOAD_INTERNAL}\",\n            router_data={RouteVar.PATH: \"/\", RouteVar.ORIGIN: \"/\", RouteVar.QUERY: {}},\n        ),\n        sid=\"sid\",\n        headers={},\n        client_ip=\"\",\n    ):\n        assert isinstance(update, StateUpdate)\n        updates.append(update)\n    assert len(updates) == 1\n    assert updates[0].delta[State.get_name()].pop(\"router\" + FIELD_MARKER) is not None\n    assert updates[0].delta == exp_is_hydrated(state, False)\n\n    events = updates[0].events\n    assert len(events) == 3\n    async for update in state._process(events[0]):\n        assert update.delta == {OnLoadState.get_full_name(): {\"num\" + FIELD_MARKER: 1}}\n    async for update in state._process(events[1]):\n        assert update.delta == {OnLoadState.get_full_name(): {\"num\" + FIELD_MARKER: 2}}\n    async for update in state._process(events[2]):\n        assert update.delta == exp_is_hydrated(state)\n\n    await app.state_manager.close()\n\n\n@pytest.mark.asyncio\nasync def test_get_state(mock_app: rx.App, token: str):\n    \"\"\"Test that a get_state populates the top level state and delta calculation is correct.\n\n    Args:\n        mock_app: An app that will be returned by `get_app()`\n        token: A token.\n    \"\"\"\n    mock_app.state_manager.state = mock_app._state = TestState\n\n    # Get instance of ChildState2.\n    test_state = await mock_app.state_manager.get_state(\n        _substate_key(token, ChildState2)\n    )\n    assert isinstance(test_state, TestState)\n    if isinstance(mock_app.state_manager, (StateManagerMemory, StateManagerDisk)):\n        # All substates are available\n        assert tuple(sorted(test_state.substates)) == (\n            ChildState.get_name(),\n            ChildState2.get_name(),\n            ChildState3.get_name(),\n        )\n    else:\n        # Sibling states are only populated if they have computed vars\n        assert tuple(sorted(test_state.substates)) == (\n            ChildState2.get_name(),\n            ChildState3.get_name(),\n        )\n\n    # Because ChildState3 has a computed var, it is always dirty, and always populated.\n    grandchild_state3 = test_state.substates[ChildState3.get_name()].substates[\n        GrandchildState3.get_name()\n    ]\n    assert isinstance(grandchild_state3, GrandchildState3)\n    assert grandchild_state3.computed == \"\"\n\n    # Get the child_state2 directly.\n    child_state2_direct = test_state.get_substate([ChildState2.get_name()])\n    child_state2_get_state = await test_state.get_state(ChildState2)\n    # These should be the same object.\n    assert child_state2_direct is child_state2_get_state\n\n    # Get arbitrary GrandchildState.\n    grandchild_state = await child_state2_get_state.get_state(GrandchildState)\n    assert isinstance(grandchild_state, GrandchildState)\n\n    # Now the original root should have all substates populated.\n    assert tuple(sorted(test_state.substates)) == (\n        ChildState.get_name(),\n        ChildState2.get_name(),\n        ChildState3.get_name(),\n    )\n\n    # ChildState should be retrievable\n    child_state_direct = test_state.get_substate([ChildState.get_name()])\n    child_state_get_state = await test_state.get_state(ChildState)\n    # These should be the same object.\n    assert child_state_direct is child_state_get_state\n\n    # GrandchildState instance should be the same as the one retrieved from the child_state2.\n    assert grandchild_state is child_state_direct.get_substate([\n        GrandchildState.get_name()\n    ])\n    grandchild_state.value2 = \"set_value\"\n\n    assert test_state.get_delta() == {\n        GrandchildState.get_full_name(): {\n            \"value2\" + FIELD_MARKER: \"set_value\",\n        },\n        GrandchildState3.get_full_name(): {\n            \"computed\" + FIELD_MARKER: \"\",\n        },\n    }\n\n    # Get a fresh instance\n    new_test_state = await mock_app.state_manager.get_state(\n        _substate_key(token, ChildState2)\n    )\n    assert isinstance(new_test_state, TestState)\n    if isinstance(mock_app.state_manager, (StateManagerMemory, StateManagerDisk)):\n        # In memory, it's the same instance\n        assert new_test_state is test_state\n        test_state._clean()\n        # All substates are available\n        assert tuple(sorted(new_test_state.substates)) == (\n            ChildState.get_name(),\n            ChildState2.get_name(),\n            ChildState3.get_name(),\n        )\n    else:\n        # With redis, we get a whole new instance\n        assert new_test_state is not test_state\n        # Sibling states are only populated if they have computed vars\n        assert tuple(sorted(new_test_state.substates)) == (\n            ChildState2.get_name(),\n            ChildState3.get_name(),\n        )\n\n    # Set a value on child_state2, should update cached var in grandchild_state2\n    child_state2 = new_test_state.get_substate((ChildState2.get_name(),))\n    child_state2.value = \"set_c2_value\"\n\n    assert new_test_state.get_delta() == {\n        ChildState2.get_full_name(): {\n            \"value\" + FIELD_MARKER: \"set_c2_value\",\n        },\n        GrandchildState2.get_full_name(): {\n            \"cached\" + FIELD_MARKER: \"set_c2_value\",\n        },\n        GrandchildState3.get_full_name(): {\n            \"computed\" + FIELD_MARKER: \"\",\n        },\n    }\n\n\n@pytest.mark.asyncio\nasync def test_get_state_from_sibling_not_cached(mock_app: rx.App, token: str):\n    \"\"\"A test simulating update_vars_internal when setting cookies with computed vars.\n\n    In that case, a sibling state, UpdateVarsInternalState handles the fetching\n    of states that need to have values set. Only the states that have a computed\n    var are pre-fetched (like Child3 in this test), so `get_state` needs to\n    avoid refetching those already-cached states when getting substates,\n    otherwise the set values will be overridden by the freshly deserialized\n    version and lost.\n\n    Explicit regression test for https://github.com/reflex-dev/reflex/issues/2851.\n\n    Args:\n        mock_app: An app that will be returned by `get_app()`\n        token: A token.\n    \"\"\"\n\n    class Parent(BaseState):\n        \"\"\"A root state like rx.State.\"\"\"\n\n        parent_var: int = 0\n\n    class Child(Parent):\n        \"\"\"A state simulating UpdateVarsInternalState.\"\"\"\n\n    class Child2(Parent):\n        \"\"\"An unconnected child state.\"\"\"\n\n    class Child3(Parent):\n        \"\"\"A child state with a computed var causing it to be pre-fetched.\n\n        If child3_var gets set to a value, and `get_state` erroneously\n        re-fetches it from redis, the value will be lost.\n        \"\"\"\n\n        child3_var: int = 0\n\n        @rx.var(cache=False)\n        def v(self) -> None:\n            pass\n\n    class Grandchild3(Child3):\n        \"\"\"An extra layer of substate to catch an issue discovered in\n        _determine_missing_parent_states while writing the regression test where\n        invalid parent state names were being constructed.\n        \"\"\"\n\n    class GreatGrandchild3(Grandchild3):\n        \"\"\"Fetching this state wants to also fetch Child3 as a missing parent.\n        However, Child3 should already be cached in the state tree because it\n        has a computed var.\n        \"\"\"\n\n    mock_app.state_manager.state = mock_app._state = Parent\n\n    # Get the top level state via unconnected sibling.\n    root = await mock_app.state_manager.get_state(_substate_key(token, Child))\n    # Set value in parent_var to assert it does not get refetched later.\n    root.parent_var = 1\n\n    if isinstance(mock_app.state_manager, StateManagerRedis):\n        # When redis is used, only states with computed vars are pre-fetched.\n        assert Child2.get_name() not in root.substates\n        assert Child3.get_name() in root.substates  # (due to @rx.var)\n\n    # Get the unconnected sibling state, which will be used to `get_state` other instances.\n    child = root.get_substate(Child.get_full_name().split(\".\"))\n\n    # Get an uncached child state.\n    child2 = await child.get_state(Child2)\n    assert child2.parent_var == 1\n\n    # Set value on already-cached Child3 state (prefetched because it has a Computed Var).\n    child3 = await child.get_state(Child3)\n    child3.child3_var = 1\n\n    # Get uncached great_grandchild3 state.\n    great_grandchild3 = await child.get_state(GreatGrandchild3)\n\n    # Assert that we didn't re-fetch the parent and child3 state from redis\n    assert great_grandchild3.parent_var == 1\n    assert great_grandchild3.child3_var == 1\n\n\n# Save a reference to the rx.State to shadow the name State for testing.\nRxState = State\n\n\ndef test_potentially_dirty_states():\n    \"\"\"Test that potentially_dirty_substates returns the correct substates.\n\n    Even if the name \"State\" is shadowed, it should still work correctly.\n    \"\"\"\n\n    class State(RxState):\n        @computed_var\n        def foo(self) -> str:\n            return \"\"\n\n    class C1(State):\n        @computed_var\n        def bar(self) -> str:\n            return \"\"\n\n    assert RxState._get_potentially_dirty_states() == set()\n    assert State._get_potentially_dirty_states() == set()\n    assert C1._get_potentially_dirty_states() == set()\n\n\n@pytest.mark.asyncio\nasync def test_router_var_dep(state_manager: StateManager, token: str) -> None:\n    \"\"\"Test that router var dependencies are correctly tracked.\n\n    Args:\n        state_manager: A state manager.\n        token: A token.\n    \"\"\"\n\n    class RouterVarParentState(State):\n        \"\"\"A parent state for testing router var dependency.\"\"\"\n\n    class RouterVarDepState(RouterVarParentState):\n        \"\"\"A state with a router var dependency.\"\"\"\n\n        @rx.var\n        def foo(self) -> str:\n            return self.router._page.params.get(\"foo\", \"\")\n\n    foo = RouterVarDepState.computed_vars[\"foo\"]\n    State._init_var_dependency_dicts()\n\n    assert foo._deps(objclass=RouterVarDepState) == {\n        RouterVarDepState.get_full_name(): {\"router\"}\n    }\n    assert (RouterVarDepState.get_full_name(), \"foo\") in State._var_dependencies[\n        \"router\"\n    ]\n\n    # Get state from state manager.\n    state_manager.state = State\n    rx_state = await state_manager.get_state(_substate_key(token, State))\n    assert RouterVarParentState.get_name() in rx_state.substates\n    parent_state = rx_state.substates[RouterVarParentState.get_name()]\n    assert RouterVarDepState.get_name() in parent_state.substates\n    state = parent_state.substates[RouterVarDepState.get_name()]\n\n    assert state.dirty_vars == set()\n\n    # Reassign router var\n    state.router = state.router\n    assert rx_state.dirty_vars == {\"router\"}\n    assert state.dirty_vars == {\"foo\"}\n    assert parent_state.dirty_substates == {RouterVarDepState.get_name()}\n\n\n@pytest.mark.asyncio\nasync def test_setvar(mock_app: rx.App, token: str):\n    \"\"\"Test that setvar works correctly.\n\n    Args:\n        mock_app: An app that will be returned by `get_app()`\n        token: A token.\n    \"\"\"\n    state = await mock_app.state_manager.get_state(_substate_key(token, TestState))\n    assert isinstance(state, TestState)\n\n    # Set Var in same state (with Var type casting)\n    for event in rx.event.fix_events(\n        [TestState.setvar(\"num1\", 42), TestState.setvar(\"num2\", \"4.2\")], token\n    ):\n        async for update in state._process(event):\n            print(update)\n    assert state.num1 == 42\n    assert math.isclose(state.num2, 4.2)\n\n    # Set Var in parent state\n    for event in rx.event.fix_events([GrandchildState.setvar(\"array\", [43])], token):\n        async for update in state._process(event):\n            print(update)\n    assert state.array == [43]\n\n    # Cannot setvar for non-existent var\n    with pytest.raises(AttributeError):\n        TestState.setvar(\"non_existent_var\")\n\n    # Cannot setvar for computed vars\n    with pytest.raises(AttributeError):\n        TestState.setvar(\"sum\")\n\n    # Cannot setvar with non-string\n    with pytest.raises(ValueError):\n        TestState.setvar(42, 42)\n\n\ndef test_setvar_async_setter():\n    \"\"\"Test that overridden async setters raise Exception when used with setvar.\"\"\"\n    with pytest.raises(NotImplementedError):\n        TestState.setvar(\"asynctest\", 42)\n\n\n@pytest.mark.parametrize(\n    (\"expiration_kwargs\", \"expected_values\"),\n    [\n        (\n            {\"redis_lock_expiration\": 20000},\n            (\n                20000,\n                constants.Expiration.TOKEN,\n                constants.Expiration.LOCK_WARNING_THRESHOLD,\n            ),\n        ),\n        (\n            {\"redis_lock_expiration\": 50000, \"redis_token_expiration\": 5600},\n            (50000, 5600, constants.Expiration.LOCK_WARNING_THRESHOLD),\n        ),\n        (\n            {\"redis_token_expiration\": 7600},\n            (\n                constants.Expiration.LOCK,\n                7600,\n                constants.Expiration.LOCK_WARNING_THRESHOLD,\n            ),\n        ),\n        (\n            {\"redis_lock_expiration\": 50000, \"redis_lock_warning_threshold\": 1500},\n            (50000, constants.Expiration.TOKEN, 1500),\n        ),\n        (\n            {\"redis_token_expiration\": 5600, \"redis_lock_warning_threshold\": 3000},\n            (constants.Expiration.LOCK, 5600, 3000),\n        ),\n        (\n            {\n                \"redis_lock_expiration\": 50000,\n                \"redis_token_expiration\": 5600,\n                \"redis_lock_warning_threshold\": 2000,\n            },\n            (50000, 5600, 2000),\n        ),\n    ],\n)\ndef test_redis_state_manager_config_knobs(tmp_path, expiration_kwargs, expected_values):\n    proj_root = tmp_path / \"project1\"\n    proj_root.mkdir()\n\n    config_items = \",\\n    \".join(\n        f\"{key} = {value}\" for key, value in expiration_kwargs.items()\n    )\n\n    config_string = f\"\"\"\nimport reflex as rx\nconfig = rx.Config(\n    app_name=\"project1\",\n    redis_url=\"redis://localhost:6379\",\n    state_manager_mode=\"redis\",\n    {config_items}\n)\n\"\"\"\n    (proj_root / \"rxconfig.py\").write_text(dedent(config_string))\n\n    with chdir(proj_root):\n        # reload config for each parameter to avoid stale values\n        reflex.config.get_config(reload=True)\n        from reflex.state import State\n\n        state_manager = StateManagerRedis(state=State, redis=mock_redis())\n        assert state_manager.lock_expiration == expected_values[0]  # pyright: ignore [reportAttributeAccessIssue]\n        assert state_manager.token_expiration == expected_values[1]  # pyright: ignore [reportAttributeAccessIssue]\n        assert state_manager.lock_warning_threshold == expected_values[2]  # pyright: ignore [reportAttributeAccessIssue]\n\n\n@pytest.mark.parametrize(\n    (\"redis_lock_expiration\", \"redis_lock_warning_threshold\"),\n    [\n        (10000, 10000),\n        (20000, 30000),\n    ],\n)\ndef test_redis_state_manager_config_knobs_invalid_lock_warning_threshold(\n    tmp_path, redis_lock_expiration, redis_lock_warning_threshold\n):\n    proj_root = tmp_path / \"project1\"\n    proj_root.mkdir()\n\n    config_string = f\"\"\"\nimport reflex as rx\nconfig = rx.Config(\n    app_name=\"project1\",\n    redis_url=\"redis://localhost:6379\",\n    state_manager_mode=\"redis\",\n    redis_lock_expiration = {redis_lock_expiration},\n    redis_lock_warning_threshold = {redis_lock_warning_threshold},\n)\n    \"\"\"\n\n    (proj_root / \"rxconfig.py\").write_text(dedent(config_string))\n\n    with chdir(proj_root):\n        # reload config for each parameter to avoid stale values\n        reflex.config.get_config(reload=True)\n        from reflex.state import State\n\n        with pytest.raises(InvalidLockWarningThresholdError):\n            StateManagerRedis(state=State, redis=mock_redis())\n        del sys.modules[constants.Config.MODULE]\n\n\ndef test_auto_setters_off(tmp_path):\n    proj_root = tmp_path / \"project1\"\n    proj_root.mkdir()\n\n    config_string = \"\"\"\nimport reflex as rx\nconfig = rx.Config(\n    app_name=\"project1\",\n    state_auto_setters=False,\n)\n    \"\"\"\n\n    (proj_root / \"rxconfig.py\").write_text(dedent(config_string))\n\n    with chdir(proj_root):\n        # reload config for each parameter to avoid stale values\n        reflex.config.get_config(reload=True)\n        from reflex.state import State\n\n        class TestState(State):\n            \"\"\"A test state.\"\"\"\n\n            num: int = 0\n\n        assert list(TestState.event_handlers) == [\"setvar\"]\n\n\nclass MixinState(State, mixin=True):\n    \"\"\"A mixin state for testing.\"\"\"\n\n    num: int = 0\n    _backend: int = 0\n    _backend_no_default: dict\n\n    @rx.var\n    def computed(self) -> str:\n        \"\"\"A computed var on mixin state.\n\n        Returns:\n            A computed value.\n        \"\"\"\n        return \"\"\n\n\nclass UsesMixinState(MixinState, State):\n    \"\"\"A state that uses the mixin state.\"\"\"\n\n\nclass ChildUsesMixinState(UsesMixinState):\n    \"\"\"A child state that uses the mixin state.\"\"\"\n\n\nclass ChildMixinState(ChildUsesMixinState, mixin=True):\n    \"\"\"A mixin state that inherits from a concrete state that uses mixins.\"\"\"\n\n\nclass GrandchildUsesMixinState(ChildMixinState):\n    \"\"\"A grandchild state that uses the mixin state.\"\"\"\n\n\nclass BareMixin:\n    \"\"\"A bare mixin which does not inherit from rx.State.\"\"\"\n\n    _bare_mixin: int = 0\n\n\nclass BareStateMixin(BareMixin, rx.State, mixin=True):\n    \"\"\"A state mixin that uses a bare mixin.\"\"\"\n\n\nclass BareMixinState(BareStateMixin, State):\n    \"\"\"A state that uses a bare mixin.\"\"\"\n\n\nclass ChildBareMixinState(BareMixinState):\n    \"\"\"A child state that uses a bare mixin.\"\"\"\n\n\ndef test_mixin_state() -> None:\n    \"\"\"Test that a mixin state works correctly.\"\"\"\n    assert \"num\" in UsesMixinState.base_vars\n    assert \"num\" in UsesMixinState.vars\n    assert UsesMixinState.backend_vars == {\n        \"_backend\": 0,\n        \"_backend_no_default\": {},\n        \"_reflex_internal_links\": None,\n    }\n\n    assert \"computed\" in UsesMixinState.computed_vars\n    assert \"computed\" in UsesMixinState.vars\n\n    assert (\n        UsesMixinState(_reflex_internal_init=True)._backend_no_default  # pyright: ignore [reportCallIssue]\n        is not UsesMixinState.backend_vars[\"_backend_no_default\"]\n    )\n\n    assert UsesMixinState.get_parent_state() == State\n    assert UsesMixinState.get_root_state() == State\n\n\ndef test_child_mixin_state() -> None:\n    \"\"\"Test that mixin vars are only applied to the highest state in the hierarchy.\"\"\"\n    assert \"num\" in ChildUsesMixinState.inherited_vars\n    assert \"num\" not in ChildUsesMixinState.base_vars\n\n    assert \"computed\" in ChildUsesMixinState.inherited_vars\n    assert \"computed\" not in ChildUsesMixinState.computed_vars\n\n    assert ChildUsesMixinState.get_parent_state() == UsesMixinState\n    assert ChildUsesMixinState.get_root_state() == State\n\n\ndef test_grandchild_mixin_state() -> None:\n    \"\"\"Test that a mixin can inherit from a concrete state class.\"\"\"\n    assert \"num\" in GrandchildUsesMixinState.inherited_vars\n    assert \"num\" not in GrandchildUsesMixinState.base_vars\n\n    assert \"computed\" in GrandchildUsesMixinState.inherited_vars\n    assert \"computed\" not in GrandchildUsesMixinState.computed_vars\n\n    assert ChildMixinState.get_parent_state() == ChildUsesMixinState\n    assert ChildMixinState.get_root_state() == State\n\n    assert GrandchildUsesMixinState.get_parent_state() == ChildUsesMixinState\n    assert GrandchildUsesMixinState.get_root_state() == State\n\n\ndef test_bare_mixin_state() -> None:\n    \"\"\"Test that a mixin can inherit from a concrete state class.\"\"\"\n    assert \"_bare_mixin\" not in BareMixinState.inherited_vars\n    assert \"_bare_mixin\" not in BareMixinState.base_vars\n\n    assert BareMixinState.get_parent_state() == State\n    assert BareMixinState.get_root_state() == State\n\n    assert \"_bare_mixin\" not in ChildBareMixinState.inherited_vars\n    assert \"_bare_mixin\" not in ChildBareMixinState.base_vars\n\n    assert ChildBareMixinState.get_parent_state() == BareMixinState\n    assert ChildBareMixinState.get_root_state() == State\n\n\ndef test_mixin_event_handler_preserves_event_actions() -> None:\n    \"\"\"Test that event_actions from @rx.event decorator are preserved when inherited from mixins.\"\"\"\n\n    class EventActionsMixin(BaseState, mixin=True):\n        @rx.event(prevent_default=True, stop_propagation=True)\n        def handle_with_actions(self):\n            pass\n\n    class UsesEventActionsMixin(EventActionsMixin, State):\n        pass\n\n    handler = UsesEventActionsMixin.handle_with_actions\n    assert handler.event_actions == {\"preventDefault\": True, \"stopPropagation\": True}\n\n\ndef test_assignment_to_undeclared_vars():\n    \"\"\"Test that an attribute error is thrown when undeclared vars are set.\"\"\"\n\n    class State(BaseState):\n        val: str\n        _val: str\n        __val: str  # pyright: ignore [reportGeneralTypeIssues]\n\n        def handle_supported_regular_vars(self):\n            self.val = \"no underscore\"\n            self._val = \"single leading underscore\"\n            self.__val = \"double leading underscore\"\n\n        def handle_regular_var(self):\n            self.num = 5\n\n        def handle_backend_var(self):\n            self._num = 5\n\n        def handle_non_var(self):\n            self.__num = 5\n\n    class Substate(State):\n        def handle_var(self):\n            self.value = 20\n\n    state = State()  # pyright: ignore [reportCallIssue]\n    sub_state = Substate()  # pyright: ignore [reportCallIssue]\n\n    with pytest.raises(SetUndefinedStateVarError):\n        state.handle_regular_var()\n\n    with pytest.raises(SetUndefinedStateVarError):\n        sub_state.handle_var()\n\n    with pytest.raises(SetUndefinedStateVarError):\n        state.handle_backend_var()\n\n    state.handle_supported_regular_vars()\n    state.handle_non_var()\n\n\n@pytest.mark.asyncio\nasync def test_deserialize_gc_state_disk(token):\n    \"\"\"Test that a state can be deserialized from disk with a grandchild state.\n\n    Args:\n        token: A token.\n    \"\"\"\n\n    class Root(BaseState):\n        pass\n\n    class State(Root):\n        num: int = 42\n\n    class Child(State):\n        foo: str = \"bar\"\n\n    dsm = StateManagerDisk(state=Root)\n    async with dsm.modify_state(token) as root:\n        s = await root.get_state(State)\n        s.num += 1\n        c = await root.get_state(Child)\n        assert s._get_was_touched()\n        assert not c._get_was_touched()\n    await dsm.close()\n\n    dsm2 = StateManagerDisk(state=Root)\n    root = await dsm2.get_state(token)\n    s = await root.get_state(State)\n    assert s.num == 43\n    c = await root.get_state(Child)\n    assert c.foo == \"bar\"\n    await dsm2.close()\n\n\nclass Obj(Base):\n    \"\"\"A object containing a callable for testing fallback pickle.\"\"\"\n\n    _f: Callable\n\n\ndef test_fallback_pickle():\n    \"\"\"Test that state serialization will fall back to dill.\"\"\"\n\n    class DillState(BaseState):\n        _o: Obj | None = None\n        _f: Callable | None = None\n        _g: Any = None\n\n    state = DillState(_reflex_internal_init=True)  # pyright: ignore [reportCallIssue]\n    state._o = Obj(_f=lambda: 42)\n    state._f = lambda: 420\n\n    pk = state._serialize()\n\n    unpickled_state = BaseState._deserialize(pk)\n    assert isinstance(unpickled_state, DillState)\n    assert unpickled_state._f is not None\n    assert unpickled_state._f() == 420\n    assert unpickled_state._o is not None\n    assert unpickled_state._o._f() == 42\n\n    # Threading locks are unpicklable normally, and raise TypeError instead of PicklingError.\n    state2 = DillState(_reflex_internal_init=True)  # pyright: ignore [reportCallIssue]\n    state2._g = threading.Lock()\n    pk2 = state2._serialize()\n    unpickled_state2 = BaseState._deserialize(pk2)\n    assert isinstance(unpickled_state2, DillState)\n    assert isinstance(unpickled_state2._g, type(threading.Lock()))\n\n    # Some object, like generator, are still unpicklable with dill.\n    state3 = DillState(_reflex_internal_init=True)  # pyright: ignore [reportCallIssue]\n    state3._g = (i for i in range(10))\n\n    with pytest.raises(StateSerializationError):\n        _ = state3._serialize()\n\n\ndef test_typed_state() -> None:\n    class TypedState(rx.State):\n        field: rx.Field[str] = rx.field(\"\")\n\n    _ = TypedState(field=\"str\")\n\n\nclass ModelV1(BaseModelV1):\n    \"\"\"A pydantic BaseModel v1.\"\"\"\n\n    foo: str = \"bar\"\n\n    def set_foo(self, val: str):\n        \"\"\"Set the attribute foo.\n\n        Args:\n            val: The value to set.\n        \"\"\"\n        self.foo = val\n\n    def double_foo(self) -> str:\n        \"\"\"Concatenate foo with foo.\n\n        Returns:\n            foo + foo\n        \"\"\"\n        return self.foo + self.foo\n\n\nclass ModelV2(BaseModelV2):\n    \"\"\"A pydantic BaseModel v2.\"\"\"\n\n    foo: str = \"bar\"\n\n    def set_foo(self, val: str):\n        \"\"\"Set the attribute foo.\n\n        Args:\n            val: The value to set.\n        \"\"\"\n        self.foo = val\n\n    def double_foo(self) -> str:\n        \"\"\"Concatenate foo with foo.\n\n        Returns:\n            foo + foo\n        \"\"\"\n        return self.foo + self.foo\n\n\nclass PydanticState(rx.State):\n    \"\"\"A state with pydantic BaseModel vars.\"\"\"\n\n    v1: ModelV1 = ModelV1()\n    v2: ModelV2 = ModelV2()\n    dc: ModelDC = ModelDC()\n\n\ndef test_mutable_models():\n    \"\"\"Test that dataclass and pydantic BaseModel v1 and v2 use dep tracking.\"\"\"\n    state = PydanticState()\n    assert isinstance(state.v1, MutableProxy)\n    state.v1.foo = \"baz\"\n    assert state.dirty_vars == {\"v1\"}\n    state.dirty_vars.clear()\n    state.v1.set_foo(\"quuc\")\n    assert state.dirty_vars == {\"v1\"}\n    state.dirty_vars.clear()\n    assert state.v1.double_foo() == \"quucquuc\"\n    assert state.dirty_vars == set()\n    state.v1.copy(update={\"foo\": \"larp\"})\n    assert state.dirty_vars == set()\n\n    assert isinstance(state.v2, MutableProxy)\n    state.v2.foo = \"baz\"\n    assert state.dirty_vars == {\"v2\"}\n    state.dirty_vars.clear()\n    state.v2.set_foo(\"quuc\")\n    assert state.dirty_vars == {\"v2\"}\n    state.dirty_vars.clear()\n    assert state.v2.double_foo() == \"quucquuc\"\n    assert state.dirty_vars == set()\n    state.v2.model_copy(update={\"foo\": \"larp\"})\n    assert state.dirty_vars == set()\n\n    assert isinstance(state.dc, MutableProxy)\n    state.dc.foo = \"baz\"\n    assert state.dirty_vars == {\"dc\"}\n    state.dirty_vars.clear()\n    assert state.dirty_vars == set()\n    state.dc.set_foo(\"quuc\")\n    assert state.dirty_vars == {\"dc\"}\n    state.dirty_vars.clear()\n    assert state.dirty_vars == set()\n    assert state.dc.double_foo() == \"quucquuc\"\n    assert state.dirty_vars == set()\n    state.dc.ls.append({\"hi\": \"reflex\"})\n    assert state.dirty_vars == {\"dc\"}\n    state.dirty_vars.clear()\n    assert state.dirty_vars == set()\n    assert dataclasses.asdict(state.dc) == {\"foo\": \"quuc\", \"ls\": [{\"hi\": \"reflex\"}]}\n    assert dataclasses.astuple(state.dc) == (\"quuc\", [{\"hi\": \"reflex\"}])\n    # creating a new instance shouldn't mark the state dirty\n    assert dataclasses.replace(state.dc, foo=\"larp\") == ModelDC(\n        foo=\"larp\", ls=[{\"hi\": \"reflex\"}]\n    )\n    assert state.dirty_vars == set()\n    dc_copy = state.dc.copy()\n    assert dc_copy == state.dc\n    assert dc_copy is not state.dc\n    dc_copy.foo = \"new_foo\"\n    assert state.dirty_vars == set()\n    dc_copy.append_to_ls({\"new\": \"item\"})\n    assert state.dirty_vars == set()\n    state.dc.append_to_ls({\"new\": \"item\"})\n    assert state.dirty_vars == {\"dc\"}\n    state.dirty_vars.clear()\n\n    dc_from_dict = state.dc.from_dict({\"foo\": \"from_dict\", \"ls\": []})\n    assert dc_from_dict == ModelDC(foo=\"from_dict\", ls=[])\n    assert state.dirty_vars == set()\n\n\ndef test_dict_and_get_delta():\n    class GetValueState(rx.State):\n        foo: str = \"FOO\"\n        bar: str = \"BAR\"\n\n    state = GetValueState()\n\n    assert state.dict() == {\n        state.get_full_name(): {\n            \"foo\" + FIELD_MARKER: \"FOO\",\n            \"bar\" + FIELD_MARKER: \"BAR\",\n        }\n    }\n    assert state.get_delta() == {}\n\n    state.bar = \"foo\"\n\n    assert state.dict() == {\n        state.get_full_name(): {\n            \"foo\" + FIELD_MARKER: \"FOO\",\n            \"bar\" + FIELD_MARKER: \"foo\",\n        }\n    }\n    assert state.get_delta() == {\n        state.get_full_name(): {\n            \"bar\" + FIELD_MARKER: \"foo\",\n        }\n    }\n\n\n@pytest.mark.parametrize(\n    (\"key_factory\", \"expected_result\", \"should_raise\"),\n    [\n        # Valid string keys\n        (lambda state: \"foo\", \"FOO\", False),\n        (lambda state: \"bar\", \"BAR\", False),\n        # MutableProxy keys (deprecated but supported)\n        (\n            lambda state: MutableProxy(\n                wrapped=\"test_wrapped_value\", state=state, field_name=\"test_field\"\n            ),\n            \"test_wrapped_value\",\n            False,\n        ),\n        (\n            lambda state: MutableProxy(\n                wrapped=42, state=state, field_name=\"test_field\"\n            ),\n            42,\n            False,\n        ),\n        # Invalid key types\n        (lambda state: 123, None, True),\n        (lambda state: [], None, True),\n        (lambda state: {}, None, True),\n        (lambda state: None, None, True),\n    ],\n)\ndef test_get_value(key_factory, expected_result, should_raise):\n    \"\"\"Test the get_value method directly with various key types.\n\n    Args:\n        key_factory: Factory function to create the key for testing.\n        expected_result: The expected return value from get_value.\n        should_raise: Whether the test should expect a TypeError.\n    \"\"\"\n\n    class GetValueState(rx.State):\n        \"\"\"Test state class for get_value testing.\"\"\"\n\n        foo: str = \"FOO\"\n        bar: str = \"BAR\"\n\n    state = GetValueState()\n    key = key_factory(state)\n\n    if should_raise:\n        with pytest.raises(TypeError, match=\"Invalid key type\"):\n            state.get_value(key)\n    else:\n        result = state.get_value(key)\n        assert result == expected_result\n\n        # Verify dirty state is not affected\n        initial_dirty_vars = copy.copy(state.dirty_vars)\n        state.get_value(key)\n        assert state.dirty_vars == initial_dirty_vars\n\n\ndef test_init_mixin() -> None:\n    \"\"\"Ensure that State mixins can not be instantiated directly.\"\"\"\n\n    class Mixin(BaseState, mixin=True):\n        pass\n\n    with pytest.raises(ReflexRuntimeError):\n        Mixin()\n\n    class SubMixin(Mixin, mixin=True):\n        pass\n\n    with pytest.raises(ReflexRuntimeError):\n        SubMixin()\n\n\nclass UpcastState(rx.State):\n    \"\"\"A state for testing upcasting.\"\"\"\n\n    passed: bool = False\n\n    def rx_base(self, o: Object):  # noqa: D102\n        assert isinstance(o, Object)\n        self.passed = True\n\n    def rx_base_or_none(self, o: Object | None):  # noqa: D102\n        if o is not None:\n            assert isinstance(o, Object)\n        self.passed = True\n\n    def rx_basemodelv1(self, m: ModelV1):  # noqa: D102\n        assert isinstance(m, ModelV1)\n        self.passed = True\n\n    def rx_basemodelv2(self, m: ModelV2):  # noqa: D102\n        assert isinstance(m, ModelV2)\n        self.passed = True\n\n    def rx_dataclass(self, dc: ModelDC):  # noqa: D102\n        assert isinstance(dc, ModelDC)\n        self.passed = True\n\n    def py_set(self, s: set):  # noqa: D102\n        assert isinstance(s, set)\n        self.passed = True\n\n    def py_Set(self, s: set):  # noqa: D102\n        assert isinstance(s, set)\n        self.passed = True\n\n    def py_tuple(self, t: tuple):  # noqa: D102\n        assert isinstance(t, tuple)\n        self.passed = True\n\n    def py_Tuple(self, t: tuple):  # noqa: D102\n        assert isinstance(t, tuple)\n        self.passed = True\n\n    def py_dict(self, d: dict[str, str]):  # noqa: D102\n        assert isinstance(d, dict)\n        self.passed = True\n\n    def py_list(self, ls: list[str]):  # noqa: D102\n        assert isinstance(ls, list)\n        self.passed = True\n\n    def py_Any(self, a: Any):  # noqa: D102\n        assert isinstance(a, list)\n        self.passed = True\n\n    def py_unresolvable(self, u: Unresolvable):  # noqa: D102, F821 # pyright: ignore [reportUndefinedVariable]\n        assert isinstance(u, list)\n        self.passed = True\n\n\n@pytest.mark.asyncio\n@pytest.mark.usefixtures(\"mock_app_simple\")\n@pytest.mark.parametrize(\n    (\"handler\", \"payload\"),\n    [\n        (UpcastState.rx_base, {\"o\": {\"foo\": \"bar\"}}),\n        (UpcastState.rx_base_or_none, {\"o\": {\"foo\": \"bar\"}}),\n        (UpcastState.rx_base_or_none, {\"o\": None}),\n        (UpcastState.rx_basemodelv1, {\"m\": {\"foo\": \"bar\"}}),\n        (UpcastState.rx_basemodelv2, {\"m\": {\"foo\": \"bar\"}}),\n        (UpcastState.rx_dataclass, {\"dc\": {\"foo\": \"bar\"}}),\n        (UpcastState.py_set, {\"s\": [\"foo\", \"foo\"]}),\n        (UpcastState.py_Set, {\"s\": [\"foo\", \"foo\"]}),\n        (UpcastState.py_tuple, {\"t\": [\"foo\", \"foo\"]}),\n        (UpcastState.py_Tuple, {\"t\": [\"foo\", \"foo\"]}),\n        (UpcastState.py_dict, {\"d\": {\"foo\": \"bar\"}}),\n        (UpcastState.py_list, {\"ls\": [\"foo\", \"foo\"]}),\n        (UpcastState.py_Any, {\"a\": [\"foo\"]}),\n        (UpcastState.py_unresolvable, {\"u\": [\"foo\"]}),\n    ],\n)\nasync def test_upcast_event_handler_arg(handler, payload):\n    \"\"\"Test that upcast event handler args work correctly.\n\n    Args:\n        handler: The handler to test.\n        payload: The payload to test.\n    \"\"\"\n    state = UpcastState()\n    async for update in state._process_event(handler, state, payload):\n        assert update.delta == {\n            UpcastState.get_full_name(): {\"passed\" + FIELD_MARKER: True}\n        }\n\n\n@pytest.mark.asyncio\nasync def test_get_var_value(state_manager: StateManager, substate_token: str):\n    \"\"\"Test that get_var_value works correctly.\n\n    Args:\n        state_manager: The state manager to use.\n        substate_token: Token for the substate used by state_manager.\n    \"\"\"\n    state = await state_manager.get_state(substate_token)\n\n    # State Var from same state\n    assert await state.get_var_value(TestState.num1) == 0\n    state.num1 = 42\n    assert await state.get_var_value(TestState.num1) == 42\n\n    # State Var from another state\n    child_state = await state.get_state(ChildState)\n    assert await state.get_var_value(ChildState.count) == 23\n    child_state.count = 66\n    assert await state.get_var_value(ChildState.count) == 66\n\n    # LiteralVar with known value\n    assert await state.get_var_value(rx.Var.create([1, 2, 3])) == [1, 2, 3]\n\n    # Generic Var with no state\n    with pytest.raises(UnretrievableVarValueError):\n        await state.get_var_value(rx.Var(\"undefined\"))\n\n    # ObjectVar\n    assert await state.get_var_value(TestState.mapping) == {\n        \"a\": [1, 2, 3],\n        \"b\": [4, 5, 6],\n    }\n\n\n@pytest.mark.asyncio\nasync def test_async_computed_var_get_state(mock_app: rx.App, token: str):\n    \"\"\"A test where an async computed var depends on a var in another state.\n\n    Args:\n        mock_app: An app that will be returned by `get_app()`\n        token: A token.\n    \"\"\"\n\n    class Parent(BaseState):\n        \"\"\"A root state like rx.State.\"\"\"\n\n        parent_var: int = 0\n\n    class Child2(Parent):\n        \"\"\"An unconnected child state.\"\"\"\n\n    class Child3(Parent):\n        \"\"\"A child state with a computed var causing it to be pre-fetched.\n\n        If child3_var gets set to a value, and `get_state` erroneously\n        re-fetches it from redis, the value will be lost.\n        \"\"\"\n\n        child3_var: int = 0\n\n        @rx.var(cache=True)\n        def v(self) -> int:\n            return self.child3_var\n\n    class Child(Parent):\n        \"\"\"A state simulating UpdateVarsInternalState.\"\"\"\n\n        @rx.var(cache=True)\n        async def v(self) -> int:\n            p = await self.get_state(Parent)\n            child3 = await self.get_state(Child3)\n            return child3.child3_var + p.parent_var\n\n    mock_app.state_manager.state = mock_app._state = Parent\n\n    # Get the top level state via unconnected sibling.\n    root = await mock_app.state_manager.get_state(_substate_key(token, Child))\n    # Set value in parent_var to assert it does not get refetched later.\n    root.parent_var = 1\n\n    if isinstance(mock_app.state_manager, StateManagerRedis):\n        # When redis is used, only states with uncached computed vars are pre-fetched.\n        assert Child2.get_name() not in root.substates\n        assert Child3.get_name() not in root.substates\n\n    # Get the unconnected sibling state, which will be used to `get_state` other instances.\n    child = root.get_substate(Child.get_full_name().split(\".\"))\n    assert isinstance(child, Child)\n\n    # Get an uncached child state.\n    child2 = await child.get_state(Child2)\n    assert child2.parent_var == 1\n\n    # Set value on already-cached Child3 state (prefetched because it has a Computed Var).\n    child3 = await child.get_state(Child3)\n    child3.child3_var = 1\n\n    assert await child.v == 2\n    assert await child.v == 2\n    root.parent_var = 2\n    assert await child.v == 3\n\n\nclass Table(rx.ComponentState):\n    \"\"\"A table state.\"\"\"\n\n    _data: ClassVar[Var]\n\n    @rx.var(cache=True, auto_deps=False)\n    async def data(self) -> list[dict[str, Any]]:\n        \"\"\"Computed var over the given rows.\n\n        Returns:\n            The data rows.\n        \"\"\"\n        return await self.get_var_value(self._data)\n\n    @rx.var\n    async def foo(self) -> list[dict[str, Any]]:\n        \"\"\"Another computed var that depends on data in this state.\n\n        Returns:\n            The data rows.\n        \"\"\"\n        return await self.data\n\n    @classmethod\n    def get_component(cls, data: Var) -> rx.Component:\n        \"\"\"Get the component for the table.\n\n        Args:\n            data: The data var.\n\n        Returns:\n            The component.\n        \"\"\"\n        cls._data = data\n        cls.computed_vars[\"data\"].add_dependency(cls, data)\n        return rx.foreach(data, lambda d: rx.text(d.to_string()))\n\n\n@pytest.mark.asyncio\nasync def test_async_computed_var_get_var_value(mock_app: rx.App, token: str):\n    \"\"\"A test where an async computed var depends on a var in another state.\n\n    Args:\n        mock_app: An app that will be returned by `get_app()`\n        token: A token.\n    \"\"\"\n\n    class OtherState(rx.State):\n        \"\"\"A state with a var.\"\"\"\n\n        data: list[dict[str, Any]] = [{\"foo\": \"bar\"}]\n\n    mock_app.state_manager.state = mock_app._state = rx.State\n    comp = Table.create(data=OtherState.data)\n    state = await mock_app.state_manager.get_state(_substate_key(token, OtherState))\n    other_state = await state.get_state(OtherState)\n    assert comp.State is not None\n    # The state should have been pre-cached from the dependency.\n    assert comp.State.get_name() in state.substates\n    comp_state = await state.get_state(comp.State)\n    assert comp_state.dirty_vars == set()\n\n    other_state.data.append({\"foo\": \"baz\"})\n    assert \"data\" in comp_state.dirty_vars\n    assert \"foo\" in comp_state.dirty_vars\n\n\ndef test_computed_var_mutability() -> None:\n    class CvMixin(rx.State, mixin=True):\n        @rx.var(cache=True, deps=[\"hi\"])\n        def cv(self) -> int:\n            return 42\n\n    class FirstCvState(CvMixin, rx.State):\n        pass\n\n    class SecondCvState(CvMixin, rx.State):\n        pass\n\n    first_cv = FirstCvState.computed_vars[\"cv\"]\n    second_cv = SecondCvState.computed_vars[\"cv\"]\n\n    assert first_cv is not second_cv\n    assert first_cv._static_deps is not second_cv._static_deps\n\n\n@pytest.mark.asyncio\nasync def test_add_dependency_get_state_regression(mock_app: rx.App, token: str):\n    \"\"\"Ensure that a state class can be fetched separately when it's is explicit dep.\"\"\"\n\n    class DataState(rx.State):\n        \"\"\"A state with a var.\"\"\"\n\n        data: Field[list[int]] = field(default_factory=lambda: [1, 2, 3])\n\n    class StatsState(rx.State):\n        \"\"\"A state with a computed var depending on DataState.\"\"\"\n\n        @rx.var(cache=True)\n        async def total(self) -> int:\n            data_state = await self.get_state(DataState)\n            return sum(data_state.data)\n\n    StatsState.computed_vars[\"total\"].add_dependency(StatsState, DataState.data)\n\n    class OtherState(rx.State):\n        \"\"\"A state that gets DataState.\"\"\"\n\n        @rx.event\n        async def fetch_data_state(self) -> None:\n            print(await self.get_state(DataState))\n\n    mock_app.state_manager.state = mock_app._state = rx.State\n    state = await mock_app.state_manager.get_state(_substate_key(token, OtherState))\n    other_state = await state.get_state(OtherState)\n    await other_state.fetch_data_state()  # Should not raise exception.\n\n\nclass MutableProxyState(BaseState):\n    \"\"\"A test state with a MutableProxy var.\"\"\"\n\n    data: dict[str, list[int]] = {\"a\": [1], \"b\": [2]}\n\n\n@pytest.mark.asyncio\nasync def test_rebind_mutable_proxy(mock_app: rx.App, token: str) -> None:\n    \"\"\"Test that previously bound MutableProxy instances can be rebound correctly.\"\"\"\n    mock_app.state_manager.state = mock_app._state = MutableProxyState\n    async with mock_app.state_manager.modify_state(\n        _substate_key(token, MutableProxyState)\n    ) as state:\n        state.router = RouterData.from_router_data({\n            \"query\": {},\n            \"token\": token,\n            \"sid\": \"test_sid\",\n        })\n        assert isinstance(state, MutableProxyState)\n        assert isinstance(state.data, MutableProxy)\n        assert not isinstance(state.data, ImmutableMutableProxy)\n        state_proxy = StateProxy(state)\n        assert isinstance(state_proxy.data, ImmutableMutableProxy)\n    async with state_proxy:\n        # This assigns an ImmutableMutableProxy to data[\"a\"].\n        state_proxy.data[\"a\"] = state_proxy.data[\"b\"]\n    assert isinstance(state_proxy.data[\"a\"], ImmutableMutableProxy)\n    assert state_proxy.data[\"a\"] is not state_proxy.data[\"b\"]\n    assert state_proxy.data[\"a\"].__wrapped__ is state_proxy.data[\"b\"].__wrapped__\n\n    # Rebinding with a non-proxy should return a MutableProxy object (not ImmutableMutableProxy).\n    assert isinstance(state_proxy.__wrapped__.data[\"a\"], MutableProxy)\n    assert not isinstance(state_proxy.__wrapped__.data[\"a\"], ImmutableMutableProxy)\n\n    # Flush any oplock.\n    await mock_app.state_manager.close()\n\n    new_state_proxy = StateProxy(state)\n    assert state_proxy is not new_state_proxy\n    assert new_state_proxy.data[\"a\"]._self_state is new_state_proxy\n    assert state_proxy.data[\"a\"]._self_state is state_proxy\n    assert state_proxy.__wrapped__.data[\"a\"]._self_state is state_proxy.__wrapped__\n\n    async with state_proxy:\n        state_proxy.data[\"a\"].append(3)\n\n    async with mock_app.state_manager.modify_state(\n        _substate_key(token, MutableProxyState)\n    ) as state:\n        assert isinstance(state, MutableProxyState)\n        assert state.data[\"a\"] == [2, 3]\n        # Object identity persists across serialization, so data[\"b\"] is also mutated.\n        assert state.data[\"b\"] == [2, 3]\n"
  },
  {
    "path": "tests/units/test_state_tree.py",
    "content": "\"\"\"Specialized test for a larger state tree.\"\"\"\n\nfrom collections.abc import AsyncGenerator\n\nimport pytest\nimport pytest_asyncio\n\nimport reflex as rx\nfrom reflex.constants.state import FIELD_MARKER\nfrom reflex.istate.manager.redis import StateManagerRedis\nfrom reflex.state import BaseState, StateManager, _substate_key\n\n\nclass Root(BaseState):\n    \"\"\"Root of the state tree.\"\"\"\n\n    root: int\n\n\nclass TreeA(Root):\n    \"\"\"TreeA is a child of Root.\"\"\"\n\n    a: int\n\n\nclass SubA_A(TreeA):\n    \"\"\"SubA_A is a child of TreeA.\"\"\"\n\n    sub_a_a: int\n\n\nclass SubA_A_A(SubA_A):\n    \"\"\"SubA_A_A is a child of SubA_A.\"\"\"\n\n    sub_a_a_a: int\n\n\nclass SubA_A_A_A(SubA_A_A):\n    \"\"\"SubA_A_A_A is a child of SubA_A_A.\"\"\"\n\n    sub_a_a_a_a: int\n\n\nclass SubA_A_A_B(SubA_A_A):\n    \"\"\"SubA_A_A_B is a child of SubA_A_A.\"\"\"\n\n    @rx.var\n    def sub_a_a_a_cached(self) -> int:\n        \"\"\"A cached var.\n\n        Returns:\n            The value of sub_a_a_a + 1\n        \"\"\"\n        return self.sub_a_a_a + 1\n\n\nclass SubA_A_A_C(SubA_A_A):\n    \"\"\"SubA_A_A_C is a child of SubA_A_A.\"\"\"\n\n    sub_a_a_a_c: int\n\n\nclass SubA_A_B(SubA_A):\n    \"\"\"SubA_A_B is a child of SubA_A.\"\"\"\n\n    sub_a_a_b: int\n\n\nclass SubA_B(TreeA):\n    \"\"\"SubA_B is a child of TreeA.\"\"\"\n\n    sub_a_b: int\n\n\nclass TreeB(Root):\n    \"\"\"TreeB is a child of Root.\"\"\"\n\n    b: int\n\n\nclass SubB_A(TreeB):\n    \"\"\"SubB_A is a child of TreeB.\"\"\"\n\n    sub_b_a: int\n\n\nclass SubB_B(TreeB):\n    \"\"\"SubB_B is a child of TreeB.\"\"\"\n\n    sub_b_b: int\n\n\nclass SubB_C(TreeB):\n    \"\"\"SubB_C is a child of TreeB.\"\"\"\n\n    sub_b_c: int\n\n\nclass SubB_C_A(SubB_C):\n    \"\"\"SubB_C_A is a child of SubB_C.\"\"\"\n\n    sub_b_c_a: int\n\n\nclass TreeC(Root):\n    \"\"\"TreeC is a child of Root.\"\"\"\n\n    c: int\n\n\nclass SubC_A(TreeC):\n    \"\"\"SubC_A is a child of TreeC.\"\"\"\n\n    sub_c_a: int\n\n\nclass TreeD(Root):\n    \"\"\"TreeD is a child of Root.\"\"\"\n\n    d: int\n\n    @rx.var(cache=False)\n    def d_var(self) -> int:\n        \"\"\"A computed var.\n\n        Returns:\n            The value of d + 1\n        \"\"\"\n        return self.d + 1\n\n\nclass TreeE(Root):\n    \"\"\"TreeE is a child of Root.\"\"\"\n\n    e: int\n\n\nclass SubE_A(TreeE):\n    \"\"\"SubE_A is a child of TreeE.\"\"\"\n\n    sub_e_a: int\n\n\nclass SubE_A_A(SubE_A):\n    \"\"\"SubE_A_A is a child of SubE_A.\"\"\"\n\n    sub_e_a_a: int\n\n\nclass SubE_A_A_A(SubE_A_A):\n    \"\"\"SubE_A_A_A is a child of SubE_A_A.\"\"\"\n\n    sub_e_a_a_a: int\n\n\nclass SubE_A_A_A_A(SubE_A_A_A):\n    \"\"\"SubE_A_A_A_A is a child of SubE_A_A_A.\"\"\"\n\n    sub_e_a_a_a_a: int\n\n    @rx.var(cache=False)\n    def sub_e_a_a_a_a_var(self) -> int:\n        \"\"\"A computed var.\n\n        Returns:\n            The value of sub_e_a_a_a_a + 1\n        \"\"\"\n        return self.sub_e_a_a_a + 1\n\n\nclass SubE_A_A_A_B(SubE_A_A_A):\n    \"\"\"SubE_A_A_A_B is a child of SubE_A_A_A.\"\"\"\n\n    sub_e_a_a_a_b: int\n\n\nclass SubE_A_A_A_C(SubE_A_A_A):\n    \"\"\"SubE_A_A_A_C is a child of SubE_A_A_A.\"\"\"\n\n    sub_e_a_a_a_c: int\n\n\nclass SubE_A_A_A_D(SubE_A_A_A):\n    \"\"\"SubE_A_A_A_D is a child of SubE_A_A_A.\"\"\"\n\n    sub_e_a_a_a_d: int\n\n    @rx.var\n    def sub_e_a_a_a_d_var(self) -> int:\n        \"\"\"A computed var.\n\n        Returns:\n            The value of sub_e_a_a_a_a + 1\n        \"\"\"\n        return self.sub_e_a_a_a + 1\n\n\nALWAYS_COMPUTED_VARS = {\n    TreeD.get_full_name(): {\"d_var\" + FIELD_MARKER: 1},\n    SubE_A_A_A_A.get_full_name(): {\"sub_e_a_a_a_a_var\" + FIELD_MARKER: 1},\n}\n\nALWAYS_COMPUTED_DICT_KEYS = [\n    Root.get_full_name(),\n    TreeD.get_full_name(),\n    TreeE.get_full_name(),\n    SubE_A.get_full_name(),\n    SubE_A_A.get_full_name(),\n    SubE_A_A_A.get_full_name(),\n    SubE_A_A_A_A.get_full_name(),\n    SubE_A_A_A_D.get_full_name(),\n]\n\n\n@pytest_asyncio.fixture(loop_scope=\"function\", scope=\"function\")\nasync def state_manager_redis(\n    app_module_mock,\n) -> AsyncGenerator[StateManager, None]:\n    \"\"\"Instance of state manager for redis only.\n\n    Args:\n        app_module_mock: The app module mock fixture.\n\n    Yields:\n        A state manager instance\n    \"\"\"\n    app_module_mock.app = rx.App(_state=Root)\n    state_manager = app_module_mock.app.state_manager\n\n    if not isinstance(state_manager, StateManagerRedis):\n        pytest.skip(\"Test requires redis\")\n\n    yield state_manager\n\n    await state_manager.close()\n\n\n@pytest.mark.asyncio\n@pytest.mark.parametrize(\n    (\"substate_cls\", \"exp_root_substates\", \"exp_root_dict_keys\"),\n    [\n        (\n            Root,\n            [\n                TreeA.get_name(),\n                TreeB.get_name(),\n                TreeC.get_name(),\n                TreeD.get_name(),\n                TreeE.get_name(),\n            ],\n            [\n                TreeA.get_full_name(),\n                SubA_A.get_full_name(),\n                SubA_A_A.get_full_name(),\n                SubA_A_A_A.get_full_name(),\n                SubA_A_A_B.get_full_name(),\n                SubA_A_A_C.get_full_name(),\n                SubA_A_B.get_full_name(),\n                SubA_B.get_full_name(),\n                TreeB.get_full_name(),\n                SubB_A.get_full_name(),\n                SubB_B.get_full_name(),\n                SubB_C.get_full_name(),\n                SubB_C_A.get_full_name(),\n                TreeC.get_full_name(),\n                SubC_A.get_full_name(),\n                SubE_A_A_A_B.get_full_name(),\n                SubE_A_A_A_C.get_full_name(),\n                *ALWAYS_COMPUTED_DICT_KEYS,\n            ],\n        ),\n        (\n            TreeA,\n            (TreeA.get_name(), TreeD.get_name(), TreeE.get_name()),\n            [\n                TreeA.get_full_name(),\n                SubA_A.get_full_name(),\n                SubA_A_A.get_full_name(),\n                SubA_A_A_A.get_full_name(),\n                SubA_A_A_B.get_full_name(),\n                SubA_A_A_C.get_full_name(),\n                SubA_A_B.get_full_name(),\n                SubA_B.get_full_name(),\n                *ALWAYS_COMPUTED_DICT_KEYS,\n            ],\n        ),\n        (\n            SubA_A_A_A,\n            [TreeA.get_name(), TreeD.get_name(), TreeE.get_name()],\n            [\n                TreeA.get_full_name(),\n                SubA_A.get_full_name(),\n                SubA_A_A.get_full_name(),\n                SubA_A_A_A.get_full_name(),\n                SubA_A_A_B.get_full_name(),  # Cached var dep\n                *ALWAYS_COMPUTED_DICT_KEYS,\n            ],\n        ),\n        (\n            TreeB,\n            [TreeB.get_name(), TreeD.get_name(), TreeE.get_name()],\n            [\n                TreeB.get_full_name(),\n                SubB_A.get_full_name(),\n                SubB_B.get_full_name(),\n                SubB_C.get_full_name(),\n                SubB_C_A.get_full_name(),\n                *ALWAYS_COMPUTED_DICT_KEYS,\n            ],\n        ),\n        (\n            SubB_B,\n            [TreeB.get_name(), TreeD.get_name(), TreeE.get_name()],\n            [\n                TreeB.get_full_name(),\n                SubB_B.get_full_name(),\n                *ALWAYS_COMPUTED_DICT_KEYS,\n            ],\n        ),\n        (\n            SubB_C_A,\n            [TreeB.get_name(), TreeD.get_name(), TreeE.get_name()],\n            [\n                TreeB.get_full_name(),\n                SubB_C.get_full_name(),\n                SubB_C_A.get_full_name(),\n                *ALWAYS_COMPUTED_DICT_KEYS,\n            ],\n        ),\n        (\n            TreeC,\n            [TreeC.get_name(), TreeD.get_name(), TreeE.get_name()],\n            [\n                TreeC.get_full_name(),\n                SubC_A.get_full_name(),\n                *ALWAYS_COMPUTED_DICT_KEYS,\n            ],\n        ),\n        (\n            TreeD,\n            [TreeD.get_name(), TreeE.get_name()],\n            [\n                *ALWAYS_COMPUTED_DICT_KEYS,\n            ],\n        ),\n        (\n            TreeE,\n            [TreeE.get_name(), TreeD.get_name()],\n            [\n                # Extra siblings of computed var included now.\n                SubE_A_A_A_B.get_full_name(),\n                SubE_A_A_A_C.get_full_name(),\n                *ALWAYS_COMPUTED_DICT_KEYS,\n            ],\n        ),\n    ],\n)\nasync def test_get_state_tree(\n    state_manager_redis,\n    token,\n    substate_cls,\n    exp_root_substates,\n    exp_root_dict_keys,\n):\n    \"\"\"Test getting state trees and assert on which branches are retrieved.\n\n    Args:\n        state_manager_redis: The state manager redis fixture.\n        token: The token fixture.\n        substate_cls: The substate class to retrieve.\n        exp_root_substates: The expected substates of the root state.\n        exp_root_dict_keys: The expected keys of the root state dict.\n    \"\"\"\n    state = await state_manager_redis.get_state(_substate_key(token, substate_cls))\n    assert isinstance(state, Root)\n    assert sorted(state.substates) == sorted(exp_root_substates)\n\n    # Only computed vars should be returned\n    assert state.get_delta() == ALWAYS_COMPUTED_VARS\n\n    # All of TreeA, TreeD, and TreeE substates should be in the dict\n    assert sorted(state.dict()) == sorted(exp_root_dict_keys)\n"
  },
  {
    "path": "tests/units/test_style.py",
    "content": "from __future__ import annotations\n\nfrom typing import Any\n\nimport pytest\n\nimport reflex as rx\nfrom reflex import style\nfrom reflex.components.component import evaluate_style_namespaces\nfrom reflex.style import Style\nfrom reflex.utils.exceptions import ReflexError\nfrom reflex.vars import VarData\nfrom reflex.vars.base import LiteralVar, Var\n\nstyle_var = rx.Var.create({\"height\": \"42px\"})\n\ntest_style = [\n    ({\"a\": 1}, {\"a\": 1}),\n    ({\"&\": style_var}, {\"&\": {\"height\": \"42px\"}}),\n    (\n        {\"&\": rx.cond(style_var, style_var, {})},\n        {\"&\": rx.cond(style_var, style_var, {})},\n    ),\n    ({\"a\": LiteralVar.create(\"abc\")}, {\"a\": \"abc\"}),\n    ({\"test_case\": 1}, {\"testCase\": 1}),\n    ({\"test_case\": {\"a\": 1}}, {\"test_case\": {\"a\": 1}}),\n    ({\":test_case\": {\"a\": 1}}, {\":test_case\": {\"a\": 1}}),\n    ({\"::test_case\": {\"a\": 1}}, {\"::test_case\": {\"a\": 1}}),\n    (\n        {\"::-webkit-scrollbar\": {\"display\": \"none\"}},\n        {\"::-webkit-scrollbar\": {\"display\": \"none\"}},\n    ),\n    ({\"margin_y\": \"2rem\"}, {\"marginTop\": \"2rem\", \"marginBottom\": \"2rem\"}),\n    ({\"marginY\": \"2rem\"}, {\"marginTop\": \"2rem\", \"marginBottom\": \"2rem\"}),\n    (\n        {\"::-webkit-scrollbar\": {\"bgColor\": \"red\"}},\n        {\"::-webkit-scrollbar\": {\"backgroundColor\": \"red\"}},\n    ),\n    (\n        {\"paddingX\": [\"2rem\", \"3rem\"]},\n        {\n            \"paddingInlineStart\": [\"2rem\", \"3rem\"],\n            \"paddingInlineEnd\": [\"2rem\", \"3rem\"],\n        },\n    ),\n]\n\n\n@pytest.mark.parametrize(\n    (\"style_dict\", \"expected\"),\n    test_style,\n)\ndef test_convert(style_dict, expected):\n    \"\"\"Test Format a style dictionary.\n\n    Args:\n        style_dict: The style to check.\n        expected: The expected formatted style.\n    \"\"\"\n    converted_dict, _var_data = style.convert(style_dict)\n    assert LiteralVar.create(converted_dict).equals(LiteralVar.create(expected))\n\n\n@pytest.mark.parametrize(\n    (\"style_dict\", \"expected\"),\n    test_style,\n)\ndef test_create_style(style_dict, expected):\n    \"\"\"Test style dictionary.\n\n    Args:\n        style_dict: The style to check.\n        expected: The expected formatted style.\n    \"\"\"\n    assert LiteralVar.create(style.Style(style_dict)).equals(\n        LiteralVar.create(expected).to(style.Style)\n    )\n\n\ndef compare_dict_of_var(d1: dict[str, Any], d2: dict[str, Any]):\n    \"\"\"Compare two dictionaries of Var objects.\n\n    Args:\n        d1: The first dictionary.\n        d2: The second dictionary.\n    \"\"\"\n    assert len(d1) == len(d2)\n    for key, value in d1.items():\n        assert key in d2\n        if isinstance(value, dict):\n            compare_dict_of_var(value, d2[key])\n        elif isinstance(value, Var):\n            assert value.equals(d2[key])\n        else:\n            assert value == d2[key]\n\n\n@pytest.mark.parametrize(\n    (\"kwargs\", \"style_dict\", \"expected_get_style\"),\n    [\n        ({}, {}, {}),\n        (\n            {\"color\": \"hotpink\"},\n            {},\n            {\"css\": LiteralVar.create(Style({\"color\": \"hotpink\"}))},\n        ),\n        ({}, {\"color\": \"red\"}, {\"css\": LiteralVar.create(Style({\"color\": \"red\"}))}),\n        (\n            {\"color\": \"hotpink\"},\n            {\"color\": \"red\"},\n            {\"css\": LiteralVar.create(Style({\"color\": \"hotpink\"}))},\n        ),\n        (\n            {\"_hover\": {\"color\": \"hotpink\"}},\n            {},\n            {\"css\": LiteralVar.create(Style({\"&:hover\": {\"color\": \"hotpink\"}}))},\n        ),\n        (\n            {},\n            {\"_hover\": {\"color\": \"red\"}},\n            {\"css\": LiteralVar.create(Style({\"&:hover\": {\"color\": \"red\"}}))},\n        ),\n        (\n            {},\n            {\":hover\": {\"color\": \"red\"}},\n            {\"css\": LiteralVar.create(Style({\"&:hover\": {\"color\": \"red\"}}))},\n        ),\n        (\n            {},\n            {\"::-webkit-scrollbar\": {\"display\": \"none\"}},\n            {\n                \"css\": LiteralVar.create(\n                    Style({\"&::-webkit-scrollbar\": {\"display\": \"none\"}})\n                )\n            },\n        ),\n        (\n            {},\n            {\"::-moz-progress-bar\": {\"background_color\": \"red\"}},\n            {\n                \"css\": LiteralVar.create(\n                    Style({\"&::-moz-progress-bar\": {\"backgroundColor\": \"red\"}})\n                )\n            },\n        ),\n        (\n            {\"color\": [\"#111\", \"#222\", \"#333\", \"#444\", \"#555\"]},\n            {},\n            {\n                \"css\": LiteralVar.create(\n                    Style({\n                        \"@media screen and (min-width: 0)\": {\"color\": \"#111\"},\n                        \"@media screen and (min-width: 30em)\": {\"color\": \"#222\"},\n                        \"@media screen and (min-width: 48em)\": {\"color\": \"#333\"},\n                        \"@media screen and (min-width: 62em)\": {\"color\": \"#444\"},\n                        \"@media screen and (min-width: 80em)\": {\"color\": \"#555\"},\n                    })\n                )\n            },\n        ),\n        (\n            {\n                \"color\": [\"#111\", \"#222\", \"#333\", \"#444\", \"#555\"],\n                \"background_color\": \"#FFF\",\n            },\n            {},\n            {\n                \"css\": LiteralVar.create(\n                    Style({\n                        \"@media screen and (min-width: 0)\": {\"color\": \"#111\"},\n                        \"@media screen and (min-width: 30em)\": {\"color\": \"#222\"},\n                        \"@media screen and (min-width: 48em)\": {\"color\": \"#333\"},\n                        \"@media screen and (min-width: 62em)\": {\"color\": \"#444\"},\n                        \"@media screen and (min-width: 80em)\": {\"color\": \"#555\"},\n                        \"backgroundColor\": \"#FFF\",\n                    })\n                )\n            },\n        ),\n        (\n            {\n                \"color\": [\"#111\", \"#222\", \"#333\", \"#444\", \"#555\"],\n                \"background_color\": [\"#FFF\", \"#EEE\", \"#DDD\", \"#CCC\", \"#BBB\"],\n            },\n            {},\n            {\n                \"css\": LiteralVar.create(\n                    Style({\n                        \"@media screen and (min-width: 0)\": {\n                            \"color\": \"#111\",\n                            \"backgroundColor\": \"#FFF\",\n                        },\n                        \"@media screen and (min-width: 30em)\": {\n                            \"color\": \"#222\",\n                            \"backgroundColor\": \"#EEE\",\n                        },\n                        \"@media screen and (min-width: 48em)\": {\n                            \"color\": \"#333\",\n                            \"backgroundColor\": \"#DDD\",\n                        },\n                        \"@media screen and (min-width: 62em)\": {\n                            \"color\": \"#444\",\n                            \"backgroundColor\": \"#CCC\",\n                        },\n                        \"@media screen and (min-width: 80em)\": {\n                            \"color\": \"#555\",\n                            \"backgroundColor\": \"#BBB\",\n                        },\n                    })\n                )\n            },\n        ),\n        (\n            {\n                \"_hover\": [\n                    {\"color\": \"#111\"},\n                    {\"color\": \"#222\"},\n                    {\"color\": \"#333\"},\n                    {\"color\": \"#444\"},\n                    {\"color\": \"#555\"},\n                ]\n            },\n            {},\n            {\n                \"css\": LiteralVar.create(\n                    Style({\n                        \"&:hover\": {\n                            \"@media screen and (min-width: 0)\": {\"color\": \"#111\"},\n                            \"@media screen and (min-width: 30em)\": {\"color\": \"#222\"},\n                            \"@media screen and (min-width: 48em)\": {\"color\": \"#333\"},\n                            \"@media screen and (min-width: 62em)\": {\"color\": \"#444\"},\n                            \"@media screen and (min-width: 80em)\": {\"color\": \"#555\"},\n                        }\n                    })\n                )\n            },\n        ),\n        (\n            {\"_hover\": {\"color\": [\"#111\", \"#222\", \"#333\", \"#444\", \"#555\"]}},\n            {},\n            {\n                \"css\": LiteralVar.create(\n                    Style({\n                        \"&:hover\": {\n                            \"@media screen and (min-width: 0)\": {\"color\": \"#111\"},\n                            \"@media screen and (min-width: 30em)\": {\"color\": \"#222\"},\n                            \"@media screen and (min-width: 48em)\": {\"color\": \"#333\"},\n                            \"@media screen and (min-width: 62em)\": {\"color\": \"#444\"},\n                            \"@media screen and (min-width: 80em)\": {\"color\": \"#555\"},\n                        }\n                    })\n                )\n            },\n        ),\n        (\n            {\n                \"_hover\": {\n                    \"color\": [\"#111\", \"#222\", \"#333\", \"#444\", \"#555\"],\n                    \"background_color\": [\"#FFF\", \"#EEE\", \"#DDD\", \"#CCC\", \"#BBB\"],\n                }\n            },\n            {},\n            {\n                \"css\": LiteralVar.create(\n                    Style({\n                        \"&:hover\": {\n                            \"@media screen and (min-width: 0)\": {\n                                \"color\": \"#111\",\n                                \"backgroundColor\": \"#FFF\",\n                            },\n                            \"@media screen and (min-width: 30em)\": {\n                                \"color\": \"#222\",\n                                \"backgroundColor\": \"#EEE\",\n                            },\n                            \"@media screen and (min-width: 48em)\": {\n                                \"color\": \"#333\",\n                                \"backgroundColor\": \"#DDD\",\n                            },\n                            \"@media screen and (min-width: 62em)\": {\n                                \"color\": \"#444\",\n                                \"backgroundColor\": \"#CCC\",\n                            },\n                            \"@media screen and (min-width: 80em)\": {\n                                \"color\": \"#555\",\n                                \"backgroundColor\": \"#BBB\",\n                            },\n                        }\n                    })\n                )\n            },\n        ),\n        (\n            {\n                \"_hover\": {\n                    \"color\": [\"#111\", \"#222\", \"#333\", \"#444\", \"#555\"],\n                    \"background_color\": \"#FFF\",\n                }\n            },\n            {},\n            {\n                \"css\": LiteralVar.create(\n                    Style({\n                        \"&:hover\": {\n                            \"@media screen and (min-width: 0)\": {\"color\": \"#111\"},\n                            \"@media screen and (min-width: 30em)\": {\"color\": \"#222\"},\n                            \"@media screen and (min-width: 48em)\": {\"color\": \"#333\"},\n                            \"@media screen and (min-width: 62em)\": {\"color\": \"#444\"},\n                            \"@media screen and (min-width: 80em)\": {\"color\": \"#555\"},\n                            \"backgroundColor\": \"#FFF\",\n                        }\n                    })\n                )\n            },\n        ),\n    ],\n)\ndef test_style_via_component(\n    kwargs: dict[str, Any],\n    style_dict: dict[str, Any],\n    expected_get_style: dict[str, Any],\n):\n    \"\"\"Pass kwargs and style_dict to a component and assert the final, combined style dict.\n\n    Args:\n        kwargs: The kwargs to pass to the component.\n        style_dict: The style_dict to pass to the component.\n        expected_get_style: The expected style dict.\n    \"\"\"\n    comp = rx.el.div(style=style_dict, **kwargs)\n    compare_dict_of_var(comp._get_style(), expected_get_style)\n\n\nclass StyleState(rx.State):\n    \"\"\"Style vars in a substate.\"\"\"\n\n    color: str = \"hotpink\"\n    color2: str = \"red\"\n\n\n@pytest.mark.parametrize(\n    (\"kwargs\", \"expected_get_style\"),\n    [\n        (\n            {\"color\": StyleState.color},\n            {\"css\": LiteralVar.create(Style({\"color\": StyleState.color}))},\n        ),\n        (\n            {\"color\": f\"dark{StyleState.color}\"},\n            {\n                \"css\": Var(\n                    _js_expr=f'({{ [\"color\"] : (\"dark\"+{StyleState.color}) }})'\n                ).to(Style)\n            },\n        ),\n        (\n            {\"color\": StyleState.color, \"_hover\": {\"color\": StyleState.color2}},\n            {\n                \"css\": LiteralVar.create(\n                    Style({\n                        \"color\": StyleState.color,\n                        \"&:hover\": {\"color\": StyleState.color2},\n                    })\n                )\n            },\n        ),\n        (\n            {\"color\": [StyleState.color, \"gray\", StyleState.color2, \"yellow\", \"blue\"]},\n            {\n                \"css\": LiteralVar.create(\n                    Style({\n                        \"@media screen and (min-width: 0)\": {\"color\": StyleState.color},\n                        \"@media screen and (min-width: 30em)\": {\"color\": \"gray\"},\n                        \"@media screen and (min-width: 48em)\": {\n                            \"color\": StyleState.color2\n                        },\n                        \"@media screen and (min-width: 62em)\": {\"color\": \"yellow\"},\n                        \"@media screen and (min-width: 80em)\": {\"color\": \"blue\"},\n                    })\n                )\n            },\n        ),\n        (\n            {\n                \"_hover\": [\n                    {\"color\": StyleState.color},\n                    {\"color\": StyleState.color2},\n                    {\"color\": \"#333\"},\n                    {\"color\": \"#444\"},\n                    {\"color\": \"#555\"},\n                ]\n            },\n            {\n                \"css\": LiteralVar.create(\n                    Style({\n                        \"&:hover\": {\n                            \"@media screen and (min-width: 0)\": {\n                                \"color\": StyleState.color\n                            },\n                            \"@media screen and (min-width: 30em)\": {\n                                \"color\": StyleState.color2\n                            },\n                            \"@media screen and (min-width: 48em)\": {\"color\": \"#333\"},\n                            \"@media screen and (min-width: 62em)\": {\"color\": \"#444\"},\n                            \"@media screen and (min-width: 80em)\": {\"color\": \"#555\"},\n                        }\n                    })\n                )\n            },\n        ),\n        (\n            {\n                \"_hover\": {\n                    \"color\": [\n                        StyleState.color,\n                        StyleState.color2,\n                        \"#333\",\n                        \"#444\",\n                        \"#555\",\n                    ]\n                }\n            },\n            {\n                \"css\": LiteralVar.create(\n                    Style({\n                        \"&:hover\": {\n                            \"@media screen and (min-width: 0)\": {\n                                \"color\": StyleState.color\n                            },\n                            \"@media screen and (min-width: 30em)\": {\n                                \"color\": StyleState.color2\n                            },\n                            \"@media screen and (min-width: 48em)\": {\"color\": \"#333\"},\n                            \"@media screen and (min-width: 62em)\": {\"color\": \"#444\"},\n                            \"@media screen and (min-width: 80em)\": {\"color\": \"#555\"},\n                        }\n                    })\n                )\n            },\n        ),\n    ],\n)\ndef test_style_via_component_with_state(\n    kwargs: dict[str, Any],\n    expected_get_style: dict[str, Any],\n):\n    \"\"\"Pass kwargs to a component with state vars and assert the final, combined style dict.\n\n    Args:\n        kwargs: The kwargs to pass to the component.\n        expected_get_style: The expected style dict.\n    \"\"\"\n    comp = rx.el.div(**kwargs)\n\n    assert (\n        VarData.merge(comp.style._var_data)\n        == expected_get_style[\"css\"]._get_all_var_data()\n    )\n    # Assert that style values are equal.\n    compare_dict_of_var(comp._get_style(), expected_get_style)\n\n\ndef test_evaluate_style_namespaces():\n    \"\"\"Test that namespaces get converted to component create functions.\"\"\"\n    style_dict = {rx.text: {\"color\": \"blue\"}}\n    assert rx.text.__call__ not in style_dict\n    style_dict = evaluate_style_namespaces({**style_dict})\n    assert rx.text.__call__ in style_dict\n\n\ndef test_style_update_with_var_data():\n    \"\"\"Test that .update with a Style containing VarData works.\"\"\"\n    red_var = LiteralVar.create(\"red\")._replace(\n        merge_var_data=VarData(hooks={\"const red = true\": None}),\n    )\n    blue_var = LiteralVar.create(\"blue\")._replace(\n        merge_var_data=VarData(hooks={\"const blue = true\": None}),\n    )\n\n    s1 = Style({\n        \"color\": red_var,\n    })\n    s2 = Style()\n    s2.update(s1, background_color=f\"{blue_var}ish\")\n    assert str(LiteralVar.create(s2)) == str(\n        LiteralVar.create({\"color\": \"red\", \"backgroundColor\": \"blueish\"})\n    )\n    assert s2._var_data is not None\n    assert \"const red = true\" in s2._var_data.hooks\n    assert \"const blue = true\" in s2._var_data.hooks\n\n    s3 = s1 | s2\n    assert s3._var_data is not None\n    assert \"_varData\" not in s3\n\n\ndef test_component_as_css_value_raises_error():\n    \"\"\"Test that passing a component as a CSS prop value raises ReflexError.\"\"\"\n    with pytest.raises(ReflexError, match=\"cannot be used as style values\"):\n        rx.el.button(\n            \"Import\",\n            class_name=\"px-3 py-2 text-sm font-medium text-gray-600\",\n            left_icon=rx.icon(tag=\"cloud_upload\", class_name=\"w-4 h-4\"),\n        )\n\n    # Test other CSS props that might receive components\n    with pytest.raises(ReflexError, match=\"cannot be used as style values\"):\n        rx.el.div(\n            right_icon=rx.icon(tag=\"settings\"),\n        )\n\n    # Test components passed to style dict\n    with pytest.raises(ReflexError, match=\"cannot be used as style values\"):\n        rx.el.div(\n            style={\"background\": rx.icon(tag=\"star\")},\n        )\n\n    # Test nested style with component\n    with pytest.raises(ReflexError, match=\"cannot be used as style values\"):\n        rx.el.div(\n            style={\"_hover\": {\"content\": rx.text(\"hover\")}},\n        )\n"
  },
  {
    "path": "tests/units/test_telemetry.py",
    "content": "import pytest\nfrom packaging.version import parse as parse_python_version\nfrom pytest_mock import MockerFixture\n\nfrom reflex.utils import telemetry\n\n\ndef test_telemetry():\n    \"\"\"Test that telemetry is sent correctly.\"\"\"\n    # Check that the user OS is one of the supported operating systems.\n    user_os = telemetry.get_os()\n    assert user_os is not None\n    assert user_os in [\"Linux\", \"Darwin\", \"Java\", \"Windows\"]\n\n    # Check that the CPU count and memory are greater than 0.\n    assert telemetry.get_cpu_count() > 0\n\n    # Check that the Reflex version is not None.\n    assert telemetry.get_reflex_version() is not None\n\n    # Check that the Python version is greater than 3.7.\n    python_version = telemetry.get_python_version()\n    assert python_version is not None\n    assert parse_python_version(python_version) >= parse_python_version(\"3.7\")\n\n\ndef test_disable():\n    \"\"\"Test that disabling telemetry works.\"\"\"\n    assert not telemetry._send(\"test\", telemetry_enabled=False)\n\n\n@pytest.mark.parametrize(\"event\", [\"init\", \"reinit\", \"run-dev\", \"run-prod\", \"export\"])\ndef test_send(mocker: MockerFixture, event):\n    httpx_post_mock = mocker.patch(\"httpx.post\")\n\n    # Mock _get_event_defaults to return a complete valid response\n    mock_defaults = {\n        \"api_key\": \"test_api_key\",\n        \"properties\": {\n            \"distinct_id\": 12345,\n            \"distinct_app_id\": 78285505863498957834586115958872998605,\n            \"user_os\": \"Test OS\",\n            \"user_os_detail\": \"Mocked Platform\",\n            \"reflex_version\": \"0.8.0\",\n            \"python_version\": \"3.8.0\",\n            \"node_version\": None,\n            \"bun_version\": None,\n            \"reflex_enterprise_version\": None,\n            \"cpu_count\": 4,\n            \"memory\": 8192,\n            \"cpu_info\": {},\n        },\n    }\n    mocker.patch(\n        \"reflex.utils.telemetry._get_event_defaults\", return_value=mock_defaults\n    )\n\n    telemetry._send(event, telemetry_enabled=True)\n    httpx_post_mock.assert_called_once()\n"
  },
  {
    "path": "tests/units/test_testing.py",
    "content": "\"\"\"Unit tests for the included testing tools.\"\"\"\n\nimport pytest\n\nfrom reflex.constants import IS_WINDOWS\nfrom reflex.testing import AppHarness\n\n\n@pytest.mark.skip(\"Slow test that makes network requests.\")\ndef test_app_harness(tmp_path):\n    \"\"\"Ensure that AppHarness can compile and start an app.\n\n    Args:\n        tmp_path: pytest tmp_path fixture\n    \"\"\"\n    # Skip in Windows CI.\n    if IS_WINDOWS:\n        return\n\n    def BasicApp():\n        import reflex as rx\n\n        class State(rx.State):\n            pass\n\n        app = rx.App(_state=State)\n        app.add_page(lambda: rx.text(\"Basic App\"), route=\"/\", title=\"index\")\n        app._compile()\n\n    with AppHarness.create(\n        root=tmp_path,\n        app_source=BasicApp,\n    ) as harness:\n        assert harness.app_instance is not None\n        assert harness.backend is not None\n        assert harness.frontend_url is not None\n        assert harness.frontend_process is not None\n        assert harness.frontend_process.poll() is None\n\n    assert harness.frontend_process.poll() is not None\n"
  },
  {
    "path": "tests/units/test_var.py",
    "content": "import decimal\nimport json\nimport math\nimport typing\nfrom collections.abc import Mapping, Sequence\nfrom typing import cast\n\nimport pytest\nfrom pandas import DataFrame\nfrom pytest_mock import MockerFixture\n\nimport reflex as rx\nfrom reflex.base import Base\nfrom reflex.constants.base import REFLEX_VAR_CLOSING_TAG, REFLEX_VAR_OPENING_TAG\nfrom reflex.constants.state import FIELD_MARKER\nfrom reflex.environment import PerformanceMode\nfrom reflex.state import BaseState\nfrom reflex.utils.exceptions import (\n    PrimitiveUnserializableToJSONError,\n    UntypedComputedVarError,\n)\nfrom reflex.utils.imports import ImportVar\nfrom reflex.utils.types import get_default_value_for_type\nfrom reflex.vars import VarData\nfrom reflex.vars.base import (\n    ComputedVar,\n    LiteralVar,\n    Var,\n    computed_var,\n    var_operation,\n    var_operation_return,\n)\nfrom reflex.vars.function import (\n    ArgsFunctionOperation,\n    DestructuredArg,\n    FunctionStringVar,\n)\nfrom reflex.vars.number import LiteralBooleanVar, LiteralNumberVar, NumberVar\nfrom reflex.vars.object import LiteralObjectVar, ObjectVar\nfrom reflex.vars.sequence import (\n    ArrayVar,\n    ConcatVarOperation,\n    LiteralArrayVar,\n    LiteralStringVar,\n)\n\ntest_vars = [\n    Var(_js_expr=\"prop1\", _var_type=int),\n    Var(_js_expr=\"key\", _var_type=str),\n    Var(_js_expr=\"value\", _var_type=str)._var_set_state(\"state\"),\n    Var(_js_expr=\"local\", _var_type=str)._var_set_state(\"state\"),\n    Var(_js_expr=\"local2\", _var_type=str),\n]\n\n\nclass ATestState(BaseState):\n    \"\"\"Test state.\"\"\"\n\n    value: str\n    dict_val: dict[str, list] = {}\n\n\n@pytest.fixture\ndef TestObj():\n    class TestObj(Base):\n        foo: int\n        bar: str\n\n    return TestObj\n\n\n@pytest.fixture\ndef ParentState(TestObj):\n    class ParentState(BaseState):\n        foo: int\n        bar: int\n\n        @computed_var\n        def var_without_annotation(self):\n            return TestObj\n\n    return ParentState\n\n\n@pytest.fixture\ndef ChildState(ParentState, TestObj):\n    class ChildState(ParentState):\n        @computed_var\n        def var_without_annotation(self):\n            \"\"\"This shadows ParentState.var_without_annotation.\n\n            Returns:\n                TestObj: Test object.\n            \"\"\"\n            return TestObj\n\n    return ChildState\n\n\n@pytest.fixture\ndef GrandChildState(ChildState, TestObj):\n    class GrandChildState(ChildState):\n        @computed_var\n        def var_without_annotation(self):\n            \"\"\"This shadows ChildState.var_without_annotation.\n\n            Returns:\n                TestObj: Test object.\n            \"\"\"\n            return TestObj\n\n    return GrandChildState\n\n\n@pytest.fixture\ndef StateWithAnyVar(TestObj):\n    class StateWithAnyVar(BaseState):\n        @computed_var\n        def var_without_annotation(self) -> typing.Any:\n            return TestObj\n\n    return StateWithAnyVar\n\n\n@pytest.fixture\ndef StateWithCorrectVarAnnotation():\n    class StateWithCorrectVarAnnotation(BaseState):\n        @computed_var\n        def var_with_annotation(self) -> str:\n            return \"Correct annotation\"\n\n    return StateWithCorrectVarAnnotation\n\n\n@pytest.fixture\ndef StateWithWrongVarAnnotation(TestObj):\n    class StateWithWrongVarAnnotation(BaseState):\n        @computed_var\n        def var_with_annotation(self) -> str:\n            return TestObj\n\n    return StateWithWrongVarAnnotation\n\n\n@pytest.fixture\ndef StateWithInitialComputedVar():\n    class StateWithInitialComputedVar(BaseState):\n        @computed_var(initial_value=\"Initial value\")\n        def var_with_initial_value(self) -> str:\n            return \"Runtime value\"\n\n    return StateWithInitialComputedVar\n\n\n@pytest.fixture\ndef ChildWithInitialComputedVar(StateWithInitialComputedVar):\n    class ChildWithInitialComputedVar(StateWithInitialComputedVar):\n        @computed_var(initial_value=\"Initial value\")\n        def var_with_initial_value_child(self) -> str:\n            return \"Runtime value\"\n\n    return ChildWithInitialComputedVar\n\n\n@pytest.fixture\ndef StateWithRuntimeOnlyVar():\n    class StateWithRuntimeOnlyVar(BaseState):\n        @computed_var(initial_value=None)\n        def var_raises_at_runtime(self) -> str:\n            msg = \"So nicht, mein Freund\"\n            raise ValueError(msg)\n\n    return StateWithRuntimeOnlyVar\n\n\n@pytest.fixture\ndef ChildWithRuntimeOnlyVar(StateWithRuntimeOnlyVar):\n    class ChildWithRuntimeOnlyVar(StateWithRuntimeOnlyVar):\n        @computed_var(initial_value=\"Initial value\")\n        def var_raises_at_runtime_child(self) -> str:\n            msg = \"So nicht, mein Freund\"\n            raise ValueError(msg)\n\n    return ChildWithRuntimeOnlyVar\n\n\n@pytest.mark.parametrize(\n    (\"prop\", \"expected\"),\n    zip(\n        test_vars,\n        [\n            \"prop1\",\n            \"key\",\n            \"state.value\",\n            \"state.local\",\n            \"local2\",\n        ],\n        strict=True,\n    ),\n)\ndef test_full_name(prop, expected):\n    \"\"\"Test that the full name of a var is correct.\n\n    Args:\n        prop: The var to test.\n        expected: The expected full name.\n    \"\"\"\n    assert str(prop) == expected\n\n\n@pytest.mark.parametrize(\n    (\"prop\", \"expected\"),\n    zip(\n        test_vars,\n        [\"prop1\", \"key\", \"state.value\", \"state.local\", \"local2\"],\n        strict=True,\n    ),\n)\ndef test_str(prop, expected):\n    \"\"\"Test that the string representation of a var is correct.\n\n    Args:\n        prop: The var to test.\n        expected: The expected string representation.\n    \"\"\"\n    assert str(prop) == expected\n\n\n@pytest.mark.parametrize(\n    (\"prop\", \"expected\"),\n    [\n        (Var(_js_expr=\"p\", _var_type=int), 0),\n        (Var(_js_expr=\"p\", _var_type=float), 0.0),\n        (Var(_js_expr=\"p\", _var_type=str), \"\"),\n        (Var(_js_expr=\"p\", _var_type=bool), False),\n        (Var(_js_expr=\"p\", _var_type=list), []),\n        (Var(_js_expr=\"p\", _var_type=dict), {}),\n        (Var(_js_expr=\"p\", _var_type=tuple), ()),\n        (Var(_js_expr=\"p\", _var_type=set), set()),\n    ],\n)\ndef test_default_value(prop: Var, expected):\n    \"\"\"Test that the default value of a var is correct.\n\n    Args:\n        prop: The var to test.\n        expected: The expected default value.\n    \"\"\"\n    assert get_default_value_for_type(prop._var_type) == expected\n\n\n@pytest.mark.parametrize(\n    (\"value\", \"expected\"),\n    [\n        (None, Var(_js_expr=\"null\", _var_type=None)),\n        (1, Var(_js_expr=\"1\", _var_type=int)),\n        (\"key\", Var(_js_expr='\"key\"', _var_type=str)),\n        (3.15, Var(_js_expr=\"3.15\", _var_type=float)),\n        ([1, 2, 3], Var(_js_expr=\"[1, 2, 3]\", _var_type=Sequence[int])),\n        (\n            {\"a\": 1, \"b\": 2},\n            Var(_js_expr='({ [\"a\"] : 1, [\"b\"] : 2 })', _var_type=Mapping[str, int]),\n        ),\n    ],\n)\ndef test_create(value, expected):\n    \"\"\"Test the var create function.\n\n    Args:\n        value: The value to create a var from.\n        expected: The expected name of the setter function.\n    \"\"\"\n    prop = LiteralVar.create(value)\n    assert prop.equals(expected)\n\n\ndef test_create_type_error():\n    \"\"\"Test the var create function when inputs type error.\"\"\"\n\n    class ErrorType:\n        pass\n\n    value = ErrorType()\n\n    with pytest.raises(TypeError):\n        LiteralVar.create(value)\n\n\ndef v(value) -> Var:\n    return LiteralVar.create(value)\n\n\ndef test_basic_operations(TestObj):\n    \"\"\"Test the var operations.\n\n    Args:\n        TestObj: The test object.\n    \"\"\"\n    assert str(v(1) == v(2)) == \"(1?.valueOf?.() === 2?.valueOf?.())\"\n    assert str(v(1) != v(2)) == \"(1?.valueOf?.() !== 2?.valueOf?.())\"\n    assert str(LiteralNumberVar.create(1) < 2) == \"(1 < 2)\"\n    assert str(LiteralNumberVar.create(1) <= 2) == \"(1 <= 2)\"\n    assert str(LiteralNumberVar.create(1) > 2) == \"(1 > 2)\"\n    assert str(LiteralNumberVar.create(1) >= 2) == \"(1 >= 2)\"\n    assert str(LiteralNumberVar.create(1) + 2) == \"(1 + 2)\"\n    assert str(LiteralNumberVar.create(1) - 2) == \"(1 - 2)\"\n    assert str(LiteralNumberVar.create(1) * 2) == \"(1 * 2)\"\n    assert str(LiteralNumberVar.create(1) / 2) == \"(1 / 2)\"\n    assert str(LiteralNumberVar.create(1) // 2) == \"Math.floor(1 / 2)\"\n    assert str(LiteralNumberVar.create(1) % 2) == \"(1 % 2)\"\n    assert str(LiteralNumberVar.create(1) ** 2) == \"(1 ** 2)\"\n    assert str(LiteralNumberVar.create(1) & v(2)) == \"(1 && 2)\"\n    assert str(LiteralNumberVar.create(1) | v(2)) == \"(1 || 2)\"\n    assert str(LiteralArrayVar.create([1, 2, 3])[0]) == \"[1, 2, 3]?.at?.(0)\"\n    assert (\n        str(LiteralObjectVar.create({\"a\": 1, \"b\": 2})[\"a\"])\n        == '({ [\"a\"] : 1, [\"b\"] : 2 })?.[\"a\"]'\n    )\n    assert str(v(\"foo\") == v(\"bar\")) == '(\"foo\"?.valueOf?.() === \"bar\"?.valueOf?.())'\n    assert (\n        str(Var(_js_expr=\"foo\") == Var(_js_expr=\"bar\"))\n        == \"(foo?.valueOf?.() === bar?.valueOf?.())\"\n    )\n    assert (\n        str(LiteralVar.create(\"foo\") == LiteralVar.create(\"bar\"))\n        == '(\"foo\"?.valueOf?.() === \"bar\"?.valueOf?.())'\n    )\n    print(Var(_js_expr=\"foo\").to(ObjectVar, TestObj)._var_set_state(\"state\"))\n    assert (\n        str(\n            Var(_js_expr=\"foo\").to(ObjectVar, TestObj)._var_set_state(\"state\").bar\n            == LiteralVar.create(\"bar\")\n        )\n        == '(state.foo?.[\"bar\"]?.valueOf?.() === \"bar\"?.valueOf?.())'\n    )\n    assert (\n        str(Var(_js_expr=\"foo\").to(ObjectVar, TestObj)._var_set_state(\"state\").bar)\n        == 'state.foo?.[\"bar\"]'\n    )\n    assert str(abs(LiteralNumberVar.create(1))) == \"Math.abs(1)\"\n    assert str(LiteralArrayVar.create([1, 2, 3]).length()) == \"[1, 2, 3].length\"\n    assert (\n        str(LiteralArrayVar.create([1, 2]) + LiteralArrayVar.create([3, 4]))\n        == \"[...[1, 2], ...[3, 4]]\"\n    )\n\n    # Tests for reverse operation\n    assert (\n        str(LiteralArrayVar.create([1, 2, 3]).reverse())\n        == \"[1, 2, 3].slice().reverse()\"\n    )\n    assert (\n        str(LiteralArrayVar.create([\"1\", \"2\", \"3\"]).reverse())\n        == '[\"1\", \"2\", \"3\"].slice().reverse()'\n    )\n    assert (\n        str(Var(_js_expr=\"foo\")._var_set_state(\"state\").to(list).reverse())\n        == \"state.foo.slice().reverse()\"\n    )\n    assert str(Var(_js_expr=\"foo\").to(list).reverse()) == \"foo.slice().reverse()\"\n    assert str(Var(_js_expr=\"foo\", _var_type=str).js_type()) == \"(typeof(foo))\"\n\n\n@pytest.mark.parametrize(\n    (\"var\", \"expected\"),\n    [\n        (v([1, 2, 3]), \"[1, 2, 3]\"),\n        (v({1, 2, 3}), \"[1, 2, 3]\"),\n        (v([\"1\", \"2\", \"3\"]), '[\"1\", \"2\", \"3\"]'),\n        (\n            Var(_js_expr=\"foo\")._var_set_state(\"state\").to(list),\n            \"state.foo\",\n        ),\n        (Var(_js_expr=\"foo\").to(list), \"foo\"),\n        (v((1, 2, 3)), \"[1, 2, 3]\"),\n        (v((\"1\", \"2\", \"3\")), '[\"1\", \"2\", \"3\"]'),\n        (\n            Var(_js_expr=\"foo\")._var_set_state(\"state\").to(tuple),\n            \"state.foo\",\n        ),\n        (Var(_js_expr=\"foo\").to(tuple), \"foo\"),\n    ],\n)\ndef test_list_tuple_contains(var, expected):\n    assert str(var.contains(1)) == f\"{expected}.includes(1)\"\n    assert str(var.contains(\"1\")) == f'{expected}.includes(\"1\")'\n    assert str(var.contains(v(1))) == f\"{expected}.includes(1)\"\n    assert str(var.contains(v(\"1\"))) == f'{expected}.includes(\"1\")'\n    other_state_var = Var(_js_expr=\"other\", _var_type=str)._var_set_state(\"state\")\n    other_var = Var(_js_expr=\"other\", _var_type=str)\n    assert str(var.contains(other_state_var)) == f\"{expected}.includes(state.other)\"\n    assert str(var.contains(other_var)) == f\"{expected}.includes(other)\"\n\n\nclass Foo(rx.Base):\n    \"\"\"Foo class.\"\"\"\n\n    bar: int\n    baz: str\n\n\nclass Bar(rx.Base):\n    \"\"\"Bar class.\"\"\"\n\n    bar: str\n    baz: str\n    foo: int\n\n\n@pytest.mark.parametrize(\n    (\"var\", \"var_type\"),\n    [\n        (Var(_js_expr=\"\").to(Foo | Bar), Foo | Bar),\n        (Var(_js_expr=\"\").to(Foo | Bar).bar, int | str),\n        (Var(_js_expr=\"\").to(Foo | Bar).baz, str),\n        (\n            Var(_js_expr=\"\").to(Foo | Bar).foo,\n            int | None,\n        ),\n    ],\n)\ndef test_var_types(var, var_type):\n    assert var._var_type == var_type\n\n\n@pytest.mark.parametrize(\n    (\"var\", \"expected\"),\n    [\n        (v(\"123\"), json.dumps(\"123\")),\n        (Var(_js_expr=\"foo\")._var_set_state(\"state\").to(str), \"state.foo\"),\n        (Var(_js_expr=\"foo\").to(str), \"foo\"),\n    ],\n)\ndef test_str_contains(var, expected):\n    assert str(var.contains(\"1\")) == f'{expected}.includes(\"1\")'\n    assert str(var.contains(v(\"1\"))) == f'{expected}.includes(\"1\")'\n    other_state_var = Var(_js_expr=\"other\")._var_set_state(\"state\").to(str)\n    other_var = Var(_js_expr=\"other\").to(str)\n    assert str(var.contains(other_state_var)) == f\"{expected}.includes(state.other)\"\n    assert str(var.contains(other_var)) == f\"{expected}.includes(other)\"\n    assert (\n        str(var.contains(\"1\", \"hello\"))\n        == f'{expected}.some(obj => obj[\"hello\"] === \"1\")'\n    )\n\n\n@pytest.mark.parametrize(\n    (\"var\", \"expected\"),\n    [\n        (v({\"a\": 1, \"b\": 2}), '({ [\"a\"] : 1, [\"b\"] : 2 })'),\n        (Var(_js_expr=\"foo\")._var_set_state(\"state\").to(dict), \"state.foo\"),\n        (Var(_js_expr=\"foo\").to(dict), \"foo\"),\n    ],\n)\ndef test_dict_contains(var, expected):\n    assert str(var.contains(1)) == f\"{expected}.hasOwnProperty(1)\"\n    assert str(var.contains(\"1\")) == f'{expected}.hasOwnProperty(\"1\")'\n    assert str(var.contains(v(1))) == f\"{expected}.hasOwnProperty(1)\"\n    assert str(var.contains(v(\"1\"))) == f'{expected}.hasOwnProperty(\"1\")'\n    other_state_var = Var(_js_expr=\"other\")._var_set_state(\"state\").to(str)\n    other_var = Var(_js_expr=\"other\").to(str)\n    assert (\n        str(var.contains(other_state_var)) == f\"{expected}.hasOwnProperty(state.other)\"\n    )\n    assert str(var.contains(other_var)) == f\"{expected}.hasOwnProperty(other)\"\n\n\n@pytest.mark.parametrize(\n    \"var\",\n    [\n        Var(_js_expr=\"list\", _var_type=list[int]).guess_type(),\n        Var(_js_expr=\"tuple\", _var_type=tuple[int, int]).guess_type(),\n        Var(_js_expr=\"str\", _var_type=str).guess_type(),\n    ],\n)\ndef test_var_indexing_lists(var):\n    \"\"\"Test that we can index into str, list or tuple vars.\n\n    Args:\n        var : The str, list or tuple base var.\n    \"\"\"\n    # Test basic indexing.\n    assert str(var[0]) == f\"{var._js_expr}?.at?.(0)\"\n    assert str(var[1]) == f\"{var._js_expr}?.at?.(1)\"\n\n    # Test negative indexing.\n    assert str(var[-1]) == f\"{var._js_expr}?.at?.(-1)\"\n\n\n@pytest.mark.parametrize(\n    (\"var\", \"type_\"),\n    [\n        (Var(_js_expr=\"list\", _var_type=list[int]).guess_type(), [int, int]),\n        (\n            Var(_js_expr=\"tuple\", _var_type=tuple[int, str]).guess_type(),\n            [int, str],\n        ),\n        (Var.create((1, 2)), [int, int]),\n    ],\n)\ndef test_var_indexing_types(var, type_):\n    \"\"\"Test that indexing returns valid types.\n\n    Args:\n        var   : The list, tuple base var.\n        type_ : The type on indexed object.\n\n    \"\"\"\n    assert var[0]._var_type == type_[0]\n    assert var[1]._var_type == type_[1]\n\n\ndef test_var_indexing_str():\n    \"\"\"Test that we can index into str vars.\"\"\"\n    str_var = Var(_js_expr=\"str\").to(str)\n\n    # Test that indexing gives a type of Var[str].\n    assert isinstance(str_var[0], Var)\n    assert str_var[0]._var_type is str\n\n    # Test basic indexing.\n    assert str(str_var[0]) == \"str?.at?.(0)\"\n    assert str(str_var[1]) == \"str?.at?.(1)\"\n\n    # Test negative indexing.\n    assert str(str_var[-1]) == \"str?.at?.(-1)\"\n\n\n@pytest.mark.parametrize(\n    \"var\",\n    [\n        (Var(_js_expr=\"foo\", _var_type=int).guess_type()),\n        (Var(_js_expr=\"bar\", _var_type=float).guess_type()),\n    ],\n)\ndef test_var_replace_with_invalid_kwargs(var):\n    with pytest.raises(TypeError) as excinfo:\n        var._replace(_this_should_fail=True)\n    assert \"unexpected keyword argument\" in str(excinfo.value)\n\n\ndef test_computed_var_replace_with_invalid_kwargs():\n    @computed_var(initial_value=1)\n    def test_var(state) -> int:\n        return 1\n\n    with pytest.raises(TypeError) as excinfo:\n        test_var._replace(_random_kwarg=True)\n    assert \"Unexpected keyword argument\" in str(excinfo.value)\n\n\n@pytest.mark.parametrize(\n    (\"var\", \"index\"),\n    [\n        (Var(_js_expr=\"lst\", _var_type=list[int]).guess_type(), [1, 2]),\n        (\n            Var(_js_expr=\"lst\", _var_type=list[int]).guess_type(),\n            {\"name\": \"dict\"},\n        ),\n        (Var(_js_expr=\"lst\", _var_type=list[int]).guess_type(), {\"set\"}),\n        (\n            Var(_js_expr=\"lst\", _var_type=list[int]).guess_type(),\n            (\n                1,\n                2,\n            ),\n        ),\n        (Var(_js_expr=\"lst\", _var_type=list[int]).guess_type(), 1.5),\n        (Var(_js_expr=\"lst\", _var_type=list[int]).guess_type(), \"str\"),\n        (\n            Var(_js_expr=\"lst\", _var_type=list[int]).guess_type(),\n            Var(_js_expr=\"string_var\", _var_type=str).guess_type(),\n        ),\n        (\n            Var(_js_expr=\"lst\", _var_type=list[int]).guess_type(),\n            Var(_js_expr=\"float_var\", _var_type=float).guess_type(),\n        ),\n        (\n            Var(_js_expr=\"lst\", _var_type=list[int]).guess_type(),\n            Var(_js_expr=\"list_var\", _var_type=list[int]).guess_type(),\n        ),\n        (\n            Var(_js_expr=\"lst\", _var_type=list[int]).guess_type(),\n            Var(_js_expr=\"set_var\", _var_type=set[str]).guess_type(),\n        ),\n        (\n            Var(_js_expr=\"lst\", _var_type=list[int]).guess_type(),\n            Var(_js_expr=\"dict_var\", _var_type=dict[str, str]).guess_type(),\n        ),\n        (Var(_js_expr=\"str\", _var_type=str).guess_type(), [1, 2]),\n        (Var(_js_expr=\"lst\", _var_type=str).guess_type(), {\"name\": \"dict\"}),\n        (Var(_js_expr=\"lst\", _var_type=str).guess_type(), {\"set\"}),\n        (\n            Var(_js_expr=\"lst\", _var_type=str).guess_type(),\n            Var(_js_expr=\"string_var\", _var_type=str).guess_type(),\n        ),\n        (\n            Var(_js_expr=\"lst\", _var_type=str).guess_type(),\n            Var(_js_expr=\"float_var\", _var_type=float).guess_type(),\n        ),\n        (Var(_js_expr=\"str\", _var_type=tuple[str]).guess_type(), [1, 2]),\n        (\n            Var(_js_expr=\"lst\", _var_type=tuple[str]).guess_type(),\n            {\"name\": \"dict\"},\n        ),\n        (Var(_js_expr=\"lst\", _var_type=tuple[str]).guess_type(), {\"set\"}),\n        (\n            Var(_js_expr=\"lst\", _var_type=tuple[str]).guess_type(),\n            Var(_js_expr=\"string_var\", _var_type=str).guess_type(),\n        ),\n        (\n            Var(_js_expr=\"lst\", _var_type=tuple[str]).guess_type(),\n            Var(_js_expr=\"float_var\", _var_type=float).guess_type(),\n        ),\n    ],\n)\ndef test_var_unsupported_indexing_lists(var, index):\n    \"\"\"Test unsupported indexing throws a type error.\n\n    Args:\n        var: The base var.\n        index: The base var index.\n    \"\"\"\n    with pytest.raises(TypeError):\n        var[index]\n\n\n@pytest.mark.parametrize(\n    \"var\",\n    [\n        Var(_js_expr=\"lst\", _var_type=list[int]).guess_type(),\n        Var(_js_expr=\"tuple\", _var_type=tuple[int, int]).guess_type(),\n    ],\n)\ndef test_var_list_slicing(var):\n    \"\"\"Test that we can slice into str, list or tuple vars.\n\n    Args:\n        var : The str, list or tuple base var.\n    \"\"\"\n    assert str(var[:1]) == f\"{var._js_expr}.slice(undefined, 1)\"\n    assert str(var[1:]) == f\"{var._js_expr}.slice(1, undefined)\"\n    assert str(var[:]) == f\"{var._js_expr}.slice(undefined, undefined)\"\n\n\ndef test_str_var_slicing():\n    \"\"\"Test that we can slice into str vars.\"\"\"\n    str_var = Var(_js_expr=\"str\").to(str)\n\n    # Test that slicing gives a type of Var[str].\n    assert isinstance(str_var[:1], Var)\n    assert str_var[:1]._var_type is str\n\n    # Test basic slicing.\n    assert str(str_var[:1]) == 'str.split(\"\").slice(undefined, 1).join(\"\")'\n    assert str(str_var[1:]) == 'str.split(\"\").slice(1, undefined).join(\"\")'\n    assert str(str_var[:]) == 'str.split(\"\").slice(undefined, undefined).join(\"\")'\n    assert str(str_var[1:2]) == 'str.split(\"\").slice(1, 2).join(\"\")'\n\n    # Test negative slicing.\n    assert str(str_var[:-1]) == 'str.split(\"\").slice(undefined, -1).join(\"\")'\n    assert str(str_var[-1:]) == 'str.split(\"\").slice(-1, undefined).join(\"\")'\n    assert str(str_var[:-2]) == 'str.split(\"\").slice(undefined, -2).join(\"\")'\n    assert str(str_var[-2:]) == 'str.split(\"\").slice(-2, undefined).join(\"\")'\n\n\ndef test_dict_indexing():\n    \"\"\"Test that we can index into dict vars.\"\"\"\n    dct = Var(_js_expr=\"dct\").to(ObjectVar, dict[str, str])\n\n    # Check correct indexing.\n    assert str(dct[\"a\"]) == 'dct?.[\"a\"]'\n    assert str(dct[\"asdf\"]) == 'dct?.[\"asdf\"]'\n\n\n@pytest.mark.parametrize(\n    (\"var\", \"index\"),\n    [\n        (\n            Var(_js_expr=\"dict\", _var_type=dict[str, str]).guess_type(),\n            [1, 2],\n        ),\n        (\n            Var(_js_expr=\"dict\", _var_type=dict[str, str]).guess_type(),\n            {\"name\": \"dict\"},\n        ),\n        (\n            Var(_js_expr=\"dict\", _var_type=dict[str, str]).guess_type(),\n            {\"set\"},\n        ),\n        (\n            Var(_js_expr=\"dict\", _var_type=dict[str, str]).guess_type(),\n            (\n                1,\n                2,\n            ),\n        ),\n        (\n            Var(_js_expr=\"lst\", _var_type=dict[str, str]).guess_type(),\n            Var(_js_expr=\"list_var\", _var_type=list[int]).guess_type(),\n        ),\n        (\n            Var(_js_expr=\"lst\", _var_type=dict[str, str]).guess_type(),\n            Var(_js_expr=\"set_var\", _var_type=set[str]).guess_type(),\n        ),\n        (\n            Var(_js_expr=\"lst\", _var_type=dict[str, str]).guess_type(),\n            Var(_js_expr=\"dict_var\", _var_type=dict[str, str]).guess_type(),\n        ),\n        (\n            Var(_js_expr=\"df\", _var_type=DataFrame).guess_type(),\n            [1, 2],\n        ),\n        (\n            Var(_js_expr=\"df\", _var_type=DataFrame).guess_type(),\n            {\"name\": \"dict\"},\n        ),\n        (\n            Var(_js_expr=\"df\", _var_type=DataFrame).guess_type(),\n            {\"set\"},\n        ),\n        (\n            Var(_js_expr=\"df\", _var_type=DataFrame).guess_type(),\n            (\n                1,\n                2,\n            ),\n        ),\n        (\n            Var(_js_expr=\"df\", _var_type=DataFrame).guess_type(),\n            Var(_js_expr=\"list_var\", _var_type=list[int]).guess_type(),\n        ),\n        (\n            Var(_js_expr=\"df\", _var_type=DataFrame).guess_type(),\n            Var(_js_expr=\"set_var\", _var_type=set[str]).guess_type(),\n        ),\n        (\n            Var(_js_expr=\"df\", _var_type=DataFrame).guess_type(),\n            Var(_js_expr=\"dict_var\", _var_type=dict[str, str]).guess_type(),\n        ),\n    ],\n)\ndef test_var_unsupported_indexing_dicts(var, index):\n    \"\"\"Test unsupported indexing throws a type error.\n\n    Args:\n        var: The base var.\n        index: The base var index.\n    \"\"\"\n    with pytest.raises(TypeError):\n        var[index]\n\n\n@pytest.mark.parametrize(\n    \"fixture\",\n    [\n        \"ParentState\",\n        \"StateWithAnyVar\",\n    ],\n)\ndef test_computed_var_without_annotation_error(request, fixture):\n    \"\"\"Test that a type error is thrown when an attribute of a computed var is\n    accessed without annotating the computed var.\n\n    Args:\n        request: Fixture Request.\n        fixture: The state fixture.\n    \"\"\"\n    with pytest.raises(TypeError) as err:\n        state = request.getfixturevalue(fixture)\n        state.var_without_annotation.foo\n        full_name = state.var_without_annotation._var_full_name\n        assert (\n            err.value.args[0]\n            == f\"You must provide an annotation for the state var `{full_name}`. Annotation cannot be `typing.Any`\"\n        )\n\n\n@pytest.mark.parametrize(\n    \"fixture\",\n    [\n        \"ChildState\",\n        \"GrandChildState\",\n    ],\n)\ndef test_shadow_computed_var_error(request: pytest.FixtureRequest, fixture: str):\n    \"\"\"Test that a name error is thrown when an attribute of a computed var is\n    shadowed by another attribute.\n\n    Args:\n        request: Fixture Request.\n        fixture: The state fixture.\n    \"\"\"\n    with pytest.raises(UntypedComputedVarError):\n        state = request.getfixturevalue(fixture)\n        state.var_without_annotation.foo\n\n\n@pytest.mark.parametrize(\n    \"fixture\",\n    [\n        \"StateWithCorrectVarAnnotation\",\n        \"StateWithWrongVarAnnotation\",\n    ],\n)\ndef test_computed_var_with_annotation_error(request, fixture):\n    \"\"\"Test that an Attribute error is thrown when a non-existent attribute of an annotated computed var is\n    accessed or when the wrong annotation is provided to a computed var.\n\n    Args:\n        request: Fixture Request.\n        fixture: The state fixture.\n    \"\"\"\n    with pytest.raises(AttributeError) as err:\n        state = request.getfixturevalue(fixture)\n        state.var_with_annotation.foo\n        full_name = state.var_with_annotation._var_full_name\n        assert (\n            err.value.args[0]\n            == f\"The State var `{full_name}` has no attribute 'foo' or may have been annotated wrongly.\"\n        )\n\n\n@pytest.mark.parametrize(\n    (\n        \"fixture\",\n        \"var_name\",\n        \"expected_initial\",\n        \"expected_runtime\",\n        \"raises_at_runtime\",\n    ),\n    [\n        (\n            \"StateWithInitialComputedVar\",\n            \"var_with_initial_value\" + FIELD_MARKER,\n            \"Initial value\",\n            \"Runtime value\",\n            False,\n        ),\n        (\n            \"ChildWithInitialComputedVar\",\n            \"var_with_initial_value_child\" + FIELD_MARKER,\n            \"Initial value\",\n            \"Runtime value\",\n            False,\n        ),\n        (\n            \"StateWithRuntimeOnlyVar\",\n            \"var_raises_at_runtime\" + FIELD_MARKER,\n            None,\n            None,\n            True,\n        ),\n        (\n            \"ChildWithRuntimeOnlyVar\",\n            \"var_raises_at_runtime_child\" + FIELD_MARKER,\n            \"Initial value\",\n            None,\n            True,\n        ),\n    ],\n)\ndef test_state_with_initial_computed_var(\n    request, fixture, var_name, expected_initial, expected_runtime, raises_at_runtime\n):\n    \"\"\"Test that the initial and runtime values of a computed var are correct.\n\n    Args:\n        request: Fixture Request.\n        fixture: The state fixture.\n        var_name: The name of the computed var.\n        expected_initial: The expected initial value of the computed var.\n        expected_runtime: The expected runtime value of the computed var.\n        raises_at_runtime: Whether the computed var is runtime only.\n    \"\"\"\n    state = request.getfixturevalue(fixture)()\n    state_name = state.get_full_name()\n    initial_dict = state.dict(initial=True)[state_name]\n    assert initial_dict[var_name] == expected_initial\n\n    if raises_at_runtime:\n        with pytest.raises(ValueError):\n            state.dict()[state_name][var_name]\n    else:\n        runtime_dict = state.dict()[state_name]\n        assert runtime_dict[var_name] == expected_runtime\n\n\ndef test_literal_var():\n    complicated_var = LiteralVar.create([\n        {\"a\": 1, \"b\": 2, \"c\": {\"d\": 3, \"e\": 4}},\n        [1, 2, 3, 4],\n        9,\n        \"string\",\n        True,\n        False,\n        None,\n        {1, 2, 3},\n    ])\n    assert (\n        str(complicated_var)\n        == '[({ [\"a\"] : 1, [\"b\"] : 2, [\"c\"] : ({ [\"d\"] : 3, [\"e\"] : 4 }) }), [1, 2, 3, 4], 9, \"string\", true, false, null, [1, 2, 3]]'\n    )\n\n\ndef test_function_var():\n    addition_func = FunctionStringVar.create(\"((a, b) => a + b)\")\n    assert str(addition_func.call(1, 2)) == \"(((a, b) => a + b)(1, 2))\"\n\n    manual_addition_func = ArgsFunctionOperation.create(\n        (\"a\", \"b\"),\n        {\n            \"args\": [Var(_js_expr=\"a\"), Var(_js_expr=\"b\")],\n            \"result\": Var(_js_expr=\"a + b\"),\n        },\n    )\n    assert (\n        str(manual_addition_func.call(1, 2))\n        == '(((a, b) => ({ [\"args\"] : [a, b], [\"result\"] : a + b }))(1, 2))'\n    )\n\n    increment_func = addition_func.partial(1)\n    assert (\n        str(increment_func.call(2))\n        == \"(((...args) => (((a, b) => a + b)(1, ...args)))(2))\"\n    )\n\n    create_hello_statement = ArgsFunctionOperation.create(\n        (\"name\",), f\"Hello, {Var(_js_expr='name')}!\"\n    )\n    first_name = LiteralStringVar.create(\"Steven\")\n    last_name = LiteralStringVar.create(\"Universe\")\n    assert (\n        str(create_hello_statement.call(f\"{first_name} {last_name}\"))\n        == '(((name) => (\"Hello, \"+name+\"!\"))(\"Steven Universe\"))'\n    )\n\n    # Test with destructured arguments\n    destructured_func = ArgsFunctionOperation.create(\n        (DestructuredArg(fields=(\"a\", \"b\")),),\n        Var(_js_expr=\"a + b\"),\n    )\n    assert (\n        str(destructured_func.call({\"a\": 1, \"b\": 2}))\n        == '((({a, b}) => a + b)(({ [\"a\"] : 1, [\"b\"] : 2 })))'\n    )\n\n    # Test with explicit return\n    explicit_return_func = ArgsFunctionOperation.create(\n        (\"a\", \"b\"), Var(_js_expr=\"return a + b\"), explicit_return=True\n    )\n    assert str(explicit_return_func.call(1, 2)) == \"(((a, b) => {return a + b})(1, 2))\"\n\n\ndef test_var_operation():\n    @var_operation\n    def add(a: NumberVar | int, b: NumberVar | int):\n        return var_operation_return(js_expression=f\"({a} + {b})\", var_type=int)\n\n    assert str(add(1, 2)) == \"(1 + 2)\"\n    assert str(add(a=4, b=-9)) == \"(4 + -9)\"\n\n    five = LiteralNumberVar.create(5)\n    seven = add(2, five)\n\n    assert isinstance(seven, NumberVar)\n\n\ndef test_string_operations():\n    basic_string = LiteralStringVar.create(\"Hello, World!\")\n\n    assert str(basic_string.length()) == '\"Hello, World!\".split(\"\").length'\n    assert str(basic_string.lower()) == '\"Hello, World!\".toLowerCase()'\n    assert str(basic_string.upper()) == '\"Hello, World!\".toUpperCase()'\n    assert str(basic_string.strip()) == '\"Hello, World!\".trim()'\n    assert str(basic_string.contains(\"World\")) == '\"Hello, World!\".includes(\"World\")'\n    assert (\n        str(basic_string.split(\" \").join(\",\")) == '\"Hello, World!\".split(\" \").join(\",\")'\n    )\n\n\ndef test_all_number_operations():\n    starting_number = LiteralNumberVar.create(-5.4)\n\n    complicated_number = (((-(starting_number + 1)) * 2 / 3) // 2 % 3) ** 2\n\n    assert (\n        str(complicated_number)\n        == \"((Math.floor(((-((-5.4 + 1)) * 2) / 3) / 2) % 3) ** 2)\"\n    )\n\n    even_more_complicated_number = ~(\n        abs(math.floor(complicated_number)) | 2 & 3 & round(complicated_number)\n    )\n\n    assert (\n        str(even_more_complicated_number)\n        == \"!(isTrue((Math.abs(Math.floor(((Math.floor(((-((-5.4 + 1)) * 2) / 3) / 2) % 3) ** 2))) || (2 && Math.round(((Math.floor(((-((-5.4 + 1)) * 2) / 3) / 2) % 3) ** 2))))))\"\n    )\n\n    assert str(LiteralNumberVar.create(5) > False) == \"(5 > 0)\"\n    assert str(LiteralBooleanVar.create(False) < 5) == \"(Number(false) < 5)\"\n    assert (\n        str(LiteralBooleanVar.create(False) < LiteralBooleanVar.create(True))\n        == \"(Number(false) < Number(true))\"\n    )\n\n\n@pytest.mark.parametrize(\n    (\"var\", \"expected\"),\n    [\n        (Var.create(False), \"false\"),\n        (Var.create(True), \"true\"),\n        (Var.create(\"false\"), 'isTrue(\"false\")'),\n        (Var.create([1, 2, 3]), \"isTrue([1, 2, 3])\"),\n        (Var.create({\"a\": 1, \"b\": 2}), 'isTrue(({ [\"a\"] : 1, [\"b\"] : 2 }))'),\n        (Var(\"mysterious_var\"), \"isTrue(mysterious_var)\"),\n    ],\n)\ndef test_boolify_operations(var, expected):\n    assert str(var.bool()) == expected\n\n\ndef test_index_operation():\n    array_var = LiteralArrayVar.create([1, 2, 3, 4, 5])\n    assert str(array_var[0]) == \"[1, 2, 3, 4, 5]?.at?.(0)\"\n    assert str(array_var[1:2]) == \"[1, 2, 3, 4, 5].slice(1, 2)\"\n    assert (\n        str(array_var[1:4:2])\n        == \"[1, 2, 3, 4, 5].slice(1, 4).filter((_, i) => i % 2 === 0)\"\n    )\n    assert (\n        str(array_var[::-1])\n        == \"[1, 2, 3, 4, 5].slice(0, [1, 2, 3, 4, 5].length).slice().reverse().slice(undefined, undefined).filter((_, i) => i % 1 === 0)\"\n    )\n    assert str(array_var.reverse()) == \"[1, 2, 3, 4, 5].slice().reverse()\"\n    assert str(array_var[0].to(NumberVar) + 9) == \"([1, 2, 3, 4, 5]?.at?.(0) + 9)\"\n\n\n@pytest.mark.parametrize(\n    (\"var\", \"expected_js\"),\n    [\n        (Var.create(float(\"inf\")), \"Infinity\"),\n        (Var.create(-float(\"inf\")), \"-Infinity\"),\n        (Var.create(float(\"nan\")), \"NaN\"),\n    ],\n)\ndef test_inf_and_nan(var, expected_js):\n    assert str(var) == expected_js\n    assert isinstance(var, NumberVar)\n    assert isinstance(var, LiteralVar)\n    with pytest.raises(PrimitiveUnserializableToJSONError):\n        var.json()\n\n\ndef test_array_operations():\n    array_var = LiteralArrayVar.create([1, 2, 3, 4, 5])\n\n    assert str(array_var.length()) == \"[1, 2, 3, 4, 5].length\"\n    assert str(array_var.contains(3)) == \"[1, 2, 3, 4, 5].includes(3)\"\n    assert str(array_var.reverse()) == \"[1, 2, 3, 4, 5].slice().reverse()\"\n    assert (\n        str(ArrayVar.range(10))\n        == \"Array.from({ length: Math.ceil((10 - 0) / 1) }, (_, i) => 0 + i * 1)\"\n    )\n    assert (\n        str(ArrayVar.range(1, 10))\n        == \"Array.from({ length: Math.ceil((10 - 1) / 1) }, (_, i) => 1 + i * 1)\"\n    )\n    assert (\n        str(ArrayVar.range(1, 10, 2))\n        == \"Array.from({ length: Math.ceil((10 - 1) / 2) }, (_, i) => 1 + i * 2)\"\n    )\n    assert (\n        str(ArrayVar.range(1, 10, -1))\n        == \"Array.from({ length: Math.ceil((10 - 1) / -1) }, (_, i) => 1 + i * -1)\"\n    )\n\n\ndef test_object_operations():\n    object_var = LiteralObjectVar.create({\"a\": 1, \"b\": 2, \"c\": 3})\n\n    assert (\n        str(object_var.keys())\n        == 'Object.keys(({ [\"a\"] : 1, [\"b\"] : 2, [\"c\"] : 3 }) ?? {})'\n    )\n    assert (\n        str(object_var.values())\n        == 'Object.values(({ [\"a\"] : 1, [\"b\"] : 2, [\"c\"] : 3 }) ?? {})'\n    )\n    assert (\n        str(object_var.entries())\n        == 'Object.entries(({ [\"a\"] : 1, [\"b\"] : 2, [\"c\"] : 3 }) ?? {})'\n    )\n    assert str(object_var.a) == '({ [\"a\"] : 1, [\"b\"] : 2, [\"c\"] : 3 })?.[\"a\"]'\n    assert str(object_var[\"a\"]) == '({ [\"a\"] : 1, [\"b\"] : 2, [\"c\"] : 3 })?.[\"a\"]'\n    assert (\n        str(object_var.merge(LiteralObjectVar.create({\"c\": 4, \"d\": 5})))\n        == '({...({ [\"a\"] : 1, [\"b\"] : 2, [\"c\"] : 3 }), ...({ [\"c\"] : 4, [\"d\"] : 5 })})'\n    )\n\n\ndef test_var_component():\n    class ComponentVarState(rx.State):\n        field_var: rx.Field[rx.Component] = rx.field(rx.text(\"I am a field var\"))\n\n        @rx.var\n        def computed_var(self) -> rx.Component:\n            return rx.text(\"I am a computed var\")\n\n    def has_eval_react_component(var: Var):\n        var_data = var._get_all_var_data()\n        assert var_data is not None\n        assert any(\n            any(\n                imported_object.name == \"evalReactComponent\"\n                for imported_object in imported_objects\n            )\n            for _, imported_objects in var_data.imports\n        )\n\n    has_eval_react_component(ComponentVarState.field_var)\n    has_eval_react_component(ComponentVarState.computed_var)\n\n\ndef test_type_chains():\n    object_var = LiteralObjectVar.create({\"a\": 1, \"b\": 2, \"c\": 3})\n    assert (object_var._key_type(), object_var._value_type()) == (str, int)\n    assert (object_var.keys()._var_type, object_var.values()._var_type) == (\n        list[str],\n        list[int],\n    )\n    assert (\n        str(object_var.keys()[0].upper())\n        == 'Object.keys(({ [\"a\"] : 1, [\"b\"] : 2, [\"c\"] : 3 }) ?? {})?.at?.(0).toUpperCase()'\n    )\n    assert (\n        str(object_var.entries()[1][1] - 1)\n        == '(Object.entries(({ [\"a\"] : 1, [\"b\"] : 2, [\"c\"] : 3 }) ?? {})?.at?.(1)?.at?.(1) - 1)'\n    )\n    assert (\n        str(object_var[\"c\"] + object_var[\"b\"])  # pyright: ignore [reportCallIssue, reportOperatorIssue]\n        == '(({ [\"a\"] : 1, [\"b\"] : 2, [\"c\"] : 3 })?.[\"c\"] + ({ [\"a\"] : 1, [\"b\"] : 2, [\"c\"] : 3 })?.[\"b\"])'\n    )\n\n\ndef test_nested_dict():\n    arr = LiteralArrayVar.create([{\"bar\": [\"foo\", \"bar\"]}], list[dict[str, list[str]]])\n\n    assert (\n        str(arr[0][\"bar\"][0])\n        == '[({ [\"bar\"] : [\"foo\", \"bar\"] })]?.at?.(0)?.[\"bar\"]?.at?.(0)'  # pyright: ignore [reportIndexIssue]\n    )\n\n\ndef nested_base():\n    class Boo(Base):\n        foo: str\n        bar: int\n\n    class Foo(Base):\n        bar: Boo\n        baz: int\n\n    parent_obj = LiteralObjectVar.create(\n        Foo(bar=Boo(foo=\"bar\", bar=5), baz=5).dict(), Foo\n    )\n\n    assert (\n        str(parent_obj.bar.foo)\n        == '({ [\"bar\"] : ({ [\"foo\"] : \"bar\", [\"bar\"] : 5 }), [\"baz\"] : 5 })[\"bar\"][\"foo\"]'\n    )\n\n\ndef test_retrieval():\n    var_without_data = Var(_js_expr=\"test\")\n    assert var_without_data is not None\n\n    original_var_data = VarData(\n        state=\"Test\",\n        imports={\"react\": [ImportVar(tag=\"useRef\")]},\n        hooks={\"const state = useContext(StateContexts.state)\": None},\n    )\n\n    var_with_data = var_without_data._replace(merge_var_data=original_var_data)\n\n    f_string = f\"foo{var_with_data}bar\"\n\n    assert REFLEX_VAR_OPENING_TAG in f_string\n    assert REFLEX_VAR_CLOSING_TAG in f_string\n\n    result_var_data = LiteralVar.create(f_string)._get_all_var_data()\n    result_immutable_var_data = Var(_js_expr=f_string)._var_data\n    assert result_var_data is not None\n    assert result_immutable_var_data is not None\n    assert (\n        result_var_data.state\n        == result_immutable_var_data.state\n        == original_var_data.state\n    )\n    assert (\n        result_var_data.imports\n        == result_immutable_var_data.imports\n        == original_var_data.imports\n    )\n    assert (\n        tuple(result_var_data.hooks)\n        == tuple(result_immutable_var_data.hooks)\n        == tuple(original_var_data.hooks)\n    )\n\n\ndef test_fstring_concat():\n    original_var_with_data = LiteralVar.create(\n        \"imagination\", _var_data=VarData(state=\"fear\")\n    )\n\n    immutable_var_with_data = Var(\n        _js_expr=\"consequences\",\n        _var_data=VarData(\n            imports={\n                \"react\": [ImportVar(tag=\"useRef\")],\n                \"utils\": [ImportVar(tag=\"useEffect\")],\n            }\n        ),\n    )\n\n    f_string = f\"foo{original_var_with_data}bar{immutable_var_with_data}baz\"\n\n    string_concat = LiteralStringVar.create(\n        f_string,\n        _var_data=VarData(\n            hooks={\"const state = useContext(StateContexts.state)\": None}\n        ),\n    )\n\n    assert str(string_concat) == '(\"fooimaginationbar\"+consequences+\"baz\")'\n    assert isinstance(string_concat, ConcatVarOperation)\n    assert string_concat._get_all_var_data() == VarData(\n        state=\"fear\",\n        imports={\n            \"react\": [ImportVar(tag=\"useRef\")],\n            \"utils\": [ImportVar(tag=\"useEffect\")],\n        },\n        hooks={\"const state = useContext(StateContexts.state)\": None},\n    )\n\n\nvar = Var(_js_expr=\"var\", _var_type=str)\nmyvar = Var(_js_expr=\"myvar\", _var_type=int)._var_set_state(\"state\")\nx = Var(_js_expr=\"x\", _var_type=str)\n\n\n@pytest.mark.parametrize(\n    (\"out\", \"expected\"),\n    [\n        (f\"{var}\", f\"<reflex.Var>{hash(var)}</reflex.Var>var\"),\n        (\n            f\"testing f-string with {myvar}\",\n            f\"testing f-string with <reflex.Var>{hash(myvar)}</reflex.Var>state.myvar\",\n        ),\n        (\n            f\"testing local f-string {x}\",\n            f\"testing local f-string <reflex.Var>{hash(x)}</reflex.Var>x\",\n        ),\n    ],\n)\ndef test_fstrings(out, expected):\n    assert out == expected\n\n\n@pytest.mark.parametrize(\n    (\"value\", \"expect_state\"),\n    [\n        ([1], \"\"),\n        ({\"a\": 1}, \"\"),\n        ([LiteralVar.create(1)._var_set_state(\"foo\")], \"foo\"),\n        ({\"a\": LiteralVar.create(1)._var_set_state(\"foo\")}, \"foo\"),\n    ],\n)\ndef test_extract_state_from_container(value, expect_state):\n    \"\"\"Test that _var_state is extracted from containers containing BaseVar.\n\n    Args:\n        value: The value to create a var from.\n        expect_state: The expected state.\n    \"\"\"\n    var_data = LiteralVar.create(value)._get_all_var_data()\n    var_state = var_data.state if var_data else \"\"\n    assert var_state == expect_state\n\n\n@pytest.mark.parametrize(\n    \"value\",\n    [\n        \"var\",\n        \"\\nvar\",\n    ],\n)\ndef test_fstring_roundtrip(value):\n    \"\"\"Test that f-string roundtrip carries state.\n\n    Args:\n        value: The value to create a Var from.\n    \"\"\"\n    var = Var(_js_expr=value)._var_set_state(\"state\")\n    rt_var = LiteralVar.create(f\"{var}\")\n    assert var._var_state == rt_var._var_state\n    assert str(rt_var) == str(var)\n\n\n@pytest.mark.parametrize(\n    \"var\",\n    [\n        Var(_js_expr=\"var\", _var_type=int).guess_type(),\n        Var(_js_expr=\"var\", _var_type=float).guess_type(),\n        Var(_js_expr=\"var\", _var_type=str).guess_type(),\n        Var(_js_expr=\"var\", _var_type=bool).guess_type(),\n        Var(_js_expr=\"var\", _var_type=None).guess_type(),\n    ],\n)\ndef test_unsupported_types_for_reverse(var):\n    \"\"\"Test that unsupported types for reverse throw a type error.\n\n    Args:\n        var: The base var.\n    \"\"\"\n    with pytest.raises(TypeError) as err:\n        var.reverse()\n    assert err.value.args[0] == \"Cannot reverse non-list var.\"\n\n\n@pytest.mark.parametrize(\n    \"var\",\n    [\n        Var(_js_expr=\"var\", _var_type=int).guess_type(),\n        Var(_js_expr=\"var\", _var_type=float).guess_type(),\n        Var(_js_expr=\"var\", _var_type=bool).guess_type(),\n        Var(_js_expr=\"var\", _var_type=type(None)).guess_type(),\n    ],\n)\ndef test_unsupported_types_for_contains(var: Var):\n    \"\"\"Test that unsupported types for contains throw a type error.\n\n    Args:\n        var: The base var.\n    \"\"\"\n    with pytest.raises(TypeError) as err:\n        assert var.contains(1)  # pyright: ignore [reportAttributeAccessIssue]\n    assert (\n        err.value.args[0]\n        == f\"Var of type {var._var_type} does not support contains check.\"\n    )\n\n\n@pytest.mark.parametrize(\n    \"other\",\n    [\n        Var(_js_expr=\"other\", _var_type=int).guess_type(),\n        Var(_js_expr=\"other\", _var_type=float).guess_type(),\n        Var(_js_expr=\"other\", _var_type=bool).guess_type(),\n        Var(_js_expr=\"other\", _var_type=list).guess_type(),\n        Var(_js_expr=\"other\", _var_type=dict).guess_type(),\n        Var(_js_expr=\"other\", _var_type=tuple).guess_type(),\n        Var(_js_expr=\"other\", _var_type=set).guess_type(),\n    ],\n)\ndef test_unsupported_types_for_string_contains(other):\n    with pytest.raises(TypeError) as err:\n        assert Var(_js_expr=\"var\").to(str).contains(other)\n    assert (\n        err.value.args[0]\n        == f\"Unsupported Operand type(s) for contains: StringCastedVar, {type(other).__name__}\"\n    )\n\n\ndef test_unsupported_default_contains():\n    with pytest.raises(TypeError) as err:\n        assert 1 in Var(_js_expr=\"var\", _var_type=str).guess_type()  # pyright: ignore [reportOperatorIssue]\n    assert (\n        err.value.args[0]\n        == \"'in' operator not supported for Var types, use Var.contains() instead.\"\n    )\n\n\n@pytest.mark.parametrize(\n    (\"operand1_var\", \"operand2_var\", \"operators\"),\n    [\n        (\n            LiteralVar.create(10),\n            LiteralVar.create(5),\n            [\n                \"+\",\n                \"-\",\n                \"/\",\n                \"//\",\n                \"*\",\n                \"%\",\n                \"**\",\n                \">\",\n                \"<\",\n                \"<=\",\n                \">=\",\n                \"|\",\n                \"&\",\n            ],\n        ),\n        (\n            LiteralVar.create(10.5),\n            LiteralVar.create(5),\n            [\"+\", \"-\", \"/\", \"//\", \"*\", \"%\", \"**\", \">\", \"<\", \"<=\", \">=\"],\n        ),\n        (\n            LiteralVar.create(5),\n            LiteralVar.create(True),\n            [\n                \"+\",\n                \"-\",\n                \"/\",\n                \"//\",\n                \"*\",\n                \"%\",\n                \"**\",\n                \">\",\n                \"<\",\n                \"<=\",\n                \">=\",\n                \"|\",\n                \"&\",\n            ],\n        ),\n        (\n            LiteralVar.create(10.5),\n            LiteralVar.create(5.5),\n            [\"+\", \"-\", \"/\", \"//\", \"*\", \"%\", \"**\", \">\", \"<\", \"<=\", \">=\"],\n        ),\n        (\n            LiteralVar.create(10.5),\n            LiteralVar.create(True),\n            [\"+\", \"-\", \"/\", \"//\", \"*\", \"%\", \"**\", \">\", \"<\", \"<=\", \">=\"],\n        ),\n        (LiteralVar.create(\"10\"), LiteralVar.create(\"5\"), [\"+\", \">\", \"<\", \"<=\", \">=\"]),\n        (\n            LiteralVar.create([10, 20]),\n            LiteralVar.create([5, 6]),\n            [\"+\", \">\", \"<\", \"<=\", \">=\"],\n        ),\n        (LiteralVar.create([10, 20]), LiteralVar.create(5), [\"*\"]),\n        (LiteralVar.create([10, 20]), LiteralVar.create(True), [\"*\"]),\n        (\n            LiteralVar.create(True),\n            LiteralVar.create(True),\n            [\n                \"+\",\n                \"-\",\n                \"/\",\n                \"//\",\n                \"*\",\n                \"%\",\n                \"**\",\n                \">\",\n                \"<\",\n                \"<=\",\n                \">=\",\n                \"|\",\n                \"&\",\n            ],\n        ),\n    ],\n)\ndef test_valid_var_operations(operand1_var: Var, operand2_var, operators: list[str]):\n    \"\"\"Test that operations do not raise a TypeError.\n\n    Args:\n        operand1_var: left operand.\n        operand2_var: right operand.\n        operators: list of supported operators.\n    \"\"\"\n    for operator in operators:\n        print(\n            \"testing\",\n            operator,\n            \"on\",\n            operand1_var,\n            operand2_var,\n            \" of types\",\n            type(operand1_var),\n            type(operand2_var),\n        )\n        eval(f\"operand1_var {operator} operand2_var\")\n        eval(f\"operand2_var {operator} operand1_var\")\n\n\n@pytest.mark.parametrize(\n    (\"operand1_var\", \"operand2_var\", \"operators\"),\n    [\n        (\n            LiteralVar.create(10),\n            LiteralVar.create(5),\n            [\n                \"^\",\n                \"<<\",\n                \">>\",\n            ],\n        ),\n        (\n            LiteralVar.create(10.5),\n            LiteralVar.create(5),\n            [\n                \"^\",\n                \"<<\",\n                \">>\",\n            ],\n        ),\n        (\n            LiteralVar.create(10.5),\n            LiteralVar.create(True),\n            [\n                \"^\",\n                \"<<\",\n                \">>\",\n            ],\n        ),\n        (\n            LiteralVar.create(10.5),\n            LiteralVar.create(5.5),\n            [\n                \"^\",\n                \"<<\",\n                \">>\",\n            ],\n        ),\n        (\n            LiteralVar.create(\"10\"),\n            LiteralVar.create(\"5\"),\n            [\n                \"-\",\n                \"/\",\n                \"//\",\n                \"*\",\n                \"%\",\n                \"**\",\n                \"^\",\n                \"<<\",\n                \">>\",\n            ],\n        ),\n        (\n            LiteralVar.create([10, 20]),\n            LiteralVar.create([5, 6]),\n            [\n                \"-\",\n                \"/\",\n                \"//\",\n                \"*\",\n                \"%\",\n                \"**\",\n                \"^\",\n                \"<<\",\n                \">>\",\n            ],\n        ),\n        (\n            LiteralVar.create([10, 20]),\n            LiteralVar.create(5),\n            [\n                \"+\",\n                \"-\",\n                \"/\",\n                \"//\",\n                \"%\",\n                \"**\",\n                \">\",\n                \"<\",\n                \"<=\",\n                \">=\",\n                \"^\",\n                \"<<\",\n                \">>\",\n            ],\n        ),\n        (\n            LiteralVar.create([10, 20]),\n            LiteralVar.create(True),\n            [\n                \"+\",\n                \"-\",\n                \"/\",\n                \"//\",\n                \"%\",\n                \"**\",\n                \">\",\n                \"<\",\n                \"<=\",\n                \">=\",\n                \"^\",\n                \"<<\",\n                \">>\",\n            ],\n        ),\n        (\n            LiteralVar.create([10, 20]),\n            LiteralVar.create(\"5\"),\n            [\n                \"+\",\n                \"-\",\n                \"/\",\n                \"//\",\n                \"*\",\n                \"%\",\n                \"**\",\n                \">\",\n                \"<\",\n                \"<=\",\n                \">=\",\n                \"^\",\n                \"<<\",\n                \">>\",\n            ],\n        ),\n        (\n            LiteralVar.create([10, 20]),\n            LiteralVar.create({\"key\": \"value\"}),\n            [\n                \"+\",\n                \"-\",\n                \"/\",\n                \"//\",\n                \"*\",\n                \"%\",\n                \"**\",\n                \">\",\n                \"<\",\n                \"<=\",\n                \">=\",\n                \"^\",\n                \"<<\",\n                \">>\",\n            ],\n        ),\n        (\n            LiteralVar.create([10, 20]),\n            LiteralVar.create(5.5),\n            [\n                \"+\",\n                \"-\",\n                \"/\",\n                \"//\",\n                \"*\",\n                \"%\",\n                \"**\",\n                \">\",\n                \"<\",\n                \"<=\",\n                \">=\",\n                \"^\",\n                \"<<\",\n                \">>\",\n            ],\n        ),\n        (\n            LiteralVar.create({\"key\": \"value\"}),\n            LiteralVar.create({\"another_key\": \"another_value\"}),\n            [\n                \"+\",\n                \"-\",\n                \"/\",\n                \"//\",\n                \"*\",\n                \"%\",\n                \"**\",\n                \">\",\n                \"<\",\n                \"<=\",\n                \">=\",\n                \"^\",\n                \"<<\",\n                \">>\",\n            ],\n        ),\n        (\n            LiteralVar.create({\"key\": \"value\"}),\n            LiteralVar.create(5),\n            [\n                \"+\",\n                \"-\",\n                \"/\",\n                \"//\",\n                \"*\",\n                \"%\",\n                \"**\",\n                \">\",\n                \"<\",\n                \"<=\",\n                \">=\",\n                \"^\",\n                \"<<\",\n                \">>\",\n            ],\n        ),\n        (\n            LiteralVar.create({\"key\": \"value\"}),\n            LiteralVar.create(True),\n            [\n                \"+\",\n                \"-\",\n                \"/\",\n                \"//\",\n                \"*\",\n                \"%\",\n                \"**\",\n                \">\",\n                \"<\",\n                \"<=\",\n                \">=\",\n                \"^\",\n                \"<<\",\n                \">>\",\n            ],\n        ),\n        (\n            LiteralVar.create({\"key\": \"value\"}),\n            LiteralVar.create(5.5),\n            [\n                \"+\",\n                \"-\",\n                \"/\",\n                \"//\",\n                \"*\",\n                \"%\",\n                \"**\",\n                \">\",\n                \"<\",\n                \"<=\",\n                \">=\",\n                \"^\",\n                \"<<\",\n                \">>\",\n            ],\n        ),\n        (\n            LiteralVar.create({\"key\": \"value\"}),\n            LiteralVar.create(\"5\"),\n            [\n                \"+\",\n                \"-\",\n                \"/\",\n                \"//\",\n                \"*\",\n                \"%\",\n                \"**\",\n                \">\",\n                \"<\",\n                \"<=\",\n                \">=\",\n                \"^\",\n                \"<<\",\n                \">>\",\n            ],\n        ),\n    ],\n)\ndef test_invalid_var_operations(operand1_var: Var, operand2_var, operators: list[str]):\n    for operator in operators:\n        print(f\"testing {operator} on {operand1_var!s} and {operand2_var!s}\")\n        with pytest.raises(TypeError):\n            print(eval(f\"operand1_var {operator} operand2_var\"))\n\n        with pytest.raises(TypeError):\n            print(eval(f\"operand2_var {operator} operand1_var\"))\n\n\n@pytest.mark.parametrize(\n    (\"var\", \"expected\"),\n    [\n        (LiteralVar.create(\"string_value\"), '\"string_value\"'),\n        (LiteralVar.create(1), \"1\"),\n        (LiteralVar.create([1, 2, 3]), \"[1, 2, 3]\"),\n        (LiteralVar.create({\"foo\": \"bar\"}), '({ [\"foo\"] : \"bar\" })'),\n        (\n            LiteralVar.create(ATestState.value),\n            f\"{ATestState.get_full_name()}.value\" + FIELD_MARKER,\n        ),\n        (\n            LiteralVar.create(f\"{ATestState.value} string\"),\n            f'({ATestState.get_full_name()}.value{FIELD_MARKER}+\" string\")',\n        ),\n        (\n            LiteralVar.create(ATestState.dict_val),\n            f\"{ATestState.get_full_name()}.dict_val\" + FIELD_MARKER,\n        ),\n    ],\n)\ndef test_var_name_unwrapped(var, expected):\n    assert str(var) == expected\n\n\ndef cv_fget(state: BaseState) -> int:\n    return 1\n\n\n@pytest.mark.parametrize(\n    (\"deps\", \"expected\"),\n    [\n        ([\"a\"], {None: {\"a\"}}),\n        ([\"b\"], {None: {\"b\"}}),\n        ([ComputedVar(fget=cv_fget)], {None: {\"cv_fget\"}}),\n    ],\n)\ndef test_computed_var_deps(deps: list[str | Var], expected: set[str]):\n    @computed_var(deps=deps)\n    def test_var(state) -> int:\n        return 1\n\n    assert test_var._static_deps == expected\n\n\n@pytest.mark.parametrize(\n    \"deps\",\n    [\n        [\"\"],\n        [1],\n        [\"\", \"abc\"],\n    ],\n)\ndef test_invalid_computed_var_deps(deps: list):\n    with pytest.raises(TypeError):\n\n        @computed_var(deps=deps)\n        def test_var(state) -> int:\n            return 1\n\n\ndef test_to_string_operation():\n    class Email(str): ...\n\n    class TestState(BaseState):\n        optional_email: Email | None = None\n        email: Email = Email(\"test@reflex.dev\")\n\n    assert (\n        str(TestState.optional_email)\n        == f\"{TestState.get_full_name()}.optional_email\" + FIELD_MARKER\n    )\n    my_state = TestState()\n    assert my_state.optional_email is None\n    assert my_state.email == \"test@reflex.dev\"\n\n    assert cast(Var, TestState.email)._var_type == Email\n    assert cast(Var, TestState.optional_email)._var_type == Email | None\n\n    single_var = Var.create(Email())\n    assert single_var._var_type == Email\n\n\n@pytest.mark.asyncio\nasync def test_async_computed_var():\n    side_effect_counter = 0\n\n    class AsyncComputedVarState(BaseState):\n        v: int = 1\n\n        @computed_var(cache=True)\n        async def async_computed_var(self) -> int:\n            nonlocal side_effect_counter\n            side_effect_counter += 1\n            return self.v + 1\n\n    my_state = AsyncComputedVarState()\n    assert await my_state.async_computed_var == 2\n    assert await my_state.async_computed_var == 2\n    my_state.v = 2\n    assert await my_state.async_computed_var == 3\n    assert await my_state.async_computed_var == 3\n    assert side_effect_counter == 2\n\n\ndef test_var_data_hooks():\n    var_data_str = VarData(hooks=\"what\")\n    var_data_list = VarData(hooks=[\"what\"])\n    var_data_dict = VarData(hooks={\"what\": None})\n    assert var_data_str == var_data_list == var_data_dict\n\n    var_data_list_multiple = VarData(hooks=[\"what\", \"whot\"])\n    var_data_dict_multiple = VarData(hooks={\"what\": None, \"whot\": None})\n    assert var_data_list_multiple == var_data_dict_multiple\n\n\ndef test_var_data_with_hooks_value():\n    var_data = VarData(hooks={\"what\": VarData(hooks={\"whot\": VarData(hooks=\"whott\")})})\n    assert var_data == VarData(hooks=[\"whott\", \"whot\", \"what\"])\n\n\ndef test_str_var_in_components(mocker: MockerFixture):\n    class StateWithVar(rx.State):\n        field: int = 1\n\n    mocker.patch(\n        \"reflex.components.base.bare.get_performance_mode\",\n        return_value=PerformanceMode.RAISE,\n    )\n\n    with pytest.raises(ValueError):\n        rx.vstack(\n            str(StateWithVar.field),\n        )\n\n    mocker.patch(\n        \"reflex.components.base.bare.get_performance_mode\",\n        return_value=PerformanceMode.OFF,\n    )\n\n    rx.vstack(\n        str(StateWithVar.field),\n    )\n\n\ndef test_decimal_number_operations():\n    \"\"\"Test that decimal.Decimal values work with NumberVar operations.\"\"\"\n    dec_num = Var.create(decimal.Decimal(\"123.456\"))\n    assert isinstance(dec_num._var_value, decimal.Decimal)\n    assert str(dec_num) == \"123.456\"\n\n    result = dec_num + 10\n    assert str(result) == \"(123.456 + 10)\"\n\n    result = dec_num * 2\n    assert str(result) == \"(123.456 * 2)\"\n\n    result = dec_num / 2\n    assert str(result) == \"(123.456 / 2)\"\n\n    result = dec_num > 100\n    assert str(result) == \"(123.456 > 100)\"\n\n    result = dec_num < 200\n    assert str(result) == \"(123.456 < 200)\"\n\n    assert dec_num.json() == \"123.456\"\n\n\ndef test_decimal_var_type_compatibility():\n    \"\"\"Test that decimal.Decimal values are compatible with NumberVar type system.\"\"\"\n    dec_num = Var.create(decimal.Decimal(\"123.456\"))\n    int_num = Var.create(42)\n    float_num = Var.create(3.15)\n\n    result = dec_num + int_num\n    assert str(result) == \"(123.456 + 42)\"\n\n    result = dec_num * float_num\n    assert str(result) == \"(123.456 * 3.15)\"\n\n    result = (dec_num + int_num) / float_num\n    assert str(result) == \"((123.456 + 42) / 3.15)\"\n\n\ndef test_computed_var_type_compatibility():\n    \"\"\"Test that different ComputedVar are compatible with Var annotations of their returned type.\"\"\"\n\n    class ComputedVarTypeState(BaseState):\n        @computed_var\n        def sync_plain(self) -> str:\n            return \"Hello\"\n\n        @computed_var(initial_value=\"Test\")\n        def sync_wrapper(self) -> str:\n            return \"World\"\n\n        @computed_var\n        async def async_plain(self) -> str:\n            return \"Hello\"\n\n        @computed_var(initial_value=\"Test\")\n        async def async_wrapper(self) -> str:\n            return \"World\"\n\n    # All of these vars should be assignable to a str field statically.\n    rx.input(placeholder=ComputedVarTypeState.sync_plain)\n    rx.input(placeholder=ComputedVarTypeState.sync_wrapper)\n    rx.input(placeholder=ComputedVarTypeState.async_plain)\n    rx.input(placeholder=ComputedVarTypeState.async_wrapper)\n"
  },
  {
    "path": "tests/units/utils/__init__.py",
    "content": ""
  },
  {
    "path": "tests/units/utils/test_format.py",
    "content": "from __future__ import annotations\n\nimport datetime\nimport json\nfrom typing import Any\n\nimport plotly.graph_objects as go\nimport pytest\n\nfrom reflex.components.tags.tag import Tag\nfrom reflex.constants.state import FIELD_MARKER\nfrom reflex.event import (\n    EventChain,\n    EventHandler,\n    EventSpec,\n    JavascriptInputEvent,\n    no_args_event_spec,\n)\nfrom reflex.style import Style\nfrom reflex.utils import format\nfrom reflex.utils.serializers import serialize_figure\nfrom reflex.vars.base import LiteralVar, Var\nfrom reflex.vars.object import ObjectVar\n\npytest.importorskip(\"pydantic\")\n\n\nfrom tests.units.test_state import (\n    ChildState,\n    ChildState2,\n    ChildState3,\n    DateTimeState,\n    GrandchildState,\n    GrandchildState2,\n    GrandchildState3,\n    TestState,\n)\n\n\ndef mock_event(arg):\n    pass\n\n\n@pytest.mark.parametrize(\n    (\"input\", \"output\"),\n    [\n        (\"{\", \"}\"),\n        (\"(\", \")\"),\n        (\"[\", \"]\"),\n        (\"<\", \">\"),\n        ('\"', '\"'),\n        (\"'\", \"'\"),\n    ],\n)\ndef test_get_close_char(input: str, output: str):\n    \"\"\"Test getting the close character for a given open character.\n\n    Args:\n        input: The open character.\n        output: The expected close character.\n    \"\"\"\n    assert format.get_close_char(input) == output\n\n\n@pytest.mark.parametrize(\n    (\"text\", \"open\", \"expected\"),\n    [\n        (\"\", \"{\", False),\n        (\"{wrap}\", \"{\", True),\n        (\"{wrap\", \"{\", False),\n        (\"{wrap}\", \"(\", False),\n        (\"(wrap)\", \"(\", True),\n    ],\n)\ndef test_is_wrapped(text: str, open: str, expected: bool):\n    \"\"\"Test checking if a string is wrapped in the given open and close characters.\n\n    Args:\n        text: The text to check.\n        open: The open character.\n        expected: Whether the text is wrapped.\n    \"\"\"\n    assert format.is_wrapped(text, open) == expected\n\n\n@pytest.mark.parametrize(\n    (\"text\", \"open\", \"check_first\", \"num\", \"expected\"),\n    [\n        (\"\", \"{\", True, 1, \"{}\"),\n        (\"wrap\", \"{\", True, 1, \"{wrap}\"),\n        (\"wrap\", \"(\", True, 1, \"(wrap)\"),\n        (\"wrap\", \"(\", True, 2, \"((wrap))\"),\n        (\"(wrap)\", \"(\", True, 1, \"(wrap)\"),\n        (\"{wrap}\", \"{\", True, 2, \"{wrap}\"),\n        (\"(wrap)\", \"{\", True, 1, \"{(wrap)}\"),\n        (\"(wrap)\", \"(\", False, 1, \"((wrap))\"),\n    ],\n)\ndef test_wrap(text: str, open: str, expected: str, check_first: bool, num: int):\n    \"\"\"Test wrapping a string.\n\n    Args:\n        text: The text to wrap.\n        open: The open character.\n        expected: The expected output string.\n        check_first: Whether to check if the text is already wrapped.\n        num: The number of times to wrap the text.\n    \"\"\"\n    assert format.wrap(text, open, check_first=check_first, num=num) == expected\n\n\n@pytest.mark.parametrize(\n    (\"string\", \"expected_output\"),\n    [\n        (\"This is a random string\", \"This is a random string\"),\n        (\n            \"This is a random string with `backticks`\",\n            \"This is a random string with \\\\`backticks\\\\`\",\n        ),\n        (\n            \"This is a string with ${someValue[`string interpolation`]} unescaped\",\n            \"This is a string with ${someValue[`string interpolation`]} unescaped\",\n        ),\n        (\n            \"This is a string with `backticks` and ${someValue[`string interpolation`]} unescaped\",\n            \"This is a string with \\\\`backticks\\\\` and ${someValue[`string interpolation`]} unescaped\",\n        ),\n        (\n            \"This is a string with `backticks`, ${someValue[`the first string interpolation`]} and ${someValue[`the second`]}\",\n            \"This is a string with \\\\`backticks\\\\`, ${someValue[`the first string interpolation`]} and ${someValue[`the second`]}\",\n        ),\n    ],\n)\ndef test_escape_js_string(string, expected_output):\n    assert format._escape_js_string(string) == expected_output\n\n\n@pytest.mark.parametrize(\n    (\"text\", \"indent_level\", \"expected\"),\n    [\n        (\"\", 2, \"\"),\n        (\"hello\", 2, \"hello\"),\n        (\"hello\\nworld\", 2, \"  hello\\n  world\\n\"),\n        (\"hello\\nworld\", 4, \"    hello\\n    world\\n\"),\n        (\"  hello\\n  world\", 2, \"    hello\\n    world\\n\"),\n    ],\n)\ndef test_indent(text: str, indent_level: int, expected: str, windows_platform: bool):\n    \"\"\"Test indenting a string.\n\n    Args:\n        text: The text to indent.\n        indent_level: The number of spaces to indent by.\n        expected: The expected output string.\n        windows_platform: Whether the system is windows.\n    \"\"\"\n    assert format.indent(text, indent_level) == (\n        expected.replace(\"\\n\", \"\\r\\n\") if windows_platform else expected\n    )\n\n\n@pytest.mark.parametrize(\n    (\"input\", \"output\"),\n    [\n        (\"\", \"\"),\n        (\"hello\", \"hello\"),\n        (\"Hello\", \"hello\"),\n        (\"camelCase\", \"camel_case\"),\n        (\"camelTwoHumps\", \"camel_two_humps\"),\n        (\"_start_with_underscore\", \"_start_with_underscore\"),\n        (\"__start_with_double_underscore\", \"__start_with_double_underscore\"),\n        (\"kebab-case\", \"kebab_case\"),\n        (\"double-kebab-case\", \"double_kebab_case\"),\n        (\":start-with-colon\", \":start_with_colon\"),\n        (\":-start-with-colon-dash\", \":_start_with_colon_dash\"),\n    ],\n)\ndef test_to_snake_case(input: str, output: str):\n    \"\"\"Test converting strings to snake case.\n\n    Args:\n        input: The input string.\n        output: The expected output string.\n    \"\"\"\n    assert format.to_snake_case(input) == output\n\n\n@pytest.mark.parametrize(\n    (\"input\", \"output\"),\n    [\n        (\"\", \"\"),\n        (\"hello\", \"hello\"),\n        (\"Hello\", \"Hello\"),\n        (\"snake_case\", \"snakeCase\"),\n        (\"snake_case_two\", \"snakeCaseTwo\"),\n        (\"kebab-case\", \"kebabCase\"),\n        (\"kebab-case-two\", \"kebabCaseTwo\"),\n        (\"snake_kebab-case\", \"snakeKebabCase\"),\n        (\"_hover\", \"Hover\"),\n        (\"-starts-with-hyphen\", \"StartsWithHyphen\"),\n        (\"--starts-with-double-hyphen\", \"StartsWithDoubleHyphen\"),\n        (\"_starts_with_underscore\", \"StartsWithUnderscore\"),\n        (\"__starts_with_double_underscore\", \"StartsWithDoubleUnderscore\"),\n        (\":start-with-colon\", \":startWithColon\"),\n        (\":-start-with-colon-dash\", \":StartWithColonDash\"),\n    ],\n)\ndef test_to_camel_case(input: str, output: str):\n    \"\"\"Test converting strings to camel case.\n\n    Args:\n        input: The input string.\n        output: The expected output string.\n    \"\"\"\n    assert format.to_camel_case(input) == output\n\n\n@pytest.mark.parametrize(\n    (\"input\", \"output\"),\n    [\n        (\"\", \"\"),\n        (\"hello\", \"Hello\"),\n        (\"Hello\", \"Hello\"),\n        (\"snake_case\", \"SnakeCase\"),\n        (\"snake_case_two\", \"SnakeCaseTwo\"),\n    ],\n)\ndef test_to_title_case(input: str, output: str):\n    \"\"\"Test converting strings to title case.\n\n    Args:\n        input: The input string.\n        output: The expected output string.\n    \"\"\"\n    assert format.to_title_case(input) == output\n\n\n@pytest.mark.parametrize(\n    (\"input\", \"output\"),\n    [\n        (\"\", \"\"),\n        (\"hello\", \"hello\"),\n        (\"Hello\", \"hello\"),\n        (\"snake_case\", \"snake-case\"),\n        (\"snake_case_two\", \"snake-case-two\"),\n        (\":startWithColon\", \":start-with-colon\"),\n        (\":StartWithColonDash\", \":-start-with-colon-dash\"),\n        (\":start_with_colon\", \":start-with-colon\"),\n        (\":_start_with_colon_dash\", \":-start-with-colon-dash\"),\n    ],\n)\ndef test_to_kebab_case(input: str, output: str):\n    \"\"\"Test converting strings to kebab case.\n\n    Args:\n        input: the input string.\n        output: the output string.\n    \"\"\"\n    assert format.to_kebab_case(input) == output\n\n\n@pytest.mark.parametrize(\n    (\"input\", \"output\"),\n    [\n        (\"\", \"{``}\"),\n        (\"hello\", \"{`hello`}\"),\n        (\"hello world\", \"{`hello world`}\"),\n        (\"hello=`world`\", \"{`hello=\\\\`world\\\\``}\"),\n    ],\n)\ndef test_format_string(input: str, output: str):\n    \"\"\"Test formatting the input as JS string literal.\n\n    Args:\n        input: the input string.\n        output: the output string.\n    \"\"\"\n    assert format.format_string(input) == output\n\n\n@pytest.mark.parametrize(\n    (\"input\", \"output\"),\n    [\n        (LiteralVar.create(value=\"test\"), '\"test\"'),\n        (Var(_js_expr=\"test\"), \"test\"),\n    ],\n)\ndef test_format_var(input: Var, output: str):\n    assert str(input) == output\n\n\n@pytest.mark.parametrize(\n    (\"route\", \"expected\"),\n    [\n        (\"\", \"index\"),\n        (\"/\", \"index\"),\n        (\"custom-route\", \"custom-route\"),\n        (\"custom-route/\", \"custom-route\"),\n        (\"/custom-route\", \"custom-route\"),\n        (\"/custom_route\", \"custom_route\"),\n        (\"/CUSTOM_route\", \"CUSTOM_route\"),\n    ],\n)\ndef test_format_route(route: str, expected: str):\n    \"\"\"Test formatting a route.\n\n    Args:\n        route: The route to format.\n        expected: The expected formatted route.\n    \"\"\"\n    assert format.format_route(route) == expected\n\n\n@pytest.mark.parametrize(\n    (\"condition\", \"match_cases\", \"default\", \"expected\"),\n    [\n        (\n            \"state__state.value\",\n            [\n                ([LiteralVar.create(1)], LiteralVar.create(\"red\")),\n                (\n                    [LiteralVar.create(2), LiteralVar.create(3)],\n                    LiteralVar.create(\"blue\"),\n                ),\n                ([TestState.mapping], TestState.num1),\n                (\n                    [LiteralVar.create(f\"{TestState.map_key}-key\")],\n                    LiteralVar.create(\"return-key\"),\n                ),\n            ],\n            LiteralVar.create(\"yellow\"),\n            (\n                '(() => { switch (JSON.stringify(state__state.value)) {case JSON.stringify(1):  return (\"red\");  break;case JSON.stringify(2): case JSON.stringify(3):  '\n                f'return (\"blue\");  break;case JSON.stringify({TestState.get_full_name()}.mapping{FIELD_MARKER}):  return '\n                f'({TestState.get_full_name()}.num1{FIELD_MARKER});  break;case JSON.stringify(({TestState.get_full_name()}.map_key{FIELD_MARKER}+\"-key\")):  return (\"return-key\");'\n                '  break;default:  return (\"yellow\");  break;};})()'\n            ),\n        )\n    ],\n)\ndef test_format_match(\n    condition: str,\n    match_cases: list[tuple[list[Var], Var]],\n    default: Var,\n    expected: str,\n):\n    \"\"\"Test formatting a match statement.\n\n    Args:\n        condition: The condition to match.\n        match_cases: List of match cases to be matched.\n        default: Catchall case for the match statement.\n        expected: The expected string output.\n    \"\"\"\n    assert format.format_match(condition, match_cases, default) == expected\n\n\n@pytest.mark.parametrize(\n    (\"prop\", \"formatted\"),\n    [\n        (\"string\", '\"string\"'),\n        (\"{wrapped_string}\", '\"{wrapped_string}\"'),\n        (True, \"true\"),\n        (False, \"false\"),\n        (123, \"123\"),\n        (3.15, \"3.15\"),\n        ([1, 2, 3], \"[1, 2, 3]\"),\n        ([\"a\", \"b\", \"c\"], '[\"a\", \"b\", \"c\"]'),\n        ({\"a\": 1, \"b\": 2, \"c\": 3}, '({ [\"a\"] : 1, [\"b\"] : 2, [\"c\"] : 3 })'),\n        ({\"a\": 'foo \"bar\" baz'}, r'({ [\"a\"] : \"foo \\\"bar\\\" baz\" })'),\n        (\n            {\n                \"a\": 'foo \"{ \"bar\" }\" baz',\n                \"b\": Var(_js_expr=\"val\", _var_type=str).guess_type(),\n            },\n            r'({ [\"a\"] : \"foo \\\"{ \\\"bar\\\" }\\\" baz\", [\"b\"] : val })',\n        ),\n        (\n            EventChain(\n                events=[EventSpec(handler=EventHandler(fn=mock_event))],\n                args_spec=no_args_event_spec,\n            ),\n            '((...args) => (addEvents([(ReflexEvent(\"mock_event\", ({  }), ({  })))], args, ({  }))))',\n        ),\n        (\n            EventChain(\n                events=[\n                    EventSpec(\n                        handler=EventHandler(fn=mock_event),\n                        args=(\n                            (\n                                Var(_js_expr=\"arg\"),\n                                Var(\n                                    _js_expr=\"_e\",\n                                )\n                                .to(ObjectVar, JavascriptInputEvent)\n                                .target.value,\n                            ),\n                        ),\n                    )\n                ],\n                args_spec=lambda e: [e.target.value],\n            ),\n            '((_e) => (addEvents([(ReflexEvent(\"mock_event\", ({ [\"arg\"] : _e?.[\"target\"]?.[\"value\"] }), ({  })))], [_e], ({  }))))',\n        ),\n        (\n            EventChain(\n                events=[EventSpec(handler=EventHandler(fn=mock_event))],\n                args_spec=no_args_event_spec,\n                event_actions={\"stopPropagation\": True},\n            ),\n            '((...args) => (addEvents([(ReflexEvent(\"mock_event\", ({  }), ({  })))], args, ({ [\"stopPropagation\"] : true }))))',\n        ),\n        (\n            EventChain(\n                events=[\n                    EventSpec(\n                        handler=EventHandler(fn=mock_event),\n                        event_actions={\"stopPropagation\": True},\n                    )\n                ],\n                args_spec=no_args_event_spec,\n            ),\n            '((...args) => (addEvents([(ReflexEvent(\"mock_event\", ({  }), ({ [\"stopPropagation\"] : true })))], args, ({  }))))',\n        ),\n        (\n            EventChain(\n                events=[EventSpec(handler=EventHandler(fn=mock_event))],\n                args_spec=no_args_event_spec,\n                event_actions={\"preventDefault\": True},\n            ),\n            '((...args) => (addEvents([(ReflexEvent(\"mock_event\", ({  }), ({  })))], args, ({ [\"preventDefault\"] : true }))))',\n        ),\n        ({\"a\": \"red\", \"b\": \"blue\"}, '({ [\"a\"] : \"red\", [\"b\"] : \"blue\" })'),\n        (Var(_js_expr=\"var\", _var_type=int).guess_type(), \"var\"),\n        (\n            Var(\n                _js_expr=\"_\",\n                _var_type=Any,\n            ),\n            \"_\",\n        ),\n        (\n            Var(_js_expr='state.colors[\"a\"]', _var_type=str).guess_type(),\n            'state.colors[\"a\"]',\n        ),\n        (\n            {\"a\": Var(_js_expr=\"val\", _var_type=str).guess_type()},\n            '({ [\"a\"] : val })',\n        ),\n        (\n            {\"a\": Var(_js_expr='\"val\"', _var_type=str).guess_type()},\n            '({ [\"a\"] : \"val\" })',\n        ),\n        (\n            {\"a\": Var(_js_expr='state.colors[\"val\"]', _var_type=str).guess_type()},\n            '({ [\"a\"] : state.colors[\"val\"] })',\n        ),\n        # tricky real-world case from markdown component\n        (\n            {\n                \"h1\": Var(\n                    _js_expr=f\"(({{node, ...props}}) => <Heading {{...props}} {''.join(Tag(name='', props=Style({'as_': 'h1'})).format_props())} />)\"\n                ),\n            },\n            '({ [\"h1\"] : (({node, ...props}) => <Heading {...props} as:\"h1\" />) })',\n        ),\n    ],\n)\ndef test_format_prop(prop: Var, formatted: str):\n    \"\"\"Test that the formatted value of an prop is correct.\n\n    Args:\n        prop: The prop to test.\n        formatted: The expected formatted value.\n    \"\"\"\n    assert format.format_prop(LiteralVar.create(prop)) == formatted\n\n\n@pytest.mark.parametrize(\n    (\"single_props\", \"key_value_props\", \"output\"),\n    [\n        (\n            [Var(_js_expr=\"props\")],\n            {\"key\": 42},\n            [\"key:42\", \"...props\"],\n        ),\n    ],\n)\ndef test_format_props(single_props, key_value_props, output):\n    \"\"\"Test the result of formatting a set of props (both single and keyvalue).\n\n    Args:\n        single_props: the list of single props\n        key_value_props: the dict of key value props\n        output: the expected output\n    \"\"\"\n    assert format.format_props(*single_props, **key_value_props) == output\n\n\n@pytest.mark.parametrize(\n    (\"input\", \"output\"),\n    [\n        (EventHandler(fn=mock_event), (\"\", \"mock_event\")),\n    ],\n)\ndef test_get_handler_parts(input, output):\n    assert format.get_event_handler_parts(input) == output\n\n\n@pytest.mark.parametrize(\n    (\"input\", \"output\"),\n    [\n        (TestState.do_something, f\"{TestState.get_full_name()}.do_something\"),\n        (\n            ChildState.change_both,\n            f\"{ChildState.get_full_name()}.change_both\",\n        ),\n        (\n            GrandchildState.do_nothing,\n            f\"{GrandchildState.get_full_name()}.do_nothing\",\n        ),\n    ],\n)\ndef test_format_event_handler(input, output):\n    \"\"\"Test formatting an event handler.\n\n    Args:\n        input: The event handler input.\n        output: The expected output.\n    \"\"\"\n    assert format.format_event_handler(input) == output\n\n\n@pytest.mark.parametrize(\n    (\"input\", \"output\"),\n    [\n        (\n            EventSpec(handler=EventHandler(fn=mock_event)),\n            '(ReflexEvent(\"mock_event\", ({  }), ({  })))',\n        ),\n    ],\n)\ndef test_format_event(input, output):\n    assert str(LiteralVar.create(input)) == output\n\n\n@pytest.mark.parametrize(\n    (\"input\", \"output\"),\n    [\n        ({\"query\": {\"k1\": 1, \"k2\": 2}}, {\"k1\": 1, \"k2\": 2}),\n        ({\"query\": {\"k1\": 1, \"k-2\": 2}}, {\"k1\": 1, \"k_2\": 2}),\n    ],\n)\ndef test_format_query_params(input, output):\n    assert format.format_query_params(input) == output\n\n\nformatted_router = {\n    \"route_id\": \"\",\n    \"url\": \"\",\n    \"session\": {\"client_token\": \"\", \"client_ip\": \"\", \"session_id\": \"\"},\n    \"headers\": {\n        \"host\": \"\",\n        \"origin\": \"\",\n        \"upgrade\": \"\",\n        \"connection\": \"\",\n        \"cookie\": \"\",\n        \"pragma\": \"\",\n        \"cache_control\": \"\",\n        \"user_agent\": \"\",\n        \"sec_websocket_version\": \"\",\n        \"sec_websocket_key\": \"\",\n        \"sec_websocket_extensions\": \"\",\n        \"accept_encoding\": \"\",\n        \"accept_language\": \"\",\n        \"raw_headers\": {},\n    },\n    \"page\": {\n        \"host\": \"\",\n        \"path\": \"\",\n        \"raw_path\": \"\",\n        \"full_path\": \"\",\n        \"full_raw_path\": \"\",\n        \"params\": {},\n    },\n}\n\n\n@pytest.mark.parametrize(\n    (\"input\", \"output\"),\n    [\n        (\n            TestState(_reflex_internal_init=True).dict(),  # pyright: ignore [reportCallIssue]\n            {\n                TestState.get_full_name(): {\n                    \"array\" + FIELD_MARKER: [1, 2, 3.15],\n                    \"complex\" + FIELD_MARKER: {\n                        1: {\"prop1\": 42, \"prop2\": \"hello\"},\n                        2: {\"prop1\": 42, \"prop2\": \"hello\"},\n                    },\n                    \"dt\" + FIELD_MARKER: \"1989-11-09 18:53:00+01:00\",\n                    \"fig\" + FIELD_MARKER: serialize_figure(go.Figure()),\n                    \"key\" + FIELD_MARKER: \"\",\n                    \"map_key\" + FIELD_MARKER: \"a\",\n                    \"mapping\" + FIELD_MARKER: {\"a\": [1, 2, 3], \"b\": [4, 5, 6]},\n                    \"mixin\" + FIELD_MARKER: \"mixin_value\",\n                    \"num1\" + FIELD_MARKER: 0,\n                    \"num2\" + FIELD_MARKER: 3.15,\n                    \"obj\" + FIELD_MARKER: {\"prop1\": 42, \"prop2\": \"hello\"},\n                    \"sum\" + FIELD_MARKER: 3.15,\n                    \"upper\" + FIELD_MARKER: \"\",\n                    \"router\" + FIELD_MARKER: formatted_router,\n                    \"asynctest\" + FIELD_MARKER: 0,\n                },\n                ChildState.get_full_name(): {\n                    \"count\" + FIELD_MARKER: 23,\n                    \"value\" + FIELD_MARKER: \"\",\n                },\n                ChildState2.get_full_name(): {\"value\" + FIELD_MARKER: \"\"},\n                ChildState3.get_full_name(): {\"value\" + FIELD_MARKER: \"\"},\n                GrandchildState.get_full_name(): {\"value2\" + FIELD_MARKER: \"\"},\n                GrandchildState2.get_full_name(): {\"cached\" + FIELD_MARKER: \"\"},\n                GrandchildState3.get_full_name(): {\"computed\" + FIELD_MARKER: \"\"},\n            },\n        ),\n        (\n            DateTimeState(_reflex_internal_init=True).dict(),  # pyright: ignore [reportCallIssue]\n            {\n                DateTimeState.get_full_name(): {\n                    \"d\" + FIELD_MARKER: \"1989-11-09\",\n                    \"dt\" + FIELD_MARKER: \"1989-11-09 18:53:00+01:00\",\n                    \"t\" + FIELD_MARKER: \"18:53:00+01:00\",\n                    \"td\" + FIELD_MARKER: \"11 days, 0:11:00\",\n                    \"router\" + FIELD_MARKER: formatted_router,\n                },\n            },\n        ),\n    ],\n)\ndef test_format_state(input, output):\n    \"\"\"Test that the format state is correct.\n\n    Args:\n        input: The state to format.\n        output: The expected formatted state.\n    \"\"\"\n    assert json.loads(format.json_dumps(input)) == json.loads(format.json_dumps(output))\n\n\n@pytest.mark.parametrize(\n    (\"input\", \"output\"),\n    [\n        (\"input1\", \"ref_input1\"),\n        (\"input 1\", \"ref_input_1\"),\n        (\"input-1\", \"ref_input_1\"),\n        (\"input_1\", \"ref_input_1\"),\n        (\"a long test?1! name\", \"ref_a_long_test_1_name\"),\n    ],\n)\ndef test_format_ref(input, output):\n    \"\"\"Test formatting a ref.\n\n    Args:\n        input: The name to format.\n        output: The expected formatted name.\n    \"\"\"\n    assert format.format_ref(input) == output\n\n\n@pytest.mark.parametrize(\n    (\"input\", \"output\"),\n    [\n        ((\"my_array\", None), \"refs_my_array\"),\n        ((\"my_array\", LiteralVar.create(0)), \"refs_my_array[0]\"),\n        ((\"my_array\", LiteralVar.create(1)), \"refs_my_array[1]\"),\n    ],\n)\ndef test_format_array_ref(input, output):\n    assert format.format_array_ref(input[0], input[1]) == output\n\n\n@pytest.mark.parametrize(\n    (\"input\", \"output\"),\n    [\n        (\"library@^0.1.2\", \"library\"),\n        (\"library\", \"library\"),\n        (\"@library@^0.1.2\", \"@library\"),\n        (\"@library\", \"@library\"),\n    ],\n)\ndef test_format_library_name(input: str, output: str):\n    \"\"\"Test formatting a library name to remove the @version part.\n\n    Args:\n        input: the input string.\n        output: the output string.\n    \"\"\"\n    assert format.format_library_name(input) == output\n\n\n@pytest.mark.parametrize(\n    (\"input\", \"output\"),\n    [\n        (None, \"null\"),\n        (True, \"true\"),\n        (1, \"1\"),\n        (1.0, \"1.0\"),\n        ([], \"[]\"),\n        ([1, 2, 3], \"[1, 2, 3]\"),\n        ({}, \"{}\"),\n        ({\"k1\": False, \"k2\": True}, '{\"k1\": false, \"k2\": true}'),\n        (\n            [datetime.timedelta(1, 1, 1), datetime.timedelta(1, 1, 2)],\n            '[\"1 day, 0:00:01.000001\", \"1 day, 0:00:01.000002\"]',\n        ),\n        (\n            {\"key1\": datetime.timedelta(1, 1, 1), \"key2\": datetime.timedelta(1, 1, 2)},\n            '{\"key1\": \"1 day, 0:00:01.000001\", \"key2\": \"1 day, 0:00:01.000002\"}',\n        ),\n    ],\n)\ndef test_json_dumps(input, output):\n    assert format.json_dumps(input) == output\n"
  },
  {
    "path": "tests/units/utils/test_imports.py",
    "content": "import pytest\n\nfrom reflex.utils.imports import (\n    ImportDict,\n    ImportVar,\n    ParsedImportDict,\n    merge_imports,\n    parse_imports,\n)\n\n\n@pytest.mark.parametrize(\n    (\"import_var\", \"expected_name\"),\n    [\n        (\n            ImportVar(tag=\"BaseTag\"),\n            \"BaseTag\",\n        ),\n        (\n            ImportVar(tag=\"BaseTag\", alias=\"AliasTag\"),\n            \"BaseTag as AliasTag\",\n        ),\n        (\n            ImportVar(tag=\"BaseTag\", is_default=True),\n            \"BaseTag\",\n        ),\n        (\n            ImportVar(tag=\"BaseTag\", is_default=True, alias=\"AliasTag\"),\n            \"AliasTag\",\n        ),\n        (\n            ImportVar(tag=\"BaseTag\", is_default=False),\n            \"BaseTag\",\n        ),\n        (\n            ImportVar(tag=\"BaseTag\", is_default=False, alias=\"AliasTag\"),\n            \"BaseTag as AliasTag\",\n        ),\n        (\n            ImportVar(tag=\"*\", alias=\"AliasTag\"),\n            \"* as AliasTag\",\n        ),\n    ],\n)\ndef test_import_var(import_var: ImportVar, expected_name: str):\n    \"\"\"Test that the import var name is computed correctly.\n\n    Args:\n        import_var: The import var.\n        expected_name: The expected name.\n    \"\"\"\n    assert import_var.name == expected_name\n\n\n@pytest.mark.parametrize(\n    (\"input_1\", \"input_2\", \"output\"),\n    [\n        (\n            {\"react\": {\"Component\"}},\n            {\"react\": {\"Component\"}, \"react-dom\": {\"render\"}},\n            {\"react\": {ImportVar(\"Component\")}, \"react-dom\": {ImportVar(\"render\")}},\n        ),\n        (\n            {\"react\": {\"Component\"}, \"next/image\": {\"Image\"}},\n            {\"react\": {\"Component\"}, \"react-dom\": {\"render\"}},\n            {\n                \"react\": {ImportVar(\"Component\")},\n                \"react-dom\": {ImportVar(\"render\")},\n                \"next/image\": {ImportVar(\"Image\")},\n            },\n        ),\n        (\n            {\"react\": {\"Component\"}},\n            {\"\": {\"some/custom.css\"}},\n            {\"react\": {ImportVar(\"Component\")}, \"\": {ImportVar(\"some/custom.css\")}},\n        ),\n    ],\n)\ndef test_merge_imports(input_1, input_2, output):\n    \"\"\"Test that imports are merged correctly.\n\n    Args:\n        input_1: The first dict to merge.\n        input_2: The second dict to merge.\n        output: The expected output dict after merging.\n\n    \"\"\"\n    res = merge_imports(input_1, input_2)\n    assert res.keys() == output.keys()\n\n    for key in output:\n        assert set(res[key]) == set(output[key])\n\n\n@pytest.mark.parametrize(\n    (\"input\", \"output\"),\n    [\n        ({}, {}),\n        (\n            {\"react\": \"Component\"},\n            {\"react\": [ImportVar(tag=\"Component\")]},\n        ),\n        (\n            {\"react\": [\"Component\"]},\n            {\"react\": [ImportVar(tag=\"Component\")]},\n        ),\n        (\n            {\"react\": [\"Component\", ImportVar(tag=\"useState\")]},\n            {\"react\": [ImportVar(tag=\"Component\"), ImportVar(tag=\"useState\")]},\n        ),\n        (\n            {\"react\": [\"Component\"], \"foo\": \"anotherFunction\"},\n            {\n                \"react\": [ImportVar(tag=\"Component\")],\n                \"foo\": [ImportVar(tag=\"anotherFunction\")],\n            },\n        ),\n    ],\n)\ndef test_parse_imports(input: ImportDict, output: ParsedImportDict):\n    assert parse_imports(input) == output\n"
  },
  {
    "path": "tests/units/utils/test_processes.py",
    "content": "\"\"\"Test process utilities.\"\"\"\n\nimport socket\nimport threading\nfrom contextlib import closing\nfrom unittest import mock\n\nimport pytest\n\nfrom reflex.testing import DEFAULT_TIMEOUT, AppHarness\nfrom reflex.utils.processes import is_process_on_port\n\n\ndef test_is_process_on_port_free_port():\n    \"\"\"Test is_process_on_port returns False when port is free.\"\"\"\n    # Find a free port\n    with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:\n        sock.bind((\"\", 0))\n        free_port = sock.getsockname()[1]\n\n    # Port should be free after socket is closed\n    assert not is_process_on_port(free_port)\n\n\ndef test_is_process_on_port_occupied_port():\n    \"\"\"Test is_process_on_port returns True when port is occupied.\"\"\"\n    # Create a server socket to occupy a port\n    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n    server_socket.bind((\"\", 0))\n    server_socket.listen(1)\n\n    occupied_port = server_socket.getsockname()[1]\n\n    try:\n        # Port should be occupied\n        assert is_process_on_port(occupied_port)\n    finally:\n        server_socket.close()\n\n\ndef test_is_process_on_port_ipv6():\n    \"\"\"Test is_process_on_port works with IPv6.\"\"\"\n    # Test with IPv6 socket\n    try:\n        server_socket = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)\n        server_socket.bind((\"\", 0))\n        server_socket.listen(1)\n\n        occupied_port = server_socket.getsockname()[1]\n\n        try:\n            # Port should be occupied on IPv6\n            assert is_process_on_port(occupied_port)\n        finally:\n            server_socket.close()\n    except OSError:\n        # IPv6 might not be available on some systems\n        pytest.skip(\"IPv6 not available on this system\")\n\n\ndef test_is_process_on_port_both_protocols():\n    \"\"\"Test is_process_on_port detects occupation on either IPv4 or IPv6.\"\"\"\n    # Create IPv4 server\n    ipv4_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n    ipv4_socket.bind((\"\", 0))\n    ipv4_socket.listen(1)\n\n    port = ipv4_socket.getsockname()[1]\n\n    try:\n        # Should detect IPv4 occupation\n        assert is_process_on_port(port)\n    finally:\n        ipv4_socket.close()\n\n\n@pytest.mark.parametrize(\"port\", [0, 1, 80, 443, 8000, 3000, 65535])\ndef test_is_process_on_port_various_ports(port):\n    \"\"\"Test is_process_on_port with various port numbers.\n\n    Args:\n        port: The port number to test.\n    \"\"\"\n    # This test just ensures the function doesn't crash with different port numbers\n    # The actual result depends on what's running on the system\n    result = is_process_on_port(port)\n    assert isinstance(result, bool)\n\n\ndef test_is_process_on_port_mock_socket_error():\n    \"\"\"Test is_process_on_port handles socket errors gracefully.\"\"\"\n    with mock.patch(\"socket.socket\") as mock_socket:\n        mock_socket_instance = mock.MagicMock()\n        mock_socket.return_value = mock_socket_instance\n        mock_socket_instance.__enter__.return_value = mock_socket_instance\n        mock_socket_instance.bind.side_effect = OSError(\"Mock socket error\")\n\n        # Should return True when socket operations fail\n        result = is_process_on_port(8080)\n        assert result is True\n\n\ndef test_is_process_on_port_permission_error():\n    \"\"\"Test is_process_on_port handles permission errors.\"\"\"\n    with mock.patch(\"socket.socket\") as mock_socket:\n        mock_socket_instance = mock.MagicMock()\n        mock_socket.return_value = mock_socket_instance\n        mock_socket_instance.__enter__.return_value = mock_socket_instance\n        mock_socket_instance.bind.side_effect = PermissionError(\"Permission denied\")\n\n        # Should return True when permission is denied (can't bind = port is \"occupied\")\n        result = is_process_on_port(80)\n        assert result is True\n\n\ndef test_is_process_on_port_concurrent_access():\n    \"\"\"Test is_process_on_port works correctly with concurrent access.\"\"\"\n    shared = None\n    is_open = threading.Event()\n    do_close = threading.Event()\n\n    def create_server_and_test():\n        nonlocal do_close, is_open, shared\n        server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n        server.bind((\"\", 0))\n\n        server.listen(1)\n\n        port = server.getsockname()[1]\n        shared = port\n\n        is_open.set()\n        do_close.wait(timeout=DEFAULT_TIMEOUT)\n\n        server.close()\n\n    thread = threading.Thread(target=create_server_and_test)\n    thread.start()\n    is_open.wait(timeout=DEFAULT_TIMEOUT)\n\n    try:\n        assert shared is not None\n\n        # Port should be occupied while server is running (both bound-only and listening)\n        assert AppHarness._poll_for(\n            lambda: shared is not None and is_process_on_port(shared)\n        )\n    finally:\n        do_close.set()\n        thread.join(timeout=DEFAULT_TIMEOUT)\n\n    # Give it a moment for the socket to be fully released\n    assert AppHarness._poll_for(\n        lambda: shared is not None and not is_process_on_port(shared)\n    )\n"
  },
  {
    "path": "tests/units/utils/test_serializers.py",
    "content": "import datetime\nimport decimal\nimport json\nfrom enum import Enum\nfrom pathlib import Path\nfrom typing import Any\n\nimport pytest\n\nfrom reflex.base import Base\nfrom reflex.components.core.colors import Color\nfrom reflex.utils import serializers\nfrom reflex.utils.format import json_dumps\nfrom reflex.vars.base import LiteralVar\n\npytest.importorskip(\"pydantic\")\n\n\n@pytest.mark.parametrize(\n    (\"type_\", \"expected\"),\n    [(Enum, True)],\n)\ndef test_has_serializer(type_: type, expected: bool):\n    \"\"\"Test that has_serializer returns the correct value.\n\n    Args:\n        type_: The type to check.\n        expected: The expected result.\n    \"\"\"\n    assert serializers.has_serializer(type_) == expected\n\n\n@pytest.mark.parametrize(\n    (\"type_\", \"expected\"),\n    [\n        (datetime.datetime, serializers.serialize_datetime),\n        (datetime.date, serializers.serialize_datetime),\n        (datetime.time, serializers.serialize_datetime),\n        (datetime.timedelta, serializers.serialize_datetime),\n        (Enum, serializers.serialize_enum),\n    ],\n)\ndef test_get_serializer(type_: type, expected: serializers.Serializer):\n    \"\"\"Test that get_serializer returns the correct value.\n\n    Args:\n        type_: The type to check.\n        expected: The expected result.\n    \"\"\"\n    assert serializers.get_serializer(type_) == expected\n\n\ndef test_add_serializer():\n    \"\"\"Test that adding a serializer works.\"\"\"\n\n    class Foo:  # noqa: B903\n        \"\"\"A test class.\"\"\"\n\n        def __init__(self, name: str):\n            self.name = name\n\n    def serialize_foo(value: Foo) -> str:\n        \"\"\"Serialize an foo to a string.\n\n        Args:\n            value: The value to serialize.\n\n        Returns:\n            The serialized value.\n        \"\"\"\n        return value.name\n\n    # Initially there should be no serializer for int.\n    assert not serializers.has_serializer(Foo)\n    assert serializers.serialize(Foo(\"hi\")) is None\n\n    # Register the serializer.\n    assert serializers.serializer(serialize_foo) == serialize_foo\n\n    # There should now be a serializer for int.\n    assert serializers.has_serializer(Foo)\n    assert serializers.get_serializer(Foo) == serialize_foo\n    assert serializers.serialize(Foo(\"hi\")) == \"hi\"\n\n    # Remove the serializer.\n    serializers.SERIALIZERS.pop(Foo)\n    # LRU cache will still have the serializer, so we need to clear it.\n    assert serializers.has_serializer(Foo)\n    serializers.get_serializer.cache_clear()\n    assert not serializers.has_serializer(Foo)\n\n\nclass StrEnum(str, Enum):\n    \"\"\"An enum also inheriting from str.\"\"\"\n\n    FOO = \"foo\"\n    BAR = \"bar\"\n\n\nclass FooBarEnum(Enum):\n    \"\"\"A lone enum class.\"\"\"\n\n    FOO = \"foo\"\n    BAR = \"bar\"\n\n\nclass EnumWithPrefix(Enum):\n    \"\"\"An enum with a serializer adding a prefix.\"\"\"\n\n    FOO = \"foo\"\n    BAR = \"bar\"\n\n\n@serializers.serializer\ndef serialize_EnumWithPrefix(enum: EnumWithPrefix) -> str:\n    return \"prefix_\" + enum.value\n\n\nclass BaseSubclass(Base):\n    \"\"\"A class inheriting from Base for testing.\"\"\"\n\n    ts: datetime.timedelta = datetime.timedelta(1, 1, 1)\n\n\n@pytest.mark.parametrize(\n    (\"value\", \"expected\"),\n    [\n        (\"test\", \"test\"),\n        (1, 1),\n        (1.0, 1.0),\n        (True, True),\n        (False, False),\n        (None, None),\n        ([1, 2, 3], [1, 2, 3]),\n        ([1, \"2\", 3.0], [1, \"2\", 3.0]),\n        ([{\"key\": 1}, {\"key\": 2}], [{\"key\": 1}, {\"key\": 2}]),\n        (StrEnum.FOO, \"foo\"),\n        ([StrEnum.FOO, StrEnum.BAR], [\"foo\", \"bar\"]),\n        (\n            {\"key1\": [1, 2, 3], \"key2\": [StrEnum.FOO, StrEnum.BAR]},\n            {\n                \"key1\": [1, 2, 3],\n                \"key2\": [\"foo\", \"bar\"],\n            },\n        ),\n        (EnumWithPrefix.FOO, \"prefix_foo\"),\n        ([EnumWithPrefix.FOO, EnumWithPrefix.BAR], [\"prefix_foo\", \"prefix_bar\"]),\n        (\n            {\"key1\": EnumWithPrefix.FOO, \"key2\": EnumWithPrefix.BAR},\n            {\n                \"key1\": \"prefix_foo\",\n                \"key2\": \"prefix_bar\",\n            },\n        ),\n        (FooBarEnum.FOO, \"foo\"),\n        ([FooBarEnum.FOO, FooBarEnum.BAR], [\"foo\", \"bar\"]),\n        (\n            {\"key1\": FooBarEnum.FOO, \"key2\": FooBarEnum.BAR},\n            {\n                \"key1\": \"foo\",\n                \"key2\": \"bar\",\n            },\n        ),\n        (\n            BaseSubclass(ts=datetime.timedelta(1, 1, 1)),\n            {\n                \"ts\": \"1 day, 0:00:01.000001\",\n            },\n        ),\n        (\n            [1, LiteralVar.create(\"hi\")],\n            [1, \"hi\"],\n        ),\n        (\n            (1, LiteralVar.create(\"hi\")),\n            [1, \"hi\"],\n        ),\n        ({1: 2, 3: 4}, {1: 2, 3: 4}),\n        (\n            {1: LiteralVar.create(\"hi\")},\n            {1: \"hi\"},\n        ),\n        (datetime.datetime(2021, 1, 1, 1, 1, 1, 1), \"2021-01-01 01:01:01.000001\"),\n        (datetime.date(2021, 1, 1), \"2021-01-01\"),\n        (datetime.time(1, 1, 1, 1), \"01:01:01.000001\"),\n        (datetime.timedelta(1, 1, 1), \"1 day, 0:00:01.000001\"),\n        (\n            [datetime.timedelta(1, 1, 1), datetime.timedelta(1, 1, 2)],\n            [\"1 day, 0:00:01.000001\", \"1 day, 0:00:01.000002\"],\n        ),\n        (Color(color=\"slate\", shade=1), \"var(--slate-1)\"),\n        (Color(color=\"orange\", shade=1, alpha=True), \"var(--orange-a1)\"),\n        (Color(color=\"accent\", shade=1, alpha=True), \"var(--accent-a1)\"),\n        (decimal.Decimal(\"123.456\"), 123.456),\n        (decimal.Decimal(\"-0.5\"), -0.5),\n        (decimal.Decimal(0), 0.0),\n    ],\n)\ndef test_serialize(value: Any, expected: str):\n    \"\"\"Test that serialize returns the correct value.\n\n    Args:\n        value: The value to serialize.\n        expected: The expected result.\n    \"\"\"\n    assert json.loads(json_dumps(value)) == json.loads(json_dumps(expected))\n\n\n@pytest.mark.parametrize(\n    (\"value\", \"expected\", \"exp_var_is_string\"),\n    [\n        (\"test\", '\"test\"', False),\n        (1, \"1\", False),\n        (1.0, \"1.0\", False),\n        (True, \"true\", False),\n        (False, \"false\", False),\n        ([1, 2, 3], \"[1, 2, 3]\", False),\n        ([{\"key\": 1}, {\"key\": 2}], '[({ [\"key\"] : 1 }), ({ [\"key\"] : 2 })]', False),\n        (StrEnum.FOO, '\"foo\"', False),\n        ([StrEnum.FOO, StrEnum.BAR], '[\"foo\", \"bar\"]', False),\n        (\n            BaseSubclass(ts=datetime.timedelta(1, 1, 1)),\n            '({ [\"ts\"] : \"1 day, 0:00:01.000001\" })',\n            False,\n        ),\n        (\n            datetime.datetime(2021, 1, 1, 1, 1, 1, 1),\n            '\"2021-01-01 01:01:01.000001\"',\n            True,\n        ),\n        (datetime.date(2021, 1, 1), '\"2021-01-01\"', True),\n        (Color(color=\"slate\", shade=1), '\"var(--slate-1)\"', True),\n        (BaseSubclass, '\"BaseSubclass\"', True),\n        (Path(), '\".\"', True),\n        (decimal.Decimal(\"123.456\"), \"123.456\", True),\n        (decimal.Decimal(\"-0.5\"), \"-0.5\", True),\n    ],\n)\ndef test_serialize_var_to_str(value: Any, expected: str, exp_var_is_string: bool):\n    \"\"\"Test that serialize with `to=str` passed to a Var is marked with _var_is_string.\n\n    Args:\n        value: The value to serialize.\n        expected: The expected result.\n        exp_var_is_string: The expected value of _var_is_string.\n    \"\"\"\n    v = LiteralVar.create(value)\n    assert str(v) == expected\n"
  },
  {
    "path": "tests/units/utils/test_tasks.py",
    "content": "import asyncio\nimport contextlib\nimport os\nfrom unittest.mock import Mock\n\nimport pytest\n\nfrom reflex.utils.tasks import ensure_task\n\nCI = bool(os.environ.get(\"CI\", False))\n\n\nclass NotSuppressedError(Exception):\n    \"\"\"An exception that should not be suppressed.\"\"\"\n\n\n@pytest.mark.asyncio\nasync def test_ensure_task_suppresses_exceptions():\n    \"\"\"Test that ensure_task suppresses specified exceptions.\"\"\"\n    call_count = 0\n\n    async def faulty_coro():  # noqa: RUF029\n        nonlocal call_count\n        call_count += 1\n        if call_count < 3:\n            raise ValueError(\"Intentional error\")  # noqa: EM101\n        if call_count > 4:\n            raise NotSuppressedError(\"Should not be suppressed\")  # noqa: EM101\n        return \"Success\"\n\n    # Use ensure_task to run the faulty_coro, suppressing ValueError\n    owner = Mock()\n    ensure_task(\n        owner=owner,\n        task_attribute=\"task\",\n        coro_function=faulty_coro,\n        suppress_exceptions=[ValueError],\n        exception_delay=0,\n        exception_limit=5,\n        exception_limit_window=1.0,\n    )\n\n    with contextlib.suppress(asyncio.CancelledError), pytest.raises(NotSuppressedError):\n        await asyncio.wait_for(owner.task, timeout=1)\n\n    # Should have retried until success, then raised RuntimeError\n    assert call_count == 5\n\n\nasync def test_ensure_task_limit_window():\n    \"\"\"Test that ensure_task raises after exceeding exception limit within the limit window.\"\"\"\n    call_count = 0\n\n    async def faulty_coro():  # noqa: RUF029\n        nonlocal call_count\n        call_count += 1\n        raise ValueError(\"Intentional error\")  # noqa: EM101\n\n    owner = Mock()\n    ensure_task(\n        owner=owner,\n        task_attribute=\"task\",\n        coro_function=faulty_coro,\n        suppress_exceptions=[ValueError],\n        exception_delay=0,\n        exception_limit=3,\n        exception_limit_window=1.0,\n    )\n\n    with contextlib.suppress(asyncio.CancelledError), pytest.raises(ValueError):\n        await asyncio.wait_for(owner.task, timeout=1)\n\n    # Should have raised after exceeding the limit\n    assert call_count == 3\n\n\nasync def test_ensure_task_limit_window_passed():\n    \"\"\"Test that ensure_task resets exception limit past the limit window.\"\"\"\n    call_count = 0\n\n    async def faulty_coro():\n        nonlocal call_count\n        call_count += 1\n        await asyncio.sleep(0.5 if CI else 0.05)\n        if call_count > 3:\n            raise RuntimeError(\"Test Passed\")  # noqa: EM101\n        raise ValueError(\"Should have been suppressed\")  # noqa: EM101\n\n    owner = Mock()\n    ensure_task(\n        owner=owner,\n        task_attribute=\"task\",\n        coro_function=faulty_coro,\n        suppress_exceptions=[ValueError],\n        exception_delay=0,\n        exception_limit=2,\n        exception_limit_window=0.1 if CI else 0.01,\n    )\n\n    with contextlib.suppress(asyncio.CancelledError), pytest.raises(RuntimeError):\n        await asyncio.wait_for(owner.task, timeout=3)\n\n    # Should have raised after exceeding the limit\n    assert call_count == 4\n\n\ndef test_ensure_task_no_runtime_error_suppression():\n    \"\"\"Test that ensure_task raises if RuntimeError is in suppress_exceptions.\"\"\"\n    owner = Mock()\n\n    with pytest.raises(RuntimeError, match=\"Cannot suppress RuntimeError\"):\n        ensure_task(\n            owner=owner,\n            task_attribute=\"task\",\n            coro_function=asyncio.sleep,\n            suppress_exceptions=[RuntimeError],\n            exception_delay=0,\n            exception_limit=5,\n            exception_limit_window=1.0,\n        )\n"
  },
  {
    "path": "tests/units/utils/test_token_manager.py",
    "content": "\"\"\"Unit tests for TokenManager implementations.\"\"\"\n\nimport asyncio\nimport pickle\nimport time\nfrom collections.abc import Callable, Generator\nfrom contextlib import asynccontextmanager\nfrom unittest.mock import AsyncMock, Mock, patch\n\nimport pytest\n\nfrom reflex import config\nfrom reflex.app import EventNamespace\nfrom reflex.istate.data import RouterData\nfrom reflex.state import StateUpdate\nfrom reflex.utils.token_manager import (\n    LocalTokenManager,\n    RedisTokenManager,\n    SocketRecord,\n    TokenManager,\n)\n\n\nclass TestTokenManager:\n    \"\"\"Tests for the TokenManager factory.\"\"\"\n\n    @patch(\"reflex.utils.token_manager.prerequisites.check_redis_used\")\n    @patch(\"reflex.utils.token_manager.prerequisites.get_redis\")\n    def test_create_local_when_no_redis(self, mock_get_redis, mock_check_redis_used):\n        \"\"\"Test factory creates LocalTokenManager when Redis is not available.\n\n        Args:\n            mock_get_redis: Mock for prerequisites.get_redis.\n            mock_check_redis_used: Mock for prerequisites.check_redis_used.\n        \"\"\"\n        mock_check_redis_used.return_value = False\n\n        manager = TokenManager.create()\n\n        assert isinstance(manager, LocalTokenManager)\n        mock_get_redis.assert_not_called()\n\n    @patch(\"reflex.utils.token_manager.prerequisites.check_redis_used\")\n    @patch(\"reflex.utils.token_manager.prerequisites.get_redis\")\n    def test_create_local_when_redis_client_none(\n        self, mock_get_redis, mock_check_redis_used\n    ):\n        \"\"\"Test factory creates LocalTokenManager when Redis client is None.\n\n        Args:\n            mock_get_redis: Mock for prerequisites.get_redis.\n            mock_check_redis_used: Mock for prerequisites.check_redis_used.\n        \"\"\"\n        mock_check_redis_used.return_value = True\n        mock_get_redis.return_value = None\n\n        manager = TokenManager.create()\n\n        assert isinstance(manager, LocalTokenManager)\n\n    @patch(\"reflex.utils.token_manager.prerequisites.check_redis_used\")\n    @patch(\"reflex.utils.token_manager.prerequisites.get_redis\")\n    def test_create_redis_when_redis_available(\n        self, mock_get_redis, mock_check_redis_used\n    ):\n        \"\"\"Test factory creates RedisTokenManager when Redis is available.\n\n        Args:\n            mock_get_redis: Mock for prerequisites.get_redis.\n            mock_check_redis_used: Mock for prerequisites.check_redis_used.\n        \"\"\"\n        mock_check_redis_used.return_value = True\n        mock_redis_client = Mock()\n        mock_redis_client.get_connection_kwargs.return_value = {\"db\": 0}\n        mock_get_redis.return_value = mock_redis_client\n\n        manager = TokenManager.create()\n\n        assert isinstance(manager, RedisTokenManager)\n        assert manager.redis is mock_redis_client\n\n\nclass TestLocalTokenManager:\n    \"\"\"Tests for LocalTokenManager.\"\"\"\n\n    @pytest.fixture\n    def manager(self):\n        \"\"\"Create a LocalTokenManager instance.\n\n        Returns:\n            A LocalTokenManager instance for testing.\n        \"\"\"\n        return LocalTokenManager()\n\n    @pytest.mark.parametrize(\n        (\"token\", \"sid\"),\n        [\n            (\"token1\", \"sid1\"),\n            (\"test-token\", \"test-sid\"),\n            (\"12345\", \"67890\"),\n        ],\n    )\n    async def test_link_token_to_sid_normal_case(self, manager, token, sid):\n        \"\"\"Test normal token linking returns None.\n\n        Args:\n            manager: LocalTokenManager fixture instance.\n            token: Token string to test.\n            sid: Session ID string to test.\n        \"\"\"\n        result = await manager.link_token_to_sid(token, sid)\n\n        assert result is None\n        assert manager.token_to_sid[token] == sid\n        assert manager.sid_to_token[sid] == token\n\n    async def test_link_token_to_sid_same_token_same_sid(self, manager):\n        \"\"\"Test linking same token to same SID (reconnection).\n\n        Args:\n            manager: LocalTokenManager fixture instance.\n        \"\"\"\n        token, sid = \"token1\", \"sid1\"\n\n        await manager.link_token_to_sid(token, sid)\n        result = await manager.link_token_to_sid(token, sid)\n\n        assert result is None\n        assert manager.token_to_sid[token] == sid\n        assert manager.sid_to_token[sid] == token\n\n    async def test_link_token_to_sid_duplicate_token_different_sid(self, manager):\n        \"\"\"Test duplicate token detection generates new token.\n\n        Args:\n            manager: LocalTokenManager fixture instance.\n        \"\"\"\n        token = \"duplicate_token\"\n        sid1, sid2 = \"sid1\", \"sid2\"\n\n        # First connection\n        result1 = await manager.link_token_to_sid(token, sid1)\n        assert result1 is None\n\n        # Duplicate token with different SID\n        result2 = await manager.link_token_to_sid(token, sid2)\n        assert result2 is not None\n        assert result2 != token\n\n        # Check mappings\n        assert manager.token_to_sid[result2] == sid2\n        assert manager.sid_to_token[sid2] == result2\n        assert manager.token_to_sid[token] == sid1\n\n    @pytest.mark.parametrize(\n        (\"token\", \"sid\"),\n        [\n            (\"token1\", \"sid1\"),\n            (\"test-token\", \"test-sid\"),\n        ],\n    )\n    async def test_disconnect_token(self, manager, token, sid):\n        \"\"\"Test token disconnection cleans up mappings.\n\n        Args:\n            manager: LocalTokenManager fixture instance.\n            token: Token string to test.\n            sid: Session ID string to test.\n        \"\"\"\n        await manager.link_token_to_sid(token, sid)\n\n        await manager.disconnect_token(token, sid)\n\n        assert token not in manager.token_to_sid\n        assert sid not in manager.sid_to_token\n\n    async def test_disconnect_nonexistent_token(self, manager):\n        \"\"\"Test disconnecting nonexistent token doesn't raise error.\n\n        Args:\n            manager: LocalTokenManager fixture instance.\n        \"\"\"\n        await manager.disconnect_token(\"nonexistent\", \"nonexistent\")\n\n        assert len(manager.token_to_sid) == 0\n        assert len(manager.sid_to_token) == 0\n\n    async def test_enumerate_tokens(self, manager):\n        \"\"\"Test enumerate_tokens yields all linked tokens.\n\n        Args:\n            manager: LocalTokenManager fixture instance.\n        \"\"\"\n        tokens_sids = [(\"token1\", \"sid1\"), (\"token2\", \"sid2\"), (\"token3\", \"sid3\")]\n\n        for token, sid in tokens_sids:\n            await manager.link_token_to_sid(token, sid)\n\n        found_tokens = set()\n        async for token in manager.enumerate_tokens():\n            found_tokens.add(token)\n\n        expected_tokens = {token for token, _ in tokens_sids}\n        assert found_tokens == expected_tokens\n\n        # Disconnect a token and ensure it's removed.\n        await manager.disconnect_token(\"token2\", \"sid2\")\n        expected_tokens.remove(\"token2\")\n\n        found_tokens = set()\n        async for token in manager.enumerate_tokens():\n            found_tokens.add(token)\n\n        assert found_tokens == expected_tokens\n\n        # Disconnect all tokens, none should remain\n        await manager.disconnect_all()\n        found_tokens = set()\n        async for token in manager.enumerate_tokens():\n            found_tokens.add(token)\n        assert not found_tokens\n\n\nclass TestRedisTokenManager:\n    \"\"\"Tests for RedisTokenManager.\"\"\"\n\n    @pytest.fixture\n    def mock_redis(self):\n        \"\"\"Create a mock Redis client.\n\n        Returns:\n            AsyncMock configured as Redis client for testing.\n        \"\"\"\n        redis = AsyncMock()\n        redis.exists = AsyncMock()\n        redis.set = AsyncMock()\n        redis.delete = AsyncMock()\n\n        # Non-async call\n        redis.get_connection_kwargs = Mock(return_value={\"db\": 0})\n\n        # Mock out pubsub\n        async def listen():\n            await asyncio.sleep(1)\n            if False:\n                yield\n            return\n\n        @asynccontextmanager\n        async def pubsub():  # noqa: RUF029\n            pubsub_mock = AsyncMock()\n            pubsub_mock.listen = listen\n            yield pubsub_mock\n\n        redis.pubsub = pubsub\n        return redis\n\n    @pytest.fixture\n    def manager(self, mock_redis):\n        \"\"\"Create a RedisTokenManager instance with mocked config.\n\n        Args:\n            mock_redis: Mock Redis client fixture.\n\n        Returns:\n            RedisTokenManager instance for testing.\n        \"\"\"\n        with patch(\"reflex.config.get_config\") as mock_get_config:\n            mock_config = Mock()\n            mock_config.redis_token_expiration = 3600\n            mock_get_config.return_value = mock_config\n\n            return RedisTokenManager(mock_redis)\n\n    def test_get_redis_key(self, manager):\n        \"\"\"Test Redis key generation follows expected pattern.\n\n        Args:\n            manager: RedisTokenManager fixture instance.\n        \"\"\"\n        token = \"test_token_123\"\n        expected_key = f\"token_manager_socket_record_{token}\"\n\n        assert manager._get_redis_key(token) == expected_key\n\n    async def test_link_token_to_sid_normal_case(self, manager, mock_redis):\n        \"\"\"Test normal token linking stores in both Redis and local dicts.\n\n        Args:\n            manager: RedisTokenManager fixture instance.\n            mock_redis: Mock Redis client fixture.\n        \"\"\"\n        token, sid = \"token1\", \"sid1\"\n        mock_redis.exists.return_value = False\n\n        result = await manager.link_token_to_sid(token, sid)\n\n        assert result is None\n        mock_redis.exists.assert_called_once_with(\n            f\"token_manager_socket_record_{token}\"\n        )\n        mock_redis.set.assert_called_once_with(\n            f\"token_manager_socket_record_{token}\",\n            pickle.dumps(SocketRecord(instance_id=manager.instance_id, sid=sid)),\n            ex=3600,\n        )\n        assert manager.token_to_socket[token].sid == sid\n        assert manager.sid_to_token[sid] == token\n\n    async def test_link_token_to_sid_reconnection_skips_redis(\n        self, manager, mock_redis\n    ):\n        \"\"\"Test reconnection with same token/SID skips Redis check.\n\n        Args:\n            manager: RedisTokenManager fixture instance.\n            mock_redis: Mock Redis client fixture.\n        \"\"\"\n        token, sid = \"token1\", \"sid1\"\n        manager.token_to_socket[token] = SocketRecord(\n            instance_id=manager.instance_id, sid=sid\n        )\n\n        result = await manager.link_token_to_sid(token, sid)\n\n        assert result is None\n        mock_redis.exists.assert_not_called()\n        mock_redis.set.assert_not_called()\n\n    async def test_link_token_to_sid_duplicate_detected(self, manager, mock_redis):\n        \"\"\"Test duplicate token detection generates new token.\n\n        Args:\n            manager: RedisTokenManager fixture instance.\n            mock_redis: Mock Redis client fixture.\n        \"\"\"\n        token, sid = \"token1\", \"sid1\"\n        mock_redis.exists.return_value = True\n\n        result = await manager.link_token_to_sid(token, sid)\n\n        assert result is not None\n        assert result != token\n        assert len(result) == 36  # UUID4 length\n\n        mock_redis.exists.assert_called_once_with(\n            f\"token_manager_socket_record_{token}\"\n        )\n        mock_redis.set.assert_called_once_with(\n            f\"token_manager_socket_record_{result}\",\n            pickle.dumps(SocketRecord(instance_id=manager.instance_id, sid=sid)),\n            ex=3600,\n        )\n        assert manager.token_to_sid[result] == sid\n        assert manager.sid_to_token[sid] == result\n\n    async def test_link_token_to_sid_redis_error_fallback(self, manager, mock_redis):\n        \"\"\"Test Redis error falls back to local manager behavior.\n\n        Args:\n            manager: RedisTokenManager fixture instance.\n            mock_redis: Mock Redis client fixture.\n        \"\"\"\n        token, sid = \"token1\", \"sid1\"\n        mock_redis.exists.side_effect = Exception(\"Redis connection error\")\n\n        with patch.object(\n            LocalTokenManager, \"link_token_to_sid\", new_callable=AsyncMock\n        ) as mock_super:\n            mock_super.return_value = None\n\n            result = await manager.link_token_to_sid(token, sid)\n\n            assert result is None\n            mock_super.assert_called_once_with(token, sid)\n\n    async def test_link_token_to_sid_redis_set_error_continues(\n        self, manager, mock_redis\n    ):\n        \"\"\"Test Redis set error doesn't prevent local storage.\n\n        Args:\n            manager: RedisTokenManager fixture instance.\n            mock_redis: Mock Redis client fixture.\n        \"\"\"\n        token, sid = \"token1\", \"sid1\"\n        mock_redis.exists.return_value = False\n        mock_redis.set.side_effect = Exception(\"Redis set error\")\n\n        result = await manager.link_token_to_sid(token, sid)\n\n        assert result is None\n        assert manager.token_to_sid[token] == sid\n        assert manager.sid_to_token[sid] == token\n\n    async def test_disconnect_token_owned_locally(self, manager, mock_redis):\n        \"\"\"Test disconnect cleans up both Redis and local mappings when owned locally.\n\n        Args:\n            manager: RedisTokenManager fixture instance.\n            mock_redis: Mock Redis client fixture.\n        \"\"\"\n        token, sid = \"token1\", \"sid1\"\n        manager.token_to_socket[token] = SocketRecord(\n            instance_id=manager.instance_id, sid=sid\n        )\n        manager.sid_to_token[sid] = token\n\n        await manager.disconnect_token(token, sid)\n\n        mock_redis.delete.assert_called_once_with(\n            f\"token_manager_socket_record_{token}\"\n        )\n        assert token not in manager.token_to_sid\n        assert sid not in manager.sid_to_token\n\n    async def test_disconnect_token_not_owned_locally(self, manager, mock_redis):\n        \"\"\"Test disconnect doesn't clean up when not owned locally.\n\n        Args:\n            manager: RedisTokenManager fixture instance.\n            mock_redis: Mock Redis client fixture.\n        \"\"\"\n        token, sid = \"token1\", \"sid1\"\n\n        await manager.disconnect_token(token, sid)\n\n        mock_redis.delete.assert_not_called()\n\n    async def test_disconnect_token_redis_error(self, manager, mock_redis):\n        \"\"\"Test disconnect continues with local cleanup even if Redis fails.\n\n        Args:\n            manager: RedisTokenManager fixture instance.\n            mock_redis: Mock Redis client fixture.\n        \"\"\"\n        token, sid = \"token1\", \"sid1\"\n        manager.token_to_socket[token] = SocketRecord(\n            instance_id=manager.instance_id, sid=sid\n        )\n        manager.sid_to_token[sid] = token\n        mock_redis.delete.side_effect = Exception(\"Redis delete error\")\n\n        await manager.disconnect_token(token, sid)\n\n        assert token not in manager.token_to_sid\n        assert sid not in manager.sid_to_token\n\n    @pytest.mark.parametrize(\n        \"redis_error\",\n        [\n            Exception(\"Connection timeout\"),\n            Exception(\"Redis server down\"),\n            Exception(\"Network error\"),\n        ],\n    )\n    async def test_various_redis_errors_handled_gracefully(\n        self, manager, mock_redis, redis_error\n    ):\n        \"\"\"Test various Redis errors are handled gracefully.\n\n        Args:\n            manager: RedisTokenManager fixture instance.\n            mock_redis: Mock Redis client fixture.\n            redis_error: Exception to test error handling.\n        \"\"\"\n        token, sid = \"token1\", \"sid1\"\n        mock_redis.exists.side_effect = redis_error\n\n        with patch.object(\n            LocalTokenManager, \"link_token_to_sid\", new_callable=AsyncMock\n        ) as mock_super:\n            mock_super.return_value = None\n\n            result = await manager.link_token_to_sid(token, sid)\n\n            assert result is None\n            mock_super.assert_called_once()\n\n    def test_inheritance_from_local_manager(self, manager):\n        \"\"\"Test RedisTokenManager inherits from LocalTokenManager.\n\n        Args:\n            manager: RedisTokenManager fixture instance.\n        \"\"\"\n        assert isinstance(manager, LocalTokenManager)\n        assert hasattr(manager, \"token_to_sid\")\n        assert hasattr(manager, \"sid_to_token\")\n\n\n@pytest.fixture\ndef redis_url():\n    \"\"\"Returns the Redis URL from the environment.\"\"\"\n    redis_url = config.get_config().redis_url\n    if redis_url is None:\n        pytest.skip(\"Redis URL not configured\")\n    return redis_url\n\n\ndef query_string_for(token: str) -> dict[str, str]:\n    \"\"\"Generate query string for given token.\n\n    Args:\n        token: The token to generate query string for.\n\n    Returns:\n        The generated query string.\n    \"\"\"\n    return {\"QUERY_STRING\": f\"token={token}\"}\n\n\n@pytest.fixture\ndef event_namespace_factory() -> Generator[Callable[[], EventNamespace], None, None]:\n    \"\"\"Yields the EventNamespace factory function.\"\"\"\n    namespace = config.get_config().get_event_namespace()\n    created_objs = []\n\n    def new_event_namespace() -> EventNamespace:\n        state = Mock()\n        state.router_data = {}\n\n        mock_app = Mock()\n        mock_app.state_manager.modify_state = Mock(\n            return_value=AsyncMock(__aenter__=AsyncMock(return_value=state))\n        )\n\n        event_namespace = EventNamespace(namespace=namespace, app=mock_app)\n        event_namespace.emit = AsyncMock()\n        created_objs.append(event_namespace)\n        return event_namespace\n\n    yield new_event_namespace\n\n    for obj in created_objs:\n        asyncio.run(obj._token_manager.disconnect_all())\n\n\n@pytest.mark.usefixtures(\"redis_url\")\n@pytest.mark.asyncio\nasync def test_redis_token_manager_enumerate_tokens(\n    event_namespace_factory: Callable[[], EventNamespace],\n):\n    \"\"\"Integration test for RedisTokenManager enumerate_tokens interface.\n\n    Should support enumerating tokens across separate instances of the\n    RedisTokenManager.\n\n    Args:\n        event_namespace_factory: Factory fixture for EventNamespace instances.\n    \"\"\"\n    event_namespace1 = event_namespace_factory()\n    event_namespace2 = event_namespace_factory()\n\n    await event_namespace1.on_connect(sid=\"sid1\", environ=query_string_for(\"token1\"))\n    await event_namespace2.on_connect(sid=\"sid2\", environ=query_string_for(\"token2\"))\n\n    found_tokens = set()\n    async for token in event_namespace1._token_manager.enumerate_tokens():\n        found_tokens.add(token)\n\n    assert \"token1\" in found_tokens\n    assert \"token2\" in found_tokens\n    assert len(found_tokens) == 2\n\n    await event_namespace1._token_manager.disconnect_all()\n\n    found_tokens = set()\n    async for token in event_namespace1._token_manager.enumerate_tokens():\n        found_tokens.add(token)\n    assert \"token2\" in found_tokens\n    assert len(found_tokens) == 1\n\n    await event_namespace2._token_manager.disconnect_all()\n\n    found_tokens = set()\n    async for token in event_namespace1._token_manager.enumerate_tokens():\n        found_tokens.add(token)\n    assert not found_tokens\n\n\n@pytest.mark.usefixtures(\"redis_url\")\n@pytest.mark.asyncio\nasync def test_redis_token_manager_get_token_owner(\n    event_namespace_factory: Callable[[], EventNamespace],\n):\n    \"\"\"Integration test for RedisTokenManager get_token_owner interface.\n\n    Should support retrieving the owner of a token across separate instances of the\n    RedisTokenManager.\n\n    Args:\n        event_namespace_factory: Factory fixture for EventNamespace instances.\n    \"\"\"\n    event_namespace1 = event_namespace_factory()\n    event_namespace2 = event_namespace_factory()\n\n    await event_namespace1.on_connect(sid=\"sid1\", environ=query_string_for(\"token1\"))\n    await event_namespace2.on_connect(sid=\"sid2\", environ=query_string_for(\"token2\"))\n\n    assert isinstance((manager1 := event_namespace1._token_manager), RedisTokenManager)\n    assert isinstance((manager2 := event_namespace2._token_manager), RedisTokenManager)\n\n    assert await manager1._get_token_owner(\"token1\") == manager1.instance_id\n    assert await manager1._get_token_owner(\"token2\") == manager2.instance_id\n    assert await manager2._get_token_owner(\"token1\") == manager1.instance_id\n    assert await manager2._get_token_owner(\"token2\") == manager2.instance_id\n\n\nasync def _wait_for_call_count_positive(mock: Mock, timeout: float = 5.0):\n    \"\"\"Wait until the mock's call count is positive.\n\n    Args:\n        mock: The mock to wait on.\n        timeout: The maximum time to wait in seconds.\n    \"\"\"\n    deadline = time.monotonic() + timeout\n    while mock.call_count == 0 and time.monotonic() < deadline:  # noqa: ASYNC110\n        await asyncio.sleep(0.1)\n\n\n@pytest.mark.usefixtures(\"redis_url\")\n@pytest.mark.asyncio\nasync def test_redis_token_manager_lost_and_found(\n    event_namespace_factory: Callable[[], EventNamespace],\n):\n    \"\"\"Updates emitted for lost and found tokens should be routed correctly via redis.\n\n    Args:\n        event_namespace_factory: Factory fixture for EventNamespace instances.\n    \"\"\"\n    event_namespace1 = event_namespace_factory()\n    emit1_mock: Mock = event_namespace1.emit  # pyright: ignore[reportAssignmentType]\n    event_namespace2 = event_namespace_factory()\n    emit2_mock: Mock = event_namespace2.emit  # pyright: ignore[reportAssignmentType]\n\n    await event_namespace1.on_connect(sid=\"sid1\", environ=query_string_for(\"token1\"))\n    await event_namespace2.on_connect(sid=\"sid2\", environ=query_string_for(\"token2\"))\n\n    await event_namespace2.emit_update(StateUpdate(), token=\"token1\")\n    await _wait_for_call_count_positive(emit1_mock)\n    emit2_mock.assert_not_called()\n    emit1_mock.assert_called_once()\n    emit1_mock.reset_mock()\n\n    await event_namespace2.emit_update(StateUpdate(), token=\"token2\")\n    await _wait_for_call_count_positive(emit2_mock)\n    emit1_mock.assert_not_called()\n    emit2_mock.assert_called_once()\n    emit2_mock.reset_mock()\n\n    if task := event_namespace1.on_disconnect(sid=\"sid1\"):\n        await task\n    await event_namespace2.emit_update(StateUpdate(), token=\"token1\")\n    # Update should be dropped on the floor.\n    await asyncio.sleep(2)\n    emit1_mock.assert_not_called()\n    emit2_mock.assert_not_called()\n\n    await event_namespace2.on_connect(sid=\"sid1\", environ=query_string_for(\"token1\"))\n    await event_namespace2.emit_update(StateUpdate(), token=\"token1\")\n    await _wait_for_call_count_positive(emit2_mock)\n    emit1_mock.assert_not_called()\n    emit2_mock.assert_called_once()\n    emit2_mock.reset_mock()\n\n    if task := event_namespace2.on_disconnect(sid=\"sid1\"):\n        await task\n    await event_namespace1.on_connect(sid=\"sid1\", environ=query_string_for(\"token1\"))\n    await event_namespace2.emit_update(StateUpdate(), token=\"token1\")\n    await _wait_for_call_count_positive(emit1_mock)\n    emit2_mock.assert_not_called()\n    emit1_mock.assert_called_once()\n    emit1_mock.reset_mock()\n\n\n@pytest.mark.usefixtures(\"redis_url\")\n@pytest.mark.asyncio\nasync def test_redis_token_manager_lost_and_found_router_data(\n    event_namespace_factory: Callable[[], EventNamespace],\n):\n    \"\"\"Updates emitted for lost and found tokens should serialize properly.\n\n    Args:\n        event_namespace_factory: Factory fixture for EventNamespace instances.\n    \"\"\"\n    event_namespace1 = event_namespace_factory()\n    emit1_mock: Mock = event_namespace1.emit  # pyright: ignore[reportAssignmentType]\n    event_namespace2 = event_namespace_factory()\n    emit2_mock: Mock = event_namespace2.emit  # pyright: ignore[reportAssignmentType]\n\n    await event_namespace1.on_connect(sid=\"sid1\", environ=query_string_for(\"token1\"))\n    await event_namespace2.on_connect(sid=\"sid2\", environ=query_string_for(\"token2\"))\n\n    router = RouterData.from_router_data(\n        {\"headers\": {\"x-test\": \"value\"}},\n    )\n\n    await event_namespace2.emit_update(\n        StateUpdate(delta={\"state\": {\"router\": router}}), token=\"token1\"\n    )\n    await _wait_for_call_count_positive(emit1_mock)\n    emit2_mock.assert_not_called()\n    emit1_mock.assert_called_once()\n    assert isinstance(emit1_mock.call_args[0][1], StateUpdate)\n    assert isinstance(emit1_mock.call_args[0][1].delta[\"state\"][\"router\"], RouterData)\n    assert emit1_mock.call_args[0][1].delta[\"state\"][\"router\"] == router\n    emit1_mock.reset_mock()\n"
  },
  {
    "path": "tests/units/utils/test_types.py",
    "content": "from typing import Any, Literal, TypedDict\n\nimport pytest\n\nfrom reflex.utils import types\nfrom reflex.vars.base import Var\n\n\n@pytest.mark.parametrize(\n    (\"params\", \"allowed_value_str\", \"value_str\"),\n    [\n        ([\"size\", 1, Literal[\"1\", \"2\", \"3\"], \"Heading\"], \"'1','2','3'\", \"1\"),\n        ([\"size\", \"1\", Literal[1, 2, 3], \"Heading\"], \"1,2,3\", \"'1'\"),\n    ],\n)\ndef test_validate_literal_error_msg(params, allowed_value_str, value_str):\n    with pytest.raises(ValueError) as err:\n        types.validate_literal(*params)\n\n    assert (\n        err.value.args[0] == f\"prop value for {params[0]!s} of the `{params[-1]}` \"\n        f\"component should be one of the following: {allowed_value_str}. Got {value_str} instead\"\n    )\n\n\n@pytest.mark.parametrize(\n    (\"cls\", \"cls_check\", \"expected\"),\n    [\n        (int, Any, True),\n        (tuple[int], Any, True),\n        (list[int], Any, True),\n        (int, int, True),\n        (int, object, True),\n        (int, int | str, True),\n        (int, str | int, True),\n        (str, str | int, True),\n        (str, int | str, True),\n        (int, str | float | int, True),\n        (int, str | float, False),\n        (int, float | str, False),\n        (int, str, False),\n        (int, list[int], False),\n    ],\n)\ndef test_issubclass(\n    cls: types.GenericType, cls_check: types.GenericType, expected: bool\n) -> None:\n    assert types._issubclass(cls, cls_check) == expected\n\n\nclass CustomDict(dict[str, str]):\n    \"\"\"A custom dict with generic arguments.\"\"\"\n\n\nclass ChildCustomDict(CustomDict):\n    \"\"\"A child of CustomDict.\"\"\"\n\n\nclass GenericDict(dict):\n    \"\"\"A generic dict with no generic arguments.\"\"\"\n\n\nclass ChildGenericDict(GenericDict):\n    \"\"\"A child of GenericDict.\"\"\"\n\n\n@pytest.mark.parametrize(\n    (\"cls\", \"expected\"),\n    [\n        (int, False),\n        (str, False),\n        (float, False),\n        (tuple[int], True),\n        (list[int], True),\n        (int | str, True),\n        (str | int, True),\n        (dict[str, int], True),\n        (CustomDict, True),\n        (ChildCustomDict, True),\n        (GenericDict, False),\n        (ChildGenericDict, False),\n    ],\n)\ndef test_has_args(cls, expected: bool) -> None:\n    assert types.has_args(cls) == expected\n\n\nclass UserInfo(TypedDict, total=False):\n    \"\"\"A sample typed dict.\"\"\"\n\n    sub: str\n    name: str\n    email: str\n\n\nclass UserInfoTotal(TypedDict, total=True):\n    \"\"\"A sample typed dict.\"\"\"\n\n    sub: str\n    name: str\n    email: str\n\n\n@pytest.mark.parametrize(\n    (\"value\", \"cls\", \"expected\"),\n    [\n        (1, int, True),\n        (1, str, False),\n        (1, float, True),\n        (\"1\", str, True),\n        (\"1\", int, False),\n        (1.0, float, True),\n        (1.0, int, False),\n        ([], list[int], True),\n        ([1], list[int], True),\n        ([1.0], list[int], False),\n        ([1], list[str], False),\n        ({}, dict[str, str], True),\n        ({\"a\": \"b\"}, dict[str, str], True),\n        ({\"a\": 1}, dict[str, str], False),\n        (False, bool, True),\n        (False, Var[bool], True),\n        (False, Var[bool] | None, True),\n        (Var.create(False), bool, True),\n        (Var.create(False), Var[bool], True),\n        (Var.create(False), Var[bool] | None, True),\n        (Var.create(False), Var[bool] | str, True),\n        ({\"sub\": \"123\", \"name\": \"John\"}, UserInfo, True),\n        ({\"sub\": \"123\"}, UserInfo, True),\n        ({\"sub\": 123}, UserInfo, False),\n        ({\"sub\": \"123\", \"age\": 30}, UserInfo, True),\n        ({\"sub\": \"123\", \"name\": \"John\"}, UserInfoTotal, False),\n        ({\"sub\": \"123\"}, UserInfoTotal, False),\n        ({\"sub\": 123}, UserInfoTotal, False),\n        ({\"sub\": \"123\", \"age\": 30}, UserInfoTotal, False),\n    ],\n)\ndef test_isinstance(value, cls, expected: bool) -> None:\n    assert types._isinstance(value, cls, nested=2, treat_var_as_type=True) == expected\n"
  },
  {
    "path": "tests/units/utils/test_utils.py",
    "content": "import os\nimport typing\nfrom collections.abc import Mapping, Sequence\nfrom functools import cached_property\nfrom pathlib import Path\nfrom typing import Any, ClassVar, List, Literal, NoReturn  # noqa: UP035\n\nimport pytest\nfrom packaging import version\nfrom pytest_mock import MockerFixture\n\nfrom reflex import constants\nfrom reflex.environment import environment\nfrom reflex.event import EventHandler\nfrom reflex.state import BaseState\nfrom reflex.utils import exec as utils_exec\nfrom reflex.utils import frontend_skeleton, js_runtimes, prerequisites, templates, types\nfrom reflex.utils.exceptions import ReflexError, SystemPackageMissingError\nfrom reflex.vars.base import Var\n\n\nclass ExampleTestState(BaseState):\n    \"\"\"Test state class.\"\"\"\n\n    def test_event_handler(self):\n        \"\"\"Test event handler.\"\"\"\n\n\ndef test_func():\n    pass\n\n\n@pytest.mark.parametrize(\n    (\"cls\", \"expected\"),\n    [\n        (str, False),\n        (int, False),\n        (float, False),\n        (bool, False),\n        (List, True),  # noqa: UP006\n        (list[int], True),\n    ],\n)\ndef test_is_generic_alias(cls: type, expected: bool):\n    \"\"\"Test checking if a class is a GenericAlias.\n\n    Args:\n        cls: The class to check.\n        expected: Whether the class is a GenericAlias.\n    \"\"\"\n    assert types.is_generic_alias(cls) == expected\n\n\n@pytest.mark.parametrize(\n    (\"subclass\", \"superclass\", \"expected\"),\n    [\n        *[\n            (base_type, base_type, True)\n            for base_type in [int, float, str, bool, list, dict]\n        ],\n        *[\n            (one_type, another_type, False)\n            for one_type in [int, float, str, list, dict]\n            for another_type in [int, float, str, list, dict]\n            if one_type != another_type\n        ],\n        (bool, int, True),\n        (int, bool, False),\n        (list, list, True),\n        (list, list[str], True),  # this is wrong, but it's a limitation of the function\n        (list[int], list, True),\n        (list[int], list[str], False),\n        (list[int], list[int], True),\n        (list[int], list[float], False),\n        (list[int], list[int | float], True),\n        (list[int], list[float | str], False),\n        (int | float, list[int | float], False),\n        (int | float, int | float | str, True),\n        (int | float, str | float, False),\n        (dict[str, int], dict[str, int], True),\n        (dict[str, bool], dict[str, int], True),\n        (dict[str, int], dict[str, bool], False),\n        (dict[str, Any], dict[str, str], False),\n        (dict[str, str], dict[str, str], True),\n        (dict[str, str], dict[str, Any], True),\n        (dict[str, Any], dict[str, Any], True),\n        (Mapping[str, int], dict[str, int], False),\n        (Sequence[int], list[int], False),\n        (Sequence[int] | list[int], list[int], False),\n        (str, Literal[\"test\", \"value\"], True),\n        (str, Literal[\"test\", \"value\", 2, 3], True),\n        (int, Literal[\"test\", \"value\"], False),\n        (int, Literal[\"test\", \"value\", 2, 3], True),\n        (Literal[\"test\", \"value\"], str, True),\n        (Literal[\"test\", \"value\", 2, 3], str, False),\n        (Literal[\"test\", \"value\"], int, False),\n        (Literal[\"test\", \"value\", 2, 3], int, False),\n        *[\n            (NoReturn, super_class, True)\n            for super_class in [int, float, str, bool, list, dict, object, Any]\n        ],\n        *[\n            (list[NoReturn], list[super_class], True)\n            for super_class in [int, float, str, bool, list, dict, object, Any]\n        ],\n    ],\n)\ndef test_typehint_issubclass(subclass, superclass, expected):\n    assert types.typehint_issubclass(subclass, superclass) == expected\n\n\n@pytest.mark.parametrize(\n    (\"subclass\", \"superclass\", \"expected\"),\n    [\n        *[\n            (base_type, base_type, True)\n            for base_type in [int, float, str, bool, list, dict]\n        ],\n        *[\n            (one_type, another_type, False)\n            for one_type in [int, float, str, list, dict]\n            for another_type in [int, float, str, list, dict]\n            if one_type != another_type\n        ],\n        (bool, int, True),\n        (int, bool, False),\n        (list, list, True),\n        (list, list[str], True),  # this is wrong, but it's a limitation of the function\n        (list[int], list, True),\n        (list[int], list[str], False),\n        (list[int], list[int], True),\n        (list[int], list[float], False),\n        (list[int], list[int | float], True),\n        (list[int], list[float | str], False),\n        (int | float, list[int | float], False),\n        (int | float, int | float | str, True),\n        (int | float, str | float, False),\n        (dict[str, int], dict[str, int], True),\n        (dict[str, bool], dict[str, int], True),\n        (dict[str, int], dict[str, bool], False),\n        (dict[str, Any], dict[str, str], False),\n        (dict[str, str], dict[str, str], True),\n        (dict[str, str], dict[str, Any], True),\n        (dict[str, Any], dict[str, Any], True),\n        (Mapping[str, int], dict[str, int], True),\n        (Sequence[int], list[int], True),\n        (Sequence[int] | list[int], list[int], True),\n        (str, Literal[\"test\", \"value\"], True),\n        (str, Literal[\"test\", \"value\", 2, 3], True),\n        (int, Literal[\"test\", \"value\"], False),\n        (int, Literal[\"test\", \"value\", 2, 3], True),\n        *[\n            (NoReturn, super_class, True)\n            for super_class in [int, float, str, bool, list, dict, object, Any]\n        ],\n        *[\n            (list[NoReturn], list[super_class], True)\n            for super_class in [int, float, str, bool, list, dict, object, Any]\n        ],\n    ],\n)\ndef test_typehint_issubclass_mutable_as_immutable(subclass, superclass, expected):\n    assert (\n        types.typehint_issubclass(\n            subclass, superclass, treat_mutable_superclasss_as_immutable=True\n        )\n        == expected\n    )\n\n\ndef test_validate_none_bun_path(mocker: MockerFixture):\n    \"\"\"Test that an error is thrown when a bun path is not specified.\n\n    Args:\n        mocker: Pytest mocker object.\n    \"\"\"\n    mocker.patch(\"reflex.utils.path_ops.get_bun_path\", return_value=None)\n    # with pytest.raises(click.exceptions.Exit):\n    js_runtimes.validate_bun()\n\n\ndef test_validate_invalid_bun_path(mocker: MockerFixture):\n    \"\"\"Test that an error is thrown when a custom specified bun path is not valid\n    or does not exist.\n\n    Args:\n        mocker: Pytest mocker object.\n    \"\"\"\n    mock_path = mocker.Mock()\n    mocker.patch(\"reflex.utils.path_ops.get_bun_path\", return_value=mock_path)\n    mocker.patch(\"reflex.utils.path_ops.samefile\", return_value=False)\n    mocker.patch(\"reflex.utils.js_runtimes.get_bun_version\", return_value=None)\n\n    with pytest.raises(SystemExit):\n        js_runtimes.validate_bun()\n\n\ndef test_validate_bun_path_incompatible_version(mocker: MockerFixture):\n    \"\"\"Test that an error is thrown when the bun version does not meet minimum requirements.\n\n    Args:\n        mocker: Pytest mocker object.\n    \"\"\"\n    mock_path = mocker.Mock()\n    mock_path.samefile.return_value = False\n    mocker.patch(\"reflex.utils.path_ops.get_bun_path\", return_value=mock_path)\n    mocker.patch(\"reflex.utils.path_ops.samefile\", return_value=False)\n    mocker.patch(\n        \"reflex.utils.js_runtimes.get_bun_version\",\n        return_value=version.parse(\"0.6.5\"),\n    )\n\n    # This will just warn the user, not raise an error\n    js_runtimes.validate_bun()\n\n\ndef test_remove_existing_bun_installation(mocker: MockerFixture):\n    \"\"\"Test that existing bun installation is removed.\n\n    Args:\n        mocker: Pytest mocker.\n    \"\"\"\n    mocker.patch(\"reflex.utils.js_runtimes.Path.exists\", return_value=True)\n    rm = mocker.patch(\"reflex.utils.js_runtimes.path_ops.rm\", mocker.Mock())\n\n    js_runtimes.remove_existing_bun_installation()\n    rm.assert_called_once()\n\n\n@pytest.fixture\ndef test_backend_variable_cls():\n    class TestBackendVariable(BaseState):\n        \"\"\"Test backend variable.\"\"\"\n\n        _classvar: ClassVar[int] = 0\n        _hidden: int = 0\n        not_hidden: int = 0\n        __dunderattr__: int = 0\n\n        @classmethod\n        def _class_method(cls):\n            pass\n\n        def _hidden_method(self):\n            pass\n\n        @property\n        def _hidden_property(self):\n            pass\n\n        @cached_property\n        def _cached_hidden_property(self):\n            pass\n\n    return TestBackendVariable\n\n\n@pytest.mark.parametrize(\n    (\"input\", \"output\"),\n    [\n        (\"_classvar\", False),\n        (\"_class_method\", False),\n        (\"_hidden_method\", False),\n        (\"_hidden\", True),\n        (\"not_hidden\", False),\n        (\"__dundermethod__\", False),\n        (\"_hidden_property\", False),\n        (\"_cached_hidden_property\", False),\n    ],\n)\ndef test_is_backend_base_variable(\n    test_backend_variable_cls: type[BaseState], input: str, output: bool\n):\n    assert types.is_backend_base_variable(input, test_backend_variable_cls) == output\n\n\n@pytest.mark.parametrize(\n    (\"cls\", \"cls_check\", \"expected\"),\n    [\n        (int, int, True),\n        (int, float, False),\n        (int, int | float, True),\n        (float, int | float, True),\n        (str, int | float, False),\n        (list[int], list[int], True),\n        (list[int], list[float], True),\n        (int | float, int | float, False),\n        (int | Var[int], Var[int], False),\n        (int, Any, True),\n        (Any, Any, True),\n        (int | float, Any, True),\n        (str, Literal[\"test\", \"value\"] | int, True),\n        (int, Literal[\"test\", \"value\"] | int, True),\n        (str, Literal[\"test\", \"value\"], True),\n        (int, Literal[\"test\", \"value\"], False),\n    ],\n)\ndef test_issubclass(cls: type, cls_check: type, expected: bool):\n    assert types._issubclass(cls, cls_check) == expected\n\n\n@pytest.mark.parametrize(\"cls\", [Literal[\"test\", 1], Literal[1, \"test\"]])\ndef test_unsupported_literals(cls: type):\n    with pytest.raises(TypeError):\n        types.get_base_class(cls)\n\n\n@pytest.mark.parametrize(\n    (\"app_name\", \"expected_config_name\"),\n    [\n        (\"appname\", \"AppnameConfig\"),\n        (\"app_name\", \"AppnameConfig\"),\n        (\"app-name\", \"AppnameConfig\"),\n        (\"appname2.io\", \"AppnameioConfig\"),\n    ],\n)\ndef test_create_config(app_name: str, expected_config_name: str, mocker: MockerFixture):\n    \"\"\"Test templates.rxconfig_template is formatted with correct app name and config class name.\n\n    Args:\n        app_name: App name.\n        expected_config_name: Expected config name.\n        mocker: Mocker object.\n    \"\"\"\n    mocker.patch(\"pathlib.Path.write_text\")\n    tmpl_mock = mocker.patch(\"reflex.compiler.templates.rxconfig_template\")\n    templates.create_config(app_name)\n    tmpl_mock.assert_called_with(app_name=app_name)\n\n\n@pytest.fixture\ndef tmp_working_dir(tmp_path):\n    \"\"\"Create a temporary directory and chdir to it.\n\n    After the test executes, chdir back to the original working directory.\n\n    Args:\n        tmp_path: pytest tmp_path fixture creates per-test temp dir\n\n    Yields:\n        subdirectory of tmp_path which is now the current working directory.\n    \"\"\"\n    old_pwd = Path.cwd()\n    working_dir = tmp_path / \"working_dir\"\n    working_dir.mkdir()\n    os.chdir(working_dir)\n    yield working_dir\n    os.chdir(old_pwd)\n\n\ndef test_create_config_e2e(tmp_working_dir):\n    \"\"\"Create a new config file, exec it, and make assertions about the config.\n\n    Args:\n        tmp_working_dir: a new directory that is the current working directory\n            for the duration of the test.\n    \"\"\"\n    app_name = \"e2e\"\n    templates.create_config(app_name)\n    eval_globals = {}\n    exec((tmp_working_dir / constants.Config.FILE).read_text(), eval_globals)\n    config = eval_globals[\"config\"]\n    assert config.app_name == app_name\n\n\nclass DataFrame:\n    \"\"\"A Fake pandas DataFrame class.\"\"\"\n\n\n@pytest.mark.parametrize(\n    (\"class_type\", \"expected\"),\n    [\n        (list, False),\n        (int, False),\n        (dict, False),\n        (DataFrame, True),\n        (typing.Any, False),\n    ],\n)\ndef test_is_dataframe(class_type, expected):\n    \"\"\"Test that a type name is DataFrame.\n\n    Args:\n        class_type: the class type.\n        expected: whether type name is DataFrame\n    \"\"\"\n    assert types.is_dataframe(class_type) == expected\n\n\n@pytest.mark.parametrize(\"gitignore_exists\", [True, False])\ndef test_initialize_non_existent_gitignore(\n    tmp_path, mocker: MockerFixture, gitignore_exists\n):\n    \"\"\"Test that the generated .gitignore_file file on reflex init contains the correct file\n    names with correct formatting.\n\n    Args:\n        tmp_path: The root test path.\n        mocker: The mock object.\n        gitignore_exists: Whether a gitignore file exists in the root dir.\n    \"\"\"\n    expected = constants.GitIgnore.DEFAULTS.copy()\n    mocker.patch(\"reflex.constants.GitIgnore.FILE\", tmp_path / \".gitignore\")\n\n    gitignore_file = tmp_path / \".gitignore\"\n\n    if gitignore_exists:\n        gitignore_file.touch()\n        gitignore_file.write_text(\n            \"\"\"*.db\n        __pycache__/\n        \"\"\"\n        )\n\n    frontend_skeleton.initialize_gitignore(gitignore_file=gitignore_file)\n\n    assert gitignore_file.exists()\n    file_content = [\n        line.strip() for line in gitignore_file.open().read().splitlines() if line\n    ]\n    assert set(file_content) - expected == set()\n\n\ndef test_validate_app_name(tmp_path, mocker: MockerFixture):\n    \"\"\"Test that an error is raised if the app name is reflex or if the name is not according to python package naming conventions.\n\n    Args:\n        tmp_path: Test working dir.\n        mocker: Pytest mocker object.\n    \"\"\"\n    reflex = tmp_path / \"reflex\"\n    reflex.mkdir()\n\n    mocker.patch(\"os.getcwd\", return_value=str(reflex))\n\n    with pytest.raises(SystemExit):\n        prerequisites.validate_app_name()\n\n    with pytest.raises(SystemExit):\n        prerequisites.validate_app_name(app_name=\"1_test\")\n\n\ndef test_bun_install_without_unzip(mocker: MockerFixture):\n    \"\"\"Test that an error is thrown when installing bun with unzip not installed.\n\n    Args:\n        mocker: Pytest mocker object.\n    \"\"\"\n    mocker.patch(\"reflex.utils.path_ops.which\", return_value=None)\n    mocker.patch(\"pathlib.Path.exists\", return_value=False)\n    mocker.patch(\"reflex.utils.prerequisites.constants.IS_WINDOWS\", False)\n\n    with pytest.raises(SystemPackageMissingError):\n        js_runtimes.install_bun()\n\n\n@pytest.mark.parametrize(\"bun_version\", [constants.Bun.VERSION, \"1.0.0\"])\ndef test_bun_install_version(mocker: MockerFixture, bun_version):\n    \"\"\"Test that bun is downloaded when the host version(installed by reflex)\n    different from the current version set in reflex.\n\n    Args:\n        mocker: Pytest mocker object.\n        bun_version: the host bun version\n\n    \"\"\"\n    mocker.patch(\"reflex.utils.prerequisites.constants.IS_WINDOWS\", False)\n    mocker.patch(\"pathlib.Path.exists\", return_value=True)\n    mocker.patch(\n        \"reflex.utils.js_runtimes.get_bun_version\",\n        return_value=version.parse(bun_version),\n    )\n    mocker.patch(\"reflex.utils.path_ops.which\")\n    mock = mocker.patch(\"reflex.utils.js_runtimes.download_and_run\")\n\n    js_runtimes.install_bun()\n    if bun_version == constants.Bun.VERSION:\n        mock.assert_not_called()\n    else:\n        mock.assert_called_once()\n\n\n@pytest.mark.parametrize(\"is_windows\", [True, False])\ndef test_create_reflex_dir(mocker: MockerFixture, is_windows):\n    \"\"\"Test that a reflex directory is created on initializing frontend\n    dependencies.\n\n    Args:\n        mocker: Pytest mocker object.\n        is_windows: Whether platform is windows.\n    \"\"\"\n    mocker.patch(\"reflex.utils.prerequisites.constants.IS_WINDOWS\", is_windows)\n    mocker.patch(\"reflex.utils.processes.run_concurrently\", mocker.Mock())\n    mocker.patch(\n        \"reflex.utils.frontend_skeleton.initialize_web_directory\", mocker.Mock()\n    )\n    mocker.patch(\"reflex.utils.processes.run_concurrently\")\n    mocker.patch(\"reflex.utils.js_runtimes.validate_bun\")\n    create_cmd = mocker.patch(\n        \"reflex.utils.prerequisites.path_ops.mkdir\", mocker.Mock()\n    )\n\n    prerequisites.initialize_reflex_user_directory()\n\n    assert create_cmd.called\n\n\ndef test_output_system_info(mocker: MockerFixture):\n    \"\"\"Make sure reflex does not crash dumping system info.\n\n    Args:\n        mocker: Pytest mocker object.\n\n    This test makes no assertions about the output, other than it executes\n    without crashing.\n    \"\"\"\n    mocker.patch(\"reflex.utils.console._LOG_LEVEL\", constants.LogLevel.DEBUG)\n    utils_exec.output_system_info()\n\n\n@pytest.mark.parametrize(\n    \"callable\", [ExampleTestState.test_event_handler, test_func, lambda x: x]\n)\ndef test_style_prop_with_event_handler_value(callable):\n    \"\"\"Test that a type error is thrown when a style prop has a\n    callable as value.\n\n    Args:\n        callable: The callable function or event handler.\n\n    \"\"\"\n    import reflex as rx\n\n    style = {\n        \"color\": (\n            EventHandler(fn=callable)\n            if type(callable) is not EventHandler\n            else callable\n        )\n    }\n\n    with pytest.raises(ReflexError):\n        rx.box(style=style)\n\n\ndef test_is_prod_mode() -> None:\n    \"\"\"Test that the prod mode is correctly determined.\"\"\"\n    environment.REFLEX_ENV_MODE.set(constants.Env.PROD)\n    assert utils_exec.is_prod_mode()\n    environment.REFLEX_ENV_MODE.set(None)\n    assert not utils_exec.is_prod_mode()\n"
  },
  {
    "path": "tests/units/vars/test_base.py",
    "content": "from collections.abc import Mapping, Sequence\n\nimport pytest\n\nfrom reflex.state import State\nfrom reflex.vars.base import computed_var, figure_out_type\n\n\nclass CustomDict(dict[str, str]):\n    \"\"\"A custom dict with generic arguments.\"\"\"\n\n\nclass ChildCustomDict(CustomDict):\n    \"\"\"A child of CustomDict.\"\"\"\n\n\nclass GenericDict(dict):\n    \"\"\"A generic dict with no generic arguments.\"\"\"\n\n\nclass ChildGenericDict(GenericDict):\n    \"\"\"A child of GenericDict.\"\"\"\n\n\n@pytest.mark.parametrize(\n    (\"value\", \"expected\"),\n    [\n        (1, int),\n        (1.0, float),\n        (\"a\", str),\n        ([1, 2, 3], Sequence[int]),\n        ([1, 2.0, \"a\"], Sequence[int | float | str]),\n        ({\"a\": 1, \"b\": 2}, Mapping[str, int]),\n        ({\"a\": 1, 2: \"b\"}, Mapping[int | str, str | int]),\n        (CustomDict(), CustomDict),\n        (ChildCustomDict(), ChildCustomDict),\n        (GenericDict({1: 1}), Mapping[int, int]),\n        (ChildGenericDict({1: 1}), Mapping[int, int]),\n    ],\n)\ndef test_figure_out_type(value, expected):\n    assert figure_out_type(value) == expected\n\n\ndef test_computed_var_replace() -> None:\n    class StateTest(State):\n        @computed_var(cache=True)\n        def cv(self) -> int:\n            return 1\n\n    cv = StateTest.cv\n    assert cv._var_type is int\n\n    replaced = cv._replace(_var_type=float)\n    assert replaced._var_type is float\n"
  },
  {
    "path": "tests/units/vars/test_dep_tracking.py",
    "content": "\"\"\"Tests for dependency tracking functionality.\"\"\"\n\nfrom __future__ import annotations\n\nimport sys\n\nimport pytest\n\nimport reflex as rx\nimport tests.units.states.upload as tus_upload\nfrom reflex.state import State\nfrom reflex.utils.exceptions import VarValueError\nfrom reflex.vars.dep_tracking import (\n    DependencyTracker,\n    UntrackedLocalVarError,\n    get_cell_value,\n)\n\n\nclass DependencyTestState(State):\n    \"\"\"Test state for dependency tracking tests.\"\"\"\n\n    count: rx.Field[int] = rx.field(default=0)\n    name: rx.Field[str] = rx.field(default=\"test\")\n    items: rx.Field[list[str]] = rx.field(default_factory=list)\n    board: rx.Field[list[list[int]]] = rx.field(default_factory=list)\n\n\nclass AnotherTestState(State):\n    \"\"\"Another test state for cross-state dependencies.\"\"\"\n\n    value: rx.Field[int] = rx.field(default=42)\n    text: rx.Field[str] = rx.field(default=\"hello\")\n\n\ndef test_simple_attribute_access():\n    \"\"\"Test tracking simple attribute access on self.\"\"\"\n\n    def simple_func(self: DependencyTestState):\n        return self.count\n\n    tracker = DependencyTracker(simple_func, DependencyTestState)\n\n    expected_deps = {DependencyTestState.get_full_name(): {\"count\"}}\n    assert tracker.dependencies == expected_deps\n\n\ndef test_multiple_attribute_access():\n    \"\"\"Test tracking multiple attribute access on self.\"\"\"\n\n    def multi_attr_func(self: DependencyTestState):\n        return self.count + len(self.name) + len(self.items)\n\n    tracker = DependencyTracker(multi_attr_func, DependencyTestState)\n\n    expected_deps = {DependencyTestState.get_full_name(): {\"count\", \"name\", \"items\"}}\n    assert tracker.dependencies == expected_deps\n\n\ndef test_method_call_dependencies():\n    \"\"\"Test tracking dependencies from method calls.\"\"\"\n\n    class StateWithMethod(State):\n        value: int = 0\n\n        def helper_method(self):\n            return self.value * 2\n\n        def func_with_method_call(self):\n            return self.helper_method()\n\n    tracker = DependencyTracker(StateWithMethod.func_with_method_call, StateWithMethod)\n\n    # Should track dependencies from both the method call and the method itself\n    expected_deps = {StateWithMethod.get_full_name(): {\"value\"}}\n    assert tracker.dependencies == expected_deps\n\n\ndef test_nested_function_dependencies():\n    \"\"\"Test tracking dependencies in nested functions.\"\"\"\n\n    def func_with_nested(self: DependencyTestState):\n        def inner():\n            return self.count\n\n        return inner()\n\n    tracker = DependencyTracker(func_with_nested, DependencyTestState)\n\n    expected_deps = {DependencyTestState.get_full_name(): {\"count\"}}\n    assert tracker.dependencies == expected_deps\n\n\ndef test_list_comprehension_dependencies():\n    \"\"\"Test tracking dependencies in list comprehensions.\"\"\"\n\n    def func_with_comprehension(self: DependencyTestState):\n        return [x for x in self.items if len(x) > self.count]\n\n    tracker = DependencyTracker(func_with_comprehension, DependencyTestState)\n\n    expected_deps = {DependencyTestState.get_full_name(): {\"items\", \"count\"}}\n    assert tracker.dependencies == expected_deps\n\n\ndef test_list_comprehension_dependencies_2():\n    \"\"\"Test tracking dependencies in list comprehensions.\"\"\"\n\n    def func_with_comprehension(self: DependencyTestState):\n        return [[self.board[r][c] for r in range(3)] for c in range(5)]\n\n    tracker = DependencyTracker(func_with_comprehension, DependencyTestState)\n\n    expected_deps = {DependencyTestState.get_full_name(): {\"board\"}}\n    assert tracker.dependencies == expected_deps\n\n\ndef test_invalid_attribute_access():\n    \"\"\"Test that accessing invalid attributes raises VarValueError.\"\"\"\n\n    def invalid_func(self: DependencyTestState):\n        return self.parent_state\n\n    with pytest.raises(\n        VarValueError, match=\"cannot access arbitrary state via `parent_state`\"\n    ):\n        DependencyTracker(invalid_func, DependencyTestState)\n\n\ndef test_get_state_functionality():\n    \"\"\"Test tracking dependencies when using get_state.\"\"\"\n\n    async def func_with_get_state(self: DependencyTestState):\n        other_state = await self.get_state(AnotherTestState)\n        return other_state.value\n\n    tracker = DependencyTracker(func_with_get_state, DependencyTestState)\n\n    expected_deps = {AnotherTestState.get_full_name(): {\"value\"}}\n    assert tracker.dependencies == expected_deps\n\n\ndef test_get_state_functionality_direct():\n    \"\"\"Test tracking dependencies when using get_state without assigning to interim local variable.\"\"\"\n\n    async def func_with_get_state_direct(self: DependencyTestState):\n        return (await self.get_state(AnotherTestState)).value\n\n    tracker = DependencyTracker(func_with_get_state_direct, DependencyTestState)\n\n    expected_deps = {AnotherTestState.get_full_name(): {\"value\"}}\n    assert tracker.dependencies == expected_deps\n\n\ndef test_get_state_with_local_var_error():\n    \"\"\"Test that get_state with local variables raises appropriate error.\"\"\"\n\n    async def invalid_get_state_func(self: DependencyTestState):\n        state_cls = AnotherTestState\n        return (await self.get_state(state_cls)).value\n\n    with pytest.raises(\n        UntrackedLocalVarError, match=\"'state_cls' is not tracked in the current scope\"\n    ):\n        DependencyTracker(invalid_get_state_func, DependencyTestState)\n\n\ndef test_get_state_with_import_from():\n    \"\"\"Test that get_state with function-local `from ... import ...` finds correct dependency.\"\"\"\n\n    async def get_state_import_from(self: DependencyTestState):\n        from tests.units.states.mutation import MutableTestState\n\n        return (await self.get_state(MutableTestState)).hashmap\n\n    from tests.units.states.mutation import MutableTestState\n\n    tracker = DependencyTracker(get_state_import_from, DependencyTestState)\n    expected_deps = {MutableTestState.get_full_name(): {\"hashmap\"}}\n    assert tracker.dependencies == expected_deps\n\n\ndef test_get_state_with_import_from_multiple():\n    \"\"\"Test that get_state with function-local `from ... import ...` finds correct dependency.\"\"\"\n\n    async def get_state_import_from(self: DependencyTestState):\n        from tests.units.states.upload import ChildFileUploadState, SubUploadState\n\n        return (await self.get_state(SubUploadState)).img, (\n            await self.get_state(ChildFileUploadState)\n        ).img_list\n\n    tracker = DependencyTracker(get_state_import_from, DependencyTestState)\n    expected_deps = {\n        tus_upload.SubUploadState.get_full_name(): {\"img\"},\n        tus_upload.ChildFileUploadState.get_full_name(): {\"img_list\"},\n    }\n    assert tracker.dependencies == expected_deps\n\n\ndef test_get_state_with_import_from_as():\n    \"\"\"Test that get_state with function-local `from ... import ... as ...` finds correct dependency.\"\"\"\n\n    async def get_state_import_from_as(self: DependencyTestState):\n        from tests.units.states.mutation import MutableTestState as mts\n\n        return (await self.get_state(mts)).hashmap\n\n    from tests.units.states.mutation import MutableTestState\n\n    tracker = DependencyTracker(get_state_import_from_as, DependencyTestState)\n    expected_deps = {MutableTestState.get_full_name(): {\"hashmap\"}}\n    assert tracker.dependencies == expected_deps\n\n\ndef test_get_state_with_import():\n    \"\"\"Test that get_state with function-local `import ...` finds correct dependency.\"\"\"\n\n    async def get_state_import(self: DependencyTestState):\n        import tests.units.states.mutation\n\n        return (\n            await self.get_state(tests.units.states.mutation.MutableTestState)\n        ).hashmap\n\n    from tests.units.states.mutation import MutableTestState\n\n    tracker = DependencyTracker(get_state_import, DependencyTestState)\n    expected_deps = {MutableTestState.get_full_name(): {\"hashmap\"}}\n    assert tracker.dependencies == expected_deps\n\n\ndef test_get_state_with_import_as():\n    \"\"\"Test that get_state with function-local `import ... as ...` finds correct dependency.\"\"\"\n\n    async def get_state_import_as(self: DependencyTestState):\n        import tests.units.states.mutation as mutation\n\n        return (await self.get_state(mutation.MutableTestState)).hashmap\n\n    from tests.units.states.mutation import MutableTestState\n\n    tracker = DependencyTracker(get_state_import_as, DependencyTestState)\n    expected_deps = {MutableTestState.get_full_name(): {\"hashmap\"}}\n    assert tracker.dependencies == expected_deps\n\n\ndef test_get_state_with_import_from_method():\n    \"\"\"Test that get_state with function-local `from ... import ...` finds correct dependency through a method call.\"\"\"\n\n    async def get_state_import_from(self: DependencyTestState):\n        from tests.units.states.mutation import MutableTestState\n\n        return (await self.get_state(MutableTestState))._get_array()\n\n    from tests.units.states.mutation import MutableTestState\n\n    tracker = DependencyTracker(get_state_import_from, DependencyTestState)\n    expected_deps = {MutableTestState.get_full_name(): {\"array\"}}\n    assert tracker.dependencies == expected_deps\n\n\ndef test_get_state_access_imported_global_module():\n    \"\"\"Test tracking simple attribute access on self.\"\"\"\n\n    async def get_state_imported_global(self: DependencyTestState):\n        return (await self.get_state(tus_upload.SubUploadState)).img\n\n    tracker = DependencyTracker(get_state_imported_global, DependencyTestState)\n    expected_deps = {tus_upload.SubUploadState.get_full_name(): {\"img\"}}\n    assert tracker.dependencies == expected_deps\n\n\ndef test_nested_function():\n    \"\"\"Test tracking dependencies in nested functions.\"\"\"\n\n    def func_with_nested(self: DependencyTestState):\n        async def inner():  # noqa: RUF029\n            if self.board:\n                pass\n\n        return self.count\n\n    tracker = DependencyTracker(func_with_nested, DependencyTestState)\n\n    expected_deps = {DependencyTestState.get_full_name(): {\"board\", \"count\"}}\n    assert tracker.dependencies == expected_deps\n\n\n@pytest.mark.skipif(\n    sys.version_info < (3, 11), reason=\"Requires Python 3.11+ for positions\"\n)\ndef test_get_var_value_functionality():\n    \"\"\"Test tracking dependencies when using get_var_value.\"\"\"\n\n    async def func_with_get_var_value(self: DependencyTestState):\n        return await self.get_var_value(DependencyTestState.count)\n\n    tracker = DependencyTracker(func_with_get_var_value, DependencyTestState)\n    expected_deps = {DependencyTestState.get_full_name(): {\"count\"}}\n    assert tracker.dependencies == expected_deps\n\n\n@pytest.mark.skipif(\n    sys.version_info < (3, 11), reason=\"Requires Python 3.11+ for positions\"\n)\ndef test_get_var_value_multiple_lines_functionality():\n    \"\"\"Test tracking dependencies when using get_var_value spread out on multiple lines.\"\"\"\n\n    async def func_with_get_var_value(self: DependencyTestState):\n        return await self.get_var_value(\n            DependencyTestState.\n            # annoying comment\n            count\n        )\n\n    tracker = DependencyTracker(func_with_get_var_value, DependencyTestState)\n    expected_deps = {DependencyTestState.get_full_name(): {\"count\"}}\n    assert tracker.dependencies == expected_deps\n\n\n@pytest.mark.skipif(\n    sys.version_info < (3, 11), reason=\"Requires Python 3.11+ for positions\"\n)\ndef test_get_var_value_with_import_from():\n    \"\"\"Test that get_var_value with function-local `from ... import ...` finds correct dependency.\"\"\"\n\n    async def get_state_import_from(self: DependencyTestState):\n        from tests.units.states.mutation import MutableTestState\n\n        return await self.get_var_value(MutableTestState.hashmap)  # pyright: ignore[reportArgumentType]\n\n    from tests.units.states.mutation import MutableTestState\n\n    tracker = DependencyTracker(get_state_import_from, DependencyTestState)\n    expected_deps = {MutableTestState.get_full_name(): {\"hashmap\"}}\n    assert tracker.dependencies == expected_deps\n\n\ndef test_merge_deps():\n    \"\"\"Test merging dependencies from multiple trackers.\"\"\"\n\n    def func1(self: DependencyTestState):\n        return self.count\n\n    def func2(self: DependencyTestState):\n        return self.name\n\n    tracker1 = DependencyTracker(func1, DependencyTestState)\n    tracker2 = DependencyTracker(func2, DependencyTestState)\n\n    tracker1._merge_deps(tracker2)\n\n    expected_deps = {DependencyTestState.get_full_name(): {\"count\", \"name\"}}\n    assert tracker1.dependencies == expected_deps\n\n\ndef test_get_globals_with_function():\n    \"\"\"Test _get_globals method with a function.\"\"\"\n\n    def test_func(self: DependencyTestState):\n        return self.count\n\n    tracker = DependencyTracker(test_func, DependencyTestState)\n    globals_dict = tracker._get_globals()\n\n    assert isinstance(globals_dict, dict)\n    assert \"DependencyTestState\" in globals_dict\n    assert \"State\" in globals_dict\n\n\ndef test_get_globals_with_code_object():\n    \"\"\"Test _get_globals method with a code object.\"\"\"\n\n    def test_func(self: DependencyTestState):\n        return self.count\n\n    code_obj = test_func.__code__\n    tracker = DependencyTracker(code_obj, DependencyTestState)\n    globals_dict = tracker._get_globals()\n\n    assert not globals_dict\n\n\ndef test_get_closure_with_function():\n    \"\"\"Test _get_closure method with a function that has closure.\"\"\"\n    outer_var = \"test\"\n\n    def func_with_closure(self: DependencyTestState):\n        return self.count + len(outer_var)\n\n    tracker = DependencyTracker(func_with_closure, DependencyTestState)\n    closure_dict = tracker._get_closure()\n\n    assert isinstance(closure_dict, dict)\n    assert \"outer_var\" in closure_dict\n    assert closure_dict[\"outer_var\"] == \"test\"\n\n\ndef test_get_closure_with_code_object():\n    \"\"\"Test _get_closure method with a code object.\"\"\"\n\n    def test_func(self: DependencyTestState):\n        return self.count\n\n    code_obj = test_func.__code__\n    tracker = DependencyTracker(code_obj, DependencyTestState)\n    closure_dict = tracker._get_closure()\n\n    assert not closure_dict\n\n\ndef test_property_dependencies():\n    \"\"\"Test tracking dependencies through property access.\"\"\"\n\n    class StateWithProperty(State):\n        _value: int = 0\n\n        def computed_value(self) -> int:\n            return self._value * 2\n\n        def func_with_property(self):\n            return self.computed_value\n\n    tracker = DependencyTracker(StateWithProperty.func_with_property, StateWithProperty)\n\n    # Should track dependencies from the property getter\n    expected_deps = {StateWithProperty.get_full_name(): {\"_value\"}}\n    assert tracker.dependencies == expected_deps\n\n\ndef test_no_dependencies():\n    \"\"\"Test functions with no state dependencies.\"\"\"\n\n    def func_no_deps(self: DependencyTestState):\n        return 42\n\n    tracker = DependencyTracker(func_no_deps, DependencyTestState)\n\n    assert not tracker.dependencies\n\n\ndef test_complex_expression_dependencies():\n    \"\"\"Test tracking dependencies in complex expressions.\"\"\"\n\n    def complex_func(self: DependencyTestState):\n        return (self.count * 2 + len(self.name)) if self.items else 0\n\n    tracker = DependencyTracker(complex_func, DependencyTestState)\n\n    expected_deps = {DependencyTestState.get_full_name(): {\"count\", \"name\", \"items\"}}\n    assert tracker.dependencies == expected_deps\n\n\ndef test_equality_expression_dependencies():\n    \"\"\"Test tracking dependencies in equality expressions.\n\n    With the state attribute on the right hand side, python generates\n    LOAD_FAST_LOAD_FAST family instructions.\n    \"\"\"\n\n    def equality_func(self: DependencyTestState):\n        my_val = 2\n        return my_val == self.count\n\n    tracker = DependencyTracker(equality_func, DependencyTestState)\n    expected_deps = {DependencyTestState.get_full_name(): {\"count\"}}\n    assert tracker.dependencies == expected_deps\n\n\ndef test_equality_expression_dependencies_lhs():\n    \"\"\"Test tracking dependencies in equality expressions (state on left hand side).\"\"\"\n\n    def equality_func(self: DependencyTestState):\n        my_val = 2\n        return self.count == my_val\n\n    tracker = DependencyTracker(equality_func, DependencyTestState)\n    expected_deps = {DependencyTestState.get_full_name(): {\"count\"}}\n    assert tracker.dependencies == expected_deps\n\n\ndef test_equality_expression_dependencies_get_state():\n    \"\"\"Test tracking dependencies in equality expressions with retrieved state.\"\"\"\n\n    async def equality_func_get_state(self: DependencyTestState):\n        another_state = await self.get_state(AnotherTestState)\n        my_val = 2\n        return my_val == another_state.value\n\n    tracker = DependencyTracker(equality_func_get_state, DependencyTestState)\n\n    expected_deps = {AnotherTestState.get_full_name(): {\"value\"}}\n    assert tracker.dependencies == expected_deps\n\n\ndef test_get_cell_value_with_valid_cell():\n    \"\"\"Test get_cell_value with a valid cell containing a value.\"\"\"\n    # Create a closure to get a cell object\n    value = \"test_value\"\n\n    def outer():\n        def inner():\n            return value\n\n        return inner\n\n    inner_func = outer()\n\n    assert inner_func.__closure__ is not None\n\n    cell = inner_func.__closure__[0]\n    result = get_cell_value(cell)\n    assert result == \"test_value\"\n\n\ndef test_cross_state_dependencies_complex():\n    \"\"\"Test complex cross-state dependency scenarios.\"\"\"\n\n    class StateA(State):\n        value_a: int = 1\n\n    class StateB(State):\n        value_b: int = 2\n\n    async def complex_cross_state_func(self: DependencyTestState):\n        state_a = await self.get_state(StateA)\n        state_b = await self.get_state(StateB)\n        return state_a.value_a + state_b.value_b\n\n    tracker = DependencyTracker(complex_cross_state_func, DependencyTestState)\n\n    expected_deps = {\n        StateA.get_full_name(): {\"value_a\"},\n        StateB.get_full_name(): {\"value_b\"},\n    }\n    assert tracker.dependencies == expected_deps\n\n\ndef test_dependencies_with_computed_var():\n    \"\"\"Test that computed vars are handled correctly in dependency tracking.\"\"\"\n\n    class StateWithComputedVar(State):\n        base_value: int = 0\n\n        @rx.var\n        def computed_value(self) -> int:\n            return self.base_value * 2\n\n    def func_using_computed_var(self: StateWithComputedVar):\n        return self.computed_value\n\n    tracker = DependencyTracker(func_using_computed_var, StateWithComputedVar)\n\n    # Should track the computed var, not its dependencies\n    expected_deps = {StateWithComputedVar.get_full_name(): {\"computed_value\"}}\n    assert tracker.dependencies == expected_deps\n"
  },
  {
    "path": "tests/units/vars/test_dep_tracking_integration.py",
    "content": "\"\"\"Integration tests for dependency tracking with computed vars.\"\"\"\n\nfrom __future__ import annotations\n\nimport reflex as rx\nfrom reflex.state import State\n\n\nclass IntegrationTestState(State):\n    \"\"\"State for integration testing with dependency tracker.\"\"\"\n\n    count: int = 0\n    name: str = \"test\"\n    items: list[str] = []\n\n    @rx.var\n    def computed_count(self) -> int:\n        \"\"\"A computed var that depends on count.\n\n        Returns:\n            The double of the count.\n        \"\"\"\n        return self.count * 2\n\n    @rx.var\n    def computed_name_length(self) -> int:\n        \"\"\"A computed var that depends on name.\n\n        Returns:\n            The length of the name.\n        \"\"\"\n        return len(self.name)\n\n    @rx.var\n    def complex_computed(self) -> str:\n        \"\"\"A computed var with complex dependencies.\n\n        Returns:\n            A string combining name, count, and items length.\n        \"\"\"\n        return f\"{self.name}_{self.count}_{len(self.items)}\"\n\n    def helper_method(self) -> int:\n        \"\"\"A helper method that accesses state.\n\n        Returns:\n            The sum of count and the length of name.\n        \"\"\"\n        return self.count + len(self.name)\n\n\nclass OtherIntegrationState(State):\n    \"\"\"Another state for cross-state dependency testing.\"\"\"\n\n    value: int = 42\n\n    @rx.var\n    def doubled_value(self) -> int:\n        \"\"\"A computed var that depends on value.\n\n        Returns:\n            The double of the value.\n        \"\"\"\n        return self.value * 2\n\n\ndef test_computed_var_dependencies():\n    \"\"\"Test that computed vars automatically track dependencies correctly.\"\"\"\n    # Test the _deps method which uses DependencyTracker internally\n    computed_count = IntegrationTestState.computed_vars[\"computed_count\"]\n    deps = computed_count._deps(objclass=IntegrationTestState)\n\n    expected_deps = {IntegrationTestState.get_full_name(): {\"count\"}}\n    assert deps == expected_deps\n\n\ndef test_complex_computed_var_dependencies():\n    \"\"\"Test complex computed var with multiple dependencies.\"\"\"\n    complex_computed = IntegrationTestState.computed_vars[\"complex_computed\"]\n    deps = complex_computed._deps(objclass=IntegrationTestState)\n\n    expected_deps = {IntegrationTestState.get_full_name(): {\"name\", \"count\", \"items\"}}\n    assert deps == expected_deps\n\n\ndef test_multiple_computed_vars():\n    \"\"\"Test that different computed vars track their own dependencies.\"\"\"\n    computed_count = IntegrationTestState.computed_vars[\"computed_count\"]\n    computed_name_length = IntegrationTestState.computed_vars[\"computed_name_length\"]\n\n    count_deps = computed_count._deps(objclass=IntegrationTestState)\n    name_deps = computed_name_length._deps(objclass=IntegrationTestState)\n\n    assert count_deps == {IntegrationTestState.get_full_name(): {\"count\"}}\n    assert name_deps == {IntegrationTestState.get_full_name(): {\"name\"}}\n\n\ndef test_method_dependencies_integration():\n    \"\"\"Test tracking dependencies through method calls in computed vars.\"\"\"\n\n    class StateWithMethodDeps(State):\n        value: int = 0\n\n        def helper_method(self):\n            return self.value\n\n        @rx.var\n        def computed_with_method(self) -> int:\n            return self.helper_method() * 2\n\n    computed = StateWithMethodDeps.computed_vars[\"computed_with_method\"]\n    deps = computed._deps(objclass=StateWithMethodDeps)\n\n    expected_deps = {StateWithMethodDeps.get_full_name(): {\"value\"}}\n    assert deps == expected_deps\n\n\ndef test_cross_state_dependencies():\n    \"\"\"Test dependencies across different state classes.\"\"\"\n\n    class StateWithCrossDeps(State):\n        @rx.var\n        async def cross_state_computed(self) -> int:\n            other = await self.get_state(OtherIntegrationState)\n            return other.value + 10\n\n    computed = StateWithCrossDeps.computed_vars[\"cross_state_computed\"]\n    deps = computed._deps(objclass=StateWithCrossDeps)\n\n    expected_deps = {OtherIntegrationState.get_full_name(): {\"value\"}}\n    assert deps == expected_deps\n\n\ndef test_nested_function_in_computed_var():\n    \"\"\"Test that nested functions within computed vars track dependencies.\"\"\"\n\n    class StateWithNested(State):\n        items: list[str] = []\n        multiplier: int = 2\n\n        @rx.var\n        def nested_computed(self) -> int:\n            def inner():\n                return len(self.items) * self.multiplier\n\n            return inner()\n\n    computed = StateWithNested.computed_vars[\"nested_computed\"]\n    deps = computed._deps(objclass=StateWithNested)\n\n    expected_deps = {StateWithNested.get_full_name(): {\"items\", \"multiplier\"}}\n    assert deps == expected_deps\n\n\ndef test_list_comprehension_in_computed_var():\n    \"\"\"Test that list comprehensions in computed vars track dependencies.\"\"\"\n\n    class StateWithComprehension(State):\n        items: list[str] = []\n        min_length: int = 3\n\n        @rx.var\n        def filtered_items(self) -> list[str]:\n            return [item for item in self.items if len(item) >= self.min_length]\n\n    computed = StateWithComprehension.computed_vars[\"filtered_items\"]\n    deps = computed._deps(objclass=StateWithComprehension)\n\n    expected_deps = {StateWithComprehension.get_full_name(): {\"items\", \"min_length\"}}\n    assert deps == expected_deps\n\n\ndef test_property_access_in_computed_var():\n    \"\"\"Test that property access in computed vars tracks dependencies.\"\"\"\n\n    class StateWithProperty(State):\n        _internal_value: int = 0\n\n        @property\n        def value_property(self):\n            return self._internal_value * 2\n\n        @rx.var\n        def computed_with_property(self) -> int:\n            return self.value_property + 1\n\n    computed = StateWithProperty.computed_vars[\"computed_with_property\"]\n    deps = computed._deps(objclass=StateWithProperty)\n\n    expected_deps = {StateWithProperty.get_full_name(): {\"_internal_value\"}}\n    assert deps == expected_deps\n\n\ndef test_no_dependencies_computed_var():\n    \"\"\"Test computed vars with no state dependencies.\"\"\"\n\n    class StateWithNoDeps(State):\n        @rx.var\n        def constant_computed(self) -> int:\n            return 42\n\n    computed = StateWithNoDeps.computed_vars[\"constant_computed\"]\n    deps = computed._deps(objclass=StateWithNoDeps)\n\n    # Should have no dependencies\n    assert deps == {}\n\n\ndef test_conditional_dependencies():\n    \"\"\"Test computed vars with conditional dependencies.\"\"\"\n\n    class StateWithConditional(State):\n        flag: bool = True\n        value_a: int = 10\n        value_b: int = 20\n\n        @rx.var\n        def conditional_computed(self) -> int:\n            return self.value_a if self.flag else self.value_b\n\n    computed = StateWithConditional.computed_vars[\"conditional_computed\"]\n    deps = computed._deps(objclass=StateWithConditional)\n\n    # Should track all potentially accessed attributes\n    expected_deps = {\n        StateWithConditional.get_full_name(): {\"flag\", \"value_a\", \"value_b\"}\n    }\n    assert deps == expected_deps\n\n\ndef test_error_handling_in_dependency_tracking():\n    \"\"\"Test that dependency tracking handles errors gracefully.\"\"\"\n\n    class StateWithError(State):\n        value: int = 0\n\n        @rx.var\n        def computed_with_error(self) -> int:\n            # This should still track 'value' even if there are other issues\n            return self.value\n\n    computed = StateWithError.computed_vars[\"computed_with_error\"]\n    deps = computed._deps(objclass=StateWithError)\n\n    expected_deps = {StateWithError.get_full_name(): {\"value\"}}\n    assert deps == expected_deps\n"
  },
  {
    "path": "tests/units/vars/test_object.py",
    "content": "import dataclasses\nfrom collections.abc import Sequence\n\nimport pytest\nfrom typing_extensions import assert_type\n\nimport reflex as rx\nfrom reflex.utils.types import GenericType\nfrom reflex.vars.base import Var\nfrom reflex.vars.object import LiteralObjectVar, ObjectVar\nfrom reflex.vars.sequence import ArrayVar\n\npytest.importorskip(\"sqlalchemy\")\npytest.importorskip(\"pydantic\")\n\nfrom sqlalchemy.orm import DeclarativeBase, Mapped, MappedAsDataclass, mapped_column\n\n\nclass Bare:\n    \"\"\"A bare class with a single attribute.\"\"\"\n\n    quantity: int = 0\n\n\n@rx.serializer\ndef serialize_bare(obj: Bare) -> dict:\n    \"\"\"A serializer for the bare class.\n\n    Args:\n        obj: The object to serialize.\n\n    Returns:\n        A dictionary with the quantity attribute.\n    \"\"\"\n    return {\"quantity\": obj.quantity}\n\n\nclass Base(rx.Base):\n    \"\"\"A reflex base class with a single attribute.\"\"\"\n\n    quantity: int = 0\n\n\nclass SqlaBase(DeclarativeBase, MappedAsDataclass):\n    \"\"\"Sqlalchemy declarative mapping base class.\"\"\"\n\n\nclass SqlaModel(SqlaBase):\n    \"\"\"A sqlalchemy model with a single attribute.\"\"\"\n\n    __tablename__: str = \"sqla_model\"\n\n    id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True, init=False)\n    quantity: Mapped[int] = mapped_column(default=0)\n\n\n@dataclasses.dataclass\nclass Dataclass:\n    \"\"\"A dataclass with a single attribute.\"\"\"\n\n    quantity: int = 0\n\n\nclass ObjectState(rx.State):\n    \"\"\"A reflex state with bare, base and sqlalchemy base vars.\"\"\"\n\n    bare: rx.Field[Bare] = rx.field(Bare())\n    bare_optional: rx.Field[Bare | None] = rx.field(None)\n    base: rx.Field[Base] = rx.field(Base())\n    base_optional: rx.Field[Base | None] = rx.field(None)\n    sqlamodel: rx.Field[SqlaModel] = rx.field(SqlaModel())\n    sqlamodel_optional: rx.Field[SqlaModel | None] = rx.field(None)\n    dataclass: rx.Field[Dataclass] = rx.field(Dataclass())\n    dataclass_optional: rx.Field[Dataclass | None] = rx.field(None)\n\n    base_list: rx.Field[list[Base]] = rx.field([Base()])\n\n\n@pytest.mark.parametrize(\"type_\", [Base, Bare, SqlaModel, Dataclass])\ndef test_var_create(type_: type[Base | Bare | SqlaModel | Dataclass]) -> None:\n    my_object = type_()\n    var = Var.create(my_object)\n    assert var._var_type is type_\n    assert isinstance(var, ObjectVar)\n    quantity = var.quantity\n    assert quantity._var_type is int\n\n\n@pytest.mark.parametrize(\"type_\", [Base, Bare, SqlaModel, Dataclass])\ndef test_literal_create(type_: GenericType) -> None:\n    my_object = type_()\n    var = LiteralObjectVar.create(my_object)\n    assert var._var_type is type_\n\n    quantity = var.quantity\n    assert quantity._var_type is int\n\n\n@pytest.mark.parametrize(\"type_\", [Base, Bare, SqlaModel, Dataclass])\ndef test_guess(type_: type[Base | Bare | SqlaModel | Dataclass]) -> None:\n    my_object = type_()\n    var = Var.create(my_object)\n    var = var.guess_type()\n    assert var._var_type is type_\n    assert isinstance(var, ObjectVar)\n    quantity = var.quantity\n    assert quantity._var_type is int\n\n\n@pytest.mark.parametrize(\"type_\", [Base, Bare, SqlaModel, Dataclass])\ndef test_state(type_: GenericType) -> None:\n    attr_name = type_.__name__.lower()\n    var = getattr(ObjectState, attr_name)\n    assert var._var_type is type_\n\n    quantity = var.quantity\n    assert quantity._var_type is int\n\n\n@pytest.mark.parametrize(\"type_\", [Base, Bare, SqlaModel, Dataclass])\ndef test_state_to_operation(type_: GenericType) -> None:\n    attr_name = type_.__name__.lower()\n    original_var = getattr(ObjectState, attr_name)\n\n    var = original_var.to(ObjectVar, type_)\n    assert var._var_type is type_\n\n    var = original_var.to(ObjectVar)\n    assert var._var_type is type_\n\n\ndef test_typing() -> None:\n    # Bare\n    var = ObjectState.bare.to(ObjectVar)\n    _ = assert_type(var, ObjectVar[Bare])\n\n    # Base\n    var = ObjectState.base\n    _ = assert_type(var, ObjectVar[Base])\n    optional_var = ObjectState.base_optional\n    _ = assert_type(optional_var, ObjectVar[Base])\n    list_var = ObjectState.base_list\n    _ = assert_type(list_var, ArrayVar[Sequence[Base]])\n    list_var_0 = list_var[0]\n    _ = assert_type(list_var_0, ObjectVar[Base])\n\n    # Sqla\n    var = ObjectState.sqlamodel\n    _ = assert_type(var, ObjectVar[SqlaModel])\n    optional_var = ObjectState.sqlamodel_optional\n    _ = assert_type(optional_var, ObjectVar[SqlaModel])\n    list_var = ObjectState.base_list\n    _ = assert_type(list_var, ArrayVar[Sequence[Base]])\n    list_var_0 = list_var[0]\n    _ = assert_type(list_var_0, ObjectVar[Base])\n\n    # Dataclass\n    var = ObjectState.dataclass\n    _ = assert_type(var, ObjectVar[Dataclass])\n    optional_var = ObjectState.dataclass_optional\n    _ = assert_type(optional_var, ObjectVar[Dataclass])\n    list_var = ObjectState.base_list\n    _ = assert_type(list_var, ArrayVar[Sequence[Base]])\n    list_var_0 = list_var[0]\n    _ = assert_type(list_var_0, ObjectVar[Base])\n"
  }
]