Philipp Hörist pushed to branch master at gajim / python-nbxmpp

Commits:

5 changed files:

Changes:

  • nbxmpp/modules/base.py
    ... ... @@ -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
     
    

  • nbxmpp/modules/blocking.py
    ... ... @@ -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:
    

  • nbxmpp/protocol.py
    ... ... @@ -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()})
    

  • nbxmpp/structs.py
    ... ... @@ -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
    

  • nbxmpp/types.py
    1
    +
    
    2
    +from typing import Union
    
    3
    +from typing import Literal
    
    4
    +
    
    5
    +BlockingReportValues = Union[Literal['spam'], Literal['abuse']]