|
2 | 2 | import collections
|
3 | 3 | import contextlib
|
4 | 4 | import functools
|
| 5 | +import importlib |
5 | 6 | import itertools
|
6 | 7 | import sys
|
7 | 8 | import types
|
@@ -181,11 +182,11 @@ def quoted(self):
|
181 | 182 | yield
|
182 | 183 | self._is_quoted.pop()
|
183 | 184 |
|
184 |
| - def add_import(self, imp: sym.Symbol): |
185 |
| - self.current_ns.add_import(imp) |
| 185 | + def add_import(self, imp: sym.Symbol, mod: types.ModuleType): |
| 186 | + self.current_ns.add_import(imp, mod) |
186 | 187 |
|
187 | 188 | @property
|
188 |
| - def imports(self): |
| 189 | + def imports(self) -> lmap.Map: |
189 | 190 | return self.current_ns.imports
|
190 | 191 |
|
191 | 192 | @property
|
@@ -225,15 +226,6 @@ def attr_node(node, idx):
|
225 | 226 | return attr_node(ast.Name(id=attrs[0], ctx=ast.Load()), 1)
|
226 | 227 |
|
227 | 228 |
|
228 |
| -def _is_py_module(name: str) -> bool: |
229 |
| - """Determine if a namespace is Python module.""" |
230 |
| - try: |
231 |
| - __import__(name) |
232 |
| - return True |
233 |
| - except ModuleNotFoundError: |
234 |
| - return False |
235 |
| - |
236 |
| - |
237 | 229 | class ASTNodeType(Enum):
|
238 | 230 | DEPENDENCY = 1
|
239 | 231 | NODE = 2
|
@@ -943,22 +935,32 @@ def _if_ast(ctx: CompilerContext, form: llist.List) -> ASTStream:
|
943 | 935 |
|
944 | 936 | def _import_ast(ctx: CompilerContext, form: llist.List) -> ASTStream:
|
945 | 937 | """Append Import statements into the compiler context nodes."""
|
946 |
| - assert form[0] == _IMPORT |
| 938 | + assert form.first == _IMPORT |
947 | 939 | assert all([isinstance(f, sym.Symbol) for f in form.rest])
|
948 | 940 |
|
949 |
| - import_names = [] |
| 941 | + last = None |
950 | 942 | for s in form.rest:
|
951 |
| - if not _is_py_module(s.name): |
| 943 | + try: |
| 944 | + module = importlib.import_module(s.name) |
| 945 | + ctx.add_import(s, module) |
| 946 | + except ModuleNotFoundError: |
952 | 947 | raise ImportError(f"Module '{s.name}' not found")
|
953 |
| - ctx.add_import(s) |
| 948 | + |
954 | 949 | with ctx.quoted():
|
| 950 | + module_name = s.name.split(".", maxsplit=1)[0] |
| 951 | + yield _dependency(ast.Global(names=[module_name])) |
| 952 | + yield _dependency(ast.Assign(targets=[ast.Name(id=module_name, ctx=ast.Store())], |
| 953 | + value=ast.Call(func=_load_attr("builtins.__import__"), |
| 954 | + args=[ast.Str(s.name)], |
| 955 | + keywords=[]))) |
| 956 | + last = ast.Name(id=module_name, ctx=ast.Load()) |
955 | 957 | yield _dependency(ast.Call(
|
956 | 958 | func=_load_attr(f'{_NS_VAR_VALUE}.add_import'),
|
957 |
| - args=_unwrap_nodes(_to_ast(ctx, s)), |
| 959 | + args=list(chain(_unwrap_nodes(_to_ast(ctx, s)), [last])), |
958 | 960 | keywords=[]))
|
959 |
| - import_names.append(ast.alias(name=s.name, asname=None)) |
960 |
| - yield _dependency(ast.Import(names=import_names)) |
961 |
| - yield _node(ast.NameConstant(None)) |
| 961 | + |
| 962 | + assert last is not None |
| 963 | + yield _node(last) |
962 | 964 |
|
963 | 965 |
|
964 | 966 | def _interop_call_ast(ctx: CompilerContext, form: llist.List) -> ASTStream:
|
@@ -1780,7 +1782,7 @@ def _module_imports(ctx: CompilerContext) -> Iterable[ast.Import]:
|
1780 | 1782 | 'basilisp.lang.vector': _VEC_ALIAS,
|
1781 | 1783 | 'basilisp.lang.util': _UTIL_ALIAS}
|
1782 | 1784 | return seq(ctx.imports) \
|
1783 |
| - .map(lambda s: s.name) \ |
| 1785 | + .map(lambda entry: entry.key.name) \ |
1784 | 1786 | .map(lambda name: (name, aliases.get(name, None))) \
|
1785 | 1787 | .map(lambda t: ast.Import(names=[ast.alias(name=t[0], asname=t[1])])) \
|
1786 | 1788 | .to_list()
|
|
0 commit comments