tests: fix and enable doctests (#2546)

* fix doctest

* Update cibuildwheel/oci_container.py

Co-authored-by: Joe Rickerby <joerick@mac.com>

* Update cibuildwheel/oci_container.py

Co-authored-by: Joe Rickerby <joerick@mac.com>

* Update cibuildwheel/oci_container.py

Co-authored-by: Joe Rickerby <joerick@mac.com>

* Add xdoctest to CI

* Add doctests to run tests

* Replace test map with new native method

* Forgot key for arm64

* Allow doctests to be filtered on circleci

---------

Co-authored-by: Joe Rickerby <joerick@mac.com>
This commit is contained in:
Jon Crall
2025-08-12 09:06:12 -04:00
committed by GitHub
co-authored by Joe Rickerby
parent 8db3538534
commit 5952330610
7 changed files with 58 additions and 18 deletions
+17
View File
@@ -32,6 +32,23 @@ if __name__ == "__main__":
# move cwd to the project root
os.chdir(Path(__file__).resolve().parents[1])
# doc tests
doc_test_args = [sys.executable, "-m", "pytest", "cibuildwheel"]
print(
"\n\n================================== DOC TESTS ==================================",
flush=True,
)
result = subprocess.run(doc_test_args, check=False)
if result.returncode not in (0, 5):
# Allow case where no doctests are collected (returncode 5) because
# circleci sets an explicit "-k" filter that disables doctests. There
# isn't a pattern that will only select doctests. This can be removed
# and have check=True if the circleci PYTEST_ADDOPTS is removed.
raise subprocess.CalledProcessError(
result.returncode, result.args, output=result.stdout, stderr=result.stderr
)
# unit tests
unit_test_args = [sys.executable, "-m", "pytest", "unit_test"]
+31 -1
View File
@@ -36,6 +36,28 @@ class OCIPlatform(Enum):
RISCV64 = "linux/riscv64"
S390X = "linux/s390x"
@classmethod
def native(cls) -> "OCIPlatform":
"""Return the current OCI platform, or raise ValueError if unknown."""
arch = platform.machine().lower()
mapping = {
"i386": cls.i386,
"i686": cls.i386,
"x86_64": cls.AMD64,
"amd64": cls.AMD64,
"armv7l": cls.ARMV7,
"aarch64": cls.ARM64,
"arm64": cls.ARM64,
"ppc64le": cls.PPC64LE,
"riscv64": cls.RISCV64,
"s390x": cls.S390X,
}
try:
return mapping[arch]
except KeyError as ex:
msg = f"Unsupported platform architecture: {arch}"
raise OSError(msg) from ex
@dataclasses.dataclass(frozen=True)
class OCIContainerEngineConfig:
@@ -152,11 +174,19 @@ class OCIContainer:
back to cibuildwheel.
Example:
>>> # xdoctest: +REQUIRES(LINUX)
>>> from cibuildwheel.oci_container import * # NOQA
>>> from cibuildwheel.options import _get_pinned_container_images
>>> import pytest
>>> try:
... oci_platform = OCIPlatform.native()
... except OSError as ex:
... pytest.skip(str(ex))
>>> if oci_platform != OCIPlatform.AMD64:
... pytest.skip('only runs on amd64')
>>> image = _get_pinned_container_images()['x86_64']['manylinux2014']
>>> # Test the default container
>>> with OCIContainer(image=image) as self:
>>> with OCIContainer(image=image, oci_platform=oci_platform) as self:
... self.call(["echo", "hello world"])
... self.call(["cat", "/proc/1/cgroup"])
... print(self.get_environment())
+1
View File
@@ -391,6 +391,7 @@ class OptionsReader:
by the platform.
Example:
>>> # xdoctest: +SKIP
>>> options_reader = OptionsReader(config_file, platform='macos')
>>> options_reader.get('cool-color')
+2 -2
View File
@@ -20,8 +20,8 @@ def format_safe(template: str, **kwargs: str | os.PathLike[str]) -> str:
>>> format_safe('{a} {b[4]:3f}', a='123')
'123 {b[4]:3f}'
To avoid variable expansion, precede with a single backslash e.g.
>>> format_safe('\\{a} {b}', a='123')
To avoid variable expansion, precede with a single hash e.g.
>>> format_safe('#{a} {b}', a='123')
'{a} {b}'
"""
+1
View File
@@ -58,6 +58,7 @@ def tests(session: nox.Session) -> None:
session.run("pytest", *session.posargs)
else:
unit_test_args = ["--run-docker"] if sys.platform.startswith("linux") else []
session.run("pytest", "cibuildwheel") # run doctests
session.run("pytest", "unit_test", *unit_test_args)
session.run("pytest", "test", "-x", "--durations", "0", "--timeout=2400", "test")
+2 -1
View File
@@ -93,6 +93,7 @@ test = [
"setuptools",
"tomli_w",
"validate-pyproject",
"xdoctest",
]
dev = [
{include-group = "bin"},
@@ -103,7 +104,7 @@ dev = [
[tool.pytest.ini_options]
minversion = "6.0"
addopts = ["-ra", "--showlocals", "--strict-markers", "--strict-config"]
addopts = ["-ra", "--showlocals", "--strict-markers", "--strict-config", "--xdoctest", "--ignore-glob=*venv*"]
junit_family = "xunit2"
xfail_strict = true
filterwarnings = ["error"]
+4 -14
View File
@@ -1,6 +1,5 @@
import json
import os
import platform
import random
import shutil
import subprocess
@@ -29,16 +28,7 @@ from cibuildwheel.oci_container import (
# for these tests we use manylinux2014 images, because they're available on
# multi architectures and include python3.8
DEFAULT_IMAGE = "quay.io/pypa/manylinux2014:2025.03.08-1"
pm = platform.machine()
DEFAULT_OCI_PLATFORM = {
"AMD64": OCIPlatform.AMD64,
"x86_64": OCIPlatform.AMD64,
"ppc64le": OCIPlatform.PPC64LE,
"s390x": OCIPlatform.S390X,
"aarch64": OCIPlatform.ARM64,
"arm64": OCIPlatform.ARM64,
"ARM64": OCIPlatform.ARM64,
}[pm]
DEFAULT_OCI_PLATFORM = OCIPlatform.native()
PODMAN = OCIContainerEngineConfig(name="podman")
@@ -494,7 +484,7 @@ def test_parse_engine_config(config, name, create_args, capsys):
)
@pytest.mark.skipif(pm != "x86_64", reason="Only runs on x86_64")
@pytest.mark.skipif(DEFAULT_OCI_PLATFORM != OCIPlatform.AMD64, reason="Only runs on x86_64")
def test_enforce_32_bit(container_engine):
with OCIContainer(
engine=container_engine, image=DEFAULT_IMAGE, oci_platform=OCIPlatform.i386
@@ -551,7 +541,7 @@ def test_local_image(
) -> None:
if (
detect_ci_provider() == CIProvider.travis_ci
and pm != "x86_64"
and DEFAULT_OCI_PLATFORM != OCIPlatform.AMD64
and platform != DEFAULT_OCI_PLATFORM
):
pytest.skip("Skipping test because docker on this platform does not support QEMU")
@@ -581,7 +571,7 @@ def test_local_image(
def test_multiarch_image(container_engine, platform):
if (
detect_ci_provider() == CIProvider.travis_ci
and pm != "x86_64"
and DEFAULT_OCI_PLATFORM != OCIPlatform.AMD64
and platform != DEFAULT_OCI_PLATFORM
):
pytest.skip("Skipping test because docker on this platform does not support QEMU")