/Languages/IronPython/IronPython/Runtime/Types/PythonType.cs
C# | 3624 lines | 2649 code | 622 blank | 353 comment | 753 complexity | 2cef20ee4eb7d89ae2890c8135461ba3 MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception
Large files files are truncated, but you can click here to view the full file
- /* ****************************************************************************
- *
- * Copyright (c) Microsoft Corporation.
- *
- * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
- * copy of the license can be found in the License.html file at the root of this distribution. If
- * you cannot locate the Apache License, Version 2.0, please send an email to
- * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
- * by the terms of the Apache License, Version 2.0.
- *
- * You must not remove this notice, or any other, from this software.
- *
- *
- * ***************************************************************************/
- #if FEATURE_CORE_DLR
- using System.Linq.Expressions;
- #else
- using Microsoft.Scripting.Ast;
- #endif
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Globalization;
- using System.Linq;
- using System.Reflection;
- using System.Runtime.CompilerServices;
- using System.Dynamic;
- using System.Text;
- using System.Threading;
- using Microsoft.Scripting;
- using Microsoft.Scripting.Actions;
- using Microsoft.Scripting.Runtime;
- using Microsoft.Scripting.Utils;
- using IronPython.Runtime.Binding;
- using IronPython.Runtime.Operations;
- #if FEATURE_NUMERICS
- using System.Numerics;
- #else
- using Microsoft.Scripting.Math;
- using Complex = Microsoft.Scripting.Math.Complex64;
- #endif
- namespace IronPython.Runtime.Types {
- /// <summary>
- /// Represents a PythonType. Instances of PythonType are created via PythonTypeBuilder.
- /// </summary>
- [DebuggerDisplay("PythonType: {Name}"), DebuggerTypeProxy(typeof(PythonType.DebugProxy))]
- [PythonType("type")]
- [Documentation(@"type(object) -> gets the type of the object
- type(name, bases, dict) -> creates a new type instance with the given name, base classes, and members from the dictionary")]
- public partial class PythonType : IPythonMembersList, IDynamicMetaObjectProvider, IWeakReferenceable, IWeakReferenceableByProxy, ICodeFormattable, IFastGettable, IFastSettable, IFastInvokable {
- private Type/*!*/ _underlyingSystemType; // the underlying CLI system type for this type
- private string _name; // the name of the type
- private Dictionary<string, PythonTypeSlot> _dict; // type-level slots & attributes
- private PythonTypeAttributes _attrs; // attributes of the type
- private int _flags; // CPython-like flags on the type
- private int _version = GetNextVersion(); // version of the type
- private List<WeakReference> _subtypes; // all of the subtypes of the PythonType
- private PythonContext _pythonContext; // the context the type was created from, or null for system types.
- private bool? _objectNew, _objectInit; // true if the type doesn't override __new__ / __init__ from object.
- internal Dictionary<CachedGetKey, FastGetBase> _cachedGets; // cached gets on user defined type instances
- internal Dictionary<CachedGetKey, FastGetBase> _cachedTryGets; // cached try gets on used defined type instances
- internal Dictionary<SetMemberKey, FastSetBase> _cachedSets; // cached sets on user defined instances
- internal Dictionary<string, TypeGetBase> _cachedTypeGets; // cached gets on types (system and user types)
- internal Dictionary<string, TypeGetBase> _cachedTypeTryGets; // cached gets on types (system and user types)
- // commonly calculatable
- private List<PythonType> _resolutionOrder; // the search order for methods in the type
- private PythonType/*!*/[]/*!*/ _bases; // the base classes of the type
- private BuiltinFunction _ctor; // the built-in function which allocates an instance - a .NET ctor
- private Type _finalSystemType; // base .NET type if we're inherited from another Python-like type.
- // fields that frequently remain null
- private WeakRefTracker _weakrefTracker; // storage for Python style weak references
- private WeakReference _weakRef; // single weak ref instance used for all user PythonTypes.
- private string[] _slots; // the slots when the class was created
- private OldClass _oldClass; // the associated OldClass or null for new-style types
- private int _originalSlotCount; // the number of slots when the type was created
- private InstanceCreator _instanceCtor; // creates instances
- private CallSite<Func<CallSite, object, int>> _hashSite;
- private CallSite<Func<CallSite, object, object, bool>> _eqSite;
- private CallSite<Func<CallSite, object, object, int>> _compareSite;
- private Dictionary<CallSignature, LateBoundInitBinder> _lateBoundInitBinders;
- private string[] _optimizedInstanceNames; // optimized names stored in a custom dictionary
- private int _optimizedInstanceVersion;
- private Dictionary<string, List<MethodInfo>> _extensionMethods; // extension methods defined on the type
- private PythonSiteCache _siteCache = new PythonSiteCache();
- private PythonTypeSlot _lenSlot; // cached length slot, cleared when the type is mutated
- internal Func<string, Exception> _makeException = DefaultMakeException;
- [MultiRuntimeAware]
- private static int MasterVersion = 1;
- private static readonly CommonDictionaryStorage _pythonTypes = new CommonDictionaryStorage();
- internal static readonly PythonType _pythonTypeType = DynamicHelpers.GetPythonTypeFromType(typeof(PythonType));
- private static readonly WeakReference[] _emptyWeakRef = new WeakReference[0];
- private static object _subtypesLock = new object();
- internal static readonly Func<string, Exception> DefaultMakeException = (message) => new Exception(message);
- /// <summary>
- /// Provides delegates that will invoke a parameterless type ctor. The first key provides
- /// the dictionary for a specific type, the 2nd key provides the delegate for a specific
- /// call site type used in conjunction w/ our IFastInvokable implementation.
- /// </summary>
- private static Dictionary<Type, Dictionary<Type, Delegate>> _fastBindCtors = new Dictionary<Type, Dictionary<Type, Delegate>>();
- /// <summary>
- /// Shared built-in functions for creating instances of user defined types. Because all
- /// types w/ the same UnderlyingSystemType share the same constructors these can be
- /// shared across multiple types.
- /// </summary>
- private static Dictionary<Type, BuiltinFunction> _userTypeCtors = new Dictionary<Type, BuiltinFunction>();
- /// <summary>
- /// Creates a new type for a user defined type. The name, base classes (a tuple of type
- /// objects), and a dictionary of members is provided.
- /// </summary>
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
- public PythonType(CodeContext/*!*/ context, string name, PythonTuple bases, PythonDictionary dict)
- : this(context, name, bases, dict, String.Empty) {
- }
- /// <summary>
- /// Creates a new type for a user defined type. The name, base classes (a tuple of type
- /// objects), and a dictionary of members is provided.
- /// </summary>
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
- internal PythonType(CodeContext/*!*/ context, string name, PythonTuple bases, PythonDictionary dict, string selfNames) {
- InitializeUserType(context, name, bases, dict, selfNames);
- }
- internal PythonType() {
- }
- /// <summary>
- /// Creates a new PythonType object which is backed by the specified .NET type for
- /// storage. The type is considered a system type which can not be modified
- /// by the user.
- /// </summary>
- /// <param name="underlyingSystemType"></param>
- internal PythonType(Type underlyingSystemType) {
- _underlyingSystemType = underlyingSystemType;
- InitializeSystemType();
- }
- /// <summary>
- /// Creates a new PythonType which is a subclass of the specified PythonType.
- ///
- /// Used for runtime defined new-style classes which require multiple inheritance. The
- /// primary example of this is the exception system.
- /// </summary>
- internal PythonType(PythonType baseType, string name, Func<string, Exception> exceptionMaker) {
- _underlyingSystemType = baseType.UnderlyingSystemType;
- IsSystemType = baseType.IsSystemType;
- IsPythonType = baseType.IsPythonType;
- Name = name;
- _bases = new PythonType[] { baseType };
- ResolutionOrder = Mro.Calculate(this, _bases);
- _attrs |= PythonTypeAttributes.HasDictionary;
- _makeException = exceptionMaker;
- }
- /// <summary>
- /// Creates a new PythonType which is a subclass of the specified PythonTypes.
- ///
- /// Used for runtime defined new-style classes which require multiple inheritance. The
- /// primary example of this is the exception system.
- /// </summary>
- internal PythonType(PythonType[] baseTypes, string name) {
- bool isSystemType = false;
- bool isPythonType = false;
- foreach (PythonType baseType in baseTypes) {
- isSystemType |= baseType.IsSystemType;
- isPythonType |= baseType.IsPythonType;
- }
- IsSystemType = isSystemType;
- IsPythonType = isPythonType;
- Name = name;
- _bases = baseTypes;
- ResolutionOrder = Mro.Calculate(this, _bases);
- _attrs |= PythonTypeAttributes.HasDictionary;
- }
- /// <summary>
- /// Creates a new PythonType which is a subclass of the specified PythonTypes.
- ///
- /// Used for runtime defined new-style classes which require multiple inheritance. The
- /// primary example of this is the exception system.
- /// </summary>
- internal PythonType(PythonType[] baseTypes, Type underlyingType, string name, Func<string, Exception> exceptionMaker)
- : this(baseTypes, name) {
- _underlyingSystemType = underlyingType;
- _makeException = exceptionMaker;
- }
- /// <summary>
- /// Creates a new PythonType which is a subclass of the specified PythonType.
- ///
- /// Used for runtime defined new-style classes which require multiple inheritance. The
- /// primary example of this is the exception system.
- /// </summary>
- internal PythonType(PythonContext context, PythonType baseType, string name, string module, string doc, Func<string, Exception> exceptionMaker)
- : this(baseType, name, exceptionMaker) {
- EnsureDict();
- _dict["__doc__"] = new PythonTypeUserDescriptorSlot(doc, true);
- _dict["__module__"] = new PythonTypeUserDescriptorSlot(module, true);
- IsSystemType = false;
- IsPythonType = false;
- _pythonContext = context;
- _attrs |= PythonTypeAttributes.HasDictionary;
- }
- /// <summary>
- /// Creates a new PythonType which is a subclass of the specified PythonTypes.
- ///
- /// Used for runtime defined new-style classes which require multiple inheritance. The
- /// primary example of this is the exception system.
- /// </summary>
- internal PythonType(PythonContext context, PythonType[] baseTypes, string name, string module, string doc)
- : this(baseTypes, name) {
- EnsureDict();
- _dict["__doc__"] = new PythonTypeUserDescriptorSlot(doc, true);
- _dict["__module__"] = new PythonTypeUserDescriptorSlot(module, true);
- _pythonContext = context;
- _attrs |= PythonTypeAttributes.HasDictionary;
- }
- /// <summary>
- /// Creates a new PythonType which is a subclass of the specified PythonTypes.
- ///
- /// Used for runtime defined new-style classes which require multiple inheritance. The
- /// primary example of this is the exception system.
- /// </summary>
- internal PythonType(PythonContext context, PythonType[] baseTypes, Type underlyingType, string name, string module, string doc, Func<string, Exception> exceptionMaker)
- : this(baseTypes, underlyingType, name, exceptionMaker) {
- EnsureDict();
- _dict["__doc__"] = new PythonTypeUserDescriptorSlot(doc, true);
- _dict["__module__"] = new PythonTypeUserDescriptorSlot(module, true);
- IsSystemType = false;
- IsPythonType = false;
- _pythonContext = context;
- _attrs |= PythonTypeAttributes.HasDictionary;
- }
- /// <summary>
- /// Creates a new PythonType object which represents an Old-style class.
- /// </summary>
- internal PythonType(OldClass oc) {
- EnsureDict();
- _underlyingSystemType = typeof(OldInstance);
- Name = oc.Name;
- OldClass = oc;
- List<PythonType> ocs = new List<PythonType>(oc.BaseClasses.Count);
- foreach (OldClass klass in oc.BaseClasses) {
- ocs.Add(klass.TypeObject);
- }
- List<PythonType> mro = new List<PythonType>();
- mro.Add(this);
- _bases = ocs.ToArray();
- _resolutionOrder = mro;
- AddSlot("__class__", new PythonTypeUserDescriptorSlot(this, true));
- }
- internal BuiltinFunction Ctor {
- get {
- EnsureConstructor();
- return _ctor;
- }
- }
- #region Public API
- public static object __new__(CodeContext/*!*/ context, PythonType cls, string name, PythonTuple bases, PythonDictionary dict) {
- return __new__(context, cls, name, bases, dict, String.Empty);
- }
- internal static object __new__(CodeContext/*!*/ context, PythonType cls, string name, PythonTuple bases, PythonDictionary dict, string selfNames) {
- if (name == null) {
- throw PythonOps.TypeError("type() argument 1 must be string, not None");
- }
- if (bases == null) {
- throw PythonOps.TypeError("type() argument 2 must be tuple, not None");
- }
- if (dict == null) {
- throw PythonOps.TypeError("TypeError: type() argument 3 must be dict, not None");
- }
- EnsureModule(context, dict);
- PythonType meta = FindMetaClass(cls, bases);
- if (meta != TypeCache.OldInstance && meta != TypeCache.PythonType) {
- if (meta != cls) {
- // the user has a custom __new__ which picked the wrong meta class, call the correct metaclass
- return PythonCalls.Call(context, meta, name, bases, dict);
- }
- // we have the right user __new__, call our ctor method which will do the actual
- // creation.
- return meta.CreateInstance(context, name, bases, dict);
- }
- // no custom user type for __new__
- return new PythonType(context, name, bases, dict, selfNames);
- }
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
- public void __init__(string name, PythonTuple bases, PythonDictionary dict) {
- }
- internal static PythonType FindMetaClass(PythonType cls, PythonTuple bases) {
- PythonType meta = cls;
- foreach (object dt in bases) {
- PythonType metaCls = DynamicHelpers.GetPythonType(dt);
- if (metaCls == TypeCache.OldClass) continue;
- if (meta.IsSubclassOf(metaCls)) continue;
- if (metaCls.IsSubclassOf(meta)) {
- meta = metaCls;
- continue;
- }
- throw PythonOps.TypeError("Error when calling the metaclass bases\n metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases");
- }
- return meta;
- }
- public static object __new__(CodeContext/*!*/ context, object cls, object o) {
- return DynamicHelpers.GetPythonType(o);
- }
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
- public void __init__(object o) {
- }
- [SpecialName, PropertyMethod, WrapperDescriptor]
- public static PythonTuple Get__bases__(CodeContext/*!*/ context, PythonType/*!*/ type) {
- return type.GetBasesTuple();
- }
- private PythonTuple GetBasesTuple() {
- object[] res = new object[BaseTypes.Count];
- IList<PythonType> bases = BaseTypes;
- for (int i = 0; i < bases.Count; i++) {
- PythonType baseType = bases[i];
- if (baseType.IsOldClass) {
- res[i] = baseType.OldClass;
- } else {
- res[i] = baseType;
- }
- }
- return PythonTuple.MakeTuple(res);
- }
- [SpecialName, PropertyMethod, WrapperDescriptor]
- public static PythonType Get__base__(CodeContext/*!*/ context, PythonType/*!*/ type) {
- foreach (object typeObj in Get__bases__(context, type)) {
- PythonType pt = typeObj as PythonType;
- if (pt != null) {
- return pt;
- }
- }
- return null;
- }
- /// <summary>
- /// Used in copy_reg which is the only consumer of __flags__ in the standard library.
- ///
- /// Set if the type is user defined
- /// </summary>
- private const int TypeFlagHeapType = 0x00000200;
- /// <summary>
- /// Set if the type has __abstractmethods__ defined
- /// </summary>
- private const int TypeFlagAbstractMethodsDefined = 0x00080000;
- private const int TypeFlagAbstractMethodsNonEmpty = 0x00100000;
- private bool SetAbstractMethodFlags(string name, object value) {
- if (name != "__abstractmethods__") {
- return false;
- }
- int res = _flags | TypeFlagAbstractMethodsDefined;
- IEnumerator enumerator;
- if (value == null ||
- !PythonOps.TryGetEnumerator(DefaultContext.Default, value, out enumerator) ||
- !enumerator.MoveNext()) {
- // CPython treats None, non-iterables, and empty iterables as empty sets
- // of abstract methods, and sets this flag accordingly
- res &= ~(TypeFlagAbstractMethodsNonEmpty);
- } else {
- res |= TypeFlagAbstractMethodsNonEmpty;
- }
- _flags = res;
- return true;
- }
- /// <summary>
- /// Check whether the current type is iterabel
- /// </summary>
- /// <param name="context"></param>
- /// <returns>True if it is iterable</returns>
- internal bool IsIterable(CodeContext context)
- {
- object _dummy = null;
- if (PythonOps.TryGetBoundAttr(context, this, "__iter__", out _dummy) &&
- !Object.ReferenceEquals(_dummy, NotImplementedType.Value)
- && PythonOps.TryGetBoundAttr(context, this, "next", out _dummy) &&
- !Object.ReferenceEquals(_dummy, NotImplementedType.Value))
- {
- return true;
- }
- return false;
- }
- private void ClearAbstractMethodFlags(string name) {
- if (name == "__abstractmethods__") {
- _flags &= ~(TypeFlagAbstractMethodsDefined | TypeFlagAbstractMethodsNonEmpty);
- }
- }
- internal bool HasAbstractMethods(CodeContext/*!*/ context) {
- object abstractMethods;
- IEnumerator en;
- return (_flags & TypeFlagAbstractMethodsNonEmpty) != 0 &&
- TryGetBoundCustomMember(context, "__abstractmethods__", out abstractMethods) &&
- PythonOps.TryGetEnumerator(context, abstractMethods, out en) &&
- en.MoveNext();
- }
- internal string GetAbstractErrorMessage(CodeContext/*!*/ context) {
- if ((_flags & TypeFlagAbstractMethodsNonEmpty) == 0) {
- return null;
- }
- object abstractMethods;
- IEnumerator en;
- if (!TryGetBoundCustomMember(context, "__abstractmethods__", out abstractMethods) ||
- !PythonOps.TryGetEnumerator(context, abstractMethods, out en) ||
- !en.MoveNext()) {
- return null;
- }
- string comma = "";
- StringBuilder error = new StringBuilder("Can't instantiate abstract class ");
- error.Append(Name);
- error.Append(" with abstract methods ");
- int i = 0;
- do {
- string s = en.Current as string;
- if (s == null) {
- Extensible<string> es = en.Current as Extensible<string>;
- if (es != null) {
- s = es.Value;
- }
- }
- if (s == null) {
- return string.Format(
- "sequence item {0}: expected string, {1} found",
- i, PythonTypeOps.GetName(en.Current)
- );
- }
- error.Append(comma);
- error.Append(en.Current);
- comma = ", ";
- i++;
- } while (en.MoveNext());
- return error.ToString();
- }
- [SpecialName, PropertyMethod, WrapperDescriptor]
- public static int Get__flags__(CodeContext/*!*/ context, PythonType/*!*/ type) {
- int res = type._flags;
- if (type.IsSystemType) {
- res |= TypeFlagHeapType;
- }
- return res;
- }
- [SpecialName, PropertyMethod, WrapperDescriptor]
- public static void Set__bases__(CodeContext/*!*/ context, PythonType/*!*/ type, object value) {
- // validate we got a tuple...
- PythonTuple t = value as PythonTuple;
- if (t == null) throw PythonOps.TypeError("expected tuple of types or old-classes, got '{0}'", PythonTypeOps.GetName(value));
- List<PythonType> ldt = new List<PythonType>();
- foreach (object o in t) {
- // gather all the type objects...
- PythonType adt = o as PythonType;
- if (adt == null) {
- OldClass oc = o as OldClass;
- if (oc == null) {
- throw PythonOps.TypeError("expected tuple of types, got '{0}'", PythonTypeOps.GetName(o));
- }
- adt = oc.TypeObject;
- }
- ldt.Add(adt);
- }
- #if FEATURE_REFEMIT
- // Ensure that we are not switching the CLI type
- Type newType = NewTypeMaker.GetNewType(type.Name, t);
- if (type.UnderlyingSystemType != newType)
- throw PythonOps.TypeErrorForIncompatibleObjectLayout("__bases__ assignment", type, newType);
- #endif
- // set bases & the new resolution order
- List<PythonType> mro = CalculateMro(type, ldt);
- type.BaseTypes = ldt;
- type._resolutionOrder = mro;
- }
- private static List<PythonType> CalculateMro(PythonType type, IList<PythonType> ldt) {
- return Mro.Calculate(type, ldt);
- }
- private static bool TryReplaceExtensibleWithBase(Type curType, out Type newType) {
- if (curType.GetTypeInfo().IsGenericType &&
- curType.GetGenericTypeDefinition() == typeof(Extensible<>)) {
- newType = curType.GetGenericArguments()[0];
- return true;
- }
- newType = null;
- return false;
- }
- public object __call__(CodeContext context, params object[] args) {
- return PythonTypeOps.CallParams(context, this, args);
- }
- public object __call__(CodeContext context, [ParamDictionary]IDictionary<string, object> kwArgs, params object[] args) {
- return PythonTypeOps.CallWorker(context, this, kwArgs, args);
- }
- public int __cmp__([NotNull]PythonType other) {
- if (other != this) {
- int res = Name.CompareTo(other.Name);
- if (res == 0) {
- long thisId = IdDispenser.GetId(this);
- long otherId = IdDispenser.GetId(other);
- if (thisId > otherId) {
- return 1;
- } else {
- return -1;
- }
- }
- return res;
- }
- return 0;
- }
- // Do not override == and != because it causes lots of spurious warnings
- // TODO Replace those warnings with .ReferenceEquals calls & overload ==/!=
- public bool __eq__([NotNull]PythonType other) {
- return this.__cmp__(other) == 0;
- }
- public bool __ne__([NotNull]PythonType other) {
- return this.__cmp__(other) != 0;
- }
- [Python3Warning("type inequality comparisons not supported in 3.x")]
- public static bool operator >(PythonType self, PythonType other) {
- return self.__cmp__(other) > 0;
- }
- [Python3Warning("type inequality comparisons not supported in 3.x")]
- public static bool operator <(PythonType self, PythonType other) {
- return self.__cmp__(other) < 0;
- }
- [Python3Warning("type inequality comparisons not supported in 3.x")]
- public static bool operator >=(PythonType self, PythonType other) {
- return self.__cmp__(other) >= 0;
- }
- [Python3Warning("type inequality comparisons not supported in 3.x")]
- public static bool operator <=(PythonType self, PythonType other) {
- return self.__cmp__(other) <= 0;
- }
- public void __delattr__(CodeContext/*!*/ context, string name) {
- DeleteCustomMember(context, name);
- }
- [SlotField]
- public static PythonTypeSlot __dict__ = new PythonTypeDictSlot(_pythonTypeType);
- [SpecialName, PropertyMethod, WrapperDescriptor]
- public static object Get__doc__(CodeContext/*!*/ context, PythonType self) {
- PythonTypeSlot pts;
- object res;
- if (self.TryLookupSlot(context, "__doc__", out pts) &&
- pts.TryGetValue(context, null, self, out res)) {
- return res;
- } else if (self.IsSystemType) {
- return PythonTypeOps.GetDocumentation(self.UnderlyingSystemType);
- }
- return null;
- }
- public object __getattribute__(CodeContext/*!*/ context, string name) {
- object value;
- if (TryGetBoundCustomMember(context, name, out value)) {
- return value;
- }
- throw PythonOps.AttributeError("type object '{0}' has no attribute '{1}'", Name, name);
- }
- public PythonType this[params Type[] args] {
- get {
- if (UnderlyingSystemType == typeof(Array)) {
- if (args.Length == 1) {
- return DynamicHelpers.GetPythonTypeFromType(args[0].MakeArrayType());
- }
- throw PythonOps.TypeError("expected one argument to make array type, got {0}", args.Length);
- }
- if (!UnderlyingSystemType.IsGenericTypeDefinition()) {
- throw new InvalidOperationException("MakeGenericType on non-generic type");
- }
- return DynamicHelpers.GetPythonTypeFromType(UnderlyingSystemType.MakeGenericType(args));
- }
- }
- [SpecialName, PropertyMethod, WrapperDescriptor]
- public static object Get__module__(CodeContext/*!*/ context, PythonType self) {
- PythonTypeSlot pts;
- object res;
- if (self._dict != null &&
- self._dict.TryGetValue("__module__", out pts) &&
- pts.TryGetValue(context, self, DynamicHelpers.GetPythonType(self), out res)) {
- return res;
- }
- return PythonTypeOps.GetModuleName(context, self.UnderlyingSystemType);
- }
- [SpecialName, PropertyMethod, WrapperDescriptor, PythonHidden]
- public static string Get__clr_assembly__(PythonType self) {
- return self.UnderlyingSystemType.Namespace + " in " + self.UnderlyingSystemType.GetTypeInfo().Assembly.FullName;
- }
- [SpecialName, PropertyMethod, WrapperDescriptor]
- public static void Set__module__(CodeContext/*!*/ context, PythonType self, object value) {
- if (self.IsSystemType) {
- throw PythonOps.TypeError("can't set {0}.__module__", self.Name);
- }
- Debug.Assert(self._dict != null);
- self._dict["__module__"] = new PythonTypeUserDescriptorSlot(value);
- self.UpdateVersion();
- }
- [SpecialName, PropertyMethod, WrapperDescriptor]
- public static void Delete__module__(CodeContext/*!*/ context, PythonType self) {
- throw PythonOps.TypeError("can't delete {0}.__module__", self.Name);
- }
- [SpecialName, PropertyMethod, WrapperDescriptor]
- public static PythonTuple Get__mro__(PythonType type) {
- return PythonTypeOps.MroToPython(type.ResolutionOrder);
- }
- [SpecialName, PropertyMethod, WrapperDescriptor]
- public static string Get__name__(PythonType type) {
- return type.Name;
- }
- [SpecialName, PropertyMethod, WrapperDescriptor]
- public static void Set__name__(PythonType type, string name) {
- if (type.IsSystemType) {
- throw PythonOps.TypeError("can't set attributes of built-in/extension type '{0}'", type.Name);
- }
- type.Name = name;
- }
- public string/*!*/ __repr__(CodeContext/*!*/ context) {
- string name = Name;
- if (IsSystemType) {
- if (PythonTypeOps.IsRuntimeAssembly(UnderlyingSystemType.GetTypeInfo().Assembly) || IsPythonType) {
- object module = Get__module__(context, this);
- if (!module.Equals("__builtin__")) {
- return string.Format("<type '{0}.{1}'>", module, Name);
- }
- }
- return string.Format("<type '{0}'>", Name);
- } else {
- PythonTypeSlot dts;
- string module = "unknown";
- object modObj;
- if (TryLookupSlot(context, "__module__", out dts) &&
- dts.TryGetValue(context, this, this, out modObj)) {
- module = modObj as string;
- }
- return string.Format("<class '{0}.{1}'>", module, name);
- }
- }
- internal string/*!*/ GetTypeDebuggerDisplay() {
- PythonTypeSlot dts;
- string module = "unknown";
- object modObj;
- if (TryLookupSlot(Context.SharedContext, "__module__", out dts) &&
- dts.TryGetValue(Context.SharedContext, this, this, out modObj)) {
- module = modObj as string;
- }
- return string.Format("{0}.{1} instance", module, Name);
- }
- public void __setattr__(CodeContext/*!*/ context, string name, object value) {
- SetCustomMember(context, name, value);
- }
- public List __subclasses__(CodeContext/*!*/ context) {
- List ret = new List();
- IList<WeakReference> subtypes = SubTypes;
- if (subtypes != null) {
- PythonContext pc = PythonContext.GetContext(context);
- foreach (WeakReference wr in subtypes) {
- if (wr.IsAlive) {
- PythonType pt = (PythonType)wr.Target;
- if (pt.PythonContext == null || pt.PythonContext == pc) {
- ret.AddNoLock(wr.Target);
- }
- }
- }
- }
- return ret;
- }
- public virtual List mro() {
- return new List(Get__mro__(this));
- }
- /// <summary>
- /// Returns true if the specified object is an instance of this type.
- /// </summary>
- public virtual bool __instancecheck__(object instance) {
- return SubclassImpl(DynamicHelpers.GetPythonType(instance));
- }
- public virtual bool __subclasscheck__(PythonType sub) {
- return SubclassImpl(sub);
- }
- private bool SubclassImpl(PythonType sub) {
- if (UnderlyingSystemType.IsInterface()) {
- // interfaces aren't in bases, and therefore IsSubclassOf doesn't do this check.
- if (UnderlyingSystemType.IsAssignableFrom(sub.UnderlyingSystemType)) {
- return true;
- }
- }
- return sub.IsSubclassOf(this);
- }
- public virtual bool __subclasscheck__(OldClass sub) {
- return IsSubclassOf(sub.TypeObject);
- }
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates")]
- public static implicit operator Type(PythonType self) {
- return self.UnderlyingSystemType;
- }
- public static implicit operator TypeTracker(PythonType self) {
- return ReflectionCache.GetTypeTracker(self.UnderlyingSystemType);
- }
- #endregion
- #region Internal API
- internal bool IsMixedNewStyleOldStyle() {
- if (!IsOldClass) {
- foreach (PythonType baseType in ResolutionOrder) {
- if (baseType.IsOldClass) {
- // mixed new-style/old-style class, we can't handle
- // __init__ in an old-style class yet (it doesn't show
- // up in a slot).
- return true;
- }
- }
- }
- return false;
- }
- internal int SlotCount {
- get {
- return _originalSlotCount;
- }
- }
- /// <summary>
- /// Gets the name of the dynamic type
- /// </summary>
- internal string Name {
- get {
- return _name;
- }
- set {
- _name = value;
- }
- }
- internal int Version {
- get {
- return _version;
- }
- }
- internal bool IsNull {
- get {
- return UnderlyingSystemType == typeof(DynamicNull);
- }
- }
- /// <summary>
- /// Gets the resolution order used for attribute lookup
- /// </summary>
- internal IList<PythonType> ResolutionOrder {
- get {
- return _resolutionOrder;
- }
- set {
- lock (SyncRoot) {
- _resolutionOrder = new List<PythonType>(value);
- }
- }
- }
- /// <summary>
- /// Gets the dynamic type that corresponds with the provided static type.
- ///
- /// Returns null if no type is available. TODO: In the future this will
- /// always return a PythonType created by the DLR.
- /// </summary>
- /// <param name="type"></param>
- /// <returns></returns>
- internal static PythonType/*!*/ GetPythonType(Type type) {
- object res;
-
- if (!_pythonTypes.TryGetValue(type, out res)) {
- lock (_pythonTypes) {
- if (!_pythonTypes.TryGetValue(type, out res)) {
- res = new PythonType(type);
- _pythonTypes.Add(type, res);
- }
- }
- }
- return (PythonType)res;
- }
- /// <summary>
- /// Sets the python type that corresponds with the provided static type.
- ///
- /// This is used for built-in types which have a metaclass. Currently
- /// only used by ctypes.
- /// </summary>
- internal static PythonType SetPythonType(Type type, PythonType pyType) {
- lock (_pythonTypes) {
- Debug.Assert(!_pythonTypes.Contains(type));
- Debug.Assert(pyType.GetType() != typeof(PythonType));
- _pythonTypes.Add(type, pyType);
- }
- return pyType;
- }
- /// <summary>
- /// Allocates the storage for the instance running the .NET constructor. This provides
- /// the creation functionality for __new__ implementations.
- /// </summary>
- internal object CreateInstance(CodeContext/*!*/ context) {
- EnsureInstanceCtor();
- return _instanceCtor.CreateInstance(context);
- }
- /// <summary>
- /// Allocates the storage for the instance running the .NET constructor. This provides
- /// the creation functionality for __new__ implementations.
- /// </summary>
- internal object CreateInstance(CodeContext/*!*/ context, object arg0) {
- EnsureInstanceCtor();
- return _instanceCtor.CreateInstance(context, arg0);
- }
- /// <summary>
- /// Allocates the storage for the instance running the .NET constructor. This provides
- /// the creation functionality for __new__ implementations.
- /// </summary>
- internal object CreateInstance(CodeContext/*!*/ context, object arg0, object arg1) {
- EnsureInstanceCtor();
- return _instanceCtor.CreateInstance(context, arg0, arg1);
- }
- /// <summary>
- /// Allocates the storage for the instance running the .NET constructor. This provides
- /// the creation functionality for __new__ implementations.
- /// </summary>
- internal object CreateInstance(CodeContext/*!*/ context, object arg0, object arg1, object arg2) {
- EnsureInstanceCtor();
- return _instanceCtor.CreateInstance(context, arg0, arg1, arg2);
- }
- /// <summary>
- /// Allocates the storage for the instance running the .NET constructor. This provides
- /// the creation functionality for __new__ implementations.
- /// </summary>
- internal object CreateInstance(CodeContext context, params object[] args) {
- Assert.NotNull(args);
- EnsureInstanceCtor();
- // unpack args for common cases so we don't generate code to do it...
- switch (args.Length) {
- case 0: return _instanceCtor.CreateInstance(context);
- case 1: return _instanceCtor.CreateInstance(context, args[0]);
- case 2: return _instanceCtor.CreateInstance(context, args[0], args[1]);
- case 3: return _instanceCtor.CreateInstance(context, args[0], args[1], args[2]);
- default:
- return _instanceCtor.CreateInstance(context, args);
- }
- }
- /// <summary>
- /// Allocates the storage for the instance running the .NET constructor. This provides
- /// the creation functionality for __new__ implementations.
- /// </summary>
- internal object CreateInstance(CodeContext context, object[] args, string[] names) {
- Assert.NotNull(args, "args");
- Assert.NotNull(names, "names");
- EnsureInstanceCtor();
- return _instanceCtor.CreateInstance(context, args, names);
- }
- internal int Hash(object o) {
- EnsureHashSite();
- return _hashSite.Target(_hashSite, o);
- }
- internal bool TryGetLength(CodeContext context, object o, out int length) {
- CallSite<Func<CallSite, CodeContext, object, object>> lenSite;
- if (IsSystemType) {
- lenSite = PythonContext.GetContext(context).GetSiteCacheForSystemType(UnderlyingSystemType).GetLenSite(context);
- } else {
- lenSite = _siteCache.GetLenSite(context);
- }
- PythonTypeSlot lenSlot = _lenSlot;
- if (lenSlot == null && !PythonOps.TryResolveTypeSlot(context, this, "__len__", out lenSlot)) {
- length = 0;
- return false;
- }
- object func;
- if (!lenSlot.TryGetValue(context, o, this, out func)) {
- length = 0;
- return false;
- }
- object res = lenSite.Target(lenSite, context, func);
- if (!(res is int)) {
- throw PythonOps.ValueError("__len__ must return int");
- }
- length = (int)res;
- return true;
- }
- internal bool EqualRetBool(object self, object other) {
- if (_eqSite == null) {
- Interlocked.CompareExchange(
- ref _eqSite,
- Context.CreateComparisonSite(PythonOperationKind.Equal),
- null
- );
- }
- return _eqSite.Target(_eqSite, self, other);
- }
- internal int Compare(object self, object other) {
- if (_compareSite == null) {
- Interlocked.CompareExchange(
- ref _compareSite,
- Context.MakeSortCompareSite(),
- null
- );
- }
- return _compareSite.Target(_compareSite, self, other);
- }
- internal bool TryGetBoundAttr(CodeContext context, object o, string name, out object ret) {
- CallSite<Func<CallSite, object, CodeContext, object>> site;
- if (IsSystemType) {
- site = PythonContext.GetContext(context).GetSiteCacheForSystemType(UnderlyingSystemType).GetTryGetMemberSite(context, name);
- } else {
- site = _siteCache.GetTryGetMemberSite(context, name);
- }
- try {
- ret = site.Target(site, o, context);
- return ret != OperationFailed.Value;
- } catch (MissingMemberException) {
- ret = null;
- return false;
- }
- }
- internal CallSite<Func<CallSite, object, int>> HashSite {
- get {
- EnsureHashSite();
- return _hashSite;
- }
- }
- private void EnsureHashSite() {
- if(_hashSite == null) {
- Interlocked.CompareExchange(
- ref _hashSite,
- CallSite<Func<CallSite, object, int>>.Create(
- Context.Operation(
- PythonOperationKind.Hash
- )
- ),
- null
- );
- }
- }
- /// <summary>
- /// Gets the underlying system type that is backing this type. All instances of this
- /// type are an instance of the underlying system type.
- /// </summary>
- internal Type/*!*/ UnderlyingSystemType {
- get {
- return _underlyingSystemType;
- }
- }
- internal Type/*!*/ FinalSystemType {
- get {
- return _finalSystemType ?? (_finalSystemType = PythonTypeOps.GetFinalSystemType(_underlyingSystemType));
- }
- }
- /// <summary>
- /// Gets the extension type for this type. The extension type provides
- /// a .NET type which can be inherited from to extend sealed classes
- /// or value types which Python allows inheritance from.
- /// </summary>
- internal Type/*!*/ ExtensionType {
- get {
- if (!_underlyingSystemType.IsEnum()) {
- switch (_underlyingSystemType.GetTypeCode()) {
- case TypeCode.String: return typeof(ExtensibleString);
- case TypeCode.Int32: return typeof(Extensible<int>);
- case TypeCode.Double: return typeof(Extensible<double>);
- case TypeCode.Object:
- if (_underlyingSystemType == typeof(BigInteger)) {
- return typeof(Extensible<BigInteger>);
- } else if (_underlyingSystemType == typeof(Complex)) {
- return typeof(ExtensibleComplex);
- }
- break;
- }
- }
- return _underlyingSystemType;
- }
- }
- /// <summary>
- /// Gets the base types from which this type inherits.
- /// </summary>
- internal IList<PythonType>/*!*/ BaseTypes {
- get {
- return _bases;
- }
- set {
- // validate input...
- foreach (PythonType pt in value) {
- if (pt == null) throw new ArgumentNullException("value", "a PythonType was null while assigning base classes");
- }
- // first update our sub-type list
- lock (_bases) {
- foreach (PythonType dt in _bases) {
- dt.RemoveSubType(this);
- }
- // set the new bases
- List<PythonType> newBases = new List<PythonType>(value);
- // add us as subtypes of our new bases
- foreach (PythonType dt in newBases) {
- dt.AddSubType(this);
- }
- UpdateVersion();
- _bases = newBases.ToArray();
- }
- }
- }
- /// <summary>
- /// Returns true if this type is a subclass of other
- /// </summary>
- internal bool IsSubclassOf(PythonType other) {
- // check for a type match
- if (other == this) {
- return true;
- }
- //Python doesn't have value types inheriting from ValueType, but we fake this for interop
- if (other.UnderlyingSystemType == typeof(ValueType) && UnderlyingSystemType.IsValueType()) {
- return true;
- }
- return IsSubclassWorker(other);
- }
- private bool IsSubclassWorker(PythonType other) {
- for (int i = 0; i < _bases.Length; i++) {
- PythonType baseClass = _bases[i];
- if (baseClass == other || baseClass.IsSubclassWorker(other)) {
- return true;
- }
- }
- return false;
- }
- /// <summary>
- /// True if the type is a system type. A system type is a type which represents an
- /// underlying .NET type and not a subtype of one of these types.
- /// </summary>
- internal bool IsSystemType {
- get {
- return (_attrs & PythonTypeAttributes.SystemType) != 0;
- }
- set {
- if (value) _attrs |= PythonTypeAttributes.SystemType;
- else _attrs &= (~PythonTypeAttributes.SystemType);
- }
- }
- internal bool IsWeakReferencable {
- get {
- return (_attrs & PythonTypeAttributes.WeakReferencable) != 0;
- }
- set {
- if (value) _attrs |= PythonTypeAttributes.WeakReferencable;
- else _attrs &= (~PythonTypeAttributes.WeakReferencable);
- }
- }
- internal bool HasDictionary {
- get {
- return (_attrs & PythonTypeAttributes.HasDictionary) != 0;
- }
- set {
- if (value) _attrs |= PythonTypeAttributes.HasDictionary;
- else _attrs &= (~PythonTypeAttributes.HasDictionary);
- }
- }
- internal bool HasSystemCtor {
- get {
- return (_attrs & PythonTypeAttributes.SystemCtor) != 0;
- }
- }
- internal void SetConstructor(BuiltinFunction ctor) {
- _ctor = ctor;
- }
- internal bool IsPythonType {
- get {
- return (_attrs & PythonTypeAttributes.IsPythonType) != 0;
- }
- set {
- if (value) {
- _attrs |= PythonTypeAttributes.IsPythonType;
- } else {
- _attrs &= ~PythonTypeAttributes.IsPythonType;
- }
- }
- }
- internal OldClass OldClass {
- get {
- return _oldClass;
- }
- set {
- _oldClass = value;
- }
- }
- internal bool IsOldClass {
- get {
- return _oldClass != null;
- }
- }
- …
Large files files are truncated, but you can click here to view the full file