Skip to content

Commit 6d985e7

Browse files
committed
WrapDelphi: Handle default Indexed property.
1 parent 8dfe703 commit 6d985e7

2 files changed

Lines changed: 91 additions & 3 deletions

File tree

Source/WrapDelphi.pas

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,11 @@ TPyDelphiObject = class (TPyInterfacedObject, IFreeNotificationSubscriber)
588588
function SqItem( idx : NativeInt ) : PPyObject; override;
589589
function SqContains( obj: PPyObject): integer; override;
590590
function SqAssItem( idx : NativeInt; obj : PPyObject) : Integer; override;
591+
// Mapping services
592+
{$IFDEF EXTENDED_RTTI}
593+
function MpSubscript(obj: PPyObject) : PPyObject; override;
594+
function MpAssSubscript(obj1, obj2: PPyObject) : Integer; override;
595+
{$ENDIF EXTENDED_RTTI}
591596

592597
class function DelphiObjectClass : TClass; virtual;
593598
class procedure RegisterMethods( PythonType : TPythonType ); override;
@@ -3904,8 +3909,6 @@ class procedure TPyDelphiObject.ExposeIndexedProperties(AClass: TClass;
39043909
LClass: TClass;
39053910
LDocStr: string;
39063911
begin
3907-
// TODO: Identify and handle the default property
3908-
39093912
LRttiCtx := TRttiContext.Create();
39103913
try
39113914
LRttiType := LRttiCtx.GetType(AClass) as TRttiStructuredType;
@@ -3965,12 +3968,94 @@ class procedure TPyDelphiObject.ExposeIndexedProperties(AClass: TClass;
39653968
nil,
39663969
PAnsiChar(LExposedProperty.DocString),
39673970
nil);
3971+
3972+
// Store the default property in the type
3973+
if LRttiProperty.IsDefault and (APythonType.Tag = 0) then
3974+
begin
3975+
APythonType.Tag := NativeInt(LRttiProperty);
3976+
if LRttiProperty.IsWritable then
3977+
APythonType.Services.Mapping := [msSubscript, msAssSubscript]
3978+
else
3979+
APythonType.Services.Mapping := [msSubscript];
3980+
end;
39683981
end;
39693982
finally
39703983
LRttiCtx.Free;
39713984
end;
39723985
end;
39733986

3987+
function TPyDelphiObject.MpSubscript(obj: PPyObject) : PPyObject;
3988+
var
3989+
PyArgs: PPyObject;
3990+
Prop: TRttiIndexedProperty;
3991+
begin
3992+
Assert(PythonType.Tag <> 0);
3993+
Prop := TRttiIndexedProperty(PythonType.Tag);
3994+
3995+
// obj is a tuple only if we have more than one arguments
3996+
if PyDelphiWrapper.Engine.PyTuple_Check(obj) then
3997+
PyArgs := obj
3998+
else
3999+
PyArgs := PyDelphiWrapper.Engine.MakePyTuple([obj]);
4000+
4001+
Result := RttiCall(DelphiObject, PyDelphiWrapper, Prop.ReadMethod,
4002+
PyArgs, nil);
4003+
4004+
if not PyDelphiWrapper.Engine.PyTuple_Check(obj) then
4005+
PyDelphiWrapper.Engine.Py_DECREF(PyArgs); // release created tuple
4006+
end;
4007+
4008+
function TPyDelphiObject.MpAssSubscript(obj1, obj2: PPyObject) : Integer;
4009+
var
4010+
Engine: TPythonEngine;
4011+
Prop: TRttiIndexedProperty;
4012+
PyArgs: PPyObject;
4013+
TempPy: PPyObject;
4014+
Count, Index: Integer;
4015+
begin
4016+
Result := -1; // Signals failure
4017+
4018+
Assert(PythonType.Tag <> 0);
4019+
Prop := TRttiIndexedProperty(PythonType.Tag);
4020+
4021+
Engine := PyDelphiWrapper.Engine;
4022+
if not Prop.IsWritable then
4023+
begin
4024+
with Engine do
4025+
PyErr_SetObject(PyExc_TypeError^, PyUnicodeFromString(rs_NotWritable));
4026+
Exit;
4027+
end;
4028+
4029+
// obj is a tuple only if we have more than one arguments
4030+
if Engine.PyTuple_Check(obj1) then
4031+
begin
4032+
Count := Engine.PyTuple_Size(obj1);
4033+
PyArgs := Engine.PyTuple_New(Count + 1);
4034+
for Index := 0 to Count - 1 do
4035+
begin
4036+
TempPy := Engine.PyTuple_GetItem(obj1, Index);
4037+
Engine.Py_XINCREF(TempPy);
4038+
Engine.PyTuple_SetItem(PyArgs, Index, TempPy);
4039+
end;
4040+
Engine.Py_XINCREF(obj2);
4041+
Engine.PyTuple_SetItem(PyArgs, Count, obj2);
4042+
end
4043+
else
4044+
PyArgs := Engine.MakePyTuple([obj1, obj2]);
4045+
4046+
TempPy := RttiCall(DelphiObject, PyDelphiWrapper, Prop.WriteMethod,
4047+
PyArgs, nil);
4048+
4049+
Engine.Py_DECREF(PyArgs); // release created tuple
4050+
4051+
if TempPy <> nil then
4052+
begin
4053+
Engine.Py_DECREF(TempPy); //Should be Py_None
4054+
Result := 0; // Signal success
4055+
end;
4056+
end;
4057+
4058+
39744059
{$ENDIF EXTENDED_RTTI}
39754060

39764061
function TPyDelphiObject.Set_Owned(AValue: PPyObject;

Tests/WrapDelphiTest.pas

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ TTestRttiAccess = class
6969
procedure PassVariantArray(const Value: Variant);
7070
function ClassRefParam(ClassRef: TPersistentClass): string;
7171
property Indexed[I: Integer]: Integer read GetIndexed write SetIndexed;
72-
property Indexed2[S1, S2: string]: string read GetIndexed2 write SetIndexed2;
72+
property Indexed2[S1, S2: string]: string read GetIndexed2 write SetIndexed2; default;
7373
class var ClassField: string;
7474
class function DoubleString(S: string): string;
7575
class function Square(I: Integer): Integer; static;
@@ -325,6 +325,9 @@ procedure TTestWrapDelphi.TestIndexedProperties;
325325
Assert.AreEqual<Integer>(VarPythonEval('rtti_var.Indexed[2]'), 6);
326326
PythonEngine.ExecString('rtti_var.Indexed2["A", "B"] = "C"');
327327
Assert.AreEqual<string>(VarPythonEval('rtti_var.Indexed2["A", "B"]'), 'A,B: C');
328+
// default property
329+
PythonEngine.ExecString('rtti_var["A", "B"] = "C"');
330+
Assert.AreEqual<string>(VarPythonEval('rtti_var["A", "B"]'), 'A,B: C');
328331
end;
329332

330333
procedure TTestWrapDelphi.TestInheritance;

0 commit comments

Comments
 (0)