Skip to content

Commit

Permalink
Dropped the use of the deprecated pkg_resources API (#508)
Browse files Browse the repository at this point in the history
  • Loading branch information
graingert committed Mar 11, 2023
1 parent fb33195 commit f799533
Show file tree
Hide file tree
Showing 11 changed files with 2,728 additions and 12 deletions.
2 changes: 2 additions & 0 deletions docs/news.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ Release Notes

- Updated vendored ``packaging`` to 23.0
- Fixed spaces in platform names not being converted to underscores (PR by David Tucker)
- Fixed ``DeprecationWarning`` about the use of the deprecated ``pkg_resources`` API
(PR by Thomas Grainger)

**0.38.4 (2022-11-09)**

Expand Down
29 changes: 23 additions & 6 deletions src/wheel/bdist_wheel.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,38 @@
from shutil import rmtree
from zipfile import ZIP_DEFLATED, ZIP_STORED

import pkg_resources
import setuptools
from setuptools import Command

from . import __version__ as wheel_version
from .macosx_libfile import calculate_macosx_platform_tag
from .metadata import pkginfo_to_metadata
from .util import log
from .vendored.packaging import tags
from .vendored.packaging import version as _packaging_version
from .wheelfile import WheelFile

safe_name = pkg_resources.safe_name
safe_version = pkg_resources.safe_version
setuptools_major_version = int(
pkg_resources.get_distribution("setuptools").version.split(".")[0]
)

def safe_name(name):
"""Convert an arbitrary string to a standard distribution name
Any runs of non-alphanumeric/. characters are replaced with a single '-'.
"""
return re.sub("[^A-Za-z0-9.]+", "-", name)


def safe_version(version):
"""
Convert an arbitrary string to a standard version string
"""
try:
# normalize the version
return str(_packaging_version.Version(version))
except _packaging_version.InvalidVersion:
version = version.replace(" ", ".")
return re.sub("[^A-Za-z0-9.]+", "-", version)


setuptools_major_version = int(setuptools.__version__.split(".")[0])

PY_LIMITED_API_PATTERN = r"cp3\d"

Expand Down
82 changes: 76 additions & 6 deletions src/wheel/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,83 @@
"""
from __future__ import annotations

import functools
import itertools
import os.path
import re
import textwrap
from email.message import Message
from email.parser import Parser
from typing import Iterator

from pkg_resources import Requirement, safe_extra, split_sections
from .vendored.packaging.requirements import Requirement


def _nonblank(str):
return str and not str.startswith("#")


@functools.singledispatch
def yield_lines(iterable):
r"""
Yield valid lines of a string or iterable.
>>> list(yield_lines(''))
[]
>>> list(yield_lines(['foo', 'bar']))
['foo', 'bar']
>>> list(yield_lines('foo\nbar'))
['foo', 'bar']
>>> list(yield_lines('\nfoo\n#bar\nbaz #comment'))
['foo', 'baz #comment']
>>> list(yield_lines(['foo\nbar', 'baz', 'bing\n\n\n']))
['foo', 'bar', 'baz', 'bing']
"""
return itertools.chain.from_iterable(map(yield_lines, iterable))


@yield_lines.register(str)
def _(text):
return filter(_nonblank, map(str.strip, text.splitlines()))


def split_sections(s):
"""Split a string or iterable thereof into (section, content) pairs
Each ``section`` is a stripped version of the section header ("[section]")
and each ``content`` is a list of stripped lines excluding blank lines and
comment-only lines. If there are any such lines before the first section
header, they're returned in a first ``section`` of ``None``.
"""
section = None
content = []
for line in yield_lines(s):
if line.startswith("["):
if line.endswith("]"):
if section or content:
yield section, content
section = line[1:-1].strip()
content = []
else:
raise ValueError("Invalid section heading", line)
else:
content.append(line)

# wrap up last segment
yield section, content


def safe_extra(extra):
"""Convert an arbitrary string to a standard 'extra' name
Any runs of non-alphanumeric characters are replaced with a single '_',
and the result is always lowercased.
"""
return re.sub("[^A-Za-z0-9.-]+", "_", extra).lower()


def safe_name(name):
"""Convert an arbitrary string to a standard distribution name
Any runs of non-alphanumeric/. characters are replaced with a single '-'.
"""
return re.sub("[^A-Za-z0-9.]+", "-", name)


def requires_to_requires_dist(requirement: Requirement) -> str:
Expand All @@ -18,8 +88,8 @@ def requires_to_requires_dist(requirement: Requirement) -> str:
return " @ " + requirement.url

requires_dist = []
for op, ver in requirement.specs:
requires_dist.append(op + ver)
for spec in requirement.specifier:
requires_dist.append(spec.operator + spec.version)

if requires_dist:
return " (" + ",".join(sorted(requires_dist)) + ")"
Expand All @@ -30,13 +100,13 @@ def requires_to_requires_dist(requirement: Requirement) -> str:
def convert_requirements(requirements: list[str]) -> Iterator[str]:
"""Yield Requires-Dist: strings for parsed requirements strings."""
for req in requirements:
parsed_requirement = Requirement.parse(req)
parsed_requirement = Requirement(req)
spec = requires_to_requires_dist(parsed_requirement)
extras = ",".join(sorted(parsed_requirement.extras))
extras = ",".join(sorted(safe_extra(e) for e in parsed_requirement.extras))
if extras:
extras = f"[{extras}]"

yield parsed_requirement.project_name + extras + spec
yield safe_name(parsed_requirement.name) + extras + spec


def generate_requirements(
Expand Down

0 comments on commit f799533

Please sign in to comment.