diff --git a/Src/IronPython/Runtime/Types/PythonType.cs b/Src/IronPython/Runtime/Types/PythonType.cs index 262a45352..e47ffe4ba 100644 --- a/Src/IronPython/Runtime/Types/PythonType.cs +++ b/Src/IronPython/Runtime/Types/PythonType.cs @@ -76,7 +76,6 @@ public partial class PythonType : IPythonMembersList, IDynamicMetaObjectProvider [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 DefaultMakeException = (message, innerException) => new Exception(message, innerException); @@ -514,7 +513,7 @@ public void __delattr__(CodeContext/*!*/ context, string name) { } [SlotField] - public static PythonTypeSlot __dict__ = new PythonTypeDictSlot(_pythonTypeType); + public static PythonTypeSlot __dict__ = new PythonTypeDictSlot(TypeCache.PythonType); [SpecialName, PropertyMethod, WrapperDescriptor] public static object Get__doc__(CodeContext/*!*/ context, PythonType self) { @@ -1314,16 +1313,18 @@ internal void SetCustomMember(CodeContext/*!*/ context, string name, object valu Debug.Assert(context != null); PythonTypeSlot dts; - if (TryResolveSlot(context, name, out dts)) { - if (dts.TrySetValue(context, null, this, value)) { - return; - } + if (TryResolveSlot(context, name, out dts) && dts.TrySetValue(context, null, this, value)) { + return; } - if (PythonType._pythonTypeType.TryResolveSlot(context, name, out dts)) { - if (dts.TrySetValue(context, this, PythonType._pythonTypeType, value)) { - return; - } + // search the type + var myType = DynamicHelpers.GetPythonType(this); + if (myType.TryResolveSlot(context, name, out dts) && dts.TrySetValue(context, this, myType, value)) { + return; + } + + if (myType != TypeCache.PythonType && TypeCache.PythonType.TryResolveSlot(context, name, out dts) && dts.TrySetValue(context, this, TypeCache.PythonType, value)) { + return; } if (IsSystemType) { diff --git a/Tests/test_metaclass.py b/Tests/test_metaclass.py index 4137ef254..0d250d4a6 100644 --- a/Tests/test_metaclass.py +++ b/Tests/test_metaclass.py @@ -652,4 +652,23 @@ class XM2(C2_C1, C5, metaclass=metafactory(type)): self.assertEqual(flags['MetaClass.__init__'], 0) # !!! self.assertEqual(XM2.meta_func, "processed by function meta(XM2, ...) using metabase ") + def test_setter_on_metaclass(self): + """https://github.com/IronLanguages/ironpython3/issues/1208""" + class MetaClass(type): + @property + def test(self): + return 1 + + @test.setter + def test(self, value): + raise Exception + + class Generic(metaclass=MetaClass): + pass + + self.assertEqual(Generic.test, 1) + + with self.assertRaises(Exception): + Generic.test = 2 + run_test(__name__)