PEP 610 Parser

A parser for PEP 610 direct URL metadata.

Release v0.6.1.dev14+g958f525ee.

from importlib import metadata

import pep610

dist = metadata.distribution("pep610")

match data := pep610.read_from_distribution(dist):
    case pep610.DirectUrl(url, pep610.DirInfo(editable=True)):
        print("Editable installation, a.k.a. in development mode")
    case _:
        print("Not an editable installation")
from importlib import metadata

import pep610

dist = metadata.distribution("pep610")

if (
    (data := pep610.read_from_distribution(dist))
    and isinstance(data, pep610.DirectUrl)
    and isinstance(data.info, pep610.DirInfo)
    and data.info.is_editable()
):
    print("Editable installation, a.k.a. in development mode")
else:
    print("Not an editable installation")

It can also be used to parse the direct URL download info in pip’s Installation Report:

import json
import subprocess

import pep610

report = json.loads(
    subprocess.run(
        [
            "pip",
            "install",
            "--quiet",
            "--report",
            "-",
            "--dry-run",
            "git+https://github.com/pypa/packaging@main",
        ],
        capture_output=True,
        text=True,
    ).stdout
)

for package in report["install"]:
    if package["is_direct"]:
        data = pep610.parse(package["download_info"])
        print(data)

Direct URL Data class

class pep610.DirectUrl(url, info, subdirectory=None)

Direct URL data.

Parameters:
  • url (str) – The direct URL.

  • info (VCSInfo | ArchiveInfo | DirInfo) – The direct URL data.

  • subdirectory (str | None) – The optional directory path, relative to the root of the VCS repository, source archive or local directory, to specify where pyproject.toml or setup.py is located.

to_dict()

Convert the data to a dictionary.

Returns:

The data as a dictionary.

Return type:

DirectUrlDict

>>> direct_url = DirectUrl(
...     url="file:///home/user/pep610",
...     info=DirInfo(editable=False),
...     subdirectory="app",
... )
>>> direct_url.to_dict()
{'url': 'file:///home/user/pep610', 'subdirectory': 'app', 'dir_info': {'editable': False}}
to_json()

Convert the data to a JSON string.

Returns:

The data as a JSON string.

Return type:

str

>>> direct_url = DirectUrl(
...     url="file:///home/user/pep610",
...     info=DirInfo(editable=False),
...     subdirectory="app",
... )
>>> direct_url.to_json()
'{"dir_info": {"editable": false}, "subdirectory": "app", "url": "file:///home/user/pep610"}'

Supported direct URL formats

class pep610.ArchiveInfo(hashes=None, hash=None)

Archive information.

See the Archive URLs specification.

Parameters:
  • hashes (dict[str, str] | None) –

    Dictionary mapping a hash name to a hex encoded digest of the file.

    Any hash algorithm available via hashlib (specifically any that can be passed to hashlib.new() and do not require additional parameters) can be used as a key for the hashes dictionary. At least one secure algorithm from hashlib.algorithms_guaranteed SHOULD always be included.

  • hash (HashData | None) – The archive hash (deprecated).

has_valid_algorithms()

Has valid archive hashes?

Checks that the hashes attribute is not empty and that at least one of the hashes is present in hashlib.algorithms_guaranteed.

Returns:

Whether the archive has valid hashes.

Return type:

bool

>>> archive_info = ArchiveInfo(
...     hashes={
...         "sha256": "1dc6b5a470a1bde68946f263f1af1515a2574a150a30d6ce02c6ff742fcc0db9",
...         "md5": "c4e0f0a1e0a5e708c8e3e3c4cbe2e85f",
...     },
... )
>>> archive_info.has_valid_algorithms()
True
property all_hashes: dict[str, str]

All archive hashes.

Merges the hashes attribute with the legacy hash attribute, prioritizing the former.

Returns:

All archive hashes.

>>> archive_info = ArchiveInfo(
...     hash=HashData(
...         "sha256",
...         "2dc6b5a470a1bde68946f263f1af1515a2574a150a30d6ce02c6ff742fcc0db8",
...     ),
...     hashes={
...         "sha256": "1dc6b5a470a1bde68946f263f1af1515a2574a150a30d6ce02c6ff742fcc0db9",
...         "md5": "c4e0f0a1e0a5e708c8e3e3c4cbe2e85f",
...     },
... )
>>> archive_info.all_hashes
{'sha256': '1dc6b5a470a1bde68946f263f1af1515a2574a150a30d6ce02c6ff742fcc0db9', 'md5': 'c4e0f0a1e0a5e708c8e3e3c4cbe2e85f'}
to_dict()

Convert the archive data to a dictionary.

Returns:

The archive data as a dictionary.

Return type:

ArchiveInfoDict

>>> archive_info = ArchiveInfo(
...     hashes={
...         "sha256": "1dc6b5a470a1bde68946f263f1af1515a2574a150a30d6ce02c6ff742fcc0db9",
...         "md5": "c4e0f0a1e0a5e708c8e3e3c4cbe2e85f",
...     },
... )
>>> archive_info.to_dict()
{'hashes': {'sha256': '1dc6b5a470a1bde68946f263f1af1515a2574a150a30d6ce02c6ff742fcc0db9', 'md5': 'c4e0f0a1e0a5e708c8e3e3c4cbe2e85f'}}
class pep610.DirInfo(editable)

Local directory information.

See the Local Directories specification.

Parameters:

editable (bool | None) – Whether the distribution is installed in editable mode.

is_editable()

Distribution is editable?

True if the distribution was/is to be installed in editable mode, False otherwise. If absent, default to False

Returns:

Whether the distribution is installed in editable mode.

Return type:

bool

>>> dir_info = DirInfo(editable=True)
>>> dir_info.is_editable()
True
>>> dir_info = DirInfo(editable=False)
>>> dir_info.is_editable()
False
>>> dir_info = DirInfo(editable=None)
>>> dir_info.is_editable()
False
to_dict()

Convert the directory data to a dictionary.

Returns:

The directory data as a dictionary.

Return type:

DirectoryInfoDict

>>> dir_info = DirInfo(editable=True)
>>> dir_info.to_dict()
{'editable': True}
class pep610.VCSInfo(vcs, commit_id, requested_revision=None, resolved_revision=None, resolved_revision_type=None)

VCS information.

See the VCS URLs specification.

Parameters:
  • vcs (str) – The VCS type.

  • commit_id (str) – The exact commit/revision number that was/is to be installed.

  • requested_revision (str | None) – A branch/tag/ref/commit/revision/etc (in a format compatible with the VCS).

to_dict()

Convert the VCS data to a dictionary.

Returns:

The VCS data as a dictionary.

Return type:

VCSInfoDict

>>> vcs_info = VCSInfo(
...     vcs="git",
...     commit_id="4f42225e91a0be634625c09e84dd29ea82b85e27",
...     requested_revision="main",
... )
>>> vcs_info.to_dict()
{'vcs': 'git', 'commit_id': '4f42225e91a0be634625c09e84dd29ea82b85e27', 'requested_revision': 'main'}

Functions

pep610.parse(data)

Parse the direct URL data.

Parameters:

data (dict[str, Any]) – The direct URL data.

Returns:

The parsed direct URL data.

Raises:

DirectUrlValidationError – If the direct URL data does not contain a recognized info key.

Return type:

DirectUrl

>>> parse(
...     {
...         "url": "https://github.com/pypa/packaging",
...         "vcs_info": {
...             "vcs": "git",
...             "requested_revision": "main",
...             "commit_id": "4f42225e91a0be634625c09e84dd29ea82b85e27"
...         }
...     }
... )
DirectUrl(url='https://github.com/pypa/packaging', info=VCSInfo(vcs='git', commit_id='4f42225e91a0be634625c09e84dd29ea82b85e27', requested_revision='main', resolved_revision=None, resolved_revision_type=None), subdirectory=None)
pep610.read_from_distribution(dist)

Read the package data for a given package.

Parameters:

dist (importlib.metadata.Distribution) – The package distribution.

Returns:

The parsed PEP 610 data or None if the file is not found.

Return type:

DirectUrl | None

>>> import importlib.metadata
>>> dist = importlib.metadata.distribution("pep610")
>>> read_from_distribution(dist)
DirData(url='file:///home/user/pep610', dir_info=DirInfo(editable=False))
pep610.is_editable(distribution_name)

Wrapper around read_from_distribution() to check if a distribution is editable.

Parameters:

distribution_name (str) – The distribution name.

Returns:

Whether the distribution is editable.

Return type:

bool

>>> is_editable("pep610")
False

Exceptions

class pep610.DirectUrlValidationError

Direct URL validation error.

Types

class pep610._pep610.HashData(algorithm, value)

(Deprecated) Archive hash data tuple.

algorithm: str

The hash algorithm.

value: str

The hash value.

class pep610._types.ArchiveInfoDict

Archive information dictionary.

hashes: dict[str, str]

The hashes of the archive.

hash: str

The hash of the archive (deprecated).

class pep610._types.DirectoryInfoDict

Local directory information dictionary.

editable: bool

Whether the directory is editable.

class pep610._types.VCSInfoDict

VCS information dictionary.

vcs: Required[str]

The VCS type.

commit_id: Required[str]

The commit ID.

requested_revision: str

The requested revision.

class pep610._types.DirectUrlDict

Direct URL data dictionary.

url: Required[str]

The direct URL.