Skip to content

Commit 62b8e5d

Browse files
committed
attempting to resolve a merge conflict
1 parent bbea6cd commit 62b8e5d

File tree

1 file changed

+241
-0
lines changed

1 file changed

+241
-0
lines changed

scripts/microgenerator/tests/unit/test_generate_analyzer.py

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,247 @@
1818
import pytest
1919
from scripts.microgenerator.generate import parse_code, CodeAnalyzer
2020

21+
# --- Tests CodeAnalyzer handling of Imports ---
22+
23+
24+
class TestCodeAnalyzerImports:
25+
@pytest.mark.parametrize(
26+
"code_snippet, expected_imports",
27+
[
28+
pytest.param(
29+
"import os\nimport sys",
30+
["import os", "import sys"],
31+
id="simple_imports",
32+
),
33+
pytest.param(
34+
"import numpy as np",
35+
["import numpy as np"],
36+
id="aliased_import",
37+
),
38+
pytest.param(
39+
"from collections import defaultdict, OrderedDict",
40+
["from collections import defaultdict, OrderedDict"],
41+
id="from_import_multiple",
42+
),
43+
pytest.param(
44+
"from typing import List as L",
45+
["from typing import List as L"],
46+
id="from_import_aliased",
47+
),
48+
pytest.param(
49+
"from math import *",
50+
["from math import *"],
51+
id="from_import_wildcard",
52+
),
53+
pytest.param(
54+
"import os.path",
55+
["import os.path"],
56+
id="dotted_import",
57+
),
58+
pytest.param(
59+
"from google.cloud import bigquery",
60+
["from google.cloud import bigquery"],
61+
id="from_dotted_module",
62+
),
63+
pytest.param(
64+
"",
65+
[],
66+
id="no_imports",
67+
),
68+
pytest.param(
69+
"class MyClass:\n import json # Should not be picked up",
70+
[],
71+
id="import_inside_class",
72+
),
73+
pytest.param(
74+
"def my_func():\n from time import sleep # Should not be picked up",
75+
[],
76+
id="import_inside_function",
77+
),
78+
],
79+
)
80+
def test_import_extraction(self, code_snippet, expected_imports):
81+
analyzer = CodeAnalyzer()
82+
tree = ast.parse(code_snippet)
83+
analyzer.visit(tree)
84+
85+
# Normalize for comparison
86+
extracted = sorted(list(analyzer.imports))
87+
expected = sorted(expected_imports)
88+
89+
assert extracted == expected
90+
91+
92+
# --- Tests CodeAnalyzer handling of Attributes ---
93+
94+
95+
class TestCodeAnalyzerAttributes:
96+
@pytest.mark.parametrize(
97+
"code_snippet, expected_structure",
98+
[
99+
pytest.param(
100+
"""
101+
class MyClass:
102+
CLASS_VAR = 123
103+
""",
104+
[
105+
{
106+
"class_name": "MyClass",
107+
"methods": [],
108+
"attributes": [{"name": "CLASS_VAR", "type": None}],
109+
}
110+
],
111+
id="class_var_assign",
112+
),
113+
pytest.param(
114+
"""
115+
class MyClass:
116+
class_var: int = 456
117+
""",
118+
[
119+
{
120+
"class_name": "MyClass",
121+
"methods": [],
122+
"attributes": [{"name": "class_var", "type": "int"}],
123+
}
124+
],
125+
id="class_var_annassign",
126+
),
127+
pytest.param(
128+
"""
129+
class MyClass:
130+
class_var: int
131+
""",
132+
[
133+
{
134+
"class_name": "MyClass",
135+
"methods": [],
136+
"attributes": [{"name": "class_var", "type": "int"}],
137+
}
138+
],
139+
id="class_var_annassign_no_value",
140+
),
141+
pytest.param(
142+
"""
143+
class MyClass:
144+
def __init__(self):
145+
self.instance_var = 789
146+
""",
147+
[
148+
{
149+
"class_name": "MyClass",
150+
"methods": [
151+
{
152+
"method_name": "__init__",
153+
"args": [{"name": "self", "type": None}],
154+
"return_type": None,
155+
}
156+
],
157+
"attributes": [{"name": "instance_var", "type": None}],
158+
}
159+
],
160+
id="instance_var_assign",
161+
),
162+
pytest.param(
163+
"""
164+
class MyClass:
165+
def __init__(self):
166+
self.instance_var: str = 'hello'
167+
""",
168+
[
169+
{
170+
"class_name": "MyClass",
171+
"methods": [
172+
{
173+
"method_name": "__init__",
174+
"args": [{"name": "self", "type": None}],
175+
"return_type": None,
176+
}
177+
],
178+
"attributes": [{"name": "instance_var", "type": "str"}],
179+
}
180+
],
181+
id="instance_var_annassign",
182+
),
183+
pytest.param(
184+
"""
185+
class MyClass:
186+
def __init__(self):
187+
self.instance_var: str
188+
""",
189+
[
190+
{
191+
"class_name": "MyClass",
192+
"methods": [
193+
{
194+
"method_name": "__init__",
195+
"args": [{"name": "self", "type": None}],
196+
"return_type": None,
197+
}
198+
],
199+
"attributes": [{"name": "instance_var", "type": "str"}],
200+
}
201+
],
202+
id="instance_var_annassign_no_value",
203+
),
204+
pytest.param(
205+
"""
206+
class MyClass:
207+
VAR_A = 1
208+
var_b: int = 2
209+
def __init__(self):
210+
self.var_c = 3
211+
self.var_d: float = 4.0
212+
""",
213+
[
214+
{
215+
"class_name": "MyClass",
216+
"methods": [
217+
{
218+
"method_name": "__init__",
219+
"args": [{"name": "self", "type": None}],
220+
"return_type": None,
221+
}
222+
],
223+
"attributes": [
224+
{"name": "VAR_A", "type": None},
225+
{"name": "var_b", "type": "int"},
226+
{"name": "var_c", "type": None},
227+
{"name": "var_d", "type": "float"},
228+
],
229+
}
230+
],
231+
id="mixed_attributes",
232+
),
233+
pytest.param(
234+
"a = 123 # Module level",
235+
[],
236+
id="module_level_assign",
237+
),
238+
pytest.param(
239+
"b: int = 456 # Module level",
240+
[],
241+
id="module_level_annassign",
242+
),
243+
],
244+
)
245+
def test_attribute_extraction(self, code_snippet: str, expected_structure: list):
246+
"""Tests the extraction of class and instance attributes."""
247+
analyzer = CodeAnalyzer()
248+
tree = ast.parse(code_snippet)
249+
analyzer.visit(tree)
250+
251+
extracted = analyzer.structure
252+
# Normalize attributes for order-independent comparison
253+
for item in extracted:
254+
if "attributes" in item:
255+
item["attributes"].sort(key=lambda x: x["name"])
256+
for item in expected_structure:
257+
if "attributes" in item:
258+
item["attributes"].sort(key=lambda x: x["name"])
259+
260+
assert extracted == expected_structure
261+
21262

22263
# --- Mock Types ---
23264
class MyClass:

0 commit comments

Comments
 (0)