core, dependencies: Update Tx-XMPP to 0.12:
Tx-XMPP 0.12 has beaking change in `discoFeature.identities` because it now supports `xml:lang` attribute, so this update implies updating the code everywhere were this is used.
This commit is contained in:
parent
1548276702
commit
f6db575ee4
10 changed files with 747 additions and 696 deletions
|
|
@ -23,7 +23,7 @@ import hashlib
|
|||
import copy
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
from typing import Optional, List, Tuple, Dict, cast
|
||||
from typing import Optional, cast
|
||||
|
||||
from libervia import backend
|
||||
from libervia.backend.core.i18n import _, D_, language_switch
|
||||
|
|
@ -960,15 +960,16 @@ class LiberviaBackend(service.Service):
|
|||
|
||||
disco = await self.get_disco_infos(client, res_jid)
|
||||
|
||||
for (category, type_), name in disco.identities.items():
|
||||
for (category, type_, lang), name in disco.identities.items():
|
||||
identities = res_data.setdefault("identities", [])
|
||||
identities.append(
|
||||
{
|
||||
"name": name,
|
||||
"category": category,
|
||||
"type": type_,
|
||||
}
|
||||
)
|
||||
identity_entry = {
|
||||
"name": name,
|
||||
"category": category,
|
||||
"type": type_,
|
||||
}
|
||||
if lang:
|
||||
identity_entry["lang"] = lang
|
||||
identities.append(identity_entry)
|
||||
|
||||
ret_data.append(res_data)
|
||||
|
||||
|
|
@ -1334,22 +1335,31 @@ class LiberviaBackend(service.Service):
|
|||
|
||||
def _find_by_features(
|
||||
self,
|
||||
namespaces,
|
||||
identities,
|
||||
bare_jids,
|
||||
service,
|
||||
roster,
|
||||
own_jid,
|
||||
local_device,
|
||||
profile_key,
|
||||
):
|
||||
namespaces: list[str],
|
||||
identities: list[list[str]] | None,
|
||||
bare_jids: bool,
|
||||
service: bool,
|
||||
roster: bool,
|
||||
own_jid: bool,
|
||||
local_device: bool,
|
||||
profile_key: str,
|
||||
) -> defer.Deferred[
|
||||
tuple[
|
||||
dict[jid.JID, list[tuple[str, str, str, str]]],
|
||||
dict[jid.JID, list[tuple[str, str, str, str]]],
|
||||
dict[jid.JID, list[tuple[str, str, str, str]]],
|
||||
]
|
||||
]:
|
||||
client = self.get_client(profile_key)
|
||||
identities = [tuple(i) for i in identities] if identities else None
|
||||
identities_typed = cast(
|
||||
list[tuple[str, str]] | None,
|
||||
[tuple(i) for i in identities] if identities else None,
|
||||
)
|
||||
return defer.ensureDeferred(
|
||||
self.find_by_features(
|
||||
client,
|
||||
namespaces,
|
||||
identities,
|
||||
identities_typed,
|
||||
bare_jids,
|
||||
service,
|
||||
roster,
|
||||
|
|
@ -1361,17 +1371,17 @@ class LiberviaBackend(service.Service):
|
|||
async def find_by_features(
|
||||
self,
|
||||
client: SatXMPPEntity,
|
||||
namespaces: List[str],
|
||||
identities: Optional[List[Tuple[str, str]]] = None,
|
||||
namespaces: list[str],
|
||||
identities: list[tuple[str, str]] | None = None,
|
||||
bare_jids: bool = False,
|
||||
service: bool = True,
|
||||
roster: bool = True,
|
||||
own_jid: bool = True,
|
||||
local_device: bool = False,
|
||||
) -> Tuple[
|
||||
Dict[jid.JID, Tuple[str, str, str]],
|
||||
Dict[jid.JID, Tuple[str, str, str]],
|
||||
Dict[jid.JID, Tuple[str, str, str]],
|
||||
) -> tuple[
|
||||
dict[jid.JID, list[tuple[str, str, str, str]]],
|
||||
dict[jid.JID, list[tuple[str, str, str, str]]],
|
||||
dict[jid.JID, list[tuple[str, str, str, str]]],
|
||||
]:
|
||||
"""Retrieve all services or contacts managing a set a features
|
||||
|
||||
|
|
@ -1391,7 +1401,7 @@ class LiberviaBackend(service.Service):
|
|||
- service entities
|
||||
- own entities
|
||||
- roster entities
|
||||
Each element is a dict mapping from jid to a tuple with category, type and
|
||||
Each element is a dict mapping from jid to a tuple with category, type, lang and
|
||||
name of the entity
|
||||
"""
|
||||
assert isinstance(namespaces, list)
|
||||
|
|
@ -1423,13 +1433,13 @@ class LiberviaBackend(service.Service):
|
|||
).format(service_jid=service_jid.full())
|
||||
)
|
||||
continue
|
||||
if identities is not None and not set(infos.identities.keys()).issuperset(
|
||||
identities
|
||||
):
|
||||
if identities is not None and not set(
|
||||
k[:2] for k in infos.identities.keys()
|
||||
).issuperset(identities):
|
||||
continue
|
||||
found_identities = [
|
||||
(cat, type_, name or "")
|
||||
for (cat, type_), name in infos.identities.items()
|
||||
(cat, type_, lang, name or "")
|
||||
for (cat, type_, lang), name in infos.identities.items()
|
||||
]
|
||||
found_service[service_jid.full()] = found_identities
|
||||
|
||||
|
|
@ -1487,12 +1497,12 @@ class LiberviaBackend(service.Service):
|
|||
continue
|
||||
if infos.features.issuperset(namespaces):
|
||||
if identities is not None and not set(
|
||||
infos.identities.keys()
|
||||
k[:2] for k in infos.identities.keys()
|
||||
).issuperset(identities):
|
||||
continue
|
||||
found_identities = [
|
||||
(cat, type_, name or "")
|
||||
for (cat, type_), name in infos.identities.items()
|
||||
(cat, type_, lang, name or "")
|
||||
for (cat, type_, lang), name in infos.identities.items()
|
||||
]
|
||||
found[full_jid.full()] = found_identities
|
||||
|
||||
|
|
|
|||
|
|
@ -1489,9 +1489,9 @@ class SatMessageProtocol(xmppim.MessageProtocol):
|
|||
)
|
||||
else:
|
||||
domain_disco_infos = disco_infos
|
||||
if ("client", "bot") in disco_infos.identities:
|
||||
if any(k[:2] == ("client", "bot") for k in disco_infos.identities):
|
||||
extra["is-bot"] = True
|
||||
for (category, type_), label in domain_disco_infos.identities.items():
|
||||
for (category, type_, lang), label in domain_disco_infos.identities.items():
|
||||
if category == "gateway":
|
||||
extra["origin"] = type_
|
||||
if label:
|
||||
|
|
|
|||
|
|
@ -181,7 +181,9 @@ class Discovery(object):
|
|||
if not set(features).issubset(disco_infos.features):
|
||||
raise exceptions.FeatureNotFound()
|
||||
|
||||
if identity is not None and identity not in disco_infos.identities:
|
||||
if identity is not None and not any(
|
||||
k[:2] == identity for k in disco_infos.identities
|
||||
):
|
||||
raise exceptions.FeatureNotFound()
|
||||
|
||||
async def has_identity(
|
||||
|
|
@ -201,7 +203,7 @@ class Discovery(object):
|
|||
@return: True if the entity has the given identity
|
||||
"""
|
||||
disco_infos = await self.get_infos(client, jid_, node)
|
||||
return (category, type_) in disco_infos.identities
|
||||
return any(k[:2] == (category, type_) for k in disco_infos.identities)
|
||||
|
||||
def get_infos(
|
||||
self,
|
||||
|
|
@ -342,7 +344,7 @@ class Discovery(object):
|
|||
found_entities = set()
|
||||
|
||||
def infos_cb(infos, entity_jid):
|
||||
if (category, type_) in infos.identities:
|
||||
if any(k[:2] == (category, type_) for k in infos.identities):
|
||||
found_entities.add(entity_jid)
|
||||
|
||||
def got_items(items):
|
||||
|
|
@ -387,7 +389,9 @@ class Discovery(object):
|
|||
if entity is None:
|
||||
log.warning(_("Received an item without JID"))
|
||||
return
|
||||
if identity is not None and identity not in infos.identities:
|
||||
if identity is not None and not any(
|
||||
k[:2] == identity for k in infos.identities
|
||||
):
|
||||
return
|
||||
if features.issubset(infos.features):
|
||||
found_entities.add(entity)
|
||||
|
|
@ -489,8 +493,8 @@ class Discovery(object):
|
|||
return (
|
||||
[str(f) for f in disco_infos.features],
|
||||
[
|
||||
(cat, type_, name or "")
|
||||
for (cat, type_), name in list(disco_infos.identities.items())
|
||||
(cat, type_, lang, name or "")
|
||||
for (cat, type_, lang), name in list(disco_infos.identities.items())
|
||||
],
|
||||
extensions,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -728,10 +728,9 @@ class APGateway:
|
|||
async def is_pubsub(self, jid_: jid.JID) -> bool:
|
||||
"""Indicate if a JID is a Pubsub service"""
|
||||
host_disco = await self.host.get_disco_infos(self.client, jid_)
|
||||
return ("pubsub", "service") in host_disco.identities and not (
|
||||
"pubsub",
|
||||
"pep",
|
||||
) in host_disco.identities
|
||||
return any(
|
||||
k[:2] == ("pubsub", "service") for k in host_disco.identities
|
||||
) and not any(k[:2] == ("pubsub", "pep") for k in host_disco.identities)
|
||||
|
||||
async def get_jid_and_node(self, ap_account: str) -> tuple[jid.JID, str | None]:
|
||||
"""Decode raw AP account handle to get XMPP JID and Pubsub Node
|
||||
|
|
|
|||
|
|
@ -753,8 +753,11 @@ class Identity:
|
|||
except Exception as e:
|
||||
log.exception(f"Can't get disco infos for {entity}.")
|
||||
else:
|
||||
for (category, type_), name in disco_infos.identities.items():
|
||||
identities.append({"category": category, "type": type_, "name": name})
|
||||
for (category, type_, lang), name in disco_infos.identities.items():
|
||||
identity_entry = {"category": category, "type": type_, "name": name}
|
||||
if lang:
|
||||
identity_entry["lang"] = lang
|
||||
identities.append(identity_entry)
|
||||
|
||||
return id_data
|
||||
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ class XEP_0353:
|
|||
else:
|
||||
raise e
|
||||
else:
|
||||
categories = {c for c, __ in infos.identities}
|
||||
categories = {c for c, __, __ in infos.identities}
|
||||
if "component" in categories:
|
||||
# we don't use message initiation with components
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -1108,10 +1108,10 @@ class XEP_0373:
|
|||
"Error performing service discovery on the own bare JID."
|
||||
) from e
|
||||
|
||||
identities = cast(dict[tuple[str, str], str], infos.identities)
|
||||
identities = cast(dict[tuple[str, str, str], str], infos.identities)
|
||||
features = cast(set[DiscoFeature], infos.features)
|
||||
|
||||
if ("pubsub", "pep") not in identities:
|
||||
if not any(k[:2] == ("pubsub", "pep") for k in identities):
|
||||
raise exceptions.FeatureNotFound("Server doesn't support PEP.")
|
||||
|
||||
if "http://jabber.org/protocol/pubsub#access-whitelist" not in features:
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ dependencies = [
|
|||
"urwid >= 1.2.0, < 3",
|
||||
"urwid-satext",
|
||||
"xmlschema < 4.3.1",
|
||||
"tx-xmpp>=0.10",
|
||||
"tx-xmpp>=0.12",
|
||||
]
|
||||
keywords = [
|
||||
"XMPP",
|
||||
|
|
|
|||
|
|
@ -777,9 +777,7 @@ class TestPubsubResourceItems:
|
|||
subscriptionTo=False,
|
||||
subscriptionFrom=True,
|
||||
)
|
||||
mock_xep_0356.get_roster = AsyncMock(
|
||||
return_value={requestor_jid: roster_item}
|
||||
)
|
||||
mock_xep_0356.get_roster = AsyncMock(return_value={requestor_jid: roster_item})
|
||||
host.plugins["XEP-0356"] = mock_xep_0356
|
||||
|
||||
with raises(StanzaError, match="forbidden"):
|
||||
|
|
@ -814,9 +812,7 @@ class TestPubsubResourceItems:
|
|||
subscriptionTo=False,
|
||||
subscriptionFrom=True,
|
||||
)
|
||||
mock_xep_0356.get_roster = AsyncMock(
|
||||
return_value={requestor_jid: roster_item}
|
||||
)
|
||||
mock_xep_0356.get_roster = AsyncMock(return_value={requestor_jid: roster_item})
|
||||
|
||||
await resource._items(request)
|
||||
|
||||
|
|
@ -1478,6 +1474,6 @@ class TestPubsubAutoSubscribe:
|
|||
call_args = host.memory.storage.get_pep_last_items.call_args
|
||||
# We want the second positional argument (list of publishers)
|
||||
publishers_arg = call_args[0][1]
|
||||
assert publishers_arg == [requestor_jid], (
|
||||
f"Expected only self-subscription, got {publishers_arg}"
|
||||
)
|
||||
assert publishers_arg == [
|
||||
requestor_jid
|
||||
], f"Expected only self-subscription, got {publishers_arg}"
|
||||
|
|
|
|||
Loading…
Reference in a new issue