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 6b29f6d848828f5d0cd5706333c6570e71cbc666 Author: Andrew Stitcher <astitc...@apache.org> AuthorDate: Tue Apr 4 15:52:06 2023 -0400 PROTON-2704: Reorganise python code to avoid runtime import of _events This runtime import was causing an exception at shutdown with the new cffi based code as it can happen in a delete operation in the middle of shutting down python. This was causing the test to hang. --- python/CMakeLists.txt | 1 + python/proton/__init__.py | 3 ++- python/proton/_endpoints.py | 14 +++++----- python/proton/_events.py | 55 +++++---------------------------------- python/proton/_handler.py | 63 +++++++++++++++++++++++++++++++++++++++++++++ python/proton/_handlers.py | 5 ++-- python/proton/_reactor.py | 3 ++- 7 files changed, 84 insertions(+), 60 deletions(-) diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 2f6da5ad5..a2480b795 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -28,6 +28,7 @@ set (pysrc proton/_endpoints.py proton/_events.py proton/_exceptions.py + proton/_handler.py proton/_io.py proton/_message.py proton/_tracing.py diff --git a/python/proton/__init__.py b/python/proton/__init__.py index 5f82a4bfe..302b0ae96 100644 --- a/python/proton/__init__.py +++ b/python/proton/__init__.py @@ -38,9 +38,10 @@ from ._data import UNDESCRIBED, Array, Data, Described, char, symbol, timestamp, byte, short, int32, float32, decimal32, decimal64, decimal128, AnnotationDict, PropertyDict, SymbolList from ._delivery import Delivery, Disposition from ._endpoints import Endpoint, Connection, Session, Link, Receiver, Sender, Terminus -from ._events import Collector, Event, EventType, Handler +from ._events import Collector, Event, EventType from ._exceptions import ProtonException, MessageException, DataException, TransportException, \ SSLException, SSLUnavailable, ConnectionException, SessionException, LinkException, Timeout, Interrupt +from ._handler import Handler from ._message import Message from ._transport import Transport, SASL, SSL, SSLDomain, SSLSessionDetails from ._url import Url diff --git a/python/proton/_endpoints.py b/python/proton/_endpoints.py index ee4defe42..ae7ab81d6 100644 --- a/python/proton/_endpoints.py +++ b/python/proton/_endpoints.py @@ -61,14 +61,15 @@ from ._condition import cond2obj, obj2cond from ._data import Data, dat2obj, obj2dat, PropertyDict, SymbolList from ._delivery import Delivery from ._exceptions import ConnectionException, EXCEPTIONS, LinkException, SessionException +from ._handler import Handler from ._transport import Transport from ._wrapper import Wrapper -from typing import Callable, Dict, List, Optional, Union, TYPE_CHECKING, Any +from typing import Dict, List, Optional, Union, TYPE_CHECKING, Any if TYPE_CHECKING: from ._condition import Condition from ._data import Array, PythonAMQPData, symbol - from ._events import Collector, Handler + from ._events import Collector from ._message import Message @@ -113,7 +114,7 @@ class Endpoint(object): def _init(self) -> None: self.condition: Optional['Condition'] = None - self._handler: Optional['Handler'] = None + self._handler: Optional[Handler] = None def _update_cond(self) -> None: obj2cond(self.condition, self._get_cond_impl()) @@ -134,7 +135,7 @@ class Endpoint(object): assert False, "Subclass must override this!" @property - def handler(self) -> Optional['Handler']: + def handler(self) -> Optional[Handler]: """Handler for events. :getter: Get the event handler, or return ``None`` if no handler has been set. @@ -142,12 +143,11 @@ class Endpoint(object): return self._handler @handler.setter - def handler(self, handler: Optional['Handler']) -> None: + def handler(self, handler: Optional[Handler]) -> None: # TODO Hack This is here for some very odd (IMO) backwards compat behaviour - from ._events import Handler if handler is None: self._handler = None - elif issubclass(type(handler), Handler): + elif isinstance(handler, Handler): self._handler = handler else: self._handler = Handler() diff --git a/python/proton/_events.py b/python/proton/_events.py index 9cc721ad9..76d14f021 100644 --- a/python/proton/_events.py +++ b/python/proton/_events.py @@ -33,15 +33,13 @@ from cproton import PN_CONNECTION_BOUND, PN_CONNECTION_FINAL, PN_CONNECTION_INIT from ._delivery import Delivery from ._endpoints import Connection, Link, Session +from ._handler import Handler from ._transport import Transport -from typing import Any, List, Optional, Union, TYPE_CHECKING, Callable, Tuple, Type +from typing import Any, Optional, Union, TYPE_CHECKING if TYPE_CHECKING: - from ._reactor import Container from ._endpoints import Receiver, Sender - from ._handlers import ConnectSelectable - from ._selectable import Selectable - from types import TracebackType + from ._reactor import Container class Collector: @@ -143,11 +141,11 @@ class EventBase(object): return self._type @property - def handler(self) -> Optional['Handler']: + def handler(self) -> Optional[Handler]: """The handler for this event type. Not implemented, always returns ``None``.""" return None - def dispatch(self, handler: 'Handler', type: Optional[EventType] = None) -> None: + def dispatch(self, handler: Handler, type: Optional[EventType] = None) -> None: """ Process this event by sending it to all known handlers that are valid for this event type. @@ -474,7 +472,7 @@ class Event(EventBase): return self._context @property - def handler(self) -> Optional['Handler']: + def handler(self) -> Optional[Handler]: """ The handler for this event. The handler is determined by looking at the following in order: @@ -600,44 +598,3 @@ class Event(EventBase): is associated with it. """ return self._delivery - - -class LazyHandlers(object): - def __get__(self, obj: 'Handler', clazz: Any) -> Union['LazyHandlers', List[Any]]: - if obj is None: - return self - ret = [] - obj.__dict__['handlers'] = ret - return ret - - -class Handler(object): - """ - An abstract handler for events which supports child handlers. - """ - handlers = LazyHandlers() - - # TODO What to do with on_error? - def add( - self, - handler: Any, - on_error: Optional[Callable[[Tuple[Type[BaseException], BaseException, 'TracebackType']], None]] = None, - ) -> None: - """ - Add a child handler - - :param handler: A child handler - :type handler: :class:`Handler` or one of its derivatives. - :param on_error: Not used - """ - self.handlers.append(handler) - - def on_unhandled(self, method: str, *args) -> None: - """ - The callback for handling events which are not handled by - any other handler. - - :param method: The name of the intended handler method. - :param args: Arguments for the intended handler method. - """ - pass diff --git a/python/proton/_handler.py b/python/proton/_handler.py new file mode 100644 index 000000000..e6d911855 --- /dev/null +++ b/python/proton/_handler.py @@ -0,0 +1,63 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + + +from typing import Any, Callable, List, Optional, Tuple, Type, Union +from types import TracebackType + + +class LazyHandlers(object): + def __get__(self, obj: 'Handler', clazz: Any) -> Union['LazyHandlers', List[Any]]: + if obj is None: + return self + ret = [] + obj.__dict__['handlers'] = ret + return ret + + +class Handler(object): + """ + An abstract handler for events which supports child handlers. + """ + handlers = LazyHandlers() + + # TODO What to do with on_error? + def add( + self, + handler: Any, + on_error: Optional[Callable[[Tuple[Type[BaseException], BaseException, 'TracebackType']], None]] = None, + ) -> None: + """ + Add a child handler + + :param handler: A child handler + :type handler: :class:`Handler` or one of its derivatives. + :param on_error: Not used + """ + self.handlers.append(handler) + + def on_unhandled(self, method: str, *args) -> None: + """ + The callback for handling events which are not handled by + any other handler. + + :param method: The name of the intended handler method. + :param args: Arguments for the intended handler method. + """ + pass diff --git a/python/proton/_handlers.py b/python/proton/_handlers.py index c9d1ec21f..1d390886c 100644 --- a/python/proton/_handlers.py +++ b/python/proton/_handlers.py @@ -26,14 +26,15 @@ import weakref from ._condition import Condition from ._delivery import Delivery from ._endpoints import Endpoint -from ._events import Event, Handler, _dispatch +from ._events import Event, _dispatch from ._exceptions import ProtonException +from ._handler import Handler from ._io import IO from ._message import Message from ._selectable import Selectable from ._transport import Transport from ._url import Url -from typing import Any, List, Optional, Tuple, Union, TYPE_CHECKING, TypeVar +from typing import Any, List, Optional, Union, TYPE_CHECKING if TYPE_CHECKING: from ._delivery import DispositionType diff --git a/python/proton/_reactor.py b/python/proton/_reactor.py index 40939863e..6b86968b1 100644 --- a/python/proton/_reactor.py +++ b/python/proton/_reactor.py @@ -46,8 +46,9 @@ from cproton import PN_ACCEPTED, PN_EVENT_NONE from ._data import Described, symbol, ulong from ._delivery import Delivery from ._endpoints import Connection, Endpoint, Link, Session, Terminus -from ._events import Collector, EventType, EventBase, Handler, Event +from ._events import Collector, EventType, EventBase, Event from ._exceptions import SSLUnavailable +from ._handler import Handler from ._handlers import OutgoingMessageHandler, IOHandler from ._io import IO from ._message import Message --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org For additional commands, e-mail: commits-h...@qpid.apache.org