Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

drop use of deprecated pkg_resources #508

Merged
merged 7 commits into from
Mar 11, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/news.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Release Notes

- Updated vendored ``packaging`` to 23.0
- Fixed spaces in platform names not being converted to underscores (PR by David Tucker)
- Drop use of deprecated ``pkg_resources`` (PR by Thomas Grainger)
agronholm marked this conversation as resolved.
Show resolved Hide resolved

**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
Loading