Merge lp:~cjwatson/meliae/py310 into lp:meliae

Proposed by Colin Watson
Status: Merged
Approved by: John A Meinel
Approved revision: 232
Merged at revision: 232
Proposed branch: lp:~cjwatson/meliae/py310
Merge into: lp:meliae
Diff against target: 150 lines (+36/-8)
5 files modified
meliae/_scanner.pyx (+2/-1)
meliae/_scanner_core.c (+25/-7)
meliae/_scanner_core.h (+5/-0)
setup.py (+2/-0)
tox.ini (+2/-0)
To merge this branch: bzr merge lp:~cjwatson/meliae/py310
Reviewer Review Type Date Requested Status
John A Meinel Approve
Review via email: mp+429597@code.launchpad.net

Commit message

Add support for Python 3.9 and 3.10.

Description of the change

The hardcoded handling of `sizeof(PyGC_Head)` is kind of a mess, but I can't find any better way to get its size in 3.9 or newer; and unfortunately we now seem to have to do without the optimization for finding the size of dicts without calling into Python.

To post a comment you must log in.
Revision history for this message
John A Meinel (jameinel) wrote :

Thanks for your efforts here.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'meliae/_scanner.pyx'
2--- meliae/_scanner.pyx 2020-02-03 11:37:33 +0000
3+++ meliae/_scanner.pyx 2022-09-07 20:55:53 +0000
4@@ -36,6 +36,7 @@
5
6
7 cdef extern from "_scanner_core.h":
8+ const Py_ssize_t _sizeof_PyGC_Head
9 Py_ssize_t _size_of(object c_obj)
10 ctypedef char* const_pchar "const char*"
11 ctypedef void (*write_callback)(void *callee_data, const_pchar bytes,
12@@ -49,7 +50,7 @@
13
14
15 _word_size = sizeof(Py_ssize_t)
16-_gc_head_size = sizeof(PyGC_Head)
17+_gc_head_size = _sizeof_PyGC_Head
18 _unicode_size = Py_UNICODE_SIZE
19
20
21
22=== modified file 'meliae/_scanner_core.c'
23--- meliae/_scanner_core.c 2020-05-30 00:26:37 +0000
24+++ meliae/_scanner_core.c 2022-09-07 20:55:53 +0000
25@@ -47,6 +47,17 @@
26 # define inline
27 #endif
28
29+#if PY_VERSION_HEX < 0x03090000
30+# define SIZEOF_PYGC_HEAD sizeof(PyGC_Head)
31+#else
32+/* Obviously extremely fragile, but Python 3.9 went to some lengths to make
33+ * this opaque. See Include/internal/pycore_gc.h in Python.
34+ */
35+# define SIZEOF_PYGC_HEAD (2 * sizeof(uintptr_t))
36+#endif
37+
38+const Py_ssize_t _sizeof_PyGC_Head = SIZEOF_PYGC_HEAD;
39+
40 struct ref_info {
41 write_callback write;
42 void *data;
43@@ -83,7 +94,7 @@
44 Py_ssize_t size;
45 size = Py_TYPE(c_obj)->tp_basicsize;
46 if (PyObject_IS_GC(c_obj)) {
47- size += sizeof(PyGC_Head);
48+ size += SIZEOF_PYGC_HEAD;
49 }
50 return size;
51 }
52@@ -123,7 +134,7 @@
53 // There is one trick left. Namely, __sizeof__ doesn't include the
54 // GC overhead, so let's add that back in
55 if (PyObject_IS_GC(c_obj)) {
56- size += sizeof(PyGC_Head);
57+ size += SIZEOF_PYGC_HEAD;
58 }
59 return size;
60 }
61@@ -177,6 +188,10 @@
62 }
63
64
65+#if PY_VERSION_HEX < 0x03090000
66+/* This optimization is too difficult as of Python 3.9, since more of the
67+ * internal structure has become opaque. We'll just rely on __sizeof__.
68+ */
69 static Py_ssize_t
70 _size_of_dict(PyDictObject *c_obj)
71 {
72@@ -221,6 +236,7 @@
73 #endif
74 return size;
75 }
76+#endif
77
78
79 static Py_ssize_t
80@@ -262,7 +278,7 @@
81 ((PyASCIIObject *)c_obj)->length :
82 ((PyCompactUnicodeObject *)c_obj)->utf8_length) + 1;
83 if (PyObject_IS_GC((PyObject *)c_obj)) {
84- size += sizeof(PyGC_Head);
85+ size += SIZEOF_PYGC_HEAD;
86 }
87 #endif
88 return size;
89@@ -330,13 +346,15 @@
90 {
91 Py_ssize_t size;
92
93- if PyList_Check(c_obj) {
94+ if (PyList_Check(c_obj)) {
95 return _size_of_list((PyListObject *)c_obj);
96- } else if PyAnySet_Check(c_obj) {
97+ } else if (PyAnySet_Check(c_obj)) {
98 return _size_of_set((PySetObject *)c_obj);
99- } else if PyDict_Check(c_obj) {
100+#if PY_VERSION_HEX < 0x03090000
101+ } else if (PyDict_Check(c_obj)) {
102 return _size_of_dict((PyDictObject *)c_obj);
103- } else if PyUnicode_Check(c_obj) {
104+#endif
105+ } else if (PyUnicode_Check(c_obj)) {
106 return _size_of_unicode((PyUnicodeObject *)c_obj);
107 } else if (PyLong_CheckExact(c_obj)) {
108 return _size_of_long((PyLongObject *)c_obj);
109
110=== modified file 'meliae/_scanner_core.h'
111--- meliae/_scanner_core.h 2020-02-03 11:37:33 +0000
112+++ meliae/_scanner_core.h 2022-09-07 20:55:53 +0000
113@@ -28,6 +28,11 @@
114 #include <stdio.h>
115
116 /**
117+ * The size of PyGC_Head.
118+ */
119+extern const Py_ssize_t _sizeof_PyGC_Head;
120+
121+/**
122 * Compute the size of the data directly addressed by this object.
123 *
124 * For example, for a list, this is the number of bytes allocated plus the
125
126=== modified file 'setup.py'
127--- setup.py 2020-05-05 12:25:08 +0000
128+++ setup.py 2022-09-07 20:55:53 +0000
129@@ -57,6 +57,8 @@
130 'Programming Language :: Python :: 3.6',
131 'Programming Language :: Python :: 3.7',
132 'Programming Language :: Python :: 3.8',
133+ 'Programming Language :: Python :: 3.9',
134+ 'Programming Language :: Python :: 3.10',
135 'Programming Language :: Cython',
136 'Topic :: Software Development :: Debuggers',
137 ],
138
139=== modified file 'tox.ini'
140--- tox.ini 2020-05-05 11:07:45 +0000
141+++ tox.ini 2022-09-07 20:55:53 +0000
142@@ -6,6 +6,8 @@
143 py36
144 py37
145 py38
146+ py39
147+ py310
148
149 [testenv]
150 deps =

Subscribers

People subscribed via source and target branches

to all changes: