diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 0c50b2ec40..0000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,368 +0,0 @@ -version: 2.1 - -orbs: - browser-tools: circleci/browser-tools@1.4.8 - -executors: - docker-container: - parameters: - python_version: - description: "python version" - default: "3.12" - type: string - docker: - - image: cimg/python:<>-browsers - -commands: - test_core: - steps: - - checkout - - browser-tools/install-chrome - - browser-tools/install-chromedriver - - run: - name: Install dependencies - command: | - curl -LsSf https://astral.sh/uv/install.sh | sh - uv venv - source .venv/bin/activate - uv lock --check - uv sync --extra dev_core - - run: - name: List installed packages and python version - command: | - source .venv/bin/activate - uv pip list - python --version - - run: - name: Test core - command: | - source .venv/bin/activate - python -m pytest tests/test_core - no_output_timeout: 20m - - test_optional: - parameters: - pandas_version: - type: string - numpy_version: - type: string - steps: - - checkout - - browser-tools/install-chrome - - browser-tools/install-chromedriver - - run: - name: Install dependencies - command: | - curl -LsSf https://astral.sh/uv/install.sh | sh - uv venv - source .venv/bin/activate - uv sync --extra dev_optional - - - when: - condition: - not: - equal: - - <> - - "" - steps: - - run: - name: Install pandas - command: | - source .venv/bin/activate - uv pip install pandas==<> numpy==<> - - - run: - name: Test core - command: | - source .venv/bin/activate - python -m pytest tests/test_core - no_output_timeout: 20m - - run: - name: List installed packages and python version - command: | - source .venv/bin/activate - uv pip list - python --version - - run: - name: Test optional - command: | - source .venv/bin/activate - python -m pytest tests/test_optional - no_output_timeout: 40m - - run: - name: Test utils - command: | - source .venv/bin/activate - python -m pytest tests/test_plotly_utils/ - no_output_timeout: 20m - - run: - name: Test io - command: | - source .venv/bin/activate - python -m pytest tests/test_io - no_output_timeout: 20m - - run: - name: Test dependencies not imported - command: | - source .venv/bin/activate - python -m pytest -x test_init/test_dependencies_not_imported.py - - run: - name: Test lazy imports - command: | - source .venv/bin/activate - python -m pytest -x test_init/test_lazy_imports.py - - test_io_kaleido_v0: - steps: - - checkout - - browser-tools/install-chrome - - browser-tools/install-chromedriver - - run: - name: Install dependencies - command: | - curl -LsSf https://astral.sh/uv/install.sh | sh - uv venv - source .venv/bin/activate - uv sync --extra dev_optional - # Install Kaleido v0 instead of the v1 specified in requirements_optional.txt - uv pip uninstall kaleido - uv pip install kaleido==0.2.1 - - run: - name: List installed packages and python version - command: | - source .venv/bin/activate - uv pip list - python --version - - run: - name: Test plotly.io image output with Kaleido v0 - command: | - source .venv/bin/activate - python -m pytest tests/test_optional/test_kaleido - no_output_timeout: 20m - -jobs: - check-code-formatting: - docker: - - image: cimg/python:3.12 - - steps: - - checkout - - run: - name: Install ruff - command: | - uv venv - source .venv/bin/activate - uv sync --extra dev_core - - run: - name: Check handwritten code with ruff - command: | - source .venv/bin/activate - ruff format --check . - - test_core_py: - parameters: - python_version: - default: "3.12" - type: string - executor: - name: docker-container - python_version: <> - steps: - - test_core - - test_optional_py: - parameters: - python_version: - default: "3.12" - type: string - pandas_version: - default: "" - type: string - numpy_version: - default: "" - type: string - executor: - name: docker-container - python_version: <> - steps: - - test_optional: - pandas_version: <> - numpy_version: <> - - test_kaleido_v0: - parameters: - python_version: - default: "3.12" - type: string - executor: - name: docker-container - python_version: <> - steps: - - test_io_kaleido_v0 - - # Percy - python_311_percy: - docker: - - image: cimg/python:3.11-browsers - environment: - PERCY_ENABLED: True - PERCY_PROJECT: plotly/plotly.py - resource_class: large - - steps: - - checkout - - browser-tools/install-chrome - - browser-tools/install-chromedriver - - run: - name: Inject Percy Environment variables - command: | - echo 'export PERCY_TOKEN="$PERCY_PYTHON_TOKEN_V0"' >> $BASH_ENV - - run: - name: Install requirements - command: | - curl -LsSf https://astral.sh/uv/install.sh | sh - uv venv - source .venv/bin/activate - uv sync --extra dev_optional - - - run: - name: Build HTML figures (Pandas 2) - command: | - source .venv/bin/activate - python tests/percy/plotly-express.py - - run: - name: Build HTML figures (Pandas 1) and compare - command: | - source .venv/bin/activate - mkdir tests/percy/pandas2 - mv tests/percy/*.html tests/percy/pandas2/ - uv pip install pandas==1.5.3 numpy==1.26.4 - python tests/percy/plotly-express.py - python tests/percy/compare-pandas.py - rm -rf tests/percy/pandas2 - - run: - name: List installed packages and python version - command: | - source .venv/bin/activate - uv pip list - python --version - - run: - name: Run percy snapshots - command: | - npm i @percy/cli - npx percy snapshot -c tests/percy/snapshots.yml tests/percy/ - rm tests/percy/*.html - - plotlyjs_dev_build: - docker: - - image: cimg/python:3.12-node - environment: - LANG: en_US.UTF-8 - resource_class: large - - steps: - - checkout - - run: - name: Install dependencies - command: | - curl -LsSf https://astral.sh/uv/install.sh | sh - uv venv - source .venv/bin/activate - uv sync --extra dev_optional - - run: - name: Update plotly.js to dev - command: | - source .venv/bin/activate - python commands.py updateplotlyjsdev - - run: - name: Test core - command: | - source .venv/bin/activate - locale - pytest -k 'not nodev' tests/test_core - no_output_timeout: 20m - - run: - name: Build source distribution packages - command: | - source .venv/bin/activate - uv sync --extra dev_build - python -m build --sdist --wheel -o dist - when: always - - store_artifacts: - path: dist/ - - full_build: - docker: - - image: cimg/python:3.12-node - environment: - LANG: en_US.UTF-8 - resource_class: large - - steps: - - checkout - - run: - name: PyPI Build - command: | - curl -LsSf https://astral.sh/uv/install.sh | sh - uv venv - source .venv/bin/activate - uv sync --extra dev_build - cd js - npm ci - npm run build - cd .. - python -m build --sdist --wheel -o dist - cp -R dist output - git status - - - run: - name: Zip output - command: | - tar czf output.tgz output - - - store_artifacts: - path: output.tgz - -workflows: - code_formatting: - jobs: - - check-code-formatting - dev_build: - jobs: - - plotlyjs_dev_build - release_build: - jobs: - - full_build - build: - jobs: - - test_core_py: - matrix: - parameters: - python_version: - - "3.8" - - "3.9" - - "3.10" - - "3.11" - - "3.12" - - "3.13" - - test_optional_py: - matrix: - parameters: - python_version: - - "3.8" - - "3.9" - - "3.10" - - "3.11" - - "3.12" - - "3.13" - - test_optional_py: - name: "test_optional_py-3.9_pandas-1.2.4" - python_version: "3.9" - pandas_version: "1.2.4" - numpy_version: "1.26.4" - - test_kaleido_v0: - matrix: - parameters: - python_version: - - "3.12" - - python_311_percy diff --git a/.github/actions/setup-chrome-for-pytest/action.yml b/.github/actions/setup-chrome-for-pytest/action.yml new file mode 100644 index 0000000000..9112fd4a62 --- /dev/null +++ b/.github/actions/setup-chrome-for-pytest/action.yml @@ -0,0 +1,27 @@ +name: Set up Chrome for pytest +description: Install Chrome/Chromedriver, set BROWSER, and verify the setup +runs: + using: composite + steps: + - name: Set up Chrome + id: setup-chrome + uses: browser-actions/setup-chrome@v2.1.1 + with: + install-chromedriver: true + - name: Set BROWSER env var + shell: bash + run: | + echo "BROWSER=${{ steps.setup-chrome.outputs.chrome-path }}" >> $GITHUB_ENV + - name: Check Chrome setup + shell: bash + run: | + CHROME_PATH="${{ steps.setup-chrome.outputs.chrome-path }}" + CHROMEDRIVER_PATH="${{ steps.setup-chrome.outputs.chromedriver-path }}" + echo "Chrome path: $CHROME_PATH" + echo "Chrome version: $($CHROME_PATH --version)" + echo "Chromedriver path: $CHROMEDRIVER_PATH" + echo "Chromedriver version: $($CHROMEDRIVER_PATH --version)" + echo "chrome --version: $(chrome --version)" + echo "BROWSER = $BROWSER" + python -c "import webbrowser; webbrowser.register_standard_browsers(); print(webbrowser._tryorder)" + python -c "import webbrowser; webbrowser.get()" diff --git a/.github/workflows/build-package.yml b/.github/workflows/build-package.yml new file mode 100644 index 0000000000..d122f826a8 --- /dev/null +++ b/.github/workflows/build-package.yml @@ -0,0 +1,82 @@ +name: Build + +on: + push: + pull_request: + types: [opened, reopened] + +jobs: + plotlyjs-dev-build: + name: plotly.js dev build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.12" + - name: Set up Node + uses: actions/setup-node@v6 + with: + node-version: "22" + - name: Install dependencies + run: | + curl -LsSf https://astral.sh/uv/install.sh | sh + uv venv + source .venv/bin/activate + uv sync --extra dev_optional + - name: Update plotly.js to dev + run: | + source .venv/bin/activate + python commands.py updateplotlyjsdev + - name: Test core (excluding nodev) + run: | + source .venv/bin/activate + pytest -k 'not nodev' tests/test_core + - name: Build source distribution packages + run: | + source .venv/bin/activate + uv sync --extra dev_build + python -m build --sdist --wheel -o dist + - name: Upload dist artifacts + uses: actions/upload-artifact@v7 + with: + name: plotlyjs-dev-build-dist + path: dist/ + if-no-files-found: error + + full-build: + name: Full prod build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.12" + - name: Set up Node + uses: actions/setup-node@v6 + with: + node-version: "22" + - name: PyPI Build + run: | + curl -LsSf https://astral.sh/uv/install.sh | sh + uv venv + source .venv/bin/activate + uv sync --extra dev_build + cd js + npm ci + npm run build + cd .. + python -m build --sdist --wheel -o dist + cp -R dist output + git status + - name: Zip output + run: | + tar czf output.tgz output + - name: Upload output artifact + uses: actions/upload-artifact@v7 + with: + name: full-build-output + path: output.tgz + if-no-files-found: error diff --git a/.github/workflows/check-formatting.yml b/.github/workflows/check-formatting.yml new file mode 100644 index 0000000000..d55083c5ef --- /dev/null +++ b/.github/workflows/check-formatting.yml @@ -0,0 +1,27 @@ +name: Check Python code formatting + +on: + push: + pull_request: + types: [opened, reopened] + +jobs: + check-code-formatting: + name: Run ruff check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.12" + - name: Install dependencies + run: | + curl -LsSf https://astral.sh/uv/install.sh | sh + uv venv + source .venv/bin/activate + uv sync --extra dev_core + - name: Check handwritten code with ruff + run: | + source .venv/bin/activate + ruff format --check . diff --git a/.github/workflows/check-js-build.yml b/.github/workflows/check-js-build.yml index e1c645d608..f8748a67f5 100644 --- a/.github/workflows/check-js-build.yml +++ b/.github/workflows/check-js-build.yml @@ -1,13 +1,14 @@ on: push +name: Check JS build jobs: check-js-build: name: Check JS version number and build artifacts runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: "3.x" @@ -24,7 +25,7 @@ jobs: echo "✅ Version number $JSPROJECT_VERSION in $PKGJSON_PATH matches version number $PYPROJECT_VERSION in $PYPROJECT_PATH" fi - name: Install Node - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: '22' @@ -59,7 +60,7 @@ jobs: fi - name: Store the build artifacts from plotly/labextension - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 if: failure() with: name: labextension diff --git a/.github/workflows/run-percy.yml b/.github/workflows/run-percy.yml new file mode 100644 index 0000000000..e4d590f4a0 --- /dev/null +++ b/.github/workflows/run-percy.yml @@ -0,0 +1,45 @@ +name: Run Percy + +on: + push: + pull_request: + types: [opened, reopened] + workflow_dispatch: + +jobs: + python-311-percy: + name: Run Percy + runs-on: ubuntu-latest + env: + PERCY_ENABLED: "True" + PERCY_PROJECT: plotly/plotly.py + PERCY_TOKEN: ${{ secrets.PERCY_PYTHON_TOKEN_V0 }} + steps: + - uses: actions/checkout@v6 + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.11" + - name: Set up Node + uses: actions/setup-node@v6 + with: + node-version: "22" + - name: Set up Chrome + uses: browser-actions/setup-chrome@v2.1.1 + with: + install-chromedriver: true + - name: Install requirements + run: | + curl -LsSf https://astral.sh/uv/install.sh | sh + uv venv + source .venv/bin/activate + uv sync --extra dev_optional + - name: Build HTML figures (Pandas 2) + run: | + source .venv/bin/activate + python tests/percy/plotly-express.py + - name: Run percy snapshots + run: | + npm i @percy/cli + npx percy snapshot -c tests/percy/snapshots.yml tests/percy/ + rm tests/percy/*.html diff --git a/.github/workflows/run-pytest.yml b/.github/workflows/run-pytest.yml new file mode 100644 index 0000000000..dbd1cfb731 --- /dev/null +++ b/.github/workflows/run-pytest.yml @@ -0,0 +1,150 @@ +name: Test + +on: + push: + pull_request: + types: [opened, reopened] + +jobs: + test-core: + name: Core tests (Python ${{ matrix.python-version }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] + steps: + - uses: actions/checkout@v6 + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + curl -LsSf https://astral.sh/uv/install.sh | sh + uv venv + source .venv/bin/activate + uv lock --check + uv sync --extra dev_core + python --version + - name: Test core + run: | + source .venv/bin/activate + python -m pytest tests/test_core + + test-optional: + name: Optional tests (Python ${{ matrix.python-version }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] + steps: + - uses: actions/checkout@v6 + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: ${{ matrix.python-version }} + - name: Set up Chrome for Pytest + uses: ./.github/actions/setup-chrome-for-pytest + - name: Install dependencies + run: | + curl -LsSf https://astral.sh/uv/install.sh | sh + uv venv + source .venv/bin/activate + uv sync --extra dev_optional + python --version + - name: Test core + run: | + source .venv/bin/activate + python -m pytest tests/test_core + - name: Test optional + run: | + source .venv/bin/activate + python -m pytest tests/test_optional + - name: Test utils + run: | + source .venv/bin/activate + python -m pytest tests/test_plotly_utils/ + - name: Test io + run: | + source .venv/bin/activate + python -m pytest tests/test_io + - name: Test dependencies not imported + run: | + source .venv/bin/activate + python -m pytest -x test_init/test_dependencies_not_imported.py + - name: Test lazy imports + run: | + source .venv/bin/activate + python -m pytest -x test_init/test_lazy_imports.py + + test-optional-legacy-pandas: + name: Optional tests, Pandas 1 (Python 3.9, Pandas 1.2.4) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.9" + - name: Set up Chrome for browser tests + uses: ./.github/actions/setup-chrome-for-pytest + - name: Install dependencies + run: | + curl -LsSf https://astral.sh/uv/install.sh | sh + uv venv + source .venv/bin/activate + uv sync --extra dev_optional + uv pip install pandas==1.2.4 numpy==1.26.4 + - name: Test core + run: | + source .venv/bin/activate + python -m pytest tests/test_core + - name: Test optional + run: | + source .venv/bin/activate + python -m pytest tests/test_optional + - name: Test utils + run: | + source .venv/bin/activate + python -m pytest tests/test_plotly_utils/ + - name: Test io + run: | + source .venv/bin/activate + python -m pytest tests/test_io + - name: Test dependencies not imported + run: | + source .venv/bin/activate + python -m pytest -x test_init/test_dependencies_not_imported.py + - name: Test lazy imports + run: | + source .venv/bin/activate + python -m pytest -x test_init/test_lazy_imports.py + + test-kaleido-v0: + name: Optional tests (Kaleido only), Kaleido v0 (Python 3.12, Kaleido v0.2.1) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.12" + - name: Set up Chrome + uses: browser-actions/setup-chrome@v2.1.1 + with: + install-chromedriver: true + - name: Install dependencies + run: | + curl -LsSf https://astral.sh/uv/install.sh | sh + uv venv + source .venv/bin/activate + uv sync --extra dev_optional + uv pip uninstall kaleido + uv pip install kaleido==0.2.1 + python --version + - name: Test plotly.io image output with Kaleido v0 + run: | + source .venv/bin/activate + python -m pytest tests/test_optional/test_kaleido diff --git a/.github/workflows/test-release.yml b/.github/workflows/test-release.yml index 19c87193e1..1bceaa8bf0 100644 --- a/.github/workflows/test-release.yml +++ b/.github/workflows/test-release.yml @@ -1,24 +1,24 @@ -name: Publish Python 🐍 distribution 📦 to PyPI and TestPyPI +name: Test release on: workflow_dispatch jobs: build: - name: Build distribution 📦 + name: Full prod build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: persist-credentials: false - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: "3.x" - name: Install Node - uses: actions/setup-node@v2 + uses: actions/setup-node@v6 with: node-version: '22' @@ -41,13 +41,13 @@ jobs: - name: Build a binary wheel and a source tarball run: python3 -m build - name: Store the distribution packages - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: python-package-distributions path: dist/ publish-to-testpypi: - name: Publish Python 🐍 distribution 📦 to TestPyPI + name: Publish to TestPyPI needs: - build runs-on: ubuntu-latest @@ -61,7 +61,7 @@ jobs: steps: - name: Download all the dists - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v7 with: name: python-package-distributions path: dist/ diff --git a/pyproject.toml b/pyproject.toml index 3e11fd41f4..f09a8e8b08 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -83,6 +83,9 @@ dev = [ "plotly[dev_optional]" ] +[tool.uv] +exclude-newer = "72 hours" + [project.scripts] plotly_get_chrome = "plotly.io._kaleido:plotly_get_chrome" diff --git a/uv.lock b/uv.lock index a3823e2790..eba75516df 100644 --- a/uv.lock +++ b/uv.lock @@ -12,6 +12,10 @@ resolution-markers = [ "python_full_version <= '3.8' and sys_platform != 'win32'", ] +[options] +exclude-newer = "2026-04-04T19:20:31.457583Z" +exclude-newer-span = "PT72H" + [[package]] name = "annotated-types" version = "0.7.0"