pyscripter / python4delphi

Free components that wrap up Python into Delphi and Lazarus (FPC)
MIT License
895 stars 307 forks source link

Wrongly throwing an exception from the wrapping object #464

Closed Vobsoft closed 3 months ago

Vobsoft commented 3 months ago

Hello, I have an example like this:

TColumn = class(TPersistent)
private
FHeaderName: String;
  procedure SetHeaderName(const Value: String);
  function GetHeaderName: String;
public
  constructor Create(Index: Integer);
  procedure Auto_size;
  property header_name: String read GetHeaderName write SetHeaderName;
end;

TColumnWrapper = class(TPyClassWrapper<TColumn>)
  constructor CreateWith(APythonType: TPythonType; args, kwds: PPyObject); override;
  function repr: PPyObject; override;
end;

If I throw an exception in the auto_size function, using the procedure TColumn.Auto_Size; begin raise Exception.Create('Test error'); end An error is raised and the script terminates correctly. TypeError: "auto_size" called with invalid arguments. Error: Test error If the error is raised in SetHeaderName, it will not be displayed, the script will terminate incorrectly and a memory leak will occur. procedure TColumn.SetHeaderName(const Value: String); begin raise Exception.Create('Test error'); end

This modification solves the problem. https://github.com/pyscripter/python4delphi/blob/46e0bf78018d2feaaf8d3cfbd32cdf09fe84c191/Source/WrapDelphi.pas#L3240

function SetRttiProperty(const ParentAddr: Pointer;  Prop: TRttiProperty;
  Value: PPyObject;  PyDelphiWrapper: TPyDelphiWrapper;
  out ErrMsg: string): Boolean;
var
  AttrValue: TValue;
begin
  Result := False;

try

    if Ord(Prop.Visibility) < Ord(mvPublic) then
      ErrMsg := rs_NoAccess
    else if not Prop.IsWritable then
      ErrMsg := rs_NotWritable
    else if Prop.PropertyType = nil then
      ErrMsg := rs_ErrNoTypeInfo
    else if Prop.PropertyType.TypeKind = tkMethod then
    begin
      if (Prop is TRttiInstanceProperty) and  (Prop.Visibility = mvPublished) then
        Result := PyDelphiWrapper.EventHandlers.Link(TObject(ParentAddr),
          (Prop as TRttiInstanceProperty).PropInfo, Value, ErrMsg)
      else
        ErrMsg := rs_NotPublished;
    end
    else if PyObjectToTValue(Value, Prop.PropertyType, AttrValue, ErrMsg) then
    begin
      Prop.SetValue(ParentAddr, AttrValue);
      Result := True;
    end;
except
    on E: Exception do begin
      ErrMsg := E.Message;
    end;
  end;

end;

AttributeError: Error in setting property header_name Error: Test error

pyscripter commented 3 months ago

The fix is a bit different that yours. Could you please confirm it now works as expected?

Vobsoft commented 3 months ago

The repair is OK, thanks.