Skip to content

Commit 0ab3825

Browse files
committed
[GR-23218] Make test_descr pass - smaller fixes.
PullRequest: graalpython/1196
2 parents ea0f9a4 + 14e0651 commit 0ab3825

13 files changed

Lines changed: 298 additions & 83 deletions

File tree

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -963,3 +963,23 @@ def test_update():
963963
y = {}
964964
y.update(x)
965965
assert y == x
966+
967+
def test_module_dict():
968+
import sys
969+
ModuleType = type(sys)
970+
971+
foo = ModuleType.__new__(ModuleType)
972+
assert foo.__dict__ == None
973+
974+
foo = ModuleType.__new__(ModuleType)
975+
foo.f = 1
976+
assert foo.__dict__ == {"f" : 1}
977+
978+
del foo.f
979+
assert foo.__dict__ == {}
980+
981+
foo = ModuleType.__new__(ModuleType)
982+
foo.f = 1
983+
del foo.f
984+
assert foo.__dict__ == {}
985+

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

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2019, 2020, 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
@@ -37,6 +37,14 @@
3737
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3838
# SOFTWARE.
3939

40+
def assert_raises(err, fn, *args, **kwargs):
41+
raised = False
42+
try:
43+
fn(*args, **kwargs)
44+
except err:
45+
raised = True
46+
assert raised
47+
4048
def some_fun(self, key):
4149
return "hello from %s" % key
4250

@@ -52,3 +60,19 @@ def test_callCustomAttr():
5260
def test_getattr():
5361
assert getattr(CustomAttr(), "uff") == "hello from uff"
5462

63+
def test_key_is_string():
64+
assert_raises(TypeError, type.__getattribute__, list, type)
65+
assert_raises(TypeError, object.__getattribute__, list, type)
66+
67+
import types
68+
class M(types.ModuleType):
69+
def m(self):
70+
pass
71+
72+
assert_raises(TypeError, types.ModuleType.__getattribute__, M('a'), type)
73+
assert_raises(TypeError, types.MethodType.__getattribute__, M('a').m, type)
74+
75+
76+
assert_raises(TypeError, types.ModuleType.__getattribute__, list, type)
77+
assert_raises(TypeError, types.MethodType.__getattribute__, list, type)
78+
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
2+
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3+
#
4+
# The Universal Permissive License (UPL), Version 1.0
5+
#
6+
# Subject to the condition set forth below, permission is hereby granted to any
7+
# person obtaining a copy of this software, associated documentation and/or
8+
# data (collectively the "Software"), free of charge and under any and all
9+
# copyright rights in the Software, and any and all patent rights owned or
10+
# freely licensable by each licensor hereunder covering either (i) the
11+
# unmodified Software as contributed to or provided by such licensor, or (ii)
12+
# the Larger Works (as defined below), to deal in both
13+
#
14+
# (a) the Software, and
15+
#
16+
# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
17+
# one is included with the Software each a "Larger Work" to which the Software
18+
# is contributed by such licensors),
19+
#
20+
# without restriction, including without limitation the rights to copy, create
21+
# derivative works of, display, perform, and distribute the Software and make,
22+
# use, sell, offer for sale, import, export, have made, and have sold the
23+
# Software and the Larger Work(s), and to sublicense the foregoing rights on
24+
# either these or other terms.
25+
#
26+
# This license is subject to the following condition:
27+
#
28+
# The above copyright notice and either this complete permission notice or at a
29+
# minimum a reference to the UPL must be included in all copies or substantial
30+
# portions of the Software.
31+
#
32+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
33+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
35+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
36+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
37+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38+
# SOFTWARE.
39+
40+
def assert_raises(err, fn, *args, **kwargs):
41+
raised = False
42+
try:
43+
fn(*args, **kwargs)
44+
except err:
45+
raised = True
46+
assert raised
47+
48+
def test_key_is_string():
49+
import types
50+
class M(types.ModuleType):
51+
def m(self):
52+
pass
53+
54+
assert_raises(TypeError, type.__setattr__, M, type, 42)
55+
assert_raises(TypeError, object.__setattr__, M('m'), type, 42)
56+
assert_raises(TypeError, types.ModuleType.__setattr__, M('m'), type, 42)
57+
assert_raises(TypeError, types.MethodType.__setattr__, M('m').m, type, 42)

graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_descr.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*graalpython.lib-python.3.test.test_descr.ClassPropertiesAndMethods.test_buffer_inheritance
88
*graalpython.lib-python.3.test.test_descr.ClassPropertiesAndMethods.test_builtin_bases
99
*graalpython.lib-python.3.test.test_descr.ClassPropertiesAndMethods.test_builtin_function_or_method
10+
*graalpython.lib-python.3.test.test_descr.ClassPropertiesAndMethods.test_carloverre_multi_inherit_valid
1011
*graalpython.lib-python.3.test.test_descr.ClassPropertiesAndMethods.test_classic
1112
*graalpython.lib-python.3.test.test_descr.ClassPropertiesAndMethods.test_classic_comparisons
1213
*graalpython.lib-python.3.test.test_descr.ClassPropertiesAndMethods.test_classmethods
@@ -74,6 +75,9 @@
7475
*graalpython.lib-python.3.test.test_descr.ClassPropertiesAndMethods.test_str_subclass_as_dict_key
7576
*graalpython.lib-python.3.test.test_descr.ClassPropertiesAndMethods.test_subclass_propagation
7677
*graalpython.lib-python.3.test.test_descr.ClassPropertiesAndMethods.test_testcapi_no_segfault
78+
*graalpython.lib-python.3.test.test_descr.ClassPropertiesAndMethods.test_type___getattribute__
79+
*graalpython.lib-python.3.test.test_descr.ClassPropertiesAndMethods.test_uninitialized_modules
80+
*graalpython.lib-python.3.test.test_descr.ClassPropertiesAndMethods.test_unsubclassable_types
7781
*graalpython.lib-python.3.test.test_descr.ClassPropertiesAndMethods.test_vicious_descriptor_nonsense
7882
*graalpython.lib-python.3.test.test_descr.ClassPropertiesAndMethods.test_weakref_segfault
7983
*graalpython.lib-python.3.test.test_descr.ClassPropertiesAndMethods.test_wrapper_segfault

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignObjectBuiltins.java

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
import com.oracle.graal.python.builtins.objects.object.ObjectBuiltinsFactory;
8080
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
8181
import com.oracle.graal.python.nodes.ErrorMessages;
82+
import com.oracle.graal.python.nodes.PGuards;
8283
import com.oracle.graal.python.nodes.PRaiseNode;
8384
import com.oracle.graal.python.nodes.call.special.LookupAndCallBinaryNode;
8485
import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode;
@@ -92,6 +93,8 @@
9293
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
9394
import com.oracle.graal.python.nodes.interop.PForeignToPTypeNode;
9495
import com.oracle.graal.python.nodes.interop.PTypeToForeignNode;
96+
import com.oracle.graal.python.nodes.util.CannotCastException;
97+
import com.oracle.graal.python.nodes.util.CastToJavaStringNode;
9598
import com.oracle.graal.python.runtime.ExecutionContext.ForeignCallContext;
9699
import com.oracle.graal.python.runtime.PythonContext;
97100
import com.oracle.graal.python.runtime.exception.PythonErrorType;
@@ -101,6 +104,7 @@
101104
import com.oracle.truffle.api.dsl.CachedContext;
102105
import com.oracle.truffle.api.dsl.Fallback;
103106
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
107+
import com.oracle.truffle.api.dsl.ImportStatic;
104108
import com.oracle.truffle.api.dsl.NodeFactory;
105109
import com.oracle.truffle.api.dsl.Specialization;
106110
import com.oracle.truffle.api.frame.VirtualFrame;
@@ -664,26 +668,34 @@ abstract static class GetattrNode extends PythonBinaryBuiltinNode {
664668
@Child private PForeignToPTypeNode toPythonNode = PForeignToPTypeNode.create();
665669

666670
@Specialization
667-
protected Object doIt(Object object, String member,
668-
@CachedLibrary(limit = "getAttributeAccessInlineCacheMaxDepth()") InteropLibrary read) {
671+
protected Object doIt(Object object, Object memberObj,
672+
@CachedLibrary(limit = "getAttributeAccessInlineCacheMaxDepth()") InteropLibrary read,
673+
@Cached CastToJavaStringNode castToString) {
669674
try {
675+
String member = castToString.execute(memberObj);
670676
if (read.isMemberReadable(object, member)) {
671677
return toPythonNode.executeConvert(read.readMember(object, member));
672678
}
679+
} catch (CannotCastException e) {
680+
throw raise(PythonBuiltinClassType.TypeError, ErrorMessages.ATTR_NAME_MUST_BE_STRING, memberObj);
673681
} catch (UnknownIdentifierException | UnsupportedMessageException ignore) {
674682
}
675-
throw raise(PythonErrorType.AttributeError, ErrorMessages.FOREIGN_OBJ_HAS_NO_ATTR_S, member);
683+
throw raise(PythonErrorType.AttributeError, ErrorMessages.FOREIGN_OBJ_HAS_NO_ATTR_S, memberObj);
676684
}
677685
}
678686

687+
@ImportStatic(PGuards.class)
679688
@Builtin(name = __SETATTR__, minNumOfPositionalArgs = 3)
680689
@GenerateNodeFactory
681690
abstract static class SetattrNode extends PythonTernaryBuiltinNode {
682691
@Specialization
683-
protected PNone doIt(Object object, String key, Object value,
684-
@CachedLibrary(limit = "3") InteropLibrary lib) {
692+
protected PNone doIt(Object object, Object key, Object value,
693+
@CachedLibrary(limit = "3") InteropLibrary lib,
694+
@Cached CastToJavaStringNode castToString) {
685695
try {
686-
lib.writeMember(object, key, value);
696+
lib.writeMember(object, castToString.execute(key), value);
697+
} catch (CannotCastException e) {
698+
throw raise(PythonBuiltinClassType.TypeError, ErrorMessages.ATTR_NAME_MUST_BE_STRING, key);
687699
} catch (UnknownIdentifierException | UnsupportedMessageException | UnsupportedTypeException e) {
688700
throw raise(PythonErrorType.AttributeError, ErrorMessages.FOREIGN_OBJ_HAS_NO_ATTR_S, key);
689701
}
@@ -708,9 +720,12 @@ Object doit(VirtualFrame frame, Object object, Object key, Object value) {
708720
abstract static class DelattrNode extends PythonBinaryBuiltinNode {
709721
@Specialization
710722
protected PNone doIt(Object object, String key,
711-
@CachedLibrary(limit = "3") InteropLibrary lib) {
723+
@CachedLibrary(limit = "3") InteropLibrary lib,
724+
@Cached CastToJavaStringNode castToString) {
712725
try {
713-
lib.removeMember(object, key);
726+
lib.removeMember(object, castToString.execute(key));
727+
} catch (CannotCastException e) {
728+
throw raise(PythonBuiltinClassType.TypeError, ErrorMessages.ATTR_NAME_MUST_BE_STRING, key);
714729
} catch (UnknownIdentifierException | UnsupportedMessageException e) {
715730
throw raise(PythonErrorType.AttributeError, ErrorMessages.FOREIGN_OBJ_HAS_NO_ATTR_S, key);
716731
}

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

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__KWDEFAULTS__;
3434
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__NAME__;
3535
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__QUALNAME__;
36-
import static com.oracle.graal.python.nodes.SpecialMethodNames.__GETATTRIBUTE__;
3736
import static com.oracle.graal.python.nodes.SpecialMethodNames.__GET__;
3837
import static com.oracle.graal.python.nodes.SpecialMethodNames.__REDUCE__;
3938
import static com.oracle.graal.python.nodes.SpecialMethodNames.__REPR__;
@@ -46,10 +45,14 @@
4645
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
4746
import com.oracle.graal.python.builtins.PythonBuiltins;
4847
import com.oracle.graal.python.builtins.objects.PNone;
48+
import com.oracle.graal.python.builtins.objects.dict.PDict;
4949
import com.oracle.graal.python.builtins.objects.function.PKeyword;
5050
import com.oracle.graal.python.builtins.objects.object.ObjectBuiltins;
51+
import com.oracle.graal.python.builtins.objects.object.PythonObject;
5152
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
5253
import com.oracle.graal.python.nodes.ErrorMessages;
54+
import com.oracle.graal.python.nodes.PGuards;
55+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__GETATTRIBUTE__;
5356
import com.oracle.graal.python.nodes.builtins.FunctionNodes.GetDefaultsNode;
5457
import com.oracle.graal.python.nodes.builtins.FunctionNodes.GetKeywordDefaultsNode;
5558
import com.oracle.graal.python.nodes.call.special.LookupAndCallBinaryNode;
@@ -62,12 +65,15 @@
6265
import com.oracle.graal.python.nodes.util.CannotCastException;
6366
import com.oracle.graal.python.nodes.util.CastToJavaStringNode;
6467
import com.oracle.graal.python.runtime.exception.PException;
68+
import com.oracle.truffle.api.CompilerDirectives;
6569
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
6670
import com.oracle.truffle.api.dsl.Cached;
6771
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
72+
import com.oracle.truffle.api.dsl.ImportStatic;
6873
import com.oracle.truffle.api.dsl.NodeFactory;
6974
import com.oracle.truffle.api.dsl.Specialization;
7075
import com.oracle.truffle.api.frame.VirtualFrame;
76+
import com.oracle.truffle.api.interop.UnsupportedMessageException;
7177
import com.oracle.truffle.api.library.CachedLibrary;
7278

7379
@CoreFunctions(extendClasses = PythonBuiltinClassType.PMethod)
@@ -105,27 +111,53 @@ protected Object doIt(VirtualFrame frame, PMethod self,
105111
@Builtin(name = __DICT__, minNumOfPositionalArgs = 1, isGetter = true)
106112
@GenerateNodeFactory
107113
public abstract static class DictNode extends PythonBuiltinNode {
108-
@Specialization
109-
protected Object doIt(VirtualFrame frame, PMethod self,
110-
@Cached("create(__GETATTRIBUTE__)") LookupAndCallBinaryNode getDict) {
111-
return getDict.executeObject(frame, self.getFunction(), __DICT__);
114+
@Specialization(limit = "1")
115+
protected Object doIt(PMethod self,
116+
@CachedLibrary("self.getFunction()") PythonObjectLibrary lib) {
117+
PDict dict = lib.getDict(self.getFunction());
118+
if (dict == null) {
119+
// A native object should already have a dict,
120+
// so it's safe to assume it's a PythonObject
121+
dict = factory().createDictFixedStorage((PythonObject) self.getFunction());
122+
try {
123+
lib.setDict(self.getFunction(), dict);
124+
} catch (UnsupportedMessageException e) {
125+
CompilerDirectives.transferToInterpreterAndInvalidate();
126+
throw new IllegalStateException(e);
127+
}
128+
}
129+
return dict;
112130
}
113131
}
114132

133+
@ImportStatic(PGuards.class)
115134
@Builtin(name = __GETATTRIBUTE__, minNumOfPositionalArgs = 2)
116135
@GenerateNodeFactory
117136
public abstract static class GetattributeNode extends PythonBuiltinNode {
118137
@Specialization
119-
protected Object doIt(VirtualFrame frame, PMethod self, Object key,
138+
protected Object doIt(VirtualFrame frame, PMethod self, Object keyObj,
120139
@Cached("create()") ObjectBuiltins.GetAttributeNode objectGetattrNode,
121-
@Cached("create()") IsBuiltinClassProfile errorProfile) {
140+
@Cached("create()") IsBuiltinClassProfile errorProfile,
141+
@Cached CastToJavaStringNode castKeyToStringNode) {
142+
String key;
143+
try {
144+
key = castKeyToStringNode.execute(keyObj);
145+
} catch (CannotCastException e) {
146+
throw raise(TypeError, ErrorMessages.ATTR_NAME_MUST_BE_STRING, keyObj);
147+
}
148+
122149
try {
123150
return objectGetattrNode.execute(frame, self, key);
124151
} catch (PException e) {
125152
e.expectAttributeError(errorProfile);
126153
return objectGetattrNode.execute(frame, self.getFunction(), key);
127154
}
128155
}
156+
157+
@Specialization(guards = "!isPMethod(self)")
158+
Object getattribute(Object self, @SuppressWarnings("unused") Object key) {
159+
throw raise(TypeError, ErrorMessages.DESCRIPTOR_REQUIRES_OBJ, __GETATTRIBUTE__, "method", self);
160+
}
129161
}
130162

131163
@Builtin(name = __REPR__, minNumOfPositionalArgs = 1)

0 commit comments

Comments
 (0)