Skip to content

Commit bed48ba

Browse files
committed
Fix #435
1 parent 3e39838 commit bed48ba

File tree

3 files changed

+92
-61
lines changed

3 files changed

+92
-61
lines changed

Source/WrapDelphi.pas

+56-56
Original file line numberDiff line numberDiff line change
@@ -1031,6 +1031,9 @@ TExposedProperty = class(TExposedGetSet)
10311031
procedure RaiseNotifyEvent(PyDelphiWrapper : TPyDelphiWrapper; ACallable : PPyObject; Sender: TObject);
10321032
{Sets mulptiple properties of PyObject from keywords argument}
10331033
function SetProperties(PyObject: PPyObject; keywords: PPyObject): PPyObject;
1034+
function ValidateClassRef(PyValue: PPyObject; RefClass: TClass;
1035+
out ClassRef: TClass; out ErrMsg: string): Boolean;
1036+
procedure InvalidArguments(const MethName, ErrMsg : string);
10341037

10351038
implementation
10361039

@@ -1105,20 +1108,9 @@ function SetRttiAttr(const ParentAddr: Pointer; ParentType: TRttiStructuredType
11051108
const AttrName: string; Value: PPyObject; PyDelphiWrapper: TPyDelphiWrapper;
11061109
out ErrMsg: string): Boolean; forward;
11071110

1108-
function ValidateClassRef(PyValue: PPyObject; RefClass: TClass;
1109-
out ClassRef: TClass; out ErrMsg: string): Boolean; forward;
1110-
11111111
function ValidateClassProperty(PyValue: PPyObject; TypeInfo: PTypeInfo;
11121112
out Obj: TObject; out ErrMsg: string): Boolean; forward;
11131113

1114-
procedure InvalidArguments(const MethName, ErrMsg : string);
1115-
begin
1116-
with GetPythonEngine do
1117-
PyErr_SetObject(PyExc_TypeError^, PyUnicodeFromString(
1118-
Format(rs_ErrInvalidArgs,
1119-
[MethName, ErrMsg])));
1120-
end;
1121-
11221114
{ TAbstractExposedMember }
11231115

11241116
constructor TAbstractExposedMember.Create(ARttiMember: TRttiMember;
@@ -1373,6 +1365,59 @@ function GlobalDelphiWrapper: TPyDelphiWrapper;
13731365

13741366
{ Helper functions }
13751367

1368+
procedure InvalidArguments(const MethName, ErrMsg : string);
1369+
begin
1370+
with GetPythonEngine do
1371+
PyErr_SetObject(PyExc_TypeError^, PyUnicodeFromString(
1372+
Format(rs_ErrInvalidArgs,
1373+
[MethName, ErrMsg])));
1374+
end;
1375+
1376+
function ValidateClassRef(PyValue: PPyObject; RefClass: TClass;
1377+
out ClassRef: TClass; out ErrMsg: string): Boolean;
1378+
var
1379+
LTypeName: AnsiString;
1380+
LPythonType: TPythonType;
1381+
begin
1382+
ClassRef := nil;
1383+
if (PyValue = GetPythonEngine.Py_None) then begin
1384+
Result := True;
1385+
Exit;
1386+
end;
1387+
1388+
Result := False;
1389+
// Is PyValue a Python type?
1390+
if PyValue^.ob_type^.tp_name = 'type' then
1391+
LTypeName := PPyTypeObject(PyValue).tp_name
1392+
else
1393+
begin
1394+
ErrMsg := rs_ExpectedClass;
1395+
Exit;
1396+
end;
1397+
1398+
LPythonType := GetPythonEngine.FindPythonType(PPyTypeObject(PyValue));
1399+
if not Assigned(LPythonType) then
1400+
// Try once more with the base type to catter for pascal classes
1401+
// subclassed in Python
1402+
LPythonType := GetPythonEngine.FindPythonType(PPyTypeObject(PyValue).tp_base);
1403+
1404+
if Assigned(LPythonType) then
1405+
begin
1406+
if Assigned(LPythonType) and LPythonType.PyObjectClass.InheritsFrom(TPyDelphiObject) then
1407+
begin
1408+
ClassRef := TPyDelphiObjectClass(LPythonType.PyObjectClass).DelphiObjectClass;
1409+
if ClassRef.InheritsFrom(RefClass) then
1410+
Result := True
1411+
else
1412+
ErrMsg := rs_IncompatibleClasses;
1413+
end
1414+
else
1415+
ErrMsg := rs_ExpectedClass;
1416+
end
1417+
else
1418+
ErrMsg := rs_ExpectedClass;
1419+
end;
1420+
13761421
{$IFDEF EXTENDED_RTTI}
13771422
function DynArrayToPython(const Value: TValue): PPyObject;
13781423
var
@@ -1559,51 +1604,6 @@ function ValidateInterfaceProperty(PyValue: PPyObject; RttiType: TRttiInterfaceT
15591604
ErrMsg := rs_ExpectedInterface;
15601605
end;
15611606

1562-
function ValidateClassRef(PyValue: PPyObject; RefClass: TClass;
1563-
out ClassRef: TClass; out ErrMsg: string): Boolean;
1564-
var
1565-
LTypeName: AnsiString;
1566-
LPythonType: TPythonType;
1567-
begin
1568-
ClassRef := nil;
1569-
if (PyValue = GetPythonEngine.Py_None) then begin
1570-
Result := True;
1571-
Exit;
1572-
end;
1573-
1574-
Result := False;
1575-
// Is PyValue a Python type?
1576-
if PyValue^.ob_type^.tp_name = 'type' then
1577-
LTypeName := PPyTypeObject(PyValue).tp_name
1578-
else
1579-
begin
1580-
ErrMsg := rs_ExpectedClass;
1581-
Exit;
1582-
end;
1583-
1584-
LPythonType := GetPythonEngine.FindPythonType(PPyTypeObject(PyValue));
1585-
if not Assigned(LPythonType) then
1586-
// Try once more with the base type to catter for pascal classes
1587-
// subclassed in Python
1588-
LPythonType := GetPythonEngine.FindPythonType(PPyTypeObject(PyValue).tp_base);
1589-
1590-
if Assigned(LPythonType) then
1591-
begin
1592-
if Assigned(LPythonType) and LPythonType.PyObjectClass.InheritsFrom(TPyDelphiObject) then
1593-
begin
1594-
ClassRef := TPyDelphiObjectClass(LPythonType.PyObjectClass).DelphiObjectClass;
1595-
if ClassRef.InheritsFrom(RefClass) then
1596-
Result := True
1597-
else
1598-
ErrMsg := rs_IncompatibleClasses;
1599-
end
1600-
else
1601-
ErrMsg := rs_ExpectedClass;
1602-
end
1603-
else
1604-
ErrMsg := rs_ExpectedClass;
1605-
end;
1606-
16071607
function ValidateDynArray(PyValue: PPyObject; const RttiParam: TRttiParameter; out ParamValue: TValue; out ErrMsg: string): Boolean;
16081608
var
16091609
Arr: array of TValue;

Source/WrapDelphiWindows.pas

+24-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ interface
1919

2020
{$IFDEF MSWINDOWS}
2121
uses
22-
Windows, Classes, SysUtils, PythonEngine, WrapDelphi, WrapDelphiClasses;
22+
Windows, Classes, SysUtils, TypInfo, PythonEngine, WrapDelphi, WrapDelphiClasses;
23+
24+
function OwnerDrawStateToPython(const AOwnerDrawState: TOwnerDrawState): PPyObject;
2325
{$ENDIF MSWINDOWS}
2426

2527
implementation
@@ -31,6 +33,27 @@ implementation
3133
System.Win.HighDpi, Winapi.ShellScaling;
3234
{$ENDIF DELPHI11_OR_HIGHER}
3335

36+
function OwnerDrawStateToPython(const AOwnerDrawState: TOwnerDrawState): PPyObject;
37+
38+
procedure Append(const AList: PPyObject; const AString: string);
39+
var
40+
LItem: PPyObject;
41+
begin
42+
with GetPythonEngine do begin
43+
LItem := PyUnicodeFromString(AString);
44+
PyList_Append(AList, LItem);
45+
Py_XDecRef(LItem);
46+
end;
47+
end;
48+
49+
var
50+
LState: integer;
51+
begin
52+
Result := GetPythonEngine().PyList_New(0);
53+
for LState := Ord(odSelected) to Ord(odComboBoxEdit) do
54+
Append(Result, System.TypInfo.GetEnumName(TypeInfo(TOwnerDrawState), LState));
55+
end;
56+
3457
{ Register the wrappers, the globals and the constants }
3558
type
3659
TWindowsRegistration = class(TRegisteredUnit)

Source/vcl/WrapVclComCtrls.pas

+12-4
Original file line numberDiff line numberDiff line change
@@ -2372,6 +2372,7 @@ procedure TTVCreateNodeClassEventHandler.DoEvent(Sender: TCustomTreeView;
23722372
var
23732373
LPyObject, LPyTuple, LPyResult, LPyNodeClass: PPyObject;
23742374
LVarParam: TPyDelphiVarParameter;
2375+
ErrMsg: string;
23752376
LClass: TClass;
23762377
begin
23772378
Assert(Assigned(PyDelphiWrapper));
@@ -2388,8 +2389,11 @@ procedure TTVCreateNodeClassEventHandler.DoEvent(Sender: TCustomTreeView;
23882389
if Assigned(LPyResult) then begin
23892390
Py_DECREF(LPyResult);
23902391

2391-
LClass := TPyDelphiObjectClass(
2392-
PythonToPythonType(LVarParam.Value).PyObjectClass).DelphiObjectClass;
2392+
if not ValidateClassRef(LVarParam.Value, TTreeNode, LClass, ErrMsg) then
2393+
begin
2394+
InvalidArguments('OnCreateNode', ErrMsg);
2395+
Exit;
2396+
end;
23932397

23942398
NodeClass := TTreeNodeClass(LClass);
23952399
end;
@@ -3647,6 +3651,7 @@ procedure TLVCreateItemClassEventHandler.DoEvent(Sender: TCustomListView;
36473651
LPyObject, LPyTuple, LPyResult, LPyItemClass: PPyObject;
36483652
LVarParam: TPyDelphiVarParameter;
36493653
LClass: TClass;
3654+
ErrMsg: string;
36503655
begin
36513656
Assert(Assigned(PyDelphiWrapper));
36523657
if Assigned(Callable) and PythonOK() then
@@ -3662,8 +3667,11 @@ procedure TLVCreateItemClassEventHandler.DoEvent(Sender: TCustomListView;
36623667
if Assigned(LPyResult) then begin
36633668
Py_DECREF(LPyResult);
36643669

3665-
LClass := TPyDelphiObjectClass(
3666-
PythonToPythonType(LVarParam.Value).PyObjectClass).DelphiObjectClass;
3670+
if not ValidateClassRef(LVarParam.Value, TListItem, LClass, ErrMsg) then
3671+
begin
3672+
InvalidArguments('OnCreateItem', ErrMsg);
3673+
Exit;
3674+
end;
36673675

36683676
ItemClass := TListItemClass(LClass);
36693677
end;

0 commit comments

Comments
 (0)