From 9947d3db85e98a44a495f749d96b8632a10bde8d Mon Sep 17 00:00:00 2001 From: mathieui Date: Sun, 14 Feb 2021 12:02:13 +0100 Subject: [PATCH] XEP-0231: API changes - ``get_bob`` and ``set_bob`` are now coroutines. - ``del_bob`` returns a Future. --- docs/api/plugins/xep_0231.rst | 34 ++++++++++++++++++++++ itests/test_bob.py | 2 +- slixmpp/plugins/xep_0231/bob.py | 50 +++++++++++++++++++-------------- 3 files changed, 64 insertions(+), 22 deletions(-) diff --git a/docs/api/plugins/xep_0231.rst b/docs/api/plugins/xep_0231.rst index 29f403ca..bed0e4bb 100644 --- a/docs/api/plugins/xep_0231.rst +++ b/docs/api/plugins/xep_0231.rst @@ -9,6 +9,40 @@ XEP-0231: Bits of Binary :exclude-members: session_bind, plugin_init, plugin_end +Internal API methods +-------------------- + +The default API handlers for this plugin manage an in-memory cache of +bits of binary by content-id. + +.. glossary:: + + set_bob + - **jid**: :class:`~.JID` sending the bob + - **node**: unused + - **ifrom**: :class:`~JID` receiving the bob + - **args**: :class:`~.BitsOfBinary` element. + + Set a BoB in the cache. + + get_bob + - **jid**: :class:`~.JID` receiving the bob + - **node**: unused + - **ifrom**: :class:`~JID` sending the bob + - **args**: ``str`` content-id of the bob + - **returns**: :class:`~.BitsOfBinary` element. + + Get a BoB from the cache. + + del_bob + - **jid**: unused + - **node**: unused + - **ifrom**: :class:`~JID` sending the bob + - **args**: ``str`` content-id of the bob + + Delete a BoB from the cache. + + Stanza elements --------------- diff --git a/itests/test_bob.py b/itests/test_bob.py index d0827df0..5c95bc89 100644 --- a/itests/test_bob.py +++ b/itests/test_bob.py @@ -20,7 +20,7 @@ class TestBOB(SlixIntegration): async def test_bob(self): """Check we can send and receive a BOB.""" - cid = self.clients[0]['xep_0231'].set_bob( + cid = await self.clients[0]['xep_0231'].set_bob( self.data, 'image/jpeg', ) diff --git a/slixmpp/plugins/xep_0231/bob.py b/slixmpp/plugins/xep_0231/bob.py index e554c38c..129aca56 100644 --- a/slixmpp/plugins/xep_0231/bob.py +++ b/slixmpp/plugins/xep_0231/bob.py @@ -12,7 +12,7 @@ from typing import Optional from slixmpp import future_wrapper, JID from slixmpp.stanza import Iq, Message, Presence from slixmpp.exceptions import XMPPError -from slixmpp.xmlstream.handler import Callback +from slixmpp.xmlstream.handler import CoroutineCallback from slixmpp.xmlstream.matcher import StanzaPath from slixmpp.xmlstream import register_stanza_plugin from slixmpp.plugins.base import BasePlugin @@ -40,17 +40,17 @@ class XEP_0231(BasePlugin): register_stanza_plugin(Presence, BitsOfBinary) self.xmpp.register_handler( - Callback('Bits of Binary - Iq', + CoroutineCallback('Bits of Binary - Iq', StanzaPath('iq/bob'), self._handle_bob_iq)) self.xmpp.register_handler( - Callback('Bits of Binary - Message', + CoroutineCallback('Bits of Binary - Message', StanzaPath('message/bob'), self._handle_bob)) self.xmpp.register_handler( - Callback('Bits of Binary - Presence', + CoroutineCallback('Bits of Binary - Presence', StanzaPath('presence/bob'), self._handle_bob)) @@ -67,13 +67,14 @@ class XEP_0231(BasePlugin): def session_bind(self, jid): self.xmpp['xep_0030'].add_feature('urn:xmpp:bob') - def set_bob(self, data: bytes, mtype: str, cid: Optional[str] = None, - max_age: Optional[int] = None) -> str: + async def set_bob(self, data: bytes, mtype: str, cid: Optional[str] = None, + max_age: Optional[int] = None) -> str: """Register a blob of binary data as a BOB. .. versionchanged:: 1.8.0 If ``max_age`` is specified, the registered data will be destroyed after that time. + This function is now a coroutine. :param data: Data to register. :param mtype: Mime Type of the data (e.g. ``image/jpeg``). @@ -90,27 +91,27 @@ class XEP_0231(BasePlugin): bob['cid'] = cid bob['max_age'] = max_age - self.api['set_bob'](args=bob) + await self.api['set_bob'](args=bob) # Schedule destruction of the data if max_age is not None and max_age > 0: self.xmpp.loop.call_later(max_age, self.del_bob, cid) return cid - @future_wrapper - def get_bob(self, jid: Optional[JID] = None, cid: Optional[str] = None, - cached: bool = True, ifrom: Optional[JID] = None, - **iqkwargs) -> Future: + async def get_bob(self, jid: Optional[JID] = None, cid: Optional[str] = None, + cached: bool = True, ifrom: Optional[JID] = None, + **iqkwargs) -> Iq: """Get a BOB. .. versionchanged:: 1.8.0 Results not in cache do not raise an error when ``cached`` is True. + This function is now a coroutine. :param jid: JID to fetch the BOB from. :param cid: Content ID (actually required). :param cached: To fetch the BOB from the local cache first (from CID only) """ if cached: - data = self.api['get_bob'](None, None, ifrom, args=cid) + data = await self.api['get_bob'](None, None, ifrom, args=cid) if data is not None: if not isinstance(data, Iq): iq = self.xmpp.Iq() @@ -120,19 +121,24 @@ class XEP_0231(BasePlugin): iq = self.xmpp.make_iq_get(ito=jid, ifrom=ifrom) iq['bob']['cid'] = cid - return iq.send(**iqkwargs) + return await iq.send(**iqkwargs) - def del_bob(self, cid: str): - self.api['del_bob'](args=cid) + def del_bob(self, cid: str) -> Future: + """Delete a stored BoB. - def _handle_bob_iq(self, iq: Iq): + .. versionchanged:: 1.8.0 + This function now returns a Future. + """ + return self.api['del_bob'](args=cid) + + async def _handle_bob_iq(self, iq: Iq): cid = iq['bob']['cid'] if iq['type'] == 'result': - self.api['set_bob'](iq['from'], None, iq['to'], args=iq['bob']) + await self.api['set_bob'](iq['from'], None, iq['to'], args=iq['bob']) self.xmpp.event('bob', iq) elif iq['type'] == 'get': - data = self.api['get_bob'](iq['to'], None, iq['from'], args=cid) + data = await self.api['get_bob'](iq['to'], None, iq['from'], args=cid) if isinstance(data, Iq): data['id'] = iq['id'] data.send() @@ -142,9 +148,11 @@ class XEP_0231(BasePlugin): iq.append(data) iq.send() - def _handle_bob(self, stanza): - self.api['set_bob'](stanza['from'], None, - stanza['to'], args=stanza['bob']) + async def _handle_bob(self, stanza): + await self.api['set_bob']( + stanza['from'], None, + stanza['to'], args=stanza['bob'] + ) self.xmpp.event('bob', stanza) # =================================================================