Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions Src/IronPython/Runtime/Types/PythonType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, Exception, Exception> DefaultMakeException = (message, innerException) => new Exception(message, innerException);
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down
19 changes: 19 additions & 0 deletions Tests/test_metaclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 <class 'type'>")

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__)