move event tracking to new tracker.py file

some api cleanups
This commit is contained in:
holger krekel
2020-02-22 21:25:39 +01:00
parent 57311d731e
commit cf6391d51b
5 changed files with 107 additions and 41 deletions

View File

@@ -7,8 +7,6 @@ from contextlib import contextmanager
import os import os
import time import time
from array import array from array import array
from queue import Queue
import deltachat import deltachat
from . import const from . import const
from .capi import ffi, lib from .capi import ffi, lib
@@ -17,6 +15,7 @@ from .chat import Chat
from .message import Message from .message import Message
from .contact import Contact from .contact import Contact
from .eventlogger import EventLogger from .eventlogger import EventLogger
from .tracker import ImexTracker
from .hookspec import AccountHookSpecs, account_hookimpl from .hookspec import AccountHookSpecs, account_hookimpl
@@ -45,13 +44,14 @@ class Account(object):
self._threads = IOThreads(self._dc_context, self._evlogger._log_event) self._threads = IOThreads(self._dc_context, self._evlogger._log_event)
# initialize per-account plugin system # initialize per-account plugin system
self.plugin_manager = AccountHookSpecs._make_plugin_manager() self._pm = AccountHookSpecs._make_plugin_manager()
self.plugin_manager.register(self._evlogger) self.add_account_plugin(self)
self.add_account_plugin(self._evlogger)
# send all FFI events for this account to a plugin hook # send all FFI events for this account to a plugin hook
def _ll_event(ctx, evt_name, data1, data2): def _ll_event(ctx, evt_name, data1, data2):
assert ctx == self._dc_context assert ctx == self._dc_context
self.plugin_manager.hook.process_low_level_event( self._pm.hook.process_low_level_event(
account=self, event_name=evt_name, data1=data1, data2=data2 account=self, event_name=evt_name, data1=data1, data2=data2
) )
deltachat.set_context_callback(self._dc_context, _ll_event) deltachat.set_context_callback(self._dc_context, _ll_event)
@@ -64,6 +64,19 @@ class Account(object):
self._configkeys = self.get_config("sys.config_keys").split() self._configkeys = self.get_config("sys.config_keys").split()
atexit.register(self.shutdown) atexit.register(self.shutdown)
@account_hookimpl
def process_low_level_event(self, event_name, data1, data2):
if event_name == "DC_EVENT_CONFIGURE_PROGRESS":
if data1 == 0 or data1 == 1000:
success = data1 == 1000
self._pm.hook.configure_completed(success=success)
def add_account_plugin(self, plugin):
""" add an account plugin whose hookimpls are called. """
self._pm.register(plugin)
self._pm.check_pending()
return plugin
# def __del__(self): # def __del__(self):
# self.shutdown() # self.shutdown()
@@ -519,7 +532,7 @@ class Account(object):
deltachat.clear_context_callback(self._dc_context) deltachat.clear_context_callback(self._dc_context)
del self._dc_context del self._dc_context
atexit.unregister(self.shutdown) atexit.unregister(self.shutdown)
self.plugin_manager.unregister(self._evlogger) self._pm.unregister(self._evlogger)
def set_location(self, latitude=0.0, longitude=0.0, accuracy=0.0): def set_location(self, latitude=0.0, longitude=0.0, accuracy=0.0):
"""set a new location. It effects all chats where we currently """set a new location. It effects all chats where we currently
@@ -538,33 +551,9 @@ class Account(object):
@contextmanager @contextmanager
def temp_plugin(self, plugin): def temp_plugin(self, plugin):
""" run a code block with the given plugin temporarily registered. """ """ run a code block with the given plugin temporarily registered. """
self.plugin_manager.register(plugin) self._pm.register(plugin)
yield plugin yield plugin
self.plugin_manager.unregister(plugin) self._pm.unregister(plugin)
class ImexTracker:
def __init__(self):
self._imex_events = Queue()
@account_hookimpl
def process_low_level_event(self, event_name, data1, data2):
if event_name == "DC_EVENT_IMEX_PROGRESS":
self._imex_events.put(data1)
elif event_name == "DC_EVENT_IMEX_FILE_WRITTEN":
self._imex_events.put(data1)
def wait_finish(self, progress_timeout=60):
""" Return list of written files, raise ValueError if ExportFailed. """
files_written = []
while True:
ev = self._imex_events.get(timeout=progress_timeout)
if isinstance(ev, str):
files_written.append(ev)
elif ev == 0:
raise ValueError("export failed, exp-files: {}".format(files_written))
elif ev == 1000:
return files_written
class IOThreads: class IOThreads:

View File

@@ -1,4 +1,3 @@
import threading
import time import time
from .hookspec import account_hookimpl from .hookspec import account_hookimpl

View File

@@ -23,3 +23,7 @@ class AccountHookSpecs:
@account_hookspec @account_hookspec
def process_low_level_event(self, event_name, data1, data2): def process_low_level_event(self, event_name, data1, data2):
""" process a CFFI low level events for a given account. """ """ process a CFFI low level events for a given account. """
@account_hookspec
def configure_completed(self, success):
""" Called when a configure process completed. """

View File

@@ -0,0 +1,74 @@
from queue import Queue
from threading import Event
from .hookspec import account_hookimpl
class ImexFailed(RuntimeError):
""" Exception for signalling that import/export operations failed."""
class ImexTracker:
def __init__(self):
self._imex_events = Queue()
@account_hookimpl
def process_low_level_event(self, event_name, data1, data2):
if event_name == "DC_EVENT_IMEX_PROGRESS":
self._imex_events.put(data1)
elif event_name == "DC_EVENT_IMEX_FILE_WRITTEN":
self._imex_events.put(data1)
def wait_finish(self, progress_timeout=60):
""" Return list of written files, raise ValueError if ExportFailed. """
files_written = []
while True:
ev = self._imex_events.get(timeout=progress_timeout)
if isinstance(ev, str):
files_written.append(ev)
elif ev == 0:
raise ImexFailed("export failed, exp-files: {}".format(files_written))
elif ev == 1000:
return files_written
class ConfigureFailed(RuntimeError):
""" Exception for signalling that configuration failed."""
class ConfigureTracker:
def __init__(self):
self._configure_events = Queue()
self._smtp_finished = Event()
self._imap_finished = Event()
self._ffi_events = []
@account_hookimpl
def process_low_level_event(self, event_name, data1, data2):
self._ffi_events.append((event_name, data1, data2))
if event_name == "DC_EVENT_SMTP_CONNECTED":
self._smtp_finished.set()
elif event_name == "DC_EVENT_IMAP_CONNECTED":
self._imap_finished.set()
@account_hookimpl
def configure_completed(self, success):
self._configure_events.put(success)
def wait_smtp_connected(self):
""" wait until smtp is configured. """
self._smtp_finished.wait()
def wait_imap_connected(self):
""" wait until smtp is configured. """
self._imap_finished.wait()
def wait_finish(self):
""" wait until configure is completed.
Raise Exception if Configure failed
"""
if not self._configure_events.get():
content = "\n".join("{}: {} {}".format(*args) for args in self._ffi_events)
raise ConfigureFailed(content)

View File

@@ -6,6 +6,7 @@ import pytest
import requests import requests
import time import time
from deltachat import Account from deltachat import Account
from deltachat.tracker import ConfigureTracker
from deltachat import const from deltachat import const
from deltachat.capi import lib from deltachat.capi import lib
from _pytest.monkeypatch import MonkeyPatch from _pytest.monkeypatch import MonkeyPatch
@@ -164,8 +165,8 @@ def acfactory(pytestconfig, tmpdir, request, session_liveconfig, datadir):
def make_account(self, path, logid): def make_account(self, path, logid):
ac = Account(path, logid=logid) ac = Account(path, logid=logid)
ac._evtracker = FFIEventTracker(ac) ac._evtracker = ac.add_account_plugin(FFIEventTracker(ac))
ac.plugin_manager.register(ac._evtracker) ac._configtracker = ac.add_account_plugin(ConfigureTracker())
self._finalizers.append(ac.shutdown) self._finalizers.append(ac.shutdown)
return ac return ac
@@ -232,17 +233,16 @@ def acfactory(pytestconfig, tmpdir, request, session_liveconfig, datadir):
def get_one_online_account(self, pre_generated_key=True): def get_one_online_account(self, pre_generated_key=True):
ac1 = self.get_online_configuring_account( ac1 = self.get_online_configuring_account(
pre_generated_key=pre_generated_key) pre_generated_key=pre_generated_key)
wait_successful_IMAP_SMTP_connection(ac1) ac1._configtracker.wait_imap_connected()
wait_configuration_progress(ac1, 1000) ac1._configtracker.wait_smtp_connected()
ac1._configtracker.wait_finish()
return ac1 return ac1
def get_two_online_accounts(self): def get_two_online_accounts(self):
ac1 = self.get_online_configuring_account() ac1 = self.get_online_configuring_account()
ac2 = self.get_online_configuring_account() ac2 = self.get_online_configuring_account()
wait_successful_IMAP_SMTP_connection(ac1) ac1._configtracker.wait_finish()
wait_configuration_progress(ac1, 1000) ac2._configtracker.wait_finish()
wait_successful_IMAP_SMTP_connection(ac2)
wait_configuration_progress(ac2, 1000)
return ac1, ac2 return ac1, ac2
def clone_online_account(self, account, pre_generated_key=True): def clone_online_account(self, account, pre_generated_key=True):