From e4acab2f77288c3ad6238e752ffc8ad84ab05126 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lozier?= Date: Sat, 8 May 2021 11:22:51 -0400 Subject: [PATCH 1/2] Fix setter on metaclass --- Src/IronPython/Runtime/Types/PythonType.cs | 6 ++++++ Tests/test_metaclass.py | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/Src/IronPython/Runtime/Types/PythonType.cs b/Src/IronPython/Runtime/Types/PythonType.cs index 262a45352..30d68f2b3 100644 --- a/Src/IronPython/Runtime/Types/PythonType.cs +++ b/Src/IronPython/Runtime/Types/PythonType.cs @@ -1320,6 +1320,12 @@ internal void SetCustomMember(CodeContext/*!*/ context, string name, object valu } } + // search the type + var myType = DynamicHelpers.GetPythonType(this); + if (myType.TryResolveSlot(context, name, out dts) && dts.TrySetValue(context, this, myType, value)) { + return; + } + if (PythonType._pythonTypeType.TryResolveSlot(context, name, out dts)) { if (dts.TrySetValue(context, this, PythonType._pythonTypeType, value)) { return; 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__) From b43febe8ad6da09b1784b24bdab601b202f6e37a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lozier?= Date: Sat, 8 May 2021 11:23:17 -0400 Subject: [PATCH 2/2] Code cleanup --- Src/IronPython/Runtime/Types/PythonType.cs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/Src/IronPython/Runtime/Types/PythonType.cs b/Src/IronPython/Runtime/Types/PythonType.cs index 30d68f2b3..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,10 +1313,8 @@ 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; } // search the type @@ -1326,10 +1323,8 @@ internal void SetCustomMember(CodeContext/*!*/ context, string name, object valu return; } - if (PythonType._pythonTypeType.TryResolveSlot(context, name, out dts)) { - if (dts.TrySetValue(context, this, PythonType._pythonTypeType, value)) { - return; - } + if (myType != TypeCache.PythonType && TypeCache.PythonType.TryResolveSlot(context, name, out dts) && dts.TrySetValue(context, this, TypeCache.PythonType, value)) { + return; } if (IsSystemType) {