Backport a commit improving Python 3.12 compatibility

This commit is contained in:
Nikola Forró 2023-06-15 11:30:36 +02:00
parent 74d7e8a3bb
commit ba93f465fb
2 changed files with 513 additions and 0 deletions

View File

@ -19,6 +19,9 @@ Source0: %{pypi_source awscrt}
# one test requires internet connection, skip it
Patch0: skip-test-requiring-network.patch
# backport of https://github.com/awslabs/aws-crt-python/commit/7431e2d562f622a782b89c4ef8f22de5e710e236
Patch1: python3.12.patch
BuildRequires: python%{python3_pkgversion}-devel
BuildRequires: gcc

510
python3.12.patch Normal file
View File

@ -0,0 +1,510 @@
diff --git a/setup.py b/setup.py
index 36a8cdc..0b106b2 100644
--- a/setup.py
+++ b/setup.py
@@ -14,10 +14,11 @@ import shutil
import subprocess
import sys
import sysconfig
+from wheel.bdist_wheel import bdist_wheel
def is_64bit():
- return sys.maxsize > 2**32
+ return sys.maxsize > 2 ** 32
def is_32bit():
@@ -152,7 +153,6 @@ AWS_LIBS.append(AwsLib('aws-c-auth'))
AWS_LIBS.append(AwsLib('aws-c-mqtt'))
AWS_LIBS.append(AwsLib('aws-c-s3'))
-
PROJECT_DIR = os.path.dirname(os.path.realpath(__file__))
VERSION_RE = re.compile(r""".*__version__ = ["'](.*?)['"]""", re.S)
@@ -283,11 +283,23 @@ class awscrt_build_ext(setuptools.command.build_ext.build_ext):
super().run()
+class bdist_wheel_abi3(bdist_wheel):
+ def get_tag(self):
+ python, abi, plat = super().get_tag()
+ if python.startswith("cp") and sys.version_info >= (3, 11):
+ # on CPython, our wheels are abi3 and compatible back to 3.11
+ return "cp311", "abi3", plat
+
+ return python, abi, plat
+
+
def awscrt_ext():
# fetch the CFLAGS/LDFLAGS from env
extra_compile_args = os.environ.get('CFLAGS', '').split()
extra_link_args = os.environ.get('LDFLAGS', '').split()
extra_objects = []
+ define_macros = []
+ py_limited_api = False
libraries = [x.libname for x in AWS_LIBS]
@@ -350,6 +362,10 @@ def awscrt_ext():
if not is_macos_universal2():
extra_link_args += ['-Wl,-fatal_warnings']
+ if sys.version_info >= (3, 11):
+ define_macros.append(('Py_LIMITED_API', '0x030B0000'))
+ py_limited_api = True
+
return setuptools.Extension(
'_awscrt',
language='c',
@@ -357,7 +373,9 @@ def awscrt_ext():
sources=glob.glob('source/*.c'),
extra_compile_args=extra_compile_args,
extra_link_args=extra_link_args,
- extra_objects=extra_objects
+ extra_objects=extra_objects,
+ define_macros=define_macros,
+ py_limited_api=py_limited_api,
)
@@ -392,6 +410,6 @@ setuptools.setup(
],
python_requires='>=3.7',
ext_modules=[awscrt_ext()],
- cmdclass={'build_ext': awscrt_build_ext},
+ cmdclass={'build_ext': awscrt_build_ext, "bdist_wheel": bdist_wheel_abi3},
test_suite='test',
)
diff --git a/source/auth_credentials.c b/source/auth_credentials.c
index 80bca19..66b1afa 100644
--- a/source/auth_credentials.c
+++ b/source/auth_credentials.c
@@ -513,7 +513,7 @@ PyObject *aws_py_credentials_provider_new_chain(PyObject *self, PyObject *args)
if (!providers_pyseq) {
goto done;
}
- size_t provider_count = (size_t)PySequence_Fast_GET_SIZE(providers_pyseq);
+ size_t provider_count = (size_t)PySequence_Size(providers_pyseq);
if (provider_count == 0) {
PyErr_SetString(PyExc_ValueError, "Must supply at least one AwsCredentialsProvider.");
goto done;
@@ -526,8 +526,9 @@ PyObject *aws_py_credentials_provider_new_chain(PyObject *self, PyObject *args)
}
for (size_t i = 0; i < provider_count; ++i) {
- PyObject *provider_py = PySequence_Fast_GET_ITEM(providers_pyseq, i);
+ PyObject *provider_py = PySequence_GetItem(providers_pyseq, i); /* new reference */
providers_carray[i] = aws_py_get_credentials_provider(provider_py);
+ Py_XDECREF(provider_py);
if (!providers_carray[i]) {
goto done;
}
@@ -724,7 +725,7 @@ PyObject *aws_py_credentials_provider_new_cognito(PyObject *self, PyObject *args
goto done;
}
- logins_count = (size_t)PySequence_Fast_GET_SIZE(logins_pyseq);
+ logins_count = (size_t)PySequence_Size(logins_pyseq);
if (logins_count > 0) {
logins_carray =
@@ -735,7 +736,7 @@ PyObject *aws_py_credentials_provider_new_cognito(PyObject *self, PyObject *args
}
for (size_t i = 0; i < logins_count; ++i) {
- PyObject *login_tuple_py = PySequence_Fast_GET_ITEM(logins_pyseq, i);
+ PyObject *login_tuple_py = PySequence_GetItem(logins_pyseq, i); /* New reference */
struct aws_cognito_identity_provider_token_pair *login_entry = &logins_carray[i];
AWS_ZERO_STRUCT(*login_entry);
@@ -750,8 +751,10 @@ PyObject *aws_py_credentials_provider_new_cognito(PyObject *self, PyObject *args
PyExc_TypeError,
"cognito credentials provider: logins[%zu] is invalid, should be type (str, str)",
i);
+ Py_XDECREF(login_tuple_py);
goto done;
}
+ Py_XDECREF(login_tuple_py);
}
}
}
diff --git a/source/event_stream_headers.c b/source/event_stream_headers.c
index f8ae4ef..cfb1ac3 100644
--- a/source/event_stream_headers.c
+++ b/source/event_stream_headers.c
@@ -166,19 +166,20 @@ bool aws_py_event_stream_native_headers_init(struct aws_array_list *native_heade
bool success = false;
PyObject *sequence_py = NULL;
- sequence_py = PySequence_Fast(headers_py, "Expected sequence of Headers"); /* New reference */
+ sequence_py = PySequence_Fast(headers_py, "Expected sequence of Headers");
if (!sequence_py) {
goto done;
}
- const Py_ssize_t count = PySequence_Fast_GET_SIZE(sequence_py);
+ const Py_ssize_t count = PySequence_Size(sequence_py);
for (Py_ssize_t i = 0; i < count; ++i) {
- /* Borrowed reference, don't need to decref */
- PyObject *header_py = PySequence_Fast_GET_ITEM(sequence_py, i);
+ PyObject *header_py = PySequence_GetItem(sequence_py, i); /* New Reference */
if (!s_add_native_header(native_headers, header_py)) {
+ Py_XDECREF(header_py);
goto done;
}
+ Py_XDECREF(header_py);
}
success = true;
@@ -270,7 +271,7 @@ PyObject *aws_py_event_stream_python_headers_create(
goto error;
}
- PyList_SET_ITEM(list_py, i, tuple_py); /* steals reference to tuple */
+ PyList_SetItem(list_py, i, tuple_py); /* steals reference to tuple */
}
return list_py;
diff --git a/source/http_headers.c b/source/http_headers.c
index 187cd7c..66974f9 100644
--- a/source/http_headers.c
+++ b/source/http_headers.c
@@ -85,6 +85,29 @@ PyObject *aws_py_http_headers_add(PyObject *self, PyObject *args) {
Py_RETURN_NONE;
}
+static bool s_py_http_headers_add_pair(PyObject *py_pair, struct aws_http_headers *headers) {
+
+ const char *type_errmsg = "List of (name,value) pairs expected.";
+ if (!PyTuple_Check(py_pair) || PyTuple_Size(py_pair) != 2) {
+ PyErr_SetString(PyExc_TypeError, type_errmsg);
+ return false;
+ }
+
+ struct aws_byte_cursor name = aws_byte_cursor_from_pyunicode(PyTuple_GetItem(py_pair, 0) /* Borrowed reference */);
+ struct aws_byte_cursor value = aws_byte_cursor_from_pyunicode(PyTuple_GetItem(py_pair, 1) /* Borrowed reference */);
+ if (!name.ptr || !value.ptr) {
+ PyErr_SetString(PyExc_TypeError, type_errmsg);
+ return false;
+ }
+
+ if (aws_http_headers_add(headers, name, value)) {
+ PyErr_SetAwsLastError();
+ return false;
+ }
+
+ return true;
+}
+
PyObject *aws_py_http_headers_add_pairs(PyObject *self, PyObject *args) {
PyObject *py_pairs;
S_HEADERS_METHOD_START("O", &py_pairs);
@@ -96,25 +119,12 @@ PyObject *aws_py_http_headers_add_pairs(PyObject *self, PyObject *args) {
return NULL;
}
- const Py_ssize_t count = PySequence_Fast_GET_SIZE(py_sequence);
+ const Py_ssize_t count = PySequence_Size(py_pairs);
for (Py_ssize_t i = 0; i < count; ++i) {
- /* XYZ_GET_ITEM() calls returns borrowed references */
- PyObject *py_pair = PySequence_Fast_GET_ITEM(py_sequence, i);
-
- if (!PyTuple_Check(py_pair) || PyTuple_GET_SIZE(py_pair) != 2) {
- PyErr_SetString(PyExc_TypeError, type_errmsg);
- goto done;
- }
-
- struct aws_byte_cursor name = aws_byte_cursor_from_pyunicode(PyTuple_GET_ITEM(py_pair, 0));
- struct aws_byte_cursor value = aws_byte_cursor_from_pyunicode(PyTuple_GET_ITEM(py_pair, 1));
- if (!name.ptr || !value.ptr) {
- PyErr_SetString(PyExc_TypeError, type_errmsg);
- goto done;
- }
-
- if (aws_http_headers_add(headers, name, value)) {
- PyErr_SetAwsLastError();
+ PyObject *py_pair = PySequence_GetItem(py_sequence, i); /* New Reference */
+ bool success = s_py_http_headers_add_pair(py_pair, headers);
+ Py_DECREF(py_pair);
+ if (!success) {
goto done;
}
}
@@ -175,8 +185,8 @@ static PyObject *s_py_tuple_from_header(struct aws_http_header header) {
goto error;
}
- PyTuple_SET_ITEM(py_pair, 0, py_name);
- PyTuple_SET_ITEM(py_pair, 1, py_value);
+ PyTuple_SetItem(py_pair, 0, py_name); /* Steals a reference */
+ PyTuple_SetItem(py_pair, 1, py_value); /* Steals a reference */
return py_pair;
error:
diff --git a/source/http_stream.c b/source/http_stream.c
index 18ed406..bf70218 100644
--- a/source/http_stream.c
+++ b/source/http_stream.c
@@ -121,7 +121,7 @@ static int s_on_incoming_header_block_done(
goto done;
}
- PyList_SET_ITEM(header_list, i, tuple); /* steals reference to tuple */
+ PyList_SetItem(header_list, i, tuple); /* steals reference to tuple */
}
/* TODO: handle informational and trailing headers */
diff --git a/source/module.c b/source/module.c
index ca8a0d9..f120daa 100644
--- a/source/module.c
+++ b/source/module.c
@@ -531,20 +531,12 @@ void *aws_py_get_binding(PyObject *obj, const char *capsule_name, const char *cl
PyObject *py_binding = PyObject_GetAttrString(obj, "_binding"); /* new reference */
if (!py_binding) {
- return PyErr_Format(
- PyExc_TypeError,
- "Expected valid '%s', received '%s' (no '_binding' attribute)",
- class_name,
- Py_TYPE(obj)->tp_name);
+ return PyErr_Format(PyExc_TypeError, "Expected valid '%s' (no '_binding' attribute)", class_name);
}
void *binding = NULL;
if (!PyCapsule_CheckExact(py_binding)) {
- PyErr_Format(
- PyExc_TypeError,
- "Expected valid '%s', received '%s' ('_binding' attribute is not a capsule)",
- class_name,
- Py_TYPE(obj)->tp_name);
+ PyErr_Format(PyExc_TypeError, "Expected valid '%s' ('_binding' attribute is not a capsule)", class_name);
goto done;
}
@@ -552,9 +544,8 @@ void *aws_py_get_binding(PyObject *obj, const char *capsule_name, const char *cl
if (!binding) {
PyErr_Format(
PyExc_TypeError,
- "Expected valid '%s', received '%s' ('_binding' attribute does not contain '%s')",
+ "Expected valid '%s' ('_binding' attribute does not contain '%s')",
class_name,
- Py_TYPE(obj)->tp_name,
capsule_name);
goto done;
}
diff --git a/source/mqtt5_client.c b/source/mqtt5_client.c
index e07eb91..c43c90c 100644
--- a/source/mqtt5_client.c
+++ b/source/mqtt5_client.c
@@ -200,7 +200,7 @@ static PyObject *s_aws_set_user_properties_to_PyObject(
Py_XDECREF(user_properties_list);
return NULL;
}
- PyList_SET_ITEM(user_properties_list, i, tuple); /* Steals reference to tuple */
+ PyList_SetItem(user_properties_list, i, tuple); /* Steals reference to tuple */
}
return user_properties_list;
}
@@ -237,8 +237,10 @@ static void s_on_publish_received(const struct aws_mqtt5_packet_publish_view *pu
}
for (size_t i = 0; i < subscription_identifier_count; ++i) {
- PyList_SET_ITEM(
- subscription_identifier_list, i, PyLong_FromLongLong(publish_packet->subscription_identifiers[i]));
+ PyList_SetItem(
+ subscription_identifier_list,
+ i,
+ PyLong_FromLongLong(publish_packet->subscription_identifiers[i])); /* Steals a reference */
}
user_properties_list = s_aws_set_user_properties_to_PyObject(publish_packet->user_properties, user_property_count);
@@ -1629,7 +1631,7 @@ static void s_on_subscribe_complete_fn(
}
for (size_t i = 0; i < reason_codes_count; ++i) {
- PyList_SET_ITEM(reason_codes_list, i, PyLong_FromLong(suback->reason_codes[i]));
+ PyList_SetItem(reason_codes_list, i, PyLong_FromLong(suback->reason_codes[i])); /* Steals a reference */
}
}
@@ -1860,7 +1862,7 @@ static void s_on_unsubscribe_complete_fn(
}
for (size_t i = 0; i < reason_codes_count; ++i) {
- PyList_SET_ITEM(reason_codes_list, i, PyLong_FromLong(unsuback->reason_codes[i]));
+ PyList_SetItem(reason_codes_list, i, PyLong_FromLong(unsuback->reason_codes[i])); /* Steals a reference */
}
}
@@ -2030,23 +2032,35 @@ PyObject *aws_py_mqtt5_client_get_stats(PyObject *self, PyObject *args) {
goto done;
}
- PyTuple_SET_ITEM(result, 0, PyLong_FromUnsignedLongLong((unsigned long long)stats.incomplete_operation_count));
- if (PyTuple_GET_ITEM(result, 0) == NULL) {
+ PyTuple_SetItem(
+ result,
+ 0,
+ PyLong_FromUnsignedLongLong((unsigned long long)stats.incomplete_operation_count)); /* Steals a reference */
+ if (PyTuple_GetItem(result, 0) == NULL) { /* Borrowed reference */
goto done;
}
- PyTuple_SET_ITEM(result, 1, PyLong_FromUnsignedLongLong((unsigned long long)stats.incomplete_operation_size));
- if (PyTuple_GET_ITEM(result, 1) == NULL) {
+ PyTuple_SetItem(
+ result,
+ 1,
+ PyLong_FromUnsignedLongLong((unsigned long long)stats.incomplete_operation_size)); /* Steals a reference */
+ if (PyTuple_GetItem(result, 1) == NULL) { /* Borrowed reference */
goto done;
}
- PyTuple_SET_ITEM(result, 2, PyLong_FromUnsignedLongLong((unsigned long long)stats.unacked_operation_count));
- if (PyTuple_GET_ITEM(result, 2) == NULL) {
+ PyTuple_SetItem(
+ result,
+ 2,
+ PyLong_FromUnsignedLongLong((unsigned long long)stats.unacked_operation_count)); /* Steals a reference */
+ if (PyTuple_GetItem(result, 2) == NULL) { /* Borrowed reference */
goto done;
}
- PyTuple_SET_ITEM(result, 3, PyLong_FromUnsignedLongLong((unsigned long long)stats.unacked_operation_size));
- if (PyTuple_GET_ITEM(result, 3) == NULL) {
+ PyTuple_SetItem(
+ result,
+ 3,
+ PyLong_FromUnsignedLongLong((unsigned long long)stats.unacked_operation_size)); /* Steals a reference */
+ if (PyTuple_GetItem(result, 3) == NULL) { /* Borrowed reference */
goto done;
}
diff --git a/source/mqtt_client_connection.c b/source/mqtt_client_connection.c
index bd06d29..96e7ec6 100644
--- a/source/mqtt_client_connection.c
+++ b/source/mqtt_client_connection.c
@@ -1063,7 +1063,7 @@ static void s_suback_multi_callback(
goto done_prepping_args;
}
- PyList_SET_ITEM(topic_qos_list, i, tuple); /* Steals reference to tuple */
+ PyList_SetItem(topic_qos_list, i, tuple); /* Steals reference to tuple */
}
done_prepping_args:;
@@ -1202,23 +1202,35 @@ PyObject *aws_py_mqtt_client_connection_get_stats(PyObject *self, PyObject *args
goto done;
}
- PyTuple_SET_ITEM(result, 0, PyLong_FromUnsignedLongLong((unsigned long long)stats.incomplete_operation_count));
- if (PyTuple_GET_ITEM(result, 0) == NULL) {
+ PyTuple_SetItem(
+ result,
+ 0,
+ PyLong_FromUnsignedLongLong((unsigned long long)stats.incomplete_operation_count)); /* Steals a reference */
+ if (PyTuple_GetItem(result, 0) == NULL) { /* Borrowed reference */
goto done;
}
- PyTuple_SET_ITEM(result, 1, PyLong_FromUnsignedLongLong((unsigned long long)stats.incomplete_operation_size));
- if (PyTuple_GET_ITEM(result, 1) == NULL) {
+ PyTuple_SetItem(
+ result,
+ 1,
+ PyLong_FromUnsignedLongLong((unsigned long long)stats.incomplete_operation_size)); /* Steals a reference */
+ if (PyTuple_GetItem(result, 1) == NULL) { /* Borrowed reference */
goto done;
}
- PyTuple_SET_ITEM(result, 2, PyLong_FromUnsignedLongLong((unsigned long long)stats.unacked_operation_count));
- if (PyTuple_GET_ITEM(result, 2) == NULL) {
+ PyTuple_SetItem(
+ result,
+ 2,
+ PyLong_FromUnsignedLongLong((unsigned long long)stats.unacked_operation_count)); /* Steals a reference */
+ if (PyTuple_GetItem(result, 2) == NULL) { /* Borrowed reference */
goto done;
}
- PyTuple_SET_ITEM(result, 3, PyLong_FromUnsignedLongLong((unsigned long long)stats.unacked_operation_size));
- if (PyTuple_GET_ITEM(result, 3) == NULL) {
+ PyTuple_SetItem(
+ result,
+ 3,
+ PyLong_FromUnsignedLongLong((unsigned long long)stats.unacked_operation_size)); /* Steals a reference */
+ if (PyTuple_GetItem(result, 3) == NULL) { /* Borrowed reference */
goto done;
}
diff --git a/source/s3_meta_request.c b/source/s3_meta_request.c
index 88a7c19..f7ffa56 100644
--- a/source/s3_meta_request.c
+++ b/source/s3_meta_request.c
@@ -69,7 +69,7 @@ static PyObject *s_get_py_headers(const struct aws_http_headers *headers) {
if (!tuple) {
goto error;
}
- PyList_SET_ITEM(header_list, i, tuple); /* steals reference to tuple */
+ PyList_SetItem(header_list, i, tuple); /* steals reference to tuple */
}
return header_list;
error:
diff --git a/source/websocket.c b/source/websocket.c
index 2b056ee..95f9d8e 100644
--- a/source/websocket.c
+++ b/source/websocket.c
@@ -211,13 +211,13 @@ static void s_websocket_on_connection_setup(
PyObject *name_py = PyUnicode_FromAwsByteCursor(&header_i->name);
AWS_FATAL_ASSERT(name_py && "header name wrangling failed");
- PyTuple_SET_ITEM(tuple_py, 0, name_py);
+ PyTuple_SetItem(tuple_py, 0, name_py); /* Steals a reference */
PyObject *value_py = PyUnicode_FromAwsByteCursor(&header_i->value);
AWS_FATAL_ASSERT(value_py && "header value wrangling failed");
- PyTuple_SET_ITEM(tuple_py, 1, value_py);
+ PyTuple_SetItem(tuple_py, 1, value_py); /* Steals a reference */
- PyList_SET_ITEM(headers_py, i, tuple_py);
+ PyList_SetItem(headers_py, i, tuple_py); /* Steals a reference */
}
}
@@ -580,13 +580,13 @@ PyObject *aws_py_websocket_create_handshake_request(PyObject *self, PyObject *ar
if (!request_binding_py) {
goto cleanup;
}
- PyTuple_SET_ITEM(tuple_py, 0, request_binding_py); /* steals reference to request_binding_py */
+ PyTuple_SetItem(tuple_py, 0, request_binding_py); /* steals reference to request_binding_py */
PyObject *headers_binding_py = aws_py_http_headers_new_from_native(aws_http_message_get_headers(request));
if (!headers_binding_py) {
goto cleanup;
}
- PyTuple_SET_ITEM(tuple_py, 1, headers_binding_py); /* steals reference to headers_binding_py */
+ PyTuple_SetItem(tuple_py, 1, headers_binding_py); /* steals reference to headers_binding_py */
/* Success! */
success = true;
diff --git a/test/test_http_client.py b/test/test_http_client.py
index dd2631a..14a6d75 100644
--- a/test/test_http_client.py
+++ b/test/test_http_client.py
@@ -57,10 +57,9 @@ class TestClient(NativeResourceTest):
self.server = HTTPServer((self.hostname, 0), TestRequestHandler)
if secure:
- self.server.socket = ssl.wrap_socket(self.server.socket,
- keyfile="test/resources/unittest.key",
- certfile='test/resources/unittest.crt',
- server_side=True)
+ context = ssl.SSLContext()
+ context.load_cert_chain(certfile='test/resources/unittest.crt', keyfile="test/resources/unittest.key")
+ self.server.socket = context.wrap_socket(self.server.socket, server_side=True)
self.port = self.server.server_address[1]
# put requests are stored in this dict