14
14
from pathlib import Path
15
15
16
16
17
+ class SetupReaderError (Exception ):
18
+ pass
19
+
20
+
17
21
class SetupReader :
18
22
"""
19
23
Class that reads a setup.py file without executing it.
@@ -192,77 +196,77 @@ def _find_sub_setup_call(
192
196
return None
193
197
194
198
def _find_install_requires (self , call : ast .Call , body : list [ast .stmt ]) -> list [str ]:
195
- install_requires : list [str ] = []
196
199
value = self ._find_in_call (call , "install_requires" )
197
200
if value is None :
198
201
# Trying to find in kwargs
199
202
kwargs = self ._find_call_kwargs (call )
200
203
201
204
if kwargs is None or not isinstance (kwargs , ast .Name ):
202
- return install_requires
205
+ return []
203
206
204
207
variable = self ._find_variable_in_body (body , kwargs .id )
205
- if not isinstance (variable , (ast .Dict , ast .Call )):
206
- return install_requires
207
-
208
- if isinstance (variable , ast .Call ):
209
- if not isinstance (variable .func , ast .Name ):
210
- return install_requires
211
208
212
- if variable . func . id != "dict" :
213
- return install_requires
209
+ if isinstance ( variable , ast . Dict ) :
210
+ value = self . _find_in_dict ( variable , " install_requires" )
214
211
212
+ elif (
213
+ isinstance (variable , ast .Call )
214
+ and isinstance (variable .func , ast .Name )
215
+ and variable .func .id == "dict"
216
+ ):
215
217
value = self ._find_in_call (variable , "install_requires" )
218
+
216
219
else :
217
- value = self . _find_in_dict ( variable , "install_requires " )
220
+ raise SetupReaderError ( f"Cannot handle variable { variable } " )
218
221
219
222
if value is None :
220
- return install_requires
223
+ return []
224
+
225
+ if isinstance (value , ast .Constant ) and value .value is None :
226
+ return []
221
227
222
228
if isinstance (value , ast .List ):
223
- for el in value .elts :
224
- if isinstance (el , ast .Constant ) and isinstance (el .value , str ):
225
- install_requires .append (el .value )
226
- elif isinstance (value , ast .Name ):
227
- variable = self ._find_variable_in_body (body , value .id )
229
+ return string_list_values (value )
228
230
231
+ if isinstance (value , ast .Name ):
232
+ variable = self ._find_variable_in_body (body , value .id )
229
233
if variable is not None and isinstance (variable , ast .List ):
230
- for el in variable .elts :
231
- if isinstance (el , ast .Constant ) and isinstance (el .value , str ):
232
- install_requires .append (el .value )
234
+ return string_list_values (variable )
233
235
234
- return install_requires
236
+ raise SetupReaderError ( f"Cannot handle value of type { type ( value ) } " )
235
237
236
238
def _find_extras_require (
237
239
self , call : ast .Call , body : list [ast .stmt ]
238
240
) -> dict [str , list [str ]]:
239
- extras_require : dict [str , list [str ]] = {}
240
241
value = self ._find_in_call (call , "extras_require" )
241
242
if value is None :
242
243
# Trying to find in kwargs
243
244
kwargs = self ._find_call_kwargs (call )
244
245
245
246
if kwargs is None or not isinstance (kwargs , ast .Name ):
246
- return extras_require
247
+ return {}
247
248
248
249
variable = self ._find_variable_in_body (body , kwargs .id )
249
- if not isinstance (variable , (ast .Dict , ast .Call )):
250
- return extras_require
251
-
252
- if isinstance (variable , ast .Call ):
253
- if not isinstance (variable .func , ast .Name ):
254
- return extras_require
255
-
256
- if variable .func .id != "dict" :
257
- return extras_require
250
+ if isinstance (variable , ast .Dict ):
251
+ value = self ._find_in_dict (variable , "extras_require" )
258
252
253
+ elif (
254
+ isinstance (variable , ast .Call )
255
+ and isinstance (variable .func , ast .Name )
256
+ and variable .func .id == "dict"
257
+ ):
259
258
value = self ._find_in_call (variable , "extras_require" )
259
+
260
260
else :
261
- value = self . _find_in_dict ( variable , "extras_require " )
261
+ raise SetupReaderError ( f"Cannot handle variable { variable } " )
262
262
263
263
if value is None :
264
- return extras_require
264
+ return {}
265
+
266
+ if isinstance (value , ast .Constant ) and value .value is None :
267
+ return {}
265
268
269
+ extras_require : dict [str , list [str ]] = {}
266
270
if isinstance (value , ast .Dict ):
267
271
val : ast .expr | None
268
272
for key , val in zip (value .keys , value .values ):
@@ -272,17 +276,18 @@ def _find_extras_require(
272
276
if isinstance (val , ast .Name ):
273
277
val = self ._find_variable_in_body (body , val .id )
274
278
275
- if isinstance (val , ast .List ):
276
- extras_require [key .value ] = [
277
- e .value
278
- for e in val .elts
279
- if isinstance (e , ast .Constant ) and isinstance (e .value , str )
280
- ]
281
- elif isinstance (value , ast .Name ):
279
+ if not isinstance (val , ast .List ):
280
+ raise SetupReaderError (f"Cannot handle value of type { type (val )} " )
281
+
282
+ extras_require [key .value ] = string_list_values (val )
283
+
284
+ return extras_require
285
+
286
+ if isinstance (value , ast .Name ):
282
287
variable = self ._find_variable_in_body (body , value .id )
283
288
284
289
if variable is None or not isinstance (variable , ast .Dict ):
285
- return extras_require
290
+ return {}
286
291
287
292
for key , val in zip (variable .keys , variable .values ):
288
293
if not isinstance (key , ast .Constant ) or not isinstance (key .value , str ):
@@ -291,14 +296,14 @@ def _find_extras_require(
291
296
if isinstance (val , ast .Name ):
292
297
val = self ._find_variable_in_body (body , val .id )
293
298
294
- if isinstance (val , ast .List ):
295
- extras_require [ key . value ] = [
296
- e . value
297
- for e in val . elts
298
- if isinstance ( e , ast . Constant ) and isinstance ( e . value , str )
299
- ]
299
+ if not isinstance (val , ast .List ):
300
+ raise SetupReaderError ( f"Cannot handle value of type { type ( val ) } " )
301
+
302
+ extras_require [ key . value ] = string_list_values ( val )
303
+
304
+ return extras_require
300
305
301
- return extras_require
306
+ raise SetupReaderError ( f"Cannot handle value of type { type ( value ) } " )
302
307
303
308
def _find_single_string (
304
309
self , call : ast .Call , body : list [ast .stmt ], name : str
@@ -383,3 +388,15 @@ def _find_in_dict(self, dict_: ast.Dict, name: str) -> ast.expr | None:
383
388
return val
384
389
385
390
return None
391
+
392
+
393
+ def string_list_values (value : ast .List ) -> list [str ]:
394
+ strings = []
395
+ for element in value .elts :
396
+ if isinstance (element , ast .Constant ) and isinstance (element .value , str ):
397
+ strings .append (element .value )
398
+
399
+ else :
400
+ raise SetupReaderError ("Found non-string element in list" )
401
+
402
+ return strings
0 commit comments