diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_bytes.py b/graalpython/com.oracle.graal.python.test/src/tests/test_bytes.py
index 7a74fd9518..e4ac58ade1 100644
--- a/graalpython/com.oracle.graal.python.test/src/tests/test_bytes.py
+++ b/graalpython/com.oracle.graal.python.test/src/tests/test_bytes.py
@@ -89,6 +89,16 @@ def __bytes__(self):
assert_raises(TypeError, bytes, errors="strict")
+def test_decode_empty_skips_codec_lookup():
+ assert str(b'', 'x') == ''
+ assert str(bytearray(), 'x', 'y') == ''
+ assert str(memoryview(b''), 'x') == ''
+ assert b''.decode('x') == ''
+ assert bytearray().decode('x') == ''
+ assert_raises(LookupError, str, b'a', 'x')
+ assert_raises(TypeError, str, 1, 'x')
+
+
def test_from_ssize():
assert bytes(0) == b''
assert bytes(1) == b'\x00'
diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_complex.py b/graalpython/com.oracle.graal.python.test/src/tests/test_complex.py
index e1b6ea9ec9..096e2256ee 100644
--- a/graalpython/com.oracle.graal.python.test/src/tests/test_complex.py
+++ b/graalpython/com.oracle.graal.python.test/src/tests/test_complex.py
@@ -304,6 +304,20 @@ class SubComplex(complex):
assert result == 2 + 3j
assert type(result) is complex
+
+def test_create_checks_arguments_before_converting():
+ class RaisingReal:
+ def __float__(self):
+ raise KeyError
+
+ class RaisingImag:
+ def __float__(self):
+ raise RuntimeError
+
+ assert_raises(TypeError, complex, {}, RaisingImag())
+ assert_raises(TypeError, complex, RaisingReal(), {})
+ assert_raises(KeyError, complex, RaisingReal(), RaisingImag())
+
class ComplexTest(unittest.TestCase):
def assertAlmostEqual(self, a, b):
diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_dict.py b/graalpython/com.oracle.graal.python.test/src/tests/test_dict.py
index 63ce7afee6..96b1a538f3 100644
--- a/graalpython/com.oracle.graal.python.test/src/tests/test_dict.py
+++ b/graalpython/com.oracle.graal.python.test/src/tests/test_dict.py
@@ -2007,3 +2007,16 @@ def test_bulk_value_update_preserves_iterators():
d.update({k: -v for k, v in d.items()})
assert list(it) == expected[1:]
assert list(reverse) == expected[-2::-1]
+
+
+def test_reversed_iterator_types():
+ d = {1: 'a', 2: 'b'}
+ assert type(reversed(d)).__name__ == 'dict_reversekeyiterator'
+ assert type(reversed(d.keys())).__name__ == 'dict_reversekeyiterator'
+ assert type(reversed(d.values())).__name__ == 'dict_reversevalueiterator'
+ assert type(reversed(d.items())).__name__ == 'dict_reverseitemiterator'
+ assert type(reversed(d)) is not type(iter(d))
+ assert_raises(TypeError, type(reversed(d)))
+ assert_raises(TypeError, type(reversed(d.values())))
+ assert_raises(TypeError, type(reversed(d.items())))
+ assert list(reversed(d.items())) == [(2, 'b'), (1, 'a')]
diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_parser.py b/graalpython/com.oracle.graal.python.test/src/tests/test_parser.py
index 5941b6668d..96d1f70b19 100644
--- a/graalpython/com.oracle.graal.python.test/src/tests/test_parser.py
+++ b/graalpython/com.oracle.graal.python.test/src/tests/test_parser.py
@@ -42,6 +42,15 @@
import types
+def assert_raises(err, fn, *args, **kwargs):
+ raised = False
+ try:
+ fn(*args, **kwargs)
+ except err:
+ raised = True
+ assert raised
+
+
def test_incomplete_input_error():
flags = 0x4000 | 0x200 # PyCF_ALLOW_INCOMPLETE_INPUT | PyCF_DONT_IMPLY_DEDENT
@@ -64,6 +73,15 @@ def test_incomplete_input_error():
assert False, "SyntaxError was not raised"
+def test_compile_unrecognised_flags_message():
+ try:
+ compile("1", "", "exec", 0x7fffffff)
+ except ValueError as e:
+ assert str(e) == "compile(): unrecognised flags"
+ else:
+ assert False, "ValueError was not raised"
+
+
def test_lambdas_as_function_default_argument_values():
globs = {}
exec("""
@@ -152,6 +170,16 @@ def newhook(value):
sys.displayhook = oldhook
+def test_compile_checks_mode_before_source():
+ assert_raises(ValueError, compile, None, "", "x")
+ assert_raises(ValueError, compile, "\x00", "", "x")
+ assert_raises(ValueError, compile, b"\xff", "", "x")
+ assert_raises(ValueError, compile, b"\x00", "", "x")
+ assert_raises(ValueError, compile, None, "", "x", ast.PyCF_ONLY_AST)
+ assert_raises(ValueError, compile, None, "", "func_type")
+ assert_raises(ValueError, compile, ast.parse("1"), "", "func_type")
+
+
def test_underscore_in_numbers():
assert eval('1_0') == 10
assert eval('0b1_1') == 0b11
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java
index 2eaeb899fc..f999eca52e 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java
@@ -1011,16 +1011,11 @@ Object doCompile(VirtualFrame frame, TruffleString expression, TruffleString fil
Object compile(TruffleString expression, TruffleString filename, TruffleString mode, int flags, @SuppressWarnings("unused") boolean dontInherit, int optimize, int featureVersion) {
checkFlags(flags);
checkOptimize(optimize, optimize);
+ InputType type = getParserInputType(mode, flags);
checkSource(expression);
TruffleString code = expression;
PythonContext context = getContext();
- InputType type = getParserInputType(mode, flags);
- if (type == InputType.FUNCTION_TYPE) {
- if ((flags & PyCF_ONLY_AST) == 0) {
- throw PRaiseNode.raiseStatic(this, ValueError, ErrorMessages.COMPILE_MODE_FUNC_TYPE_REQUIED_FLAG_ONLY_AST);
- }
- }
if (lstrip && !code.isEmpty()) {
int c = code.codePointAtIndexUncached(0, TS_ENCODING);
if (c == ' ' || c == '\t') {
@@ -1087,11 +1082,12 @@ Object generic(VirtualFrame frame, Object wSource, Object wFilename, TruffleStri
}
checkFlags(flags);
checkOptimize(optimize, optimize);
+ InputType type = getParserInputType(mode, flags);
Object saved = BoundaryCallContext.enter(frame, boundaryCallData);
try {
if (AstModuleBuiltins.isAst(context, wSource)) {
- ModTy mod = AstModuleBuiltins.obj2sst(inliningTarget, context, wSource, getParserInputType(mode, flags));
+ ModTy mod = AstModuleBuiltins.obj2sst(inliningTarget, context, wSource, type);
if ((flags & PyCF_ONLY_AST) != 0) {
if ((flags & PyCF_OPTIMIZED_AST) != PyCF_OPTIMIZED_AST) {
return wSource;
@@ -1143,7 +1139,7 @@ private void checkOptimize(int optimize, Object kwOptimize) throws PException {
@TruffleBoundary
private void checkFlags(int flags) {
if ((flags & ~(PyCF_MASK | PyCF_MASK_OBSOLETE | PyCF_COMPILE_MASK)) != 0) {
- throw PRaiseNode.raiseStatic(this, ValueError, null, NO_VALUE, ErrorMessages.UNRECOGNIZED_FLAGS, PythonUtils.EMPTY_OBJECT_ARRAY);
+ throw PRaiseNode.raiseStatic(this, ValueError, ErrorMessages.UNRECOGNIZED_FLAGS);
}
}
@@ -1156,6 +1152,9 @@ private InputType getParserInputType(TruffleString mode, int flags) {
} else if (mode.equalsUncached(StringLiterals.T_SINGLE, TS_ENCODING)) {
return InputType.SINGLE;
} else if (mode.equalsUncached(StringLiterals.T_FUNC_TYPE, TS_ENCODING)) {
+ if ((flags & PyCF_ONLY_AST) == 0) {
+ throw PRaiseNode.raiseStatic(this, ValueError, ErrorMessages.COMPILE_MODE_FUNC_TYPE_REQUIED_FLAG_ONLY_AST);
+ }
return InputType.FUNCTION_TYPE;
} else {
if ((flags & PyCF_ONLY_AST) != 0) {
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/bytes/BytesCommonBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/bytes/BytesCommonBuiltins.java
index 5920ee72a9..a506ecbccb 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/bytes/BytesCommonBuiltins.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/bytes/BytesCommonBuiltins.java
@@ -203,9 +203,15 @@ protected ArgumentClinicProvider getArgumentClinic() {
@Specialization
static Object decode(VirtualFrame frame, Object self, TruffleString encoding, TruffleString errors,
@Bind Node inliningTarget,
+ @Cached GetBytesStorage getBytesStorage,
+ @Cached InlinedConditionProfile emptyStringProfile,
@Cached CodecsModuleBuiltins.DecodeNode decodeNode,
@Cached PyUnicodeCheckNode unicodeCheckNode,
@Cached PRaiseNode raiseNode) {
+ // like CPython's PyUnicode_FromEncodedObject: no codec lookup for empty input
+ if (emptyStringProfile.profile(inliningTarget, getBytesStorage.execute(inliningTarget, self).length() == 0)) {
+ return T_EMPTY_STRING;
+ }
Object result = decodeNode.executeWithStrings(frame, self, encoding, errors);
if (!unicodeCheckNode.execute(inliningTarget, result)) {
throw raiseNode.raise(inliningTarget, TypeError, DECODER_RETURNED_P_INSTEAD_OF_BYTES, encoding, result);
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/complex/ComplexBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/complex/ComplexBuiltins.java
index 6dcc4631a6..8a54ebd963 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/complex/ComplexBuiltins.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/complex/ComplexBuiltins.java
@@ -618,21 +618,17 @@ Object complexFromComplexObject(VirtualFrame frame, Object cls, Object one, Obje
@Cached.Shared("tryComplex") @Cached TryComplexSpecialMethodNode tryComplexNode,
@Cached.Shared @Cached PRaiseNode raiseNode) {
PComplex oneValue = getComplexNumberFromObject(frame, one, inliningTarget, isComplexType, tryComplexNode);
- if (canBeDoubleNode.execute(inliningTarget, two)) {
- double twoValue = asDoubleNode.execute(frame, inliningTarget, two);
- if (oneValue == null) {
- if (one == PNone.NO_VALUE) {
- return createComplexNode.execute(inliningTarget, cls, 0, twoValue);
- } else if (canBeDoubleNode.execute(inliningTarget, one)) {
- return createComplexNode.execute(inliningTarget, cls, asDoubleNode.execute(frame, inliningTarget, one), twoValue);
- } else {
- throw raiseFirstArgError(one, inliningTarget, raiseNode);
- }
- }
- return createComplexNode.execute(inliningTarget, cls, oneValue.getReal(), oneValue.getImag() + twoValue);
- } else {
+ if (oneValue == null && one != PNone.NO_VALUE && !canBeDoubleNode.execute(inliningTarget, one)) {
+ throw raiseFirstArgError(one, inliningTarget, raiseNode);
+ }
+ if (!canBeDoubleNode.execute(inliningTarget, two)) {
throw raiseSecondArgError(two, inliningTarget, raiseNode);
}
+ if (oneValue == null) {
+ double oneDouble = one == PNone.NO_VALUE ? 0 : asDoubleNode.execute(frame, inliningTarget, one);
+ return createComplexNode.execute(inliningTarget, cls, oneDouble, asDoubleNode.execute(frame, inliningTarget, two));
+ }
+ return createComplexNode.execute(inliningTarget, cls, oneValue.getReal(), oneValue.getImag() + asDoubleNode.execute(frame, inliningTarget, two));
}
@Specialization
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictBuiltins.java
index af5b42dcb5..2ecf206665 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictBuiltins.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictBuiltins.java
@@ -436,7 +436,7 @@ static Object run(Object self,
@Cached HashingStorageGetReverseIterator getReverseIterator,
@Bind PythonLanguage language) {
var storage = getStorageNode.execute(inliningTarget, self);
- return PFactory.createDictKeyIterator(language, getReverseIterator.execute(inliningTarget, storage), storage, lenNode.execute(inliningTarget, storage));
+ return PFactory.createDictReverseKeyIterator(language, getReverseIterator.execute(inliningTarget, storage), storage, lenNode.execute(inliningTarget, storage));
}
}
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictValuesBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictValuesBuiltins.java
index 4e27468861..c4c8c9dc40 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictValuesBuiltins.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictValuesBuiltins.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2025, Oracle and/or its affiliates.
+ * Copyright (c) 2017, 2026, Oracle and/or its affiliates.
* Copyright (c) 2013, Regents of the University of California
*
* All rights reserved.
@@ -109,7 +109,7 @@ static Object doPDictValuesView(PDictValuesView self,
@Cached HashingStorageGetReverseIterator getReverseIter,
@Bind PythonLanguage language) {
HashingStorage storage = self.getWrappedStorage();
- return PFactory.createDictValueIterator(language, getReverseIter.execute(inliningTarget, storage), storage, lenNode.execute(inliningTarget, storage));
+ return PFactory.createDictReverseValueIterator(language, getReverseIter.execute(inliningTarget, storage), storage, lenNode.execute(inliningTarget, storage));
}
}
}
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictViewBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictViewBuiltins.java
index a203480f5d..2f4ee1db81 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictViewBuiltins.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictViewBuiltins.java
@@ -193,7 +193,7 @@ static Object getReversedKeysViewIter(PDictKeysView self,
@Shared @Cached HashingStorageGetReverseIterator getReverseIterator,
@Bind PythonLanguage language) {
HashingStorage storage = self.getWrappedStorage();
- return PFactory.createDictKeyIterator(language, getReverseIterator.execute(inliningTarget, storage), storage, lenNode.execute(inliningTarget, storage));
+ return PFactory.createDictReverseKeyIterator(language, getReverseIterator.execute(inliningTarget, storage), storage, lenNode.execute(inliningTarget, storage));
}
@Specialization
@@ -203,7 +203,7 @@ static Object getReversedItemsViewIter(PDictItemsView self,
@Shared @Cached HashingStorageGetReverseIterator getReverseIterator,
@Bind PythonLanguage language) {
HashingStorage storage = self.getWrappedStorage();
- return PFactory.createDictItemIterator(language, getReverseIterator.execute(inliningTarget, storage), storage, lenNode.execute(inliningTarget, storage));
+ return PFactory.createDictReverseItemIterator(language, getReverseIterator.execute(inliningTarget, storage), storage, lenNode.execute(inliningTarget, storage));
}
}
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java
index 06494a5bcf..7f6f1a653a 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java
@@ -1085,14 +1085,29 @@ public static PDictItemIterator createDictItemIterator(PythonLanguage language,
initialSize);
}
+ public static PDictItemIterator createDictReverseItemIterator(PythonLanguage language, HashingStorageNodes.HashingStorageIterator iterator, HashingStorage hashingStorage, int initialSize) {
+ return new PDictItemIterator(PythonBuiltinClassType.PDictReverseItemIterator, PythonBuiltinClassType.PDictReverseItemIterator.getInstanceShape(language), iterator, hashingStorage,
+ initialSize);
+ }
+
public static PDictKeyIterator createDictKeyIterator(PythonLanguage language, HashingStorageNodes.HashingStorageIterator iterator, HashingStorage hashingStorage, int initialSize) {
return new PDictKeyIterator(PythonBuiltinClassType.PDictKeyIterator, PythonBuiltinClassType.PDictKeyIterator.getInstanceShape(language), iterator, hashingStorage, initialSize);
}
+ public static PDictKeyIterator createDictReverseKeyIterator(PythonLanguage language, HashingStorageNodes.HashingStorageIterator iterator, HashingStorage hashingStorage, int initialSize) {
+ return new PDictKeyIterator(PythonBuiltinClassType.PDictReverseKeyIterator, PythonBuiltinClassType.PDictReverseKeyIterator.getInstanceShape(language), iterator, hashingStorage,
+ initialSize);
+ }
+
public static PDictValueIterator createDictValueIterator(PythonLanguage language, HashingStorageNodes.HashingStorageIterator iterator, HashingStorage hashingStorage, int initialSize) {
return new PDictValueIterator(PythonBuiltinClassType.PDictValueIterator, PythonBuiltinClassType.PDictValueIterator.getInstanceShape(language), iterator, hashingStorage, initialSize);
}
+ public static PDictValueIterator createDictReverseValueIterator(PythonLanguage language, HashingStorageNodes.HashingStorageIterator iterator, HashingStorage hashingStorage, int initialSize) {
+ return new PDictValueIterator(PythonBuiltinClassType.PDictReverseValueIterator, PythonBuiltinClassType.PDictReverseValueIterator.getInstanceShape(language), iterator, hashingStorage,
+ initialSize);
+ }
+
public static Object createSentinelIterator(PythonLanguage language, Object callable, Object sentinel) {
return new PSentinelIterator(PythonBuiltinClassType.PSentinelIterator, PythonBuiltinClassType.PSentinelIterator.getInstanceShape(language), callable, sentinel);
}