Skip to content

Commit

Permalink
WIP: Simplify python context code
Browse files Browse the repository at this point in the history
- Needed to add a custom __new__ to Transport because its constructor
  parameters aren't compatible with the Wrapper class.
- Generalised wrap static method where possible

- Work on type annotations
  • Loading branch information
astitcher committed Jan 27, 2025
1 parent 36257ed commit 861a0a8
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 147 deletions.
18 changes: 4 additions & 14 deletions python/cproton.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,24 +340,14 @@ def pn_collector_put_pyref(collector, obj, etype):
lib.pn_collector_put_py(collector, d, etype.number)


def pn_record_def_py(record):
lib.pn_record_def_py(record)


def pn_record_get_py(record):
d = lib.pn_record_get_py(record)
if d == ffi.NULL:
return None
return ffi.from_handle(d)


def pn_record_set_py(record, value):
if value is None:
d = ffi.NULL
else:
d = ffi.new_handle(value)
d = ffi.new_handle({})
retained_objects.add(d)
lib.pn_record_set_py(record, d)
lib.pn_record_def_py(record)
lib.pn_record_set_py(record, d)
return ffi.from_handle(d)


def pn_event_class_name(event):
Expand Down
23 changes: 8 additions & 15 deletions python/proton/_delivery.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@
pn_delivery_writable, pn_disposition_annotations, pn_disposition_condition, pn_disposition_data, \
pn_disposition_get_section_number, pn_disposition_get_section_offset, pn_disposition_is_failed, \
pn_disposition_is_undeliverable, pn_disposition_set_failed, pn_disposition_set_section_number, \
pn_disposition_set_section_offset, pn_disposition_set_undeliverable, pn_disposition_type, \
isnull
pn_disposition_set_section_offset, pn_disposition_set_undeliverable, pn_disposition_type

from ._condition import cond2obj, obj2cond
from ._data import dat2obj, obj2dat
from ._transport import Transport
from ._wrapper import Wrapper

from enum import IntEnum
Expand All @@ -39,7 +39,7 @@
from ._condition import Condition
from ._data import PythonAMQPData, symbol
from ._endpoints import Receiver, Sender # circular import
from ._reactor import Connection, Session, Transport
from ._reactor import Connection, Session


class DispositionType(IntEnum):
Expand Down Expand Up @@ -277,19 +277,12 @@ class Delivery(Wrapper):
delivery being settled.
"""

@staticmethod
def wrap(impl):
if isnull(impl):
return None
else:
return Delivery(impl)
get_context = pn_delivery_attachments

def __init__(self, impl):
Wrapper.__init__(self, impl, pn_delivery_attachments)

def _init(self) -> None:
self.local = Disposition(pn_delivery_local(self._impl), True)
self.remote = Disposition(pn_delivery_remote(self._impl), False)
if self.Uninitialized():
self.local = Disposition(pn_delivery_local(self._impl), True)
self.remote = Disposition(pn_delivery_remote(self._impl), False)

@property
def tag(self) -> str:
Expand Down Expand Up @@ -414,7 +407,7 @@ def connection(self) -> 'Connection':
return self.session.connection

@property
def transport(self) -> 'Transport':
def transport(self) -> Optional[Transport]:
"""
The :class:`Transport` bound to the :class:`Connection` over which
the delivery was sent or received.
Expand Down
64 changes: 24 additions & 40 deletions python/proton/_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@
pn_terminus_is_dynamic, pn_terminus_outcomes, pn_terminus_properties, pn_terminus_set_address, \
pn_terminus_set_distribution_mode, pn_terminus_set_durability, pn_terminus_set_dynamic, \
pn_terminus_set_expiry_policy, pn_terminus_set_timeout, pn_terminus_set_type, \
pn_link_properties, pn_link_remote_properties, \
isnull
pn_link_properties, pn_link_remote_properties

from ._condition import cond2obj, obj2cond
from ._data import Data, dat2obj, obj2dat, PropertyDict, SymbolList
Expand All @@ -64,7 +63,7 @@
from ._handler import Handler
from ._transport import Transport
from ._wrapper import Wrapper
from typing import Dict, List, Optional, Union, TYPE_CHECKING, Any
from typing import Any, Dict, List, Optional, Union, TYPE_CHECKING

if TYPE_CHECKING:
from ._condition import Condition
Expand Down Expand Up @@ -112,7 +111,7 @@ class Endpoint(object):
REMOTE_CLOSED = PN_REMOTE_CLOSED
""" The remote endpoint state is closed. """

def _init(self) -> None:
def __init__(self) -> None:
self.condition: Optional['Condition'] = None
self._handler: Optional[Handler] = None

Expand Down Expand Up @@ -159,26 +158,17 @@ class Connection(Wrapper, Endpoint):
A representation of an AMQP connection.
"""

@staticmethod
def wrap(impl):
if isnull(impl):
return None
else:
return Connection(impl)
constructor = pn_connection
get_context = pn_connection_attachments

def __init__(self, impl: Any = None) -> None:
if impl is None:
Wrapper.__init__(self, constructor=pn_connection, get_context=pn_connection_attachments)
else:
Wrapper.__init__(self, impl, pn_connection_attachments)

def _init(self) -> None:
Endpoint._init(self)
self.offered_capabilities_list = None
self.desired_capabilities_list = None
self.properties = None
self.url = None
self._acceptor = None
if self.Uninitialized():
Endpoint.__init__(self)
self.offered_capabilities_list = None
self.desired_capabilities_list = None
self.properties = None
self.url = None
self._acceptor = None

def _get_attachments(self):
return pn_connection_attachments(self._impl)
Expand Down Expand Up @@ -550,15 +540,12 @@ def properties(self, properties_dict: Optional[Union[PropertyDict, Dict[str, 'Py

class Session(Wrapper, Endpoint):
"""A container of links"""
@staticmethod
def wrap(impl):
if isnull(impl):
return None
else:
return Session(impl)

get_context = pn_session_attachments

def __init__(self, impl):
Wrapper.__init__(self, impl, pn_session_attachments)
if self.Uninitialized():
Endpoint.__init__(self)

def _get_attachments(self):
return pn_session_attachments(self._impl)
Expand Down Expand Up @@ -714,21 +701,18 @@ class Link(Wrapper, Endpoint):
RCV_SECOND = PN_RCV_SECOND
"""The receiver will only settle deliveries after the sender settles."""

@staticmethod
def wrap(impl):
if isnull(impl):
return None
get_context = pn_link_attachments

def __new__(cls, impl) -> 'Link':
if pn_link_is_sender(impl):
return Sender(impl)
return super().__new__(Sender, impl)
else:
return Receiver(impl)
return super().__new__(Receiver, impl)

def __init__(self, impl):
Wrapper.__init__(self, impl, pn_link_attachments)

def _init(self) -> None:
Endpoint._init(self)
self.properties = None
if self.Uninitialized():
Endpoint.__init__(self)
self.properties = None

def _get_attachments(self):
return pn_link_attachments(self._impl)
Expand Down
46 changes: 29 additions & 17 deletions python/proton/_transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,27 +92,32 @@ def wrap(impl: Optional[Callable]) -> Optional['Transport']:
else:
return Transport(impl=impl)

constructor = pn_transport
get_context = pn_transport_attachments

def __new__(
cls,
mode: Optional[int] = None,
impl=None,
) -> 'Transport':
return super().__new__(cls, impl)

def __init__(
self,
mode: 'Optional[int]' = None,
impl: 'Callable' = None,
mode: Optional[int] = None,
impl=None,
) -> None:
if impl is None:
Wrapper.__init__(self, constructor=pn_transport, get_context=pn_transport_attachments)
else:
Wrapper.__init__(self, impl, pn_transport_attachments)
if mode == Transport.SERVER:
pn_transport_set_server(self._impl)
elif mode is None or mode == Transport.CLIENT:
pass
else:
raise TransportException("Cannot initialise Transport from mode: %s" % str(mode))

def _init(self) -> None:
self._sasl = None
self._ssl = None
self._reactor = None
self._connect_selectable = None
if self.Uninitialized():
self._sasl = None
self._ssl = None
self._reactor = None
self._connect_selectable = None

def _check(self, err: int) -> int:
if err < 0:
Expand Down Expand Up @@ -468,7 +473,9 @@ def sasl(self) -> 'SASL':
:return: SASL object associated with this transport.
"""
return SASL(self)
if not self._sasl:
self._sasl = SASL(self)
return self._sasl

def ssl(self, domain: Optional['SSLDomain'] = None, session_details: Optional['SSLSessionDetails'] = None) -> 'SSL':
"""
Expand Down Expand Up @@ -512,7 +519,7 @@ class SASLException(TransportException):
pass


class SASL(Wrapper):
class SASL:
"""
The SASL layer is responsible for establishing an authenticated
and/or encrypted tunnel over which AMQP frames are passed between
Expand Down Expand Up @@ -542,9 +549,14 @@ def extended() -> bool:
"""
return pn_sasl_extended()

def __init__(self, transport: Transport) -> None:
Wrapper.__init__(self, transport._impl, pn_transport_attachments)
self._sasl = pn_sasl(transport._impl)
def __new__(cls, transport: Transport) -> 'SASL':
if not transport._sasl:
sasl = super().__new__(cls)
sasl._sasl = pn_sasl(transport._impl)
transport._sasl = sasl
return sasl
else:
return transport._sasl

def _check(self, err):
if err < 0:
Expand Down
Loading

0 comments on commit 861a0a8

Please sign in to comment.