Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit c654c83

Browse filesBrowse files
committed
Added new support unit PythonVersions.pas
1 parent a4fd2b4 commit c654c83
Copy full SHA for c654c83

File tree

1 file changed

+322
-0
lines changed
Filter options

1 file changed

+322
-0
lines changed
+322Lines changed: 322 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,322 @@
1+
{-----------------------------------------------------------------------------
2+
Unit Name: PythonVersions
3+
Author: Kiriakos
4+
Date: PyScripter
5+
Purpose: Discover and get info about Python versions
6+
Part of the Python for Delphi library
7+
8+
History:
9+
-----------------------------------------------------------------------------}
10+
11+
unit PythonVersions;
12+
13+
interface
14+
Uses
15+
Classes;
16+
17+
type
18+
19+
TPythonVersion = record
20+
private
21+
FDisplayName: string;
22+
FHelpFile: string;
23+
function GetDLLName: string;
24+
function GetSysArchitecture:string;
25+
function GetIsPython3K: Boolean;
26+
function GetHelpFile: string;
27+
function GetDisplayName: string;
28+
public
29+
IsRegistered: Boolean;
30+
IsAllUsers: Boolean;
31+
SysVersion: string;
32+
Version: string;
33+
DLLPath: string;
34+
InstallPath: string;
35+
PythonPath: string;
36+
procedure AssignTo(PythonEngine: TPersistent);
37+
property DLLName: string read GetDLLName;
38+
property SysArchitecture: string read GetSysArchitecture;
39+
property IsPython3K: Boolean read GetIsPython3K;
40+
property HelpFile: string read GetHelpFile write FHelpFile;
41+
property DisplayName: string read GetDisplayName write FDisplayName;
42+
end;
43+
44+
TPythonVersions = array of TPythonVersion;
45+
46+
(* Compares two Version strings and returns -1, 0, 1 depending on result *)
47+
function CompareVersions(const A, B : String) : Integer;
48+
49+
50+
{$IFDEF MSWINDOWS}
51+
(* Checks whether a Python version is registered and returns the related info *)
52+
function GetRegisterPythonVersion(SysVersion: string;
53+
out PythonVersion: TPythonVersion): Boolean;
54+
(* Returns all registered Python versions *)
55+
function GetRegisteredPythonVersions : TPythonVersions;
56+
(* Returns the highest numbered registered Python version *)
57+
function GetLatestRegisteredPythonVersion(PythonVersion: TPythonVersion): Boolean;
58+
{$ENDIF}
59+
60+
implementation
61+
62+
Uses
63+
{$IFDEF MSWINDOWS}
64+
Windows,
65+
{$ENDIF}
66+
SysUtils,
67+
Math,
68+
Registry,
69+
PythonEngine;
70+
71+
{ TPythonVersion }
72+
73+
function TPythonVersion.GetDLLName: string;
74+
begin
75+
{$IFDEF MSWINDOWS}
76+
Result := 'python' + SysVersion[1] + SysVersion[3] + '.dll';
77+
{$ELSE}
78+
Result := 'libpython' + SysVersion + '.so';
79+
{$ENDIF}
80+
end;
81+
82+
function TPythonVersion.GetSysArchitecture: string;
83+
begin
84+
Result := '';
85+
{$IFDEF CPUX64}
86+
Result := '64bit';
87+
{$ENDIF}
88+
{$IFDEF CPU64}
89+
Result := '64bit';
90+
{$ENDIF}
91+
{$IFDEF CPU64bits}
92+
Result := '64bit';
93+
{$ENDIF}
94+
if Result = '' then
95+
Result := '32bit';
96+
end;
97+
98+
procedure TPythonVersion.AssignTo(PythonEngine: TPersistent);
99+
begin
100+
if PythonEngine is TPythonEngine then begin
101+
TPythonEngine(PythonEngine).UseLastKnownVersion := False;
102+
TPythonEngine(PythonEngine).RegVersion := SysVersion;
103+
TPythonEngine(PythonEngine).DllName := DLLName;
104+
TPythonEngine(PythonEngine).DllPath := DLLPath;
105+
end;
106+
end;
107+
108+
function TPythonVersion.GetDisplayName: string;
109+
begin
110+
Result := FDisplayName;
111+
if Result = '' then
112+
Result := Format('Python %s (%s)', [SysVersion, SysArchitecture]);
113+
end;
114+
115+
function TPythonVersion.GetHelpFile: string;
116+
var
117+
PythonHelpFilePath: string;
118+
Res: Integer;
119+
SR: TSearchRec;
120+
begin
121+
Result := FHelpFile;
122+
// for unregistered Python
123+
if (Result = '') and (InstallPath <> '') then
124+
begin
125+
PythonHelpFilePath := InstallPath + '\Doc\python*.chm';
126+
Res := FindFirst(PythonHelpFilePath, faAnyFile, SR);
127+
if Res = 0 then
128+
Result := InstallPath + '\Doc\' + SR.Name;
129+
FindClose(SR);
130+
end;
131+
end;
132+
133+
function TPythonVersion.GetIsPython3K: Boolean;
134+
begin
135+
try
136+
Result := StrToInt(SysVersion[1]) >= 3;
137+
except
138+
Result := False;
139+
end;
140+
end;
141+
142+
function CompareVersions(const A, B : String) : Integer;
143+
var
144+
i : Integer;
145+
_delta : Integer;
146+
_version1 : TStringList;
147+
_version2 : TStringList;
148+
_version : TStringList;
149+
begin
150+
Result := 0;
151+
_version1 := TStringList.Create;
152+
try
153+
_version1.Delimiter := '.';
154+
_version1.DelimitedText := A;
155+
_version2 := TStringList.Create;
156+
try
157+
_version2.Delimiter := '.';
158+
_version2.DelimitedText := B;
159+
for i := 0 to Min(_version1.Count, _version2.Count)-1 do
160+
begin
161+
try
162+
_delta := StrToInt(_version1[i]) - StrToInt(_version2[i]);
163+
except
164+
_delta := CompareText(_version1[i], _version2[i]);
165+
end;
166+
if _delta <> 0 then
167+
begin
168+
if _delta > 0 then
169+
Result := 1
170+
else
171+
Result := -1;
172+
Break;
173+
end;
174+
end;
175+
// if we have an equality but the 2 versions don't have the same number of parts
176+
// then check the remaining parts of the stronger version, and if it contains
177+
// something different from 0, it will win.
178+
if Result = 0 then
179+
if _version1.Count <> _version2.Count then
180+
begin
181+
if _version1.Count > _version2.Count then
182+
_version := _version1
183+
else
184+
_version := _version2;
185+
for i := Min(_version1.Count, _version2.Count) to _version.Count-1 do
186+
begin
187+
if StrToIntDef(_version[i], -1) <> 0 then
188+
begin
189+
if _version1.Count > _version2.Count then
190+
Result := 1
191+
else
192+
Result := -1;
193+
Break;
194+
end;
195+
end;
196+
end;
197+
finally
198+
_version2.Free;
199+
end;
200+
finally
201+
_version1.Free;
202+
end;
203+
end;
204+
205+
{$IFDEF MSWINDOWS}
206+
function GetRegisterPythonVersion(SysVersion: string;
207+
out PythonVersion: TPythonVersion): Boolean;
208+
// Python provides for All user and Current user installations
209+
// All User installations place the Python DLL in the Windows System directory
210+
// and write registry info to HKEY_LOCAL_MACHINE
211+
// Current User installations place the DLL in the install path and
212+
// the registry info in HKEY_CURRENT_USER.
213+
// Hence, for Current user installations we need to try and find the install path
214+
// since it may not be on the system path.
215+
216+
// The above convension was changed in Python 3.5. Now even for all user
217+
// installations the dll is located at the InstallPath.
218+
// Also from version 3.5 onwards 32 bit version have a suffix -32 e.g. "3.6-32"
219+
// See also PEP 514
220+
221+
function ReadFromRegistry(Root: HKEY; key: string): Boolean;
222+
begin
223+
Result := False;
224+
try
225+
with TRegistry.Create(KEY_READ and not KEY_NOTIFY) do
226+
try
227+
RootKey := Root;
228+
if OpenKey(Key + '\InstallPath', False) then begin
229+
PythonVersion.InstallPath := ReadString('');
230+
if PythonVersion.IsAllUsers and (CompareVersions(SysVersion, '3.5') < 0) then
231+
PythonVersion.DLLPath := ''
232+
else
233+
PythonVersion.DLLPath := PythonVersion.InstallPath;
234+
CloseKey;
235+
end;
236+
Result := PythonVersion.InstallPath <> '';
237+
if not Result then Exit;
238+
239+
if OpenKey(Key, False) then begin
240+
PythonVersion.DisplayName := ReadString('DisplayName');
241+
PythonVersion.Version := ReadString('Version');
242+
CloseKey;
243+
end;
244+
if OpenKey(Key + '\PythonPath', False) then begin
245+
PythonVersion.PythonPath := ReadString('');
246+
CloseKey;
247+
end;
248+
if OpenKey(Key + '\Help\Main Python Documentation', False) then begin
249+
PythonVersion.HelpFile := ReadString('');
250+
CloseKey;
251+
end;
252+
finally
253+
Free;
254+
end;
255+
except
256+
end;
257+
258+
end;
259+
260+
var
261+
key: string;
262+
VersionSuffix: string;
263+
begin
264+
// Initialize PythohVersion
265+
Finalize(PythonVersion);
266+
FillChar(PythonVersion, SizeOf(TPythonVersion), 0);
267+
268+
VersionSuffix := '';
269+
{$IFDEF CPUX86}
270+
if CompareVersions(SysVersion, '3.5') >= 0 then
271+
VersionSuffix := '-32';
272+
{$ENDIF}
273+
key := Format('\Software\Python\PythonCore\%s%s', [SysVersion, VersionSuffix]);
274+
275+
276+
PythonVersion.SysVersion := SysVersion;
277+
// First try HKEY_CURRENT_USER as per PEP514
278+
PythonVersion.IsAllUsers := False;
279+
Result := ReadFromRegistry(HKEY_CURRENT_USER, key);
280+
281+
//Then try for an all user installation
282+
if not Result then begin
283+
PythonVersion.IsAllUsers := True;
284+
Result := ReadFromRegistry(HKEY_LOCAL_MACHINE, key);
285+
end;
286+
287+
PythonVersion.IsRegistered := Result;
288+
end;
289+
290+
function GetRegisteredPythonVersions : TPythonVersions;
291+
Var
292+
Count: Integer;
293+
I: Integer;
294+
PythonVersion : TPythonVersion;
295+
begin
296+
Count := 0;
297+
SetLength(Result, High(PYTHON_KNOWN_VERSIONS) - COMPILED_FOR_PYTHON_VERSION_INDEX + 1);
298+
for I := High(PYTHON_KNOWN_VERSIONS) downto COMPILED_FOR_PYTHON_VERSION_INDEX do
299+
if GetRegisterPythonVersion(PYTHON_KNOWN_VERSIONS[I].RegVersion, PythonVersion) then
300+
begin
301+
Result[Count] := PythonVersion;
302+
Inc(Count);
303+
end;
304+
SetLength(Result, Count);
305+
end;
306+
307+
function GetLatestRegisteredPythonVersion(PythonVersion: TPythonVersion): Boolean;
308+
Var
309+
I: Integer;
310+
begin
311+
Result := False;
312+
for I := High(PYTHON_KNOWN_VERSIONS) downto COMPILED_FOR_PYTHON_VERSION_INDEX do
313+
begin
314+
Result := GetRegisterPythonVersion(PYTHON_KNOWN_VERSIONS[I].RegVersion, PythonVersion);
315+
if Result then break;
316+
end;
317+
end;
318+
319+
{$ENDIF}
320+
321+
322+
end.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.