Commit graph

34 commits

Author SHA1 Message Date
Sam Penny
6be8c8e2c5 Remember previous choices in reposition dialog (#1950)
* remember previous choices in reposition dialog

* remember previous choice for randomize option as well

* fix failing test
2022-07-08 11:28:38 +10:00
Damien Elmes
1939f2bfd5 Move custom study tag and limit gathering+saving into the backend
Ideally this would have been in beta 6 :-) No add-ons appear to be
using customstudy.py/taglimit.py though, so it should hopefully not be
disruptive.

In the earlier custom study changes, we didn't get around to addressing
issue #1136. Now instead of trying to determine the maximum increase
to allow (which doesn't work correctly with nested decks), we just
present the total available to the user again, and let them decide. There's
plenty of room for improvement here still, but further work here might
be better done once we look into decoupling deck limits from deck presets.

Tags and available cards are fetched prior to showing the dialog now,
and will show a progress dialog if things take a while.

Tags are stored in an aux var now, so they don't inflate the deck
object size.
2022-03-10 16:23:03 +10:00
RumovZ
cb7fdf0c8a Optionally restore original position and reset counts when forgetting (#1714)
* Add forget prompt with options

- Restore original position
- Reset reps and lapses

* Restore position when resetting for export

* Add config context to avoid passing keys

* Add routine to fetch defaults; use method-specific enum (dae)

* Keep original position by default (dae)

* Fix code completion for forget dialog (dae)

Needs to be a symbolic link to the generated file
2022-03-09 16:51:41 +10:00
RumovZ
1335c88056 Remove top_deck_id arg in deck_tree() (#1702)
Counts don't propogate correctly anymore (#1678).
2022-03-02 15:30:32 +10:00
RumovZ
de20a9ef90 Import submodules directly (#1662)
* Use submodule imports in aqt

* Use submodule imports in pylib

* More submodule imports in pylib

These required removing some direct imports to get rid of import cycles.
2022-02-13 13:40:47 +10:00
RumovZ
7a02def2c3 Backend Custom Study (#1600)
* Implement custom study on backend

* Switch frontend to backend custom study

* Skip typecheck for new pb classes

* Build tag search string on backend

Also fixes escaping of special characters in tag names.

* `cram.cards` -> `cram.card_limit`

* Assign more meaningful names in `TagLimit`

* Broaden rustfmt glob

* Use `invalid_input()` helper

* Assign `FilteredDeckForUpdate` to temp var

* Implement `SearchBuilder`

* Rewrite `custom_study()` with `SearchBuilder`

* Replace match macros with `SearchBuilder`

* Remove `into_nodes_list` & `concatenate_searches`
2022-01-20 14:25:22 +10:00
Damien Elmes
86d8ae67b8 add unbury_cards() op
https://forums.ankiweb.net/t/add-a-collection-operation-to-unbury-cards/15720
2021-12-08 09:44:47 +10:00
RumovZ
805beef792 Enable invalid-name globally in pylib (#1454) 2021-10-25 19:10:56 +10:00
RumovZ
fe514ddb30 PEP8 for rest of pylib (#1451)
* PEP8 dbproxy.py

* PEP8 errors.py

* PEP8 httpclient.py

* PEP8 lang.py

* PEP8 latex.py

* Add decorator to deprectate key words

* Make replacement for deprecated attribute optional

* Use new helper `_print_replacement_warning()`

* PEP8 media.py

* PEP8 rsbackend.py

* PEP8 sound.py

* PEP8 stdmodels.py

* PEP8 storage.py

* PEP8 sync.py

* PEP8 tags.py

* PEP8 template.py

* PEP8 types.py

* Fix DeprecatedNamesMixinForModule

The class methods need to be overridden with instance methods, so every
module has its own dicts.

* Use `# pylint: disable=invalid-name` instead of id

* PEP8 utils.py

* Only decorate `__getattr__` with `@no_type_check`

* Fix mypy issue with snakecase

Importing it from `anki._vendor` raises attribute errors.

* Format

* Remove inheritance of DeprecatedNamesMixin

There's almost no shared code now and overriding classmethods with
instance methods raises mypy issues.

* Fix traceback frames of deprecation warnings

* remove fn/TimedLog (dae)

Neither Anki nor add-ons appear to have been using it

* fix some issues with stringcase use (dae)

- the wheel was depending on the PyPI version instead of our vendored
version
- _vendor:stringcase should not have been listed in the anki py_library.
We already include the sources in py_srcs, and need to refer to them
directly. By listing _vendor:stringcase as well, we were making a
top-level stringcase library available, which would have only worked for
distributing because the wheel definition was also incorrect.
- mypy errors are what caused me to mistakenly add the above - they
were because the type: ignore at the top of stringcase.py was causing
mypy to completely ignore the file, so it was not aware of any attributes
it contained.
2021-10-25 14:50:13 +10:00
RumovZ
e37ccfdfa3 PEP8 pylib (#1443)
* PEP8 scheduler/base.py

* PEP8 _backend/__init__.py

* PEP8 _backend/genbackend.py

* PEP8 _backend/genfluent.py

* PEP8 scheduler/__init__.py

* PEP8 __init__.py

* PEP8 _legacy.py

* PEP8 syncserver/__init__.py

- Make 'ip' a good name
- Overrule `global col` being identified as a constant

* PEP8 syncserver/__main__.py

* PEP8 buildinfo.py

* Implement `DeprecatedNamesMixin` for modules

* PEP8 browser.py

* PEP8 config.py

* PEP8 consts.py

* PEP8 db.py

* Format

* Improve AttributeError for DeprecatedNamesMixin

* print the line that imported/referenced the legacy module attr (dae)

* DeprecatedNamesMixinStandalone -> ...ForModule
2021-10-22 20:39:49 +10:00
Damien Elmes
3c1729e91b run pyupgrade over codebase [python upgrade required]
This adds Python 3.9 and 3.10 typing syntax to files that import
attributions from __future___. Python 3.9 should be able to cope with
the 3.10 syntax, but Python 3.8 will no longer work.

On Windows/Mac, install the latest Python 3.9 version from python.org.
There are currently no orjson wheels for Python 3.10 on Windows/Mac,
which will break the build unless you have Rust installed separately.

On Linux, modern distros should have Python 3.9 available already. If
you're on an older distro, you'll need to build Python from source first.
2021-10-04 15:05:48 +10:00
Damien Elmes
0eab59e522 configs.proto plural workaround no longer necessary 2021-07-11 19:35:18 +10:00
Damien Elmes
2238cdaa43 rename Config in protobuf to avoid conflict with module name
+ use the enum directly, instead of wrapping it in an object

Python code retains the old "Config" name.
2021-07-11 19:27:08 +10:00
Damien Elmes
673955de5b split out sync, search, scheduler & config 2021-07-10 21:33:12 +10:00
Damien Elmes
1fb86d499d split out decks, deckconfig, notes, notetypes 2021-07-10 20:44:22 +10:00
Damien Elmes
5255409093 refactor protobuf handling for split/import
In order to split backend.proto into a more manageable size, the protobuf
handling needed to be updated. This took more time than I would have
liked, as each language handles protobuf differently:

- The Python Protobuf code ignores "package" directives, and relies
solely on how the files are laid out on disk. While it would have been
nice to keep the generated files in a private subpackage, Protobuf gets
confused if the files are located in a location that does not match
their original .proto layout, so the old approach of storing them in
_backend/ will not work. They now clutter up pylib/anki instead. I'm
rather annoyed by that, but alternatives seem to be having to add an extra
level to the Protobuf path, making the other languages suffer, or trying
to hack around the issue by munging sys.modules.
- Protobufjs fails to expose packages if they don't start with a capital
letter, despite the fact that lowercase packages are the norm in most
languages :-( This required a patch to fix.
- Rust was the easiest, as Prost is relatively straightforward compared
to Google's tools.

The Protobuf files are now stored in /proto/anki, with a separate package
for each file. I've split backend.proto into a few files as a test, but
the majority of that work is still to come.

The Python Protobuf building is a bit of a hack at the moment, hard-coding
"proto" as the top level folder, but it seems to get the job done for now.

Also changed the workspace name, as there seems to be a number of Bazel
repos moving away from the more awkward reverse DNS naming style.
2021-07-10 19:17:05 +10:00
Damien Elmes
3c46c9a7eb PEP8 decks.py 2021-06-27 14:02:48 +10:00
Damien Elmes
d89c538c48 in/out -> request/response
The saved characters weren't worth the increased difficulty when
reading, and the fact that we were deviating from protobuf norms.
2021-06-20 15:49:20 +10:00
Damien Elmes
3442ba36a9 fix 'set due date' not being remembered in browser
https://forums.ankiweb.net/t/anki-2-1-45-beta/10664/19
2021-06-16 18:50:05 +10:00
Damien Elmes
1802066afe support undo for (renamed) unbury_deck() action 2021-04-30 20:03:20 +10:00
Damien Elmes
ae7a327cae current deck change is now undoable
- make sure we set flag in changes when config var changed
- move current deck get/set into backend
- set_config() now returns a bool indicating whether a change was
made, so other operations can be gated off it
- active decks generation is deferred until sched.reset()
2021-04-06 21:52:06 +10:00
Damien Elmes
1b81653e0e update scheduling ops
- migrate to CollectionOp()
- return actual change count when suspending/burying
- add helper to convert vec to vec of newtype
2021-04-06 16:38:42 +10:00
Damien Elmes
b2bfd940e7 move filtered deck labels to backend
- use strum to generate an iterator for the protobuf enum so we don't
forget to add new labels if extending in the future
- no add-ons appear to be using dynOrderLabels(), so it has been removed

@RumovZ perhaps a similar approach might work for listing the available
browser columns as well?
2021-04-01 23:53:38 +10:00
Damien Elmes
3d11e74774 List->Sequence in a bunch of table/browser methods
Most code doesn't require a list specifically, and build a list
is an extra step.
2021-03-29 16:48:33 +10:00
Damien Elmes
6b72aaf8c2 ID -> Id in protobuf and Python
follow-up to a90d5aa359
2021-03-27 21:38:20 +10:00
Arthur Milchior
ea3b55a3a4 NF: DeckID type 2021-03-26 11:14:08 +10:00
Arthur Milchior
13710c1357 NF: CardID type 2021-03-26 11:14:08 +10:00
Damien Elmes
be9e46a9ea rework filtered deck screen & search errors
- Filtered deck creation now happens as an atomic operation, and is
undoable.
- The logic for initial search text, normalizing searches and so on
has been pushed into the backend.
- Use protobuf to pass the filtered deck to the updated dialog, so
we don't need to deal with untyped JSON.
- Change the "revise your search?" prompt to be a simple info box -
user has access to cancel and build buttons, and doesn't need a separate
prompt. Tweak the wording so the 'show excluded' button should be more
obvious.
- Filtered decks have a time appended to them instead of a number,
primarily because it's easier to implement. No objections going back to
the old behaviour if someone wants to contribute a clean patch.
The standard de-duplication will happen if two decks are created in the
same minute with the same name.
- Tweak the default sort order, and start with two searches. The UI
will still hide the second search by default, but by starting with two,
the frontend doesn't need logic for creating the starting text.
- Search errors now have their own error type, instead of using
InvalidInput, as that was intended mainly for bad API calls. The markdown
conversion is done when the error is converted from the backend, allowing
errors to printed as a string without any special handling by the calling
code.

TODO: when building a new filtered deck, update_active() is clobbering
the undo log when the overview is refreshed
2021-03-24 22:04:35 +10:00
Damien Elmes
53f8e06172 rename&simplify the deck/config type aliases
- QueueConfig is only used by the scheduler
- DeckConfig was being used in places that Config should have been used
- Add "Dict" to the name so that the bare name is free for use with a
stronger type.
2021-03-24 16:29:02 +10:00
Damien Elmes
d80ed5ff3b support undo of filtered deck build/empty 2021-03-24 12:56:06 +10:00
Damien Elmes
5c648ec4c6 make reposition undoable 2021-03-19 19:45:21 +10:00
Damien Elmes
42e20461c0 undoable ops now return changes directly; add new *_ops.py files
- Introduced a new transact() method that wraps the return value
in a separate struct that describes the changes that were made.
- Changes are now gathered from the undo log, so we don't need to
guess at what was changed - eg if update_note() is called with identical
note contents, no changes are returned. Card changes will only be set
if cards were actually generated by the update_note() call, and tag
will only be set if a new tag was added.
- mw.perform_op() has been updated to expect the op to return the changes,
or a structure with the changes in it, and it will use them to fire the
change hook, instead of fetching the changes from undo_status(), so there
is no risk of race conditions.
- the various calls to mw.perform_op() have been split into separate
files like card_ops.py. Aside from making the code cleaner, this works
around a rather annoying issue with mypy. Because we run it with
no_strict_optional, mypy is happy to accept an operation that returns None,
despite the type signature saying it requires changes to be returned.
Turning no_strict_optional on for the whole codebase is not practical
at the moment, but we can enable it for individual files.

Still todo:
- The cursor keeps moving back to the start of a field when typing -
we need to ignore the refresh hook when we are the initiator.
- The busy cursor icon should probably be delayed a few hundreds ms.
- Still need to think about a nicer way of handling saveNow()
- op_made_changes(), op_affects_study_queue() might be better embedded
as properties in the object instead
2021-03-19 19:45:21 +10:00
Damien Elmes
7f8d675e25 'set due date' now undoable 2021-03-12 14:50:31 +10:00
Damien Elmes
ab564315d8 split out common scheduler code into base.py, use scheduler/ dir
Also move the legacy aliases into a separate file
2021-03-12 14:07:52 +10:00