Packages anki and aqt do not pin their requirements,
which breaks anki <= 2.1.49 because of protobuf major version bump.
While it's possible to use requirements.txt as constraints,
it might not be the best idea:
* requirements.txt can’t be used as constraints
without some careful sed’ding to remove hashes and extras;
* its location changes between versions;
* you can’t get this file for a pre-release version of Anki
since these don't get git tags;
* it’s rarely updated anyway and hence won’t reliably
produce the environment that actual Anki uses.
So use a pypi-timemachine, which prevents pip from using packages
that were uploaded after a specified date.
While the code is a tad complex, it feels slightly less hacky,
and is likely to be producing more accurate environments.
Currently, when `skip` is true and `deleteExisting` is true the `storeMediaFile` will simply delete the media file.
However, the intended behavior should be to not touch the media file when both conditions are true.
Something in Anki is setting stdout to Null.
This is a problem because Anki itself is writing to it,
particularly when printing warnings about
the deprecated methods that we are using.
This patches Anki using the same method that
the upcoming Anki 2.1.51 is using.
Environmental variables set in `setenv` also affect pip invocations.
`HOME` determines where pip is placing its cache.
Setting HOME to anything virtual env-specific means that
every virtual environment is created with its own cache.
This wastes time, data and disk space.
* Import things from `aqt.qt` not `PyQt5`/`PyQt6`
* When testing with Qt6, disable Anki's Qt5 compatibility mode
* Depend on `pytest-anki` that is also Qt version agnostic
Waitress is a WSGI server that Anki starts to serve css etc to
its web views. It seems to have a race condition issue;
the main loop thread is trying to `select.select` the sockets
which a worker thread is closing because of a dead connection.
This makes waitress skip actually closing the sockets.
Before, pressing the Browse button would only show browser
with the cards or notes corresponding to the currently edited note.
Now, it shows all cards or notes from the dialog history,
in reverse order (last seen on top),
with the currently edited note or its cards selected.
It turns out that `pytest-anki` does what we are trying to do already.
Note that `empty_anki_session_started` creates a temporary user too.
We are “overwriting“ it in `profile_created_and_loaded`
by calling `temporary_user`. It seems that doing this is safe.
The tests can be run now using `tox` against multiple Anki versions;
see instructions in `tox.ini`.
The tests depend on `pytest-anki` that had to be slightly modified
to remove the upper constraint on Anki version, as well as
to remove a few dependencies that are not essential to using it.
Previously, tests were run against Anki launched by user.
Now,
* most tests run against isolated Anki in current process;
* tests in `test_server.py` launch another Anki in a separate process
and run a few commands to test the server;
* nearly all tests were preserved in the sense that
what was being tested is tested still.
A few tests in `test_graphical.py` are skipped due to
a problem with the method tests, see the comments;
* tests can be run:
* In a single profile, using --no-tear-down-profile-after-each-test;
* In a single app instance, but with the profile being torn down
after each test--default;
* In separate processes, using --forked.
* make previewer use a more generic Adapter to flip through cards;
* return Previewer from `show_preview()` for testing,
* as well as Edit dialog from `open_dialog_and_show_note_with_id`;
* disable/enable `Edit` editor buttons more reliably;
* a few minor changes
Don't start the web server if imported not from inside Anki
Make sure Anki Connect instance is not garbage collected.
This kills the timer that's responsible for the web server.
The method was failing due to Anki API changes.
Also, make it mandatory to call the method with `cardsToo=True`,
since deleting decks on Anki >= 2.1.28 without cards is
no longer supported, and the deprecated `decks.rem()` method
on Anki >= 2.1.45 ignores keyword arguments.