Recursively unpack Literal
values if using PEP 695 type aliases (#1…
#28
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: CI | |
on: | |
push: | |
branches: | |
- main | |
tags: | |
- '**' | |
pull_request: {} | |
env: | |
COLUMNS: 150 | |
UV_FROZEN: true | |
jobs: | |
lint: | |
runs-on: ubuntu-latest | |
name: Lint ${{ matrix.python-version }} | |
strategy: | |
fail-fast: false | |
matrix: | |
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13'] | |
steps: | |
- uses: actions/checkout@v4 | |
- uses: astral-sh/setup-uv@v4 | |
with: | |
enable-cache: true | |
python-version: ${{ matrix.python-version }} | |
- name: Install dependencies | |
run: uv sync --group linting --all-extras | |
- uses: pre-commit/[email protected] | |
with: | |
extra_args: --all-files --verbose | |
env: | |
SKIP: no-commit-to-branch | |
docs-build: | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
- uses: astral-sh/setup-uv@v4 | |
with: | |
enable-cache: true | |
python-version: '3.12' | |
- name: Install dependencies | |
# Unlike the docs build, we don't use mkdocs_material-insiders | |
# Because the secret for accessing the library is not accessible from forks, but we still want to run | |
# this job on public CI runs. | |
run: uv sync --group docs | |
- run: uv run python -c 'import docs.plugins.main' | |
# Adding local symlinks gets nice source locations like | |
# pydantic_core/core_schema.py | |
# instead of | |
# .venv/lib/python3.10/site-packages/pydantic_core/core_schema.py | |
- name: prepare shortcuts for extra modules | |
run: | | |
ln -s .venv/lib/python*/site-packages/pydantic_core pydantic_core | |
ln -s .venv/lib/python*/site-packages/pydantic_settings pydantic_settings | |
ln -s .venv/lib/python*/site-packages/pydantic_extra_types pydantic_extra_types | |
- run: uv run mkdocs build | |
test-memray: | |
name: Test memray | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
- uses: astral-sh/setup-uv@v4 | |
with: | |
enable-cache: true | |
python-version: '3.12' | |
- name: install deps | |
run: uv sync --group testing-extra | |
- name: Run tests | |
run: uv run pytest --ignore=tests/mypy/ --ignore=tests/test_docs.py --memray | |
test: | |
name: Test ${{ matrix.os }} / ${{ matrix.python-version }} | |
strategy: | |
fail-fast: false | |
matrix: | |
os: [ubuntu-latest, macos-13, macos-latest, windows-latest] | |
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13'] | |
include: | |
# no pydantic-core binaries for pypy on windows, so tests take absolute ages | |
# macos tests with pypy take ages (>10mins) since pypy is very slow | |
# so we only test pypy on ubuntu | |
- os: ubuntu-latest | |
python-version: 'pypy3.9' | |
- os: ubuntu-latest | |
python-version: 'pypy3.10' | |
exclude: | |
# Python 3.8 and 3.9 are not available on macOS 14 | |
- os: macos-13 | |
python-version: '3.10' | |
- os: macos-13 | |
python-version: '3.11' | |
- os: macos-13 | |
python-version: '3.12' | |
- os: macos-latest | |
python-version: '3.13' | |
- os: macos-latest | |
python-version: '3.8' | |
- os: macos-latest | |
python-version: '3.9' | |
env: | |
OS: ${{ matrix.os }} | |
DEPS: yes | |
UV_PYTHON_PREFERENCE: only-managed | |
runs-on: ${{ matrix.os }} | |
steps: | |
- uses: actions/checkout@v4 | |
- uses: astral-sh/setup-uv@v4 | |
with: | |
enable-cache: true | |
python-version: ${{ matrix.python-version }} | |
- name: Install dependencies | |
run: uv sync --extra timezone | |
- run: 'uv run python -c "import pydantic.version; print(pydantic.version.version_info())"' | |
- run: mkdir coverage | |
- name: Test without email-validator | |
# speed up by skipping this step on pypy | |
if: "!startsWith(matrix.python-version, 'pypy')" | |
run: make test | |
env: | |
COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}-without-deps | |
CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }}-without-deps | |
- name: Install extra dependencies | |
run: uv sync --group testing-extra --all-extras | |
- name: Test with all extra dependencies | |
run: make test | |
env: | |
COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}-with-deps | |
CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }}-with-deps | |
- name: Store coverage files | |
uses: actions/upload-artifact@v4 | |
with: | |
name: coverage-${{ matrix.os }}-${{ matrix.python-version }} | |
path: coverage | |
include-hidden-files: true | |
test-fastapi: | |
# If some tests start failing due to out-of-date schemas/validation errors/etc., | |
# update the `tests/test_fastapi.sh` script to exclude tests that have known-acceptable failures. | |
name: Test FastAPI | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
- name: set up python | |
uses: actions/setup-python@v5 | |
with: | |
python-version: '3.12' | |
- name: Run tests | |
run: make test-fastapi | |
test-plugin: | |
name: Test Pydantic plugin | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
- uses: astral-sh/setup-uv@v4 | |
with: | |
python-version: '3.12' | |
- name: Install dependencies | |
run: uv sync | |
- name: Install example plugin | |
run: uv pip install ./tests/plugin | |
- run: uv run pytest tests/plugin | |
env: | |
TEST_PLUGIN: 1 | |
test-mypy: | |
name: mypy ${{ matrix.mypy-version }} / ${{ matrix.python-version }} | |
runs-on: ubuntu-latest | |
strategy: | |
fail-fast: false | |
matrix: | |
# test the latest version on all supported Python versions and the rest on 3.12 | |
mypy-version: ['1.10.1', '1.11.2'] | |
python-version: ['3.12'] | |
include: | |
- mypy-version: '1.12.0' | |
python-version: '3.8' | |
- mypy-version: '1.12.0' | |
python-version: '3.9' | |
- mypy-version: '1.12.0' | |
python-version: '3.10' | |
- mypy-version: '1.12.0' | |
python-version: '3.11' | |
- mypy-version: '1.12.0' | |
python-version: '3.12' | |
- mypy-version: '1.12.0' | |
python-version: '3.13' | |
steps: | |
- uses: actions/checkout@v4 | |
- uses: astral-sh/setup-uv@v4 | |
with: | |
enable-cache: true | |
python-version: ${{ matrix.python-version }} | |
- name: Install dependencies | |
run: uv sync --group typechecking --all-extras | |
- name: Install mypy | |
if: steps.cache.outputs.cache-hit != 'true' | |
run: uv pip install 'mypy==${{ matrix.mypy-version }}' | |
- run: mkdir coverage | |
- name: Run mypy tests | |
run: uv run coverage run -m pytest tests/mypy --test-mypy | |
env: | |
COVERAGE_FILE: coverage/.coverage.linux-py${{ matrix.python-version }}-mypy${{ matrix.mypy-version }} | |
CONTEXT: linux-py${{ matrix.python-version }}-mypy${{ matrix.mypy-version }} | |
- name: Store coverage files | |
uses: actions/upload-artifact@v4 | |
with: | |
name: coverage-${{ matrix.python-version }}-mypy${{ matrix.mypy-version }} | |
path: coverage | |
include-hidden-files: true | |
test-typechecking-integration: | |
name: Typechecking integration tests | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
- uses: astral-sh/setup-uv@v3 | |
with: | |
enable-cache: true | |
python-version: '3.12' | |
- name: Install dependencies | |
run: uv sync --group typechecking | |
- name: Run typechecking integration tests (Pyright) | |
run: make test-typechecking-pyright | |
- name: Run typechecking integration tests (Mypy) | |
run: make test-typechecking-mypy | |
coverage-combine: | |
needs: [test, test-mypy] | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
- uses: actions/setup-python@v5 | |
with: | |
python-version: '3.12' | |
- name: Get coverage files | |
uses: actions/download-artifact@v4 | |
with: | |
merge-multiple: true | |
pattern: coverage-* | |
path: coverage | |
- run: pip install coverage[toml] | |
- run: ls -la coverage | |
- run: coverage combine coverage | |
- run: coverage report | |
- run: coverage html --show-contexts --title "pydantic coverage for ${{ github.sha }}" | |
- name: Store coverage data | |
uses: actions/upload-artifact@v4 | |
with: | |
name: coverage-data | |
path: .coverage | |
include-hidden-files: true | |
- name: Store coverage HTML | |
uses: actions/upload-artifact@v4 | |
with: | |
name: coverage-html | |
path: htmlcov | |
coverage-pr-comment: | |
needs: coverage-combine | |
runs-on: ubuntu-latest | |
if: github.event_name == 'pull_request' | |
permissions: | |
pull-requests: write | |
contents: write | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Download coverage data | |
uses: actions/download-artifact@v4 | |
with: | |
name: coverage-data | |
- name: Generate coverage comment | |
id: coverage-comment | |
uses: py-cov-action/python-coverage-comment-action@v3 | |
with: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
- name: Store coverage comment | |
uses: actions/upload-artifact@v4 | |
if: steps.coverage-comment.outputs.COMMENT_FILE_WRITTEN == 'true' | |
with: | |
name: python-coverage-comment-action | |
path: python-coverage-comment-action.txt | |
test-typing-extensions: | |
name: Test typing-extensions (`main` branch) on 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@v4 | |
- uses: astral-sh/setup-uv@v4 | |
with: | |
enable-cache: true | |
python-version: ${{ matrix.python-version }} | |
- name: Install dependencies | |
run: uv sync | |
- name: Install typing-extensions | |
run: uv pip install 'typing-extensions @ git+https://github.com/python/typing_extensions.git' | |
- name: Run tests | |
run: make test | |
# https://github.com/marketplace/actions/alls-green | |
check: # This job does nothing and is only used for the branch protection | |
if: always() | |
outputs: | |
result: ${{ steps.all-green.outputs.result }} | |
needs: | |
- lint | |
- docs-build | |
- test | |
- test-memray | |
- test-mypy | |
- test-fastapi | |
- test-plugin | |
runs-on: ubuntu-latest | |
steps: | |
- name: Decide whether the needed jobs succeeded or failed | |
uses: re-actors/alls-green@release/v1 | |
id: all-green | |
with: | |
jobs: ${{ toJSON(needs) }} | |
release: | |
needs: [check] | |
if: needs.check.outputs.result == 'success' && startsWith(github.ref, 'refs/tags/') | |
runs-on: ubuntu-latest | |
environment: release | |
permissions: | |
id-token: write | |
outputs: | |
pydantic-version: ${{ steps.check-tag.outputs.VERSION }} | |
steps: | |
- uses: actions/checkout@v4 | |
- uses: actions/setup-python@v5 | |
with: | |
python-version: '3.12' | |
- name: Install 'build' library | |
run: pip install -U build | |
- name: Check version | |
id: check-tag | |
uses: samuelcolvin/[email protected] | |
with: | |
version_file_path: pydantic/version.py | |
- name: Build library | |
run: python -m build | |
- name: Upload package to PyPI | |
uses: pypa/gh-action-pypi-publish@release/v1 | |
send-tweet: | |
name: Send tweet | |
needs: [release] | |
if: needs.release.result == 'success' | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/setup-python@v5 | |
with: | |
python-version: '3.12' | |
- name: Install dependencies | |
run: pip install tweepy==4.14.0 | |
- name: Send tweet | |
shell: python | |
run: | | |
import os | |
import tweepy | |
client = tweepy.Client( | |
access_token=os.getenv("TWITTER_ACCESS_TOKEN"), | |
access_token_secret=os.getenv("TWITTER_ACCESS_TOKEN_SECRET"), | |
consumer_key=os.getenv("TWITTER_CONSUMER_KEY"), | |
consumer_secret=os.getenv("TWITTER_CONSUMER_SECRET"), | |
) | |
version = os.getenv("VERSION").strip('"') | |
if "b" in version: | |
official_version = version[:version.index("b")] | |
tweet = os.getenv("BETA_TWEET").format(version=version, official_version=official_version) | |
else: | |
tweet = os.getenv("TWEET").format(version=version) | |
client.create_tweet(text=tweet) | |
env: | |
VERSION: ${{ needs.release.outputs.pydantic-version }} | |
TWEET: | | |
Pydantic version {version} is out! 🎉 | |
https://github.com/pydantic/pydantic/releases/tag/v{version} | |
BETA_TWEET: | | |
Pydantic beta version {version} is out! 🚀 | |
Please try v{version} in the next week before we release v{official_version}, | |
and let us know if you encounter any issues! | |
https://github.com/pydantic/pydantic/releases/tag/v{version} | |
TWITTER_CONSUMER_KEY: ${{ secrets.TWITTER_CONSUMER_KEY }} | |
TWITTER_CONSUMER_SECRET: ${{ secrets.TWITTER_CONSUMER_SECRET }} | |
TWITTER_ACCESS_TOKEN: ${{ secrets.TWITTER_ACCESS_TOKEN }} | |
TWITTER_ACCESS_TOKEN_SECRET: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }} |