diff --git a/Demos/Demo06/Unit1.dfm b/Demos/Demo06/Unit1.dfm index 19538b07..c3a31c64 100644 --- a/Demos/Demo06/Unit1.dfm +++ b/Demos/Demo06/Unit1.dfm @@ -10,8 +10,6 @@ object Form1: TForm1 Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] - OldCreateOrder = True - PixelsPerInch = 96 TextHeight = 13 object Splitter1: TSplitter Left = 0 @@ -20,7 +18,6 @@ object Form1: TForm1 Height = 3 Cursor = crVSplit Align = alTop - ExplicitWidth = 536 end object Memo1: TMemo Left = 0 diff --git a/Demos/Demo06/Unit1.pas b/Demos/Demo06/Unit1.pas index df25433d..cf6e6faf 100644 --- a/Demos/Demo06/Unit1.pas +++ b/Demos/Demo06/Unit1.pas @@ -42,7 +42,7 @@ TForm1 = class(TForm) end; PyPointRec = record - ob_refcnt : NativeInt; + ob_refcnt : NativeUInt; ob_type : PPyTypeObject; po_x : Integer; po_y : Integer; @@ -151,6 +151,8 @@ procedure PyPoint_dealloc(obj : PPyObject); cdecl; // object.value // object.method(args) function PyPoint_getattr(obj : PPyObject; key : PAnsiChar) : PPyObject; cdecl; +var + Py_Key: PPyObject; begin with GetPythonEngine, PPyPoint(obj)^ do begin @@ -163,9 +165,14 @@ function PyPoint_getattr(obj : PPyObject; key : PAnsiChar) : PPyObject; cdecl; else begin // Else check for a method - Result := PyObject_GenericGetAttr(obj, PyUnicodeFromString(key)); - if not Assigned(Result) then - PyErr_SetString (PyExc_AttributeError^, PAnsiChar(Utf8Encode(Format('Unknown attribute "%s"',[key])))); + Py_Key := PyUnicodeFromString(key); + try + Result := PyObject_GenericGetAttr(obj, Py_key); + if not Assigned(Result) then + PyErr_SetString (PyExc_AttributeError^, PAnsiChar(Utf8Encode(Format('Unknown attribute "%s"',[key])))); + finally + Py_DECREF(Py_Key); + end; end; end; end; diff --git a/Demos/Demo07/Unit1.dfm b/Demos/Demo07/Unit1.dfm index 51b77e56..500ec0e6 100644 --- a/Demos/Demo07/Unit1.dfm +++ b/Demos/Demo07/Unit1.dfm @@ -13,8 +13,6 @@ object Form1: TForm1 Font.Name = 'MS Sans Serif' Font.Pitch = fpVariable Font.Style = [] - OldCreateOrder = True - PixelsPerInch = 96 TextHeight = 13 object Splitter1: TSplitter Left = 0 @@ -23,7 +21,6 @@ object Form1: TForm1 Height = 3 Cursor = crVSplit Align = alTop - ExplicitWidth = 536 end object Memo1: TMemo Left = 0 diff --git a/Demos/Demo07/Unit1.pas b/Demos/Demo07/Unit1.pas index 012507af..3514b6a3 100644 --- a/Demos/Demo07/Unit1.pas +++ b/Demos/Demo07/Unit1.pas @@ -48,7 +48,7 @@ TForm1 = class(TForm) end; PyPointRec = record - ob_refcnt : NativeInt; + ob_refcnt : NativeUInt; ob_type : PPyTypeObject; po_x : Integer; po_y : Integer; @@ -191,6 +191,8 @@ procedure PyPoint_dealloc(obj : PPyObject); cdecl; // object.value // object.method(args) function PyPoint_getattr(obj : PPyObject; key : PAnsiChar) : PPyObject; cdecl; +var + Py_Key: PPyObject; begin with GetPythonEngine, PPyPoint(obj)^ do begin @@ -203,9 +205,14 @@ function PyPoint_getattr(obj : PPyObject; key : PAnsiChar) : PPyObject; cdecl; else begin // Else check for a method - Result := PyObject_GenericGetAttr(obj, PyUnicodeFromString(key)); - if not Assigned(Result) then - PyErr_SetString (PyExc_AttributeError^, PAnsiChar(AnsiString(Format('Unknown attribute "%s"',[key])))); + Py_Key := PyUnicodeFromString(key); + try + Result := PyObject_GenericGetAttr(obj, Py_Key); + if not Assigned(Result) then + PyErr_SetString (PyExc_AttributeError^, PAnsiChar(Utf8Encode(Format('Unknown attribute "%s"',[key])))); + finally + Py_DECREF(Py_Key); + end; end; end; end; @@ -226,7 +233,7 @@ function PyPoint_setattrfunc(obj : PPyObject; key : PAnsiChar; value : PPyObjec Result := 0; end else - PyErr_SetString (PyExc_AttributeError^, PAnsiChar(AnsiString(Format('Attribute "%s" needs an integer',[key])))); + PyErr_SetString (PyExc_AttributeError^, PAnsiChar(Utf8Encode(Format('Attribute "%s" needs an integer',[key])))); // Check for attribute y end else if key = 'y' then begin if PyLong_Check(value) then @@ -235,9 +242,9 @@ function PyPoint_setattrfunc(obj : PPyObject; key : PAnsiChar; value : PPyObjec Result := 0; end else - PyErr_SetString (PyExc_AttributeError^, PAnsiChar(AnsiString(Format('Attribute "%s" needs an integer',[key])))); + PyErr_SetString (PyExc_AttributeError^, PAnsiChar(Utf8Encode(Format('Attribute "%s" needs an integer',[key])))); end else - PyErr_SetString (PyExc_AttributeError^, PAnsiChar(AnsiString(Format('Unknown attribute "%s"',[key])))); + PyErr_SetString (PyExc_AttributeError^, PAnsiChar(Utf8Encode(Format('Unknown attribute "%s"',[key])))); end; end; diff --git a/Demos/Demo11/ThSort.dfm b/Demos/Demo11/ThSort.dfm index 2f5f2710..f0c50c0d 100644 --- a/Demos/Demo11/ThSort.dfm +++ b/Demos/Demo11/ThSort.dfm @@ -165,7 +165,6 @@ object ThreadSortForm: TThreadSortForm OnClick = SaveBtnClick end object PythonEngine1: TPythonEngine - InitThreads = True RedirectIO = False Left = 16 Top = 32 diff --git a/Demos/Demo29/Unit1.dfm b/Demos/Demo29/Unit1.dfm index c149398f..c151b511 100644 --- a/Demos/Demo29/Unit1.dfm +++ b/Demos/Demo29/Unit1.dfm @@ -10,11 +10,9 @@ object Form1: TForm1 Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] - OldCreateOrder = False DesignSize = ( 668 701) - PixelsPerInch = 96 TextHeight = 13 object Image1: TImage Left = 8 diff --git a/Demos/Demo29/Unit1.pas b/Demos/Demo29/Unit1.pas index 025c5cd1..b969d646 100644 --- a/Demos/Demo29/Unit1.pas +++ b/Demos/Demo29/Unit1.pas @@ -86,7 +86,7 @@ procedure TForm1.Button2Click(Sender: TObject); with GetPythonEngine do begin pargs := MakePyTuple([ExtractPythonObjectFrom(_im)]); try - presult := PyEval_CallObjectWithKeywords( + presult := PyObject_Call( ExtractPythonObjectFrom(MainModule.ImageToBytes), pargs, nil); try if PyBytes_AsStringAndSize(presult, P, Len) < 0 then begin diff --git a/Demos/Demo33/ThSort.dfm b/Demos/Demo33/ThSort.dfm index fa04fa71..3b4c41e6 100644 --- a/Demos/Demo33/ThSort.dfm +++ b/Demos/Demo33/ThSort.dfm @@ -171,7 +171,6 @@ object ThreadSortForm: TThreadSortForm OnClick = StopBtnClick end object PythonEngine1: TPythonEngine - InitThreads = True PyFlags = [pfDebug, pfInteractive, pfVerbose] RedirectIO = False Left = 16 diff --git a/Demos/Demo36/ParallelPython.dpr b/Demos/Demo36/ParallelPython.dpr index 00883f7a..abcfb0fa 100644 --- a/Demos/Demo36/ParallelPython.dpr +++ b/Demos/Demo36/ParallelPython.dpr @@ -109,6 +109,7 @@ begin WriteLn('Elapsed ms: ' + SW.ElapsedMilliseconds.ToString); WriteLn; finally + Sleep(1000); // allow some time for the threads to terminate DestroyEngine; end; except diff --git a/Demos/FPC/Demo06/Unit1.pas b/Demos/FPC/Demo06/Unit1.pas index 34c8a901..75e705bb 100644 --- a/Demos/FPC/Demo06/Unit1.pas +++ b/Demos/FPC/Demo06/Unit1.pas @@ -47,7 +47,7 @@ TForm1 = class(TForm) end; PyPointRec = record - ob_refcnt : NativeInt; + ob_refcnt : NativeUInt; ob_type : PPyTypeObject; po_x : Integer; po_y : Integer; diff --git a/Demos/FPC/Demo35/project1.lpi b/Demos/FPC/Demo35/project1.lpi new file mode 100644 index 00000000..ff71647f --- /dev/null +++ b/Demos/FPC/Demo35/project1.lpi @@ -0,0 +1,71 @@ + + + + + + + + + + + + + <UseAppBundle Value="False"/> + <ResourceType Value="res"/> + </General> + <BuildModes> + <Item Name="Default" Default="True"/> + </BuildModes> + <PublishOptions> + <Version Value="2"/> + <UseFileFilters Value="True"/> + </PublishOptions> + <RunParams> + <FormatVersion Value="2"/> + </RunParams> + <RequiredPackages> + <Item> + <PackageName Value="P4DLaz"/> + </Item> + </RequiredPackages> + <Units> + <Unit> + <Filename Value="project1.lpr"/> + <IsPartOfProject Value="True"/> + </Unit> + <Unit> + <Filename Value="stopwatch.pas"/> + <IsPartOfProject Value="True"/> + </Unit> + </Units> + </ProjectOptions> + <CompilerOptions> + <Version Value="11"/> + <PathDelim Value="\"/> + <Target> + <Filename Value="project1"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + <Linking> + <Debugging> + <DebugInfoType Value="dsDwarf3"/> + </Debugging> + </Linking> + </CompilerOptions> + <Debugging> + <Exceptions> + <Item> + <Name Value="EAbort"/> + </Item> + <Item> + <Name Value="ECodetoolError"/> + </Item> + <Item> + <Name Value="EFOpenError"/> + </Item> + </Exceptions> + </Debugging> +</CONFIG> diff --git a/Demos/FPC/Demo35/project1.lpr b/Demos/FPC/Demo35/project1.lpr new file mode 100644 index 00000000..bb83f928 --- /dev/null +++ b/Demos/FPC/Demo35/project1.lpr @@ -0,0 +1,148 @@ +program project1; + +{$mode delphi}{$H+} + +uses + {$IFDEF UNIX} + cthreads, + {$ENDIF} + Classes, SysUtils, CustApp, + { you can add units after this } + Variants, + PythonEngine, + VarPyth, + stopwatch; + +var + PyEngine: TPythonEngine; + +procedure CreatePyEngine; +begin + MaskFPUExceptions(True, True); + PyEngine := TPythonEngine.Create(nil); + PyEngine.Name := 'PythonEngine'; + PyEngine.UseLastKnownVersion := False; + PyEngine.RegVersion:= '3.12'; + PyEngine.DllName:= 'python312.dll'; + PyEngine.LoadDll; +end; + +procedure DestroyEngine; +begin + PyEngine.Free; +end; + +const + N = 100000; + +type + PIntArray = ^TIntArray; + {$IFDEF MSWINDOWS} + TIntArray = array[0..N - 1] of Integer; + {$ELSE} + TIntArray = array[0..N - 1] of NativeInt; + {$ENDIF} + + { TBufferProtocol } + + TBufferProtocol = class(TCustomApplication) + protected + procedure DoRun; override; + public + constructor Create(TheOwner: TComponent); override; + destructor Destroy; override; + end; + +{ TBufferProtocol } + +procedure TBufferProtocol.DoRun; +var + SW: TStopwatch; + Sum: Int64; + np: Variant; + arr: Variant; + np_arr: PPyObject; + PyBuffer: Py_buffer; + V: Variant; + I: Integer; + Count: Integer; + ArrItem: Variant; +begin + try + CreatePyEngine; + try + // Import numpy and create an array + np := Import('numpy'); + arr := np.&array(BuiltinModule.range(N)); + + // This is the slow way to iterate the array + WriteLn('Lazy but slow:'); + SW := TStopwatch.StartNew; + Sum := 0; + Count := VarPythonToVariant(arr.Length); + for I := 0 to Count - 1 do + begin + ArrItem := BuiltinModule.int(arr.GetItem(I)); + Sum := Sum + Int64(VarPythonToVariant(ArrItem)); + end; + + //for V in VarPyIterate(arr) do + // Sum := Sum + Int64(VarPythonToVariant(BuiltinModule.int(V))); + SW.Stop; + WriteLn(Format('Sum from 0 to %d = %d', [N, Sum])); + WriteLn('Elapsed ms: ' + SW.ElapsedMilliseconds.ToString); + WriteLn; + + WriteLn('Using Py_Buffer:'); + SW := TStopwatch.StartNew; + np_arr := ExtractPythonObjectFrom(arr); + PyEngine.PyObject_GetBuffer(np_arr, @PyBuffer, PyBUF_CONTIG); + PyEngine.CheckError; + try + Sum := 0; + for I := 0 to N - 1 do + Sum := Sum + PIntArray(PyBuffer.buf)^[I]; + SW.Stop; + WriteLn(Format('Sum from 0 to %d = %d', [N, Sum])); + finally + PyEngine.PyBuffer_Release(@PyBuffer); + end; + WriteLn('Elapsed ms: ' + SW.ElapsedMilliseconds.ToString); + WriteLn; + + // test write access + PIntArray(PyBuffer.buf)^[0] := 999; + if VarPythonToVariant(BuiltinModule.int(arr.GetItem(0))) = 999 then + WriteLn('Successfully modified the numpy array using Py_buffer'); + finally + DestroyEngine; + end; + except + on E: Exception do + Writeln(E.ClassName, ': ', E.Message); + end; + Readln; + // stop program loop + Terminate; +end; + +constructor TBufferProtocol.Create(TheOwner: TComponent); +begin + inherited Create(TheOwner); + StopOnException:=True; +end; + +destructor TBufferProtocol.Destroy; +begin + inherited Destroy; +end; + +var + Application: TBufferProtocol; +begin + Application:=TBufferProtocol.Create(nil); + Application.Title:='BufferProtocol'; + Application.Run; + Application.Free; +end. + diff --git a/Demos/FPC/Demo35/stopwatch.pas b/Demos/FPC/Demo35/stopwatch.pas new file mode 100644 index 00000000..d2ef8baf --- /dev/null +++ b/Demos/FPC/Demo35/stopwatch.pas @@ -0,0 +1,191 @@ +{ High frequency stop watch implemntation. + Copyright (c) 2012 by Inoussa OUEDRAOGO + + This source code is distributed under the Library GNU General Public License + with the following modification: + + - object files and libraries linked into an application may be + distributed without source code. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + **********************************************************************} + +{$IFDEF FPC} + {$mode objfpc}{$H+} + {$modeswitch advancedrecords} +{$ENDIF} + +{$IFDEF MSWINDOWS} + {$IFNDEF WINDOWS} + {$DEFINE WINDOWS} + {$ENDIF WINDOWS} +{$ENDIF MSWINDOWS} + +unit stopwatch; + +interface +uses + SysUtils + {$IFDEF LINUX} + ,unixtype, linux + {$ENDIF LINUX} + ; + +type + + { TStopWatch } + + TStopWatch = record + private + const + C_THOUSAND = 1000; + C_MILLION = C_THOUSAND * C_THOUSAND; + C_BILLION = C_THOUSAND * C_THOUSAND * C_THOUSAND; + TicksPerNanoSecond = 100; + TicksPerMilliSecond = 10000; + TicksPerSecond = C_BILLION div 100; + Type + TBaseMesure = + {$IFDEF WINDOWS} + Int64; + {$ENDIF WINDOWS} + {$IFDEF LINUX} + TTimeSpec; + {$ENDIF LINUX} + strict private + class var FFrequency : Int64; + class var FIsHighResolution : Boolean; + strict private + FElapsed : Int64; + FRunning : Boolean; + FStartPosition : TBaseMesure; + strict private + procedure CheckInitialization();inline; + function GetElapsedMilliseconds: Int64; + function GetElapsedTicks: Int64; + public + class function Create() : TStopWatch;static; + class function StartNew() : TStopWatch;static; + class property Frequency : Int64 read FFrequency; + class property IsHighResolution : Boolean read FIsHighResolution; + procedure Reset(); + procedure Start(); + procedure Stop(); + property ElapsedMilliseconds : Int64 read GetElapsedMilliseconds; + property ElapsedTicks : Int64 read GetElapsedTicks; + property IsRunning : Boolean read FRunning; + end; + +resourcestring + sStopWatchNotInitialized = 'The StopWatch is not initialized.'; + +implementation +{$IFDEF WINDOWS} +uses + Windows; +{$ENDIF WINDOWS} + +{ TStopWatch } + +class function TStopWatch.Create(): TStopWatch; +{$IFDEF LINUX} +var + r : TBaseMesure; +{$ENDIF LINUX} +begin + if (FFrequency = 0) then begin +{$IFDEF WINDOWS} + FIsHighResolution := QueryPerformanceFrequency(FFrequency); +{$ENDIF WINDOWS} +{$IFDEF LINUX} + FIsHighResolution := (clock_getres(CLOCK_MONOTONIC,@r) = 0); + FIsHighResolution := FIsHighResolution and (r.tv_nsec <> 0); + if (r.tv_nsec <> 0) then + FFrequency := C_BILLION div r.tv_nsec; +{$ENDIF LINUX} + end; + FillChar(Result,SizeOf(Result),0); +end; + +class function TStopWatch.StartNew() : TStopWatch; +begin + Result := TStopWatch.Create(); + Result.Start(); +end; + +procedure TStopWatch.CheckInitialization(); +begin + if (FFrequency = 0) then + raise Exception.Create(sStopWatchNotInitialized); +end; + +function TStopWatch.GetElapsedMilliseconds: Int64; +begin + {$IFDEF WINDOWS} + Result := ElapsedTicks * TicksPerMilliSecond; + {$ENDIF WINDOWS} + {$IFDEF LINUX} + Result := FElapsed div C_MILLION; + {$ENDIF LINUX} +end; + +function TStopWatch.GetElapsedTicks: Int64; +begin + CheckInitialization(); +{$IFDEF WINDOWS} + Result := (FElapsed * TicksPerSecond) div FFrequency; +{$ENDIF WINDOWS} +{$IFDEF LINUX} + Result := FElapsed div TicksPerNanoSecond; +{$ENDIF LINUX} +end; + +procedure TStopWatch.Reset(); +begin + Stop(); + FElapsed := 0; + FillChar(FStartPosition,SizeOf(FStartPosition),0); +end; + +procedure TStopWatch.Start(); +begin + if FRunning then + exit; + FRunning := True; +{$IFDEF WINDOWS} + QueryPerformanceCounter(FStartPosition); +{$ENDIF WINDOWS} +{$IFDEF LINUX} + clock_gettime(CLOCK_MONOTONIC,@FStartPosition); +{$ENDIF LINUX} +end; + +procedure TStopWatch.Stop(); +var + locEnd : TBaseMesure; + s, n : Int64; +begin + if not FRunning then + exit; + FRunning := False; +{$IFDEF WINDOWS} + QueryPerformanceCounter(locEnd); + FElapsed := FElapsed + (UInt64(locEnd) - UInt64(FStartPosition)); +{$ENDIF WINDOWS} +{$IFDEF LINUX} + clock_gettime(CLOCK_MONOTONIC,@locEnd); + if (locEnd.tv_nsec < FStartPosition.tv_nsec) then begin + s := locEnd.tv_sec - FStartPosition.tv_sec - 1; + n := C_BILLION + locEnd.tv_nsec - FStartPosition.tv_nsec; + end else begin + s := locEnd.tv_sec - FStartPosition.tv_sec; + n := locEnd.tv_nsec - FStartPosition.tv_nsec; + end; + FElapsed := FElapsed + (s * C_BILLION) + n; +{$ENDIF LINUX} +end; + +end. diff --git a/Modules/DemoModule/uMain.pas b/Modules/DemoModule/uMain.pas index 89ef3d22..8df2b082 100644 --- a/Modules/DemoModule/uMain.pas +++ b/Modules/DemoModule/uMain.pas @@ -49,7 +49,6 @@ function PyInit_DemoModule: PPyObject; try gEngine := TPythonEngine.Create(nil); gEngine.AutoFinalize := False; - gEngine.UseLastKnownVersion := False; gEngine.UseLastKnownVersion := True; gModule := TPythonModule.Create(nil); diff --git a/Modules/RttiModule/uMain.pas b/Modules/RttiModule/uMain.pas index 5afc2b19..386b522f 100644 --- a/Modules/RttiModule/uMain.pas +++ b/Modules/RttiModule/uMain.pas @@ -34,10 +34,7 @@ function PyInit_DemoModule: PPyObject; try gEngine := TPythonEngine.Create(nil); gEngine.AutoFinalize := False; - gEngine.UseLastKnownVersion := False; - // Adapt to the desired python version - gEngine.RegVersion := '3.8'; - gEngine.DllName := 'python38.dll'; + gEngine.UseLastKnownVersion := True; gModule := TPythonModule.Create(nil); gModule.Engine := gEngine; @@ -47,7 +44,7 @@ function PyInit_DemoModule: PPyObject; gDelphiWrapper.Engine := gEngine; gDelphiWrapper.Module := gModule; - gEngine.LoadDll; + gEngine.LoadDllInExtensionModule; Py := gDelphiWrapper.Wrap(DelphiFunctions, TObjectOwnership.soReference); gModule.SetVar('delphi_funcs', Py); gEngine.Py_DecRef(Py); diff --git a/Packages/Delphi/Delphi 10.4+/Python.dproj b/Packages/Delphi/Delphi 10.4+/Python.dproj index c41368d4..568730b8 100644 --- a/Packages/Delphi/Delphi 10.4+/Python.dproj +++ b/Packages/Delphi/Delphi 10.4+/Python.dproj @@ -7,8 +7,9 @@ <MainSource>Python.dpk</MainSource> <Platform Condition="'$(Platform)'==''">Win32</Platform> <ProjectGuid>{018AAA56-F5BD-4A04-BCCA-A0043EAAA5CE}</ProjectGuid> - <ProjectVersion>19.5</ProjectVersion> - <TargetedPlatforms>168083</TargetedPlatforms> + <ProjectVersion>20.1</ProjectVersion> + <TargetedPlatforms>693395</TargetedPlatforms> + <ProjectName Condition="'$(ProjectName)'==''">Python</ProjectName> </PropertyGroup> <PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''"> <Base>true</Base> @@ -54,6 +55,12 @@ <Cfg_1>true</Cfg_1> <Base>true</Base> </PropertyGroup> + <PropertyGroup Condition="('$(Platform)'=='iOSDevice64' and '$(Cfg_1)'=='true') or '$(Cfg_1_iOSDevice64)'!=''"> + <Cfg_1_iOSDevice64>true</Cfg_1_iOSDevice64> + <CfgParent>Cfg_1</CfgParent> + <Cfg_1>true</Cfg_1> + <Base>true</Base> + </PropertyGroup> <PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Cfg_1)'=='true') or '$(Cfg_1_Win64)'!=''"> <Cfg_1_Win64>true</Cfg_1_Win64> <CfgParent>Cfg_1</CfgParent> @@ -88,7 +95,7 @@ <DCC_DcuOutput>..\..\..\lib\$(Platform)\$(Config)</DCC_DcuOutput> <DCC_Description>Python4Delphi - Run-time Engine Package</DCC_Description> <DCC_ImageBase>00400000</DCC_ImageBase> - <DCC_Namespace>Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;DUnitX.Loggers.GUI;Winapi;System.Win;$(DCC_Namespace)</DCC_Namespace> + <DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;DUnitX.Loggers.GUI;Winapi;System.Win;$(DCC_Namespace)</DCC_Namespace> <DllSuffix>$(Auto)</DllSuffix> <GenDll>true</GenDll> <GenPackage>true</GenPackage> @@ -109,11 +116,11 @@ </PropertyGroup> <PropertyGroup Condition="'$(Base_OSX64)'!=''"> <BT_BuildType>Debug</BT_BuildType> - <VerInfo_Keys>CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities;NSLocationUsageDescription=The reason for accessing the location information of the user;NSContactsUsageDescription=The reason for accessing the contacts;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSCameraUsageDescription=The reason for accessing the camera;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSMotionUsageDescription=The reason for accessing the accelerometer;NSDesktopFolderUsageDescription=The reason for accessing the Desktop folder;NSDocumentsFolderUsageDescription=The reason for accessing the Documents folder;NSDownloadsFolderUsageDescription=The reason for accessing the Downloads folder;NSNetworkVolumesUsageDescription=The reason for accessing files on a network volume;NSRemovableVolumesUsageDescription=The reason for accessing files on a removable volume;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple's speech recognition servers;ITSAppUsesNonExemptEncryption=false</VerInfo_Keys> + <VerInfo_Keys>CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities;NSLocationUsageDescription=The reason for accessing the location information of the user;NSContactsUsageDescription=The reason for accessing the contacts;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSCameraUsageDescription=The reason for accessing the camera;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSMotionUsageDescription=The reason for accessing the accelerometer;NSDesktopFolderUsageDescription=The reason for accessing the Desktop folder;NSDocumentsFolderUsageDescription=The reason for accessing the Documents folder;NSDownloadsFolderUsageDescription=The reason for accessing the Downloads folder;NSNetworkVolumesUsageDescription=The reason for accessing files on a network volume;NSRemovableVolumesUsageDescription=The reason for accessing files on a removable volume;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple's speech recognition servers;ITSAppUsesNonExemptEncryption=false;NSBluetoothAlwaysUsageDescription=The reason for accessing the Bluetooth interface</VerInfo_Keys> </PropertyGroup> <PropertyGroup Condition="'$(Base_OSXARM64)'!=''"> <BT_BuildType>Debug</BT_BuildType> - <VerInfo_Keys>CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities;NSLocationUsageDescription=The reason for accessing the location information of the user;NSContactsUsageDescription=The reason for accessing the contacts;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSCameraUsageDescription=The reason for accessing the camera;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSMotionUsageDescription=The reason for accessing the accelerometer;NSDesktopFolderUsageDescription=The reason for accessing the Desktop folder;NSDocumentsFolderUsageDescription=The reason for accessing the Documents folder;NSDownloadsFolderUsageDescription=The reason for accessing the Downloads folder;NSNetworkVolumesUsageDescription=The reason for accessing files on a network volume;NSRemovableVolumesUsageDescription=The reason for accessing files on a removable volume;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple's speech recognition servers;ITSAppUsesNonExemptEncryption=false</VerInfo_Keys> + <VerInfo_Keys>CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities;NSLocationUsageDescription=The reason for accessing the location information of the user;NSContactsUsageDescription=The reason for accessing the contacts;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSCameraUsageDescription=The reason for accessing the camera;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSMotionUsageDescription=The reason for accessing the accelerometer;NSDesktopFolderUsageDescription=The reason for accessing the Desktop folder;NSDocumentsFolderUsageDescription=The reason for accessing the Documents folder;NSDownloadsFolderUsageDescription=The reason for accessing the Downloads folder;NSNetworkVolumesUsageDescription=The reason for accessing files on a network volume;NSRemovableVolumesUsageDescription=The reason for accessing files on a removable volume;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple's speech recognition servers;ITSAppUsesNonExemptEncryption=false;NSBluetoothAlwaysUsageDescription=The reason for accessing the Bluetooth interface</VerInfo_Keys> </PropertyGroup> <PropertyGroup Condition="'$(Base_Win32)'!=''"> <BT_BuildType>Debug</BT_BuildType> @@ -136,6 +143,9 @@ <VerInfo_Build>1</VerInfo_Build> <VerInfo_Keys>package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=</VerInfo_Keys> </PropertyGroup> + <PropertyGroup Condition="'$(Cfg_1_iOSDevice64)'!=''"> + <BT_BuildType>Debug</BT_BuildType> + </PropertyGroup> <PropertyGroup Condition="'$(Cfg_1_Win64)'!=''"> <VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo> <VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys> @@ -204,13 +214,14 @@ <Platforms> <Platform value="Android">True</Platform> <Platform value="Android64">True</Platform> + <Platform value="iOSDevice64">True</Platform> + <Platform value="iOSSimARM64">True</Platform> <Platform value="Linux64">True</Platform> <Platform value="OSX64">True</Platform> <Platform value="OSXARM64">True</Platform> <Platform value="Win32">True</Platform> <Platform value="Win64">True</Platform> - <Platform value="iOSDevice64">False</Platform> - <Platform value="iOSSimARM64">False</Platform> + <Platform value="Win64x">False</Platform> </Platforms> </BorlandProject> <ProjectFileVersion>12</ProjectFileVersion> diff --git a/Packages/Delphi/Delphi 10.4+/PythonFmx.dproj b/Packages/Delphi/Delphi 10.4+/PythonFmx.dproj index 224e44cc..e45231c0 100644 --- a/Packages/Delphi/Delphi 10.4+/PythonFmx.dproj +++ b/Packages/Delphi/Delphi 10.4+/PythonFmx.dproj @@ -7,8 +7,9 @@ <MainSource>PythonFmx.dpk</MainSource> <Platform Condition="'$(Platform)'==''">Win32</Platform> <ProjectGuid>{513BF750-373D-4C95-A672-78CA8DDF3F63}</ProjectGuid> - <ProjectVersion>19.5</ProjectVersion> - <TargetedPlatforms>167955</TargetedPlatforms> + <ProjectVersion>20.1</ProjectVersion> + <TargetedPlatforms>693395</TargetedPlatforms> + <ProjectName Condition="'$(ProjectName)'==''">PythonFmx</ProjectName> </PropertyGroup> <PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''"> <Base>true</Base> @@ -59,9 +60,14 @@ <CfgParent>Base</CfgParent> <Base>true</Base> </PropertyGroup> + <PropertyGroup Condition="('$(Platform)'=='iOSDevice64' and '$(Cfg_2)'=='true') or '$(Cfg_2_iOSDevice64)'!=''"> + <Cfg_2_iOSDevice64>true</Cfg_2_iOSDevice64> + <CfgParent>Cfg_2</CfgParent> + <Cfg_2>true</Cfg_2> + <Base>true</Base> + </PropertyGroup> <PropertyGroup Condition="'$(Base)'!=''"> <SanitizedProjectName>PythonFmx</SanitizedProjectName> - <DCC_CBuilderOutput>All</DCC_CBuilderOutput> <DCC_DcuOutput>..\..\..\lib\$(Platform)\$(Config)</DCC_DcuOutput> <DCC_Description>Python4Delphi - Run-time Engine Package for FMX</DCC_Description> <DCC_ExeOutput>.\$(Platform)\$(Config)</DCC_ExeOutput> @@ -87,11 +93,11 @@ </PropertyGroup> <PropertyGroup Condition="'$(Base_OSX64)'!=''"> <BT_BuildType>Debug</BT_BuildType> - <VerInfo_Keys>CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities;NSLocationUsageDescription=The reason for accessing the location information of the user;NSContactsUsageDescription=The reason for accessing the contacts;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSCameraUsageDescription=The reason for accessing the camera;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSMotionUsageDescription=The reason for accessing the accelerometer;NSDesktopFolderUsageDescription=The reason for accessing the Desktop folder;NSDocumentsFolderUsageDescription=The reason for accessing the Documents folder;NSDownloadsFolderUsageDescription=The reason for accessing the Downloads folder;NSNetworkVolumesUsageDescription=The reason for accessing files on a network volume;NSRemovableVolumesUsageDescription=The reason for accessing files on a removable volume;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple's speech recognition servers;ITSAppUsesNonExemptEncryption=false</VerInfo_Keys> + <VerInfo_Keys>CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities;NSLocationUsageDescription=The reason for accessing the location information of the user;NSContactsUsageDescription=The reason for accessing the contacts;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSCameraUsageDescription=The reason for accessing the camera;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSMotionUsageDescription=The reason for accessing the accelerometer;NSDesktopFolderUsageDescription=The reason for accessing the Desktop folder;NSDocumentsFolderUsageDescription=The reason for accessing the Documents folder;NSDownloadsFolderUsageDescription=The reason for accessing the Downloads folder;NSNetworkVolumesUsageDescription=The reason for accessing files on a network volume;NSRemovableVolumesUsageDescription=The reason for accessing files on a removable volume;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple's speech recognition servers;ITSAppUsesNonExemptEncryption=false;NSBluetoothAlwaysUsageDescription=The reason for accessing the Bluetooth interface</VerInfo_Keys> </PropertyGroup> <PropertyGroup Condition="'$(Base_OSXARM64)'!=''"> <BT_BuildType>Debug</BT_BuildType> - <VerInfo_Keys>CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities;NSLocationUsageDescription=The reason for accessing the location information of the user;NSContactsUsageDescription=The reason for accessing the contacts;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSCameraUsageDescription=The reason for accessing the camera;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSMotionUsageDescription=The reason for accessing the accelerometer;NSDesktopFolderUsageDescription=The reason for accessing the Desktop folder;NSDocumentsFolderUsageDescription=The reason for accessing the Documents folder;NSDownloadsFolderUsageDescription=The reason for accessing the Downloads folder;NSNetworkVolumesUsageDescription=The reason for accessing files on a network volume;NSRemovableVolumesUsageDescription=The reason for accessing files on a removable volume;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple's speech recognition servers;ITSAppUsesNonExemptEncryption=false</VerInfo_Keys> + <VerInfo_Keys>CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities;NSLocationUsageDescription=The reason for accessing the location information of the user;NSContactsUsageDescription=The reason for accessing the contacts;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSCameraUsageDescription=The reason for accessing the camera;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSMotionUsageDescription=The reason for accessing the accelerometer;NSDesktopFolderUsageDescription=The reason for accessing the Desktop folder;NSDocumentsFolderUsageDescription=The reason for accessing the Documents folder;NSDownloadsFolderUsageDescription=The reason for accessing the Downloads folder;NSNetworkVolumesUsageDescription=The reason for accessing files on a network volume;NSRemovableVolumesUsageDescription=The reason for accessing files on a removable volume;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple's speech recognition servers;ITSAppUsesNonExemptEncryption=false;NSBluetoothAlwaysUsageDescription=The reason for accessing the Bluetooth interface</VerInfo_Keys> </PropertyGroup> <PropertyGroup Condition="'$(Base_Win32)'!=''"> <BT_BuildType>Debug</BT_BuildType> @@ -127,6 +133,9 @@ <DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols> <DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo> </PropertyGroup> + <PropertyGroup Condition="'$(Cfg_2_iOSDevice64)'!=''"> + <BT_BuildType>Debug</BT_BuildType> + </PropertyGroup> <ItemGroup> <DelphiCompile Include="$(MainSource)"> <MainSource>MainSource</MainSource> @@ -185,13 +194,14 @@ <Platforms> <Platform value="Android">True</Platform> <Platform value="Android64">True</Platform> - <Platform value="Linux64">False</Platform> + <Platform value="iOSDevice64">True</Platform> + <Platform value="iOSSimARM64">True</Platform> + <Platform value="Linux64">True</Platform> <Platform value="OSX64">True</Platform> <Platform value="OSXARM64">True</Platform> <Platform value="Win32">True</Platform> <Platform value="Win64">True</Platform> - <Platform value="iOSDevice64">False</Platform> - <Platform value="iOSSimARM64">False</Platform> + <Platform value="Win64x">False</Platform> </Platforms> </BorlandProject> <ProjectFileVersion>12</ProjectFileVersion> diff --git a/Packages/Delphi/Delphi 10.4+/PythonFmxLinux.dpk b/Packages/Delphi/Delphi 10.4+/PythonFmxLinux.dpk deleted file mode 100644 index 9525324e..00000000 --- a/Packages/Delphi/Delphi 10.4+/PythonFmxLinux.dpk +++ /dev/null @@ -1,63 +0,0 @@ -package PythonFmxLinux; - -{$R *.res} -{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users} -{$ALIGN 8} -{$ASSERTIONS ON} -{$BOOLEVAL OFF} -{$DEBUGINFO OFF} -{$EXTENDEDSYNTAX ON} -{$IMPORTEDDATA ON} -{$IOCHECKS ON} -{$LOCALSYMBOLS OFF} -{$LONGSTRINGS ON} -{$OPENSTRINGS ON} -{$OPTIMIZATION ON} -{$OVERFLOWCHECKS OFF} -{$RANGECHECKS OFF} -{$REFERENCEINFO OFF} -{$SAFEDIVIDE OFF} -{$STACKFRAMES OFF} -{$TYPEDADDRESS OFF} -{$VARSTRINGCHECKS ON} -{$WRITEABLECONST OFF} -{$MINENUMSIZE 1} -{$DEFINE RELEASE} -{$ENDIF IMPLICITBUILDING} -{$DESCRIPTION 'Python4Delphi - Run-time Engine Package for FMXLinux'} -{$LIBSUFFIX AUTO} -{$RUNONLY} -{$IMPLICITBUILD ON} - -requires - rtl, - python, - fmx; - -contains - FMX.PythonGUIInputOutput in '..\..\..\Source\fmx\FMX.PythonGUIInputOutput.pas', - WrapDelphiFmx in '..\..\..\Source\fmx\WrapDelphiFmx.pas', - WrapFmxActnList in '..\..\..\Source\fmx\WrapFmxActnList.pas', - WrapFmxColors in '..\..\..\Source\fmx\WrapFmxColors.pas', - WrapFmxComCtrls in '..\..\..\Source\fmx\WrapFmxComCtrls.pas', - WrapFmxControls in '..\..\..\Source\fmx\WrapFmxControls.pas', - WrapFmxDialogs in '..\..\..\Source\fmx\WrapFmxDialogs.pas', - WrapFmxEdit in '..\..\..\Source\fmx\WrapFmxEdit.pas', - WrapFmxForms in '..\..\..\Source\fmx\WrapFmxForms.pas', - WrapFmxGrids in '..\..\..\Source\fmx\WrapFmxGrids.pas', - WrapFmxLayouts in '..\..\..\Source\fmx\WrapFmxLayouts.pas', - WrapFmxListBox in '..\..\..\Source\fmx\WrapFmxListBox.pas', - WrapFmxListView in '..\..\..\Source\fmx\WrapFmxListView.pas', - WrapFmxMedia in '..\..\..\Source\fmx\WrapFmxMedia.pas', - WrapFmxMemo in '..\..\..\Source\fmx\WrapFmxMemo.pas', - WrapFmxMenus in '..\..\..\Source\fmx\WrapFmxMenus.pas', - WrapFmxScrollBox in '..\..\..\Source\fmx\WrapFmxScrollBox.pas', - WrapFmxShapes in '..\..\..\Source\fmx\WrapFmxShapes.pas', - WrapFmxStdActns in '..\..\..\Source\fmx\WrapFmxStdActns.pas', - WrapFmxStdCtrls in '..\..\..\Source\fmx\WrapFmxStdCtrls.pas', - WrapFmxStyles in '..\..\..\Source\fmx\WrapFmxStyles.pas', - WrapFmxTypes in '..\..\..\Source\fmx\WrapFmxTypes.pas', - WrapFmxDateTime in '..\..\..\Source\fmx\WrapFmxDateTime.pas'; - -end. - diff --git a/Packages/Delphi/Delphi 10.4+/PythonFmxLinux.dproj b/Packages/Delphi/Delphi 10.4+/PythonFmxLinux.dproj deleted file mode 100644 index 445f21ac..00000000 --- a/Packages/Delphi/Delphi 10.4+/PythonFmxLinux.dproj +++ /dev/null @@ -1,968 +0,0 @@ -<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <PropertyGroup> - <ProjectGuid>{B0F48139-24FB-42F3-93E8-05DA2E142904}</ProjectGuid> - <MainSource>PythonFmxLinux.dpk</MainSource> - <Base>True</Base> - <Config Condition="'$(Config)'==''">Release</Config> - <TargetedPlatforms>128</TargetedPlatforms> - <AppType>Package</AppType> - <FrameworkType>FMX</FrameworkType> - <ProjectVersion>19.5</ProjectVersion> - <Platform Condition="'$(Platform)'==''">Linux64</Platform> - </PropertyGroup> - <PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''"> - <Base>true</Base> - </PropertyGroup> - <PropertyGroup Condition="('$(Platform)'=='Android' and '$(Base)'=='true') or '$(Base_Android)'!=''"> - <Base_Android>true</Base_Android> - <CfgParent>Base</CfgParent> - <Base>true</Base> - </PropertyGroup> - <PropertyGroup Condition="('$(Platform)'=='Android64' and '$(Base)'=='true') or '$(Base_Android64)'!=''"> - <Base_Android64>true</Base_Android64> - <CfgParent>Base</CfgParent> - <Base>true</Base> - </PropertyGroup> - <PropertyGroup Condition="('$(Platform)'=='iOSDevice64' and '$(Base)'=='true') or '$(Base_iOSDevice64)'!=''"> - <Base_iOSDevice64>true</Base_iOSDevice64> - <CfgParent>Base</CfgParent> - <Base>true</Base> - </PropertyGroup> - <PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Base)'=='true') or '$(Base_Win32)'!=''"> - <Base_Win32>true</Base_Win32> - <CfgParent>Base</CfgParent> - <Base>true</Base> - </PropertyGroup> - <PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_1)'!=''"> - <Cfg_1>true</Cfg_1> - <CfgParent>Base</CfgParent> - <Base>true</Base> - </PropertyGroup> - <PropertyGroup Condition="('$(Platform)'=='Linux64' and '$(Cfg_1)'=='true') or '$(Cfg_1_Linux64)'!=''"> - <Cfg_1_Linux64>true</Cfg_1_Linux64> - <CfgParent>Cfg_1</CfgParent> - <Cfg_1>true</Cfg_1> - <Base>true</Base> - </PropertyGroup> - <PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_2)'!=''"> - <Cfg_2>true</Cfg_2> - <CfgParent>Base</CfgParent> - <Base>true</Base> - </PropertyGroup> - <PropertyGroup Condition="('$(Platform)'=='Android64' and '$(Cfg_2)'=='true') or '$(Cfg_2_Android64)'!=''"> - <Cfg_2_Android64>true</Cfg_2_Android64> - <CfgParent>Cfg_2</CfgParent> - <Cfg_2>true</Cfg_2> - <Base>true</Base> - </PropertyGroup> - <PropertyGroup Condition="('$(Platform)'=='iOSDevice64' and '$(Cfg_2)'=='true') or '$(Cfg_2_iOSDevice64)'!=''"> - <Cfg_2_iOSDevice64>true</Cfg_2_iOSDevice64> - <CfgParent>Cfg_2</CfgParent> - <Cfg_2>true</Cfg_2> - <Base>true</Base> - </PropertyGroup> - <PropertyGroup Condition="('$(Platform)'=='OSX64' and '$(Cfg_2)'=='true') or '$(Cfg_2_OSX64)'!=''"> - <Cfg_2_OSX64>true</Cfg_2_OSX64> - <CfgParent>Cfg_2</CfgParent> - <Cfg_2>true</Cfg_2> - <Base>true</Base> - </PropertyGroup> - <PropertyGroup Condition="('$(Platform)'=='OSXARM64' and '$(Cfg_2)'=='true') or '$(Cfg_2_OSXARM64)'!=''"> - <Cfg_2_OSXARM64>true</Cfg_2_OSXARM64> - <CfgParent>Cfg_2</CfgParent> - <Cfg_2>true</Cfg_2> - <Base>true</Base> - </PropertyGroup> - <PropertyGroup Condition="'$(Base)'!=''"> - <DCC_E>false</DCC_E> - <DCC_F>false</DCC_F> - <DCC_K>false</DCC_K> - <DCC_N>false</DCC_N> - <DCC_S>false</DCC_S> - <DCC_ImageBase>00400000</DCC_ImageBase> - <GenDll>true</GenDll> - <GenPackage>true</GenPackage> - <SanitizedProjectName>PythonFmxLinux</SanitizedProjectName> - <DCC_Description>Python4Delphi - Run-time Engine Package for FMXLinux</DCC_Description> - <DllSuffix>$(Auto)</DllSuffix> - <RuntimeOnlyPackage>true</RuntimeOnlyPackage> - <VerInfo_Locale>1046</VerInfo_Locale> - <VerInfo_Keys>CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName=</VerInfo_Keys> - <DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;REST.Authenticator.OAuth.WebForm;$(DCC_Namespace)</DCC_Namespace> - <DCC_UnitSearchPath>$(BDSCatalogRepositoryAllUsers)\FmxLinux-1.71\redist;$(DCC_UnitSearchPath)</DCC_UnitSearchPath> - </PropertyGroup> - <PropertyGroup Condition="'$(Base_Android)'!=''"> - <VerInfo_Keys>package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=</VerInfo_Keys> - <BT_BuildType>Debug</BT_BuildType> - <Android_LauncherIcon192>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png</Android_LauncherIcon192> - <EnabledSysJars>annotation-1.2.0.dex.jar;asynclayoutinflater-1.0.0.dex.jar;billing-4.0.0.dex.jar;browser-1.0.0.dex.jar;cloud-messaging.dex.jar;collection-1.0.0.dex.jar;coordinatorlayout-1.0.0.dex.jar;core-1.5.0-rc02.dex.jar;core-common-2.0.1.dex.jar;core-runtime-2.0.1.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;firebase-annotations-16.0.0.dex.jar;firebase-common-20.0.0.dex.jar;firebase-components-17.0.0.dex.jar;firebase-datatransport-18.0.0.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.0.0.dex.jar;firebase-installations-interop-17.0.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-22.0.0.dex.jar;fmx.dex.jar;fragment-1.0.0.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;legacy-support-core-ui-1.0.0.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.0.0.dex.jar;lifecycle-livedata-2.0.0.dex.jar;lifecycle-livedata-core-2.0.0.dex.jar;lifecycle-runtime-2.0.0.dex.jar;lifecycle-service-2.0.0.dex.jar;lifecycle-viewmodel-2.0.0.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;play-services-ads-20.1.0.dex.jar;play-services-ads-base-20.1.0.dex.jar;play-services-ads-identifier-17.0.0.dex.jar;play-services-ads-lite-20.1.0.dex.jar;play-services-base-17.5.0.dex.jar;play-services-basement-17.6.0.dex.jar;play-services-cloud-messaging-16.0.0.dex.jar;play-services-drive-17.0.0.dex.jar;play-services-games-21.0.0.dex.jar;play-services-location-18.0.0.dex.jar;play-services-maps-17.0.1.dex.jar;play-services-measurement-base-18.0.0.dex.jar;play-services-measurement-sdk-api-18.0.0.dex.jar;play-services-places-placereport-17.0.0.dex.jar;play-services-stats-17.0.0.dex.jar;play-services-tasks-17.2.0.dex.jar;print-1.0.0.dex.jar;room-common-2.1.0.dex.jar;room-runtime-2.1.0.dex.jar;slidingpanelayout-1.0.0.dex.jar;sqlite-2.0.1.dex.jar;sqlite-framework-2.0.1.dex.jar;swiperefreshlayout-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.0.0.dex.jar;transport-runtime-3.0.0.dex.jar;user-messaging-platform-1.0.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.1.0.dex.jar</EnabledSysJars> - </PropertyGroup> - <PropertyGroup Condition="'$(Base_Android64)'!=''"> - <Android_LauncherIcon192>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png</Android_LauncherIcon192> - <EnabledSysJars>annotation-1.2.0.dex.jar;asynclayoutinflater-1.0.0.dex.jar;billing-4.0.0.dex.jar;browser-1.0.0.dex.jar;cloud-messaging.dex.jar;collection-1.0.0.dex.jar;coordinatorlayout-1.0.0.dex.jar;core-1.5.0-rc02.dex.jar;core-common-2.0.1.dex.jar;core-runtime-2.0.1.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;firebase-annotations-16.0.0.dex.jar;firebase-common-20.0.0.dex.jar;firebase-components-17.0.0.dex.jar;firebase-datatransport-18.0.0.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.0.0.dex.jar;firebase-installations-interop-17.0.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-22.0.0.dex.jar;fmx.dex.jar;fragment-1.0.0.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;legacy-support-core-ui-1.0.0.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.0.0.dex.jar;lifecycle-livedata-2.0.0.dex.jar;lifecycle-livedata-core-2.0.0.dex.jar;lifecycle-runtime-2.0.0.dex.jar;lifecycle-service-2.0.0.dex.jar;lifecycle-viewmodel-2.0.0.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;play-services-ads-20.1.0.dex.jar;play-services-ads-base-20.1.0.dex.jar;play-services-ads-identifier-17.0.0.dex.jar;play-services-ads-lite-20.1.0.dex.jar;play-services-base-17.5.0.dex.jar;play-services-basement-17.6.0.dex.jar;play-services-cloud-messaging-16.0.0.dex.jar;play-services-drive-17.0.0.dex.jar;play-services-games-21.0.0.dex.jar;play-services-location-18.0.0.dex.jar;play-services-maps-17.0.1.dex.jar;play-services-measurement-base-18.0.0.dex.jar;play-services-measurement-sdk-api-18.0.0.dex.jar;play-services-places-placereport-17.0.0.dex.jar;play-services-stats-17.0.0.dex.jar;play-services-tasks-17.2.0.dex.jar;print-1.0.0.dex.jar;room-common-2.1.0.dex.jar;room-runtime-2.1.0.dex.jar;slidingpanelayout-1.0.0.dex.jar;sqlite-2.0.1.dex.jar;sqlite-framework-2.0.1.dex.jar;swiperefreshlayout-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.0.0.dex.jar;transport-runtime-3.0.0.dex.jar;user-messaging-platform-1.0.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.1.0.dex.jar</EnabledSysJars> - </PropertyGroup> - <PropertyGroup Condition="'$(Base_iOSDevice64)'!=''"> - <iOS_AppStore1024>$(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_1024x1024.png</iOS_AppStore1024> - </PropertyGroup> - <PropertyGroup Condition="'$(Base_Win32)'!=''"> - <DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace> - <BT_BuildType>Debug</BT_BuildType> - <VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo> - <VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)</VerInfo_Keys> - <VerInfo_Locale>1033</VerInfo_Locale> - </PropertyGroup> - <PropertyGroup Condition="'$(Cfg_1)'!=''"> - <DCC_Define>RELEASE;$(DCC_Define)</DCC_Define> - <DCC_DebugInformation>0</DCC_DebugInformation> - <DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols> - <DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo> - </PropertyGroup> - <PropertyGroup Condition="'$(Cfg_1_Linux64)'!=''"> - <Debugger_Launcher>/usr/bin/gnome-terminal -- "%debuggee%"</Debugger_Launcher> - </PropertyGroup> - <PropertyGroup Condition="'$(Cfg_2)'!=''"> - <DCC_Define>DEBUG;$(DCC_Define)</DCC_Define> - <DCC_Optimize>false</DCC_Optimize> - <DCC_GenerateStackFrames>true</DCC_GenerateStackFrames> - <DCC_RangeChecking>true</DCC_RangeChecking> - <DCC_IntegerOverflowCheck>true</DCC_IntegerOverflowCheck> - </PropertyGroup> - <PropertyGroup Condition="'$(Cfg_2_Android64)'!=''"> - <BT_BuildType>Debug</BT_BuildType> - </PropertyGroup> - <PropertyGroup Condition="'$(Cfg_2_iOSDevice64)'!=''"> - <BT_BuildType>Debug</BT_BuildType> - </PropertyGroup> - <PropertyGroup Condition="'$(Cfg_2_OSX64)'!=''"> - <BT_BuildType>Debug</BT_BuildType> - </PropertyGroup> - <PropertyGroup Condition="'$(Cfg_2_OSXARM64)'!=''"> - <BT_BuildType>Debug</BT_BuildType> - </PropertyGroup> - <ItemGroup> - <DelphiCompile Include="$(MainSource)"> - <MainSource>MainSource</MainSource> - </DelphiCompile> - <DCCReference Include="rtl.dcp"/> - <DCCReference Include="python.dcp"/> - <DCCReference Include="fmx.dcp"/> - <DCCReference Include="..\..\..\Source\fmx\FMX.PythonGUIInputOutput.pas"/> - <DCCReference Include="..\..\..\Source\fmx\WrapDelphiFmx.pas"/> - <DCCReference Include="..\..\..\Source\fmx\WrapFmxActnList.pas"/> - <DCCReference Include="..\..\..\Source\fmx\WrapFmxColors.pas"/> - <DCCReference Include="..\..\..\Source\fmx\WrapFmxComCtrls.pas"/> - <DCCReference Include="..\..\..\Source\fmx\WrapFmxControls.pas"/> - <DCCReference Include="..\..\..\Source\fmx\WrapFmxDialogs.pas"/> - <DCCReference Include="..\..\..\Source\fmx\WrapFmxEdit.pas"/> - <DCCReference Include="..\..\..\Source\fmx\WrapFmxForms.pas"/> - <DCCReference Include="..\..\..\Source\fmx\WrapFmxGrids.pas"/> - <DCCReference Include="..\..\..\Source\fmx\WrapFmxLayouts.pas"/> - <DCCReference Include="..\..\..\Source\fmx\WrapFmxListBox.pas"/> - <DCCReference Include="..\..\..\Source\fmx\WrapFmxListView.pas"/> - <DCCReference Include="..\..\..\Source\fmx\WrapFmxMedia.pas"/> - <DCCReference Include="..\..\..\Source\fmx\WrapFmxMemo.pas"/> - <DCCReference Include="..\..\..\Source\fmx\WrapFmxMenus.pas"/> - <DCCReference Include="..\..\..\Source\fmx\WrapFmxScrollBox.pas"/> - <DCCReference Include="..\..\..\Source\fmx\WrapFmxShapes.pas"/> - <DCCReference Include="..\..\..\Source\fmx\WrapFmxStdActns.pas"/> - <DCCReference Include="..\..\..\Source\fmx\WrapFmxStdCtrls.pas"/> - <DCCReference Include="..\..\..\Source\fmx\WrapFmxStyles.pas"/> - <DCCReference Include="..\..\..\Source\fmx\WrapFmxTypes.pas"/> - <DCCReference Include="..\..\..\Source\fmx\WrapFmxDateTime.pas"/> - <BuildConfiguration Include="Base"> - <Key>Base</Key> - </BuildConfiguration> - <BuildConfiguration Include="Release"> - <Key>Cfg_1</Key> - <CfgParent>Base</CfgParent> - </BuildConfiguration> - <BuildConfiguration Include="Debug"> - <Key>Cfg_2</Key> - <CfgParent>Base</CfgParent> - </BuildConfiguration> - </ItemGroup> - <ProjectExtensions> - <Borland.Personality>Delphi.Personality.12</Borland.Personality> - <Borland.ProjectType>Package</Borland.ProjectType> - <BorlandProject> - <Delphi.Personality> - <Source> - <Source Name="MainSource">PythonFmxLinux.dpk</Source> - </Source> - <Excluded_Packages> - <Excluded_Packages Name="$(BDSBIN)\bcboffice2k280.bpl">Embarcadero C++Builder Office 2000 Servers Package</Excluded_Packages> - <Excluded_Packages Name="$(BDSBIN)\bcbofficexp280.bpl">Embarcadero C++Builder Office XP Servers Package</Excluded_Packages> - <Excluded_Packages Name="$(BDSBIN)\dcloffice2k280.bpl">Microsoft Office 2000 Sample Automation Server Wrapper Components</Excluded_Packages> - <Excluded_Packages Name="$(BDSBIN)\dclofficexp280.bpl">Microsoft Office XP Sample Automation Server Wrapper Components</Excluded_Packages> - </Excluded_Packages> - </Delphi.Personality> - <Platforms> - <Platform value="Android">False</Platform> - <Platform value="Android64">False</Platform> - <Platform value="iOSDevice64">False</Platform> - <Platform value="iOSSimARM64">False</Platform> - <Platform value="Linux64">True</Platform> - <Platform value="OSX64">False</Platform> - <Platform value="OSXARM64">False</Platform> - <Platform value="Win32">False</Platform> - <Platform value="Win64">False</Platform> - </Platforms> - <Deployment Version="4"> - <DeployFile LocalName="$(BDS)\Redist\iossimulator\libcgunwind.1.0.dylib" Class="DependencyModule"> - <Platform Name="iOSSimulator"> - <Overwrite>true</Overwrite> - </Platform> - </DeployFile> - <DeployFile LocalName="$(BDS)\Redist\iossimulator\libpcre.dylib" Class="DependencyModule"> - <Platform Name="iOSSimulator"> - <Overwrite>true</Overwrite> - </Platform> - </DeployFile> - <DeployFile LocalName="$(BDS)\Redist\osx32\libcgunwind.1.0.dylib" Class="DependencyModule"> - <Platform Name="OSX32"> - <Overwrite>true</Overwrite> - </Platform> - </DeployFile> - <DeployFile LocalName="C:\Users\Public\Documents\Embarcadero\Studio\22.0\Bpl\Linux64\bplPythonFmxLinux280.so" Configuration="Release" Class="ProjectOutput"> - <Platform Name="Linux64"> - <RemoteName>bplPythonFmxLinux.so</RemoteName> - <Overwrite>true</Overwrite> - </Platform> - </DeployFile> - <DeployFile LocalName="C:\Users\Public\Documents\Embarcadero\Studio\22.0\Bpl\PythonFmxLinux280.bpl" Configuration="Debug" Class="ProjectOutput"> - <Platform Name="Win32"> - <RemoteName>PythonFmxLinux.bpl</RemoteName> - <Overwrite>true</Overwrite> - </Platform> - </DeployFile> - <DeployClass Name="AdditionalDebugSymbols"> - <Platform Name="OSX32"> - <Operation>1</Operation> - </Platform> - <Platform Name="Win32"> - <Operation>0</Operation> - </Platform> - </DeployClass> - <DeployClass Name="AndroidClasses"> - <Platform Name="Android"> - <RemoteDir>classes</RemoteDir> - <Operation>64</Operation> - </Platform> - <Platform Name="Android64"> - <RemoteDir>classes</RemoteDir> - <Operation>64</Operation> - </Platform> - </DeployClass> - <DeployClass Name="AndroidFileProvider"> - <Platform Name="Android"> - <RemoteDir>res\xml</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="Android64"> - <RemoteDir>res\xml</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="AndroidGDBServer"> - <Platform Name="Android"> - <RemoteDir>library\lib\armeabi-v7a</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="AndroidLibnativeArmeabiFile"> - <Platform Name="Android"> - <RemoteDir>library\lib\armeabi</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="Android64"> - <RemoteDir>library\lib\armeabi</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="AndroidLibnativeArmeabiv7aFile"> - <Platform Name="Android64"> - <RemoteDir>library\lib\armeabi-v7a</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="AndroidLibnativeMipsFile"> - <Platform Name="Android"> - <RemoteDir>library\lib\mips</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="Android64"> - <RemoteDir>library\lib\mips</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="AndroidServiceOutput"> - <Platform Name="Android"> - <RemoteDir>library\lib\armeabi-v7a</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="Android64"> - <RemoteDir>library\lib\arm64-v8a</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="AndroidServiceOutput_Android32"> - <Platform Name="Android64"> - <RemoteDir>library\lib\armeabi-v7a</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="AndroidSplashImageDef"> - <Platform Name="Android"> - <RemoteDir>res\drawable</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="Android64"> - <RemoteDir>res\drawable</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="AndroidSplashStyles"> - <Platform Name="Android"> - <RemoteDir>res\values</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="Android64"> - <RemoteDir>res\values</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="AndroidSplashStylesV21"> - <Platform Name="Android"> - <RemoteDir>res\values-v21</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="Android64"> - <RemoteDir>res\values-v21</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="Android_Colors"> - <Platform Name="Android"> - <RemoteDir>res\values</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="Android64"> - <RemoteDir>res\values</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="Android_DefaultAppIcon"> - <Platform Name="Android"> - <RemoteDir>res\drawable</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="Android64"> - <RemoteDir>res\drawable</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="Android_LauncherIcon144"> - <Platform Name="Android"> - <RemoteDir>res\drawable-xxhdpi</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="Android64"> - <RemoteDir>res\drawable-xxhdpi</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="Android_LauncherIcon192"> - <Platform Name="Android"> - <RemoteDir>res\drawable-xxxhdpi</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="Android64"> - <RemoteDir>res\drawable-xxxhdpi</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="Android_LauncherIcon36"> - <Platform Name="Android"> - <RemoteDir>res\drawable-ldpi</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="Android64"> - <RemoteDir>res\drawable-ldpi</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="Android_LauncherIcon48"> - <Platform Name="Android"> - <RemoteDir>res\drawable-mdpi</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="Android64"> - <RemoteDir>res\drawable-mdpi</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="Android_LauncherIcon72"> - <Platform Name="Android"> - <RemoteDir>res\drawable-hdpi</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="Android64"> - <RemoteDir>res\drawable-hdpi</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="Android_LauncherIcon96"> - <Platform Name="Android"> - <RemoteDir>res\drawable-xhdpi</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="Android64"> - <RemoteDir>res\drawable-xhdpi</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="Android_NotificationIcon24"> - <Platform Name="Android"> - <RemoteDir>res\drawable-mdpi</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="Android64"> - <RemoteDir>res\drawable-mdpi</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="Android_NotificationIcon36"> - <Platform Name="Android"> - <RemoteDir>res\drawable-hdpi</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="Android64"> - <RemoteDir>res\drawable-hdpi</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="Android_NotificationIcon48"> - <Platform Name="Android"> - <RemoteDir>res\drawable-xhdpi</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="Android64"> - <RemoteDir>res\drawable-xhdpi</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="Android_NotificationIcon72"> - <Platform Name="Android"> - <RemoteDir>res\drawable-xxhdpi</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="Android64"> - <RemoteDir>res\drawable-xxhdpi</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="Android_NotificationIcon96"> - <Platform Name="Android"> - <RemoteDir>res\drawable-xxxhdpi</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="Android64"> - <RemoteDir>res\drawable-xxxhdpi</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="Android_SplashImage426"> - <Platform Name="Android"> - <RemoteDir>res\drawable-small</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="Android64"> - <RemoteDir>res\drawable-small</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="Android_SplashImage470"> - <Platform Name="Android"> - <RemoteDir>res\drawable-normal</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="Android64"> - <RemoteDir>res\drawable-normal</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="Android_SplashImage640"> - <Platform Name="Android"> - <RemoteDir>res\drawable-large</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="Android64"> - <RemoteDir>res\drawable-large</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="Android_SplashImage960"> - <Platform Name="Android"> - <RemoteDir>res\drawable-xlarge</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="Android64"> - <RemoteDir>res\drawable-xlarge</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="Android_Strings"> - <Platform Name="Android"> - <RemoteDir>res\values</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="Android64"> - <RemoteDir>res\values</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="DebugSymbols"> - <Platform Name="iOSSimulator"> - <Operation>1</Operation> - </Platform> - <Platform Name="OSX32"> - <Operation>1</Operation> - </Platform> - <Platform Name="Win32"> - <Operation>0</Operation> - </Platform> - </DeployClass> - <DeployClass Name="DependencyFramework"> - <Platform Name="OSX32"> - <Operation>1</Operation> - <Extensions>.framework</Extensions> - </Platform> - <Platform Name="OSX64"> - <Operation>1</Operation> - <Extensions>.framework</Extensions> - </Platform> - <Platform Name="OSXARM64"> - <Operation>1</Operation> - <Extensions>.framework</Extensions> - </Platform> - <Platform Name="Win32"> - <Operation>0</Operation> - </Platform> - </DeployClass> - <DeployClass Name="DependencyModule"> - <Platform Name="OSX32"> - <Operation>1</Operation> - <Extensions>.dylib</Extensions> - </Platform> - <Platform Name="OSX64"> - <Operation>1</Operation> - <Extensions>.dylib</Extensions> - </Platform> - <Platform Name="OSXARM64"> - <Operation>1</Operation> - <Extensions>.dylib</Extensions> - </Platform> - <Platform Name="Win32"> - <Operation>0</Operation> - <Extensions>.dll;.bpl</Extensions> - </Platform> - </DeployClass> - <DeployClass Required="true" Name="DependencyPackage"> - <Platform Name="iOSDevice32"> - <Operation>1</Operation> - <Extensions>.dylib</Extensions> - </Platform> - <Platform Name="iOSDevice64"> - <Operation>1</Operation> - <Extensions>.dylib</Extensions> - </Platform> - <Platform Name="iOSSimARM64"> - <Operation>1</Operation> - <Extensions>.dylib</Extensions> - </Platform> - <Platform Name="OSX32"> - <Operation>1</Operation> - <Extensions>.dylib</Extensions> - </Platform> - <Platform Name="OSX64"> - <Operation>1</Operation> - <Extensions>.dylib</Extensions> - </Platform> - <Platform Name="OSXARM64"> - <Operation>1</Operation> - <Extensions>.dylib</Extensions> - </Platform> - <Platform Name="Win32"> - <Operation>0</Operation> - <Extensions>.bpl</Extensions> - </Platform> - </DeployClass> - <DeployClass Name="File"> - <Platform Name="Android"> - <Operation>0</Operation> - </Platform> - <Platform Name="Android64"> - <Operation>0</Operation> - </Platform> - <Platform Name="iOSDevice32"> - <Operation>0</Operation> - </Platform> - <Platform Name="iOSDevice64"> - <Operation>0</Operation> - </Platform> - <Platform Name="iOSSimARM64"> - <Operation>0</Operation> - </Platform> - <Platform Name="OSX32"> - <Operation>0</Operation> - </Platform> - <Platform Name="OSX64"> - <Operation>0</Operation> - </Platform> - <Platform Name="OSXARM64"> - <Operation>0</Operation> - </Platform> - <Platform Name="Win32"> - <Operation>0</Operation> - </Platform> - </DeployClass> - <DeployClass Name="iOS_AppStore1024"> - <Platform Name="iOSDevice64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="iOSSimARM64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="iPad_AppIcon152"> - <Platform Name="iOSDevice64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="iOSSimARM64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="iPad_AppIcon167"> - <Platform Name="iOSDevice64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="iOSSimARM64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="iPad_Launch2x"> - <Platform Name="iOSDevice64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="iOSSimARM64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="iPad_LaunchDark2x"> - <Platform Name="iOSDevice64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="iOSSimARM64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="iPad_Notification40"> - <Platform Name="iOSDevice64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="iOSSimARM64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="iPad_Setting58"> - <Platform Name="iOSDevice64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="iOSSimARM64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="iPad_SpotLight80"> - <Platform Name="iOSDevice64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="iOSSimARM64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="iPhone_AppIcon120"> - <Platform Name="iOSDevice64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="iOSSimARM64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="iPhone_AppIcon180"> - <Platform Name="iOSDevice64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="iOSSimARM64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="iPhone_Launch2x"> - <Platform Name="iOSDevice64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="iOSSimARM64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="iPhone_Launch3x"> - <Platform Name="iOSDevice64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="iOSSimARM64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="iPhone_LaunchDark2x"> - <Platform Name="iOSDevice64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="iOSSimARM64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="iPhone_LaunchDark3x"> - <Platform Name="iOSDevice64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="iOSSimARM64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="iPhone_Notification40"> - <Platform Name="iOSDevice64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="iOSSimARM64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="iPhone_Notification60"> - <Platform Name="iOSDevice64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="iOSSimARM64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="iPhone_Setting58"> - <Platform Name="iOSDevice64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="iOSSimARM64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="iPhone_Setting87"> - <Platform Name="iOSDevice64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="iOSSimARM64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="iPhone_Spotlight120"> - <Platform Name="iOSDevice64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="iOSSimARM64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="iPhone_Spotlight80"> - <Platform Name="iOSDevice64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="iOSSimARM64"> - <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="ProjectAndroidManifest"> - <Platform Name="Android"> - <Operation>1</Operation> - </Platform> - <Platform Name="Android64"> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="ProjectiOSDeviceDebug"> - <Platform Name="iOSDevice32"> - <RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="iOSDevice64"> - <RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="iOSSimARM64"> - <RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="ProjectiOSEntitlements"/> - <DeployClass Name="ProjectiOSInfoPList"/> - <DeployClass Name="ProjectiOSLaunchScreen"/> - <DeployClass Name="ProjectiOSResource"> - <Platform Name="iOSDevice32"> - <Operation>1</Operation> - </Platform> - <Platform Name="iOSDevice64"> - <Operation>1</Operation> - </Platform> - <Platform Name="iOSSimARM64"> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="ProjectOSXDebug"/> - <DeployClass Name="ProjectOSXEntitlements"/> - <DeployClass Name="ProjectOSXInfoPList"/> - <DeployClass Name="ProjectOSXResource"> - <Platform Name="OSX32"> - <RemoteDir>Contents\Resources</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="OSX64"> - <RemoteDir>Contents\Resources</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="OSXARM64"> - <RemoteDir>Contents\Resources</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Required="true" Name="ProjectOutput"> - <Platform Name="Android"> - <RemoteDir>library\lib\armeabi-v7a</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="Android64"> - <RemoteDir>library\lib\arm64-v8a</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="iOSDevice32"> - <Operation>1</Operation> - </Platform> - <Platform Name="iOSDevice64"> - <Operation>1</Operation> - </Platform> - <Platform Name="iOSSimARM64"> - <Operation>1</Operation> - </Platform> - <Platform Name="Linux64"> - <Operation>1</Operation> - </Platform> - <Platform Name="OSX32"> - <Operation>1</Operation> - </Platform> - <Platform Name="OSX64"> - <Operation>1</Operation> - </Platform> - <Platform Name="OSXARM64"> - <Operation>1</Operation> - </Platform> - <Platform Name="Win32"> - <Operation>0</Operation> - </Platform> - </DeployClass> - <DeployClass Name="ProjectOutput_Android32"> - <Platform Name="Android64"> - <RemoteDir>library\lib\armeabi-v7a</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="ProjectUWPManifest"> - <Platform Name="Win32"> - <Operation>1</Operation> - </Platform> - <Platform Name="Win64"> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="UWP_DelphiLogo150"> - <Platform Name="Win32"> - <RemoteDir>Assets</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="Win64"> - <RemoteDir>Assets</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <DeployClass Name="UWP_DelphiLogo44"> - <Platform Name="Win32"> - <RemoteDir>Assets</RemoteDir> - <Operation>1</Operation> - </Platform> - <Platform Name="Win64"> - <RemoteDir>Assets</RemoteDir> - <Operation>1</Operation> - </Platform> - </DeployClass> - <ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/> - <ProjectRoot Platform="Android64" Name="$(PROJECTNAME)"/> - <ProjectRoot Platform="iOSDevice32" Name="$(PROJECTNAME).app"/> - <ProjectRoot Platform="iOSDevice64" Name="$(PROJECTNAME).app"/> - <ProjectRoot Platform="iOSSimARM64" Name="$(PROJECTNAME).app"/> - <ProjectRoot Platform="Linux64" Name="$(PROJECTNAME)"/> - <ProjectRoot Platform="OSX32" Name="$(PROJECTNAME)"/> - <ProjectRoot Platform="OSX64" Name="$(PROJECTNAME)"/> - <ProjectRoot Platform="OSXARM64" Name="$(PROJECTNAME)"/> - <ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/> - <ProjectRoot Platform="Win64" Name="$(PROJECTNAME)"/> - </Deployment> - </BorlandProject> - <ProjectFileVersion>12</ProjectFileVersion> - </ProjectExtensions> - <Import Project="$(BDS)\Bin\CodeGear.Delphi.Targets" Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')"/> - <Import Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj" Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')"/> - <Import Project="$(MSBuildProjectName).deployproj" Condition="Exists('$(MSBuildProjectName).deployproj')"/> -</Project> diff --git a/Packages/Delphi/Delphi 10.4+/PythonVcl.dproj b/Packages/Delphi/Delphi 10.4+/PythonVcl.dproj index 3f40f175..9ccee1e3 100644 --- a/Packages/Delphi/Delphi 10.4+/PythonVcl.dproj +++ b/Packages/Delphi/Delphi 10.4+/PythonVcl.dproj @@ -7,7 +7,8 @@ <MainSource>PythonVcl.dpk</MainSource> <Platform Condition="'$(Platform)'==''">Win32</Platform> <ProjectGuid>{D8908301-393C-4CFA-8842-4948A9935E21}</ProjectGuid> - <ProjectVersion>19.5</ProjectVersion> + <ProjectName Condition="'$(ProjectName)'==''">PythonVcl</ProjectName> + <ProjectVersion>20.1</ProjectVersion> <TargetedPlatforms>3</TargetedPlatforms> </PropertyGroup> <PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''"> @@ -144,13 +145,14 @@ <Platforms> <Platform value="Android">False</Platform> <Platform value="Android64">False</Platform> + <Platform value="iOSDevice64">False</Platform> + <Platform value="iOSSimARM64">False</Platform> <Platform value="Linux64">False</Platform> <Platform value="OSX64">False</Platform> <Platform value="OSXARM64">False</Platform> <Platform value="Win32">True</Platform> <Platform value="Win64">True</Platform> - <Platform value="iOSDevice64">False</Platform> - <Platform value="iOSSimARM64">False</Platform> + <Platform value="Win64x">False</Platform> </Platforms> </BorlandProject> <ProjectFileVersion>12</ProjectFileVersion> diff --git a/Packages/Delphi/Delphi 10.4+/dclPython.dproj b/Packages/Delphi/Delphi 10.4+/dclPython.dproj index a2f01927..749430a6 100644 --- a/Packages/Delphi/Delphi 10.4+/dclPython.dproj +++ b/Packages/Delphi/Delphi 10.4+/dclPython.dproj @@ -7,7 +7,8 @@ <MainSource>dclPython.dpk</MainSource> <Platform Condition="'$(Platform)'==''">Win32</Platform> <ProjectGuid>{D9AB994C-54A3-4E76-81C8-6D0BB035A091}</ProjectGuid> - <ProjectVersion>19.5</ProjectVersion> + <ProjectName Condition="'$(ProjectName)'==''">dclPython</ProjectName> + <ProjectVersion>20.1</ProjectVersion> <TargetedPlatforms>1</TargetedPlatforms> </PropertyGroup> <PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''"> @@ -149,6 +150,7 @@ <Platform value="OSXARM64">False</Platform> <Platform value="Win32">True</Platform> <Platform value="Win64">False</Platform> + <Platform value="Win64x">False</Platform> <Platform value="iOSDevice64">False</Platform> <Platform value="iOSSimARM64">False</Platform> </Platforms> diff --git a/Packages/Delphi/Delphi 10.4+/dclPythonFmx.dproj b/Packages/Delphi/Delphi 10.4+/dclPythonFmx.dproj index 9fed4132..1104549c 100644 --- a/Packages/Delphi/Delphi 10.4+/dclPythonFmx.dproj +++ b/Packages/Delphi/Delphi 10.4+/dclPythonFmx.dproj @@ -7,7 +7,8 @@ <MainSource>dclPythonFmx.dpk</MainSource> <Platform Condition="'$(Platform)'==''">Win32</Platform> <ProjectGuid>{E057921E-25DB-426E-8090-FE3F428894FF}</ProjectGuid> - <ProjectVersion>19.5</ProjectVersion> + <ProjectName Condition="'$(ProjectName)'==''">dclPythonFmx</ProjectName> + <ProjectVersion>20.1</ProjectVersion> <TargetedPlatforms>1</TargetedPlatforms> </PropertyGroup> <PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''"> @@ -125,6 +126,7 @@ <Platform value="OSXARM64">False</Platform> <Platform value="Win32">True</Platform> <Platform value="Win64">False</Platform> + <Platform value="Win64x">False</Platform> <Platform value="iOSDevice64">False</Platform> <Platform value="iOSSimARM64">False</Platform> </Platforms> diff --git a/Packages/Delphi/Delphi 10.4+/dclPythonVcl.dproj b/Packages/Delphi/Delphi 10.4+/dclPythonVcl.dproj index 3944b8d3..7a1e1ec3 100644 --- a/Packages/Delphi/Delphi 10.4+/dclPythonVcl.dproj +++ b/Packages/Delphi/Delphi 10.4+/dclPythonVcl.dproj @@ -7,7 +7,8 @@ <MainSource>dclPythonVcl.dpk</MainSource> <Platform Condition="'$(Platform)'==''">Win32</Platform> <ProjectGuid>{48DDC28A-E154-4CA0-864A-30EB8C4CCBB3}</ProjectGuid> - <ProjectVersion>19.5</ProjectVersion> + <ProjectName Condition="'$(ProjectName)'==''">dclPythonVcl</ProjectName> + <ProjectVersion>20.1</ProjectVersion> <TargetedPlatforms>1</TargetedPlatforms> </PropertyGroup> <PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''"> @@ -125,6 +126,7 @@ <Platform value="OSXARM64">False</Platform> <Platform value="Win32">True</Platform> <Platform value="Win64">False</Platform> + <Platform value="Win64x">False</Platform> <Platform value="iOSDevice64">False</Platform> <Platform value="iOSSimARM64">False</Platform> </Platforms> diff --git a/Packages/Delphi/P4DLinuxComponentSuite.groupproj b/Packages/Delphi/P4DLinuxComponentSuite.groupproj deleted file mode 100644 index 544e8812..00000000 --- a/Packages/Delphi/P4DLinuxComponentSuite.groupproj +++ /dev/null @@ -1,108 +0,0 @@ -<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <PropertyGroup> - <ProjectGuid>{8BE1193B-E609-445D-9BA3-F57DBEA042F5}</ProjectGuid> - </PropertyGroup> - <ItemGroup> - <Projects Include="Delphi 10.4+\Python.dproj"> - <Dependencies/> - </Projects> - <Projects Include="Delphi 10.4+\dclPython.dproj"> - <Dependencies>Delphi 10.4+\Python.dproj</Dependencies> - </Projects> - <Projects Include="Delphi 10.4+\PythonVcl.dproj"> - <Dependencies>Delphi 10.4+\Python.dproj</Dependencies> - </Projects> - <Projects Include="Delphi 10.4+\dclPythonVcl.dproj"> - <Dependencies>Delphi 10.4+\PythonVcl.dproj</Dependencies> - </Projects> - <Projects Include="Delphi 10.4+\PythonFmx.dproj"> - <Dependencies/> - </Projects> - <Projects Include="Delphi 10.4+\PythonFmxLinux.dproj"> - <Dependencies/> - </Projects> - <Projects Include="Delphi 10.4+\dclPythonFmx.dproj"> - <Dependencies/> - </Projects> - </ItemGroup> - <ProjectExtensions> - <Borland.Personality>Default.Personality.12</Borland.Personality> - <Borland.ProjectType/> - <BorlandProject> - <Default.Personality/> - </BorlandProject> - </ProjectExtensions> - <Target Name="Python"> - <MSBuild Projects="Delphi 10.4+\Python.dproj"/> - </Target> - <Target Name="Python:Clean"> - <MSBuild Projects="Delphi 10.4+\Python.dproj" Targets="Clean"/> - </Target> - <Target Name="Python:Make"> - <MSBuild Projects="Delphi 10.4+\Python.dproj" Targets="Make"/> - </Target> - <Target Name="dclPython" DependsOnTargets="Python"> - <MSBuild Projects="Delphi 10.4+\dclPython.dproj"/> - </Target> - <Target Name="dclPython:Clean" DependsOnTargets="Python:Clean"> - <MSBuild Projects="Delphi 10.4+\dclPython.dproj" Targets="Clean"/> - </Target> - <Target Name="dclPython:Make" DependsOnTargets="Python:Make"> - <MSBuild Projects="Delphi 10.4+\dclPython.dproj" Targets="Make"/> - </Target> - <Target Name="PythonVcl" DependsOnTargets="Python"> - <MSBuild Projects="Delphi 10.4+\PythonVcl.dproj"/> - </Target> - <Target Name="PythonVcl:Clean" DependsOnTargets="Python:Clean"> - <MSBuild Projects="Delphi 10.4+\PythonVcl.dproj" Targets="Clean"/> - </Target> - <Target Name="PythonVcl:Make" DependsOnTargets="Python:Make"> - <MSBuild Projects="Delphi 10.4+\PythonVcl.dproj" Targets="Make"/> - </Target> - <Target Name="dclPythonVcl" DependsOnTargets="PythonVcl"> - <MSBuild Projects="Delphi 10.4+\dclPythonVcl.dproj"/> - </Target> - <Target Name="dclPythonVcl:Clean" DependsOnTargets="PythonVcl:Clean"> - <MSBuild Projects="Delphi 10.4+\dclPythonVcl.dproj" Targets="Clean"/> - </Target> - <Target Name="dclPythonVcl:Make" DependsOnTargets="PythonVcl:Make"> - <MSBuild Projects="Delphi 10.4+\dclPythonVcl.dproj" Targets="Make"/> - </Target> - <Target Name="PythonFmx"> - <MSBuild Projects="Delphi 10.4+\PythonFmx.dproj"/> - </Target> - <Target Name="PythonFmx:Clean"> - <MSBuild Projects="Delphi 10.4+\PythonFmx.dproj" Targets="Clean"/> - </Target> - <Target Name="PythonFmx:Make"> - <MSBuild Projects="Delphi 10.4+\PythonFmx.dproj" Targets="Make"/> - </Target> - <Target Name="PythonFmxLinux"> - <MSBuild Projects="Delphi 10.4+\PythonFmxLinux.dproj"/> - </Target> - <Target Name="PythonFmxLinux:Clean"> - <MSBuild Projects="Delphi 10.4+\PythonFmxLinux.dproj" Targets="Clean"/> - </Target> - <Target Name="PythonFmxLinux:Make"> - <MSBuild Projects="Delphi 10.4+\PythonFmxLinux.dproj" Targets="Make"/> - </Target> - <Target Name="dclPythonFmx"> - <MSBuild Projects="Delphi 10.4+\dclPythonFmx.dproj"/> - </Target> - <Target Name="dclPythonFmx:Clean"> - <MSBuild Projects="Delphi 10.4+\dclPythonFmx.dproj" Targets="Clean"/> - </Target> - <Target Name="dclPythonFmx:Make"> - <MSBuild Projects="Delphi 10.4+\dclPythonFmx.dproj" Targets="Make"/> - </Target> - <Target Name="Build"> - <CallTarget Targets="Python;dclPython;PythonVcl;dclPythonVcl;PythonFmx;PythonFmxLinux;dclPythonFmx"/> - </Target> - <Target Name="Clean"> - <CallTarget Targets="Python:Clean;dclPython:Clean;PythonVcl:Clean;dclPythonVcl:Clean;PythonFmx:Clean;PythonFmxLinux:Clean;dclPythonFmx:Clean"/> - </Target> - <Target Name="Make"> - <CallTarget Targets="Python:Make;dclPython:Make;PythonVcl:Make;dclPythonVcl:Make;PythonFmx:Make;PythonFmxLinux:Make;dclPythonFmx:Make"/> - </Target> - <Import Project="$(BDS)\Bin\CodeGear.Group.Targets" Condition="Exists('$(BDS)\Bin\CodeGear.Group.Targets')"/> -</Project> diff --git a/Source/PythonAction.pas b/Source/PythonAction.pas index 60af65e5..d94d610e 100644 --- a/Source/PythonAction.pas +++ b/Source/PythonAction.pas @@ -17,7 +17,7 @@ interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, - ActnList, PythonEngine; + Actions, ActnList, PythonEngine; type TPythonAction = class(TAction) @@ -114,21 +114,21 @@ function TPythonAction.HandlesTarget(Target: TObject): Boolean; procedure TPythonAction.InitializeAction; var - docString: string; + docString: string; begin if not (csDesigning in ComponentState) and Assigned(PythonModule) then begin fClearname := 'Clear' + Name; docString := 'Claer all events of "' + Owner.Name + '.' + Name + '" action'; - PythonModule.AddDelphiMethod(PChar(fClearname), PythonClear, PChar(docString)); + PythonModule.AddDelphiMethod(PAnsiChar(fClearname), PythonClear, PAnsiChar(docString)); fRegistername := 'Register' + Name; docString := 'Register an event againt the "' + Owner.Name + '.' + Name + '" action'; - PythonModule.AddDelphiMethod(PChar(fRegistername), PythonRegister, PChar(docString)); + PythonModule.AddDelphiMethod(PAnsiChar(fRegistername), PythonRegister, PAnsiChar(docString)); fUnregistername := 'Unregister' + Name; docString := 'Unregister an event againt the "' + Owner.Name + '.' + Name + '" action'; - PythonModule.AddDelphiMethod(PChar(fUnregistername), PythonUnregister, PChar(docString)); + PythonModule.AddDelphiMethod(PAnsiChar(fUnregistername), PythonUnregister, PAnsiChar(docString)); end; end; @@ -152,7 +152,7 @@ function TPythonAction.PythonRegister(pself, args: PPyObject): PPyObject; ( not PyFunction_Check(func)) then begin s := fRegistername + '(function)'; - PyErr_SetString(PyExc_TypeError^,PChar(s)); + PyErr_SetString(PyExc_TypeError^, PAnsiChar(Utf8Encode(s))); end else with RegisteredMethods do @@ -174,7 +174,7 @@ function TPythonAction.PythonUnregister(pself, args: PPyObject): PPyObject; (RegisteredMethods.IndexOf(func) = -1) then begin s := fUnregistername + '(function)'; - PyErr_SetString(PyExc_TypeError^,PChar(s)); + PyErr_SetString(PyExc_TypeError^, PAnsiChar(Utf8Encode(s))); end else with RegisteredMethods do diff --git a/Source/PythonEngine.pas b/Source/PythonEngine.pas index 7bd52c93..422146b0 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -73,59 +73,51 @@ TPythonVersionProp = record end; const {$IFDEF MSWINDOWS} - PYTHON_KNOWN_VERSIONS: array[1..10] of TPythonVersionProp = + PYTHON_KNOWN_VERSIONS: array[1..7] of TPythonVersionProp = ( - (DllName: 'python33.dll'; RegVersion: '3.3'; APIVersion: 1013), - (DllName: 'python34.dll'; RegVersion: '3.4'; APIVersion: 1013), - (DllName: 'python35.dll'; RegVersion: '3.5'; APIVersion: 1013), - (DllName: 'python36.dll'; RegVersion: '3.6'; APIVersion: 1013), - (DllName: 'python37.dll'; RegVersion: '3.7'; APIVersion: 1013), (DllName: 'python38.dll'; RegVersion: '3.8'; APIVersion: 1013), (DllName: 'python39.dll'; RegVersion: '3.9'; APIVersion: 1013), (DllName: 'python310.dll'; RegVersion: '3.10'; APIVersion: 1013), (DllName: 'python311.dll'; RegVersion: '3.11'; APIVersion: 1013), - (DllName: 'python312.dll'; RegVersion: '3.12'; APIVersion: 1013) + (DllName: 'python312.dll'; RegVersion: '3.12'; APIVersion: 1013), + (DllName: 'python313.dll'; RegVersion: '3.13'; APIVersion: 1013), + (DllName: 'python314.dll'; RegVersion: '3.14'; APIVersion: 1013) ); {$ENDIF} {$IFDEF _so_files} - PYTHON_KNOWN_VERSIONS: array[1..10] of TPythonVersionProp = + PYTHON_KNOWN_VERSIONS: array[1..7] of TPythonVersionProp = ( - (DllName: 'libpython3.3m.so'; RegVersion: '3.3'; APIVersion: 1013), - (DllName: 'libpython3.4m.so'; RegVersion: '3.4'; APIVersion: 1013), - (DllName: 'libpython3.5m.so'; RegVersion: '3.5'; APIVersion: 1013), - (DllName: 'libpython3.6m.so'; RegVersion: '3.6'; APIVersion: 1013), - (DllName: 'libpython3.7m.so'; RegVersion: '3.7'; APIVersion: 1013), (DllName: 'libpython3.8.so'; RegVersion: '3.8'; APIVersion: 1013), (DllName: 'libpython3.9.so'; RegVersion: '3.9'; APIVersion: 1013), (DllName: 'libpython3.10.so'; RegVersion: '3.10'; APIVersion: 1013), (DllName: 'libpython3.11.so'; RegVersion: '3.11'; APIVersion: 1013), - (DllName: 'libpython3.12.so'; RegVersion: '3.12'; APIVersion: 1013) + (DllName: 'libpython3.12.so'; RegVersion: '3.12'; APIVersion: 1013), + (DllName: 'libpython3.13.so'; RegVersion: '3.13'; APIVersion: 1013), + (DllName: 'libpython3.14.so'; RegVersion: '3.14'; APIVersion: 1013) ); {$ENDIF} {$IFDEF DARWIN} - PYTHON_KNOWN_VERSIONS: array[1..10] of TPythonVersionProp = + PYTHON_KNOWN_VERSIONS: array[1..7] of TPythonVersionProp = ( - (DllName: 'libpython3.3.dylib'; RegVersion: '3.3'; APIVersion: 1013), - (DllName: 'libpython3.4.dylib'; RegVersion: '3.4'; APIVersion: 1013), - (DllName: 'libpython3.5.dylib'; RegVersion: '3.5'; APIVersion: 1013), - (DllName: 'libpython3.6.dylib'; RegVersion: '3.6'; APIVersion: 1013), - (DllName: 'libpython3.7.dylib'; RegVersion: '3.7'; APIVersion: 1013), (DllName: 'libpython3.8.dylib'; RegVersion: '3.8'; APIVersion: 1013), (DllName: 'libpython3.9.dylib'; RegVersion: '3.9'; APIVersion: 1013), (DllName: 'libpython3.10.dylib'; RegVersion: '3.10'; APIVersion: 1013), (DllName: 'libpython3.11.dylib'; RegVersion: '3.11'; APIVersion: 1013), - (DllName: 'libpython3.12.dylib'; RegVersion: '3.12'; APIVersion: 1013) + (DllName: 'libpython3.12.dylib'; RegVersion: '3.12'; APIVersion: 1013), + (DllName: 'libpython3.13.dylib'; RegVersion: '3.13'; APIVersion: 1013), + (DllName: 'libpython3.14.dylib'; RegVersion: '3.14'; APIVersion: 1013) ); {$ENDIF} {$IFDEF ANDROID} - PYTHON_KNOWN_VERSIONS: array[5..10] of TPythonVersionProp = + PYTHON_KNOWN_VERSIONS: array[1..7] of TPythonVersionProp = ( - (DllName: 'libpython3.7m.so'; RegVersion: '3.7'; APIVersion: 1013), (DllName: 'libpython3.8.so'; RegVersion: '3.8'; APIVersion: 1013), (DllName: 'libpython3.9.so'; RegVersion: '3.9'; APIVersion: 1013), (DllName: 'libpython3.10.so'; RegVersion: '3.10'; APIVersion: 1013), (DllName: 'libpython3.11.so'; RegVersion: '3.11'; APIVersion: 1013), - (DllName: 'libpython3.12.so'; RegVersion: '3.12'; APIVersion: 1013) + (DllName: 'libpython3.12.so'; RegVersion: '3.12'; APIVersion: 1013), + (DllName: 'libpython3.13.so'; RegVersion: '3.13'; APIVersion: 1013), + (DllName: 'libpython3.14.so'; RegVersion: '3.14'; APIVersion: 1013) ); {$ENDIF} @@ -188,8 +180,8 @@ TPythonVersionProp = record WCharTString = UnicodeString; {$ENDIF} - PPy_ssize_t = PNativeInt; - Py_ssize_t = NativeInt; + PPy_ssize_t = PNativeUInt; + Py_ssize_t = NativeUInt; const { @@ -482,7 +474,7 @@ TPythonVersionProp = record end; PyObject = {$IFDEF CPUX86}packed{$ENDIF} record - ob_refcnt: NativeInt; + ob_refcnt: NativeUInt; ob_type: PPyTypeObject; end; @@ -493,7 +485,7 @@ TPythonVersionProp = record end; PySliceObject = {$IFDEF CPUX86}packed{$ENDIF} record - ob_refcnt: NativeInt; + ob_refcnt: NativeUInt; ob_type: PPyTypeObject; start, stop, step: PPyObject; end; @@ -546,28 +538,31 @@ TPythonVersionProp = record {#define PyDescr_COMMON \ PyObject_HEAD \ PyTypeObject *d_type; \ - PyObject *d_name + PyObject *d_name \ + PyObject *d_qualname } PPyDescrObject = ^PyDescrObject; PyDescrObject = {$IFDEF CPUX86}packed{$ENDIF} record // Start of the Head of an object - ob_refcnt : NativeInt; + ob_refcnt : NativeUInt; ob_type : PPyTypeObject; // End of the Head of an object d_type : PPyTypeObject; d_name : PPyObject; + d_qualname : PPyObject; end; PPyMethodDescrObject = ^PyMethodDescrObject; PyMethodDescrObject = {$IFDEF CPUX86}packed{$ENDIF} record // Start of PyDescr_COMMON // Start of the Head of an object - ob_refcnt : NativeInt; + ob_refcnt : NativeUInt; ob_type : PPyTypeObject; // End of the Head of an object d_type : PPyTypeObject; d_name : PPyObject; + d_qualname : PPyObject; // End of PyDescr_COMMON d_method : PPyMethodDef; end; @@ -576,11 +571,12 @@ TPythonVersionProp = record PyMemberDescrObject = {$IFDEF CPUX86}packed{$ENDIF} record // Start of PyDescr_COMMON // Start of the Head of an object - ob_refcnt : NativeInt; + ob_refcnt : NativeUInt; ob_type : PPyTypeObject; // End of the Head of an object d_type : PPyTypeObject; d_name : PPyObject; + d_qualname : PPyObject; // End of PyDescr_COMMON d_member : PPyMemberDef; end; @@ -589,11 +585,12 @@ TPythonVersionProp = record PyGetSetDescrObject = {$IFDEF CPUX86}packed{$ENDIF} record // Start of PyDescr_COMMON // Start of the Head of an object - ob_refcnt : NativeInt; + ob_refcnt : NativeUInt; ob_type : PPyTypeObject; // End of the Head of an object d_type : PPyTypeObject; d_name : PPyObject; + d_qualname : PPyObject; // End of PyDescr_COMMON d_getset : PPyGetSetDef; end; @@ -602,11 +599,12 @@ TPythonVersionProp = record PyWrapperDescrObject = {$IFDEF CPUX86}packed{$ENDIF} record // Start of PyDescr_COMMON // Start of the Head of an object - ob_refcnt : NativeInt; + ob_refcnt : NativeUInt; ob_type : PPyTypeObject; // End of the Head of an object d_type : PPyTypeObject; d_name : PPyObject; + d_qualname : PPyObject; // End of PyDescr_COMMON d_base : pwrapperbase; d_wrapped : Pointer; // This can be any function pointer @@ -615,7 +613,7 @@ TPythonVersionProp = record PPyModuleDef_Base = ^PyModuleDef_Base; PyModuleDef_Base = {$IFDEF CPUX86}packed{$ENDIF} record // Start of the Head of an object - ob_refcnt : NativeInt; + ob_refcnt : NativeUInt; ob_type : PPyTypeObject; // End of the Head of an object m_init : function( ) : PPyObject; cdecl; @@ -623,6 +621,15 @@ TPythonVersionProp = record m_copy : PPyObject; end; + // Slots are used for two phase module initialization + // which is not yet implemented + + PPyModuleDef_Slot = ^PyModuleDef_Slot; + PyModuleDef_Slot = {$IFDEF CPUX86}packed{$ENDIF} record + slot: integer; + value: Pointer; + end; + PPyModuleDef = ^PyModuleDef; PyModuleDef = {$IFDEF CPUX86}packed{$ENDIF} record m_base : PyModuleDef_Base; @@ -630,7 +637,7 @@ TPythonVersionProp = record m_doc : PAnsiChar; m_size : NativeInt; m_methods : PPyMethodDef; - m_reload : inquiry; + m_slots : PPyModuleDef_Slot; m_traverse : traverseproc; m_clear : inquiry; m_free : inquiry; @@ -666,7 +673,7 @@ PyBufferProcs = record // object.h PyTypeObject = {$IFDEF CPUX86}packed{$ENDIF} record - ob_refcnt: NativeInt; + ob_refcnt: NativeUInt; ob_type: PPyTypeObject; ob_size: NativeInt; // Number of items in variable part tp_name: PAnsiChar; // For printing @@ -813,7 +820,7 @@ PyBufferProcs = record type PyDateTime_Delta = {$IFDEF CPUX86}packed{$ENDIF} record // Start of the Head of an object - ob_refcnt : NativeInt; + ob_refcnt : NativeUInt; ob_type : PPyTypeObject; // End of the Head of an object hashcode : NativeInt; // -1 when unknown @@ -825,7 +832,7 @@ PyBufferProcs = record PyDateTime_TZInfo = {$IFDEF CPUX86}packed{$ENDIF} record // a pure abstract base clase // Start of the Head of an object - ob_refcnt : NativeInt; + ob_refcnt : NativeUInt; ob_type : PPyTypeObject; // End of the Head of an object end; @@ -848,7 +855,7 @@ PyBufferProcs = record _PyDateTime_BaseTZInfo = {$IFDEF CPUX86}packed{$ENDIF} record // Start of _PyTZINFO_HEAD // Start of the Head of an object - ob_refcnt : NativeInt; + ob_refcnt : NativeUInt; ob_type : PPyTypeObject; // End of the Head of an object hashcode : Integer; @@ -872,7 +879,7 @@ PyBufferProcs = record // Start of _PyDateTime_TIMEHEAD // Start of _PyTZINFO_HEAD // Start of the Head of an object - ob_refcnt : NativeInt; + ob_refcnt : NativeUInt; ob_type : PPyTypeObject; // End of the Head of an object hashcode : Integer; @@ -887,7 +894,7 @@ PyBufferProcs = record // Start of _PyDateTime_TIMEHEAD // Start of _PyTZINFO_HEAD // Start of the Head of an object - ob_refcnt : NativeInt; + ob_refcnt : NativeUInt; ob_type : PPyTypeObject; // End of the Head of an object hashcode : Integer; @@ -909,7 +916,7 @@ PyBufferProcs = record PyDateTime_Date = {$IFDEF CPUX86}packed{$ENDIF} record // Start of _PyTZINFO_HEAD // Start of the Head of an object - ob_refcnt : NativeInt; + ob_refcnt : NativeUInt; ob_type : PPyTypeObject; // End of the Head of an object hashcode : Integer; @@ -928,7 +935,7 @@ PyBufferProcs = record _PyDateTime_BaseDateTime = {$IFDEF CPUX86}packed{$ENDIF} record // hastzinfo false // Start of _PyTZINFO_HEAD // Start of the Head of an object - ob_refcnt : NativeInt; + ob_refcnt : NativeUInt; ob_type : PPyTypeObject; // End of the Head of an object hashcode : Integer; @@ -942,7 +949,7 @@ PyBufferProcs = record // Start of _PyDateTime_DATETIMEHEAD // Start of _PyTZINFO_HEAD // Start of the Head of an object - ob_refcnt : NativeInt; + ob_refcnt : NativeUInt; ob_type : PPyTypeObject; // End of the Head of an object hashcode : Integer; @@ -957,7 +964,7 @@ PyBufferProcs = record //bytearrayobject.h PyByteArrayObject = {$IFDEF CPUX86}packed{$ENDIF} record - ob_refcnt: NativeInt; + ob_refcnt: NativeUInt; ob_type: PPyTypeObject; ob_alloc: Py_ssize_t; ob_bytes: PAnsiChar; @@ -966,6 +973,7 @@ PyBufferProcs = record end; //initconfig.h + //See https://docs.python.org/3/c-api/init_config.html const _PyStatus_TYPE_OK = 0; @@ -982,6 +990,80 @@ PyBufferProcs = record exitcode: Integer; end; + PPyWideStringList = ^PyWideStringList; + PyWideStringList = {$IFDEF CPUX86}packed{$ENDIF} record + length: Py_ssize_t; + items: PPWCharT; + end; + + PPyConfig = ^PyConfig; + PyConfig = record + // The definition of PyConfig has been changing in every python version + // So we make this structure opaque and we access its fields through + // the ConfigOffsets below + Filler: array [0..1000] of Byte; + end; + + // Opaque structure PEP 741 + PPyInitConfig = Pointer; + +{$SCOPEDENUMS ON} + TConfigFields = ( + use_environment, + parse_argv, + argv, + site_import, + interactive, + optimization_level, + parser_debug, + verbose, + pathconfig_warnings, + program_name, + home, + module_search_paths_set, + module_search_paths, + executable); +{$SCOPEDENUMS OFF} + + TConfigOffsets = array [8..13] of array [TConfigFields] of Integer; + + // The followng needs updating when new versions are added + const + ConfigOffests: TConfigOffsets = + {$IFDEF MSWINDOWS} + {$IFDEF CPU64BITS} + ((8, 80, 88, 144, 156, 160, 164, 172, 224, 104, 240, 248, 256, 272), + (8, 80, 88, 144, 156, 160, 164, 172, 224, 104, 240, 248, 256, 272), + (8, 80, 104, 152, 168, 172, 176, 184, 240, 248, 264, 280, 288, 304), + (8, 96, 120, 168, 184, 188, 192, 200, 264, 272, 288, 304, 312, 336), + (8, 96, 120, 168, 184, 188, 192, 200, 268, 272, 288, 304, 312, 336), + (8, 96, 120, 168, 184, 188, 192, 200, 272, 280, 296, 312, 320, 344)); + {$ELSE} + ((8, 68, 72, 100, 112, 116, 120, 128, 164, 80, 172, 176, 180, 188), + (8, 68, 72, 100, 112, 116, 120, 128, 164, 80, 172, 176, 180, 188), + (8, 64, 76, 100, 116, 120, 124, 132, 168, 172, 180, 188, 192, 200), + (8, 72, 84, 108, 124, 128, 132, 140, 184, 188, 196, 204, 208, 220), + (8, 76, 88, 112, 128, 132, 136, 144, 192, 196, 204, 212, 216, 228), + (8, 76, 88, 112, 128, 132, 136, 144, 196, 200, 208, 216, 220, 232)); + {$ENDIF} + {$ELSE} + {$IFDEF CPU64BITS} + ((8, 88, 96, 152, 164, 168, 172, 180, 224, 112, 240, 248, 256, 272), + (8, 88, 96, 152, 164, 168, 172, 180, 224, 112, 240, 248, 256, 272), + (8, 80, 104, 152, 168, 172, 176, 184, 232, 240, 256, 272, 280, 296), + (8, 96, 120, 168, 184, 188, 192, 200, 256, 264, 280, 296, 304, 328), + (8, 104, 128, 176, 192, 196, 200, 208, 268, 272, 288, 304, 312, 336), + (8, 104, 128, 176, 192, 196, 200, 208, 272, 280, 296, 312, 320, 344)); + {$ELSE} + ((8, 68, 72, 100, 112, 116, 120, 128, 160, 80, 168, 172, 176, 184), + (8, 68, 72, 100, 112, 116, 120, 128, 160, 80, 168, 172, 176, 184), + (8, 64, 76, 100, 116, 120, 124, 132, 164, 168, 176, 184, 188, 196), + (8, 72, 84, 108, 124, 128, 132, 140, 180, 184, 192, 200, 204, 216), + (8, 76, 88, 112, 128, 132, 136, 144, 188, 192, 200, 208, 212, 224), + (8, 76, 88, 112, 128, 132, 136, 144, 192, 196, 204, 212, 216, 228)); + {$ENDIF} + {$ENDIF} + //####################################################### //## ## //## GIL related ## @@ -999,7 +1081,7 @@ PyBufferProcs = record PyInterpreterConfig_SHARED_GIL = 1; PyInterpreterConfig_OWN_GIL = 2; - type +type PPyInterpreterConfig = ^PyInterpreterConfig; PyInterpreterConfig = {$IFDEF CPUX86}packed{$ENDIF} record use_main_obmalloc: Integer; @@ -1011,7 +1093,7 @@ PyBufferProcs = record gil: Integer; end; -const +var _PyInterpreterConfig_INIT: PyInterpreterConfig = ( use_main_obmalloc: 0; allow_fork: 0; @@ -1355,15 +1437,6 @@ TPythonInterface=class(TDynamicDll) procedure CheckPython; public - // define Python flags. See file pyDebug.h - Py_DebugFlag: PInteger; - Py_VerboseFlag: PInteger; - Py_InteractiveFlag: PInteger; - Py_OptimizeFlag: PInteger; - Py_NoSiteFlag: PInteger; - Py_FrozenFlag: PInteger; - Py_IgnoreEnvironmentFlag: PInteger; - PyImport_FrozenModules: PP_frozen; Py_None: PPyObject; @@ -1446,6 +1519,7 @@ TPythonInterface=class(TDynamicDll) PySuper_Type: PPyTypeObject; PyTraceBack_Type: PPyTypeObject; PyUnicode_Type: PPyTypeObject; + PyGetSetDescr_Type: PPyTypeObject; PyWrapperDescr_Type: PPyTypeObject; _PyWeakref_RefType: PPyTypeObject; _PyWeakref_ProxyType: PPyTypeObject; @@ -1517,7 +1591,6 @@ TPythonInterface=class(TDynamicDll) PyBytes_AsString: function( ob: PPyObject): PAnsiChar; cdecl; PyBytes_AsStringAndSize: function( ob: PPyObject; var buffer: PAnsiChar; var size: NativeInt): integer; cdecl; PyByteArray_AsString: function(ob: PPyObject): PAnsiChar; cdecl; - PySys_SetArgv: procedure( argc: Integer; argv: PPWCharT); cdecl; PyCFunction_NewEx: function(md:PPyMethodDef;self, ob:PPyObject):PPyObject; cdecl; @@ -1532,14 +1605,10 @@ TPythonInterface=class(TDynamicDll) len: Py_ssize_t; readonly: Integer; flags: Integer): Integer; cdecl; PyBuffer_Release: procedure(view: PPy_buffer); cdecl; - // Removed. Use PyEval_CallObjectWithKeywords with third argument nil - // PyEval_CallObject: function(callable_obj, args:PPyObject):PPyObject; cdecl; - PyEval_CallObjectWithKeywords:function (callable_obj, args, kw:PPyObject):PPyObject; cdecl; PyEval_GetFrame:function :PPyObject; cdecl; PyEval_GetGlobals:function :PPyObject; cdecl; PyEval_GetLocals:function :PPyObject; cdecl; - PyEval_InitThreads:procedure; cdecl; PyEval_RestoreThread:procedure( tstate: PPyThreadState); cdecl; PyEval_SaveThread:function :PPyThreadState; cdecl; @@ -1580,6 +1649,7 @@ TPythonInterface=class(TDynamicDll) PyLong_FromLongLong:function(val:Int64): PPyObject; cdecl; PyLong_FromUnsignedLongLong:function(val:UInt64) : PPyObject; cdecl; PyLong_AsLongLong:function(ob:PPyObject): Int64; cdecl; + PyLong_AsVoidPtr:function(ob:PPyObject): Pointer; cdecl; PyLong_FromVoidPtr:function(p: Pointer): PPyObject; cdecl; PyMapping_Check:function (ob:PPyObject):integer; cdecl; PyMapping_GetItemString:function (ob:PPyObject;key:PAnsiChar):PPyObject; cdecl; @@ -1695,7 +1765,6 @@ TPythonInterface=class(TDynamicDll) PySet_Size: function(anyset: PPyObject): Py_ssize_t; cdecl; PySys_GetObject:function (s:PAnsiChar):PPyObject; cdecl; PySys_SetObject:function (s:PAnsiChar;ob:PPyObject):integer; cdecl; - PySys_SetPath:procedure(path:PAnsiChar); cdecl; PyTraceBack_Here:function (p:pointer):integer; cdecl; PyTraceBack_Print:function (ob1,ob2:PPyObject):integer; cdecl; PyTuple_GetItem:function (ob:PPyObject;i:NativeInt):PPyObject; cdecl; @@ -1738,25 +1807,19 @@ TPythonInterface=class(TDynamicDll) Py_GetCopyright : function : PAnsiChar; cdecl; Py_GetExecPrefix : function : PWCharT; cdecl; Py_GetPath : function : PWCharT; cdecl; - Py_SetPath : procedure (path: PWCharT); cdecl; - Py_SetPythonHome : procedure (home : PWCharT); cdecl; Py_GetPythonHome : function : PWCharT; cdecl; Py_GetPrefix : function : PWCharT; cdecl; Py_GetProgramName : function : PWCharT; cdecl; - PyParser_SimpleParseStringFlags : function ( str : PAnsiChar; start, flags : Integer) : PNode; cdecl; - PyNode_Free : procedure( n : PNode ); cdecl; - PyErr_NewException : function ( name : PAnsiChar; base, dict : PPyObject ) : PPyObject; cdecl; - PyMem_Malloc : function ( size : NativeUInt ) : Pointer; + PyErr_NewException : function (name : PAnsiChar; base, dict : PPyObject): PPyObject; cdecl; + PyMem_Malloc : function (size: NativeUInt): Pointer; cdecl; + PyMem_Free : procedure (P: Pointer); cdecl; - Py_SetProgramName : procedure( name: PWCharT); cdecl; Py_IsInitialized : function : integer; cdecl; Py_GetProgramFullPath : function : PAnsiChar; cdecl; Py_NewInterpreter : function : PPyThreadState; cdecl; Py_NewInterpreterFromConfig : function( tstate: PPyThreadState; config: PPyInterpreterConfig): PyStatus; cdecl; Py_EndInterpreter : procedure( tstate: PPyThreadState); cdecl; - PyEval_AcquireLock : procedure; cdecl; - PyEval_ReleaseLock : procedure; cdecl; PyEval_AcquireThread : procedure( tstate: PPyThreadState); cdecl; PyEval_ReleaseThread : procedure( tstate: PPyThreadState); cdecl; PyInterpreterState_New : function : PPyInterpreterState; cdecl; @@ -1771,11 +1834,29 @@ TPythonInterface=class(TDynamicDll) PyGILState_Ensure : function() : PyGILstate_STATE; cdecl; PyGILState_Release : procedure(gilstate : PyGILState_STATE); cdecl; - // Not exported in Python 3.8 and implemented as functions - this has been fixed - // TODO - deal with the following: - // the PyParser_* functions are deprecated in python 3.9 and will be removed in - // Python 3.10 - function PyParser_SimpleParseString(str : PAnsiChar; start : Integer) : PNode; cdecl; + // PEP 587 Initialization functions + PyWideStringList_Append : function(list: PPyWideStringList; item: PWCharT): PyStatus; cdecl; + PyWideStringList_Insert : function(list: PPyWideStringList; index: Py_ssize_t; item: PWCharT): PyStatus; cdecl; + PyConfig_InitPythonConfig : procedure(var config: PyConfig); cdecl; + PyConfig_InitIsolatedConfig : procedure(var config: PyConfig); cdecl; + PyConfig_Clear : procedure(var config: PyConfig); cdecl; + PyConfig_SetString : function(var config: PyConfig; config_str: PPWCharT; str: PWCharT): PyStatus; cdecl; + PyConfig_Read : function(var config: PyConfig): PyStatus; cdecl; + PyConfig_SetArgv : function(var config: PyConfig; argc: Py_ssize_t; argv: PPWCharT): PyStatus; cdecl; + PyConfig_SetWideStringList : function(var config: PyConfig; list: PPyWideStringList; length: Py_ssize_t; items: PPWCharT): PyStatus; cdecl; + Py_InitializeFromConfig : function({$IFDEF FPC}constref{$ELSE}[Ref] const{$ENDIF} config: PyConfig): PyStatus; cdecl; + + // PEP 741 Initialization functions - python 3.14+ + PyInitConfig_Create : function(): PPyInitConfig; cdecl; + PyInitConfig_Free : procedure(config: PPyInitConfig); cdecl; + Py_InitializeFromInitConfig : function(config: PPyInitConfig): Integer; cdecl; + PyInitConfig_SetInt : function(config: PPyInitConfig; name: PAnsiChar; value: Int64): Integer; cdecl; + PyInitConfig_SetStr : function(config: PPyInitConfig; name: PAnsiChar; value: PAnsiChar): Integer; cdecl; + PyInitConfig_SetStrList : function(config: PPyInitConfig; name: PAnsiChar; Lenght: Py_ssize_t; value: PPAnsiChar): Integer; cdecl; + PyInitConfig_GetError : function(config: PPyInitConfig; err_msg: PPAnsiChar): integer; cdecl; + PyConfig_Get : function(name: PAnsiChar): PPyObject; cdecl; + PyConfig_Set : function(name: PAnsiChar; value: PPyObject): Integer; cdecl; + function Py_CompileString(str,filename:PAnsiChar;start:integer) : PPyObject; cdecl; // functions redefined in Delphi @@ -1880,15 +1961,26 @@ TPythonInterface=class(TDynamicDll) //-------------------------------------------------------- type TDatetimeConversionMode = (dcmToTuple, dcmToDatetime); + TPythonFlag = (pfDebug, pfInteractive, pfNoSite, pfOptimize, pfVerbose, + pfFrozen, pfIgnoreEnvironment, pfNoUserSiteDirectory, + pfDontWriteBytecode, pfIsolated); + TPythonFlags = set of TPythonFlag; + const DEFAULT_DATETIME_CONVERSION_MODE = dcmToTuple; + DEFAULT_FLAGS = + {$IFDEF IOS} + [pfIsolated, pfNoUserSiteDirectory, pfIgnoreEnvironment, + pfDontWriteBytecodeFlag] + {$ELSE} + [] + {$ENDIF IOS}; + type TEngineClient = class; - TPathInitializationEvent = procedure ( Sender : TObject; var Path : string ) of Object; - TSysPathInitEvent = procedure ( Sender : TObject; PathList : PPyObject ) of Object; - TPythonFlag = (pfDebug, pfInteractive, pfNoSite, pfOptimize, pfVerbose, - pfFrozenFlag, pfIgnoreEnvironmentFlag); - TPythonFlags = set of TPythonFlag; + TSysPathInitEvent = procedure(Sender: TObject; PathList: PPyObject) of object; + // Config will be either PPyConfig if version < 3.14 or PPyInitConfig + TConfigInitEvent = procedure(Sender: TObject; Config: Pointer) of object; TTracebackItem = class @@ -1925,7 +2017,7 @@ TPythonType = class; //forward declaration {$IFEND} TPythonEngine = class(TPythonInterface) private - FVenvPythonExe: string; + FPythonExecutable: string; FInitScript: TStrings; FIO: TPythonInputOutput; FRedirectIO: Boolean; @@ -1933,12 +2025,11 @@ TPythonEngine = class(TPythonInterface) FClients: TList; FExecModule: AnsiString; FAutoFinalize: Boolean; - FProgramName: WCharTString; - FPythonHome: WCharTString; - FPythonPath: WCharTString; - FInitThreads: Boolean; - FOnPathInitialization: TPathInitializationEvent; + FProgramName: UnicodeString; + FPythonHome: UnicodeString; + FPythonPath: UnicodeString; FOnSysPathInit: TSysPathInitEvent; + FOnConfigInit: TConfigInitEvent; FTraceback: TPythonTraceback; FUseWindowsConsole: Boolean; FGlobalVars: PPyObject; @@ -1955,10 +2046,6 @@ TPythonEngine = class(TPythonInterface) FPyDateTime_TZInfoType: PPyObject; FPyDateTime_TimeTZType: PPyObject; FPyDateTime_DateTimeTZType: PPyObject; - function GetPythonHome: UnicodeString; - function GetProgramName: UnicodeString; - function GetPythonPath: UnicodeString; - procedure SetPythonPath(const Value: UnicodeString); protected procedure Initialize; @@ -1968,20 +2055,16 @@ TPythonEngine = class(TPythonInterface) procedure DoOpenDll(const aDllName : string); override; procedure SetInitScript(Value: TStrings); function GetThreadState: PPyThreadState; - procedure SetInitThreads(Value: Boolean); function GetClientCount : Integer; function GetClients( idx : Integer ) : TEngineClient; procedure Notification(AComponent: TComponent; Operation: TOperation); override; - procedure CheckRegistry; - procedure SetProgramArgs; procedure InitWinConsole; procedure SetUseWindowsConsole( const Value : Boolean ); procedure SetGlobalVars(const Value: PPyObject); procedure SetLocalVars(const Value: PPyObject); procedure SetPyFlags(const Value: TPythonFlags); procedure SetIO(InputOutput: TPythonInputOutput); - procedure AssignPyFlags; public // Constructors & Destructors @@ -1994,11 +2077,8 @@ TPythonEngine = class(TPythonInterface) function Run_CommandAsString(const command: AnsiString; mode: Integer; const FileName: string = '<string>'): string; function Run_CommandAsObject(const command: AnsiString; mode: Integer; const FileName: string = '<string>'): PPyObject; function Run_CommandAsObjectWithDict(const command: AnsiString; mode: Integer; locals, globals: PPyObject; const FileName: string = '<string>'): PPyObject; - function EncodeString (const str: UnicodeString): AnsiString; {$IFDEF FPC}overload;{$ENDIF} - {$IFDEF FPC} - overload; - function EncodeString (const str: AnsiString): AnsiString; overload; - {$ENDIF} + function EncodeString(const str: UnicodeString): AnsiString; overload; + function EncodeString(const str: AnsiString): AnsiString; overload; function EncodeWindowsFilePath(const str: string): AnsiString; procedure ExecString(const command: AnsiString; const FileName: string = '<string>'); overload; procedure ExecStrings(strings: TStrings; const FileName: string = '<string>'); overload; @@ -2079,22 +2159,25 @@ TPythonEngine = class(TPythonInterface) property LocalVars : PPyObject read FLocalVars Write SetLocalVars; property GlobalVars : PPyObject read FGlobalVars Write SetGlobalVars; property IOPythonModule: TObject read FIOPythonModule; {TPythonModule} - property PythonHome: UnicodeString read GetPythonHome write SetPythonHome; - property ProgramName: UnicodeString read GetProgramName write SetProgramName; - property PythonPath: UnicodeString read GetPythonPath write SetPythonPath; + property PythonHome: UnicodeString read FPythonHome write SetPythonHome; + property ProgramName: UnicodeString read FProgramName write SetProgramName; + // List of paths separated with the path delimiter + // If used with pfNoSite, it completely overwrites the pyhon path on initialization! + // For adding directories to sys.path use the OnSysPathInit event instead. + property PythonPath: UnicodeString read FPythonPath write FPythonPath; published property AutoFinalize: Boolean read FAutoFinalize write FAutoFinalize default True; - property VenvPythonExe: string read FVenvPythonExe write FVenvPythonExe; + property PythonExecutable: string read FPythonExecutable write FPythonExecutable; property DatetimeConversionMode: TDatetimeConversionMode read FDatetimeConversionMode write FDatetimeConversionMode default DEFAULT_DATETIME_CONVERSION_MODE; property InitScript: TStrings read FInitScript write SetInitScript; - property InitThreads: Boolean read FInitThreads write SetInitThreads default False; property IO: TPythonInputOutput read FIO write SetIO; - property PyFlags: TPythonFlags read FPyFlags write SetPyFlags default []; + property PyFlags: TPythonFlags read FPyFlags write SetPyFlags default DEFAULT_FLAGS; property RedirectIO: Boolean read FRedirectIO write FRedirectIO default True; property UseWindowsConsole: Boolean read FUseWindowsConsole write FUseWindowsConsole default False; property OnAfterInit: TNotifyEvent read FOnAfterInit write FOnAfterInit; - property OnPathInitialization: TPathInitializationEvent read FOnPathInitialization write FOnPathInitialization; property OnSysPathInit: TSysPathInitEvent read FOnSysPathInit write FOnSysPathInit; + property OnConfigInit: TConfigInitEvent read FOnConfigInit write FOnConfigInit; + end; @@ -2372,8 +2455,8 @@ TError = class(TCollectionItem) destructor Destroy; override; procedure Assign(Source: TPersistent); override; procedure BuildError( const ModuleName : AnsiString ); - procedure RaiseError( const msg : AnsiString ); - procedure RaiseErrorObj( const msg : AnsiString; obj : PPyObject ); + procedure RaiseError(const msg : AnsiString); + procedure RaiseErrorObj(const msg : AnsiString; obj : PPyObject); function Owner : TErrors; property Error : PPyObject read FError write FError; published @@ -2501,9 +2584,9 @@ TPythonModule = class(TMethodsContainer) // The base class of all new Python types TPyObject = class private - function Get_ob_refcnt: NativeInt; + function Get_ob_refcnt: NativeUInt; function Get_ob_type: PPyTypeObject; - procedure Set_ob_refcnt(const Value: NativeInt); + procedure Set_ob_refcnt(const Value: NativeUInt); procedure Set_ob_type(const Value: PPyTypeObject); public PythonType : TPythonType; @@ -2524,7 +2607,7 @@ TPyObject = class procedure Adjust(PyPointer: Pointer); function GetModule : TPythonModule; - property ob_refcnt : NativeInt read Get_ob_refcnt write Set_ob_refcnt; + property ob_refcnt : NativeUInt read Get_ob_refcnt write Set_ob_refcnt; property ob_type : PPyTypeObject read Get_ob_type write Set_ob_type; // Type services @@ -2857,9 +2940,9 @@ TPythonThread = class(TThread) private class threadvar f_savethreadstate: PPyThreadState; + protected // Do not overwrite Execute! Use ExecuteWithPython instead! procedure Execute; override; - protected procedure ExecuteWithPython; virtual; abstract; function InterpreterConfig: PyInterpreterConfig; virtual; public @@ -2914,6 +2997,7 @@ procedure PythonVersionFromDLLName(LibName: string; out MajorVersion, MinorVersi function PythonVersionFromRegVersion(const ARegVersion: string; out AMajorVersion, AMinorVersion: integer): boolean; function PyStatus_Exception(const APyStatus: PyStatus): Boolean; +function StringToWCharTString(Str: string): WcharTString; //####################################################### //## ## @@ -2971,9 +3055,8 @@ function CleanString(const s : UnicodeString; AppendLF : Boolean = True) : Unico implementation uses -{$IFDEF FPC} StrUtils, -{$ELSE} +{$IFNDEF FPC} AnsiStrings, {$ENDIF} {$IFDEF MSWINDOWS} @@ -2995,6 +3078,61 @@ implementation SPyConvertionError = 'Conversion Error: %s expects a %s Python object'; SPyExcStopIteration = 'Stop Iteration'; SPyExcSystemError = 'Unhandled SystemExit exception. Code: %s'; +SPyInitFailed = 'Python initialization failed: %s'; +SPyInitFailedUnknown = 'Unknown initialization error'; +SCannotCreateMain = 'Run_CommandAsObject: can''t create __main__'; +SRaiseError = 'RaiseError: couldn''t fetch last exception'; +SMissingModuleDateTime = 'dcmToDatetime DatetimeConversionMode cannot be used with this version of python. Missing module datetime'; +SInvalidDateTimeConvMode = 'Invalid DatetimeConversionMode'; +SUnexpectedTypeInTimeObject = 'Unexpected type found in member %s of a time_struct object'; +SArguementTypeNotAllowed = 'Argument type not allowed'; +SCouldNotCreateTuple = 'Could not create a new tuple object'; +SCouldNotCreateList = 'Could not create a new list object'; +SCouldNotCreateDict = 'Could not create a new dict object'; +SArgumemntsShouldBeEven = 'You must provide an even number of arguments'; +SExpectedList = 'The python object is not a list'; +SExpectedTuple = 'The python object is not a tuple'; +SCouldNotSetVar = 'Could not set var "%s" in module "%s"'; +SCannotSetVarNoInit = 'Can''t set var "%s" in module "%s", because it is not yet initialized'; +SCannotGetDict = 'Can''t get __dict__ of module "%s"'; +SCannotDelVarNoInit = 'Can''t delete var "%s" in module "%s", because it is not yet initialized'; +SExpectedDelphiClass = 'Pytho;n object "%s" is not a Delphi class'; +SCannotCreateModule = 'CreateVar: can''t create module "%s"'; +SVarNotCreated = 'No variable was created'; +SVarExists = 'A variable "%s" already exists in the module "%s"'; +SCannotCreateThreadState = 'Could not create a new thread state'; +SCannotCreatePythonEngine = 'No Python engine was created'; +SCannotInitPythonEngine = 'The Python engine is not properly initialized'; +SThreadPythonExec = 'ThreadPythonExec should only be called from the main thread'; +SQuitMessage = 'Dll %s could not be loaded. We must quit.'; +SPythonQuitMessage = 'Python DLL %s could not be initialized. We must quit.'; +SErrCannotOpenDLL = 'Error %d: Could not open Dll "%s"'; +SPythonNoInit = 'Python is not initialized'; +SOnlyOnePythonEngine = 'You canott have more than one TPythonEngine component'; +SMoreThanOnePythonEngine = 'There is already one instance of TPythonEngine running'; +SGlobalVarsShouldBeDict = 'You must set a Python dictionary in the GlobalVars property'; +SLocalVarsShouldBeDict = 'You must set a Python dictionary in the LocalVars property'; +SCannotModifyFlags = 'You can''t modify Python flags after it has been initialized'; +SCannotFindType = 'Could not find type: %s'; +SCannotFindModule = 'Could not find module: %s'; +SCannotFindComponent = 'Could not find component: %s'; +SCannotHandleMoreThan3Dim = 'Can''t convert a variant array of more than 3 dimensions to a Python sequence'; +SNoEngineForComponent = 'No Engine defined for component "%s"'; +SIndexOutOfRange = '%s: Index %d out of range'; +SUnknownMemberType = 'Unknown member type'; +SUnknownMemberFlag = 'Unknown member flag'; +SDuplicateErrorName = 'In module "%s", there''s already an error named "%s"'; +SNoModuleWithParentClass = 'Could not find module containing the parent class of error "%s"'; +SCannotFindParentClass = 'Could not find the parent class "%s" of error "%s"'; +SObjectNotClass = 'The object "%s" in module "%s" is not a class'; +SErrorNotClass = 'Error without name in module "%s"'; +SCouldNotCreateError = 'Could not create error "%s"'; +STErrorCouldNotCreateInstance = 'TError.RaiseErrorObj: Could not create an instance of "%s"'; +STErrorCouldNotCreateTuple = 'TError.RaiseErrorObj: Could not create an empty tuple'; +STErrorNoInstance = 'TError.RaiseErrorObj: I didn''t get an instance'; +SCouldNotFindError = 'Could not find error "%s"'; +SCouldNotMapSymbol = 'Error %d: could not map symbol "%s"'; +SUndeterminedPythonVersion = 'Undetermined Python version'; (*******************************************************) (** **) @@ -3346,7 +3484,7 @@ procedure TDynamicDll.OpenDll(const aDllName : string); if not IsHandleValid then begin {$IFDEF MSWINDOWS} - s := Format('Error %d: Could not open Dll "%s"',[GetLastError, DllName]); + s := Format(SErrCannotOpenDLL, [GetLastError, DllName]); {$ELSE} s := Format('Error: Could not open Dll "%s"',[DllName]); {$ENDIF} @@ -3394,7 +3532,7 @@ function TDynamicDll.Import(const funcname: AnsiString; canFail : Boolean = True {$IFEND} if (Result = nil) and canFail then begin {$IFDEF MSWINDOWS} - E := EDllImportError.CreateFmt('Error %d: could not map symbol "%s"', [GetLastError, funcname]); + E := EDllImportError.CreateFmt(SCouldNotMapSymbol, [GetLastError, funcname]); E.ErrorCode := GetLastError; {$ELSE} E := EDllImportError.CreateFmt('Error: could not map symbol "%s"', [funcname]); @@ -3489,7 +3627,7 @@ procedure TDynamicDll.LoadPythonInfoFromModule; end; if not LFound then - raise EDLLLoadError.Create('Undetermined Python version from loaded module.'); + raise EDLLLoadError.Create(SUndeterminedPythonVersion); end; procedure TDynamicDll.LoadDll; @@ -3542,7 +3680,7 @@ procedure TDynamicDll.BeforeUnload; function TDynamicDll.GetQuitMessage : string; begin - Result := Format( 'Dll %s could not be loaded. We must quit.', [DllName]); + Result := Format(SQuitMessage, [DllName]); end; function TDynamicDll.HasPythonSymbolsInLibrary: boolean; @@ -3615,7 +3753,7 @@ procedure TPythonInterface.AfterLoad; if not FInExtensionModule then PythonVersionFromDLLName(DLLName, FMajorVersion, FMinorVersion) else if not PythonVersionFromRegVersion(RegVersion, FMajorVersion, FMinorVersion) then - raise EDLLLoadError.Create('Undetermined Python version.'); + raise EDLLLoadError.Create(SUndeterminedPythonVersion); FBuiltInModuleName := 'builtins'; @@ -3636,26 +3774,17 @@ procedure TPythonInterface.AfterLoad; function TPythonInterface.GetQuitMessage : string; begin - Result := Format( 'Python could not be properly initialized. We must quit.', [DllName]); + Result := Format(SPythonQuitMessage, [DllName]); end; procedure TPythonInterface.CheckPython; begin if not Initialized then - raise Exception.Create('Python is not properly initialized' ); + raise Exception.Create(SPythonNoInit); end; procedure TPythonInterface.MapDll; begin - Py_DebugFlag := Import('Py_DebugFlag'); - Py_VerboseFlag := Import('Py_VerboseFlag'); - Py_InteractiveFlag := Import('Py_InteractiveFlag'); - Py_OptimizeFlag := Import('Py_OptimizeFlag'); - Py_NoSiteFlag := Import('Py_NoSiteFlag'); - Py_FrozenFlag := Import('Py_FrozenFlag'); - - Py_IgnoreEnvironmentFlag := Import('Py_IgnoreEnvironmentFlag'); - Py_None := Import('_Py_NoneStruct'); Py_Ellipsis := Import('_Py_EllipsisObject'); Py_False := Import('_Py_FalseStruct'); @@ -3738,6 +3867,7 @@ procedure TPythonInterface.MapDll; PyStaticMethod_Type := Import('PyStaticMethod_Type'); PySuper_Type := Import('PySuper_Type'); PyTraceBack_Type := Import('PyTraceBack_Type'); + PyGetSetDescr_Type := Import('PyGetSetDescr_Type'); PyWrapperDescr_Type := Import('PyWrapperDescr_Type'); _PyWeakref_RefType := Import('_PyWeakref_RefType'); _PyWeakref_ProxyType := Import('_PyWeakref_ProxyType'); @@ -3798,7 +3928,6 @@ procedure TPythonInterface.MapDll; PyRun_String := Import('PyRun_String'); PyRun_SimpleString := Import('PyRun_SimpleString'); PyDict_GetItemString := Import('PyDict_GetItemString'); - PySys_SetArgv := Import('PySys_SetArgv'); Py_Exit := Import('Py_Exit'); PyCFunction_NewEx := Import('PyCFunction_NewEx'); @@ -3813,11 +3942,9 @@ procedure TPythonInterface.MapDll; if (FMajorVersion > 3) or (FMinorVersion > 9) then PyBuffer_SizeFromFormat := Import('PyBuffer_SizeFromFormat'); - PyEval_CallObjectWithKeywords:= Import('PyEval_CallObjectWithKeywords'); PyEval_GetFrame := Import('PyEval_GetFrame'); PyEval_GetGlobals := Import('PyEval_GetGlobals'); PyEval_GetLocals := Import('PyEval_GetLocals'); - PyEval_InitThreads := Import('PyEval_InitThreads'); PyEval_RestoreThread := Import('PyEval_RestoreThread'); PyEval_SaveThread := Import('PyEval_SaveThread'); PyFile_GetLine := Import('PyFile_GetLine'); @@ -3858,6 +3985,7 @@ procedure TPythonInterface.MapDll; PyLong_FromLongLong := Import('PyLong_FromLongLong'); PyLong_FromUnsignedLongLong := Import('PyLong_FromUnsignedLongLong'); PyLong_AsLongLong := Import('PyLong_AsLongLong'); + PyLong_AsVoidPtr := Import('PyLong_AsVoidPtr'); PyLong_FromVoidPtr := Import('PyLong_FromVoidPtr'); PyMapping_Check := Import('PyMapping_Check'); PyMapping_GetItemString := Import('PyMapping_GetItemString'); @@ -3977,7 +4105,6 @@ procedure TPythonInterface.MapDll; PySet_Size := Import('PySet_Size'); PySys_GetObject := Import('PySys_GetObject'); PySys_SetObject := Import('PySys_SetObject'); - PySys_SetPath := Import('PySys_SetPath'); PyTraceBack_Here := Import('PyTraceBack_Here'); PyTraceBack_Print := Import('PyTraceBack_Print'); PyTuple_GetItem := Import('PyTuple_GetItem'); @@ -4020,24 +4147,14 @@ procedure TPythonInterface.MapDll; Py_GetCopyright := Import('Py_GetCopyright'); Py_GetExecPrefix := Import('Py_GetExecPrefix'); Py_GetPath := Import('Py_GetPath'); - Py_SetPath := Import('Py_SetPath'); - Py_SetPythonHome := Import('Py_SetPythonHome'); Py_GetPythonHome := Import('Py_GetPythonHome'); Py_GetPrefix := Import('Py_GetPrefix'); Py_GetProgramName := Import('Py_GetProgramName'); - if (FMajorVersion = 3) and (FMinorVersion < 10) then - begin - PyParser_SimpleParseStringFlags := Import('PyParser_SimpleParseStringFlags'); - PyNode_Free := Import('PyNode_Free'); - end; + PyErr_NewException := Import('PyErr_NewException'); + PyMem_Malloc := Import ('PyMem_Malloc'); + PyMem_Free := Import ('PyMem_Free'); - PyErr_NewException := Import('PyErr_NewException'); - try - PyMem_Malloc := Import ('PyMem_Malloc'); - except - end; - Py_SetProgramName := Import('Py_SetProgramName'); Py_IsInitialized := Import('Py_IsInitialized'); Py_GetProgramFullPath := Import('Py_GetProgramFullPath'); Py_GetBuildInfo := Import('Py_GetBuildInfo'); @@ -4045,8 +4162,6 @@ procedure TPythonInterface.MapDll; if (FMajorVersion > 3) or (FMinorVersion >= 12) then Py_NewInterpreterFromConfig := Import('Py_NewInterpreterFromConfig'); Py_EndInterpreter := Import('Py_EndInterpreter'); - PyEval_AcquireLock := Import('PyEval_AcquireLock'); - PyEval_ReleaseLock := Import('PyEval_ReleaseLock'); PyEval_AcquireThread := Import('PyEval_AcquireThread'); PyEval_ReleaseThread := Import('PyEval_ReleaseThread'); PyInterpreterState_New := Import('PyInterpreterState_New'); @@ -4060,6 +4175,31 @@ procedure TPythonInterface.MapDll; PyErr_SetInterrupt := Import('PyErr_SetInterrupt'); PyGILState_Ensure := Import('PyGILState_Ensure'); PyGILState_Release := Import('PyGILState_Release'); + + PyWideStringList_Append := Import('PyWideStringList_Append'); + PyWideStringList_Insert := Import('PyWideStringList_Insert'); + PyConfig_InitPythonConfig := Import('PyConfig_InitPythonConfig'); + PyConfig_InitIsolatedConfig := Import('PyConfig_InitIsolatedConfig'); + PyConfig_Clear := Import('PyConfig_Clear'); + PyConfig_SetString := Import('PyConfig_SetString'); + PyConfig_Read := Import('PyConfig_Read'); + PyConfig_SetArgv := Import('PyConfig_SetArgv'); + PyConfig_SetWideStringList := Import('PyConfig_SetWideStringList'); + Py_InitializeFromConfig := Import('Py_InitializeFromConfig'); + + // PEP 741 + if (MajorVersion > 3) or (MinorVersion >= 14) then + begin + PyInitConfig_Create := Import('PyInitConfig_Create'); + PyInitConfig_Free := Import('PyInitConfig_Free'); + Py_InitializeFromInitConfig := Import('Py_InitializeFromInitConfig'); + PyInitConfig_SetInt := Import('PyInitConfig_SetInt'); + PyInitConfig_SetStr := Import('PyInitConfig_SetStr'); + PyInitConfig_SetStrList := Import('PyInitConfig_SetStrList'); + PyInitConfig_GetError := Import('PyInitConfig_GetError'); + PyConfig_Get := Import('PyConfig_Get'); + PyConfig_Set := Import('PyConfig_Set'); + end; end; function TPythonInterface.Py_CompileString(str,filename:PAnsiChar;start:integer):PPyObject; @@ -4067,11 +4207,6 @@ function TPythonInterface.Py_CompileString(str,filename:PAnsiChar;start:integer) Result := Py_CompileStringExFlags(str, filename, start, nil, -1); end; -function TPythonInterface.PyParser_SimpleParseString( str : PAnsiChar; start : integer) : PNode; cdecl; -begin - Result := PyParser_SimpleParseStringFlags(str, start, 0); -end; - class procedure TPythonInterface.Py_INCREF(op: PPyObject); begin Inc(op^.ob_refcnt); @@ -4364,7 +4499,7 @@ procedure TPythonTraceback.Clear; * This method is automatically called by the Exec/Eval methods of * TPythonEngine. But if you use the Python core API, then don't * forget to refresh the traceback yourself. Or much better, - * simply use the method CheckError wich will call PyErr_Print, + * simply use the method CheckError which will call PyErr_Print, * Traceback.Refresh and RaiseError for you. } procedure TPythonTraceback.Refresh(pytraceback: PPyObject); @@ -4481,17 +4616,16 @@ constructor TPythonEngine.Create(AOwner: TComponent); FRedirectIO := True; FExecModule := '__main__'; FAutoFinalize := True; - FInitThreads := False; FTraceback := TPythonTraceback.Create; FUseWindowsConsole := False; - FPyFlags := []; + FPyFlags := DEFAULT_FLAGS; FDatetimeConversionMode := DEFAULT_DATETIME_CONVERSION_MODE; if csDesigning in ComponentState then begin for i := 0 to AOwner.ComponentCount - 1 do if (AOwner.Components[i] is TPythonEngine) and (AOwner.Components[i] <> Self) then - raise Exception.Create('You can''t drop more than one TPythonEngine component'); + raise Exception.Create(SOnlyOnePythonEngine); end; end; @@ -4596,45 +4730,250 @@ procedure TPythonEngine.DoOpenDll(const aDllName : string); end; end; -procedure TPythonEngine.AssignPyFlags; +procedure TPythonEngine.Initialize; + + procedure ConfigPEP587(var ErrMsg: string); + // Initialize according to PEP587 available since python 3.8 - procedure SetFlag( AFlag: PInteger; AValue : Boolean ); + procedure AssignPyFlags(var Config: PyConfig); + begin + PInteger(PByte(@Config) + ConfigOffests[MinorVersion, TConfigFields.parser_debug])^ := + IfThen(pfDebug in FPyFlags, 1, 0); + PInteger(PByte(@Config) + ConfigOffests[MinorVersion, TConfigFields.verbose])^ := + IfThen(pfVerbose in FPyFlags, 1, 0); + PInteger(PByte(@Config) + ConfigOffests[MinorVersion, TConfigFields.interactive])^ := + IfThen(pfInteractive in FPyFlags, 1, 0); + PInteger(PByte(@Config) + ConfigOffests[MinorVersion, TConfigFields.optimization_level])^ := + IfThen(pfOptimize in FPyFlags, 1, 0); + PInteger(PByte(@Config) + ConfigOffests[MinorVersion, TConfigFields.site_import])^ := + IfThen(pfNoSite in FPyFlags, 0, 1); + PInteger(PByte(@Config) + ConfigOffests[MinorVersion, TConfigFields.pathconfig_warnings])^ := + IfThen(pfFrozen in FPyFlags, 1, 0); + PInteger(PByte(@Config) + ConfigOffests[MinorVersion, TConfigFields.use_environment])^ := + IfThen(pfIgnoreEnvironment in FPyFlags, 0, 1); + end; + + procedure SetProgramArgs(var Config: PyConfig); + var + I: Integer; + TempS: UnicodeString; + Str: WCharTString; + + begin + // do not parse further + PInteger(PByte(@Config) + ConfigOffests[MinorVersion, TConfigFields.parse_argv])^ := 0; + for I := 0 to ParamCount do + begin + { + ... the first entry should refer to the script file to be executed rather + than the executable hosting the Python interpreter. If there isn’t a + script that will be run, the first entry in argv can be an empty string. + } + if I = 0 then + TempS := '' + else + TempS := ParamStr(I); + {$IFDEF POSIX} + Str := UnicodeStringToUCS4String(TempS); + {$ELSE} + Str := TempS; + {$ENDIF} + PyWideStringList_Append( + PPyWideStringList(PByte(@Config) + ConfigOffests[MinorVersion, TConfigFields.argv]), + PWCharT(Str)); + end; + end; + + procedure SetPythonPath(var Config: PyConfig); + var + Paths: TStringDynArray; + I: Integer; + PWSL: PPyWideStringList; + begin + if FPythonPath = '' then Exit; + + PWSL := PPyWideStringList(PByte(@Config) + ConfigOffests[MinorVersion, + TConfigFields.module_search_paths]); + Paths := SplitString(string(FPythonPath), PathSep); + for I := 0 to Length(Paths) - 1 do + begin + if (Paths[I] = '') and (I > 0) then + Continue; + PyWideStringList_Append(PWSL, PWCharT(StringToWCharTString(Paths[I]))); + end; + + if PWSL^.length > 0 then + PInteger(PByte(@Config) + ConfigOffests[MinorVersion, + TConfigFields.module_search_paths_set])^ := 1; + end; + + var + Config: PyConfig; + Status: PyStatus; begin - if AValue then - AFlag^ := 1 + // Fills Config with zeros and then sets some default values + if pfIsolated in FPyFlags then + PyConfig_InitIsolatedConfig(Config) else - AFlag^ := 0; + PyConfig_InitPythonConfig(Config); + try + AssignPyFlags(Config); + + // Set programname and pythonhome if available + if FProgramName <> '' then + PyConfig_SetString(Config, + PPWcharT(PByte(@Config) + ConfigOffests[MinorVersion, TConfigFields.program_name]), + PWCharT(StringToWCharTString(FProgramName))); + if FPythonHome <> '' then + PyConfig_SetString(Config, + PPWcharT(PByte(@Config) + ConfigOffests[MinorVersion, TConfigFields.home]), + PWCharT(StringToWCharTString(FPythonHome))); + // Set venv executable if available + if FPythonExecutable <> '' then + PyConfig_SetString(Config, + PPWcharT(PByte(@Config) + ConfigOffests[MinorVersion, TConfigFields.executable]), + PWCharT(StringToWCharTString(FPythonExecutable))); + + // Set program arguments (sys.argv) + SetProgramArgs(Config); + + // PythonPath + SetPythonPath(Config); + + // Fine tune Config + if Assigned(FOnConfigInit) then + FOnConfigInit(Self, @Config); + + Status := Py_InitializeFromConfig(Config); + FInitialized := Py_IsInitialized() <> 0; + + if PyStatus_Exception(Status) then + ErrMsg := Format(SPyInitFailed, [string(Status.err_msg)]) + else if not FInitialized then + ErrMsg := Format(SPyInitFailed, [SPyInitFailedUnknown]); + + finally + PyConfig_Clear(Config); + end; end; -begin - // define each Python flag. See file pyDebug.h - SetFlag(Py_DebugFlag, pfDebug in FPyFlags); - SetFlag(Py_VerboseFlag, pfVerbose in FPyFlags); - SetFlag(Py_InteractiveFlag, pfInteractive in FPyFlags); - SetFlag(Py_OptimizeFlag, pfOptimize in FPyFlags); - SetFlag(Py_NoSiteFlag, pfNoSite in FPyFlags); - SetFlag(Py_FrozenFlag, pfFrozenFlag in FPyFlags); - SetFlag(Py_IgnoreEnvironmentFlag, pfIgnoreEnvironmentFlag in FPyFlags); -end; + procedure ConfigPEP741(var ErrMsg: string); + // Initialize according to PEP587 available since python 3.8 -procedure TPythonEngine.Initialize; + procedure AssignPyFlags(Config: PPyInitConfig); + begin + PyInitConfig_SetInt(Config, 'isolated', IfThen(pfIsolated in FPyFlags, 1, 0)); + PyInitConfig_SetInt(Config, 'parser_debug', IfThen(pfDebug in FPyFlags, 1, 0)); + PyInitConfig_SetInt(Config, 'verbose', IfThen(pfVerbose in FPyFlags, 1, 0)); + PyInitConfig_SetInt(Config, 'interactive', IfThen(pfInteractive in FPyFlags, 1, 0)); + PyInitConfig_SetInt(Config, 'optimization_level', IfThen(pfOptimize in FPyFlags, 1, 0)); + PyInitConfig_SetInt(Config, 'site_import', IfThen(pfNoSite in FPyFlags, 0, 1)); + PyInitConfig_SetInt(Config, 'pathconfig_warnings', IfThen(pfFrozen in FPyFlags, 1, 0)); + PyInitConfig_SetInt(Config, 'use_environment', IfThen(pfIgnoreEnvironment in FPyFlags, 0, 1)); + PyInitConfig_SetInt(Config, 'user_site_directory', IfThen(pfNoUserSiteDirectory in FPyFlags, 0, 1)); + PyInitConfig_SetInt(Config, 'write_bytecode', IfThen(pfDontWriteBytecode in FPyFlags, 0, 1)); + end; + + procedure SetProgramArgs(Config: PPyInitConfig); + var + I: Integer; + Params: TArray<AnsiString>; + PParams: TArray<PAnsiChar>; + begin + // do not parse further + PyInitConfig_SetInt(Config, 'parse_argv', 0); + + SetLength(Params, ParamCount + 1); + SetLength(PParams, ParamCount + 1); + for I := 0 to ParamCount do + begin + { + ... the first entry should refer to the script file to be executed rather + than the executable hosting the Python interpreter. If there isn’t a + script that will be run, the first entry in argv can be an empty string. + } + if I = 0 then + Params[I] := '' + else + Params[I] := EncodeString(ParamStr(I)); + PParams[I] := PAnsiChar(Params[I]) + end; + PyInitConfig_SetStrList(Config, 'argv', ParamCount + 1, @PParams[0]); + end; + + procedure SetPythonPath(Config: PPyInitConfig); + var + Paths: TStringDynArray; + I: Integer; + Utf8Paths: TArray<AnsiString>; + PUtf8Paths: TArray<PAnsiChar>; + begin + if FPythonPath = '' then Exit; + + Paths := SplitString(string(FPythonPath), PathSep); + + if Length(Paths) = 0 then Exit; + + SetLength(Utf8Paths, Length(Paths)); + SetLength(PUtf8Paths, Length(Paths)); + + for I := 0 to Length(Paths) - 1 do + begin + Utf8Paths[I] := EncodeString(Paths[I]); + PUtf8Paths[I] := PAnsiChar(Utf8Paths[I]); + end; + + // The following Also sets module_search_paths_set + PyInitConfig_SetStrList(Config, 'module_search_paths', Length(Paths), @PUtf8Paths[0]); + end; + + var + Config: PPyInitConfig; + PErrMsg: PAnsiChar; + begin + Config := PyInitConfig_Create; + try + AssignPyFlags(Config); + + // Set programname and pythonhome if available + if FProgramName <> '' then + PyInitConfig_SetStr(Config, 'program_name', PAnsiChar(EncodeString(FProgramName))); + if FPythonHome <> '' then + PyInitConfig_SetStr(Config, 'home', PAnsiChar(EncodeString(FPythonHome))); + // Set venv executable if available + if FPythonExecutable <> '' then + PyInitConfig_SetStr(Config, 'executable', PAnsiChar(EncodeString(FPythonExecutable))); + + // Set program arguments (sys.argv) + SetProgramArgs(Config); + + // PythonPath + SetPythonPath(Config); + + // Fine tune Config + if Assigned(FOnConfigInit) then + FOnConfigInit(Self, Config); + + if Py_InitializeFromInitConfig(Config) <> 0 then + begin + FInitialized := False; + PyInitConfig_GetError(Config, @PErrMsg); + if PErrMsg <> nil then + ErrMsg := Format(SPyInitFailed, [UTF8ToString(AnsiString(PErrMsg))]); + end + else + FInitialized := Py_IsInitialized() <> 0; + if not FInitialized and (ErrMsg = '') then + ErrMsg := Format(SPyInitFailed, [SPyInitFailedUnknown]); + finally + PyInitConfig_Free(Config); + end; + end; procedure InitSysPath; var _path : PPyObject; - const Script = - 'import sys' + sLineBreak + - 'sys.executable = r"%s"' + sLineBreak + - 'path = sys.path' + sLineBreak + - 'for i in range(len(path)-1, -1, -1):' + sLineBreak + - ' if path[i].find("site-packages") > 0:' + sLineBreak + - ' path.pop(i)' + sLineBreak + - 'import site' + sLineBreak + - 'site.main()' + sLineBreak + - 'del sys, path, i, site'; begin - if VenvPythonExe <> '' then - ExecString(AnsiString(Format(Script, [VenvPythonExe]))); _path := PySys_GetObject('path'); if Assigned(FOnSysPathInit) then FOnSysPathInit(Self, _path); @@ -4689,9 +5028,10 @@ procedure TPythonEngine.Initialize; var i : Integer; + ErrMsg: string; begin if Assigned(gPythonEngine) then - raise Exception.Create('There is already one instance of TPythonEngine running' ); + raise Exception.Create(SMoreThanOnePythonEngine); gPythonEngine := Self; @@ -4700,21 +5040,26 @@ procedure TPythonEngine.Initialize; FInitialized := True else begin - CheckRegistry; - if Assigned(Py_SetProgramName) and (Length(FProgramName) > 0) then - Py_SetProgramName(PWCharT(FProgramName)); - AssignPyFlags; - if Length(FPythonHome) > 0 then - Py_SetPythonHome(PWCharT(FPythonHome)); - Py_Initialize; - if Assigned(Py_IsInitialized) then - FInitialized := Py_IsInitialized() <> 0 + if (MajorVersion > 3) or (MinorVersion >= 14) then + ConfigPEP741(ErrMsg) else - FInitialized := True; + ConfigPEP587(ErrMsg); + + if not FInitialized then + begin + if FatalMsgDlg then + {$IFDEF MSWINDOWS} + MessageBox( GetActiveWindow, PChar(ErrMsg), 'Error', MB_TASKMODAL or MB_ICONSTOP ); + {$ELSE} + WriteLn(ErrOutput, ErrMsg); + {$ENDIF} + if FatalAbort then + Quit + else + raise Exception.Create(ErrMsg); + end; + InitSysPath; - SetProgramArgs; - if InitThreads and Assigned(PyEval_InitThreads) then - PyEval_InitThreads; if RedirectIO and Assigned(FIO) then DoRedirectIO; end; @@ -4746,16 +5091,6 @@ function TPythonEngine.GetThreadState: PPyThreadState; Result := nil; end; -procedure TPythonEngine.SetInitThreads(Value: Boolean); -begin - if Value <> FInitThreads then - begin - if Value and Assigned(PyEval_InitThreads) then - PyEval_InitThreads; - FInitThreads := Value; - end; -end; - procedure TPythonEngine.SetIO(InputOutput: TPythonInputOutput); begin if InputOutput <> fIO then @@ -4786,96 +5121,6 @@ procedure TPythonEngine.Notification( AComponent: TComponent; IO := nil end; -procedure TPythonEngine.CheckRegistry; -{$IFDEF MSWINDOWS} -var - key : string; - Path : string; - NewPath : string; -{$IFDEF CPUX86} - LMajorVersion : integer; - LMinorVersion : integer; -{$ENDIF} - VersionSuffix: string; -{$ENDIF} -begin -{$IFDEF MSWINDOWS} - if Assigned( FOnPathInitialization ) then - try - with TRegistry.Create(KEY_ALL_ACCESS and not KEY_NOTIFY) do - try - VersionSuffix := ''; -{$IFDEF CPUX86} - PythonVersionFromRegVersion(RegVersion, LMajorVersion, LMinorVersion); - if (LMajorVersion > 3) or ((LMajorVersion = 3) and (LMinorVersion >= 5)) then - VersionSuffix := '-32'; -{$ENDIF} - key := Format('\Software\Python\PythonCore\%s%s\PythonPath', [RegVersion, VersionSuffix]); - - RootKey := HKEY_LOCAL_MACHINE; - if not KeyExists( key ) then - begin - // try a current user installation - RootKey := HKEY_CURRENT_USER; - if not KeyExists( key ) then Exit; - end; - // Key found - OpenKey( key, True ); - try - Path := ReadString(''); - NewPath := Path; - FOnPathInitialization( Self, NewPath ); - if NewPath <> Path then - begin - WriteString( '', NewPath ); - end; - finally - CloseKey; - end; - finally - Free; - end; - except - // under WinNT, with a user without admin rights, the access to the - // LocalMachine keys would raise an exception. - end; -{$ENDIF} -end; - -procedure TPythonEngine.SetProgramArgs; -var - I, argc : Integer; - wargv : array of PWCharT; - WL : array of WCharTString; - TempS: UnicodeString; -begin - // we build a string list of the arguments, because ParamStr returns a volatile string - // and we want to build an array of PWCharT, pointing to valid strings. - argc := ParamCount; - SetLength(wargv, argc + 1); - // build the PWCharT array - SetLength(WL, argc+1); - for I := 0 to argc do begin - { - ... the first entry should refer to the script file to be executed rather - than the executable hosting the Python interpreter. If there isn’t a - script that will be run, the first entry in argv can be an empty string. - } - if I = 0 then - TempS := '' - else - TempS := ParamStr(I); - {$IFDEF POSIX} - WL[I] := UnicodeStringToUCS4String(TempS); - {$ELSE} - WL[I] := UnicodeString(TempS); - {$ENDIF} - wargv[I] := PWCharT(WL[I]); - end; - // set the argv list of the sys module with the application arguments - PySys_SetArgv( argc + 1, PPWCharT(wargv) ); -end; - procedure TPythonEngine.InitWinConsole; begin {$IFDEF MSWINDOWS} @@ -4903,7 +5148,7 @@ procedure TPythonEngine.SetGlobalVars(const Value: PPyObject); else begin FGlobalVars := nil; - raise Exception.Create('You must set a Python dictionary in the GlobalVars property'); + raise Exception.Create(SGlobalVarsShouldBeDict); end else FGlobalVars := nil; @@ -4921,7 +5166,7 @@ procedure TPythonEngine.SetLocalVars(const Value: PPyObject); else begin FLocalVars := nil; - raise Exception.Create('You must set a Python dictionary in the LocalVars property'); + raise Exception.Create(SLocalVarsShouldBeDict); end else FLocalVars := nil; @@ -4933,35 +5178,11 @@ procedure TPythonEngine.SetPyFlags(const Value: TPythonFlags); if FPyFlags <> Value then begin if Initialized then - raise Exception.Create('You can''t modify Python flags after it has been initialized'); + raise Exception.Create(SCannotModifyFlags); FPyFlags := Value; end; // of if end; -function TPythonEngine.GetPythonHome: UnicodeString; -begin -{$IFDEF POSIX} - if Length(FPythonHome) = 0 then - Result := '' - else - Result := UCS4StringToUnicodeString(FPythonHome); -{$ELSE} - Result := FPythonHome; -{$ENDIF} -end; - -function TPythonEngine.GetPythonPath: UnicodeString; -begin -{$IFDEF POSIX} - if (Length(FPythonPath) > 0) then - Result := UCS4StringToUnicodeString(FPythonPath) - else - Result := ''; -{$ELSE} - Result := FPythonPath; -{$ENDIF} -end; - function TPythonEngine.GetSequenceItem(sequence: PPyObject; idx: Integer): Variant; var @@ -4975,43 +5196,14 @@ function TPythonEngine.GetSequenceItem(sequence: PPyObject; end; end; -function TPythonEngine.GetProgramName: UnicodeString; -begin -{$IFDEF POSIX} - if Length(FProgramName) = 0 then - Result := '' - else - Result := UCS4StringToUnicodeString(FProgramName); -{$ELSE} - Result := FProgramName; -{$ENDIF} -end; - procedure TPythonEngine.SetPythonHome(const PythonHome: UnicodeString); begin -{$IFDEF POSIX} - FPythonHome := UnicodeStringToUCS4String(PythonHome); -{$ELSE} FPythonHome := PythonHome; -{$ENDIF} -end; - -procedure TPythonEngine.SetPythonPath(const Value: UnicodeString); -begin -{$IFDEF POSIX} - FPythonPath := UnicodeStringToUCS4String(Value); -{$ELSE} - FPythonPath := Value; -{$ENDIF} end; procedure TPythonEngine.SetProgramName(const ProgramName: UnicodeString); begin -{$IFDEF POSIX} - FProgramName := UnicodeStringToUCS4String(ProgramName); -{$ELSE} FProgramName := ProgramName; -{$ENDIF} end; function TPythonEngine.EvalPyFunction(pyfunc, pyargs:PPyObject): Variant; @@ -5021,7 +5213,7 @@ function TPythonEngine.EvalPyFunction(pyfunc, pyargs:PPyObject): Variant; Result := -1; if pyfunc = nil then exit; try - presult := PyEval_CallObjectWithKeywords(pyfunc,pyargs, nil); + presult := PyObject_Call(pyfunc,pyargs, nil); CheckError(False); if presult = nil then // should not happen since an exception would have been raised @@ -5127,7 +5319,7 @@ function TPythonEngine.Run_CommandAsObjectWithDict(const command: AnsiString; m := GetMainModule; if m = nil then - raise EPythonError.Create('Run_CommandAsObject: can''t create __main__'); + raise EPythonError.Create(SCannotCreateMain); if Assigned(locals) then _locals := locals @@ -5233,22 +5425,11 @@ function TPythonEngine.CheckExecSyntax( const str : AnsiString ) : Boolean; function TPythonEngine.CheckSyntax( const str : AnsiString; mode : Integer ) : Boolean; var - n : PNode; PyCode: PPyObject; begin - if (FMajorVersion = 3) and (MinorVersion < 10) then - begin - n := PyParser_SimpleParseString( PAnsiChar(str), mode ); - result := Assigned(n); - if Assigned( n ) then - PyNode_Free(n); - end - else - begin - PyCode := Py_CompileString(PAnsiChar(str), '<string>', mode); - Result := Assigned(PyCode); - Py_XDECREF(PyCode); - end; + PyCode := Py_CompileString(PAnsiChar(str), '<string>', mode); + Result := Assigned(PyCode); + Py_XDECREF(PyCode); end; procedure TPythonEngine.RaiseError; @@ -5389,9 +5570,7 @@ procedure TPythonEngine.RaiseError; s_type := GetTypeAsString(err_type); s_value := PyObjectAsString(err_value); - if (PyErr_GivenExceptionMatches(err_type, PyExc_SystemExit^) <> 0) then - raise Define( EPySystemExit.Create(''), s_type, s_value ) - else if (PyErr_GivenExceptionMatches(err_type, PyExc_StopIteration^) <> 0) then + if (PyErr_GivenExceptionMatches(err_type, PyExc_StopIteration^) <> 0) then raise Define( EPyStopIteration.Create(''), s_type, s_value ) else if (PyErr_GivenExceptionMatches(err_type, PyExc_KeyboardInterrupt^) <> 0) then raise Define( EPyKeyboardInterrupt.Create(''), s_type, s_value ) @@ -5482,31 +5661,28 @@ procedure TPythonEngine.RaiseError; raise Define( EPyExecError.Create(''), s_type, s_value ); end else - raise EPythonError.Create('RaiseError: couldn''t fetch last exception'); + raise EPythonError.Create(SRaiseError); end; function TPythonEngine.PyObjectAsString( obj : PPyObject ) : string; var S : PPyObject; - W : UnicodeString; begin Result := ''; if not Assigned( obj ) then Exit; if PyUnicode_Check(obj) then + Result := string(PyUnicodeAsString(obj)) + else if PyBytes_Check(obj) then + Result := string(UTF8ToString(PyBytesAsAnsiString(obj))) + else begin - W := PyUnicodeAsString(obj); - Result := string(W); - Exit; - end; - S := PyObject_Str( obj ); - if Assigned(S) and PyUnicode_Check(S) then - begin - W := PyUnicodeAsString(S); - Result := string(W); + S := PyObject_Str( obj ); + if Assigned(S) and PyUnicode_Check(S) then + Result := string(PyUnicodeAsString(S)); + Py_XDECREF(S); end; - Py_XDECREF(S); end; procedure TPythonEngine.DoRedirectIO; @@ -5588,17 +5764,15 @@ function TPythonEngine.FindClient( const aName : string ) : TEngineClient; end; end; -function TPythonEngine.EncodeString(const str: UnicodeString): AnsiString; {$IFDEF FPC}overload;{$ENDIF} +function TPythonEngine.EncodeString(const str: UnicodeString): AnsiString; begin - Result := UTF8Encode(str) + Result := UTF8Encode(str); end; -{$IFDEF FPC} -function TPythonEngine.EncodeString (const str: AnsiString): AnsiString; overload; +function TPythonEngine.EncodeString(const str: AnsiString): AnsiString; begin - Result := str; + Result := UTF8Encode(str); end; -{$ENDIF} function TPythonEngine.EncodeWindowsFilePath(const str: string): AnsiString; {PEP 529} @@ -5621,7 +5795,7 @@ function TPythonEngine.TypeByName( const aTypeName : AnsiString ) : PPyTypeObjec Result := TheTypePtr; Exit; end; - raise Exception.CreateFmt('Could not find type: %s', [aTypeName]); + raise Exception.CreateFmt(SCannotFindType, [aTypeName]); end; function TPythonEngine.ModuleByName( const aModuleName : AnsiString ) : PPyObject; @@ -5636,7 +5810,7 @@ function TPythonEngine.ModuleByName( const aModuleName : AnsiString ) : PPyObj Result := Module; Exit; end; - raise Exception.CreateFmt('Could not find module: %s', [aModuleName]); + raise Exception.CreateFmt(SCannotFindModule, [aModuleName]); end; function TPythonEngine.MethodsByName( const aMethodsContainer: string ) : PPyMethodDef; @@ -5651,7 +5825,7 @@ function TPythonEngine.MethodsByName( const aMethodsContainer: string ) : PPyMet Result := MethodsData; Exit; end; - raise Exception.CreateFmt('Could not find component: %s', [aMethodsContainer]); + raise Exception.CreateFmt(SCannotFindComponent, [aMethodsContainer]); end; function TPythonEngine.VariantAsPyObject( const V : Variant ) : PPyObject; @@ -5771,17 +5945,17 @@ function TPythonEngine.VariantAsPyObject( const V : Variant ) : PPyObject; else if (DatetimeConversionMode = dcmToDatetime) then begin if not Assigned(FPyDateTime_DateTimeType) then - raise EPythonError.Create('dcmToDatetime DatetimeConversionMode cannot be used with this version of python. Missing module datetime'); + raise EPythonError.Create(SMissingModuleDateTime); args := ArrayToPyTuple([y, m, d, h, mi, sec, ms*1000]); try - Result := PyEval_CallObjectWithKeywords(FPyDateTime_DateTimeType, args, nil); + Result := PyObject_Call(FPyDateTime_DateTimeType, args, nil); CheckError(False); finally Py_DecRef(args); end; end else - raise EPythonError.Create('Invalid DatetimeConversionMode'); + raise EPythonError.Create(SInvalidDateTimeConvMode); end; varOleStr: begin @@ -5809,7 +5983,7 @@ function TPythonEngine.VariantAsPyObject( const V : Variant ) : PPyObject; 2: Result := ArrayVarDim2; 3: Result := ArrayVarDim3; else - raise Exception.Create('Can''t convert a variant array of more than 3 dimensions to a Python sequence'); + raise Exception.Create(SCannotHandleMoreThan3Dim); end; end else if VarIsNull(DeRefV) or VarIsEmpty(DeRefV) then @@ -5835,7 +6009,7 @@ function TPythonEngine.PyObjectAsVariant( obj : PPyObject ) : Variant; if PyLong_Check(member) then Result := PyLong_AsLong(member) else - raise EPythonError.CreateFmt('Unexpected type found in member %s of a time_struct object', [AMember]); + raise EPythonError.CreateFmt(SUnexpectedTypeInTimeObject, [AMember]); Py_XDecRef(member); end; @@ -6025,7 +6199,7 @@ function TPythonEngine.VarRecAsPyObject( const v : TVarRec ) : PPyObject; Result := PyUnicodeFromString(''); end; else - Raise Exception.Create('Argument type not allowed'); + Raise Exception.Create(SArguementTypeNotAllowed); end; end; @@ -6038,7 +6212,7 @@ function TPythonEngine.MakePyTuple( const objects : array of PPyObject ) : PPyOb begin Result := PyTuple_New( High(objects)+1 ); if not Assigned(Result) then - raise EPythonError.Create('Could not create a new tuple object'); + raise EPythonError.Create(SCouldNotCreateTuple); for i := Low(objects) to High(objects) do begin Py_XINCREF( objects[i] ); @@ -6055,7 +6229,7 @@ function TPythonEngine.MakePyList( const objects : array of PPyObject ) : PPyObj begin Result := PyList_New( High(objects)+1 ); if not Assigned(Result) then - raise EPythonError.Create('Could not create a new list object'); + raise EPythonError.Create(SCouldNotCreateList); for i := Low(objects) to High(objects) do begin Py_XIncRef( objects[i] ); @@ -6069,7 +6243,7 @@ function TPythonEngine.ArrayToPyTuple( const items : array of const) : PPyObject begin Result := PyTuple_New( High(items)+1 ); if not Assigned(Result) then - raise EPythonError.Create('Could not create a new tuple object'); + raise EPythonError.Create(SCouldNotCreateTuple); for i := Low(items) to High(items) do PyTuple_SetItem( Result, i, VarRecAsPyObject( items[i] ) ); end; @@ -6080,7 +6254,7 @@ function TPythonEngine.ArrayToPyList( const items : array of const) : PPyObject; begin Result := PyList_New( High(items)+1 ); if not Assigned(Result) then - raise EPythonError.Create('Could not create a new list object'); + raise EPythonError.Create(SCouldNotCreateList); for i := Low(items) to High(items) do PyList_SetItem( Result, i, VarRecAsPyObject( items[i] ) ); end; @@ -6136,7 +6310,7 @@ function TPythonEngine.ArrayToPyDict( const items : array of const) : PPyObject; Result := ''; end; else - Raise Exception.Create('Argument type not allowed'); + Raise Exception.Create(SArguementTypeNotAllowed); end; end; @@ -6146,10 +6320,10 @@ function TPythonEngine.ArrayToPyDict( const items : array of const) : PPyObject; obj : PPyObject; begin if ((High(items)+1) mod 2) <> 0 then - raise Exception.Create('You must provide an even number of arguments'); + raise Exception.Create(SArgumemntsShouldBeEven); Result := PyDict_New; if not Assigned(Result) then - raise EPythonError.Create('Could not create a new dict object'); + raise EPythonError.Create(SCouldNotCreateDict); i := Low(items); try while i <= High(items) do @@ -6174,7 +6348,7 @@ function TPythonEngine.StringsToPyList( strings : TStrings ) : PPyObject; begin Result := PyList_New( strings.Count ); if not Assigned(Result) then - raise EPythonError.Create('Could not create a new list object'); + raise EPythonError.Create(SCouldNotCreateList); for i := 0 to strings.Count - 1 do PyList_SetItem( Result, i, PyUnicodeFromString(strings.Strings[i])); @@ -6186,7 +6360,7 @@ function TPythonEngine.StringsToPyTuple( strings : TStrings ) : PPyObject; begin Result := PyTuple_New( strings.Count ); if not Assigned(Result) then - raise EPythonError.Create('Could not create a new tuple object'); + raise EPythonError.Create(SCouldNotCreateTuple); for i := 0 to strings.Count - 1 do PyTuple_SetItem( Result, i, PyUnicodeFromString(strings.Strings[i])); @@ -6198,7 +6372,7 @@ procedure TPythonEngine.PyListToStrings(list: PPyObject; Strings: TStrings; i : Integer; begin if not PyList_Check(list) then - raise EPythonError.Create('the python object is not a list'); + raise EPythonError.Create(SExpectedList); if ClearStrings then Strings.Clear; for i := 0 to PyList_Size( list ) - 1 do @@ -6210,7 +6384,7 @@ procedure TPythonEngine.PyTupleToStrings( tuple: PPyObject; strings : TStrings ) i : Integer; begin if not PyTuple_Check(tuple) then - raise EPythonError.Create('the python object is not a tuple'); + raise EPythonError.Create(SExpectedTuple); strings.Clear; for i := 0 to PyTuple_Size( tuple ) - 1 do strings.Add( PyObjectAsString( PyTuple_GetItem( tuple, i ) ) ); @@ -6430,6 +6604,7 @@ procedure TPythonEngine.CheckError(ACatchStopEx : Boolean = False); var errtype, errvalue, errtraceback: PPyObject; SErrValue: string; + SystemExit: EPySystemExit; begin // PyErr_Fetch clears the error. The returned python objects are new references PyErr_Fetch(errtype, errvalue, errtraceback); @@ -6438,7 +6613,11 @@ procedure TPythonEngine.CheckError(ACatchStopEx : Boolean = False); Py_XDECREF(errtype); Py_XDECREF(errvalue); Py_XDECREF(errtraceback); - raise EPySystemExit.CreateResFmt(@SPyExcSystemError, [SErrValue]); + + SystemExit := EPySystemExit.CreateResFmt(@SPyExcSystemError, [SErrValue]); + SystemExit.EValue := SErrValue; + SystemExit.EName := 'SystemExit'; + raise SystemExit; end; var @@ -6612,7 +6791,7 @@ procedure TEngineClient.ClearEngine; procedure TEngineClient.CheckEngine; begin if not Assigned(FEngine) then - raise Exception.CreateFmt('No Engine defined for component "%s"', [Name]); + raise Exception.CreateFmt(SNoEngineForComponent, [Name]); end; @@ -6758,7 +6937,7 @@ procedure TMethodsContainer.ReallocMethods; function TMethodsContainer.GetMethods( idx : Integer ) : PPyMethodDef; begin if (idx < 0) or (idx > MethodCount) then - raise Exception.CreateFmt('%s: Index %d out of range', [ClassName, idx]); + raise Exception.CreateFmt(SIndexOutOfRange, [ClassName, idx]); Result := @( FMethods[idx] ); end; @@ -6891,7 +7070,7 @@ procedure TMembersContainer.AddMember(MemberName: PAnsiChar; MemberType : TPyMe mtStringInplace: _type := T_STRING_INPLACE; mtObjectEx: _type := T_OBJECT_EX; else - raise Exception.Create('Unknown member type'); + raise Exception.Create(SUnknownMemberType); end; offset := MemberOffset + GetMembersStartOffset; case MemberFlags of @@ -6901,9 +7080,9 @@ procedure TMembersContainer.AddMember(MemberName: PAnsiChar; MemberType : TPyMe mfWriteRestricted: flags := PY_WRITE_RESTRICTED; mfRestricted: flags := RESTRICTED; else - raise Exception.Create('Unknown member flag'); + raise Exception.Create(SUnknownMemberFlag); end; - doc := MemberDoc; + doc := MemberDoc; end; Inc( FMemberCount ); end; @@ -6954,7 +7133,7 @@ procedure TMembersContainer.FreeMembers; function TMembersContainer.GetMembers(idx: Integer): PPyMemberDef; begin if (idx < 0) or (idx > MemberCount) then - raise Exception.CreateFmt('%s: Index %d out of range', [ClassName, idx]); + raise Exception.CreateFmt(SIndexOutOfRange, [ClassName, idx]); Result := @( FMembers[idx] ); end; @@ -7031,7 +7210,7 @@ procedure TGetSetContainer.FreeGetSets; function TGetSetContainer.GetGetSet(idx: Integer): PPyGetSetDef; begin if (idx < 0) or (idx > GetSetCount) then - raise Exception.CreateFmt('%s: Index %d out of range', [ClassName, idx]); + raise Exception.CreateFmt(SIndexOutOfRange, [ClassName, idx]); Result := @( FGetSets[idx] ); end; @@ -7068,7 +7247,8 @@ procedure TParentClassError.AssignTo( Dest: TPersistent ); function TError.GetDisplayName: string; begin Result := string(Name); - if Result = '' then Result := inherited GetDisplayName; + if Result = '' then + Result := inherited GetDisplayName; end; procedure TError.SetName( const Value : AnsiString ); @@ -7086,8 +7266,8 @@ procedure TError.SetName( const Value : AnsiString ); for i := 0 to Count - 1 do with Items[i] do if Name = Value then - raise Exception.CreateFmt( 'In module "%s", there''s already an error named "%s"', - [m.ModuleName, Value]); + raise Exception.CreateFmt(SDuplicateErrorName, + [m.ModuleName, Value]); end; end; @@ -7197,13 +7377,13 @@ procedure TError.BuildError( const ModuleName : AnsiString ); else m := FindModule( ModuleName ); if not Assigned(m) then - raise Exception.CreateFmt('Could not find module containing the parent class of error "%s"', [Self.Name]); + raise Exception.CreateFmt(SNoModuleWithParentClass, [Self.Name]); d := PyModule_GetDict(m); Result := PyDict_GetItemString( d, PAnsiChar(ParentClass.Name) ); if not Assigned(Result) then - raise Exception.CreateFmt('Could not find the parent class "%s" of error "%s"', [ParentClass.Name, Self.Name]); + raise Exception.CreateFmt(SCannotFindParentClass, [ParentClass.Name, Self.Name]); if not PyClass_Check( Result ) and not PyType_CheckExact( Result ) then - raise Exception.CreateFmt('The object "%s" in module "%s" is not a class', [ParentClass.Name, ParentClass.Module] ); + raise Exception.CreateFmt(SObjectNotClass, [ParentClass.Name, ParentClass.Module] ); end; end; @@ -7214,7 +7394,7 @@ procedure TError.BuildError( const ModuleName : AnsiString ); Exit; if Name = '' then with GetOwner as TPythonModule do - raise Exception.CreateFmt( 'Error without name in module "%s"', [ModuleName] ); + raise Exception.CreateFmt(SErrorNotClass, [ModuleName] ); if Text = '' then Text := Name; Owner.Owner.CheckEngine; @@ -7234,17 +7414,17 @@ procedure TError.BuildError( const ModuleName : AnsiString ); end; end; if not Assigned(Error) then - raise Exception.CreateFmt( 'Could not create error "%s"', [Name] ); + raise Exception.CreateFmt(SCouldNotCreateError, [Name]); end; -procedure TError.RaiseError( const msg : AnsiString ); +procedure TError.RaiseError(const msg : AnsiString); begin Owner.Owner.CheckEngine; with Owner.Owner.Engine do - PyErr_SetString( Error, PAnsiChar(msg) ); + PyErr_SetString(Error, PAnsiChar(EncodeString(msg))); end; -procedure TError.RaiseErrorObj( const msg : AnsiString; obj : PPyObject ); +procedure TError.RaiseErrorObj(const msg : AnsiString; obj : PPyObject); var args, res, str : PPyObject; i : Integer; @@ -7258,24 +7438,20 @@ procedure TError.RaiseErrorObj( const msg : AnsiString; obj : PPyObject ); // instance. if PyDict_Check( obj ) then begin - args := PyTuple_New(0); - if not Assigned(args) then - raise Exception.Create('TError.RaiseErrorObj: Could not create an empty tuple'); - res := PyEval_CallObjectWithKeywords(Error, args, nil); - Py_DECREF(args); + res := PyObject_CallObject(Error, nil); if not Assigned(res) then - raise Exception.CreateFmt('TError.RaiseErrorObj: Could not create an instance of "%s"', [Self.Name]); + raise Exception.CreateFmt(STErrorCouldNotCreateInstance, [Self.Name]); if PyObject_TypeCheck(res, PPyTypeObject(PyExc_Exception^)) then begin args := PyTuple_New(1); if not Assigned(args) then - raise Exception.Create('TError.RaiseErrorObj: Could not create an empty tuple'); + raise Exception.Create(STErrorCouldNotCreateTuple); str := PyUnicodeFromString(msg); PyTuple_SetItem(args, 0, str); - res := PyEval_CallObjectWithKeywords(Error, args, nil); + res := PyObject_Call(Error, args, nil); Py_DECREF(args); if not Assigned(res) then - raise Exception.CreateFmt('TError.RaiseErrorObj: Could not create an instance of "%s"', [Self.Name]); + raise Exception.CreateFmt(STErrorCouldNotCreateInstance, [Self.Name]); keys := PyDict_Keys(obj); for i := 0 to PySequence_Length(keys)-1 do begin @@ -7291,11 +7467,12 @@ procedure TError.RaiseErrorObj( const msg : AnsiString; obj : PPyObject ); Py_XDECREF(keys); end else - raise Exception.Create('TError.RaiseErrorObj: I didn''t get an instance' ); - PyErr_SetObject( Error, res ); + raise Exception.Create(STErrorNoInstance); + PyErr_SetObject(Error, res); + Py_XDECREF(res); end else - PyErr_SetObject( Error, obj ); + PyErr_SetObject(Error, obj); end; function TError.Owner : TErrors; @@ -7490,7 +7667,7 @@ function TPythonModule.ErrorByName( const AName : AnsiString ) : TError; Result := Errors.Items[i]; Exit; end; - raise Exception.CreateFmt( 'Could not find error "%s"', [AName] ); + raise Exception.CreateFmt(SCouldNotFindError, [AName] ); end; procedure TPythonModule.RaiseError( const error, msg : AnsiString ); @@ -7542,10 +7719,10 @@ procedure TPythonModule.SetVar( const varName : AnsiString; value : PPyObject ); if Assigned(FEngine) and Assigned( FModule ) then begin if Engine.PyObject_SetAttrString(Module, PAnsiChar(varName), value ) <> 0 then - raise EPythonError.CreateFmt( 'Could not set var "%s" in module "%s"', [varName, ModuleName] ); + raise EPythonError.CreateFmt(SCouldNotSetVar, [varName, ModuleName]); end else - raise EPythonError.CreateFmt( 'Can''t set var "%s" in module "%s", because it is not yet initialized', [varName, ModuleName] ); + raise EPythonError.CreateFmt(SCannotSetVarNoInit, [varName, ModuleName]); end; // warning, this function will increase the refcount of value, @@ -7559,7 +7736,7 @@ function TPythonModule.GetVar( const varName : AnsiString ) : PPyObject; Engine.PyErr_Clear; end else - raise EPythonError.CreateFmt( 'Can''t get var "%s" in module "%s", because it is not yet initialized', [varName, ModuleName] ); + raise EPythonError.CreateFmt(SCannotSetVarNoInit, [varName, ModuleName]); end; procedure TPythonModule.DeleteVar( const varName : AnsiString ); @@ -7570,11 +7747,12 @@ procedure TPythonModule.DeleteVar( const varName : AnsiString ); with Engine do begin dict := PyModule_GetDict( Module ); - if not Assigned(dict) then raise EPythonError.CreateFmt( 'Can''t get __dict__ of module "%s"', [ModuleName] ); + if not Assigned(dict) then + raise EPythonError.CreateFmt(SCannotGetDict, [ModuleName] ); PyDict_DelItemString( dict, PAnsiChar(varName) ); end else - raise EPythonError.CreateFmt( 'Can''t delete var "%s" in module "%s", because it is not yet initialized', [varName, ModuleName] ); + raise EPythonError.CreateFmt(SCannotDelVarNoInit, [varName, ModuleName]); end; procedure TPythonModule.ClearVars; @@ -7706,7 +7884,7 @@ function TPyObject.GetModule : TPythonModule; Result := nil; end; -function TPyObject.Get_ob_refcnt: NativeInt; +function TPyObject.Get_ob_refcnt: NativeUInt; begin Result := GetSelf^.ob_refcnt; end; @@ -7716,7 +7894,7 @@ function TPyObject.Get_ob_type: PPyTypeObject; Result := GetSelf^.ob_type; end; -procedure TPyObject.Set_ob_refcnt(const Value: NativeInt); +procedure TPyObject.Set_ob_refcnt(const Value: NativeUInt); begin GetSelf^.ob_refcnt := Value; end; @@ -7755,8 +7933,8 @@ function TPyObject.SetAttr(key : PAnsiChar; value : PPyObject) : Integer; with GetPythonEngine do begin Result := -1; - PyErr_SetString (PyExc_AttributeError^, - PAnsiChar(AnsiString(Format('Unknown attribute "%s"',[key])))); + PyErr_SetString(PyExc_AttributeError^, + PAnsiChar(EncodeString(Format('Unknown attribute "%s"',[key])))); end; end; @@ -7793,7 +7971,7 @@ function TPyObject.GetBuffer(view: PPy_buffer; flags: Integer): Integer; begin view^.obj := nil; with GetPythonEngine do - PyErr_SetObject(PyExc_BufferError^, PyUnicodeFromString('')); + PyErr_SetString(PyExc_BufferError^, ''); Result := -1; end; @@ -8142,7 +8320,7 @@ function PythonToDelphi( obj : PPyObject ) : TPyObject; if IsDelphiObject( obj ) then Result := TPyObject(PAnsiChar(obj)+Sizeof(PyObject)) else - raise EPythonError.CreateFmt( 'Python object "%s" is not a Delphi class', [GetPythonEngine.PyObjectAsString(obj)] ); + raise EPythonError.CreateFmt(SExpectedDelphiClass, [GetPythonEngine.PyObjectAsString(obj)]); end; procedure PyObjectDestructor( pSelf : PPyObject); cdecl; @@ -8426,7 +8604,6 @@ function TPythonType.NewSubtypeInst( aType: PPyTypeObject; args, kwds : PPyObje begin Engine.Py_DECREF(Result); Result := nil; - obj.Free; end; end; end; @@ -8994,7 +9171,7 @@ procedure TPythonDelphiVar.CreateVar; // Add a reference to this var in the module m := PyImport_AddModule(PAnsiChar(Module)); if m = nil then - raise EPythonError.CreateFmt('CreateVar: can''t create module "%s"', [Module]); + raise EPythonError.CreateFmt(SCannotCreateModule, [Module]); d := PyModule_GetDict(m); if @PyDict_SetItemString = nil then raise Exception.Create('nil'); @@ -9008,7 +9185,7 @@ function TPythonDelphiVar.GetValue : Variant; with TPyVar(PythonToDelphi(FVarObject)) do Result := GetValueAsVariant else - raise Exception.Create('No variable was created' ); + raise Exception.Create(SVarNotCreated); end; procedure TPythonDelphiVar.SetValue( const val : Variant ); @@ -9017,7 +9194,7 @@ procedure TPythonDelphiVar.SetValue( const val : Variant ); with TPyVar(PythonToDelphi(FVarObject)) do SetValueFromVariant(val) else - raise Exception.Create('No variable was created' ); + raise Exception.Create(SVarNotCreated); end; // Warning: GetValueAsPyObject returns a preincremented object ! @@ -9027,7 +9204,7 @@ function TPythonDelphiVar.GetValueAsPyObject : PPyObject; with TPyVar(PythonToDelphi(FVarObject)) do Result := GetValue else - raise Exception.Create('No variable was created' ); + raise Exception.Create(SVarNotCreated); end; procedure TPythonDelphiVar.SetValueFromPyObject( val : PPyObject ); @@ -9036,7 +9213,7 @@ procedure TPythonDelphiVar.SetValueFromPyObject( val : PPyObject ); with TPyVar(PythonToDelphi(FVarObject)) do SetValue(val) else - raise Exception.Create('No variable was created' ); + raise Exception.Create(SVarNotCreated); end; function TPythonDelphiVar.IsVariantOk( const v : Variant ) : Boolean; @@ -9089,7 +9266,7 @@ procedure TPythonDelphiVar.SetVarName( const val : AnsiString ); if Owner.Components[i] is TPythonDelphiVar then with TPythonDelphiVar(Owner.Components[i]) do if (VarName = val) and (Module = Self.Module) then - raise Exception.CreateFmt('A variable "%s" already exists in the module "%s"',[val, Module]); + raise Exception.CreateFmt(SVarExists, [val, Module]); end; begin @@ -9358,7 +9535,7 @@ procedure TPythonThread.Execute; finally PyGILState_Release(gilstate); end; - end else {fThreadExecMode} + end else begin gilstate := PyGILState_Ensure(); global_state := PyThreadState_Get; @@ -9381,8 +9558,8 @@ procedure TPythonThread.Execute; PyThreadState_Swap(global_state); PyGILState_Release(gilstate); end else - raise EPythonError.Create( 'Could not create a new thread state'); - end; {withinterp} + raise EPythonError.Create(SCannotCreateThreadState); + end; end; end; @@ -9589,9 +9766,9 @@ function pyio_GetTypesStats(self, args : PPyObject) : PPyObject; function GetPythonEngine : TPythonEngine; begin if not Assigned( gPythonEngine ) then - raise Exception.Create( 'No Python engine was created' ); + raise Exception.Create(SCannotCreatePythonEngine); if not gPythonEngine.Finalizing and not gPythonEngine.Initialized then - raise Exception.Create( 'The Python engine is not properly initialized' ); + raise Exception.Create(SCannotInitPythonEngine); Result := gPythonEngine; end; @@ -9829,6 +10006,15 @@ function PyStatus_Exception(const APyStatus: PyStatus): Boolean; Result := APyStatus._type <> _PyStatus_TYPE_OK; end; +function StringToWCharTString(Str: string): WcharTString; +begin + {$IFDEF POSIX} + Result := UnicodeStringToUCS4String(UnicodeString(Str)); + {$ELSE} + Result := WcharTString(Str); + {$ENDIF} +end; + { TPyEngineAndGIL - Internal class for SafePythonEngine } type @@ -9935,7 +10121,7 @@ procedure ThreadPythonExec(ExecuteProc : TProc; TerminateProc : TProc; Thread: TAnonymousPythonThread; begin if GetCurrentThreadId <> MainThreadID then - raise Exception.Create('ThreadPythonExec should only be called from the main thread'); + raise Exception.Create(SThreadPythonExec); Thread := TAnonymousPythonThread.Create(ExecuteProc, TerminateProc, WaitToFinish, ThreadExecMode); if WaitToFinish then begin diff --git a/Source/PythonVersions.pas b/Source/PythonVersions.pas index 569ba52f..ea79ed84 100644 --- a/Source/PythonVersions.pas +++ b/Source/PythonVersions.pas @@ -33,7 +33,7 @@ TPythonVersion = record function GetDisplayName: string; function GetApiVersion: integer; function GetSysArchitecture: string; - function GetPythonExecutable: string; + function GetPythonExecutable(Index: Integer): string; public IsRegistered: Boolean; IsAllUsers: Boolean; @@ -46,7 +46,8 @@ TPythonVersion = record function Is_virtualenv: Boolean; function Is_conda: Boolean; procedure AssignTo(PythonEngine: TPersistent); - property PythonExecutable: string read GetPythonExecutable; + property PythonExecutable: string index 0 read GetPythonExecutable; + property PythonFreeThreadedExecutable: string index 1 read GetPythonExecutable; property DLLName: string read GetDLLName; property SysArchitecture: string read GetSysArchitecture; property IsPython3K: Boolean read GetIsPython3K; @@ -127,7 +128,7 @@ procedure TPythonVersion.AssignTo(PythonEngine: TPersistent); TPythonEngine(PythonEngine).DllPath := DLLPath; TPythonEngine(PythonEngine).APIVersion := ApiVersion; if Is_venv then begin - TPythonEngine(PythonEngine).VenvPythonExe := PythonExecutable; + TPythonEngine(PythonEngine).PythonExecutable := PythonExecutable; TPythonEngine(PythonEngine).SetPythonHome(DLLPath); end else { @@ -204,11 +205,18 @@ function TPythonVersion.GetIsPython3K: Boolean; end; end; -function TPythonVersion.GetPythonExecutable: string; +function TPythonVersion.GetPythonExecutable(Index: Integer): string; +var + ExeName: string; begin - Result := IncludeTrailingPathDelimiter(InstallPath) + 'python.exe'; + if Index = 0 then + ExeName := 'python.exe' + else + ExeName := Format('python%st.exe', [SysVersion]); + + Result := IncludeTrailingPathDelimiter(InstallPath) + ExeName; if not FileExists(Result) then begin - Result := IncludeTrailingPathDelimiter(InstallPath) + 'Scripts' + PathDelim + 'python.exe'; + Result := IncludeTrailingPathDelimiter(InstallPath) + 'Scripts' + PathDelim + ExeName; if not FileExists(Result) then Result := ''; end; end; diff --git a/Source/VarPyth.pas b/Source/VarPyth.pas index fd69085f..52607cf0 100644 --- a/Source/VarPyth.pas +++ b/Source/VarPyth.pas @@ -1604,7 +1604,7 @@ function TPythonVariantType.EvalPython(const V: TVarData; PyDict_SetItemString(_KW, LNamedParams[i].Name, ArgAsPythonObject(LNamedParams[i].Index)); // call the func or method, with or without named parameters (KW) - Result := PyEval_CallObjectWithKeywords(_obj, _Args, _KW); + Result := PyObject_Call(_obj, _Args, _KW); CheckError(True); finally Py_XDecRef(_Args); @@ -2154,7 +2154,7 @@ procedure VarPyToStrings(const AValue : Variant; const AStrings: TStrings); V: Variant; begin for V in VarPyIterate(AValue) do - AStrings.Add(V) + AStrings.Add(VarPythonAsString(V)) end; initialization diff --git a/Source/WrapDelphi.pas b/Source/WrapDelphi.pas index 6ec11c1f..a19bc718 100644 --- a/Source/WrapDelphi.pas +++ b/Source/WrapDelphi.pas @@ -553,16 +553,16 @@ TPyDelphiObject = class (TPyInterfacedObject, IFreeNotificationSubscriber) class function ExcludedExposedMembers(APythonType: TPythonType): TArray<string>; virtual; class procedure ExposeMethods(AClass: TClass; NearestAncestorClass: TClass; APythonType: TPythonType; APyDelphiWrapper: TPyDelphiWrapper; - AExcludedMethodNames: TArray<string> = []); + AExcludedMethodNames: TArray<string> = nil); class procedure ExposeFields(AClass: TClass; NearestAncestorClass: TClass; APythonType: TPythonType; APyDelphiWrapper: TPyDelphiWrapper; - AExcludedFieldNames: TArray<string> = []); + AExcludedFieldNames: TArray<string> = nil); class procedure ExposeProperties(AClass: TClass; NearestAncestorClass: TClass; APythonType: TPythonType; APyDelphiWrapper: TPyDelphiWrapper; - AExcludedPropertyNames: TArray<string> = []); + AExcludedPropertyNames: TArray<string> = nil); class procedure ExposeIndexedProperties(AClass: TClass; NearestAncestorClass: TClass; APythonType: TPythonType; APyDelphiWrapper: TPyDelphiWrapper; - AExcludedPropertyNames: TArray<string> = []); + AExcludedPropertyNames: TArray<string> = nil); {$ENDIF EXTENDED_RTTI} public PyDelphiWrapper : TPyDelphiWrapper; @@ -616,25 +616,26 @@ TPyDelphiObjectClass = class of TPyDelphiObject; Generic wrapper for pascal classes Can be used from unit wrappers as follows: - APyDelphiWrapper.RegisterDelphiWrapper(TPyClassWrapper<TMyClass>); + PyDelphiWrapper1.RegisterDelphiWrapper(TPyClassWrapper<TMyClass>); or at runtime (e.g. inside the FormCreate handler: PyDelphiWrapper1.RegisterDelphiWrapper(TPyClassWrapper<TMyClass>).Initialize; if you want your class to capable of being instantiated from python then do: - TTestWrapper = class(TPyClassWrapper<TTest>) + TMyClassWrapper = class(TPyClassWrapper<TMyClass>) constructor CreateWith(APythonType: TPythonType; args, kwds: PPyObject); overload; override; end; - constuctor TTestWrapper.CreateWith(APythonType: TPythonType; args, kwds: PPyObject); + constuctor TMyClassWrapper.CreateWith(APythonType: TPythonType; args, kwds: PPyObject); begin Create(APythonType); - DelphiObject := TTest.Create; + DelphiObject := TMyClass.Create; end; - PyDelphiWrapper1.RegisterDelphiWrapper(TTestWrapper).Initialize; + PyDelphiWrapper1.RegisterDelphiWrapper(TMyClassWrapper).Initialize; } TPyClassWrapper<T: class> = class(TPyDelphiObject) + private function GetDelphiObject: T; procedure SetDelphiObject(const Value: T); public @@ -991,6 +992,8 @@ TPyDelphiWrapper = class(TEngineClient, IFreeNotificationSubscriber) {$IFDEF EXTENDED_RTTI} function CreateVarParam(PyDelphiWrapper : TPyDelphiWrapper; const AValue: TValue) : PPyObject; overload; + function SimpleValueToPython(const Value: TValue; + out ErrMsg: string): PPyObject; function TValueToPyObject(const Value: TValue; DelphiWrapper: TPyDelphiWrapper; out ErrMsg: string): PPyObject; function PyObjectToTValue(PyArg : PPyObject; ArgType: TRttiType; @@ -1021,12 +1024,13 @@ implementation rs_ErrCheckBound = 'Delphi wrapper %s is not bound'; rs_ErrSequence = 'Wrapper %s does not support sequences'; rs_ErrInvalidArgs = '"%s" called with invalid arguments.'#$A'Error: %s'; - rs_ErrInvalidRet = 'Call "%s" returned a value that could not be coverted to Python'#$A'Error: %s'; - rs_IncompatibleArguments = 'Expected and actual arguements are incompatible'; + rs_ErrInvalidRet = 'Call "%s" returned a value that could not be converted to Python'#$A'Error: %s'; + rs_IncompatibleArguments = 'Expected and actual arguments are incompatible'; rs_ErrAttrGet = 'Error in getting property "%s".'#$A'Error: %s'; rs_UnknownAttribute = 'Unknown attribute'; rs_ErrIterSupport = 'Wrapper %s does not support iterators'; - rs_ErrAttrSetr = 'Error in setting property %s'#$A'Error: %s'; + rs_ErrAttrSet = 'Error in setting property %s'#$A'Error: %s'; + rs_ErrObjectDestroyed = 'Trying to access a destroyed pascal object'; rs_IncompatibleClasses = 'Incompatible classes'; rs_IncompatibleRecords = 'Incompatible record types'; rs_IncompatibleInterfaces = 'Incompatible interfaces'; @@ -1038,6 +1042,7 @@ implementation rs_ExpectedNil = 'In static methods Self should be nil'; rs_ExpectedInterface = 'Expected a Pascal interface'; rs_ExpectedSequence = 'Expected a python sequence'; + rsExpectedPointer = 'Expected a Pointer'; rs_InvalidClass = 'Invalid class'; rs_ErrEventNotReg = 'No Registered EventHandler for events of type "%s'; rs_ErrEventNoSuport = 'Class %s does not support events because it must '+ @@ -1523,8 +1528,8 @@ function TExposedGetSet.GetterWrapper(AObj: PPyObject; AContext : Pointer): PPyO if not Assigned(Result) then with GetPythonEngine do - PyErr_SetObject (PyExc_AttributeError^, - PyUnicodeFromString(Format(rs_ErrAttrGet, [FRttiMember.Name, LOutMsg]))); + PyErr_SetString(PyExc_AttributeError^, + PAnsiChar(EncodeString(Format(rs_ErrAttrGet, [FRttiMember.Name, LOutMsg])))); end; function TExposedGetSet.SetterWrapper(AObj, AValue: PPyObject; AContext: Pointer): Integer; cdecl; @@ -1548,8 +1553,8 @@ function TExposedGetSet.SetterWrapper(AObj, AValue: PPyObject; AContext: Pointer if Result <> 0 then with GetPythonEngine do - PyErr_SetObject (PyExc_AttributeError^, - PyUnicodeFromString(Format(rs_ErrAttrSetr, [FRttiMember.Name, ErrMsg]))); + PyErr_SetString (PyExc_AttributeError^, + PAnsiChar(EncodeString(Format(rs_ErrAttrSet, [FRttiMember.Name, ErrMsg])))); end; { TExposedField } @@ -1644,8 +1649,8 @@ function TExposedEvent.SetterWrapper(AObj, AValue: PPyObject; AContext: Pointer) if Result <> 0 then with GetPythonEngine do - PyErr_SetObject (PyExc_AttributeError^, - PyUnicodeFromString(Format(rs_ErrAttrSetr, [FRttiMember.Name, ErrMsg]))); + PyErr_SetString (PyExc_AttributeError^, + PAnsiChar(EncodeString(Format(rs_ErrAttrSet, [FRttiMember.Name, ErrMsg])))); end; { TExposedIndexedProperty } @@ -1741,7 +1746,7 @@ function TPyIndexedProperty.MpAssSubscript(obj1, obj2: PPyObject) : Integer; if not FProperty.IsWritable then begin with Engine do - PyErr_SetObject(PyExc_TypeError^, PyUnicodeFromString(rs_NotWritable)); + PyErr_SetString(PyExc_TypeError^, PAnsiChar(EncodeString(rs_NotWritable))); Exit; end; @@ -1865,8 +1870,8 @@ class procedure TRttiEventHandler.ImplCallback(UserData: Pointer; if Assigned(PyResult) and (EventHandler.MethodType.ReturnType <> nil) and not PyObjectToTValue(PyResult, EventHandler.MethodType.ReturnType, Result, ErrMsg) then - Engine.PyErr_SetObject(Engine.PyExc_TypeError^, Engine.PyUnicodeFromString( - Format(rs_ErrInvalidRet, [string(EventHandler.PropertyInfo.Name), ErrMsg]))); + Engine.PyErr_SetString(Engine.PyExc_TypeError^, PAnsiChar(Engine.EncodeString( + Format(rs_ErrInvalidRet, [string(EventHandler.PropertyInfo.Name), ErrMsg])))); Engine.Py_XDECREF(PyResult); finally Engine.Py_XDECREF(PyArgs); @@ -1900,9 +1905,8 @@ function GlobalDelphiWrapper: TPyDelphiWrapper; procedure InvalidArguments(const MethName, ErrMsg : string); begin with GetPythonEngine do - PyErr_SetObject(PyExc_TypeError^, PyUnicodeFromString( - Format(rs_ErrInvalidArgs, - [MethName, ErrMsg]))); + PyErr_SetString(PyExc_TypeError^, PAnsiChar(EncodeString( + Format(rs_ErrInvalidArgs, [MethName, ErrMsg])))); end; function ValidateClassRef(PyValue: PPyObject; RefClass: TClass; @@ -2032,8 +2036,16 @@ function SimplePythonToValue(PyValue: PPyObject; TypeInfo: PTypeInfo; end else ErrMsg := rs_ErrPythonToValue; - tkString, tkWString, tkUString, - tkLString, tkChar, tkWChar: + tkString, tkLString, tkChar: + begin + if GetPythonEngine.PyBytes_Check(PyValue) then + V := TValue.From(GetPythonEngine.PyBytesAsAnsiString(PyValue)) + else + V := GetPythonEngine.PyObjectAsString(PyValue); + Value := V.Cast(TypeInfo); + Result := True; + end; + tkWString, tkUString, tkWChar: begin V := GetPythonEngine.PyObjectAsString(PyValue); Value := V.Cast(TypeInfo); @@ -2176,6 +2188,40 @@ function ValidateDynArray(PyValue: PPyObject; const RttiType: TRttiType; end; end; +function ValidatePointer(PyValue: PPyObject; const RttiType: TRttiType; + out ParamValue: TValue; out ErrMsg: string): Boolean; +var + RefType: TRttiType; + PyEngine: TPythonEngine; + P: Pointer; +begin + Result := False; + PyEngine := GetPythonEngine; + + if (RTTIType is TRttiPointerType) then + begin + RefType := TRttiPointerType(RTTIType).ReferredType; + if Assigned(RefType) and (RefType.Name = 'PyObject') then + begin + Result := True; + ParamValue := TValue.From<PPyObject>(PyValue); + end + else if PyEngine.PyLong_Check(PyValue) then + begin + P := PyEngine.PyLong_AsVoidPtr(PyValue); + if PyEngine.PyErr_Occurred = nil then + begin + Result := True; + ParamValue := TValue.From<Pointer>(P); + end + else + PyEngine.PyErr_Clear; + end; + end; + if not Result then + ErrMsg := rsExpectedPointer; +end; + function PyObjectToTValue(PyArg: PPyObject; ArgType: TRttiType; out Arg: TValue; out ErrMsg: string): Boolean; var @@ -2205,7 +2251,9 @@ function PyObjectToTValue(PyArg: PPyObject; ArgType: TRttiType; tkRecord{$IFDEF MANAGED_RECORD}, tkMRecord{$ENDIF}: Result := ValidateRecordProperty(PyArg, ArgType.Handle, Arg, ErrMsg); tkDynArray: - Result := ValidateDynArray(PyArg, ArgType, Arg, ErrMsg) + Result := ValidateDynArray(PyArg, ArgType, Arg, ErrMsg); + tkPointer: + Result := ValidatePointer(PyArg, ArgType, Arg, ErrMsg); else Result := SimplePythonToValue(PyArg, ArgType.Handle, Arg, ErrMsg); end; @@ -2244,7 +2292,7 @@ function TValueToPyObject(const Value: TValue; DelphiWrapper: TPyDelphiWrapper; out ErrMsg: string): PPyObject; begin if Value.IsEmpty then - Result := GetPythonEngine.ReturnNone + Result := DelphiWrapper.Engine.ReturnNone else case Value.Kind of tkClass: Result := DelphiWrapper.Wrap(Value.AsObject); @@ -2254,6 +2302,11 @@ function TValueToPyObject(const Value: TValue; Result := DelphiWrapper.WrapRecord(Value); tkArray, tkDynArray: Result := DynArrayToPython(Value, DelphiWrapper, ErrMsg); + tkPointer: + if Value.TypeInfo = TypeInfo(PPyObject) then + Result := Value.AsType<PPyObject> + else + Result := DelphiWrapper.Engine.PyLong_FromVoidPtr(Value.AsType<Pointer>); else Result := SimpleValueToPython(Value, ErrMsg); end; @@ -2313,8 +2366,8 @@ function CheckIndex(AIndex, ACount : Integer; const AIndexName : string = 'Index with GetPythonEngine do begin Result := False; - PyErr_SetObject (PyExc_IndexError^, PyUnicodeFromString( - Format(rs_ErrCheckIndex,[AIndexName, AIndex]))); + PyErr_SetString(PyExc_IndexError^, PAnsiChar(EncodeString( + Format(rs_ErrCheckIndex,[AIndexName, AIndex])))); end else Result := True; @@ -2331,8 +2384,8 @@ function CheckIntAttribute(AAttribute : PPyObject; const AAttributeName : string begin Result := False; with GetPythonEngine do - PyErr_SetObject (PyExc_AttributeError^, - PyUnicodeFromString(Format(rs_ErrCheckInt, [AAttributeName]))); + PyErr_SetString(PyExc_AttributeError^, + PAnsiChar(EncodeString(Format(rs_ErrCheckInt, [AAttributeName])))); end; end; @@ -2347,8 +2400,8 @@ function CheckFloatAttribute(AAttribute : PPyObject; const AAttributeName : stri begin Result := False; with GetPythonEngine do - PyErr_SetObject (PyExc_AttributeError^, - PyUnicodeFromString(Format(rs_ErrCheckFloat, [AAttributeName]))); + PyErr_SetString(PyExc_AttributeError^, + PAnsiChar(EncodeString(Format(rs_ErrCheckFloat, [AAttributeName])))); end; end; @@ -2369,8 +2422,8 @@ function CheckStrAttribute(AAttribute : PPyObject; const AAttributeName : string begin Result := False; with GetPythonEngine do - PyErr_SetObject (PyExc_AttributeError^, - PyUnicodeFromString(Format(rs_ErrCheckStr, [AAttributeName]))); + PyErr_SetString(PyExc_AttributeError^, + PAnsiChar(EncodeString(Format(rs_ErrCheckStr, [AAttributeName])))); end; end; @@ -2382,8 +2435,8 @@ function CheckCallableAttribute(AAttribute : PPyObject; const AAttributeName : s begin Result := False; with GetPythonEngine do - PyErr_SetObject (PyExc_AttributeError^, - PyUnicodeFromString(Format(rs_ErrCheckCallable, [AAttributeName]))); + PyErr_SetString(PyExc_AttributeError^, + PAnsiChar(EncodeString(Format(rs_ErrCheckCallable, [AAttributeName])))); end; end; @@ -2395,9 +2448,9 @@ function CheckEnum(const AEnumName : string; AValue, AMinValue, AMaxValue : Int begin Result := False; with GetPythonEngine do - PyErr_SetObject (PyExc_AttributeError^, - PyUnicodeFromString(Format(rs_ErrCheckEnum, - [AEnumName, AMinValue, AMaxValue, AValue]))); + PyErr_SetString(PyExc_AttributeError^, + PAnsiChar(EncodeString(Format(rs_ErrCheckEnum, + [AEnumName, AMinValue, AMaxValue, AValue])))); end; end; @@ -2420,8 +2473,8 @@ function CheckObjAttribute(AAttribute : PPyObject; const AAttributeName : string begin Result := False; with GetPythonEngine do - PyErr_SetObject (PyExc_AttributeError^, - PyUnicodeFromString(Format(rs_ErrCheckObjOfType, [AAttributeName, AExpectedClass.ClassName]))); + PyErr_SetString(PyExc_AttributeError^, + PAnsiChar(EncodeString(Format(rs_ErrCheckObjOfType, [AAttributeName, AExpectedClass.ClassName])))); end else begin @@ -2433,8 +2486,8 @@ function CheckObjAttribute(AAttribute : PPyObject; const AAttributeName : string begin Result := False; with GetPythonEngine do - PyErr_SetObject (PyExc_AttributeError^, - PyUnicodeFromString(Format(rs_ErrCheckObj, [AAttributeName]))); + PyErr_SetString(PyExc_AttributeError^, + PAnsiChar(EncodeString(Format(rs_ErrCheckObj, [AAttributeName])))); end; end; @@ -2774,8 +2827,8 @@ function TPyDelphiContainer.SqAssItem(idx: NativeInt; begin Result := -1; with GetPythonEngine do - PyErr_SetObject( PyExc_SystemError^, - PyUnicodeFromString(Format(rs_ErrSqAss, [fContainerAccess.Name])) ); + PyErr_SetString( PyExc_SystemError^, + PAnsiChar(EncodeString(Format(rs_ErrSqAss, [fContainerAccess.Name])))); end; end; @@ -2792,8 +2845,8 @@ function TPyDelphiContainer.SqContains(obj: PPyObject): integer; begin Result := -1; with GetPythonEngine do - PyErr_SetObject( PyExc_SystemError^, - PyUnicodeFromString(Format(rs_ErrSqContains, [fContainerAccess.Name])) ); + PyErr_SetString(PyExc_SystemError^, + PAnsiChar(EncodeString(Format(rs_ErrSqContains, [fContainerAccess.Name])))); end; end; @@ -2887,8 +2940,8 @@ function TPyDelphiObject.CheckBound: Boolean; Result := Assigned(DelphiObject); if not Result then with GetPythonEngine do - PyErr_SetObject(PyExc_AttributeError^, - PyUnicodeFromString(Format(rs_ErrCheckBound, [ClassName]))); + PyErr_SetString(PyExc_AttributeError^, + PAnsiChar(EncodeString(Format(rs_ErrCheckBound, [ClassName])))); end; function TPyDelphiObject.Compare(obj: PPyObject): Integer; @@ -2918,8 +2971,8 @@ constructor TPyDelphiObject.Create(APythonType: TPythonType); constructor TPyDelphiObject.CreateWith(APythonType: TPythonType; args, kwds: PPyObject); begin with APythonType.Engine do - PyErr_SetObject(PyExc_TypeError^, PyUnicodeFromString( - Format(rs_CannotCreate, [APythonType.TypeName]))); + PyErr_SetString(PyExc_TypeError^, PAnsiChar(EncodeString( + Format(rs_CannotCreate, [APythonType.TypeName])))); end; function TPyDelphiObject.CreateContainerAccess: TContainerAccess; @@ -3148,8 +3201,8 @@ function RttiCall(ParentAddress: pointer; DelphiWrapper: TPyDelphiWrapper; if Result = nil then with DelphiWrapper.Engine do - PyErr_SetObject(PyExc_TypeError^, PyUnicodeFromString( - Format(rs_ErrInvalidRet, [Method.Name, ErrMsg]))); + PyErr_SetString(PyExc_TypeError^, PAnsiChar(EncodeString( + Format(rs_ErrInvalidRet, [Method.Name, ErrMsg])))); except on E: Exception do begin Result := nil; @@ -3364,8 +3417,8 @@ function TPyRttiObject.GetAttrO(key: PPyObject): PPyObject; Result := GetRttiAttr(fAddr, RttiType, KeyName, PyDelphiWrapper, ErrMsg); if not Assigned(Result) then with GetPythonEngine do - PyErr_SetObject (PyExc_AttributeError^, - PyUnicodeFromString(Format(rs_ErrAttrGet,[KeyName, ErrMsg]))); + PyErr_SetString(PyExc_AttributeError^, + PAnsiChar(EncodeString(Format(rs_ErrAttrGet,[KeyName, ErrMsg])))); end; class procedure TPyRttiObject.RegisterMethods(PythonType: TPythonType); @@ -3395,8 +3448,8 @@ function TPyRttiObject.SetAttrO(key, value: PPyObject): Integer; if Result <> 0 then with GetPythonEngine do - PyErr_SetObject(PyExc_AttributeError^, PyUnicodeFromString( - Format(rs_ErrAttrSetr, [KeyName, ErrMsg]))); + PyErr_SetString(PyExc_AttributeError^, PAnsiChar(EncodeString( + Format(rs_ErrAttrSet, [KeyName, ErrMsg])))); end; function TPyRttiObject.SetProps(args, keywords: PPyObject): PPyObject; @@ -3505,6 +3558,7 @@ function TPyDelphiObject.GetAttrO(key: PPyObject): PPyObject; var KeyName: string; ErrMsg : string; + PyEngine: TPythonEngine; {$IFNDEF EXTENDED_RTTI} {$IFNDEF FPC} Info: PMethodInfoHeader; @@ -3516,16 +3570,24 @@ function TPyDelphiObject.GetAttrO(key: PPyObject): PPyObject; RttiType: TRttiStructuredType; {$ENDIF} begin - Result := inherited GetAttrO(key); - if GetPythonEngine.PyErr_Occurred = nil then Exit; // We found what we wanted + Result := nil; + PyEngine := GetPythonEngine; - // should not happen - if not (Assigned(DelphiObject) and - CheckStrAttribute(Key, 'GetAttrO key parameter', KeyName)) - then + // If DelphiObject is nil exit immediately with an error + if not Assigned(DelphiObject) then + begin + PyEngine.PyErr_SetString(PyEngine.PyExc_AttributeError^, + PAnsiChar(PyEngine.EncodeString(rs_ErrObjectDestroyed))); Exit; + end; + + if not CheckStrAttribute(Key, 'GetAttrO key parameter', KeyName) then + Exit; // should not happen + + Result := inherited GetAttrO(key); + if PyEngine.PyErr_Occurred = nil then Exit; // We found what we wanted - GetPythonEngine.PyErr_Clear; + PyEngine.PyErr_Clear; {$IFDEF EXTENDED_RTTI} // Use RTTI if Assigned(DelphiObject) then begin @@ -3582,17 +3644,17 @@ function TPyDelphiObject.GetAttrO(key: PPyObject): PPyObject; {$ELSE FPC} if GetTypeData(PropInfo^.PropType^)^.BaseType^ = TypeInfo(Boolean) then {$ENDIF FPC} - Result := GetPythonEngine.VariantAsPyObject(Boolean(GetOrdProp(Self.DelphiObject, PropInfo))) + Result := PyEngine.VariantAsPyObject(Boolean(GetOrdProp(Self.DelphiObject, PropInfo))) else {$IFDEF FPC} - Result := GetPythonEngine.PyUnicodeFromString(GetEnumName(PropInfo^.PropType, + Result := PyEngine.PyUnicodeFromString(GetEnumName(PropInfo^.PropType, {$ELSE FPC} - Result := GetPythonEngine.PyUnicodeFromString(GetEnumName(PropInfo^.PropType^, + Result := PyEngine.PyUnicodeFromString(GetEnumName(PropInfo^.PropType^, {$ENDIF FPC} GetOrdProp(Self.DelphiObject, PropInfo))); end end else - Result := GetPythonEngine.VariantAsPyObject(GetPropValue(DelphiObject, PropInfo)); + Result := PyEngine.VariantAsPyObject(GetPropValue(DelphiObject, PropInfo)); end; except on E: Exception do begin @@ -3602,9 +3664,8 @@ function TPyDelphiObject.GetAttrO(key: PPyObject): PPyObject; end; {$ENDIF} if not Assigned(Result) then - with GetPythonEngine do - PyErr_SetObject (PyExc_AttributeError^, - PyUnicodeFromString(Format(rs_ErrAttrGet,[KeyName, ErrMsg]))); + PyEngine.PyErr_SetString(PyEngine.PyExc_AttributeError^, + PAnsiChar(PyEngine.EncodeString(Format(rs_ErrAttrGet,[KeyName, ErrMsg])))); end; function TPyDelphiObject.GetContainerAccess: TContainerAccess; @@ -3767,9 +3828,9 @@ function TPyDelphiObject.Iter: PPyObject; begin Result := nil; with GetPythonEngine do - PyErr_SetObject( PyExc_SystemError^, - PyUnicodeFromString(Format(rs_ErrIterSupport, - [Self.ClassName])) ); + PyErr_SetString(PyExc_SystemError^, + PAnsiChar(EncodeString(Format(rs_ErrIterSupport, + [Self.ClassName])))); end; end; @@ -3788,7 +3849,7 @@ class procedure TPyDelphiObject.RegisterGetSets(PythonType: TPythonType); PythonType.AddGetSet('__bound__', @TPyDelphiObject.Get_Bound, nil, 'Returns True if the wrapper is still bound to the Delphi instance.', nil); PythonType.AddGetSet('__owned__', @TPyDelphiObject.Get_Owned, @TPyDelphiObject.Set_Owned, - 'Returns True if the wrapper owns the Delphi instance.', nil); + 'Boolean read/write property that determines weather the wrapper owns the Delphi instance.', nil); end; class procedure TPyDelphiObject.RegisterMethods(PythonType: TPythonType); @@ -3906,11 +3967,16 @@ function TPyDelphiObject.SetAttrO(key, value: PPyObject): Integer; Result := -1; PyEngine := GetPythonEngine; - // should not happen - if not (Assigned(DelphiObject) and - CheckStrAttribute(Key, 'SetAttrO key parameter', KeyName)) - then + // If DelphiObject is nil exit immediately with an error + if not Assigned(DelphiObject) then + begin + PyEngine.PyErr_SetString(PyEngine.PyExc_AttributeError^, + PAnsiChar(PyEngine.EncodeString(rs_ErrObjectDestroyed))); Exit; + end; + + if not CheckStrAttribute(Key, 'SetAttrO key parameter', KeyName) then + Exit; // should not happen // Only call the inherited method at this stage if the attribute exists PyObj := PyEngine.PyObject_GenericGetAttr(GetSelf, key); @@ -3949,10 +4015,6 @@ function TPyDelphiObject.SetAttrO(key, value: PPyObject): Integer; // Subclasses have a __dict__ and can set extra fields if Result <> 0 then Result := inherited SetAttrO(key, value); - if Result <> 0 then - with PyEngine do - PyErr_SetObject(PyEngine.PyExc_AttributeError^, PyUnicodeFromString( - Format(rs_ErrAttrSetr, [KeyName, ErrMsg]))); end; procedure TPyDelphiObject.SetDelphiObject(const Value: TObject); @@ -4127,7 +4189,7 @@ class procedure TPyDelphiObject.ExposeMethods(AClass: TClass; // Ignore methods with unhandled return type if Assigned(LRttiMethod.ReturnType) and (LRttiMethod.ReturnType.TypeKind - in [tkUnknown, tkMethod, tkPointer, tkProcedure]) + in [tkUnknown, tkMethod, tkProcedure]) then Continue; @@ -4229,7 +4291,7 @@ class procedure TPyDelphiObject.ExposeFields(AClass: TClass; Continue; // Skip if the type cannot be handled - if LRttiField.FieldType.TypeKind in [tkUnknown, tkMethod, tkPointer, tkProcedure] then + if LRttiField.FieldType.TypeKind in [tkUnknown, tkMethod, tkProcedure] then Continue; AddedFields := AddedFields + [LRttiField.Name]; @@ -4242,7 +4304,7 @@ class procedure TPyDelphiObject.ExposeFields(AClass: TClass; if Assigned(PyDocServer) and PyDocServer.Initialized and PyDocServer.ReadMemberDocStr(LRttiField, LDocStr) then - LExposedField.DocString := AnsiString(LDocStr); + LExposedField.DocString := Utf8Encode(LDocStr); // Keep it alive until the Wrapper is Finalized APyDelphiWrapper.fExposedMembers.Add(LExposedField); @@ -4315,7 +4377,7 @@ class procedure TPyDelphiObject.ExposeProperties(AClass: TClass; else begin // Skip if the type cannot be handled - if LRttiProperty.PropertyType.TypeKind in [tkUnknown, tkPointer, tkMethod, tkProcedure] then + if LRttiProperty.PropertyType.TypeKind in [tkUnknown, tkMethod, tkProcedure] then Continue; // Create the exposed property @@ -4329,7 +4391,7 @@ class procedure TPyDelphiObject.ExposeProperties(AClass: TClass; if Assigned(PyDocServer) and PyDocServer.Initialized and PyDocServer.ReadMemberDocStr(LRttiProperty, LDocStr) then - LExposedProperty.DocString := AnsiString(LDocStr); + LExposedProperty.DocString := Utf8Encode(LDocStr); // Keep it alive until the Wrapper is Finalized APyDelphiWrapper.fExposedMembers.Add(LExposedProperty); @@ -4399,7 +4461,7 @@ class procedure TPyDelphiObject.ExposeIndexedProperties(AClass: TClass; Continue; // Skip if the type cannot be handled - if LRttiProperty.PropertyType.TypeKind in [tkUnknown, tkPointer, tkMethod, tkProcedure] then + if LRttiProperty.PropertyType.TypeKind in [tkUnknown, tkMethod, tkProcedure] then Continue; AddedProperties := AddedProperties + [LRttiProperty.Name]; @@ -4412,7 +4474,7 @@ class procedure TPyDelphiObject.ExposeIndexedProperties(AClass: TClass; if Assigned(PyDocServer) and PyDocServer.Initialized and PyDocServer.ReadMemberDocStr(LRttiProperty, LDocStr) then - LExposedProperty.DocString := AnsiString(LDocStr); + LExposedProperty.DocString := Utf8Encode(LDocStr); // Keep it alive until the Wrapper is Finalized APyDelphiWrapper.fExposedMembers.Add(LExposedProperty); @@ -4478,7 +4540,7 @@ function TPyDelphiObject.MpAssSubscript(obj1, obj2: PPyObject) : Integer; if not Prop.IsWritable then begin with Engine do - PyErr_SetObject(PyExc_TypeError^, PyUnicodeFromString(rs_NotWritable)); + PyErr_SetString(PyExc_TypeError^, PAnsiChar(EncodeString(rs_NotWritable))); Exit; end; @@ -4545,8 +4607,8 @@ function TPyDelphiObject.SqAssItem(idx: NativeInt; obj: PPyObject): integer; begin Result := -1; with GetPythonEngine do - PyErr_SetObject( PyExc_SystemError^, - PyUnicodeFromString(Format(rs_ErrSqAss, [Self.ClassName])) ); + PyErr_SetString( PyExc_SystemError^, + PAnsiChar(EncodeString(Format(rs_ErrSqAss, [Self.ClassName])))); end; end; @@ -4576,8 +4638,8 @@ function TPyDelphiObject.SqItem(idx: NativeInt): PPyObject; begin Result := nil; with GetPythonEngine do - PyErr_SetObject( PyExc_SystemError^, - PyUnicodeFromString(Format(rs_ErrSequence, [Self.ClassName])) ); + PyErr_SetString(PyExc_SystemError^, + PAnsiChar(EncodeString(Format(rs_ErrSequence, [Self.ClassName])))); end; end; @@ -4608,8 +4670,8 @@ function TPyDelphiObject.ToList_Wrapper(args: PPyObject): PPyObject; begin Result := nil; with GetPythonEngine do - PyErr_SetObject( PyExc_SystemError^, - PyUnicodeFromString(Format(rs_ErrSequence, [Self.ClassName])) ); + PyErr_SetString(PyExc_SystemError^, + PAnsiChar(EncodeString(Format(rs_ErrSequence, [Self.ClassName])))); end else if GetPythonEngine.PyArg_ParseTuple( args, ':ToList' ) <> 0 then with GetPythonEngine do @@ -4632,8 +4694,8 @@ function TPyDelphiObject.ToTuple_Wrapper(args: PPyObject): PPyObject; begin Result := nil; with GetPythonEngine do - PyErr_SetObject( PyExc_SystemError^, - PyUnicodeFromString(Format(rs_ErrSequence, [Self.ClassName])) ); + PyErr_SetString( PyExc_SystemError^, + PAnsiChar(EncodeString(Format(rs_ErrSequence, [Self.ClassName])))); end else if GetPythonEngine.PyArg_ParseTuple( args, ':ToTuple' ) <> 0 then with GetPythonEngine do @@ -4699,9 +4761,9 @@ function TPyDelphiMethodObject.Call(ob1, ob2: PPyObject): PPyObject; on E: Exception do begin Result := nil; - PyErr_SetObject (PyExc_TypeError^, - PyUnicodeFromString(Format(rs_ErrInvalidArgs, - [MethodInfo.Name, E.Message]))); + PyErr_SetString(PyExc_TypeError^, + PAnsiChar(EncodeString(Format(rs_ErrInvalidArgs, + [MethodInfo.Name, E.Message])))); end; end; end; @@ -5177,9 +5239,8 @@ function TPyDelphiWrapper.CreateComponent(pself, args: PPyObject): PPyObject; Klass := nil; end; if (Klass = nil) or not Klass.InheritsFrom(TComponent) then begin - PyErr_SetObject(PyExc_TypeError^, PyUnicodeFromString( - Format(rs_ErrInvalidArgs, - ['CreateComponent', rs_InvalidClass]))); + PyErr_SetString(PyExc_TypeError^, PAnsiChar(EncodeString( + Format(rs_ErrInvalidArgs, ['CreateComponent', rs_InvalidClass])))); Exit; end; @@ -5194,9 +5255,8 @@ function TPyDelphiWrapper.CreateComponent(pself, args: PPyObject): PPyObject; Ownership := soOwned; Result := Self.Wrap(Component, Ownership); end else - PyErr_SetObject(PyExc_TypeError^, PyUnicodeFromString( - Format(rs_ErrInvalidArgs, - ['CreateComponent', '']))); + PyErr_SetString(PyExc_TypeError^, PAnsiChar(EncodeString( + Format(rs_ErrInvalidArgs, ['CreateComponent', ''])))); end; end; diff --git a/Source/WrapDelphiClasses.pas b/Source/WrapDelphiClasses.pas index bfee8aa3..f7f57a86 100644 --- a/Source/WrapDelphiClasses.pas +++ b/Source/WrapDelphiClasses.pas @@ -1221,13 +1221,13 @@ function TPyDelphiComponent.MpSubscript(obj: PPyObject): PPyObject; else begin Result := nil; - PyErr_SetString (PyExc_KeyError^, PAnsiChar(AnsiString(_name))); + PyErr_SetString(PyExc_KeyError^, PAnsiChar(EncodeString(_name))); end; end else begin Result := nil; - PyErr_SetString (PyExc_KeyError^, 'Key must be a string'); + PyErr_SetString(PyExc_KeyError^, 'Key must be a string'); end; end; end; @@ -1329,7 +1329,7 @@ function TStringsAccess.SetItem(AIndex: Integer; AValue: PPyObject): Boolean; else begin Result := False; - PyErr_SetString (PyExc_AttributeError^, 'You can only assign strings to TStrings items'); + PyErr_SetString(PyExc_AttributeError^, 'You can only assign strings to TStrings items'); end; end end; @@ -1393,7 +1393,7 @@ function TStringsObjectsAccess.SetItem(AIndex: Integer; AValue: PPyObject): Bool else begin Result := False; - PyErr_SetString (PyExc_AttributeError^, 'You can only assign Delphi wrappers to Objects items'); + PyErr_SetString(PyExc_AttributeError^, 'You can only assign Delphi wrappers to Objects items'); end; end end; @@ -1617,11 +1617,11 @@ function TPyDelphiStrings.MpSubscript(obj: PPyObject): PPyObject; else Result := GetPythonEngine.ReturnNone; end else with GetPythonEngine do begin - PyErr_SetString (PyExc_KeyError^, PAnsiChar(AnsiString(S))); + PyErr_SetString(PyExc_KeyError^, PAnsiChar(EncodeString(S))); Result := nil; end; end else with GetPythonEngine do begin - PyErr_SetString (PyExc_KeyError^, '<Empty String>'); + PyErr_SetString(PyExc_KeyError^, '<Empty String>'); Result := nil; end; end; @@ -2445,7 +2445,7 @@ TResourceStreamClass = class of TResourceStream; except on E: Exception do with GetPythonEngine do - PyErr_SetString(PyExc_RuntimeError^, PAnsiChar(AnsiString(E.Message))); + PyErr_SetString(PyExc_RuntimeError^, PAnsiChar(EncodeString(E.Message))); end; //Maybe it was created on the next attempt... diff --git a/Source/WrapDelphiTypes.pas b/Source/WrapDelphiTypes.pas index e572b851..86f00e22 100644 --- a/Source/WrapDelphiTypes.pas +++ b/Source/WrapDelphiTypes.pas @@ -229,8 +229,8 @@ function CheckPointAttribute(AAttribute : PPyObject; const AAttributeName : stri begin Result := False; with GetPythonEngine do - PyErr_SetString (PyExc_AttributeError^, - PAnsiChar(AnsiString(Format('%s receives only Point objects', [AAttributeName])))); + PyErr_SetString(PyExc_AttributeError^, + PAnsiChar(EncodeString(Format('%s receives only Point objects', [AAttributeName])))); end; end; end; @@ -248,8 +248,8 @@ function CheckRectAttribute(AAttribute : PPyObject; const AAttributeName : strin begin Result := False; with GetPythonEngine do - PyErr_SetString (PyExc_AttributeError^, - PAnsiChar(AnsiString(Format('%s receives only Rect objects', [AAttributeName])))); + PyErr_SetString(PyExc_AttributeError^, + PAnsiChar(EncodeString(Format('%s receives only Rect objects', [AAttributeName])))); end; end; end; @@ -267,8 +267,8 @@ function CheckSizeAttribute(AAttribute : PPyObject; const AAttributeName : strin begin Result := False; with GetPythonEngine do - PyErr_SetString (PyExc_AttributeError^, - PAnsiChar(AnsiString(Format('%s receives only Size objects', [AAttributeName])))); + PyErr_SetString(PyExc_AttributeError^, + PAnsiChar(EncodeString(Format('%s receives only Size objects', [AAttributeName])))); end; end; end; diff --git a/Source/WrapFireDAC.pas b/Source/WrapFireDAC.pas index eefa7af9..76e64aec 100644 --- a/Source/WrapFireDAC.pas +++ b/Source/WrapFireDAC.pas @@ -597,7 +597,7 @@ function TPyDBField.CheckField : Boolean; if not Assigned(DelphiObject) then begin Result := False; with GetPythonEngine do - PyErr_SetString (PyExc_RuntimeError^, PAnsiChar('No field defined !') ); + PyErr_SetString(PyExc_RuntimeError^, PAnsiChar('No field defined !') ); end else Result := True; @@ -978,7 +978,7 @@ function TPyDBDataset.Do_Fields( args : PPyObject ): PPyObject; Result := PyDelphiWrapper.Wrap(l_oDataset.Fields[idx]) else begin Result := nil; - PyErr_SetString (PyExc_AttributeError^, PAnsiChar(AnsiString(Format('Value out of range : %d', [idx])))); + PyErr_SetString(PyExc_AttributeError^, PAnsiChar(EncodeString(Format('Value out of range : %d', [idx])))); end; end else @@ -1011,7 +1011,7 @@ function TPyDBDataset.Do_FieldByName( args : PPyObject ) : PPyObject; Result := PyDelphiWrapper.Wrap(fld) else begin Result := nil; - PyErr_SetString (PyExc_AttributeError^, PAnsiChar(AnsiString(Format('Unknown field "%s"', [String(s)]))) ); + PyErr_SetString(PyExc_AttributeError^, PAnsiChar(AnsiString(Format('Unknown field "%s"', [String(s)]))) ); end; end else @@ -1191,7 +1191,7 @@ function TPyDBDataset.Do_Locate( args : PPyObject ) : PPyObject; try if PyArg_ParseTuple( args, 'sOO:DBDataset.Locate',@keyFields, @keyValues, @options ) <> 0 then begin if PySequence_Check(options) = 0 then - PyErr_SetString (PyExc_AttributeError^, 'Third argument of Locate must be a sequence.') + PyErr_SetString(PyExc_AttributeError^, 'Third argument of Locate must be a sequence.') else begin // Prepare the locate options ListToSet( options, @opt, sizeof(opt) ); @@ -1391,14 +1391,14 @@ function TPyDBTable.CheckActiveDBTable(aMustOpen: Boolean): Boolean; if not aMustOpen then begin Result := False; with GetPythonEngine do - PyErr_SetString (PyExc_RuntimeError^, PAnsiChar('DBTable is open!') ); + PyErr_SetString(PyExc_RuntimeError^, PAnsiChar('DBTable is open!') ); end; end else begin if aMustOpen then begin Result := False; with GetPythonEngine do - PyErr_SetString (PyExc_RuntimeError^, PAnsiChar('DBTable is not open!') ); + PyErr_SetString(PyExc_RuntimeError^, PAnsiChar('DBTable is not open!') ); end; end; end; @@ -1838,10 +1838,10 @@ function TPyDBTable.Do_SetRange( args : PPyObject ) : PPyObject; if l_oTable.Active and (PyArg_ParseTuple( args, 'OO:FDTable.SetRange',@l_oPyStartValues, @l_oPyEndValues ) <> 0) then begin if PySequence_Check(l_oPyStartValues) = 0 then begin - PyErr_SetString (PyExc_AttributeError^, 'First argument of SetRange must be a sequence.'); + PyErr_SetString(PyExc_AttributeError^, 'First argument of SetRange must be a sequence.'); end else if PySequence_Check(l_oPyEndValues) = 0 then begin - PyErr_SetString (PyExc_AttributeError^, 'Second argument of SetRange must be a sequence.'); + PyErr_SetString(PyExc_AttributeError^, 'Second argument of SetRange must be a sequence.'); end else begin l_oTable.SetRangeStart; @@ -1952,14 +1952,14 @@ function TPyDBQuery.CheckActiveDBQuery(aMustOpen: Boolean): Boolean; if not aMustOpen then begin Result := False; with GetPythonEngine do - PyErr_SetString (PyExc_RuntimeError^, PAnsiChar('DBQuery is open!') ); + PyErr_SetString(PyExc_RuntimeError^, PAnsiChar('DBQuery is open!') ); end; end else begin if aMustOpen then begin Result := False; with GetPythonEngine do - PyErr_SetString (PyExc_RuntimeError^, PAnsiChar('DBQuery is not open!') ); + PyErr_SetString(PyExc_RuntimeError^, PAnsiChar('DBQuery is not open!') ); end; end; end; diff --git a/Source/fmx/WrapDelphiFmx.pas b/Source/fmx/WrapDelphiFmx.pas index 0bcc5f45..92f11120 100644 --- a/Source/fmx/WrapDelphiFmx.pas +++ b/Source/fmx/WrapDelphiFmx.pas @@ -24,9 +24,7 @@ implementation WrapDelphiWindows, {$ENDIF MSWINDOWS} WrapDelphiDataBind, - {$IFNDEF LINUX} WrapFmxDataBind, - {$ENDIF LINUX} WrapFmxTypes, WrapFmxImgList, WrapFmxControls, diff --git a/Source/fmx/WrapFmxForms.pas b/Source/fmx/WrapFmxForms.pas index f3a2b68e..906f14b5 100644 --- a/Source/fmx/WrapFmxForms.pas +++ b/Source/fmx/WrapFmxForms.pas @@ -466,7 +466,7 @@ function TPyDelphiCommonCustomForm.LoadProps_Wrapper( except on E: Exception do with GetPythonEngine do - PyErr_SetString(PyExc_RuntimeError^, PAnsiChar(AnsiString(E.Message))); + PyErr_SetString(PyExc_RuntimeError^, PAnsiChar(Utf8Encode(E.Message))); end; Result := nil; end; diff --git a/Source/fmx/WrapFmxTypes.pas b/Source/fmx/WrapFmxTypes.pas index 53e36d9f..b7bbb8d5 100644 --- a/Source/fmx/WrapFmxTypes.pas +++ b/Source/fmx/WrapFmxTypes.pas @@ -505,7 +505,7 @@ function CheckPointFAttribute(AAttribute : PPyObject; const AAttributeName : str Result := False; with GetPythonEngine do PyErr_SetString (PyExc_AttributeError^, - PAnsiChar(AnsiString(Format('%s receives only PointF objects', [AAttributeName])))); + PAnsiChar(Utf8Encode(Format('%s receives only PointF objects', [AAttributeName])))); end; end; end; @@ -524,7 +524,7 @@ function CheckSizeFAttribute(AAttribute : PPyObject; const AAttributeName : stri Result := False; with GetPythonEngine do PyErr_SetString (PyExc_AttributeError^, - PAnsiChar(AnsiString(Format('%s receives only SizeF objects', [AAttributeName])))); + PAnsiChar(Utf8Encode(Format('%s receives only SizeF objects', [AAttributeName])))); end; end; end; @@ -543,7 +543,7 @@ function CheckRectFAttribute(AAttribute: PPyObject; const AAttributeName: string Result := False; with GetPythonEngine do PyErr_SetString (PyExc_AttributeError^, - PAnsiChar(AnsiString(Format('%s receives only RectF objects', [AAttributeName])))); + PAnsiChar(Utf8Encode(Format('%s receives only RectF objects', [AAttributeName])))); end; end; end; @@ -562,7 +562,7 @@ function CheckTouchAttribute(AAttribute: PPyObject; const AAttributeName: string Result := False; with GetPythonEngine do PyErr_SetString (PyExc_AttributeError^, - PAnsiChar(AnsiString(Format('%s receives only Touch objects', [AAttributeName])))); + PAnsiChar(Utf8Encode(Format('%s receives only Touch objects', [AAttributeName])))); end; end; end; diff --git a/Source/vcl/WrapVclComCtrls.pas b/Source/vcl/WrapVclComCtrls.pas index 18c161e8..aff247eb 100644 --- a/Source/vcl/WrapVclComCtrls.pas +++ b/Source/vcl/WrapVclComCtrls.pas @@ -742,8 +742,10 @@ TPyDelphiListView = class(TPyDelphiCustomListView) implementation uses - WrapDelphiTypes, WrapDelphiWindows, - Vcl.ExtCtrls; + System.Rtti, + Vcl.ExtCtrls, + WrapDelphiTypes, + WrapDelphiWindows; { Register the wrappers, the globals and the constants } type @@ -781,30 +783,12 @@ function CustomDrawStageToPython(const ACustomDrawStage: TCustomDrawStage): PPyO end; function CustomDrawStateToPython(const ACustomDrawState: TCustomDrawState): PPyObject; - - procedure Append(const AList: PPyObject; const AString: string); - var - LItem: PPyObject; - begin - with GetPythonEngine do begin - LItem := PyUnicodeFromString(AString); - PyList_Append(AList, LItem); - Py_XDecRef(LItem); - end; - end; - var - LCompType: PTypeInfo; - LMin: integer; - LMax: integer; - LState: integer; + ErrMsg: string; + Value: TValue; begin - Result := GetPythonEngine().PyList_New(0); - LCompType := GetTypeData(TypeInfo(TCustomDrawState)).CompType^; - LMin := LCompType^.TypeData^.MinValue; - LMax := LCompType^.TypeData^.MaxValue; - for LState := LMin to LMax do - Append(Result, GetEnumName(LCompType, LState)); + Value := TValue.From(ACustomDrawState); + Result := SimpleValueToPython(Value, ErrMsg); end; function ItemChangeToPython(const AItemChange: TItemChange): PPyObject; diff --git a/Source/vcl/WrapVclForms.pas b/Source/vcl/WrapVclForms.pas index 0a373dfa..b3d77bec 100644 --- a/Source/vcl/WrapVclForms.pas +++ b/Source/vcl/WrapVclForms.pas @@ -572,7 +572,7 @@ function TPyDelphiCustomForm.LoadProps_Wrapper(args: PPyObject): PPyObject; except on E: Exception do with GetPythonEngine() do - PyErr_SetString(PyExc_RuntimeError^, PAnsiChar(AnsiString(E.Message))); + PyErr_SetString(PyExc_RuntimeError^, PAnsiChar(EncodeString(E.Message))); end; Result := nil; end; @@ -1072,7 +1072,7 @@ class procedure TPyDelphiScreen.RegisterMethods(PythonType: TPythonType); 'Allows forms to be aligned in the screen.'); PythonType.AddMethod('Realign', @TPyDelphiScreen.Realign_Wrapper, 'TScreen.Realign()'#10 + - 'Realigns the screen’s forms according to their Align properties.'); + 'Realigns the screen''s forms according to their Align properties.'); PythonType.AddMethod('ResetFonts', @TPyDelphiScreen.ResetFonts_Wrapper, 'TScreen.ResetFonts()'#10 + 'Reinitializes the fonts listed in the Fonts property.'); diff --git a/Source/vcl/WrapVclGraphics.pas b/Source/vcl/WrapVclGraphics.pas index 1479d5f6..21a54013 100644 --- a/Source/vcl/WrapVclGraphics.pas +++ b/Source/vcl/WrapVclGraphics.pas @@ -1057,7 +1057,7 @@ function TPyDelphiBitmap.Set_HandleType(AValue: PPyObject; else begin with GetPythonEngine do - PyErr_SetString (PyExc_AttributeError^, PAnsiChar(AnsiString(Format('Unknown THandleType value "%s"', [_value])))); + PyErr_SetString(PyExc_AttributeError^, PAnsiChar(EncodeString(Format('Unknown THandleType value "%s"', [_value])))); Result := -1; Exit; end; @@ -1143,7 +1143,7 @@ function TPyDelphiBitmap.Set_PixelFormat(AValue: PPyObject; DelphiObject.PixelFormat := pfCustom else begin - PyErr_SetString (PyExc_AttributeError^, PAnsiChar(AnsiString(Format('Unknown TPixelFormat value "%s"', [_value])))); + PyErr_SetString(PyExc_AttributeError^, PAnsiChar(EncodeString(Format('Unknown TPixelFormat value "%s"', [_value])))); Result := -1; Exit; end; @@ -1184,7 +1184,7 @@ function TPyDelphiBitmap.Set_TransparentMode(AValue: PPyObject; else begin with GetPythonEngine do - PyErr_SetString (PyExc_AttributeError^, PAnsiChar(AnsiString(Format('Unknown TTransparentMode value "%s"', [_value])))); + PyErr_SetString(PyExc_AttributeError^, PAnsiChar(EncodeString(Format('Unknown TTransparentMode value "%s"', [_value])))); Result := -1; Exit; end; @@ -1615,7 +1615,7 @@ function TPyDelphiCanvas.PolyBezier_Wrapper(args: PPyObject): PPyObject; else begin Result := nil; - PyErr_SetString (PyExc_AttributeError^, 'PolyBezier accepts only a sequence of points as single parameter'); + PyErr_SetString(PyExc_AttributeError^, 'PolyBezier accepts only a sequence of points as single parameter'); end; end else @@ -1662,7 +1662,7 @@ function TPyDelphiCanvas.PolyBezierTo_Wrapper(args: PPyObject): PPyObject; else begin Result := nil; - PyErr_SetString (PyExc_AttributeError^, 'PolyBezierTo accepts only a sequence of points as single parameter'); + PyErr_SetString(PyExc_AttributeError^, 'PolyBezierTo accepts only a sequence of points as single parameter'); end; end else @@ -1709,7 +1709,7 @@ function TPyDelphiCanvas.Polygon_Wrapper(args: PPyObject): PPyObject; else begin Result := nil; - PyErr_SetString (PyExc_AttributeError^, 'Polygon accepts only a sequence of points as single parameter'); + PyErr_SetString(PyExc_AttributeError^, 'Polygon accepts only a sequence of points as single parameter'); end; end else @@ -1755,7 +1755,7 @@ function TPyDelphiCanvas.Polyline_Wrapper(args: PPyObject): PPyObject; else begin Result := nil; - PyErr_SetString (PyExc_AttributeError^, 'Polyline accepts only a sequence of points as single parameter'); + PyErr_SetString(PyExc_AttributeError^, 'Polyline accepts only a sequence of points as single parameter'); end; end else diff --git a/Tests/AutoWrapEventHandlerTest.pas b/Tests/AutoWrapEventHandlerTest.pas index feb9656d..173794c2 100644 --- a/Tests/AutoWrapEventHandlerTest.pas +++ b/Tests/AutoWrapEventHandlerTest.pas @@ -71,7 +71,6 @@ procedure TTestAutoWrapEventHandlers.SetupFixture; PythonEngine.FatalMsgDlg := True; PythonEngine.UseLastKnownVersion := True; PythonEngine.AutoFinalize := True; - PythonEngine.InitThreads := True; PythonEngine.PyFlags := [pfInteractive]; DelphiModule := TPythonModule.Create(nil); DelphiModule.Name := 'DelphiModule'; diff --git a/Tests/FMX/Android/NumberServicesTest.pas b/Tests/FMX/Android/NumberServicesTest.pas index 115ba066..3aee6737 100644 --- a/Tests/FMX/Android/NumberServicesTest.pas +++ b/Tests/FMX/Android/NumberServicesTest.pas @@ -288,7 +288,7 @@ constructor PyTRandomInteger.CreateWith(PythonType: TPythonType; args, FRandomInteger.Value := PythonToTRandomInteger(val1).Value; except on e: Exception do - PyErr_SetString(PyExc_Exception^, PAnsiChar(AnsiString(e.Message))); + PyErr_SetString(PyExc_Exception^, PAnsiChar(EncodeString(e.Message))); end; end; end; diff --git a/Tests/NumberServicesTest.pas b/Tests/NumberServicesTest.pas index d1e1a3cf..0b100950 100644 --- a/Tests/NumberServicesTest.pas +++ b/Tests/NumberServicesTest.pas @@ -176,7 +176,6 @@ procedure TTestNumberServices.SetupFixture; PythonEngine.UseLastKnownVersion := True; PythonEngine.AutoFinalize := True; - PythonEngine.InitThreads := True; PythonEngine.PyFlags := [pfInteractive]; PythonEngine.LoadDll; @@ -292,7 +291,7 @@ constructor PyTRandomInteger.CreateWith(PythonType: TPythonType; args, FRandomInteger.Value := PythonToTRandomInteger(val1).Value; except on e: Exception do - PyErr_SetString(PyExc_Exception^, PAnsiChar(AnsiString(e.Message))); + PyErr_SetString(PyExc_Exception^, PAnsiChar(EncodeString(e.Message))); end; end; end; diff --git a/Tests/VarPythTest.pas b/Tests/VarPythTest.pas index 34e68f0a..f32fa7de 100644 --- a/Tests/VarPythTest.pas +++ b/Tests/VarPythTest.pas @@ -74,7 +74,6 @@ procedure TTestVarPyth.SetupFixture; PythonEngine.UseLastKnownVersion := True; PythonEngine.AutoFinalize := True; - PythonEngine.InitThreads := True; PythonEngine.PyFlags := [pfInteractive]; PythonEngine.LoadDll; end; diff --git a/Tests/WrapDelphiEventHandlerTest.pas b/Tests/WrapDelphiEventHandlerTest.pas index c6cda4ce..efaf5b44 100644 --- a/Tests/WrapDelphiEventHandlerTest.pas +++ b/Tests/WrapDelphiEventHandlerTest.pas @@ -215,7 +215,6 @@ procedure TTestWrapDelphiEventHandlers.SetupFixture; PythonEngine.FatalMsgDlg := True; PythonEngine.UseLastKnownVersion := True; PythonEngine.AutoFinalize := True; - PythonEngine.InitThreads := True; PythonEngine.PyFlags := [pfInteractive]; DelphiModule := TPythonModule.Create(nil); DelphiModule.Name := 'DelphiModule'; diff --git a/Tests/WrapDelphiTest.pas b/Tests/WrapDelphiTest.pas index ba7ff43e..d320f53a 100644 --- a/Tests/WrapDelphiTest.pas +++ b/Tests/WrapDelphiTest.pas @@ -55,6 +55,7 @@ TTestRttiAccess = class ObjectField: TObject; RecordField: TTestRecord; InterfaceField: ITestInterface; + PointerField: Pointer; ClassRef: TClass; function GetData: TObject; procedure BuyFruits(AFruits: TFruits); @@ -71,6 +72,7 @@ TTestRttiAccess = class procedure VarArgsProc1(var I: Integer); function VarArgsFunc1(var I: Integer): Integer; procedure VarArgsProc2(var I: Integer; var S: string); + function PlaceInNewList(PyObj: PPyObject): PPyObject; property Indexed[I: Integer]: Integer read GetIndexed write SetIndexed; property Indexed2[S1, S2: string]: string read GetIndexed2 write SetIndexed2; default; class var ClassField: string; @@ -157,6 +159,10 @@ TTestWrapDelphi = class(TObject) procedure TestIndexedProperties; [Test] procedure TestVarArgs; + [Test] + procedure TestPPyObjects; + [Test] + procedure TestPointers; end; implementation @@ -202,7 +208,6 @@ procedure TTestWrapDelphi.SetupFixture; PythonEngine.UseLastKnownVersion := True; PythonEngine.AutoFinalize := True; - PythonEngine.InitThreads := True; PythonEngine.PyFlags := [pfInteractive]; DelphiModule := TPythonModule.Create(nil); @@ -428,6 +433,21 @@ procedure TTestWrapDelphi.TestPassVariantArray; Assert.Pass; end; +procedure TTestWrapDelphi.TestPPyObjects; +var + List: Variant; +begin + List := rtti_var.PlaceInNewList('abc'); + Assert.IsTrue(VarIsPythonList(List)); + Assert.AreEqual<string>(List.GetItem(0), 'abc'); +end; + +procedure TTestWrapDelphi.TestPointers; +begin + rtti_var.PointerField := $FFFF; + Assert.AreEqual<NativeUInt>(rtti_var.PointerField, $FFFF); +end; + procedure TTestWrapDelphi.TestRecord; begin Rtti_rec.StringField := 'abcd'; @@ -616,6 +636,16 @@ procedure TTestRttiAccess.PassVariantArray(const Value: Variant); Assert.IsTrue(VarIsArray(Value) and (VarArrayHighBound(Value, 1) = 9)); end; +function TTestRttiAccess.PlaceInNewList(PyObj: PPyObject): PPyObject; +begin + with GetPythonEngine do + begin + Result := PyList_New(1); + Py_XIncRef(PyObj); + PyList_SetItem(Result, 0, PyObj); + end; +end; + procedure TTestRttiAccess.SellFruits(const AFruits: TFruitDynArray); var Fruit: TFruit; diff --git a/Tutorials/Webinar II/AnalyticsDemo/MainFormSVG.dfm b/Tutorials/Webinar II/AnalyticsDemo/MainFormSVG.dfm index 15464024..1642832f 100644 --- a/Tutorials/Webinar II/AnalyticsDemo/MainFormSVG.dfm +++ b/Tutorials/Webinar II/AnalyticsDemo/MainFormSVG.dfm @@ -254,7 +254,6 @@ object Form1: TForm1 Top = 89 end object PythonEngine1: TPythonEngine - InitThreads = True IO = PythonGUIInputOutput1 Left = 632 Top = 136 diff --git a/Tutorials/Webinar II/VizDemo/MainFormSVG.dfm b/Tutorials/Webinar II/VizDemo/MainFormSVG.dfm index cda1daa9..0d78949a 100644 --- a/Tutorials/Webinar II/VizDemo/MainFormSVG.dfm +++ b/Tutorials/Webinar II/VizDemo/MainFormSVG.dfm @@ -10,17 +10,12 @@ object Form1: TForm1 Font.Height = -11 Font.Name = 'Tahoma' Font.Style = [] - OldCreateOrder = False OnCreate = FormCreate - PixelsPerInch = 96 TextHeight = 13 object Splitter1: TSplitter Left = 489 Top = 0 Height = 613 - ExplicitLeft = 528 - ExplicitTop = 280 - ExplicitHeight = 100 end object SVGIconImage1: TSVGIconImage Left = 960 @@ -35,8 +30,6 @@ object Form1: TForm1 Width = 543 Height = 613 AutoSize = False - ParentDoubleBuffered = False - DoubleBuffered = True Align = alClient end object PageControl1: TPageControl @@ -46,7 +39,7 @@ object Form1: TForm1 Height = 613 ActivePage = TabSheet1 Align = alLeft - TabOrder = 2 + TabOrder = 0 object TabSheet1: TTabSheet Caption = 'matplotlib' object Panel1: TPanel @@ -63,8 +56,6 @@ object Form1: TForm1 Height = 3 Cursor = crVSplit Align = alBottom - ExplicitTop = 10 - ExplicitWidth = 492 end object SynEdit1: TSynEdit Left = 1 @@ -72,6 +63,7 @@ object Form1: TForm1 Width = 479 Height = 444 Align = alClient + CaseSensitive = True Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -13 @@ -85,6 +77,8 @@ object Form1: TForm1 Gutter.Font.Height = -11 Gutter.Font.Name = 'Consolas' Gutter.Font.Style = [] + Gutter.Font.Quality = fqClearTypeNatural + Gutter.Bands = <> Highlighter = SynPythonSyn1 Lines.Strings = ( 'from delphi_module import svg_image' @@ -102,10 +96,16 @@ object Form1: TForm1 '# stores the date as an np.datetime64 with a day unit ('#39'D'#39') in t' + 'he date column.' - - 'price_data = (cbook.get_sample_data('#39'goog.npz'#39', np_load=True)['#39'p' + - 'rice_data'#39']' - ' .view(np.recarray))' + '# Load Google stock price data from Matplotlib'#39's sample data' + 'data = cbook.get_sample_data('#39'goog.npz'#39')' + '' + '# Handle different return types from get_sample_data' + 'if isinstance(data, np.lib.npyio.NpzFile):' + ' # Already an NpzFile, access price_data directly' + ' price_data = data['#39'price_data'#39'].view(np.recarray)' + 'else:' + ' # Assume data is a path or file-like object, use np.load' + ' price_data = np.load(data)['#39'price_data'#39'].view(np.recarray)' 'price_data = price_data[-250:] # get the most recent 250 tradin' + 'g days' @@ -138,6 +138,7 @@ object Form1: TForm1 'svg_image.SvgText = figdata_svg' '' '#plt.show()') + ScrollbarAnnotations = <> end object Panel2: TPanel Left = 1 @@ -183,8 +184,6 @@ object Form1: TForm1 Height = 3 Cursor = crVSplit Align = alBottom - ExplicitTop = 151 - ExplicitWidth = 433 end object SynEdit2: TSynEdit Left = 1 @@ -192,6 +191,7 @@ object Form1: TForm1 Width = 479 Height = 376 Align = alClient + CaseSensitive = True Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -13 @@ -205,6 +205,8 @@ object Form1: TForm1 Gutter.Font.Height = -11 Gutter.Font.Name = 'Consolas' Gutter.Font.Style = [] + Gutter.Font.Quality = fqClearTypeNatural + Gutter.Bands = <> Highlighter = SynPythonSyn1 Lines.Strings = ( 'from delphi_module import svg_image' @@ -222,6 +224,7 @@ object Form1: TForm1 '' '#plt.show()' '') + ScrollbarAnnotations = <> end object Panel6: TPanel Left = 1 @@ -252,9 +255,6 @@ object Form1: TForm1 end end object SynPythonSyn1: TSynPythonSyn - Options.AutoDetectEnabled = False - Options.AutoDetectLineLimit = 0 - Options.Visible = False Left = 632 Top = 40 end @@ -264,6 +264,10 @@ object Form1: TForm1 Top = 89 end object PythonEngine1: TPythonEngine + DllName = 'python313.dll' + APIVersion = 1013 + RegVersion = '3.13' + UseLastKnownVersion = False IO = PythonGUIInputOutput1 Left = 632 Top = 136 <!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'> <html xmlns='http://www.w3.org/1999/xhtml'> <head> <title>pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy