This is an automated email from the ASF dual-hosted git repository.

jdanek pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/qpid-proton.git


The following commit(s) were added to refs/heads/main by this push:
     new 38e1768  PROTON-2407 Introduce more optional typing annotations to 
Python binding (#326)
38e1768 is described below

commit 38e176816c18de1b7490ec449fb71893e1287304
Author: Jiri Daněk <jda...@redhat.com>
AuthorDate: Thu Aug 5 21:12:49 2021 +0200

    PROTON-2407 Introduce more optional typing annotations to Python binding 
(#326)
---
 python/proton/_condition.py  |  15 +++--
 python/proton/_data.py       |   8 ++-
 python/proton/_delivery.py   |   8 +--
 python/proton/_endpoints.py  |  29 +++------
 python/proton/_handlers.py   |  19 +++---
 python/proton/_io.py         |   2 +-
 python/proton/_message.py    |  13 ++--
 python/proton/_reactor.py    | 141 ++++++++++++++++++++++++++-----------------
 python/proton/_selectable.py |  14 +++--
 python/proton/_transport.py  |  23 ++++---
 python/proton/_utils.py      |  74 ++++++++++++-----------
 python/proton/_wrapper.py    |  15 ++---
 12 files changed, 201 insertions(+), 160 deletions(-)

diff --git a/python/proton/_condition.py b/python/proton/_condition.py
index 445c912..ab390af 100644
--- a/python/proton/_condition.py
+++ b/python/proton/_condition.py
@@ -17,13 +17,16 @@
 # under the License.
 #
 
-from typing import Optional
+from typing import Optional, TYPE_CHECKING
 
 from cproton import pn_condition_clear, pn_condition_set_name, 
pn_condition_set_description, pn_condition_info, \
     pn_condition_is_set, pn_condition_get_name, pn_condition_get_description
 
 from ._data import Data, dat2obj
 
+if TYPE_CHECKING:
+    from ._data import PythonAMQPData
+
 
 class Condition:
     """
@@ -48,16 +51,18 @@ class Condition:
     information relevant to the identified condition.
 
     :ivar ~.name: The name of the condition.
-    :vartype ~.name: ``str``
     :ivar ~.description: A description of the condition.
-    :vartype ~.description: ``str``
     :ivar ~.info: A data object that holds the additional information 
associated
         with the condition. The data object may be used both to access and to
         modify the additional information associated with the condition.
-    :vartype ~.info: :class:`Data`
     """
 
-    def __init__(self, name, description=None, info=None):
+    def __init__(
+            self,
+            name: str,
+            description: Optional[str] = None,
+            info: Optional['PythonAMQPData'] = None
+    ) -> None:
         self.name = name
         self.description = description
         self.info = info
diff --git a/python/proton/_data.py b/python/proton/_data.py
index 6e91a37..f88cec5 100644
--- a/python/proton/_data.py
+++ b/python/proton/_data.py
@@ -22,10 +22,14 @@ from typing import Callable, List, Tuple, Union, Optional, 
Any, Dict, Iterable,
 try:
     from typing import Literal
 except ImportError:
-    class Literal:
-        def __class_getitem__(cls, item):
+    # https://www.python.org/dev/peps/pep-0560/#class-getitem
+    class GenericMeta(type):
+        def __getitem__(self, item):
             pass
 
+    class Literal(metaclass=GenericMeta):
+        pass
+
 from cproton import PN_ARRAY, PN_BINARY, PN_BOOL, PN_BYTE, PN_CHAR, 
PN_DECIMAL128, PN_DECIMAL32, PN_DECIMAL64, \
     PN_DESCRIBED, PN_DOUBLE, PN_FLOAT, PN_INT, PN_LIST, PN_LONG, PN_MAP, 
PN_NULL, PN_OVERFLOW, PN_SHORT, PN_STRING, \
     PN_SYMBOL, PN_TIMESTAMP, PN_UBYTE, PN_UINT, PN_ULONG, PN_USHORT, PN_UUID, 
pn_data, pn_data_clear, pn_data_copy, \
diff --git a/python/proton/_delivery.py b/python/proton/_delivery.py
index 7104753..3fe9875 100644
--- a/python/proton/_delivery.py
+++ b/python/proton/_delivery.py
@@ -40,7 +40,7 @@ if TYPE_CHECKING:
 class NamedInt(int):
     values: Dict[int, str] = {}
 
-    def __new__(cls, i, name):
+    def __new__(cls: Type['DispositionType'], i: int, name: str) -> 
'DispositionType':
         ni = super(NamedInt, cls).__new__(cls, i)
         cls.values[i] = ni
         return ni
@@ -55,7 +55,7 @@ class NamedInt(int):
         return self.name
 
     @classmethod
-    def get(cls, i):
+    def get(cls, i: int) -> Union[int, 'DispositionType']:
         return cls.values.get(i, i)
 
 
@@ -320,11 +320,9 @@ class Delivery(Wrapper):
         self.remote = Disposition(pn_delivery_remote(self._impl), False)
 
     @property
-    def tag(self):
+    def tag(self) -> str:
         """
         The identifier for the delivery.
-
-        :type: ``bytes``
         """
         return pn_delivery_tag(self._impl)
 
diff --git a/python/proton/_endpoints.py b/python/proton/_endpoints.py
index 9520d68..b27be28 100644
--- a/python/proton/_endpoints.py
+++ b/python/proton/_endpoints.py
@@ -63,7 +63,8 @@ from ._delivery import Delivery
 from ._exceptions import ConnectionException, EXCEPTIONS, LinkException, 
SessionException
 from ._transport import Transport
 from ._wrapper import Wrapper
-from typing import Callable, Dict, List, Optional, Union, TYPE_CHECKING
+from typing import Callable, Dict, List, Optional, Union, TYPE_CHECKING, Any
+
 if TYPE_CHECKING:
     from ._condition import Condition
     from ._data import Array, symbol
@@ -165,7 +166,7 @@ class Connection(Wrapper, Endpoint):
         else:
             return Connection(impl)
 
-    def __init__(self, impl=pn_connection):
+    def __init__(self, impl: Callable[[], Any] = pn_connection) -> None:
         Wrapper.__init__(self, impl, pn_connection_attachments)
 
     def _init(self) -> None:
@@ -375,15 +376,11 @@ class Connection(Wrapper, Endpoint):
         return dat2obj(pn_connection_remote_properties(self._impl))
 
     @property
-    def connected_address(self):
-        """
-        The address for this connection.
-
-        :type: ``str``
-        """
+    def connected_address(self) -> str:
+        """The address for this connection."""
         return self.url and str(self.url)
 
-    def open(self):
+    def open(self) -> None:
         """
         Opens the connection.
 
@@ -893,7 +890,7 @@ class Link(Wrapper, Endpoint):
         """
         return self.session.transport
 
-    def delivery(self, tag):
+    def delivery(self, tag: str) -> Delivery:
         """
         Create a delivery. Every delivery object within a
         link must be supplied with a unique tag. Links
@@ -901,8 +898,6 @@ class Link(Wrapper, Endpoint):
         they are created.
 
         :param tag: Delivery tag unique for this link.
-        :type tag: ``bytes``
-        :rtype: :class:`Delivery`
         """
         return Delivery(pn_delivery(self._impl, tag))
 
@@ -1040,23 +1035,19 @@ class Link(Wrapper, Endpoint):
         return pn_link_is_receiver(self._impl)
 
     @property
-    def remote_snd_settle_mode(self):
+    def remote_snd_settle_mode(self) -> int:
         """
         The remote sender settle mode for this link. One of
         :const:`SND_UNSETTLED`, :const:`SND_SETTLED` or
         :const:`SND_MIXED`.
-
-        :type: ``int``
         """
         return pn_link_remote_snd_settle_mode(self._impl)
 
     @property
-    def remote_rcv_settle_mode(self):
+    def remote_rcv_settle_mode(self) -> int:
         """
         The remote receiver settle mode for this link. One of
         :const:`RCV_FIRST` or :const:`RCV_SECOND`.
-
-        :type: ``int``
         """
         return pn_link_remote_rcv_settle_mode(self._impl)
 
@@ -1161,7 +1152,7 @@ class Link(Wrapper, Endpoint):
         """
         return pn_link_detach(self._impl)
 
-    def free(self):
+    def free(self) -> None:
         """
         Free this link object. When a link object is freed,
         all :class:`Delivery` objects associated with the session (**<-- CHECK 
THIS**)
diff --git a/python/proton/_handlers.py b/python/proton/_handlers.py
index 0191b98..7ec1c6b 100644
--- a/python/proton/_handlers.py
+++ b/python/proton/_handlers.py
@@ -36,6 +36,7 @@ from ._url import Url
 from typing import Any, List, Optional, Tuple, Union, TYPE_CHECKING, TypeVar
 
 if TYPE_CHECKING:
+    from ._delivery import DispositionType
     from ._reactor import Container, Transaction
     from ._endpoints import Sender, Receiver
 
@@ -159,7 +160,7 @@ class Acking(object):
     A class containing methods for handling received messages.
     """
 
-    def accept(self, delivery: Delivery):
+    def accept(self, delivery: Delivery) -> None:
         """
         Accepts a received message.
 
@@ -171,7 +172,7 @@ class Acking(object):
         """
         self.settle(delivery, Delivery.ACCEPTED)
 
-    def reject(self, delivery: Delivery):
+    def reject(self, delivery: Delivery) -> None:
         """
         Rejects a received message that is considered invalid or
         unprocessable.
@@ -184,7 +185,7 @@ class Acking(object):
         """
         self.settle(delivery, Delivery.REJECTED)
 
-    def release(self, delivery: Delivery, delivered: bool = True):
+    def release(self, delivery: Delivery, delivered: bool = True) -> None:
         """
         Releases a received message, making it available at the source
         for any (other) interested receiver. The ``delivered``
@@ -207,16 +208,14 @@ class Acking(object):
         else:
             self.settle(delivery, Delivery.RELEASED)
 
-    def settle(self, delivery, state=None):
+    def settle(self, delivery: Delivery, state: Optional['DispositionType'] = 
None) -> None:
         """
         Settles the message delivery, and optionally updating the
         delivery state.
 
         :param delivery: The message delivery tracking object
-        :type delivery: :class:`proton.Delivery`
-        :param state: The delivery state, or ``None`` if not update
+        :param state: The delivery state, or ``None`` if no update
             is to be performed.
-        :type  state: ``int`` or ``None``
         """
         if state:
             delivery.update(state)
@@ -228,13 +227,12 @@ class IncomingMessageHandler(Handler, Acking):
     A utility for simpler and more intuitive handling of delivery
     events related to incoming i.e. received messages.
 
-    :type auto_accept: ``bool``
     :param auto_accept: If ``True``, accept all messages (default). Otherwise
         messages must be individually accepted or rejected.
     :param delegate: A client handler for the endpoint event
     """
 
-    def __init__(self, auto_accept=True, delegate=None):
+    def __init__(self, auto_accept: bool = True, delegate: Optional[Handler] = 
None) -> None:
         self.delegate = delegate
         self.auto_accept = auto_accept
 
@@ -316,11 +314,10 @@ class EndpointStateHandler(Handler):
     :param peer_close_is_error: If ``True``, a peer endpoint closing will be
         treated as an error with an error callback. Otherwise (default), the
         normal callbacks for the closing will occur.
-    :type peer_close_is_error:  ``bool``
     :param delegate: A client handler for the endpoint event
     """
 
-    def __init__(self, peer_close_is_error=False, delegate=None):
+    def __init__(self, peer_close_is_error: bool = False, delegate: 
Optional[Handler] = None) -> None:
         self.delegate = delegate
         self.peer_close_is_error = peer_close_is_error
 
diff --git a/python/proton/_io.py b/python/proton/_io.py
index 2758587..5628d1d 100644
--- a/python/proton/_io.py
+++ b/python/proton/_io.py
@@ -125,7 +125,7 @@ class IO(object):
                 self._writing.add(selectable)
             self.update_deadline()
 
-        def select(self, timeout):
+        def select(self, timeout: float) -> Tuple[List, List, List]:
 
             def select_inner(timeout):
                 # This inner select adds the writing fds to the exception fd 
set
diff --git a/python/proton/_message.py b/python/proton/_message.py
index 3d12a04..54e9fe9 100644
--- a/python/proton/_message.py
+++ b/python/proton/_message.py
@@ -506,18 +506,15 @@ class Message(object):
         self._check(pn_message_decode(self._msg, data))
         self._post_decode()
 
-    def send(self, sender, tag=None):
+    def send(self, sender: 'Sender', tag: Optional[str] = None) -> 'Delivery':
         """
         Encodes and sends the message content using the specified sender,
         and, if present, using the specified tag. Upon success, will
         return the :class:`Delivery` object for the sent message.
 
         :param sender: The sender to send the message
-        :type sender: :class:`Sender`
         :param tag: The delivery tag for the sent message
-        :type tag: ``bytes``
         :return: The delivery associated with the sent message
-        :rtype: :class:`Delivery`
         """
         dlv = sender.delivery(tag or sender.delivery_tag())
         encoded = self.encode()
@@ -527,7 +524,11 @@ class Message(object):
             dlv.settle()
         return dlv
 
-    def recv(self, link):
+    @overload
+    def recv(self, link: 'Sender') -> None:
+        ...
+
+    def recv(self, link: 'Receiver') -> Optional['Delivery']:
         """
         Receives and decodes the message content for the current 
:class:`Delivery`
         from the link. Upon success it will return the current delivery
@@ -536,9 +537,7 @@ class Message(object):
         return ``None``.
 
         :param link: The link to receive a message from
-        :type link: :class:`Link`
         :return: the delivery associated with the decoded message (or None)
-        :rtype: :class:`Delivery`
 
         """
         if link.is_sender:
diff --git a/python/proton/_reactor.py b/python/proton/_reactor.py
index 8e69d4a..aeabc53 100644
--- a/python/proton/_reactor.py
+++ b/python/proton/_reactor.py
@@ -23,15 +23,18 @@ import logging
 import re
 import os
 import queue
-from typing import Any, Dict, Iterator, Optional, List, Union, Callable
+from typing import Any, Dict, Iterator, Optional, List, Union, Callable, 
TYPE_CHECKING
 try:
     from typing import Literal
 except ImportError:
-    class Literal:
-        @classmethod
-        def __class_getitem__(cls, item):
+    # https://www.python.org/dev/peps/pep-0560/#class-getitem
+    class GenericMeta(type):
+        def __getitem__(self, item):
             pass
 
+    class Literal(metaclass=GenericMeta):
+        pass
+
 import time
 import traceback
 import uuid
@@ -39,25 +42,22 @@ from functools import total_ordering
 
 from cproton import PN_PYREF, PN_ACCEPTED, PN_EVENT_NONE
 
+from ._common import isstring, unicode2utf8, utf82unicode
+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 ._exceptions import SSLUnavailable
-from ._data import Described, symbol, ulong
+from ._handlers import OutgoingMessageHandler, IOHandler
+from ._io import IO
 from ._message import Message
 from ._transport import Transport, SSL, SSLDomain
 from ._url import Url
-from ._common import isstring, unicode2utf8, utf82unicode
-from ._events import Collector, EventType, EventBase, Handler, Event
 from ._selectable import Selectable
 
-from ._handlers import OutgoingMessageHandler, IOHandler
-
-from ._io import IO
-from typing import TYPE_CHECKING
 if TYPE_CHECKING:
     from ._endpoints import Receiver, Sender
-    from ._handlers import ConnectSelectable, TransactionHandler
-    from ._utils import BlockingConnection
+    from ._handlers import TransactionHandler
     from socket import socket
     from uuid import UUID
 
@@ -140,7 +140,7 @@ class Reactor(object):
     # TODO: need to make this actually return a proxy which catches exceptions 
and calls
     # on error.
     # [Or arrange another way to deal with exceptions thrown by handlers]
-    def _make_handler(self, handler):
+    def _make_handler(self, handler: Handler) -> Handler:
         """
         Return a proxy handler that dispatches to the provided handler.
 
@@ -283,7 +283,7 @@ class Reactor(object):
     def stop_events(self) -> None:
         self._collector.release()
 
-    def schedule(self, delay, handler):
+    def schedule(self, delay: Union[float, int], handler: Handler) -> Task:
         """
         Schedule a task to run on this container after a given delay,
         and using the supplied handler.
@@ -325,7 +325,12 @@ class Reactor(object):
                 return t._deadline
         return None
 
-    def acceptor(self, host, port, handler=None):
+    def acceptor(
+            self,
+            host: str,
+            port: Union[str, Url.Port],
+            handler: Optional[Handler] = None,
+    ) -> 'Acceptor':
         impl = self._make_handler(handler)
         a = Acceptor(self, unicode2utf8(host), int(port), impl)
         if a:
@@ -333,7 +338,7 @@ class Reactor(object):
         else:
             raise IOError("%s (%s:%s)" % (str(self.errors), host, port))
 
-    def connection(self, handler=None):
+    def connection(self, handler: Optional[Handler] = None) -> Connection:
         """Deprecated: use connection_to_host() instead
         """
         impl = self._make_handler(handler)
@@ -360,7 +365,7 @@ class Reactor(object):
         """
         connection.set_address(host, port)
 
-    def get_connection_address(self, connection):
+    def get_connection_address(self, connection: Connection) -> str:
         """*Deprecated* in favor of the property 
proton.Connection.connected_address.
         This may be used to retrieve the remote peer address.
         :return: string containing the address in URL format or None if no
@@ -369,7 +374,11 @@ class Reactor(object):
         """
         return connection.connected_address
 
-    def selectable(self, handler=None, delegate=None):
+    def selectable(
+            self,
+            handler: Optional[Union['Acceptor', 'EventInjector']] = None,
+            delegate: Optional['socket'] = None
+    ) -> Selectable:
         """
         NO IDEA!
 
@@ -384,10 +393,14 @@ class Reactor(object):
         result.handler = handler
         return result
 
-    def update(self, selectable):
+    def update(self, selectable: Selectable) -> None:
         selectable.update()
 
-    def push_event(self, obj, etype):
+    def push_event(
+            self,
+            obj: Union[Task, 'Container', Selectable],
+            etype: EventType
+    ) -> None:
         self._collector.put(obj, etype)
 
 
@@ -407,7 +420,7 @@ class EventInjector(object):
         self._transport = None
         self._closed = False
 
-    def trigger(self, event):
+    def trigger(self, event: 'ApplicationEvent') -> None:
         """
         Request that the given event be dispatched on the event thread
         of the container to which this EventInjector was added.
@@ -495,7 +508,7 @@ class ApplicationEvent(EventBase):
         self.subject = subject
 
     @property
-    def context(self):
+    def context(self) -> 'ApplicationEvent':
         """
         A reference to this event.
         """
@@ -523,7 +536,12 @@ class Transaction(object):
     (for a successful transaction), or :meth:`abort` (for a failed 
transaction).
     """
 
-    def __init__(self, txn_ctrl, handler, settle_before_discharge=False):
+    def __init__(
+            self,
+            txn_ctrl: 'Sender',
+            handler: 'TransactionHandler',
+            settle_before_discharge: bool = False,
+    ) -> None:
         self.txn_ctrl = txn_ctrl
         self.handler = handler
         self.id = None
@@ -560,18 +578,19 @@ class Transaction(object):
         delivery.transaction = self
         return delivery
 
-    def send(self, sender, msg, tag=None):
+    def send(
+            self,
+            sender: 'Sender',
+            msg: Message,
+            tag: Optional[bytes] = None,
+    ) -> Delivery:
         """
         Send a message under this transaction.
 
         :param sender: Link over which to send the message.
-        :type sender: :class:`proton.Sender`
         :param msg: Message to be sent under this transaction.
-        :type msg: :class:`proton.Message`
         :param tag: The delivery tag
-        :type tag: ``bytes``
         :return: Delivery object for this message.
-        :rtype: :class:`proton.Delivery`
         """
         dlv = sender.send(msg, tag=tag)
         dlv.local.data = [self.id]
@@ -590,7 +609,7 @@ class Transaction(object):
         else:
             self._pending.append(delivery)
 
-    def update(self, delivery, state=None):
+    def update(self, delivery: Delivery, state: Optional[ulong] = None) -> 
None:
         if state:
             delivery.local.data = [self.id, Described(ulong(state), [])]
             delivery.update(0x34)
@@ -725,10 +744,9 @@ class DynamicNodeProperties(LinkOption):
     they will be converted to symbols before being applied).
 
     :param props: A map of link options to be applied to a link.
-    :type props: ``dict``
     """
 
-    def __init__(self, props={}):
+    def __init__(self, props: dict = {}) -> None:
         self.properties = {}
         for k in props:
             if isinstance(k, symbol):
@@ -774,12 +792,10 @@ class Selector(Filter):
     Configures a receiver with a message selector filter
 
     :param value: Selector filter string
-    :type value: ``str``
     :param name: Name of the selector, defaults to ``"selector"``.
-    :type name: ``str``
     """
 
-    def __init__(self, value, name='selector'):
+    def __init__(self, value: Union[bytes, str], name: str = 'selector') -> 
None:
         super(Selector, self).__init__({symbol(name): Described(
             symbol('apache.org:selector-filter:string'), utf82unicode(value))})
 
@@ -836,7 +852,10 @@ class Copy(ReceiverOption):
         receiver.source.distribution_mode = Terminus.DIST_MODE_COPY
 
 
-def _apply_link_options(options, link):
+def _apply_link_options(
+        options: Optional[Union[LinkOption, List[LinkOption]]],
+        link: Union['Sender', 'Receiver']
+) -> None:
     if options:
         if isinstance(options, list):
             for o in options:
@@ -994,7 +1013,7 @@ def make_backoff_wrapper(backoff):
 
 
 class Urls(object):
-    def __init__(self, values):
+    def __init__(self, values: List[Union[Url, str]]) -> None:
         self.values = [Url(v) for v in values]
 
     def __iter__(self) -> Iterator[Url]:
@@ -1133,7 +1152,7 @@ def _find_config_file() -> Optional[str]:
     return None
 
 
-def _get_default_config():
+def _get_default_config() -> Dict[str, Any]:
     conf = os.environ.get('MESSAGING_CONNECT_FILE') or _find_config_file()
     if conf and os.path.isfile(conf):
         with open(conf, 'r') as f:
@@ -1189,8 +1208,17 @@ class Container(Reactor):
             self.user = None
             self.password = None
 
-    def connect(self, url=None, urls=None, address=None, handler=None, 
reconnect=None, heartbeat=None, ssl_domain=None,
-                **kwargs):
+    def connect(
+            self,
+            url: Optional[Union[str, Url]] = None,
+            urls: Optional[List[str]] = None,
+            address: Optional[str] = None,
+            handler: Optional[Handler] = None,
+            reconnect: Union[None, Literal[False], Backoff] = None,
+            heartbeat: Optional[float] = None,
+            ssl_domain: Optional[SSLDomain] = None,
+            **kwargs
+    ) -> Connection:
         """
         Initiates the establishment of an AMQP connection.
 
@@ -1218,30 +1246,23 @@ class Container(Reactor):
             ``ca`` above (:const:`proton.SSLDomain.VERIFY_PEER_NAME`).
 
         :param url: URL string of process to connect to
-        :type url: ``str``
-
         :param urls: list of URL strings of process to try to connect to
-        :type urls: ``[str, str, ...]``
 
         :param reconnect: Reconnect is enabled by default.  You can
             pass in an instance of :class:`Backoff` to control reconnect 
behavior.
             A value of ``False`` will prevent the library from automatically
             trying to reconnect if the underlying socket is disconnected
             before the connection has been closed.
-        :type reconnect: :class:`Backoff` or ``bool``
 
         :param heartbeat: A value in seconds indicating the
             desired frequency of heartbeats used to test the underlying
             socket is alive.
-        :type heartbeat: ``float``
 
         :param ssl_domain: SSL configuration.
-        :type ssl_domain: :class:`proton.SSLDomain`
 
         :param handler: a connection scoped handler that will be
             called to process any events in the scope of this connection
             or its child links.
-        :type handler: Any child of :class:`proton.Events.Handler`
 
         :param kwargs:
 
@@ -1279,7 +1300,6 @@ class Container(Reactor):
                 peers.
 
         :return: A new connection object.
-        :rtype: :class:`proton.Connection`
 
         .. note:: Only one of ``url`` or ``urls`` should be specified.
 
@@ -1330,7 +1350,16 @@ class Container(Reactor):
             return self._connect(url=url, urls=urls, handler=handler, 
reconnect=reconnect,
                                  heartbeat=heartbeat, ssl_domain=ssl_domain, 
**kwargs)
 
-    def _connect(self, url=None, urls=None, handler=None, reconnect=None, 
heartbeat=None, ssl_domain=None, **kwargs):
+    def _connect(
+            self,
+            url: Optional[Union[str, Url]] = None,
+            urls: Optional[List[str]] = None,
+            handler: Optional['Handler'] = None,
+            reconnect: Optional[Union[List[Union[float, int]], bool, Backoff]] 
= None,
+            heartbeat: None = None,
+            ssl_domain: Optional[SSLDomain] = None,
+            **kwargs
+    ) -> Connection:
         conn = self.connection(handler)
         conn.container = self.container_id or str(_generate_uuid())
         conn.offered_capabilities = kwargs.get('offered_capabilities')
@@ -1369,7 +1398,7 @@ class Container(Reactor):
         conn.open()
         return conn
 
-    def _get_id(self, container, remote, local):
+    def _get_id(self, container: str, remote: Optional[str], local: 
Optional[str]) -> str:
         if local and remote:
             "%s-%s-%s" % (container, remote, local)
         elif local:
@@ -1394,13 +1423,13 @@ class Container(Reactor):
 
     def create_sender(
             self,
-            context: Union[str, Connection],
+            context: Union[str, Url, Connection],
             target: Optional[str] = None,
             source: Optional[str] = None,
             name: Optional[str] = None,
             handler: Optional[Handler] = None,
             tags: Optional[Callable[[], bytes]] = None,
-            options: Optional[Union['SenderOption', List['SenderOption']]] = 
None
+            options: Optional[Union['SenderOption', List['SenderOption'], 
'LinkOption', List['LinkOption']]] = None
     ) -> 'Sender':
         """
         Initiates the establishment of a link over which messages can
@@ -1455,13 +1484,13 @@ class Container(Reactor):
 
     def create_receiver(
             self,
-            context: Union[Connection, str],
+            context: Union[Connection, Url, str],
             source: Optional[str] = None,
             target: Optional[str] = None,
             name: Optional[str] = None,
             dynamic: bool = False,
             handler: Optional[Handler] = None,
-            options: Optional[Union[ReceiverOption, List[ReceiverOption]]] = 
None
+            options: Optional[Union[ReceiverOption, List[ReceiverOption], 
LinkOption, List[LinkOption]]] = None
     ) -> 'Receiver':
         """
         Initiates the establishment of a link over which messages can
@@ -1547,15 +1576,13 @@ class Container(Reactor):
             
context._txn_ctrl.target.capabilities.put_object(symbol(u'amqp:local-transactions'))
         return Transaction(context._txn_ctrl, handler, settle_before_discharge)
 
-    def listen(self, url, ssl_domain=None):
+    def listen(self, url: Union[str, Url], ssl_domain: Optional[SSLDomain] = 
None) -> Acceptor:
         """
         Initiates a server socket, accepting incoming AMQP connections
         on the interface and port specified.
 
         :param url: URL on which to listen for incoming AMQP connections.
-        :type url: ``str`` or :class:`Url`
         :param ssl_domain: SSL configuration object if SSL is to be used, 
``None`` otherwise.
-        :type ssl_domain: :class:`proton.SSLDomain` or ``None``
         """
         url = Url(url)
         acceptor = self.acceptor(url.host, url.port)
diff --git a/python/proton/_selectable.py b/python/proton/_selectable.py
index a54d2b4..4eb370d 100644
--- a/python/proton/_selectable.py
+++ b/python/proton/_selectable.py
@@ -17,20 +17,24 @@
 # under the License.
 #
 
+from typing import Optional, Union, TYPE_CHECKING, Any
+
 from ._events import Event
 from ._io import PN_INVALID_SOCKET
 
-from typing import Callable, Optional, Union, TYPE_CHECKING
 if TYPE_CHECKING:
     from ._events import EventType
-    from ._handlers import ConnectSelectable
-    from ._reactor import Container, EventInjector, TimerSelectable
+    from ._reactor import Container, EventInjector
     from socket import socket
 
 
 class Selectable(object):
 
-    def __init__(self, delegate, reactor):
+    def __init__(
+            self,
+            delegate: Optional[Union['EventInjector', 'socket']],
+            reactor: 'Container',
+    ) -> None:
         self._delegate = delegate
         self.reading = False
         self.writing = False
@@ -51,7 +55,7 @@ class Selectable(object):
         else:
             return PN_INVALID_SOCKET
 
-    def __getattr__(self, name):
+    def __getattr__(self, name: str) -> Any:
         return getattr(self._delegate, name)
 
     def _get_deadline(self):
diff --git a/python/proton/_transport.py b/python/proton/_transport.py
index 50f2720..bf5e5ab 100644
--- a/python/proton/_transport.py
+++ b/python/proton/_transport.py
@@ -17,6 +17,8 @@
 # under the License.
 #
 
+from typing import Callable, Optional, Type, Union, TYPE_CHECKING, List
+
 from cproton import PN_EOS, PN_OK, PN_SASL_AUTH, PN_SASL_NONE, PN_SASL_OK, 
PN_SASL_PERM, PN_SASL_SYS, PN_SASL_TEMP, \
     PN_SSL_ANONYMOUS_PEER, PN_SSL_CERT_SUBJECT_CITY_OR_LOCALITY, 
PN_SSL_CERT_SUBJECT_COMMON_NAME, \
     PN_SSL_CERT_SUBJECT_COUNTRY_NAME, PN_SSL_CERT_SUBJECT_ORGANIZATION_NAME, 
PN_SSL_CERT_SUBJECT_ORGANIZATION_UNIT, \
@@ -45,8 +47,6 @@ from ._condition import cond2obj, obj2cond
 from ._exceptions import EXCEPTIONS, SSLException, SSLUnavailable, 
SessionException, TransportException
 from ._wrapper import Wrapper
 
-from typing import Callable, Optional, Type, Union, TYPE_CHECKING, List
-
 if TYPE_CHECKING:
     from ._condition import Condition
     from ._endpoints import Connection  # would produce circular import
@@ -54,7 +54,7 @@ if TYPE_CHECKING:
 
 class TraceAdapter:
 
-    def __init__(self, tracer):
+    def __init__(self, tracer: Callable[['Transport', str], None]) -> None:
         self.tracer = tracer
 
     def __call__(self, trans_impl, message):
@@ -85,13 +85,17 @@ class Transport(Wrapper):
     """ Transport mode is as a server. """
 
     @staticmethod
-    def wrap(impl):
+    def wrap(impl: Optional[Callable]) -> Optional['Transport']:
         if impl is None:
             return None
         else:
             return Transport(_impl=impl)
 
-    def __init__(self, mode=None, _impl=pn_transport):
+    def __init__(
+            self,
+            mode: 'Optional[int]' = None,
+            _impl: 'Callable' = pn_transport,
+    ) -> None:
         Wrapper.__init__(self, _impl, pn_transport_attachments)
         if mode == Transport.SERVER:
             pn_transport_set_server(self._impl)
@@ -862,7 +866,12 @@ class SSL(object):
         else:
             return err
 
-    def __new__(cls, transport, domain, session_details=None):
+    def __new__(
+            cls: Type['SSL'],
+            transport: Transport,
+            domain: SSLDomain,
+            session_details: Optional['SSLSessionDetails'] = None
+    ) -> 'SSL':
         """Enforce a singleton SSL object per Transport"""
         if transport._ssl:
             # unfortunately, we've combined the allocation and the 
configuration in a
@@ -1122,7 +1131,7 @@ class SSL(object):
     RESUME_REUSED = PN_SSL_RESUME_REUSED
     """Session resumed from previous session."""
 
-    def resume_status(self):
+    def resume_status(self) -> int:
         """
         Check whether the state has been resumed.
 
diff --git a/python/proton/_utils.py b/python/proton/_utils.py
index f14db9f..bdc1b34 100644
--- a/python/proton/_utils.py
+++ b/python/proton/_utils.py
@@ -34,14 +34,19 @@ from typing import Callable, Optional, Union, 
TYPE_CHECKING, List
 try:
     from typing import Literal
 except ImportError:
-    class Literal:
-        def __class_getitem__(cls, item):
+    # https://www.python.org/dev/peps/pep-0560/#class-getitem
+    class GenericMeta(type):
+        def __getitem__(self, item):
             pass
 
+    class Literal(metaclass=GenericMeta):
+        pass
+
 if TYPE_CHECKING:
+    from ._delivery import DispositionType
     from ._transport import SSLDomain
-    from ._reactor import Backoff, SenderOption, ReceiverOption, Connection
-    from ._endpoints import Receiver, Sender, Terminus
+    from ._reactor import SenderOption, ReceiverOption, Connection, 
LinkOption, Backoff
+    from ._endpoints import Receiver, Sender
     from ._events import Event
     from ._message import Message
 
@@ -112,7 +117,12 @@ class BlockingSender(BlockingLink):
             self.link.close()
             raise LinkException("Failed to open sender %s, target does not 
match" % self.link.name)
 
-    def send(self, msg, timeout=False, error_states=None):
+    def send(
+            self,
+            msg: 'Message',
+            timeout: Union[None, Literal[False], float] = False,
+            error_states: Optional[List['DispositionType']] = None,
+    ) -> Delivery:
         """
         Blocking send which will return only when the send is complete
         and the message settled.
@@ -120,13 +130,10 @@ class BlockingSender(BlockingLink):
         :param timeout: Timeout in seconds. If ``False``, the value of 
``timeout`` used in the
             constructor of the :class:`BlockingConnection` object used in the 
constructor will be used.
             If ``None``, there is no timeout. Any other value is treated as a 
timeout in seconds.
-        :type timeout: ``None``, ``False``, ``float``
         :param error_states: List of delivery flags which when present in 
Delivery object
             will cause a :class:`SendException` exception to be raised. If 
``None``, these
             will default to a list containing 
:const:`proton.Delivery.REJECTED` and :const:`proton.Delivery.RELEASED`.
-        :type error_states: ``list``
         :return: Delivery object for this message.
-        :rtype: :class:`proton.Delivery`
         """
         delivery = self.link.send(msg)
         self.connection.wait(lambda: _is_settled(delivery), msg="Sending on 
sender %s" % self.link.name,
@@ -144,14 +151,9 @@ class BlockingSender(BlockingLink):
 class Fetcher(MessagingHandler):
     """
     A message handler for blocking receivers.
-
-    :param connection:
-    :type connection: :class:
-    :param prefetch:
-    :type prefetch:
     """
 
-    def __init__(self, connection, prefetch):
+    def __init__(self, connection: 'Connection', prefetch: int):
         super(Fetcher, self).__init__(prefetch=prefetch, auto_accept=False)
         self.connection = connection
         self.incoming = collections.deque([])
@@ -236,7 +238,10 @@ class BlockingReceiver(BlockingLink):
         if hasattr(self, "container"):
             self.link.handler = None  # implicit call to reactor
 
-    def receive(self, timeout=False):
+    def receive(
+            self,
+            timeout: Union[None, Literal[False], float] = False
+    ) -> 'Message':
         """
         Blocking receive call which will return only when a message is 
received or
         a timeout (if supplied) occurs.
@@ -244,7 +249,6 @@ class BlockingReceiver(BlockingLink):
         :param timeout: Timeout in seconds. If ``False``, the value of 
``timeout`` used in the
             constructor of the :class:`BlockingConnection` object used in the 
constructor will be used.
             If ``None``, there is no timeout. Any other value is treated as a 
timeout in seconds.
-        :type timeout: ``None``, ``False``, ``float``
         """
         if not self.fetcher:
             raise Exception("Can't call receive on this receiver as a handler 
was not provided")
@@ -282,7 +286,7 @@ class BlockingReceiver(BlockingLink):
         else:
             self.settle(Delivery.RELEASED)
 
-    def settle(self, state=None):
+    def settle(self, state: Optional['DispositionType'] = None):
         """
         Settle any received messages.
 
@@ -349,23 +353,28 @@ class BlockingConnection(Handler):
     always executed on exit.
 
     :param url: The connection URL.
-    :type url: ``str``
     :param timeout: Connection timeout in seconds. If ``None``, defaults to 60 
seconds.
-    :type timeout: ``None`` or float
     :param container: Container to process the events on the connection. If 
``None``,
         a new :class:`proton.Container` will be created.
     :param ssl_domain:
     :param heartbeat: A value in seconds indicating the desired frequency of
         heartbeats used to test the underlying socket is alive.
-    :type heartbeat: ``float``
     :param urls: A list of connection URLs to try to connect to.
-    :type urls: ``list``[``str``]
     :param kwargs: Container keyword arguments. See 
:class:`proton.reactor.Container`
         for a list of the valid kwargs.
     """
 
-    def __init__(self, url=None, timeout=None, container=None, 
ssl_domain=None, heartbeat=None, urls=None,
-                 reconnect=None, **kwargs):
+    def __init__(
+            self,
+            url: Optional[Union[str, Url]] = None,
+            timeout: Optional[float] = None,
+            container: Optional[Container] = None,
+            ssl_domain: Optional['SSLDomain'] = None,
+            heartbeat: Optional[float] = None,
+            urls: Optional[List[str]] = None,
+            reconnect: Union[None, Literal[False], 'Backoff'] = None,
+            **kwargs
+    ) -> None:
         self.disconnected = False
         self.timeout = timeout or 60
         self.container = container or Container()
@@ -393,21 +402,16 @@ class BlockingConnection(Handler):
             address: Optional[str],
             handler: Optional[Handler] = None,
             name: Optional[str] = None,
-            options: Optional[Union['SenderOption', List['SenderOption']]] = 
None
+            options: Optional[Union['SenderOption', List['SenderOption'], 
'LinkOption', List['LinkOption']]] = None
     ) -> BlockingSender:
         """
         Create a blocking sender.
 
         :param address: Address of target node.
-        :type address: ``str``
         :param handler: Event handler for this sender.
-        :type handler: Any child class of :class:`proton.Handler`
         :param name: Sender name.
-        :type name: ``str``
         :param options: A single option, or a list of sender options
-        :type options: :class:`SenderOption` or [SenderOption, SenderOption, 
...]
         :return: New blocking sender instance.
-        :rtype: :class:`BlockingSender`
         """
         return BlockingSender(self, self.container.create_sender(self.conn, 
address, name=name, handler=handler,
                                                                  
options=options))
@@ -419,7 +423,7 @@ class BlockingConnection(Handler):
             dynamic: bool = False,
             handler: Optional[Handler] = None,
             name: Optional[str] = None,
-            options: Optional[Union['ReceiverOption', List['ReceiverOption']]] 
= None
+            options: Optional[Union['ReceiverOption', List['ReceiverOption'], 
'LinkOption', List['LinkOption']]] = None
     ) -> BlockingReceiver:
         """
         Create a blocking receiver.
@@ -490,18 +494,20 @@ class BlockingConnection(Handler):
         self.container.stop()
         self.container.process()
 
-    def wait(self, condition, timeout=False, msg=None):
+    def wait(
+            self,
+            condition: Callable[[], bool],
+            timeout: Union[None, Literal[False], float] = False,
+            msg: Optional[str] = None
+    ) -> None:
         """
         Process events until ``condition()`` returns ``True``.
 
         :param condition: Condition which determines when the wait will end.
-        :type condition: Function which returns ``bool``
         :param timeout: Timeout in seconds. If ``False``, the value of 
``timeout`` used in the
             constructor of this object will be used. If ``None``, there is no 
timeout. Any other
             value is treated as a timeout in seconds.
-        :type timeout: ``None``, ``False``, ``float``
         :param msg: Context message for :class:`proton.Timeout` exception
-        :type msg: ``str``
         """
         if timeout is False:
             timeout = self.timeout
diff --git a/python/proton/_wrapper.py b/python/proton/_wrapper.py
index 7ad4c87..4b3973f 100644
--- a/python/proton/_wrapper.py
+++ b/python/proton/_wrapper.py
@@ -17,6 +17,8 @@
 # under the License.
 #
 
+from typing import Any, Callable, Optional, Union
+
 from cproton import pn_incref, pn_decref, \
     pn_py2void, pn_void2py, \
     pn_record_get, pn_record_def, pn_record_set, \
@@ -24,11 +26,6 @@ from cproton import pn_incref, pn_decref, \
 
 from ._exceptions import ProtonException
 
-from typing import Any, Callable, Optional, Union, TYPE_CHECKING
-if TYPE_CHECKING:
-    from ._delivery import Delivery  # circular import
-    from ._transport import SASL, Transport
-
 
 class EmptyAttrs:
 
@@ -62,7 +59,11 @@ class Wrapper(object):
 
     """
 
-    def __init__(self, impl_or_constructor, get_context=None):
+    def __init__(
+            self,
+            impl_or_constructor: Union[Any, Callable[[], Any]],
+            get_context: Optional[Callable[[Any], Any]] = None,
+    ) -> None:
         init = False
         if callable(impl_or_constructor):
             # we are constructing a new object
@@ -119,7 +120,7 @@ class Wrapper(object):
     def __hash__(self) -> int:
         return hash(addressof(self._impl))
 
-    def __eq__(self, other):
+    def __eq__(self, other: Any) -> bool:
         if isinstance(other, Wrapper):
             return addressof(self._impl) == addressof(other._impl)
         return False

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org
For additional commands, e-mail: commits-h...@qpid.apache.org

Reply via email to