Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
pyscripter committed Jul 16, 2022
1 parent cd5fbbb commit 556b33e
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 15 deletions.
2 changes: 2 additions & 0 deletions Source/PythonEngine.pas
Original file line number Diff line number Diff line change
Expand Up @@ -1521,6 +1521,7 @@ TPythonInterface=class(TDynamicDll)
PyObject_GetAttrString:function (ob:PPyObject;c:PAnsiChar):PPyObject; cdecl;
PyObject_GetItem:function (ob,key:PPyObject):PPyObject; cdecl;
PyObject_DelItem:function (ob,key:PPyObject):PPyObject; cdecl;
PyObject_HasAttr:function (ob, attr_name:PPyObject):integer; cdecl;
PyObject_HasAttrString:function (ob:PPyObject;key:PAnsiChar):integer; cdecl;
PyObject_Hash:function (ob:PPyObject):NativeInt; cdecl;
PyObject_IsTrue:function (ob:PPyObject):integer; cdecl;
Expand Down Expand Up @@ -3711,6 +3712,7 @@ procedure TPythonInterface.MapDll;
PyObject_GetAttrString := Import('PyObject_GetAttrString');
PyObject_GetItem := Import('PyObject_GetItem');
PyObject_DelItem := Import('PyObject_DelItem');
PyObject_HasAttr := Import('PyObject_HasAttr');
PyObject_HasAttrString := Import('PyObject_HasAttrString');
PyObject_Hash := Import('PyObject_Hash');
PyObject_IsTrue := Import('PyObject_IsTrue');
Expand Down
44 changes: 29 additions & 15 deletions Source/WrapDelphi.pas
Original file line number Diff line number Diff line change
Expand Up @@ -2226,9 +2226,10 @@ function TPyDelphiObject.GetAttrO(key: PPyObject): PPyObject;
Result := inherited GetAttrO(key);
if GetPythonEngine.PyErr_Occurred = nil then Exit; // We found what we wanted

if Assigned(DelphiObject) and GetPythonEngine.PyUnicode_Check(Key) then
KeyName := GetPythonEngine.PyUnicodeAsString(Key)
else
// should not happen
if not (Assigned(DelphiObject) and
CheckStrAttribute(Key, 'GetAttrO key parameter', KeyName))
then
Exit;

GetPythonEngine.PyErr_Clear;
Expand Down Expand Up @@ -2512,11 +2513,15 @@ function TPyDelphiObject.Repr: PPyObject;

function TPyDelphiObject.SetAttrO(key, value: PPyObject): Integer;
(*
First look whether the attribute has ben wrapped (RegisterGetSet, RegisterMethod).
This is done by calling the inherited SetAttrO. If this fails then
First look whether the attribute exists., e.g. has been wrapped with
RegisterGetSet, RegisterMethod, etc.
If it does then the inherited generic SetAttrO is called.
If the attribute does not exist or the generic SetAttO fails (unlikely) then
- Use Rtti to locate the property in DELPHIXE_OR_HIGHER (EXTENDED_RTTI)
or for other versions
- Look for published properties
Finally, if all the above fail then you call the inherited generic SetAttrO
which adds a new field in the object dictionary
*)

function HandleEvent(PropInfo: PPropInfo; out ErrMsg: string) : Integer;
Expand Down Expand Up @@ -2582,20 +2587,29 @@ function TPyDelphiObject.SetAttrO(key, value: PPyObject): Integer;
{$ENDIF}
KeyName: string;
ErrMsg: string;
PyEngine: TPythonEngine;
PyObj: PPyobject;
begin
Result := -1;
if Assigned(DelphiObject) and GetPythonEngine.PyUnicode_Check(Key) then
KeyName := GetPythonEngine.PyUnicodeAsString(Key)
else begin
PyEngine := GetPythonEngine;

// should not happen
if not (Assigned(DelphiObject) and
CheckStrAttribute(Key, 'SetAttrO key parameter', KeyName))
then
Exit;
end;

// Only call the inherited method if the attribute exists
if GetPythonEngine.PyObject_HasAttrString(GetSelf, PAnsiChar(key)) = 1 then
// Only call the inherited method at this stage if the attribute exists
PyObj := PyEngine.PyObject_GenericGetAttr(GetSelf, key);
if Assigned(PyObj) then
begin
PyEngine.Py_DECREF(PyObj); // not needed
Result := inherited SetAttrO(key, value);
if Result = 0 then Exit;
if Result = 0 then
Exit;
end;

GetPythonEngine.PyErr_Clear;
PyEngine.PyErr_Clear;
{$IFDEF EXTENDED_RTTI}
Context := TRttiContext.Create();
try
Expand Down Expand Up @@ -2623,8 +2637,8 @@ function TPyDelphiObject.SetAttrO(key, value: PPyObject): Integer;
if Result <> 0 then
Result := inherited SetAttrO(key, value);
if Result <> 0 then
with GetPythonEngine do
PyErr_SetObject(PyExc_AttributeError^, PyUnicodeFromString(
with PyEngine do
PyErr_SetObject(PyEngine.PyExc_AttributeError^, PyUnicodeFromString(
Format(rs_ErrAttrSetr, [KeyName, ErrMsg])));
end;

Expand Down

0 comments on commit 556b33e

Please sign in to comment.