Skip to content

Commit 172d8b9

Browse files
committed
[GR-17643] setattr via decorator on class member
PullRequest: graalpython/611
2 parents a6e4c5f + 442e507 commit 172d8b9

File tree

2 files changed

+53
-1
lines changed

2 files changed

+53
-1
lines changed

graalpython/com.oracle.graal.python.test/src/tests/test_class-set-attrib.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
22
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
33
#
44
# The Universal Permissive License (UPL), Version 1.0
@@ -102,3 +102,24 @@ def test_assignments():
102102
assert object.baz == 119, "custom set"
103103

104104

105+
def test_setattr_via_decorator():
106+
def setdec(func):
107+
setattr(func, 'SPECIAL_ATTR', {'a': 1, 'b': 2})
108+
return func
109+
110+
@setdec
111+
def f():
112+
return 1
113+
114+
assert hasattr(f, 'SPECIAL_ATTR')
115+
assert getattr(f, 'SPECIAL_ATTR') == {'a': 1, 'b': 2}
116+
117+
118+
class MyClass(object):
119+
@setdec
120+
def f(self):
121+
return 1
122+
123+
m = MyClass()
124+
assert hasattr(m.f, 'SPECIAL_ATTR')
125+
assert getattr(m.f, 'SPECIAL_ATTR') == {'a': 1, 'b': 2}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/method/MethodBuiltins.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,10 @@
2828

2929
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__CODE__;
3030
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__DEFAULTS__;
31+
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__DICT__;
3132
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__FUNC__;
3233
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__KWDEFAULTS__;
34+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__GETATTRIBUTE__;
3335
import static com.oracle.graal.python.nodes.SpecialMethodNames.__GET__;
3436
import static com.oracle.graal.python.nodes.SpecialMethodNames.__REDUCE__;
3537
import static com.oracle.graal.python.nodes.SpecialMethodNames.__REPR__;
@@ -43,6 +45,7 @@
4345
import com.oracle.graal.python.builtins.PythonBuiltins;
4446
import com.oracle.graal.python.builtins.objects.PNone;
4547
import com.oracle.graal.python.builtins.objects.function.PKeyword;
48+
import com.oracle.graal.python.builtins.objects.object.ObjectBuiltins;
4649
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode;
4750
import com.oracle.graal.python.nodes.SpecialAttributeNames;
4851
import com.oracle.graal.python.nodes.attributes.GetAttributeNode;
@@ -54,6 +57,8 @@
5457
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode;
5558
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
5659
import com.oracle.graal.python.nodes.object.GetLazyClassNode;
60+
import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile;
61+
import com.oracle.graal.python.runtime.exception.PException;
5762
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
5863
import com.oracle.truffle.api.dsl.Cached;
5964
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
@@ -93,6 +98,32 @@ protected Object doIt(VirtualFrame frame, PMethod self,
9398
}
9499
}
95100

101+
@Builtin(name = __DICT__, minNumOfPositionalArgs = 1, isGetter = true)
102+
@GenerateNodeFactory
103+
public abstract static class DictNode extends PythonBuiltinNode {
104+
@Specialization
105+
protected Object doIt(VirtualFrame frame, PMethod self,
106+
@Cached("create(__GETATTRIBUTE__)") LookupAndCallBinaryNode getDict) {
107+
return getDict.executeObject(frame, self.getFunction(), __DICT__);
108+
}
109+
}
110+
111+
@Builtin(name = __GETATTRIBUTE__, minNumOfPositionalArgs = 2)
112+
@GenerateNodeFactory
113+
public abstract static class GetattributeNode extends PythonBuiltinNode {
114+
@Specialization
115+
protected Object doIt(VirtualFrame frame, PMethod self, Object key,
116+
@Cached("create()") ObjectBuiltins.GetAttributeNode objectGetattrNode,
117+
@Cached("create()") IsBuiltinClassProfile errorProfile) {
118+
try {
119+
return objectGetattrNode.execute(frame, self, key);
120+
} catch (PException e) {
121+
e.expectAttributeError(errorProfile);
122+
return objectGetattrNode.execute(frame, self.getFunction(), key);
123+
}
124+
}
125+
}
126+
96127
@Builtin(name = __REPR__, minNumOfPositionalArgs = 1)
97128
@GenerateNodeFactory
98129
public abstract static class ReprNode extends PythonUnaryBuiltinNode {

0 commit comments

Comments
 (0)