Skip to content

Commit 27fe2e9

Browse files
committed
Avoid manually wrapped members to be overridden by dynamically expose members
Fixes: Embarcadero/DelphiVCL4Python#57
1 parent f09be63 commit 27fe2e9

File tree

1 file changed

+67
-16
lines changed

1 file changed

+67
-16
lines changed

Source/WrapDelphi.pas

+67-16
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,11 @@ TPyDelphiObject = class (TPyInterfacedObject, IFreeNotificationSubscriber)
644644
class procedure SetupType( PythonType : TPythonType ); override;
645645
// Expose methods, properties and fields via RTTI at definition time
646646
{$IFDEF EXPOSE_MEMBERS}
647+
class function GetExcludedExposeMethods(
648+
const APythonType: TPythonType): TArray<string>; virtual;
649+
class function GetExcludedExposeGettersSetters(
650+
const APythonType: TPythonType): TArray<string>; virtual;
651+
647652
class procedure ExposeMethods(const AClass: TClass;
648653
const APythonType: TPythonType; const APyDelphiWrapper: TPyDelphiWrapper;
649654
const ADeclaredMethodsOnly: boolean = false;
@@ -668,6 +673,9 @@ TPyDelphiObject = class (TPyInterfacedObject, IFreeNotificationSubscriber)
668673
const AIncludedFieldNames: TArray<string> = [];
669674
const AExcludedFieldNames: TArray<string> = [];
670675
const ADefCallback: TExposedFieldDefCallback = nil); virtual;
676+
677+
class procedure DynamicallyExposeMembers(const APythonType: TPythonType;
678+
const APyDelphiWrapper: TPyDelphiWrapper);
671679
{$ENDIF EXPOSE_MEMBERS}
672680
// if the class is a container (TStrings, TComponent, TCollection...),
673681
// then return the class implementing the access to the contained items.
@@ -4101,9 +4109,6 @@ function TPyDelphiObject.SetProps(args, keywords: PPyObject): PPyObject;
41014109
class procedure TPyDelphiObject.SetupType(PythonType: TPythonType);
41024110
var
41034111
_ContainerAccessClass : TContainerAccessClass;
4104-
{$IFDEF EXPOSE_MEMBERS}
4105-
LDocStr: string;
4106-
{$ENDIF EXPOSE_MEMBERS}
41074112
begin
41084113
inherited;
41094114
PythonType.TypeName := AnsiString(GetTypeName);
@@ -4121,23 +4126,31 @@ class procedure TPyDelphiObject.SetupType(PythonType: TPythonType);
41214126
if _ContainerAccessClass.SupportsIndexOf then
41224127
PythonType.Services.Sequence := PythonType.Services.Sequence + [ssContains];
41234128
end;
4129+
end;
41244130

4125-
{$IFDEF EXPOSE_MEMBERS}
4126-
PythonType.TypeFlags := PythonType.TypeFlags + [TPFlag.tpTypeSubclass];
4131+
{$IFDEF EXPOSE_MEMBERS}
4132+
class function TPyDelphiObject.GetExcludedExposeMethods(
4133+
const APythonType: TPythonType): TArray<string>;
4134+
var
4135+
I: integer;
4136+
begin
4137+
Result := ['CPP_ABI_1', 'CPP_ABI_2', 'CPP_ABI_3'];
4138+
//Any method manually wrapped must be excluded
4139+
for I := 0 to APythonType.MethodCount - 1 do
4140+
Result := Result + [String(APythonType.Methods[I].ml_name)];
4141+
end;
41274142

4128-
//Try to load the class doc string from doc server
4129-
if TPythonDocServer.Instance.ReadTypeDocStr(DelphiObjectClass.ClassInfo, LDocStr) then
4130-
PythonType.DocString.Text := LDocStr;
4131-
4132-
ExposeMethods(DelphiObjectClass, PythonType,PythonType.Owner as TPyDelphiWrapper,
4133-
true, [], ['CPP_ABI_1', 'CPP_ABI_2', 'CPP_ABI_3']);
4134-
ExposeFields(DelphiObjectClass, PythonType, PythonType.Owner as TPyDelphiWrapper, true);
4135-
ExposeProperties(DelphiObjectClass, PythonType, PythonType.Owner as TPyDelphiWrapper, true);
4136-
ExposeIndexedProperties(DelphiObjectClass, PythonType, PythonType.Owner as TPyDelphiWrapper, true);
4137-
{$ENDIF EXPOSE_MEMBERS}
4143+
class function TPyDelphiObject.GetExcludedExposeGettersSetters(
4144+
const APythonType: TPythonType): TArray<string>;
4145+
var
4146+
I: integer;
4147+
begin
4148+
Result := [];
4149+
//Any field, property or indexed property manually wrapped must be excluded
4150+
for I := 0 to APythonType.GetSetCount - 1 do
4151+
Result := Result + [String(APythonType.GetSet[I].name)];
41384152
end;
41394153

4140-
{$IFDEF EXPOSE_MEMBERS}
41414154
class procedure TPyDelphiObject.ExposeMethods(const AClass: TClass;
41424155
const APythonType: TPythonType; const APyDelphiWrapper: TPyDelphiWrapper;
41434156
const ADeclaredMethodsOnly: boolean; const AIncludedMethodNames,
@@ -4476,6 +4489,38 @@ class procedure TPyDelphiObject.ExposeFields(const AClass: TClass;
44764489
LRttiCtx.Free;
44774490
end;
44784491
end;
4492+
4493+
class procedure TPyDelphiObject.DynamicallyExposeMembers(
4494+
const APythonType: TPythonType; const APyDelphiWrapper: TPyDelphiWrapper);
4495+
var
4496+
LDocStr: string;
4497+
LExcludedMethods: TArray<string>;
4498+
LExcludedGettersAndSetters: TArray<string>;
4499+
LDelphiObjectClass: TClass;
4500+
begin
4501+
APythonType.TypeFlags := APythonType.TypeFlags + [TPFlag.tpTypeSubclass];
4502+
4503+
LDelphiObjectClass := TPyDelphiObjectClass(APythonType.PyObjectClass).DelphiObjectClass;
4504+
4505+
//Try to load the class doc string from doc server
4506+
if TPythonDocServer.Instance.ReadTypeDocStr(LDelphiObjectClass.ClassInfo, LDocStr) then
4507+
APythonType.DocString.Text := LDocStr;
4508+
4509+
//Get excluded methods manually wrapped
4510+
LExcludedMethods := GetExcludedExposeMethods(APythonType);
4511+
//Get excluded fields, porperties and indexed properties manually wrapped
4512+
LExcludedGettersAndSetters := GetExcludedExposeGettersSetters(APythonType);
4513+
4514+
ExposeMethods(LDelphiObjectClass, APythonType, APyDelphiWrapper, true,
4515+
[], LExcludedMethods);
4516+
ExposeFields(LDelphiObjectClass, APythonType, APyDelphiWrapper, true,
4517+
[], LExcludedGettersAndSetters);
4518+
ExposeProperties(LDelphiObjectClass, APythonType, APyDelphiWrapper, true,
4519+
[], LExcludedGettersAndSetters);
4520+
ExposeIndexedProperties(LDelphiObjectClass, APythonType, APyDelphiWrapper, true,
4521+
[], LExcludedGettersAndSetters);
4522+
end;
4523+
44794524
{$ENDIF EXPOSE_MEMBERS}
44804525

44814526
function TPyDelphiObject.Set_Owned(AValue: PPyObject;
@@ -5352,6 +5397,12 @@ procedure TPyDelphiWrapper.RegisterDelphiWrapper(
53525397
RegisteredClass.PythonType.Engine := Engine;
53535398
RegisteredClass.PythonType.Module := fModule;
53545399
RegisteredClass.PythonType.PyObjectClass := AWrapperClass;
5400+
5401+
{$IFDEF EXPOSE_MEMBERS}
5402+
//Must run after manually wrapped members
5403+
TPyDelphiObject.DynamicallyExposeMembers(RegisteredClass.PythonType, Self);
5404+
{$ENDIF EXPOSE_MEMBERS}
5405+
53555406
// Find nearest registered parent class and set it as base
53565407
for Index := fClassRegister.Count - 1 downto 0 do
53575408
with TRegisteredClass(fClassRegister[Index]) do

0 commit comments

Comments
 (0)