api: make run() always return a Future
plugins must be modified to make use of this, but this keeps synchronous code synchrouns while allowing coroutine in api, which makes sense.
This commit is contained in:
parent
8da5310ea6
commit
d51c4e307d
1 changed files with 25 additions and 11 deletions
|
@ -1,3 +1,5 @@
|
|||
from typing import Any, Optional
|
||||
from asyncio import iscoroutinefunction, Future
|
||||
from slixmpp.xmlstream import JID
|
||||
|
||||
|
||||
|
@ -44,7 +46,7 @@ class APIRegistry(object):
|
|||
self.xmpp = xmpp
|
||||
self.settings = {}
|
||||
|
||||
def _setup(self, ctype, op):
|
||||
def _setup(self, ctype: str, op: str):
|
||||
"""Initialize the API callback dictionaries.
|
||||
|
||||
:param string ctype: The name of the API to initialize.
|
||||
|
@ -61,17 +63,19 @@ class APIRegistry(object):
|
|||
'jid': {},
|
||||
'node': {}}
|
||||
|
||||
def wrap(self, ctype):
|
||||
def wrap(self, ctype: str) -> APIWrapper:
|
||||
"""Return a wrapper object that targets a specific API."""
|
||||
return APIWrapper(self, ctype)
|
||||
|
||||
def purge(self, ctype):
|
||||
def purge(self, ctype: str):
|
||||
"""Remove all information for a given API."""
|
||||
del self.settings[ctype]
|
||||
del self._handler_defaults[ctype]
|
||||
del self._handlers[ctype]
|
||||
|
||||
def run(self, ctype, op, jid=None, node=None, ifrom=None, args=None):
|
||||
def run(self, ctype: str, op: str, jid: Optional[JID] = None,
|
||||
node: Optional[str] = None, ifrom: Optional[JID] = None,
|
||||
args: Any = None) -> Future:
|
||||
"""Execute an API callback, based on specificity.
|
||||
|
||||
The API callback that is executed is chosen based on the combination
|
||||
|
@ -90,12 +94,16 @@ class APIRegistry(object):
|
|||
Handlers should check that the JID ``ifrom`` is authorized to perform
|
||||
the desired action.
|
||||
|
||||
:param string ctype: The name of the API to use.
|
||||
:param string op: The API operation to perform.
|
||||
:param JID jid: Optionally provide specific JID.
|
||||
:param string node: Optionally provide specific node.
|
||||
:param JID ifrom: Optionally provide the requesting JID.
|
||||
:param tuple args: Optional positional arguments to the handler.
|
||||
.. versionchanged:: 1.8.0
|
||||
``run()`` always returns a future, if the handler is a coroutine
|
||||
the future should be awaited on.
|
||||
|
||||
:param ctype: The name of the API to use.
|
||||
:param op: The API operation to perform.
|
||||
:param jid: Optionally provide specific JID.
|
||||
:param node: Optionally provide specific node.
|
||||
:param ifrom: Optionally provide the requesting JID.
|
||||
:param args: Optional arguments to the handler.
|
||||
"""
|
||||
self._setup(ctype, op)
|
||||
|
||||
|
@ -130,7 +138,13 @@ class APIRegistry(object):
|
|||
|
||||
if handler:
|
||||
try:
|
||||
return handler(jid, node, ifrom, args)
|
||||
if iscoroutinefunction(handler):
|
||||
return self.xmpp.wrap(handler(jid, node, ifrom, args))
|
||||
else:
|
||||
future = Future()
|
||||
result = handler(jid, node, ifrom, args)
|
||||
future.set_result(result)
|
||||
return future
|
||||
except TypeError:
|
||||
# To preserve backward compatibility, drop the ifrom
|
||||
# parameter for existing handlers that don't understand it.
|
||||
|
|
Loading…
Reference in a new issue