Skip to content

Commit 07f631f

Browse files
committed
fix __defaults__ access for methods
- added relevant unit tests
1 parent 1be31f6 commit 07f631f

File tree

4 files changed

+86
-63
lines changed

4 files changed

+86
-63
lines changed

graalpython/com.oracle.graal.python.test/src/tests/test_functions.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,15 @@
3838
# SOFTWARE.
3939

4040

41+
def assert_raises(err, fn, *args, **kwargs):
42+
raised = False
43+
try:
44+
fn(*args, **kwargs)
45+
except err:
46+
raised = True
47+
assert raised
48+
49+
4150
def test_name():
4251
def foo():
4352
pass
@@ -63,11 +72,25 @@ def f2(a=f(1, 2), b=10):
6372
return a, b
6473

6574

75+
class MyClass(object):
76+
def __init__(self, x = 10):
77+
pass
78+
79+
6680
def test_defaults():
6781
assert f.__defaults__ == (10,)
6882
assert f2.__defaults__ == ((1, 2, 10, (), {}), 10)
6983

7084

85+
def test_defaults_method():
86+
obj = MyClass()
87+
assert obj.__init__.__defaults__ == (10,)
88+
89+
def assgn():
90+
obj.__init__.__defaults__ = (12,)
91+
assert_raises(AttributeError, assgn)
92+
93+
7194
def test_constructor():
7295
import types
7396
func_copy = types.FunctionType(f.__code__, f.__globals__, f.__name__, f.__defaults__, f.__closure__)

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/AbstractFunctionBuiltins.java

Lines changed: 0 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__ANNOTATIONS__;
3030
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__CLOSURE__;
3131
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__CODE__;
32-
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__DEFAULTS__;
3332
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__DICT__;
3433
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__GLOBALS__;
3534
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__MODULE__;
@@ -39,7 +38,6 @@
3938
import static com.oracle.graal.python.runtime.exception.PythonErrorType.AttributeError;
4039
import static com.oracle.graal.python.runtime.exception.PythonErrorType.NotImplementedError;
4140

42-
import java.util.ArrayList;
4341
import java.util.List;
4442

4543
import com.oracle.graal.python.builtins.Builtin;
@@ -54,9 +52,7 @@
5452
import com.oracle.graal.python.builtins.objects.method.PMethod;
5553
import com.oracle.graal.python.builtins.objects.module.PythonModule;
5654
import com.oracle.graal.python.builtins.objects.object.PythonObject;
57-
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
5855
import com.oracle.graal.python.nodes.argument.CreateArgumentsNode;
59-
import com.oracle.graal.python.nodes.argument.ReadKeywordNode;
6056
import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode;
6157
import com.oracle.graal.python.nodes.attributes.WriteAttributeToObjectNode;
6258
import com.oracle.graal.python.nodes.call.CallDispatchNode;
@@ -67,14 +63,12 @@
6763
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
6864
import com.oracle.graal.python.nodes.subscript.GetItemNode;
6965
import com.oracle.truffle.api.CompilerDirectives;
70-
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
7166
import com.oracle.truffle.api.dsl.Cached;
7267
import com.oracle.truffle.api.dsl.Fallback;
7368
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
7469
import com.oracle.truffle.api.dsl.NodeFactory;
7570
import com.oracle.truffle.api.dsl.Specialization;
7671
import com.oracle.truffle.api.frame.VirtualFrame;
77-
import com.oracle.truffle.api.nodes.NodeUtil;
7872
import com.oracle.truffle.api.profiles.ConditionProfile;
7973

8074
@CoreFunctions(extendClasses = {PythonBuiltinClassType.PFunction, PythonBuiltinClassType.PBuiltinFunction})
@@ -264,63 +258,6 @@ Object builtinCode(PBuiltinFunction self, Object none) {
264258
}
265259
}
266260

267-
@Builtin(name = __DEFAULTS__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true)
268-
@GenerateNodeFactory
269-
public abstract static class GetDefaultsNode extends PythonBinaryBuiltinNode {
270-
protected final ConditionProfile nullDefaultsProfile = ConditionProfile.createBinaryProfile();
271-
272-
@TruffleBoundary
273-
private static Object[] extractDefaults(PFunction function) {
274-
List<Object> defaultValues = new ArrayList<>();
275-
List<ReadKeywordNode> readKeywordNodes = NodeUtil.findAllNodeInstances(function.getFunctionRootNode(), ReadKeywordNode.class);
276-
for (ReadKeywordNode readKeywordNode : readKeywordNodes) {
277-
Object defaultValue = readKeywordNode.getDefaultValue();
278-
if (defaultValue != null) {
279-
defaultValues.add(defaultValue);
280-
}
281-
}
282-
return defaultValues.toArray();
283-
}
284-
285-
private Object getDefaults(PFunction function) {
286-
Object[] defaults = function.getDefaults();
287-
if (nullDefaultsProfile.profile(defaults == null)) {
288-
defaults = extractDefaults(function);
289-
}
290-
291-
assert defaults != null;
292-
return (defaults.length == 0) ? PNone.NONE : factory().createTuple(defaults);
293-
}
294-
295-
@Specialization
296-
Object defaults(PFunction self, @SuppressWarnings("unused") PNone defaults) {
297-
return getDefaults(self);
298-
}
299-
300-
@Specialization
301-
Object defaults(PFunction self, PTuple defaults) {
302-
self.setDefaults(defaults.getArray());
303-
return PNone.NONE;
304-
}
305-
306-
@Specialization
307-
Object defaults(PMethod self, @SuppressWarnings("unused") PNone defaults) {
308-
return getDefaults(self.getFunction());
309-
}
310-
311-
@Specialization
312-
Object defaults(PMethod self, PTuple defaults) {
313-
self.getFunction().setDefaults(defaults.getArray());
314-
return PNone.NONE;
315-
}
316-
317-
@SuppressWarnings("unused")
318-
@Specialization
319-
Object defaults(PBuiltinFunction self, Object defaults) {
320-
throw raise(AttributeError, "'builtin_function_or_method' object has no attribute '__defaults__'");
321-
}
322-
}
323-
324261
@Builtin(name = __DICT__, fixedNumOfPositionalArgs = 1, isGetter = true)
325262
@GenerateNodeFactory
326263
static abstract class DictNode extends PythonUnaryBuiltinNode {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/FunctionBuiltins.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,22 @@
2626

2727
package com.oracle.graal.python.builtins.objects.function;
2828

29+
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__DEFAULTS__;
2930
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__NAME__;
3031
import static com.oracle.graal.python.nodes.SpecialMethodNames.__REPR__;
3132

33+
import java.util.ArrayList;
3234
import java.util.List;
3335

3436
import com.oracle.graal.python.builtins.Builtin;
3537
import com.oracle.graal.python.builtins.CoreFunctions;
3638
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
3739
import com.oracle.graal.python.builtins.PythonBuiltins;
3840
import com.oracle.graal.python.builtins.objects.PNone;
41+
import com.oracle.graal.python.builtins.objects.function.FunctionBuiltinsFactory.GetFunctionDefaultsNodeFactory;
3942
import com.oracle.graal.python.builtins.objects.str.PString;
43+
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
44+
import com.oracle.graal.python.nodes.argument.ReadKeywordNode;
4045
import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode;
4146
import com.oracle.graal.python.nodes.attributes.WriteAttributeToObjectNode;
4247
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
@@ -52,6 +57,8 @@
5257
import com.oracle.truffle.api.dsl.NodeFactory;
5358
import com.oracle.truffle.api.dsl.Specialization;
5459
import com.oracle.truffle.api.dsl.TypeSystemReference;
60+
import com.oracle.truffle.api.nodes.NodeUtil;
61+
import com.oracle.truffle.api.profiles.ConditionProfile;
5562

5663
@CoreFunctions(extendClasses = PythonBuiltinClassType.PFunction)
5764
public class FunctionBuiltins extends PythonBuiltins {
@@ -128,4 +135,47 @@ Object setName(Object self, Object value) {
128135
}
129136
}
130137

138+
@Builtin(name = __DEFAULTS__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true)
139+
@GenerateNodeFactory
140+
public abstract static class GetFunctionDefaultsNode extends PythonBinaryBuiltinNode {
141+
protected final ConditionProfile nullDefaultsProfile = ConditionProfile.createBinaryProfile();
142+
143+
@TruffleBoundary
144+
private static Object[] extractDefaults(PFunction function) {
145+
List<Object> defaultValues = new ArrayList<>();
146+
List<ReadKeywordNode> readKeywordNodes = NodeUtil.findAllNodeInstances(function.getFunctionRootNode(), ReadKeywordNode.class);
147+
for (ReadKeywordNode readKeywordNode : readKeywordNodes) {
148+
Object defaultValue = readKeywordNode.getDefaultValue();
149+
if (defaultValue != null) {
150+
defaultValues.add(defaultValue);
151+
}
152+
}
153+
return defaultValues.toArray();
154+
}
155+
156+
private Object getDefaults(PFunction function) {
157+
Object[] defaults = function.getDefaults();
158+
if (nullDefaultsProfile.profile(defaults == null)) {
159+
defaults = extractDefaults(function);
160+
}
161+
162+
assert defaults != null;
163+
return (defaults.length == 0) ? PNone.NONE : factory().createTuple(defaults);
164+
}
165+
166+
@Specialization
167+
Object defaults(PFunction self, @SuppressWarnings("unused") PNone defaults) {
168+
return getDefaults(self);
169+
}
170+
171+
@Specialization
172+
Object defaults(PFunction self, PTuple defaults) {
173+
self.setDefaults(defaults.getArray());
174+
return PNone.NONE;
175+
}
176+
177+
public static GetFunctionDefaultsNode create() {
178+
return GetFunctionDefaultsNodeFactory.create();
179+
}
180+
}
131181
}

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
package com.oracle.graal.python.builtins.objects.method;
2828

2929
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__CODE__;
30+
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__DEFAULTS__;
3031
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__FUNC__;
3132
import static com.oracle.graal.python.nodes.SpecialMethodNames.__REPR__;
3233

@@ -36,6 +37,8 @@
3637
import com.oracle.graal.python.builtins.CoreFunctions;
3738
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
3839
import com.oracle.graal.python.builtins.PythonBuiltins;
40+
import com.oracle.graal.python.builtins.objects.PNone;
41+
import com.oracle.graal.python.builtins.objects.function.FunctionBuiltins;
3942
import com.oracle.graal.python.nodes.call.special.LookupAndCallBinaryNode;
4043
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
4144
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
@@ -92,4 +95,14 @@ Object reprMethod(PMethod self,
9295
return String.format("<built-in method %s of %s object at 0x%x>", self.getName(), getClassNode.execute(self.getSelf()).getName(), self.hashCode());
9396
}
9497
}
98+
99+
@Builtin(name = __DEFAULTS__, fixedNumOfPositionalArgs = 1, isGetter = true)
100+
@GenerateNodeFactory
101+
public abstract static class GetMethodDefaultsNode extends PythonUnaryBuiltinNode {
102+
@Specialization
103+
Object defaults(PMethod self,
104+
@Cached("create()") FunctionBuiltins.GetFunctionDefaultsNode getFunctionDefaultsNode) {
105+
return getFunctionDefaultsNode.execute(self.getFunction(), PNone.NO_VALUE);
106+
}
107+
}
95108
}

0 commit comments

Comments
 (0)