diff --git a/CHANGELOG.md b/CHANGELOG.md index 2af0eeee..94efd8db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added * Added support for Python 3.14 (#1282) +### Fixed + * Fix a bug where `import` refers would incorrectly be applied to all import modules in the same form (#1274) + ### Removed * Removed support for Python 3.9 (#1283) @@ -33,7 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed * Fix a bug where protocols with methods with leading hyphens in method names could not be defined (#1230) * Fix a bug where attempting to `:refer` a non-existent Var from another namespace would throw an unhelpful exception (#1231) - * Fixed a bug where `(range 0)` would return `(0)` rather than than `()` as expected (#1258) + * Fix a bug where `(range 0)` would return `(0)` rather than `()` as expected (#1258) ## [v0.3.8] ### Added diff --git a/src/basilisp/lang/compiler/analyzer.py b/src/basilisp/lang/compiler/analyzer.py index 94ec4764..a73af115 100644 --- a/src/basilisp/lang/compiler/analyzer.py +++ b/src/basilisp/lang/compiler/analyzer.py @@ -2574,8 +2574,9 @@ def _do_warn_on_import_or_require_name_clash( def _import_ast(form: ISeq, ctx: AnalyzerContext) -> Import: assert form.first == SpecialForm.IMPORT - aliases, refers, refer_all = [], [], False + aliases = [] for f in form.rest: # pylint: disable=too-many-nested-blocks + refers, refer_all = [], False if isinstance(f, sym.Symbol): module_name = f module_alias = None @@ -2678,6 +2679,8 @@ def _import_ast(form: ISeq, ctx: AnalyzerContext) -> Import: form=f, name=module_name.name, alias=module_alias, + refers=refers, + refer_all=refer_all, env=ctx.get_node_env(), ) ) @@ -2691,8 +2694,6 @@ def _import_ast(form: ISeq, ctx: AnalyzerContext) -> Import: return Import( form=form, aliases=aliases, - refers=refers, - refer_all=refer_all, env=ctx.get_node_env(pos=ctx.syntax_position), ) diff --git a/src/basilisp/lang/compiler/generator.py b/src/basilisp/lang/compiler/generator.py index 7e9ee898..431803dc 100644 --- a/src/basilisp/lang/compiler/generator.py +++ b/src/basilisp/lang/compiler/generator.py @@ -2411,7 +2411,7 @@ def _import_to_py_ast(ctx: GeneratorContext, node: Import) -> GeneratedPyAST[ast ) refers: Optional[ast.expr] = None - if node.refer_all: + if alias.refer_all: key, val = genname("k"), genname("v") refers = ast.DictComp( key=ast.Call( @@ -2447,10 +2447,10 @@ def _import_to_py_ast(ctx: GeneratorContext, node: Import) -> GeneratedPyAST[ast ) ], ) - elif node.refers: + elif alias.refers: refer_keys: list[Optional[ast.expr]] = [] refer_vals: list[ast.expr] = [] - for refer in node.refers: + for refer in alias.refers: refer_keys.append( ast.Call( func=_NEW_SYM_FN_NAME, args=[ast.Constant(refer)], keywords=[] diff --git a/src/basilisp/lang/compiler/nodes.py b/src/basilisp/lang/compiler/nodes.py index 36067f24..ff460554 100644 --- a/src/basilisp/lang/compiler/nodes.py +++ b/src/basilisp/lang/compiler/nodes.py @@ -613,8 +613,6 @@ class If(Node[SpecialForm]): class Import(Node[SpecialForm]): form: SpecialForm aliases: Iterable["ImportAlias"] - refers: Iterable[str] - refer_all: bool env: NodeEnv = attr.field(hash=False) children: Sequence[kw.Keyword] = vec.EMPTY op: NodeOp = NodeOp.IMPORT @@ -627,6 +625,8 @@ class ImportAlias(Node[Union[sym.Symbol, vec.PersistentVector]]): form: Union[sym.Symbol, vec.PersistentVector] name: str alias: Optional[str] + refers: Iterable[str] + refer_all: bool env: NodeEnv = attr.field(hash=False) children: Sequence[kw.Keyword] = vec.EMPTY op: NodeOp = NodeOp.IMPORT_ALIAS diff --git a/tests/basilisp/compiler_test.py b/tests/basilisp/compiler_test.py index 6efb7412..be2b8d56 100644 --- a/tests/basilisp/compiler_test.py +++ b/tests/basilisp/compiler_test.py @@ -3572,6 +3572,17 @@ def test_multi_import(self, lcompile: CompileFn): ) ) + def test_multi_import_with_refer(self, lcompile: CompileFn): + import sys + from os import mkdir + + assert [sys, mkdir] == list( + lcompile("(import sys [os :refer [mkdir]]) [sys mkdir]") + ) + assert [sys, mkdir] == list( + lcompile("(import [os :refer [mkdir]] sys) [sys mkdir]") + ) + def test_nested_imports_visible_with_parent(self, lcompile: CompileFn): import collections.abc