Skip to content

Commit 00a9815

Browse files
authored
Fix slots and deleted attributes in incremental mode (#12645)
They weren't serialized before. Manually written serialization code is a pain to keep up-to-date.
1 parent a16c414 commit 00a9815

File tree

5 files changed

+54
-1
lines changed

5 files changed

+54
-1
lines changed

mypy/nodes.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2907,6 +2907,8 @@ def serialize(self) -> JsonDict:
29072907
None if self.typeddict_type is None else self.typeddict_type.serialize(),
29082908
'flags': get_flags(self, TypeInfo.FLAGS),
29092909
'metadata': self.metadata,
2910+
'slots': list(sorted(self.slots)) if self.slots is not None else None,
2911+
'deletable_attributes': self.deletable_attributes,
29102912
}
29112913
return data
29122914

@@ -2944,6 +2946,8 @@ def deserialize(cls, data: JsonDict) -> 'TypeInfo':
29442946
ti.typeddict_type = (None if data['typeddict_type'] is None
29452947
else mypy.types.TypedDictType.deserialize(data['typeddict_type']))
29462948
ti.metadata = data['metadata']
2949+
ti.slots = set(data['slots']) if data['slots'] is not None else None
2950+
ti.deletable_attributes = data['deletable_attributes']
29472951
set_flags(ti, data['flags'])
29482952
return ti
29492953

mypyc/ir/class_ir.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ def serialize(self) -> JsonDict:
325325
'children': [
326326
cir.fullname for cir in self.children
327327
] if self.children is not None else None,
328+
'deletable': self.deletable,
328329
}
329330

330331
@classmethod
@@ -373,6 +374,7 @@ def deserialize(cls, data: JsonDict, ctx: 'DeserMaps') -> 'ClassIR':
373374
ir.mro = [ctx.classes[s] for s in data['mro']]
374375
ir.base_mro = [ctx.classes[s] for s in data['base_mro']]
375376
ir.children = data['children'] and [ctx.classes[s] for s in data['children']]
377+
ir.deletable = data['deletable']
376378

377379
return ir
378380

mypyc/test-data/fixtures/ir.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ def next(i: Iterator[T]) -> T: pass
294294
def next(i: Iterator[T], default: T) -> T: pass
295295
def hash(o: object) -> int: ...
296296
def globals() -> Dict[str, Any]: ...
297-
def getattr(obj: object, name: str) -> Any: ...
297+
def getattr(obj: object, name: str, default: Any = None) -> Any: ...
298298
def setattr(obj: object, name: str, value: Any) -> None: ...
299299
def enumerate(x: Iterable[T]) -> Iterator[Tuple[int, T]]: ...
300300
@overload

mypyc/test-data/run-multimodule.test

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,3 +798,25 @@ def foo() -> int: return 10
798798
import native
799799

800800
[rechecked native, other_a]
801+
802+
[case testIncrementalCompilationWithDeletable]
803+
import other_a
804+
[file other_a.py]
805+
from other_b import C
806+
[file other_a.py.2]
807+
from other_b import C
808+
c = C()
809+
print(getattr(c, 'x', None))
810+
del c.x
811+
print(getattr(c, 'x', None))
812+
[file other_b.py]
813+
class C:
814+
__deletable__ = ['x']
815+
def __init__(self) -> None:
816+
self.x = 0
817+
[file driver.py]
818+
import native
819+
[out]
820+
[out2]
821+
0
822+
None

test-data/unit/check-incremental.test

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5633,3 +5633,28 @@ main:5: error: Cannot override final attribute "x" (previously declared in base
56335633
main:3: error: Cannot override writable attribute "x" with a final one
56345634
main:4: error: Cannot extend enum with existing members: "FinalEnum"
56355635
main:5: error: Cannot override final attribute "x" (previously declared in base class "FinalEnum")
5636+
5637+
[case testSlotsSerialization]
5638+
import a
5639+
[file a.py]
5640+
from b import C
5641+
5642+
class D(C):
5643+
pass
5644+
[file b.py]
5645+
class C:
5646+
__slots__ = ('x',)
5647+
[file a.py.2]
5648+
from b import C
5649+
5650+
class D(C):
5651+
__slots__ = ('y',)
5652+
5653+
def __init__(self) -> None:
5654+
self.x = 1
5655+
self.y = 2
5656+
self.z = 3
5657+
[builtins fixtures/tuple.pyi]
5658+
[out]
5659+
[out2]
5660+
tmp/a.py:9: error: Trying to assign name "z" that is not in "__slots__" of type "a.D"

0 commit comments

Comments
 (0)