From d1d43e889a6ff030dd58b4fd586ecc020823292c Mon Sep 17 00:00:00 2001 From: link2xt Date: Thu, 16 Feb 2023 18:24:19 +0000 Subject: [PATCH] python: add more type annotations --- python/pyproject.toml | 2 +- python/src/deltachat/account.py | 8 ++++---- python/src/deltachat/chat.py | 12 ++++++------ python/src/deltachat/contact.py | 6 +++--- python/src/deltachat/direct_imap.py | 2 +- python/src/deltachat/events.py | 9 ++++++--- python/src/deltachat/message.py | 4 ++-- python/src/deltachat/reactions.py | 4 ++-- python/src/deltachat/testplugin.py | 18 ++++++++++-------- python/src/deltachat/tracker.py | 20 ++++++++++++++++---- python/tests/stress_test_db.py | 4 ++-- python/tests/test_1_online.py | 2 +- 12 files changed, 54 insertions(+), 37 deletions(-) diff --git a/python/pyproject.toml b/python/pyproject.toml index ce8dfaf5b..fb846cc8f 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -51,7 +51,7 @@ git_describe_command = "git describe --dirty --tags --long --match v*.*" line-length = 120 [tool.ruff] -select = ["E", "F", "W", "YTT", "C4", "ISC", "ICN", "TID", "DTZ", "PLC", "PLE", "PLW", "PIE", "COM", "UP004", "UP010", "UP031", "UP032"] +select = ["E", "F", "W", "YTT", "C4", "ISC", "ICN", "TID", "DTZ", "PLC", "PLE", "PLW", "PIE", "COM", "UP004", "UP010", "UP031", "UP032", "ANN204"] line-length = 120 [tool.isort] diff --git a/python/src/deltachat/account.py b/python/src/deltachat/account.py index b1b08b43b..c41286ce8 100644 --- a/python/src/deltachat/account.py +++ b/python/src/deltachat/account.py @@ -121,7 +121,7 @@ class Account: """re-enable logging.""" self._logging = True - def __repr__(self): + def __repr__(self) -> str: return f"" # def __del__(self): @@ -363,12 +363,12 @@ class Account: :returns: list of :class:`deltachat.contact.Contact` objects. """ flags = 0 - query = as_dc_charpointer(query) + query_c = as_dc_charpointer(query) if only_verified: flags |= const.DC_GCL_VERIFIED_ONLY if with_self: flags |= const.DC_GCL_ADD_SELF - dc_array = ffi.gc(lib.dc_get_contacts(self._dc_context, flags, query), lib.dc_array_unref) + dc_array = ffi.gc(lib.dc_get_contacts(self._dc_context, flags, query_c), lib.dc_array_unref) return list(iter_array(dc_array, lambda x: Contact(self, x))) def get_fresh_messages(self) -> Generator[Message, None, None]: @@ -767,7 +767,7 @@ class Account: class ScannedQRCode: - def __init__(self, dc_lot): + def __init__(self, dc_lot) -> None: self._dc_lot = dc_lot def is_ask_verifycontact(self): diff --git a/python/src/deltachat/chat.py b/python/src/deltachat/chat.py index e666b6cd4..6275a61fe 100644 --- a/python/src/deltachat/chat.py +++ b/python/src/deltachat/chat.py @@ -24,7 +24,7 @@ class Chat: You obtain instances of it through :class:`deltachat.account.Account`. """ - def __init__(self, account, id) -> None: + def __init__(self, account, id: int) -> None: from .account import Account assert isinstance(account, Account), repr(account) @@ -532,13 +532,13 @@ class Chat: # ------ location streaming API ------------------------------ - def is_sending_locations(self): + def is_sending_locations(self) -> bool: """return True if this chat has location-sending enabled currently. :returns: True if location sending is enabled. """ - return lib.dc_is_sending_locations_to_chat(self.account._dc_context, self.id) + return bool(lib.dc_is_sending_locations_to_chat(self.account._dc_context, self.id)) - def enable_sending_locations(self, seconds): + def enable_sending_locations(self, seconds) -> None: """enable sending locations for this chat. all subsequent messages will carry a location with them. @@ -572,7 +572,7 @@ class Chat: class Location: - def __init__(self, latitude, longitude, accuracy, timestamp, marker): + def __init__(self, latitude, longitude, accuracy, timestamp, marker) -> None: assert isinstance(timestamp, datetime) self.latitude = latitude self.longitude = longitude @@ -580,5 +580,5 @@ class Location: self.timestamp = timestamp self.marker = marker - def __eq__(self, other): + def __eq__(self, other) -> bool: return self.__dict__ == other.__dict__ diff --git a/python/src/deltachat/contact.py b/python/src/deltachat/contact.py index f317eb315..f49b91fbc 100644 --- a/python/src/deltachat/contact.py +++ b/python/src/deltachat/contact.py @@ -15,7 +15,7 @@ class Contact: You obtain instances of it through :class:`deltachat.account.Account`. """ - def __init__(self, account, id): + def __init__(self, account, id) -> None: from .account import Account assert isinstance(account, Account), repr(account) @@ -27,10 +27,10 @@ class Contact: return False return self.account._dc_context == other.account._dc_context and self.id == other.id - def __ne__(self, other): + def __ne__(self, other) -> bool: return not self == other - def __repr__(self): + def __repr__(self) -> str: return f"" @property diff --git a/python/src/deltachat/direct_imap.py b/python/src/deltachat/direct_imap.py index d95bd29ab..7584bcec5 100644 --- a/python/src/deltachat/direct_imap.py +++ b/python/src/deltachat/direct_imap.py @@ -191,7 +191,7 @@ class DirectImap: class IdleManager: - def __init__(self, direct_imap): + def __init__(self, direct_imap) -> None: self.direct_imap = direct_imap self.log = direct_imap.account.log # fetch latest messages before starting idle so that it only diff --git a/python/src/deltachat/events.py b/python/src/deltachat/events.py index 006095da0..38f6e2698 100644 --- a/python/src/deltachat/events.py +++ b/python/src/deltachat/events.py @@ -25,12 +25,12 @@ def get_dc_event_name(integer, _DC_EVENTNAME_MAP={}): class FFIEvent: - def __init__(self, name: str, data1, data2): + def __init__(self, name: str, data1, data2) -> None: self.name = name self.data1 = data1 self.data2 = data2 - def __str__(self): + def __str__(self) -> str: if self.name == "DC_EVENT_INFO": return f"INFO {self.data2}" if self.name == "DC_EVENT_WARNING": @@ -84,7 +84,10 @@ class FFIEventLogger: class FFIEventTracker: - def __init__(self, account, timeout=None): + account: Account + _event_queue: Queue + + def __init__(self, account: Account, timeout=None) -> None: self.account = account self._timeout = timeout self._event_queue = Queue() diff --git a/python/src/deltachat/message.py b/python/src/deltachat/message.py index f0a1cd08b..1c2986728 100644 --- a/python/src/deltachat/message.py +++ b/python/src/deltachat/message.py @@ -19,7 +19,7 @@ class Message: :class:`deltachat.chat.Chat`. """ - def __init__(self, account, dc_msg): + def __init__(self, account, dc_msg) -> None: self.account = account assert isinstance(self.account._dc_context, ffi.CData) assert isinstance(dc_msg, ffi.CData) @@ -33,7 +33,7 @@ class Message: return False return self.account == other.account and self.id == other.id - def __repr__(self): + def __repr__(self) -> str: c = self.get_sender_contact() typ = "outgoing" if self.is_outgoing() else "incoming" return ( diff --git a/python/src/deltachat/reactions.py b/python/src/deltachat/reactions.py index 1ab2744d0..9838174ce 100644 --- a/python/src/deltachat/reactions.py +++ b/python/src/deltachat/reactions.py @@ -10,14 +10,14 @@ class Reactions: You obtain instances of it through :class:`deltachat.message.Message`. """ - def __init__(self, account, dc_reactions): + def __init__(self, account, dc_reactions) -> None: assert isinstance(account._dc_context, ffi.CData) assert isinstance(dc_reactions, ffi.CData) assert dc_reactions != ffi.NULL self.account = account self._dc_reactions = dc_reactions - def __repr__(self): + def __repr__(self) -> str: return f"" @classmethod diff --git a/python/src/deltachat/testplugin.py b/python/src/deltachat/testplugin.py index ebbb13aaf..c48b1101f 100644 --- a/python/src/deltachat/testplugin.py +++ b/python/src/deltachat/testplugin.py @@ -9,7 +9,7 @@ import threading import time import weakref from queue import Queue -from typing import Callable, List, Optional +from typing import Callable, List, Optional, Dict, Set import pytest import requests @@ -65,8 +65,8 @@ def pytest_configure(config): # Additionally make the acfactory use a logging/no-logging default. class LoggingAspect: - def __init__(self): - self._accounts = weakref.WeakSet() + def __init__(self) -> None: + self._accounts: weakref.WeakSet = weakref.WeakSet() @deltachat.global_hookimpl def dc_account_init(self, account): @@ -143,10 +143,12 @@ def testprocess(request): class TestProcess: """A pytest session-scoped instance to help with managing "live" account configurations.""" - def __init__(self, pytestconfig): + _addr2files: Dict[str, Dict[pathlib.Path, bytes]] + + def __init__(self, pytestconfig) -> None: self.pytestconfig = pytestconfig self._addr2files = {} - self._configlist = [] + self._configlist: List[Dict[str, str]] = [] def get_liveconfig_producer(self): """provide live account configs, cached on a per-test-process scope @@ -277,10 +279,10 @@ class ACSetup: _configured_events: Queue - def __init__(self, testprocess, init_time): + def __init__(self, testprocess, init_time) -> None: self._configured_events = Queue() - self._account2state = {} - self._imap_cleaned = set() + self._account2state: Dict[Account, str] = {} + self._imap_cleaned: Set[str] = set() self.testprocess = testprocess self.init_time = init_time diff --git a/python/src/deltachat/tracker.py b/python/src/deltachat/tracker.py index 2dc2ad41b..f8fbc3f8f 100644 --- a/python/src/deltachat/tracker.py +++ b/python/src/deltachat/tracker.py @@ -1,19 +1,25 @@ from queue import Queue from threading import Event +from typing import List, TYPE_CHECKING from .hookspec import Global, account_hookimpl +if TYPE_CHECKING: + from .events import FFIEvent + class ImexFailed(RuntimeError): """Exception for signalling that import/export operations failed.""" class ImexTracker: - def __init__(self): + _imex_events: Queue + + def __init__(self) -> None: self._imex_events = Queue() @account_hookimpl - def ac_process_ffi_event(self, ffi_event): + def ac_process_ffi_event(self, ffi_event: "FFIEvent") -> None: if ffi_event.name == "DC_EVENT_IMEX_PROGRESS": self._imex_events.put(ffi_event.data1) elif ffi_event.name == "DC_EVENT_IMEX_FILE_WRITTEN": @@ -50,7 +56,13 @@ class ConfigureFailed(RuntimeError): class ConfigureTracker: ConfigureFailed = ConfigureFailed - def __init__(self, account): + _configure_events: Queue + _smtp_finished: Event + _imap_finished: Event + _ffi_events: List["FFIEvent"] + _progress: Queue + + def __init__(self, account) -> None: self.account = account self._configure_events = Queue() self._smtp_finished = Event() @@ -60,7 +72,7 @@ class ConfigureTracker: self._gm = Global._get_plugin_manager() @account_hookimpl - def ac_process_ffi_event(self, ffi_event): + def ac_process_ffi_event(self, ffi_event: "FFIEvent") -> None: self._ffi_events.append(ffi_event) if ffi_event.name == "DC_EVENT_SMTP_CONNECTED": self._smtp_finished.set() diff --git a/python/tests/stress_test_db.py b/python/tests/stress_test_db.py index a8b942a09..43a04116a 100644 --- a/python/tests/stress_test_db.py +++ b/python/tests/stress_test_db.py @@ -77,7 +77,7 @@ class ReportType: class AutoReplier: - def __init__(self, account, log, num_send, num_bigfiles, report_func): + def __init__(self, account, log, num_send, num_bigfiles, report_func) -> None: self.account = account self._log = log self.report_func = report_func @@ -90,7 +90,7 @@ class AutoReplier: self._thread.setDaemon(True) self._thread.start() - def log(self, message): + def log(self, message) -> None: self._log(f"{self.addr} {message}") def thread_stats(self): diff --git a/python/tests/test_1_online.py b/python/tests/test_1_online.py index c25fcb85b..a807bbe3c 100644 --- a/python/tests/test_1_online.py +++ b/python/tests/test_1_online.py @@ -1604,7 +1604,7 @@ def test_add_remove_member_remote_events(acfactory, lp): in_list = queue.Queue() class EventHolder: - def __init__(self, **kwargs): + def __init__(self, **kwargs) -> None: self.__dict__.update(kwargs) class InPlugin: