Skip to content

Commit 19192ad

Browse files
authored
Merge pull request #31 from pyscripter/master
Merging head repository last changes
2 parents 3af6852 + 556b33e commit 19192ad

File tree

2 files changed

+37
-20
lines changed

2 files changed

+37
-20
lines changed

Source/PythonEngine.pas

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1521,6 +1521,7 @@ TPythonInterface=class(TDynamicDll)
15211521
PyObject_GetAttrString:function (ob:PPyObject;c:PAnsiChar):PPyObject; cdecl;
15221522
PyObject_GetItem:function (ob,key:PPyObject):PPyObject; cdecl;
15231523
PyObject_DelItem:function (ob,key:PPyObject):PPyObject; cdecl;
1524+
PyObject_HasAttr:function (ob, attr_name:PPyObject):integer; cdecl;
15241525
PyObject_HasAttrString:function (ob:PPyObject;key:PAnsiChar):integer; cdecl;
15251526
PyObject_Hash:function (ob:PPyObject):NativeInt; cdecl;
15261527
PyObject_IsTrue:function (ob:PPyObject):integer; cdecl;
@@ -3711,6 +3712,7 @@ procedure TPythonInterface.MapDll;
37113712
PyObject_GetAttrString := Import('PyObject_GetAttrString');
37123713
PyObject_GetItem := Import('PyObject_GetItem');
37133714
PyObject_DelItem := Import('PyObject_DelItem');
3715+
PyObject_HasAttr := Import('PyObject_HasAttr');
37143716
PyObject_HasAttrString := Import('PyObject_HasAttrString');
37153717
PyObject_Hash := Import('PyObject_Hash');
37163718
PyObject_IsTrue := Import('PyObject_IsTrue');
@@ -7311,11 +7313,12 @@ function TPythonModule.GetVarAsVariant( const varName : AnsiString ) : Variant;
73117313
with Engine do
73127314
begin
73137315
obj := GetVar( varName );
7314-
try
7315-
Result := PyObjectAsVariant( obj );
7316-
finally
7317-
Py_XDecRef(obj);
7318-
end;
7316+
if Assigned(obj) then
7317+
try
7318+
Result := PyObjectAsVariant( obj );
7319+
finally
7320+
Py_XDecRef(obj);
7321+
end;
73197322
end;
73207323
end;
73217324

Source/WrapDelphi.pas

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2226,9 +2226,10 @@ function TPyDelphiObject.GetAttrO(key: PPyObject): PPyObject;
22262226
Result := inherited GetAttrO(key);
22272227
if GetPythonEngine.PyErr_Occurred = nil then Exit; // We found what we wanted
22282228

2229-
if Assigned(DelphiObject) and GetPythonEngine.PyUnicode_Check(Key) then
2230-
KeyName := GetPythonEngine.PyUnicodeAsString(Key)
2231-
else
2229+
// should not happen
2230+
if not (Assigned(DelphiObject) and
2231+
CheckStrAttribute(Key, 'GetAttrO key parameter', KeyName))
2232+
then
22322233
Exit;
22332234

22342235
GetPythonEngine.PyErr_Clear;
@@ -2512,11 +2513,15 @@ function TPyDelphiObject.Repr: PPyObject;
25122513

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

25222527
function HandleEvent(PropInfo: PPropInfo; out ErrMsg: string) : Integer;
@@ -2582,20 +2587,29 @@ function TPyDelphiObject.SetAttrO(key, value: PPyObject): Integer;
25822587
{$ENDIF}
25832588
KeyName: string;
25842589
ErrMsg: string;
2590+
PyEngine: TPythonEngine;
2591+
PyObj: PPyobject;
25852592
begin
25862593
Result := -1;
2587-
if Assigned(DelphiObject) and GetPythonEngine.PyUnicode_Check(Key) then
2588-
KeyName := GetPythonEngine.PyUnicodeAsString(Key)
2589-
else begin
2594+
PyEngine := GetPythonEngine;
2595+
2596+
// should not happen
2597+
if not (Assigned(DelphiObject) and
2598+
CheckStrAttribute(Key, 'SetAttrO key parameter', KeyName))
2599+
then
25902600
Exit;
2591-
end;
25922601

2593-
// Only call the inherited method if the attribute exists
2594-
if GetPythonEngine.PyObject_HasAttrString(GetSelf, PAnsiChar(key)) = 1 then
2602+
// Only call the inherited method at this stage if the attribute exists
2603+
PyObj := PyEngine.PyObject_GenericGetAttr(GetSelf, key);
2604+
if Assigned(PyObj) then
2605+
begin
2606+
PyEngine.Py_DECREF(PyObj); // not needed
25952607
Result := inherited SetAttrO(key, value);
2596-
if Result = 0 then Exit;
2608+
if Result = 0 then
2609+
Exit;
2610+
end;
25972611

2598-
GetPythonEngine.PyErr_Clear;
2612+
PyEngine.PyErr_Clear;
25992613
{$IFDEF EXTENDED_RTTI}
26002614
Context := TRttiContext.Create();
26012615
try
@@ -2623,8 +2637,8 @@ function TPyDelphiObject.SetAttrO(key, value: PPyObject): Integer;
26232637
if Result <> 0 then
26242638
Result := inherited SetAttrO(key, value);
26252639
if Result <> 0 then
2626-
with GetPythonEngine do
2627-
PyErr_SetObject(PyExc_AttributeError^, PyUnicodeFromString(
2640+
with PyEngine do
2641+
PyErr_SetObject(PyEngine.PyExc_AttributeError^, PyUnicodeFromString(
26282642
Format(rs_ErrAttrSetr, [KeyName, ErrMsg])));
26292643
end;
26302644

0 commit comments

Comments
 (0)