@@ -1096,6 +1096,67 @@ def GetValue(self, fixture):
10961096 }
10971097 }
10981098
1099+ public class CSharpTestClass
1100+ {
1101+ public string CSharpProperty { get ; set ; }
1102+ }
1103+
1104+ [ Test ]
1105+ public void TestKeepsPythonReferenceForDynamicPropertiesFromPythonClassDerivedFromCSharpClass ( )
1106+ {
1107+ var expectedCSharpPropertyValue = "C# property" ;
1108+ var expectedPythonPropertyValue = "Python property" ;
1109+
1110+ var testModule = PyModule . FromString ( "module" , $@ "
1111+ from clr import AddReference
1112+ AddReference(""Python.EmbeddingTest"")
1113+ AddReference(""System"")
1114+
1115+ from Python.EmbeddingTest import TestPropertyAccess
1116+
1117+ class PythonTestClass(TestPropertyAccess.CSharpTestClass):
1118+ def __init__(self):
1119+ super().__init__()
1120+
1121+ def SetPythonObjectToFixture(fixture: TestPropertyAccess.DynamicFixture) -> None:
1122+ obj = PythonTestClass()
1123+ obj.CSharpProperty = '{ expectedCSharpPropertyValue } '
1124+ obj.PythonProperty = '{ expectedPythonPropertyValue } '
1125+ fixture.PythonClassObject = obj
1126+
1127+ def AssertPythonClassObjectType(fixture: TestPropertyAccess.DynamicFixture) -> None:
1128+ if type(fixture.PythonClassObject) != PythonTestClass:
1129+ raise Exception('PythonClassObject is not of type PythonTestClass')
1130+
1131+ def AccessCSharpProperty(fixture: TestPropertyAccess.DynamicFixture) -> str:
1132+ return fixture.PythonClassObject.CSharpProperty
1133+
1134+ def AccessPythonProperty(fixture: TestPropertyAccess.DynamicFixture) -> str:
1135+ return fixture.PythonClassObject.PythonProperty
1136+ " ) ;
1137+
1138+ dynamic fixture = new DynamicFixture ( ) ;
1139+
1140+ using ( Py . GIL ( ) )
1141+ {
1142+ dynamic SetPythonObjectToFixture = testModule . GetAttr ( "SetPythonObjectToFixture" ) ;
1143+ SetPythonObjectToFixture ( fixture ) ;
1144+
1145+ dynamic AssertPythonClassObjectType = testModule . GetAttr ( "AssertPythonClassObjectType" ) ;
1146+ Assert . DoesNotThrow ( ( ) => AssertPythonClassObjectType ( fixture ) ) ;
1147+
1148+ // Access the C# class property
1149+ dynamic AccessCSharpProperty = testModule . GetAttr ( "AccessCSharpProperty" ) ;
1150+ Assert . AreEqual ( expectedCSharpPropertyValue , AccessCSharpProperty ( fixture ) . As < string > ( ) ) ;
1151+ Assert . AreEqual ( expectedCSharpPropertyValue , fixture . PythonClassObject . CSharpProperty . As < string > ( ) ) ;
1152+
1153+ // Access the Python class property
1154+ dynamic AccessPythonProperty = testModule . GetAttr ( "AccessPythonProperty" ) ;
1155+ Assert . AreEqual ( expectedPythonPropertyValue , AccessPythonProperty ( fixture ) . As < string > ( ) ) ;
1156+ Assert . AreEqual ( expectedPythonPropertyValue , fixture . PythonClassObject . PythonProperty . As < string > ( ) ) ;
1157+ }
1158+ }
1159+
10991160 private static TestCaseData [ ] DynamicPropertiesSetterTestCases ( ) => new [ ]
11001161 {
11011162 new TestCaseData ( "True" , null ) ,
@@ -1136,10 +1197,15 @@ def GetPythonValue(self):
11361197 using ( Py . GIL ( ) )
11371198 {
11381199 model . SetValue ( fixture ) ;
1200+
11391201 var expectedAsPyObject = model . GetPythonValue ( ) as PyObject ;
1140- var expected = expectedType != null ? expectedAsPyObject . AsManagedObject ( expectedType ) : expectedAsPyObject ;
1202+ Assert . AreEqual ( expectedAsPyObject , fixture . DynamicProperty ) ;
1203+
1204+ if ( expectedType != null )
1205+ {
1206+ Assert . AreEqual ( expectedAsPyObject . AsManagedObject ( expectedType ) , fixture . DynamicProperty . AsManagedObject ( expectedType ) ) ;
1207+ }
11411208
1142- Assert . AreEqual ( expected , fixture . DynamicProperty ) ;
11431209 }
11441210 }
11451211
0 commit comments