diff --git a/Cargo.toml b/Cargo.toml index 68214c2..ffb03fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,9 +22,9 @@ edition = "2021" repository = "https://github.com/mtshiba/pylyzer" [workspace.dependencies] -erg_common = { version = "0.6.40-nightly.1", features = ["py_compat", "els"] } -erg_compiler = { version = "0.6.40-nightly.1", features = ["py_compat", "els"] } -els = { version = "0.1.52-nightly.1", features = ["py_compat"] } +erg_common = { version = "0.6.40", features = ["py_compat", "els"] } +erg_compiler = { version = "0.6.40", features = ["py_compat", "els"] } +els = { version = "0.1.52", features = ["py_compat"] } # rustpython-parser = { version = "0.3.0", features = ["all-nodes-with-ranges", "location"] } # rustpython-ast = { version = "0.3.0", features = ["all-nodes-with-ranges", "location"] } rustpython-parser = { git = "https://github.com/RustPython/Parser", version = "0.3.1", features = ["all-nodes-with-ranges", "location"] } diff --git a/crates/py2erg/gen_decl.rs b/crates/py2erg/gen_decl.rs index c4226a4..cab06da 100644 --- a/crates/py2erg/gen_decl.rs +++ b/crates/py2erg/gen_decl.rs @@ -65,6 +65,14 @@ impl DeclFileGenerator { } } + // e.g. `x: foo.Bar` => `foo = pyimport "foo"; x: foo.Bar` + fn prepare_using_type(&mut self, typ: &Type) { + let namespace = Str::rc(typ.namespace().split('.').next().unwrap()); + if !namespace.is_empty() && self.imported.insert(namespace.clone()) { + self.code += &format!("{namespace} = pyimport \"{namespace}\"\n"); + } + } + fn gen_chunk_decl(&mut self, chunk: &Expr) { match chunk { Expr::Def(def) => { @@ -75,6 +83,7 @@ impl DeclFileGenerator { .replace('\0', "") .replace(['%', '*'], "___"); let ref_t = def.sig.ident().ref_t(); + self.prepare_using_type(ref_t); let typ = escape_type(ref_t.replace_failure().to_string_unabbreviated()); // Erg can automatically import nested modules // `import http.client` => `http = pyimport "http"` @@ -119,6 +128,7 @@ impl DeclFileGenerator { .typ() .replace_failure() .to_string_unabbreviated(); + self.prepare_using_type(class.sup.typ()); let sup = escape_type(sup); let decl = format!(".{class_name} <: {sup}\n"); self.code += &decl; @@ -129,6 +139,7 @@ impl DeclFileGenerator { }) = def.obj.base_or_sup() { for (attr, t) in rec.iter() { + self.prepare_using_type(t); let typ = escape_type(t.replace_failure().to_string_unabbreviated()); let decl = format!("{}.{}: {typ}\n", self.namespace, attr.symbol); self.code += &decl; @@ -140,6 +151,7 @@ impl DeclFileGenerator { }) = def.obj.additional() { for (attr, t) in rec.iter() { + self.prepare_using_type(t); let typ = escape_type(t.replace_failure().to_string_unabbreviated()); let decl = format!("{}.{}: {typ}\n", self.namespace, attr.symbol); self.code += &decl; diff --git a/tests/foo/__init__.py b/tests/foo/__init__.py index 98d94b6..d231887 100644 --- a/tests/foo/__init__.py +++ b/tests/foo/__init__.py @@ -1,4 +1,4 @@ -from .bar import i, Bar +from .bar import i, Bar, Baz, Qux from . import bar from . import baz diff --git a/tests/foo/bar.py b/tests/foo/bar.py index 0fbe907..5c1d692 100644 --- a/tests/foo/bar.py +++ b/tests/foo/bar.py @@ -2,3 +2,9 @@ class Bar: def f(self): return 1 + +class Baz(Exception): + pass + +class Qux(Baz): + pass diff --git a/tests/import.py b/tests/import.py index 500582d..11228de 100644 --- a/tests/import.py +++ b/tests/import.py @@ -41,3 +41,5 @@ Resp = http.client.HTTPResponse assert export.http.client.HTTPResponse == Resp + +_ = bar.Baz