Skip to content

Commit a3efc7c

Browse files
committed
PythonManagedClass: fix setting of __name__ and __qualname__ attributes
1 parent 060ba80 commit a3efc7c

File tree

6 files changed

+83
-29
lines changed

6 files changed

+83
-29
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/module/ModuleBuiltins.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,20 +103,21 @@ protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFa
103103
public abstract static class ModuleReprNode extends PythonUnaryBuiltinNode {
104104
@Specialization
105105
public Object repr(PythonModule self,
106-
@CachedLibrary(limit = "1") InteropLibrary lib,
107-
@CachedContext(PythonLanguage.class) PythonContext context) {
106+
@CachedLibrary(limit = "1") InteropLibrary lib,
107+
@CachedContext(PythonLanguage.class) PythonContext context) {
108108
// PyObject_CallMethod(interp->importlib, "_module_repr", "O", m);
109109
PythonModule builtins = context.getCore().getBuiltins();
110110
try {
111111
Object __import__ = lib.readMember(builtins, "__import__");
112-
Object module_repr = importFrom( __import__, "importlib._bootstrap", "_module_repr", lib);
112+
Object module_repr = importFrom(__import__, "importlib._bootstrap", "_module_repr", lib);
113113
return lib.execute(module_repr, self);
114114
} catch (UnknownIdentifierException | UnsupportedMessageException | UnsupportedTypeException | ArityException e) {
115115
return self.toString();
116116
}
117117
}
118118

119-
private Object importFrom(Object importBuiltinFunction, String moduleName, String from, InteropLibrary lib) throws UnsupportedTypeException, ArityException, UnsupportedMessageException, UnknownIdentifierException {
119+
private Object importFrom(Object importBuiltinFunction, String moduleName, String from, InteropLibrary lib)
120+
throws UnsupportedTypeException, ArityException, UnsupportedMessageException, UnknownIdentifierException {
120121
Object _bootstrap = lib.execute(importBuiltinFunction, moduleName, PNone.NONE, PNone.NONE, factory().createList(new Object[]{from}));
121122
return lib.readMember(_bootstrap, from);
122123
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/PythonObject.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ public int compareTo(Object o) {
181181
public String toString() {
182182
String className = "unknown";
183183
if (storedPythonClass instanceof PythonManagedClass) {
184-
className = ((PythonManagedClass) storedPythonClass).getName();
184+
className = ((PythonManagedClass) storedPythonClass).getQualName();
185185
} else if (storedPythonClass instanceof PythonBuiltinClassType) {
186186
className = ((PythonBuiltinClassType) storedPythonClass).getName();
187187
} else if (PGuards.isNativeClass(storedPythonClass)) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/str/StringUtils.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
*/
4141
package com.oracle.graal.python.builtins.objects.str;
4242

43+
import com.oracle.truffle.api.CompilerDirectives;
44+
4345
public final class StringUtils {
4446
public enum StripKind {
4547
LEFT,
@@ -199,4 +201,13 @@ public static String strip(String str, String chars, StripKind stripKind) {
199201

200202
return str.substring(i, j);
201203
}
204+
205+
@CompilerDirectives.TruffleBoundary
206+
public static boolean containsNullCharacter(String value) {
207+
return value.indexOf(0) > 0;
208+
}
209+
210+
public static boolean containsNullCharacter(PString value) {
211+
return containsNullCharacter(value.getValue());
212+
}
202213
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonManagedClass.java

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,6 @@
2525
*/
2626
package com.oracle.graal.python.builtins.objects.type;
2727

28-
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__DOC__;
29-
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__NAME__;
30-
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__QUALNAME__;
31-
3228
import java.util.Collections;
3329
import java.util.Set;
3430
import java.util.WeakHashMap;
@@ -52,9 +48,9 @@
5248
import com.oracle.truffle.api.object.DynamicObject;
5349
import com.oracle.truffle.api.object.Shape;
5450

55-
public abstract class PythonManagedClass extends PythonObject implements PythonAbstractClass {
51+
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__DOC__;
5652

57-
private final String className;
53+
public abstract class PythonManagedClass extends PythonObject implements PythonAbstractClass {
5854

5955
@CompilationFinal(dimensions = 1) private PythonAbstractClass[] baseClasses;
6056

@@ -63,6 +59,8 @@ public abstract class PythonManagedClass extends PythonObject implements PythonA
6359
private final Set<PythonAbstractClass> subClasses = Collections.newSetFromMap(new WeakHashMap<PythonAbstractClass, Boolean>());
6460
private final Shape instanceShape;
6561
private final FlagsContainer flags;
62+
private String name;
63+
private String qualName;
6664

6765
/** {@code true} if the MRO contains a native class. */
6866
private final boolean needsNativeAllocation;
@@ -71,7 +69,6 @@ public abstract class PythonManagedClass extends PythonObject implements PythonA
7169
@TruffleBoundary
7270
protected PythonManagedClass(Object typeClass, DynamicObject storage, Shape instanceShape, String name, PythonAbstractClass... baseClasses) {
7371
super(typeClass, storage);
74-
this.className = name;
7572

7673
this.methodResolutionOrder = new MroSequenceStorage(name, 0);
7774

@@ -88,9 +85,10 @@ protected PythonManagedClass(Object typeClass, DynamicObject storage, Shape inst
8885
this.methodResolutionOrder.setInitialized();
8986
this.needsNativeAllocation = computeNeedsNativeAllocation();
9087

91-
setAttribute(__NAME__, getBaseName(name));
92-
setAttribute(__QUALNAME__, className);
88+
this.name = getBaseName(name);
89+
this.qualName = name;
9390
setAttribute(__DOC__, PNone.NONE);
91+
9492
if (instanceShape != null) {
9593
this.instanceShape = instanceShape;
9694
} else {
@@ -140,8 +138,20 @@ public MroSequenceStorage getMethodResolutionOrder() {
140138
return methodResolutionOrder;
141139
}
142140

141+
public String getQualName() {
142+
return qualName;
143+
}
144+
145+
public void setQualName(String qualName) {
146+
this.qualName = qualName;
147+
}
148+
143149
public String getName() {
144-
return className;
150+
return name;
151+
}
152+
153+
public void setName(String name) {
154+
this.name = name;
145155
}
146156

147157
private boolean computeNeedsNativeAllocation() {
@@ -228,7 +238,7 @@ final Set<PythonAbstractClass> getSubClasses() {
228238
@Override
229239
public String toString() {
230240
CompilerAsserts.neverPartOfCompilation();
231-
return String.format("<class '%s'>", className);
241+
return String.format("<class '%s'>", qualName);
232242
}
233243

234244
public PythonAbstractClass[] getBaseClasses() {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
package com.oracle.graal.python.builtins.objects.type;
2828

29+
import static com.oracle.graal.python.builtins.objects.str.StringUtils.containsNullCharacter;
2930
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__BASES__;
3031
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__BASE__;
3132
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__BASICSIZE__;
@@ -79,6 +80,7 @@
7980
import com.oracle.graal.python.builtins.objects.mappingproxy.PMappingproxy;
8081
import com.oracle.graal.python.builtins.objects.object.PythonObject;
8182
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
83+
import com.oracle.graal.python.builtins.objects.str.PString;
8284
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
8385
import com.oracle.graal.python.builtins.objects.type.TypeBuiltinsFactory.CallNodeFactory;
8486
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode;
@@ -820,9 +822,8 @@ String getNameBuiltin(PythonBuiltinClass cls, @SuppressWarnings("unused") PNone
820822
}
821823

822824
@Specialization(guards = {"isNoValue(value)", "!isPythonBuiltinClass(cls)"})
823-
Object getName(PythonClass cls, @SuppressWarnings("unused") PNone value,
824-
@Cached("create()") ReadAttributeFromObjectNode getName) {
825-
return getName.execute(cls, __NAME__);
825+
Object getName(PythonClass cls, @SuppressWarnings("unused") PNone value) {
826+
return cls.getName();
826827
}
827828

828829
@Specialization(guards = "!isNoValue(value)")
@@ -836,9 +837,28 @@ Object setName(@SuppressWarnings("unused") PythonBuiltinClass cls, @SuppressWarn
836837
}
837838

838839
@Specialization(guards = {"!isNoValue(value)", "!isPythonBuiltinClass(cls)"})
840+
Object setName(PythonClass cls, String value) {
841+
if (containsNullCharacter(value)) {
842+
throw raise(PythonBuiltinClassType.ValueError, "type name must not contain null characters");
843+
}
844+
cls.setName(value);
845+
return PNone.NONE;
846+
}
847+
848+
@Specialization(guards = {"!isNoValue(value)", "!isPythonBuiltinClass(cls)", "isBuiltinString(value, profile)"}, limit = "1")
849+
Object setName(PythonClass cls, PString value,
850+
@Cached.Shared("builtinStringProfile") @Cached IsBuiltinClassProfile profile) {
851+
if (containsNullCharacter(value)) {
852+
throw raise(PythonBuiltinClassType.ValueError, "type name must not contain null characters");
853+
}
854+
cls.setName(value.getValue());
855+
return PNone.NONE;
856+
}
857+
858+
@Specialization(guards = {"!isNoValue(value)", "!isPythonBuiltinClass(cls)", "!isBuiltinString(value, profile)"}, limit = "1")
839859
Object setName(PythonClass cls, Object value,
840-
@Cached("create()") WriteAttributeToObjectNode setName) {
841-
return setName.execute(cls, __NAME__, value);
860+
@Cached.Shared("builtinStringProfile") @Cached IsBuiltinClassProfile profile) {
861+
throw raise(PythonBuiltinClassType.TypeError, "can only assign string to %p.__name__, not '%p'", cls, value);
842862
}
843863

844864
@Specialization(guards = "isNoValue(value)")
@@ -928,13 +948,12 @@ String getName(PythonBuiltinClassType cls, @SuppressWarnings("unused") PNone val
928948

929949
@Specialization(guards = "isNoValue(value)")
930950
String getName(PythonBuiltinClass cls, @SuppressWarnings("unused") PNone value) {
931-
return cls.getName();
951+
return cls.getQualName();
932952
}
933953

934954
@Specialization(guards = {"isNoValue(value)", "!isPythonBuiltinClass(cls)"})
935-
Object getName(PythonClass cls, @SuppressWarnings("unused") PNone value,
936-
@Cached("create()") ReadAttributeFromObjectNode getName) {
937-
return getName.execute(cls, __QUALNAME__);
955+
Object getName(PythonClass cls, @SuppressWarnings("unused") PNone value) {
956+
return cls.getQualName();
938957
}
939958

940959
@Specialization(guards = "!isNoValue(value)")
@@ -943,9 +962,22 @@ Object setName(@SuppressWarnings("unused") PythonBuiltinClass cls, @SuppressWarn
943962
}
944963

945964
@Specialization(guards = {"!isNoValue(value)", "!isPythonBuiltinClass(cls)"})
965+
Object setName(PythonClass cls, String value) {
966+
cls.setQualName(value);
967+
return PNone.NONE;
968+
}
969+
970+
@Specialization(guards = {"!isNoValue(value)", "!isPythonBuiltinClass(cls)", "isBuiltinString(value, profile)"}, limit = "1")
971+
Object setName(PythonClass cls, PString value,
972+
@Cached.Shared("builtinStringProfile") @Cached IsBuiltinClassProfile profile) {
973+
cls.setQualName(value.getValue());
974+
return PNone.NONE;
975+
}
976+
977+
@Specialization(guards = {"!isNoValue(value)", "!isPythonBuiltinClass(cls)", "!isBuiltinString(value, profile)"}, limit = "1")
946978
Object setName(PythonClass cls, Object value,
947-
@Cached("create()") WriteAttributeToObjectNode setName) {
948-
return setName.execute(cls, __QUALNAME__, value);
979+
@Cached.Shared("builtinStringProfile") @Cached IsBuiltinClassProfile profile) {
980+
throw raise(PythonBuiltinClassType.TypeError, "can only assign string to %p.__qualname__, not '%p'", cls, value);
949981
}
950982

951983
@Specialization(guards = "isNoValue(value)")

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ public abstract static class GetNameNode extends Node {
321321

322322
@Specialization
323323
String doManagedClass(PythonManagedClass obj) {
324-
return obj.getName();
324+
return obj.getQualName();
325325
}
326326

327327
@Specialization
@@ -339,7 +339,7 @@ String doNativeClass(PythonNativeClass obj,
339339
@TruffleBoundary
340340
public static String doSlowPath(Object obj) {
341341
if (obj instanceof PythonManagedClass) {
342-
return ((PythonManagedClass) obj).getName();
342+
return ((PythonManagedClass) obj).getQualName();
343343
} else if (obj instanceof PythonBuiltinClassType) {
344344
return ((PythonBuiltinClassType) obj).getName();
345345
} else if (PGuards.isNativeClass(obj)) {

0 commit comments

Comments
 (0)