vorta
vorta copied to clipboard
PyQt6 Upgrade
New version of PyQt was released beginning of Jan. We need to update some references and possible make small API adjustments. Not expecting any major issues.
https://pypi.org/project/PyQt6/
We should wait until PyQt6 is in Debian stable before we upgrade, otherwise we will lose a lot of compatibility. Alternatively, we could do something like matplotlib, but it looks very long and scary https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/backends/qt_compat.py.
Not super familiar with Debian, but I assumed that new versions of Vorta hit sid together with pyqt6. And then it moves together with it to testing and then to stable, no?
Debian 11 (bullseye) was frozen 12 Feb 2021. It will probably be at least six months before it is released, and I believe user satisfaction and Vorta's reputation would be better served by waiting a few months after that. Because Debian follows a stable release rather than rolling release model the vast majority of users (who use the stable release) will depend on targeted fixes cherry picked onto 0.7.3, which will also need to be approved and release-team review+exception as a stable update.
In other words, making this transition too soon will expose a potentially large number of users to a situation where those bugs cannot be fixed. eg: please wait ~9 months, and maybe also do this work on a feature branch if you'd like me to be able to cherry pick bug fixes.
It will definitely take a while. I heard not all Qt5 features are available in Qt6 yet.
It will definitely take a while. I heard not all Qt5 features are available in Qt6 yet.
Fiou! :-)
https://www.pythonguis.com/faq/pyqt5-vs-pyqt6/
Looks like PyQt6 will be in debian bookworm. Also is in Ubuntu >= 22.10.
Interestingly, installing pyqt6 on macOS M1 just works (unlike pyqt5):
(qt-testing) tw@mba2020 ~ % pip install pyqt6
Collecting pyqt6
Downloading PyQt6-6.4.2-cp37-abi3-macosx_10_14_universal2.whl (11.6 MB)
|████████████████████████████████| 11.6 MB 30.3 MB/s
Collecting PyQt6-Qt6>=6.4.0
Downloading PyQt6_Qt6-6.4.3-py3-none-macosx_11_0_arm64.whl (45.6 MB)
|████████████████████████████████| 45.6 MB 237 kB/s
Collecting PyQt6-sip<14,>=13.4
Downloading PyQt6_sip-13.4.1-cp39-cp39-macosx_10_9_universal2.whl (131 kB)
|████████████████████████████████| 131 kB 15.6 MB/s
Installing collected packages: PyQt6-sip, PyQt6-Qt6, pyqt6
Successfully installed PyQt6-Qt6-6.4.3 PyQt6-sip-13.4.1 pyqt6-6.4.2
Interestingly, installing pyqt6 on macOS M1 just works (unlike pyqt5):
PyQt6 natively supports ARM architecture, PyQt5 used to support ARM but a recent PyQt update broke the support for ARM on PyQt5.
Hey @m3nu, I got most of it to work with PyQt6. But when running the tests its failing on one and giving errors on two
FAILED tests/test_extract.py::test_selection - AttributeError: 'NoneType' object has no attribute 'checked_children'
ERROR tests/test_profile.py::test_profile_add - RuntimeError: wrapped C/C++ object of type AddProfileWindow has been deleted
ERROR tests/test_profile.py::test_profile_edit - AssertionError: previous item was not torn down properly
Any potential fix you might see on the top of your head?
Complete output:
============================================== test session starts ==============================================
platform darwin -- Python 3.10.7, pytest-7.2.2, pluggy-1.0.0 -- /Users/1tsm3ky/Desktop/TempVorta/vorta/env/bin/python3
cachedir: .pytest_cache
PyQt6 6.4.2 -- Qt runtime 6.4.3 -- Qt compiled 6.4.2
rootdir: /Users/1tsm3ky/Desktop/TempVorta/vorta, configfile: setup.cfg, testpaths: tests
plugins: qt-4.2.0, mock-3.10.0, cov-4.0.0
collected 126 items
tests/test_archives.py::test_prune_intervals qt.qpa.fonts: Populating font family aliases took 90 ms. Replace uses of missing font family "Courier" with one that exists to avoid this cost.
PASSED
tests/test_archives.py::test_repo_list PASSED
tests/test_archives.py::test_repo_prune PASSED
tests/test_archives.py::test_repo_compact PASSED
tests/test_archives.py::test_check PASSED
tests/test_archives.py::test_mount PASSED
tests/test_archives.py::test_archive_extract PASSED
tests/test_archives.py::test_archive_delete PASSED
tests/test_archives.py::test_archive_rename PASSED
tests/test_borg.py::test_borg_prune PASSED
tests/test_create.py::test_create_paths_from_command PASSED
tests/test_diff.py::test_archive_diff[diff_archives-test] PASSED
tests/test_diff.py::test_archive_diff[diff_archives_dict_issue-Users] PASSED
tests/test_diff.py::test_archive_diff_parser[changed link some/changed/link-expected0] PASSED
tests/test_diff.py::test_archive_diff_parser[ +77.8 kB -77.8 kB some/changed/file-expected1] PASSED
tests/test_diff.py::test_archive_diff_parser[ +77.8 kB -77.8 kB [-rw-rw-rw- -> -rw-r--r--] some/changed/file-expected2] PASSED
tests/test_diff.py::test_archive_diff_parser[[-rw-rw-rw- -> -rw-r--r--] some/changed/file-expected3] PASSED
tests/test_diff.py::test_archive_diff_parser[added directory some/changed/dir-expected4] PASSED
tests/test_diff.py::test_archive_diff_parser[removed directory some/changed/dir-expected5] PASSED
tests/test_diff.py::test_archive_diff_parser[[user:user -> nfsnobody:nfsnobody] home/user/arrays/test.txt-expected6] PASSED
tests/test_diff.py::test_archive_diff_parser[[a:a -> b:b] home/user/arrays/test.txt-expected7] PASSED
tests/test_diff.py::test_archive_diff_parser[ +77.8 kB -800 B [user:user -> nfsnobody:nfsnobody] [-rw-rw-rw- -> -rw-r--r--] home/user/arrays/test.txt-expected8] PASSED
tests/test_diff.py::test_archive_diff_json_parser[line0-expected0] PASSED
tests/test_diff.py::test_archive_diff_json_parser[line1-expected1] PASSED
tests/test_diff.py::test_archive_diff_json_parser[line2-expected2] PASSED
tests/test_diff.py::test_archive_diff_json_parser[line3-expected3] PASSED
tests/test_diff.py::test_archive_diff_json_parser[line4-expected4] PASSED
tests/test_diff.py::test_archive_diff_json_parser[line5-expected5] PASSED
tests/test_diff.py::test_archive_diff_json_parser[line6-expected6] PASSED
tests/test_diff.py::test_archive_diff_json_parser[line7-expected7] PASSED
tests/test_diff.py::test_archive_diff_json_parser[line8-expected8] PASSED
tests/test_diff.py::test_archive_diff_json_parser[line9-expected9] PASSED
tests/test_diff.py::test_archive_diff_json_parser[line10-expected10] PASSED
tests/test_extract.py::test_parser PASSED
tests/test_extract.py::test_selection FAILED
tests/test_import_export.py::test_import_success PASSED
tests/test_import_export.py::test_import_bootstrap_success PASSED
tests/test_import_export.py::test_import_fail_not_json PASSED
tests/test_import_export.py::test_export_success PASSED
tests/test_import_export.py::test_export_fail_unwritable PASSED
tests/test_lock.py::test_create_perm_error PASSED
tests/test_lock.py::test_create_lock PASSED
tests/test_misc.py::test_autostart PASSED
tests/test_misc.py::test_check_full_disk_access PASSED
tests/test_notifications.py::test_linux_background_notifications SKIPPED (DBus notifications only on ...)
tests/test_profile.py::test_profile_add PASSED
tests/test_profile.py::test_profile_add ERROR
tests/test_profile.py::test_profile_edit ERROR
tests/test_repo.py::test_repo_add_failures PASSED
tests/test_repo.py::test_repo_unlink PASSED
tests/test_repo.py::test_password_autofill PASSED
tests/test_repo.py::test_repo_add_success PASSED
tests/test_repo.py::test_ssh_dialog PASSED
tests/test_repo.py::test_create PASSED
tests/test_schedule.py::test_schedule_tab PASSED
tests/test_scheduler.py::test_scheduler_create_backup PASSED
tests/test_scheduler.py::test_manual_mode PASSED
tests/test_scheduler.py::test_simple_schedule PASSED
tests/test_scheduler.py::test_interval[passed_time0-now0-hours-3-added_time0-True] PASSED
tests/test_scheduler.py::test_interval[passed_time0-now0-hours-3-added_time0-False] PASSED
tests/test_scheduler.py::test_interval[passed_time1-now1-hours-20-added_time1-True] PASSED
tests/test_scheduler.py::test_interval[passed_time1-now1-hours-20-added_time1-False] PASSED
tests/test_scheduler.py::test_interval[passed_time2-now2-hours-3-added_time2-True] PASSED
tests/test_scheduler.py::test_interval[passed_time2-now2-hours-3-added_time2-False] PASSED
tests/test_scheduler.py::test_interval[passed_time3-now3-hours-3-added_time3-True] PASSED
tests/test_scheduler.py::test_interval[passed_time3-now3-hours-3-added_time3-False] PASSED
tests/test_scheduler.py::test_interval[passed_time4-now4-hours-3-added_time4-True] PASSED
tests/test_scheduler.py::test_interval[passed_time4-now4-hours-3-added_time4-False] PASSED
tests/test_scheduler.py::test_fixed[now0-15-0-passed_time0-True] PASSED
tests/test_scheduler.py::test_fixed[now0-15-0-passed_time0-False] PASSED
tests/test_scheduler.py::test_fixed[now0-15-0-passed_time1-True] PASSED
tests/test_scheduler.py::test_fixed[now0-15-0-passed_time1-False] PASSED
tests/test_scheduler.py::test_fixed[now0-15-0-passed_time2-True] PASSED
tests/test_scheduler.py::test_fixed[now0-15-0-passed_time2-False] PASSED
tests/test_scheduler.py::test_fixed[now0-15-0-passed_time3-True] PASSED
tests/test_scheduler.py::test_fixed[now0-15-0-passed_time3-False] PASSED
tests/test_scheduler.py::test_fixed[now1-3-30-passed_time0-True] PASSED
tests/test_scheduler.py::test_fixed[now1-3-30-passed_time0-False] PASSED
tests/test_scheduler.py::test_fixed[now1-3-30-passed_time1-True] PASSED
tests/test_scheduler.py::test_fixed[now1-3-30-passed_time1-False] PASSED
tests/test_scheduler.py::test_fixed[now1-3-30-passed_time2-True] PASSED
tests/test_scheduler.py::test_fixed[now1-3-30-passed_time2-False] PASSED
tests/test_scheduler.py::test_fixed[now1-3-30-passed_time3-True] PASSED
tests/test_scheduler.py::test_fixed[now1-3-30-passed_time3-False] PASSED
tests/test_source.py::test_add_folder PASSED
tests/test_treemodel.py::TestFileSystemItem::test_tuple PASSED
tests/test_treemodel.py::TestFileSystemItem::test_add PASSED
tests/test_treemodel.py::TestFileSystemItem::test_remove PASSED
tests/test_treemodel.py::TestFileSystemItem::test_get PASSED
tests/test_treemodel.py::TestFileSystemItem::test_get_subpath PASSED
tests/test_treemodel.py::TestFileTreeModel::test_basic_setup PASSED
tests/test_treemodel.py::TestFileTreeModel::test_empty_path PASSED
tests/test_treemodel.py::TestFileTreeModel::test_root PASSED
tests/test_treemodel.py::TestFileTreeModel::test_flat PASSED
tests/test_treemodel.py::TestFileTreeModel::test_simplified_tree PASSED
tests/test_utils.py::test_keyring PASSED
tests/test_utils.py::test_best_size_unit_precision0 PASSED
tests/test_utils.py::test_best_size_unit_precision1 PASSED
tests/test_utils.py::test_best_size_unit_empty PASSED
tests/test_utils.py::test_best_size_unit_precision3 PASSED
tests/test_utils.py::test_best_size_unit_nonmetric1 PASSED
tests/test_utils.py::test_best_size_unit_nonmetric2 PASSED
tests/test_utils.py::test_pretty_bytes_metric_fixed1 PASSED
tests/test_utils.py::test_pretty_bytes_metric_fixed2 PASSED
tests/test_utils.py::test_pretty_bytes_metric_fixed3 PASSED
tests/test_utils.py::test_pretty_bytes_nonmetric_fixed1 PASSED
tests/test_utils.py::test_pretty_bytes_metric_nonfixed2 PASSED
tests/test_utils.py::test_pretty_bytes_metric_large PASSED
tests/network_manager/test_darwin.py::test_is_network_metered[normal_router-False] PASSED
tests/network_manager/test_darwin.py::test_is_network_metered[phone-True] PASSED
tests/network_manager/test_darwin.py::test_get_network_devices PASSED
tests/network_manager/test_network_manager.py::test_is_network_status_available PASSED
tests/network_manager/test_network_manager.py::test_is_network_metered[NMMetered.UNKNOWN-False] PASSED
tests/network_manager/test_network_manager.py::test_is_network_metered[NMMetered.YES-True] PASSED
tests/network_manager/test_network_manager.py::test_is_network_metered[NMMetered.NO-False] PASSED
tests/network_manager/test_network_manager.py::test_is_network_metered[NMMetered.GUESS_YES-True] PASSED
tests/network_manager/test_network_manager.py::test_is_network_metered[NMMetered.GUESS_NO-False] PASSED
tests/network_manager/test_network_manager.py::test_get_current_wifi[/org/freedesktop/NetworkManager/ActiveConnection/1-802-11-wireless-type_settings0-TEST] PASSED
tests/network_manager/test_network_manager.py::test_get_current_wifi[/org/freedesktop/NetworkManager/ActiveConnection/2-802-11-ethernet-type_settings1-None] PASSED
tests/network_manager/test_network_manager.py::test_get_current_wifi_with_no_connection PASSED
tests/network_manager/test_network_manager.py::test_get_known_wifis PASSED
tests/network_manager/test_network_manager.py::test_get_known_wifis_with_never_used_connection PASSED
tests/network_manager/test_network_manager.py::test_get_known_wifis_partial_failure PASSED
tests/network_manager/test_network_manager.py::test_get_known_wifis_with_no_wifi_connections PASSED
tests/network_manager/test_network_manager.py::test_decode_ssid[ssid_bytes0-TEST] PASSED
tests/network_manager/test_network_manager.py::test_decode_ssid[ssid_bytes1-\U0001f596] PASSED
tests/network_manager/test_network_manager.py::test_decode_ssid[ssid_bytes2-\\x00\\x01\\x02\\n"'] PASSED
==================================================== ERRORS =====================================================
_____________________________________ ERROR at teardown of test_profile_add _____________________________________
item = <Function test_profile_add>
@pytest.hookimpl(hookwrapper=True, trylast=True)
def pytest_runtest_teardown(item):
"""
Hook called after each test tear down, to process any pending events and
avoiding leaking events to the next test. Also, if exceptions have
been captured during fixtures teardown, fail the test.
"""
_process_events()
> _close_widgets(item)
env/lib/python3.10/site-packages/pytestqt/plugin.py:193:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
item = <Function test_profile_add>
def _close_widgets(item):
"""
Close all widgets registered in the pytest item.
"""
widgets = getattr(item, "qt_widgets", None)
if widgets:
for w, before_close_func in item.qt_widgets:
w = w()
if w is not None:
if before_close_func is not None:
before_close_func(w)
> w.close()
E RuntimeError: wrapped C/C++ object of type AddProfileWindow has been deleted
env/lib/python3.10/site-packages/pytestqt/qtbot.py:743: RuntimeError
______________________________________ ERROR at setup of test_profile_edit ______________________________________
cls = <class '_pytest.runner.CallInfo'>, func = <function call_runtest_hook.<locals>.<lambda> at 0x13d017010>
when = 'setup', reraise = (<class '_pytest.outcomes.Exit'>, <class 'KeyboardInterrupt'>)
@classmethod
def from_call(
cls,
func: "Callable[[], TResult]",
when: "Literal['collect', 'setup', 'call', 'teardown']",
reraise: Optional[
Union[Type[BaseException], Tuple[Type[BaseException], ...]]
] = None,
) -> "CallInfo[TResult]":
"""Call func, wrapping the result in a CallInfo.
:param func:
The function to call. Called without arguments.
:param when:
The phase in which the function is called.
:param reraise:
Exception or exceptions that shall propagate if raised by the
function, instead of being wrapped in the CallInfo.
"""
excinfo = None
start = timing.time()
precise_start = timing.perf_counter()
try:
> result: Optional[TResult] = func()
env/lib/python3.10/site-packages/_pytest/runner.py:339:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
env/lib/python3.10/site-packages/_pytest/runner.py:260: in <lambda>
lambda: ihook(item=item, **kwds), when=when, reraise=reraise
env/lib/python3.10/site-packages/pluggy/_hooks.py:265: in __call__
return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult)
env/lib/python3.10/site-packages/pluggy/_manager.py:80: in _hookexec
return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
env/lib/python3.10/site-packages/_pytest/runner.py:155: in pytest_runtest_setup
item.session._setupstate.setup(item)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <_pytest.runner.SetupState object at 0x10a1e5690>, item = <Function test_profile_edit>
def setup(self, item: Item) -> None:
"""Setup objects along the collector chain to the item."""
needed_collectors = item.listchain()
# If a collector fails its setup, fail its entire subtree of items.
# The setup is not retried for each item - the same exception is used.
for col, (finalizers, exc) in self.stack.items():
> assert col in needed_collectors, "previous item was not torn down properly"
E AssertionError: previous item was not torn down properly
env/lib/python3.10/site-packages/_pytest/runner.py:483: AssertionError
=================================================== FAILURES ====================================================
________________________________________________ test_selection _________________________________________________
def test_selection():
"""Test selecting items for extraction."""
lines = [
updated("a", {}),
updated("a/b", {}),
updated("a/b/c", {}),
updated("a/b/d", {}),
updated("a/a", {}),
updated("a/a/a", {}),
updated("a/a/b", {}),
updated("a/a/c", {}),
updated("a/a/d", {}),
updated("a/a/e", {}),
updated("c", {}),
]
model = ExtractTree()
parse_json_lines(lines, model)
# Test select
ic = model.sibling(1, 0, QModelIndex())
c: FileSystemItem[FileData] = ic.internalPointer()
select(model, ic)
assert c.data.checkstate == Qt.CheckState(2)
assert c.data.checked_children == 0
# Test deselect
deselect(model, ic)
assert c.data.checkstate == Qt.CheckState(0)
assert c.data.checked_children == 0
# Test select parent as well as children
ia = model.sibling(0, 0, QModelIndex())
a: FileSystemItem[FileData] = ia.internalPointer()
aa = model.getItem(("a", "a"))
aab = model.getItem(("a", "a", "b"))
ab = model.getItem(("a", "b"))
abc = model.getItem(("a", "b", "c"))
> select(model, ia)
tests/test_extract.py:111:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/test_extract.py:65: in select
model.setData(index, Qt.CheckState.Checked, Qt.ItemDataRole.CheckStateRole)
src/vorta/views/extract_dialog.py:591: in setData
self.set_checkstate_recursively(index, value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <vorta.views.extract_dialog.ExtractTree object at 0x13d07edd0>
index = <PyQt6.QtCore.QModelIndex object at 0x139bd8a50>, value = <CheckState.Checked: 2>
def set_checkstate_recursively(self, index: QModelIndex, value: Qt.CheckState):
"""
Set the checkstate of the children of an index recursively.
Parameters
----------
index : QModelIndex
The parent index to start with.
value : Qt.CheckState
The state to set.
"""
number_children = self.rowCount(index)
if not number_children:
return
index.internalPointer().data.checked_children = 0 if value == Qt.CheckState.Unchecked else number_children
item = index.internalPointer()
for i in range(number_children):
child = index.sibling(i, 0)
child_item: ExtractFileItem = child.internalPointer()
child_item.data.checkstate = value
# set state of hidden items
parent = child_item._parent
while parent != item:
# hidden parent must have 1 child
> parent.data.checked_children = 0 if value == Qt.CheckState.Unchecked else self.rowCount(child)
E AttributeError: 'NoneType' object has no attribute 'checked_children'
src/vorta/views/extract_dialog.py:627: AttributeError
=============================================== warnings summary ================================================
tests/test_lock.py::test_create_lock
/Users/1tsm3ky/Desktop/TempVorta/vorta/env/lib/python3.10/site-packages/_pytest/threadexception.py:73: PytestUnhandledThreadExceptionWarning: Exception in thread Thread-15
Traceback (most recent call last):
File "/Users/1tsm3ky/Desktop/TempVorta/vorta/env/lib/python3.10/site-packages/peewee.py", line 3236, in execute_sql
cursor.execute(sql, params or ())
sqlite3.OperationalError: no such table: eventlogmodel
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/threading.py", line 1016, in _bootstrap_inner
self.run()
File "/Users/1tsm3ky/Desktop/TempVorta/vorta/src/vorta/borg/jobs_manager.py", line 57, in run
job.run()
File "/Users/1tsm3ky/Desktop/TempVorta/vorta/src/vorta/borg/borg_job.py", line 325, in run
log_entry.save()
File "/Users/1tsm3ky/Desktop/TempVorta/vorta/env/lib/python3.10/site-packages/playhouse/signals.py", line 71, in save
ret = super(Model, self).save(*args, **kwargs)
File "/Users/1tsm3ky/Desktop/TempVorta/vorta/env/lib/python3.10/site-packages/peewee.py", line 6745, in save
rows = self.update(**field_dict).where(self._pk_expr()).execute()
File "/Users/1tsm3ky/Desktop/TempVorta/vorta/env/lib/python3.10/site-packages/peewee.py", line 1962, in inner
return method(self, database, *args, **kwargs)
File "/Users/1tsm3ky/Desktop/TempVorta/vorta/env/lib/python3.10/site-packages/peewee.py", line 2033, in execute
return self._execute(database)
File "/Users/1tsm3ky/Desktop/TempVorta/vorta/env/lib/python3.10/site-packages/peewee.py", line 2551, in _execute
cursor = database.execute(self)
File "/Users/1tsm3ky/Desktop/TempVorta/vorta/env/lib/python3.10/site-packages/peewee.py", line 3244, in execute
return self.execute_sql(sql, params)
File "/Users/1tsm3ky/Desktop/TempVorta/vorta/env/lib/python3.10/site-packages/peewee.py", line 3234, in execute_sql
with __exception_wrapper__:
File "/Users/1tsm3ky/Desktop/TempVorta/vorta/env/lib/python3.10/site-packages/peewee.py", line 3010, in __exit__
reraise(new_type, new_type(exc_value, *exc_args), traceback)
File "/Users/1tsm3ky/Desktop/TempVorta/vorta/env/lib/python3.10/site-packages/peewee.py", line 192, in reraise
raise value.with_traceback(tb)
File "/Users/1tsm3ky/Desktop/TempVorta/vorta/env/lib/python3.10/site-packages/peewee.py", line 3236, in execute_sql
cursor.execute(sql, params or ())
peewee.OperationalError: no such table: eventlogmodel
warnings.warn(pytest.PytestUnhandledThreadExceptionWarning(msg))
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
---------- coverage: platform darwin, python 3.10.7-final-0 ----------
Name Stmts Miss Cover
-----------------------------------------------------------------
src/vorta/__init__.py 1 0 100%
src/vorta/__main__.py 43 43 0%
src/vorta/_version.py 1 0 100%
src/vorta/application.py 223 86 61%
src/vorta/autostart.py 39 19 51%
src/vorta/borg/__init__.py 0 0 100%
src/vorta/borg/_compatibility.py 10 2 80%
src/vorta/borg/borg_job.py 194 29 85%
src/vorta/borg/break_lock.py 20 1 95%
src/vorta/borg/check.py 29 4 86%
src/vorta/borg/compact.py 32 6 81%
src/vorta/borg/create.py 107 32 70%
src/vorta/borg/delete.py 36 4 89%
src/vorta/borg/diff.py 27 4 85%
src/vorta/borg/extract.py 45 33 27%
src/vorta/borg/info_archive.py 40 31 22%
src/vorta/borg/info_repo.py 41 32 22%
src/vorta/borg/init.py 30 2 93%
src/vorta/borg/jobs_manager.py 69 11 84%
src/vorta/borg/list_archive.py 22 2 91%
src/vorta/borg/list_repo.py 37 2 95%
src/vorta/borg/mount.py 33 6 82%
src/vorta/borg/prune.py 41 4 90%
src/vorta/borg/rename.py 28 3 89%
src/vorta/borg/umount.py 32 5 84%
src/vorta/borg/version.py 19 12 37%
src/vorta/config.py 13 0 100%
src/vorta/i18n/__init__.py 41 16 61%
src/vorta/keyring/__init__.py 0 0 100%
src/vorta/keyring/abc.py 41 9 78%
src/vorta/keyring/darwin.py 51 2 96%
src/vorta/keyring/db.py 30 10 67%
src/vorta/keyring/kwallet.py 51 26 49%
src/vorta/keyring/secretstorage.py 44 40 9%
src/vorta/log.py 19 14 26%
src/vorta/network_status/__init__.py 0 0 100%
src/vorta/network_status/abc.py 34 12 65%
src/vorta/network_status/darwin.py 42 12 71%
src/vorta/network_status/network_manager.py 122 43 65%
src/vorta/notifications.py 66 32 52%
src/vorta/profile_export.py 112 10 91%
src/vorta/qt_single_application.py 47 21 55%
src/vorta/scheduler.py 250 84 66%
src/vorta/store/__init__.py 0 0 100%
src/vorta/store/connection.py 41 3 93%
src/vorta/store/migrations.py 61 55 10%
src/vorta/store/models.py 125 2 98%
src/vorta/store/settings.py 13 1 92%
src/vorta/tray_menu.py 56 9 84%
src/vorta/updater.py 20 20 0%
src/vorta/utils.py 270 123 54%
src/vorta/views/__init__.py 0 0 100%
src/vorta/views/archive_tab.py 589 118 80%
src/vorta/views/diff_result.py 425 155 64%
src/vorta/views/export_window.py 56 1 98%
src/vorta/views/extract_dialog.py 306 118 61%
src/vorta/views/import_window.py 57 19 67%
src/vorta/views/main_window.py 211 51 76%
src/vorta/views/misc_tab.py 77 2 97%
src/vorta/views/partials/__init__.py 0 0 100%
src/vorta/views/partials/loading_button.py 22 1 95%
src/vorta/views/partials/tooltip_button.py 28 8 71%
src/vorta/views/partials/treemodel.py 325 56 83%
src/vorta/views/profile_add_edit_dialog.py 56 12 79%
src/vorta/views/repo_add_dialog.py 173 60 65%
src/vorta/views/repo_tab.py 210 42 80%
src/vorta/views/schedule_tab.py 142 7 95%
src/vorta/views/source_tab.py 227 57 75%
src/vorta/views/ssh_dialog.py 56 6 89%
src/vorta/views/utils.py 11 0 100%
-----------------------------------------------------------------
TOTAL 5719 1630 71%
============================================ short test summary info ============================================
FAILED tests/test_extract.py::test_selection - AttributeError: 'NoneType' object has no attribute 'checked_children'
ERROR tests/test_profile.py::test_profile_add - RuntimeError: wrapped C/C++ object of type AddProfileWindow has been deleted
ERROR tests/test_profile.py::test_profile_edit - AssertionError: previous item was not torn down properly
=================== 1 failed, 123 passed, 1 skipped, 1 warning, 2 errors in 108.32s (0:01:48) ==================
Not bad! The errors you see happen when some test threads keep running after tests have finished. Needs some care to make sure the previous test doesn't use the DB. Since we reuse the same DB. Can you share this as new PR? Then I'll have a look.
Yeah sure! I'll create a PR in a bit.
Edit: Also could you please check my PR for the White icons on MacOS issue? It changes the tray icon color based on the system tray color to have a contrast between the two.