From 9d4a980e3f6985a6d89fcfc03ef4b4898b098901 Mon Sep 17 00:00:00 2001 From: pyscripter Date: Mon, 1 Apr 2024 16:53:13 +0300 Subject: [PATCH 01/49] Implement PEP587 Python Initialzation Configuration. (necessary for python 3.13 support) Support python 3.13 (incomplete) Drop support for python for python 3.3-3.7 (do not contain support for PEP587) --- Source/PythonEngine.pas | 261 ++++++++++++++++++++++++++-------------- 1 file changed, 174 insertions(+), 87 deletions(-) diff --git a/Source/PythonEngine.pas b/Source/PythonEngine.pas index 7bd52c93..b124f59d 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -73,59 +73,47 @@ TPythonVersionProp = record end; const {$IFDEF MSWINDOWS} - PYTHON_KNOWN_VERSIONS: array[1..10] of TPythonVersionProp = + PYTHON_KNOWN_VERSIONS: array[1..6] 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) ); {$ENDIF} {$IFDEF _so_files} - PYTHON_KNOWN_VERSIONS: array[1..10] of TPythonVersionProp = + PYTHON_KNOWN_VERSIONS: array[1..6] 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) ); {$ENDIF} {$IFDEF DARWIN} - PYTHON_KNOWN_VERSIONS: array[1..10] of TPythonVersionProp = + PYTHON_KNOWN_VERSIONS: array[1..6] 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) ); {$ENDIF} {$IFDEF ANDROID} - PYTHON_KNOWN_VERSIONS: array[5..10] of TPythonVersionProp = + PYTHON_KNOWN_VERSIONS: array[1..6] 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.13.so'; RegVersion: '3.13'; APIVersion: 1013) ); {$ENDIF} @@ -966,6 +954,7 @@ PyBufferProcs = record end; //initconfig.h + //See https://docs.python.org/3/c-api/init_config.html const _PyStatus_TYPE_OK = 0; @@ -982,6 +971,92 @@ PyBufferProcs = record exitcode: Integer; end; + PPyWideStringList = ^PyWideStringList; + PyWideStringList = {$IFDEF CPUX86}packed{$ENDIF} record + length: Py_ssize_t; + items: PPWCharT; + end; + + PPyConfig = ^PyConfig; + PyConfig = record + _config_init: Integer; + isolated: Integer; + use_environment: Integer; + dev_mode: Integer; + install_signal_handlers: Integer; + use_hash_seed: Integer; + hash_seed: C_ULong; + faulthandler: Integer; + tracemalloc: Integer; + perf_profiling: Integer; + import_time: Integer; + code_debug_ranges: Integer; + show_ref_count: Integer; + dump_refs: Integer; + dump_refs_file: PWCharT; + malloc_stats: Integer; + filesystem_encoding: PWCharT; + filesystem_errors: PWCharT; + pycache_prefix: PWCharT; + parse_argv: Integer; + orig_argv: PyWideStringList; + argv: PyWideStringList; + xoptions: PyWideStringList; + warnoptions: PyWideStringList ; + site_import: Integer; + bytes_warning: Integer; + warn_default_encoding: Integer; + inspect: Integer; + interactive: Integer; + optimization_level: Integer; + parser_debug: Integer; + write_bytecode: Integer; + verbose: Integer; + quiet: Integer; + user_site_directory: Integer; + configure_c_stdio: Integer; + buffered_stdio: Integer; + stdio_encoding: PWCharT; + stdio_errors: PWCharT; + {$IFDEF MSWINDOWS} + legacy_windows_stdio: Integer; + {$ENDIF} + check_hash_pycs_mode: PWCharT; + use_frozen_modules: Integer; + safe_path: Integer; + int_max_str_digits: Integer; + + (* --- Path configuration inputs ------------ *) + pathconfig_warnings: Integer; + program_name: PWCharT; + pythonpath_env: PWCharT; + home: PWCharT; + platlibdir: PWCharT; + + (* --- Path configuration outputs ----------- *) + module_search_paths_set: Integer; + module_search_paths: PyWideStringList; + stdlib_dir: PWCharT; + executable: PWCharT; + base_executable: PWCharT; + prefix: PWCharT; + base_prefix: PWCharT; + exec_prefix: PWCharT; + base_exec_prefix: PWCharT; + + (* --- Parameter only used by Py_Main() ---------- *) + kip_source_first_line: Integer; + un_command: PWCharT; + un_module: PWCharT; + un_filename: PWCharT; + + (* --- Private fields ---------------------------- *) + install_importlib: Integer; + init_main: Integer; + is_python_build: Integer; +end; + + //####################################################### //## ## //## GIL related ## @@ -1355,15 +1430,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; @@ -1771,6 +1837,18 @@ TPythonInterface=class(TDynamicDll) PyGILState_Ensure : function() : PyGILstate_STATE; cdecl; PyGILState_Release : procedure(gilstate : PyGILState_STATE); cdecl; + // Initialization functions + PyWideStringList_Append : function(var list: PyWideStringList; item: PWCharT): PyStatus; cdecl; + PyWideStringList_Insert : function(var list: PyWideStringList; 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; + // 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 @@ -1887,7 +1965,7 @@ 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); + pfFrozenFlag, pfIgnoreEnvironmentFlag, pfIsolated); TPythonFlags = set of TPythonFlag; @@ -1974,14 +2052,14 @@ TPythonEngine = class(TPythonInterface) procedure Notification(AComponent: TComponent; Operation: TOperation); override; procedure CheckRegistry; - procedure SetProgramArgs; + procedure SetProgramArgs(var Config: PyConfig); 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; + procedure AssignPyFlags(var Config: PyConfig); public // Constructors & Destructors @@ -3647,15 +3725,6 @@ procedure TPythonInterface.CheckPython; 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'); @@ -4060,6 +4129,17 @@ 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'); end; function TPythonInterface.Py_CompileString(str,filename:PAnsiChar;start:integer):PPyObject; @@ -4596,25 +4676,15 @@ procedure TPythonEngine.DoOpenDll(const aDllName : string); end; end; -procedure TPythonEngine.AssignPyFlags; - - procedure SetFlag( AFlag: PInteger; AValue : Boolean ); - begin - if AValue then - AFlag^ := 1 - else - AFlag^ := 0; - end; - +procedure TPythonEngine.AssignPyFlags(var Config: PyConfig); 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); + Config.parser_debug := IfThen(pfDebug in FPyFlags, 1, 0); + Config.verbose := IfThen(pfVerbose in FPyFlags, 1, 0); + Config.interactive := IfThen(pfInteractive in FPyFlags, 1, 0); + Config.optimization_level := IfThen(pfOptimize in FPyFlags, 1, 0); + Config.site_import := IfThen(pfNoSite in FPyFlags, 0, 1); + Config.pathconfig_warnings := IfThen(pfFrozenFlag in FPyFlags, 1, 0); + Config.use_environment := IfThen(pfIgnoreEnvironmentFlag in FPyFlags, 0, 1); end; procedure TPythonEngine.Initialize; @@ -4689,6 +4759,7 @@ procedure TPythonEngine.Initialize; var i : Integer; + Config: PyConfig; begin if Assigned(gPythonEngine) then raise Exception.Create('There is already one instance of TPythonEngine running' ); @@ -4700,19 +4771,41 @@ 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; +// 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; + + // Fills Config with zeros and then sets some default values + if pfIsolated in FPyFlags then + PyConfig_InitIsolatedConfig(Config) + else + PyConfig_InitPythonConfig(Config); + try + AssignPyFlags(Config); + + // Set programname and pythonhome if available + if Length(FProgramName) > 0 then + PyConfig_SetString(Config, @Config.program_name, PWCharT(FProgramName)); + if Length(FPythonHome) > 0 then + PyConfig_SetString(Config, @Config.program_name, PWCharT(FPythonHome)); + + // Set program arguments (sys.argv) + SetProgramArgs(Config); + + Py_InitializeFromConfig(Config); + finally + PyConfig_Clear(Config); + end; + if Assigned(Py_IsInitialized) then FInitialized := Py_IsInitialized() <> 0 else FInitialized := True; InitSysPath; - SetProgramArgs; if InitThreads and Assigned(PyEval_InitThreads) then PyEval_InitThreads; if RedirectIO and Assigned(FIO) then @@ -4842,20 +4935,16 @@ procedure TPythonEngine.CheckRegistry; {$ENDIF} end; -procedure TPythonEngine.SetProgramArgs; +procedure TPythonEngine.SetProgramArgs(var Config: PyConfig); var - I, argc : Integer; - wargv : array of PWCharT; - WL : array of WCharTString; + I: Integer; TempS: UnicodeString; + Str: WCharTString; + 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 + Config.parse_argv := 0; // do not parse + 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 @@ -4866,14 +4955,12 @@ procedure TPythonEngine.SetProgramArgs; else TempS := ParamStr(I); {$IFDEF POSIX} - WL[I] := UnicodeStringToUCS4String(TempS); + Str := UnicodeStringToUCS4String(TempS); {$ELSE} - WL[I] := UnicodeString(TempS); + Str := 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) ); + PyWideStringList_Append(Config.argv, PWCharT(Str)); + end; end; procedure TPythonEngine.InitWinConsole; From d26ede5cfe71cc80992ebccea6d6d4cb47396379 Mon Sep 17 00:00:00 2001 From: pyscripter Date: Mon, 1 Apr 2024 18:41:12 +0300 Subject: [PATCH 02/49] Set VenvPythonExe using PyConfig PythonHome and ProgramName no longer need to be stored as WCharTString --- Source/PythonEngine.pas | 74 +++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 48 deletions(-) diff --git a/Source/PythonEngine.pas b/Source/PythonEngine.pas index b124f59d..3af53848 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -2011,8 +2011,8 @@ TPythonEngine = class(TPythonInterface) FClients: TList; FExecModule: AnsiString; FAutoFinalize: Boolean; - FProgramName: WCharTString; - FPythonHome: WCharTString; + FProgramName: UnicodeString; + FPythonHome: UnicodeString; FPythonPath: WCharTString; FInitThreads: Boolean; FOnPathInitialization: TPathInitializationEvent; @@ -2033,8 +2033,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); @@ -2074,7 +2072,6 @@ TPythonEngine = class(TPythonInterface) function Run_CommandAsObjectWithDict(const command: AnsiString; mode: Integer; locals, globals: PPyObject; const FileName: string = ''): PPyObject; function EncodeString (const str: UnicodeString): AnsiString; {$IFDEF FPC}overload;{$ENDIF} {$IFDEF FPC} - overload; function EncodeString (const str: AnsiString): AnsiString; overload; {$ENDIF} function EncodeWindowsFilePath(const str: string): AnsiString; @@ -2157,8 +2154,8 @@ 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 PythonHome: UnicodeString read FPythonHome write SetPythonHome; + property ProgramName: UnicodeString read FProgramName write SetProgramName; property PythonPath: UnicodeString read GetPythonPath write SetPythonPath; published property AutoFinalize: Boolean read FAutoFinalize write FAutoFinalize default True; @@ -2992,6 +2989,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; //####################################################### //## ## @@ -4692,19 +4690,7 @@ procedure TPythonEngine.Initialize; 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); @@ -4788,11 +4774,18 @@ procedure TPythonEngine.Initialize; AssignPyFlags(Config); // Set programname and pythonhome if available - if Length(FProgramName) > 0 then - PyConfig_SetString(Config, @Config.program_name, PWCharT(FProgramName)); - if Length(FPythonHome) > 0 then - PyConfig_SetString(Config, @Config.program_name, PWCharT(FPythonHome)); - + if FProgramName <> '' then + PyConfig_SetString(Config, @Config.program_name, + PWCharT(StringToWCharTString(FProgramName))); + if FPythonHome <> '' then + PyConfig_SetString(Config, @Config.program_name, + PWCharT(StringToWCharTString(FPythonHome))); + // Set venv executable if available + if FVenvPythonExe <> '' then + PyConfig_SetString(Config, @Config.program_name, + PWCharT(StringToWCharTString(FVenvPythonExe))); + + PyConfig_Read(Config); // Set program arguments (sys.argv) SetProgramArgs(Config); @@ -5025,18 +5018,6 @@ procedure TPythonEngine.SetPyFlags(const Value: TPythonFlags); 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} @@ -5062,18 +5043,6 @@ 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} @@ -9916,6 +9885,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 := Str; + {$ENDIF} +end; + { TPyEngineAndGIL - Internal class for SafePythonEngine } type From 6cd46ca269fc6d8f3fbe9970ebce0e188b7fa0e5 Mon Sep 17 00:00:00 2001 From: pyscripter Date: Mon, 1 Apr 2024 18:46:23 +0300 Subject: [PATCH 03/49] Removed CheckRegistry and associated OnPathInitialization event. It was a bad way to change the python path by modifying the Windows Registry. --- Source/PythonEngine.pas | 76 ----------------------------------------- 1 file changed, 76 deletions(-) diff --git a/Source/PythonEngine.pas b/Source/PythonEngine.pas index 3af53848..13aa5d06 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -1962,7 +1962,6 @@ TPythonInterface=class(TDynamicDll) DEFAULT_DATETIME_CONVERSION_MODE = dcmToTuple; 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, pfIsolated); @@ -2015,7 +2014,6 @@ TPythonEngine = class(TPythonInterface) FPythonHome: UnicodeString; FPythonPath: WCharTString; FInitThreads: Boolean; - FOnPathInitialization: TPathInitializationEvent; FOnSysPathInit: TSysPathInitEvent; FTraceback: TPythonTraceback; FUseWindowsConsole: Boolean; @@ -2049,7 +2047,6 @@ TPythonEngine = class(TPythonInterface) function GetClients( idx : Integer ) : TEngineClient; procedure Notification(AComponent: TComponent; Operation: TOperation); override; - procedure CheckRegistry; procedure SetProgramArgs(var Config: PyConfig); procedure InitWinConsole; procedure SetUseWindowsConsole( const Value : Boolean ); @@ -2168,7 +2165,6 @@ TPythonEngine = class(TPythonInterface) 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; end; @@ -4757,14 +4753,6 @@ 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; - // Fills Config with zeros and then sets some default values if pfIsolated in FPyFlags then PyConfig_InitIsolatedConfig(Config) @@ -4872,62 +4860,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 Config: PyConfig); var I: Integer; @@ -5045,11 +4977,7 @@ function TPythonEngine.GetSequenceItem(sequence: PPyObject; procedure TPythonEngine.SetPythonHome(const PythonHome: UnicodeString); begin -{$IFDEF POSIX} - FPythonHome := UnicodeStringToUCS4String(PythonHome); -{$ELSE} FPythonHome := PythonHome; -{$ENDIF} end; procedure TPythonEngine.SetPythonPath(const Value: UnicodeString); @@ -5063,11 +4991,7 @@ procedure TPythonEngine.SetPythonPath(const Value: UnicodeString); procedure TPythonEngine.SetProgramName(const ProgramName: UnicodeString); begin -{$IFDEF POSIX} - FProgramName := UnicodeStringToUCS4String(ProgramName); -{$ELSE} FProgramName := ProgramName; -{$ENDIF} end; function TPythonEngine.EvalPyFunction(pyfunc, pyargs:PPyObject): Variant; From 603a9f638f87eda0e71ca323d40ae611eea1676d Mon Sep 17 00:00:00 2001 From: pyscripter Date: Mon, 1 Apr 2024 19:02:48 +0300 Subject: [PATCH 04/49] Removed InitThreads property and deprecated PyEval_InitThreads which does nothing since python 3.7. --- Demos/Demo11/ThSort.dfm | 1 - Demos/Demo33/ThSort.dfm | 1 - Source/PythonEngine.pas | 18 ------------------ Tests/AutoWrapEventHandlerTest.pas | 1 - Tests/NumberServicesTest.pas | 1 - Tests/VarPythTest.pas | 1 - Tests/WrapDelphiEventHandlerTest.pas | 1 - Tests/WrapDelphiTest.pas | 1 - .../Webinar II/AnalyticsDemo/MainFormSVG.dfm | 1 - 9 files changed, 26 deletions(-) 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/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/Source/PythonEngine.pas b/Source/PythonEngine.pas index 13aa5d06..34824c6c 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -1605,7 +1605,6 @@ TPythonInterface=class(TDynamicDll) 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; @@ -2013,7 +2012,6 @@ TPythonEngine = class(TPythonInterface) FProgramName: UnicodeString; FPythonHome: UnicodeString; FPythonPath: WCharTString; - FInitThreads: Boolean; FOnSysPathInit: TSysPathInitEvent; FTraceback: TPythonTraceback; FUseWindowsConsole: Boolean; @@ -2042,7 +2040,6 @@ 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; @@ -2159,7 +2156,6 @@ TPythonEngine = class(TPythonInterface) property VenvPythonExe: string read FVenvPythonExe write FVenvPythonExe; 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 RedirectIO: Boolean read FRedirectIO write FRedirectIO default True; @@ -3880,7 +3876,6 @@ procedure TPythonInterface.MapDll; 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'); @@ -4555,7 +4550,6 @@ constructor TPythonEngine.Create(AOwner: TComponent); FRedirectIO := True; FExecModule := '__main__'; FAutoFinalize := True; - FInitThreads := False; FTraceback := TPythonTraceback.Create; FUseWindowsConsole := False; FPyFlags := []; @@ -4787,8 +4781,6 @@ procedure TPythonEngine.Initialize; else FInitialized := True; InitSysPath; - if InitThreads and Assigned(PyEval_InitThreads) then - PyEval_InitThreads; if RedirectIO and Assigned(FIO) then DoRedirectIO; end; @@ -4820,16 +4812,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 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/NumberServicesTest.pas b/Tests/NumberServicesTest.pas index d1e1a3cf..ca1bdb1a 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; 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..384584fa 100644 --- a/Tests/WrapDelphiTest.pas +++ b/Tests/WrapDelphiTest.pas @@ -202,7 +202,6 @@ procedure TTestWrapDelphi.SetupFixture; PythonEngine.UseLastKnownVersion := True; PythonEngine.AutoFinalize := True; - PythonEngine.InitThreads := True; PythonEngine.PyFlags := [pfInteractive]; DelphiModule := TPythonModule.Create(nil); 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 From 5b2a7bdebdfe788d86a7f4691a37e5d5dfbeeeea Mon Sep 17 00:00:00 2001 From: pyscripter Date: Mon, 1 Apr 2024 20:11:32 +0300 Subject: [PATCH 05/49] The public PythonPath property can be used to initialize sys.path. --- Source/PythonEngine.pas | 49 +++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/Source/PythonEngine.pas b/Source/PythonEngine.pas index 34824c6c..e0d886e9 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -2011,7 +2011,7 @@ TPythonEngine = class(TPythonInterface) FAutoFinalize: Boolean; FProgramName: UnicodeString; FPythonHome: UnicodeString; - FPythonPath: WCharTString; + FPythonPath: UnicodeString; FOnSysPathInit: TSysPathInitEvent; FTraceback: TPythonTraceback; FUseWindowsConsole: Boolean; @@ -2029,8 +2029,6 @@ TPythonEngine = class(TPythonInterface) FPyDateTime_TZInfoType: PPyObject; FPyDateTime_TimeTZType: PPyObject; FPyDateTime_DateTimeTZType: PPyObject; - function GetPythonPath: UnicodeString; - procedure SetPythonPath(const Value: UnicodeString); protected procedure Initialize; @@ -2150,7 +2148,10 @@ TPythonEngine = class(TPythonInterface) property IOPythonModule: TObject read FIOPythonModule; {TPythonModule} property PythonHome: UnicodeString read FPythonHome write SetPythonHome; property ProgramName: UnicodeString read FProgramName write SetProgramName; - property PythonPath: UnicodeString read GetPythonPath write SetPythonPath; + // 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; @@ -4686,6 +4687,21 @@ procedure TPythonEngine.Initialize; FOnSysPathInit(Self, _path); end; + procedure SetPythonPath(var Config: PyConfig); + var + Paths: TArray; + I: Integer; + begin + if FPythonPath = '' then Exit; + + Paths := FPythonPath.Split([PathSep], TStringSplitOptions.ExcludeLastEmpty); + for I := 0 to Length(Paths) - 1 do + PyWideStringList_Append(Config.module_search_paths, + PWCharT(StringToWCharTString(Paths[I]))); + if Config.module_search_paths.length > 0 then + Config.module_search_paths_set := 1; + end; + function GetVal(AModule : PPyObject; AVarName : AnsiString) : PPyObject; begin Result := PyObject_GetAttrString(AModule, PAnsiChar(AVarName)); @@ -4767,10 +4783,12 @@ procedure TPythonEngine.Initialize; PyConfig_SetString(Config, @Config.program_name, PWCharT(StringToWCharTString(FVenvPythonExe))); - PyConfig_Read(Config); // Set program arguments (sys.argv) SetProgramArgs(Config); + // PythonPath + SetPythonPath(Config); + Py_InitializeFromConfig(Config); finally PyConfig_Clear(Config); @@ -4932,18 +4950,6 @@ procedure TPythonEngine.SetPyFlags(const Value: TPythonFlags); end; // of if 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 @@ -4962,15 +4968,6 @@ procedure TPythonEngine.SetPythonHome(const PythonHome: UnicodeString); FPythonHome := PythonHome; 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 FProgramName := ProgramName; From a7ea765319d077310f20a927548154906fb89f7c Mon Sep 17 00:00:00 2001 From: pyscripter Date: Mon, 1 Apr 2024 20:16:50 +0300 Subject: [PATCH 06/49] Added OnConfigInit event. --- Source/PythonEngine.pas | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Source/PythonEngine.pas b/Source/PythonEngine.pas index e0d886e9..afaa7842 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -1961,7 +1961,8 @@ TPythonInterface=class(TDynamicDll) DEFAULT_DATETIME_CONVERSION_MODE = dcmToTuple; type TEngineClient = class; - TSysPathInitEvent = procedure ( Sender : TObject; PathList : PPyObject ) of Object; + TSysPathInitEvent = procedure(Sender: TObject; PathList: PPyObject) of object; + TConfigInitEvent = procedure(Sender: TObject; var Config: PyConfig) of object; TPythonFlag = (pfDebug, pfInteractive, pfNoSite, pfOptimize, pfVerbose, pfFrozenFlag, pfIgnoreEnvironmentFlag, pfIsolated); TPythonFlags = set of TPythonFlag; @@ -2013,6 +2014,7 @@ TPythonEngine = class(TPythonInterface) FPythonHome: UnicodeString; FPythonPath: UnicodeString; FOnSysPathInit: TSysPathInitEvent; + FOnConfigInit: TConfigInitEvent; FTraceback: TPythonTraceback; FUseWindowsConsole: Boolean; FGlobalVars: PPyObject; @@ -2163,6 +2165,8 @@ TPythonEngine = class(TPythonInterface) property UseWindowsConsole: Boolean read FUseWindowsConsole write FUseWindowsConsole default False; property OnAfterInit: TNotifyEvent read FOnAfterInit write FOnAfterInit; property OnSysPathInit: TSysPathInitEvent read FOnSysPathInit write FOnSysPathInit; + property OnConfigInit: TConfigInitEvent read FOnConfigInit write FOnConfigInit; + end; @@ -4789,6 +4793,10 @@ procedure TPythonEngine.Initialize; // PythonPath SetPythonPath(Config); + // Fine tune Config + if Assigned(FOnConfigInit) then + FOnConfigInit(Self, Config); + Py_InitializeFromConfig(Config); finally PyConfig_Clear(Config); From 862db52ff979664b631e96a83045c4f725ba854d Mon Sep 17 00:00:00 2001 From: pyscripter Date: Wed, 3 Apr 2024 01:35:13 +0300 Subject: [PATCH 07/49] Fix #466 Python 3.13 support implemented and tested (preliminary since 3.13 is still in alpha) Since the PyConfig structure is python version dependent it was made opaque. --- Demos/Demo29/Unit1.dfm | 2 - Demos/Demo29/Unit1.pas | 2 +- Source/PythonEngine.pas | 259 +++++++++++++++++----------------------- Source/VarPyth.pas | 2 +- 4 files changed, 109 insertions(+), 156 deletions(-) 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/Source/PythonEngine.pas b/Source/PythonEngine.pas index afaa7842..968452a6 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -979,83 +979,68 @@ PyBufferProcs = record PPyConfig = ^PyConfig; PyConfig = record - _config_init: Integer; - isolated: Integer; - use_environment: Integer; - dev_mode: Integer; - install_signal_handlers: Integer; - use_hash_seed: Integer; - hash_seed: C_ULong; - faulthandler: Integer; - tracemalloc: Integer; - perf_profiling: Integer; - import_time: Integer; - code_debug_ranges: Integer; - show_ref_count: Integer; - dump_refs: Integer; - dump_refs_file: PWCharT; - malloc_stats: Integer; - filesystem_encoding: PWCharT; - filesystem_errors: PWCharT; - pycache_prefix: PWCharT; - parse_argv: Integer; - orig_argv: PyWideStringList; - argv: PyWideStringList; - xoptions: PyWideStringList; - warnoptions: PyWideStringList ; - site_import: Integer; - bytes_warning: Integer; - warn_default_encoding: Integer; - inspect: Integer; - interactive: Integer; - optimization_level: Integer; - parser_debug: Integer; - write_bytecode: Integer; - verbose: Integer; - quiet: Integer; - user_site_directory: Integer; - configure_c_stdio: Integer; - buffered_stdio: Integer; - stdio_encoding: PWCharT; - stdio_errors: PWCharT; + // 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; + +{$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} - legacy_windows_stdio: Integer; + {$IFDEF CPU64BITS} + ((8, 80, 88, 144, 156, 160, 164, 172, 216, 104, 232, 240, 248, 264), + (8, 80, 88, 144, 156, 160, 164, 172, 216, 104, 232, 240, 248, 264), + (8, 80, 104, 152, 168, 172, 176, 184, 232, 240, 256, 272, 280, 296), + (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} - check_hash_pycs_mode: PWCharT; - use_frozen_modules: Integer; - safe_path: Integer; - int_max_str_digits: Integer; - - (* --- Path configuration inputs ------------ *) - pathconfig_warnings: Integer; - program_name: PWCharT; - pythonpath_env: PWCharT; - home: PWCharT; - platlibdir: PWCharT; - - (* --- Path configuration outputs ----------- *) - module_search_paths_set: Integer; - module_search_paths: PyWideStringList; - stdlib_dir: PWCharT; - executable: PWCharT; - base_executable: PWCharT; - prefix: PWCharT; - base_prefix: PWCharT; - exec_prefix: PWCharT; - base_exec_prefix: PWCharT; - - (* --- Parameter only used by Py_Main() ---------- *) - kip_source_first_line: Integer; - un_command: PWCharT; - un_module: PWCharT; - un_filename: PWCharT; - - (* --- Private fields ---------------------------- *) - install_importlib: Integer; - init_main: Integer; - is_python_build: Integer; -end; - //####################################################### //## ## @@ -1583,7 +1568,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; @@ -1598,9 +1582,6 @@ 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; @@ -1760,7 +1741,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; @@ -1803,25 +1783,18 @@ 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; - 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; @@ -1837,8 +1810,8 @@ TPythonInterface=class(TDynamicDll) PyGILState_Release : procedure(gilstate : PyGILState_STATE); cdecl; // Initialization functions - PyWideStringList_Append : function(var list: PyWideStringList; item: PWCharT): PyStatus; cdecl; - PyWideStringList_Insert : function(var list: PyWideStringList; index: Py_ssize_t; item: PWCharT): PyStatus; cdecl; + 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; @@ -1848,11 +1821,6 @@ TPythonInterface=class(TDynamicDll) 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; - // 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; function Py_CompileString(str,filename:PAnsiChar;start:integer) : PPyObject; cdecl; // functions redefined in Delphi @@ -3862,7 +3830,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'); @@ -3877,7 +3844,6 @@ 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'); @@ -4040,7 +4006,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'); @@ -4083,24 +4048,15 @@ 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'); 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'); @@ -4108,8 +4064,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'); @@ -4141,11 +4095,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); @@ -4671,13 +4620,20 @@ procedure TPythonEngine.DoOpenDll(const aDllName : string); procedure TPythonEngine.AssignPyFlags(var Config: PyConfig); begin - Config.parser_debug := IfThen(pfDebug in FPyFlags, 1, 0); - Config.verbose := IfThen(pfVerbose in FPyFlags, 1, 0); - Config.interactive := IfThen(pfInteractive in FPyFlags, 1, 0); - Config.optimization_level := IfThen(pfOptimize in FPyFlags, 1, 0); - Config.site_import := IfThen(pfNoSite in FPyFlags, 0, 1); - Config.pathconfig_warnings := IfThen(pfFrozenFlag in FPyFlags, 1, 0); - Config.use_environment := IfThen(pfIgnoreEnvironmentFlag in FPyFlags, 0, 1); + 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(pfFrozenFlag in FPyFlags, 1, 0); + PInteger(PByte(@Config) + ConfigOffests[MinorVersion, TConfigFields.use_environment])^ := + IfThen(pfIgnoreEnvironmentFlag in FPyFlags, 0, 1); end; procedure TPythonEngine.Initialize; @@ -4695,15 +4651,23 @@ procedure TPythonEngine.Initialize; var Paths: TArray; I: Integer; + PWSL: PPyWideStringList; begin if FPythonPath = '' then Exit; - Paths := FPythonPath.Split([PathSep], TStringSplitOptions.ExcludeLastEmpty); + PWSL := PPyWideStringList(PByte(@Config) + ConfigOffests[MinorVersion, + TConfigFields.module_search_paths]); + Paths := FPythonPath.Split([PathSep]); for I := 0 to Length(Paths) - 1 do - PyWideStringList_Append(Config.module_search_paths, - PWCharT(StringToWCharTString(Paths[I]))); - if Config.module_search_paths.length > 0 then - Config.module_search_paths_set := 1; + 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; function GetVal(AModule : PPyObject; AVarName : AnsiString) : PPyObject; @@ -4777,14 +4741,17 @@ procedure TPythonEngine.Initialize; // Set programname and pythonhome if available if FProgramName <> '' then - PyConfig_SetString(Config, @Config.program_name, + PyConfig_SetString(Config, + PPWcharT(PByte(@Config) + ConfigOffests[MinorVersion, TConfigFields.program_name]), PWCharT(StringToWCharTString(FProgramName))); if FPythonHome <> '' then - PyConfig_SetString(Config, @Config.program_name, + PyConfig_SetString(Config, + PPWcharT(PByte(@Config) + ConfigOffests[MinorVersion, TConfigFields.home]), PWCharT(StringToWCharTString(FPythonHome))); // Set venv executable if available if FVenvPythonExe <> '' then - PyConfig_SetString(Config, @Config.program_name, + PyConfig_SetString(Config, + PPWcharT(PByte(@Config) + ConfigOffests[MinorVersion, TConfigFields.executable]), PWCharT(StringToWCharTString(FVenvPythonExe))); // Set program arguments (sys.argv) @@ -4875,7 +4842,8 @@ procedure TPythonEngine.SetProgramArgs(var Config: PyConfig); Str: WCharTString; begin - Config.parse_argv := 0; // do not parse + // do not parse further + PInteger(PByte(@Config) + ConfigOffests[MinorVersion, TConfigFields.parse_argv])^ := 0; for I := 0 to ParamCount do begin { @@ -4892,7 +4860,9 @@ procedure TPythonEngine.SetProgramArgs(var Config: PyConfig); {$ELSE} Str := TempS; {$ENDIF} - PyWideStringList_Append(Config.argv, PWCharT(Str)); + PyWideStringList_Append( + PPyWideStringList(PByte(@Config) + ConfigOffests[MinorVersion, TConfigFields.argv]), + PWCharT(Str)); end; end; @@ -4988,7 +4958,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 @@ -5200,22 +5170,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), '', mode); - Result := Assigned(PyCode); - Py_XDECREF(PyCode); - end; + PyCode := Py_CompileString(PAnsiChar(str), '', mode); + Result := Assigned(PyCode); + Py_XDECREF(PyCode); end; procedure TPythonEngine.RaiseError; @@ -5741,7 +5700,7 @@ function TPythonEngine.VariantAsPyObject( const V : Variant ) : PPyObject; raise EPythonError.Create('dcmToDatetime DatetimeConversionMode cannot be used with this version of python. Missing module datetime'); 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); @@ -7225,11 +7184,7 @@ 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]); if PyObject_TypeCheck(res, PPyTypeObject(PyExc_Exception^)) then @@ -7239,7 +7194,7 @@ procedure TError.RaiseErrorObj( const msg : AnsiString; obj : PPyObject ); raise Exception.Create('TError.RaiseErrorObj: Could not create an empty tuple'); 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]); diff --git a/Source/VarPyth.pas b/Source/VarPyth.pas index fd69085f..b16f91b8 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); From 7b485c1d612c1b516b283a19e584cf61ae65aa2d Mon Sep 17 00:00:00 2001 From: pyscripter Date: Mon, 8 Apr 2024 08:27:17 +0300 Subject: [PATCH 08/49] Fix #469 --- Source/WrapDelphi.pas | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/WrapDelphi.pas b/Source/WrapDelphi.pas index 6ec11c1f..79e626f6 100644 --- a/Source/WrapDelphi.pas +++ b/Source/WrapDelphi.pas @@ -1021,8 +1021,8 @@ 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'; From b3e051cb254ef77eecde76e13dd82c62f1586323 Mon Sep 17 00:00:00 2001 From: pyscripter Date: Mon, 8 Apr 2024 14:47:44 +0300 Subject: [PATCH 09/49] Wrap methods with parameters and/or return values PPyObjects. --- Source/WrapDelphi.pas | 40 +++++++++++++++++++++++++++++++++++----- Tests/WrapDelphiTest.pas | 22 ++++++++++++++++++++++ 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/Source/WrapDelphi.pas b/Source/WrapDelphi.pas index 79e626f6..04ecc415 100644 --- a/Source/WrapDelphi.pas +++ b/Source/WrapDelphi.pas @@ -1038,6 +1038,7 @@ implementation rs_ExpectedNil = 'In static methods Self should be nil'; rs_ExpectedInterface = 'Expected a Pascal interface'; rs_ExpectedSequence = 'Expected a python sequence'; + rsExpectedPPyObject = 'Expected a PPyObject'; 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 '+ @@ -2176,6 +2177,25 @@ function ValidateDynArray(PyValue: PPyObject; const RttiType: TRttiType; end; end; +function ValidatePPyObject(PyValue: PPyObject; const RttiType: TRttiType; + out ParamValue: TValue; out ErrMsg: string): Boolean; +var + RefType: TRttiType; +begin + Result := False; + if (RTTIType is TRttiPointerType) then + begin + RefType := TRttiPointerType(RTTIType).ReferredType; + if Assigned(RefType) and (RefType.Name = 'PyObject') then + begin + Result := True; + ParamValue := TValue.From(PyValue); + end; + end; + if not Result then + ErrMsg := rsExpectedPPyObject; +end; + function PyObjectToTValue(PyArg: PPyObject; ArgType: TRttiType; out Arg: TValue; out ErrMsg: string): Boolean; var @@ -2205,7 +2225,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 := ValidatePPyObject(PyArg, ArgType, Arg, ErrMsg); else Result := SimplePythonToValue(PyArg, ArgType.Handle, Arg, ErrMsg); end; @@ -2254,6 +2276,14 @@ function TValueToPyObject(const Value: TValue; Result := DelphiWrapper.WrapRecord(Value); tkArray, tkDynArray: Result := DynArrayToPython(Value, DelphiWrapper, ErrMsg); + tkPointer: + if Value.IsType then + Result := Value.AsType + else + begin + Result := nil; + ErrMsg := rs_ErrValueToPython; + end; else Result := SimpleValueToPython(Value, ErrMsg); end; @@ -4127,7 +4157,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 +4259,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]; @@ -4315,7 +4345,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 @@ -4399,7 +4429,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]; diff --git a/Tests/WrapDelphiTest.pas b/Tests/WrapDelphiTest.pas index 384584fa..350b0bb2 100644 --- a/Tests/WrapDelphiTest.pas +++ b/Tests/WrapDelphiTest.pas @@ -71,6 +71,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 +158,8 @@ TTestWrapDelphi = class(TObject) procedure TestIndexedProperties; [Test] procedure TestVarArgs; + [Test] + procedure TestPPyObjects; end; implementation @@ -427,6 +430,15 @@ procedure TTestWrapDelphi.TestPassVariantArray; Assert.Pass; end; +procedure TTestWrapDelphi.TestPPyObjects; +var + List: Variant; +begin + List := rtti_var.PlaceInNewList('abc'); + Assert.IsTrue(VarIsPythonList(List)); + Assert.AreEqual(List.GetItem(0), 'abc'); +end; + procedure TTestWrapDelphi.TestRecord; begin Rtti_rec.StringField := 'abcd'; @@ -615,6 +627,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; From b2512c6334e9495c0b178e1c07866220dac71c3e Mon Sep 17 00:00:00 2001 From: pyscripter Date: Sat, 13 Apr 2024 05:57:41 +0100 Subject: [PATCH 10/49] Improve the handling of python bytes and AnsiStrings --- Source/PythonEngine.pas | 19 ++++++++----------- Source/WrapDelphi.pas | 12 ++++++++++-- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/Source/PythonEngine.pas b/Source/PythonEngine.pas index 968452a6..c3e7745e 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -5414,25 +5414,22 @@ procedure TPythonEngine.RaiseError; 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; diff --git a/Source/WrapDelphi.pas b/Source/WrapDelphi.pas index 04ecc415..b2cea15e 100644 --- a/Source/WrapDelphi.pas +++ b/Source/WrapDelphi.pas @@ -2033,8 +2033,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); From bddf7c8460ee4ee084a3fffdc3bad82f37dc94e9 Mon Sep 17 00:00:00 2001 From: pyscripter Date: Fri, 17 May 2024 21:55:15 +0300 Subject: [PATCH 11/49] Fix Initialization for python versions 3.8 and 3.9. Added error handling for initialization errors. --- Source/PythonEngine.pas | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/Source/PythonEngine.pas b/Source/PythonEngine.pas index c3e7745e..fa92d7be 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -1010,8 +1010,8 @@ PyConfig = record ConfigOffests: TConfigOffsets = {$IFDEF MSWINDOWS} {$IFDEF CPU64BITS} - ((8, 80, 88, 144, 156, 160, 164, 172, 216, 104, 232, 240, 248, 264), - (8, 80, 88, 144, 156, 160, 164, 172, 216, 104, 232, 240, 248, 264), + ((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, 232, 240, 256, 272, 280, 296), (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), @@ -3036,6 +3036,8 @@ 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'; (*******************************************************) (** **) @@ -4720,6 +4722,8 @@ procedure TPythonEngine.Initialize; var i : Integer; Config: PyConfig; + Status: PyStatus; + ErrMsg: string; begin if Assigned(gPythonEngine) then raise Exception.Create('There is already one instance of TPythonEngine running' ); @@ -4764,15 +4768,30 @@ procedure TPythonEngine.Initialize; if Assigned(FOnConfigInit) then FOnConfigInit(Self, Config); - Py_InitializeFromConfig(Config); + Status := Py_InitializeFromConfig(Config); + FInitialized := Py_IsInitialized() <> 0 finally PyConfig_Clear(Config); end; - if Assigned(Py_IsInitialized) then - FInitialized := Py_IsInitialized() <> 0 - else - FInitialized := True; + if not FInitialized then + begin + if PyStatus_Exception(Status) then + ErrMsg := Format(SPyInitFailed, [string(Status.err_msg)]) + else + ErrMsg := Format(SPyInitFailed, [SPyInitFailedUnknown]); + 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; if RedirectIO and Assigned(FIO) then DoRedirectIO; From 0599a8851ee2176c0fb01e17f7b889ce7b3cfdda Mon Sep 17 00:00:00 2001 From: pyscripter Date: Sun, 19 May 2024 01:16:41 +0300 Subject: [PATCH 12/49] Corrected the definition of PyModuleDef. --- Source/PythonEngine.pas | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Source/PythonEngine.pas b/Source/PythonEngine.pas index fa92d7be..0e0969a7 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -611,6 +611,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; @@ -618,7 +627,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; From c113a4ffaef3738019c1726575908dff9a4b87b4 Mon Sep 17 00:00:00 2001 From: pyscripter Date: Sat, 25 May 2024 07:45:46 +0100 Subject: [PATCH 13/49] Check for DelphiObject = nil immediately in TPyDelphiObject.SetAttrO and TPyDelphiObject.GetAttrO --- Source/WrapDelphi.pas | 62 ++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/Source/WrapDelphi.pas b/Source/WrapDelphi.pas index b2cea15e..970bcb48 100644 --- a/Source/WrapDelphi.pas +++ b/Source/WrapDelphi.pas @@ -1026,7 +1026,8 @@ implementation 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'; @@ -1550,7 +1551,7 @@ 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]))); + PyUnicodeFromString(Format(rs_ErrAttrSet, [FRttiMember.Name, ErrMsg]))); end; { TExposedField } @@ -1646,7 +1647,7 @@ 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]))); + PyUnicodeFromString(Format(rs_ErrAttrSet, [FRttiMember.Name, ErrMsg]))); end; { TExposedIndexedProperty } @@ -3434,7 +3435,7 @@ function TPyRttiObject.SetAttrO(key, value: PPyObject): Integer; if Result <> 0 then with GetPythonEngine do PyErr_SetObject(PyExc_AttributeError^, PyUnicodeFromString( - Format(rs_ErrAttrSetr, [KeyName, ErrMsg]))); + Format(rs_ErrAttrSet, [KeyName, ErrMsg]))); end; function TPyRttiObject.SetProps(args, keywords: PPyObject): PPyObject; @@ -3543,6 +3544,7 @@ function TPyDelphiObject.GetAttrO(key: PPyObject): PPyObject; var KeyName: string; ErrMsg : string; + PyEngine: TPythonEngine; {$IFNDEF EXTENDED_RTTI} {$IFNDEF FPC} Info: PMethodInfoHeader; @@ -3554,16 +3556,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_SetObject(PyEngine.PyExc_AttributeError^, + PyEngine.PyUnicodeFromString(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 @@ -3620,17 +3630,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 @@ -3640,9 +3650,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_SetObject (PyEngine.PyExc_AttributeError^, + PyEngine.PyUnicodeFromString(Format(rs_ErrAttrGet,[KeyName, ErrMsg]))); end; function TPyDelphiObject.GetContainerAccess: TContainerAccess; @@ -3944,11 +3953,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_SetObject(PyEngine.PyExc_AttributeError^, + PyEngine.PyUnicodeFromString(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); @@ -3989,8 +4003,8 @@ function TPyDelphiObject.SetAttrO(key, value: PPyObject): Integer; Result := inherited SetAttrO(key, value); if Result <> 0 then with PyEngine do - PyErr_SetObject(PyEngine.PyExc_AttributeError^, PyUnicodeFromString( - Format(rs_ErrAttrSetr, [KeyName, ErrMsg]))); + PyErr_SetObject(PyExc_AttributeError^, PyUnicodeFromString( + Format(rs_ErrAttrSet, [KeyName, ErrMsg]))); end; procedure TPyDelphiObject.SetDelphiObject(const Value: TObject); From 7eb051e1f708f492fef50cda796bcb5000f2cad1 Mon Sep 17 00:00:00 2001 From: pyscripter Date: Sat, 25 May 2024 07:56:14 +0100 Subject: [PATCH 14/49] GenericSetAttrO raises the AttributeError on failure. No need to raise it again. --- Source/WrapDelphi.pas | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Source/WrapDelphi.pas b/Source/WrapDelphi.pas index 970bcb48..96bc881b 100644 --- a/Source/WrapDelphi.pas +++ b/Source/WrapDelphi.pas @@ -3559,7 +3559,7 @@ function TPyDelphiObject.GetAttrO(key: PPyObject): PPyObject; Result := nil; PyEngine := GetPythonEngine; - // If DelphiObject is nil Exit immediately with an error + // If DelphiObject is nil exit immediately with an error if not Assigned(DelphiObject) then begin PyEngine.PyErr_SetObject(PyEngine.PyExc_AttributeError^, @@ -3953,7 +3953,7 @@ function TPyDelphiObject.SetAttrO(key, value: PPyObject): Integer; Result := -1; PyEngine := GetPythonEngine; - // If DelphiObject is nil Exit immediately with an error + // If DelphiObject is nil exit immediately with an error if not Assigned(DelphiObject) then begin PyEngine.PyErr_SetObject(PyEngine.PyExc_AttributeError^, @@ -4001,10 +4001,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(PyExc_AttributeError^, PyUnicodeFromString( - Format(rs_ErrAttrSet, [KeyName, ErrMsg]))); end; procedure TPyDelphiObject.SetDelphiObject(const Value: TObject); From 4426ae3fdfb302cd048110d92a2dc6d1aeda99bf Mon Sep 17 00:00:00 2001 From: pyscripter Date: Tue, 28 May 2024 13:35:10 +0300 Subject: [PATCH 15/49] Changed then __owned__ docstring to reflect that it is now a read/write property. --- Source/WrapDelphi.pas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/WrapDelphi.pas b/Source/WrapDelphi.pas index 96bc881b..2ea65440 100644 --- a/Source/WrapDelphi.pas +++ b/Source/WrapDelphi.pas @@ -3835,7 +3835,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); From 38b228f7fd5c91510642f9d1ab9800965b468369 Mon Sep 17 00:00:00 2001 From: pyscripter Date: Fri, 31 May 2024 22:05:03 +0300 Subject: [PATCH 16/49] Use LoadDLLinExtensionModule instead of LoadDLL in RttiModule/uMain.pas --- Modules/DemoModule/uMain.pas | 1 - Modules/RttiModule/uMain.pas | 7 ++----- 2 files changed, 2 insertions(+), 6 deletions(-) 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); From b402379ff9cda88dbc612af8a28352e44cd32418 Mon Sep 17 00:00:00 2001 From: pyscripter Date: Thu, 20 Jun 2024 11:52:34 +0300 Subject: [PATCH 17/49] Fix backward compatibility --- Source/WrapDelphi.pas | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/WrapDelphi.pas b/Source/WrapDelphi.pas index 2ea65440..638e524a 100644 --- a/Source/WrapDelphi.pas +++ b/Source/WrapDelphi.pas @@ -553,16 +553,16 @@ TPyDelphiObject = class (TPyInterfacedObject, IFreeNotificationSubscriber) class function ExcludedExposedMembers(APythonType: TPythonType): TArray; virtual; class procedure ExposeMethods(AClass: TClass; NearestAncestorClass: TClass; APythonType: TPythonType; APyDelphiWrapper: TPyDelphiWrapper; - AExcludedMethodNames: TArray = []); + AExcludedMethodNames: TArray = nil); class procedure ExposeFields(AClass: TClass; NearestAncestorClass: TClass; APythonType: TPythonType; APyDelphiWrapper: TPyDelphiWrapper; - AExcludedFieldNames: TArray = []); + AExcludedFieldNames: TArray = nil); class procedure ExposeProperties(AClass: TClass; NearestAncestorClass: TClass; APythonType: TPythonType; APyDelphiWrapper: TPyDelphiWrapper; - AExcludedPropertyNames: TArray = []); + AExcludedPropertyNames: TArray = nil); class procedure ExposeIndexedProperties(AClass: TClass; NearestAncestorClass: TClass; APythonType: TPythonType; APyDelphiWrapper: TPyDelphiWrapper; - AExcludedPropertyNames: TArray = []); + AExcludedPropertyNames: TArray = nil); {$ENDIF EXTENDED_RTTI} public PyDelphiWrapper : TPyDelphiWrapper; From ec485c100453c8d9d2029cef9574e935c822edfe Mon Sep 17 00:00:00 2001 From: pyscripter Date: Thu, 20 Jun 2024 23:43:52 +0300 Subject: [PATCH 18/49] TPythonTread.Execute should be protected. --- Source/PythonEngine.pas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/PythonEngine.pas b/Source/PythonEngine.pas index 0e0969a7..d16b814c 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -2906,9 +2906,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 From ad3d8c7140812ea36924cb862e1598a4828aab20 Mon Sep 17 00:00:00 2001 From: pyscripter Date: Sun, 23 Jun 2024 11:59:48 +0300 Subject: [PATCH 19/49] Utf8 encoding of docstrings. See https://github.com/Embarcadero/DelphiVCL4Python/issues/84 --- Source/WrapDelphi.pas | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/WrapDelphi.pas b/Source/WrapDelphi.pas index 638e524a..0a863e3f 100644 --- a/Source/WrapDelphi.pas +++ b/Source/WrapDelphi.pas @@ -4290,7 +4290,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); @@ -4377,7 +4377,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); @@ -4460,7 +4460,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); From e7b3a0a541e04fa7ea638fd21dedc1a6255dc8cd Mon Sep 17 00:00:00 2001 From: pyscripter Date: Sun, 23 Jun 2024 18:14:08 +0300 Subject: [PATCH 20/49] Fix Screen.Realign docstring See https://github.com/Embarcadero/DelphiVCL4Python/issues/84 --- Source/vcl/WrapVclForms.pas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/vcl/WrapVclForms.pas b/Source/vcl/WrapVclForms.pas index 0a373dfa..fd0799c3 100644 --- a/Source/vcl/WrapVclForms.pas +++ b/Source/vcl/WrapVclForms.pas @@ -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.'); From 6b2cc0eb1eb48aa6d823da5c8b3353ac672fe56e Mon Sep 17 00:00:00 2001 From: pyscripter Date: Fri, 28 Jun 2024 19:52:49 +0300 Subject: [PATCH 21/49] Fix #477 --- Source/PythonEngine.pas | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/PythonEngine.pas b/Source/PythonEngine.pas index d16b814c..d2ec67df 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -4668,7 +4668,7 @@ procedure TPythonEngine.Initialize; PWSL := PPyWideStringList(PByte(@Config) + ConfigOffests[MinorVersion, TConfigFields.module_search_paths]); - Paths := FPythonPath.Split([PathSep]); + Paths := string(FPythonPath).Split([PathSep]); for I := 0 to Length(Paths) - 1 do begin if (Paths[I] = '') and (I > 0) then @@ -9781,7 +9781,7 @@ function StringToWCharTString(Str: string): WcharTString; {$IFDEF POSIX} Result := UnicodeStringToUCS4String(UnicodeString(Str)); {$ELSE} - Result := Str; + Result := WcharTString(Str); {$ENDIF} end; From 847039615dab9146239414367430b09c43987e3c Mon Sep 17 00:00:00 2001 From: pyscripter Date: Mon, 8 Jul 2024 22:41:59 +0300 Subject: [PATCH 22/49] Fix #478 --- Source/vcl/WrapVclComCtrls.pas | 50 ++++++++++++---------------------- 1 file changed, 18 insertions(+), 32 deletions(-) diff --git a/Source/vcl/WrapVclComCtrls.pas b/Source/vcl/WrapVclComCtrls.pas index 18c161e8..c7b90fac 100644 --- a/Source/vcl/WrapVclComCtrls.pas +++ b/Source/vcl/WrapVclComCtrls.pas @@ -731,7 +731,8 @@ TPyDelphiListView = class(TPyDelphiCustomListView) function CustomDrawTargetToPython(const ACustomDrawTarget: TCustomDrawTarget): PPyObject; function CustomDrawStageToPython(const ACustomDrawStage: TCustomDrawStage): PPyObject; - function CustomDrawStateToPython(const ACustomDrawState: TCustomDrawState): PPyObject; + function CustomDrawStateToPython(const ACustomDrawState: TCustomDrawState; + DelphiWrapper: TPyDelphiWrapper): PPyObject; function ItemChangeToPython(const AItemChange: TItemChange): PPyObject; function ItemStateToPython(const AItemState: TItemState): PPyObject; @@ -742,8 +743,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 @@ -780,31 +783,14 @@ function CustomDrawStageToPython(const ACustomDrawStage: TCustomDrawStage): PPyO Ord(ACustomDrawStage))); 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; - +function CustomDrawStateToPython(const ACustomDrawState: TCustomDrawState; + DelphiWrapper: TPyDelphiWrapper): PPyObject; 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 := TValueToPyObject(Value, DelphiWrapper, ErrMsg); end; function ItemChangeToPython(const AItemChange: TItemChange): PPyObject; @@ -2203,7 +2189,7 @@ procedure TTVCustomDrawItemEventHandler.DoEvent(Sender: TCustomTreeView; LPyTuple := PyTuple_New(4); PyTuple_SetItem(LPyTuple, 0, LPyObject); PyTuple_SetItem(LPyTuple, 1, LPyNode); - PyTuple_SetItem(LPyTuple, 2, CustomDrawStateToPython(State)); + PyTuple_SetItem(LPyTuple, 2, CustomDrawStateToPython(State, PyDelphiWrapper)); PyTuple_SetItem(LPyTuple, 3, LPyDefaultDraw); try LPyResult := PyObject_CallObject(Callable, LPyTuple); @@ -2306,7 +2292,7 @@ procedure TTVAdvancedCustomDrawItemEventHandler.DoEvent(Sender: TCustomTreeView; LPyTuple := PyTuple_New(6); PyTuple_SetItem(LPyTuple, 0, LPyObject); PyTuple_SetItem(LPyTuple, 1, LPyNode); - PyTuple_SetItem(LPyTuple, 2, CustomDrawStateToPython(State)); + PyTuple_SetItem(LPyTuple, 2, CustomDrawStateToPython(State, PyDelphiWrapper)); PyTuple_SetItem(LPyTuple, 3, CustomDrawStageToPython(Stage)); PyTuple_SetItem(LPyTuple, 4, LPyPaintImages); PyTuple_SetItem(LPyTuple, 5, LPyDefaultDraw); @@ -3098,7 +3084,7 @@ procedure TLVCustomDrawItemEventHandler.DoEvent(Sender: TCustomListView; LPyTuple := PyTuple_New(4); PyTuple_SetItem(LPyTuple, 0, LPyObject); PyTuple_SetItem(LPyTuple, 1, LPyItem); - PyTuple_SetItem(LPyTuple, 2, CustomDrawStateToPython(State)); + PyTuple_SetItem(LPyTuple, 2, CustomDrawStateToPython(State, PyDelphiWrapper)); PyTuple_SetItem(LPyTuple, 3, LPyDefaultDraw); try LPyResult := PyObject_CallObject(Callable, LPyTuple); @@ -3150,7 +3136,7 @@ procedure TLVCustomDrawSubItemEventHandler.DoEvent(Sender: TCustomListView; PyTuple_SetItem(LPyTuple, 0, LPyObject); PyTuple_SetItem(LPyTuple, 1, LPyItem); PyTuple_SetItem(LPyTuple, 2, PyLong_FromLong(SubItem)); - PyTuple_SetItem(LPyTuple, 3, CustomDrawStateToPython(State)); + PyTuple_SetItem(LPyTuple, 3, CustomDrawStateToPython(State, PyDelphiWrapper)); PyTuple_SetItem(LPyTuple, 4, LPyDefaultDraw); try LPyResult := PyObject_CallObject(Callable, LPyTuple); @@ -3251,7 +3237,7 @@ procedure TLVAdvancedCustomDrawItemEventHandler.DoEvent(Sender: TCustomListView; LPyTuple := PyTuple_New(5); PyTuple_SetItem(LPyTuple, 0, LPyObject); PyTuple_SetItem(LPyTuple, 1, LPyItem); - PyTuple_SetItem(LPyTuple, 2, CustomDrawStateToPython(State)); + PyTuple_SetItem(LPyTuple, 2, CustomDrawStateToPython(State, PyDelphiWrapper)); PyTuple_SetItem(LPyTuple, 3, CustomDrawStageToPython(Stage)); PyTuple_SetItem(LPyTuple, 4, LPyDefaultDraw); try @@ -3304,7 +3290,7 @@ procedure TLVAdvancedCustomDrawSubItemEventHandler.DoEvent( PyTuple_SetItem(LPyTuple, 0, LPyObject); PyTuple_SetItem(LPyTuple, 1, LPyItem); PyTuple_SetItem(LPyTuple, 2, PyLong_FromLong(SubItem)); - PyTuple_SetItem(LPyTuple, 3, CustomDrawStateToPython(State)); + PyTuple_SetItem(LPyTuple, 3, CustomDrawStateToPython(State, PyDelphiWrapper)); PyTuple_SetItem(LPyTuple, 4, CustomDrawStageToPython(Stage)); PyTuple_SetItem(LPyTuple, 5, LPyDefaultDraw); try From fc96036b96f6504f07c9be917f28ad14c6cc5fb4 Mon Sep 17 00:00:00 2001 From: pyscripter Date: Mon, 8 Jul 2024 22:56:26 +0300 Subject: [PATCH 23/49] Improve previous commit. --- Source/WrapDelphi.pas | 2 ++ Source/vcl/WrapVclComCtrls.pas | 20 +++++++++----------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Source/WrapDelphi.pas b/Source/WrapDelphi.pas index 0a863e3f..70b5b837 100644 --- a/Source/WrapDelphi.pas +++ b/Source/WrapDelphi.pas @@ -991,6 +991,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; diff --git a/Source/vcl/WrapVclComCtrls.pas b/Source/vcl/WrapVclComCtrls.pas index c7b90fac..aff247eb 100644 --- a/Source/vcl/WrapVclComCtrls.pas +++ b/Source/vcl/WrapVclComCtrls.pas @@ -731,8 +731,7 @@ TPyDelphiListView = class(TPyDelphiCustomListView) function CustomDrawTargetToPython(const ACustomDrawTarget: TCustomDrawTarget): PPyObject; function CustomDrawStageToPython(const ACustomDrawStage: TCustomDrawStage): PPyObject; - function CustomDrawStateToPython(const ACustomDrawState: TCustomDrawState; - DelphiWrapper: TPyDelphiWrapper): PPyObject; + function CustomDrawStateToPython(const ACustomDrawState: TCustomDrawState): PPyObject; function ItemChangeToPython(const AItemChange: TItemChange): PPyObject; function ItemStateToPython(const AItemState: TItemState): PPyObject; @@ -783,14 +782,13 @@ function CustomDrawStageToPython(const ACustomDrawStage: TCustomDrawStage): PPyO Ord(ACustomDrawStage))); end; -function CustomDrawStateToPython(const ACustomDrawState: TCustomDrawState; - DelphiWrapper: TPyDelphiWrapper): PPyObject; +function CustomDrawStateToPython(const ACustomDrawState: TCustomDrawState): PPyObject; var ErrMsg: string; Value: TValue; begin Value := TValue.From(ACustomDrawState); - Result := TValueToPyObject(Value, DelphiWrapper, ErrMsg); + Result := SimpleValueToPython(Value, ErrMsg); end; function ItemChangeToPython(const AItemChange: TItemChange): PPyObject; @@ -2189,7 +2187,7 @@ procedure TTVCustomDrawItemEventHandler.DoEvent(Sender: TCustomTreeView; LPyTuple := PyTuple_New(4); PyTuple_SetItem(LPyTuple, 0, LPyObject); PyTuple_SetItem(LPyTuple, 1, LPyNode); - PyTuple_SetItem(LPyTuple, 2, CustomDrawStateToPython(State, PyDelphiWrapper)); + PyTuple_SetItem(LPyTuple, 2, CustomDrawStateToPython(State)); PyTuple_SetItem(LPyTuple, 3, LPyDefaultDraw); try LPyResult := PyObject_CallObject(Callable, LPyTuple); @@ -2292,7 +2290,7 @@ procedure TTVAdvancedCustomDrawItemEventHandler.DoEvent(Sender: TCustomTreeView; LPyTuple := PyTuple_New(6); PyTuple_SetItem(LPyTuple, 0, LPyObject); PyTuple_SetItem(LPyTuple, 1, LPyNode); - PyTuple_SetItem(LPyTuple, 2, CustomDrawStateToPython(State, PyDelphiWrapper)); + PyTuple_SetItem(LPyTuple, 2, CustomDrawStateToPython(State)); PyTuple_SetItem(LPyTuple, 3, CustomDrawStageToPython(Stage)); PyTuple_SetItem(LPyTuple, 4, LPyPaintImages); PyTuple_SetItem(LPyTuple, 5, LPyDefaultDraw); @@ -3084,7 +3082,7 @@ procedure TLVCustomDrawItemEventHandler.DoEvent(Sender: TCustomListView; LPyTuple := PyTuple_New(4); PyTuple_SetItem(LPyTuple, 0, LPyObject); PyTuple_SetItem(LPyTuple, 1, LPyItem); - PyTuple_SetItem(LPyTuple, 2, CustomDrawStateToPython(State, PyDelphiWrapper)); + PyTuple_SetItem(LPyTuple, 2, CustomDrawStateToPython(State)); PyTuple_SetItem(LPyTuple, 3, LPyDefaultDraw); try LPyResult := PyObject_CallObject(Callable, LPyTuple); @@ -3136,7 +3134,7 @@ procedure TLVCustomDrawSubItemEventHandler.DoEvent(Sender: TCustomListView; PyTuple_SetItem(LPyTuple, 0, LPyObject); PyTuple_SetItem(LPyTuple, 1, LPyItem); PyTuple_SetItem(LPyTuple, 2, PyLong_FromLong(SubItem)); - PyTuple_SetItem(LPyTuple, 3, CustomDrawStateToPython(State, PyDelphiWrapper)); + PyTuple_SetItem(LPyTuple, 3, CustomDrawStateToPython(State)); PyTuple_SetItem(LPyTuple, 4, LPyDefaultDraw); try LPyResult := PyObject_CallObject(Callable, LPyTuple); @@ -3237,7 +3235,7 @@ procedure TLVAdvancedCustomDrawItemEventHandler.DoEvent(Sender: TCustomListView; LPyTuple := PyTuple_New(5); PyTuple_SetItem(LPyTuple, 0, LPyObject); PyTuple_SetItem(LPyTuple, 1, LPyItem); - PyTuple_SetItem(LPyTuple, 2, CustomDrawStateToPython(State, PyDelphiWrapper)); + PyTuple_SetItem(LPyTuple, 2, CustomDrawStateToPython(State)); PyTuple_SetItem(LPyTuple, 3, CustomDrawStageToPython(Stage)); PyTuple_SetItem(LPyTuple, 4, LPyDefaultDraw); try @@ -3290,7 +3288,7 @@ procedure TLVAdvancedCustomDrawSubItemEventHandler.DoEvent( PyTuple_SetItem(LPyTuple, 0, LPyObject); PyTuple_SetItem(LPyTuple, 1, LPyItem); PyTuple_SetItem(LPyTuple, 2, PyLong_FromLong(SubItem)); - PyTuple_SetItem(LPyTuple, 3, CustomDrawStateToPython(State, PyDelphiWrapper)); + PyTuple_SetItem(LPyTuple, 3, CustomDrawStateToPython(State)); PyTuple_SetItem(LPyTuple, 4, CustomDrawStageToPython(Stage)); PyTuple_SetItem(LPyTuple, 5, LPyDefaultDraw); try From b2f9224922f6fbbc3360410827466556c13a3788 Mon Sep 17 00:00:00 2001 From: pyscripter Date: Fri, 12 Jul 2024 14:13:12 +0300 Subject: [PATCH 24/49] Added FPC Demo35 --- Demos/FPC/Demo35/project1.lpi | 71 ++++++++++++ Demos/FPC/Demo35/project1.lpr | 144 +++++++++++++++++++++++++ Demos/FPC/Demo35/stopwatch.pas | 191 +++++++++++++++++++++++++++++++++ 3 files changed, 406 insertions(+) create mode 100644 Demos/FPC/Demo35/project1.lpi create mode 100644 Demos/FPC/Demo35/project1.lpr create mode 100644 Demos/FPC/Demo35/stopwatch.pas 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..0856f9f4 --- /dev/null +++ b/Demos/FPC/Demo35/project1.lpr @@ -0,0 +1,144 @@ +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; + TIntArray = array[0..N - 1] of Integer; + + { 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. From a90a14f1b29aee7c7540abb6fccf49418ad40107 Mon Sep 17 00:00:00 2001 From: pyscripter <pyscripter@gmail.com> Date: Fri, 12 Jul 2024 14:44:05 +0300 Subject: [PATCH 25/49] Fix for Linux and other non-Windows platforms. --- Demos/FPC/Demo35/project1.lpr | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Demos/FPC/Demo35/project1.lpr b/Demos/FPC/Demo35/project1.lpr index 0856f9f4..bb83f928 100644 --- a/Demos/FPC/Demo35/project1.lpr +++ b/Demos/FPC/Demo35/project1.lpr @@ -36,9 +36,13 @@ procedure DestroyEngine; N = 100000; type - PIntArray = ^TIntArray; - TIntArray = array[0..N - 1] of Integer; - + PIntArray = ^TIntArray; + {$IFDEF MSWINDOWS} + TIntArray = array[0..N - 1] of Integer; + {$ELSE} + TIntArray = array[0..N - 1] of NativeInt; + {$ENDIF} + { TBufferProtocol } TBufferProtocol = class(TCustomApplication) From b8d57195402040a7825fa81b0673537569896408 Mon Sep 17 00:00:00 2001 From: pyscripter <pyscripter@gmail.com> Date: Sat, 13 Jul 2024 04:33:26 +0300 Subject: [PATCH 26/49] _PyInterpreterConfig_INIT is now a variable. --- Source/PythonEngine.pas | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/PythonEngine.pas b/Source/PythonEngine.pas index d2ec67df..83c924f8 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -1068,7 +1068,7 @@ PyConfig = record PyInterpreterConfig_SHARED_GIL = 1; PyInterpreterConfig_OWN_GIL = 2; - type +type PPyInterpreterConfig = ^PyInterpreterConfig; PyInterpreterConfig = {$IFDEF CPUX86}packed{$ENDIF} record use_main_obmalloc: Integer; @@ -1080,7 +1080,7 @@ PyConfig = record gil: Integer; end; -const +var _PyInterpreterConfig_INIT: PyInterpreterConfig = ( use_main_obmalloc: 0; allow_fork: 0; @@ -9305,7 +9305,7 @@ procedure TPythonThread.Execute; finally PyGILState_Release(gilstate); end; - end else {fThreadExecMode} + end else begin gilstate := PyGILState_Ensure(); global_state := PyThreadState_Get; @@ -9328,8 +9328,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('Could not create a new thread state'); + end; end; end; From e57e2feffb926d624834b67955517c6b5e36a52c Mon Sep 17 00:00:00 2001 From: pyscripter <pyscripter@gmail.com> Date: Thu, 18 Jul 2024 20:52:29 +0300 Subject: [PATCH 27/49] Fix #481 --- Source/PythonEngine.pas | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/PythonEngine.pas b/Source/PythonEngine.pas index 83c924f8..90cfca3b 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -8373,7 +8373,6 @@ function TPythonType.NewSubtypeInst( aType: PPyTypeObject; args, kwds : PPyObje begin Engine.Py_DECREF(Result); Result := nil; - obj.Free; end; end; end; From a650ee79b838d9d0574af9a677350d4fb8d0649c Mon Sep 17 00:00:00 2001 From: pyscripter <pyscripter@gmail.com> Date: Wed, 18 Sep 2024 01:40:44 +0300 Subject: [PATCH 28/49] #483 --- Source/PythonEngine.pas | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Source/PythonEngine.pas b/Source/PythonEngine.pas index 90cfca3b..50c5f8a6 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -3021,9 +3021,8 @@ function CleanString(const s : UnicodeString; AppendLF : Boolean = True) : Unico implementation uses -{$IFDEF FPC} StrUtils, -{$ELSE} +{$IFNDEF FPC} AnsiStrings, {$ENDIF} {$IFDEF MSWINDOWS} @@ -4660,7 +4659,7 @@ procedure TPythonEngine.Initialize; procedure SetPythonPath(var Config: PyConfig); var - Paths: TArray<string>; + Paths: TStringDynArray; I: Integer; PWSL: PPyWideStringList; begin @@ -4668,7 +4667,7 @@ procedure TPythonEngine.Initialize; PWSL := PPyWideStringList(PByte(@Config) + ConfigOffests[MinorVersion, TConfigFields.module_search_paths]); - Paths := string(FPythonPath).Split([PathSep]); + Paths := SplitString(string(FPythonPath), PathSep); for I := 0 to Length(Paths) - 1 do begin if (Paths[I] = '') and (I > 0) then From c32596f9b8bc9cc0fb80f4c4a44657fc2c2049b3 Mon Sep 17 00:00:00 2001 From: pyscripter <pyscripter@gmail.com> Date: Mon, 23 Sep 2024 17:46:42 +0300 Subject: [PATCH 29/49] Expose EncodeString (const str: AnsiString) to Delphi and correct its implementation. --- Source/PythonEngine.pas | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/Source/PythonEngine.pas b/Source/PythonEngine.pas index 50c5f8a6..13604e26 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -2041,10 +2041,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} - 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; @@ -5538,17 +5536,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} From 311860e766683435bee7147ad7f3d5972716c0ab Mon Sep 17 00:00:00 2001 From: pyscripter <pyscripter@gmail.com> Date: Mon, 23 Sep 2024 18:43:17 +0300 Subject: [PATCH 30/49] Fix #485 --- Source/PythonEngine.pas | 7 +- Source/WrapDelphi.pas | 137 ++++++++++++++++++++-------------------- 2 files changed, 71 insertions(+), 73 deletions(-) diff --git a/Source/PythonEngine.pas b/Source/PythonEngine.pas index 13604e26..a0a72e0d 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -7234,10 +7234,11 @@ procedure TError.RaiseErrorObj( const msg : AnsiString; obj : PPyObject ); end else raise Exception.Create('TError.RaiseErrorObj: I didn''t get an instance' ); - PyErr_SetObject( Error, res ); + PyErr_SetObject(Error, res); + Py_XDECREF(res); end else - PyErr_SetObject( Error, obj ); + PyErr_SetObject(Error, obj); end; function TError.Owner : TErrors; @@ -7735,7 +7736,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; diff --git a/Source/WrapDelphi.pas b/Source/WrapDelphi.pas index 70b5b837..67d0535c 100644 --- a/Source/WrapDelphi.pas +++ b/Source/WrapDelphi.pas @@ -1527,8 +1527,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; @@ -1552,8 +1552,8 @@ function TExposedGetSet.SetterWrapper(AObj, AValue: PPyObject; AContext: Pointer if Result <> 0 then with GetPythonEngine do - PyErr_SetObject (PyExc_AttributeError^, - PyUnicodeFromString(Format(rs_ErrAttrSet, [FRttiMember.Name, ErrMsg]))); + PyErr_SetString (PyExc_AttributeError^, + PAnsiChar(EncodeString(Format(rs_ErrAttrSet, [FRttiMember.Name, ErrMsg])))); end; { TExposedField } @@ -1648,8 +1648,8 @@ function TExposedEvent.SetterWrapper(AObj, AValue: PPyObject; AContext: Pointer) if Result <> 0 then with GetPythonEngine do - PyErr_SetObject (PyExc_AttributeError^, - PyUnicodeFromString(Format(rs_ErrAttrSet, [FRttiMember.Name, ErrMsg]))); + PyErr_SetString (PyExc_AttributeError^, + PAnsiChar(EncodeString(Format(rs_ErrAttrSet, [FRttiMember.Name, ErrMsg])))); end; { TExposedIndexedProperty } @@ -1745,7 +1745,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; @@ -1869,8 +1869,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); @@ -1904,9 +1904,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; @@ -2354,8 +2353,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; @@ -2372,8 +2371,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; @@ -2388,8 +2387,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; @@ -2410,8 +2409,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; @@ -2423,8 +2422,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; @@ -2436,9 +2435,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; @@ -2461,8 +2460,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 @@ -2474,8 +2473,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; @@ -2815,8 +2814,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; @@ -2833,8 +2832,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; @@ -2928,8 +2927,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; @@ -2959,8 +2958,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; @@ -3189,8 +3188,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; @@ -3405,8 +3404,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); @@ -3436,8 +3435,8 @@ function TPyRttiObject.SetAttrO(key, value: PPyObject): Integer; if Result <> 0 then with GetPythonEngine do - PyErr_SetObject(PyExc_AttributeError^, PyUnicodeFromString( - Format(rs_ErrAttrSet, [KeyName, ErrMsg]))); + PyErr_SetString(PyExc_AttributeError^, PAnsiChar(EncodeString( + Format(rs_ErrAttrSet, [KeyName, ErrMsg])))); end; function TPyRttiObject.SetProps(args, keywords: PPyObject): PPyObject; @@ -3564,8 +3563,8 @@ function TPyDelphiObject.GetAttrO(key: PPyObject): PPyObject; // If DelphiObject is nil exit immediately with an error if not Assigned(DelphiObject) then begin - PyEngine.PyErr_SetObject(PyEngine.PyExc_AttributeError^, - PyEngine.PyUnicodeFromString(rs_ErrObjectDestroyed)); + PyEngine.PyErr_SetString(PyEngine.PyExc_AttributeError^, + PAnsiChar(PyEngine.EncodeString(rs_ErrObjectDestroyed))); Exit; end; @@ -3652,8 +3651,8 @@ function TPyDelphiObject.GetAttrO(key: PPyObject): PPyObject; end; {$ENDIF} if not Assigned(Result) then - PyEngine.PyErr_SetObject (PyEngine.PyExc_AttributeError^, - PyEngine.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; @@ -3816,9 +3815,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; @@ -3958,8 +3957,8 @@ function TPyDelphiObject.SetAttrO(key, value: PPyObject): Integer; // If DelphiObject is nil exit immediately with an error if not Assigned(DelphiObject) then begin - PyEngine.PyErr_SetObject(PyEngine.PyExc_AttributeError^, - PyEngine.PyUnicodeFromString(rs_ErrObjectDestroyed)); + PyEngine.PyErr_SetString(PyEngine.PyExc_AttributeError^, + PAnsiChar(PyEngine.EncodeString(rs_ErrObjectDestroyed))); Exit; end; @@ -4528,7 +4527,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; @@ -4595,8 +4594,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; @@ -4626,8 +4625,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; @@ -4658,8 +4657,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 @@ -4682,8 +4681,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 @@ -4749,9 +4748,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; @@ -5227,9 +5226,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; @@ -5244,9 +5242,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; From 01b73d4b5a99430574de41151b627b41ef6f2302 Mon Sep 17 00:00:00 2001 From: pyscripter <pyscripter@gmail.com> Date: Mon, 23 Sep 2024 20:04:43 +0300 Subject: [PATCH 31/49] PyErr_SetString should be called with utf8 encoded strings --- Demos/Demo07/Unit1.dfm | 3 --- Demos/Demo07/Unit1.pas | 8 ++++---- Source/PythonAction.pas | 14 +++++++------- Source/PythonEngine.pas | 14 +++++++------- Source/WrapDelphiClasses.pas | 14 +++++++------- Source/WrapDelphiTypes.pas | 12 ++++++------ Source/WrapFireDAC.pas | 20 ++++++++++---------- Source/fmx/WrapFmxForms.pas | 2 +- Source/fmx/WrapFmxTypes.pas | 8 ++++---- Source/vcl/WrapVclForms.pas | 2 +- Source/vcl/WrapVclGraphics.pas | 14 +++++++------- Tests/FMX/Android/NumberServicesTest.pas | 2 +- Tests/NumberServicesTest.pas | 2 +- 13 files changed, 56 insertions(+), 59 deletions(-) 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..67e672b0 100644 --- a/Demos/Demo07/Unit1.pas +++ b/Demos/Demo07/Unit1.pas @@ -205,7 +205,7 @@ function PyPoint_getattr(obj : PPyObject; key : PAnsiChar) : PPyObject; cdecl; // 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])))); + PyErr_SetString (PyExc_AttributeError^, PAnsiChar(Utf8Encode(Format('Unknown attribute "%s"',[key])))); end; end; end; @@ -226,7 +226,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 +235,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/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 a0a72e0d..c08ea1dc 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -2419,8 +2419,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 @@ -7183,14 +7183,14 @@ procedure TError.BuildError( const ModuleName : AnsiString ); raise Exception.CreateFmt( 'Could not create error "%s"', [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; @@ -7698,8 +7698,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; 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/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/WrapVclForms.pas b/Source/vcl/WrapVclForms.pas index fd0799c3..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; 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/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 ca1bdb1a..0b100950 100644 --- a/Tests/NumberServicesTest.pas +++ b/Tests/NumberServicesTest.pas @@ -291,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; From 70bc12a9801be2101c6ea080220de5193e32cdbf Mon Sep 17 00:00:00 2001 From: pyscripter <pyscripter@gmail.com> Date: Mon, 23 Sep 2024 20:39:50 +0300 Subject: [PATCH 32/49] Fix reference counting error in demos 6 and 7. --- Demos/Demo06/Unit1.dfm | 3 --- Demos/Demo06/Unit1.pas | 13 ++++++++++--- Demos/Demo07/Unit1.pas | 13 ++++++++++--- 3 files changed, 20 insertions(+), 9 deletions(-) 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..e038b4fa 100644 --- a/Demos/Demo06/Unit1.pas +++ b/Demos/Demo06/Unit1.pas @@ -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.pas b/Demos/Demo07/Unit1.pas index 67e672b0..f33b8817 100644 --- a/Demos/Demo07/Unit1.pas +++ b/Demos/Demo07/Unit1.pas @@ -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(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; From 53c24628f24f460e1805d7fd33f37cca5a1d45d6 Mon Sep 17 00:00:00 2001 From: pyscripter <pyscripter@gmail.com> Date: Sun, 29 Sep 2024 00:54:56 -0400 Subject: [PATCH 33/49] Fix issue reported in https://en.delphipraxis.net/topic/12281-python4delphi-crash-immediately-after-launch --- Demos/Demo36/ParallelPython.dpr | 1 + 1 file changed, 1 insertion(+) 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 From d1951c18d614cc8931cc7b9edda019bcb7cb13ad Mon Sep 17 00:00:00 2001 From: pyscripter <pyscripter@gmail.com> Date: Tue, 1 Oct 2024 00:24:22 -0400 Subject: [PATCH 34/49] TPyClassWrapper methods declared private. Documentation improved. --- Source/WrapDelphi.pas | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Source/WrapDelphi.pas b/Source/WrapDelphi.pas index 67d0535c..bed385ea 100644 --- a/Source/WrapDelphi.pas +++ b/Source/WrapDelphi.pas @@ -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 From 6afe08111fe099609a445e8b6346e0c03bdf9c18 Mon Sep 17 00:00:00 2001 From: pyscripter <pyscripter@gmail.com> Date: Sun, 8 Dec 2024 23:38:28 +0200 Subject: [PATCH 35/49] Support for Python 3.14. Implemented PEP741 initialization. --- Source/PythonEngine.pas | 427 +++++++++++++++++++++++++++------------- 1 file changed, 292 insertions(+), 135 deletions(-) diff --git a/Source/PythonEngine.pas b/Source/PythonEngine.pas index c08ea1dc..93cfa6d2 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -73,47 +73,51 @@ TPythonVersionProp = record end; const {$IFDEF MSWINDOWS} - PYTHON_KNOWN_VERSIONS: array[1..6] of TPythonVersionProp = + PYTHON_KNOWN_VERSIONS: array[1..7] of TPythonVersionProp = ( (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: 'python313.dll'; RegVersion: '3.13'; 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..6] of TPythonVersionProp = + PYTHON_KNOWN_VERSIONS: array[1..7] of TPythonVersionProp = ( (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.13.so'; RegVersion: '3.13'; 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..6] of TPythonVersionProp = + PYTHON_KNOWN_VERSIONS: array[1..7] of TPythonVersionProp = ( (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.13.dylib'; RegVersion: '3.13'; 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[1..6] of TPythonVersionProp = + PYTHON_KNOWN_VERSIONS: array[1..7] of TPythonVersionProp = ( (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.13.so'; RegVersion: '3.13'; 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} @@ -176,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 { @@ -994,6 +998,9 @@ PyConfig = record Filler: array [0..1000] of Byte; end; + // Opaque structure PEP 741 + PPyInitConfig = Pointer; + {$SCOPEDENUMS ON} TConfigFields = ( use_environment, @@ -1796,8 +1803,9 @@ TPythonInterface=class(TDynamicDll) Py_GetPrefix : function : PWCharT; cdecl; Py_GetProgramName : function : PWCharT; 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_IsInitialized : function : integer; cdecl; Py_GetProgramFullPath : function : PAnsiChar; cdecl; @@ -1818,7 +1826,7 @@ TPythonInterface=class(TDynamicDll) PyGILState_Ensure : function() : PyGILstate_STATE; cdecl; PyGILState_Release : procedure(gilstate : PyGILState_STATE); cdecl; - // Initialization functions + // 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; @@ -1830,6 +1838,17 @@ TPythonInterface=class(TDynamicDll) 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 @@ -1939,7 +1958,8 @@ TPythonInterface=class(TDynamicDll) type TEngineClient = class; TSysPathInitEvent = procedure(Sender: TObject; PathList: PPyObject) of object; - TConfigInitEvent = procedure(Sender: TObject; var Config: PyConfig) of object; + // Config will be either PPyConfig if version < 3.14 or PPyInitConfig + TConfigInitEvent = procedure(Sender: TObject; Config: Pointer) of object; TPythonFlag = (pfDebug, pfInteractive, pfNoSite, pfOptimize, pfVerbose, pfFrozenFlag, pfIgnoreEnvironmentFlag, pfIsolated); TPythonFlags = set of TPythonFlag; @@ -2021,14 +2041,12 @@ TPythonEngine = class(TPythonInterface) function GetClients( idx : Integer ) : TEngineClient; procedure Notification(AComponent: TComponent; Operation: TOperation); override; - procedure SetProgramArgs(var Config: PyConfig); 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(var Config: PyConfig); public // Constructors & Destructors @@ -4060,11 +4078,10 @@ procedure TPythonInterface.MapDll; Py_GetPrefix := Import('Py_GetPrefix'); Py_GetProgramName := Import('Py_GetProgramName'); - PyErr_NewException := Import('PyErr_NewException'); - try - PyMem_Malloc := Import ('PyMem_Malloc'); - except - end; + PyErr_NewException := Import('PyErr_NewException'); + PyMem_Malloc := Import ('PyMem_Malloc'); + PyMem_Free := Import ('PyMem_Free'); + Py_IsInitialized := Import('Py_IsInitialized'); Py_GetProgramFullPath := Import('Py_GetProgramFullPath'); Py_GetBuildInfo := Import('Py_GetBuildInfo'); @@ -4096,6 +4113,20 @@ procedure TPythonInterface.MapDll; 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; @@ -4626,56 +4657,253 @@ procedure TPythonEngine.DoOpenDll(const aDllName : string); end; end; -procedure TPythonEngine.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(pfFrozenFlag in FPyFlags, 1, 0); - PInteger(PByte(@Config) + ConfigOffests[MinorVersion, TConfigFields.use_environment])^ := - IfThen(pfIgnoreEnvironmentFlag in FPyFlags, 0, 1); -end; - procedure TPythonEngine.Initialize; - procedure InitSysPath; + procedure ConfgigPEP587(var ErrMsg: string); + // Initialize according to PEP587 available since python 3.8 + + 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(pfFrozenFlag in FPyFlags, 1, 0); + PInteger(PByte(@Config) + ConfigOffests[MinorVersion, TConfigFields.use_environment])^ := + IfThen(pfIgnoreEnvironmentFlag 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 - _path : PPyObject; + Config: PyConfig; + Status: PyStatus; begin - _path := PySys_GetObject('path'); - if Assigned(FOnSysPathInit) then - FOnSysPathInit(Self, _path); + // Fills Config with zeros and then sets some default values + if pfIsolated in FPyFlags then + PyConfig_InitIsolatedConfig(Config) + else + 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 FVenvPythonExe <> '' then + PyConfig_SetString(Config, + PPWcharT(PByte(@Config) + ConfigOffests[MinorVersion, TConfigFields.executable]), + PWCharT(StringToWCharTString(FVenvPythonExe))); + + // 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; - procedure SetPythonPath(var Config: PyConfig); + procedure ConfgigPEP741(var ErrMsg: string); + // Initialize according to PEP587 available since python 3.8 + + procedure AssignPyFlags(Config: PPyInitConfig); + begin + 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, 'user_site_directory', IfThen(pfNoSite in FPyFlags, 0, 1)); + PyInitConfig_SetInt(Config, 'pathconfig_warnings', IfThen(pfFrozenFlag in FPyFlags, 1, 0)); + PyInitConfig_SetInt(Config, 'use_environment', IfThen(pfIgnoreEnvironmentFlag 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 - Paths: TStringDynArray; - I: Integer; - PWSL: PPyWideStringList; + Config: PPyInitConfig; + PErrMsg: PAnsiChar; begin - if FPythonPath = '' then Exit; + Config := PyInitConfig_Create; + try + PyInitConfig_SetInt(Config, 'isolated', IfThen(pfIsolated in FPyFlags, 1, 0)); - 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]))); + 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 FVenvPythonExe <> '' then + PyInitConfig_SetStr(Config, 'executable', PAnsiChar(EncodeString(FPythonHome))); + + // 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; - if PWSL^.length > 0 then - PInteger(PByte(@Config) + ConfigOffests[MinorVersion, - TConfigFields.module_search_paths_set])^ := 1; + procedure InitSysPath; + var + _path : PPyObject; + begin + _path := PySys_GetObject('path'); + if Assigned(FOnSysPathInit) then + FOnSysPathInit(Self, _path); end; function GetVal(AModule : PPyObject; AVarName : AnsiString) : PPyObject; @@ -4727,8 +4955,6 @@ procedure TPythonEngine.Initialize; var i : Integer; - Config: PyConfig; - Status: PyStatus; ErrMsg: string; begin if Assigned(gPythonEngine) then @@ -4741,51 +4967,13 @@ procedure TPythonEngine.Initialize; FInitialized := True else begin - // Fills Config with zeros and then sets some default values - if pfIsolated in FPyFlags then - PyConfig_InitIsolatedConfig(Config) + if (MajorVersion > 3) or (MinorVersion >= 14) then + ConfgigPEP741(ErrMsg) else - 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 FVenvPythonExe <> '' then - PyConfig_SetString(Config, - PPWcharT(PByte(@Config) + ConfigOffests[MinorVersion, TConfigFields.executable]), - PWCharT(StringToWCharTString(FVenvPythonExe))); - - // 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 - finally - PyConfig_Clear(Config); - end; + ConfgigPEP587(ErrMsg); if not FInitialized then begin - if PyStatus_Exception(Status) then - ErrMsg := Format(SPyInitFailed, [string(Status.err_msg)]) - else - ErrMsg := Format(SPyInitFailed, [SPyInitFailedUnknown]); if FatalMsgDlg then {$IFDEF MSWINDOWS} MessageBox( GetActiveWindow, PChar(ErrMsg), 'Error', MB_TASKMODAL or MB_ICONSTOP ); @@ -4860,37 +5048,6 @@ procedure TPythonEngine.Notification( AComponent: TComponent; IO := nil end; -procedure TPythonEngine.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 TPythonEngine.InitWinConsole; begin {$IFDEF MSWINDOWS} From f9ab2dca4978778ca1277ff6265556f579268b4c Mon Sep 17 00:00:00 2001 From: pyscripter <pyscripter@gmail.com> Date: Tue, 10 Dec 2024 02:00:45 +0200 Subject: [PATCH 36/49] Merged downstream from embarcadero/python4Delphi --- Packages/Delphi/Delphi 10.4+/Python.dproj | 25 +- Packages/Delphi/Delphi 10.4+/PythonFmx.dproj | 26 +- .../Delphi/Delphi 10.4+/PythonFmxLinux.dpk | 63 -- .../Delphi/Delphi 10.4+/PythonFmxLinux.dproj | 968 ------------------ Packages/Delphi/Delphi 10.4+/PythonVcl.dproj | 8 +- Packages/Delphi/Delphi 10.4+/dclPython.dproj | 4 +- .../Delphi/Delphi 10.4+/dclPythonFmx.dproj | 4 +- .../Delphi/Delphi 10.4+/dclPythonVcl.dproj | 4 +- .../Delphi/P4DLinuxComponentSuite.groupproj | 108 -- Source/PythonEngine.pas | 14 +- Source/fmx/WrapDelphiFmx.pas | 2 - 11 files changed, 59 insertions(+), 1167 deletions(-) delete mode 100644 Packages/Delphi/Delphi 10.4+/PythonFmxLinux.dpk delete mode 100644 Packages/Delphi/Delphi 10.4+/PythonFmxLinux.dproj delete mode 100644 Packages/Delphi/P4DLinuxComponentSuite.groupproj 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/PythonEngine.pas b/Source/PythonEngine.pas index 93cfa6d2..6102ed35 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -1953,16 +1953,20 @@ TPythonInterface=class(TDynamicDll) //-------------------------------------------------------- type TDatetimeConversionMode = (dcmToTuple, dcmToDatetime); + TPythonFlag = (pfDebug, pfInteractive, pfNoSite, pfOptimize, pfVerbose, + pfFrozenFlag, pfIgnoreEnvironmentFlag, + pfDontWriteBytecodeFlag, pfIsolated); + TPythonFlags = set of TPythonFlag; + const DEFAULT_DATETIME_CONVERSION_MODE = dcmToTuple; + DEFAULT_FLAGS = {$IFDEF IOS}[pfIsolated, pfDontWriteBytecodeFlag]{$ELSE}[]{$ENDIF IOS}; + type TEngineClient = class; 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; - TPythonFlag = (pfDebug, pfInteractive, pfNoSite, pfOptimize, pfVerbose, - pfFrozenFlag, pfIgnoreEnvironmentFlag, pfIsolated); - TPythonFlags = set of TPythonFlag; TTracebackItem = class @@ -2153,7 +2157,7 @@ TPythonEngine = class(TPythonInterface) property DatetimeConversionMode: TDatetimeConversionMode read FDatetimeConversionMode write FDatetimeConversionMode default DEFAULT_DATETIME_CONVERSION_MODE; property InitScript: TStrings read FInitScript write SetInitScript; 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; @@ -4545,7 +4549,7 @@ constructor TPythonEngine.Create(AOwner: TComponent); FAutoFinalize := True; FTraceback := TPythonTraceback.Create; FUseWindowsConsole := False; - FPyFlags := []; + FPyFlags := DEFAULT_FLAGS; FDatetimeConversionMode := DEFAULT_DATETIME_CONVERSION_MODE; if csDesigning in ComponentState then begin 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, From 29aafb1ffde4c16d090c483ad7a25ca04ee1aad9 Mon Sep 17 00:00:00 2001 From: pyscripter <pyscripter@gmail.com> Date: Tue, 10 Dec 2024 02:08:08 +0200 Subject: [PATCH 37/49] Renamed VENVPythonExe to PythonExecutable --- Source/PythonEngine.pas | 12 ++++++------ Source/PythonVersions.pas | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Source/PythonEngine.pas b/Source/PythonEngine.pas index 6102ed35..72a91647 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -2003,7 +2003,7 @@ TPythonType = class; //forward declaration {$IFEND} TPythonEngine = class(TPythonInterface) private - FVenvPythonExe: string; + FPythonExecutable: string; FInitScript: TStrings; FIO: TPythonInputOutput; FRedirectIO: Boolean; @@ -2153,7 +2153,7 @@ TPythonEngine = class(TPythonInterface) 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 IO: TPythonInputOutput read FIO write SetIO; @@ -4760,10 +4760,10 @@ procedure TPythonEngine.Initialize; PPWcharT(PByte(@Config) + ConfigOffests[MinorVersion, TConfigFields.home]), PWCharT(StringToWCharTString(FPythonHome))); // Set venv executable if available - if FVenvPythonExe <> '' then + if FPythonExecutable <> '' then PyConfig_SetString(Config, PPWcharT(PByte(@Config) + ConfigOffests[MinorVersion, TConfigFields.executable]), - PWCharT(StringToWCharTString(FVenvPythonExe))); + PWCharT(StringToWCharTString(FPythonExecutable))); // Set program arguments (sys.argv) SetProgramArgs(Config); @@ -4872,8 +4872,8 @@ procedure TPythonEngine.Initialize; if FPythonHome <> '' then PyInitConfig_SetStr(Config, 'home', PAnsiChar(EncodeString(FPythonHome))); // Set venv executable if available - if FVenvPythonExe <> '' then - PyInitConfig_SetStr(Config, 'executable', PAnsiChar(EncodeString(FPythonHome))); + if FPythonExecutable <> '' then + PyInitConfig_SetStr(Config, 'executable', PAnsiChar(EncodeString(FPythonExecutable))); // Set program arguments (sys.argv) SetProgramArgs(Config); diff --git a/Source/PythonVersions.pas b/Source/PythonVersions.pas index 569ba52f..71d38a84 100644 --- a/Source/PythonVersions.pas +++ b/Source/PythonVersions.pas @@ -127,7 +127,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 { From 4025534d9bcbda7e7af691b154bb706290e731dc Mon Sep 17 00:00:00 2001 From: pyscripter <pyscripter@gmail.com> Date: Tue, 10 Dec 2024 02:46:24 +0200 Subject: [PATCH 38/49] Consistent naming of python flags --- Source/PythonEngine.pas | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/Source/PythonEngine.pas b/Source/PythonEngine.pas index 72a91647..9aad17bd 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -1954,13 +1954,19 @@ TPythonInterface=class(TDynamicDll) type TDatetimeConversionMode = (dcmToTuple, dcmToDatetime); TPythonFlag = (pfDebug, pfInteractive, pfNoSite, pfOptimize, pfVerbose, - pfFrozenFlag, pfIgnoreEnvironmentFlag, - pfDontWriteBytecodeFlag, pfIsolated); + pfFrozen, pfIgnoreEnvironment, pfNoUserSiteDirectory, + pfDontWriteBytecode, pfIsolated); TPythonFlags = set of TPythonFlag; const DEFAULT_DATETIME_CONVERSION_MODE = dcmToTuple; - DEFAULT_FLAGS = {$IFDEF IOS}[pfIsolated, pfDontWriteBytecodeFlag]{$ELSE}[]{$ENDIF IOS}; + DEFAULT_FLAGS = + {$IFDEF IOS} + [pfIsolated, pfNoUserSiteDirectory, pfIgnoreEnvironment, + pfDontWriteBytecodeFlag] + {$ELSE} + [] + {$ENDIF IOS}; type TEngineClient = class; @@ -4679,9 +4685,9 @@ procedure TPythonEngine.Initialize; PInteger(PByte(@Config) + ConfigOffests[MinorVersion, TConfigFields.site_import])^ := IfThen(pfNoSite in FPyFlags, 0, 1); PInteger(PByte(@Config) + ConfigOffests[MinorVersion, TConfigFields.pathconfig_warnings])^ := - IfThen(pfFrozenFlag in FPyFlags, 1, 0); + IfThen(pfFrozen in FPyFlags, 1, 0); PInteger(PByte(@Config) + ConfigOffests[MinorVersion, TConfigFields.use_environment])^ := - IfThen(pfIgnoreEnvironmentFlag in FPyFlags, 0, 1); + IfThen(pfIgnoreEnvironment in FPyFlags, 0, 1); end; procedure SetProgramArgs(var Config: PyConfig); @@ -4793,14 +4799,16 @@ 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, 'user_site_directory', IfThen(pfNoSite in FPyFlags, 0, 1)); - PyInitConfig_SetInt(Config, 'pathconfig_warnings', IfThen(pfFrozenFlag in FPyFlags, 1, 0)); - PyInitConfig_SetInt(Config, 'use_environment', IfThen(pfIgnoreEnvironmentFlag 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); @@ -4862,8 +4870,6 @@ procedure TPythonEngine.Initialize; begin Config := PyInitConfig_Create; try - PyInitConfig_SetInt(Config, 'isolated', IfThen(pfIsolated in FPyFlags, 1, 0)); - AssignPyFlags(Config); // Set programname and pythonhome if available From 7b9ada223b5779e8739591d25e15eda3c69df952 Mon Sep 17 00:00:00 2001 From: pyscripter <pyscripter@gmail.com> Date: Tue, 10 Dec 2024 03:15:44 +0200 Subject: [PATCH 39/49] ob_refcnt should be unsigned integer (NativeUInt) --- Demos/Demo06/Unit1.pas | 2 +- Demos/Demo07/Unit1.pas | 2 +- Demos/FPC/Demo06/Unit1.pas | 2 +- Source/PythonEngine.pas | 46 +++++++++++++++++++------------------- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Demos/Demo06/Unit1.pas b/Demos/Demo06/Unit1.pas index e038b4fa..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; diff --git a/Demos/Demo07/Unit1.pas b/Demos/Demo07/Unit1.pas index f33b8817..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; 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/Source/PythonEngine.pas b/Source/PythonEngine.pas index 9aad17bd..f579a420 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -474,7 +474,7 @@ TPythonVersionProp = record end; PyObject = {$IFDEF CPUX86}packed{$ENDIF} record - ob_refcnt: NativeInt; + ob_refcnt: NativeUInt; ob_type: PPyTypeObject; end; @@ -485,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; @@ -544,7 +544,7 @@ TPythonVersionProp = record 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; @@ -555,7 +555,7 @@ TPythonVersionProp = record 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; @@ -568,7 +568,7 @@ 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; @@ -581,7 +581,7 @@ 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; @@ -594,7 +594,7 @@ 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; @@ -607,7 +607,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; @@ -667,7 +667,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 @@ -814,7 +814,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 @@ -826,7 +826,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; @@ -849,7 +849,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; @@ -873,7 +873,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; @@ -888,7 +888,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; @@ -910,7 +910,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; @@ -929,7 +929,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; @@ -943,7 +943,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; @@ -958,7 +958,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; @@ -2576,9 +2576,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; @@ -2599,7 +2599,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 @@ -7816,7 +7816,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; @@ -7826,7 +7826,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; From abbaeee55759277aa5c867a82dea1d1aad52935f Mon Sep 17 00:00:00 2001 From: pyscripter <pyscripter@gmail.com> Date: Fri, 13 Dec 2024 18:12:04 +0200 Subject: [PATCH 40/49] Detect free-threaded python presence. --- Source/PythonVersions.pas | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/Source/PythonVersions.pas b/Source/PythonVersions.pas index 71d38a84..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; @@ -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; From a1471e2b98cad83bb05a693373e6dc8496505fff Mon Sep 17 00:00:00 2001 From: pyscripter <pyscripter@gmail.com> Date: Tue, 17 Dec 2024 01:55:40 +0200 Subject: [PATCH 41/49] Fix spelling --- Source/PythonEngine.pas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/PythonEngine.pas b/Source/PythonEngine.pas index f579a420..27c510a3 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -4436,7 +4436,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); From eac8094f7211dc88791bf7e3ce7014e95a47afe9 Mon Sep 17 00:00:00 2001 From: pyscripter <pyscripter@gmail.com> Date: Sun, 29 Dec 2024 01:07:50 +0200 Subject: [PATCH 42/49] Refactored error messages as resource strings --- Source/PythonEngine.pas | 193 ++++++++++++++++++++++++++-------------- 1 file changed, 124 insertions(+), 69 deletions(-) diff --git a/Source/PythonEngine.pas b/Source/PythonEngine.pas index 27c510a3..18928cfa 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -3072,6 +3072,59 @@ implementation 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'; (*******************************************************) (** **) @@ -3423,7 +3476,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} @@ -3471,7 +3524,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]); @@ -3566,7 +3619,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; @@ -3619,7 +3672,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; @@ -3692,7 +3745,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'; @@ -3713,13 +3766,13 @@ 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; @@ -4562,7 +4615,7 @@ constructor TPythonEngine.Create(AOwner: TComponent); 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; @@ -4968,7 +5021,7 @@ procedure TPythonEngine.Initialize; ErrMsg: string; begin if Assigned(gPythonEngine) then - raise Exception.Create('There is already one instance of TPythonEngine running' ); + raise Exception.Create(SMoreThanOnePythonEngine); gPythonEngine := Self; @@ -5085,7 +5138,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; @@ -5103,7 +5156,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; @@ -5115,7 +5168,7 @@ 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; @@ -5256,7 +5309,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 @@ -5600,7 +5653,7 @@ 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; @@ -5734,7 +5787,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; @@ -5749,7 +5802,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; @@ -5764,7 +5817,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; @@ -5884,7 +5937,7 @@ 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 := PyObject_Call(FPyDateTime_DateTimeType, args, nil); @@ -5894,7 +5947,7 @@ function TPythonEngine.VariantAsPyObject( const V : Variant ) : PPyObject; end; end else - raise EPythonError.Create('Invalid DatetimeConversionMode'); + raise EPythonError.Create(SInvalidDateTimeConvMode); end; varOleStr: begin @@ -5922,7 +5975,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 @@ -5948,7 +6001,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; @@ -6138,7 +6191,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; @@ -6151,7 +6204,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] ); @@ -6168,7 +6221,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] ); @@ -6182,7 +6235,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; @@ -6193,7 +6246,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; @@ -6249,7 +6302,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; @@ -6259,10 +6312,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 @@ -6287,7 +6340,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])); @@ -6299,7 +6352,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])); @@ -6311,7 +6364,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 @@ -6323,7 +6376,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 ) ) ); @@ -6725,7 +6778,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; @@ -6871,7 +6924,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; @@ -7004,7 +7057,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 @@ -7014,9 +7067,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; @@ -7067,7 +7120,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; @@ -7144,7 +7197,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; @@ -7181,7 +7234,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 ); @@ -7199,8 +7253,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; @@ -7310,13 +7364,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; @@ -7327,7 +7381,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; @@ -7347,7 +7401,7 @@ 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); @@ -7373,18 +7427,18 @@ procedure TError.RaiseErrorObj(const msg : AnsiString; obj : PPyObject); begin 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 := 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 @@ -7400,7 +7454,7 @@ procedure TError.RaiseErrorObj(const msg : AnsiString; obj : PPyObject); Py_XDECREF(keys); end else - raise Exception.Create('TError.RaiseErrorObj: I didn''t get an instance' ); + raise Exception.Create(STErrorNoInstance); PyErr_SetObject(Error, res); Py_XDECREF(res); end @@ -7600,7 +7654,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 ); @@ -7652,10 +7706,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, @@ -7669,7 +7723,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 ); @@ -7680,11 +7734,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; @@ -8252,7 +8307,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; @@ -9103,7 +9158,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'); @@ -9117,7 +9172,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 ); @@ -9126,7 +9181,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 ! @@ -9136,7 +9191,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 ); @@ -9145,7 +9200,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; @@ -9198,7 +9253,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 @@ -9490,7 +9545,7 @@ procedure TPythonThread.Execute; PyThreadState_Swap(global_state); PyGILState_Release(gilstate); end else - raise EPythonError.Create('Could not create a new thread state'); + raise EPythonError.Create(SCannotCreateThreadState); end; end; end; @@ -9698,9 +9753,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; @@ -10053,7 +10108,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 From 189fb29322bdd95b492468cde0141368024ccdca Mon Sep 17 00:00:00 2001 From: pyscripter <pyscripter@gmail.com> Date: Tue, 7 Jan 2025 13:20:47 +0200 Subject: [PATCH 43/49] Fix #493 --- Source/PythonEngine.pas | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Source/PythonEngine.pas b/Source/PythonEngine.pas index 18928cfa..dd43d6eb 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -538,7 +538,8 @@ TPythonVersionProp = record {#define PyDescr_COMMON \ PyObject_HEAD \ PyTypeObject *d_type; \ - PyObject *d_name + PyObject *d_name \ + PyObject *d_qualname } PPyDescrObject = ^PyDescrObject; @@ -549,6 +550,7 @@ TPythonVersionProp = record // End of the Head of an object d_type : PPyTypeObject; d_name : PPyObject; + d_qualname : PPyObject; end; PPyMethodDescrObject = ^PyMethodDescrObject; @@ -560,6 +562,7 @@ TPythonVersionProp = record // End of the Head of an object d_type : PPyTypeObject; d_name : PPyObject; + d_qualname : PPyObject; // End of PyDescr_COMMON d_method : PPyMethodDef; end; @@ -573,6 +576,7 @@ TPythonVersionProp = record // End of the Head of an object d_type : PPyTypeObject; d_name : PPyObject; + d_qualname : PPyObject; // End of PyDescr_COMMON d_member : PPyMemberDef; end; @@ -586,6 +590,7 @@ TPythonVersionProp = record // End of the Head of an object d_type : PPyTypeObject; d_name : PPyObject; + d_qualname : PPyObject; // End of PyDescr_COMMON d_getset : PPyGetSetDef; end; @@ -599,6 +604,7 @@ TPythonVersionProp = record // 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 @@ -1513,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; @@ -3859,6 +3866,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'); From 4c42c6c636d97a9e72b012f3ec1338be2f547fbc Mon Sep 17 00:00:00 2001 From: pyscripter <pyscripter@gmail.com> Date: Sat, 8 Mar 2025 00:54:27 +0200 Subject: [PATCH 44/49] Fix #495 --- Source/PythonEngine.pas | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/PythonEngine.pas b/Source/PythonEngine.pas index dd43d6eb..ec974172 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -1034,7 +1034,7 @@ PyConfig = record {$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, 232, 240, 256, 272, 280, 296), + (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)); @@ -4730,7 +4730,7 @@ procedure TPythonEngine.DoOpenDll(const aDllName : string); procedure TPythonEngine.Initialize; - procedure ConfgigPEP587(var ErrMsg: string); + procedure ConfigPEP587(var ErrMsg: string); // Initialize according to PEP587 available since python 3.8 procedure AssignPyFlags(var Config: PyConfig); @@ -4855,7 +4855,7 @@ procedure TPythonEngine.Initialize; end; end; - procedure ConfgigPEP741(var ErrMsg: string); + procedure ConfigPEP741(var ErrMsg: string); // Initialize according to PEP587 available since python 3.8 procedure AssignPyFlags(Config: PPyInitConfig); @@ -5039,9 +5039,9 @@ procedure TPythonEngine.Initialize; else begin if (MajorVersion > 3) or (MinorVersion >= 14) then - ConfgigPEP741(ErrMsg) + ConfigPEP741(ErrMsg) else - ConfgigPEP587(ErrMsg); + ConfigPEP587(ErrMsg); if not FInitialized then begin From e0164565660d44ca623cb08eccf2d5aa5ff8fa90 Mon Sep 17 00:00:00 2001 From: pyscripter <pyscripter@gmail.com> Date: Wed, 9 Apr 2025 17:28:47 +0300 Subject: [PATCH 45/49] Added PyLong_AsVoidPtr --- Source/PythonEngine.pas | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/PythonEngine.pas b/Source/PythonEngine.pas index ec974172..ff16be8d 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -1649,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; PyLong_FromVoidPtr:function(p: Pointer): PPyObject; cdecl; PyMapping_Check:function (ob:PPyObject):integer; cdecl; PyMapping_GetItemString:function (ob:PPyObject;key:PAnsiChar):PPyObject; cdecl; @@ -3984,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'); From 83f6b5ee3e24d35a27c73bb3fbe433a78a391d15 Mon Sep 17 00:00:00 2001 From: pyscripter <pyscripter@gmail.com> Date: Thu, 10 Apr 2025 05:23:15 +0300 Subject: [PATCH 46/49] Handle Pointer fields, properties and parameters - stored as python integers. --- Source/PythonEngine.pas | 2 +- Source/WrapDelphi.pas | 32 ++++++++++++++++++++++---------- Tests/WrapDelphiTest.pas | 9 +++++++++ 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/Source/PythonEngine.pas b/Source/PythonEngine.pas index ff16be8d..c15fbf48 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -1649,7 +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; + 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; diff --git a/Source/WrapDelphi.pas b/Source/WrapDelphi.pas index bed385ea..a19bc718 100644 --- a/Source/WrapDelphi.pas +++ b/Source/WrapDelphi.pas @@ -1042,7 +1042,7 @@ implementation rs_ExpectedNil = 'In static methods Self should be nil'; rs_ExpectedInterface = 'Expected a Pascal interface'; rs_ExpectedSequence = 'Expected a python sequence'; - rsExpectedPPyObject = 'Expected a PPyObject'; + 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 '+ @@ -2188,12 +2188,16 @@ function ValidateDynArray(PyValue: PPyObject; const RttiType: TRttiType; end; end; -function ValidatePPyObject(PyValue: PPyObject; const RttiType: TRttiType; +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; @@ -2201,10 +2205,21 @@ function ValidatePPyObject(PyValue: PPyObject; const RttiType: TRttiType; 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 := rsExpectedPPyObject; + ErrMsg := rsExpectedPointer; end; function PyObjectToTValue(PyArg: PPyObject; ArgType: TRttiType; @@ -2238,7 +2253,7 @@ function PyObjectToTValue(PyArg: PPyObject; ArgType: TRttiType; tkDynArray: Result := ValidateDynArray(PyArg, ArgType, Arg, ErrMsg); tkPointer: - Result := ValidatePPyObject(PyArg, ArgType, Arg, ErrMsg); + Result := ValidatePointer(PyArg, ArgType, Arg, ErrMsg); else Result := SimplePythonToValue(PyArg, ArgType.Handle, Arg, ErrMsg); end; @@ -2277,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); @@ -2288,13 +2303,10 @@ function TValueToPyObject(const Value: TValue; tkArray, tkDynArray: Result := DynArrayToPython(Value, DelphiWrapper, ErrMsg); tkPointer: - if Value.IsType<PPyObject> then + if Value.TypeInfo = TypeInfo(PPyObject) then Result := Value.AsType<PPyObject> else - begin - Result := nil; - ErrMsg := rs_ErrValueToPython; - end; + Result := DelphiWrapper.Engine.PyLong_FromVoidPtr(Value.AsType<Pointer>); else Result := SimpleValueToPython(Value, ErrMsg); end; diff --git a/Tests/WrapDelphiTest.pas b/Tests/WrapDelphiTest.pas index 350b0bb2..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); @@ -160,6 +161,8 @@ TTestWrapDelphi = class(TObject) procedure TestVarArgs; [Test] procedure TestPPyObjects; + [Test] + procedure TestPointers; end; implementation @@ -439,6 +442,12 @@ procedure TTestWrapDelphi.TestPPyObjects; 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'; From 92717b84a747285b5cb932f71ec454317329239d Mon Sep 17 00:00:00 2001 From: pyscripter <pyscripter@gmail.com> Date: Sun, 13 Apr 2025 02:15:28 +0300 Subject: [PATCH 47/49] Fix #497 --- Source/VarPyth.pas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/VarPyth.pas b/Source/VarPyth.pas index b16f91b8..52607cf0 100644 --- a/Source/VarPyth.pas +++ b/Source/VarPyth.pas @@ -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 From 179b7a666d3b2d765b0014681e2cc757097e1876 Mon Sep 17 00:00:00 2001 From: pyscripter <pyscripter@gmail.com> Date: Thu, 1 May 2025 16:15:52 +0300 Subject: [PATCH 48/49] Made python code compatible with recent versions of numpy and matplotlib. --- Tutorials/Webinar II/VizDemo/MainFormSVG.dfm | 42 +++++++++++--------- 1 file changed, 23 insertions(+), 19 deletions(-) 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 From 8b4a78f5b6d62822db65fae543b61ce99a208007 Mon Sep 17 00:00:00 2001 From: pyscripter <pyscripter@gmail.com> Date: Sat, 21 Jun 2025 23:17:48 +0300 Subject: [PATCH 49/49] EPySystemExit was not fully specified. --- Source/PythonEngine.pas | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Source/PythonEngine.pas b/Source/PythonEngine.pas index c15fbf48..422146b0 100644 --- a/Source/PythonEngine.pas +++ b/Source/PythonEngine.pas @@ -5570,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 ) @@ -6606,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); @@ -6614,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 <!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