Philipp Hörist pushed to branch master at gajim / python-nbxmpp
Commits:
-
0c23dfbc
by lovetox at 2021-11-03T00:44:47+01:00
-
c3eb064b
by lovetox at 2021-11-03T00:45:16+01:00
-
1550765b
by lovetox at 2021-11-03T00:46:22+01:00
5 changed files:
- nbxmpp/modules/base.py
- nbxmpp/modules/blocking.py
- nbxmpp/protocol.py
- nbxmpp/structs.py
- + nbxmpp/types.py
Changes:
| ... | ... | @@ -15,21 +15,29 @@ |
| 15 | 15 |
# You should have received a copy of the GNU General Public License
|
| 16 | 16 |
# along with this program; If not, see <http://www.gnu.org/licenses/>.
|
| 17 | 17 |
|
| 18 |
+from __future__ import annotations
|
|
| 19 |
+ |
|
| 20 |
+from typing import TYPE_CHECKING
|
|
| 21 |
+from typing import Any
|
|
| 22 |
+ |
|
| 18 | 23 |
import logging
|
| 19 | 24 |
|
| 20 | 25 |
from nbxmpp.util import LogAdapter
|
| 21 | 26 |
|
| 27 |
+if TYPE_CHECKING:
|
|
| 28 |
+ from nbxmpp.client import Client
|
|
| 29 |
+ |
|
| 22 | 30 |
|
| 23 | 31 |
class BaseModule:
|
| 24 | 32 |
|
| 25 |
- _depends = {}
|
|
| 33 |
+ _depends: dict[str, str] = {}
|
|
| 26 | 34 |
|
| 27 |
- def __init__(self, client):
|
|
| 35 |
+ def __init__(self, client: Client):
|
|
| 28 | 36 |
logger_name = 'nbxmpp.m.%s' % self.__class__.__name__.lower()
|
| 29 | 37 |
self._log = LogAdapter(logging.getLogger(logger_name),
|
| 30 | 38 |
{'context': client.log_context})
|
| 31 | 39 |
|
| 32 |
- def __getattr__(self, name):
|
|
| 40 |
+ def __getattr__(self, name: str) -> Any:
|
|
| 33 | 41 |
if name not in self._depends:
|
| 34 | 42 |
raise AttributeError('Unknown method: %s' % name)
|
| 35 | 43 |
|
| ... | ... | @@ -15,20 +15,35 @@ |
| 15 | 15 |
# You should have received a copy of the GNU General Public License
|
| 16 | 16 |
# along with this program; If not, see <http://www.gnu.org/licenses/>.
|
| 17 | 17 |
|
| 18 |
+from __future__ import annotations
|
|
| 19 |
+ |
|
| 20 |
+from typing import Literal, Optional
|
|
| 21 |
+from typing import Union
|
|
| 22 |
+from typing import Set
|
|
| 23 |
+from typing import TYPE_CHECKING
|
|
| 24 |
+ |
|
| 18 | 25 |
from nbxmpp.namespaces import Namespace
|
| 26 |
+from nbxmpp.simplexml import Node
|
|
| 19 | 27 |
from nbxmpp.protocol import Iq
|
| 20 | 28 |
from nbxmpp.protocol import JID
|
| 21 |
-from nbxmpp.modules.base import BaseModule
|
|
| 22 | 29 |
from nbxmpp.errors import StanzaError
|
| 23 | 30 |
from nbxmpp.errors import MalformedStanzaError
|
| 24 | 31 |
from nbxmpp.task import iq_request_task
|
| 25 |
-from nbxmpp.structs import BlockingPush
|
|
| 26 | 32 |
from nbxmpp.structs import StanzaHandler
|
| 33 |
+from nbxmpp.structs import BlockingProperties
|
|
| 34 |
+from nbxmpp.structs import BlockingPush
|
|
| 35 |
+from nbxmpp.types import BlockingReportValues
|
|
| 36 |
+from nbxmpp.modules.base import BaseModule
|
|
| 27 | 37 |
from nbxmpp.modules.util import process_response
|
| 28 | 38 |
|
| 29 | 39 |
|
| 40 |
+if TYPE_CHECKING:
|
|
| 41 |
+ from nbxmpp.client import Client
|
|
| 42 |
+ |
|
| 43 |
+ |
|
| 44 |
+ |
|
| 30 | 45 |
class Blocking(BaseModule):
|
| 31 |
- def __init__(self, client):
|
|
| 46 |
+ def __init__(self, client: Client):
|
|
| 32 | 47 |
BaseModule.__init__(self, client)
|
| 33 | 48 |
|
| 34 | 49 |
self._client = client
|
| ... | ... | @@ -66,21 +81,27 @@ class Blocking(BaseModule): |
| 66 | 81 |
yield blocked
|
| 67 | 82 |
|
| 68 | 83 |
@iq_request_task
|
| 69 |
- def block(self, jids, report=None):
|
|
| 84 |
+ def block(self,
|
|
| 85 |
+ jids: list[JID],
|
|
| 86 |
+ report: Optional[BlockingReportValues] = None):
|
|
| 87 |
+ |
|
| 70 | 88 |
_task = yield
|
| 71 | 89 |
|
| 72 | 90 |
response = yield _make_block_request(jids, report)
|
| 73 | 91 |
yield process_response(response)
|
| 74 | 92 |
|
| 75 | 93 |
@iq_request_task
|
| 76 |
- def unblock(self, jids):
|
|
| 94 |
+ def unblock(self, jids: list[JID]):
|
|
| 77 | 95 |
_task = yield
|
| 78 | 96 |
|
| 79 | 97 |
response = yield _make_unblock_request(jids)
|
| 80 | 98 |
yield process_response(response)
|
| 81 | 99 |
|
| 82 | 100 |
@staticmethod
|
| 83 |
- def _process_blocking_push(client, stanza, properties):
|
|
| 101 |
+ def _process_blocking_push(client: Client,
|
|
| 102 |
+ stanza: Iq,
|
|
| 103 |
+ properties: BlockingProperties):
|
|
| 104 |
+ |
|
| 84 | 105 |
unblock = stanza.getTag('unblock', namespace=Namespace.BLOCKING)
|
| 85 | 106 |
if unblock is not None:
|
| 86 | 107 |
properties.blocking = _parse_push(unblock)
|
| ... | ... | @@ -93,17 +114,19 @@ class Blocking(BaseModule): |
| 93 | 114 |
client.send_stanza(reply)
|
| 94 | 115 |
|
| 95 | 116 |
|
| 96 |
-def _make_blocking_list_request():
|
|
| 117 |
+def _make_blocking_list_request() -> Iq:
|
|
| 97 | 118 |
iq = Iq('get', Namespace.BLOCKING)
|
| 98 | 119 |
iq.setQuery('blocklist')
|
| 99 | 120 |
return iq
|
| 100 | 121 |
|
| 101 | 122 |
|
| 102 |
-def _make_block_request(jids, report):
|
|
| 123 |
+def _make_block_request(jids: list[JID],
|
|
| 124 |
+ report: Optional[BlockingReportValues]) -> Iq:
|
|
| 125 |
+ |
|
| 103 | 126 |
iq = Iq('set', Namespace.BLOCKING)
|
| 104 | 127 |
query = iq.setQuery(name='block')
|
| 105 | 128 |
for jid in jids:
|
| 106 |
- item = query.addChild(name='item', attrs={'jid': jid})
|
|
| 129 |
+ item = query.addChild(name='item', attrs={'jid': str(jid)})
|
|
| 107 | 130 |
if report in ('spam', 'abuse'):
|
| 108 | 131 |
action = item.addChild(name='report',
|
| 109 | 132 |
namespace=Namespace.REPORTING)
|
| ... | ... | @@ -111,20 +134,20 @@ def _make_block_request(jids, report): |
| 111 | 134 |
return iq
|
| 112 | 135 |
|
| 113 | 136 |
|
| 114 |
-def _make_unblock_request(jids):
|
|
| 137 |
+def _make_unblock_request(jids: list[JID]) -> Iq:
|
|
| 115 | 138 |
iq = Iq('set', Namespace.BLOCKING)
|
| 116 | 139 |
query = iq.setQuery(name='unblock')
|
| 117 | 140 |
for jid in jids:
|
| 118 |
- query.addChild(name='item', attrs={'jid': jid})
|
|
| 141 |
+ query.addChild(name='item', attrs={'jid': str(jid)})
|
|
| 119 | 142 |
return iq
|
| 120 | 143 |
|
| 121 | 144 |
|
| 122 |
-def _parse_push(node):
|
|
| 145 |
+def _parse_push(node: Node) -> BlockingPush:
|
|
| 123 | 146 |
items = node.getTags('item')
|
| 124 | 147 |
if not items:
|
| 125 | 148 |
return BlockingPush(block=set(), unblock=set(), unblock_all=True)
|
| 126 | 149 |
|
| 127 |
- jids = set()
|
|
| 150 |
+ jids: Set[JID] = set()
|
|
| 128 | 151 |
for item in items:
|
| 129 | 152 |
jid = item.getAttr('jid')
|
| 130 | 153 |
if not jid:
|
| ... | ... | @@ -137,8 +160,8 @@ def _parse_push(node): |
| 137 | 160 |
|
| 138 | 161 |
jids.add(jid)
|
| 139 | 162 |
|
| 140 |
- |
|
| 141 |
- block, unblock = set(), set()
|
|
| 163 |
+ block: Set[JID] = set()
|
|
| 164 |
+ unblock: Set[JID] = set()
|
|
| 142 | 165 |
if node.getName() == 'block':
|
| 143 | 166 |
block = jids
|
| 144 | 167 |
else:
|
| ... | ... | @@ -1387,14 +1387,14 @@ class Iq(Protocol): |
| 1387 | 1387 |
"""
|
| 1388 | 1388 |
|
| 1389 | 1389 |
def __init__(self,
|
| 1390 |
- typ=None,
|
|
| 1391 |
- queryNS=None,
|
|
| 1392 |
- attrs=None,
|
|
| 1393 |
- to=None,
|
|
| 1394 |
- frm=None,
|
|
| 1395 |
- payload=None,
|
|
| 1396 |
- xmlns=Namespace.CLIENT,
|
|
| 1397 |
- node=None):
|
|
| 1390 |
+ typ: Optional[str] = None,
|
|
| 1391 |
+ queryNS: Optional[str] = None,
|
|
| 1392 |
+ attrs: Optional[dict[str, str]] = None,
|
|
| 1393 |
+ to: Optional[Union[JID, str]] = None,
|
|
| 1394 |
+ frm: Optional[Union[JID, str]] = None,
|
|
| 1395 |
+ payload: Optional[list[Union[Node, str]]] = None,
|
|
| 1396 |
+ xmlns: str = Namespace.CLIENT,
|
|
| 1397 |
+ node: Optional[Node] = None):
|
|
| 1398 | 1398 |
"""
|
| 1399 | 1399 |
You can specify type, query namespace any additional attributes,
|
| 1400 | 1400 |
recipient of the iq, sender of the iq, any additional payload (f.e.
|
| ... | ... | @@ -1416,7 +1416,7 @@ class Iq(Protocol): |
| 1416 | 1416 |
if queryNS:
|
| 1417 | 1417 |
self.setQueryNS(queryNS)
|
| 1418 | 1418 |
|
| 1419 |
- def getQuery(self):
|
|
| 1419 |
+ def getQuery(self) -> Optional[Node]:
|
|
| 1420 | 1420 |
"""
|
| 1421 | 1421 |
Return the IQ's child element if it exists, None otherwise.
|
| 1422 | 1422 |
"""
|
| ... | ... | @@ -1426,7 +1426,7 @@ class Iq(Protocol): |
| 1426 | 1426 |
return children[0]
|
| 1427 | 1427 |
return None
|
| 1428 | 1428 |
|
| 1429 |
- def getQueryNS(self):
|
|
| 1429 |
+ def getQueryNS(self) -> Optional[str]:
|
|
| 1430 | 1430 |
"""
|
| 1431 | 1431 |
Return the namespace of the 'query' child element
|
| 1432 | 1432 |
"""
|
| ... | ... | @@ -1435,7 +1435,7 @@ class Iq(Protocol): |
| 1435 | 1435 |
return tag.getNamespace()
|
| 1436 | 1436 |
return None
|
| 1437 | 1437 |
|
| 1438 |
- def getQuerynode(self):
|
|
| 1438 |
+ def getQuerynode(self) -> Optional[str]:
|
|
| 1439 | 1439 |
"""
|
| 1440 | 1440 |
Return the 'node' attribute value of the 'query' child element
|
| 1441 | 1441 |
"""
|
| ... | ... | @@ -1444,7 +1444,7 @@ class Iq(Protocol): |
| 1444 | 1444 |
return tag.getAttr('node')
|
| 1445 | 1445 |
return None
|
| 1446 | 1446 |
|
| 1447 |
- def getQueryPayload(self):
|
|
| 1447 |
+ def getQueryPayload(self) -> Optional[list[Union[Node, str]]]:
|
|
| 1448 | 1448 |
"""
|
| 1449 | 1449 |
Return the 'query' child element payload
|
| 1450 | 1450 |
"""
|
| ... | ... | @@ -1453,7 +1453,7 @@ class Iq(Protocol): |
| 1453 | 1453 |
return tag.getPayload()
|
| 1454 | 1454 |
return None
|
| 1455 | 1455 |
|
| 1456 |
- def getQueryChildren(self):
|
|
| 1456 |
+ def getQueryChildren(self) -> Optional[list[Node]]:
|
|
| 1457 | 1457 |
"""
|
| 1458 | 1458 |
Return the 'query' child element child nodes
|
| 1459 | 1459 |
"""
|
| ... | ... | @@ -1462,7 +1462,7 @@ class Iq(Protocol): |
| 1462 | 1462 |
return tag.getChildren()
|
| 1463 | 1463 |
return None
|
| 1464 | 1464 |
|
| 1465 |
- def getQueryChild(self, name=None):
|
|
| 1465 |
+ def getQueryChild(self, name: Optional[str] = None) -> Optional[Node]:
|
|
| 1466 | 1466 |
"""
|
| 1467 | 1467 |
Return the 'query' child element with name, or the first element
|
| 1468 | 1468 |
which is not an error element
|
| ... | ... | @@ -1479,7 +1479,7 @@ class Iq(Protocol): |
| 1479 | 1479 |
return node
|
| 1480 | 1480 |
return None
|
| 1481 | 1481 |
|
| 1482 |
- def setQuery(self, name=None):
|
|
| 1482 |
+ def setQuery(self, name: Optional[str] = None) -> Node:
|
|
| 1483 | 1483 |
"""
|
| 1484 | 1484 |
Change the name of the query node, creating it if needed. Keep the
|
| 1485 | 1485 |
existing name if none is given (use 'query' if it's a creation).
|
| ... | ... | @@ -1492,25 +1492,25 @@ class Iq(Protocol): |
| 1492 | 1492 |
query.setName(name)
|
| 1493 | 1493 |
return query
|
| 1494 | 1494 |
|
| 1495 |
- def setQueryNS(self, namespace):
|
|
| 1495 |
+ def setQueryNS(self, namespace: str) -> None:
|
|
| 1496 | 1496 |
"""
|
| 1497 | 1497 |
Set the namespace of the 'query' child element
|
| 1498 | 1498 |
"""
|
| 1499 | 1499 |
self.setQuery().setNamespace(namespace)
|
| 1500 | 1500 |
|
| 1501 |
- def setQueryPayload(self, payload):
|
|
| 1501 |
+ def setQueryPayload(self, payload: list[Union[Node, str]]):
|
|
| 1502 | 1502 |
"""
|
| 1503 | 1503 |
Set the 'query' child element payload
|
| 1504 | 1504 |
"""
|
| 1505 | 1505 |
self.setQuery().setPayload(payload)
|
| 1506 | 1506 |
|
| 1507 |
- def setQuerynode(self, node):
|
|
| 1507 |
+ def setQuerynode(self, node: str) -> None:
|
|
| 1508 | 1508 |
"""
|
| 1509 | 1509 |
Set the 'node' attribute value of the 'query' child element
|
| 1510 | 1510 |
"""
|
| 1511 | 1511 |
self.setQuery().setAttr('node', node)
|
| 1512 | 1512 |
|
| 1513 |
- def buildReply(self, typ):
|
|
| 1513 |
+ def buildReply(self, typ: str) -> Iq:
|
|
| 1514 | 1514 |
"""
|
| 1515 | 1515 |
Build and return another Iq object of specified type. The to, from and
|
| 1516 | 1516 |
query child node of new Iq are pre-set as reply to this Iq.
|
| ... | ... | @@ -1522,7 +1522,7 @@ class Iq(Protocol): |
| 1522 | 1522 |
iq.setQuery(self.getQuery().getName()).setNamespace(self.getQueryNS())
|
| 1523 | 1523 |
return iq
|
| 1524 | 1524 |
|
| 1525 |
- def buildSimpleReply(self, typ):
|
|
| 1525 |
+ def buildSimpleReply(self, typ: str) -> Iq:
|
|
| 1526 | 1526 |
return Iq(typ,
|
| 1527 | 1527 |
to=self.getFrom(),
|
| 1528 | 1528 |
attrs={'id': self.getID()})
|
| ... | ... | @@ -17,6 +17,7 @@ |
| 17 | 17 |
|
| 18 | 18 |
from __future__ import annotations
|
| 19 | 19 |
|
| 20 |
+import typing
|
|
| 20 | 21 |
from typing import Any
|
| 21 | 22 |
from typing import Optional
|
| 22 | 23 |
from typing import Set
|
| ... | ... | @@ -36,7 +37,8 @@ from nbxmpp.simplexml import Node |
| 36 | 37 |
from nbxmpp.namespaces import Namespace
|
| 37 | 38 |
from nbxmpp.protocol import Protocol
|
| 38 | 39 |
from nbxmpp.protocol import JID
|
| 39 |
-from nbxmpp.const import AdHocAction, IqType
|
|
| 40 |
+from nbxmpp.const import AdHocAction
|
|
| 41 |
+from nbxmpp.const import IqType
|
|
| 40 | 42 |
from nbxmpp.const import AdHocNoteType
|
| 41 | 43 |
from nbxmpp.const import MessageType
|
| 42 | 44 |
from nbxmpp.const import AvatarState
|
| ... | ... | @@ -1119,6 +1121,24 @@ class IqProperties: |
| 1119 | 1121 |
return self.roster is not None
|
| 1120 | 1122 |
|
| 1121 | 1123 |
|
| 1124 |
+class IqPropertiesBase(typing.Protocol):
|
|
| 1125 |
+ own_jid: JID
|
|
| 1126 |
+ type: IqType
|
|
| 1127 |
+ jid: JID
|
|
| 1128 |
+ id: str
|
|
| 1129 |
+ error: Optional[Any]
|
|
| 1130 |
+ query: Optional[Node]
|
|
| 1131 |
+ payload: Optional[Node]
|
|
| 1132 |
+ |
|
| 1133 |
+ |
|
| 1134 |
+class BlockingProperties(IqPropertiesBase):
|
|
| 1135 |
+ |
|
| 1136 |
+ blocking: BlockingPush
|
|
| 1137 |
+ |
|
| 1138 |
+ @property
|
|
| 1139 |
+ def is_blocking(self) -> bool: ...
|
|
| 1140 |
+ |
|
| 1141 |
+ |
|
| 1122 | 1142 |
@dataclass
|
| 1123 | 1143 |
class PresenceProperties:
|
| 1124 | 1144 |
own_jid: JID
|
| 1 |
+ |
|
| 2 |
+from typing import Union
|
|
| 3 |
+from typing import Literal
|
|
| 4 |
+ |
|
| 5 |
+BlockingReportValues = Union[Literal['spam'], Literal['abuse']]
|