Skip to content

Commit

Permalink
Merge branch 'main' into pep_639
Browse files Browse the repository at this point in the history
  • Loading branch information
brettcannon authored Oct 7, 2024
2 parents 42d6452 + 28e7da7 commit 461d183
Show file tree
Hide file tree
Showing 10 changed files with 203 additions and 20 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a # v3.25.15
uses: github/codeql-action/init@e2b3eafc8d227b0241d48be5f425d47c2d750a13 # v3.26.10
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
Expand All @@ -47,9 +47,9 @@ jobs:

# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
- name: Autobuild
uses: github/codeql-action/autobuild@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a # v3.25.15
uses: github/codeql-action/autobuild@e2b3eafc8d227b0241d48be5f425d47c2d750a13 # v3.26.10

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a # v3.25.15
uses: github/codeql-action/analyze@e2b3eafc8d227b0241d48be5f425d47c2d750a13 # v3.26.10
with:
category: "/language:${{matrix.language}}"
4 changes: 2 additions & 2 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0

- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
name: Install Python
with:
python-version: "3.9"
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0

- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
name: Install Python
with:
python-version: "3.9"
Expand All @@ -46,13 +46,13 @@ jobs:
needs: lint

steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0

- name: Build
run: pipx run build

- name: Archive files
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
with:
name: dist
path: dist
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ jobs:
["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "pypy3.8", "pypy3.9", "pypy3.10"]

steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0

- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
name: Install Python ${{ matrix.python_version }}
with:
python-version: ${{ matrix.python_version }}
Expand Down
9 changes: 6 additions & 3 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@ Changelog
*unreleased*
~~~~~~~~~~~~

No unreleased changes.
* Support creating a ``SpecifierSet`` from an iterable of ``Specifier`` objects (:issue:`775`)

24.1 - 2024-06-10
~~~~~~~~~~~~~~~~~

No unreleased changes.
* Document ``markers.default_environment()`` (:issue:`753`).
* Add support for Python 3.13 (:issue:`783`).
* Modernise type annotations (:issue:`785`).
* Work around ``platform.python_version()`` returning non PEP 440 compliant version
for non-tagged CPython builds (:issue:`802`).

24.0 - 2024-03-10
~~~~~~~~~~~~~~~~~
Expand All @@ -24,7 +28,6 @@ No unreleased changes.
have not been provided (:issue:`733`)
* Fix a bug preventing the use of the built in ``ExceptionGroup`` on versions of
Python that support it (:issue:`725`)
* Support creating a ``SpecifierSet`` from an iterable of ``Specifier`` objects (:issue:`775`)

23.2 - 2023-10-01
~~~~~~~~~~~~~~~~~
Expand Down
1 change: 1 addition & 0 deletions docs/development/release-process.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Release Process

$ pip install nox

#. Manually update the changelog to list all unreleased changes. Also verify that no new changes were added to a previous release in an earlier PR due to merge/rebase issues.
#. Run the release automation with the required version number (YY.N)::

$ nox -s release -- YY.N
Expand Down
15 changes: 15 additions & 0 deletions docs/tags.rst
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,21 @@ to the implementation to provide.
compatibility


.. function:: ios_platforms(version=None, multiarch=None)

Yields the :attr:`~Tag.platform` tags for iOS.

:param tuple version: A two-item tuple representing the version of iOS.
Defaults to the current system's version.
:param str multiarch: The CPU architecture+ABI to be used. This should be in
the format by ``sys.implementation._multiarch`` (e.g.,
``arm64_iphoneos`` or ``x84_64_iphonesimulator``).
Defaults to the current system's multiarch value.

.. note::
Behavior of this method is undefined if invoked on non-iOS platforms
without providing explicit version and multiarch arguments.

.. function:: platform_tags(version=None, arch=None)

Yields the :attr:`~Tag.platform` tags for the running interpreter.
Expand Down
2 changes: 2 additions & 0 deletions src/packaging/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,8 @@ def from_email(cls, data: bytes | str, *, validate: bool = True) -> Metadata:
metadata_version: _Validator[_MetadataVersion] = _Validator()
""":external:ref:`core-metadata-metadata-version`
(required; validated to be a valid metadata version)"""
# `name` is not normalized/typed to NormalizedName so as to provide access to
# the original/raw name.
name: _Validator[str] = _Validator()
""":external:ref:`core-metadata-name`
(required; validated using :func:`~packaging.utils.canonicalize_name` and its
Expand Down
69 changes: 64 additions & 5 deletions src/packaging/tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
logger = logging.getLogger(__name__)

PythonVersion = Sequence[int]
MacVersion = Tuple[int, int]
AppleVersion = Tuple[int, int]

INTERPRETER_SHORT_NAMES: dict[str, str] = {
"python": "py", # Generic.
Expand Down Expand Up @@ -362,7 +362,7 @@ def _mac_arch(arch: str, is_32bit: bool = _32_BIT_INTERPRETER) -> str:
return "i386"


def _mac_binary_formats(version: MacVersion, cpu_arch: str) -> list[str]:
def _mac_binary_formats(version: AppleVersion, cpu_arch: str) -> list[str]:
formats = [cpu_arch]
if cpu_arch == "x86_64":
if version < (10, 4):
Expand Down Expand Up @@ -395,7 +395,7 @@ def _mac_binary_formats(version: MacVersion, cpu_arch: str) -> list[str]:


def mac_platforms(
version: MacVersion | None = None, arch: str | None = None
version: AppleVersion | None = None, arch: str | None = None
) -> Iterator[str]:
"""
Yields the platform tags for a macOS system.
Expand All @@ -407,7 +407,7 @@ def mac_platforms(
"""
version_str, _, cpu_arch = platform.mac_ver()
if version is None:
version = cast("MacVersion", tuple(map(int, version_str.split(".")[:2])))
version = cast("AppleVersion", tuple(map(int, version_str.split(".")[:2])))
if version == (10, 16):
# When built against an older macOS SDK, Python will report macOS 10.16
# instead of the real version.
Expand All @@ -423,7 +423,7 @@ def mac_platforms(
stdout=subprocess.PIPE,
text=True,
).stdout
version = cast("MacVersion", tuple(map(int, version_str.split(".")[:2])))
version = cast("AppleVersion", tuple(map(int, version_str.split(".")[:2])))
else:
version = version
if arch is None:
Expand Down Expand Up @@ -473,6 +473,63 @@ def mac_platforms(
yield f"macosx_{major_version}_{minor_version}_{binary_format}"


def ios_platforms(
version: AppleVersion | None = None, multiarch: str | None = None
) -> Iterator[str]:
"""
Yields the platform tags for an iOS system.
:param version: A two-item tuple specifying the iOS version to generate
platform tags for. Defaults to the current iOS version.
:param multiarch: The CPU architecture+ABI to generate platform tags for -
(the value used by `sys.implementation._multiarch` e.g.,
`arm64_iphoneos` or `x84_64_iphonesimulator`). Defaults to the current
multiarch value.
"""
if version is None:
# if iOS is the current platform, ios_ver *must* be defined. However,
# it won't exist for CPython versions before 3.13, which causes a mypy
# error.
_, release, _, _ = platform.ios_ver() # type: ignore[attr-defined]
version = cast("AppleVersion", tuple(map(int, release.split(".")[:2])))

if multiarch is None:
multiarch = sys.implementation._multiarch
multiarch = multiarch.replace("-", "_")

ios_platform_template = "ios_{major}_{minor}_{multiarch}"

# Consider any iOS major.minor version from the version requested, down to
# 12.0. 12.0 is the first iOS version that is known to have enough features
# to support CPython. Consider every possible minor release up to X.9. There
# highest the minor has ever gone is 8 (14.8 and 15.8) but having some extra
# candidates that won't ever match doesn't really hurt, and it saves us from
# having to keep an explicit list of known iOS versions in the code. Return
# the results descending order of version number.

# If the requested major version is less than 12, there won't be any matches.
if version[0] < 12:
return

# Consider the actual X.Y version that was requested.
yield ios_platform_template.format(
major=version[0], minor=version[1], multiarch=multiarch
)

# Consider every minor version from X.0 to the minor version prior to the
# version requested by the platform.
for minor in range(version[1] - 1, -1, -1):
yield ios_platform_template.format(
major=version[0], minor=minor, multiarch=multiarch
)

for major in range(version[0] - 1, 11, -1):
for minor in range(9, -1, -1):
yield ios_platform_template.format(
major=major, minor=minor, multiarch=multiarch
)


def _linux_platforms(is_32bit: bool = _32_BIT_INTERPRETER) -> Iterator[str]:
linux = _normalize_string(sysconfig.get_platform())
if not linux.startswith("linux_"):
Expand Down Expand Up @@ -502,6 +559,8 @@ def platform_tags() -> Iterator[str]:
"""
if platform.system() == "Darwin":
return mac_platforms()
elif platform.system() == "iOS":
return ios_platforms()
elif platform.system() == "Linux":
return _linux_platforms()
else:
Expand Down
103 changes: 103 additions & 0 deletions tests/test_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,30 @@ def mock(name):
return mock


@pytest.fixture
def mock_ios(monkeypatch):
# Monkeypatch the platform to be iOS
monkeypatch.setattr(sys, "platform", "ios")

# Mock a fake architecture that will fit the expected pattern, but
# wont actually be a legal multiarch.
monkeypatch.setattr(
sys.implementation,
"_multiarch",
"gothic-iphoneos",
raising=False,
)

# Mock the return value of platform.ios_ver.
def mock_ios_ver(*args):
return ("iOS", "13.2", "iPhone15,2", False)

if sys.version_info < (3, 13):
platform.ios_ver = mock_ios_ver
else:
monkeypatch.setattr(platform, "ios_ver", mock_ios_ver)


class TestTag:
def test_lowercasing(self):
tag = tags.Tag("PY3", "None", "ANY")
Expand Down Expand Up @@ -335,6 +359,84 @@ def test_macos_11(self, major, minor):
assert "macosx_12_0_universal2" in platforms


class TestIOSPlatforms:
def test_version_detection(self, mock_ios):
platforms = list(tags.ios_platforms(multiarch="arm64-iphoneos"))
assert platforms == [
"ios_13_2_arm64_iphoneos",
"ios_13_1_arm64_iphoneos",
"ios_13_0_arm64_iphoneos",
"ios_12_9_arm64_iphoneos",
"ios_12_8_arm64_iphoneos",
"ios_12_7_arm64_iphoneos",
"ios_12_6_arm64_iphoneos",
"ios_12_5_arm64_iphoneos",
"ios_12_4_arm64_iphoneos",
"ios_12_3_arm64_iphoneos",
"ios_12_2_arm64_iphoneos",
"ios_12_1_arm64_iphoneos",
"ios_12_0_arm64_iphoneos",
]

def test_multiarch_detection(self, mock_ios):
platforms = list(tags.ios_platforms(version=(12, 0)))
assert platforms == ["ios_12_0_gothic_iphoneos"]

def test_ios_platforms(self, mock_ios):
# Pre-iOS 12.0 releases won't match anything
platforms = list(tags.ios_platforms((7, 0), "arm64-iphoneos"))
assert platforms == []

# iOS 12.0 returns exactly 1 match
platforms = list(tags.ios_platforms((12, 0), "arm64-iphoneos"))
assert platforms == ["ios_12_0_arm64_iphoneos"]

# iOS 13.0 returns a match for 13.0, plus every 12.X
platforms = list(tags.ios_platforms((13, 0), "x86_64-iphonesimulator"))
assert platforms == [
"ios_13_0_x86_64_iphonesimulator",
"ios_12_9_x86_64_iphonesimulator",
"ios_12_8_x86_64_iphonesimulator",
"ios_12_7_x86_64_iphonesimulator",
"ios_12_6_x86_64_iphonesimulator",
"ios_12_5_x86_64_iphonesimulator",
"ios_12_4_x86_64_iphonesimulator",
"ios_12_3_x86_64_iphonesimulator",
"ios_12_2_x86_64_iphonesimulator",
"ios_12_1_x86_64_iphonesimulator",
"ios_12_0_x86_64_iphonesimulator",
]

# iOS 14.3 returns a match for 14.3-14.0, plus every 13.X and every 12.X
platforms = list(tags.ios_platforms((14, 3), "arm64-iphoneos"))
assert platforms == [
"ios_14_3_arm64_iphoneos",
"ios_14_2_arm64_iphoneos",
"ios_14_1_arm64_iphoneos",
"ios_14_0_arm64_iphoneos",
"ios_13_9_arm64_iphoneos",
"ios_13_8_arm64_iphoneos",
"ios_13_7_arm64_iphoneos",
"ios_13_6_arm64_iphoneos",
"ios_13_5_arm64_iphoneos",
"ios_13_4_arm64_iphoneos",
"ios_13_3_arm64_iphoneos",
"ios_13_2_arm64_iphoneos",
"ios_13_1_arm64_iphoneos",
"ios_13_0_arm64_iphoneos",
"ios_12_9_arm64_iphoneos",
"ios_12_8_arm64_iphoneos",
"ios_12_7_arm64_iphoneos",
"ios_12_6_arm64_iphoneos",
"ios_12_5_arm64_iphoneos",
"ios_12_4_arm64_iphoneos",
"ios_12_3_arm64_iphoneos",
"ios_12_2_arm64_iphoneos",
"ios_12_1_arm64_iphoneos",
"ios_12_0_arm64_iphoneos",
]


class TestManylinuxPlatform:
def teardown_method(self):
# Clear the version cache
Expand Down Expand Up @@ -619,6 +721,7 @@ def test_linux_not_linux(self, monkeypatch):
"platform_name,dispatch_func",
[
("Darwin", "mac_platforms"),
("iOS", "ios_platforms"),
("Linux", "_linux_platforms"),
("Generic", "_generic_platforms"),
],
Expand Down

0 comments on commit 461d183

Please sign in to comment.