| | from queue import Queue |
| | from threading import Event |
| | from typing import TYPE_CHECKING, List |
| |
|
| | 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: |
| | _imex_events: Queue |
| |
|
| | def __init__(self) -> None: |
| | self._imex_events = Queue() |
| |
|
| | @account_hookimpl |
| | 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": |
| | self._imex_events.put(ffi_event.data2) |
| |
|
| | def wait_progress(self, target_progress, progress_upper_limit=1000, progress_timeout=60): |
| | while True: |
| | ev = self._imex_events.get(timeout=progress_timeout) |
| | if isinstance(ev, int) and ev >= target_progress: |
| | assert ev <= progress_upper_limit, ( |
| | str(ev) + " exceeded upper progress limit " + str(progress_upper_limit) |
| | ) |
| | return ev |
| | if ev == 0: |
| | return None |
| |
|
| | 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(f"export failed, exp-files: {files_written}") |
| | elif ev == 1000: |
| | return files_written |
| |
|
| |
|
| | class ConfigureFailed(RuntimeError): |
| | """Exception for signalling that configuration failed.""" |
| |
|
| |
|
| | class ConfigureTracker: |
| | ConfigureFailed = ConfigureFailed |
| |
|
| | _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() |
| | self._imap_finished = Event() |
| | self._ffi_events = [] |
| | self._progress = Queue() |
| | self._gm = Global._get_plugin_manager() |
| |
|
| | @account_hookimpl |
| | 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() |
| | elif ffi_event.name == "DC_EVENT_IMAP_CONNECTED": |
| | self._imap_finished.set() |
| | elif ffi_event.name == "DC_EVENT_CONFIGURE_PROGRESS": |
| | self._progress.put(ffi_event.data1) |
| |
|
| | @account_hookimpl |
| | def ac_configure_completed(self, success): |
| | if success: |
| | self._gm.hook.dc_account_extra_configure(account=self.account) |
| | self._configure_events.put(success) |
| | self.account.remove_account_plugin(self) |
| |
|
| | def wait_smtp_connected(self): |
| | """Wait until SMTP is configured.""" |
| | self._smtp_finished.wait() |
| |
|
| | def wait_imap_connected(self): |
| | """Wait until IMAP is configured.""" |
| | self._imap_finished.wait() |
| |
|
| | def wait_progress(self, data1=None): |
| | while True: |
| | evdata = self._progress.get() |
| | if data1 is None or evdata == data1: |
| | break |
| |
|
| | def wait_finish(self, timeout=None): |
| | """ |
| | Wait until configure is completed. |
| | |
| | Raise Exception if Configure failed |
| | """ |
| | if not self._configure_events.get(timeout=timeout): |
| | content = "\n".join(map(str, self._ffi_events)) |
| | raise ConfigureFailed(content) |
| |
|