(qpid-proton) 03/04: PROTON-2892: [Python] Use python library IntFlag for Endpoint state
This is an automated email from the ASF dual-hosted git repository. astitcher pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/qpid-proton.git commit d8ff8f7314f4a046c4033886b92edfc20cd09e72 Author: Andrew Stitcher AuthorDate: Tue Apr 22 12:11:21 2025 -0400 PROTON-2892: [Python] Use python library IntFlag for Endpoint state --- python/proton/_endpoints.py | 52 + 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/python/proton/_endpoints.py b/python/proton/_endpoints.py index d83f7e72f..13b837444 100644 --- a/python/proton/_endpoints.py +++ b/python/proton/_endpoints.py @@ -65,6 +65,7 @@ from ._transport import Transport from ._wrapper import Wrapper from collections.abc import Iterator +from enum import IntFlag from typing import Any, Callable, ClassVar, Optional, Union, TYPE_CHECKING, overload if TYPE_CHECKING: @@ -74,25 +75,11 @@ if TYPE_CHECKING: from ._message import Message -class Endpoint(Wrapper): +class EndpointState(IntFlag): """ -Abstract class from which :class:`Connection`, :class:`Session` -and :class:`Link` are derived, and which defines the state -of these classes. - -The :class:`Endpoint` state is an integral value with flags that +The state of an AMQP endpoint. This is a bit field with flags that encode both the local and remote state of an AMQP Endpoint (:class:`Connection`, :class:`Link`, or :class:`Session`). -The individual bits may be accessed using :const:`LOCAL_UNINIT`, -:const:`LOCAL_ACTIVE`, :const:`LOCAL_CLOSED`, and -:const:`REMOTE_UNINIT`, :const:`REMOTE_ACTIVE`, :const:`REMOTE_CLOSED`. - -Every AMQP endpoint (:class:`Connection`, :class:`Link`, or -:class:`Session`) starts out in an uninitialized state and then -proceeds linearly to an active and then closed state. This -lifecycle occurs at both endpoints involved, and so the state -model for an endpoint includes not only the known local state, -but also the last known state of the remote endpoint. """ LOCAL_UNINIT = PN_LOCAL_UNINIT @@ -113,9 +100,38 @@ class Endpoint(Wrapper): REMOTE_CLOSED = PN_REMOTE_CLOSED """ The remote endpoint state is closed. """ + +class Endpoint(Wrapper): +""" +Abstract class from which :class:`Connection`, :class:`Session` +and :class:`Link` are derived, and which defines the state +of these classes. + +The :class:`Endpoint` state is an integral value with flags that +encode both the local and remote state of an AMQP Endpoint +(:class:`Connection`, :class:`Link`, or :class:`Session`). +The individual bits may be accessed using :const:`LOCAL_UNINIT`, +:const:`LOCAL_ACTIVE`, :const:`LOCAL_CLOSED`, and +:const:`REMOTE_UNINIT`, :const:`REMOTE_ACTIVE`, :const:`REMOTE_CLOSED`. + +Every AMQP endpoint (:class:`Connection`, :class:`Link`, or +:class:`Session`) starts out in an uninitialized state and then +proceeds linearly to an active and then closed state. This +lifecycle occurs at both endpoints involved, and so the state +model for an endpoint includes not only the known local state, +but also the last known state of the remote endpoint. +""" + +LOCAL_UNINIT = EndpointState.LOCAL_UNINIT +REMOTE_UNINIT = EndpointState.REMOTE_UNINIT +LOCAL_ACTIVE = EndpointState.LOCAL_ACTIVE +REMOTE_ACTIVE = EndpointState.REMOTE_ACTIVE +LOCAL_CLOSED = EndpointState.LOCAL_CLOSED +REMOTE_CLOSED = EndpointState.REMOTE_CLOSED + get_condition: ClassVar[Callable[[Any], Any]] get_remote_condition: ClassVar[Callable[[Any], Any]] -get_state: ClassVar[Callable[[Any], int]] +get_state: ClassVar[Callable[[Any], EndpointState]] def __init__(self) -> None: self.condition: Optional['Condition'] = None @@ -133,7 +149,7 @@ class Endpoint(Wrapper): return cond2obj(type(self).get_remote_condition(self._impl)) @property -def state(self) -> int: +def state(self) -> EndpointState: """ The state of the endpoint as a bit field. The state has a local and a remote component. Each of these can be in one of three - To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org For additional commands, e-mail: commits-h...@qpid.apache.org
(qpid-proton) 02/04: PROTON-2868: [Python] More work simplifying wrapped classes
This is an automated email from the ASF dual-hosted git repository. astitcher pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/qpid-proton.git commit 1fafacd74a7e0df37c86d65316b09d2a038580eb Author: Andrew Stitcher AuthorDate: Fri Apr 18 18:25:13 2025 -0400 PROTON-2868: [Python] More work simplifying wrapped classes --- python/proton/_endpoints.py | 102 +--- python/proton/_wrapper.py | 2 +- 2 files changed, 31 insertions(+), 73 deletions(-) diff --git a/python/proton/_endpoints.py b/python/proton/_endpoints.py index 21171b16d..d83f7e72f 100644 --- a/python/proton/_endpoints.py +++ b/python/proton/_endpoints.py @@ -65,7 +65,7 @@ from ._transport import Transport from ._wrapper import Wrapper from collections.abc import Iterator -from typing import Any, Optional, Union, TYPE_CHECKING, overload +from typing import Any, Callable, ClassVar, Optional, Union, TYPE_CHECKING, overload if TYPE_CHECKING: from ._condition import Condition @@ -74,7 +74,7 @@ if TYPE_CHECKING: from ._message import Message -class Endpoint(object): +class Endpoint(Wrapper): """ Abstract class from which :class:`Connection`, :class:`Session` and :class:`Link` are derived, and which defines the state @@ -113,12 +113,16 @@ class Endpoint(object): REMOTE_CLOSED = PN_REMOTE_CLOSED """ The remote endpoint state is closed. """ +get_condition: ClassVar[Callable[[Any], Any]] +get_remote_condition: ClassVar[Callable[[Any], Any]] +get_state: ClassVar[Callable[[Any], int]] + def __init__(self) -> None: self.condition: Optional['Condition'] = None self._handler: Optional[Handler] = None def _update_cond(self) -> None: -obj2cond(self.condition, self._get_cond_impl()) +obj2cond(self.condition, type(self).get_condition(self._impl)) @property def remote_condition(self) -> Optional['Condition']: @@ -126,14 +130,18 @@ class Endpoint(object): The remote condition associated with the connection endpoint. See :class:`Condition` for more information. """ -return cond2obj(self._get_remote_cond_impl()) - -# the following must be provided by subclasses -def _get_cond_impl(self): -assert False, "Subclass must override this!" +return cond2obj(type(self).get_remote_condition(self._impl)) -def _get_remote_cond_impl(self): -assert False, "Subclass must override this!" +@property +def state(self) -> int: +""" +The state of the endpoint as a bit field. The state has a local +and a remote component. Each of these can be in one of three +states: ``UNINIT``, ``ACTIVE`` or ``CLOSED``. These can be tested by masking +against :const:`LOCAL_UNINIT`, :const:`LOCAL_ACTIVE`, :const:`LOCAL_CLOSED`, :const:`REMOTE_UNINIT`, +:const:`REMOTE_ACTIVE` and :const:`REMOTE_CLOSED`. +""" +return type(self).get_state(self._impl) @property def handler(self) -> Optional[Handler]: @@ -155,13 +163,16 @@ class Endpoint(object): self._handler.add(handler) -class Connection(Wrapper, Endpoint): +class Connection(Endpoint): """ A representation of an AMQP connection. """ constructor = pn_connection get_context = pn_connection_attachments +get_condition = pn_connection_condition +get_remote_condition = pn_connection_remote_condition +get_state = pn_connection_state def __init__(self, impl: Any = None) -> None: if self.Uninitialized(): @@ -172,9 +183,6 @@ class Connection(Wrapper, Endpoint): self.url = None self._acceptor = None -def _get_attachments(self): -return pn_connection_attachments(self._impl) - @property def connection(self) -> 'Connection': """ @@ -197,12 +205,6 @@ class Connection(Wrapper, Endpoint): else: return err -def _get_cond_impl(self): -return pn_connection_condition(self._impl) - -def _get_remote_cond_impl(self): -return pn_connection_remote_condition(self._impl) - # TODO: Blacklisted API call def collect(self, collector: 'Collector') -> None: if collector is None: @@ -403,17 +405,6 @@ class Connection(Wrapper, Endpoint): s.terminate() s.update() -@property -def state(self) -> int: -""" -The state of the connection as a bit field. The state has a local -and a remote component. Each of these can be in one of three -states: ``UNINIT``, ``ACTIVE`` or ``CLOSED``. These can be tested by masking -against :const:`LOCAL_UNINIT`, :const:`LOCAL_ACTIVE`, :const:`LOCAL_CLOSED`, :const:`REMOTE_UNINIT`, -:const:`REMOTE_ACTIVE` and :const:`REMOTE_CLOSED`. -""" -return pn_connection_state(self._impl) - def session(self) -> 'Session':
(qpid-proton) 04/04: PROTON-2893: [Python] Add callback for all delivery updates
This is an automated email from the ASF dual-hosted git repository. astitcher pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/qpid-proton.git commit 3191f95d88b3dbf78ac46474b4ce89d7627fce32 Author: Andrew Stitcher AuthorDate: Wed May 22 18:02:36 2024 -0400 PROTON-2893: [Python] Add callback for all delivery updates This is useful for responding to delivery updates besides the common AMQP updates. Specifically for better transaction support. --- python/proton/_handlers.py | 24 1 file changed, 24 insertions(+) diff --git a/python/proton/_handlers.py b/python/proton/_handlers.py index 79a6f3df5..e2d194db2 100644 --- a/python/proton/_handlers.py +++ b/python/proton/_handlers.py @@ -115,6 +115,7 @@ class OutgoingMessageHandler(Handler): self.on_rejected(event) elif dlv.remote_state == Delivery.RELEASED or dlv.remote_state == Delivery.MODIFIED: self.on_released(event) +self.on_delivery_updated(event) if dlv.settled: self.on_settled(event) if self.auto_settle: @@ -163,6 +164,18 @@ class OutgoingMessageHandler(Handler): if self.delegate is not None: _dispatch(self.delegate, 'on_released', event) +def on_delivery_updated(self, event: DeliveryEvent): +""" +Called when the remote peer updates the status of a delivery. Note that +this will be called even if the more specific disposition update events +are also called. + +:param event: The underlying event object. Use this to obtain further +information on the event. +""" +if self.delegate is not None: +_dispatch(self.delegate, 'on_delivery_updated', event) + def on_settled(self, event: DeliveryEvent): """ Called when the remote peer has settled the outgoing @@ -917,6 +930,17 @@ class MessagingHandler(Handler, Acking): """ pass +def on_delivery_updated(self, event: DeliveryEvent) -> None: +""" +Called when the remote peer updates the status of a delivery. Note that +this will be called even if the more specific disposition update events +are also called. + +:param event: The underlying event object. Use this to obtain further +information on the event. +""" +pass + def on_settled(self, event: DeliveryEvent) -> None: """ Called when the remote peer has settled the outgoing - To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org For additional commands, e-mail: commits-h...@qpid.apache.org
(qpid-proton) 01/04: PROTON-2891: [Python] Improve typing annotations especially for Events
This is an automated email from the ASF dual-hosted git repository. astitcher pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/qpid-proton.git commit 5de2b8e93300b366c1952d942897d1aa92206acb Author: Andrew Stitcher AuthorDate: Fri Apr 18 18:37:57 2025 -0400 PROTON-2891: [Python] Improve typing annotations especially for Events --- python/proton/_delivery.py | 3 + python/proton/_endpoints.py | 7 +- python/proton/_events.py| 2 +- python/proton/_handlers.py | 196 ++-- 4 files changed, 128 insertions(+), 80 deletions(-) diff --git a/python/proton/_delivery.py b/python/proton/_delivery.py index 90bf3689f..41c39d84a 100644 --- a/python/proton/_delivery.py +++ b/python/proton/_delivery.py @@ -133,6 +133,9 @@ class Disposition: MODIFIED = DispositionType.MODIFIED TRANSACTIONAL_STATE = DispositionType.TRANSACTIONAL_STATE +@property +def type(self) -> Union[int, DispositionType]: ... + class RemoteDisposition(Disposition): diff --git a/python/proton/_endpoints.py b/python/proton/_endpoints.py index 2559a4dd5..21171b16d 100644 --- a/python/proton/_endpoints.py +++ b/python/proton/_endpoints.py @@ -65,7 +65,7 @@ from ._transport import Transport from ._wrapper import Wrapper from collections.abc import Iterator -from typing import Any, Optional, Union, TYPE_CHECKING +from typing import Any, Optional, Union, TYPE_CHECKING, overload if TYPE_CHECKING: from ._condition import Condition @@ -1170,6 +1170,11 @@ class Sender(Link): """ return self._check(pn_link_send(self._impl, data)) +@overload +def send(self, obj: bytes) -> int: ... +@overload +def send(self, obj: 'Message', tag: Optional[str] = None) -> Delivery: ... + def send(self, obj: Union[bytes, 'Message'], tag: Optional[str] = None) -> Union[int, Delivery]: """ A convenience method to send objects as message content. diff --git a/python/proton/_events.py b/python/proton/_events.py index 55c5d7717..e9995b9dc 100644 --- a/python/proton/_events.py +++ b/python/proton/_events.py @@ -556,7 +556,7 @@ class Event(EventBase): return self._session @property -def link(self) -> Optional[Union['Receiver', 'Sender']]: +def link(self) -> Optional[Link]: """ The link associated with the event, or ``None`` if none is associated with it. diff --git a/python/proton/_handlers.py b/python/proton/_handlers.py index 819f8431c..79a6f3df5 100644 --- a/python/proton/_handlers.py +++ b/python/proton/_handlers.py @@ -24,8 +24,8 @@ import time import weakref from ._condition import Condition -from ._delivery import Delivery, ModifiedDisposition -from ._endpoints import Endpoint +from ._delivery import Delivery, DispositionType, ModifiedDisposition +from ._endpoints import Connection, Endpoint, Link, Receiver, Session from ._events import Event, _dispatch from ._exceptions import ProtonException from ._handler import Handler @@ -34,16 +34,56 @@ from ._message import Message from ._selectable import Selectable from ._transport import Transport from ._url import Url -from typing import Any, Optional, Union, TYPE_CHECKING + +from typing import Any, Optional, TYPE_CHECKING if TYPE_CHECKING: -from ._delivery import DispositionType from ._reactor import Container, Transaction -from ._endpoints import Sender, Receiver log = logging.getLogger("proton") +class ConnectionEvent(Event): +@property +def connection(self) -> Connection: ... + + +class SessionEvent(ConnectionEvent): +@property +def session(self) -> Session: ... + + +class LinkEvent(SessionEvent): +@property +def link(self) -> Link: ... + + +class DeliveryEvent(LinkEvent): +@property +def delivery(self) -> Delivery: ... + + +class MessageEvent(DeliveryEvent): +@property +def message(self) -> Message: ... + +@property +def receiver(self) -> Receiver: ... + + +class TransportEvent(Event): +@property +def transport(self) -> Transport: ... + + +class ConnectionBoundEvent(Event): +@property +def connection(self) -> Connection: ... + +@property +def transport(self) -> Transport: ... + + class OutgoingMessageHandler(Handler): """ A utility for simpler and more intuitive handling of delivery @@ -60,13 +100,13 @@ class OutgoingMessageHandler(Handler): self.auto_settle = auto_settle self.delegate = delegate -def on_link_flow(self, event: Event): +def on_link_flow(self, event: LinkEvent): if event.link.is_sender and event.link.credit \ and event.link.state & Endpoint.LOCAL_ACTIVE \ and event.link.state & Endpoint.REMOTE_ACTIVE: self.on_sendable(event) -def on_delivery(self, event: Event): +def on_delivery(self, event: DeliveryEvent): dlv = event.delivery if dlv.link.is_sender and dlv.updat
(qpid-proton) branch main updated (e1d147e22 -> 3191f95d8)
This is an automated email from the ASF dual-hosted git repository. astitcher pushed a change to branch main in repository https://gitbox.apache.org/repos/asf/qpid-proton.git from e1d147e22 PROTON-2890: [Python examples] Simple recv now deduplicates more accurately new 5de2b8e93 PROTON-2891: [Python] Improve typing annotations especially for Events new 1fafacd74 PROTON-2868: [Python] More work simplifying wrapped classes new d8ff8f731 PROTON-2892: [Python] Use python library IntFlag for Endpoint state new 3191f95d8 PROTON-2893: [Python] Add callback for all delivery updates The 4 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "add" were already present in the repository and have only been added to this reference. Summary of changes: python/proton/_delivery.py | 3 + python/proton/_endpoints.py | 153 +- python/proton/_events.py| 2 +- python/proton/_handlers.py | 220 python/proton/_wrapper.py | 2 +- 5 files changed, 213 insertions(+), 167 deletions(-) - To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org For additional commands, e-mail: commits-h...@qpid.apache.org