8000 Merge pull request #2249 from pythonnet/python-3.12 · spsforks/pythonnet-pythonnet@88418da · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit 88418da

Browse files
authored
Merge pull request pythonnet#2249 from pythonnet/python-3.12
Python 3.12
2 parents a9e757f + 293f8b1 commit 88418da

File tree

10 files changed

+187
-64
lines changed

10 files changed

+187
-64
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
fail-fast: false
1717
matrix:
1818
os: [windows, ubuntu, macos]
19-
python: ["3.7", "3.8", "3.9", "3.10", "3.11"]
19+
python: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"]
2020
platform: [x64, x86]
2121
exclude:
2222
- os: ubuntu

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ This document follows the conventions laid out in [Keep a CHANGELOG][].
99

1010
### Added
1111

12-
- use enum name in repr
12+
- Use enum name in `repr`
13+
- Support for Python 3.12
1314

1415
### Changed
1516

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ dependencies = [
1313
"clr_loader>=0.2.6,<0.3.0"
1414
]
1515

16-
requires-python = ">=3.7, <3.12"
16+
requires-python = ">=3.7, <3.13"
1717

1818
classifiers = [
1919
"Development Status :: 5 - Production/Stable",
@@ -26,6 +26,7 @@ classifiers = [
2626
"Programming Language :: Python :: 3.9",
2727
"Programming Language :: Python :: 3.10",
2828
"Programming Language :: Python :: 3.11",
29+
"Programming Language :: Python :: 3.12",
2930
"Operating System :: Microsoft :: Windows",
3031
"Operating System :: POSIX :: Linux",
3132
"Operating System :: MacOS :: MacOS X",

src/embed_tests/Codecs.cs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -371,11 +371,23 @@ public void FloatDerivedDecoded()
371371
[Test]
372372
public void ExceptionDecodedNoInstance()
373373
{
374-
PyObjectConversions.RegisterDecoder(new InstancelessExceptionDecoder());
375-
using var scope = Py.CreateScope();
376-
var error = Assert.Throws<ValueErrorWrapper>(() => PythonEngine.Exec(
377-
$"[].__iter__().__next__()"));
378-
Assert.AreEqual(TestExceptionMessage, error.Message);
374+
if (Runtime.PyVersion < new Version(3, 12))
375+
{
376+
PyObjectConversions.RegisterDecoder(new InstancelessExceptionDecoder());
377+
using var scope = Py.CreateScope();
378+
379+
var error = Assert.Throws<ValueErrorWrapper>(() =>
380+
PythonEngine.Exec($"[].__iter__().__next__()")
381+
);
382+
Assert.AreEqual(TestExceptionMessage, error.Message);
383+
}
384+
else
385+
{
386+
Assert.Ignore(
387+
"This test does not work for Python 3.12, see " +
388+
"https://github.com/python/cpython/issues/101578"
389+
);
390+
}
379391
}
380392

381393
public static void AcceptsDateTime(DateTime v) {}

src/runtime/Converter.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -686,10 +686,8 @@ internal static bool ToPrimitive(BorrowedReference value, Type obType, out objec
686686
{
687687
if (Runtime.PyUnicode_GetLength(value) == 1)
688688
{
689-
IntPtr unicodePtr = Runtime.PyUnicode_AsUnicode(value);
690-
Char[] buff = new Char[1];
691-
Marshal.Copy(unicodePtr, buff, 0, 1);
692-
result = buff[0];
689+
int chr = Runtime.PyUnicode_ReadChar(value, 0);
690+
result = (Char)chr;
693691
return true;
694692
}
695693
goto type_error;

src/runtime/Native/TypeOffset312.cs

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
2+
// Auto-generated by geninterop.py.
3+
// DO NOT MODIFY BY HAND.
4+
5+
// Python 3.12: ABI flags: ''
6+
7+
// ReSharper disable InconsistentNaming
8+
// ReSharper disable IdentifierTypo
9+
10+
using System;
11+
using System.Diagnostics.CodeAnalysis;
12+
using System.Runtime.InteropServices;
13+
14+
using Python.Runtime.Native;
15+
16+
namespace Python.Runtime
17+
{
18+
[SuppressMessage("Style", "IDE1006:Naming Styles",
19+
Justification = "Following CPython",
20+
Scope = "type")]
21+
22+
[StructLayout(LayoutKind.Sequential)]
23+
internal class TypeOffset312 : GeneratedTypeOffsets, ITypeOffsets
24+
{
25+
public TypeOffset312() { }
26+
// Auto-generated from PyHeapTypeObject in Python.h
27+
public int ob_refcnt { get; private set; }
28+
public int ob_type { get; private set; }
29+
public int ob_size { get; private set; }
30+
public int tp_name { get; private set; }
31+
public int tp_basicsize { get; private set; }
32+
public int tp_itemsize { get; private set; }
33+
public int tp_dealloc { get; private set; }
34+
public int tp_vectorcall_offset { get; private set; }
35+
public int tp_getattr { get; private set; }
36+
public int tp_setattr { get; private set; }
37+
public int tp_as_async { get; private set; }
38+
public int tp_repr { get; private set; }
39+
public int tp_as_number { get; private set; }
40+
public int tp_as_sequence { get; private set; }
41+
public int tp_as_mapping { get; private set; }
42+
public int tp_hash { get; private set; }
43+
public int tp_call { get; private set; }
44+
public int tp_str { get; private set; }
45+
public int tp_getattro { get; private set; }
46+
179B public int tp_setattro { get; private set; }
47+
public int tp_as_buffer { get; private set; }
48+
public int tp_flags { get; private set; }
49+
public int tp_doc { get; private set; }
50+
public int tp_traverse { get; private set; }
51+
public int tp_clear { get; private set; }
52+
public int tp_richcompare { get; private set; }
53+
public int tp_weaklistoffset { get; private set; }
54+
public int tp_iter { get; private set; }
55+
public int tp_iternext { get; private set; }
56+
public int tp_methods { get; private set; }
57+
public int tp_members { get; private set; }
58+
public int tp_getset { get; private set; }
59+
public int tp_base { get; private set; }
60+
public int tp_dict { get; private set; }
61+
public int tp_descr_get { get; private set; }
62+
public int tp_descr_set { get; private set; }
63+
public int tp_dictoffset { get; private set; }
64+
public int tp_init { get; private set; }
65+
public int tp_alloc { get; private set; }
66+
public int tp_new { get; private set; }
67+
public int tp_free { get; private set; }
68+
public int tp_is_gc { get; private set; }
69+
public int tp_bases { get; private set; }
70+
public int tp_mro { get; private set; }
71+
public int tp_cache { get; private set; }
72+
public int tp_subclasses { get; private set; }
73+
public int tp_weaklist { get; private set; }
74+
public int tp_del { get; private set; }
75+
public int tp_version_tag { get; private set; }
76+
public int tp_finalize { get; private set; }
77+
public int tp_vectorcall { get; private set; }
78+
public int tp_watched { get; private set; }
79+
public int am_await { get; private set; }
80+
public int am_aiter { get; private set; }
81+
public int am_anext { get; private set; }
82+
public int am_send { get; private set; }
83+
public int nb_add { get; private set; }
84+
public int nb_subtract { get; private set; }
85+
public int nb_multiply { get; private set; }
86+
public int nb_remainder { get; private set; }
87+
public int nb_divmod { get; private set; }
88+
public int nb_power { get; private set; }
89+
public int nb_negative { get; private set; }
90+
public int nb_positive { get; private set; }
91+
public int nb_absolute { get; private set; }
92+
public int nb_bool { get; private set; }
93+
public int nb_invert { get; private set; }
94+
public int nb_lshift { get; private set; }
95+
public int nb_rshift { get; private set; }
96+
public int nb_and { get; private set; }
97+
public int nb_xor { get; private set; }
98+
public int nb_or { get; private set; }
99+
public int nb_int { get; private set; }
100+
public int nb_reserved { get; private set; }
101+
public int nb_float { get; private set; }
102+
public int nb_inplace_add { get; private set; }
103+
public int nb_inplace_subtract { get; private set; }
104+
public int nb_inplace_multiply { get; private set; }
105+
public int nb_inplace_remainder { get; private set; }
106+
public int nb_inplace_power { get; private set; }
107+
public int nb_inplace_lshift { get; private set; }
108+
public int nb_inplace_rshift { get; private set; }
109+
public int nb_inplace_and { get; private set; }
110+
public int nb_inplace_xor { get; private set; }
111+
public int nb_inplace_or { get; private set; }
112+
public int nb_floor_divide { get; private set; }
113+
public int nb_true_divide { get; private set; }
114+
public int nb_inplace_floor_divide { get; private set; }
115+
public int nb_inplace_true_divide { get; private set; }
116+
public int nb_index { get; private set; }
117+
public int nb_matrix_multiply { get; private set; }
118+
public int nb_inplace_matrix_multiply { get; private set; }
119+
public int mp_length { get; private set; }
120+
public int mp_subscript { get; private set; }
121+
public int mp_ass_subscript { get; private set; }
122+
public int sq_length { get; private set; }
123+
public int sq_concat { get; private set; }
124+
public int sq_repeat { get; private set; }
125+
public int sq_item { get; private set; }
126+
public int was_sq_slice { get; private set; }
127+
public int sq_ass_item { get; private set; }
128+
public int was_sq_ass_slice { get; private set; }
129+
public int sq_contains { get; private set; }
130+
public int sq_inplace_concat { get; private set; }
131+
public int sq_inplace_repeat { get; private set; }
132+
public int bf_getbuffer { get; private set; }
133+
public int bf_releasebuffer { get; private set; }
134+
public int name { get; private set; }
135+
public int ht_slots { get; private set; }
136+
public int qualname { get; private set; }
137+
public int ht_cached_keys { get; private set; }
138+
public int ht_module { get; private set; }
139+
public int _ht_tpname { get; private set; }
140+
public int spec_cache_getitem { get; private set; }
141+
public int getitem_version { get; private set; }
142+
}
143+
}
144+

src/runtime/PythonEngine.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ public static string PythonPath
135135
}
136136

137137
public static Version MinSupportedVersion => new(3, 7);
138-
public static Version MaxSupportedVersion => new(3, 11, int.MaxValue, int.MaxValue);
138+
public static Version MaxSupportedVersion => new(3, 12, int.MaxValue, int.MaxValue);
139139
public static bool IsSupportedVersion(Version version) => version >= MinSupportedVersion && version <= MaxSupportedVersion;
140140

141141
public static string Version

src/runtime/Runtime.Delegates.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,8 @@ static Delegates()
164164
PyUnicode_AsUTF8 = (delegate* unmanaged[Cdecl]<BorrowedReference, IntPtr>)GetFunctionByName(nameof(PyUnicode_AsUTF8), GetUnmanagedDll(_PythonDll));
165165
PyUnicode_DecodeUTF16 = (delegate* unmanaged[Cdecl]<IntPtr, nint, IntPtr, IntPtr, NewReference>)GetFunctionByName(nameof(PyUnicode_DecodeUTF16), GetUnmanagedDll(_PythonDll));
166166
PyUnicode_GetLength = (delegate* unmanaged[Cdecl]<BorrowedReference, nint>)GetFunctionByName(nameof(PyUnicode_GetLength), GetUnmanagedDll(_PythonDll));
167-
PyUnicode_AsUnicode = (delegate* unmanaged[Cdecl]<BorrowedReference, IntPtr>)GetFunctionByName(nameof(PyUnicode_AsUnicode), GetUnmanagedDll(_PythonDll));
168167
PyUnicode_AsUTF16String = (delegate* unmanaged[Cdecl]<BorrowedReference, NewReference>)GetFunctionByName(nameof(PyUnicode_AsUTF16String), GetUnmanagedDll(_PythonDll));
168+
PyUnicode_ReadChar = (delegate* unmanaged[Cdecl]<BorrowedReference, nint, int>)GetFunctionByName(nameof(PyUnicode_ReadChar), GetUnmanagedDll(_PythonDll));
169169
PyUnicode_FromOrdinal = (delegate* unmanaged[Cdecl]<int, NewReference>)GetFunctionByName(nameof(PyUnicode_FromOrdinal), GetUnmanagedDll(_PythonDll));
170170
PyUnicode_InternFromString = (delegate* unmanaged[Cdecl]<StrPtr, NewReference>)GetFunctionByName(nameof(PyUnicode_InternFromString), GetUnmanagedDll(_PythonDll));
171171
PyUnicode_Compare = (delegate* unmanaged[Cdecl]<BorrowedReference, BorrowedReference, int>)GetFunctionByName(nameof(PyUnicode_Compare), GetUnmanagedDll(_PythonDll));
@@ -441,7 +441,7 @@ static Delegates()
441441
internal static delegate* unmanaged[Cdecl]<BorrowedReference, IntPtr> PyUnicode_AsUTF8 { get; }
442442
internal static delegate* unmanaged[Cdecl]<IntPtr, nint, IntPtr, IntPtr, NewReference> PyUnicode_DecodeUTF16 { get; }
443443
internal static delegate* unmanaged[Cdecl]<BorrowedReference, nint> PyUnicode_GetLength { get; }
444-
internal static delegate* unmanaged[Cdecl]<BorrowedReference, IntPtr> PyUnicode_AsUnicode { get; }
444+
internal static delegate* unmanaged[Cdecl]<BorrowedReference, nint, int> PyUnicode_ReadChar { get; }
445445
internal static delegate* unmanaged[Cdecl]<BorrowedReference, NewReference> PyUnicode_AsUTF16String { get; }
446446
internal static delegate* unmanaged[Cdecl]<int, NewReference> PyUnicode_FromOrdinal { get; }
447447
internal static delegate* unmanaged[Cdecl]<StrPtr, NewReference> PyUnicode_InternFromString { get; }

src/runtime/Runtime.cs

Lines changed: 3 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -598,23 +598,8 @@ internal static void CheckExceptionOccurred()
598598
[Obsolete("Use NewReference or PyObject constructor instead")]
599599
internal static unsafe void XIncref(BorrowedReference op)
600600
{
601-
#if !CUSTOM_INCDEC_REF
602601
Py_IncRef(op);
603602
return;
604-
#else
605-
var p = (void*)op;
606-
if ((void*)0 != p)
607-
{
608-
if (Is32Bit)
609-
{
610-
(*(int*)p)++;
611-
}
612-
else
613-
{
614-
(*(long*)p)++;
615-
}
616-
}
617-
#endif
618603
}
619604

620605
internal static unsafe void XDecref(StolenReference op)
@@ -623,40 +608,9 @@ internal static unsafe void XDecref(StolenReference op)
623608
Debug.Assert(op == null || Refcount(new BorrowedReference(op.Pointer)) > 0);
624609
Debug.Assert(_isInitialized || Py_IsInitialized() != 0 || _Py_IsFinalizing() != false);
625610
#endif
626-
#if !CUSTOM_INCDEC_REF
627611
if (op == null) return;
628612
Py_DecRef(op.AnalyzerWorkaround());
629613
return;
630-
#else
631-
var p = (void*)op;
632-
if ((void*)0 != p)
633-
{
634-
if (Is32Bit)
635-
{
636-
--(*(int*)p);
637-
}
638-
else
639-
{
640-
--(*(long*)p);
641-
}
642-
if ((*(int*)p) == 0)
643-
{
644-
// PyObject_HEAD: struct _typeobject *ob_type
645-
void* t = Is32Bit
646-
? (void*)(*((uint*)p + 1))
647-
: (void*)(*((ulong*)p + 1));
648-
// PyTypeObject: destructor tp_dealloc
649-
void* f = Is32Bit
650-
? (void*)(*((uint*)t + 6))
651-
: (void*)(*((ulong*)t + 6));
652-
if ((void*)0 == f)
653-
{
654-
return;
655-
}
656-
NativeCall.Void_Call_1(new IntPtr(f), op);
657-
}
658-
}
659-
#endif
660614
}
661615

662616
[Pure]
@@ -985,7 +939,7 @@ internal static BorrowedReference PyObject_GetWeakRefList(BorrowedReference ob)
985939
Debug.Assert(ob != null);
986940
var type = PyObject_TYPE(ob);
987941
int offset = Util.ReadInt32(type, TypeOffset.tp_weaklistoffset);
988-
if (offset == 0) return BorrowedReference.Null;
942+
if (offset <= 0) return BorrowedReference.Null;
989943
Debug.Assert(offset > 0);
990944
return Util.ReadRef(ob, offset);
991945
}
@@ -1336,9 +1290,10 @@ internal static IntPtr PyBytes_AsString(BorrowedReference ob)
13361290
internal static nint PyUnicode_GetLength(BorrowedReference ob) => Delegates.PyUnicode_GetLength(ob);
13371291

13381292

1339-
internal static IntPtr PyUnicode_AsUnicode(BorrowedReference ob) => Delegates.PyUnicode_AsUnicode(ob);
13401293
internal static NewReference PyUnicode_AsUTF16String(BorrowedReference ob) => Delegates.PyUnicode_AsUTF16String(ob);
13411294

1295+
internal static int PyUnicode_ReadChar(BorrowedReference ob, nint index) => Delegates.PyUnicode_ReadChar(ob, index);
1296+
13421297

13431298

13441299
internal static NewReference PyUnicode_FromOrdinal(int c) => Delegates.PyUnicode_FromOrdinal(c);

tools/geninterop/geninterop.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ def visit(self, node):
7676
self.visit_ptrdecl(node)
7777
elif isinstance(node, c_ast.IdentifierType):
7878
self.visit_identifier(node)
79+
elif isinstance(node, c_ast.Union):
80+
self.visit_union(node)
7981

8082
def visit_ast(self, ast):
8183
for _name, node in ast.children():
@@ -119,6 +121,16 @@ def visit_identifier(self, identifier):
119121
type_name = " ".join(identifier.names)
120122
self._add_struct_member(type_name)
121123

124+
def visit_union(self, union):
125+
# Treat the field as if it was just the first declaration for now. This
126+
# is not really correct, but handles the one case that is relevant for
127+
# us right now (ob_refcnt being "split" in Python 3.12)
128+
if self._struct_members_stack and union.decls:
129+
decl = union.decls[0]
130+
self._struct_members_stack.pop(0)
131+
self._struct_members_stack.insert(0, decl.name)
132+
self.visit(decl)
133+
122134
def _add_struct_member(self, type_name):
123135
if not (self._struct_stack and self._struct_members_stack):
124136
return
@@ -245,7 +257,7 @@ def gen_interop_head(writer, version, abi_flags):
245257
// Auto-generated by {filename}.
246258
// DO NOT MODIFY BY HAND.
247259
248-
// Python {".".join(version[:2])}: ABI flags: '{abi_flags}'
260+
// Python {".".join(map(str, version[:2]))}: ABI flags: '{abi_flags}'
249261
250262
// ReSharper disable InconsistentNaming
251263
// ReSharper disable IdentifierTypo

0 commit comments

Comments
 (0)
0