diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 70f1e4a2..c05a2fa8 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -65,7 +65,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- python-version: ["3.5", "3.6", "3.7", "3.8", "3.9", "3.10", "3.11"]
+ python-version: ["3.8", "3.9", "3.10", "3.11"]
env:
AUSTIN_TESTS_PYTHON_VERSIONS: ${{ matrix.python-version }}
@@ -194,7 +194,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- python-version: ["2.7", "3.5", "3.6", "3.7", "3.8", "3.9", "3.10", "3.11"]
+ python-version: ["3.8", "3.9", "3.10", "3.11"]
env:
AUSTIN_TESTS_PYTHON_VERSIONS: ${{ matrix.python-version }}
@@ -303,7 +303,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- python-version: ["2.7", "3.5", "3.6", "3.7", "3.8", "3.9", "3.10", "3.11"]
+ python-version: ["3.8", "3.9", "3.10", "3.11"]
env:
AUSTIN_TESTS_PYTHON_VERSIONS: ${{ matrix.python-version }}
@@ -381,7 +381,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- python-version: ["3.5", "3.6", "3.7", "3.8", "3.9", "3.10", "3.11"]
+ python-version: ["3.8", "3.9", "3.10", "3.11"]
env:
AUSTIN_TESTS_PYTHON_VERSIONS: ${{ matrix.python-version }}
diff --git a/ChangeLog b/ChangeLog
index 7b182165..00aab9f1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2023-xx-xx v3.6.0
+
+ Dropped support for Python 2, 3.3, 3.4, 3.5, 3.6 and 3.7.
+
+
2023-02-21 v3.5.0
Added support for fine-grained, column-level location information when
diff --git a/README.md b/README.md
index e5dc0e61..aaf96fb1 100644
--- a/README.md
+++ b/README.md
@@ -581,7 +581,7 @@ folder in either the SVG, PDF or PNG format
# Compatibility
-Austin supports Python 2.3-2.7 and 3.3-3.11 and has been tested on the
+Austin supports Python 3.8-3.11 and has been tested on the
following platforms and architectures
| | | | |
@@ -594,7 +594,8 @@ following platforms and architectures
> **NOTE** Austin *might* work with other versions of Python on all the
> platforms and architectures above. So it is worth giving it a try even if
-> your system is not listed below.
+> your system is not listed below. If you are looking for support for Python <
+> 3.8, you can use Austin 3.5.
Because of platform-specific details, Austin usage may vary slightly. Below are
further compatibility details to be aware of.
diff --git a/configure.ac b/configure.ac
index 8cda77ff..1f62949c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6,7 +6,7 @@ AC_PREREQ([2.69])
# from scripts.utils import get_current_version_from_changelog as version
# print(f"AC_INIT([austin], [{version()}], [https://github.com/p403n1x87/austin/issues])")
# ]]]
-AC_INIT([austin], [3.5.0], [https://github.com/p403n1x87/austin/issues])
+AC_INIT([austin], [3.6.0], [https://github.com/p403n1x87/austin/issues])
# [[[end]]]
AC_CONFIG_SRCDIR([config.h.in])
AC_CONFIG_HEADERS([config.h])
diff --git a/doc/cheatsheet.pdf b/doc/cheatsheet.pdf
index ceb0183a..9a5b6739 100644
Binary files a/doc/cheatsheet.pdf and b/doc/cheatsheet.pdf differ
diff --git a/doc/cheatsheet.png b/doc/cheatsheet.png
index b66f0831..fecbd6fb 100644
Binary files a/doc/cheatsheet.png and b/doc/cheatsheet.png differ
diff --git a/doc/cheatsheet.svg b/doc/cheatsheet.svg
index ed54a09a..8ab215aa 100644
--- a/doc/cheatsheet.svg
+++ b/doc/cheatsheet.svg
@@ -7,7 +7,7 @@
viewBox="0 0 210 297"
version="1.1"
id="svg8"
- inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
+ inkscape:version="1.2.2 (b0a8486, 2022-12-01)"
sodipodi:docname="cheatsheet.svg"
inkscape:export-filename="/home/gabriele/Projects/austin/doc/cheatsheet.png"
inkscape:export-xdpi="191.99664"
@@ -757,17 +757,19 @@
inkscape:pageopacity="1"
inkscape:pageshadow="2"
inkscape:zoom="1.4"
- inkscape:cx="355.35714"
- inkscape:cy="-3878.5714"
+ inkscape:cx="273.21429"
+ inkscape:cy="20"
inkscape:document-units="mm"
- inkscape:current-layer="layer1"
+ inkscape:current-layer="layer3"
showgrid="false"
- inkscape:window-width="2560"
- inkscape:window-height="1413"
+ inkscape:window-width="1440"
+ inkscape:window-height="900"
inkscape:window-x="0"
- inkscape:window-y="328"
- inkscape:window-maximized="1"
- inkscape:pagecheckerboard="0" />
+ inkscape:window-y="0"
+ inkscape:window-maximized="0"
+ inkscape:pagecheckerboard="0"
+ inkscape:showpageshadow="2"
+ inkscape:deskcolor="#ebece0" />
@@ -6340,7 +6342,7 @@
y="293.48233"
x="49.886612"
id="tspan9522"
- sodipodi:role="line">2.3 thru 2.7 and 3.3 thru 3.11
+ sodipodi:role="line">3.8 | 3.9 | 3.10 | 3.11
CHEATSHEET
for version 3.5
+ sodipodi:role="line">for version 3.6
filename);
p++;
*major = *(p++) - '0';
- if (*major != 2 && *major != 3) {
+ if (*major != 3) {
FAIL;
}
@@ -175,7 +175,6 @@ _get_version_from_filename(char * filename, const char * needle, int * major, in
#elif defined PL_MACOS /* MAC */
char * ver_needle = strstr(filename, "3.");
- if (ver_needle == NULL) ver_needle = strstr(filename, "2.");
if (ver_needle != NULL && sscanf(ver_needle, "%d.%d", major, minor) == 2) {
SUCCESS;
}
@@ -323,30 +322,6 @@ _py_proc__infer_python_version(py_proc_t * self) {
set_version:
self->py_v = get_version_descriptor(major, minor, patch);
SUCCESS;
-
- // Scan the rodata section for something that looks like the Python version.
- // There are good chances this is at the very beginning of the section so
- // it shouldn't take too long to find a match. This is more reliable than
- // waiting until the version appears in the bss section at run-time.
- // NOTE: This method is not guaranteed to find a valid Python version.
- // If this causes problems then another method is required.
- // char * p_ver = (char *) map + (Elf64_Addr) self->map.rodata.base;
- // for (register int i = 0; i < self->map.rodata.size; i++) {
- // if (
- // p_ver[i] == '.' &&
- // p_ver[i+1] != '.' &&
- // p_ver[i+2] == '.' &&
- // p_ver[i-2] == 0
- // ) {
- // if (
- // sscanf(p_ver + i - 1, "%d.%d.%d", &major, &minor, &patch) == 3 &&
- // (major == 2 || major == 3)
- // ) {
- // log_i("Python version: %s", p_ver + i - 1, p_ver);
- // // break;
- // }
- // }
- // }
}
@@ -434,57 +409,6 @@ _py_proc__check_interp_state(py_proc_t * self, void * raddr) {
SUCCESS;
}
-
-#ifdef CHECK_HEAP
-// ----------------------------------------------------------------------------
-static int
-_py_proc__is_heap_raddr(py_proc_t * self, void * raddr) {
- if (!isvalid(self) || !isvalid(raddr) || !isvalid(self->map.heap.base))
- return FALSE;
-
- return (
- raddr >= self->map.heap.base &&
- raddr < self->map.heap.base + self->map.heap.size
- );
-}
-
-
-// ----------------------------------------------------------------------------
-static int
-_py_proc__is_raddr_within_max_range(py_proc_t * self, void * raddr) {
- if (!isvalid(self) || !isvalid(raddr) || !isvalid(self->map.heap.base))
- return FALSE;
-
- return (raddr >= self->min_raddr && raddr < self->max_raddr);
-}
-
-
-// ----------------------------------------------------------------------------
-static int
-_py_proc__scan_heap(py_proc_t * self) {
- log_d("Scanning HEAP");
- // NOTE: This seems to be required by Python 2.7 on i386 Linux.
- void * upper_bound = self->map.heap.base + self->map.heap.size;
- for (
- register void ** raddr = (void **) self->map.heap.base;
- (void *) raddr < upper_bound;
- raddr++
- ) {
- switch (_py_proc__check_interp_state(self, raddr)) {
- case 0:
- self->is_raddr = raddr;
- SUCCESS;
-
- case OUT_OF_BOUND:
- return OUT_OF_BOUND;
- }
- }
-
- FAIL;
-}
-#endif
-
-
// ----------------------------------------------------------------------------
static int
_py_proc__scan_bss(py_proc_t * self) {
@@ -531,11 +455,6 @@ _py_proc__scan_bss(py_proc_t * self) {
) {
if (
(!shift &&
- #ifdef CHECK_HEAP
- (isvalid(self->lib_path)
- ? _py_proc__is_raddr_within_max_range(self, *raddr)
- : _py_proc__is_heap_raddr(self, *raddr)) &&
- #endif
success(_py_proc__check_interp_state(self, *raddr)))
||(shift && success(_py_proc__check_interp_state(self, (void*) raddr - self->bss + base)))
) {
@@ -755,22 +674,6 @@ _py_proc__wait_for_interp_state(py_proc_t * self) {
if (self->child)
FAIL;
- #ifdef CHECK_HEAP
- log_w("BSS scan unsuccessful so we scan the heap directly ...");
-
- // TODO: Consider copying heap over and check for pointers
- TIMER_SET(100)
- TIMER_START
- switch (_py_proc__scan_heap(self)) {
- case 0:
- SUCCESS;
-
- case OUT_OF_BOUND:
- TIMER_STOP
- }
- TIMER_END
- #endif
-
set_error(EPROCISTIMEOUT);
FAIL;
} // _py_proc__wait_for_interp_state
diff --git a/src/py_string.h b/src/py_string.h
index d1651687..b6db19f4 100644
--- a/src/py_string.h
+++ b/src/py_string.h
@@ -57,59 +57,38 @@ string__hash(char * string) {
// ----------------------------------------------------------------------------
static inline char *
_string_from_raddr(proc_ref_t pref, void * raddr, python_v * py_v) {
- PyStringObject string;
PyUnicodeObject3 unicode;
char * buffer = NULL;
ssize_t len = 0;
- // This switch statement is required by the changes regarding the string type
- // introduced in Python 3.
- switch (py_v->major) {
- case 2:
- if (fail(copy_datatype(pref, raddr, string))) {
- log_ie("Cannot read remote PyStringObject");
- goto failed;
- }
-
- len = string.ob_base.ob_size;
- buffer = (char *) malloc(len + 1);
- if (fail(copy_memory(pref, raddr + offsetof(PyStringObject, ob_sval), len, buffer))) {
- log_ie("Cannot read remote value of PyStringObject");
- goto failed;
- }
- buffer[len] = 0;
- break;
-
- case 3:
- if (fail(copy_datatype(pref, raddr, unicode))) {
- log_ie("Cannot read remote PyUnicodeObject3");
- goto failed;
- }
-
- PyASCIIObject ascii = unicode._base._base;
-
- if (ascii.state.kind != 1) {
- set_error(ECODEFMT);
- goto failed;
- }
-
- void * data = ascii.state.compact ? p_ascii_data(raddr) : unicode._base.utf8;
- len = ascii.state.compact ? ascii.length : unicode._base.utf8_length;
-
- if (len < 0 || len > 4096) {
- log_e("Invalid string length");
- goto failed;
- }
-
- buffer = (char *) malloc(len + 1);
-
- if (!isvalid(data) || fail(copy_memory(pref, data, len, buffer))) {
- log_ie("Cannot read remote value of PyUnicodeObject3");
- goto failed;
- }
- buffer[len] = 0;
+ if (fail(copy_datatype(pref, raddr, unicode))) {
+ log_ie("Cannot read remote PyUnicodeObject3");
+ goto failed;
}
+ PyASCIIObject ascii = unicode._base._base;
+
+ if (ascii.state.kind != 1) {
+ set_error(ECODEFMT);
+ goto failed;
+ }
+
+ void * data = ascii.state.compact ? p_ascii_data(raddr) : unicode._base.utf8;
+ len = ascii.state.compact ? ascii.length : unicode._base.utf8_length;
+
+ if (len < 0 || len > 4096) {
+ log_e("Invalid string length");
+ goto failed;
+ }
+
+ buffer = (char *) malloc(len + 1);
+
+ if (!isvalid(data) || fail(copy_memory(pref, data, len, buffer))) {
+ log_ie("Cannot read remote value of PyUnicodeObject3");
+ goto failed;
+ }
+ buffer[len] = 0;
+
return buffer;
failed:
@@ -121,51 +100,25 @@ _string_from_raddr(proc_ref_t pref, void * raddr, python_v * py_v) {
// ----------------------------------------------------------------------------
static inline unsigned char *
_bytes_from_raddr(proc_ref_t pref, void * raddr, ssize_t * size, python_v * py_v) {
- PyStringObject string;
PyBytesObject bytes;
ssize_t len = 0;
unsigned char * array = NULL;
- switch (py_v->major) {
- case 2: // Python 2
- if (fail(copy_datatype(pref, raddr, string))) {
- log_ie("Cannot read remote PyStringObject");
- goto error;
- }
-
- len = string.ob_base.ob_size + 1;
- if (py_v->minor <= 4) {
- // In Python 2.4, the ob_size field is of type int. If we cannot
- // allocate on the first try it's because we are getting a ridiculous
- // value for len. In that case, chop it down to an int and try again.
- // This approach is simpler than adding version support.
- len = (int) len;
- }
-
- array = (unsigned char *) malloc((len + 1) * sizeof(unsigned char *));
- if (fail(copy_memory(pref, raddr + offsetof(PyStringObject, ob_sval), len, array))) {
- log_ie("Cannot read remote value of PyStringObject");
- goto error;
- }
- break;
-
- case 3: // Python 3
- if (fail(copy_datatype(pref, raddr, bytes))) {
- log_ie("Cannot read remote PyBytesObject");
- goto error;
- }
-
- if ((len = bytes.ob_base.ob_size + 1) < 1) { // Include null-terminator
- set_error(ECODEBYTES);
- log_e("PyBytesObject is too short");
- goto error;
- }
-
- array = (unsigned char *) malloc((len + 1) * sizeof(unsigned char *));
- if (fail(copy_memory(pref, raddr + offsetof(PyBytesObject, ob_sval), len, array))) {
- log_ie("Cannot read remote value of PyBytesObject");
- goto error;
- }
+ if (fail(copy_datatype(pref, raddr, bytes))) {
+ log_ie("Cannot read remote PyBytesObject");
+ goto error;
+ }
+
+ if ((len = bytes.ob_base.ob_size + 1) < 1) { // Include null-terminator
+ set_error(ECODEBYTES);
+ log_e("PyBytesObject is too short");
+ goto error;
+ }
+
+ array = (unsigned char *) malloc((len + 1) * sizeof(unsigned char *));
+ if (fail(copy_memory(pref, raddr + offsetof(PyBytesObject, ob_sval), len, array))) {
+ log_ie("Cannot read remote value of PyBytesObject");
+ goto error;
}
array[len] = 0;
diff --git a/src/py_thread.c b/src/py_thread.c
index a542ef16..15c92d08 100644
--- a/src/py_thread.c
+++ b/src/py_thread.c
@@ -946,8 +946,7 @@ py_thread__emit_collapsed_stack(py_thread_t * self, ctime_t time_delta, ssize_t
int is_frame_eval = FALSE;
if (isvalid(eval_frame_fn)) {
char c = *(eval_frame_fn+16);
- V_DESC(self->proc->py_v);
- is_frame_eval = (c == 'D') || (V_MAX(3, 5) && c == 'E');
+ is_frame_eval = (c == 'D');
}
if (!stack_is_empty() && is_frame_eval) {
// TODO: if the py stack is empty we have a mismatch.
diff --git a/src/python/code.h b/src/python/code.h
index b4438e33..74aed199 100644
--- a/src/python/code.h
+++ b/src/python/code.h
@@ -32,64 +32,6 @@
// ---- code.h ----------------------------------------------------------------
-typedef struct {
- PyObject_HEAD
- int co_argcount; /* #arguments, except *args */
- int co_nlocals; /* #local variables */
- int co_stacksize; /* #entries needed for evaluation stack */
- int co_flags; /* CO_..., see below */
- PyObject *co_code; /* instruction opcodes */
- PyObject *co_consts; /* list (constants used) */
- PyObject *co_names; /* list of strings (names used) */
- PyObject *co_varnames; /* tuple of strings (local variable names) */
- PyObject *co_freevars; /* tuple of strings (free variable names) */
- PyObject *co_cellvars; /* tuple of strings (cell variable names) */
- PyObject *co_filename; /* string (where it was loaded from) */
- PyObject *co_name; /* string (name, for reference) */
- int co_firstlineno; /* first source line number */
- PyObject *co_lnotab; /* string (encoding addr<->lineno mapping) */
-} PyCodeObject2;
-
-typedef struct {
- PyObject_HEAD
- int co_argcount; /* #arguments, except *args */
- int co_kwonlyargcount; /* #keyword only arguments */
- int co_nlocals; /* #local variables */
- int co_stacksize; /* #entries needed for evaluation stack */
- int co_flags; /* CO_..., see below */
- PyObject *co_code; /* instruction opcodes */
- PyObject *co_consts; /* list (constants used) */
- PyObject *co_names; /* list of strings (names used) */
- PyObject *co_varnames; /* tuple of strings (local variable names) */
- PyObject *co_freevars; /* tuple of strings (free variable names) */
- PyObject *co_cellvars; /* tuple of strings (cell variable names) */
- unsigned char *co_cell2arg; /* Maps cell vars which are arguments. */
- PyObject *co_filename; /* unicode (where it was loaded from) */
- PyObject *co_name; /* unicode (name, for reference) */
- int co_firstlineno; /* first source line number */
- PyObject *co_lnotab; /* string (encoding addr<->lineno mapping) */
-} PyCodeObject3_3;
-
-typedef struct {
- PyObject_HEAD
- int co_argcount; /* #arguments, except *args */
- int co_kwonlyargcount; /* #keyword only arguments */
- int co_nlocals; /* #local variables */
- int co_stacksize; /* #entries needed for evaluation stack */
- int co_flags; /* CO_..., see below */
- int co_firstlineno; /* first source line number */
- PyObject *co_code; /* instruction opcodes */
- PyObject *co_consts; /* list (constants used) */
- PyObject *co_names; /* list of strings (names used) */
- PyObject *co_varnames; /* tuple of strings (local variable names) */
- PyObject *co_freevars; /* tuple of strings (free variable names) */
- PyObject *co_cellvars; /* tuple of strings (cell variable names) */
- unsigned char *co_cell2arg; /* Maps cell vars which are arguments. */
- PyObject *co_filename; /* unicode (where it was loaded from) */
- PyObject *co_name; /* unicode (name, for reference) */
- PyObject *co_lnotab; /* string (encoding addr<->lineno mapping) */
-} PyCodeObject3_6;
-
typedef struct {
PyObject_HEAD
int co_argcount; /* #arguments, except *args */
@@ -151,9 +93,6 @@ typedef struct _PyCode_DEF_311(1) PyCodeObject3_11;
typedef union {
- PyCodeObject2 v2;
- PyCodeObject3_3 v3_3;
- PyCodeObject3_6 v3_6;
PyCodeObject3_8 v3_8;
PyCodeObject3_11 v3_11;
} PyCodeObject;
diff --git a/src/python/frame.h b/src/python/frame.h
index 76a471e8..cd51b320 100644
--- a/src/python/frame.h
+++ b/src/python/frame.h
@@ -33,24 +33,6 @@
// ---- frameobject.h ---------------------------------------------------------
-typedef struct _frame2_3 {
- PyObject_VAR_HEAD
- struct _frame2_3 *f_back; /* previous frame, or NULL */
- PyCodeObject *f_code; /* code segment */
- PyObject *f_builtins; /* builtin symbol table (PyDictObject) */
- PyObject *f_globals; /* global symbol table (PyDictObject) */
- PyObject *f_locals; /* local symbol table (any mapping) */
- PyObject **f_valuestack; /* points after the last local */
- PyObject **f_stacktop;
- PyObject *f_trace; /* Trace function */
-
- PyObject *f_exc_type, *f_exc_value, *f_exc_traceback;
- PyObject *f_gen;
-
- int f_lasti; /* Last instruction if called */
- int f_lineno; /* Current line number */
-} PyFrameObject2;
-
typedef struct _frame3_7 {
PyObject_VAR_HEAD
struct _frame3_7 *f_back; /* previous frame, or NULL */
@@ -90,7 +72,6 @@ typedef struct _frame3_10 {
} PyFrameObject3_10;
typedef union {
- PyFrameObject2 v2;
PyFrameObject3_7 v3_7;
PyFrameObject3_10 v3_10;
} PyFrameObject;
diff --git a/src/python/gc.h b/src/python/gc.h
index 85ac238c..9ce10f4d 100644
--- a/src/python/gc.h
+++ b/src/python/gc.h
@@ -34,15 +34,6 @@
// ---- include/objimpl.h -----------------------------------------------------
-typedef union _gc_head3_7 {
- struct {
- union _gc_head3_7 *gc_next;
- union _gc_head3_7 *gc_prev;
- Py_ssize_t gc_refs;
- } gc;
- long double dummy; /* force worst-case alignment */
-} PyGC_Head3_7;
-
typedef struct {
uintptr_t _gc_next;
uintptr_t _gc_prev;
@@ -52,13 +43,6 @@ typedef struct {
#define NUM_GENERATIONS 3
-struct gc_generation3_7 {
- PyGC_Head3_7 head;
- int threshold; /* collection threshold */
- int count; /* count of allocations or collections of younger
- generations */
-};
-
struct gc_generation3_8 {
PyGC_Head3_8 head;
@@ -74,18 +58,6 @@ struct gc_generation_stats {
Py_ssize_t uncollectable;
};
-struct _gc_runtime_state3_7 {
- PyObject *trash_delete_later;
- int trash_delete_nesting;
- int enabled;
- int debug;
- struct gc_generation3_7 generations[NUM_GENERATIONS];
- PyGC_Head3_7 *generation0;
- struct gc_generation3_7 permanent_generation;
- struct gc_generation_stats generation_stats[NUM_GENERATIONS];
- int collecting;
-};
-
struct _gc_runtime_state3_8 {
PyObject *trash_delete_later;
int trash_delete_nesting;
@@ -99,7 +71,6 @@ struct _gc_runtime_state3_8 {
};
typedef union {
- struct _gc_runtime_state3_7 v3_7;
struct _gc_runtime_state3_8 v3_8;
} GCRuntimeState;
diff --git a/src/python/runtime.h b/src/python/runtime.h
index 22f7722a..44d0bc51 100644
--- a/src/python/runtime.h
+++ b/src/python/runtime.h
@@ -34,29 +34,6 @@
#include "misc.h"
#include "thread.h"
-// ---- internal/pystate.h ----------------------------------------------------
-
-typedef struct pyruntimestate3_7 {
- int initialized;
- int core_initialized;
- PyThreadState *finalizing;
-
- struct pyinterpreters3_7 {
- PyThread_type_lock mutex;
- PyInterpreterState *head;
- PyInterpreterState *main;
- int64_t next_id;
- } interpreters;
-#define NEXITFUNCS 32
- void (*exitfuncs[NEXITFUNCS])(void);
- int nexitfuncs;
-
- struct _gc_runtime_state3_7 gc;
- // struct _warnings_runtime_state warnings;
- // struct _ceval_runtime_state ceval;
- // struct _gilstate_runtime_state gilstate;
-} _PyRuntimeState3_7;
-
// ---- internal/pycore_pystate.h ---------------------------------------------
typedef struct pyruntimestate3_8 {
@@ -125,7 +102,6 @@ typedef struct pyruntimestate3_11 {
typedef union {
- _PyRuntimeState3_7 v3_7;
_PyRuntimeState3_8 v3_8;
_PyRuntimeState3_11 v3_11;
} _PyRuntimeState;
diff --git a/src/python/string.h b/src/python/string.h
index 56bd0a18..ed36fa3d 100644
--- a/src/python/string.h
+++ b/src/python/string.h
@@ -42,16 +42,6 @@ typedef uint8_t Py_UCS1;
typedef PY_UNICODE_TYPE Py_UNICODE;
-
-typedef struct {
- PyObject_HEAD
- Py_ssize_t length; /* Length of raw Unicode data in buffer */
- Py_UNICODE *str; /* Raw Unicode buffer */
- long hash; /* Hash value; -1 if not set */
- PyObject *defenc; /* (Default) Encoded version as Python string */
-} PyUnicodeObject2;
-
-
typedef Py_ssize_t Py_hash_t;
typedef struct {
@@ -91,7 +81,6 @@ typedef struct {
typedef union {
- PyUnicodeObject2 v2;
PyUnicodeObject3 v3;
} PyUnicodeObject;
diff --git a/src/python/thread.h b/src/python/thread.h
index 56d94a11..44270ba1 100644
--- a/src/python/thread.h
+++ b/src/python/thread.h
@@ -40,107 +40,11 @@ struct _frame;
typedef int (*Py_tracefunc)(PyObject *, struct _frame *, int, PyObject *);
-typedef struct _ts2 {
- struct _ts2 *next;
- PyInterpreterState *interp;
-
- struct _frame *frame;
- int recursion_depth;
- char overflowed;
- char recursion_critical;
- int tracing;
- int use_tracing;
-
- Py_tracefunc c_profilefunc;
- Py_tracefunc c_tracefunc;
- PyObject *c_profileobj;
- PyObject *c_traceobj;
-
- PyObject *curexc_type;
- PyObject *curexc_value;
- PyObject *curexc_traceback;
-
- PyObject *exc_type;
- PyObject *exc_value;
- PyObject *exc_traceback;
-
- PyObject *dict; /* Stores per-thread state */
-
- int tick_counter;
-
- int gilstate_counter;
-
- PyObject *async_exc; /* Asynchronous exception to raise */
- long thread_id; /* Thread id where this tstate was created */
-} PyThreadState2;
-
-
-typedef struct _ts3_4 {
- struct _ts3_4 *prev;
- struct _ts3_4 *next;
- PyInterpreterState *interp;
-
- struct _frame *frame;
- int recursion_depth;
- char overflowed;
- char recursion_critical;
- int tracing;
- int use_tracing;
-
- Py_tracefunc c_profilefunc;
- Py_tracefunc c_tracefunc;
- PyObject *c_profileobj;
- PyObject *c_traceobj;
-
- PyObject *curexc_type;
- PyObject *curexc_value;
- PyObject *curexc_traceback;
-
- PyObject *exc_type;
- PyObject *exc_value;
- PyObject *exc_traceback;
-
- PyObject *dict; /* Stores per-thread state */
-
- int gilstate_counter;
-
- PyObject *async_exc; /* Asynchronous exception to raise */
- long thread_id; /* Thread id where this tstate was created */
-} PyThreadState3_4;
-
-
-
typedef struct _err_stackitem3_7 {
PyObject *exc_type, *exc_value, *exc_traceback;
struct _err_stackitem3_7 *previous_item;
} _PyErr_StackItem3_7;
-typedef struct _ts_3_7 {
- struct _ts *prev;
- struct _ts *next;
- PyInterpreterState *interp;
- struct _frame *frame;
- int recursion_depth;
- char overflowed;
- char recursion_critical;
- int stackcheck_counter;
- int tracing;
- int use_tracing;
- Py_tracefunc c_profilefunc;
- Py_tracefunc c_tracefunc;
- PyObject *c_profileobj;
- PyObject *c_traceobj;
- PyObject *curexc_type;
- PyObject *curexc_value;
- PyObject *curexc_traceback;
- _PyErr_StackItem3_7 exc_state;
- _PyErr_StackItem3_7 *exc_info;
- PyObject *dict; /* Stores per-thread state */
- int gilstate_counter;
- PyObject *async_exc; /* Asynchronous exception to raise */
- unsigned long thread_id; /* Thread id where this tstate was created */
-} PyThreadState3_7;
-
typedef struct _ts3_8 {
struct _ts *prev;
@@ -249,8 +153,6 @@ typedef struct _ts3_11 {
typedef union {
- PyThreadState2 v2;
- PyThreadState3_4 v3_4;
PyThreadState3_8 v3_8;
PyThreadState3_11 v3_11;
} PyThreadState;
diff --git a/src/version.h b/src/version.h
index 6c373571..e2022942 100644
--- a/src/version.h
+++ b/src/version.h
@@ -79,8 +79,8 @@
* @return TRUE if the current version is at least/at most the requested one,
* FALSE otherwise.
*/
-#define V_MIN(M, m) (py_v->major > M || (py_v->major == M && py_v->minor >= m))
-#define V_MAX(M, m) (py_v->major < M || (py_v->major == M && py_v->minor <= m))
+#define V_MIN(M, m) (((py_v->major << 8) | py_v->minor) >= ((M << 8) | m))
+#define V_MAX(M, m) (((py_v->major << 8) | py_v->minor) <= ((M << 8) | m))
typedef unsigned long offset_t;
@@ -234,17 +234,6 @@ typedef struct {
offsetof(s, is_entry), \
}
-
-/* Hack. Python 3.3 and below don't have the prev field */
-#define PY_THREAD_2(s) { \
- sizeof(s), \
- offsetof(s, next), \
- offsetof(s, next), \
- offsetof(s, interp), \
- offsetof(s, frame), \
- offsetof(s, thread_id) \
-}
-
#define PY_THREAD(s) { \
sizeof(s), \
offsetof(s, prev), \
@@ -305,53 +294,6 @@ typedef struct {
offsetof(s, collecting), \
}
-// ---- Python 2 --------------------------------------------------------------
-
-python_v python_v2 = {
- PY_CODE (PyCodeObject2),
- PY_FRAME (PyFrameObject2),
- PY_THREAD_2 (PyThreadState2),
- PY_IS (PyInterpreterState2),
-};
-
-// ---- Python 3.3 ------------------------------------------------------------
-
-python_v python_v3_3 = {
- PY_CODE (PyCodeObject3_3),
- PY_FRAME (PyFrameObject2),
- PY_THREAD_2 (PyThreadState2),
- PY_IS (PyInterpreterState2),
-};
-
-// ---- Python 3.4 ------------------------------------------------------------
-
-python_v python_v3_4 = {
- PY_CODE (PyCodeObject3_3),
- PY_FRAME (PyFrameObject2),
- PY_THREAD (PyThreadState3_4),
- PY_IS (PyInterpreterState2),
-};
-
-// ---- Python 3.6 ------------------------------------------------------------
-
-python_v python_v3_6 = {
- PY_CODE (PyCodeObject3_6),
- PY_FRAME (PyFrameObject2),
- PY_THREAD (PyThreadState3_4),
- PY_IS (PyInterpreterState2),
-};
-
-// ---- Python 3.7 ------------------------------------------------------------
-
-python_v python_v3_7 = {
- PY_CODE (PyCodeObject3_6),
- PY_FRAME (PyFrameObject3_7),
- PY_THREAD (PyThreadState3_7),
- PY_IS (PyInterpreterState2),
- PY_RUNTIME (_PyRuntimeState3_7),
- PY_GC (struct _gc_runtime_state3_7),
-};
-
// ---- Python 3.8 ------------------------------------------------------------
python_v python_v3_8 = {
@@ -409,48 +351,19 @@ get_version_descriptor(int major, int minor, int patch) {
switch (major) {
- // ---- Python 2 ------------------------------------------------------------
- case 2:
+ // ---- Python 3 ------------------------------------------------------------
+ case 3:
switch (minor) {
case 0:
case 1:
case 2:
- UNSUPPORTED_VERSION; // NOTE: These versions haven't been tested.
-
- // 2.3, 2.4, 2.5, 2.6, 2.7
case 3:
case 4:
case 5:
case 6:
- case 7: py_v = &python_v2;
- break;
-
- default: py_v = &python_v2;
- UNSUPPORTED_VERSION;
- }
- break;
-
- // ---- Python 3 ------------------------------------------------------------
- case 3:
- switch (minor) {
- case 0:
- case 1:
- case 2:
+ case 7:
UNSUPPORTED_VERSION; // NOTE: These versions haven't been tested.
- // 3.3
- case 3: py_v = &python_v3_3; break;
-
- // 3.4, 3.5
- case 4:
- case 5: py_v = &python_v3_4; break;
-
- // 3.6
- case 6: py_v = &python_v3_6; break;
-
- // 3.7
- case 7: py_v = &python_v3_7; break;
-
// 3.8
case 8: py_v = &python_v3_8; break;
diff --git a/src/win/py_proc.h b/src/win/py_proc.h
index 2454f237..8ac39c00 100644
--- a/src/win/py_proc.h
+++ b/src/win/py_proc.h
@@ -30,7 +30,6 @@
#include "../resources.h"
-#define CHECK_HEAP
#define DEREF_SYM
diff --git a/test/__init__.py b/test/__init__.py
index f1543e76..2e9b4318 100644
--- a/test/__init__.py
+++ b/test/__init__.py
@@ -1,7 +1,6 @@
import os
import platform
-
PY3_LATEST = 11
try:
@@ -16,9 +15,9 @@
match platform.system():
case "Darwin":
PYTHON_VERSIONS = REQUESTED_PYTHON_VERSIONS or [
- (3, _) for _ in range(7, PY3_LATEST + 1)
+ (3, _) for _ in range(8, PY3_LATEST + 1)
]
case _:
- PYTHON_VERSIONS = REQUESTED_PYTHON_VERSIONS or [(2, 7)] + [
- (3, _) for _ in range(5, PY3_LATEST + 1)
+ PYTHON_VERSIONS = REQUESTED_PYTHON_VERSIONS or [
+ (3, _) for _ in range(8, PY3_LATEST + 1)
]