Skip to content

Commit b5ab8aa

Browse files
committed
Replace use of pkg_resources with importlib.metadata and packaging
1 parent 01bc97a commit b5ab8aa

File tree

3 files changed

+33
-50
lines changed

3 files changed

+33
-50
lines changed

liccheck/command_line.py

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@
22
import collections
33
import os.path
44

5-
from liccheck.requirements import parse_requirements, resolve, resolve_without_deps
5+
from liccheck.requirements import parse_requirements, resolve
66

77
from configparser import ConfigParser, NoOptionError
88
import enum
99
import functools
1010
import re
1111
import textwrap
12+
from packaging.requirements import Requirement
1213
import sys
1314
import semantic_version
1415
import toml
@@ -138,10 +139,7 @@ class Reason(enum.Enum):
138139

139140

140141
def get_packages_info(requirement_file, no_deps=False):
141-
regex_license = re.compile(r"License(?:-Expression)?: (?P<license>.*)?$", re.M)
142-
regex_classifier = re.compile(
143-
r"Classifier: License(?: :: OSI Approved)?(?: :: (?P<classifier>.*))?$", re.M
144-
)
142+
regex_classifier = re.compile(r"^License(?: :: OSI Approved)?(?: :: (?P<classifier>.*))?$")
145143

146144
requirements = parse_requirements(requirement_file)
147145

@@ -153,31 +151,27 @@ def transform(dist):
153151
licenses = list(set([strip_license(l) for l in licenses]))
154152

155153
return {
156-
"name": dist.project_name,
154+
"name": dist.name,
157155
"version": dist.version,
158-
"location": dist.location,
159-
"dependencies": [dependency.project_name for dependency in dist.requires()],
156+
"dependencies": [Requirement(r).name for r in dist.requires] if dist.requires is not None else [],
160157
"licenses": licenses,
161158
}
162159

163160
def get_license(dist):
164-
if dist.has_metadata(dist.PKG_INFO):
165-
metadata = dist.get_metadata(dist.PKG_INFO)
166-
match = regex_license.search(metadata)
167-
if match:
168-
license = match.group("license")
169-
if license != "UNKNOWN": # Value when license not specified.
170-
return [license]
161+
if dist.metadata is not None:
162+
license = dist.metadata.get('License-Expression') or dist.metadata.get('License')
163+
if license is not None:
164+
return [license]
171165

172166
return []
173167

174168
def get_licenses_from_classifiers(dist):
175-
if dist.has_metadata(dist.PKG_INFO):
176-
metadata = dist.get_metadata(dist.PKG_INFO)
177-
178-
# match might be found, but None if using the classifier:
179-
# License :: OSI Approved
180-
return [m for m in regex_classifier.findall(metadata) if m]
169+
if dist.metadata is not None:
170+
classifiers = dist.metadata.get_all('Classifier')
171+
if classifiers is not None:
172+
# match might be found, but None if using the classifier:
173+
# License :: OSI Approved
174+
return [l.group(1) for l in [regex_classifier.match(m) for m in classifiers] if l]
181175

182176
return []
183177

@@ -191,11 +185,12 @@ def strip_license(license):
191185
return license[: -len(" license")]
192186
return license
193187

194-
resolve_func = resolve_without_deps if no_deps else resolve
195-
packages = [transform(dist) for dist in resolve_func(requirements)]
188+
packages = [transform(dist) for dist in resolve(requirements, without_deps=no_deps)]
196189
# keep only unique values as there are maybe some duplicates
197190
unique = []
198-
[unique.append(item) for item in packages if item not in unique]
191+
for item in packages:
192+
if item not in unique:
193+
unique.append(item)
199194

200195
return sorted(unique, key=(lambda item: item["name"].lower()))
201196

liccheck/requirements.py

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
import pkg_resources
1+
import importlib.metadata as ilm
2+
from packaging.markers import Marker, default_environment
3+
from packaging.requirements import Requirement
24

35
try:
46
from pip._internal.network.session import PipSession
@@ -24,29 +26,21 @@ def parse_requirements(requirement_file):
2426
requirements = []
2527
for req in pip_parse_requirements(requirement_file, session=PipSession()):
2628
install_req = install_req_from_parsed_requirement(req)
27-
if install_req.markers and not pkg_resources.evaluate_marker(str(install_req.markers)):
29+
if install_req.markers is not None and not install_req.markers.evaluate():
2830
# req should not installed due to env markers
2931
continue
3032
elif install_req.editable:
3133
# skip editable req as they are failing in the resolve phase
3234
continue
33-
requirements.append(pkg_resources.Requirement.parse(str(install_req.req)))
35+
requirements.append(install_req.req)
3436
return requirements
3537

3638

37-
def resolve_without_deps(requirements):
38-
working_set = pkg_resources.working_set
39+
def resolve(requirements, without_deps=False):
3940
for req in requirements:
40-
env = pkg_resources.Environment(working_set.entries)
41-
dist = env.best_match(
42-
req=req,
43-
working_set=working_set,
44-
installer=None,
45-
replace_conflicting=False,
46-
)
47-
yield dist
48-
49-
50-
def resolve(requirements):
51-
for dist in pkg_resources.working_set.resolve(requirements):
41+
dist = ilm.distribution(req.name)
5242
yield dist
43+
if not without_deps and dist.requires is not None:
44+
requires = [Requirement(r) for r in dist.requires]
45+
requires = [r for r in requires if r.marker is None or r.marker.evaluate()]
46+
yield from resolve(requires)

tests/test_get_packages_info.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import sys
22

3-
import pkg_resources
3+
import importlib.metadata as ilm
44
import pytest
55

66
from liccheck.command_line import get_packages_info
@@ -24,10 +24,7 @@ def test_license_strip_with_return_carriage(tmp_path, mocker):
2424
tmpfh.write(b"Name: pip\r\n")
2525
tmpfh.write(b"Version: 23.3.1\r\n")
2626
tmpfh.write(b"Classifier: License :: OSI Approved :: MIT License\r\n")
27-
metadata = pkg_resources.PathMetadata(tmp_path, tmp_path)
28-
resolve.return_value = [
29-
pkg_resources.Distribution(project_name="pip", metadata=metadata)
30-
]
27+
resolve.return_value = [ilm.Distribution.at(tmp_path)]
3128
assert get_packages_info(req_path)[0]["licenses"] == ["MIT"]
3229

3330

@@ -86,8 +83,5 @@ def test_license_expression(tmp_path, mocker):
8683
tmpfh.write("Name: Twisted\n")
8784
tmpfh.write("Version: 23.8.0\n")
8885
tmpfh.write("License-Expression: MIT\n")
89-
metadata = pkg_resources.FileMetadata(pkg_info_path)
90-
resolve.return_value = [
91-
pkg_resources.Distribution(project_name="Twisted", metadata=metadata)
92-
]
86+
resolve.return_value = [ilm.Distribution.at(tmp_path)]
9387
assert get_packages_info(req_path)[0]["licenses"] == ["MIT"]

0 commit comments

Comments
 (0)