3
3
Code adapted from the find-imports project, currently in graveyard archive.
4
4
"""
5
5
import ast
6
- from inspect import Attribute
7
6
import os
8
7
import pkgutil
9
8
from pathlib import Path
10
- from typing import Union
11
9
from collections import namedtuple , defaultdict
12
10
from itertools import filterfalse , chain
13
11
@@ -18,38 +16,35 @@ class UnsupportedFileType(Exception):
18
16
pass
19
17
20
18
21
- ImportInfo = namedtuple ("ImportInfo" , ["packages" , "paths" ])
22
-
23
-
24
19
class NamespaceInfo :
25
20
def __init__ (self , source_fpath : Path ) -> None :
26
21
# expanding base_folder to absolute as pkgutils.FileFinder will do so - easier for later purging
27
22
self .base_folder = str (source_fpath .parent .absolute ())
28
23
self .source_mod_name = source_fpath .stem
29
24
self ._collect ()
30
25
# storing this as it will be useful for multiple lookups
31
- self ._all_namespace = set (chain (self .modules , self .packages ))
26
+ self ._all_namespace = set (chain (self .modules , self ._packages ))
32
27
33
28
def _collect (self ):
34
29
iter_modules_paths = [self .base_folder ]
35
30
for root , dirs , files in os .walk (self .base_folder ):
36
31
for dirname in dirs :
37
32
iter_modules_paths .append (os .path .join (root , dirname ))
38
33
39
- # need to consume generator as I will iterate two times for packages , and modules
34
+ # need to consume generator as I will iterate two times for _packages , and modules
40
35
pkg_mods = tuple (pkgutil .iter_modules (iter_modules_paths ))
41
36
modules = map (
42
37
lambda mi : os .path .join (mi .module_finder .path , mi .name ),
43
38
filterfalse (
44
39
lambda mi : mi .ispkg or mi .name == self .source_mod_name , pkg_mods
45
40
),
46
41
)
47
- packages = map (
42
+ _packages = map (
48
43
lambda mi : os .path .join (mi .module_finder .path , mi .name ),
49
44
filter (lambda mi : mi .ispkg , pkg_mods ),
50
45
)
51
46
self .modules = set (map (self ._dotted_path , modules ))
52
- self .packages = set (map (self ._dotted_path , packages ))
47
+ self ._packages = set (map (self ._dotted_path , _packages ))
53
48
54
49
def _dotted_path (self , p : str ):
55
50
p = p .replace (self .base_folder , "" ).replace (os .path .sep , "." )
@@ -61,41 +56,52 @@ def __contains__(self, item: str) -> bool:
61
56
return item in self ._all_namespace
62
57
63
58
def __str__ (self ) -> str :
64
- return f"NameSpace info for { self .base_folder } \n \t Modules: { self .modules } \n \t Packages: { self .packages } "
59
+ return f"NameSpace info for { self .base_folder } \n \t Modules: { self .modules } \n \t Packages: { self ._packages } "
65
60
66
61
def __repr__ (self ) -> str :
67
62
return str (self )
68
63
69
64
70
65
class FinderResult :
71
66
def __init__ (self ) -> None :
72
- self .packages = set ()
73
- self .locals = set ()
74
- self .unsupported = defaultdict (set )
67
+ self ._packages = set ()
68
+ self ._locals = set ()
69
+ self ._unsupported = defaultdict (set )
75
70
76
71
def add_package (self , pkg_name : str ) -> None :
77
- self .packages .add (pkg_name )
72
+ self ._packages .add (pkg_name )
78
73
79
74
def add_locals (self , pkg_name : str ) -> None :
80
- self .locals .add (pkg_name )
75
+ self ._locals .add (pkg_name )
81
76
82
77
def add_unsupported_external_package (self , pkg_name : str ) -> None :
83
- self .unsupported ["external" ].add (pkg_name )
78
+ self ._unsupported ["external" ].add (pkg_name )
84
79
85
80
def add_unsupported_local_package (self , pkg_name : str ) -> None :
86
- self .unsupported ["local" ].add (pkg_name )
81
+ self ._unsupported ["local" ].add (pkg_name )
87
82
88
83
@property
89
84
def has_warnings (self ):
90
- return len (self .unsupported ) > 0
85
+ return len (self ._unsupported ) > 0
91
86
92
87
@property
93
88
def unsupported_packages (self ):
94
- return self .unsupported ["external" ]
89
+ return self ._unsupported ["external" ]
95
90
96
91
@property
97
92
def unsupported_paths (self ):
98
- return self .unsupported ["local" ]
93
+ return self ._unsupported ["local" ]
94
+
95
+ @property
96
+ def packages (self ):
97
+ return self ._packages
98
+
99
+ @property
100
+ def paths (self ):
101
+ pyenv_paths = map (
102
+ lambda l : "{}.py" .format (l .replace ("." , os .path .sep )), self ._locals
103
+ )
104
+ return set (pyenv_paths )
99
105
100
106
101
107
# https://stackoverflow.com/a/58847554
@@ -123,7 +129,7 @@ def visit_ImportFrom(self, node):
123
129
124
130
def _import_name (self , imported ):
125
131
if imported in self .context :
126
- if imported not in self .context .packages :
132
+ if imported not in self .context ._packages :
127
133
self .results .add_locals (imported )
128
134
else :
129
135
self .results .add_unsupported_local_package (imported )
@@ -146,18 +152,7 @@ def _find_modules(source: str, source_fpath: Path):
146
152
147
153
finder = ModuleFinder (context = namespace_info )
148
154
finder .visit (nodes )
149
- report = finder .results
150
- pyenv_paths = map (
151
- lambda l : "{}.py" .format (l .replace ("." , os .path .sep )), report .locals
152
- )
153
- pyenv = ImportInfo (packages = report .packages , paths = set (pyenv_paths ))
154
- if not report .has_warnings :
155
- return pyenv , None
156
-
157
- warnings = ImportInfo (
158
- packages = report .unsupported_packages , paths = report .unsupported_paths
159
- )
160
- return pyenv , warnings
155
+ return finder .results
161
156
162
157
163
158
def _convert_notebook (source_fpath : Path ) -> str :
@@ -169,12 +164,10 @@ def _convert_notebook(source_fpath: Path) -> str:
169
164
return source
170
165
171
166
172
- def find_imports (
173
- source_fpath : Path ,
174
- ) -> Union [ImportInfo , tuple [ImportInfo , ImportInfo ]]:
167
+ def find_imports (source_fpath : Path ,) -> FinderResult :
175
168
"""
176
169
Parse the input source, and returns its dependencies, as organised in
177
- the sets of external packages , and local modules, respectively.
170
+ the sets of external _packages , and local modules, respectively.
178
171
Any modules or package with the same name found in the local
179
172
180
173
Parameters
@@ -184,11 +177,10 @@ def find_imports(
184
177
185
178
Returns
186
179
-------
187
- Union[ImportInfo, tuple[ImportInfo, ImportInfo]]
188
- The function returns an instance of `ImportInfo` containing the
189
- environment with packages and paths to include in py-env.
190
- Optionally, if the parsing detected unsupported packages and local modules,
191
- this will be returned as well (still as `ImportInfo` instance)
180
+ FinderResults
181
+ Return the results of parsing as a `FinderResults` instance.
182
+ This instance provides reference to packages and paths to
183
+ include in the py-env, as well as any unsuppoted import.
192
184
"""
193
185
fname , extension = source_fpath .name , source_fpath .suffix
194
186
if extension == ".py" :
0 commit comments