Skip to content

Commit

Permalink
Merge branch 'pr/tested/1-newtypes_no-pure-interface' into master-rhi…
Browse files Browse the repository at this point in the history
…no-8.x
  • Loading branch information
eirannejad committed May 15, 2024
2 parents 0c7c3c7 + 2914f98 commit 8dd081a
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 1 deletion.
45 changes: 44 additions & 1 deletion src/runtime/Types/InterfaceObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ public static NewReference tp_getattro(BorrowedReference ob, BorrowedReference k
Exceptions.Clear();

using var pyObj = Converter.ToPython(clrObj.inst);
return Runtime.PyObject_GenericGetAttr(pyObj.Borrow(), key);
var get = Runtime.PyObject_GenericGetAttr(pyObj.Borrow(), key);
return get;
}
return value;
}
Expand All @@ -137,6 +138,48 @@ public static NewReference tp_getattro(BorrowedReference ob, BorrowedReference k
return Runtime.PyObject_GenericGetAttr(ob, key);
}

public static int tp_setattro(BorrowedReference ob, BorrowedReference key, BorrowedReference value)
{
var clrObj = (CLRObject)GetManagedObject(ob)!;

if (!Runtime.PyString_Check(key))
{
Exceptions.RaiseTypeError("string expected");
return -1;
}

string? name = Runtime.GetManagedString(key);
if (name != null)
{
if (name == "__implementation__"
|| name == "__raw_implementation__")
{
Exceptions.SetError(Exceptions.AttributeError, "attribute is read-only");
return -1;
}
else
{
// try set attr to wrapped object first we we do not
// add attributes to the object dictionary
using var pyObj = Converter.ToPython(clrObj.inst);
int res = Runtime.PyObject_GenericSetAttr(pyObj.Borrow(), key, value);
if (Exceptions.ErrorOccurred())
{
// if that didn't work, clear errors
// and try set to pure interface wrapper
Exceptions.Clear();

return Runtime.PyObject_GenericSetAttr(ob, key, value);
}
return res;
}
}


return Runtime.PyObject_GenericSetAttr(ob, key, value);
}


protected override void OnDeserialization(object sender)
{
base.OnDeserialization(sender);
Expand Down
25 changes: 25 additions & 0 deletions src/testing/interfacetest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ public static int CallMyMethod_Out(IOutArg myInterface)
}
}


public interface IGenericInterface<T>
{
public T Get(T x);
Expand All @@ -114,4 +115,28 @@ public GenericInterfaceUser(IGenericInterface<T> some, T x)
some.Get(x);
}
}

public interface IGetSetTest
{
public bool Value { get; set; }
}

public class GetSetInterfacePropsTest : IGetSetTest
{
public bool ValueNotInInterfaceTest = false;

public bool Value
{
get => ValueNotInInterfaceTest;
set => ValueNotInInterfaceTest = value;
}

public bool PropertyNotInInterfaceTest = false;

public bool PropertyNotInInterface
{
get => PropertyNotInInterfaceTest;
set => PropertyNotInInterfaceTest = value;
}
}
}
23 changes: 23 additions & 0 deletions tests/test_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,26 @@ def test_methods_of_Object_are_available():
assert clrVal.GetHashCode() == i.GetHashCode()
assert clrVal.GetType() == i.GetType()
assert clrVal.ToString() == i.ToString()


def test_interface_getset_can_set_interface_property():
# tests an interface instance can set properties
# on the wrapped object if they are not part of interface

from Python.Test import GetSetInterfacePropsTest

ob = GetSetInterfacePropsTest()
ob.Value = True

assert ob.ValueNotInInterfaceTest == True

def test_interface_getset_can_set_wrapped_object_property():
# tests an interface instance can set properties
# on the wrapped object if they are not part of interface

from Python.Test import GetSetInterfacePropsTest

ob = GetSetInterfacePropsTest()
ob.PropertyNotInInterface = True

assert ob.PropertyNotInInterfaceTest == True

0 comments on commit 8dd081a

Please sign in to comment.