Skip to content

Commit 63da9e6

Browse files
committed
Implement relative import handling in PythonParser and refactor import processing logic
1 parent fa913f2 commit 63da9e6

File tree

1 file changed

+43
-5
lines changed

1 file changed

+43
-5
lines changed

codetide/parsers/python_parser.py

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
from codetide.parsers.base_parser import BaseParser
2-
from codetide.core.common import readFile
3-
from codetide.core.models import (
1+
from .base_parser import BaseParser
2+
from ..core.common import readFile
3+
from ..core.models import (
44
ClassAttribute, ClassDefinition, CodeBase, CodeReference,
55
FunctionDefinition, FunctionSignature, ImportStatement,
66
CodeFileModel, MethodDefinition, Parameter, VariableDeclaration
@@ -14,7 +14,7 @@
1414
from pathlib import Path
1515
import asyncio
1616
import re
17-
17+
import os
1818
class PythonParser(BaseParser):
1919
"""
2020
Python-specific implementation of the BaseParser using tree-sitter.
@@ -133,15 +133,48 @@ def _process_node(cls, node: Node, code: bytes, codeFile :CodeFileModel):
133133
# elif child.type == "assignment": # <- class attribute
134134
# cls._process_assignment(child, code, codeFile)
135135

136+
@staticmethod
137+
def _rebuild_source_from_relative(relative_import_source :str, relative_import_name :str, filepath :str)->str:
138+
relative_location_index = relative_import_source.count(".")
139+
source_location = Path(filepath).parent
140+
for _ in range(1, relative_location_index):
141+
source_location = Path(source_location).parent
142+
source_id = str(source_location).replace(os.path.sep, ".")
143+
return f"{source_id}.{relative_import_name}"
144+
145+
@classmethod
146+
def _process_relative_import_node(cls, node: Node, code: bytes, codeFile :CodeFileModel):
147+
print("inside")
148+
source = None
149+
relative_import_source = None
150+
relative_import_name = None
151+
for child in node.children:
152+
if child.type == "import_prefix":
153+
relative_import_source = cls._get_content(code, child)
154+
elif child.type == "dotted_name":
155+
relative_import_name = cls._get_content(code, child)
156+
if relative_import_source and relative_import_name:
157+
source = cls._rebuild_source_from_relative(
158+
relative_import_source=relative_import_source,
159+
relative_import_name=relative_import_name,
160+
filepath=codeFile.file_path
161+
)
162+
print(f"{source=}\n")
163+
return source
164+
136165
@classmethod
137166
def _process_import_node(cls, node: Node, code: bytes, codeFile :CodeFileModel):
138167
source = None
139168
next_is_from_import = False
140169
next_is_import = False
170+
is_relative = False
141171
for child in node.children:
142172
if child.type == "from":
143173
next_is_from_import = True
144-
elif child.type == "dotted_name" and next_is_from_import:
174+
elif child.type == "relative_import":
175+
source = cls._process_relative_import_node(child, code, codeFile)
176+
is_relative = True
177+
elif child.type == "dotted_name" and next_is_from_import and not is_relative:
145178
next_is_from_import = False
146179
source = cls._get_content(code, child)
147180
elif child.type == "import":
@@ -159,6 +192,8 @@ def _process_import_node(cls, node: Node, code: bytes, codeFile :CodeFileModel):
159192
source=source,
160193
name=name
161194
)
195+
if is_relative:
196+
importStatement.import_type = "relative"
162197
codeFile.add_import(importStatement)
163198
cls._generate_unique_import_id(codeFile.imports[-1])
164199

@@ -378,6 +413,9 @@ def _default_unique_import_id(cls, importModel :ImportStatement)->str:
378413
def _generate_unique_import_id(cls, importModel :ImportStatement):
379414
"""Generate a unique ID for the function definition"""
380415
unique_id = cls._default_unique_import_id(importModel)
416+
417+
if unique_id.startswith("."):
418+
print(f"{unique_id=}")
381419

382420
if "__init__" in importModel.file_path:
383421
# if Path(importModel.file_path).with_suffix("") == Path(importModel.file_path):

0 commit comments

Comments
 (0)