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
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 @@ -89,3 +89,21 @@ def __call__(self, x, y):

assert isinstance(method1(), A)
assert method2(1) == "A is 1", method2(1)


def test_method_qualname_uses_wrapped_callable():
import types

def f():
pass

class A:
def g(self):
pass

m = classmethod(f)

assert A().g.__qualname__ == "test_method_qualname_uses_wrapped_callable.<locals>.A.g"
assert types.MethodType(f, A).__qualname__ == "test_method_qualname_uses_wrapped_callable.<locals>.f"
assert A.m.__qualname__ == "test_method_qualname_uses_wrapped_callable.<locals>.f"
assert A.__dict__["m"].__qualname__ == "test_method_qualname_uses_wrapped_callable.<locals>.f"
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) 2014, Regents of the University of California
*
* All rights reserved.
Expand Down Expand Up @@ -55,10 +55,8 @@
import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject;
import com.oracle.graal.python.builtins.objects.function.PKeyword;
import com.oracle.graal.python.builtins.objects.module.PythonModule;
import com.oracle.graal.python.builtins.objects.str.StringUtils.SimpleTruffleStringFormatNode;
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.TpSlotHashFun.HashBuiltinNode;
import com.oracle.graal.python.builtins.objects.type.slots.TpSlotRichCompare.RichCmpBuiltinNode;
import com.oracle.graal.python.lib.PyObjectGetAttr;
Expand All @@ -76,15 +74,13 @@
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
import com.oracle.graal.python.nodes.function.builtins.PythonVarargsBuiltinNode;
import com.oracle.graal.python.nodes.object.GetClassNode;
import com.oracle.graal.python.nodes.util.CannotCastException;
import com.oracle.graal.python.nodes.util.CastToTruffleStringNode;
import com.oracle.graal.python.runtime.ExecutionContext.BoundaryCallContext;
import com.oracle.graal.python.runtime.IndirectCallData.BoundaryCallData;
import com.oracle.graal.python.runtime.PythonContext;
import com.oracle.graal.python.runtime.object.PFactory;
import com.oracle.graal.python.util.PythonUtils;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Bind;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Cached.Shared;
Expand Down Expand Up @@ -285,105 +281,44 @@ static Object getDoc(PBuiltinMethod self,
}
}

static TruffleString getFunctionAttr(VirtualFrame frame, Object self, Node inliningTarget, CastToTruffleStringNode toStringNode, PyObjectGetAttr getAttr, PRaiseNode raiseNode,
TruffleString attrName) {
Object function;
if (self instanceof PMethod method) {
function = method.getFunction();
} else {
function = ((PBuiltinMethod) self).getFunction();
}
try {
return toStringNode.execute(inliningTarget, getAttr.execute(frame, inliningTarget, function, attrName));
} catch (CannotCastException cce) {
throw raiseNode.raise(inliningTarget, PythonBuiltinClassType.TypeError, ErrorMessages.IS_NOT_A_UNICODE_OBJECT, attrName);
}
}

@Builtin(name = J___NAME__, minNumOfPositionalArgs = 1, isGetter = true)
@GenerateNodeFactory
public abstract static class NameNode extends PythonUnaryBuiltinNode {
@Specialization
static Object getName(VirtualFrame frame, PBuiltinMethod method,
@Bind Node inliningTarget,
@Shared("toStringNode") @Cached CastToTruffleStringNode toStringNode,
@Shared("getAttr") @Cached PyObjectGetAttr getAttr) {
try {
return toStringNode.execute(inliningTarget, getAttr.execute(frame, inliningTarget, method.getFunction(), T___NAME__));
} catch (CannotCastException cce) {
throw CompilerDirectives.shouldNotReachHere();
}
}

@Specialization
static Object getName(VirtualFrame frame, PMethod method,
static TruffleString getName(VirtualFrame frame, Object self,
@Bind Node inliningTarget,
@Shared("toStringNode") @Cached CastToTruffleStringNode toStringNode,
@Shared("getAttr") @Cached PyObjectGetAttr getAttr) {
try {
return toStringNode.execute(inliningTarget, getAttr.execute(frame, inliningTarget, method.getFunction(), T___NAME__));
} catch (CannotCastException cce) {
throw CompilerDirectives.shouldNotReachHere();
}
@Cached CastToTruffleStringNode toStringNode,
@Cached PyObjectGetAttr getAttr,
@Cached PRaiseNode raiseNode) {
return getFunctionAttr(frame, self, inliningTarget, toStringNode, getAttr, raiseNode, T___NAME__);
}
}

@Builtin(name = J___QUALNAME__, minNumOfPositionalArgs = 1, isGetter = true)
@GenerateNodeFactory
public abstract static class QualNameNode extends PythonUnaryBuiltinNode {

protected static boolean isSelfModuleOrNull(PMethod method) {
return method.getSelf() == PNone.NO_VALUE || PGuards.isPythonModule(method.getSelf());
}

protected static boolean isSelfModuleOrNull(PBuiltinMethod method) {
return method.getSelf() == PNone.NO_VALUE || PGuards.isPythonModule(method.getSelf());
}

@Specialization(guards = "isSelfModuleOrNull(method)")
static TruffleString doSelfIsModule(VirtualFrame frame, PMethod method,
@Bind Node inliningTarget,
@Shared("toStringNode") @Cached CastToTruffleStringNode toStringNode,
@Shared("lookupName") @Cached PyObjectLookupAttr lookupName) {
return getName(frame, inliningTarget, method.getFunction(), toStringNode, lookupName);
}

@Specialization(guards = "isSelfModuleOrNull(method)")
static TruffleString doSelfIsModule(VirtualFrame frame, PBuiltinMethod method,
@Bind Node inliningTarget,
@Shared("toStringNode") @Cached CastToTruffleStringNode toStringNode,
@Shared("lookupName") @Cached PyObjectLookupAttr lookupName) {
return getName(frame, inliningTarget, method.getFunction(), toStringNode, lookupName);
}

@Specialization(guards = "!isSelfModuleOrNull(method)")
static TruffleString doSelfIsObject(VirtualFrame frame, PMethod method,
@Bind Node inliningTarget,
@Shared @Cached GetClassNode getClassNode,
@Shared @Cached TypeNodes.IsTypeNode isTypeNode,
@Shared("toStringNode") @Cached CastToTruffleStringNode toStringNode,
@Shared("getQualname") @Cached PyObjectGetAttr getQualname,
@Shared("lookupName") @Cached PyObjectLookupAttr lookupName,
@Shared("formatter") @Cached SimpleTruffleStringFormatNode simpleTruffleStringFormatNode,
@Shared @Cached PRaiseNode raiseNode) {
return getQualName(frame, inliningTarget, method.getSelf(), method.getFunction(), getClassNode, isTypeNode, toStringNode, getQualname, lookupName, simpleTruffleStringFormatNode,
raiseNode);
}

@Specialization(guards = "!isSelfModuleOrNull(method)")
static TruffleString doSelfIsObject(VirtualFrame frame, PBuiltinMethod method,
@Specialization
static TruffleString getQualname(VirtualFrame frame, Object self,
@Bind Node inliningTarget,
@Shared @Cached GetClassNode getClassNode,
@Shared @Cached TypeNodes.IsTypeNode isTypeNode,
@Shared("toStringNode") @Cached CastToTruffleStringNode toStringNode,
@Shared("getQualname") @Cached PyObjectGetAttr getQualname,
@Shared("lookupName") @Cached PyObjectLookupAttr lookupName,
@Shared("formatter") @Cached SimpleTruffleStringFormatNode simpleTruffleStringFormatNode,
@Shared @Cached PRaiseNode raiseNode) {
return getQualName(frame, inliningTarget, method.getSelf(), method.getFunction(), getClassNode, isTypeNode, toStringNode, getQualname, lookupName, simpleTruffleStringFormatNode,
raiseNode);
}

private static TruffleString getQualName(VirtualFrame frame, Node inliningTarget, Object self, Object func, GetClassNode getClassNode, TypeNodes.IsTypeNode isTypeNode,
CastToTruffleStringNode toStringNode, PyObjectGetAttr getQualname, PyObjectLookupAttr lookupName, SimpleTruffleStringFormatNode simpleTruffleStringFormatNode,
PRaiseNode raiseNode) {
Object type = isTypeNode.execute(inliningTarget, self) ? self : getClassNode.execute(inliningTarget, self);

try {
TruffleString typeQualName = toStringNode.execute(inliningTarget, getQualname.execute(frame, inliningTarget, type, T___QUALNAME__));
return simpleTruffleStringFormatNode.format("%s.%s", typeQualName, getName(frame, inliningTarget, func, toStringNode, lookupName));
} catch (CannotCastException cce) {
throw raiseNode.raise(inliningTarget, PythonBuiltinClassType.TypeError, ErrorMessages.IS_NOT_A_UNICODE_OBJECT, T___QUALNAME__);
}
}

private static TruffleString getName(VirtualFrame frame, Node inliningTarget, Object func, CastToTruffleStringNode toStringNode, PyObjectLookupAttr lookupName) {
return toStringNode.execute(inliningTarget, lookupName.execute(frame, inliningTarget, func, T___NAME__));
@Cached CastToTruffleStringNode toStringNode,
@Cached PyObjectGetAttr getQualname,
@Cached PRaiseNode raiseNode) {
return getFunctionAttr(frame, self, inliningTarget, toStringNode, getQualname, raiseNode, T___QUALNAME__);
}
}

Expand Down
Loading