Skip to content

Commit a9f81ea

Browse files
authored
Experiment: Override __class__ for Builtin types to shadow isinstance (#347)
This allows us to do `isinstance(symbol, list)` instead of `isinstance(symbol, codegen.sdk.core.List)` This applies to changes to: - List - Dict - Tuple - String - Number - Boolean
1 parent cfc67e9 commit a9f81ea

File tree

10 files changed

+123
-4
lines changed

10 files changed

+123
-4
lines changed

src/codegen/sdk/core/expressions/boolean.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,7 @@ def __bool__(self):
2525
@override
2626
def _compute_dependencies(self, usage_type: UsageKind, dest: HasName | None = None) -> None:
2727
pass
28+
29+
@property
30+
def __class__(self):
31+
return bool

src/codegen/sdk/core/expressions/number.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,7 @@ class Number(Expression[Parent], Builtin, Generic[Parent]):
2222
@override
2323
def _compute_dependencies(self, usage_type: UsageKind, dest: HasName | None = None) -> None:
2424
pass
25+
26+
@property
27+
def __class__(self):
28+
return int

src/codegen/sdk/core/expressions/string.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,7 @@ def _compute_dependencies(self, usage_type: UsageKind | None = None, dest: HasNa
6868
# If the string is a template string, we need to compute the dependencies of the string content
6969
for expression in self.expressions:
7070
expression._compute_dependencies(usage_type, dest)
71+
72+
@property
73+
def __class__(self):
74+
return str

src/codegen/sdk/core/interfaces/editable.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,10 +168,10 @@ def __rich_console__(self, console: Console, options: ConsoleOptions) -> RenderR
168168
def __eq__(self, other: object):
169169
if other is None:
170170
return False
171-
if isinstance(other, str):
172-
return self.source == other
173171
if isinstance(other, Editable):
174172
return self.filepath == other.filepath and self.ts_node.kind_id == other.ts_node.kind_id and self.range == other.range
173+
if isinstance(other, str):
174+
return self.source == other
175175
return False
176176

177177
@reader

src/codegen/sdk/core/symbol_group.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,10 @@ def __hash__(self):
4747
def __eq__(self, other: object) -> bool:
4848
if other is None:
4949
return False
50-
if isinstance(other, list):
51-
return self.symbols == other
5250
if isinstance(other, SymbolGroup):
5351
return self.symbols == other.symbols
52+
if isinstance(other, list):
53+
return self.symbols == other
5454
return super().__eq__(other)
5555

5656
@property

src/codegen/sdk/core/symbol_groups/dict.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,3 +174,7 @@ def descendant_symbols(self) -> list["Importable"]:
174174
if child.value:
175175
ret.extend(child.value.descendant_symbols)
176176
return ret
177+
178+
@property
179+
def __class__(self):
180+
return dict

src/codegen/sdk/core/symbol_groups/list.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,7 @@ class List(Collection["Expression[Self, None]", Parent], Expression[Parent], Bui
2424
def __init__(self, ts_node: TSNode, file_node_id: NodeId, G: "CodebaseGraph", parent: Parent) -> None:
2525
super().__init__(ts_node, file_node_id, G, parent)
2626
self._init_children([self._parse_expression(child) for child in ts_node.named_children if child.type])
27+
28+
@property
29+
def __class__(self):
30+
return list

src/codegen/sdk/core/symbol_groups/tuple.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,7 @@ class Tuple(Collection["Expression[Self, None]", Parent], Expression[Parent], Bu
2424
def __init__(self, ts_node: TSNode, file_node_id: NodeId, G: "CodebaseGraph", parent: Parent) -> None:
2525
super().__init__(ts_node, file_node_id, G, parent)
2626
self._init_children([self._parse_expression(child) for child in ts_node.named_children if child.type])
27+
28+
@property
29+
def __class__(self):
30+
return tuple
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
from codegen.sdk.codebase.factory.get_session import get_codebase_session
2+
from codegen.sdk.core.expressions.boolean import Boolean
3+
from codegen.sdk.core.expressions.number import Number
4+
from codegen.sdk.core.expressions.string import String
5+
from codegen.sdk.core.symbol_groups.dict import Dict
6+
from codegen.sdk.core.symbol_groups.list import List
7+
from codegen.sdk.core.symbol_groups.tuple import Tuple
8+
from codegen.sdk.enums import ProgrammingLanguage
9+
10+
11+
def test_builtin_types(tmpdir):
12+
# language=python
13+
content = """
14+
a = 1
15+
b = "hello"
16+
c = True
17+
d = [1, 2, 3]
18+
e = {"a": 1, "b": 2}
19+
f = (1, 2, 3)
20+
"""
21+
with get_codebase_session(tmpdir=tmpdir, files={"test.py": content}, programming_language=ProgrammingLanguage.PYTHON) as codebase:
22+
file = codebase.get_file("test.py")
23+
# Test Number
24+
a = file.get_global_var("a")
25+
assert isinstance(a.value, Number)
26+
assert isinstance(a.value, int)
27+
28+
# Test String
29+
b = file.get_global_var("b")
30+
assert isinstance(b.value, String)
31+
assert isinstance(b.value, str)
32+
33+
# Test Boolean
34+
c = file.get_global_var("c")
35+
assert isinstance(c.value, Boolean)
36+
assert isinstance(c.value, bool)
37+
38+
# Test List
39+
d = file.get_global_var("d")
40+
assert isinstance(d.value, List)
41+
assert isinstance(d.value, list)
42+
43+
# Test Dict
44+
e = file.get_global_var("e")
45+
assert isinstance(e.value, Dict)
46+
assert isinstance(e.value, dict)
47+
48+
# Test Tuple
49+
f = file.get_global_var("f")
50+
assert isinstance(f.value, Tuple)
51+
assert isinstance(f.value, tuple)
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
from codegen.sdk.codebase.factory.get_session import get_codebase_session
2+
from codegen.sdk.core.expressions.boolean import Boolean
3+
from codegen.sdk.core.expressions.number import Number
4+
from codegen.sdk.core.expressions.string import String
5+
from codegen.sdk.core.symbol_groups.dict import Dict
6+
from codegen.sdk.core.symbol_groups.list import List
7+
from codegen.sdk.enums import ProgrammingLanguage
8+
9+
10+
def test_builtin_types(tmpdir):
11+
# language=typescript
12+
content = """
13+
let a = 1;
14+
let b = "hello";
15+
let c = true;
16+
let d = [1, 2, 3];
17+
let e = {"a": 1, "b": 2};
18+
"""
19+
with get_codebase_session(tmpdir=tmpdir, files={"test.ts": content}, programming_language=ProgrammingLanguage.TYPESCRIPT) as codebase:
20+
file = codebase.get_file("test.ts")
21+
# Test Number
22+
a = file.get_global_var("a")
23+
assert isinstance(a.value, Number)
24+
assert isinstance(a.value, int)
25+
26+
# Test String
27+
b = file.get_global_var("b")
28+
assert isinstance(b.value, String)
29+
assert isinstance(b.value, str)
30+
31+
# Test Boolean
32+
c = file.get_global_var("c")
33+
assert isinstance(c.value, Boolean)
34+
assert isinstance(c.value, bool)
35+
36+
# Test List/Array
37+
d = file.get_global_var("d")
38+
assert isinstance(d.value, List)
39+
assert isinstance(d.value, list)
40+
41+
# Test Dict/Object
42+
e = file.get_global_var("e")
43+
assert isinstance(e.value, Dict)
44+
assert isinstance(e.value, dict)

0 commit comments

Comments
 (0)