|
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