Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions graalpython/com.oracle.graal.python.test/src/tests/test_bytes.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
14 changes: 14 additions & 0 deletions graalpython/com.oracle.graal.python.test/src/tests/test_complex.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
13 changes: 13 additions & 0 deletions graalpython/com.oracle.graal.python.test/src/tests/test_dict.py
Original file line number Diff line number Diff line change
Expand Up @@ -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')]
28 changes: 28 additions & 0 deletions graalpython/com.oracle.graal.python.test/src/tests/test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

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


def test_compile_unrecognised_flags_message():
try:
compile("1", "<input>", "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("""
Expand Down Expand Up @@ -152,6 +170,16 @@ def newhook(value):
sys.displayhook = oldhook


def test_compile_checks_mode_before_source():
assert_raises(ValueError, compile, None, "<input>", "x")
assert_raises(ValueError, compile, "\x00", "<input>", "x")
assert_raises(ValueError, compile, b"\xff", "<input>", "x")
assert_raises(ValueError, compile, b"\x00", "<input>", "x")
assert_raises(ValueError, compile, None, "<input>", "x", ast.PyCF_ONLY_AST)
assert_raises(ValueError, compile, None, "<input>", "func_type")
assert_raises(ValueError, compile, ast.parse("1"), "<input>", "func_type")


def test_underscore_in_numbers():
assert eval('1_0') == 10
assert eval('0b1_1') == 0b11
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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') {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
}

Expand All @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
Loading