Skip to content

Deep union type-checking optimization. #1030

Deep union type-checking optimization.

Deep union type-checking optimization. #1030

Workflow file for this run

---
# --------------------( LICENSE )--------------------
# Copyright (c) 2014-2024 Beartype authors.
# See "LICENSE" for further details.
#
# --------------------( SYNOPSIS )--------------------
# GitHub-specific continuous integration (CI) configuration, enabling the usual
# GitHub Actions workflow for pure-Python packages exercised by "tox".
#
# --------------------( SEE ALSO )--------------------
# * https://hynek.me/articles/python-github-actions
# Well-authored blog post strongly inspiring this configuration.
# ....................{ TODO }....................
#FIXME: [CACHING] Add support for caching "pip" downloads across runs.
#Currently, unresolved issues in GitHub Actions prevents sane caching of "pip"
#downloads. Naturally, horrifying hacks circumventing these issues do exist but
#are presumably worse than these issues. See also this pertinent comment:
# https://github.com/actions/cache/issues/342#issuecomment-673371329
#FIXME: [CACHING] Huzzah! The "setup-python" action itself now supports
#out-of-the-box caching. Note that doing so will require a minor of
#configuration on our part -- but nothing *TOO* tremendous, hopefully. See:
# https://github.com/actions/setup-python#caching-packages-dependencies
# ....................{ METADATA }....................
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# WARNING: Changes to this name *MUST* be manually synchronized with:
# * The "|GitHub Actions badge|" image URL in our top-level "README.rst".
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# Non-human-readable (i.e., machine-readable) label associated with this
# GitHub Actions workflow.
name: test
# ....................{ TRIGGER }....................
# Confine testing to only...
#
# Note that "**" matches all (possibly deeply "/"-nested) branches. See also:
# * https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet
# GitHub-specific glob syntax for matching branches and tags below.
on:
# Pushes to the main branch. Pushes to other branches are assumed to be
# developer-specific and thus already tested locally by that developer.
push:
branches:
- main
# Pull requests against the main branch. Pull requests against other branches
# should, ideally, *NEVER* occur; if and when they do, we ignore them.
pull_request:
branches:
- main # '**'
# ....................{ VARIABLES }....................
# List of private environment variables specific to this configuration and
# globally set for *ALL* jobs declared below. To avoid conflict with
# third-party processes, prefix the name of each variable by "_".
env:
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# CAUTION: Optional in-flight test-time dependencies (e.g., NumPy, mypy) are
# intentionally listed in the "beartype.meta.LIBS_TESTTIME_OPTIONAL" global
# rather than below. "tox" isolates both the package being tested and its
# dependency tree to virtual environments. Listing in-flight dependencies
# here would install those dependencies outside those virtual environments,
# thus reducing to a pointless, expensive, and failure-prone noop.
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# Whitespace-delimited list of the names of all Python packages to be
# installed by "pip" below. Although this package has *NO* mandatory runtime
# dependencies, fully exercising all tests necessitates these pre-flight
# test-time dependencies. These include:
# * "tox", the only mandatory test-time dependency.
_PIP_PACKAGE_NAMES: |
tox
# ....................{ MAIN }....................
jobs:
# ...................{ TESTS }...................
# Job iteratively exercising our test suite against all Python interpreters
# supported by this package (and also measuring the coverage of that suite).
tests:
# ..................{ MATRIX }..................
strategy:
matrix:
# List of all platform-specific Docker images to test against,
# including:
# * The latest Long-Term Service (LTS) release of Ubuntu Linux, still
# the most popular Linux distro and thus a sane baseline.
# * The latest *whatever* release of Microsoft Windows. Although Linux
# and macOS are both POSIX-compliant and thus crudely comparable from
# the low-level CLI perspective, Windows is POSIX-noncompliant and
# thus heavily divergent from both macOS and Linux.
# * The latest *whatever* release of Apple macOS. We don't particularly
# need to exercise tests on macOS, given the platform's patent
# POSIX-compliant low-level similarities to Linux, but... what the
# heck. Why not? Since this is the lowest priority, we defer macOS
# testing until last.
platform: [ubuntu-latest, windows-latest, macos-latest]
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# WARNING: Changes to this section *MUST* be manually synchronized with:
# * The "envlist" setting of the "[tox]" subsection in "tox.ini".
# * The "include" setting below.
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# List of all "tox" environments (defined by the "envlist" setting of
# the "[tox]" subsection in "tox.ini") to be tested, which the
# ${TOXENV} environment variable declared below exposes to "tox".
tox-env:
- py38-coverage
- py39-coverage
- py310-coverage
- py311-coverage
- py312-coverage
#FIXME: Uncomment after we resolve tests currently broken under *ANY*
#PyPy version. All tests used to pass under PyPy 3.7 and 3.8, but were
#recently broken by work generalizing @beartype to decorate builtin
#method descriptors (e.g., @property, @classmethod, @staticmethod).
# - pypy37-coverage
# - pypy38-coverage
# - pypy39-coverage
# Map each "tox" environment name listed in the "tox-env" list above to
# the corresponding "python-version" string supported by the
# "actions/setup-python" GitHub Action run below.
#
# Note that:
# * Python version specifiers *MUST* be quoted: e.g.,
# # Do this.
# python-version: "3.10"
# # Do *NOT* do this.
# python-version: 3.10
# Why? Because YAML sensibly treats an unquoted literal satisfying
# floating-point syntax as a floating-point number and thus silently
# truncates *ALL* ignorable zeroes suffixing that number (e.g.,
# truncating 3.10 to 3.1). That then results in non-human-readable CI
# errors, as discussed upstream at:
# https://github.com/actions/setup-python/issues/160#issuecomment-724485470
# * Python pre-releases may be selected with a space-delimited range
# embedded in a single quoted version specifier. For example,
# selecting the Python 3.11 pre-release reduces to:
# python-version: "3.11.0-alpha - 3.11.0"
include:
- tox-env: py38-coverage
python-version: "3.8"
- tox-env: py39-coverage
python-version: "3.9"
- tox-env: py310-coverage
python-version: "3.10"
- tox-env: py311-coverage
python-version: "3.11"
- tox-env: py312-coverage
python-version: "3.12"
#- tox-env: pypy37-coverage
# python-version: "pypy-3.7"
#- tox-env: pypy38-coverage
# python-version: "pypy-3.8"
#FIXME: Uncomment after PyPy 3.9 goes live.
# - tox-env: pypy39-coverage
# python-version: "pypy-3.9"
# ..................{ SETTINGS }..................
# Arbitrary human-readable description.
name: "[${{ matrix.platform }}] Python ${{ matrix.python-version }} CI"
# Name of the current Docker image to run tests under.
runs-on: "${{ matrix.platform }}"
# Time in minutes to wait on the command pipeline run below to exit
# *BEFORE* sending a non-graceful termination request (i.e., "SIGTERM"
# under POSIX-compliant systems).
timeout-minutes: 10
# ..................{ VARIABLES }..................
# External shell environment variables exposed to commands run below.
env:
# Prevent "pip" from wasting precious continuous integration (CI) minutes
# deciding whether it should be upgrading. We're *NOT* upgrading you,
# "pip". Accept this and let us test faster.
PIP_NO_PIP_VERSION_CHECK: 1
# Map from the current item of the "tox-env" list defined above to the
# ${TOXENV} environment variable recognized by "tox".
TOXENV: "${{ matrix.tox-env }}"
# ..................{ PROCESS }..................
steps:
# ..................{ SETUP }..................
- name: 'Checking out repository...'
uses: 'actions/checkout@v4'
- name: "Installing Python ${{ matrix.python-version }}..."
uses: 'actions/setup-python@v5'
with:
python-version: "${{ matrix.python-version }}"
- name: 'Displaying Python metadata...'
run: |
python3 -VV
python3 -m site
# ..................{ INSTALL }..................
# Note that:
# * This command *MUST* be platform-agnostic by running under both:
# * POSIX-compliant platforms (e.g., Linux, macOS).
# * POSIX-noncompliant platforms (e.g., Windows).
# In particular, commands that assume a POSIX-compliant shell (e.g.,
# Bash) *MUST* be avoided.
# * Packaging dependencies (e.g., "pip") are upgraded *BEFORE* all
# remaining dependencies (e.g., "tox").
- name: 'Upgrading packager dependencies...'
run: |
python3 -m pip --quiet install --upgrade pip setuptools wheel
- name: 'Installing package dependencies...'
run: |
python3 -m pip --quiet install --upgrade ${{ env._PIP_PACKAGE_NAMES }}
# ..................{ TYPE-CHECK }..................
# Type-check this package *BEFORE* testing this package. Why? Because
# "tox" internally creates a copy of this package residing at a temporary
# "build/lib/{package_name}" subdirectory. When type-checking this package
# *AFTER* testing this package, the existence of that subdirectory
# confuses mypy into believing that multiple duplicate copies of this
# package exist, which induces mypy to emit false positives, which induces
# this entire job and thus run to fail. In short, mypy.
# Type-check this package with "pyright". See also:
# https://github.com/jakebailey/pyright-action
- name: 'Type-checking package with "pyright"...'
uses: 'jakebailey/pyright-action@v2'
with:
python-version: "${{ matrix.python-version }}"
#FIXME: Revisit @jpetrucciani's otherwise stellar GitHub Action
#"jpetrucciani/mypy-check" once the issue tracker there settles a bit.
#See also these open issue currently blocking our usage here:
# https://github.com/jpetrucciani/mypy-check/issues/31
# https://github.com/jpetrucciani/mypy-check/issues/30
# Type-check this package with "mypy".
- name: 'Type-checking package with "mypy:"...'
run: |
# Manually install "mypy" in the standard way.
python3 -m pip --quiet install mypy
# Log this "mypy" version for debuggability.
mypy --version
# Run this "mypy" instance against our main package.
mypy ./beartype/
# ..................{ TEST }..................
- name: 'Testing package with "tox"...'
# Run the subsequent script as a Bash script. Although POSIX-compliant
# platforms (e.g., Linux, macOS) sensibly default to Bash, Windows
# insanely defaults to a Windows-specific shell (e.g., PowerShell).
shell: bash
run: |
# If the current platform is macOS, export a "tox"-specific
# environment variable circumventing "pip" installation issues by
# instructing "tox" to reinstall already installed Python packages.
# By default, "tox" avoids doing so for efficiency. This is required
# to specifically circumvent installation of NumPy under macOS. As
# discussed at numpy/numpy#15947, macOS bundles a patently broken
# BLAS replacement called "Accelerate" causing NumPy to raise
# exceptions on importation resembling:
# RuntimeError: Polyfit sanity test emitted a warning, most
# likely due to using a buggy Accelerate backend. If you compiled
# yourself, more information is available at
# https://numpy.org/doc/stable/user/building.html#accelerated-blas-lapack-libraries
# Otherwise report this to the vendor that provided NumPy.
# RankWarning: Polyfit may be poorly conditioned
#
# The kludge leveraged here is the canonical solution. See also:
# https://github.com/numpy/numpy/issues/15947#issuecomment-745428684
#
# Ideally, we would instead isolate setting this environment variable
# in a prior step with sane GitHub Actions syntax: e.g.,
# if: ${{ matrix.platform }} == 'macos-latest'
# env:
# _TOX_PIP_INSTALL_OPTIONS: '--force-reinstall'
#
# Sadly, the "env:" map only locally exports the environment
# variables it declares to the current step. Thanks, GitHub Actions.
if [[ ${{ matrix.platform }} == 'macos-latest' ]]; then
export _TOX_PIP_INSTALL_OPTIONS='--force-reinstall'
echo "Massaging macOS dependencies with \"pip install ${_TOX_PIP_INSTALL_OPTIONS}\"..."
fi
# Dismantled, this is:
# * "--skip-missing-interpreters=false" disables the corresponding
# "skip_missing_interpreters = true" setting globally enabled by
# our top-level "tox.ini" configuration, forcing CI failures for
# unavailable Python environments. See also:
# https://github.com/tox-dev/tox/issues/903
python3 -m tox --skip-missing-interpreters=false
# ..................{ COVERAGE }..................
- name: 'Publishing test coverage to Codecov...'
uses: 'codecov/codecov-action@v4'
with:
name: "${{ matrix.platform }}-${{ matrix.python-version }}"