@@ -215,6 +215,204 @@ def func_1():
215
215
assert call_site .file == consumer_file
216
216
217
217
218
+ def test_import_resolution_init_wildcard (tmpdir : str ) -> None :
219
+ """Tests that named import from a file with wildcard resolves properly"""
220
+ # language=python
221
+ content1 = """TEST_CONST=2
222
+ foo=9
223
+ """
224
+ content2 = """from testdir.test1 import *
225
+ bar=foo
226
+ test=TEST_CONST"""
227
+ content3 = """from testdir import TEST_CONST
228
+ test3=TEST_CONST"""
229
+ with get_codebase_session (tmpdir = tmpdir , files = {"testdir/test1.py" : content1 , "testdir/__init__.py" : content2 , "test3.py" : content3 }) as codebase :
230
+ file1 : SourceFile = codebase .get_file ("testdir/test1.py" )
231
+ file2 : SourceFile = codebase .get_file ("testdir/__init__.py" )
232
+ file3 : SourceFile = codebase .get_file ("test3.py" )
233
+
234
+ symb = file1 .get_symbol ("TEST_CONST" )
235
+ test = file2 .get_symbol ("test" )
236
+ test3 = file3 .get_symbol ("test3" )
237
+ test3_import = file3 .get_import ("TEST_CONST" )
238
+
239
+ assert len (symb .usages ) == 3
240
+ assert symb .symbol_usages == [test , test3 , test3_import ]
241
+
242
+
243
+ def test_import_resolution_wildcard_func (tmpdir : str ) -> None :
244
+ """Tests that named import from a file with wildcard resolves properly"""
245
+ # language=python
246
+ content1 = """
247
+ def foo():
248
+ pass
249
+ def bar():
250
+ pass
251
+ """
252
+ content2 = """
253
+ from testa import *
254
+
255
+ foo()
256
+ """
257
+
258
+ with get_codebase_session (tmpdir = tmpdir , files = {"testa.py" : content1 , "testb.py" : content2 }) as codebase :
259
+ testa : SourceFile = codebase .get_file ("testa.py" )
260
+ testb : SourceFile = codebase .get_file ("testb.py" )
261
+
262
+ foo = testa .get_symbol ("foo" )
263
+ bar = testa .get_symbol ("bar" )
264
+ assert len (foo .usages ) == 1
265
+ assert len (foo .call_sites ) == 1
266
+
267
+ assert len (bar .usages ) == 0
268
+ assert len (bar .call_sites ) == 0
269
+ assert len (testb .function_calls ) == 1
270
+
271
+
272
+ def test_import_resolution_chaining_wildcards (tmpdir : str ) -> None :
273
+ """Tests that chaining wildcard imports resolves properly"""
274
+ # language=python
275
+ content1 = """TEST_CONST=2
276
+ foo=9
277
+ """
278
+ content2 = """from testdir.test1 import *
279
+ bar=foo
280
+ test=TEST_CONST"""
281
+ content3 = """from testdir import *
282
+ test3=TEST_CONST"""
283
+ with get_codebase_session (tmpdir = tmpdir , files = {"testdir/test1.py" : content1 , "testdir/__init__.py" : content2 , "test3.py" : content3 }) as codebase :
284
+ file1 : SourceFile = codebase .get_file ("testdir/test1.py" )
285
+ file2 : SourceFile = codebase .get_file ("testdir/__init__.py" )
286
+ file3 : SourceFile = codebase .get_file ("test3.py" )
287
+
288
+ symb = file1 .get_symbol ("TEST_CONST" )
289
+ test = file2 .get_symbol ("test" )
290
+ bar = file2 .get_symbol ("bar" )
291
+ mid_import = file2 .get_import ("testdir.test1" )
292
+ test3 = file3 .get_symbol ("test3" )
293
+
294
+ assert len (symb .usages ) == 2
295
+ assert symb .symbol_usages == [test , test3 ]
296
+ assert mid_import .symbol_usages == [test , bar , test3 ]
297
+
298
+
299
+ def test_import_resolution_init_deep_nested_wildcards (tmpdir : str ) -> None :
300
+ """Tests that chaining wildcard imports resolves properly"""
301
+ # language=python
302
+
303
+ files = {
304
+ "test/nest/nest2/test1.py" : """test_const=5
305
+ test_not_used=2
306
+ test_used_parent=5
307
+ """ ,
308
+ "test/nest/nest2/__init__.py" : """from .test1 import *
309
+ t1=test_used_parent
310
+ """ ,
311
+ "test/nest/__init__.py" : """from .nest2 import *""" ,
312
+ "test/__init__.py" : """from .nest import *""" ,
313
+ "main.py" : """
314
+ from test import *
315
+ main_test=test_const
316
+ """ ,
317
+ }
318
+ with get_codebase_session (tmpdir = tmpdir , files = files ) as codebase :
319
+ deepest_layer : SourceFile = codebase .get_file ("test/nest/nest2/test1.py" )
320
+ main : SourceFile = codebase .get_file ("main.py" )
321
+ parent_file : SourceFile = codebase .get_file ("test/nest/nest2/__init__.py" )
322
+
323
+ main_test = main .get_symbol ("main_test" )
324
+ t1 = parent_file .get_symbol ("t1" )
325
+ test_const = deepest_layer .get_symbol ("test_const" )
326
+ test_not_used = deepest_layer .get_symbol ("test_not_used" )
327
+ test_used_parent = deepest_layer .get_symbol ("test_used_parent" )
328
+
329
+ assert len (test_const .usages ) == 1
330
+ assert test_const .usages [0 ].usage_symbol == main_test
331
+ assert len (test_not_used .usages ) == 0
332
+ assert len (test_used_parent .usages ) == 1
333
+ assert test_used_parent .usages [0 ].usage_symbol == t1
334
+
335
+
336
+ def test_import_resolution_chaining_many_wildcards (tmpdir : str ) -> None :
337
+ """Tests that chaining wildcard imports resolves properly"""
338
+ # language=python
339
+
340
+ files = {
341
+ "test1.py" : """
342
+ test_const=5
343
+ test_not_used=2
344
+ test_used_parent=5
345
+ """ ,
346
+ "test2.py" : """from test1 import *
347
+ t1=test_used_parent
348
+ """ ,
349
+ "test3.py" : """from test2 import *""" ,
350
+ "test4.py" : """from test3 import *""" ,
351
+ "main.py" : """
352
+ from test4 import *
353
+ main_test=test_const
354
+ """ ,
355
+ }
356
+ with get_codebase_session (tmpdir = tmpdir , files = files ) as codebase :
357
+ furthest_layer : SourceFile = codebase .get_file ("test1.py" )
358
+ main : SourceFile = codebase .get_file ("main.py" )
359
+ parent_file : SourceFile = codebase .get_file ("test2.py" )
360
+
361
+ main_test = main .get_symbol ("main_test" )
362
+ t1 = parent_file .get_symbol ("t1" )
363
+ test_const = furthest_layer .get_symbol ("test_const" )
364
+ test_not_used = furthest_layer .get_symbol ("test_not_used" )
365
+ test_used_parent = furthest_layer .get_symbol ("test_used_parent" )
366
+
367
+ assert len (test_const .usages ) == 1
368
+ assert test_const .usages [0 ].usage_symbol == main_test
369
+ assert len (test_not_used .usages ) == 0
370
+ assert len (test_used_parent .usages ) == 1
371
+ assert test_used_parent .usages [0 ].usage_symbol == t1
372
+
373
+
374
+ def test_import_resolution_init_deep_nested_wildcards_named (tmpdir : str ) -> None :
375
+ """Tests that chaining wildcard imports resolves properly"""
376
+ # language=python
377
+
378
+ files = {
379
+ "test/nest/nest2/test1.py" : """test_const=5
380
+ test_not_used=2
381
+ test_used_parent=5
382
+ """ ,
383
+ "test/nest/nest2/__init__.py" : """from .test1 import *
384
+ t1=test_used_parent
385
+ """ ,
386
+ "test/nest/__init__.py" : """from .nest2 import *""" ,
387
+ "test/__init__.py" : """from .nest import *""" ,
388
+ "main.py" : """
389
+ from test import test_const
390
+ main_test=test_const
391
+ """ ,
392
+ }
393
+ with get_codebase_session (tmpdir = tmpdir , files = files ) as codebase :
394
+ deepest_layer : SourceFile = codebase .get_file ("test/nest/nest2/test1.py" )
395
+ main : SourceFile = codebase .get_file ("main.py" )
396
+ parent_file : SourceFile = codebase .get_file ("test/nest/nest2/__init__.py" )
397
+ test_nest : SourceFile = codebase .get_file ("test/__init__.py" )
398
+
399
+ main_test = main .get_symbol ("main_test" )
400
+ t1 = parent_file .get_symbol ("t1" )
401
+ test_const = deepest_layer .get_symbol ("test_const" )
402
+ test_not_used = deepest_layer .get_symbol ("test_not_used" )
403
+ test_used_parent = deepest_layer .get_symbol ("test_used_parent" )
404
+
405
+ test_const_imp = main .get_import ("test_const" )
406
+
407
+ assert len (test_const .usages ) == 2
408
+ assert test_const .usages [0 ].usage_symbol == main_test
409
+ assert test_const .usages [1 ].usage_symbol == test_const_imp
410
+
411
+ assert len (test_not_used .usages ) == 0
412
+ assert len (test_used_parent .usages ) == 1
413
+ assert test_used_parent .usages [0 ].usage_symbol == t1
414
+
415
+
218
416
def test_import_resolution_circular (tmpdir : str ) -> None :
219
417
"""Tests function.usages returns usages from file imports"""
220
418
# language=python
@@ -367,4 +565,66 @@ def test_import_wildcard_preserves_import_resolution(tmpdir: str) -> None:
367
565
) as codebase :
368
566
mainfile : SourceFile = codebase .get_file ("file.py" )
369
567
370
- assert len (mainfile .ctx .edges ) == 5
568
+ assert len (mainfile .ctx .edges ) == 10
569
+
570
+
571
+ def test_import_resolution_init_wildcard_no_dupe (tmpdir : str ) -> None :
572
+ """Tests that named import from a file with wildcard resolves properly and doesn't
573
+ result in duplicate usages
574
+ """
575
+ # language=python
576
+ content1 = """TEST_CONST=2
577
+ foo=9
578
+ """
579
+ content2 = """from testdir.test1 import *
580
+ bar=foo
581
+ test=TEST_CONST"""
582
+ content3 = """from testdir import TEST_CONST
583
+ test3=TEST_CONST"""
584
+ content4 = """from testdir import foo
585
+ test4=foo"""
586
+ with get_codebase_session (tmpdir = tmpdir , files = {"testdir/test1.py" : content1 , "testdir/__init__.py" : content2 , "test3.py" : content3 , "test4.py" : content4 }) as codebase :
587
+ file1 : SourceFile = codebase .get_file ("testdir/test1.py" )
588
+ file2 : SourceFile = codebase .get_file ("testdir/__init__.py" )
589
+ file3 : SourceFile = codebase .get_file ("test3.py" )
590
+
591
+ symb = file1 .get_symbol ("TEST_CONST" )
592
+ test = file2 .get_symbol ("test" )
593
+ test3 = file3 .get_symbol ("test3" )
594
+ test3_import = file3 .get_import ("TEST_CONST" )
595
+
596
+ assert len (symb .usages ) == 3
597
+ assert symb .symbol_usages == [test , test3 , test3_import ]
598
+
599
+
600
+ def test_import_resolution_init_wildcard_chainging_deep (tmpdir : str ) -> None :
601
+ """Tests that named import from a file with wildcard resolves properly and doesn't
602
+ result in duplicate usages
603
+ """
604
+ # language=python
605
+ content1 = """TEST_CONST=2
606
+ """
607
+ content2 = """from .file1 import *"""
608
+ content3 = """from .dir import *"""
609
+ content4 = """from .dir import TEST_CONST
610
+ test1=TEST_CONST"""
611
+ with get_codebase_session (
612
+ tmpdir = tmpdir ,
613
+ files = {
614
+ "dir/dir/dir/dir/file1.py" : content1 ,
615
+ "dir/dir/dir/dir/__init__.py" : content2 ,
616
+ "dir/dir/dir/__init__.py" : content3 ,
617
+ "dir/dir/__init__.py" : content3 ,
618
+ "dir/__init__.py" : content3 ,
619
+ "file2.py" : content4 ,
620
+ },
621
+ ) as codebase :
622
+ file1 : SourceFile = codebase .get_file ("dir/dir/dir/dir/file1.py" )
623
+ file2 : SourceFile = codebase .get_file ("file2.py" )
624
+
625
+ symb = file1 .get_symbol ("TEST_CONST" )
626
+ test1 = file2 .get_symbol ("test1" )
627
+ imp = file2 .get_import ("TEST_CONST" )
628
+
629
+ assert len (symb .usages ) == 2
630
+ assert symb .symbol_usages == [test1 , imp ]
0 commit comments