Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: pypa/packaging
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 23.1
Choose a base ref
...
head repository: pypa/packaging
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 23.2
Choose a head ref

Commits on Apr 12, 2023

  1. Bump for development

    pradyunsg committed Apr 12, 2023
    Copy the full SHA
    30d4a1c View commit details

Commits on Apr 13, 2023

  1. Ensure that the entire string is consumed with parse_marker (#687)

    Co-authored-by: Pradyun Gedam <pradyunsg@users.noreply.github.com>
    mwerschy and pradyunsg authored Apr 13, 2023
    Copy the full SHA
    55584fb View commit details

Commits on May 24, 2023

  1. Create a Security Policy file (#695)

    Signed-off-by: Joyce <joycebrum@google.com>
    joycebrum authored May 24, 2023
    Copy the full SHA
    1182c88 View commit details

Commits on May 31, 2023

  1. Add Python 3.12 to CI (#689)

    mayeut authored May 31, 2023
    Copy the full SHA
    63f4cfe View commit details

Commits on Jun 13, 2023

  1. Remove URL validation from requirement parsing (#684)

    The scheme and path validation logic limits how users of the library can
    provide URL support. This limitation is lifted, and dependants now need
    to implement their own URL validation logic they see fit.
    
    Co-authored-by: Brett Cannon <brett@python.org>
    uranusjr and brettcannon authored Jun 13, 2023
    Copy the full SHA
    fe8f0bb View commit details

Commits on Jun 16, 2023

  1. Add types for packaging.version._Version (#665)

    This makes interactions with the internal _version object type safe,
    instead of having them all resolve to Any.
    hauntsaninja authored Jun 16, 2023
    Copy the full SHA
    f8893d4 View commit details

Commits on Jun 19, 2023

  1. Add PyPy 3.10 to CI (#699)

    mayeut authored Jun 19, 2023
    Copy the full SHA
    2b389f3 View commit details

Commits on Jul 7, 2023

  1. Copy the full SHA
    538cd15 View commit details
  2. Canonicalize names for requirements comparison (#696)

    Signed-off-by: Juan Luis Cano Rodríguez <juan_luis_cano@mckinsey.com>
    Co-authored-by: Brett Cannon <brett@python.org>
    astrojuanlu and brettcannon authored Jul 7, 2023
    Copy the full SHA
    e8f839f View commit details
  3. Add platform tag support for LoongArch (#693)

    Co-authored-by: Brett Cannon <brett@python.org>
    loongson-zn and brettcannon authored Jul 7, 2023
    Copy the full SHA
    2f80de7 View commit details

Commits on Jul 14, 2023

  1. Ability to install armv7l manylinux/musllinux wheels on armv8l (#690

    )
    
    aarch64 systems running under linux32 emulation will report an armv8l
    machine rather than armv7l. This shall not prevent packaging to report
    musllinux/manylinux armv7l compatibiility as long as the running python
    has a compatible ABI.
    mayeut authored Jul 14, 2023
    Copy the full SHA
    1277904 View commit details

Commits on Jul 26, 2023

  1. Copy the full SHA
    3030822 View commit details

Commits on Aug 11, 2023

  1. Copy the full SHA
    e5a7893 View commit details
  2. Copy the full SHA
    e120b49 View commit details

Commits on Aug 15, 2023

  1. Copy the full SHA
    33cc1f7 View commit details

Commits on Aug 18, 2023

  1. Support enriched metadata in packaging.metadata (#686)

    Introduce the `packaging.metadata.Metadata` class which gives an object API similar to `packaging.metadata.RawMetadata` while returning "enriched" objects like `version.Version` where appropriate. It also supports validating the metadata.
    
    Part of #570
    brettcannon authored Aug 18, 2023
    Copy the full SHA
    61e6efb View commit details

Commits on Aug 19, 2023

  1. Copy the full SHA
    7e68d82 View commit details

Commits on Sep 1, 2023

  1. fix: Detect when a platform is 32-bit more accurately (#711)

    When running a 64-bit version of GraalPy (either x86_64 or aarch64), packaging returns the wrong platform tag (either i686 or armv8l).
    
    Fix this by using the same default implementation as found in stdlib platform.architecture https://github.com/python/cpython/blob/4d4393139fae39db26dead33529b6ae0bafbfc58/Lib/platform.py#L713-L716
    
    Co-authored-by: Brett Cannon <brett@python.org>
    mayeut and brettcannon authored Sep 1, 2023
    Copy the full SHA
    c1346df View commit details

Commits on Sep 2, 2023

  1. Copy the full SHA
    39786bb View commit details

Commits on Sep 6, 2023

  1. fix: Update copyright date for docs (#713)

    Co-authored-by: Brett Cannon <brett@python.org>
    garrypolley and brettcannon authored Sep 6, 2023
    Copy the full SHA
    7023537 View commit details

Commits on Sep 7, 2023

  1. Bump pip version to avoid known vulnerabilities (#720)

    Signed-off-by: Joyce <joycebrum@google.com>
    joycebrum authored Sep 7, 2023
    Copy the full SHA
    0206c39 View commit details

Commits on Sep 12, 2023

  1. Typing annotations fixed (#723)

    Co-authored-by: Vasily Zakharov <v.zakharov@wwpass.com>
    jolaf and Vasily Zakharov authored Sep 12, 2023
    Copy the full SHA
    b509bef View commit details

Commits on Oct 1, 2023

  1. Copy the full SHA
    524b701 View commit details
  2. Fix code blocks in CHANGELOG.md (#724)

    Previously the mixed single/double backtick usage meant
    the code block didn't end at the correct location and instead
    ran into the normal text.
    edmorley authored Oct 1, 2023
    Copy the full SHA
    d7ce40d View commit details
  3. Bump for release

    pradyunsg committed Oct 1, 2023
    Copy the full SHA
    b3a5d7d View commit details
10 changes: 3 additions & 7 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@ jobs:
matrix:
os: [Ubuntu, Windows, macOS]
python_version:
["3.7", "3.8", "3.9", "3.10", "3.11", "pypy3.8", "pypy3.9"]
["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "pypy3.8", "pypy3.9", "pypy3.10"]

steps:
- uses: actions/checkout@v3
@@ -33,11 +33,7 @@ jobs:
with:
python-version: ${{ matrix.python_version }}
cache: "pip"
allow-prereleases: true

- name: Run nox
run: |
# Need to remove "-dev" suffix
INTERPRETER=${{ matrix.python_version }}
INTERPRETER=${INTERPRETER/-dev/}
pipx run nox --error-on-missing-interpreters -s tests-${INTERPRETER}
shell: bash
run: pipx run nox --error-on-missing-interpreters -s tests-${{ matrix.python_version }}
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -19,7 +19,7 @@ repos:
rev: v3.3.1
hooks:
- id: pyupgrade
args: [--py36-plus]
args: [--py37-plus]

- repo: https://github.com/psf/black
rev: 22.12.0
14 changes: 14 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
Changelog
---------

23.2 - 2023-10-01
~~~~~~~~~~~~~~~~~

* Document calendar-based versioning scheme (:issue:`716`)
* Enforce that the entire marker string is parsed (:issue:`687`)
* Requirement parsing no longer automatically validates the URL (:issue:`120`)
* Canonicalize names for requirements comparison (:issue:`644`)
* Introduce ``metadata.Metadata`` (along with ``metadata.ExceptionGroup`` and ``metadata.InvalidMetadata``; :issue:`570`)
* Introduce the ``validate`` keyword parameter to ``utils.validate_name()`` (:issue:`570`)
* Introduce ``utils.is_normalized_name()`` (:issue:`570`)
* Make ``utils.parse_sdist_filename()`` and ``utils.parse_wheel_filename()``
raise ``InvalidSdistFilename`` and ``InvalidWheelFilename``, respectively,
when the version component of the name is invalid

23.1 - 2023-04-12
~~~~~~~~~~~~~~~~~

5 changes: 2 additions & 3 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
@@ -17,7 +17,6 @@ https://packaging.pypa.io/en/latest/development/
Security issues
---------------

To report a security issue, please follow the special `security reporting
guidelines`_, do not report them in the public issue tracker.
See `Security Policy`_ for information about how to report security issues.

.. _`security reporting guidelines`: https://packaging.pypa.io/en/latest/security/
.. _`Security Policy`: https://github.com/pypa/packaging/security
2 changes: 2 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
@@ -34,6 +34,8 @@ Use ``pip`` to install these utilities::

pip install packaging

The ``packaging`` library uses calendar-based versioning (``YY.N``).

Discussion
----------

5 changes: 5 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Security Policy
=========================

To report a security issue, please follow the special [security reporting
guidelines](https://packaging.pypa.io/en/latest/security/), do not report them in the public issue tracker.
2 changes: 2 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
@@ -15,6 +15,8 @@ You can install packaging with ``pip``:
$ pip install packaging
The ``packaging`` library uses calendar-based versioning (``YY.N``).


.. toctree::
:maxdepth: 1
26 changes: 25 additions & 1 deletion docs/metadata.rst
Original file line number Diff line number Diff line change
@@ -25,15 +25,39 @@ Usage
'packaging'
>>> raw["version"]
'24.0'
>>> from packaging.metadata import Metadata
>>> parsed = Metadata.from_raw(raw)
>>> parsed.name
'packaging'
>>> parsed.version
<Version('24.0')>


Reference
---------

High Level Interface
''''''''''''''''''''

.. autoclass:: packaging.metadata.Metadata
:members:

Low Level Interface
'''''''''''''''''''

.. automodule:: packaging.metadata
.. autoclass:: packaging.metadata.RawMetadata
:members:

.. autofunction:: packaging.metadata.parse_email


Exceptions
''''''''''

.. autoclass:: packaging.metadata.InvalidMetadata
:members:

.. autoclass:: packaging.metadata.ExceptionGroup
:members:


7 changes: 7 additions & 0 deletions docs/requirements.rst
Original file line number Diff line number Diff line change
@@ -56,6 +56,13 @@ Usage
>>> requirements1 == requirements2
True

.. versionchanged:: 23.2

When a requirement is specified with a URL, the :class:`Requirement` class
used to check the URL and reject values containing invalid scheme and
netloc combinations. This is no longer performed since PEP 508 does not
specify such rules, and the check incorrectly disallows valid requirement
strings from being parsed.

Reference
---------
26 changes: 25 additions & 1 deletion docs/utils.rst
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@ Reference

A :class:`typing.NewType` of :class:`str`, representing a normalized name.

.. function:: canonicalize_name(name)
.. function:: canonicalize_name(name, validate=False)

This function takes a valid Python package or extra name, and returns the
normalized form of it.
@@ -23,7 +23,13 @@ Reference
checkers to help require that a string has passed through this function
before use.

If **validate** is true, then the function will check if **name** is a valid
distribution name before normalizing.

:param str name: The name to normalize.
:param bool validate: Check whether the name is a valid distribution name.
:raises InvalidName: If **validate** is true and the name is not an
acceptable distribution name.

.. doctest::

@@ -35,6 +41,21 @@ Reference
>>> canonicalize_name("requests")
'requests'

.. function:: is_normalized_name(name)

Check if a name is already normalized (i.e. :func:`canonicalize_name` would
roundtrip to the same value).

:param str name: The name to check.

.. doctest::

>>> from packaging.utils import is_normalized_name
>>> is_normalized_name("requests")
True
>>> is_normalized_name("Django")
False

.. function:: canonicalize_version(version)

This function takes a string representing a package version (or a
@@ -103,6 +124,9 @@ Reference
>>> ver == Version('1.0')
True

.. exception:: InvalidName

Raised when a distribution name is invalid.

.. exception:: InvalidWheelFilename

14 changes: 13 additions & 1 deletion noxfile.py
Original file line number Diff line number Diff line change
@@ -21,7 +21,19 @@
nox.options.reuse_existing_virtualenvs = True


@nox.session(python=["3.7", "3.8", "3.9", "3.10", "3.11", "pypy3.8", "pypy3.9"])
@nox.session(
python=[
"3.7",
"3.8",
"3.9",
"3.10",
"3.11",
"3.12",
"pypy3.8",
"pypy3.9",
"pypy3.10",
]
)
def tests(session):
def coverage(*args):
session.run("python", "-m", "coverage", *args)
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -23,6 +23,7 @@ classifiers = [
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
"Typing :: Typed",
@@ -35,7 +36,7 @@ Source = "https://github.com/pypa/packaging"


[tool.flit.sdist]
include = ["LICENSE*", "tests/", "docs/"]
include = ["LICENSE*", "tests/", "docs/", "CHANGELOG.rst"]
exclude = ["docs/_build", "tests/manylinux/build-hello-world.sh", "tests/musllinux/build.sh", "tests/hello-world.c", "tests/__pycache__", "build/__pycache__"]


4 changes: 2 additions & 2 deletions src/packaging/__init__.py
Original file line number Diff line number Diff line change
@@ -6,10 +6,10 @@
__summary__ = "Core utilities for Python packages"
__uri__ = "https://github.com/pypa/packaging"

__version__ = "23.1"
__version__ = "23.2"

__author__ = "Donald Stufft and individual contributors"
__email__ = "donald@stufft.io"

__license__ = "BSD-2-Clause or Apache-2.0"
__copyright__ = "2014-2019 %s" % __author__
__copyright__ = "2014 %s" % __author__
62 changes: 37 additions & 25 deletions src/packaging/_manylinux.py
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@
import re
import sys
import warnings
from typing import Dict, Generator, Iterator, NamedTuple, Optional, Tuple
from typing import Dict, Generator, Iterator, NamedTuple, Optional, Sequence, Tuple

from ._elffile import EIClass, EIData, ELFFile, EMachine

@@ -50,12 +50,13 @@ def _is_linux_i686(executable: str) -> bool:
)


def _have_compatible_abi(executable: str, arch: str) -> bool:
if arch == "armv7l":
def _have_compatible_abi(executable: str, archs: Sequence[str]) -> bool:
if "armv7l" in archs:
return _is_linux_armhf(executable)
if arch == "i686":
if "i686" in archs:
return _is_linux_i686(executable)
return arch in {"x86_64", "aarch64", "ppc64", "ppc64le", "s390x"}
allowed_archs = {"x86_64", "aarch64", "ppc64", "ppc64le", "s390x", "loongarch64"}
return any(arch in allowed_archs for arch in archs)


# If glibc ever changes its major version, we need to know what the last
@@ -167,7 +168,7 @@ def _get_glibc_version() -> Tuple[int, int]:


# From PEP 513, PEP 600
def _is_compatible(name: str, arch: str, version: _GLibCVersion) -> bool:
def _is_compatible(arch: str, version: _GLibCVersion) -> bool:
sys_glibc = _get_glibc_version()
if sys_glibc < version:
return False
@@ -203,12 +204,22 @@ def _is_compatible(name: str, arch: str, version: _GLibCVersion) -> bool:
}


def platform_tags(linux: str, arch: str) -> Iterator[str]:
if not _have_compatible_abi(sys.executable, arch):
def platform_tags(archs: Sequence[str]) -> Iterator[str]:
"""Generate manylinux tags compatible to the current platform.
:param archs: Sequence of compatible architectures.
The first one shall be the closest to the actual architecture and be the part of
platform tag after the ``linux_`` prefix, e.g. ``x86_64``.
The ``linux_`` prefix is assumed as a prerequisite for the current platform to
be manylinux-compatible.
:returns: An iterator of compatible manylinux tags.
"""
if not _have_compatible_abi(sys.executable, archs):
return
# Oldest glibc to be supported regardless of architecture is (2, 17).
too_old_glibc2 = _GLibCVersion(2, 16)
if arch in {"x86_64", "i686"}:
if set(archs) & {"x86_64", "i686"}:
# On x86/i686 also oldest glibc to be supported is (2, 5).
too_old_glibc2 = _GLibCVersion(2, 4)
current_glibc = _GLibCVersion(*_get_glibc_version())
@@ -222,19 +233,20 @@ def platform_tags(linux: str, arch: str) -> Iterator[str]:
for glibc_major in range(current_glibc.major - 1, 1, -1):
glibc_minor = _LAST_GLIBC_MINOR[glibc_major]
glibc_max_list.append(_GLibCVersion(glibc_major, glibc_minor))
for glibc_max in glibc_max_list:
if glibc_max.major == too_old_glibc2.major:
min_minor = too_old_glibc2.minor
else:
# For other glibc major versions oldest supported is (x, 0).
min_minor = -1
for glibc_minor in range(glibc_max.minor, min_minor, -1):
glibc_version = _GLibCVersion(glibc_max.major, glibc_minor)
tag = "manylinux_{}_{}".format(*glibc_version)
if _is_compatible(tag, arch, glibc_version):
yield linux.replace("linux", tag)
# Handle the legacy manylinux1, manylinux2010, manylinux2014 tags.
if glibc_version in _LEGACY_MANYLINUX_MAP:
legacy_tag = _LEGACY_MANYLINUX_MAP[glibc_version]
if _is_compatible(legacy_tag, arch, glibc_version):
yield linux.replace("linux", legacy_tag)
for arch in archs:
for glibc_max in glibc_max_list:
if glibc_max.major == too_old_glibc2.major:
min_minor = too_old_glibc2.minor
else:
# For other glibc major versions oldest supported is (x, 0).
min_minor = -1
for glibc_minor in range(glibc_max.minor, min_minor, -1):
glibc_version = _GLibCVersion(glibc_max.major, glibc_minor)
tag = "manylinux_{}_{}".format(*glibc_version)
if _is_compatible(arch, glibc_version):
yield f"{tag}_{arch}"
# Handle the legacy manylinux1, manylinux2010, manylinux2014 tags.
if glibc_version in _LEGACY_MANYLINUX_MAP:
legacy_tag = _LEGACY_MANYLINUX_MAP[glibc_version]
if _is_compatible(arch, glibc_version):
yield f"{legacy_tag}_{arch}"
19 changes: 11 additions & 8 deletions src/packaging/_musllinux.py
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@
import re
import subprocess
import sys
from typing import Iterator, NamedTuple, Optional
from typing import Iterator, NamedTuple, Optional, Sequence

from ._elffile import ELFFile

@@ -47,24 +47,27 @@ def _get_musl_version(executable: str) -> Optional[_MuslVersion]:
return None
if ld is None or "musl" not in ld:
return None
proc = subprocess.run([ld], stderr=subprocess.PIPE, universal_newlines=True)
proc = subprocess.run([ld], stderr=subprocess.PIPE, text=True)
return _parse_musl_version(proc.stderr)


def platform_tags(arch: str) -> Iterator[str]:
def platform_tags(archs: Sequence[str]) -> Iterator[str]:
"""Generate musllinux tags compatible to the current platform.
:param arch: Should be the part of platform tag after the ``linux_``
prefix, e.g. ``x86_64``. The ``linux_`` prefix is assumed as a
prerequisite for the current platform to be musllinux-compatible.
:param archs: Sequence of compatible architectures.
The first one shall be the closest to the actual architecture and be the part of
platform tag after the ``linux_`` prefix, e.g. ``x86_64``.
The ``linux_`` prefix is assumed as a prerequisite for the current platform to
be musllinux-compatible.
:returns: An iterator of compatible musllinux tags.
"""
sys_musl = _get_musl_version(sys.executable)
if sys_musl is None: # Python not dynamically linked against musl.
return
for minor in range(sys_musl.minor, -1, -1):
yield f"musllinux_{sys_musl.major}_{minor}_{arch}"
for arch in archs:
for minor in range(sys_musl.minor, -1, -1):
yield f"musllinux_{sys_musl.major}_{minor}_{arch}"


if __name__ == "__main__": # pragma: no cover
Loading