Skip to content

Commit 1dda809

Browse files
committed
Python 3.12 compatibility
1 parent 287628d commit 1dda809

File tree

1 file changed

+39
-67
lines changed

1 file changed

+39
-67
lines changed

Source/PythonEngine.pas

+39-67
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ TPythonVersionProp = record
116116
end;
117117
const
118118
{$IFDEF MSWINDOWS}
119-
PYTHON_KNOWN_VERSIONS: array[1..9] of TPythonVersionProp =
119+
PYTHON_KNOWN_VERSIONS: array[1..10] of TPythonVersionProp =
120120
(
121121
(DllName: 'python33.dll'; RegVersion: '3.3'; APIVersion: 1013),
122122
(DllName: 'python34.dll'; RegVersion: '3.4'; APIVersion: 1013),
@@ -126,11 +126,12 @@ TPythonVersionProp = record
126126
(DllName: 'python38.dll'; RegVersion: '3.8'; APIVersion: 1013),
127127
(DllName: 'python39.dll'; RegVersion: '3.9'; APIVersion: 1013),
128128
(DllName: 'python310.dll'; RegVersion: '3.10'; APIVersion: 1013),
129-
(DllName: 'python311.dll'; RegVersion: '3.11'; APIVersion: 1013)
129+
(DllName: 'python311.dll'; RegVersion: '3.11'; APIVersion: 1013),
130+
(DllName: 'python312.dll'; RegVersion: '3.12'; APIVersion: 1013)
130131
);
131132
{$ENDIF}
132133
{$IFDEF _so_files}
133-
PYTHON_KNOWN_VERSIONS: array[1..9] of TPythonVersionProp =
134+
PYTHON_KNOWN_VERSIONS: array[1..10] of TPythonVersionProp =
134135
(
135136
(DllName: 'libpython3.3m.so'; RegVersion: '3.3'; APIVersion: 1013),
136137
(DllName: 'libpython3.4m.so'; RegVersion: '3.4'; APIVersion: 1013),
@@ -140,11 +141,12 @@ TPythonVersionProp = record
140141
(DllName: 'libpython3.8.so'; RegVersion: '3.8'; APIVersion: 1013),
141142
(DllName: 'libpython3.9.so'; RegVersion: '3.9'; APIVersion: 1013),
142143
(DllName: 'libpython3.10.so'; RegVersion: '3.10'; APIVersion: 1013),
143-
(DllName: 'libpython3.11.so'; RegVersion: '3.11'; APIVersion: 1013)
144+
(DllName: 'libpython3.11.so'; RegVersion: '3.11'; APIVersion: 1013),
145+
(DllName: 'libpython3.12.so'; RegVersion: '3.12'; APIVersion: 1013)
144146
);
145147
{$ENDIF}
146148
{$IFDEF DARWIN}
147-
PYTHON_KNOWN_VERSIONS: array[1..9] of TPythonVersionProp =
149+
PYTHON_KNOWN_VERSIONS: array[1..10] of TPythonVersionProp =
148150
(
149151
(DllName: 'libpython3.3.dylib'; RegVersion: '3.3'; APIVersion: 1013),
150152
(DllName: 'libpython3.4.dylib'; RegVersion: '3.4'; APIVersion: 1013),
@@ -154,16 +156,18 @@ TPythonVersionProp = record
154156
(DllName: 'libpython3.8.dylib'; RegVersion: '3.8'; APIVersion: 1013),
155157
(DllName: 'libpython3.9.dylib'; RegVersion: '3.9'; APIVersion: 1013),
156158
(DllName: 'libpython3.10.dylib'; RegVersion: '3.10'; APIVersion: 1013),
157-
(DllName: 'libpython3.11.dylib'; RegVersion: '3.11'; APIVersion: 1013)
159+
(DllName: 'libpython3.11.dylib'; RegVersion: '3.11'; APIVersion: 1013),
160+
(DllName: 'libpython3.12.dylib'; RegVersion: '3.12'; APIVersion: 1013)
158161
);
159162
{$ENDIF}
160163
{$IFDEF ANDROID}
161-
PYTHON_KNOWN_VERSIONS: array[6..9] of TPythonVersionProp =
164+
PYTHON_KNOWN_VERSIONS: array[6..10] of TPythonVersionProp =
162165
(
163166
(DllName: 'libpython3.8.so'; RegVersion: '3.8'; APIVersion: 1013),
164167
(DllName: 'libpython3.9.so'; RegVersion: '3.9'; APIVersion: 1013),
165168
(DllName: 'libpython3.10.so'; RegVersion: '3.10'; APIVersion: 1013),
166-
(DllName: 'libpython3.11.so'; RegVersion: '3.11'; APIVersion: 1013)
169+
(DllName: 'libpython3.11.so'; RegVersion: '3.11'; APIVersion: 1013),
170+
(DllName: 'libpython3.12.so'; RegVersion: '3.12'; APIVersion: 1013)
167171
);
168172
{$ENDIF}
169173

@@ -1274,7 +1278,6 @@ TPythonInterface=class(TDynamicDll)
12741278
procedure AfterLoad; override;
12751279
function GetQuitMessage : string; override;
12761280
procedure CheckPython;
1277-
function GetUnicodeTypeSuffix : string;
12781281

12791282
public
12801283
// define Python flags. See file pyDebug.h
@@ -1607,7 +1610,7 @@ TPythonInterface=class(TDynamicDll)
16071610
PyUnicode_DecodeUTF16:function (const s:PAnsiChar; size: NativeInt; const errors: PAnsiChar; byteoder: PInteger):PPyObject; cdecl;
16081611
PyUnicode_AsEncodedString:function (unicode:PPyObject; const encoding:PAnsiChar; const errors:PAnsiChar):PPyObject; cdecl;
16091612
PyUnicode_FromOrdinal:function (ordinal:integer):PPyObject; cdecl;
1610-
PyUnicode_GetSize:function (unicode:PPyObject):NativeInt; cdecl;
1613+
PyUnicode_GetLength:function (unicode:PPyObject):NativeInt; cdecl;
16111614
PyWeakref_GetObject: function ( ref : PPyObject) : PPyObject; cdecl;
16121615
PyWeakref_NewProxy: function ( ob, callback : PPyObject) : PPyObject; cdecl;
16131616
PyWeakref_NewRef: function ( ob, callback : PPyObject) : PPyObject; cdecl;
@@ -3464,28 +3467,8 @@ procedure TPythonInterface.CheckPython;
34643467
raise Exception.Create('Python is not properly initialized' );
34653468
end;
34663469

3467-
function TPythonInterface.GetUnicodeTypeSuffix : string;
3468-
begin
3469-
if (fMajorVersion > 3) or ((fMajorVersion = 3) and (fMinorVersion >= 3)) then
3470-
Result := ''
3471-
else if APIVersion >= 1011 then
3472-
Result :=
3473-
{$IF DEFINED(MSWINDOWS) or DEFINED(DARWIN) or DEFINED(SOLARIS)}
3474-
'UCS2'
3475-
{$ELSE}
3476-
'UCS4'
3477-
{$IFEND}
3478-
else
3479-
Result := '';
3480-
end;
3481-
34823470
procedure TPythonInterface.MapDll;
3483-
Var
3484-
UnicodeSuffix : string;
3485-
34863471
begin
3487-
UnicodeSuffix := GetUnicodeTypeSuffix;
3488-
34893472
Py_DebugFlag := Import('Py_DebugFlag');
34903473
Py_VerboseFlag := Import('Py_VerboseFlag');
34913474
Py_InteractiveFlag := Import('Py_InteractiveFlag');
@@ -3796,18 +3779,18 @@ procedure TPythonInterface.MapDll;
37963779
PyType_GenericAlloc := Import('PyType_GenericAlloc');
37973780
PyType_GenericNew := Import('PyType_GenericNew');
37983781
PyType_Ready := Import('PyType_Ready');
3799-
PyUnicode_FromWideChar := Import(AnsiString(Format('PyUnicode%s_FromWideChar',[UnicodeSuffix])));
3800-
PyUnicode_FromString := Import(AnsiString(Format('PyUnicode%s_FromString',[UnicodeSuffix])));
3801-
PyUnicode_FromStringAndSize := Import(AnsiString(Format('PyUnicode%s_FromStringAndSize',[UnicodeSuffix])));
3802-
PyUnicode_FromKindAndData := Import(AnsiString(Format('PyUnicode%s_FromKindAndData',[UnicodeSuffix])));
3803-
PyUnicode_AsWideChar := Import(AnsiString(Format('PyUnicode%s_AsWideChar',[UnicodeSuffix])));
3804-
PyUnicode_AsUTF8 := Import(AnsiString(Format('PyUnicode%s_AsUTF8',[UnicodeSuffix])));
3805-
PyUnicode_AsUTF8AndSize := Import(AnsiString(Format('PyUnicode%s_AsUTF8AndSize',[UnicodeSuffix])));
3806-
PyUnicode_Decode := Import(AnsiString(Format('PyUnicode%s_Decode',[UnicodeSuffix])));
3807-
PyUnicode_DecodeUTF16 := Import(AnsiString(Format('PyUnicode%s_DecodeUTF16',[UnicodeSuffix])));
3808-
PyUnicode_AsEncodedString := Import(AnsiString(Format('PyUnicode%s_AsEncodedString',[UnicodeSuffix])));
3809-
PyUnicode_FromOrdinal := Import(AnsiString(Format('PyUnicode%s_FromOrdinal',[UnicodeSuffix])));
3810-
PyUnicode_GetSize := Import(AnsiString(Format('PyUnicode%s_GetSize',[UnicodeSuffix])));
3782+
PyUnicode_FromWideChar := Import('PyUnicode_FromWideChar');
3783+
PyUnicode_FromString := Import('PyUnicode_FromString');
3784+
PyUnicode_FromStringAndSize := Import('PyUnicode_FromStringAndSize');
3785+
PyUnicode_FromKindAndData := Import('PyUnicode_FromKindAndData');
3786+
PyUnicode_AsWideChar := Import('PyUnicode_AsWideChar');
3787+
PyUnicode_AsUTF8 := Import('PyUnicode_AsUTF8');
3788+
PyUnicode_AsUTF8AndSize := Import('PyUnicode_AsUTF8AndSize');
3789+
PyUnicode_Decode := Import('PyUnicode_Decode');
3790+
PyUnicode_DecodeUTF16 := Import('PyUnicode_DecodeUTF16');
3791+
PyUnicode_AsEncodedString := Import('PyUnicode_AsEncodedString');
3792+
PyUnicode_FromOrdinal := Import('PyUnicode_FromOrdinal');
3793+
PyUnicode_GetLength := Import('PyUnicode_GetLength');
38113794
PyWeakref_GetObject := Import('PyWeakref_GetObject');
38123795
PyWeakref_NewProxy := Import('PyWeakref_NewProxy');
38133796
PyWeakref_NewRef := Import('PyWeakref_NewRef');
@@ -6055,35 +6038,24 @@ function TPythonEngine.PyBytesAsAnsiString(obj: PPyObject): AnsiString;
60556038
raise EPythonError.CreateFmt(SPyConvertionError, ['PyBytesAsAnsiString', 'Bytes']);
60566039
end;
60576040

6058-
function TPythonEngine.PyUnicodeAsString( obj : PPyObject ) : UnicodeString;
6041+
function TPythonEngine.PyUnicodeAsString(obj : PPyObject): UnicodeString;
60596042
var
6060-
_size : Integer;
6061-
{$IFDEF POSIX}
6062-
_ucs4Str : UCS4String;
6063-
{$ENDIF}
6043+
Buffer: PAnsiChar;
6044+
Size: NativeInt;
6045+
NewSize: Cardinal;
60646046
begin
60656047
if PyUnicode_Check(obj) then
60666048
begin
6067-
_size := PyUnicode_GetSize(obj);
6068-
if _size > 0 then
6069-
begin
6070-
{$IFDEF POSIX}
6071-
// Note that Linux uses UCS4 strings, whereas it declares using UCS2 strings!!!
6072-
SetLength(_ucs4Str, _size+1);
6073-
if PyUnicode_AsWideChar(obj, @_ucs4Str[0], _size) <> _size then
6074-
raise EPythonError.Create('Could not copy the whole Unicode string into its buffer');
6075-
Result := UCS4StringToWideString(_ucs4Str);
6076-
// remove trailing zeros
6077-
while (Length(Result) > 0) and (Result[Length(Result)] = #0) do
6078-
Delete(Result, Length(Result), 1);
6079-
{$ELSE}
6080-
SetLength(Result, _size);
6081-
if PyUnicode_AsWideChar(obj, @Result[1], _size) <> _size then
6082-
raise EPythonError.Create('Could not copy the whole Unicode string into its buffer');
6083-
{$ENDIF}
6084-
end
6085-
else
6086-
Result := '';
6049+
// Size does not include the final #0
6050+
Buffer := PyUnicode_AsUTF8AndSize(obj, @Size);
6051+
SetLength(Result, Size);
6052+
if (Size = 0) or (Buffer = nil) then
6053+
Exit;
6054+
6055+
// The second argument is the size of the destination (Result) including #0
6056+
NewSize := Utf8ToUnicode(PChar(Result), Cardinal(Size + 1), Buffer, Cardinal(Size));
6057+
// NewSize includes #0
6058+
SetLength(Result, NewSize - 1);
60876059
end
60886060
else
60896061
raise EPythonError.CreateFmt(SPyConvertionError, ['PyUnicodeAsString', 'Unicode']);

0 commit comments

Comments
 (0)