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
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2018, 2024, 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 @@ -71,18 +71,18 @@ def _reference_pop(args):
except AttributeError:
raise SystemError


def _reference_discard(args):
s = args[0]
if not (isinstance(s, set)):
raise SystemError

if args[1] in s:
s.discard(args[1])
return 1
return 0


class FrozenSetSubclass(frozenset):
pass

Expand Down Expand Up @@ -267,7 +267,7 @@ class TestPySet(CPyExtTestCase):
if (!res) {
// avoid problems when building the result value
*key = set;
*hash = 0;
*hash = 0;
Py_INCREF(set);
}
return res;
Expand Down Expand Up @@ -296,7 +296,7 @@ class TestPySet(CPyExtTestCase):
argspec='O',
cmpfunc=unhandled_error_compare
)

# PySet_Discard
test_PySet_Discard = CPyExtFunction(
_reference_discard,
Expand All @@ -313,3 +313,29 @@ class TestPySet(CPyExtTestCase):
argumentnames=("set, key"),
cmpfunc=unhandled_error_compare
)

# Note: frozensets are allowed to be mutated if refcnt == 1
test_PySet_Add = CPyExtFunction(
lambda args: frozenset({*args[1], args[2]}) if args[0] else {*args[1], args[2]},
lambda: (
(False, [1], 2),
(True, [1], 2),
),
resultspec="O",
argspec='iOO',
arguments=("int frozen", "PyObject* iterable", "PyObject* object"),
code='''
PyObject* wrap_PySet_Add(int frozen, PyObject* iterable, PyObject* object) {
PyObject* set = frozen? PyFrozenSet_New(iterable) : PySet_New(iterable);
if (!set)
return NULL;
if (PySet_Add(set, object) < 0) {
Py_DECREF(set);
return NULL;
}
return set;
}
''',
callfunction="wrap_PySet_Add",
cmpfunc=unhandled_error_compare,
)
29 changes: 28 additions & 1 deletion graalpython/com.oracle.graal.python.test/src/tests/test_descr.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2024, 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 @@ -77,3 +77,30 @@ def __eq__(self, other):
o = ObjWithHashSlot()
o.__hash__ = lambda: 1
assert hash(o) == 1


def test_attribute_error_message():
obj = object()

try:
obj.foo
except AttributeError as e:
assert e.obj == obj
assert e.name == "foo"
assert str(e) == "'object' object has no attribute 'foo'"

try:
obj.foo = 1
except AttributeError as e:
# Note: as of 3.12, CPython doesn't set obj and name
assert str(e) == "'object' object has no attribute 'foo'"

class MyClass:
pass

try:
MyClass.foo
except AttributeError as e:
assert e.obj == MyClass
assert e.name == "foo"
assert str(e) == "type object 'MyClass' has no attribute 'foo'"
30 changes: 29 additions & 1 deletion graalpython/com.oracle.graal.python.test/src/tests/test_scope.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2018, 2021, 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 @@ -37,6 +37,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from tests import util

def assert_raises(err, fn, *args, **kwargs):
raised = False
Expand Down Expand Up @@ -945,3 +946,30 @@ def toInternal(obj):
c = fnc.__code__
assert c.co_freevars == ('var',)
assert c.co_cellvars == tuple()


@util.skipUnlessBytecodeDSL("name atttribute not populated in manual interpreter")
def test_name_errors():
def assert_raises_name_error(name, fn, *args, **kwargs):
try:
fn(*args, **kwargs)
except NameError as e:
assert str(e) == f"name '{name}' is not defined"
assert e.name == name

assert_raises_name_error('foo', exec, 'foo')
assert_raises_name_error('foo', exec, 'foo', {})
assert_raises_name_error('foo', exec, 'del foo')
assert_raises_name_error('foo', exec, 'del foo', {})

def load_global():
global xxx
xxx

assert_raises_name_error('xxx', load_global)

def delete_global():
global yyy
del yyy

assert_raises_name_error('yyy', delete_global)
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ test.test_dict.DictTest.test_pop @ darwin-arm64,linux-aarch64,linux-aarch64-gith
test.test_dict.DictTest.test_popitem @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github,win32-AMD64,win32-AMD64-github
test.test_dict.DictTest.test_reentrant_insertion @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github,win32-AMD64,win32-AMD64-github
test.test_dict.DictTest.test_repr @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github,win32-AMD64,win32-AMD64-github
test.test_dict.DictTest.test_repr_deep @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github,win32-AMD64,win32-AMD64-github
# Transiently doesn't raise RecursionError
!test.test_dict.DictTest.test_repr_deep
test.test_dict.DictTest.test_resize1 @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github,win32-AMD64,win32-AMD64-github
test.test_dict.DictTest.test_resize2 @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github,win32-AMD64,win32-AMD64-github
test.test_dict.DictTest.test_reverse_iterator_for_empty_dict @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github,win32-AMD64,win32-AMD64-github
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 @@ -102,9 +102,6 @@
import com.oracle.graal.python.builtins.modules.RandomModuleBuiltins;
import com.oracle.graal.python.builtins.modules.ReadlineModuleBuiltins;
import com.oracle.graal.python.builtins.modules.ResourceModuleBuiltins;
import com.oracle.graal.python.builtins.modules.re.MatchBuiltins;
import com.oracle.graal.python.builtins.modules.re.PatternBuiltins;
import com.oracle.graal.python.builtins.modules.re.SREModuleBuiltins;
import com.oracle.graal.python.builtins.modules.SSLModuleBuiltins;
import com.oracle.graal.python.builtins.modules.SelectModuleBuiltins;
import com.oracle.graal.python.builtins.modules.SignalModuleBuiltins;
Expand Down Expand Up @@ -204,6 +201,9 @@
import com.oracle.graal.python.builtins.modules.pickle.PicklerMemoProxyBuiltins;
import com.oracle.graal.python.builtins.modules.pickle.UnpicklerBuiltins;
import com.oracle.graal.python.builtins.modules.pickle.UnpicklerMemoProxyBuiltins;
import com.oracle.graal.python.builtins.modules.re.MatchBuiltins;
import com.oracle.graal.python.builtins.modules.re.PatternBuiltins;
import com.oracle.graal.python.builtins.modules.re.SREModuleBuiltins;
import com.oracle.graal.python.builtins.modules.re.SREScannerBuiltins;
import com.oracle.graal.python.builtins.modules.weakref.ProxyTypeBuiltins;
import com.oracle.graal.python.builtins.modules.zlib.ZLibModuleBuiltins;
Expand Down Expand Up @@ -247,6 +247,7 @@
import com.oracle.graal.python.builtins.objects.exception.BaseExceptionGroupBuiltins;
import com.oracle.graal.python.builtins.objects.exception.ImportErrorBuiltins;
import com.oracle.graal.python.builtins.objects.exception.KeyErrorBuiltins;
import com.oracle.graal.python.builtins.objects.exception.NameErrorBuiltins;
import com.oracle.graal.python.builtins.objects.exception.OsErrorBuiltins;
import com.oracle.graal.python.builtins.objects.exception.StopIterationBuiltins;
import com.oracle.graal.python.builtins.objects.exception.SyntaxErrorBuiltins;
Expand Down Expand Up @@ -583,6 +584,7 @@ private static PythonBuiltins[] initializeBuiltins(TruffleLanguage.Env env) {
new com.oracle.graal.python.builtins.objects.types.UnionTypeBuiltins(),
// exceptions
new AttributeErrorBuiltins(),
new NameErrorBuiltins(),
new SystemExitBuiltins(),
new ImportErrorBuiltins(),
new StopIterationBuiltins(),
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 @@ -168,6 +168,7 @@
import com.oracle.graal.python.builtins.objects.exception.BaseExceptionGroupBuiltins;
import com.oracle.graal.python.builtins.objects.exception.ImportErrorBuiltins;
import com.oracle.graal.python.builtins.objects.exception.KeyErrorBuiltins;
import com.oracle.graal.python.builtins.objects.exception.NameErrorBuiltins;
import com.oracle.graal.python.builtins.objects.exception.OsErrorBuiltins;
import com.oracle.graal.python.builtins.objects.exception.StopIterationBuiltins;
import com.oracle.graal.python.builtins.objects.exception.SyntaxErrorBuiltins;
Expand Down Expand Up @@ -756,7 +757,7 @@ It can be called either on the class (e.g. C.f()) or on an instance
IndexError("IndexError", LookupError, newBuilder().publishInModule(J_BUILTINS).basetype().addDict()),
KeyError("KeyError", LookupError, newBuilder().publishInModule(J_BUILTINS).basetype().addDict().slots(KeyErrorBuiltins.SLOTS)),
MemoryError("MemoryError", Exception, newBuilder().publishInModule(J_BUILTINS).basetype().addDict()),
NameError("NameError", Exception, newBuilder().publishInModule(J_BUILTINS).basetype().addDict()),
NameError("NameError", Exception, newBuilder().publishInModule(J_BUILTINS).basetype().addDict().slots(NameErrorBuiltins.SLOTS)),
UnboundLocalError("UnboundLocalError", NameError, newBuilder().publishInModule(J_BUILTINS).basetype().addDict()),
OSError("OSError", Exception, newBuilder().publishInModule(J_BUILTINS).basetype().addDict().slots(OsErrorBuiltins.SLOTS)),
BlockingIOError("BlockingIOError", OSError, newBuilder().publishInModule(J_BUILTINS).basetype().addDict()),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 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 @@ -113,7 +113,6 @@
import com.oracle.graal.python.nodes.function.builtins.clinic.ArgumentClinicProvider;
import com.oracle.graal.python.nodes.object.BuiltinClassProfiles.IsBuiltinObjectProfile;
import com.oracle.graal.python.nodes.object.GetClassNode;
import com.oracle.graal.python.nodes.object.GetDictFromGlobalsNode;
import com.oracle.graal.python.nodes.object.GetOrCreateDictNode;
import com.oracle.graal.python.nodes.statement.AbstractImportNode;
import com.oracle.graal.python.nodes.util.CannotCastException;
Expand Down Expand Up @@ -215,7 +214,6 @@ static final class WarningsModuleNode extends Node {
@Child PyObjectIsTrueNode isTrueNode;
@Child IsSubClassNode isSubClassNode;
@Child GetOrCreateDictNode getDictNode;
@Child GetDictFromGlobalsNode getDictFromGlobalsNode;
@Child ReadFrameNode readFrameNode;
@Child PyObjectLookupAttr lookupAttrNode;
@Child PyObjectCallMethodObjArgs callMethodNode;
Expand Down Expand Up @@ -398,15 +396,6 @@ private PDict getSysDict() {
return getDictNode.executeCached(getContext().lookupBuiltinModule(T_SYS));
}

private PDict getGlobalsDict(Object globals) {
if (getDictFromGlobalsNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
reportPolymorphicSpecialize();
getDictFromGlobalsNode = insert(GetDictFromGlobalsNode.create());
}
return getDictFromGlobalsNode.executeCached(globals);
}

private PFrame getCallerFrame(VirtualFrame frame, int stackLevel, TruffleString[] skipFilePrefixes) {
if (readFrameNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
Expand Down Expand Up @@ -891,7 +880,7 @@ private void setupContext(VirtualFrame frame, int stackLevel, TruffleString[] sk
filename[0] = T_SYS;
lineno[0] = 1;
} else {
globals = getGlobalsDict(f.getGlobals());
globals = (PDict) f.getGlobals();
lineno[0] = f.getLine();
RootCallTarget ct = f.getTarget();
if (ct != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2025, 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 @@ -40,6 +40,7 @@
*/
package com.oracle.graal.python.builtins.modules.datetime;

import static com.oracle.graal.python.builtins.PythonBuiltinClassType.TypeError;
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.ValueError;
import static com.oracle.graal.python.builtins.modules.datetime.DatetimeModuleBuiltins.MAX_YEAR;
import static com.oracle.graal.python.builtins.modules.datetime.DatetimeModuleBuiltins.MIN_YEAR;
Expand Down Expand Up @@ -199,9 +200,10 @@ static PDate asManaged(PDate obj) {
return obj;
}

@Specialization
static PDate asManagedNative(PythonAbstractNativeObject obj,
@Specialization(guards = "checkNode.execute(inliningTarget, obj)", limit = "1")
static PDate asManagedNative(@SuppressWarnings("unused") Node inliningTarget, PythonAbstractNativeObject obj,
@Bind PythonLanguage language,
@SuppressWarnings("unused") @Cached DateCheckNode checkNode,
@Cached CStructAccess.ReadByteNode readByteNode) {
int year = getYear(obj, readByteNode);
int month = getMonth(obj, readByteNode);
Expand All @@ -223,6 +225,12 @@ static int getMonth(PythonAbstractNativeObject self, CStructAccess.ReadByteNode
static int getDay(PythonAbstractNativeObject self, CStructAccess.ReadByteNode readNode) {
return readNode.readFromObjUnsigned(self, CFields.PyDateTime_Date__data, 3);
}

@Fallback
static PDate error(Object obj,
@Bind Node inliningTarget) {
throw PRaiseNode.raiseStatic(inliningTarget, TypeError, ErrorMessages.S_EXPECTED_GOT_P, "date", obj);
}
}

@GenerateUncached
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -308,9 +308,10 @@ static PDateTime asManaged(PDateTime obj) {
return obj;
}

@Specialization
static PDateTime asManagedNative(PythonAbstractNativeObject obj,
@Specialization(guards = "checkNode.execute(inliningTarget, obj)", limit = "1")
static PDateTime asManagedNative(@SuppressWarnings("unused") Node inliningTarget, PythonAbstractNativeObject obj,
@Bind PythonLanguage language,
@SuppressWarnings("unused") @Cached DateTimeCheckNode checkNode,
@Cached CStructAccess.ReadByteNode readByteNode,
@Cached CStructAccess.ReadObjectNode readObjectNode) {
int year = getYear(obj, readByteNode);
Expand All @@ -329,6 +330,12 @@ static PDateTime asManagedNative(PythonAbstractNativeObject obj,
return new PDateTime(cls, cls.getInstanceShape(language), year, month, day, hour, minute, second, microsecond, tzInfo, fold);
}

@Fallback
static PDateTime error(Object obj,
@Bind Node inliningTarget) {
throw PRaiseNode.raiseStatic(inliningTarget, TypeError, ErrorMessages.S_EXPECTED_GOT_P, "datetime", obj);
}

static int getYear(PythonAbstractNativeObject self, CStructAccess.ReadByteNode readNode) {
int b0 = readNode.readFromObjUnsigned(self, CFields.PyDateTime_DateTime__data, 0);
int b1 = readNode.readFromObjUnsigned(self, CFields.PyDateTime_DateTime__data, 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,9 +281,10 @@ static PTimeDelta doPTimeDelta(PTimeDelta value) {
return value;
}

@Specialization
static PTimeDelta doNative(PythonAbstractNativeObject nativeDelta,
@Specialization(guards = "checkNode.execute(inliningTarget, nativeDelta)", limit = "1")
static PTimeDelta doNative(@SuppressWarnings("unused") Node inliningTarget, PythonAbstractNativeObject nativeDelta,
@Bind PythonLanguage language,
@SuppressWarnings("unused") @Cached TimeDeltaCheckNode checkNode,
@Cached CStructAccess.ReadI32Node readIntNode) {
int days = getDays(nativeDelta, readIntNode);
int seconds = getSeconds(nativeDelta, readIntNode);
Expand All @@ -304,5 +305,11 @@ static int getSeconds(PythonAbstractNativeObject self, CStructAccess.ReadI32Node
static int getMicroseconds(PythonAbstractNativeObject self, CStructAccess.ReadI32Node readNode) {
return readNode.readFromObj(self, CFields.PyDateTime_Delta__microseconds);
}

@Fallback
static PTimeDelta error(Object obj,
@Bind Node inliningTarget) {
throw PRaiseNode.raiseStatic(inliningTarget, TypeError, ErrorMessages.S_EXPECTED_GOT_P, "timedelta", obj);
}
}
}
Loading
Loading