Skip to content

Commit

Permalink
PROTON-2430: Changed python binding to use pn_message_set/get_id/corr…
Browse files Browse the repository at this point in the history
…elation_id

Stop using pn_message_id/pn_message_correlation_id which are inherently
ineefficient and should be deprecated.

Added in a SWIG typemap for pn_msgid_t that knows the types that are
necessary for msgid types.
  • Loading branch information
astitcher committed Sep 3, 2021
1 parent 7bc27ef commit 7f2fd8d
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 20 deletions.
82 changes: 78 additions & 4 deletions python/cproton.i
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,8 @@ PN_HANDLE(PNI_PYTRACER);

// These are not used/needed in the python binding
%ignore pn_dtag;
%ignore pn_message_get_id;
%ignore pn_message_set_id;
%ignore pn_message_get_correlation_id;
%ignore pn_message_set_correlation_id;
%ignore pn_message_id;
%ignore pn_message_correlation_id;

%ignore pn_list;
%ignore pn_list_size;
Expand Down Expand Up @@ -163,6 +161,7 @@ PN_HANDLE(PNI_PYTRACER);
$result = PyLong_FromVoidPtr((void*)$1);
}


%typemap(in) pn_bytes_t {
if ($input == Py_None) {
$1.start = NULL;
Expand All @@ -181,6 +180,81 @@ PN_HANDLE(PNI_PYTRACER);
$result = PyBytes_FromStringAndSize($1.start, $1.size);
}

%typemap(in) pn_msgid_t {
if (PyTuple_Check($input)) {
pn_type_t type = PyLong_AsUnsignedLong(PyTuple_GetItem($input, 0));
PyObject* obj = PyTuple_GetItem($input, 1);
switch (type) {
case PN_NULL:
break;
case PN_ULONG:
$1.u.as_ulong = PyLong_AsUnsignedLong(obj);
break;
case PN_UUID:
if (PyBytes_Check(obj)) {
memmove(&$1.u.as_uuid, PyBytes_AsString(obj), (PyBytes_Size(obj) < 16 ? PyBytes_Size(obj) : 16));
break;
}
type = PN_NULL;
break;
case PN_BINARY:
if (PyBytes_Check(obj)) {
$1.u.as_bytes = (pn_bytes_t){.size=PyBytes_Size(obj), .start=PyBytes_AsString(obj)};
break;
}
type = PN_NULL;
break;
case PN_STRING:
if (PyBytes_Check(obj)) {
$1.u.as_bytes = (pn_bytes_t){.size=PyBytes_Size(obj), .start=PyBytes_AsString(obj)};
break;
}
default:
type = PN_NULL;
break;
}
$1.type = type;
} else if (PyLong_Check($input)) {
$1.type = PN_ULONG;
$1.u.as_ulong = PyLong_AsUnsignedLong($input);
} else if (PyBytes_Check($input)) {
$1.type = PN_BINARY;
$1.u.as_bytes = (pn_bytes_t){.size=PyBytes_Size($input), .start=PyBytes_AsString($input)};
} else if (PyUnicode_Check($input)) {
$1.type = PN_STRING;
Py_ssize_t utf8size;
const char *utf8 = PyUnicode_AsUTF8AndSize($input, &utf8size);
$1.u.as_bytes = (pn_bytes_t){.size=utf8size, .start=utf8};
} else {
$1.type = PN_NULL;
}
}

%typemap(out) pn_msgid_t {
switch ($1.type) {
case PN_NULL:
$result = Py_None;
break;
case PN_ULONG:
$result = PyLong_FromUnsignedLong($1.u.as_ulong);
break;
case PN_BINARY:
$result = PyBytes_FromStringAndSize($1.u.as_bytes.start, $1.u.as_bytes.size);
break;
case PN_STRING:
$result = PyUnicode_FromStringAndSize($1.u.as_bytes.start, $1.u.as_bytes.size);
break;
case PN_UUID:
$result = PyTuple_New(2);
PyTuple_SetItem($result, 0, PyLong_FromUnsignedLong($1.type));
PyTuple_SetItem($result, 1, PyBytes_FromStringAndSize($1.u.as_uuid.bytes, 16));
break;
default:
$result = Py_None;
break;
}
}

%typemap(out) pn_delivery_tag_t {
$result = PyBytes_FromStringAndSize($1.bytes, $1.size);
}
Expand Down
40 changes: 24 additions & 16 deletions python/proton/_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,30 +19,30 @@

from __future__ import absolute_import

from cproton import PN_DEFAULT_PRIORITY, PN_OVERFLOW, pn_error_text, pn_message, \
pn_message_annotations, pn_message_body, pn_message_clear, pn_message_correlation_id, pn_message_decode, \
from cproton import PN_DEFAULT_PRIORITY, PN_STRING, PN_UUID, PN_OVERFLOW, pn_error_text, pn_message, \
pn_message_annotations, pn_message_body, pn_message_clear, pn_message_decode, \
pn_message_encode, pn_message_error, pn_message_free, pn_message_get_address, pn_message_get_content_encoding, \
pn_message_get_content_type, pn_message_get_creation_time, pn_message_get_delivery_count, \
pn_message_get_expiry_time, pn_message_get_group_id, pn_message_get_group_sequence, pn_message_get_priority, \
pn_message_get_content_type, pn_message_get_correlation_id, pn_message_get_creation_time, pn_message_get_delivery_count, \
pn_message_get_expiry_time, pn_message_get_group_id, pn_message_get_group_sequence, pn_message_get_id, pn_message_get_priority, \
pn_message_get_reply_to, pn_message_get_reply_to_group_id, pn_message_get_subject, pn_message_get_ttl, \
pn_message_get_user_id, pn_message_id, pn_message_instructions, pn_message_is_durable, \
pn_message_get_user_id, pn_message_instructions, pn_message_is_durable, \
pn_message_is_first_acquirer, pn_message_is_inferred, pn_message_properties, pn_message_set_address, \
pn_message_set_content_encoding, pn_message_set_content_type, pn_message_set_creation_time, \
pn_message_set_content_encoding, pn_message_set_content_type, pn_message_set_correlation_id, pn_message_set_creation_time, \
pn_message_set_delivery_count, pn_message_set_durable, pn_message_set_expiry_time, pn_message_set_first_acquirer, \
pn_message_set_group_id, pn_message_set_group_sequence, pn_message_set_inferred, pn_message_set_priority, \
pn_message_set_group_id, pn_message_set_group_sequence, pn_message_set_id, pn_message_set_inferred, pn_message_set_priority, \
pn_message_set_reply_to, pn_message_set_reply_to_group_id, pn_message_set_subject, \
pn_message_set_ttl, pn_message_set_user_id

from ._common import isinteger, millis2secs, secs2millis, unicode2utf8, utf82unicode
from ._data import char, Data, symbol, ulong, AnnotationDict
from ._endpoints import Link
from ._exceptions import EXCEPTIONS, MessageException
from uuid import UUID
from typing import Dict, Optional, Union, TYPE_CHECKING, overload

if TYPE_CHECKING:
from proton._delivery import Delivery
from proton._endpoints import Sender, Receiver
from uuid import UUID
from proton._data import Described, PythonAMQPData


Expand All @@ -69,8 +69,6 @@ def __init__(
**kwargs
) -> None:
self._msg = pn_message()
self._id = Data(pn_message_id(self._msg))
self._correlation_id = Data(pn_message_correlation_id(self._msg))
self.instructions = None
self.annotations = None
self.properties = None
Expand Down Expand Up @@ -273,14 +271,19 @@ def id(self) -> Optional[Union[str, bytes, 'UUID', ulong]]:
* ``bytes``
* ``str``
"""
return self._id.get_object()
value = pn_message_get_id(self._msg)
if isinstance(value, tuple):
if value[0] == PN_UUID:
value = UUID(bytes=value[1])
return value

@id.setter
def id(self, value: Optional[Union[str, bytes, 'UUID', int]]) -> None:
if isinteger(value):
value = ulong(value)
self._id.rewind()
self._id.put_object(value)
elif isinstance(value, UUID):
value = (PN_UUID, value.bytes)
pn_message_set_id(self._msg, value)

@property
def user_id(self) -> bytes:
Expand Down Expand Up @@ -341,14 +344,19 @@ def correlation_id(self) -> Optional[Union['UUID', ulong, str, bytes]]:
* ``bytes``
* ``str``
"""
return self._correlation_id.get_object()
value = pn_message_get_correlation_id(self._msg)
if isinstance(value, tuple):
if value[0] == PN_UUID:
value = UUID(bytes=value[1])
return value

@correlation_id.setter
def correlation_id(self, value: Optional[Union[str, bytes, 'UUID', int]]) -> None:
if isinteger(value):
value = ulong(value)
self._correlation_id.rewind()
self._correlation_id.put_object(value)
elif isinstance(value, UUID):
value = (PN_UUID, value.bytes)
pn_message_set_correlation_id(self._msg, value)

@property
def content_type(self) -> symbol:
Expand Down

0 comments on commit 7f2fd8d

Please sign in to comment.