Merge pull request #1175 from mayeut/python-3.7

chore: drop python 3.6 for cibuildwheel driver
This commit is contained in:
Joe Rickerby
2022-07-29 16:13:56 +01:00
committed by GitHub
80 changed files with 323 additions and 232 deletions
+5 -5
View File
@@ -1,7 +1,7 @@
version: 2
jobs:
osx-python3.6:
osx-python3.9:
macos:
xcode: 12.5.1
environment:
@@ -17,9 +17,9 @@ jobs:
command: venv/bin/python ./bin/run_tests.py
no_output_timeout: 30m
linux-python3.6:
linux-python3.9:
docker:
- image: circleci/python:3.6
- image: circleci/python:3.9
environment:
PYTHON: python3
# Temporarily restrict the tests that are run on CircleCI to prevent
@@ -41,5 +41,5 @@ workflows:
version: 2
all-tests:
jobs:
- osx-python3.6
- linux-python3.6
- osx-python3.9
- linux-python3.9
+6 -14
View File
@@ -17,13 +17,8 @@ repos:
rev: v2.37.1
hooks:
- id: pyupgrade
name: PyUpgrade 3.6+
args: ["--py36-plus"]
exclude: ^bin/
- id: pyupgrade
name: PyUpgrade 3.7+ on bin
exclude: ^(cibuildwheel|unit_test|test)/
args: ["--py37-plus"]
exclude: ^cibuildwheel/resources/.*py$
# Autoremoves unused imports
- repo: https://github.com/hadialqattan/pycln
@@ -37,6 +32,8 @@ repos:
rev: 5.10.1
hooks:
- id: isort
args: ["-a", "from __future__ import annotations"]
exclude: ^cibuildwheel/resources/.*py$
- repo: https://github.com/psf/black
rev: 22.6.0
@@ -52,9 +49,9 @@ repos:
rev: v0.961
hooks:
- id: mypy
name: mypy 3.6 on cibuildwheel/
exclude: ^(bin|cibuildwheel/resources|docs)/.*py$
args: ["--python-version=3.6"]
name: mypy 3.7 on cibuildwheel/
exclude: ^cibuildwheel/resources/.*py$
args: ["--python-version=3.7"]
additional_dependencies: &mypy-dependencies
- nox
- packaging>=21.0
@@ -70,11 +67,6 @@ repos:
- types-requests
- bracex
- dataclasses
- id: mypy
name: mypy 3.7+ on bin/
files: ^((bin|docs)/.*py)$
args: ["--python-version=3.7"]
additional_dependencies: *mypy-dependencies
- id: mypy
name: mypy 3.10
args: ["--python-version=3.10"]
+11 -11
View File
@@ -8,21 +8,21 @@ branches:
jobs:
include:
- name: Linux | x86_64 + i686 | Python 3.6
python: 3.6
- name: Linux | x86_64 + i686 | Python 3.7
python: 3.7
services: docker
env: PYTHON=python
- name: Linux | arm64 | Python 3.6
python: 3.6
- name: Linux | arm64 | Python 3.7
python: 3.7
services: docker
arch: arm64-graviton2
group: edge
virt: vm
env: PYTHON=python
- name: Linux | ppc64le | Python 3.6
python: 3.6
- name: Linux | ppc64le | Python 3.7
python: 3.7
services: docker
arch: ppc64le
allow_failure: True
@@ -32,18 +32,18 @@ jobs:
# c.f. https://travis-ci.community/t/running-out-of-disk-space-quota-when-using-docker-on-ppc64le/11634
- PYTEST_ADDOPTS='-k "not test_manylinuxXXXX_only"'
- name: Windows | x86_64 | Python 3.6
- name: Windows | x86_64 | Python 3.7
os: windows
language: shell
before_install:
- choco upgrade python3 -y --version 3.6.8 --limit-output
- choco upgrade python3 -y --version 3.7.9 --limit-output
# Update root certificates to fix SSL error; see http://www.chawn.com/RootCerts.htm
- powershell "md C:\temp\certs; CertUtil -generateSSTFromWU C:\temp\certs\RootStore.sst; Get-ChildItem -Path C:\\temp\certs\Rootstore.sst | Import-Certificate -CertStoreLocation Cert:\\LocalMachine\\Root\\ | out-null"
env:
- PYTHON=C:\\Python36\\python
- PYTHON=C:\\Python37\\python
- name: Linux | s390x | Python 3.6
python: 3.6
- name: Linux | s390x | Python 3.7
python: 3.7
services: docker
arch: s390x
env: PYTHON=python
+6 -6
View File
@@ -1,11 +1,11 @@
This is a summary of the Python versions and platforms covered by the different CI platforms:
| | 3.6 | 3.7 | 3.8 |
|----------|------------------------------|-----------------------------|------------------|
| Linux | Travis CI / CircleCI | AppVeyor¹ / GitHub Actions | Azure Pipelines |
| macOS | CircleCI | AppVeyor¹ / GitHub Actions | Azure Pipelines |
| Windows | Travis CI / Azure Pipelines | AppVeyor¹ / GitHub Actions | Azure Pipelines |
| | 3.7 | 3.8 | 3.9 | 3.10 |
|----------|-----------------------|---------------------------|----------|----------------|
| Linux | AppVeyor¹ / Travis CI | Azure Pipelines / GitLab | CircleCI | GitHub Actions |
| macOS | AppVeyor¹ / Travis CI | Azure Pipelines | CircleCI | GitHub Actions |
| Windows | AppVeyor¹ / Travis CI | Azure Pipelines | | GitHub Actions |
> ¹ AppVeyor only runs the "basic" test to reduce load.
Non-x86 architectures are covered on Travis CI using Python 3.6.
Non-x86 architectures are covered on Travis CI using Python 3.7.
-11
View File
@@ -20,17 +20,6 @@ jobs:
python -m pip install -e ".[dev]" pytest-azurepipelines
python ./bin/run_tests.py
- job: windows_36
pool: {vmImage: 'windows-2019'}
timeoutInMinutes: 180
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '3.6'
- bash: |
python -m pip install -e ".[dev]" pytest-azurepipelines
python ./bin/run_tests.py
- job: windows_38
pool: {vmImage: 'windows-2019'}
timeoutInMinutes: 180
+2
View File
@@ -1,5 +1,7 @@
#!/usr/bin/env python3
from __future__ import annotations
import argparse
import os
import subprocess
+2 -1
View File
@@ -1,5 +1,6 @@
#!/usr/bin/env python3
# This file supports 3.6+
from __future__ import annotations
import os
import shutil
+2
View File
@@ -1,5 +1,7 @@
#!/usr/bin/env python3
from __future__ import annotations
import re
import sys
from pathlib import Path
+2
View File
@@ -1 +1,3 @@
from __future__ import annotations
__version__ = "2.8.1"
+11 -10
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import argparse
import os
import shutil
@@ -7,7 +9,6 @@ import tempfile
import textwrap
from pathlib import Path
from tempfile import mkdtemp
from typing import List, Set, Union
import cibuildwheel
import cibuildwheel.linux
@@ -257,7 +258,7 @@ def build_in_directory(args: CommandLineArguments) -> None:
log.warning(f"Can't delete temporary folder '{str(tmp_path)}'")
def print_preamble(platform: str, options: Options, identifiers: List[str]) -> None:
def print_preamble(platform: str, options: Options, identifiers: list[str]) -> None:
print(
textwrap.dedent(
"""
@@ -287,13 +288,13 @@ def print_preamble(platform: str, options: Options, identifiers: List[str]) -> N
def get_build_identifiers(
platform: PlatformName, build_selector: BuildSelector, architectures: Set[Architecture]
) -> List[str]:
python_configurations: Union[
List[cibuildwheel.linux.PythonConfiguration],
List[cibuildwheel.windows.PythonConfiguration],
List[cibuildwheel.macos.PythonConfiguration],
]
platform: PlatformName, build_selector: BuildSelector, architectures: set[Architecture]
) -> list[str]:
python_configurations: (
list[cibuildwheel.linux.PythonConfiguration]
| list[cibuildwheel.windows.PythonConfiguration]
| list[cibuildwheel.macos.PythonConfiguration]
)
if platform == "linux":
python_configurations = cibuildwheel.linux.get_python_configurations(
@@ -313,7 +314,7 @@ def get_build_identifiers(
return [config.identifier for config in python_configurations]
def detect_warnings(*, options: Options, identifiers: List[str]) -> List[str]:
def detect_warnings(*, options: Options, identifiers: list[str]) -> list[str]:
warnings = []
# warn about deprecated {python} and {pip}
+8 -7
View File
@@ -1,8 +1,9 @@
from __future__ import annotations
import functools
import platform as platform_module
import re
from enum import Enum
from typing import Set
from .typing import Final, Literal, PlatformName, assert_never
@@ -32,11 +33,11 @@ class Architecture(Enum):
ARM64 = "ARM64"
# Allow this to be sorted
def __lt__(self, other: "Architecture") -> bool:
def __lt__(self, other: Architecture) -> bool:
return self.value < other.value
@staticmethod
def parse_config(config: str, platform: PlatformName) -> "Set[Architecture]":
def parse_config(config: str, platform: PlatformName) -> set[Architecture]:
result = set()
for arch_str in re.split(r"[\s,]+", config):
if arch_str == "auto":
@@ -54,7 +55,7 @@ class Architecture(Enum):
return result
@staticmethod
def auto_archs(platform: PlatformName) -> "Set[Architecture]":
def auto_archs(platform: PlatformName) -> set[Architecture]:
native_architecture = Architecture(platform_module.machine())
result = {native_architecture}
@@ -72,7 +73,7 @@ class Architecture(Enum):
return result
@staticmethod
def all_archs(platform: PlatformName) -> "Set[Architecture]":
def all_archs(platform: PlatformName) -> set[Architecture]:
all_archs_map = {
"linux": {
Architecture.x86_64,
@@ -87,7 +88,7 @@ class Architecture(Enum):
return all_archs_map[platform]
@staticmethod
def bitness_archs(platform: PlatformName, bitness: Literal["64", "32"]) -> "Set[Architecture]":
def bitness_archs(platform: PlatformName, bitness: Literal["64", "32"]) -> set[Architecture]:
archs_32 = {Architecture.i686, Architecture.x86}
auto_archs = Architecture.auto_archs(platform)
@@ -101,7 +102,7 @@ class Architecture(Enum):
def allowed_architectures_check(
platform: PlatformName,
architectures: Set[Architecture],
architectures: set[Architecture],
) -> None:
allowed_architectures = Architecture.all_archs(platform)
+8 -8
View File
@@ -1,6 +1,8 @@
from __future__ import annotations
import subprocess
from dataclasses import dataclass
from typing import Callable, Dict, List, Optional, Sequence
from typing import Callable, Dict, List, Sequence
import bashlex
@@ -8,21 +10,19 @@ import bashlex
EnvironmentExecutor = Callable[[List[str], Dict[str, str]], str]
def local_environment_executor(command: List[str], env: Dict[str, str]) -> str:
return subprocess.run(
command, env=env, universal_newlines=True, stdout=subprocess.PIPE, check=True
).stdout
def local_environment_executor(command: list[str], env: dict[str, str]) -> str:
return subprocess.run(command, env=env, text=True, stdout=subprocess.PIPE, check=True).stdout
@dataclass(frozen=True)
class NodeExecutionContext:
environment: Dict[str, str]
environment: dict[str, str]
input: str
executor: EnvironmentExecutor
def evaluate(
value: str, environment: Dict[str, str], executor: Optional[EnvironmentExecutor] = None
value: str, environment: dict[str, str], executor: EnvironmentExecutor | None = None
) -> str:
if not value:
# empty string evaluates to empty string
@@ -103,7 +103,7 @@ def evaluate_nodes_as_compound_command(
def evaluate_nodes_as_simple_command(
nodes: List[bashlex.ast.node], context: NodeExecutionContext
nodes: list[bashlex.ast.node], context: NodeExecutionContext
) -> str:
command = [evaluate_node(part, context=context) for part in nodes]
return context.executor(command, context.environment)
+11 -9
View File
@@ -1,5 +1,7 @@
from __future__ import annotations
import dataclasses
from typing import Any, Dict, List, Mapping, Optional, Sequence
from typing import Any, Mapping, Sequence
import bashlex
@@ -12,7 +14,7 @@ class EnvironmentParseError(Exception):
pass
def split_env_items(env_string: str) -> List[str]:
def split_env_items(env_string: str) -> list[str]:
"""Splits space-separated variable assignments into a list of individual assignments.
>>> split_env_items('VAR=abc')
@@ -47,8 +49,8 @@ class EnvironmentAssignment(Protocol):
def evaluated_value(
self,
*,
environment: Dict[str, str],
executor: Optional[bashlex_eval.EnvironmentExecutor] = None,
environment: dict[str, str],
executor: bashlex_eval.EnvironmentExecutor | None = None,
) -> str:
"""Returns the value of this assignment, as evaluated in the environment"""
@@ -84,8 +86,8 @@ class EnvironmentAssignmentBash:
def evaluated_value(
self,
environment: Dict[str, str],
executor: Optional[bashlex_eval.EnvironmentExecutor] = None,
environment: dict[str, str],
executor: bashlex_eval.EnvironmentExecutor | None = None,
) -> str:
return bashlex_eval.evaluate(self.value, environment=environment, executor=executor)
@@ -100,7 +102,7 @@ class EnvironmentAssignmentBash:
@dataclasses.dataclass
class ParsedEnvironment:
assignments: List[EnvironmentAssignment]
assignments: list[EnvironmentAssignment]
def __init__(self, assignments: Sequence[EnvironmentAssignment]) -> None:
self.assignments = list(assignments)
@@ -108,8 +110,8 @@ class ParsedEnvironment:
def as_dictionary(
self,
prev_environment: Mapping[str, str],
executor: Optional[bashlex_eval.EnvironmentExecutor] = None,
) -> Dict[str, str]:
executor: bashlex_eval.EnvironmentExecutor | None = None,
) -> dict[str, str]:
environment = dict(**prev_environment)
for assignment in self.assignments:
+3 -2
View File
@@ -2,8 +2,9 @@
These are utilities for the `/bin` scripts, not for the `cibuildwheel` program.
"""
from __future__ import annotations
from io import StringIO
from typing import Dict, List
from .typing import Protocol
@@ -15,7 +16,7 @@ class Printable(Protocol):
...
def dump_python_configurations(inp: Dict[str, Dict[str, List[Dict[str, Printable]]]]) -> str:
def dump_python_configurations(inp: dict[str, dict[str, list[dict[str, Printable]]]]) -> str:
output = StringIO()
for header, values in inp.items():
output.write(f"[{header}]\n")
+8 -6
View File
@@ -1,5 +1,7 @@
from __future__ import annotations
from threading import RLock
from typing import Any, Callable, Generic, Optional, Type, TypeVar, overload
from typing import Any, Callable, Generic, TypeVar, overload
__all__ = ["cached_property"]
@@ -11,11 +13,11 @@ _T = TypeVar("_T")
class cached_property(Generic[_T]):
def __init__(self, func: Callable[[Any], _T]):
self.func = func
self.attrname: Optional[str] = None
self.attrname: str | None = None
self.__doc__ = func.__doc__
self.lock = RLock()
def __set_name__(self, owner: Type[Any], name: str) -> None:
def __set_name__(self, owner: type[Any], name: str) -> None:
if self.attrname is None:
self.attrname = name
elif name != self.attrname:
@@ -25,14 +27,14 @@ class cached_property(Generic[_T]):
)
@overload
def __get__(self, instance: None, owner: Optional[Type[Any]] = ...) -> "cached_property[_T]":
def __get__(self, instance: None, owner: type[Any] | None = ...) -> cached_property[_T]:
...
@overload
def __get__(self, instance: object, owner: Optional[Type[Any]] = ...) -> _T:
def __get__(self, instance: object, owner: type[Any] | None = ...) -> _T:
...
def __get__(self, instance: Optional[object], owner: Optional[Type[Any]] = None) -> Any:
def __get__(self, instance: object | None, owner: type[Any] | None = None) -> Any:
if instance is None:
return self
if self.attrname is None:
+11 -9
View File
@@ -1,9 +1,11 @@
from __future__ import annotations
import subprocess
import sys
import textwrap
from dataclasses import dataclass
from pathlib import Path, PurePath, PurePosixPath
from typing import Iterator, List, Set, Tuple
from typing import Iterator, Tuple
from .architecture import Architecture
from .logger import log
@@ -35,15 +37,15 @@ class PythonConfiguration:
@dataclass(frozen=True)
class BuildStep:
platform_configs: List[PythonConfiguration]
platform_configs: list[PythonConfiguration]
platform_tag: str
container_image: str
def get_python_configurations(
build_selector: BuildSelector,
architectures: Set[Architecture],
) -> List[PythonConfiguration]:
architectures: set[Architecture],
) -> list[PythonConfiguration]:
full_python_configs = read_python_configs("linux")
@@ -79,7 +81,7 @@ def container_image_for_python_configuration(config: PythonConfiguration, option
def get_build_steps(
options: Options, python_configurations: List[PythonConfiguration]
options: Options, python_configurations: list[PythonConfiguration]
) -> Iterator[BuildStep]:
"""
Groups PythonConfigurations into BuildSteps. Each BuildStep represents a
@@ -110,7 +112,7 @@ def get_build_steps(
def build_in_container(
*,
options: Options,
platform_configs: List[PythonConfiguration],
platform_configs: list[PythonConfiguration],
container: OCIContainer,
container_project_path: PurePath,
container_package_dir: PurePath,
@@ -140,13 +142,13 @@ def build_in_container(
)
container.call(["sh", "-c", before_all_prepared], env=env)
built_wheels: List[PurePosixPath] = []
built_wheels: list[PurePosixPath] = []
for config in platform_configs:
log.build_start(config.identifier)
build_options = options.build_options(config.identifier)
dependency_constraint_flags: List[PathOrStr] = []
dependency_constraint_flags: list[PathOrStr] = []
if build_options.dependency_constraints:
constraints_file = build_options.dependency_constraints.get_for_python_version(
@@ -395,7 +397,7 @@ def build(options: Options, tmp_path: Path) -> None: # pylint: disable=unused-a
sys.exit(1)
def _matches_prepared_command(error_cmd: List[str], command_template: str) -> bool:
def _matches_prepared_command(error_cmd: list[str], command_template: str) -> bool:
if len(error_cmd) < 3 or error_cmd[0:2] != ["sh", "-c"]:
return False
command_prefix = command_template.split("{", maxsplit=1)[0].strip()
+11 -9
View File
@@ -1,9 +1,11 @@
from __future__ import annotations
import codecs
import os
import re
import sys
import time
from typing import IO, AnyStr, Optional, Union
from typing import IO, AnyStr
from cibuildwheel.typing import Final
from cibuildwheel.util import CIProvider, detect_ci_provider
@@ -39,10 +41,10 @@ class Logger:
fold_mode: str
colors_enabled: bool
unicode_enabled: bool
active_build_identifier: Optional[str] = None
build_start_time: Optional[float] = None
step_start_time: Optional[float] = None
active_fold_group_name: Optional[str] = None
active_build_identifier: str | None = None
build_start_time: float | None = None
step_start_time: float | None = None
active_fold_group_name: str | None = None
def __init__(self) -> None:
if sys.platform == "win32" and hasattr(sys.stdout, "reconfigure"):
@@ -120,7 +122,7 @@ class Logger:
self.step_start_time = None
def step_end_with_error(self, error: Union[BaseException, str]) -> None:
def step_end_with_error(self, error: BaseException | str) -> None:
self.step_end(success=False)
self.error(error)
@@ -131,7 +133,7 @@ class Logger:
c = self.colors
print(f"{c.yellow}Warning{c.end}: {message}\n", file=sys.stderr)
def error(self, error: Union[BaseException, str]) -> None:
def error(self, error: BaseException | str) -> None:
if self.fold_mode == "github":
print(f"::error::{error}\n", file=sys.stderr)
else:
@@ -174,11 +176,11 @@ class Logger:
return identifier.lower()[:20]
@property
def colors(self) -> "Colors":
def colors(self) -> Colors:
return Colors(enabled=self.colors_enabled)
@property
def symbols(self) -> "Symbols":
def symbols(self) -> Symbols:
return Symbols(unicode=self.unicode_enabled)
+10 -8
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import functools
import os
import platform
@@ -7,7 +9,7 @@ import subprocess
import sys
from dataclasses import dataclass
from pathlib import Path
from typing import Dict, List, Sequence, Set, Tuple, cast
from typing import Sequence, Tuple, cast
from filelock import FileLock
@@ -37,7 +39,7 @@ from .util import (
)
def get_macos_version() -> Tuple[int, int]:
def get_macos_version() -> tuple[int, int]:
"""
Returns the macOS major/minor version, as a tuple, e.g. (10, 15) or (11, 0)
@@ -51,7 +53,7 @@ def get_macos_version() -> Tuple[int, int]:
return cast(Tuple[int, int], version)
def get_macos_sdks() -> List[str]:
def get_macos_sdks() -> list[str]:
output = call("xcodebuild", "-showsdks", capture_stdout=True)
return [m.group(1) for m in re.finditer(r"-sdk (macosx\S+)", output)]
@@ -64,8 +66,8 @@ class PythonConfiguration:
def get_python_configurations(
build_selector: BuildSelector, architectures: Set[Architecture]
) -> List[PythonConfiguration]:
build_selector: BuildSelector, architectures: set[Architecture]
) -> list[PythonConfiguration]:
full_python_configs = read_python_configs("macos")
@@ -134,7 +136,7 @@ def setup_python(
dependency_constraint_flags: Sequence[PathOrStr],
environment: ParsedEnvironment,
build_frontend: BuildFrontend,
) -> Dict[str, str]:
) -> dict[str, str]:
tmp.mkdir()
implementation_id = python_configuration.identifier.split("-")[0]
log.step(f"Installing Python {implementation_id}...")
@@ -295,7 +297,7 @@ def build(options: Options, tmp_path: Path) -> None:
)
shell(before_all_prepared, env=env)
built_wheels: List[Path] = []
built_wheels: list[Path] = []
for config in python_configurations:
build_options = options.build_options(config.identifier)
@@ -418,7 +420,7 @@ def build(options: Options, tmp_path: Path) -> None:
if build_options.test_command and build_options.test_selector(config.identifier):
machine_arch = platform.machine()
testing_archs: List[Literal["x86_64", "arm64"]]
testing_archs: list[Literal["x86_64", "arm64"]]
if config_is_arm64:
testing_archs = ["arm64"]
+14 -12
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import io
import json
import os
@@ -9,7 +11,7 @@ import sys
import uuid
from pathlib import Path, PurePath, PurePosixPath
from types import TracebackType
from typing import IO, Dict, List, Optional, Sequence, Type, cast
from typing import IO, Dict, Sequence, cast
from cibuildwheel.util import CIProvider, detect_ci_provider
@@ -52,7 +54,7 @@ class OCIContainer:
*,
image: str,
simulate_32_bit: bool = False,
cwd: Optional[PathOrStr] = None,
cwd: PathOrStr | None = None,
engine: ContainerEngine = "docker",
):
if not image:
@@ -61,10 +63,10 @@ class OCIContainer:
self.image = image
self.simulate_32_bit = simulate_32_bit
self.cwd = cwd
self.name: Optional[str] = None
self.name: str | None = None
self.engine = engine
def __enter__(self) -> "OCIContainer":
def __enter__(self) -> OCIContainer:
self.name = f"cibuildwheel-{uuid.uuid4()}"
@@ -122,9 +124,9 @@ class OCIContainer:
def __exit__(
self,
exc_type: Optional[Type[BaseException]],
exc_val: Optional[BaseException],
exc_tb: Optional[TracebackType],
exc_type: type[BaseException] | None,
exc_val: BaseException | None,
exc_tb: TracebackType | None,
) -> None:
self.bash_stdin.write(b"exit 0\n")
@@ -217,7 +219,7 @@ class OCIContainer:
else:
raise KeyError(self.engine)
def glob(self, path: PurePosixPath, pattern: str) -> List[PurePosixPath]:
def glob(self, path: PurePosixPath, pattern: str) -> list[PurePosixPath]:
glob_pattern = path.joinpath(pattern)
path_strings = json.loads(
@@ -236,9 +238,9 @@ class OCIContainer:
def call(
self,
args: Sequence[PathOrStr],
env: Optional[Dict[str, str]] = None,
env: dict[str, str] | None = None,
capture_output: bool = False,
cwd: Optional[PathOrStr] = None,
cwd: PathOrStr | None = None,
) -> str:
if cwd is None:
@@ -314,7 +316,7 @@ class OCIContainer:
return output
def get_environment(self) -> Dict[str, str]:
def get_environment(self) -> dict[str, str]:
env = json.loads(
self.call(
[
@@ -327,7 +329,7 @@ class OCIContainer:
)
return cast(Dict[str, str], env)
def environment_executor(self, command: List[str], environment: Dict[str, str]) -> str:
def environment_executor(self, command: list[str], environment: dict[str, str]) -> str:
# used as an EnvironmentExecutor to evaluate commands and capture output
return self.call(command, env=environment, capture_output=True)
+36 -45
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import functools
import os
import sys
@@ -6,18 +8,7 @@ from configparser import ConfigParser
from contextlib import contextmanager
from dataclasses import asdict, dataclass
from pathlib import Path
from typing import (
Any,
Dict,
Generator,
List,
Mapping,
Optional,
Set,
Tuple,
Union,
cast,
)
from typing import Any, Dict, Generator, List, Mapping, Union, cast
if sys.version_info >= (3, 11):
import tomllib
@@ -50,7 +41,7 @@ from .util import (
@dataclass
class CommandLineArguments:
platform: Literal["auto", "linux", "macos", "windows"]
archs: Optional[str]
archs: str | None
output_dir: Path
config_file: str
package_dir: Path
@@ -65,7 +56,7 @@ class GlobalOptions:
output_dir: Path
build_selector: BuildSelector
test_selector: TestSelector
architectures: Set[Architecture]
architectures: set[Architecture]
container_engine: ContainerEngine
@@ -74,14 +65,14 @@ class BuildOptions:
globals: GlobalOptions
environment: ParsedEnvironment
before_all: str
before_build: Optional[str]
before_build: str | None
repair_command: str
manylinux_images: Optional[Dict[str, str]]
musllinux_images: Optional[Dict[str, str]]
dependency_constraints: Optional[DependencyConstraints]
test_command: Optional[str]
before_test: Optional[str]
test_requires: List[str]
manylinux_images: dict[str, str] | None
musllinux_images: dict[str, str] | None
dependency_constraints: DependencyConstraints | None
test_command: str | None
before_test: str | None
test_requires: list[str]
test_extras: str
build_verbosity: int
build_frontend: BuildFrontend
@@ -103,7 +94,7 @@ class BuildOptions:
return self.globals.test_selector
@property
def architectures(self) -> Set[Architecture]:
def architectures(self) -> set[Architecture]:
return self.globals.architectures
@@ -113,7 +104,7 @@ Setting = Union[Dict[str, str], List[str], str, int]
@dataclass(frozen=True)
class Override:
select_pattern: str
options: Dict[str, Setting]
options: dict[str, Setting]
MANYLINUX_OPTIONS = {f"manylinux-{build_platform}-image" for build_platform in MANYLINUX_ARCHS}
@@ -134,7 +125,7 @@ class ConfigOptionError(KeyError):
pass
def _dig_first(*pairs: Tuple[Mapping[str, Setting], str], ignore_empty: bool = False) -> Setting:
def _dig_first(*pairs: tuple[Mapping[str, Setting], str], ignore_empty: bool = False) -> Setting:
"""
Return the first dict item that matches from pairs of dicts and keys.
Will throw a KeyError if missing.
@@ -176,10 +167,10 @@ class OptionsReader:
def __init__(
self,
config_file_path: Optional[Path] = None,
config_file_path: Path | None = None,
*,
platform: PlatformName,
disallow: Optional[Dict[str, Set[str]]] = None,
disallow: dict[str, set[str]] | None = None,
) -> None:
self.platform = platform
self.disallow = disallow or {}
@@ -189,8 +180,8 @@ class OptionsReader:
self.default_options, self.default_platform_options = self._load_file(defaults_path)
# Load the project config file
config_options: Dict[str, Any] = {}
config_platform_options: Dict[str, Any] = {}
config_options: dict[str, Any] = {}
config_platform_options: dict[str, Any] = {}
if config_file_path is not None:
config_options, config_platform_options = self._load_file(config_file_path)
@@ -209,8 +200,8 @@ class OptionsReader:
self.config_options = config_options
self.config_platform_options = config_platform_options
self.overrides: List[Override] = []
self.current_identifier: Optional[str] = None
self.overrides: list[Override] = []
self.current_identifier: str | None = None
config_overrides = self.config_options.get("overrides")
@@ -251,7 +242,7 @@ class OptionsReader:
return name in allowed_option_names
def _load_file(self, filename: Path) -> Tuple[Dict[str, Any], Dict[str, Any]]:
def _load_file(self, filename: Path) -> tuple[dict[str, Any], dict[str, Any]]:
"""
Load a toml file, returns global and platform as separate dicts.
"""
@@ -264,7 +255,7 @@ class OptionsReader:
return global_options, platform_options
@property
def active_config_overrides(self) -> List[Override]:
def active_config_overrides(self) -> list[Override]:
if self.current_identifier is None:
return []
return [
@@ -272,7 +263,7 @@ class OptionsReader:
]
@contextmanager
def identifier(self, identifier: Optional[str]) -> Generator[None, None, None]:
def identifier(self, identifier: str | None) -> Generator[None, None, None]:
self.current_identifier = identifier
try:
yield
@@ -284,8 +275,8 @@ class OptionsReader:
name: str,
*,
env_plat: bool = True,
sep: Optional[str] = None,
table: Optional[TableFmt] = None,
sep: str | None = None,
table: TableFmt | None = None,
ignore_empty: bool = False,
) -> str:
"""
@@ -349,7 +340,7 @@ class Options:
)
@property
def config_file_path(self) -> Optional[Path]:
def config_file_path(self) -> Path | None:
args = self.command_line_arguments
if args.config_file:
@@ -363,7 +354,7 @@ class Options:
return None
@cached_property
def package_requires_python_str(self) -> Optional[str]:
def package_requires_python_str(self) -> str | None:
args = self.command_line_arguments
return get_requires_python_str(Path(args.package_dir))
@@ -383,7 +374,7 @@ class Options:
# This is not supported in tool.cibuildwheel, as it comes from a standard location.
# Passing this in as an environment variable will override pyproject.toml, setup.cfg, or setup.py
requires_python_str: Optional[str] = (
requires_python_str: str | None = (
os.environ.get("CIBW_PROJECT_REQUIRES_PYTHON") or self.package_requires_python_str
)
requires_python = None if requires_python_str is None else SpecifierSet(requires_python_str)
@@ -417,7 +408,7 @@ class Options:
container_engine=container_engine,
)
def build_options(self, identifier: Optional[str]) -> BuildOptions:
def build_options(self, identifier: str | None) -> BuildOptions:
"""
Compute BuildOptions for a single run configuration.
"""
@@ -469,9 +460,9 @@ class Options:
pass
if dependency_versions == "pinned":
dependency_constraints: Optional[
dependency_constraints: None | (
DependencyConstraints
] = DependencyConstraints.with_defaults()
) = DependencyConstraints.with_defaults()
elif dependency_versions == "latest":
dependency_constraints = None
else:
@@ -486,8 +477,8 @@ class Options:
except ValueError:
build_verbosity = 0
manylinux_images: Dict[str, str] = {}
musllinux_images: Dict[str, str] = {}
manylinux_images: dict[str, str] = {}
musllinux_images: dict[str, str] = {}
if self.platform == "linux":
all_pinned_container_images = _get_pinned_container_images()
@@ -539,7 +530,7 @@ class Options:
build_frontend=build_frontend,
)
def check_for_invalid_configuration(self, identifiers: List[str]) -> None:
def check_for_invalid_configuration(self, identifiers: list[str]) -> None:
if self.platform in ["macos", "windows"]:
before_all_values = {self.build_options(i).before_all for i in identifiers}
@@ -562,7 +553,7 @@ class Options:
deprecated_selectors("CIBW_SKIP", build_selector.skip_config)
deprecated_selectors("CIBW_TEST_SKIP", test_selector.skip_config)
def summary(self, identifiers: List[str]) -> str:
def summary(self, identifiers: list[str]) -> str:
lines = [
f"{option_name}: {option_value!r}"
for option_name, option_value in sorted(asdict(self.globals).items())
+6 -4
View File
@@ -1,8 +1,10 @@
from __future__ import annotations
import ast
import sys
from configparser import ConfigParser
from pathlib import Path
from typing import Any, Optional
from typing import Any
if sys.version_info >= (3, 11):
import tomllib
@@ -24,7 +26,7 @@ else:
class Analyzer(ast.NodeVisitor):
def __init__(self) -> None:
self.requires_python: Optional[str] = None
self.requires_python: str | None = None
def visit(self, node: ast.AST) -> None:
for inner_node in ast.walk(node):
@@ -43,7 +45,7 @@ class Analyzer(ast.NodeVisitor):
self.requires_python = get_constant(node.value)
def setup_py_python_requires(content: str) -> Optional[str]:
def setup_py_python_requires(content: str) -> str | None:
try:
tree = ast.parse(content)
analyzer = Analyzer()
@@ -53,7 +55,7 @@ def setup_py_python_requires(content: str) -> Optional[str]:
return None
def get_requires_python_str(package_dir: Path) -> Optional[str]:
def get_requires_python_str(package_dir: Path) -> str | None:
"""Return the python requires string from the most canonical source available, or None"""
# Read in from pyproject.toml:project.requires-python
+3 -1
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import os
import subprocess
import sys
@@ -36,7 +38,7 @@ else:
PlatformName = Literal["linux", "macos", "windows"]
PLATFORMS: Final[Set[PlatformName]] = {"linux", "macos", "windows"}
PLATFORMS: Final[set[PlatformName]] = {"linux", "macos", "windows"}
def assert_never(value: NoReturn) -> NoReturn:
+22 -26
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import contextlib
import fnmatch
import itertools
@@ -18,15 +20,11 @@ from time import sleep
from typing import (
Any,
ClassVar,
Dict,
Generator,
Iterable,
List,
Optional,
Sequence,
TextIO,
TypeVar,
Union,
cast,
overload,
)
@@ -98,8 +96,8 @@ IS_WIN: Final = sys.platform.startswith("win")
@overload
def call(
*args: PathOrStr,
env: Optional[Dict[str, str]] = None,
cwd: Optional[PathOrStr] = None,
env: dict[str, str] | None = None,
cwd: PathOrStr | None = None,
capture_stdout: Literal[False] = ...,
) -> None:
...
@@ -108,8 +106,8 @@ def call(
@overload
def call(
*args: PathOrStr,
env: Optional[Dict[str, str]] = None,
cwd: Optional[PathOrStr] = None,
env: dict[str, str] | None = None,
cwd: PathOrStr | None = None,
capture_stdout: Literal[True],
) -> str:
...
@@ -117,10 +115,10 @@ def call(
def call(
*args: PathOrStr,
env: Optional[Dict[str, str]] = None,
cwd: Optional[PathOrStr] = None,
env: dict[str, str] | None = None,
cwd: PathOrStr | None = None,
capture_stdout: bool = False,
) -> Optional[str]:
) -> str | None:
"""
Run subprocess.run, but print the commands first. Takes the commands as
*args. Uses shell=True on Windows due to a bug. Also converts to
@@ -130,7 +128,7 @@ def call(
args_ = [str(arg) for arg in args]
# print the command executing for the logs
print("+ " + " ".join(shlex.quote(a) for a in args_))
kwargs: Dict[str, Any] = {}
kwargs: dict[str, Any] = {}
if capture_stdout:
kwargs["universal_newlines"] = True
kwargs["stdout"] = subprocess.PIPE
@@ -140,9 +138,7 @@ def call(
return cast(str, result.stdout)
def shell(
*commands: str, env: Optional[Dict[str, str]] = None, cwd: Optional[PathOrStr] = None
) -> None:
def shell(*commands: str, env: dict[str, str] | None = None, cwd: PathOrStr | None = None) -> None:
command = " ".join(commands)
print(f"+ {command}")
subprocess.run(command, env=env, cwd=cwd, shell=True, check=True)
@@ -200,7 +196,7 @@ def prepare_command(command: str, **kwargs: PathOrStr) -> str:
return format_safe(command, python="python", pip="pip", **kwargs)
def get_build_verbosity_extra_flags(level: int) -> List[str]:
def get_build_verbosity_extra_flags(level: int) -> list[str]:
if level > 0:
return ["-" + level * "v"]
elif level < 0:
@@ -209,11 +205,11 @@ def get_build_verbosity_extra_flags(level: int) -> List[str]:
return []
def read_python_configs(config: PlatformName) -> List[Dict[str, str]]:
def read_python_configs(config: PlatformName) -> list[dict[str, str]]:
input_file = resources_dir / "build-platforms.toml"
with input_file.open("rb") as f:
loaded_file = tomllib.load(f)
results: List[Dict[str, str]] = list(loaded_file[config]["python_configurations"])
results: list[dict[str, str]] = list(loaded_file[config]["python_configurations"])
return results
@@ -243,7 +239,7 @@ class BuildSelector:
build_config: str
skip_config: str
requires_python: Optional[SpecifierSet] = None
requires_python: SpecifierSet | None = None
# a pattern that skips prerelease versions, when include_prereleases is False.
PRERELEASE_SKIP: ClassVar[str] = "cp311-*"
@@ -328,7 +324,7 @@ class DependencyConstraints:
self.base_file_path = base_file_path.resolve()
@staticmethod
def with_defaults() -> "DependencyConstraints":
def with_defaults() -> DependencyConstraints:
return DependencyConstraints(base_file_path=resources_dir / "constraints.txt")
def get_for_python_version(self, version: str) -> Path:
@@ -400,7 +396,7 @@ class CIProvider(Enum):
other = "other"
def detect_ci_provider() -> Optional[CIProvider]:
def detect_ci_provider() -> CIProvider | None:
if "TRAVIS" in os.environ:
return CIProvider.travis_ci
elif "APPVEYOR" in os.environ:
@@ -473,7 +469,7 @@ def print_new_wheels(msg: str, output_dir: Path) -> Generator[None, None, None]:
)
def get_pip_version(env: Dict[str, str]) -> str:
def get_pip_version(env: dict[str, str]) -> str:
versions_output_text = call(
"python", "-m", "pip", "freeze", "--all", capture_stdout=True, env=env
)
@@ -501,7 +497,7 @@ def _ensure_virtualenv() -> Path:
def _parse_constraints_for_virtualenv(
dependency_constraint_flags: Sequence[PathOrStr],
) -> Dict[str, str]:
) -> dict[str, str]:
"""
Parses the constraints file referenced by `dependency_constraint_flags` and returns a dict where
the key is the package name, and the value is the constraint version.
@@ -547,7 +543,7 @@ def _parse_constraints_for_virtualenv(
def virtualenv(
python: Path, venv_path: Path, dependency_constraint_flags: Sequence[PathOrStr]
) -> Dict[str, str]:
) -> dict[str, str]:
assert python.exists()
virtualenv_app = _ensure_virtualenv()
constraints = _parse_constraints_for_virtualenv(dependency_constraint_flags)
@@ -589,7 +585,7 @@ def virtualenv(
T = TypeVar("T", bound=PurePath)
def find_compatible_wheel(wheels: Sequence[T], identifier: str) -> Optional[T]:
def find_compatible_wheel(wheels: Sequence[T], identifier: str) -> T | None:
"""
Finds a wheel with an abi3 or a none ABI tag in `wheels` compatible with the Python interpreter
specified by `identifier` that is previously built.
@@ -641,7 +637,7 @@ else:
# Can be replaced by contextlib.chdir in Python 3.11
@contextlib.contextmanager
def chdir(new_path: Union[Path, str]) -> Generator[None, None, None]:
def chdir(new_path: Path | str) -> Generator[None, None, None]:
"""Non thread-safe context manager to change the current working directory."""
cwd = os.getcwd()
+9 -7
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import os
import shutil
import subprocess
@@ -5,7 +7,7 @@ import sys
from dataclasses import dataclass
from functools import lru_cache
from pathlib import Path
from typing import Dict, List, Optional, Sequence, Set
from typing import Sequence
from zipfile import ZipFile
from filelock import FileLock
@@ -34,7 +36,7 @@ from .util import (
)
def get_nuget_args(version: str, arch: str, output_directory: Path) -> List[str]:
def get_nuget_args(version: str, arch: str, output_directory: Path) -> list[str]:
platform_suffix = {"32": "x86", "64": "", "ARM64": "arm64"}
python_name = "python" + platform_suffix[arch]
return [
@@ -53,13 +55,13 @@ class PythonConfiguration:
version: str
arch: str
identifier: str
url: Optional[str] = None
url: str | None = None
def get_python_configurations(
build_selector: BuildSelector,
architectures: Set[Architecture],
) -> List[PythonConfiguration]:
architectures: set[Architecture],
) -> list[PythonConfiguration]:
full_python_configs = read_python_configs("windows")
@@ -124,7 +126,7 @@ def setup_python(
dependency_constraint_flags: Sequence[PathOrStr],
environment: ParsedEnvironment,
build_frontend: BuildFrontend,
) -> Dict[str, str]:
) -> dict[str, str]:
tmp.mkdir()
implementation_id = python_configuration.identifier.split("-")[0]
log.step(f"Installing Python {implementation_id}...")
@@ -253,7 +255,7 @@ def build(options: Options, tmp_path: Path) -> None:
)
shell(before_all_prepared, env=env)
built_wheels: List[Path] = []
built_wheels: list[Path] = []
for config in python_configurations:
build_options = options.build_options(config.identifier)
-2
View File
@@ -94,7 +94,6 @@ This has been moved to using docker, so you only need the following instructions
The dependency update script in the next section requires multiple python versions installed. One way to do this is to use `pyenv`:
```bash
pyenv install 3.6.11
pyenv install 3.7.8
# Optionally add 3.8 and make it the local version;
# otherwise assuming 3.8+ already is your current python version
@@ -103,7 +102,6 @@ pyenv install 3.7.8
Then, you need to make the required virtual environments:
```bash
$(pyenv prefix 3.6.11)/bin/python -m venv env36
$(pyenv prefix 3.7.8)/bin/python -m venv env37
```
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import subprocess
from typing import Any
+1 -1
View File
@@ -4,7 +4,7 @@ jobs:
linux-wheels:
working_directory: ~/linux-wheels
docker:
- image: circleci/python:3.6
- image: circleci/python:3.9
steps:
- checkout
- setup_remote_docker
-1
View File
@@ -9,7 +9,6 @@ os: linux
dist: focal
language: python
python:
- 3.6
- 3.7
- 3.8
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import os
import shutil
import sys
+2 -2
View File
@@ -8,7 +8,7 @@ build-backend = "setuptools.build_meta"
[tool.black]
line-length = 100
target-version = ['py36', 'py37', 'py38', 'py39', 'py310']
target-version = ['py37', 'py38', 'py39', 'py310']
[tool.isort]
@@ -88,7 +88,7 @@ ignore = [
]
[tool.pylint]
master.py-version = "3.6"
master.py-version = "3.7"
master.jobs = "0"
master.fail-on = ["E", "F"]
master.fail-under = "9.8"
+1 -3
View File
@@ -16,7 +16,6 @@ classifiers =
Natural Language :: English
Programming Language :: Python :: 3
Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
@@ -37,10 +36,9 @@ install_requires =
filelock
packaging>=20.9
platformdirs
dataclasses;python_version < '3.7'
tomli;python_version < '3.11'
typing-extensions>=3.10.0.0;python_version < '3.8'
python_requires = >=3.6
python_requires = >=3.7
include_package_data = True
zip_safe = False
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
from setuptools import setup
extras = {
+2 -2
View File
@@ -1,4 +1,4 @@
from typing import Dict
from __future__ import annotations
import pytest
@@ -13,5 +13,5 @@ def pytest_addoption(parser) -> None:
@pytest.fixture(
params=[{"CIBW_BUILD_FRONTEND": "pip"}, {"CIBW_BUILD_FRONTEND": "build"}], ids=["pip", "build"]
)
def build_frontend_env(request) -> Dict[str, str]:
def build_frontend_env(request) -> dict[str, str]:
return request.param # type: ignore[no-any-return]
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import textwrap
import pytest
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import textwrap
from . import test_projects, utils
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import subprocess
import textwrap
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import subprocess
import textwrap
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
from . import test_projects, utils
before_test_project = test_projects.new_c_project()
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import textwrap
from . import test_projects, utils
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import platform
import textwrap
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import os
import jinja2
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import re
import textwrap
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import subprocess
import pytest
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import os
import subprocess
import textwrap
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import os
import subprocess
import sys
+4 -3
View File
@@ -1,6 +1,7 @@
from __future__ import annotations
import platform
import subprocess
from typing import Tuple
import pytest
@@ -14,10 +15,10 @@ ALL_MACOS_WHEELS = {
}
def get_xcode_version() -> Tuple[int, int]:
def get_xcode_version() -> tuple[int, int]:
output = subprocess.run(
["xcodebuild", "-version"],
universal_newlines=True,
text=True,
check=True,
stdout=subprocess.PIPE,
).stdout
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import platform
import textwrap
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import textwrap
from . import test_projects, utils
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import pytest
from . import test_projects, utils
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
from .base import TestProject
from .c import new_c_project
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import importlib
import subprocess
import sys
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
from pathlib import Path
from typing import Any, Dict, Union
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import jinja2
from .base import TestProject
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import subprocess
from test import test_projects
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import subprocess
from test import test_projects
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import textwrap
from . import test_projects, utils
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
from pathlib import Path
import jinja2
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import os
import subprocess
import textwrap
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import subprocess
import pytest
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import pytest
from . import test_projects, utils
+3 -1
View File
@@ -4,6 +4,8 @@ Utility functions used by the cibuildwheel tests.
This file is added to the PYTHONPATH in the test runner at bin/run_test.py.
"""
from __future__ import annotations
import os
import platform as pm
import subprocess
@@ -35,7 +37,7 @@ def cibuildwheel_get_build_identifiers(project_path, env=None, *, prerelease_pyt
cmd_output = subprocess.run(
cmd,
universal_newlines=True,
text=True,
env=env,
check=True,
stdout=subprocess.PIPE,
+3 -2
View File
@@ -1,5 +1,6 @@
from __future__ import annotations
import sys
from typing import Dict, List
if sys.version_info >= (3, 11):
import tomllib
@@ -27,7 +28,7 @@ def test_compare_configs():
def test_dump_with_Version():
# MyPy doesn't understand deeply nested dicts correctly
example: Dict[str, Dict[str, List[Dict[str, Printable]]]] = {
example: dict[str, dict[str, list[dict[str, Printable]]]] = {
"windows": {
"python_configurations": [
{"identifier": "cp27-win32", "version": Version("2.7.18"), "arch": "32"},
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
from packaging.specifiers import SpecifierSet
from cibuildwheel.util import BuildSelector
+5 -1
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import sys
from pathlib import Path
@@ -12,7 +14,7 @@ def pytest_addoption(parser):
@pytest.fixture
def fake_package_dir(monkeypatch):
def fake_package_dir(tmp_path, monkeypatch):
"""
Monkey-patch enough for the main() function to run
"""
@@ -25,6 +27,8 @@ def fake_package_dir(monkeypatch):
return real_path_exists(path)
args = ["cibuildwheel", str(MOCK_PACKAGE_DIR)]
tmp_path.joinpath(MOCK_PACKAGE_DIR).mkdir()
monkeypatch.setattr(Path, "exists", mock_path_exists)
monkeypatch.setattr(sys, "argv", args)
monkeypatch.chdir(tmp_path)
return args
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
from pathlib import Path
from cibuildwheel.util import DependencyConstraints
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import ssl
import certifi
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import os
from cibuildwheel.environment import parse_environment
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import textwrap
from pathlib import Path
from pprint import pprint
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import contextlib
import platform as platform_module
import subprocess
@@ -1,3 +1,5 @@
from __future__ import annotations
import sys
from fnmatch import fnmatch
from pathlib import Path
@@ -1,3 +1,5 @@
from __future__ import annotations
import sys
import pytest
@@ -1,3 +1,5 @@
from __future__ import annotations
import sys
import textwrap
+4 -2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import os
import platform
import random
@@ -83,7 +85,7 @@ def test_container_removed(container_engine):
shell=True,
check=True,
stdout=subprocess.PIPE,
universal_newlines=True,
text=True,
).stdout
assert container.name is not None
assert container.name in docker_containers_listing
@@ -94,7 +96,7 @@ def test_container_removed(container_engine):
shell=True,
check=True,
stdout=subprocess.PIPE,
universal_newlines=True,
text=True,
).stdout
assert old_container_name not in docker_containers_listing
+3 -1
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import platform as platform_module
import subprocess
import sys
@@ -44,7 +46,7 @@ def mock_build_container(monkeypatch):
def test_build_default_launches(mock_build_container, fake_package_dir, monkeypatch):
monkeypatch.setattr(sys, "argv", ["cibuildwheel", "--platform=linux"])
monkeypatch.setattr(sys, "argv", sys.argv + ["--platform=linux"])
main()
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import platform as platform_module
import pytest
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
from pathlib import Path
import pytest
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
from textwrap import dedent
from cibuildwheel.projectfiles import get_requires_python_str, setup_py_python_requires
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
from pathlib import Path
from cibuildwheel.options import CommandLineArguments
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
from pathlib import PurePath
import pytest
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import pytest
from cibuildwheel.util import print_new_wheels