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
25 changes: 25 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 @@ -205,6 +205,31 @@ def test_init():
d.__init__({'d':4})
assert d == {'a':1, 'b':2, 'c':3, 'd':4}


def test_dict_update_does_not_call_overridden_setitem():
class DictSubclass(dict):
def __setitem__(self, key, value):
raise AssertionError("dict update called overridden __setitem__")

d = DictSubclass()
dict.__init__(d, [('key', 'value')])
assert d == {'key': 'value'}

class Mapping:
def keys(self):
return ['other']

def __getitem__(self, key):
assert key == 'other'
return 'value'

dict.__init__(d, Mapping())
assert d == {'key': 'value', 'other': 'value'}

dict.update(d, [('third', 'value')])
assert d == {'key': 'value', 'other': 'value', 'third': 'value'}


def test_init1():
try:
dict([("a", 1), ("b", 2)], [("c", 3), ("d", 4)])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@
import unittest


def expected_failure_on_old_windows(test):
def skip_on_old_windows(test):
# Despite the documented Windows 10 1607 cutoff, SetCurrentDirectoryW still rejects long paths
# on Windows Server 2016 (build 14393), even when RtlAreLongPathsEnabled() returns true.
if os.name == 'nt' and int(platform.version().split('.')[2]) <= 14393:
return unittest.expectedFailure(test)
return unittest.skip("old windows")(test)
return test


Expand Down Expand Up @@ -110,7 +110,7 @@ def test_long_paths(self):
if root is not None:
shutil.rmtree(root)

@expected_failure_on_old_windows
@skip_on_old_windows
def test_long_path_chdir(self):
root = tempfile.mkdtemp()
old_cwd = os.getcwd()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.KeyError;
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.RuntimeError;
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.TypeError;
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.ValueError;
import static com.oracle.graal.python.nodes.SpecialAttributeNames.J___DICT__;
import static com.oracle.graal.python.nodes.SpecialMethodNames.J_ITEMS;
import static com.oracle.graal.python.nodes.SpecialMethodNames.J_KEYS;
Expand Down Expand Up @@ -75,16 +76,20 @@
import com.oracle.graal.python.builtins.objects.common.HashingStorage;
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes;
import com.oracle.graal.python.builtins.objects.common.ObjectHashMap;
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
import com.oracle.graal.python.builtins.objects.dict.DictReprBuiltin.ReprOrderedDictItemsNode;
import com.oracle.graal.python.builtins.objects.dict.PDict;
import com.oracle.graal.python.builtins.objects.function.PKeyword;
import com.oracle.graal.python.builtins.objects.list.PList;
import com.oracle.graal.python.builtins.objects.ordereddict.POrderedDict.ODictNode;
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
import com.oracle.graal.python.builtins.objects.type.TpSlots;
import com.oracle.graal.python.builtins.objects.type.TypeNodes;
import com.oracle.graal.python.builtins.objects.type.slots.TpSlotBinaryOp.BinaryOpBuiltinNode;
import com.oracle.graal.python.builtins.objects.type.slots.TpSlotMpAssSubscript.MpAssSubscriptBuiltinNode;
import com.oracle.graal.python.builtins.objects.type.slots.TpSlotRichCompare.RichCmpBuiltinNode;
import com.oracle.graal.python.lib.PyDictMerge;
import com.oracle.graal.python.lib.IteratorExhausted;
import com.oracle.graal.python.lib.PyIterNextNode;
import com.oracle.graal.python.lib.PyObjectCallMethodObjArgs;
import com.oracle.graal.python.lib.PyObjectDelItem;
import com.oracle.graal.python.lib.PyObjectGetItem;
Expand All @@ -98,6 +103,7 @@
import com.oracle.graal.python.lib.RichCmpOp;
import com.oracle.graal.python.nodes.ErrorMessages;
import com.oracle.graal.python.nodes.PGuards;
import com.oracle.graal.python.nodes.PNodeWithContext;
import com.oracle.graal.python.nodes.PRaiseNode;
import com.oracle.graal.python.nodes.call.CallNode;
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
Expand All @@ -113,6 +119,7 @@
import com.oracle.graal.python.nodes.object.SetDictNode;
import com.oracle.graal.python.runtime.PythonContext;
import com.oracle.graal.python.runtime.object.PFactory;
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Bind;
import com.oracle.truffle.api.dsl.Cached;
Expand Down Expand Up @@ -205,6 +212,114 @@ static void delitem(VirtualFrame frame, POrderedDict self, Object key, @Suppress
}
}

@GenerateInline
@GenerateCached(false)
abstract static class UpdateMappingNode extends PNodeWithContext {
abstract void execute(VirtualFrame frame, Node inliningTarget, Object target, Object mapping, Object keysMethod);

@Specialization
static void doMerge(VirtualFrame frame, Node inliningTarget, Object target, Object mapping, Object keysMethod,
@Cached CallNode callKeys,
@Cached PyObjectGetIter getIter,
@Cached PyIterNextNode next,
@Cached PyObjectGetItem getItem,
@Cached PyObjectSetItem setItem) {
Object keys = callKeys.execute(frame, keysMethod);
Object iterator = getIter.execute(frame, inliningTarget, keys);
while (true) {
Object key;
try {
key = next.execute(frame, inliningTarget, iterator);
} catch (IteratorExhausted e) {
break;
}
Object value = getItem.execute(frame, inliningTarget, mapping, key);
setItem.execute(frame, inliningTarget, target, key, value);
}
}
}

@GenerateInline
@GenerateCached(false)
abstract static class UpdateFromSequenceNode extends PNodeWithContext {
abstract void execute(VirtualFrame frame, Node inliningTarget, Object target, Object iterable);

@Specialization
static void doIterable(VirtualFrame frame, Node inliningTarget, Object target, Object iterable,
@Cached PyObjectGetIter getIter,
@Cached PyIterNextNode next,
@Cached SetItemFromSequenceNode setItemFromSequence) {
Object iterator = getIter.execute(frame, inliningTarget, iterable);
while (true) {
Object element;
try {
element = next.execute(frame, inliningTarget, iterator);
} catch (IteratorExhausted e) {
break;
}
setItemFromSequence.execute(frame, inliningTarget, target, element);
}
}
}

@GenerateInline
@GenerateCached(false)
abstract static class SetItemFromSequenceNode extends PNodeWithContext {
abstract void execute(VirtualFrame frame, Node inliningTarget, Object target, Object element);

@Specialization
static void doGeneric(VirtualFrame frame, Node inliningTarget, Object target, Object element,
@Cached SequenceStorageNodes.GetItemScalarNode getItem,
@Cached PyObjectGetIter getIter,
@Cached PyIterNextNode next,
@Cached PyObjectSetItem setItem,
@Cached InlinedBranchProfile tupleProfile,
@Cached InlinedBranchProfile listProfile,
@Cached PRaiseNode raiseNode) {
Object key, value;
SequenceStorage storage = null;
if (element instanceof PTuple tuple && PGuards.isBuiltinTuple(tuple)) {
tupleProfile.enter(inliningTarget);
storage = tuple.getSequenceStorage();
} else if (element instanceof PList list && PGuards.isBuiltinList(list)) {
listProfile.enter(inliningTarget);
storage = list.getSequenceStorage();
}
if (storage != null) {
int length = storage.length();
if (length == 0) {
throw raiseNode.raise(inliningTarget, ValueError, ErrorMessages.NEED_MORE_THAN_D_VALUES_TO_UNPACK, 0);
} else if (length == 1) {
throw raiseNode.raise(inliningTarget, ValueError, ErrorMessages.NEED_MORE_THAN_D_VALUES_TO_UNPACK, 1);
} else if (length > 2) {
throw raiseNode.raise(inliningTarget, ValueError, ErrorMessages.TOO_MANY_VALUES_TO_UNPACK, 2);
}
key = getItem.execute(inliningTarget, storage, 0);
value = getItem.execute(inliningTarget, storage, 1);
} else {
// Acts as a profile
Object iterator = getIter.execute(frame, inliningTarget, element);
try {
key = next.execute(frame, inliningTarget, iterator);
} catch (IteratorExhausted e) {
throw raiseNode.raise(inliningTarget, ValueError, ErrorMessages.NEED_MORE_THAN_D_VALUES_TO_UNPACK, 0);
}
try {
value = next.execute(frame, inliningTarget, iterator);
} catch (IteratorExhausted e) {
throw raiseNode.raise(inliningTarget, ValueError, ErrorMessages.NEED_MORE_THAN_D_VALUES_TO_UNPACK, 1);
}
try {
next.execute(frame, inliningTarget, iterator);
throw raiseNode.raise(inliningTarget, ValueError, ErrorMessages.TOO_MANY_VALUES_TO_UNPACK, 2);
} catch (IteratorExhausted e) {
// Expected
}
}
setItem.execute(frame, inliningTarget, target, key, value);
}
}

@GenerateInline
@GenerateCached(false)
abstract static class UpdateFromArgsNode extends Node {
Expand All @@ -217,8 +332,8 @@ final void execute(VirtualFrame frame, Node inliningTarget, Object self, Object
@Specialization
static void update(VirtualFrame frame, Node inliningTarget, Object self, Object mapping, PKeyword[] kwargs,
@Cached PyObjectLookupAttr lookupKeys,
@Cached PyDictMerge.MappingNode updateMapping,
@Cached PyDictMerge.FromSeq2Node updateFromSequence,
@Cached UpdateMappingNode updateMapping,
@Cached UpdateFromSequenceNode updateFromSequence,
@Cached PyObjectSetItem setItem,
@Cached HashingStorageNodes.HashingStorageGetIterator getIterator,
@Cached HashingStorageNodes.HashingStorageIteratorNext iteratorNext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import static com.oracle.graal.python.runtime.exception.PythonErrorType.TypeError;
import static com.oracle.graal.python.runtime.exception.PythonErrorType.ValueError;

import com.oracle.graal.python.builtins.objects.common.HashingCollectionNodes;
import com.oracle.graal.python.builtins.objects.common.HashingStorage;
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageGetIterator;
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageIterator;
Expand Down Expand Up @@ -146,7 +147,7 @@ static void doMerge(VirtualFrame frame, Node inliningTarget, Object target, Obje
@Cached ListNodes.FastConstructListNode materializeKeys,
@Cached SequenceStorageNodes.GetItemScalarNode getKey,
@Cached PyObjectGetItem getItem,
@Cached PyObjectSetItem setItem,
@Cached HashingCollectionNodes.SetItemNode setItem,
@Cached InlinedLoopConditionProfile loopProfile) {
PList keys = materializeKeys.execute(frame, inliningTarget, callKeys.execute(frame, keysMethod));
SequenceStorage keysStorage = keys.getSequenceStorage();
Expand Down Expand Up @@ -196,7 +197,7 @@ abstract static class SetItemFromSequenceNode extends PNodeWithContext {
static void doGeneric(VirtualFrame frame, Node inliningTarget, Object target, Object element, int index,
@Cached ListNodes.ConstructListNode createList,
@Cached SequenceStorageNodes.GetItemScalarNode getItem,
@Cached PyObjectSetItem setItem,
@Cached HashingCollectionNodes.SetItemNode setItem,
@Cached IsBuiltinObjectProfile isTypeErrorProfile,
@Cached InlinedBranchProfile tupleProfile,
@Cached InlinedBranchProfile listProfile,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,7 @@ public abstract class ErrorMessages {
public static final TruffleString NEGATIVE_COUNT = tsLiteral("negative count");
public static final TruffleString NEGATIVE_SHIFT_COUNT = tsLiteral("negative shift count");
public static final TruffleString NEGATIVE_SIZE_PASSED = tsLiteral("negative size passed");
public static final TruffleString NEED_MORE_THAN_D_VALUES_TO_UNPACK = tsLiteral("need more than %d values to unpack");
public static final TruffleString NEW_TAKES_ONE_ARG = tsLiteral("object.__new__() takes exactly one argument (the type to instantiate)");
public static final TruffleString NEW_TAKES_NO_ARGS = tsLiteral("%N() takes no arguments");
public static final TruffleString NO_ACTIVE_EX_TO_RERAISE = tsLiteral("No active exception to reraise");
Expand Down Expand Up @@ -813,6 +814,7 @@ public abstract class ErrorMessages {
public static final TruffleString UNSUPPORTED_SIZE_WAS = tsLiteral("unsupported %s size; was: %d");
public static final TruffleString UNSUPPORTED_TARGET_SIZE = tsLiteral("Unsupported target size: %d");
public static final TruffleString UNSUPPORTED_USE_OF_SYS_EXECUTABLE = tsLiteral("internal error: unsupported use of sys.executable");
public static final TruffleString UPDATE_TAKES_AT_MOST_ONE_POSITIONAL_ARGUMENT_D_GIVEN = tsLiteral("update() takes at most 1 positional argument (%d given)");
public static final TruffleString UPDATING_FINALIZED_DIGEST_IS_NOT_SUPPORTED = tsLiteral("internal error: updating a finalized digest is not supported");
public static final TruffleString UTIME_CANNOT_USE_DIR_FD_AND_FOLLOW_SYMLINKS = tsLiteral("utime: cannot use dir_fd and follow_symlinks together on this platform");
public static final TruffleString VALUE_TOO_LARGE_TO_FIT_INTO_INDEX = tsLiteral("value too large to fit into index-sized integer");
Expand Down
7 changes: 7 additions & 0 deletions mx.graalpython/downstream_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,11 +147,18 @@ def downstream_test_pydantic_core(graalpy, testdir):
'--no-install-package', 'pytest-codspeed', '--no-install-package', 'cffi', '--inexact',
# GraalPy change: greenlet crashes on import
'--no-install-package', 'greenlet',
# The latest rpds-py release does not yet include the PyO3 fix needed by GraalPy
'--no-install-package', 'rpds-py',
],
cwd=repo,
env=env,
)
del env['UV_PYTHON']
run(
['uv', 'pip', 'install', 'rpds-py @ git+https://github.com/crate-py/rpds.git@main', '--no-deps', '--force-reinstall'],
cwd=repo,
env=env,
)
run(
['uv', 'pip', 'install', './pydantic-core', '--no-deps', '--force-reinstall'],
cwd=repo,
Expand Down
Loading