diff --git a/hy/compiler.py b/hy/compiler.py index 7e88579..062ee00 100644 --- a/hy/compiler.py +++ b/hy/compiler.py @@ -464,11 +464,47 @@ class HyASTCompiler(object): @builds("import") def compile_import_expression(self, expr): + def _compile_import(expr, module, names = None, importer = ast.Import): + return [ + importer( + lineno=expr.start_line, + col_offset=expr.start_column, + module=ast_str(module), + names=names or [ast.alias(name=ast_str(module), asname=None)], + level=0) + ] + expr.pop(0) # index - return ast.Import( - lineno=expr.start_line, - col_offset=expr.start_column, - names=[ast.alias(name=ast_str(x), asname=None) for x in expr]) + rimports = [] + while len(expr) > 0: + iexpr = expr.pop(0) + + if type(iexpr) == HySymbol: + rimports += _compile_import(expr, iexpr) + elif type(iexpr) == HyList and len(iexpr) == 1: + rimports += _compile_import(expr, iexpr.pop(0)) + elif type(iexpr) == HyList: + module = iexpr.pop(0) + if type(iexpr[0]) == HyKeyword and iexpr[0] == HyKeyword(":as"): + assert len(iexpr) == 2, "garbage after aliased import" + iexpr.pop(0) # :as + alias=iexpr.pop(0) + rimports += _compile_import(expr, ast_str(module), + [ast.alias(name=ast_str(module), + asname=ast_str(alias))]) + elif type(iexpr[0] == HyList): + symbol_list = iexpr.pop(0) + names = [] + while len(symbol_list) > 0: + sym = symbol_list.pop(0) + if len(symbol_list) > 0 and type(symbol_list[0]) == HyKeyword: + symbol_list.pop(0) + alias = ast_str(symbol_list.pop(0)) + else: + alias = None + names += [ast.alias(name=ast_str(sym), asname=alias)] + rimports += _compile_import(expr, module, names, ast.ImportFrom) + return rimports @builds("import_as") def compile_import_as_expression(self, expr): diff --git a/tests/native_tests/language.hy b/tests/native_tests/language.hy index eb0fdd7..bb945ec 100644 --- a/tests/native_tests/language.hy +++ b/tests/native_tests/language.hy @@ -560,3 +560,31 @@ (assert (= "foobar" (eval (quote "foobar")))) (setv x (quote 42)) (assert (= x (eval x)))) + +(defn test-import-syntax [] + "NATIVE: test the import syntax." + + ; Simple import + (import sys os) + + ; from os.path import basename + (import [os.path [basename]]) + (assert (= (basename "/some/path") "path")) + + ; import os.path as p + (import [os.path :as p]) + (assert (= p.basename basename)) + + ; from os.path import basename as bn + (import [os.path [basename :as bn]]) + (assert (= bn basename)) + + (import [sys]) + + ;; Multiple stuff to import + (import sys [os.path [dirname]] + [os.path :as op] + [os.path [dirname :as dn]]) + (assert (= (dirname "/some/path") "/some")) + (assert (= op.dirname dirname)) + (assert (= dn dirname)))