iqrf
Members-
Content Count
44 -
Joined
-
Last visited
Community Reputation
3 NeutralTechnical Information
-
Delphi-Version
Delphi 11 Alexandria
Recent Profile Visitors
1108 profile views
-
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'>
-
Thank you, I got to that too var a := VarPythonCreate(pColor).value the second way var valueObj := PyObject_GetAttrString(pColor, 'value'); if Assigned(valueObj) then begin a := PyLong_AsLong(valueObj); Py_XDECREF(valueObj); end else PyErr_Print();
-
Hi, how to use PyArg_ParseTupleAndKeywords to get the value of a function parameter that is of type Python enum. E.g class color (enum): RED = 5 GREEN = 8 BLUE = 9 TestFunction (Color.RED) var pColor: PPyObject; if (PyArg_ParseTupleAndKeywords(args, kwargs, '|O', @keyPointerArray[0], @pColor) <> 0) then begin PyEnum_Check(pColor) returns False why? How to get value 5 from pColor? I tried this too var a := VarPythonCreate(pColor); VarIsEnum(a) also returns False in 'a' is the string 'color.RED' Thank you for your help.
-
OK 😞 So I define an enum in python and use it in delphi, which works. Now I understand why it is like this: procedure TButtonsRegistration.DefineVars(APyDelphiWrapper: TPyDelphiWrapper); begin inherited; APyDelphiWrapper.DefineVar('bkCustom', bkCustom); APyDelphiWrapper.DefineVar('bkOK', bkOK); APyDelphiWrapper.DefineVar('bkCancel', bkCancel); APyDelphiWrapper.DefineVar('bkHelp', bkHelp); APyDelphiWrapper.DefineVar('bkYes', bkYes); APyDelphiWrapper.DefineVar('bkNo', bkNo); APyDelphiWrapper.DefineVar('bkClose', bkClose); APyDelphiWrapper.DefineVar('bkAbort', bkAbort); APyDelphiWrapper.DefineVar('bkRetry', bkRetry); APyDelphiWrapper.DefineVar('bkIgnore', bkIgnore); APyDelphiWrapper.DefineVar('bkAll', bkAll); end; Thanks for your time.
-
Sure this is ok. I would like in Python a = TColor.RED print(type(a)) ### <enum 'TColor'> where TColor defined in Delphi
-
I don't want to define an enum in both Delphi and Python. I just want to use an enum defined in Delphi in Python. WrapDelphi I use both FPythonWrapper.DefineVar() and FPythonWrapper.Wrap(TDelphi, soOwned) and FPythonWrapper.RegisterDelphiWrapper(TPyClassWrapper<...>).Initialize But I have no idea how to use the same functionality for an enumeration type.
-
Thanks a lot. And how do I get the enumerated type TColor into Python?
-
I don't understand how I can write in Python a = TColor.RED without exporting to Python? var colorEnum := MainModule.Color; var Red := colorEnum.RED; result := Red; E2010 Incompatible types: 'PPyObject' and 'Variant' But that's the variant type, I need to return a PPyObject. Thanks
-
How to export from delphi to python type TColor = (RED = 5, GREEN = 8, BLUE = 9) and in the return value of the delphi function called from Python to return a PPyObject of type TColor. Is it any other way than clumsily like this? FEngine.PyRun_SimpleString('from enum import Enum' + #13 + 'Color = Enum(''Color'', {''RED'':5, ''GREEN'':8, ''BLUE'':9})'); ... FEngine.ExecString(UTF8Encode(FScript), UTF8Encode(FCode.Path)); ... //result my function mainModule, colorEnum, redColor: PPyObject; .... mainModule := PyImport_AddModule('__main__'); colorEnum := PyObject_GetAttrString(mainModule, 'Color'); redColor := PyObject_GetAttrString(colorEnum, 'RED'); result := redColor; ... if mymodule.test_func() == Color.RED: ... Thanks for the ideas.
-
Hi, not using exit() is not the solution for me. Users use exit() when debugging a script. If to ProcessSystemExit; i add Py_DecRef(errtraceback); so the memory leak problem will disappear. The destructor TTerminalLogSettings will already be called. I have no idea, but how is that possible. procedure TPythonEngine.CheckError(ACatchStopEx : Boolean = False); procedure ProcessSystemExit; var errtype, errvalue, errtraceback: PPyObject; SErrValue: string; begin PyErr_Fetch(errtype, errvalue, errtraceback); Traceback.Refresh(errtraceback); SErrValue := PyObjectAsString(errvalue); Py_DecRef(errtraceback); // workaround PyErr_Clear; raise EPySystemExit.CreateResFmt(@SPyExcSystemError, [SErrValue]); end;
-
Wrap TDictionary - TypeError: 'Object' object is not subscriptable
iqrf replied to iqrf's topic in Python4Delphi
It is possible to somehow distinguish whether the SetVisible function was called from new_column.visible = True or myPoint.ColumnA['Note1'].Visible = True procedure TColumn.SetVisible(const Value: Boolean); begin FVisible := Value; ... end; Thanks for the advice. -
Hi, i have this code TColumn = class(TPersistent) private FHeaderName: String; FVisible: Boolean; FWidth: Integer; FPosition: Integer; procedure SetHeaderName(const Value: String); procedure SetVisible(const Value: Boolean); procedure SetWidth(const Value: Integer); procedure SetPosition(const Value: Integer); public property HeaderName: String read FHeaderName write SetHeaderName; property Visible: Boolean read FVisible write SetVisible; property Width: Integer read FWidth write SetWidth; property Position: Integer read FPosition write SetPosition; end; TColumnWrapper = class(TPyClassWrapper<TColumn>) constructor CreateWith(APythonType: TPythonType; args, kwds: PPyObject); override; end; TTerminalLogSettings = class(TPersistent) private fColumn: TDictionary<String,TColumn>; function GetAutoScroll: Boolean; function GetSeparatorH: Boolean; function GetSeparatorV: Boolean; function GetViewData: Boolean; procedure SetAutoScroll(const Value: Boolean); procedure SetSeparatorH(const Value: Boolean); procedure SetSeparatorV(const Value: Boolean); procedure SetViewData(const Value: Boolean); public constructor Create; destructor Destroy; override; property AutoScroll: Boolean read GetAutoScroll write SetAutoScroll; property SeparatorH: Boolean read GetSeparatorH write SetSeparatorH; property SeparatorV: Boolean read GetSeparatorV write SetSeparatorV; property ViewData: Boolean read GetViewData write SetViewData; property Column: TDictionary<String, TColumn> read fColumn write fColumn; end; ... FPythonModule_TerminalLog := TPythonModule.Create(nil); FPythonModule_TerminalLog.Name := 'FPythonModule_TerminalLog'; FPythonModule_TerminalLog.Engine := FEngine; FPythonModule_TerminalLog.ModuleName := 'terminal_log'; FPythonModule_TerminalLog.OnInitialization := OnInitialization_TerminalLog; FPythonModule_TerminalLog.OnAfterInitialization := OnAfterInitialization_TerminalLog; ... FPythonVersion.AssignTo(FEngine); FEngine.LoadDll; ... terminalLogSettings := TTerminalLogSettings.Create; pTerminalLogSettings := FPythonWrapper.Wrap(terminalLogSettings, soOwned); FPythonModule_TerminalLog.SetVar( 'settings', pTerminalLogSettings); FEngine.Py_DecRef(pTerminalLogSettings); FPythonWrapper.RegisterDelphiWrapper(TColumnWrapper).Initialize; FPythonWrapper.RegisterDelphiWrapper(TPyClassWrapper<TDictionary<string, TColumn>>).Initialize; ... if used in this way in the script, then after the script finishes I correctly call the TTerminalLogSettings destructor and free the memory ... iqrfide.terminal_log.settings.autoScroll = True ... settings_object = iqrfide.terminal_log.settings setattr(settings_object, 'autoScroll', True) ... If the script is interrupted using exit(), the destructor is not called and the memory is not freed. Any explanation? ... iqrfide.terminal_log.settings.autoScroll = True ... settings_object = iqrfide.terminal_log.settings setattr(settings_object, 'autoScroll', True) exit() ... Putting settings_object = None before exit solves the problem.
-
Wrap TDictionary - TypeError: 'Object' object is not subscriptable
iqrf replied to iqrf's topic in Python4Delphi
Is there any way to iterate over TDictionary in Python? for key in spam.myPoint.ColumnA.Keys: #TypeError: 'Object' object is not iterable print(key) for key, value in spam.myPoint.ColumnA.Items: #TypeError: 'IndexedProperty' object is not iterable print(key, value) -
Wrap TDictionary - TypeError: 'Object' object is not subscriptable
iqrf replied to iqrf's topic in Python4Delphi
Many thanks once again. Question about TPyPoint. From python it is always called CreateWith, you cannot call Create. Why is that? I solved it like this. To write p = spam.Point() , I changed ii: to |ii PyArg_ParseTupleAndKeywords(args, kwds, '|ii:CreatePoint', @KeyPointerArray[0], @fx, @fy) -
Wrap TDictionary - TypeError: 'Object' object is not subscriptable
iqrf replied to iqrf's topic in Python4Delphi
Of course it works. I don't know how to put elements of type TColumn into a dictionary ColumnA in Python. This doesn't work col = spam.myPoint.Column() col.Visible = True col.Width = 255 spam.myPoint.ColumnA.["Note1"] = col or spam.myPoint.ColumnA.["Note1"] = spam.myPoint.Column(True, 255)