Skip to content

Commit de00f05

Browse files
committed
Improved find_imports encapsulation
find_imports functions now leverages directly on the FinderResults class to encapsualte parsing results.
1 parent 39c7fc2 commit de00f05

File tree

1 file changed

+34
-42
lines changed

1 file changed

+34
-42
lines changed

src/pyscript/_node_parser.py

Lines changed: 34 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@
33
Code adapted from the find-imports project, currently in graveyard archive.
44
"""
55
import ast
6-
from inspect import Attribute
76
import os
87
import pkgutil
98
from pathlib import Path
10-
from typing import Union
119
from collections import namedtuple, defaultdict
1210
from itertools import filterfalse, chain
1311

@@ -18,38 +16,35 @@ class UnsupportedFileType(Exception):
1816
pass
1917

2018

21-
ImportInfo = namedtuple("ImportInfo", ["packages", "paths"])
22-
23-
2419
class NamespaceInfo:
2520
def __init__(self, source_fpath: Path) -> None:
2621
# expanding base_folder to absolute as pkgutils.FileFinder will do so - easier for later purging
2722
self.base_folder = str(source_fpath.parent.absolute())
2823
self.source_mod_name = source_fpath.stem
2924
self._collect()
3025
# 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))
3227

3328
def _collect(self):
3429
iter_modules_paths = [self.base_folder]
3530
for root, dirs, files in os.walk(self.base_folder):
3631
for dirname in dirs:
3732
iter_modules_paths.append(os.path.join(root, dirname))
3833

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
4035
pkg_mods = tuple(pkgutil.iter_modules(iter_modules_paths))
4136
modules = map(
4237
lambda mi: os.path.join(mi.module_finder.path, mi.name),
4338
filterfalse(
4439
lambda mi: mi.ispkg or mi.name == self.source_mod_name, pkg_mods
4540
),
4641
)
47-
packages = map(
42+
_packages = map(
4843
lambda mi: os.path.join(mi.module_finder.path, mi.name),
4944
filter(lambda mi: mi.ispkg, pkg_mods),
5045
)
5146
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))
5348

5449
def _dotted_path(self, p: str):
5550
p = p.replace(self.base_folder, "").replace(os.path.sep, ".")
@@ -61,41 +56,52 @@ def __contains__(self, item: str) -> bool:
6156
return item in self._all_namespace
6257

6358
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}"
6560

6661
def __repr__(self) -> str:
6762
return str(self)
6863

6964

7065
class FinderResult:
7166
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)
7570

7671
def add_package(self, pkg_name: str) -> None:
77-
self.packages.add(pkg_name)
72+
self._packages.add(pkg_name)
7873

7974
def add_locals(self, pkg_name: str) -> None:
80-
self.locals.add(pkg_name)
75+
self._locals.add(pkg_name)
8176

8277
def add_unsupported_external_package(self, pkg_name: str) -> None:
83-
self.unsupported["external"].add(pkg_name)
78+
self._unsupported["external"].add(pkg_name)
8479

8580
def add_unsupported_local_package(self, pkg_name: str) -> None:
86-
self.unsupported["local"].add(pkg_name)
81+
self._unsupported["local"].add(pkg_name)
8782

8883
@property
8984
def has_warnings(self):
90-
return len(self.unsupported) > 0
85+
return len(self._unsupported) > 0
9186

9287
@property
9388
def unsupported_packages(self):
94-
return self.unsupported["external"]
89+
return self._unsupported["external"]
9590

9691
@property
9792
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)
99105

100106

101107
# https://stackoverflow.com/a/58847554
@@ -123,7 +129,7 @@ def visit_ImportFrom(self, node):
123129

124130
def _import_name(self, imported):
125131
if imported in self.context:
126-
if imported not in self.context.packages:
132+
if imported not in self.context._packages:
127133
self.results.add_locals(imported)
128134
else:
129135
self.results.add_unsupported_local_package(imported)
@@ -146,18 +152,7 @@ def _find_modules(source: str, source_fpath: Path):
146152

147153
finder = ModuleFinder(context=namespace_info)
148154
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
161156

162157

163158
def _convert_notebook(source_fpath: Path) -> str:
@@ -169,12 +164,10 @@ def _convert_notebook(source_fpath: Path) -> str:
169164
return source
170165

171166

172-
def find_imports(
173-
source_fpath: Path,
174-
) -> Union[ImportInfo, tuple[ImportInfo, ImportInfo]]:
167+
def find_imports(source_fpath: Path,) -> FinderResult:
175168
"""
176169
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.
178171
Any modules or package with the same name found in the local
179172
180173
Parameters
@@ -184,11 +177,10 @@ def find_imports(
184177
185178
Returns
186179
-------
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.
192184
"""
193185
fname, extension = source_fpath.name, source_fpath.suffix
194186
if extension == ".py":

0 commit comments

Comments
 (0)