Skip to content
Open
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
65 changes: 65 additions & 0 deletions graalpython/com.oracle.graal.python.test/src/tests/test_weakref.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,16 @@
# SOFTWARE.
import weakref


def assert_raises(err, fn, *args, **kwargs):
raised = False
try:
fn(*args, **kwargs)
except err:
raised = True
assert raised


MAX_WAIT_COUNT = 500

import sys
Expand Down Expand Up @@ -322,3 +332,58 @@ def __call__(self):
proxy = weakref.proxy(a)
assert callable(proxy) is True
assert proxy() == 42


def test_weakref_with_callback_object_type_support():
def callback(ref):
pass

assert_raises(TypeError, weakref.ref, {}, callback)
assert_raises(TypeError, weakref.proxy, {}, callback)
assert_raises(TypeError, weakref.ref, [1, 2], callback)
assert_raises(TypeError, weakref.proxy, [1, 2], callback)
assert_raises(TypeError, weakref.ref, 42, callback)
assert_raises(TypeError, weakref.proxy, 42, callback)
assert_raises(TypeError, weakref.ref, None, callback)
assert_raises(TypeError, weakref.proxy, None, callback)


def test_weakref_builtin_types_with_weaklist():
import _queue, _struct, array, collections, contextvars, mmap, typing

def callback(ref):
pass

d = collections.deque()
assert weakref.ref(d)() is d
assert weakref.ref(d, callback)() is d
a = array.array('b')
assert weakref.ref(a)() is a
assert weakref.ref(a, callback)() is a
with mmap.mmap(-1, 1) as m:
assert weakref.ref(m)() is m
assert weakref.ref(m, callback)() is m
c = contextvars.copy_context()
assert weakref.ref(c)() is c
assert weakref.ref(c, callback)() is c
q = _queue.SimpleQueue()
assert weakref.ref(q)() is q
assert weakref.ref(q, callback)() is q
s = _struct.Struct('b')
assert weakref.ref(s)() is s
assert weakref.ref(s, callback)() is s
t = typing.TypeVar('T')
assert weakref.ref(t)() is t
assert weakref.ref(t, callback)() is t
ts = typing.TypeVarTuple('Ts')
assert weakref.ref(ts)() is ts
assert weakref.ref(ts, callback)() is ts
p = typing.ParamSpec('P')
assert weakref.ref(p)() is p
assert weakref.ref(p, callback)() is p
pa = p.args
assert weakref.ref(pa)() is pa
assert weakref.ref(pa, callback)() is pa
pk = p.kwargs
assert weakref.ref(pk)() is pk
assert weakref.ref(pk, callback)() is pk
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@ public static int getBuiltinTypeWeaklistoffset(PythonBuiltinClassType cls) {
-> 40;
case PMethod, // method
PFileIO, // _io.FileIO
PTee // itertools._tee
PTee, // itertools._tee
ContextVarsContext // _contextvars.Context
-> 32;
case PFunction -> 80; // function
case PIOBase, // _io._IOBase
Expand All @@ -122,9 +123,14 @@ public static int getBuiltinTypeWeaklistoffset(PythonBuiltinClassType cls) {
PLock // _thread.LockType
-> 24;
case PBytesIO, // _io.BytesIO
PPartial // functools.partial
PPartial, // functools.partial
PArray, // array.array
PStruct // _struct.Struct
-> 48;
case PPattern -> 64; // _sre.Pattern
case PPattern, // _sre.Pattern
PSimpleQueue // _queue.SimpleQueue
-> 64;
case PMMap -> 72; // mmap.mmap
case PStringIO -> 112; // _io.StringIO
case PBufferedReader, // _io.BufferedReader
PBufferedWriter, // _io.BufferedWriter
Expand All @@ -134,6 +140,13 @@ public static int getBuiltinTypeWeaklistoffset(PythonBuiltinClassType cls) {
case PickleBuffer -> 96; // _pickle.PickleBuffer
case PTextIOWrapper -> 176; // _io.TextIOWrapper
case POrderedDict -> 104;
case PDeque -> 208; // collections.deque
case PTypeVar, // typing.TypeVar
PTypeVarTuple, // typing.TypeVarTuple
PParamSpec, // typing.ParamSpec
PParamSpecArgs, // typing.ParamSpecArgs
PParamSpecKwargs // typing.ParamSpecKwargs
-> -32;
default -> 0;
// @formatter:on
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
Expand Down Expand Up @@ -160,9 +160,13 @@ static PReferenceType refType(Object cls, Object object, @SuppressWarnings("unus
@Specialization(guards = {"!isNativeObject(object)", "!isPNone(callback)"})
static PReferenceType refTypeWithCallback(Object cls, Object object, Object callback,
@Bind Node inliningTarget,
@Cached.Exclusive @Cached GetClassNode getClassNode,
@Cached.Exclusive @Cached HiddenAttr.ReadNode readQueueNode,
@Bind PythonLanguage language,
@Shared @Cached TypeNodes.GetInstanceShape getInstanceShape) {
if (getClassNode.execute(inliningTarget, object) instanceof PythonBuiltinClassType type && type.getWeaklistoffset() == 0) {
throw PRaiseNode.raiseStatic(inliningTarget, TypeError, ErrorMessages.CANNOT_CREATE_WEAK_REFERENCE_TO, object);
}
return PFactory.createReferenceType(language, cls, getInstanceShape.execute(cls), object, callback, getWeakReferenceQueue(inliningTarget, readQueueNode));
}

Expand Down