2
2
"""
3
3
from __future__ import annotations
4
4
5
+ import re
5
6
from importlib import metadata
6
7
from pathlib import Path
7
8
from typing import Any
@@ -56,8 +57,10 @@ def _doGetReqs(
56
57
using : str , extras : str | None , pyproject : dict [str , Any ], requirementsPaths : list [Path ]
57
58
) -> set [ucstr ]:
58
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
59
61
60
62
reqs = set ()
63
+ extras_reqs = dict ()
61
64
62
65
if using == "poetry" :
63
66
try :
@@ -75,8 +78,12 @@ def _doGetReqs(
75
78
reqLists .append (project .get ("dev-dependencies" , {}))
76
79
for reqList in reqLists :
77
80
for req in reqList :
78
- reqs .add (resolveReq (req ))
79
-
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 ))
80
87
# PEP631 (hatch)
81
88
if using == "PEP631" :
82
89
try :
@@ -90,7 +97,12 @@ def _doGetReqs(
90
97
reqLists .extend (project ["optional-dependencies" ][x ] for x in extras .split (";" ))
91
98
for reqList in reqLists :
92
99
for req in reqList :
93
- reqs .add (resolveReq (req ))
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 ))
94
106
95
107
# Requirements
96
108
if using == "requirements" :
@@ -100,7 +112,12 @@ def _doGetReqs(
100
112
101
113
with open (reqPath , encoding = "utf-8" ) as requirementsTxt :
102
114
for req in requirements .parse (requirementsTxt ):
103
- reqs .add (str (req .name ).lower ())
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 ))
104
121
105
122
try :
106
123
reqs .remove ("PYTHON" )
@@ -115,16 +132,19 @@ def _doGetReqs(
115
132
for req in [resolveReq (req ) for req in pkgMetadata .get_all ("Requires-Dist" ) or []]:
116
133
requirementsWithDeps .add (req )
117
134
except metadata .PackageNotFoundError :
118
- request = session .get (f"https://pypi.org/pypi/{ requirement } /json" , timeout = 60 )
135
+ request = session .get (f"https://pypi.org/pypi/{ requirement . split ( '[' )[ 0 ] } /json" , timeout = 60 )
119
136
response = request .json ()
120
137
try :
121
- for req in [resolveReq (req ) for req in response ["info" ]["requires_dist" ]]:
122
- requirementsWithDeps .add (req )
138
+ 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
+ else :
143
+ requirementsWithDeps .add (resolveReq (dependency ))
123
144
except (KeyError , TypeError ):
124
145
pass
125
146
126
- return requirementsWithDeps
127
-
147
+ return {r .split ('[' )[0 ] for r in requirementsWithDeps }
128
148
129
149
def getDepsWithLicenses (
130
150
using : str ,
0 commit comments