Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-nbxmpp for openSUSE:Factory 
checked in at 2023-08-13 19:17:44
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-nbxmpp (Old)
 and      /work/SRC/openSUSE:Factory/.python-nbxmpp.new.11712 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-nbxmpp"

Sun Aug 13 19:17:44 2023 rev:43 rq:1103600 version:4.3.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-nbxmpp/python-nbxmpp.changes      
2023-06-05 18:06:15.603010476 +0200
+++ /work/SRC/openSUSE:Factory/.python-nbxmpp.new.11712/python-nbxmpp.changes   
2023-08-13 19:17:52.896077391 +0200
@@ -1,0 +2,13 @@
+Mon Aug  7 23:17:29 UTC 2023 - Alexei Sorokin <sor.ale...@meowr.ru>
+
+- Update to version 4.3.2:
+  * SecurityLabels: Add get_label_hash().
+  * JID: Add sqlite3 adapter magic method.
+  * MessageProperties: Add origin_id attribute.
+  * MessageProperties: Add remote_jid attribute.
+  * Client: Return only copy of ignored errors.
+  * CommonError: Add "by" attribute.
+  * Moderation: Parse more data.
+  * HTTP: Add set_accept_certificate().
+
+-------------------------------------------------------------------

Old:
----
  python-nbxmpp-4.3.1.tar.bz2

New:
----
  python-nbxmpp-4.3.2.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-nbxmpp.spec ++++++
--- /var/tmp/diff_new_pack.4yDDap/_old  2023-08-13 19:17:54.368086809 +0200
+++ /var/tmp/diff_new_pack.4yDDap/_new  2023-08-13 19:17:54.372086835 +0200
@@ -24,7 +24,7 @@
 %endif
 %define _name   nbxmpp
 Name:           python-nbxmpp
-Version:        4.3.1
+Version:        4.3.2
 Release:        0
 Summary:        XMPP library by Gajim team
 License:        GPL-3.0-or-later
@@ -41,6 +41,7 @@
 BuildRequires:  %{python_module packaging}
 BuildRequires:  %{python_module pip}
 BuildRequires:  %{python_module precis-i18n}
+BuildRequires:  %{python_module sqlite3}
 BuildRequires:  %{python_module wheel}
 BuildRequires:  typelib(Soup) = 3.0
 Recommends:     python-gssapi

++++++ python-nbxmpp-4.3.1.tar.bz2 -> python-nbxmpp-4.3.2.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-nbxmpp-4.3.1/ChangeLog 
new/python-nbxmpp-4.3.2/ChangeLog
--- old/python-nbxmpp-4.3.1/ChangeLog   2023-05-28 23:18:18.000000000 +0200
+++ new/python-nbxmpp-4.3.2/ChangeLog   2023-08-07 22:57:16.000000000 +0200
@@ -1,3 +1,22 @@
+nbxmpp 4.3.2 (04 Jul 2023)
+
+  New
+
+  * SecurityLabels: Add get_label_hash()
+  * JID: Add sqlite3 adapter magic method
+  * MessageProperties: Add origin_id attribute
+  * MessageProperties: Add remote_jid attribute
+
+  Improvements
+
+  * Client: Return only copy of ignored errors
+  * CommonError: Add 'by' attribute
+  * Moderation: Parse more data
+
+  Bug Fixes
+
+  * HTTP: Add set_accept_certificate()
+
 nbxmpp 4.3.1 (28 May 2023)
 
   Bug Fixes
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-nbxmpp-4.3.1/nbxmpp/__init__.py 
new/python-nbxmpp-4.3.2/nbxmpp/__init__.py
--- old/python-nbxmpp-4.3.1/nbxmpp/__init__.py  2023-05-28 23:18:18.000000000 
+0200
+++ new/python-nbxmpp-4.3.2/nbxmpp/__init__.py  2023-08-07 22:57:16.000000000 
+0200
@@ -3,4 +3,4 @@
 
 from .protocol import *  # pylint: disable=wrong-import-position
 
-__version__: str = '4.3.1'
+__version__: str = '4.3.2'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-nbxmpp-4.3.1/nbxmpp/client.py 
new/python-nbxmpp-4.3.2/nbxmpp/client.py
--- old/python-nbxmpp-4.3.1/nbxmpp/client.py    2023-05-28 23:18:18.000000000 
+0200
+++ new/python-nbxmpp-4.3.2/nbxmpp/client.py    2023-08-07 22:57:16.000000000 
+0200
@@ -203,7 +203,7 @@
 
     @property
     def ignored_tls_errors(self):
-        return self._ignored_tls_errors
+        return set(self._ignored_tls_errors)
 
     def set_ignored_tls_errors(self, errors):
         if errors is None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-nbxmpp-4.3.1/nbxmpp/http.py 
new/python-nbxmpp-4.3.2/nbxmpp/http.py
--- old/python-nbxmpp-4.3.1/nbxmpp/http.py      2023-05-28 23:18:18.000000000 
+0200
+++ new/python-nbxmpp-4.3.2/nbxmpp/http.py      2023-08-07 22:57:16.000000000 
+0200
@@ -112,6 +112,7 @@
         self._is_complete = False
         self._timeout_reached = False
         self._timeout_id = None
+        self._accept_certificate_func = None
 
         self._response_body_file: Optional[Gio.File] = None
         self._response_body_data = b''
@@ -183,6 +184,9 @@
         self._log.info('Cancel requested')
         self._cancellable.cancel()
 
+    def set_accept_certificate_func(self, func: Any) -> None:
+        self._accept_certificate_func = func
+
     def set_request_body_from_path(self, content_type: str, path: Path) -> 
None:
         if not path.exists():
             raise ValueError('%s does not exist' % path)
@@ -285,6 +289,8 @@
         self._message.connect('restarted', self._on_restarted)
         self._message.connect('finished', self._on_finished)
         self._message.connect('got-headers', self._on_got_headers)
+        if self._accept_certificate_func is not None:
+            self._message.connect('accept-certificate', 
self._accept_certificate_func)
 
         soup_session = self._session.get_soup_session()
         soup_session.send_async(self._message,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-nbxmpp-4.3.1/nbxmpp/modules/date_and_time.py 
new/python-nbxmpp-4.3.2/nbxmpp/modules/date_and_time.py
--- old/python-nbxmpp-4.3.1/nbxmpp/modules/date_and_time.py     2023-05-28 
23:18:18.000000000 +0200
+++ new/python-nbxmpp-4.3.2/nbxmpp/modules/date_and_time.py     2023-08-07 
22:57:16.000000000 +0200
@@ -124,7 +124,7 @@
     return timezone(timedelta(hours=hours, minutes=minutes))
 
 
-def parse_datetime(timestring, check_utc=False,
+def parse_datetime(timestring: str | None, check_utc=False,
                    convert='utc', epoch=False):
     '''
     Parse a XEP-0082 DateTime Profile String
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-nbxmpp-4.3.1/nbxmpp/modules/message.py 
new/python-nbxmpp-4.3.2/nbxmpp/modules/message.py
--- old/python-nbxmpp-4.3.1/nbxmpp/modules/message.py   2023-05-28 
23:18:18.000000000 +0200
+++ new/python-nbxmpp-4.3.2/nbxmpp/modules/message.py   2023-08-07 
22:57:16.000000000 +0200
@@ -42,7 +42,6 @@
     def _process_message_base(self, _client, stanza, properties):
         properties.type = self._parse_type(stanza)
 
-        # Determine remote JID
         if properties.is_carbon_message and properties.carbon.is_sent:
             properties.jid = stanza.getTo()
 
@@ -56,16 +55,35 @@
         else:
             properties.jid = stanza.getFrom()
 
+        self._parse_if_private_message(stanza, properties)
+
+        properties.remote_jid = self._determine_remote_jid(properties)
         properties.from_ = stanza.getFrom()
         properties.to = stanza.getTo()
         properties.id = stanza.getID()
         properties.self_message = self._parse_self_message(stanza, properties)
 
+        properties.origin_id = stanza.getOriginID()
         properties.stanza_ids = self._parse_stanza_ids(stanza)
 
         if properties.type.is_error:
             properties.error = error_factory(stanza)
 
+    def _determine_remote_jid(self, properties):
+        if properties.is_muc_pm:
+            return properties.jid
+        return properties.jid.new_as_bare()
+
+    def _parse_if_private_message(self, stanza, properties) -> None:
+        muc_user = stanza.getTag('x', namespace=Namespace.MUC_USER)
+        if muc_user is None:
+            return
+
+        if (properties.type.is_chat or
+                properties.type.is_error and
+                not muc_user.getChildren()):
+            properties.muc_private_message = True
+
     def _process_message_after_base(self, _client, stanza, properties):
         # This handler runs after decryption handlers had the chance
         # to decrypt the body
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-nbxmpp-4.3.1/nbxmpp/modules/misc.py 
new/python-nbxmpp-4.3.2/nbxmpp/modules/misc.py
--- old/python-nbxmpp-4.3.1/nbxmpp/modules/misc.py      2023-05-28 
23:18:18.000000000 +0200
+++ new/python-nbxmpp-4.3.2/nbxmpp/modules/misc.py      2023-08-07 
22:57:16.000000000 +0200
@@ -103,7 +103,7 @@
 
     # Timestamp parsing
     # Most servers dont set the 'from' attr, so we cant check for it
-    delay_timestamp = parse_delay(forwarded)
+    delay_timestamp = parse_delay(forwarded, epoch=True)
     if delay_timestamp is None:
         log.warning('No timestamp on MAM message')
         log.warning(stanza)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-nbxmpp-4.3.1/nbxmpp/modules/muc/moderation.py 
new/python-nbxmpp-4.3.2/nbxmpp/modules/muc/moderation.py
--- old/python-nbxmpp-4.3.1/nbxmpp/modules/muc/moderation.py    2023-05-28 
23:18:18.000000000 +0200
+++ new/python-nbxmpp-4.3.2/nbxmpp/modules/muc/moderation.py    2023-08-07 
22:57:16.000000000 +0200
@@ -17,17 +17,18 @@
 
 from typing import Optional
 
-from nbxmpp.modules.base import BaseModule
-from nbxmpp.modules.util import process_response
-
 from nbxmpp import JID
 from nbxmpp.namespaces import Namespace
 from nbxmpp.protocol import Iq
+from nbxmpp.protocol import NodeProcessed
 from nbxmpp.structs import StanzaHandler
 from nbxmpp.structs import MessageProperties
 from nbxmpp.structs import ModerationData
 from nbxmpp.simplexml import Node
 from nbxmpp.task import iq_request_task
+from nbxmpp.modules.base import BaseModule
+from nbxmpp.modules.date_and_time import parse_datetime
+from nbxmpp.modules.util import process_response
 
 
 class Moderation(BaseModule):
@@ -41,6 +42,11 @@
                           typ='groupchat',
                           ns=Namespace.FASTEN,
                           priority=20),
+            StanzaHandler(name='message',
+                          callback=self._process_message_moderated_tombstone,
+                          typ='groupchat',
+                          ns=Namespace.MESSAGE_MODERATE,
+                          priority=20),
         ]
 
     @iq_request_task
@@ -52,9 +58,29 @@
 
         yield process_response(response)
 
-    @staticmethod
-    def _process_message(_client, stanza: Node,
-                        properties: MessageProperties) -> None:
+    def _process_message_moderated_tombstone(
+        self,
+        _client,
+        stanza: Node,
+        properties: MessageProperties
+    ) -> None:
+
+        if not properties.is_mam_message:
+            return
+
+        moderated = stanza.getTag(
+            'moderated', namespace=Namespace.MESSAGE_MODERATE)
+        if moderated is None:
+            return
+
+        properties.moderation = self._parse_moderated(
+            moderated, properties, properties.mam.id)
+
+    def _process_message(self,
+                         _client,
+                         stanza: Node,
+                         properties: MessageProperties) -> None:
+
         if not properties.jid.is_bare:
             return
 
@@ -68,21 +94,94 @@
         if moderated is None:
             return
 
-        retract = moderated.getTag(
-                'retract', namespace=Namespace.MESSAGE_RETRACT)
-        if retract is None:
-            # Tag can be 'retract' or 'retracted', depending on whether the
-            # server applies a tombstone for MAM messages or not.
-            retract = moderated.getTag(
-                'retracted', namespace=Namespace.MESSAGE_RETRACT)
+        stanza_id = apply_to.getAttr('id')
+        if stanza_id is None:
+            self._log.warning('apply-to element without stanza-id')
+            self._log.warning(stanza)
+            raise NodeProcessed
+
+        properties.moderation = self._parse_moderated(moderated, properties, 
stanza_id)
+
+    def _parse_moderated(
+        self,
+        moderated: Node,
+        properties: MessageProperties,
+        stanza_id: str
+    ) -> ModerationData | None:
+
+        retract, is_tombstone = _get_retract_element(moderated, properties)
         if retract is None:
-            return
+            self._log.warning('Failed to find <retract/ed> element')
+            return None
 
-        properties.moderation = ModerationData(
-            stanza_id=apply_to.getAttr('id'),
-            moderator_jid=moderated.getAttr('by'),
+        try:
+            by = _parse_by_attr(moderated)
+        except ValueError as error:
+            self._log.warning(error)
+            by = None
+
+        stamp = _parse_moderation_timestamp(retract, is_tombstone, properties)
+
+        occupant_id = moderated.getTagAttr('occupant-id',
+                                           'id',
+                                           namespace=Namespace.OCCUPANT_ID)
+
+        return ModerationData(
+            stanza_id=stanza_id,
+            moderator_jid=str(by),
+            by=by,
+            occupant_id=occupant_id,
             reason=moderated.getTagData('reason'),
-            timestamp=retract.getAttr('stamp'))
+            timestamp=retract.getAttr('stamp'),
+            stamp=stamp,
+            is_tombstone=is_tombstone)
+
+
+def _get_retract_element(
+    moderated: Node,
+    properties: MessageProperties
+) -> tuple[Node | None, bool]:
+
+    retract = moderated.getTag(
+            'retract', namespace=Namespace.MESSAGE_RETRACT)
+    if retract is not None:
+        return retract, False
+
+    retracted = moderated.getTag(
+        'retracted', namespace=Namespace.MESSAGE_RETRACT)
+    if retracted is not None:
+        return retracted, True and properties.is_mam_message
+    return None, False
+
+
+def _parse_by_attr(moderated: Node) -> JID | None:
+    by_attr = moderated.getAttr('by')
+    if by_attr is None:
+        return None
+
+    try:
+        return JID.from_string(by_attr)
+    except Exception as error:
+        raise ValueError('Invalid JID: %s, %s' % (by_attr, error))
+
+
+def _parse_moderation_timestamp(
+    retract: Node,
+    is_tombstone: bool,
+    properties: MessageProperties
+) -> float:
+
+    if is_tombstone:
+        stamp_attr = retract.getAttr('stamp')
+        stamp = parse_datetime(
+            stamp_attr, check_utc=True, convert='utc', epoch=True)
+        if stamp is not None:
+            return stamp
+
+    if properties.is_mam_message:
+        return properties.mam.timestamp
+
+    return properties.timestamp
 
 
 def _make_retract_request(muc_jid: JID, stanza_id: str,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-nbxmpp-4.3.1/nbxmpp/modules/muc/muc.py 
new/python-nbxmpp-4.3.2/nbxmpp/modules/muc/muc.py
--- old/python-nbxmpp-4.3.1/nbxmpp/modules/muc/muc.py   2023-05-28 
23:18:18.000000000 +0200
+++ new/python-nbxmpp-4.3.2/nbxmpp/modules/muc/muc.py   2023-08-07 
22:57:16.000000000 +0200
@@ -245,13 +245,6 @@
 
         properties.occupant_id = occupant_id
 
-        # MUC Private message
-        if (properties.type.is_chat or
-                properties.type.is_error and
-                not muc_user.getChildren()):
-            properties.muc_private_message = True
-            return
-
         if properties.is_muc_invite_or_decline:
             return
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-nbxmpp-4.3.1/nbxmpp/modules/security_labels.py 
new/python-nbxmpp-4.3.2/nbxmpp/modules/security_labels.py
--- old/python-nbxmpp-4.3.1/nbxmpp/modules/security_labels.py   2023-05-28 
23:18:18.000000000 +0200
+++ new/python-nbxmpp-4.3.2/nbxmpp/modules/security_labels.py   2023-08-07 
22:57:16.000000000 +0200
@@ -18,6 +18,7 @@
 from typing import Dict
 
 from dataclasses import dataclass
+import hashlib
 
 from nbxmpp.protocol import Iq
 from nbxmpp.simplexml import Node
@@ -150,6 +151,10 @@
 
         return cls(displaymarking=displaymarking, label=label)
 
+    def get_label_hash(self) -> str:
+        sha = hashlib.sha512()
+        sha.update(str(self.label).encode())
+        return sha.hexdigest()
 
 @dataclass
 class Catalog:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-nbxmpp-4.3.1/nbxmpp/protocol.py 
new/python-nbxmpp-4.3.2/nbxmpp/protocol.py
--- old/python-nbxmpp-4.3.1/nbxmpp/protocol.py  2023-05-28 23:18:18.000000000 
+0200
+++ new/python-nbxmpp-4.3.2/nbxmpp/protocol.py  2023-08-07 22:57:16.000000000 
+0200
@@ -30,6 +30,7 @@
 import time
 import hashlib
 import functools
+import sqlite3
 import warnings
 from base64 import b64encode
 from dataclasses import dataclass
@@ -704,6 +705,11 @@
             return f'{jid}/{self.resource}'
         return jid
 
+    def __conform__(self, protocol: sqlite3.PrepareProtocol):
+        if protocol is sqlite3.PrepareProtocol:
+            return str(self)
+        raise ValueError
+
     def __hash__(self):
         return hash(str(self))
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-nbxmpp-4.3.1/nbxmpp/structs.py 
new/python-nbxmpp-4.3.2/nbxmpp/structs.py
--- old/python-nbxmpp-4.3.1/nbxmpp/structs.py   2023-05-28 23:18:18.000000000 
+0200
+++ new/python-nbxmpp-4.3.2/nbxmpp/structs.py   2023-08-07 22:57:16.000000000 
+0200
@@ -299,9 +299,13 @@
 
 class ModerationData(NamedTuple):
     stanza_id: str
-    moderator_jid: str
-    reason: Optional[str] = None
-    timestamp: Optional[str] = None
+    moderator_jid: Optional[str]
+    by: Optional[JID]
+    reason: Optional[str]
+    timestamp: Optional[str]
+    stamp: float
+    is_tombstone: bool
+    occupant_id: Optional[str]
 
 
 class DiscoItems(NamedTuple):
@@ -769,10 +773,18 @@
         self.condition_data = self._error_node.getTagData(self.condition)
         self.app_condition = stanza.getAppError()
         self.type = stanza.getErrorType()
+        self.by = None
         self.jid = stanza.getFrom()
         self.id = stanza.getID()
         self._text = {}
 
+        by = self._error_node.getAttr('by')
+        if by is not None:
+            try:
+                self.by = JID.from_string(by)
+            except Exception:
+                pass
+
         text_elements = self._error_node.getTags('text', 
namespace=Namespace.STANZAS)
         for element in text_elements:
             lang = element.getXmlLang()
@@ -917,7 +929,7 @@
     query_id: str
     archive: JID
     namespace: str
-    timestamp: datetime
+    timestamp: float
 
     @property
     def is_ver_1(self) -> bool:
@@ -964,9 +976,11 @@
     type: MessageType = MessageType.NORMAL
     id: Optional[str] = None
     stanza_ids: list[StanzaIDData] = field(default_factory=list)
+    origin_id: Optional[str] = None
     from_: Optional[JID] = None
     to: Optional[JID] = None
     jid: Optional[JID] = None
+    remote_jid: Optional[JID] = None
     subject = None
     body: Optional[str] = None
     thread: Optional[str] = None

Reply via email to