8000 [mypyc] Raise AttributeError also for non-refcounted types by JukkaL · Pull Request #11940 · python/mypy · GitHub
[go: up one dir, main page]

Skip to content

[mypyc] Raise AttributeError also for non-refcounted types #11940

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions mypyc/codegen/emitfunc.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,17 +287,17 @@ def visit_get_attr(self, op: GetAttr) -> None:
# Otherwise, use direct or offset struct access.
attr_expr = self.get_attr_expr(obj, op, decl_cl)
self.emitter.emit_line('{} = {};'.format(dest, attr_expr))
self.emitter.emit_undefined_attr_check(
attr_rtype, attr_expr, '==', unlikely=True
)
exc_class = 'PyExc_AttributeError'
self.emitter.emit_line(
'PyErr_SetString({}, "attribute {} of {} undefined");'.format(
exc_class, repr(op.attr), repr(cl.name)))
if attr_rtype.is_refcounted:
self.emitter.emit_undefined_attr_check(
attr_rtype, attr_expr, '==', unlikely=True
)
exc_class = 'PyExc_AttributeError'
self.emitter.emit_lines(
'PyErr_SetString({}, "attribute {} of {} undefined");'.format(
exc_class, repr(op.attr), repr(cl.name)),
'} else {')
self.emitter.emit_line('} else {')
self.emitter.emit_inc_ref(attr_expr, attr_rtype)
self.emitter.emit_line('}')
self.emitter.emit_line('}')

def visit_set_attr(self, op: SetAttr) -> None:
dest = self.reg(op)
Expand Down
15 changes: 15 additions & 0 deletions mypyc/test-data/run-classes.test
8000
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ class C:
b: bool
c: C
d: object
e: int

def setattrs(o: C, a: List[int], b: bool, c: C) -> None:
o.a = a
Expand All @@ -346,6 +347,8 @@ def getattrs(o: C) -> Tuple[List[int], bool, C]:
return o.a, o.b, o.c
[file driver.py]
from native import C, setattrs, getattrs
from testutil import assertRaises

c1 = C()
c2 = C()
aa = [2]
Expand All @@ -359,6 +362,18 @@ o = object()
c1.d = o
assert c1.d is o

c3 = C()
with assertRaises(AttributeError, "attribute 'a' of 'C' undefined"):
c3.a
with assertRaises(AttributeError, "attribute 'b' of 'C' undefined"):
c3.b
with assertRaises(AttributeError, "attribute 'c' of 'C' undefined"):
c3.c
with assertRaises(AttributeError, "attribute 'd' of 'C' undefined"):
c3.d
with assertRaises(AttributeError, "attribute 'e' of 'C' undefined"):
c3.e

[case testInitMethodWithMissingNoneReturnAnnotation]
class C:
def __init__(self):
Expand Down
9 changes: 9 additions & 0 deletions mypyc/test/test_emitfunc.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,15 @@ def test_get_attr(self) -> None:
}
""")

def test_get_attr_non_refcounted(self) -> None:
self.assert_emit(
GetAttr(self.r, 'x', 1),
"""cpy_r_r0 = ((mod___AObject *)cpy_r_r)->_x;
if (unlikely(((mod___AObject *)cpy_r_r)->_x == 2)) {
PyErr_SetString(PyExc_AttributeError, "attribute 'x' of 'A' undefined");
}
""")

def test_set_attr(self) -> None:
self.assert_emit(
SetAttr(self.r, 'y', self.m, 1),
Expand Down
0