|
84 | 84 | import static com.oracle.graal.python.runtime.exception.PythonErrorType.ValueError;
|
85 | 85 |
|
86 | 86 | import java.math.BigInteger;
|
| 87 | +import java.nio.charset.StandardCharsets; |
87 | 88 | import java.util.Arrays;
|
88 | 89 | import java.util.List;
|
89 | 90 | import java.util.Locale;
|
|
160 | 161 | import com.oracle.graal.python.nodes.BuiltinNames;
|
161 | 162 | import com.oracle.graal.python.nodes.ErrorMessages;
|
162 | 163 | import com.oracle.graal.python.nodes.PGuards;
|
| 164 | +import com.oracle.graal.python.nodes.SpecialAttributeNames; |
163 | 165 | import com.oracle.graal.python.nodes.SpecialMethodNames;
|
164 | 166 | import com.oracle.graal.python.nodes.attributes.GetAttributeNode;
|
165 | 167 | import com.oracle.graal.python.nodes.attributes.GetAttributeNode.GetAnyAttributeNode;
|
@@ -2146,23 +2148,24 @@ public abstract static class TypeNode extends PythonBuiltinNode {
|
2146 | 2148 | @Specialization(guards = {"isNoValue(bases)", "isNoValue(dict)"})
|
2147 | 2149 | @SuppressWarnings("unused")
|
2148 | 2150 | Object type(Object cls, Object obj, PNone bases, PNone dict, PKeyword[] kwds,
|
2149 |
| - @Cached("create()") GetClassNode getClass) { |
| 2151 | + @Cached GetClassNode getClass) { |
2150 | 2152 | return getClass.execute(obj);
|
2151 | 2153 | }
|
2152 | 2154 |
|
2153 |
| - @Specialization |
2154 |
| - Object type(VirtualFrame frame, Object cls, String name, PTuple bases, PDict namespace, PKeyword[] kwds, |
| 2155 | + @Specialization(guards = "isString(wName)") |
| 2156 | + Object typeNew(VirtualFrame frame, Object cls, Object wName, PTuple bases, PDict namespace, PKeyword[] kwds, |
2155 | 2157 | @CachedLibrary(limit = "4") PythonObjectLibrary lib,
|
2156 |
| - @CachedLibrary(limit = "1") HashingStorageLibrary nslib, |
2157 |
| - @CachedLibrary(limit = "1") HashingStorageLibrary glib, |
| 2158 | + @CachedLibrary(limit = "2") HashingStorageLibrary nslib, |
2158 | 2159 | @Cached BranchProfile updatedStorage,
|
2159 | 2160 | @Cached("create(__NEW__)") LookupInheritedAttributeNode getNewFuncNode,
|
2160 | 2161 | @Cached("create(__INIT_SUBCLASS__)") GetAttributeNode getInitSubclassNode,
|
2161 | 2162 | @Cached("create(__SET_NAME__)") LookupInheritedAttributeNode getSetNameNode,
|
| 2163 | + @Cached CastToJavaStringNode castStr, |
2162 | 2164 | @Cached CallNode callSetNameNode,
|
2163 | 2165 | @Cached CallNode callInitSubclassNode,
|
2164 | 2166 | @Cached CallNode callNewFuncNode) {
|
2165 | 2167 | // Determine the proper metatype to deal with this
|
| 2168 | + String name = castStr.execute(wName); |
2166 | 2169 | Object metaclass = calculate_metaclass(frame, cls, bases, lib);
|
2167 | 2170 | if (metaclass != cls) {
|
2168 | 2171 | Object newFunc = getNewFuncNode.execute(metaclass);
|
@@ -2195,7 +2198,7 @@ Object type(VirtualFrame frame, Object cls, String name, PTuple bases, PDict nam
|
2195 | 2198 | PFrame callerFrame = getReadCallerFrameNode().executeWith(frame, 0);
|
2196 | 2199 | PythonObject globals = callerFrame.getGlobals();
|
2197 | 2200 | if (globals != null) {
|
2198 |
| - String moduleName = getModuleNameFromGlobals(globals, glib); |
| 2201 | + String moduleName = getModuleNameFromGlobals(globals, nslib); |
2199 | 2202 | if (moduleName != null) {
|
2200 | 2203 | ensureWriteAttrNode().execute(frame, newType, __MODULE__, moduleName);
|
2201 | 2204 | }
|
@@ -2225,6 +2228,19 @@ Object type(VirtualFrame frame, Object cls, String name, PTuple bases, PDict nam
|
2225 | 2228 | }
|
2226 | 2229 | }
|
2227 | 2230 |
|
| 2231 | + @Fallback |
| 2232 | + Object generic(@SuppressWarnings("unused") Object cls, @SuppressWarnings("unused") Object name, Object bases, Object namespace, @SuppressWarnings("unused") Object kwds) { |
| 2233 | + if (!(bases instanceof PTuple)) { |
| 2234 | + throw raise(TypeError, ErrorMessages.ARG_D_MUST_BE_S_NOT_P, "type.__new__()", 2, "tuple", bases); |
| 2235 | + } else if (namespace == PNone.NO_VALUE) { |
| 2236 | + throw raise(TypeError, ErrorMessages.TAKES_D_OR_D_ARGS, "type()", 1, 3); |
| 2237 | + } else if (!(namespace instanceof PDict)) { |
| 2238 | + throw raise(TypeError, ErrorMessages.ARG_D_MUST_BE_S_NOT_P, "type.__new__()", 3, "dict", bases); |
| 2239 | + } else { |
| 2240 | + throw CompilerDirectives.shouldNotReachHere("type fallback reached incorrectly"); |
| 2241 | + } |
| 2242 | + } |
| 2243 | + |
2228 | 2244 | private String getModuleNameFromGlobals(PythonObject globals, HashingStorageLibrary hlib) {
|
2229 | 2245 | Object nameAttr;
|
2230 | 2246 | if (globals instanceof PythonModule) {
|
@@ -2295,6 +2311,22 @@ private PythonClass typeMetaclass(VirtualFrame frame, String name, PTuple bases,
|
2295 | 2311 | } else {
|
2296 | 2312 | pythonClass.setAttribute(key, value);
|
2297 | 2313 | }
|
| 2314 | + } else if (SpecialAttributeNames.__DOC__.equals(key)) { |
| 2315 | + // CPython sets tp_doc to a copy of dict['__doc__'], if that is a string. It |
| 2316 | + // forcibly encodes the string as UTF-8, and raises an error if that is not |
| 2317 | + // possible. |
| 2318 | + String doc = null; |
| 2319 | + if (value instanceof String) { |
| 2320 | + doc = (String) value; |
| 2321 | + } else if (value instanceof PString) { |
| 2322 | + doc = ((PString) value).getValue(); |
| 2323 | + } |
| 2324 | + if (doc != null) { |
| 2325 | + if (!canEncode(doc)) { |
| 2326 | + throw raise(PythonBuiltinClassType.UnicodeEncodeError, ErrorMessages.CANNOT_ENCODE_DOCSTR, doc); |
| 2327 | + } |
| 2328 | + } |
| 2329 | + pythonClass.setAttribute(key, value); |
2298 | 2330 | } else {
|
2299 | 2331 | pythonClass.setAttribute(key, value);
|
2300 | 2332 | }
|
@@ -2365,6 +2397,11 @@ private PythonClass typeMetaclass(VirtualFrame frame, String name, PTuple bases,
|
2365 | 2397 | return pythonClass;
|
2366 | 2398 | }
|
2367 | 2399 |
|
| 2400 | + @TruffleBoundary |
| 2401 | + private static boolean canEncode(String doc) { |
| 2402 | + return StandardCharsets.UTF_8.newEncoder().canEncode(doc); |
| 2403 | + } |
| 2404 | + |
2368 | 2405 | @TruffleBoundary
|
2369 | 2406 | private PTuple copySlots(String className, SequenceStorage slotList, int slotlen, boolean add_dict, boolean add_weak, PDict namespace, HashingStorageLibrary nslib) {
|
2370 | 2407 | SequenceStorage newSlots = new ObjectSequenceStorage(slotlen - PInt.intValue(add_dict) - PInt.intValue(add_weak));
|
@@ -2659,44 +2696,30 @@ Object doNative(PythonAbstractNativeObject self, Object[] varargs, PKeyword[] kw
|
2659 | 2696 | @Builtin(name = "NotImplementedType", minNumOfPositionalArgs = 1, constructsClass = PythonBuiltinClassType.PNotImplemented, isPublic = false)
|
2660 | 2697 | @GenerateNodeFactory
|
2661 | 2698 | public abstract static class NotImplementedTypeNode extends PythonBuiltinNode {
|
2662 |
| - protected PythonBuiltinClass getNotImplementedClass() { |
2663 |
| - return getCore().lookupType(PythonBuiltinClassType.PNotImplemented); |
2664 |
| - } |
2665 |
| - |
| 2699 | + @SuppressWarnings("unused") |
2666 | 2700 | @Specialization
|
2667 | 2701 | public PNotImplemented module(Object cls) {
|
2668 |
| - if (cls != getNotImplementedClass()) { |
2669 |
| - throw raise(TypeError, ErrorMessages.OBJ_ISNT_CALLABLE, "NotImplementedType"); |
2670 |
| - } else { |
2671 |
| - return PNotImplemented.NOT_IMPLEMENTED; |
2672 |
| - } |
| 2702 | + return PNotImplemented.NOT_IMPLEMENTED; |
2673 | 2703 | }
|
2674 | 2704 | }
|
2675 | 2705 |
|
2676 |
| - @Builtin(name = "ellipsis", takesVarArgs = true, takesVarKeywordArgs = true, constructsClass = PythonBuiltinClassType.PEllipsis, isPublic = false) |
| 2706 | + @Builtin(name = "ellipsis", minNumOfPositionalArgs = 1, constructsClass = PythonBuiltinClassType.PEllipsis, isPublic = false) |
2677 | 2707 | @GenerateNodeFactory
|
2678 | 2708 | public abstract static class EllipsisTypeNode extends PythonBuiltinNode {
|
2679 | 2709 | @SuppressWarnings("unused")
|
2680 | 2710 | @Specialization
|
2681 |
| - public PEllipsis call(Object cls, Object args, Object kwds) { |
| 2711 | + public PEllipsis call(Object cls) { |
2682 | 2712 | return PEllipsis.INSTANCE;
|
2683 | 2713 | }
|
2684 | 2714 | }
|
2685 | 2715 |
|
2686 | 2716 | @Builtin(name = "NoneType", minNumOfPositionalArgs = 1, constructsClass = PythonBuiltinClassType.PNone, isPublic = false)
|
2687 | 2717 | @GenerateNodeFactory
|
2688 | 2718 | public abstract static class NoneTypeNode extends PythonBuiltinNode {
|
2689 |
| - protected PythonBuiltinClass getNoneClass() { |
2690 |
| - return getCore().lookupType(PythonBuiltinClassType.PNone); |
2691 |
| - } |
2692 |
| - |
| 2719 | + @SuppressWarnings("unused") |
2693 | 2720 | @Specialization
|
2694 | 2721 | public PNone module(Object cls) {
|
2695 |
| - if (cls != getNoneClass()) { |
2696 |
| - throw raise(TypeError, ErrorMessages.IS_NOT_SUBTYPE_OF, "NoneType.__new__", cls, "NoneType"); |
2697 |
| - } else { |
2698 |
| - return PNone.NONE; |
2699 |
| - } |
| 2722 | + return PNone.NONE; |
2700 | 2723 | }
|
2701 | 2724 | }
|
2702 | 2725 |
|
|
0 commit comments