7
7
from pathlib import Path
8
8
from typing import Any
9
9
10
- import pkg_resources
11
- import requirements
12
10
import tomli
11
+ from packaging .requirements import Requirement
12
+ from packaging .utils import canonicalize_name
13
13
14
14
from licensecheck import license_matrix , packageinfo
15
15
from licensecheck .types import JOINS , License , PackageInfo , session , ucstr
@@ -56,11 +56,25 @@ def getReqs(using: str) -> set[ucstr]:
56
56
def _doGetReqs (
57
57
using : str , extras : str | None , pyproject : dict [str , Any ], requirementsPaths : list [Path ]
58
58
) -> set [ucstr ]:
59
- resolveReq = lambda req : ucstr (pkg_resources .Requirement .parse (req ).project_name )
60
- resolveExtraReq = lambda extra_req : re .sub ("extra == " , "" , re .findall (r"extra == '.*?'" ,extra_req )[0 ].replace ("'" , "" )) if len (re .findall (r"extra == '.*?'" ,extra_req )) > 0 else None
61
59
62
60
reqs = set ()
63
- extras_reqs = dict ()
61
+ extrasReqs = {}
62
+
63
+ def resolveReq (req : str , extra : bool = True ) -> ucstr :
64
+ requirement = Requirement (req )
65
+ extras = {ucstr (extra ) for extra in requirement .extras }
66
+ name = ucstr (canonicalize_name (requirement .name ))
67
+ canonicalName = name
68
+ if len (extras ) > 0 :
69
+ canonicalName = ucstr (f"{ name } [{ list (extras )[0 ]} ]" )
70
+ extrasReqs [name ] = extras
71
+ return canonicalName if extra else name
72
+
73
+ def resolveExtraReq (extraReq : str ) -> ucstr | None :
74
+ match = re .search (r"extra\s*==\s*'(.*?)'" , extraReq )
75
+ if match is None :
76
+ return None
77
+ return ucstr (match .group (1 ))
64
78
65
79
if using == "poetry" :
66
80
try :
@@ -78,12 +92,7 @@ def _doGetReqs(
78
92
reqLists .append (project .get ("dev-dependencies" , {}))
79
93
for reqList in reqLists :
80
94
for req in reqList :
81
- try :
82
- extra = re .search (r'(?<=\[)(.*?)(?=\])' ,req ).group (0 )
83
- extras_reqs [resolveReq (req )] = extra
84
- reqs .add (f"{ resolveReq (req )} [{ extra } ]" )
85
- except (KeyError , AttributeError ):
86
- reqs .add (resolveReq (req ))
95
+ reqs .add (resolveReq (req ))
87
96
# PEP631 (hatch)
88
97
if using == "PEP631" :
89
98
try :
@@ -97,27 +106,19 @@ def _doGetReqs(
97
106
reqLists .extend (project ["optional-dependencies" ][x ] for x in extras .split (";" ))
98
107
for reqList in reqLists :
99
108
for req in reqList :
100
- try :
101
- extra = re .search (r'(?<=\[)(.*?)(?=\])' ,req ).group (0 )
102
- extras_reqs [resolveReq (req )] = extra
103
- reqs .add (f"{ resolveReq (req )} [{ extra } ]" )
104
- except (KeyError , AttributeError ):
105
- reqs .add (resolveReq (req ))
109
+ reqs .add (resolveReq (req ))
106
110
107
111
# Requirements
108
112
if using == "requirements" :
109
113
for reqPath in requirementsPaths :
110
114
if not reqPath .exists ():
111
115
raise RuntimeError (f"Could not find specification of requirements ({ reqPath } )." )
112
116
113
- with open (reqPath , encoding = "utf-8" ) as requirementsTxt :
114
- for req in requirements .parse (requirementsTxt ):
115
- if len (req .extras )> 0 :
116
- extras_reqs [resolveReq (req .name )] = req .extras
117
- for extra in req .extras :
118
- reqs .add (f"{ resolveReq (req .name )} [{ extra } ]" )
119
- else :
120
- reqs .add (resolveReq (req .name ))
117
+ for line in reqPath .read_text (encoding = "utf-8" ).splitlines ():
118
+ line = line .strip ()
119
+ if not line or line [0 ] in {"#" , "-" }:
120
+ continue
121
+ reqs .add (resolveReq (line ))
121
122
122
123
try :
123
124
reqs .remove ("PYTHON" )
@@ -132,19 +133,26 @@ def _doGetReqs(
132
133
for req in [resolveReq (req ) for req in pkgMetadata .get_all ("Requires-Dist" ) or []]:
133
134
requirementsWithDeps .add (req )
134
135
except metadata .PackageNotFoundError :
135
- request = session .get (f"https://pypi.org/pypi/{ requirement .split ('[' )[0 ]} /json" , timeout = 60 )
136
+ request = session .get (
137
+ f"https://pypi.org/pypi/{ requirement .split ('[' )[0 ]} /json" , timeout = 60
138
+ )
136
139
response = request .json ()
137
140
try :
138
141
for dependency in response ["info" ]["requires_dist" ]:
139
- if resolveExtraReq (dependency ) is not None :
140
- if (resolveReq (requirement ) in extras_reqs .keys ()) and (resolveExtraReq (dependency ) in extras_reqs [resolveReq (requirement )]):
141
- requirementsWithDeps .add (resolveReq (dependency ))
142
+ dep = resolveReq (dependency , False )
143
+ req = resolveReq (requirement , False )
144
+ extra = resolveExtraReq (dependency )
145
+ if extra is not None :
146
+ if req in extrasReqs and extra in extrasReqs .get (req , []):
147
+ requirementsWithDeps .add (dep )
148
+ # else: pass
142
149
else :
143
- requirementsWithDeps .add (resolveReq ( dependency ) )
150
+ requirementsWithDeps .add (dep )
144
151
except (KeyError , TypeError ):
145
152
pass
146
153
147
- return {r .split ('[' )[0 ] for r in requirementsWithDeps }
154
+ return {r .split ("[" )[0 ] for r in requirementsWithDeps }
155
+
148
156
149
157
def getDepsWithLicenses (
150
158
using : str ,
0 commit comments