Skip to content

Commit 9439701

Browse files
committed
[GR-34598] improve compat with pytest
PullRequest: graalpython/2149
2 parents 68bb2d7 + 03d2e87 commit 9439701

File tree

11 files changed

+233
-54
lines changed

11 files changed

+233
-54
lines changed

graalpython/com.oracle.graal.python.cext/posix/posix.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -130,8 +130,10 @@ int32_t call_dup(int32_t fd) {
130130

131131
int32_t call_dup2(int32_t oldfd, int32_t newfd, int32_t inheritable) {
132132
#ifdef __gnu_linux__
133-
return dup3(oldfd, newfd, inheritable ? 0 : O_CLOEXEC);
134-
#else
133+
if (!inheritable) {
134+
return dup3(oldfd, newfd, O_CLOEXEC);
135+
}
136+
#endif
135137
int res = dup2(oldfd, newfd);
136138
if (res < 0) {
137139
return res;
@@ -143,7 +145,6 @@ int32_t call_dup2(int32_t oldfd, int32_t newfd, int32_t inheritable) {
143145
}
144146
}
145147
return res;
146-
#endif
147148
}
148149

149150
int32_t call_pipe2(int32_t *pipefd) {

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2018, 2022, 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
@@ -47,6 +47,14 @@ def test_lineno():
4747
assert sys._getframe(0).f_lineno == 47
4848

4949

50+
# IMPORTANT: DO NOT MOVE!
51+
def test_nested_lineno():
52+
def test_nested():
53+
return sys._getframe(0)
54+
f = test_nested()
55+
assert f.f_lineno == 53
56+
57+
5058
def test_read_and_write_locals():
5159
a = 1
5260
b = ''

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

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2018, 2022, 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
@@ -249,3 +249,21 @@ def test_function_text_signature_writable():
249249
def foo(): pass
250250
foo.__text_signature__ = 'foo()'
251251
assert foo.__text_signature__ == 'foo()'
252+
253+
254+
def test_function_no_module():
255+
def wrapper_2(func):
256+
ns = {}
257+
exec('def fail_func(): raise ValueError("fail")', ns)
258+
return ns['fail_func']
259+
260+
def wrapper_1(func):
261+
assert hasattr(func, '__name__')
262+
assert hasattr(func, '__module__')
263+
assert func.__module__ is None
264+
return func
265+
266+
@wrapper_1
267+
@wrapper_2
268+
def test_func():
269+
pass

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

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,29 +1045,32 @@ static final class SyntaxErrData {
10451045
final int lineNo;
10461046
final int offset;
10471047
final Object text;
1048+
final boolean err;
10481049

1049-
SyntaxErrData(Object message, Object fileName, int lineNo, int offset, Object text) {
1050+
SyntaxErrData(Object message, Object fileName, int lineNo, int offset, Object text, boolean err) {
10501051
this.message = message;
10511052
this.fileName = fileName;
10521053
this.lineNo = lineNo;
10531054
this.offset = offset;
10541055
this.text = text;
1056+
this.err = err;
10551057
}
10561058
}
10571059

10581060
private SyntaxErrData parseSyntaxError(VirtualFrame frame, Object err) {
1059-
String msg, fileName = null, text = null;
1060-
int lineNo = 0, offset = 0, hold = 0;
1061+
Object v, msg;
1062+
String fileName = null, text = null;
1063+
int lineNo = 0, offset = 0, hold;
10611064

10621065
// new style errors. `err' is an instance
1063-
msg = objectLookupAttrAsString(frame, err, ATTR_MSG);
1064-
if (msg == null) {
1065-
return new SyntaxErrData(msg, fileName, lineNo, offset, text);
1066+
msg = objectLookupAttr(frame, err, ATTR_MSG);
1067+
if (msg == PNone.NO_VALUE) {
1068+
return new SyntaxErrData(null, fileName, lineNo, offset, text, true);
10661069
}
10671070

1068-
Object v = objectLookupAttr(frame, err, ATTR_FILENAME);
1071+
v = objectLookupAttr(frame, err, ATTR_FILENAME);
10691072
if (v == PNone.NO_VALUE) {
1070-
return new SyntaxErrData(msg, fileName, lineNo, offset, text);
1073+
return new SyntaxErrData(msg, fileName, lineNo, offset, text, true);
10711074
}
10721075
if (v == PNone.NONE) {
10731076
fileName = VALUE_STRING;
@@ -1077,42 +1080,42 @@ private SyntaxErrData parseSyntaxError(VirtualFrame frame, Object err) {
10771080

10781081
v = objectLookupAttr(frame, err, ATTR_LINENO);
10791082
if (v == PNone.NO_VALUE) {
1080-
return new SyntaxErrData(msg, fileName, lineNo, offset, text);
1083+
return new SyntaxErrData(msg, fileName, lineNo, offset, text, true);
10811084
}
10821085
try {
10831086
hold = longAsInt(frame, v);
10841087
} catch (PException pe) {
1085-
return new SyntaxErrData(msg, fileName, lineNo, offset, text);
1088+
return new SyntaxErrData(msg, fileName, lineNo, offset, text, true);
10861089
}
10871090

10881091
lineNo = hold;
10891092

10901093
v = objectLookupAttr(frame, err, ATTR_OFFSET);
10911094
if (v == PNone.NO_VALUE) {
1092-
return new SyntaxErrData(msg, fileName, lineNo, offset, text);
1095+
return new SyntaxErrData(msg, fileName, lineNo, offset, text, true);
10931096
}
10941097
if (v == PNone.NONE) {
10951098
offset = -1;
10961099
} else {
10971100
try {
10981101
hold = longAsInt(frame, v);
10991102
} catch (PException pe) {
1100-
return new SyntaxErrData(msg, fileName, lineNo, offset, text);
1103+
return new SyntaxErrData(msg, fileName, lineNo, offset, text, true);
11011104
}
11021105
offset = hold;
11031106
}
11041107

11051108
v = objectLookupAttr(frame, err, ATTR_TEXT);
11061109
if (v == PNone.NO_VALUE) {
1107-
return new SyntaxErrData(msg, fileName, lineNo, offset, text);
1110+
return new SyntaxErrData(msg, fileName, lineNo, offset, text, true);
11081111
}
11091112
if (v == PNone.NONE) {
11101113
text = null;
11111114
} else {
11121115
text = castToString(v);
11131116
}
11141117

1115-
return new SyntaxErrData(msg, fileName, lineNo, offset, text);
1118+
return new SyntaxErrData(msg, fileName, lineNo, offset, text, false);
11161119
}
11171120

11181121
private void printErrorText(VirtualFrame frame, Object out, SyntaxErrData syntaxErrData) {
@@ -1200,14 +1203,16 @@ protected void printException(VirtualFrame frame, PythonModule sys, Object out,
12001203
if (objectHasAttr(frame, value, ATTR_PRINT_FILE_AND_LINE)) {
12011204
// SyntaxError case
12021205
final SyntaxErrData syntaxErrData = parseSyntaxError(frame, value);
1203-
value = syntaxErrData.message;
1204-
StringBuilder sb = PythonUtils.newStringBuilder(" File \"");
1205-
PythonUtils.append(sb, castToString(objectStr(frame, syntaxErrData.fileName)), "\", line ", syntaxErrData.lineNo, "\n");
1206-
fileWriteString(frame, out, PythonUtils.sbToString(sb));
1207-
1208-
// Can't be bothered to check all those PyFile_WriteString() calls
1209-
if (syntaxErrData.text != null) {
1210-
printErrorText(frame, out, syntaxErrData);
1206+
if (!syntaxErrData.err) {
1207+
value = syntaxErrData.message;
1208+
StringBuilder sb = PythonUtils.newStringBuilder(" File \"");
1209+
PythonUtils.append(sb, castToString(objectStr(frame, syntaxErrData.fileName)), "\", line ", syntaxErrData.lineNo, "\n");
1210+
fileWriteString(frame, out, PythonUtils.sbToString(sb));
1211+
1212+
// Can't be bothered to check all those PyFile_WriteString() calls
1213+
if (syntaxErrData.text != null) {
1214+
printErrorText(frame, out, syntaxErrData);
1215+
}
12111216
}
12121217
}
12131218

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/PFrame.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -300,6 +300,10 @@ public void setLocation(Node location) {
300300
this.location = location;
301301
}
302302

303+
public Node getLocation() {
304+
return location;
305+
}
306+
303307
/**
304308
* Last bytecode instruction. Since we don't have bytecode this is -1 by default, but can be set
305309
* to a different value to distinguish started generators from unstarted

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

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2021, Oracle and/or its affiliates.
2+
* Copyright (c) 2017, 2022, Oracle and/or its affiliates.
33
* Copyright (c) 2014, Regents of the University of California
44
*
55
* All rights reserved.
@@ -67,6 +67,7 @@
6767
import com.oracle.graal.python.nodes.object.GetOrCreateDictNode;
6868
import com.oracle.graal.python.nodes.object.SetDictNode;
6969
import com.oracle.graal.python.nodes.subscript.GetItemNode;
70+
import com.oracle.graal.python.runtime.exception.PException;
7071
import com.oracle.truffle.api.CompilerDirectives;
7172
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
7273
import com.oracle.truffle.api.dsl.Cached;
@@ -181,10 +182,15 @@ static Object getModule(VirtualFrame frame, PFunction self, @SuppressWarnings("u
181182
if (module == PNone.NO_VALUE) {
182183
CompilerDirectives.transferToInterpreter();
183184
PythonObject globals = self.getGlobals();
184-
if (globals instanceof PythonModule) {
185-
module = globals.getAttribute(__NAME__);
186-
} else {
187-
module = getItem.execute(frame, globals, __NAME__);
185+
// __module__: If module name is in globals, use it. Otherwise, use None.
186+
try {
187+
if (globals instanceof PythonModule) {
188+
module = globals.getAttribute(__NAME__);
189+
} else {
190+
module = getItem.execute(frame, globals, __NAME__);
191+
}
192+
} catch (PException pe) {
193+
module = PNone.NONE;
188194
}
189195
writeObject.execute(self, __MODULE__, module);
190196
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package com.oracle.graal.python.lib;
42+
43+
import com.oracle.graal.python.builtins.objects.PNone;
44+
import com.oracle.graal.python.nodes.ErrorMessages;
45+
import com.oracle.graal.python.nodes.PNodeWithContext;
46+
import com.oracle.graal.python.nodes.PRaiseNode;
47+
import com.oracle.graal.python.runtime.exception.PythonErrorType;
48+
import com.oracle.truffle.api.dsl.Cached;
49+
import com.oracle.truffle.api.dsl.GenerateUncached;
50+
import com.oracle.truffle.api.dsl.Specialization;
51+
import com.oracle.truffle.api.frame.Frame;
52+
import com.oracle.truffle.api.frame.VirtualFrame;
53+
54+
/**
55+
* Equivalent of CPython's {@code _Py_convert_optional_to_ssize_t} function. If value is
56+
* {@code None}, {@code defaultValue} is returned.
57+
*/
58+
@GenerateUncached
59+
public abstract class PyConvertOptionalToSizeNode extends PNodeWithContext {
60+
public abstract int execute(Frame frame, Object object, int defaultValue);
61+
62+
@Specialization(guards = "isNone(value)")
63+
int doOptional(VirtualFrame frame, @SuppressWarnings("unused") PNone value, int defaultValue) {
64+
return defaultValue;
65+
}
66+
67+
@Specialization(guards = {"!isNone(value)", "!isNoValue(value)"})
68+
int doObject(VirtualFrame frame, Object value, @SuppressWarnings("unused") int defaultValue,
69+
@Cached PRaiseNode raiseNode,
70+
@Cached PyIndexCheckNode indexCheckNode,
71+
@Cached PyNumberAsSizeNode asSizeNode) {
72+
int limit;
73+
if (indexCheckNode.execute(value)) {
74+
limit = asSizeNode.executeExact(frame, value);
75+
} else {
76+
throw raiseNode.raise(PythonErrorType.TypeError, ErrorMessages.ARG_SHOULD_BE_INT_OR_NONE, value);
77+
}
78+
return limit;
79+
}
80+
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ErrorMessages.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ public abstract class ErrorMessages {
5757
public static final String ARG_IS_EMPTY_SEQ = "%s() arg is an empty sequence";
5858
public static final String ARG_MUST_BE_INT_OR_HAVE_FILENO_METHOD = "argument must be an int, or have a fileno() method.";
5959
public static final String ARG_MUST_BE_NUMBER = "%s argument must be a number, not '%p'";
60-
public static final String ARG_MUST_BE_S_NOT_P = "%s argument must be a %s, not %p";
60+
public static final String ARG_MUST_BE_S_NOT_P = "%s argument must be %s, not %p";
6161
public static final String ARGUMENTS_MUST_BE_ITERATORS = "Arguments must be iterators";
62-
public static final String S_BRACKETS_ARG_MUST_BE_S_NOT_P = "%s() argument must be a %s, not %p";
62+
public static final String S_BRACKETS_ARG_MUST_BE_S_NOT_P = "%s() argument must be %s, not %p";
6363
public static final String S_BRACKETS_ARG_MUST_BE_READ_WRITE_BYTES_LIKE_NOT_P = "%s() argument must be read-write bytes-like object, not %p";
6464
public static final String ARG_MUST_BE_CALLABLE = "argument must be callable";
6565
public static final String S_ARG_MUST_BE_CALLABLE = "%s argument must be callable";

0 commit comments

Comments
 (0)