Skip to content

Commit a4ce643

Browse files
committed
do not access annotations too early
1 parent 41a7bf4 commit a4ce643

File tree

12 files changed

+169
-21
lines changed

12 files changed

+169
-21
lines changed

python/code/wypp/records.py

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,6 @@ def init(enableTypeChecking=True):
1717
global _typeCheckingEnabled
1818
_typeCheckingEnabled = enableTypeChecking
1919

20-
def _collectDataClassAttributes(cls):
21-
result = dict()
22-
for c in cls.mro():
23-
if hasattr(c, '__kind') and c.__kind == 'record' and hasattr(c, '__annotations__'):
24-
result = c.__annotations__ | result
25-
return result
26-
2720
def _checkRecordAttr(cls: typing.Any,
2821
ns: myTypeguard.Namespaces,
2922
name: str,
@@ -48,11 +41,8 @@ def _patchDataClass(cls, mutable: bool, ns: myTypeguard.Namespaces):
4841
fieldNames = [f.name for f in dataclasses.fields(cls)]
4942
setattr(cls, EQ_ATTRS_ATTR, fieldNames)
5043

51-
if hasattr(cls, '__annotations__'):
52-
# add annotions for type checked constructor.
53-
cls.__kind = 'record'
54-
cls.__init__.__annotations__ = _collectDataClassAttributes(cls)
55-
cls.__init__ = typecheck.wrapTypecheckRecordConstructor(cls, ns)
44+
cls.__kind = 'record'
45+
cls.__init__ = typecheck.wrapTypecheckRecordConstructor(cls, ns)
5646

5747
if mutable:
5848
# prevent new fields being added

python/file-test-data/basics/recursive2_ok.err

Whitespace-only changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Kinzig
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from __future__ import annotations
2+
from wypp import *
3+
4+
# Ein Flussabschnitt ist entweder
5+
# - ein Bach mit Namen und Quelle, oder
6+
# - ein Zusammenfluss eines Haupt- und Nebenflussabschnitts an einem bestimmten Ort.
7+
8+
@record
9+
class Creek:
10+
origin: str
11+
name: str
12+
13+
@record
14+
class Confluence:
15+
location: str
16+
mainStem: RiverSection
17+
tributary: RiverSection
18+
19+
type RiverSection = Union[Creek, Confluence]
20+
21+
kinzig1 = Creek('Loßburg', 'Kinzig')
22+
gutach = Creek('Schönwald', 'Gutach')
23+
kinzig2 = Confluence('Hausach', kinzig1, gutach)
24+
schutter1 = Creek('Schweighausen', 'Schutter')
25+
heidengraben = Creek('Lahr', 'Heidengraben')
26+
schutter2 = Confluence('Lahr', schutter1, heidengraben)
27+
kinzig3 = Confluence('Kehl', kinzig2, schutter2)
28+
29+
# Name eines Flussabschnitts bestimmen
30+
# Eingabe: den Flussabschnitt (Typ: RiverSection)
31+
# Ergebnis: der Name (Typ: str)
32+
def riverName(r: RiverSection) -> str:
33+
if isinstance(r, Creek):
34+
return r.name
35+
elif isinstance(r, Confluence):
36+
return riverName(r.mainStem)
37+
38+
print(riverName(kinzig3))

python/file-test-data/basics/recursive_ok.err

Whitespace-only changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Kinzig
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
from wypp import *
2+
3+
# Ein Flussabschnitt ist entweder
4+
# - ein Bach mit Namen und Quelle, oder
5+
# - ein Zusammenfluss eines Haupt- und Nebenflussabschnitts an einem bestimmten Ort.
6+
7+
@record
8+
class Creek:
9+
origin: str
10+
name: str
11+
12+
@record
13+
class Confluence:
14+
location: str
15+
mainStem: RiverSection
16+
tributary: RiverSection
17+
18+
type RiverSection = Union[Creek, Confluence]
19+
20+
kinzig1 = Creek('Loßburg', 'Kinzig')
21+
gutach = Creek('Schönwald', 'Gutach')
22+
kinzig2 = Confluence('Hausach', kinzig1, gutach)
23+
schutter1 = Creek('Schweighausen', 'Schutter')
24+
heidengraben = Creek('Lahr', 'Heidengraben')
25+
schutter2 = Confluence('Lahr', schutter1, heidengraben)
26+
kinzig3 = Confluence('Kehl', kinzig2, schutter2)
27+
28+
# Name eines Flussabschnitts bestimmen
29+
# Eingabe: den Flussabschnitt (Typ: RiverSection)
30+
# Ergebnis: der Name (Typ: str)
31+
def riverName(r: RiverSection) -> str:
32+
if isinstance(r, Creek):
33+
return r.name
34+
elif isinstance(r, Confluence):
35+
return riverName(r.mainStem)
36+
37+
print(riverName(kinzig3))
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Traceback (most recent call last):
2+
File "file-test-data/basics/recursive_old_fail.py", line 13, in <module>
3+
class Confluence:
4+
File "file-test-data/basics/recursive_old_fail.py", line 15, in Confluence
5+
mainStem: RiverSection
6+
NameError: name 'RiverSection' is not defined

python/file-test-data/basics/recursive_old_fail.out

Whitespace-only changes.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
from wypp import *
2+
3+
# Ein Flussabschnitt ist entweder
4+
# - ein Bach mit Namen und Quelle, oder
5+
# - ein Zusammenfluss eines Haupt- und Nebenflussabschnitts an einem bestimmten Ort.
6+
7+
@record
8+
class Creek:
9+
origin: str
10+
name: str
11+
12+
@record
13+
class Confluence:
14+
location: str
15+
mainStem: RiverSection
16+
tributary: RiverSection
17+
18+
type RiverSection = Union[Creek, Confluence]
19+
20+
kinzig1 = Creek('Loßburg', 'Kinzig')
21+
gutach = Creek('Schönwald', 'Gutach')
22+
kinzig2 = Confluence('Hausach', kinzig1, gutach)
23+
schutter1 = Creek('Schweighausen', 'Schutter')
24+
heidengraben = Creek('Lahr', 'Heidengraben')
25+
schutter2 = Confluence('Lahr', schutter1, heidengraben)
26+
kinzig3 = Confluence('Kehl', kinzig2, schutter2)
27+
28+
# Name eines Flussabschnitts bestimmen
29+
# Eingabe: den Flussabschnitt (Typ: RiverSection)
30+
# Ergebnis: der Name (Typ: str)
31+
def riverName(r: RiverSection) -> str:
32+
if isinstance(r, Creek):
33+
return r.name
34+
elif isinstance(r, Confluence):
35+
return riverName(r.mainStem)
36+
37+
print(riverName(kinzig3))

0 commit comments

Comments
 (0)