Jump to content
iqrf

Wrapping a delphi object containing an attribute with an enum return value defined in Python

Recommended Posts

Posted (edited)

Hi, it's a little crazy, but it works.
property update_state: PPyObject read GetUpdateState;

function TServerRepo.GetUpdateState: PPyObject;
begin
  with GetPythonEngine do begin
    result := ExtractPythonObjectFrom(MainModule.RepositoryState.uExpired);
    Py_IncRef(result);
  end;
end;

I achieved this by modifying WrapDelphi.pas
Is it a correct solution?

function TValueToPyObject(const Value: TValue;
   DelphiWrapper: TPyDelphiWrapper; out ErrMsg: string): PPyObject;
begin
  if Value.IsEmpty then
    Result := GetPythonEngine.ReturnNone
  else
    case Value.Kind of
      tkClass: Result := DelphiWrapper.Wrap(Value.AsObject);
      tkClassRef: Result := DelphiWrapper.WrapClass(Value.AsClass);
      tkInterface: Result := DelphiWrapper.WrapInterface(Value);
      tkRecord{$IFDEF MANAGED_RECORD},tkMRecord{$ENDIF}:
        Result := DelphiWrapper.WrapRecord(Value);
      tkArray, tkDynArray:
        Result := DynArrayToPython(Value, DelphiWrapper, ErrMsg);
// Add ->
      tkPointer: begin
        if Value.IsType<PPyObject> then
            Result := PPyObject(Value.AsType<Pointer>)
          else begin
            ErrMsg := rs_ErrValueToPython;
            Result := nil;
          end;
      end;
// <- Add
    else
      Result := SimpleValueToPython(Value, ErrMsg);
    end;
end;
  TServerRepo = class(TPersistent)
  private
    function GetAPIVersion: Integer;
    function GetUpdateState: PPyObject;
    function GetLastDownload: TDateTime;
  public
    constructor Create(OnlineStatus: Boolean);
    property api_version: Integer read GetAPIVersion;
    property update_state: PPyObject read GetUpdateState;
    property last_download: TDateTime read GetLastDownload;
  end;

TPythonRepositorySettings = class(TPersistent)
  private
    FOfflineStatus: TServerRepo;
  public
    constructor Create;
    destructor Destroy; override;
    property online_status: TServerRepo read FOnlineStatus;
  end;

  TPyServerRepo = class(TPyDelphiPersistent)
    constructor CreateWith(PythonType: TPythonType; args, kwds: PPyObject); override;
    function Repr: PPyObject; override;
    class function DelphiObjectClass : TClass; override;
  end;

  TPyRepositorySettings = class(TPyDelphiPersistent)
    constructor CreateWith(PythonType: TPythonType; args, kwds: PPyObject); override;
    function Repr: PPyObject; override;
    class function DelphiObjectClass : TClass; override;
  end;

....

procedure TPython.OnDelphiWrapperInitialization(Sender: TObject);
begin
  FPythonWrapper.RegisterDelphiWrapper(TPyServerRepo);
  FPythonWrapper.RegisterDelphiWrapper(TPyRepositorySettings);
end;

...

repositorySettings := TPythonRepositorySettings.Create;
prepositorySettings := FPythonWrapper.Wrap(repositorySettings, soOwned);
FPythonModule_Repository.SetVar('settings', prepositorySettings);
FEngine.Py_DecRef(prepositorySettings);
@unique
class RepositoryState(Enum):
    uActual = 0
    uExpired = 1
    uNonActual = 2
    
from ide import repository as repo
from repository import settings as repoSet

update_state = repoSet.local_cache.update_state
print(update_state)
print(type(update_state))
print(type(RepositoryState))
RepositoryState.uExpired
<enum 'RepositoryState'>
<class 'enum.EnumType'>

 

Edited by iqrf

Share this post


Link to post

You don't need to modify WrapDelphi.  Just use the latest version.

 

function TValueToPyObject(const Value: TValue;
   DelphiWrapper: TPyDelphiWrapper; out ErrMsg: string): PPyObject;
begin
  if Value.IsEmpty then
    Result := GetPythonEngine.ReturnNone
  else
    case Value.Kind of
      tkClass: Result := DelphiWrapper.Wrap(Value.AsObject);
      tkClassRef: Result := DelphiWrapper.WrapClass(Value.AsClass);
      tkInterface: Result := DelphiWrapper.WrapInterface(Value);
      tkRecord{$IFDEF MANAGED_RECORD},tkMRecord{$ENDIF}:
        Result := DelphiWrapper.WrapRecord(Value);
      tkArray, tkDynArray:
        Result := DynArrayToPython(Value, DelphiWrapper, ErrMsg);
      tkPointer:
        if Value.IsType<PPyObject> then
          Result := Value.AsType<PPyObject>
        else
        begin
          Result := nil;
          ErrMsg := rs_ErrValueToPython;
        end;
    else
      Result := SimpleValueToPython(Value, ErrMsg);
    end;
end;

 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×