Skip to content

Commit bf582d8

Browse files
committed
[GR-80787] GitHub PRs #1227-1232
PullRequest: graalpython/4973
2 parents 0d21997 + eed07ce commit bf582d8

11 files changed

Lines changed: 107 additions & 26 deletions

File tree

‎graalpython/com.oracle.graal.python.test/src/tests/test_bytes.py‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,16 @@ def __bytes__(self):
8989
assert_raises(TypeError, bytes, errors="strict")
9090

9191

92+
def test_decode_empty_skips_codec_lookup():
93+
assert str(b'', 'x') == ''
94+
assert str(bytearray(), 'x', 'y') == ''
95+
assert str(memoryview(b''), 'x') == ''
96+
assert b''.decode('x') == ''
97+
assert bytearray().decode('x') == ''
98+
assert_raises(LookupError, str, b'a', 'x')
99+
assert_raises(TypeError, str, 1, 'x')
100+
101+
92102
def test_from_ssize():
93103
assert bytes(0) == b''
94104
assert bytes(1) == b'\x00'

‎graalpython/com.oracle.graal.python.test/src/tests/test_complex.py‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,20 @@ class SubComplex(complex):
304304
assert result == 2 + 3j
305305
assert type(result) is complex
306306

307+
308+
def test_create_checks_arguments_before_converting():
309+
class RaisingReal:
310+
def __float__(self):
311+
raise KeyError
312+
313+
class RaisingImag:
314+
def __float__(self):
315+
raise RuntimeError
316+
317+
assert_raises(TypeError, complex, {}, RaisingImag())
318+
assert_raises(TypeError, complex, RaisingReal(), {})
319+
assert_raises(KeyError, complex, RaisingReal(), RaisingImag())
320+
307321
class ComplexTest(unittest.TestCase):
308322

309323
def assertAlmostEqual(self, a, b):

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2007,3 +2007,16 @@ def test_bulk_value_update_preserves_iterators():
20072007
d.update({k: -v for k, v in d.items()})
20082008
assert list(it) == expected[1:]
20092009
assert list(reverse) == expected[-2::-1]
2010+
2011+
2012+
def test_reversed_iterator_types():
2013+
d = {1: 'a', 2: 'b'}
2014+
assert type(reversed(d)).__name__ == 'dict_reversekeyiterator'
2015+
assert type(reversed(d.keys())).__name__ == 'dict_reversekeyiterator'
2016+
assert type(reversed(d.values())).__name__ == 'dict_reversevalueiterator'
2017+
assert type(reversed(d.items())).__name__ == 'dict_reverseitemiterator'
2018+
assert type(reversed(d)) is not type(iter(d))
2019+
assert_raises(TypeError, type(reversed(d)))
2020+
assert_raises(TypeError, type(reversed(d.values())))
2021+
assert_raises(TypeError, type(reversed(d.items())))
2022+
assert list(reversed(d.items())) == [(2, 'b'), (1, 'a')]

‎graalpython/com.oracle.graal.python.test/src/tests/test_parser.py‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,15 @@
4242
import types
4343

4444

45+
def assert_raises(err, fn, *args, **kwargs):
46+
raised = False
47+
try:
48+
fn(*args, **kwargs)
49+
except err:
50+
raised = True
51+
assert raised
52+
53+
4554
def test_incomplete_input_error():
4655
flags = 0x4000 | 0x200 # PyCF_ALLOW_INCOMPLETE_INPUT | PyCF_DONT_IMPLY_DEDENT
4756

@@ -64,6 +73,15 @@ def test_incomplete_input_error():
6473
assert False, "SyntaxError was not raised"
6574

6675

76+
def test_compile_unrecognised_flags_message():
77+
try:
78+
compile("1", "<input>", "exec", 0x7fffffff)
79+
except ValueError as e:
80+
assert str(e) == "compile(): unrecognised flags"
81+
else:
82+
assert False, "ValueError was not raised"
83+
84+
6785
def test_lambdas_as_function_default_argument_values():
6886
globs = {}
6987
exec("""
@@ -152,6 +170,16 @@ def newhook(value):
152170
sys.displayhook = oldhook
153171

154172

173+
def test_compile_checks_mode_before_source():
174+
assert_raises(ValueError, compile, None, "<input>", "x")
175+
assert_raises(ValueError, compile, "\x00", "<input>", "x")
176+
assert_raises(ValueError, compile, b"\xff", "<input>", "x")
177+
assert_raises(ValueError, compile, b"\x00", "<input>", "x")
178+
assert_raises(ValueError, compile, None, "<input>", "x", ast.PyCF_ONLY_AST)
179+
assert_raises(ValueError, compile, None, "<input>", "func_type")
180+
assert_raises(ValueError, compile, ast.parse("1"), "<input>", "func_type")
181+
182+
155183
def test_underscore_in_numbers():
156184
assert eval('1_0') == 10
157185
assert eval('0b1_1') == 0b11

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

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,16 +1011,11 @@ Object doCompile(VirtualFrame frame, TruffleString expression, TruffleString fil
10111011
Object compile(TruffleString expression, TruffleString filename, TruffleString mode, int flags, @SuppressWarnings("unused") boolean dontInherit, int optimize, int featureVersion) {
10121012
checkFlags(flags);
10131013
checkOptimize(optimize, optimize);
1014+
InputType type = getParserInputType(mode, flags);
10141015
checkSource(expression);
10151016

10161017
TruffleString code = expression;
10171018
PythonContext context = getContext();
1018-
InputType type = getParserInputType(mode, flags);
1019-
if (type == InputType.FUNCTION_TYPE) {
1020-
if ((flags & PyCF_ONLY_AST) == 0) {
1021-
throw PRaiseNode.raiseStatic(this, ValueError, ErrorMessages.COMPILE_MODE_FUNC_TYPE_REQUIED_FLAG_ONLY_AST);
1022-
}
1023-
}
10241019
if (lstrip && !code.isEmpty()) {
10251020
int c = code.codePointAtIndexUncached(0, TS_ENCODING);
10261021
if (c == ' ' || c == '\t') {
@@ -1087,11 +1082,12 @@ Object generic(VirtualFrame frame, Object wSource, Object wFilename, TruffleStri
10871082
}
10881083
checkFlags(flags);
10891084
checkOptimize(optimize, optimize);
1085+
InputType type = getParserInputType(mode, flags);
10901086

10911087
Object saved = BoundaryCallContext.enter(frame, boundaryCallData);
10921088
try {
10931089
if (AstModuleBuiltins.isAst(context, wSource)) {
1094-
ModTy mod = AstModuleBuiltins.obj2sst(inliningTarget, context, wSource, getParserInputType(mode, flags));
1090+
ModTy mod = AstModuleBuiltins.obj2sst(inliningTarget, context, wSource, type);
10951091
if ((flags & PyCF_ONLY_AST) != 0) {
10961092
if ((flags & PyCF_OPTIMIZED_AST) != PyCF_OPTIMIZED_AST) {
10971093
return wSource;
@@ -1143,7 +1139,7 @@ private void checkOptimize(int optimize, Object kwOptimize) throws PException {
11431139
@TruffleBoundary
11441140
private void checkFlags(int flags) {
11451141
if ((flags & ~(PyCF_MASK | PyCF_MASK_OBSOLETE | PyCF_COMPILE_MASK)) != 0) {
1146-
throw PRaiseNode.raiseStatic(this, ValueError, null, NO_VALUE, ErrorMessages.UNRECOGNIZED_FLAGS, PythonUtils.EMPTY_OBJECT_ARRAY);
1142+
throw PRaiseNode.raiseStatic(this, ValueError, ErrorMessages.UNRECOGNIZED_FLAGS);
11471143
}
11481144
}
11491145

@@ -1156,6 +1152,9 @@ private InputType getParserInputType(TruffleString mode, int flags) {
11561152
} else if (mode.equalsUncached(StringLiterals.T_SINGLE, TS_ENCODING)) {
11571153
return InputType.SINGLE;
11581154
} else if (mode.equalsUncached(StringLiterals.T_FUNC_TYPE, TS_ENCODING)) {
1155+
if ((flags & PyCF_ONLY_AST) == 0) {
1156+
throw PRaiseNode.raiseStatic(this, ValueError, ErrorMessages.COMPILE_MODE_FUNC_TYPE_REQUIED_FLAG_ONLY_AST);
1157+
}
11591158
return InputType.FUNCTION_TYPE;
11601159
} else {
11611160
if ((flags & PyCF_ONLY_AST) != 0) {

‎graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/bytes/BytesCommonBuiltins.java‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,9 +203,15 @@ protected ArgumentClinicProvider getArgumentClinic() {
203203
@Specialization
204204
static Object decode(VirtualFrame frame, Object self, TruffleString encoding, TruffleString errors,
205205
@Bind Node inliningTarget,
206+
@Cached GetBytesStorage getBytesStorage,
207+
@Cached InlinedConditionProfile emptyStringProfile,
206208
@Cached CodecsModuleBuiltins.DecodeNode decodeNode,
207209
@Cached PyUnicodeCheckNode unicodeCheckNode,
208210
@Cached PRaiseNode raiseNode) {
211+
// like CPython's PyUnicode_FromEncodedObject: no codec lookup for empty input
212+
if (emptyStringProfile.profile(inliningTarget, getBytesStorage.execute(inliningTarget, self).length() == 0)) {
213+
return T_EMPTY_STRING;
214+
}
209215
Object result = decodeNode.executeWithStrings(frame, self, encoding, errors);
210216
if (!unicodeCheckNode.execute(inliningTarget, result)) {
211217
throw raiseNode.raise(inliningTarget, TypeError, DECODER_RETURNED_P_INSTEAD_OF_BYTES, encoding, result);

‎graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/complex/ComplexBuiltins.java‎

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -618,21 +618,17 @@ Object complexFromComplexObject(VirtualFrame frame, Object cls, Object one, Obje
618618
@Cached.Shared("tryComplex") @Cached TryComplexSpecialMethodNode tryComplexNode,
619619
@Cached.Shared @Cached PRaiseNode raiseNode) {
620620
PComplex oneValue = getComplexNumberFromObject(frame, one, inliningTarget, isComplexType, tryComplexNode);
621-
if (canBeDoubleNode.execute(inliningTarget, two)) {
622-
double twoValue = asDoubleNode.execute(frame, inliningTarget, two);
623-
if (oneValue == null) {
624-
if (one == PNone.NO_VALUE) {
625-
return createComplexNode.execute(inliningTarget, cls, 0, twoValue);
626-
} else if (canBeDoubleNode.execute(inliningTarget, one)) {
627-
return createComplexNode.execute(inliningTarget, cls, asDoubleNode.execute(frame, inliningTarget, one), twoValue);
628-
} else {
629-
throw raiseFirstArgError(one, inliningTarget, raiseNode);
630-
}
631-
}
632-
return createComplexNode.execute(inliningTarget, cls, oneValue.getReal(), oneValue.getImag() + twoValue);
633-
} else {
621+
if (oneValue == null && one != PNone.NO_VALUE && !canBeDoubleNode.execute(inliningTarget, one)) {
622+
throw raiseFirstArgError(one, inliningTarget, raiseNode);
623+
}
624+
if (!canBeDoubleNode.execute(inliningTarget, two)) {
634625
throw raiseSecondArgError(two, inliningTarget, raiseNode);
635626
}
627+
if (oneValue == null) {
628+
double oneDouble = one == PNone.NO_VALUE ? 0 : asDoubleNode.execute(frame, inliningTarget, one);
629+
return createComplexNode.execute(inliningTarget, cls, oneDouble, asDoubleNode.execute(frame, inliningTarget, two));
630+
}
631+
return createComplexNode.execute(inliningTarget, cls, oneValue.getReal(), oneValue.getImag() + asDoubleNode.execute(frame, inliningTarget, two));
636632
}
637633

638634
@Specialization

‎graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictBuiltins.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ static Object run(Object self,
436436
@Cached HashingStorageGetReverseIterator getReverseIterator,
437437
@Bind PythonLanguage language) {
438438
var storage = getStorageNode.execute(inliningTarget, self);
439-
return PFactory.createDictKeyIterator(language, getReverseIterator.execute(inliningTarget, storage), storage, lenNode.execute(inliningTarget, storage));
439+
return PFactory.createDictReverseKeyIterator(language, getReverseIterator.execute(inliningTarget, storage), storage, lenNode.execute(inliningTarget, storage));
440440
}
441441
}
442442

‎graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictValuesBuiltins.java‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2025, Oracle and/or its affiliates.
2+
* Copyright (c) 2017, 2026, Oracle and/or its affiliates.
33
* Copyright (c) 2013, Regents of the University of California
44
*
55
* All rights reserved.
@@ -109,7 +109,7 @@ static Object doPDictValuesView(PDictValuesView self,
109109
@Cached HashingStorageGetReverseIterator getReverseIter,
110110
@Bind PythonLanguage language) {
111111
HashingStorage storage = self.getWrappedStorage();
112-
return PFactory.createDictValueIterator(language, getReverseIter.execute(inliningTarget, storage), storage, lenNode.execute(inliningTarget, storage));
112+
return PFactory.createDictReverseValueIterator(language, getReverseIter.execute(inliningTarget, storage), storage, lenNode.execute(inliningTarget, storage));
113113
}
114114
}
115115
}

‎graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictViewBuiltins.java‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ static Object getReversedKeysViewIter(PDictKeysView self,
193193
@Shared @Cached HashingStorageGetReverseIterator getReverseIterator,
194194
@Bind PythonLanguage language) {
195195
HashingStorage storage = self.getWrappedStorage();
196-
return PFactory.createDictKeyIterator(language, getReverseIterator.execute(inliningTarget, storage), storage, lenNode.execute(inliningTarget, storage));
196+
return PFactory.createDictReverseKeyIterator(language, getReverseIterator.execute(inliningTarget, storage), storage, lenNode.execute(inliningTarget, storage));
197197
}
198198

199199
@Specialization
@@ -203,7 +203,7 @@ static Object getReversedItemsViewIter(PDictItemsView self,
203203
@Shared @Cached HashingStorageGetReverseIterator getReverseIterator,
204204
@Bind PythonLanguage language) {
205205
HashingStorage storage = self.getWrappedStorage();
206-
return PFactory.createDictItemIterator(language, getReverseIterator.execute(inliningTarget, storage), storage, lenNode.execute(inliningTarget, storage));
206+
return PFactory.createDictReverseItemIterator(language, getReverseIterator.execute(inliningTarget, storage), storage, lenNode.execute(inliningTarget, storage));
207207
}
208208
}
209209

0 commit comments

Comments
 (0)