Anki/pylib/anki/stdmodels.py
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

122 lines
3.6 KiB
Python

# Copyright: Ankitects Pty Ltd and contributors
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
# pylint: enable=invalid-name
from __future__ import annotations
from typing import Any, Callable, no_type_check
import anki.collection
import anki.models
from anki import notetypes_pb2
from anki._legacy import DeprecatedNamesMixinForModule
from anki.utils import from_json_bytes
# pylint: disable=no-member
StockNotetypeKind = notetypes_pb2.StockNotetype.Kind
# add-on authors can add ("note type name", function)
# to this list to have it shown in the add/clone note type screen
models: list[tuple] = []
def _get_stock_notetype(
col: anki.collection.Collection, kind: StockNotetypeKind.V
) -> anki.models.NotetypeDict:
return from_json_bytes(col._backend.get_stock_notetype_legacy(kind))
def get_stock_notetypes(
col: anki.collection.Collection,
) -> list[tuple[str, Callable[[anki.collection.Collection], anki.models.NotetypeDict]]]:
out: list[
tuple[str, Callable[[anki.collection.Collection], anki.models.NotetypeDict]]
] = []
# add standard
for kind in [
StockNotetypeKind.BASIC,
StockNotetypeKind.BASIC_TYPING,
StockNotetypeKind.BASIC_AND_REVERSED,
StockNotetypeKind.BASIC_OPTIONAL_REVERSED,
StockNotetypeKind.CLOZE,
]:
note_type = from_json_bytes(col._backend.get_stock_notetype_legacy(kind))
def instance_getter(
model: Any,
) -> Callable[[anki.collection.Collection], anki.models.NotetypeDict]:
return lambda col: model
out.append((note_type["name"], instance_getter(note_type)))
# add extras from add-ons
for (name_or_func, func) in models:
if not isinstance(name_or_func, str):
name = name_or_func()
else:
name = name_or_func
out.append((name, func))
return out
#
# Legacy functions that added the notetype before returning it
#
def _legacy_add_basic_model(
col: anki.collection.Collection,
) -> anki.models.NotetypeDict:
note_type = _get_stock_notetype(col, StockNotetypeKind.BASIC)
col.models.add(note_type)
return note_type
def _legacy_add_basic_typing_model(
col: anki.collection.Collection,
) -> anki.models.NotetypeDict:
note_type = _get_stock_notetype(col, StockNotetypeKind.BASIC_TYPING)
col.models.add(note_type)
return note_type
def _legacy_add_forward_reverse(
col: anki.collection.Collection,
) -> anki.models.NotetypeDict:
note_type = _get_stock_notetype(col, StockNotetypeKind.BASIC_AND_REVERSED)
col.models.add(note_type)
return note_type
def _legacy_add_forward_optional_reverse(
col: anki.collection.Collection,
) -> anki.models.NotetypeDict:
note_type = _get_stock_notetype(col, StockNotetypeKind.BASIC_OPTIONAL_REVERSED)
col.models.add(note_type)
return note_type
def _legacy_add_cloze_model(
col: anki.collection.Collection,
) -> anki.models.NotetypeDict:
note_type = _get_stock_notetype(col, StockNotetypeKind.CLOZE)
col.models.add(note_type)
return note_type
_deprecated_names = DeprecatedNamesMixinForModule(globals())
_deprecated_names.register_deprecated_attributes(
addBasicModel=(_legacy_add_basic_model, get_stock_notetypes),
addBasicTypingModel=(_legacy_add_basic_typing_model, get_stock_notetypes),
addForwardReverse=(_legacy_add_forward_reverse, get_stock_notetypes),
addForwardOptionalReverse=(
_legacy_add_forward_optional_reverse,
get_stock_notetypes,
),
addClozeModel=(_legacy_add_cloze_model, get_stock_notetypes),
)
@no_type_check
def __getattr__(name: str) -> Any:
return _deprecated_names.__getattr__(name)