Skip to content

Commit 0e50b95

Browse files
authored
Revert "Fix module resolution bug" (#227)
Reverts #190
1 parent f5924e3 commit 0e50b95

File tree

6 files changed

+14
-110
lines changed

6 files changed

+14
-110
lines changed

src/codegen/sdk/core/external_module.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,14 @@ class ExternalModule(
3535
"""
3636

3737
node_type: Literal[NodeType.EXTERNAL] = NodeType.EXTERNAL
38-
_import: Import | None = None
3938

40-
def __init__(self, ts_node: TSNode, file_node_id: NodeId, G: CodebaseGraph, import_name: Name, import_node: Import | None = None) -> None:
39+
def __init__(self, ts_node: TSNode, file_node_id: NodeId, G: CodebaseGraph, import_name: Name) -> None:
4140
self.node_id = G.add_node(self)
4241
super().__init__(ts_node, file_node_id, G, None)
4342
self._name_node = import_name
4443
self.return_type = StubPlaceholder(parent=self)
4544
assert self._idx_key not in self.G._ext_module_idx
4645
self.G._ext_module_idx[self._idx_key] = self.node_id
47-
self._import = import_node
4846

4947
@property
5048
def _idx_key(self) -> str:
@@ -70,7 +68,7 @@ def from_import(cls, imp: Import) -> ExternalModule:
7068
Returns:
7169
ExternalModule: A new ExternalModule instance representing the external module.
7270
"""
73-
return cls(imp.ts_node, imp.file_node_id, imp.G, imp._unique_node, imp)
71+
return cls(imp.ts_node, imp.file_node_id, imp.G, imp._unique_node)
7472

7573
@property
7674
@reader
@@ -138,7 +136,7 @@ def viz(self) -> VizNode:
138136
@noapidoc
139137
@reader
140138
def resolve_attribute(self, name: str) -> ExternalModule | None:
141-
return self._import.resolve_attribute(name) or self
139+
return self
142140

143141
@noapidoc
144142
@commiter

src/codegen/sdk/core/import_resolution.py

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
from codegen.sdk.core.expressions.name import Name
1212
from codegen.sdk.core.external_module import ExternalModule
1313
from codegen.sdk.core.interfaces.chainable import Chainable
14-
from codegen.sdk.core.interfaces.has_attribute import HasAttribute
1514
from codegen.sdk.core.interfaces.usable import Usable
1615
from codegen.sdk.core.statements.import_statement import ImportStatement
1716
from codegen.sdk.enums import EdgeType, ImportType, NodeType
@@ -58,7 +57,7 @@ class ImportResolution(Generic[TSourceFile]):
5857

5958

6059
@apidoc
61-
class Import(Usable[ImportStatement], Chainable, Generic[TSourceFile], HasAttribute[TSourceFile]):
60+
class Import(Usable[ImportStatement], Chainable, Generic[TSourceFile]):
6261
"""Represents a single symbol being imported.
6362
6463
For example, this is one `Import` in Python (and similar applies to Typescript, etc.):
@@ -116,7 +115,7 @@ def __rich_repr__(self) -> rich.repr.Result:
116115

117116
@noapidoc
118117
@abstractmethod
119-
def resolve_import(self, base_path: str | None = None, *, add_module_name: str | None = None) -> ImportResolution[TSourceFile] | None:
118+
def resolve_import(self, base_path: str | None = None) -> ImportResolution[TSourceFile] | None:
120119
"""Resolves the import to a symbol defined outside the file.
121120
122121
Returns an ImportResolution object.
@@ -663,17 +662,6 @@ def remove_if_unused(self) -> None:
663662
):
664663
self.remove()
665664

666-
@noapidoc
667-
@reader
668-
def resolve_attribute(self, attribute: str) -> TSourceFile | None:
669-
# Handles implicit namespace imports in python
670-
if not isinstance(self._imported_symbol(), ExternalModule):
671-
return None
672-
resolved = self.resolve_import(add_module_name=attribute)
673-
if resolved:
674-
return resolved.symbol or resolved.from_file
675-
return None
676-
677665

678666
TImport = TypeVar("TImport", bound="Import")
679667

src/codegen/sdk/python/file.py

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from codegen.sdk.core.file import SourceFile
77
from codegen.sdk.core.interface import Interface
88
from codegen.sdk.enums import ImportType, ProgrammingLanguage
9-
from codegen.sdk.extensions.utils import cached_property, iter_all_descendants
9+
from codegen.sdk.extensions.utils import iter_all_descendants
1010
from codegen.sdk.python import PyAssignment
1111
from codegen.sdk.python.class_definition import PyClass
1212
from codegen.sdk.python.detached_symbols.code_block import PyCodeBlock
@@ -20,7 +20,6 @@
2020

2121
if TYPE_CHECKING:
2222
from codegen.sdk.codebase.codebase_graph import CodebaseGraph
23-
from codegen.sdk.core.import_resolution import WildcardImport
2423
from codegen.sdk.python.symbol import PySymbol
2524

2625

@@ -174,20 +173,3 @@ def add_import_from_import_string(self, import_string: str) -> None:
174173
def remove_unused_exports(self) -> None:
175174
"""Removes unused exports from the file. NO-OP for python"""
176175
pass
177-
178-
@cached_property
179-
@noapidoc
180-
@reader(cache=True)
181-
def valid_import_names(self) -> dict[str, PySymbol | PyImport | WildcardImport[PyImport]]:
182-
"""Returns a dict mapping name => Symbol (or import) in this file that can be imported from
183-
another file.
184-
"""
185-
if self.name == "__init__":
186-
ret = {}
187-
if self.directory:
188-
for file in self.directory:
189-
if file.name == "__init__":
190-
continue
191-
ret[file.name] = file
192-
return ret
193-
return super().valid_import_names

src/codegen/sdk/python/import_resolution.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,10 @@ def imported_exports(self) -> list[Exportable]:
8282

8383
@noapidoc
8484
@reader
85-
def resolve_import(self, base_path: str | None = None, *, add_module_name: str | None = None) -> ImportResolution[PyFile] | None:
85+
def resolve_import(self, base_path: str | None = None) -> ImportResolution[PyFile] | None:
8686
base_path = base_path or self.G.projects[0].base_path or ""
8787
module_source = self.module.source if self.module else ""
88-
symbol_name = self.symbol_name.source if self.symbol_name else ""
89-
if add_module_name:
90-
module_source += f".{symbol_name}"
91-
symbol_name = add_module_name
88+
9289
# If import is relative, convert to absolute path
9390
if module_source.startswith("."):
9491
module_source = self._relative_to_absolute_import(module_source)
@@ -102,7 +99,7 @@ def resolve_import(self, base_path: str | None = None, *, add_module_name: str |
10299
# `from a.b.c import foo`
103100
filepath = os.path.join(
104101
base_path,
105-
module_source.replace(".", "/") + "/" + symbol_name + ".py",
102+
module_source.replace(".", "/") + "/" + self.symbol_name.source + ".py",
106103
)
107104
if file := self.G.get_file(filepath):
108105
return ImportResolution(from_file=file, symbol=None, imports_file=True)
@@ -117,22 +114,22 @@ def resolve_import(self, base_path: str | None = None, *, add_module_name: str |
117114
filepath = module_source.replace(".", "/") + ".py"
118115
filepath = os.path.join(base_path, filepath)
119116
if file := self.G.get_file(filepath):
120-
symbol = file.get_node_by_name(symbol_name)
117+
symbol = file.get_node_by_name(self.symbol_name.source)
121118
return ImportResolution(from_file=file, symbol=symbol)
122119

123120
# =====[ Check if `module/__init__.py` file exists in the graph ]=====
124121
filepath = filepath.replace(".py", "/__init__.py")
125122
if from_file := self.G.get_file(filepath):
126-
symbol = from_file.get_node_by_name(symbol_name)
123+
symbol = from_file.get_node_by_name(self.symbol_name.source)
127124
return ImportResolution(from_file=from_file, symbol=symbol)
128125

129126
# =====[ Case: Can't resolve the import ]=====
130127
if base_path == "":
131128
# Try to resolve with "src" as the base path
132-
return self.resolve_import(base_path="src", add_module_name=add_module_name)
129+
return self.resolve_import(base_path="src")
133130
if base_path == "src":
134131
# Try "test" next
135-
return self.resolve_import(base_path="test", add_module_name=add_module_name)
132+
return self.resolve_import(base_path="test")
136133

137134
# if not G_override:
138135
# for resolver in G.import_resolvers:

src/codegen/sdk/typescript/import_resolution.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ def resolved_symbol(self) -> Symbol | ExternalModule | TSFile | None:
197197
return resolved_symbol
198198

199199
@reader
200-
def resolve_import(self, base_path: str | None = None, *, add_module_name: str | None = None) -> ImportResolution[TSFile] | None:
200+
def resolve_import(self, base_path: str | None = None) -> ImportResolution[TSFile] | None:
201201
"""Resolves an import statement to its target file and symbol.
202202
203203
This method is used by GraphBuilder to resolve import statements to their target files and symbols. It handles both relative and absolute imports,

tests/unit/codegen/sdk/python/import_resolution/test_import_resolution.py

Lines changed: 0 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -249,64 +249,3 @@ def c_sym():
249249
assert "c_sym" in b_file.valid_symbol_names
250250
assert "a_sym" in c_file.valid_symbol_names
251251
assert "b_sym" in c_file.valid_symbol_names.keys()
252-
253-
254-
def test_import_resolution_nested_module(tmpdir: str) -> None:
255-
"""Tests import resolution works with nested module imports"""
256-
# language=python
257-
with get_codebase_session(
258-
tmpdir,
259-
files={
260-
"a/b/c.py": """
261-
def d():
262-
pass
263-
""",
264-
"consumer.py": """
265-
from a import b
266-
267-
b.c.d()
268-
""",
269-
},
270-
) as codebase:
271-
consumer_file: SourceFile = codebase.get_file("consumer.py")
272-
c_file: SourceFile = codebase.get_file("a/b/c.py")
273-
274-
# Verify import resolution
275-
assert len(consumer_file.imports) == 1
276-
277-
# Verify function call resolution
278-
d_func = c_file.get_function("d")
279-
call_sites = d_func.call_sites
280-
assert len(call_sites) == 1
281-
assert call_sites[0].file == consumer_file
282-
283-
284-
def test_import_resolution_nested_module_init(tmpdir: str) -> None:
285-
"""Tests import resolution works with nested module imports"""
286-
# language=python
287-
with get_codebase_session(
288-
tmpdir,
289-
files={
290-
"a/b/c.py": """
291-
def d():
292-
pass
293-
""",
294-
"a/b/__init__.py": """""",
295-
"consumer.py": """
296-
from a import b
297-
298-
b.c.d()
299-
""",
300-
},
301-
) as codebase:
302-
consumer_file: SourceFile = codebase.get_file("consumer.py")
303-
c_file: SourceFile = codebase.get_file("a/b/c.py")
304-
305-
# Verify import resolution
306-
assert len(consumer_file.imports) == 1
307-
308-
# Verify function call resolution
309-
d_func = c_file.get_function("d")
310-
call_sites = d_func.call_sites
311-
assert len(call_sites) == 1
312-
assert call_sites[0].file == consumer_file

0 commit comments

Comments
 (0)