diff --git a/.github/requirements.txt b/.github/requirements.txt new file mode 100644 index 000000000..47df11979 --- /dev/null +++ b/.github/requirements.txt @@ -0,0 +1,9 @@ +devtools[pygments] +pre-commit +coverage[toml]>=6.5 +pytest +dash[testing] +chromedriver-autoinstaller-fix +toml +pyyaml +openpyxl diff --git a/.github/workflows/release-if-needed.yml b/.github/workflows/check-release.yml similarity index 96% rename from .github/workflows/release-if-needed.yml rename to .github/workflows/check-release.yml index 05aa19fe9..0a76fe8f7 100644 --- a/.github/workflows/release-if-needed.yml +++ b/.github/workflows/check-release.yml @@ -1,13 +1,10 @@ -name: Release if needed +name: Check versions and build-publish on: push: branches: - main -env: - PYTHON_VERSION: "3.11" - jobs: check-version: runs-on: ubuntu-latest @@ -16,7 +13,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: ${{ env.PYTHON_VERSION }} + python-version: "3.10" - name: Install dependencies run: | python -m pip install --upgrade pip @@ -53,7 +50,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: ${{ env.PYTHON_VERSION }} + python-version: "3.10" - name: Install dependencies run: | python -m pip install --upgrade pip @@ -106,7 +103,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: ${{ env.PYTHON_VERSION }} + python-version: "3.10" - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/.github/workflows/checks-vizro-ai.yml b/.github/workflows/checks-vizro-ai.yml index 5f318cba4..e85b86435 100644 --- a/.github/workflows/checks-vizro-ai.yml +++ b/.github/workflows/checks-vizro-ai.yml @@ -1,5 +1,4 @@ -name: Checks for VizroAI - +name: checks-vizro-ai defaults: run: working-directory: vizro-ai @@ -19,31 +18,35 @@ concurrency: group: checks-ai-${{ github.head_ref }} env: - PYTHONUNBUFFERED: 1 - FORCE_COLOR: 1 - PYTHON_VERSION: "3.11" + PYTHONUNBUFFERED: "1" + FORCE_COLOR: "1" jobs: - checks-vizro-ai: + run: + name: Python ${{ matrix.python-version }} on Linux runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.9"] + steps: - uses: actions/checkout@v4 with: fetch-depth: ${{ github.event_name == 'pull_request' && 2 || 0 }} - - name: Set up Python ${{ env.PYTHON_VERSION }} + - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: - python-version: ${{ env.PYTHON_VERSION }} + python-version: ${{ matrix.python-version }} - name: Install Hatch run: pip install --upgrade hatch - name: List dependencies - run: hatch run all.py${{ env.PYTHON_VERSION }}:pip freeze + run: hatch run all.py${{ matrix.python-version }}:pip freeze - name: Check requirements for Snyk are up to date - run: hatch run all.py${{ env.PYTHON_VERSION }}:update-snyk-requirements --check + run: hatch run all.py${{ matrix.python-version }}:update-snyk-requirements --check - name: Find added changelog fragments id: added-files diff --git a/.github/workflows/checks-vizro-core.yml b/.github/workflows/checks-vizro-core.yml index a07837799..6bfc49684 100644 --- a/.github/workflows/checks-vizro-core.yml +++ b/.github/workflows/checks-vizro-core.yml @@ -1,4 +1,4 @@ -name: Checks for Vizro +name: checks-vizro-core defaults: run: @@ -19,34 +19,38 @@ concurrency: group: checks-core-${{ github.head_ref }} env: - PYTHONUNBUFFERED: 1 - FORCE_COLOR: 1 - PYTHON_VERSION: "3.11" + PYTHONUNBUFFERED: "1" + FORCE_COLOR: "1" jobs: - checks-vizro-core: + run: + name: Python ${{ matrix.python-version }} on Linux runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.8"] + steps: - uses: actions/checkout@v4 with: fetch-depth: ${{ github.event_name == 'pull_request' && 2 || 0 }} - - name: Set up Python ${{ env.PYTHON_VERSION }} + - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: - python-version: ${{ env.PYTHON_VERSION }} + python-version: ${{ matrix.python-version }} - name: Install Hatch run: pip install --upgrade hatch - name: List dependencies - run: hatch run all.py${{ env.PYTHON_VERSION }}:pip freeze + run: hatch run all.py${{ matrix.python-version }}:pip freeze - name: Check schema is up to date - run: hatch run all.py${{ env.PYTHON_VERSION }}:schema --check + run: hatch run all.py${{ matrix.python-version }}:schema --check - name: Check requirements for Snyk are up to date - run: hatch run all.py${{ env.PYTHON_VERSION }}:update-snyk-requirements --check + run: hatch run all.py${{ matrix.python-version }}:update-snyk-requirements --check - name: Find added changelog fragments id: added-files diff --git a/.github/workflows/lint-vizro-all.yml b/.github/workflows/lint-vizro-all.yml index 6d22e7518..6836ff174 100644 --- a/.github/workflows/lint-vizro-all.yml +++ b/.github/workflows/lint-vizro-all.yml @@ -1,4 +1,4 @@ -name: Lint +name: lint-vizro-all defaults: run: @@ -9,32 +9,35 @@ on: branches: [main] pull_request: branches: - - main + - "main" concurrency: group: lint-${{ github.head_ref }} env: - PYTHONUNBUFFERED: 1 - FORCE_COLOR: 1 - PYTHON_VERSION: "3.11" + PYTHONUNBUFFERED: "1" + FORCE_COLOR: "1" jobs: - lint-vizro-all: + run: + name: Python ${{ matrix.python-version }} on Linux runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.8"] steps: - uses: actions/checkout@v4 with: fetch-depth: ${{ github.event_name == 'pull_request' && 2 || 0 }} - - name: Set up Python ${{ env.PYTHON_VERSION }} + - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: - python-version: ${{ env.PYTHON_VERSION }} + python-version: ${{ matrix.python-version }} - name: Install Hatch run: pip install --upgrade hatch - name: Lint - run: hatch run lint + run: hatch run lint:lint diff --git a/.github/workflows/secret-scan.yml b/.github/workflows/secret-scan.yml index 9d049ad4f..a40670715 100644 --- a/.github/workflows/secret-scan.yml +++ b/.github/workflows/secret-scan.yml @@ -1,27 +1,23 @@ -name: Secret scan - +name: gitleaks (secret scan) on: pull_request: push: workflow_dispatch: schedule: - cron: "0 4 * * *" # run once a day at 4 AM - -env: - PYTHON_VERSION: "3.11" - jobs: - secret-scan: + scan: + name: gitleaks runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v4 - - name: Set up Python ${{ env.PYTHON_VERSION }} + - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: - python-version: ${{ env.PYTHON_VERSION }} + python-version: ${{ matrix.python-version }} - name: Install pre-commit run: pip install pre-commit diff --git a/.github/workflows/test-integration-vizro-ai.yml b/.github/workflows/test-integration-vizro-ai.yml index 3e12e4feb..eebcd3fcb 100644 --- a/.github/workflows/test-integration-vizro-ai.yml +++ b/.github/workflows/test-integration-vizro-ai.yml @@ -1,4 +1,4 @@ -name: Integration tests for VizroAI +name: test-integration-vizro-ai defaults: run: @@ -9,33 +9,22 @@ on: branches: [main] pull_request: branches: - - main + - "main" concurrency: group: test-integration-${{ github.head_ref }} env: - PYTHONUNBUFFERED: 1 - FORCE_COLOR: 1 + PYTHONUNBUFFERED: "1" + FORCE_COLOR: "1" jobs: - test-integration-vizro-ai: - name: test-integration-vizro-ai on Py${{ matrix.python-version }} ${{ matrix.label }} - + run: + name: Python ${{ matrix.python-version }} on Linux runs-on: ubuntu-latest strategy: - fail-fast: false matrix: - include: - - python-version: "3.9" - hatch-env: all.py3.9 - - python-version: "3.10" - hatch-env: all.py3.10 - - python-version: "3.11" - hatch-env: all.py3.11 - - python-version: "3.11" - hatch-env: lower-bounds - label: lower bounds + python-version: ["3.9", "3.10", "3.11"] steps: - uses: actions/checkout@v4 @@ -50,14 +39,11 @@ jobs: - name: Install Hatch run: pip install --upgrade hatch - - name: List dependencies - run: hatch run ${{ matrix.hatch-env }}:pip freeze - - name: Run vizro-ai integration tests with pypi vizro run: | export OPENAI_API_KEY=${{ secrets.OPENAI_API_KEY }} export OPENAI_API_BASE=${{ secrets.OPENAI_API_BASE }} - hatch run ${{ matrix.hatch-env }}:test-integration + hatch run all.py${{ matrix.python-version }}:test-integration - name: Run vizro-ai integration tests with local vizro run: | @@ -66,5 +52,5 @@ jobs: cd ../vizro-core hatch build cd ../vizro-ai - hatch run ${{ matrix.hatch-env }}:pip install ../vizro-core/dist/vizro*.tar.gz - hatch run ${{ matrix.hatch-env }}:test-integration + hatch run all.py${{ matrix.python-version }}:pip install ../vizro-core/dist/vizro*.tar.gz + hatch run all.py${{ matrix.python-version }}:test-integration diff --git a/.github/workflows/test-integration-vizro-core.yml b/.github/workflows/test-integration-vizro-core.yml index f73e3ed79..637b3df7b 100644 --- a/.github/workflows/test-integration-vizro-core.yml +++ b/.github/workflows/test-integration-vizro-core.yml @@ -1,4 +1,4 @@ -name: Integration tests for Vizro +name: test-integration-vizro-core defaults: run: @@ -9,49 +9,56 @@ on: branches: [main] pull_request: branches: - - main + - "main" concurrency: group: test-integration-${{ github.head_ref }} env: - PYTHONUNBUFFERED: 1 - FORCE_COLOR: 1 + PYTHONUNBUFFERED: "1" + FORCE_COLOR: "1" jobs: - test-integration-vizro-core: - name: test-integration-vizro-core on Py${{ matrix.python-version }} ${{ matrix.label }} - - runs-on: ubuntu-latest + run: + name: Python ${{ matrix.python-version }} on ${{ matrix.os }} + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - include: - - python-version: "3.8" - hatch-env: all.py3.8 - - python-version: "3.9" - hatch-env: all.py3.9 - - python-version: "3.10" - hatch-env: all.py3.10 - - python-version: "3.11" - hatch-env: all.py3.11 - - python-version: "3.11" - hatch-env: lower-bounds - label: lower bounds + os: [ubuntu-latest, windows-latest] + python-version: ["3.8", "3.9", "3.10", "3.11"] steps: - uses: actions/checkout@v4 + - name: Get branch name + id: branch-name + uses: tj-actions/branch-names@v7 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - - name: Install Hatch - run: pip install --upgrade hatch + - uses: actions/cache@v3 + with: + path: ${{ env.pythonLocation }} + key: ${{ matrix.os }}-${{ matrix.python-version }}-${{ steps.branch-name.outputs.current_branch }}-pip-${{ hashFiles('hatch.toml') }}-${{ hashFiles('pyproject.toml') }} + restore-keys: | + ${{ matrix.os }}-${{ matrix.python-version }}-${{ steps.branch-name.outputs.current_branch }}-pip- - - name: List dependencies - run: hatch run ${{ matrix.hatch-env }}:pip freeze + - name: Run ubuntu integration tests + if: ${{ matrix.os == 'ubuntu-latest' }} + run: | + pip install --upgrade hatch + hatch run all.py${{ matrix.python-version }}:test-integration - - name: Run integration tests - run: hatch run ${{ matrix.hatch-env }}:test-integration + - name: Run windows integration tests + if: ${{ matrix.os == 'windows-latest' }} + run: | + $env:PYTHONPATH=".;D:\a\vizro\vizro\vizro-core\src" + pip install -r ../.github/requirements.txt + pip install . + pytest tests/integration --headless -k default + pytest tests/integration --headless -k dict + pytest tests/integration --headless -k json + pytest tests/integration --headless -k yaml diff --git a/.github/workflows/test-unit-vizro-ai.yml b/.github/workflows/test-unit-vizro-ai.yml index c82616aaf..7fb4d0523 100644 --- a/.github/workflows/test-unit-vizro-ai.yml +++ b/.github/workflows/test-unit-vizro-ai.yml @@ -1,4 +1,4 @@ -name: Unit tests for VizroAI +name: test-unit-vizro-ai defaults: run: @@ -9,33 +9,24 @@ on: branches: [main] pull_request: branches: - - main + - "main" concurrency: group: test-unit-${{ github.head_ref }} env: - PYTHONUNBUFFERED: 1 - FORCE_COLOR: 1 + PYTHONUNBUFFERED: "1" + FORCE_COLOR: "1" jobs: - test-unit-vizro-ai: - name: test-unit-vizro-ai on Py${{ matrix.python-version }} ${{ matrix.label }} - - runs-on: ubuntu-latest + run: + name: Python ${{ matrix.python-version }} on ${{ startsWith(matrix.os, 'windows-') && 'Windows' || 'Linux' }} + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - include: - - python-version: "3.9" - hatch-env: all.py3.9 - - python-version: "3.10" - hatch-env: all.py3.10 - - python-version: "3.11" - hatch-env: all.py3.11 - - python-version: "3.11" - hatch-env: lower-bounds - label: lower bounds + os: [ubuntu-latest] + python-version: ["3.9", "3.10", "3.11"] steps: - uses: actions/checkout@v4 @@ -49,7 +40,8 @@ jobs: run: pip install --upgrade hatch - name: List dependencies - run: hatch run ${{ matrix.hatch-env }}:pip freeze + run: hatch run all.py${{ matrix.python-version }}:pip freeze - name: Run unit tests - run: hatch run ${{ matrix.hatch-env }}:test-unit-coverage + run: | + hatch run all.py${{ matrix.python-version }}:cov diff --git a/.github/workflows/test-unit-vizro-core.yml b/.github/workflows/test-unit-vizro-core.yml index 890091d42..aef297520 100644 --- a/.github/workflows/test-unit-vizro-core.yml +++ b/.github/workflows/test-unit-vizro-core.yml @@ -1,4 +1,4 @@ -name: Unit tests for Vizro +name: test-unit-vizro-core defaults: run: @@ -9,35 +9,24 @@ on: branches: [main] pull_request: branches: - - main + - "main" concurrency: group: test-unit-${{ github.head_ref }} env: - PYTHONUNBUFFERED: 1 - FORCE_COLOR: 1 + PYTHONUNBUFFERED: "1" + FORCE_COLOR: "1" jobs: - test-unit-vizro-core: - name: test-unit-vizro-core on Py${{ matrix.python-version }} ${{ matrix.label }} - - runs-on: ubuntu-latest + run: + name: Python ${{ matrix.python-version }} on ${{ startsWith(matrix.os, 'windows-') && 'Windows' || 'Linux' }} + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - include: - - python-version: "3.8" - hatch-env: all.py3.8 - - python-version: "3.9" - hatch-env: all.py3.9 - - python-version: "3.10" - hatch-env: all.py3.10 - - python-version: "3.11" - hatch-env: all.py3.11 - - python-version: "3.11" - hatch-env: lower-bounds - label: lower bounds + os: [ubuntu-latest] + python-version: ["3.8", "3.9", "3.10", "3.11"] steps: - uses: actions/checkout@v4 @@ -51,7 +40,8 @@ jobs: run: pip install --upgrade hatch - name: List dependencies - run: hatch run ${{ matrix.hatch-env }}:pip freeze + run: hatch run all.py${{ matrix.python-version }}:pip freeze - name: Run unit tests - run: hatch run ${{ matrix.hatch-env }}:test-unit-coverage + run: | + hatch run all.py${{ matrix.python-version }}:cov diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9b4c50b01..df8064356 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -71,7 +71,7 @@ repos: - id: mypy files: ^vizro-core/src/ additional_dependencies: - - pydantic>=1.10.13, <2 # deliberately pinned to <2 until we bump our pydantic requirement to strictly >=2 + - pydantic>=1.10.13, <2 - repo: https://github.com/gitleaks/gitleaks rev: v8.16.4 diff --git a/vizro-ai/changelog.d/20231205_121131_antony.milne.md b/vizro-ai/changelog.d/20231205_121131_antony.milne.md deleted file mode 100644 index f1f65e73c..000000000 --- a/vizro-ai/changelog.d/20231205_121131_antony.milne.md +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - diff --git a/vizro-ai/changelog.d/20231206_212921_antony.milne_pydantic_v2.md b/vizro-ai/changelog.d/20231206_212921_antony.milne_pydantic_v2.md deleted file mode 100644 index f1f65e73c..000000000 --- a/vizro-ai/changelog.d/20231206_212921_antony.milne_pydantic_v2.md +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - diff --git a/vizro-ai/hatch.toml b/vizro-ai/hatch.toml index d04a70dde..727f65f6b 100644 --- a/vizro-ai/hatch.toml +++ b/vizro-ai/hatch.toml @@ -22,6 +22,14 @@ dependencies = [ VIZRO_AI_LOG_LEVEL = "DEBUG" [envs.default.scripts] +cov = [ + "test-cov", + "cov-report" +] +cov-report = [ + "- coverage combine", + "coverage report" +] lint = "hatch run lint:lint {args:--all-files}" prep-release = [ "hatch version release", @@ -31,14 +39,15 @@ prep-release = [ ] pypath = "hatch run python -c 'import sys; print(sys.executable)'" secrets = "pre-commit run gitleaks --all-files" -test = "pytest tests {args}" -test-integration = "pytest -v tests/integration {args}" -test-unit = "pytest tests/unit {args}" -test-unit-coverage = [ - "coverage run -m pytest tests/unit {args}", - "- coverage combine", - "coverage report" +test = [ + "- test-unit", + "test-integration" +] +test-cov = "coverage run -m pytest tests/unit {args}" +test-integration = [ + "pytest -v tests/integration" ] +test-unit = "pytest tests/unit {args}" update-snyk-requirements = "python ../tools/generate_snyk_requirements.py {args}" [envs.docs] @@ -58,8 +67,5 @@ dependencies = [ detached = true scripts = {lint = "SKIP=gitleaks pre-commit run {args:--all-files}"} -[envs.lower-bounds] -extra-dependencies = ["pydantic==1.10.13"] - [version] path = "src/vizro_ai/__init__.py" diff --git a/vizro-ai/src/vizro_ai/chains/_llm_models.py b/vizro-ai/src/vizro_ai/chains/_llm_models.py index dc51ae98d..73210fc8d 100644 --- a/vizro-ai/src/vizro_ai/chains/_llm_models.py +++ b/vizro-ai/src/vizro_ai/chains/_llm_models.py @@ -1,11 +1,7 @@ from typing import Callable, Dict, List, Union from langchain.chat_models import ChatOpenAI - -try: - from pydantic.v1 import BaseModel, Field -except ImportError: # pragma: no cov - from pydantic import BaseModel, Field +from pydantic import BaseModel, Field # TODO add new wrappers in if new model support is added LLM_MODELS = Union[ChatOpenAI] diff --git a/vizro-ai/src/vizro_ai/components/chart_selection.py b/vizro-ai/src/vizro_ai/components/chart_selection.py index 2d280d9b8..bda57bb58 100644 --- a/vizro-ai/src/vizro_ai/components/chart_selection.py +++ b/vizro-ai/src/vizro_ai/components/chart_selection.py @@ -2,11 +2,7 @@ from typing import Dict, Tuple import pandas as pd - -try: - from pydantic.v1 import BaseModel, Field -except ImportError: # pragma: no cov - from pydantic import BaseModel, Field +from pydantic import BaseModel, Field from vizro_ai.chains._chain_utils import _log_time from vizro_ai.chains._llm_models import LLM_MODELS diff --git a/vizro-ai/src/vizro_ai/components/code_validation.py b/vizro-ai/src/vizro_ai/components/code_validation.py index fd18a5f03..0d4f32633 100644 --- a/vizro-ai/src/vizro_ai/components/code_validation.py +++ b/vizro-ai/src/vizro_ai/components/code_validation.py @@ -2,10 +2,7 @@ import traceback from typing import Dict, Tuple -try: - from pydantic.v1 import BaseModel, Field -except ImportError: # pragma: no cov - from pydantic import BaseModel, Field +from pydantic import BaseModel, Field from vizro_ai.chains._chain_utils import _log_time from vizro_ai.chains._llm_models import LLM_MODELS diff --git a/vizro-ai/src/vizro_ai/components/custom_chart_wrap.py b/vizro-ai/src/vizro_ai/components/custom_chart_wrap.py index a4a9d850d..07783bf2a 100644 --- a/vizro-ai/src/vizro_ai/components/custom_chart_wrap.py +++ b/vizro-ai/src/vizro_ai/components/custom_chart_wrap.py @@ -2,10 +2,7 @@ import logging from typing import Dict, Tuple -try: - from pydantic.v1 import BaseModel, Field -except ImportError: # pragma: no cov - from pydantic import BaseModel, Field +from pydantic import BaseModel, Field from vizro_ai.chains._chain_utils import _log_time from vizro_ai.chains._llm_models import LLM_MODELS diff --git a/vizro-ai/src/vizro_ai/components/dataframe_craft.py b/vizro-ai/src/vizro_ai/components/dataframe_craft.py index 2e836b281..65f95f445 100755 --- a/vizro-ai/src/vizro_ai/components/dataframe_craft.py +++ b/vizro-ai/src/vizro_ai/components/dataframe_craft.py @@ -4,11 +4,7 @@ from typing import Dict, Tuple import pandas as pd - -try: - from pydantic.v1 import BaseModel, Field -except ImportError: # pragma: no cov - from pydantic import BaseModel, Field +from pydantic import BaseModel, Field from vizro_ai.chains._chain_utils import _log_time from vizro_ai.chains._llm_models import LLM_MODELS diff --git a/vizro-ai/src/vizro_ai/components/explanation.py b/vizro-ai/src/vizro_ai/components/explanation.py index f22421053..3a1148cbc 100644 --- a/vizro-ai/src/vizro_ai/components/explanation.py +++ b/vizro-ai/src/vizro_ai/components/explanation.py @@ -1,10 +1,7 @@ """Chart Type Selection Component.""" from typing import Dict, Tuple -try: - from pydantic.v1 import BaseModel, Field -except ImportError: # pragma: no cov - from pydantic import BaseModel, Field +from pydantic import BaseModel, Field from vizro_ai.chains._chain_utils import _log_time from vizro_ai.chains._llm_models import LLM_MODELS diff --git a/vizro-ai/src/vizro_ai/components/visual_code.py b/vizro-ai/src/vizro_ai/components/visual_code.py index e2894471d..1570ba5a3 100644 --- a/vizro-ai/src/vizro_ai/components/visual_code.py +++ b/vizro-ai/src/vizro_ai/components/visual_code.py @@ -1,10 +1,7 @@ """Visual Code Component.""" from typing import Dict, Tuple -try: - from pydantic.v1 import BaseModel, Field -except ImportError: # pragma: no cov - from pydantic import BaseModel, Field +from pydantic import BaseModel, Field from vizro_ai.chains._chain_utils import _log_time from vizro_ai.chains._llm_models import LLM_MODELS diff --git a/vizro-ai/src/vizro_ai/schema_manager/schema_manager.py b/vizro-ai/src/vizro_ai/schema_manager/schema_manager.py index 3bc13f79e..9d0033de5 100644 --- a/vizro-ai/src/vizro_ai/schema_manager/schema_manager.py +++ b/vizro-ai/src/vizro_ai/schema_manager/schema_manager.py @@ -2,10 +2,7 @@ import inspect from typing import Callable, List, Union -try: - from pydantic.v1 import BaseModel, Field, create_model -except ImportError: # pragma: no cov - from pydantic import BaseModel, Field, create_model +from pydantic import BaseModel, Field, create_model class SchemaManager: diff --git a/vizro-core/changelog.d/20231201_152948_nadija_ratkusic_graca_navigation_css_refinements.md b/vizro-core/changelog.d/20231201_152948_nadija_ratkusic_graca_navigation_css_refinements.md deleted file mode 100644 index 403407a16..000000000 --- a/vizro-core/changelog.d/20231201_152948_nadija_ratkusic_graca_navigation_css_refinements.md +++ /dev/null @@ -1,47 +0,0 @@ - - - - - -### Added - -- Enable tooltips for `NavLink`. ([#186](https://github.com/mckinsey/vizro/pull/186)) - - - - - diff --git a/vizro-core/changelog.d/20231201_155112_antony.milne_pydantic_v2.md b/vizro-core/changelog.d/20231201_155112_antony.milne_pydantic_v2.md deleted file mode 100644 index f1f65e73c..000000000 --- a/vizro-core/changelog.d/20231201_155112_antony.milne_pydantic_v2.md +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - diff --git a/vizro-core/changelog.d/20231205_121059_antony.milne.md b/vizro-core/changelog.d/20231205_121059_antony.milne.md deleted file mode 100644 index f1f65e73c..000000000 --- a/vizro-core/changelog.d/20231205_121059_antony.milne.md +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - diff --git a/vizro-core/docs/assets/user_guides/navigation/accordion_inside_nav_bar.png b/vizro-core/docs/assets/user_guides/navigation/accordion_inside_nav_bar.png index 27dce9979..caf529a84 100644 Binary files a/vizro-core/docs/assets/user_guides/navigation/accordion_inside_nav_bar.png and b/vizro-core/docs/assets/user_guides/navigation/accordion_inside_nav_bar.png differ diff --git a/vizro-core/docs/assets/user_guides/navigation/custom_icons.png b/vizro-core/docs/assets/user_guides/navigation/custom_icons.png index bc14546f4..19a456bf1 100644 Binary files a/vizro-core/docs/assets/user_guides/navigation/custom_icons.png and b/vizro-core/docs/assets/user_guides/navigation/custom_icons.png differ diff --git a/vizro-core/docs/assets/user_guides/navigation/nav_bar.png b/vizro-core/docs/assets/user_guides/navigation/nav_bar.png index 5189386d1..e2715cdcb 100644 Binary files a/vizro-core/docs/assets/user_guides/navigation/nav_bar.png and b/vizro-core/docs/assets/user_guides/navigation/nav_bar.png differ diff --git a/vizro-core/docs/pages/development/contributing.md b/vizro-core/docs/pages/development/contributing.md index 264e59e45..360f17af8 100644 --- a/vizro-core/docs/pages/development/contributing.md +++ b/vizro-core/docs/pages/development/contributing.md @@ -79,7 +79,7 @@ To run tests against a particular Python version, specify the particular Hatch e hatch run all.py3.10:test -vv ``` -The script executed by `hatch run test-unit-coverage` measures test coverage and generates a report. +The script executed by `hatch run cov` measures test coverage and generates a report. To run jest unit tests for javascript functions, run `hatch run test-js`. Note that Node.js is required to run tests written in the jest framework. If you don't have `Node.js` installed, guidelines on how to install Node.js will appear when you run the command: `hatch run test-js`. diff --git a/vizro-core/docs/pages/user_guides/navigation.md b/vizro-core/docs/pages/user_guides/navigation.md index f84efe438..fd9a00166 100644 --- a/vizro-core/docs/pages/user_guides/navigation.md +++ b/vizro-core/docs/pages/user_guides/navigation.md @@ -174,7 +174,7 @@ Another way to group together pages in the navigation is to use a [`NavBar`][viz [NavBar]: ../../assets/user_guides/navigation/nav_bar.png -Here, the first level of the navigation hierarchy ("Group A" and "Group B") is represented by an icon in a navigation bar, and the second level of the navigation (the pages) is represented by an accordion. By default, the icons are the [`filter` icons from the Google Material icons library](https://fonts.google.com/icons?icon.query=filter). The icon label ("Group A" and "Group B") appears as a tooltip on hovering over the icon. +Here, the first level of the navigation hierarchy ("Group A" and "Group B") is represented by an icon in a navigation bar, and the second level of the navigation (the pages) is represented by an accordion. By default, the icons are the [`filter` icons from the Google Material icons library](https://fonts.google.com/icons?icon.query=filter). ## Customizing the navigation bar diff --git a/vizro-core/hatch.toml b/vizro-core/hatch.toml index 0ab203a2e..707b62da8 100644 --- a/vizro-core/hatch.toml +++ b/vizro-core/hatch.toml @@ -31,6 +31,14 @@ DASH_DEBUG = "true" VIZRO_LOG_LEVEL = "DEBUG" [envs.default.scripts] +cov = [ + "test-cov", + "cov-report" +] +cov-report = [ + "- coverage combine", + "coverage report" +] example = "cd examples/{args:default}; python app.py" lint = "hatch run lint:lint {args:--all-files}" prep-release = [ @@ -45,15 +53,20 @@ prep-release = [ pypath = "python -c 'import sys; print(sys.executable)'" schema = ["python schemas/generate.py {args}", '- hatch run lint --files="schemas/$(hatch version).json" > /dev/null'] secrets = "pre-commit run gitleaks --all-files" -test = "pytest tests --headless {args}" -test-integration = "pytest tests/integration --headless {args}" +test = [ + "- test-unit", + "test-integration" +] +test-cov = "coverage run -m pytest tests/unit {args}" +test-integration = [ + "- pytest tests/integration/test_examples.py::test_default_dashboard --headless", + "- pytest tests/integration/test_examples.py::test_dict_dashboard --headless", + "- pytest tests/integration/test_examples.py::test_json_dashboard --headless", + "- pytest tests/integration/test_examples.py::test_yaml_dashboard --headless", + "pytest tests/integration/test_navigation.py" +] test-js = "./tools/run_jest.sh {args}" test-unit = "pytest tests/unit {args}" -test-unit-coverage = [ - "coverage run -m pytest tests/unit {args}", - "- coverage combine", - "coverage report" -] update-snyk-requirements = "python ../tools/generate_snyk_requirements.py {args}" [envs.docs] @@ -73,9 +86,6 @@ dependencies = [ detached = true scripts = {lint = "SKIP=gitleaks pre-commit run {args:--all-files}"} -[envs.lower-bounds] -extra-dependencies = ["pydantic==1.10.13"] - [publish.index] disable = true diff --git a/vizro-core/pyproject.toml b/vizro-core/pyproject.toml index f5088da68..b65a2586f 100644 --- a/vizro-core/pyproject.toml +++ b/vizro-core/pyproject.toml @@ -21,9 +21,8 @@ dependencies = [ # 2.11 needed for https://dash.plotly.com/dash-in-jupyter "dash_bootstrap_components", "pandas", - "pydantic>=1.10.13", # must be synced with pre-commit mypy hook manually + "pydantic>=1.10.13, <2", # must be synced with pre-commit mypy hook "dash_daq", - "dash_mantine_components", "ipython>=8.10.0", # not directly required, pinned by Snyk to avoid a vulnerability: https://app.snyk.io/vuln/SNYK-PYTHON-IPYTHON-3318382 "numpy>=1.22.2", # not directly required, pinned by Snyk to avoid a vulnerability: https://security.snyk.io/vuln/SNYK-PYTHON-NUMPY-2321970 "tornado>=6.3.2", # not directly required, pinned by Snyk to avoid a vulnerability: https://security.snyk.io/vuln/SNYK-PYTHON-TORNADO-5537286 diff --git a/vizro-core/schemas/0.1.7.dev0.json b/vizro-core/schemas/0.1.7.dev0.json index 0af9f1feb..360ffb8db 100644 --- a/vizro-core/schemas/0.1.7.dev0.json +++ b/vizro-core/schemas/0.1.7.dev0.json @@ -1073,7 +1073,15 @@ }, "nav_selector": { "title": "Nav Selector", - "anyOf": [ + "description": "Component for rendering navigation.", + "discriminator": { + "propertyName": "type", + "mapping": { + "accordion": "#/definitions/Accordion", + "nav_bar": "#/definitions/NavBar" + } + }, + "oneOf": [ { "$ref": "#/definitions/Accordion" }, diff --git a/vizro-core/schemas/0.1.7.dev1.json b/vizro-core/schemas/0.1.7.dev1.json deleted file mode 100644 index 0af9f1feb..000000000 --- a/vizro-core/schemas/0.1.7.dev1.json +++ /dev/null @@ -1,1089 +0,0 @@ -{ - "title": "Dashboard", - "description": "Vizro Dashboard to be used within [`Vizro`][vizro._vizro.Vizro.build].\n\nArgs:\n pages (List[Page]): See [`Page`][vizro.models.Page].\n theme (Literal[\"vizro_dark\", \"vizro_light\"]): Layout theme to be applied across dashboard.\n Defaults to `vizro_dark`.\n navigation (Optional[Navigation]): See [`Navigation`][vizro.models.Navigation]. Defaults to `None`.\n title (str): Dashboard title to appear on every page on top left-side. Defaults to `\"\"`.", - "type": "object", - "properties": { - "id": { - "title": "Id", - "description": "ID to identify model. Must be unique throughout the whole dashboard.When no ID is chosen, ID will be automatically generated.", - "default": "", - "type": "string" - }, - "pages": { - "title": "Pages", - "type": "array", - "items": { - "$ref": "#/definitions/Page" - } - }, - "theme": { - "title": "Theme", - "description": "Layout theme to be applied across dashboard. Defaults to `vizro_dark`", - "default": "vizro_dark", - "enum": ["vizro_dark", "vizro_light"], - "type": "string" - }, - "navigation": { - "$ref": "#/definitions/Navigation" - }, - "title": { - "title": "Title", - "description": "Dashboard title to appear on every page on top left-side.", - "default": "", - "type": "string" - } - }, - "required": ["pages"], - "additionalProperties": false, - "definitions": { - "Action": { - "title": "Action", - "description": "Action to be inserted into `actions` of relevant component.\n\nArgs:\n function (CapturedCallable): See [`CapturedCallable`][vizro.models.types.CapturedCallable].\n inputs (List[str]): Inputs in the form `.` passed to the action function.\n Defaults to `[]`.\n outputs (List[str]): Outputs in the form `.` changed by the action function.\n Defaults to `[]`.", - "type": "object", - "properties": { - "id": { - "title": "Id", - "description": "ID to identify model. Must be unique throughout the whole dashboard.When no ID is chosen, ID will be automatically generated.", - "default": "", - "type": "string" - }, - "inputs": { - "title": "Inputs", - "description": "Inputs in the form `.` passed to the action function.", - "default": [], - "pattern": "^[a-zA-Z0-9_]+[.][a-zA-Z_]+$", - "type": "array", - "items": { - "type": "string", - "pattern": "^[a-zA-Z0-9_]+[.][a-zA-Z_]+$" - } - }, - "outputs": { - "title": "Outputs", - "description": "Outputs in the form `.` changed by the action function.", - "default": [], - "pattern": "^[a-zA-Z0-9_]+[.][a-zA-Z_]+$", - "type": "array", - "items": { - "type": "string", - "pattern": "^[a-zA-Z0-9_]+[.][a-zA-Z_]+$" - } - } - }, - "additionalProperties": false - }, - "Button": { - "title": "Button", - "description": "Component provided to `Page` to trigger any defined `action` in `Page`.\n\nArgs:\n type (Literal[\"button\"]): Defaults to `\"button\"`.\n text (str): Text to be displayed on button. Defaults to `\"Click me!\"`.\n actions (List[Action]): See [`Action`][vizro.models.Action]. Defaults to `[]`.", - "type": "object", - "properties": { - "id": { - "title": "Id", - "description": "ID to identify model. Must be unique throughout the whole dashboard.When no ID is chosen, ID will be automatically generated.", - "default": "", - "type": "string" - }, - "type": { - "title": "Type", - "default": "button", - "enum": ["button"], - "type": "string" - }, - "text": { - "title": "Text", - "description": "Text to be displayed on button.", - "default": "Click me!", - "type": "string" - }, - "actions": { - "title": "Actions", - "default": [], - "type": "array", - "items": { - "$ref": "#/definitions/Action" - } - } - }, - "additionalProperties": false - }, - "Card": { - "title": "Card", - "description": "Creates a card utilizing `dcc.Markdown` as title and text component.\n\nArgs:\n type (Literal[\"card\"]): Defaults to `\"card\"`.\n text (str): Markdown string to create card title/text that should adhere to the CommonMark Spec.\n href (str): URL (relative or absolute) to navigate to. If not provided the Card serves as a text card\n only. Defaults to `\"\"`.", - "type": "object", - "properties": { - "id": { - "title": "Id", - "description": "ID to identify model. Must be unique throughout the whole dashboard.When no ID is chosen, ID will be automatically generated.", - "default": "", - "type": "string" - }, - "type": { - "title": "Type", - "default": "card", - "enum": ["card"], - "type": "string" - }, - "text": { - "title": "Text", - "description": "Markdown string to create card title/text that should adhere to the CommonMark Spec.", - "type": "string" - }, - "href": { - "title": "Href", - "description": "URL (relative or absolute) to navigate to. If not provided the Card serves as a text card only.", - "default": "", - "type": "string" - } - }, - "required": ["text"], - "additionalProperties": false - }, - "Graph": { - "title": "Graph", - "description": "Wrapper for `dcc.Graph` to visualize charts in dashboard.\n\nArgs:\n type (Literal[\"graph\"]): Defaults to `\"graph\"`.\n figure (CapturedCallable): See [`CapturedCallable`][vizro.models.types.CapturedCallable].\n actions (List[Action]): See [`Action`][vizro.models.Action]. Defaults to `[]`.", - "type": "object", - "properties": { - "id": { - "title": "Id", - "description": "ID to identify model. Must be unique throughout the whole dashboard.When no ID is chosen, ID will be automatically generated.", - "default": "", - "type": "string" - }, - "type": { - "title": "Type", - "default": "graph", - "enum": ["graph"], - "type": "string" - }, - "actions": { - "title": "Actions", - "default": [], - "type": "array", - "items": { - "$ref": "#/definitions/Action" - } - } - }, - "additionalProperties": false - }, - "Table": { - "title": "Table", - "description": "Wrapper for table components to visualize in dashboard.\n\nArgs:\n type (Literal[\"table\"]): Defaults to `\"table\"`.\n figure (CapturedCallable): Table like object to be displayed. Current choices include:\n [`dash_table.DataTable`](https://dash.plotly.com/datatable).\n title (str): Title of the table. Defaults to `\"\"`.\n actions (List[Action]): See [`Action`][vizro.models.Action]. Defaults to `[]`.", - "type": "object", - "properties": { - "id": { - "title": "Id", - "description": "ID to identify model. Must be unique throughout the whole dashboard.When no ID is chosen, ID will be automatically generated.", - "default": "", - "type": "string" - }, - "type": { - "title": "Type", - "default": "table", - "enum": ["table"], - "type": "string" - }, - "title": { - "title": "Title", - "description": "Title of the table", - "default": "", - "type": "string" - }, - "actions": { - "title": "Actions", - "default": [], - "type": "array", - "items": { - "$ref": "#/definitions/Action" - } - } - }, - "additionalProperties": false - }, - "Layout": { - "title": "Layout", - "description": "Grid specification to place chart/components on the [`Page`][vizro.models.Page].\n\nArgs:\n grid (List[List[int]]): Grid specification to arrange components on screen.\n row_gap (str): Gap between rows in px. Defaults to `\"12px\"`.\n col_gap (str): Gap between columns in px. Defaults to `\"12px\"`.\n row_min_height (str): Minimum row height in px. Defaults to `\"0px\"`.\n col_min_width (str): Minimum column width in px. Defaults to `\"0px\"`.", - "type": "object", - "properties": { - "id": { - "title": "Id", - "description": "ID to identify model. Must be unique throughout the whole dashboard.When no ID is chosen, ID will be automatically generated.", - "default": "", - "type": "string" - }, - "grid": { - "title": "Grid", - "description": "Grid specification to arrange components on screen.", - "type": "array", - "items": { - "type": "array", - "items": { - "type": "integer" - } - } - }, - "row_gap": { - "title": "Row Gap", - "description": "Gap between rows in px. Defaults to 12px.", - "default": "12px", - "pattern": "[0-9]+px", - "type": "string" - }, - "col_gap": { - "title": "Col Gap", - "description": "Gap between columns in px. Defaults to 12px.", - "default": "12px", - "pattern": "[0-9]+px", - "type": "string" - }, - "row_min_height": { - "title": "Row Min Height", - "description": "Minimum row height in px. Defaults to 0px.", - "default": "0px", - "pattern": "[0-9]+px", - "type": "string" - }, - "col_min_width": { - "title": "Col Min Width", - "description": "Minimum column width in px. Defaults to 0px.", - "default": "0px", - "pattern": "[0-9]+px", - "type": "string" - } - }, - "required": ["grid"], - "additionalProperties": false - }, - "OptionsDictType": { - "title": "OptionsDictType", - "type": "object", - "properties": { - "label": { - "title": "Label", - "type": "string" - }, - "value": { - "title": "Value", - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "number" - }, - { - "type": "string" - } - ] - } - }, - "required": ["label", "value"], - "additionalProperties": false - }, - "Checklist": { - "title": "Checklist", - "description": "Categorical multi-selector `Checklist` to be provided to [`Filter`][vizro.models.Filter].\n\nArgs:\n type (Literal[\"checklist\"]): Defaults to `\"checklist\"`.\n options (OptionsType): See [`OptionsType`][vizro.models.types.OptionsType]. Defaults to `[]`.\n value (Optional[MultiValueType]): See [`MultiValueType`][vizro.models.types.MultiValueType]. Defaults to `None`.\n title (str): Title to be displayed. Defaults to `\"\"`.\n actions (List[Action]): See [`Action`][vizro.models.Action]. Defaults to `[]`.", - "type": "object", - "properties": { - "id": { - "title": "Id", - "description": "ID to identify model. Must be unique throughout the whole dashboard.When no ID is chosen, ID will be automatically generated.", - "default": "", - "type": "string" - }, - "type": { - "title": "Type", - "default": "checklist", - "enum": ["checklist"], - "type": "string" - }, - "options": { - "title": "Options", - "default": [], - "anyOf": [ - { - "type": "array", - "items": { - "type": "boolean" - } - }, - { - "type": "array", - "items": { - "type": "number" - } - }, - { - "type": "array", - "items": { - "type": "string" - } - }, - { - "type": "array", - "items": { - "$ref": "#/definitions/OptionsDictType" - } - } - ] - }, - "value": { - "title": "Value", - "anyOf": [ - { - "type": "array", - "items": { - "type": "boolean" - } - }, - { - "type": "array", - "items": { - "type": "number" - } - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ] - }, - "title": { - "title": "Title", - "description": "Title to be displayed", - "default": "", - "type": "string" - }, - "actions": { - "title": "Actions", - "default": [], - "type": "array", - "items": { - "$ref": "#/definitions/Action" - } - } - }, - "additionalProperties": false - }, - "Dropdown": { - "title": "Dropdown", - "description": "Categorical multi-selector `Dropdown` to be provided to [`Filter`][vizro.models.Filter].\n\nArgs:\n type (Literal[\"dropdown\"]): Defaults to `\"dropdown\"`.\n options (OptionsType): See [`OptionsType`][vizro.models.types.OptionsType]. Defaults to `[]`.\n value (Optional[Union[SingleValueType, MultiValueType]]): See\n [`SingleValueType`][vizro.models.types.SingleValueType] and\n [`MultiValueType`][vizro.models.types.MultiValueType]. Defaults to `None`.\n multi (bool): Whether to allow selection of multiple values. Defaults to `True`.\n title (str): Title to be displayed. Defaults to `\"\"`.\n actions (List[Action]): See [`Action`][vizro.models.Action]. Defaults to `[]`.", - "type": "object", - "properties": { - "id": { - "title": "Id", - "description": "ID to identify model. Must be unique throughout the whole dashboard.When no ID is chosen, ID will be automatically generated.", - "default": "", - "type": "string" - }, - "type": { - "title": "Type", - "default": "dropdown", - "enum": ["dropdown"], - "type": "string" - }, - "options": { - "title": "Options", - "default": [], - "anyOf": [ - { - "type": "array", - "items": { - "type": "boolean" - } - }, - { - "type": "array", - "items": { - "type": "number" - } - }, - { - "type": "array", - "items": { - "type": "string" - } - }, - { - "type": "array", - "items": { - "$ref": "#/definitions/OptionsDictType" - } - } - ] - }, - "value": { - "title": "Value", - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "number" - }, - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "boolean" - } - }, - { - "type": "array", - "items": { - "type": "number" - } - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ] - }, - "multi": { - "title": "Multi", - "description": "Whether to allow selection of multiple values", - "default": true, - "type": "boolean" - }, - "title": { - "title": "Title", - "description": "Title to be displayed", - "default": "", - "type": "string" - }, - "actions": { - "title": "Actions", - "default": [], - "type": "array", - "items": { - "$ref": "#/definitions/Action" - } - } - }, - "additionalProperties": false - }, - "RadioItems": { - "title": "RadioItems", - "description": "Categorical single-selector `RadioItems` to be provided to `Filter`.\n\nArgs:\n type (Literal[\"radio_items\"]): Defaults to `\"radio_items\"`.\n options (OptionsType): See [`OptionsType`][vizro.models.types.OptionsType]. Defaults to `[]`.\n value (Optional[SingleValueType]): See [`SingleValueType`][vizro.models.types.SingleValueType].\n Defaults to `None`.\n title (str): Title to be displayed. Defaults to `\"\"`.\n actions (List[Action]): See [`Action`][vizro.models.Action]. Defaults to `[]`.", - "type": "object", - "properties": { - "id": { - "title": "Id", - "description": "ID to identify model. Must be unique throughout the whole dashboard.When no ID is chosen, ID will be automatically generated.", - "default": "", - "type": "string" - }, - "type": { - "title": "Type", - "default": "radio_items", - "enum": ["radio_items"], - "type": "string" - }, - "options": { - "title": "Options", - "default": [], - "anyOf": [ - { - "type": "array", - "items": { - "type": "boolean" - } - }, - { - "type": "array", - "items": { - "type": "number" - } - }, - { - "type": "array", - "items": { - "type": "string" - } - }, - { - "type": "array", - "items": { - "$ref": "#/definitions/OptionsDictType" - } - } - ] - }, - "value": { - "title": "Value", - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "number" - }, - { - "type": "string" - } - ] - }, - "title": { - "title": "Title", - "description": "Title to be displayed", - "default": "", - "type": "string" - }, - "actions": { - "title": "Actions", - "default": [], - "type": "array", - "items": { - "$ref": "#/definitions/Action" - } - } - }, - "additionalProperties": false - }, - "RangeSlider": { - "title": "RangeSlider", - "description": "Numeric multi-selector `RangeSlider`.\n\nCan be provided to [`Filter`][vizro.models.Filter] or\n[`Parameter`][vizro.models.Parameter]. Based on the underlying\n[`dcc.RangeSlider`](https://dash.plotly.com/dash-core-components/rangeslider).\n\nArgs:\n type (Literal[\"range_slider\"]): Defaults to `\"range_slider\"`.\n min (Optional[float]): Start value for slider. Defaults to `None`.\n max (Optional[float]): End value for slider. Defaults to `None`.\n step (Optional[float]): Step-size for marks on slider. Defaults to `None`.\n marks (Optional[Dict[float, str]]): Marks to be displayed on slider. Defaults to `{}`.\n value (Optional[List[float]]): Default start and end value for slider. Must be 2 items. Defaults to `None`.\n title (str): Title to be displayed. Defaults to `\"\"`.\n actions (List[Action]): See [`Action`][vizro.models.Action]. Defaults to `[]`.", - "type": "object", - "properties": { - "id": { - "title": "Id", - "description": "ID to identify model. Must be unique throughout the whole dashboard.When no ID is chosen, ID will be automatically generated.", - "default": "", - "type": "string" - }, - "type": { - "title": "Type", - "default": "range_slider", - "enum": ["range_slider"], - "type": "string" - }, - "min": { - "title": "Min", - "description": "Start value for slider.", - "type": "number" - }, - "max": { - "title": "Max", - "description": "End value for slider.", - "type": "number" - }, - "step": { - "title": "Step", - "description": "Step-size for marks on slider.", - "type": "number" - }, - "marks": { - "title": "Marks", - "description": "Marks to be displayed on slider.", - "default": {}, - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "value": { - "title": "Value", - "description": "Default start and end value for slider", - "minItems": 2, - "maxItems": 2, - "type": "array", - "items": { - "type": "number" - } - }, - "title": { - "title": "Title", - "description": "Title to be displayed.", - "default": "", - "type": "string" - }, - "actions": { - "title": "Actions", - "default": [], - "type": "array", - "items": { - "$ref": "#/definitions/Action" - } - } - }, - "additionalProperties": false - }, - "Slider": { - "title": "Slider", - "description": "Numeric single-selector `Slider`.\n\nCan be provided to [`Filter`][vizro.models.Filter] or\n[`Parameter`][vizro.models.Parameter]. Based on the underlying\n[`dcc.Slider`](https://dash.plotly.com/dash-core-components/slider).\n\nArgs:\n type (Literal[\"range_slider\"]): Defaults to `\"range_slider\"`.\n min (Optional[float]): Start value for slider. Defaults to `None`.\n max (Optional[float]): End value for slider. Defaults to `None`.\n step (Optional[float]): Step-size for marks on slider. Defaults to `None`.\n marks (Optional[Dict[float, str]]): Marks to be displayed on slider. Defaults to `{}`.\n value (Optional[float]): Default value for slider. Defaults to `None`.\n title (str): Title to be displayed. Defaults to `\"\"`.\n actions (List[Action]): See [`Action`][vizro.models.Action]. Defaults to `[]`.", - "type": "object", - "properties": { - "id": { - "title": "Id", - "description": "ID to identify model. Must be unique throughout the whole dashboard.When no ID is chosen, ID will be automatically generated.", - "default": "", - "type": "string" - }, - "type": { - "title": "Type", - "default": "slider", - "enum": ["slider"], - "type": "string" - }, - "min": { - "title": "Min", - "description": "Start value for slider.", - "type": "number" - }, - "max": { - "title": "Max", - "description": "End value for slider.", - "type": "number" - }, - "step": { - "title": "Step", - "description": "Step-size for marks on slider.", - "type": "number" - }, - "marks": { - "title": "Marks", - "description": "Marks to be displayed on slider.", - "default": {}, - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "value": { - "title": "Value", - "description": "Default value for slider.", - "type": "number" - }, - "title": { - "title": "Title", - "description": "Title to be displayed.", - "default": "", - "type": "string" - }, - "actions": { - "title": "Actions", - "default": [], - "type": "array", - "items": { - "$ref": "#/definitions/Action" - } - } - }, - "additionalProperties": false - }, - "Filter": { - "title": "Filter", - "description": "Filter the data supplied to `targets` on the [`Page`][vizro.models.Page].\n\nExamples:\n >>> print(repr(Filter(column=\"species\")))\n\nArgs:\n type (Literal[\"filter\"]): Defaults to `\"filter\"`.\n column (str): Column of `DataFrame` to filter.\n targets (List[ModelID]): Target component to be affected by filter. If none are given then target all components\n on the page that use `column`.\n selector (Optional[SelectorType]): See [SelectorType][vizro.models.types.SelectorType]. Defaults to `None`.", - "type": "object", - "properties": { - "id": { - "title": "Id", - "description": "ID to identify model. Must be unique throughout the whole dashboard.When no ID is chosen, ID will be automatically generated.", - "default": "", - "type": "string" - }, - "type": { - "title": "Type", - "default": "filter", - "enum": ["filter"], - "type": "string" - }, - "column": { - "title": "Column", - "description": "Column of DataFrame to filter.", - "type": "string" - }, - "targets": { - "title": "Targets", - "description": "Target component to be affected by filter. If none are given then target all components on the page that use `column`.", - "default": [], - "type": "array", - "items": { - "type": "string" - } - }, - "selector": { - "title": "Selector", - "anyOf": [ - { - "$ref": "#/definitions/Checklist" - }, - { - "$ref": "#/definitions/Dropdown" - }, - { - "$ref": "#/definitions/RadioItems" - }, - { - "$ref": "#/definitions/RangeSlider" - }, - { - "$ref": "#/definitions/Slider" - } - ] - } - }, - "required": ["column"], - "additionalProperties": false - }, - "Parameter": { - "title": "Parameter", - "description": "Alter the arguments supplied to any `targets` on the [`Page`][vizro.models.Page].\n\nExamples:\n >>> print(repr(Parameter(\n >>> targets=[\"scatter.x\"], selector=Slider(min=0, max=1, default=0.8, title=\"Bubble opacity\"))))\n\nArgs:\n type (Literal[\"parameter\"]): Defaults to `\"parameter\"`.\n targets (List[str]): Targets in the form of `.`.\n selector (SelectorType): See [SelectorType][vizro.models.types.SelectorType]. Converts selector value\n `\"NONE\"` into `None` to allow optional parameters.\n\nRaises:\n ValueError: If targets are invalid and not of the form `.`.", - "type": "object", - "properties": { - "id": { - "title": "Id", - "description": "ID to identify model. Must be unique throughout the whole dashboard.When no ID is chosen, ID will be automatically generated.", - "default": "", - "type": "string" - }, - "type": { - "title": "Type", - "default": "parameter", - "enum": ["parameter"], - "type": "string" - }, - "targets": { - "title": "Targets", - "description": "Targets in the form of `.`.", - "type": "array", - "items": { - "type": "string" - } - }, - "selector": { - "title": "Selector", - "description": "Selectors to be used inside a control.", - "discriminator": { - "propertyName": "type", - "mapping": { - "checklist": "#/definitions/Checklist", - "dropdown": "#/definitions/Dropdown", - "radio_items": "#/definitions/RadioItems", - "range_slider": "#/definitions/RangeSlider", - "slider": "#/definitions/Slider" - } - }, - "oneOf": [ - { - "$ref": "#/definitions/Checklist" - }, - { - "$ref": "#/definitions/Dropdown" - }, - { - "$ref": "#/definitions/RadioItems" - }, - { - "$ref": "#/definitions/RangeSlider" - }, - { - "$ref": "#/definitions/Slider" - } - ] - } - }, - "required": ["targets", "selector"], - "additionalProperties": false - }, - "ActionsChain": { - "title": "ActionsChain", - "description": "All models that are registered to the model manager should inherit from this class.\n\nArgs:\n id (str): ID to identify model. Must be unique throughout the whole dashboard. Defaults to `\"\"`.\n When no ID is chosen, ID will be automatically generated.", - "type": "object", - "properties": { - "id": { - "title": "Id", - "description": "ID to identify model. Must be unique throughout the whole dashboard.When no ID is chosen, ID will be automatically generated.", - "default": "", - "type": "string" - }, - "trigger": { - "title": "Trigger", - "type": "array", - "items": [ - { - "title": "Component Id", - "type": "string" - }, - { - "title": "Component Property", - "type": "string" - } - ], - "minItems": 2, - "maxItems": 2 - }, - "actions": { - "title": "Actions", - "default": [], - "type": "array", - "items": { - "$ref": "#/definitions/Action" - } - } - }, - "required": ["trigger"], - "additionalProperties": false - }, - "Page": { - "title": "Page", - "description": "A page in [`Dashboard`][vizro.models.Dashboard] with its own URL path and place in the `Navigation`.\n\nArgs:\n components (List[ComponentType]): See [ComponentType][vizro.models.types.ComponentType]. At least one component\n has to be provided.\n title (str): Title to be displayed.\n layout (Optional[Layout]): Layout to place components in. Defaults to `None`.\n controls (List[ControlType]): See [ControlType][vizro.models.types.ControlType]. Defaults to `[]`.\n path (str): Path to navigate to page. Defaults to `\"\"`.\n\nRaises:\n ValueError: If number of page and grid components is not the same", - "type": "object", - "properties": { - "id": { - "title": "Id", - "description": "ID to identify model. Must be unique throughout the whole dashboard.When no ID is chosen, ID will be automatically generated.", - "default": "", - "type": "string" - }, - "components": { - "title": "Components", - "type": "array", - "items": { - "discriminator": { - "propertyName": "type", - "mapping": { - "button": "#/definitions/Button", - "card": "#/definitions/Card", - "graph": "#/definitions/Graph", - "table": "#/definitions/Table" - } - }, - "oneOf": [ - { - "$ref": "#/definitions/Button" - }, - { - "$ref": "#/definitions/Card" - }, - { - "$ref": "#/definitions/Graph" - }, - { - "$ref": "#/definitions/Table" - } - ] - } - }, - "title": { - "title": "Title", - "description": "Title to be displayed.", - "type": "string" - }, - "layout": { - "$ref": "#/definitions/Layout" - }, - "controls": { - "title": "Controls", - "default": [], - "type": "array", - "items": { - "discriminator": { - "propertyName": "type", - "mapping": { - "filter": "#/definitions/Filter", - "parameter": "#/definitions/Parameter" - } - }, - "oneOf": [ - { - "$ref": "#/definitions/Filter" - }, - { - "$ref": "#/definitions/Parameter" - } - ] - } - }, - "path": { - "title": "Path", - "description": "Path to navigate to page.", - "default": "", - "type": "string" - }, - "actions": { - "title": "Actions", - "default": [], - "type": "array", - "items": { - "$ref": "#/definitions/ActionsChain" - } - } - }, - "required": ["components", "title"], - "additionalProperties": false - }, - "Accordion": { - "title": "Accordion", - "description": "Accordion to be used as nav_selector in [`Navigation`][vizro.models.Navigation].\n\nArgs:\n type (Literal[\"accordion\"]): Defaults to `\"accordion\"`.\n pages (Dict[str, List[str]]): Mapping from name of a pages group to a list of page IDs. Defaults to `{}`.", - "type": "object", - "properties": { - "id": { - "title": "Id", - "description": "ID to identify model. Must be unique throughout the whole dashboard.When no ID is chosen, ID will be automatically generated.", - "default": "", - "type": "string" - }, - "type": { - "title": "Type", - "default": "accordion", - "enum": ["accordion"], - "type": "string" - }, - "pages": { - "title": "Pages", - "description": "Mapping from name of a pages group to a list of page IDs.", - "default": {}, - "type": "object", - "additionalProperties": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "additionalProperties": false - }, - "NavLink": { - "title": "NavLink", - "description": "Icon to be used in Navigation Panel of Dashboard.\n\nArgs:\n ages (Optional[NavPagesType]): See [`NavPagesType`][vizro.models.types.NavPagesType].\n Defaults to `[]`.\n label (str): Text description of the icon for use in tooltip.\n icon (str): Icon name from [Google Material icons library](https://fonts.google.com/icons).\n Defaults to `\"\"`.", - "type": "object", - "properties": { - "id": { - "title": "Id", - "description": "ID to identify model. Must be unique throughout the whole dashboard.When no ID is chosen, ID will be automatically generated.", - "default": "", - "type": "string" - }, - "pages": { - "title": "Pages", - "default": [], - "anyOf": [ - { - "type": "array", - "items": { - "type": "string" - } - }, - { - "type": "object", - "additionalProperties": { - "type": "array", - "items": { - "type": "string" - } - } - } - ] - }, - "label": { - "title": "Label", - "description": "Text description of the icon for use in tooltip.", - "type": "string" - }, - "icon": { - "title": "Icon", - "description": "Icon name from Google Material icons library.", - "default": "", - "type": "string" - } - }, - "required": ["label"], - "additionalProperties": false - }, - "NavBar": { - "title": "NavBar", - "description": "Navigation bar to be used as a nav_selector for `Navigation`.\n\nArgs:\n type (Literal[\"nav_bar\"]): Defaults to `\"nav_bar\"`.\n pages (Dict[str, List[str]]): Mapping from name of a pages group to a list of page IDs. Defaults to `{}`.\n items (List[NavLink]): See [`NavLink`][vizro.models.NavLink]. Defaults to `[]`.", - "type": "object", - "properties": { - "id": { - "title": "Id", - "description": "ID to identify model. Must be unique throughout the whole dashboard.When no ID is chosen, ID will be automatically generated.", - "default": "", - "type": "string" - }, - "type": { - "title": "Type", - "default": "nav_bar", - "enum": ["nav_bar"], - "type": "string" - }, - "pages": { - "title": "Pages", - "description": "Mapping from name of a pages group to a list of page IDs.", - "default": {}, - "type": "object", - "additionalProperties": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "items": { - "title": "Items", - "default": [], - "type": "array", - "items": { - "$ref": "#/definitions/NavLink" - } - } - }, - "additionalProperties": false - }, - "Navigation": { - "title": "Navigation", - "description": "Navigation in [`Dashboard`][vizro.models.Dashboard] to structure [`Pages`][vizro.models.Page].\n\nArgs:\n pages (Optional[NavPagesType]): See [`NavPagesType`][vizro.models.types.NavPagesType].\n Defaults to [].\n nav_selector (Optional[NavSelectorType]): See [`NavSelectorType`][vizro.models.types.NavSelectorType].\n Defaults to `None`.", - "type": "object", - "properties": { - "id": { - "title": "Id", - "description": "ID to identify model. Must be unique throughout the whole dashboard.When no ID is chosen, ID will be automatically generated.", - "default": "", - "type": "string" - }, - "pages": { - "title": "Pages", - "default": [], - "anyOf": [ - { - "type": "array", - "items": { - "type": "string" - } - }, - { - "type": "object", - "additionalProperties": { - "type": "array", - "items": { - "type": "string" - } - } - } - ] - }, - "nav_selector": { - "title": "Nav Selector", - "anyOf": [ - { - "$ref": "#/definitions/Accordion" - }, - { - "$ref": "#/definitions/NavBar" - } - ] - } - }, - "additionalProperties": false - } - } -} diff --git a/vizro-core/schemas/generate.py b/vizro-core/schemas/generate.py index d4a1ec681..e0bd86a63 100644 --- a/vizro-core/schemas/generate.py +++ b/vizro-core/schemas/generate.py @@ -17,7 +17,7 @@ if args.check: if json.loads(schema_path.read_text()) != json.loads(schema_json): - sys.exit("JSON schema is out of date. Run `hatch run all.py3.11:schema` to update it.") + sys.exit("JSON schema is out of date. Run `hatch run schema` to update it.") print("JSON schema is up to date.") # noqa: T201 else: schema_path.write_text(schema_json) diff --git a/vizro-core/snyk/requirements.txt b/vizro-core/snyk/requirements.txt index 81b4e6dbe..a65406ad0 100644 --- a/vizro-core/snyk/requirements.txt +++ b/vizro-core/snyk/requirements.txt @@ -1,9 +1,8 @@ dash>=2.11 dash_bootstrap_components pandas -pydantic>=1.10.13 +pydantic>=1.10.13, <2 dash_daq -dash_mantine_components ipython>=8.10.0 numpy>=1.22.2 tornado>=6.3.2 diff --git a/vizro-core/src/vizro/__init__.py b/vizro-core/src/vizro/__init__.py index de001d411..35cc3b86b 100644 --- a/vizro-core/src/vizro/__init__.py +++ b/vizro-core/src/vizro/__init__.py @@ -5,6 +5,6 @@ __all__ = ["Vizro"] -__version__ = "0.1.7.dev1" +__version__ = "0.1.7.dev0" logging.basicConfig(level=os.getenv("VIZRO_LOG_LEVEL", "WARNING")) diff --git a/vizro-core/src/vizro/actions/_action_loop/_action_loop.py b/vizro-core/src/vizro/actions/_action_loop/_action_loop.py index 23e94503d..def923e60 100644 --- a/vizro-core/src/vizro/actions/_action_loop/_action_loop.py +++ b/vizro-core/src/vizro/actions/_action_loop/_action_loop.py @@ -16,7 +16,7 @@ def _create_app_callbacks(cls) -> html.Div: Returns: List of required components for the action loop and for each `Action` in the `Dashboard`. """ - return html.Div([cls._build_action_loop(), cls._build_actions_models()], id="app_components_div", hidden=True) + return html.Div([cls._build_action_loop(), cls._build_actions_models()], id="app_components_div") @staticmethod def _build_action_loop(): @@ -36,4 +36,4 @@ def _build_actions_models(): List of required components for each `Action` in the `Dashboard` e.g. List[dcc.Download] """ actions = _get_actions_on_registered_pages() - return html.Div([action.build() for action in actions], id="app_action_models_components_div", hidden=True) + return html.Div([action.build() for action in actions], id="app_action_models_components_div") diff --git a/vizro-core/src/vizro/actions/_action_loop/_action_loop_utils.py b/vizro-core/src/vizro/actions/_action_loop/_action_loop_utils.py index dceba7d76..a43b34dd6 100644 --- a/vizro-core/src/vizro/actions/_action_loop/_action_loop_utils.py +++ b/vizro-core/src/vizro/actions/_action_loop/_action_loop_utils.py @@ -18,7 +18,7 @@ def _get_actions_chains_on_registered_pages() -> List[ActionsChain]: actions_chains: List[ActionsChain] = [] for registered_page in page_registry.values(): try: - page: Page = model_manager[registered_page["module"]] + page: Page = model_manager[registered_page["module"]] # type: ignore[assignment] except KeyError: continue actions_chains.extend(page._get_page_actions_chains()) diff --git a/vizro-core/src/vizro/actions/_actions_utils.py b/vizro-core/src/vizro/actions/_actions_utils.py index 6b197b129..4f4363203 100644 --- a/vizro-core/src/vizro/actions/_actions_utils.py +++ b/vizro-core/src/vizro/actions/_actions_utils.py @@ -78,7 +78,7 @@ def _apply_graph_filter_interaction( source_graph_id: ModelID = ctd_click_data["id"] source_graph_actions = _get_component_actions(model_manager[source_graph_id]) try: - custom_data_columns = model_manager[source_graph_id]["custom_data"] + custom_data_columns = model_manager[source_graph_id]["custom_data"] # type: ignore[index] except KeyError as exc: raise KeyError(f"No `custom_data` argument found for source graph with id {source_graph_id}.") from exc @@ -156,7 +156,7 @@ def _validate_selector_value_none(value: Union[SingleValueType, MultiValueType]) if value == NONE_OPTION: return None elif isinstance(value, list): - return [i for i in value if i != NONE_OPTION] or [None] + return [i for i in value if i != NONE_OPTION] or [None] # type: ignore[list-item, return-value] return value @@ -186,7 +186,7 @@ def _get_parametrized_config( for target in targets: # TODO - avoid calling _captured_callable. Once we have done this we can remove _arguments from # CapturedCallable entirely. - graph_config = deepcopy(model_manager[target].figure._arguments) + graph_config = deepcopy(model_manager[target].figure._arguments) # type: ignore[attr-defined] if "data_frame" in graph_config: graph_config.pop("data_frame") @@ -263,6 +263,8 @@ def _get_modified_page_figures( outputs = {} for target in targets: - outputs[target] = model_manager[target](data_frame=filtered_data[target], **parameterized_config[target]) + outputs[target] = model_manager[target]( # type: ignore[operator] + data_frame=filtered_data[target], **parameterized_config[target] + ) return outputs diff --git a/vizro-core/src/vizro/actions/_callback_mapping/_callback_mapping_utils.py b/vizro-core/src/vizro/actions/_callback_mapping/_callback_mapping_utils.py index 344a41819..90b6baf17 100644 --- a/vizro-core/src/vizro/actions/_callback_mapping/_callback_mapping_utils.py +++ b/vizro-core/src/vizro/actions/_callback_mapping/_callback_mapping_utils.py @@ -72,7 +72,8 @@ def _get_inputs_of_chart_interactions( # TODO: Refactor this and util functions once we implement "_get_input_property" method in VizroBaseModel models def _get_action_callback_inputs(action_id: ModelID) -> Dict[str, List[Union[State, Dict[str, State]]]]: """Creates mapping of pre-defined action names and a list of States.""" - action_function = model_manager[action_id].function._function + action_function = model_manager[action_id].function._function # type: ignore[attr-defined] + page: Page = model_manager._get_model_page(model_id=action_id) if action_function == export_data.__wrapped__: include_inputs = ["filters", "filter_interaction"] @@ -98,7 +99,7 @@ def _get_action_callback_inputs(action_id: ModelID) -> Dict[str, List[Union[Stat # CALLBACK OUTPUTS -------------- def _get_action_callback_outputs(action_id: ModelID) -> Dict[str, Output]: """Creates mapping of target names and their Output.""" - action_function = model_manager[action_id].function._function + action_function = model_manager[action_id].function._function # type: ignore[attr-defined] # The right solution for mypy here is to not e.g. define new attributes on the base but instead to get mypy to # recognize that model_manager[action_id] is of type Action and hence has the function attribute. @@ -106,7 +107,7 @@ def _get_action_callback_outputs(action_id: ModelID) -> Dict[str, Output]: # If not then we can do the cast to Action at the point of consumption here to avoid needing mypy ignores. try: - targets = model_manager[action_id].function["targets"] + targets = model_manager[action_id].function["targets"] # type: ignore[attr-defined] except KeyError: targets = [] @@ -116,7 +117,7 @@ def _get_action_callback_outputs(action_id: ModelID) -> Dict[str, Output]: return { target: Output( component_id=target, - component_property=model_manager[target]._output_property, + component_property=model_manager[target]._output_property, # type: ignore[attr-defined] allow_duplicate=True, ) for target in targets @@ -128,7 +129,7 @@ def _get_export_data_callback_outputs(action_id: ModelID) -> Dict[str, List[Stat action = model_manager[action_id] try: - targets = action.function["targets"] + targets = action.function["targets"] # type: ignore[attr-defined] except KeyError: targets = None @@ -154,7 +155,7 @@ def _get_export_data_callback_components(action_id: ModelID) -> List[dcc.Downloa action = model_manager[action_id] try: - targets = action.function["targets"] + targets = action.function["targets"] # type: ignore[attr-defined] except KeyError: targets = None diff --git a/vizro-core/src/vizro/actions/_callback_mapping/_get_action_callback_mapping.py b/vizro-core/src/vizro/actions/_callback_mapping/_get_action_callback_mapping.py index d69acecb7..43baef8b2 100644 --- a/vizro-core/src/vizro/actions/_callback_mapping/_get_action_callback_mapping.py +++ b/vizro-core/src/vizro/actions/_callback_mapping/_get_action_callback_mapping.py @@ -23,7 +23,7 @@ def _get_action_callback_mapping( action_id: ModelID, argument: str ) -> Union[List[dcc.Download], Dict[str, DashDependency]]: """Creates mapping of action name and required callback input/output.""" - action_function = model_manager[action_id].function._function + action_function = model_manager[action_id].function._function # type: ignore[attr-defined] action_callback_mapping: Dict[str, Any] = { export_data.__wrapped__: { diff --git a/vizro-core/src/vizro/actions/_on_page_load_action.py b/vizro-core/src/vizro/actions/_on_page_load_action.py index 4e9d7901f..9d38e2aff 100644 --- a/vizro-core/src/vizro/actions/_on_page_load_action.py +++ b/vizro-core/src/vizro/actions/_on_page_load_action.py @@ -23,12 +23,6 @@ def _on_page_load(targets: List[ModelID], **inputs: Dict[str, Any]) -> Dict[Mode Returns: Dict mapping target chart ids to modified figures e.g. {'my_scatter': Figure({})} """ - targets = [ - component.id - for component in model_manager[page_id].components - if data_manager._has_registered_data(component.id) - ] - return _get_modified_page_figures( targets=targets, ctds_filter=ctx.args_grouping["filters"], diff --git a/vizro-core/src/vizro/models/__init__.py b/vizro-core/src/vizro/models/__init__.py index 0fd2023d7..14807a303 100644 --- a/vizro-core/src/vizro/models/__init__.py +++ b/vizro-core/src/vizro/models/__init__.py @@ -32,7 +32,6 @@ # Please keep alphabetically ordered __all__ = [ - "Accordion", "Action", "Button", "Card", diff --git a/vizro-core/src/vizro/models/_action/_action.py b/vizro-core/src/vizro/models/_action/_action.py index 5aea95a6b..6f9800a1e 100644 --- a/vizro-core/src/vizro/models/_action/_action.py +++ b/vizro-core/src/vizro/models/_action/_action.py @@ -2,12 +2,8 @@ import logging from typing import Any, Dict, List -from dash import Input, Output, State, callback, html, ctx - -try: - from pydantic.v1 import Field, validator -except ImportError: # pragma: no cov - from pydantic import Field, validator +from dash import Input, Output, State, callback, ctx, html +from pydantic import Field, validator import vizro.actions from vizro.managers._model_manager import ModelID @@ -162,4 +158,7 @@ def build(self): def callback_wrapper(trigger: None, **inputs: Dict[str, Any]) -> Dict[str, Any]: return self._action_callback_function(**inputs) - return html.Div(children=action_components, id=f"{self.id}_action_model_components_div", hidden=True) + return html.Div( + children=action_components, + id=f"{self.id}_action_model_components_div", + ) diff --git a/vizro-core/src/vizro/models/_action/_actions_chain.py b/vizro-core/src/vizro/models/_action/_actions_chain.py index 00c453b34..57f193190 100644 --- a/vizro-core/src/vizro/models/_action/_actions_chain.py +++ b/vizro-core/src/vizro/models/_action/_actions_chain.py @@ -1,10 +1,7 @@ from functools import partial from typing import Any, Dict, List, NamedTuple -try: - from pydantic.v1 import validator -except ImportError: # pragma: no cov - from pydantic import validator +from pydantic import validator from vizro.models import Action, VizroBaseModel diff --git a/vizro-core/src/vizro/models/_base.py b/vizro-core/src/vizro/models/_base.py index f25792b5e..a46f04367 100644 --- a/vizro-core/src/vizro/models/_base.py +++ b/vizro-core/src/vizro/models/_base.py @@ -1,14 +1,8 @@ from typing import Any, List, Type, Union -try: - from pydantic.v1 import BaseModel, Field, validator - from pydantic.v1.fields import SHAPE_LIST, ModelField - from pydantic.v1.typing import get_args -except ImportError: # pragma: no cov - from pydantic import BaseModel, Field, validator - from pydantic.fields import SHAPE_LIST, ModelField - from pydantic.typing import get_args - +from pydantic import BaseModel, Field, validator +from pydantic.fields import SHAPE_LIST, ModelField +from pydantic.typing import get_args from typing_extensions import Annotated from vizro.managers import model_manager @@ -64,7 +58,7 @@ def _is_discriminated_union(field): return hasattr(field.outer_type_, "__metadata__") and get_args(field.outer_type_)[1].discriminator field = cls.__fields__[field_name] - sub_field = field.sub_fields[0] if field.shape == SHAPE_LIST else None + sub_field = field.sub_fields[0] if field.shape == SHAPE_LIST else None # type: ignore[index] if _is_discriminated_union(field): # Field itself is a non-optional discriminated union, e.g. selector: SelectorType or Optional[SelectorType]. diff --git a/vizro-core/src/vizro/models/_components/_form.py b/vizro-core/src/vizro/models/_components/_form.py index 1ef9b44a6..3ee9c1cd5 100644 --- a/vizro-core/src/vizro/models/_components/_form.py +++ b/vizro-core/src/vizro/models/_components/_form.py @@ -3,11 +3,7 @@ from typing import TYPE_CHECKING, List, Literal, Optional from dash import html - -try: - from pydantic.v1 import validator -except ImportError: # pragma: no cov - from pydantic import validator +from pydantic import validator from vizro.models import VizroBaseModel from vizro.models._components.form import ( diff --git a/vizro-core/src/vizro/models/_components/button.py b/vizro-core/src/vizro/models/_components/button.py index 9e063fd51..140c7e7e7 100644 --- a/vizro-core/src/vizro/models/_components/button.py +++ b/vizro-core/src/vizro/models/_components/button.py @@ -2,11 +2,7 @@ import dash_bootstrap_components as dbc from dash import html - -try: - from pydantic.v1 import Field -except ImportError: # pragma: no cov - from pydantic import Field +from pydantic import Field from vizro.models import Action, VizroBaseModel from vizro.models._action._actions_chain import _action_validator_factory diff --git a/vizro-core/src/vizro/models/_components/card.py b/vizro-core/src/vizro/models/_components/card.py index 6c9c0c448..c1f850008 100644 --- a/vizro-core/src/vizro/models/_components/card.py +++ b/vizro-core/src/vizro/models/_components/card.py @@ -2,11 +2,7 @@ import dash_bootstrap_components as dbc from dash import dcc, get_relative_path, html - -try: - from pydantic.v1 import Field -except ImportError: # pragma: no cov - from pydantic import Field +from pydantic import Field from vizro.models import VizroBaseModel from vizro.models._models_utils import _log_call diff --git a/vizro-core/src/vizro/models/_components/form/_alert.py b/vizro-core/src/vizro/models/_components/form/_alert.py index e4ee08107..fbd6d21cd 100644 --- a/vizro-core/src/vizro/models/_components/form/_alert.py +++ b/vizro-core/src/vizro/models/_components/form/_alert.py @@ -2,11 +2,7 @@ import dash_bootstrap_components as dbc from dash import html - -try: - from pydantic.v1 import Field -except ImportError: # pragma: no cov - from pydantic import Field +from pydantic import Field from vizro.models import Action, VizroBaseModel from vizro.models._models_utils import _log_call diff --git a/vizro-core/src/vizro/models/_components/form/_user_input.py b/vizro-core/src/vizro/models/_components/form/_user_input.py index 812ffc279..fa3890d1d 100644 --- a/vizro-core/src/vizro/models/_components/form/_user_input.py +++ b/vizro-core/src/vizro/models/_components/form/_user_input.py @@ -2,11 +2,7 @@ import dash_bootstrap_components as dbc from dash import html - -try: - from pydantic.v1 import Field -except ImportError: # pragma: no cov - from pydantic import Field +from pydantic import Field from vizro.models import Action, VizroBaseModel from vizro.models._action._actions_chain import _action_validator_factory diff --git a/vizro-core/src/vizro/models/_components/form/checklist.py b/vizro-core/src/vizro/models/_components/form/checklist.py index 4be346041..0c6afff28 100644 --- a/vizro-core/src/vizro/models/_components/form/checklist.py +++ b/vizro-core/src/vizro/models/_components/form/checklist.py @@ -1,11 +1,7 @@ from typing import List, Literal, Optional from dash import dcc, html - -try: - from pydantic.v1 import Field, PrivateAttr, root_validator, validator -except ImportError: # pragma: no cov - from pydantic import Field, PrivateAttr, root_validator, validator +from pydantic import Field, PrivateAttr, root_validator, validator from vizro.models import Action, VizroBaseModel from vizro.models._action._actions_chain import _action_validator_factory @@ -26,7 +22,7 @@ class Checklist(VizroBaseModel): """ type: Literal["checklist"] = "checklist" - options: OptionsType = [] + options: OptionsType = [] # type: ignore[assignment] value: Optional[MultiValueType] = None title: str = Field("", description="Title to be displayed") actions: List[Action] = [] diff --git a/vizro-core/src/vizro/models/_components/form/dropdown.py b/vizro-core/src/vizro/models/_components/form/dropdown.py index 5df9d580f..2b2a84dd8 100755 --- a/vizro-core/src/vizro/models/_components/form/dropdown.py +++ b/vizro-core/src/vizro/models/_components/form/dropdown.py @@ -1,11 +1,7 @@ from typing import List, Literal, Optional, Union from dash import dcc, html - -try: - from pydantic.v1 import Field, PrivateAttr, root_validator, validator -except ImportError: # pragma: no cov - from pydantic import Field, PrivateAttr, root_validator, validator +from pydantic import Field, PrivateAttr, root_validator, validator from vizro.models import Action, VizroBaseModel from vizro.models._action._actions_chain import _action_validator_factory @@ -29,7 +25,7 @@ class Dropdown(VizroBaseModel): """ type: Literal["dropdown"] = "dropdown" - options: OptionsType = [] + options: OptionsType = [] # type: ignore[assignment] value: Optional[Union[SingleValueType, MultiValueType]] = None multi: bool = Field(True, description="Whether to allow selection of multiple values") title: str = Field("", description="Title to be displayed") diff --git a/vizro-core/src/vizro/models/_components/form/radio_items.py b/vizro-core/src/vizro/models/_components/form/radio_items.py index 07569c3c2..0fa6733d2 100644 --- a/vizro-core/src/vizro/models/_components/form/radio_items.py +++ b/vizro-core/src/vizro/models/_components/form/radio_items.py @@ -1,11 +1,7 @@ from typing import List, Literal, Optional from dash import dcc, html - -try: - from pydantic.v1 import Field, PrivateAttr, root_validator, validator -except ImportError: # pragma: no cov - from pydantic import Field, PrivateAttr, root_validator, validator +from pydantic import Field, PrivateAttr, root_validator, validator from vizro.models import Action, VizroBaseModel from vizro.models._action._actions_chain import _action_validator_factory @@ -27,7 +23,7 @@ class RadioItems(VizroBaseModel): """ type: Literal["radio_items"] = "radio_items" - options: OptionsType = [] + options: OptionsType = [] # type: ignore[assignment] value: Optional[SingleValueType] = None title: str = Field("", description="Title to be displayed") actions: List[Action] = [] diff --git a/vizro-core/src/vizro/models/_components/form/range_slider.py b/vizro-core/src/vizro/models/_components/form/range_slider.py index 3740dee38..6249aba22 100644 --- a/vizro-core/src/vizro/models/_components/form/range_slider.py +++ b/vizro-core/src/vizro/models/_components/form/range_slider.py @@ -1,11 +1,7 @@ from typing import Dict, List, Literal, Optional from dash import ClientsideFunction, Input, Output, State, clientside_callback, dcc, html - -try: - from pydantic.v1 import Field, PrivateAttr, validator -except ImportError: # pragma: no cov - from pydantic import Field, PrivateAttr, validator +from pydantic import Field, PrivateAttr, validator from vizro.models import Action, VizroBaseModel from vizro.models._action._actions_chain import _action_validator_factory diff --git a/vizro-core/src/vizro/models/_components/form/slider.py b/vizro-core/src/vizro/models/_components/form/slider.py index b8b21d9a3..687f51491 100644 --- a/vizro-core/src/vizro/models/_components/form/slider.py +++ b/vizro-core/src/vizro/models/_components/form/slider.py @@ -1,11 +1,7 @@ from typing import Dict, List, Literal, Optional from dash import ClientsideFunction, Input, Output, State, clientside_callback, dcc, html - -try: - from pydantic.v1 import Field, PrivateAttr, validator -except ImportError: # pragma: no cov - from pydantic import Field, PrivateAttr, validator +from pydantic import Field, PrivateAttr, validator from vizro.models import Action, VizroBaseModel from vizro.models._action._actions_chain import _action_validator_factory diff --git a/vizro-core/src/vizro/models/_components/graph.py b/vizro-core/src/vizro/models/_components/graph.py index 07bfe2d5f..33b5dbe09 100644 --- a/vizro-core/src/vizro/models/_components/graph.py +++ b/vizro-core/src/vizro/models/_components/graph.py @@ -4,11 +4,7 @@ from dash import ctx, dcc from dash.exceptions import MissingCallbackContextException from plotly import graph_objects as go - -try: - from pydantic.v1 import Field, PrivateAttr, validator -except ImportError: # pragma: no cov - from pydantic import Field, PrivateAttr, validator +from pydantic import Field, PrivateAttr, validator import vizro.plotly.express as px from vizro import _themes as themes diff --git a/vizro-core/src/vizro/models/_components/table.py b/vizro-core/src/vizro/models/_components/table.py index 5ee771261..79addb8b1 100644 --- a/vizro-core/src/vizro/models/_components/table.py +++ b/vizro-core/src/vizro/models/_components/table.py @@ -3,11 +3,7 @@ from dash import dash_table, dcc, html from pandas import DataFrame - -try: - from pydantic.v1 import Field, PrivateAttr, validator -except ImportError: # pragma: no cov - from pydantic import Field, PrivateAttr, validator +from pydantic import Field, PrivateAttr, validator import vizro.tables as vt from vizro.managers import data_manager @@ -42,7 +38,7 @@ class Table(VizroBaseModel): _output_property: str = PrivateAttr("children") # validator - set_actions = _action_validator_factory("active_cell") + set_actions = _action_validator_factory("active_cell") # type: ignore[pydantic-field] _validate_callable = validator("figure", allow_reuse=True, always=True)(_process_callable_data_frame) # Convenience wrapper/syntactic sugar. diff --git a/vizro-core/src/vizro/models/_controls/filter.py b/vizro-core/src/vizro/models/_controls/filter.py index fb2f9afa7..b37d82f60 100644 --- a/vizro-core/src/vizro/models/_controls/filter.py +++ b/vizro-core/src/vizro/models/_controls/filter.py @@ -4,11 +4,7 @@ import pandas as pd from pandas.api.types import is_numeric_dtype - -try: - from pydantic.v1 import Field, PrivateAttr, validator -except ImportError: # pragma: no cov - from pydantic import Field, PrivateAttr, validator +from pydantic import Field, PrivateAttr, validator from vizro._constants import FILTER_ACTION_PREFIX from vizro.actions import _filter diff --git a/vizro-core/src/vizro/models/_controls/parameter.py b/vizro-core/src/vizro/models/_controls/parameter.py index be5f1b3c0..9c61b3135 100644 --- a/vizro-core/src/vizro/models/_controls/parameter.py +++ b/vizro-core/src/vizro/models/_controls/parameter.py @@ -1,9 +1,6 @@ from typing import List, Literal -try: - from pydantic.v1 import Field, validator -except ImportError: # pragma: no cov - from pydantic import Field, validator +from pydantic import Field, validator from vizro._constants import PARAMETER_ACTION_PREFIX from vizro.actions import _parameter diff --git a/vizro-core/src/vizro/models/_dashboard.py b/vizro-core/src/vizro/models/_dashboard.py index c1d78c4b3..d6f4fefcd 100644 --- a/vizro-core/src/vizro/models/_dashboard.py +++ b/vizro-core/src/vizro/models/_dashboard.py @@ -8,11 +8,7 @@ import dash_bootstrap_components as dbc import dash_daq as daq from dash import ClientsideFunction, Input, Output, clientside_callback, get_relative_path, html - -try: - from pydantic.v1 import Field, validator -except ImportError: # pragma: no cov - from pydantic import Field, validator +from pydantic import Field, validator import vizro from vizro._constants import MODULE_PAGE_404, STATIC_URL_PREFIX @@ -87,7 +83,7 @@ def build(self): return dbc.Container( id="dashboard_container_outer", children=[ - html.Div(vizro.__version__, id="vizro_version", hidden=True), + html.Div(id=f"vizro_version_{vizro.__version__}"), ActionLoop._create_app_callbacks(), dash.page_container, ], diff --git a/vizro-core/src/vizro/models/_layout.py b/vizro-core/src/vizro/models/_layout.py index b2ccb6b0c..0bc22e43e 100644 --- a/vizro-core/src/vizro/models/_layout.py +++ b/vizro-core/src/vizro/models/_layout.py @@ -2,11 +2,7 @@ import numpy as np from numpy import ma - -try: - from pydantic.v1 import Field, PrivateAttr, ValidationError, validator -except ImportError: # pragma: no cov - from pydantic import Field, PrivateAttr, ValidationError, validator +from pydantic import Field, PrivateAttr, ValidationError, validator from vizro._constants import EMPTY_SPACE_CONST from vizro.models import VizroBaseModel diff --git a/vizro-core/src/vizro/models/_navigation/accordion.py b/vizro-core/src/vizro/models/_navigation/accordion.py index 724dda7d6..4bd374444 100644 --- a/vizro-core/src/vizro/models/_navigation/accordion.py +++ b/vizro-core/src/vizro/models/_navigation/accordion.py @@ -5,11 +5,7 @@ import dash import dash_bootstrap_components as dbc from dash import html - -try: - from pydantic.v1 import Field, validator -except ImportError: # pragma: no cov - from pydantic import Field, validator +from pydantic import Field, validator from vizro._constants import ACCORDION_DEFAULT_TITLE from vizro.models import VizroBaseModel @@ -52,7 +48,7 @@ def build(self, *, active_page_id=None): dbc.AccordionItem( children=accordion_buttons, title=page_group.upper(), - class_name="accordion-item-header", + class_name="accordion_item", ) ) diff --git a/vizro-core/src/vizro/models/_navigation/nav_bar.py b/vizro-core/src/vizro/models/_navigation/nav_bar.py index 11a062d39..270fe0f1e 100644 --- a/vizro-core/src/vizro/models/_navigation/nav_bar.py +++ b/vizro-core/src/vizro/models/_navigation/nav_bar.py @@ -4,11 +4,7 @@ from typing import Dict, List, Literal from dash import html - -try: - from pydantic.v1 import Field, validator -except ImportError: # pragma: no cov - from pydantic import Field, validator +from pydantic import Field, validator from vizro.models import VizroBaseModel from vizro.models._models_utils import _log_call diff --git a/vizro-core/src/vizro/models/_navigation/nav_link.py b/vizro-core/src/vizro/models/_navigation/nav_link.py index 319addaa2..fd899bcb5 100644 --- a/vizro-core/src/vizro/models/_navigation/nav_link.py +++ b/vizro-core/src/vizro/models/_navigation/nav_link.py @@ -4,13 +4,8 @@ import dash import dash_bootstrap_components as dbc -import dash_mantine_components as dmc from dash import html - -try: - from pydantic.v1 import Field, PrivateAttr, validator -except ImportError: # pragma: no cov - from pydantic import Field, PrivateAttr, validator +from pydantic import Field, PrivateAttr, validator from vizro.models import VizroBaseModel from vizro.models._models_utils import _log_call @@ -44,7 +39,7 @@ class NavLink(VizroBaseModel): def pre_build(self): from vizro.models._navigation.accordion import Accordion - self._nav_selector = Accordion(pages=self.pages) + self._nav_selector = Accordion(pages=self.pages) # type: ignore[arg-type] @_log_call def build(self, *, active_page_id=None): @@ -62,13 +57,10 @@ def build(self, *, active_page_id=None): button = dbc.Button( [ - dmc.Tooltip( - label=self.label, - offset=4, - withArrow=True, - children=[html.Span(self.icon, className="material-symbols-outlined")], - position="bottom-start", - ) + html.Span(self.icon, className="material-symbols-outlined"), + # TODO: commented out until we insert styling for the tooltip or find a better way to display it (e.g. + # try dbc.Popover or Dash mantine components tooltip?). + # dbc.Tooltip(html.P(self.label), target=self.id, placement="bottom", className="custom-tooltip"), ], id=self.id, className="icon-button", diff --git a/vizro-core/src/vizro/models/_navigation/navigation.py b/vizro-core/src/vizro/models/_navigation/navigation.py index f71b75096..a243862f4 100644 --- a/vizro-core/src/vizro/models/_navigation/navigation.py +++ b/vizro-core/src/vizro/models/_navigation/navigation.py @@ -1,11 +1,7 @@ from __future__ import annotations from dash import html - -try: - from pydantic.v1 import validator -except ImportError: # pragma: no cov - from pydantic import validator +from pydantic import validator from vizro.models import VizroBaseModel from vizro.models._models_utils import _log_call diff --git a/vizro-core/src/vizro/models/_page.py b/vizro-core/src/vizro/models/_page.py index f4d4f5ef3..eb554f9a5 100644 --- a/vizro-core/src/vizro/models/_page.py +++ b/vizro-core/src/vizro/models/_page.py @@ -3,11 +3,7 @@ from typing import List, Optional, TypedDict from dash import Input, Output, Patch, callback, dcc, html - -try: - from pydantic.v1 import Field, root_validator, validator -except ImportError: # pragma: no cov - from pydantic import Field, root_validator, validator +from pydantic import Field, root_validator, validator from vizro._constants import ON_PAGE_LOAD_ACTION_PREFIX from vizro.actions import _on_page_load diff --git a/vizro-core/src/vizro/models/types.py b/vizro-core/src/vizro/models/types.py index 3117dfb0c..fc4bf6939 100644 --- a/vizro-core/src/vizro/models/types.py +++ b/vizro-core/src/vizro/models/types.py @@ -6,15 +6,9 @@ import inspect from typing import Any, Dict, List, Literal, Protocol, Union, runtime_checkable -try: - from pydantic.v1 import Field, StrictBool - from pydantic.v1.fields import ModelField - from pydantic.v1.schema import SkipField -except ImportError: # pragma: no cov - from pydantic import Field, StrictBool - from pydantic.fields import ModelField - from pydantic.schema import SkipField - +from pydantic import Field, StrictBool +from pydantic.fields import ModelField +from pydantic.schema import SkipField from typing_extensions import Annotated, TypedDict from vizro.charts._charts_utils import _DashboardReadyFigure diff --git a/vizro-core/src/vizro/static/css/layout.css b/vizro-core/src/vizro/static/css/layout.css index 7aedb29b2..32b7842ad 100644 --- a/vizro-core/src/vizro/static/css/layout.css +++ b/vizro-core/src/vizro/static/css/layout.css @@ -123,7 +123,7 @@ .icon-button { background-color: var(--surfaces-bg-02); - width: 100%; + width: 64px; height: 64px; display: flex; align-items: center; @@ -137,28 +137,32 @@ div.dashboard_container .tooltip-inner { div.dashboard_container .custom-tooltip { color: var(--text-primary); } +.icon-text { + font-size: var(--text-size-02); + letter-spacing: var(--letter-spacing-body-edit-01); + color: var(--text-secondary); + padding: 4px; +} + +.nav-icon { + filter: var(--fill-accordion-button); + width: 24px; + height: 24px; +} + +.nav-icon-text { + display: flex; + flex-direction: column; + align-items: center; + gap: 6px; + justify-content: center; +} -.icon-button.btn.btn-primary.active .material-symbols-outlined { - color: var(--text-active); +.icon-button.btn.btn-primary.active { + background-color: var(--state-overlays-selected); } + .loading-container { height: 100%; width: 100%; } - -.mantine-Tooltip-tooltip { - font-size: var(--text-size-01); - font-weight: var(--text-weight-light); - line-height: 16px; - letter-spacing: var(--letter-spacing-help-text); - padding: var(--spacing-01) var(--spacing-02); - color: var(--tooltip-text-primary); - background-color: var(--border-selected); - max-width: 180px; - overflow-wrap: break-word; - text-wrap: wrap; - filter: drop-shadow(0px 2px 2px #141721); - border-radius: 0; - box-shadow: var(--box-shadow-elevation-tooltip-hover); - white-space: pre-wrap; -} diff --git a/vizro-core/src/vizro/static/css/slider.css b/vizro-core/src/vizro/static/css/slider.css index 8d43bf480..31d171387 100644 --- a/vizro-core/src/vizro/static/css/slider.css +++ b/vizro-core/src/vizro/static/css/slider.css @@ -134,7 +134,3 @@ justify-content: space-between; width: 100%; } - -input.dash-input:invalid { - outline: none; -} diff --git a/vizro-core/src/vizro/static/css/variables.css b/vizro-core/src/vizro/static/css/variables.css index 09ad4b158..9da41f8fb 100644 --- a/vizro-core/src/vizro/static/css/variables.css +++ b/vizro-core/src/vizro/static/css/variables.css @@ -85,9 +85,6 @@ --state-overlays-selected-hover: var( --state-overlays-dark-mode-selected-hover ); - --tooltip-text-primary: rgba(20, 23, 33, 0.88); - --box-shadow-elevation-tooltip-hover: 0px 4px 8px 0px rgba(20, 23, 33, 0.38), - 0px 2px 4px -1px rgba(20, 23, 33, 0.88); } .vizro_light { @@ -146,7 +143,4 @@ --state-overlays-selected-hover: var( --state-overlays-light-mode-selected-hover ); - --tooltip-text-primary: rgba(255, 255, 255, 0.88); - --box-shadow-elevation-tooltip-hover: 0px 4px 8px 0px rgba(20, 23, 33, 0.12), - 0px 2px 4px -1px rgba(20, 23, 33, 0.08); } diff --git a/vizro-core/tests/integration/test_examples.py b/vizro-core/tests/integration/test_examples.py index 375979e6e..85885b373 100644 --- a/vizro-core/tests/integration/test_examples.py +++ b/vizro-core/tests/integration/test_examples.py @@ -1,6 +1,5 @@ # ruff: noqa: F403, F405 import os -import runpy from pathlib import Path import chromedriver_autoinstaller_fix @@ -26,14 +25,65 @@ def setup_integration_test_environment(monkeypatch_session): chromedriver_autoinstaller_fix.install() -@pytest.fixture(params=["default", "from_dict", "from_json", "from_yaml"]) -def dashboard(request, monkeypatch): - monkeypatch.chdir(Path(__file__).parents[2] / f"examples/{request.param}") - app = runpy.run_path("app.py") - return app["dashboard"] +@pytest.fixture +def default_dashboard(monkeypatch): + monkeypatch.chdir(Path(__file__).parents[2] / "examples/default") + monkeypatch.syspath_prepend(Path.cwd()) + from app import dashboard + return dashboard -def test_dashboard(dash_duo, dashboard): - app = Vizro(assets_folder=Path(__file__).parents[2] / "examples/assets").build(dashboard).dash + +@pytest.fixture +def dict_dashboard(monkeypatch): + monkeypatch.chdir(Path(__file__).parents[2] / "examples/from_dict") + monkeypatch.syspath_prepend(Path.cwd()) + from app import dashboard + + return dashboard + + +@pytest.fixture +def json_dashboard(monkeypatch): + monkeypatch.chdir(Path(__file__).parents[2] / "examples/from_json") + monkeypatch.syspath_prepend(Path.cwd()) + from app import dashboard + + return dashboard + + +@pytest.fixture +def yaml_dashboard(monkeypatch): + monkeypatch.chdir(Path(__file__).parents[2] / "examples/from_yaml") + monkeypatch.syspath_prepend(Path.cwd()) + from app import dashboard + + return dashboard + + +def test_default_dashboard(dash_duo, default_dashboard): + """Test if default example dashboard starts and has no errors in logs.""" + app = Vizro().build(default_dashboard).dash + dash_duo.start_server(app) + assert dash_duo.get_logs() == [] + + +def test_dict_dashboard(dash_duo, dict_dashboard): + """Test if dictionary example dashboard starts and has no errors in logs.""" + app = Vizro().build(dict_dashboard).dash + dash_duo.start_server(app) + assert dash_duo.get_logs() == [] + + +def test_json_dashboard(dash_duo, json_dashboard): + """Test if json example dashboard starts and has no errors in logs.""" + app = Vizro().build(json_dashboard).dash + dash_duo.start_server(app) + assert dash_duo.get_logs() == [] + + +def test_yaml_dashboard(dash_duo, yaml_dashboard): + """Test if yaml example dashboard starts and has no errors in logs.""" + app = Vizro().build(yaml_dashboard).dash dash_duo.start_server(app) assert dash_duo.get_logs() == [] diff --git a/vizro-core/tests/unit/vizro/models/_action/test_action.py b/vizro-core/tests/unit/vizro/models/_action/test_action.py index 1768a0d91..088f6b495 100644 --- a/vizro-core/tests/unit/vizro/models/_action/test_action.py +++ b/vizro-core/tests/unit/vizro/models/_action/test_action.py @@ -9,12 +9,7 @@ from dash import html from dash._callback_context import context_value from dash._utils import AttributeDict - -try: - from pydantic.v1 import ValidationError -except ImportError: # pragma: no cov - from pydantic import ValidationError - +from pydantic import ValidationError from vizro.actions import export_data from vizro.models._action._action import Action @@ -66,7 +61,6 @@ def custom_action_build_expected(): return html.Div( children=[], id="action_test_action_model_components_div", - hidden=True, ) diff --git a/vizro-core/tests/unit/vizro/models/_components/form/test_checklist.py b/vizro-core/tests/unit/vizro/models/_components/form/test_checklist.py index 528a614ab..56509ab10 100755 --- a/vizro-core/tests/unit/vizro/models/_components/form/test_checklist.py +++ b/vizro-core/tests/unit/vizro/models/_components/form/test_checklist.py @@ -4,11 +4,7 @@ import plotly import pytest from dash import dcc, html - -try: - from pydantic.v1 import ValidationError -except ImportError: # pragma: no cov - from pydantic import ValidationError +from pydantic import ValidationError from vizro.models._action._action import Action from vizro.models._components.form import Checklist diff --git a/vizro-core/tests/unit/vizro/models/_components/form/test_dropdown.py b/vizro-core/tests/unit/vizro/models/_components/form/test_dropdown.py index 12cb3301f..5b4a2f9b4 100755 --- a/vizro-core/tests/unit/vizro/models/_components/form/test_dropdown.py +++ b/vizro-core/tests/unit/vizro/models/_components/form/test_dropdown.py @@ -4,11 +4,7 @@ import plotly import pytest from dash import dcc, html - -try: - from pydantic.v1 import ValidationError -except ImportError: # pragma: no cov - from pydantic import ValidationError +from pydantic import ValidationError from vizro.models._action._action import Action from vizro.models._components.form import Dropdown diff --git a/vizro-core/tests/unit/vizro/models/_components/form/test_radioitems.py b/vizro-core/tests/unit/vizro/models/_components/form/test_radioitems.py index e27804723..b9998e90c 100755 --- a/vizro-core/tests/unit/vizro/models/_components/form/test_radioitems.py +++ b/vizro-core/tests/unit/vizro/models/_components/form/test_radioitems.py @@ -4,11 +4,7 @@ import plotly import pytest from dash import dcc, html - -try: - from pydantic.v1 import ValidationError -except ImportError: # pragma: no cov - from pydantic import ValidationError +from pydantic import ValidationError from vizro.models._action._action import Action from vizro.models._components.form import RadioItems diff --git a/vizro-core/tests/unit/vizro/models/_components/form/test_range_slider.py b/vizro-core/tests/unit/vizro/models/_components/form/test_range_slider.py index 0eaebfaff..8cb6a9ab6 100644 --- a/vizro-core/tests/unit/vizro/models/_components/form/test_range_slider.py +++ b/vizro-core/tests/unit/vizro/models/_components/form/test_range_slider.py @@ -4,11 +4,7 @@ import plotly import pytest from dash import dcc, html - -try: - from pydantic.v1 import ValidationError -except ImportError: # pragma: no cov - from pydantic import ValidationError +from pydantic import ValidationError import vizro.models as vm diff --git a/vizro-core/tests/unit/vizro/models/_components/form/test_slider.py b/vizro-core/tests/unit/vizro/models/_components/form/test_slider.py index d51f9cd66..ad8e466ff 100755 --- a/vizro-core/tests/unit/vizro/models/_components/form/test_slider.py +++ b/vizro-core/tests/unit/vizro/models/_components/form/test_slider.py @@ -4,11 +4,7 @@ import plotly import pytest from dash import dcc, html - -try: - from pydantic.v1 import ValidationError -except ImportError: # pragma: no cov - from pydantic import ValidationError +from pydantic import ValidationError import vizro.models as vm diff --git a/vizro-core/tests/unit/vizro/models/_components/test_card.py b/vizro-core/tests/unit/vizro/models/_components/test_card.py index 1d9b4821a..8c0d049b9 100755 --- a/vizro-core/tests/unit/vizro/models/_components/test_card.py +++ b/vizro-core/tests/unit/vizro/models/_components/test_card.py @@ -5,11 +5,7 @@ import plotly import pytest from dash import dcc, html - -try: - from pydantic.v1 import ValidationError -except ImportError: # pragma: no cov - from pydantic import ValidationError +from pydantic import ValidationError import vizro.models as vm diff --git a/vizro-core/tests/unit/vizro/models/_components/test_graph.py b/vizro-core/tests/unit/vizro/models/_components/test_graph.py index b41468b98..6f3e190f9 100644 --- a/vizro-core/tests/unit/vizro/models/_components/test_graph.py +++ b/vizro-core/tests/unit/vizro/models/_components/test_graph.py @@ -7,11 +7,7 @@ from dash import dcc from dash._callback_context import context_value from dash._utils import AttributeDict - -try: - from pydantic.v1 import ValidationError -except ImportError: # pragma: no cov - from pydantic import ValidationError +from pydantic import ValidationError import vizro.models as vm import vizro.plotly.express as px diff --git a/vizro-core/tests/unit/vizro/models/_components/test_table.py b/vizro-core/tests/unit/vizro/models/_components/test_table.py index 4ae7c2ce2..87f4bd1e7 100644 --- a/vizro-core/tests/unit/vizro/models/_components/test_table.py +++ b/vizro-core/tests/unit/vizro/models/_components/test_table.py @@ -4,11 +4,7 @@ import plotly import pytest from dash import dash_table, dcc, html - -try: - from pydantic.v1 import ValidationError -except ImportError: # pragma: no cov - from pydantic import ValidationError +from pydantic import ValidationError import vizro.models as vm import vizro.plotly.express as px diff --git a/vizro-core/tests/unit/vizro/models/_navigation/test_accordion.py b/vizro-core/tests/unit/vizro/models/_navigation/test_accordion.py index 41eb562b3..894275c73 100644 --- a/vizro-core/tests/unit/vizro/models/_navigation/test_accordion.py +++ b/vizro-core/tests/unit/vizro/models/_navigation/test_accordion.py @@ -5,11 +5,7 @@ import pytest from asserts import assert_component_equal from dash import html - -try: - from pydantic.v1 import ValidationError -except ImportError: # pragma: no cov - from pydantic import ValidationError +from pydantic import ValidationError import vizro.models as vm from vizro._constants import ACCORDION_DEFAULT_TITLE diff --git a/vizro-core/tests/unit/vizro/models/_navigation/test_nav_bar.py b/vizro-core/tests/unit/vizro/models/_navigation/test_nav_bar.py index 93fd01544..ff633a6a6 100644 --- a/vizro-core/tests/unit/vizro/models/_navigation/test_nav_bar.py +++ b/vizro-core/tests/unit/vizro/models/_navigation/test_nav_bar.py @@ -2,15 +2,10 @@ import re import dash_bootstrap_components as dbc -import dash_mantine_components as dmc import pytest from asserts import assert_component_equal from dash import html - -try: - from pydantic.v1 import ValidationError -except ImportError: # pragma: no cov - from pydantic import ValidationError +from pydantic import ValidationError import vizro.models as vm @@ -78,21 +73,11 @@ def test_items_with_with_pages_icons(self, pages_as_dict): class TestNavBarBuildMethod: """Tests NavBar model build method.""" - common_args = {"offset": 4, "withArrow": True, "position": "bottom-start"} - def test_nav_bar_active_pages_as_dict(self, pages_as_dict): nav_bar = vm.NavBar(pages=pages_as_dict) nav_bar.pre_build() built_nav_bar = nav_bar.build(active_page_id="Page 1") - expected_button = html.Div( - [ - dbc.Button( - children=[dmc.Tooltip(label="Group", children=[html.Span("filter_1")], **self.common_args)], - active=True, - href="/", - ) - ] - ) + expected_button = html.Div([dbc.Button(children=[html.Span(children="filter_1")], active=True, href="/")]) assert_component_equal(built_nav_bar["nav_bar_outer"], expected_button) assert_component_equal( built_nav_bar["nav_panel_outer"], html.Div(id="nav_panel_outer"), keys_to_strip={"children", "className"} @@ -105,16 +90,8 @@ def test_nav_bar_active_pages_as_list(self, pages_as_list): built_nav_bar = nav_bar.build(active_page_id="Page 1") expected_buttons = html.Div( [ - dbc.Button( - children=[dmc.Tooltip(label="Page 1", children=[html.Span("filter_1")], **self.common_args)], - active=True, - href="/", - ), - dbc.Button( - children=[dmc.Tooltip(label="Page 2", children=[html.Span("filter_2")], **self.common_args)], - active=False, - href="/page-2", - ), + dbc.Button(children=[html.Span(children="filter_1")], active=True, href="/"), + dbc.Button(children=[html.Span(children="filter_2")], active=False, href="/page-2"), ] ) assert_component_equal(built_nav_bar["nav_bar_outer"], expected_buttons) @@ -128,15 +105,7 @@ def test_nav_bar_not_active_pages_as_dict(self, pages_as_dict): nav_bar = vm.NavBar(pages=pages_as_dict) nav_bar.pre_build() built_nav_bar = nav_bar.build(active_page_id="Page 3") - expected_button = html.Div( - [ - dbc.Button( - children=[dmc.Tooltip(label="Group", children=[html.Span("filter_1")], **self.common_args)], - active=False, - href="/", - ) - ] - ) + expected_button = html.Div([dbc.Button(children=[html.Span(children="filter_1")], active=False, href="/")]) assert_component_equal(built_nav_bar["nav_bar_outer"], expected_button) assert_component_equal( built_nav_bar["nav_panel_outer"], html.Div(hidden=True, id="nav_panel_outer"), keys_to_strip={} @@ -148,16 +117,8 @@ def test_nav_bar_not_active_pages_as_list(self, pages_as_list): built_nav_bar = nav_bar.build(active_page_id="Page 3") expected_buttons = html.Div( [ - dbc.Button( - children=[dmc.Tooltip(label="Page 1", children=[html.Span("filter_1")], **self.common_args)], - active=False, - href="/", - ), - dbc.Button( - children=[dmc.Tooltip(label="Page 2", children=[html.Span("filter_2")], **self.common_args)], - active=False, - href="/page-2", - ), + dbc.Button(children=[html.Span(children="filter_1")], active=False, href="/"), + dbc.Button(children=[html.Span(children="filter_2")], active=False, href="/page-2"), ] ) assert_component_equal(built_nav_bar["nav_bar_outer"], expected_buttons) diff --git a/vizro-core/tests/unit/vizro/models/_navigation/test_nav_link.py b/vizro-core/tests/unit/vizro/models/_navigation/test_nav_item.py similarity index 84% rename from vizro-core/tests/unit/vizro/models/_navigation/test_nav_link.py rename to vizro-core/tests/unit/vizro/models/_navigation/test_nav_item.py index c02d55247..71710ed2a 100644 --- a/vizro-core/tests/unit/vizro/models/_navigation/test_nav_link.py +++ b/vizro-core/tests/unit/vizro/models/_navigation/test_nav_item.py @@ -2,15 +2,10 @@ import re import dash_bootstrap_components as dbc -import dash_mantine_components as dmc import pytest from asserts import assert_component_equal from dash import html - -try: - from pydantic.v1 import ValidationError -except ImportError: # pragma: no cov - from pydantic import ValidationError +from pydantic import ValidationError import vizro.models as vm @@ -73,18 +68,12 @@ def test_nav_link(self, pages_as_dict): class TestNavLinkBuildMethod: """Tests NavLink model build method.""" - common_args = {"offset": 4, "withArrow": True, "position": "bottom-start"} - def test_nav_link_active(self, pages, request): pages = request.getfixturevalue(pages) nav_link = vm.NavLink(id="nav_link", label="Label", icon="icon", pages=pages) nav_link.pre_build() built_nav_link = nav_link.build(active_page_id="Page 1") - expected_button = dbc.Button( - children=[dmc.Tooltip(label="Label", children=[html.Span("icon")], **self.common_args)], - active=True, - href="/", - ) + expected_button = dbc.Button(id="nav_link", children=[html.Span("icon")], active=True, href="/") assert_component_equal(built_nav_link["nav_link"], expected_button) assert all(isinstance(child, dbc.Accordion) for child in built_nav_link["nav_panel_outer"].children) @@ -93,10 +82,6 @@ def test_nav_link_not_active(self, pages, request): nav_link = vm.NavLink(id="nav_link", label="Label", icon="icon", pages=pages) nav_link.pre_build() built_nav_link = nav_link.build(active_page_id="Page 3") - expected_button = dbc.Button( - children=[dmc.Tooltip(label="Label", children=[html.Span("icon")], **self.common_args)], - active=False, - href="/", - ) + expected_button = dbc.Button(id="nav_link", children=[html.Span("icon")], active=False, href="/") assert_component_equal(built_nav_link["nav_link"], expected_button) assert "nav_panel_outer" not in built_nav_link diff --git a/vizro-core/tests/unit/vizro/models/_navigation/test_navigation.py b/vizro-core/tests/unit/vizro/models/_navigation/test_navigation.py index 895ae1061..73abd6fdc 100644 --- a/vizro-core/tests/unit/vizro/models/_navigation/test_navigation.py +++ b/vizro-core/tests/unit/vizro/models/_navigation/test_navigation.py @@ -5,11 +5,7 @@ import pytest from asserts import assert_component_equal from dash import html - -try: - from pydantic.v1 import ValidationError -except ImportError: # pragma: no cov - from pydantic import ValidationError +from pydantic import ValidationError import vizro.models as vm diff --git a/vizro-core/tests/unit/vizro/models/test_base.py b/vizro-core/tests/unit/vizro/models/test_base.py index ae5a09e43..84bafd561 100644 --- a/vizro-core/tests/unit/vizro/models/test_base.py +++ b/vizro-core/tests/unit/vizro/models/test_base.py @@ -1,11 +1,7 @@ from typing import List, Literal, Optional, Union import pytest - -try: - from pydantic.v1 import Field, ValidationError -except ImportError: # pragma: no cov - from pydantic import Field, ValidationError +from pydantic import Field, ValidationError from typing_extensions import Annotated import vizro.models as vm diff --git a/vizro-core/tests/unit/vizro/models/test_dashboard.py b/vizro-core/tests/unit/vizro/models/test_dashboard.py index 39f499528..2529a57cf 100644 --- a/vizro-core/tests/unit/vizro/models/test_dashboard.py +++ b/vizro-core/tests/unit/vizro/models/test_dashboard.py @@ -7,11 +7,7 @@ import plotly import pytest from dash import html - -try: - from pydantic.v1 import ValidationError -except ImportError: # pragma: no cov - from pydantic import ValidationError +from pydantic import ValidationError import vizro import vizro.models as vm @@ -23,7 +19,7 @@ def dashboard_container(): return dbc.Container( id="dashboard_container_outer", children=[ - html.Div(vizro.__version__, id="vizro_version", hidden=True), + html.Div(id=f"vizro_version_{vizro.__version__}"), ActionLoop._create_app_callbacks(), dash.page_container, ], diff --git a/vizro-core/tests/unit/vizro/models/test_layout.py b/vizro-core/tests/unit/vizro/models/test_layout.py index 9d78849f4..322cbf3e3 100755 --- a/vizro-core/tests/unit/vizro/models/test_layout.py +++ b/vizro-core/tests/unit/vizro/models/test_layout.py @@ -1,10 +1,6 @@ import numpy as np import pytest - -try: - from pydantic.v1 import ValidationError -except ImportError: # pragma: no cov - from pydantic import ValidationError +from pydantic import ValidationError import vizro.models as vm from vizro.models._layout import GAP_DEFAULT, MIN_DEFAULT, ColRowGridLines diff --git a/vizro-core/tests/unit/vizro/models/test_page.py b/vizro-core/tests/unit/vizro/models/test_page.py index 254c2f9f4..34229a4c9 100644 --- a/vizro-core/tests/unit/vizro/models/test_page.py +++ b/vizro-core/tests/unit/vizro/models/test_page.py @@ -2,11 +2,7 @@ import pandas as pd import pytest - -try: - from pydantic.v1 import ValidationError -except ImportError: # pragma: no cov - from pydantic import ValidationError +from pydantic import ValidationError import vizro.models as vm import vizro.plotly.express as px diff --git a/vizro-core/tests/unit/vizro/models/test_types.py b/vizro-core/tests/unit/vizro/models/test_types.py index 8b0b7242b..910c30b7b 100644 --- a/vizro-core/tests/unit/vizro/models/test_types.py +++ b/vizro-core/tests/unit/vizro/models/test_types.py @@ -3,11 +3,7 @@ import plotly.express as plotly_express import plotly.graph_objects as go import pytest - -try: - from pydantic.v1 import Field, ValidationError -except ImportError: # pragma: no cov - from pydantic import Field, ValidationError +from pydantic import Field, ValidationError from vizro.charts._charts_utils import _DashboardReadyFigure from vizro.models import VizroBaseModel