summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml25
-rw-r--r--itests/test_pep.py9
-rw-r--r--slixmpp/jid.py8
-rw-r--r--slixmpp/plugins/xep_0030/disco.py1
-rw-r--r--slixmpp/plugins/xep_0045/muc.py2
-rw-r--r--slixmpp/plugins/xep_0045/stanza.py9
-rw-r--r--slixmpp/plugins/xep_0047/stream.py2
-rw-r--r--slixmpp/plugins/xep_0425/moderation.py1
-rw-r--r--slixmpp/xmlstream/handler/waiter.py2
-rw-r--r--slixmpp/xmlstream/xmlstream.py38
10 files changed, 82 insertions, 15 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 48c6be9a..69bd7b7a 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -23,6 +23,29 @@ test:
- pip3 install emoji aiohttp
- ./run_tests.py
+test-3.10:
+ stage: test
+ tags:
+ - docker
+ image: python:3.10
+ script:
+ - apt update
+ - apt install -y python3 python3-pip cython3 gpg
+ - pip3 install emoji aiohttp
+ - ./run_tests.py
+
+test-3.11:
+ stage: test
+ tags:
+ - docker
+ image: python:3.11-rc
+ allow_failure: true
+ script:
+ - apt update
+ - apt install -y python3 python3-pip cython3 gpg
+ - pip3 install emoji aiohttp
+ - ./run_tests.py
+
test_integration:
stage: test
tags:
@@ -42,6 +65,6 @@ trigger_poezio:
stage: trigger
tags:
- docker
- image: appropriate/curl:latest
+ image: curlimages/curl:7.79.1
script:
- curl --request POST -F token="$SLIXMPP_TRIGGER_TOKEN" -F ref=master https://lab.louiz.org/api/v4/projects/18/trigger/pipeline
diff --git a/itests/test_pep.py b/itests/test_pep.py
index a674a348..382c22b6 100644
--- a/itests/test_pep.py
+++ b/itests/test_pep.py
@@ -34,7 +34,14 @@ class TestPEP(SlixIntegration):
"""Check we can get and set public PEP data"""
stanza = Mystanza()
stanza['test'] = str(uuid4().hex)
- await self.clients[0]['xep_0222'].store(stanza, id='toto')
+ try:
+ await self.clients[0]['xep_0060'].delete_node(
+ self.clients[0].boundjid.bare,
+ node=stanza.namespace,
+ )
+ except:
+ pass
+ await self.clients[0]['xep_0222'].store(stanza, node=stanza.namespace, id='toto')
fetched = await self.clients[0]['xep_0222'].retrieve(
stanza.namespace,
)
diff --git a/slixmpp/jid.py b/slixmpp/jid.py
index adde95a4..d02f98a3 100644
--- a/slixmpp/jid.py
+++ b/slixmpp/jid.py
@@ -133,15 +133,15 @@ def _validate_domain(domain: str):
try:
domain = idna(domain)
except StringprepError:
- raise InvalidJID('idna validation failed')
+ raise InvalidJID(f'idna validation failed: {domain}')
if ':' in domain:
- raise InvalidJID('Domain containing a port')
+ raise InvalidJID(f'Domain containing a port: {domain}')
for label in domain.split('.'):
if not label:
- raise InvalidJID('Domain containing too many dots')
+ raise InvalidJID(f'Domain containing too many dots: {domain}')
if '-' in (label[0], label[-1]):
- raise InvalidJID('Domain started or ended with -')
+ raise InvalidJID(f'Domain starting or ending with -: {domain}')
if not domain:
raise InvalidJID('Domain must not be 0 bytes')
diff --git a/slixmpp/plugins/xep_0030/disco.py b/slixmpp/plugins/xep_0030/disco.py
index 0fa09927..37d453aa 100644
--- a/slixmpp/plugins/xep_0030/disco.py
+++ b/slixmpp/plugins/xep_0030/disco.py
@@ -326,7 +326,6 @@ class XEP_0030(BasePlugin):
info_futures, _ = await asyncio.wait(
infos,
timeout=timeout,
- loop=self.xmpp.loop
)
self.domain_infos[domain] = [
diff --git a/slixmpp/plugins/xep_0045/muc.py b/slixmpp/plugins/xep_0045/muc.py
index 21f5c896..52988d44 100644
--- a/slixmpp/plugins/xep_0045/muc.py
+++ b/slixmpp/plugins/xep_0045/muc.py
@@ -35,6 +35,7 @@ from slixmpp.plugins.xep_0045 import stanza
from slixmpp.plugins.xep_0045.stanza import (
MUCInvite,
MUCDecline,
+ MUCDestroy,
MUCPresence,
MUCJoin,
MUCMessage,
@@ -88,6 +89,7 @@ class XEP_0045(BasePlugin):
register_stanza_plugin(MUCMessage, MUCStatus)
register_stanza_plugin(MUCPresence, MUCStatus)
register_stanza_plugin(Presence, MUCPresence)
+ register_stanza_plugin(MUCPresence, MUCDestroy)
register_stanza_plugin(Presence, MUCJoin)
register_stanza_plugin(MUCJoin, MUCHistory)
register_stanza_plugin(Message, MUCMessage)
diff --git a/slixmpp/plugins/xep_0045/stanza.py b/slixmpp/plugins/xep_0045/stanza.py
index 428dbce7..6c3d2244 100644
--- a/slixmpp/plugins/xep_0045/stanza.py
+++ b/slixmpp/plugins/xep_0045/stanza.py
@@ -235,6 +235,7 @@ class MUCOwnerQuery(ElementBase):
class MUCOwnerDestroy(ElementBase):
name = 'destroy'
plugin_attrib = 'destroy'
+ namespace = NS_OWNER
interfaces = {'reason', 'jid'}
sub_interfaces = {'reason'}
@@ -288,3 +289,11 @@ class MUCActor(ElementBase):
if jid:
return JID(jid)
return jid
+
+
+class MUCDestroy(ElementBase):
+ name = 'destroy'
+ plugin_attrib = 'destroy'
+ namespace = NS_USER
+ interfaces = {'reason', 'jid'}
+ sub_interfaces = {'reason'}
diff --git a/slixmpp/plugins/xep_0047/stream.py b/slixmpp/plugins/xep_0047/stream.py
index f020ea68..0cda5dd9 100644
--- a/slixmpp/plugins/xep_0047/stream.py
+++ b/slixmpp/plugins/xep_0047/stream.py
@@ -115,7 +115,7 @@ class IBBytestream(object):
self.xmpp.add_event_handler('ibb_stream_end', on_close)
self.xmpp.add_event_handler('ibb_stream_data', on_data)
try:
- await asyncio.wait_for(end_future, timeout, loop=self.xmpp.loop)
+ await asyncio.wait_for(end_future, timeout)
except asyncio.TimeoutError:
raise IqTimeout(result)
finally:
diff --git a/slixmpp/plugins/xep_0425/moderation.py b/slixmpp/plugins/xep_0425/moderation.py
index 053e18f6..3c1308fc 100644
--- a/slixmpp/plugins/xep_0425/moderation.py
+++ b/slixmpp/plugins/xep_0425/moderation.py
@@ -44,4 +44,5 @@ class XEP_0425(BasePlugin):
iq = self.xmpp.make_iq_set(ito=room.bare, ifrom=ifrom)
iq['apply_to']['id'] = id
iq['apply_to']['moderate']['reason'] = reason
+ iq['apply_to']['moderate'].enable('retract')
await iq.send(**iqkwargs)
diff --git a/slixmpp/xmlstream/handler/waiter.py b/slixmpp/xmlstream/handler/waiter.py
index dde49754..599004b5 100644
--- a/slixmpp/xmlstream/handler/waiter.py
+++ b/slixmpp/xmlstream/handler/waiter.py
@@ -80,7 +80,7 @@ class Waiter(BaseHandler):
try:
await wait_for(
- self._event.wait(), timeout, loop=stream.loop
+ self._event.wait(), timeout,
)
except TimeoutError:
log.warning("Timed out waiting for %s", self.name)
diff --git a/slixmpp/xmlstream/xmlstream.py b/slixmpp/xmlstream/xmlstream.py
index 30f99071..82611bfd 100644
--- a/slixmpp/xmlstream/xmlstream.py
+++ b/slixmpp/xmlstream/xmlstream.py
@@ -15,6 +15,7 @@ from typing import (
Coroutine,
Callable,
Iterator,
+ Iterable,
List,
Optional,
Set,
@@ -46,6 +47,7 @@ from asyncio import (
iscoroutinefunction,
wait,
)
+from pathlib import Path
from slixmpp.types import FilterString
from slixmpp.xmlstream.tostring import tostring
@@ -74,6 +76,15 @@ class NotConnectedError(Exception):
"""
+class InvalidCABundle(Exception):
+ """
+ Exception raised when the CA Bundle file hasn't been found.
+ """
+
+ def __init__(self, path: Optional[Path]):
+ self.path = path
+
+
_T = TypeVar('_T', str, ElementBase, StanzaBase)
@@ -161,7 +172,7 @@ class XMLStream(asyncio.BaseProtocol):
#:
#: On Mac OS X, certificates in the system keyring will
#: be consulted, even if they are not in the provided file.
- ca_certs: Optional[str]
+ ca_certs: Optional[Union[Path, Iterable[Path]]]
#: Path to a file containing a client certificate to use for
#: authenticating via SASL EXTERNAL. If set, there must also
@@ -449,7 +460,7 @@ class XMLStream(asyncio.BaseProtocol):
if self._connect_loop_wait > 0:
self.event('reconnect_delay', self._connect_loop_wait)
- await asyncio.sleep(self._connect_loop_wait, loop=self.loop)
+ await asyncio.sleep(self._connect_loop_wait)
record = await self._pick_dns_answer(self.default_domain)
if record is not None:
@@ -504,10 +515,10 @@ class XMLStream(asyncio.BaseProtocol):
else:
self.loop.run_until_complete(self.disconnected)
else:
- tasks: List[Future] = [asyncio.sleep(timeout, loop=self.loop)]
+ tasks: List[Future] = [asyncio.sleep(timeout)]
if not forever:
tasks.append(self.disconnected)
- self.loop.run_until_complete(asyncio.wait(tasks, loop=self.loop))
+ self.loop.run_until_complete(asyncio.wait(tasks))
def init_parser(self) -> None:
"""init the XML parser. The parser must always be reset for each new
@@ -715,7 +726,7 @@ class XMLStream(asyncio.BaseProtocol):
log.debug("reconnecting...")
async def handler(event: Any) -> None:
# We yield here to allow synchronous handlers to work first
- await asyncio.sleep(0, loop=self.loop)
+ await asyncio.sleep(0)
self.connect()
self.add_event_handler('disconnected', handler, disposable=True)
self.disconnect(wait, reason)
@@ -759,8 +770,23 @@ class XMLStream(asyncio.BaseProtocol):
log.debug('Loaded cert file %s and key file %s',
self.certfile, self.keyfile)
if self.ca_certs is not None:
+ ca_cert: Optional[Path] = None
+ # XXX: Compat before d733c54518.
+ if isinstance(self.ca_certs, str):
+ self.ca_certs = Path(self.ca_certs)
+ if isinstance(self.ca_certs, Path):
+ if self.ca_certs.is_file():
+ ca_cert = self.ca_certs
+ else:
+ for bundle in self.ca_certs:
+ if bundle.is_file():
+ ca_cert = bundle
+ break
+ if ca_cert is None:
+ raise InvalidCABundle(ca_cert)
+
self.ssl_context.verify_mode = ssl.CERT_REQUIRED
- self.ssl_context.load_verify_locations(cafile=self.ca_certs)
+ self.ssl_context.load_verify_locations(cafile=ca_cert)
return self.ssl_context