From 79f5e736b002e089fa5b56524a2afc98820cbc87 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Sun, 23 Feb 2020 17:43:29 +0100 Subject: [PATCH] make eventlogger module a global plugin --- python/src/deltachat/__init__.py | 5 +++ python/src/deltachat/account.py | 57 +++++++++++------------------ python/src/deltachat/eventlogger.py | 30 ++++++++++++++- python/src/deltachat/hookspec.py | 11 +++--- python/tests/conftest.py | 10 ++--- python/tests/test_lowlevel.py | 15 ++++---- 6 files changed, 74 insertions(+), 54 deletions(-) diff --git a/python/src/deltachat/__init__.py b/python/src/deltachat/__init__.py index e6449181d..2e52cbc46 100644 --- a/python/src/deltachat/__init__.py +++ b/python/src/deltachat/__init__.py @@ -1,6 +1,7 @@ from . import capi, const, hookspec from .capi import ffi from .account import Account # noqa +from . import eventlogger from pkg_resources import get_distribution, DistributionNotFound try: @@ -79,3 +80,7 @@ def get_dc_event_name(integer, _DC_EVENTNAME_MAP={}): def register_global_plugin(plugin): gm = hookspec.Global._get_plugin_manager() gm.register(plugin) + gm.check_pending() + + +register_global_plugin(eventlogger) diff --git a/python/src/deltachat/account.py b/python/src/deltachat/account.py index 8976b3cd4..f138b4450 100644 --- a/python/src/deltachat/account.py +++ b/python/src/deltachat/account.py @@ -45,20 +45,10 @@ class Account(object): ) hook = hookspec.Global._get_plugin_manager().hook - hook.at_account_init(account=self, db_path=db_path) + hook.account_init(account=self, db_path=db_path) - self._shutdown_event = Event() self._threads = iothreads.IOThreads(self) - # send all FFI events for this account to a plugin hook - def _ll_event(ctx, evt_name, data1, data2): - assert ctx == self._dc_context - ffi_event = FFIEvent(name=evt_name, data1=data1, data2=data2) - self._pm.hook.process_ffi_event( - account=self, ffi_event=ffi_event - ) - deltachat.set_context_callback(self._dc_context, _ll_event) - # open database if hasattr(db_path, "encode"): db_path = db_path.encode("utf8") @@ -66,6 +56,8 @@ class Account(object): raise ValueError("Could not dc_open: {}".format(db_path)) self._configkeys = self.get_config("sys.config_keys").split() atexit.register(self.shutdown) + self._shutdown_event = Event() + @hookspec.account_hookimpl def process_ffi_event(self, ffi_event): @@ -549,20 +541,19 @@ class Account(object): If this account is not configured, an internal configuration job will be scheduled if config values are sufficiently specified. + You may call :method:`wait_shutdown` or `shutdown` after the + account is in started mode. + :raises MissingCredentials: if `addr` and `mail_pw` values are not set. :returns: None """ if not self.is_configured(): - if not self.get_config("addr") or not self.get_config("mail_pwd"): + if not self.get_config("addr") or not self.get_config("mail_pw"): raise MissingCredentials("addr or mail_pwd not set in config") lib.dc_configure(self._dc_context) self._threads.start() - @hookspec.account_hookimpl - def after_shutdown(self): - self._shutdown_event.set() - def wait_shutdown(self): """ wait until shutdown of this account has completed. """ self._shutdown_event.wait() @@ -570,16 +561,20 @@ class Account(object): def shutdown(self, wait=True): """ shutdown account, stop threads and close and remove underlying dc_context and callbacks. """ - if hasattr(self, "_dc_context") and hasattr(self, "_threads"): - if self._threads.is_started(): - self.stop_ongoing() - self._threads.stop(wait=False) - lib.dc_close(self._dc_context) - self._threads.stop(wait=wait) # to wait for threads - deltachat.clear_context_callback(self._dc_context) - del self._dc_context - atexit.unregister(self.shutdown) - self._pm.hook.after_shutdown() + dc_context = self._dc_context + if dc_context is None: + return + + if self._threads.is_started(): + self.stop_ongoing() + self._threads.stop(wait=False) + lib.dc_close(dc_context) + self._threads.stop(wait=wait) # to wait for threads + self._dc_context = None + atexit.unregister(self.shutdown) + hook = hookspec.Global._get_plugin_manager().hook + hook.account_after_shutdown(account=self, dc_context=dc_context) + self._shutdown_event.set() def _destroy_dc_context(dc_context, dc_context_unref=lib.dc_context_unref): @@ -593,16 +588,6 @@ def _destroy_dc_context(dc_context, dc_context_unref=lib.dc_context_unref): pass -class FFIEvent: - def __init__(self, name, data1, data2): - self.name = name - self.data1 = data1 - self.data2 = data2 - - def __str__(self): - return "{name} data1={data1} data2={data2}".format(**self.__dict__) - - class ScannedQRCode: def __init__(self, dc_lot): self._dc_lot = dc_lot diff --git a/python/src/deltachat/eventlogger.py b/python/src/deltachat/eventlogger.py index f813ab1ec..363f0359a 100644 --- a/python/src/deltachat/eventlogger.py +++ b/python/src/deltachat/eventlogger.py @@ -1,6 +1,34 @@ +import deltachat import threading import time -from .hookspec import account_hookimpl +from .hookspec import account_hookimpl, global_hookimpl + + +@global_hookimpl +def account_init(account): + # send all FFI events for this account to a plugin hook + def _ll_event(ctx, evt_name, data1, data2): + assert ctx == account._dc_context + ffi_event = FFIEvent(name=evt_name, data1=data1, data2=data2) + account._pm.hook.process_ffi_event( + account=account, ffi_event=ffi_event + ) + deltachat.set_context_callback(account._dc_context, _ll_event) + + +@global_hookimpl +def account_after_shutdown(dc_context): + deltachat.clear_context_callback(dc_context) + + +class FFIEvent: + def __init__(self, name, data1, data2): + self.name = name + self.data1 = data1 + self.data2 = data2 + + def __str__(self): + return "{name} data1={data1} data2={data2}".format(**self.__dict__) class FFIEventLogger: diff --git a/python/src/deltachat/hookspec.py b/python/src/deltachat/hookspec.py index a697028f2..159b4a3f8 100644 --- a/python/src/deltachat/hookspec.py +++ b/python/src/deltachat/hookspec.py @@ -47,10 +47,6 @@ class PerAccount: def process_message_delivered(self, message): """ Called when an outgoing message has been delivered to SMTP. """ - @account_hookspec - def after_shutdown(self): - """ Called after the account has been shutdown. """ - class Global: """ global hook specifications using a per-process singleton plugin manager instance. @@ -66,5 +62,10 @@ class Global: return cls._plugin_manager @global_hookspec - def at_account_init(self, account): + def account_init(self, account): """ called when `Account::__init__()` function starts executing. """ + + @global_hookspec + def account_after_shutdown(self, account, dc_context): + """ Called after the account has been shutdown. """ + diff --git a/python/tests/conftest.py b/python/tests/conftest.py index 50b35beb1..c470b2236 100644 --- a/python/tests/conftest.py +++ b/python/tests/conftest.py @@ -230,8 +230,8 @@ def acfactory(pytestconfig, tmpdir, request, session_liveconfig, datadir): configdict.update(config) configdict["mvbox_watch"] = str(int(mvbox)) configdict["mvbox_move"] = "1" - ac.configure(**configdict) - ac.start_threads() + ac.update_config(configdict) + ac.start() return ac def get_one_online_account(self, pre_generated_key=True): @@ -257,14 +257,14 @@ def acfactory(pytestconfig, tmpdir, request, session_liveconfig, datadir): self._preconfigure_key(ac, account.get_config("addr")) ac._evtracker.init_time = self.init_time ac._evtracker.set_timeout(30) - ac.configure( + ac.update_config(dict( addr=account.get_config("addr"), mail_pw=account.get_config("mail_pw"), mvbox_watch=account.get_config("mvbox_watch"), mvbox_move=account.get_config("mvbox_move"), sentbox_watch=account.get_config("sentbox_watch"), - ) - ac.start_threads() + )) + ac.start() return ac am = AccountMaker() diff --git a/python/tests/test_lowlevel.py b/python/tests/test_lowlevel.py index f1c7238ba..1a6259a2e 100644 --- a/python/tests/test_lowlevel.py +++ b/python/tests/test_lowlevel.py @@ -1,6 +1,7 @@ from __future__ import print_function from deltachat import capi, cutil, const, set_context_callback, clear_context_callback -from deltachat.hookspec import account_hookimpl +from deltachat import register_global_plugin +from deltachat.hookspec import account_hookimpl, global_hookimpl from deltachat.capi import ffi from deltachat.capi import lib @@ -24,14 +25,14 @@ def test_dc_close_events(tmpdir, acfactory): shutdowns = [] class ShutdownPlugin: - @account_hookimpl - def after_shutdown(self): - assert not hasattr(ac1, "_dc_context") - shutdowns.append(1) - ac1.add_account_plugin(ShutdownPlugin()) + @global_hookimpl + def account_after_shutdown(self, account): + assert account._dc_context is None + shutdowns.append(account) + register_global_plugin(ShutdownPlugin()) assert hasattr(ac1, "_dc_context") ac1.shutdown() - assert shutdowns == [1] + assert shutdowns == [ac1] def find(info_string): evlog = ac1._evtracker