Skip to content

Commit ca746a1

Browse files
committed
Fix: 'dir()' did not access the locals.
1 parent 6eeb959 commit ca746a1

File tree

4 files changed

+77
-35
lines changed

4 files changed

+77
-35
lines changed

graalpython/com.oracle.graal.python.test/src/tests/package1/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,5 @@
4040
"""PACKAGE DOC"""
4141

4242
from .lib import *
43+
from .lib1 import *
4344
from . import exported
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Copyright (c) 2019, 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+
lib1_hello = "hello"
41+
def lib1_world(*args):
42+
pass
43+
44+
def __lib1_hidden(*args):
45+
pass
46+
47+
__all__ = [s for s in dir() if not s.startswith("__")]

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,5 +151,9 @@ def test_imp_cached_imports():
151151

152152
def test_import_package_all() :
153153
import package1
154-
assert hasattr(package1, "moduleX"), "'package1' does not have attribute 'moduleX'"
154+
expected_syms = ["moduleX", "lib1_hello", "lib1_world"]
155+
cnt = 0
156+
for expected_sym in expected_syms:
157+
assert hasattr(package1, expected_sym), "'package1' does not have attribute '%s'" % expected_sym
158+
cnt += 1
155159
assert package1.exported.__testname__ == "package1.exported", "expected 'test_import_package_all' but was '%s'" % str(package1.exported.__testname__)

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java

Lines changed: 24 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@
6767
import static com.oracle.graal.python.nodes.SpecialMethodNames.__LEN__;
6868
import static com.oracle.graal.python.nodes.SpecialMethodNames.__NEXT__;
6969
import static com.oracle.graal.python.nodes.SpecialMethodNames.__SUBCLASSCHECK__;
70-
import static com.oracle.graal.python.nodes.frame.FrameSlotIDs.RETURN_SLOT_ID;
7170
import static com.oracle.graal.python.runtime.exception.PythonErrorType.OverflowError;
7271
import static com.oracle.graal.python.runtime.exception.PythonErrorType.TypeError;
7372
import static com.oracle.graal.python.runtime.exception.PythonErrorType.ValueError;
@@ -106,7 +105,6 @@
106105
import com.oracle.graal.python.builtins.objects.function.Signature;
107106
import com.oracle.graal.python.builtins.objects.generator.PGenerator;
108107
import com.oracle.graal.python.builtins.objects.ints.PInt;
109-
import com.oracle.graal.python.builtins.objects.list.PList;
110108
import com.oracle.graal.python.builtins.objects.method.PMethod;
111109
import com.oracle.graal.python.builtins.objects.module.PythonModule;
112110
import com.oracle.graal.python.builtins.objects.object.PythonObject;
@@ -134,7 +132,8 @@
134132
import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode;
135133
import com.oracle.graal.python.nodes.attributes.SetAttributeNode;
136134
import com.oracle.graal.python.nodes.attributes.WriteAttributeToObjectNode;
137-
import com.oracle.graal.python.nodes.builtins.ListNodes.AppendNode;
135+
import com.oracle.graal.python.nodes.builtins.ListNodes;
136+
import com.oracle.graal.python.nodes.builtins.ListNodes.ConstructListContextManager;
138137
import com.oracle.graal.python.nodes.call.CallNode;
139138
import com.oracle.graal.python.nodes.call.GenericInvokeNode;
140139
import com.oracle.graal.python.nodes.call.PythonCallNode;
@@ -188,8 +187,6 @@
188187
import com.oracle.truffle.api.dsl.Specialization;
189188
import com.oracle.truffle.api.dsl.TypeSystemReference;
190189
import com.oracle.truffle.api.frame.Frame;
191-
import com.oracle.truffle.api.frame.FrameDescriptor;
192-
import com.oracle.truffle.api.frame.FrameSlot;
193190
import com.oracle.truffle.api.frame.VirtualFrame;
194191
import com.oracle.truffle.api.interop.UnsupportedMessageException;
195192
import com.oracle.truffle.api.library.CachedLibrary;
@@ -521,41 +518,29 @@ Object hash(VirtualFrame frame, Object object,
521518
@Builtin(name = DIR, minNumOfPositionalArgs = 0, maxNumOfPositionalArgs = 1)
522519
@GenerateNodeFactory
523520
public abstract static class DirNode extends PythonBuiltinNode {
524-
@Child private AppendNode appendNode;
525521

522+
// logic like in 'Objects/object.c: _dir_locals'
526523
@Specialization(guards = "isNoValue(object)")
527-
@SuppressWarnings("unused")
528-
public Object dir(VirtualFrame frame, Object object) {
529-
PList locals = factory().createList();
530-
FrameDescriptor frameDescriptor = frame.getFrameDescriptor();
531-
addIdsFromDescriptor(locals, frameDescriptor);
532-
return locals;
533-
}
524+
Object locals(VirtualFrame frame, @SuppressWarnings("unused") Object object,
525+
@Cached ReadLocalsNode readLocalsNode,
526+
@Cached ReadCallerFrameNode readCallerFrameNode,
527+
@Cached MaterializeFrameNode materializeNode,
528+
@Cached("createBinaryProfile()") ConditionProfile inGenerator,
529+
@Cached("create(KEYS)") LookupAndCallUnaryNode callKeysNode,
530+
@Cached ListNodes.ConstructListNode constructListNode) {
534531

535-
@TruffleBoundary
536-
private void addIdsFromDescriptor(PList locals, FrameDescriptor frameDescriptor) {
537-
for (FrameSlot slot : frameDescriptor.getSlots()) {
538-
// XXX: remove this special case
539-
if (slot.getIdentifier().equals(RETURN_SLOT_ID)) {
540-
continue;
541-
}
542-
getAppendNode().execute(locals, slot.getIdentifier());
532+
Object localsDict = LocalsNode.getLocalsDict(frame, this, readLocalsNode, readCallerFrameNode, materializeNode, inGenerator);
533+
Object keysObj = callKeysNode.executeObject(frame, localsDict);
534+
try (ConstructListContextManager cm = constructListNode.withGlobalState(getContextRef(), frame)) {
535+
return cm.execute(keysObj);
543536
}
544537
}
545538

546539
@Specialization(guards = "!isNoValue(object)")
547-
public Object dir(VirtualFrame frame, Object object,
540+
Object dir(VirtualFrame frame, Object object,
548541
@Cached("create(__DIR__)") LookupAndCallUnaryNode dirNode) {
549542
return dirNode.executeObject(frame, object);
550543
}
551-
552-
private AppendNode getAppendNode() {
553-
if (appendNode == null) {
554-
CompilerDirectives.transferToInterpreterAndInvalidate();
555-
appendNode = insert(AppendNode.create());
556-
}
557-
return appendNode;
558-
}
559544
}
560545

561546
// divmod(a, b)
@@ -1973,19 +1958,24 @@ public Object globals(VirtualFrame frame,
19731958
@Builtin(name = "locals", minNumOfPositionalArgs = 0)
19741959
@GenerateNodeFactory
19751960
abstract static class LocalsNode extends PythonBuiltinNode {
1976-
private final ConditionProfile inGenerator = ConditionProfile.createBinaryProfile();
19771961

19781962
@Specialization
1979-
public Object locals(VirtualFrame frame,
1963+
Object locals(VirtualFrame frame,
19801964
@Cached ReadLocalsNode readLocalsNode,
19811965
@Cached ReadCallerFrameNode readCallerFrameNode,
1982-
@Cached MaterializeFrameNode materializeNode) {
1966+
@Cached MaterializeFrameNode materializeNode,
1967+
@Cached("createBinaryProfile()") ConditionProfile inGenerator) {
1968+
return getLocalsDict(frame, this, readLocalsNode, readCallerFrameNode, materializeNode, inGenerator);
1969+
}
1970+
1971+
static Object getLocalsDict(VirtualFrame frame, Node n, ReadLocalsNode readLocalsNode, ReadCallerFrameNode readCallerFrameNode, MaterializeFrameNode materializeNode,
1972+
ConditionProfile inGenerator) {
19831973
PFrame callerFrame = readCallerFrameNode.executeWith(frame, 0);
19841974
Frame generatorFrame = PArguments.getGeneratorFrame(callerFrame.getArguments());
19851975
if (inGenerator.profile(generatorFrame == null)) {
19861976
return readLocalsNode.execute(frame, callerFrame);
19871977
} else {
1988-
return readLocalsNode.execute(frame, materializeNode.execute(frame, this, false, false, generatorFrame));
1978+
return readLocalsNode.execute(frame, materializeNode.execute(frame, n, false, false, generatorFrame));
19891979
}
19901980
}
19911981
}

0 commit comments

Comments
 (0)