use top level defs for protobuf enum cases

While mypy can understand nested references like ConfigBool.Key.COLLAPSE_RECENT,
PyCharm doesn't understand the metaclass syntax, and shows the definitions
as invalid.
This commit is contained in:
Damien Elmes 2021-02-05 19:13:55 +10:00
parent bb30e8f7bc
commit dfe3c457e5
13 changed files with 59 additions and 54 deletions

View file

@ -2,6 +2,12 @@
ignore-patterns=.*_pb2.* ignore-patterns=.*_pb2.*
persistent = no persistent = no
[TYPECHECK]
ignored-classes=
FormatTimespanIn,
UnburyCardsInCurrentDeckIn,
BuryOrSuspendCardsIn
[MESSAGES CONTROL] [MESSAGES CONTROL]
disable=C,R, disable=C,R,
fixme, fixme,

View file

@ -11,7 +11,7 @@ from anki._backend.generated import RustBackendGenerated
from anki.dbproxy import Row as DBRow from anki.dbproxy import Row as DBRow
from anki.dbproxy import ValueForDB from anki.dbproxy import ValueForDB
from anki.errors import backend_exception_to_pylib from anki.errors import backend_exception_to_pylib
from anki.lang import TR, FormatTimeSpanContext from anki.lang import TR, FormatTimeSpan
from anki.utils import from_json_bytes, to_json_bytes from anki.utils import from_json_bytes, to_json_bytes
from . import backend_pb2 as pb from . import backend_pb2 as pb
@ -88,7 +88,7 @@ class RustBackend(RustBackendGenerated):
def format_time_span( def format_time_span(
self, self,
seconds: float, seconds: float,
context: FormatTimeSpanContext.V = FormatTimeSpanContext.INTERVALS, context: FormatTimeSpan.Context.V = FormatTimeSpan.INTERVALS,
) -> str: ) -> str:
print( print(
"please use col.format_timespan() instead of col.backend.format_time_span()" "please use col.format_timespan() instead of col.backend.format_time_span()"

View file

@ -27,7 +27,7 @@ from anki.consts import *
from anki.dbproxy import DBProxy from anki.dbproxy import DBProxy
from anki.decks import DeckManager from anki.decks import DeckManager
from anki.errors import AnkiError, DBError from anki.errors import AnkiError, DBError
from anki.lang import TR, FormatTimeSpanContext from anki.lang import TR, FormatTimeSpan
from anki.media import MediaManager, media_paths_from_col_path from anki.media import MediaManager, media_paths_from_col_path
from anki.models import ModelManager from anki.models import ModelManager
from anki.notes import Note from anki.notes import Note
@ -50,11 +50,11 @@ MediaSyncProgress = _pb.MediaSyncProgress
FullSyncProgress = _pb.FullSyncProgress FullSyncProgress = _pb.FullSyncProgress
NormalSyncProgress = _pb.NormalSyncProgress NormalSyncProgress = _pb.NormalSyncProgress
DatabaseCheckProgress = _pb.DatabaseCheckProgress DatabaseCheckProgress = _pb.DatabaseCheckProgress
ConfigBoolKey = _pb.ConfigBool.Key # pylint: disable=no-member ConfigBool = _pb.ConfigBool
EmptyCardsReport = _pb.EmptyCardsReport EmptyCardsReport = _pb.EmptyCardsReport
NoteWithEmptyCards = _pb.NoteWithEmptyCards NoteWithEmptyCards = _pb.NoteWithEmptyCards
GraphPreferences = _pb.GraphPreferences GraphPreferences = _pb.GraphPreferences
BuiltinSortKind = _pb.SortOrder.Builtin.Kind # pylint: disable=no-member BuiltinSort = _pb.SortOrder.Builtin
Preferences = _pb.Preferences Preferences = _pb.Preferences
@ -117,7 +117,7 @@ class Collection:
def format_timespan( def format_timespan(
self, self,
seconds: float, seconds: float,
context: FormatTimeSpanContext.V = FormatTimeSpanContext.INTERVALS, context: FormatTimeSpan.Context.V = FormatTimeSpan.INTERVALS,
) -> str: ) -> str:
return self._backend.format_timespan(seconds=seconds, context=context) return self._backend.format_timespan(seconds=seconds, context=context)
@ -461,7 +461,7 @@ class Collection:
def find_cards( def find_cards(
self, self,
query: str, query: str,
order: Union[bool, str, BuiltinSortKind.V] = False, order: Union[bool, str, BuiltinSort.Kind.V] = False,
reverse: bool = False, reverse: bool = False,
) -> Sequence[int]: ) -> Sequence[int]:
if isinstance(order, str): if isinstance(order, str):
@ -554,9 +554,9 @@ class Collection:
term = self._backend.filter_to_search(term) term = self._backend.filter_to_search(term)
searches.append(term) searches.append(term)
if match_any: if match_any:
sep = _pb.ConcatenateSearchesIn.Separator.OR sep = _pb.ConcatenateSearchesIn.OR
else: else:
sep = _pb.ConcatenateSearchesIn.Separator.AND sep = _pb.ConcatenateSearchesIn.AND
search_string = self._backend.concatenate_searches(sep=sep, searches=searches) search_string = self._backend.concatenate_searches(sep=sep, searches=searches)
if negate: if negate:
search_string = self._backend.negate_search(search_string) search_string = self._backend.negate_search(search_string)
@ -586,10 +586,10 @@ class Collection:
"This is a debugging aid. Prefer .get_config() when you know the key you need." "This is a debugging aid. Prefer .get_config() when you know the key you need."
return from_json_bytes(self._backend.get_all_config()) return from_json_bytes(self._backend.get_all_config())
def get_config_bool(self, key: ConfigBoolKey.V) -> bool: def get_config_bool(self, key: ConfigBool.Key.V) -> bool:
return self._backend.get_config_bool(key) return self._backend.get_config_bool(key)
def set_config_bool(self, key: ConfigBoolKey.V, value: bool) -> None: def set_config_bool(self, key: ConfigBool.Key.V, value: bool) -> None:
self.setMod() self.setMod()
self._backend.set_config_bool(key=key, value=value) self._backend.set_config_bool(key=key, value=value)

View file

@ -13,7 +13,9 @@ import anki._backend.fluent_pb2 as _fluent_pb
# public exports # public exports
TR = _fluent_pb.FluentString TR = _fluent_pb.FluentString
FormatTimeSpanContext = _pb.FormatTimespanIn.Context # pylint: disable=no-member FormatTimeSpan = _pb.FormatTimespanIn
# legacy alias used by add-ons
FormatTimeSpanContext = FormatTimeSpan
langs = sorted( langs = sorted(
[ [

View file

@ -9,4 +9,4 @@
from anki.decks import DeckTreeNode from anki.decks import DeckTreeNode
from anki.errors import InvalidInput, NotFoundError from anki.errors import InvalidInput, NotFoundError
from anki.lang import FormatTimeSpanContext from anki.lang import FormatTimeSpan

View file

@ -15,16 +15,15 @@ from anki import hooks
from anki.cards import Card from anki.cards import Card
from anki.consts import * from anki.consts import *
from anki.decks import Deck, DeckConfig, DeckManager, DeckTreeNode, QueueConfig from anki.decks import Deck, DeckConfig, DeckManager, DeckTreeNode, QueueConfig
from anki.lang import FormatTimeSpanContext from anki.lang import FormatTimeSpan
from anki.notes import Note from anki.notes import Note
from anki.utils import from_json_bytes, ids2str, intTime from anki.utils import from_json_bytes, ids2str, intTime
CongratsInfo = _pb.CongratsInfoOut CongratsInfo = _pb.CongratsInfoOut
CountsForDeckToday = _pb.CountsForDeckTodayOut CountsForDeckToday = _pb.CountsForDeckTodayOut
SchedTimingToday = _pb.SchedTimingTodayOut SchedTimingToday = _pb.SchedTimingTodayOut
UnburyCurrentDeck = _pb.UnburyCardsInCurrentDeckIn
UnburyCurrentDeckMode = _pb.UnburyCardsInCurrentDeckIn.Mode # pylint:disable=no-member BuryOrSuspend = _pb.BuryOrSuspendCardsIn
BuryOrSuspendMode = _pb.BuryOrSuspendCardsIn.Mode # pylint:disable=no-member
# card types: 0=new, 1=lrn, 2=rev, 3=relrn # card types: 0=new, 1=lrn, 2=rev, 3=relrn
# queue types: 0=new, 1=(re)lrn, 2=rev, 3=day (re)lrn, # queue types: 0=new, 1=(re)lrn, 2=rev, 3=day (re)lrn,
@ -1254,7 +1253,7 @@ due = (case when odue>0 then odue else due end), odue = 0, odid = 0, usn = ? whe
ivl_secs = self.nextIvl(card, ease) ivl_secs = self.nextIvl(card, ease)
if not ivl_secs: if not ivl_secs:
return self.col.tr(TR.SCHEDULING_END) return self.col.tr(TR.SCHEDULING_END)
s = self.col.format_timespan(ivl_secs, FormatTimeSpanContext.ANSWER_BUTTONS) s = self.col.format_timespan(ivl_secs, FormatTimeSpan.ANSWER_BUTTONS)
if ivl_secs < self.col.conf["collapseTime"]: if ivl_secs < self.col.conf["collapseTime"]:
s = "<" + s s = "<" + s
return s return s
@ -1315,20 +1314,20 @@ due = (case when odue>0 then odue else due end), odue = 0, odid = 0, usn = ? whe
def unbury_cards_in_current_deck( def unbury_cards_in_current_deck(
self, self,
mode: UnburyCurrentDeckMode.V = UnburyCurrentDeckMode.ALL, mode: UnburyCurrentDeck.Mode.V = UnburyCurrentDeck.ALL,
) -> None: ) -> None:
self.col._backend.unbury_cards_in_current_deck(mode) self.col._backend.unbury_cards_in_current_deck(mode)
def suspend_cards(self, ids: Sequence[int]) -> None: def suspend_cards(self, ids: Sequence[int]) -> None:
self.col._backend.bury_or_suspend_cards( self.col._backend.bury_or_suspend_cards(
card_ids=ids, mode=BuryOrSuspendMode.SUSPEND card_ids=ids, mode=BuryOrSuspend.SUSPEND
) )
def bury_cards(self, ids: Sequence[int], manual: bool = True) -> None: def bury_cards(self, ids: Sequence[int], manual: bool = True) -> None:
if manual: if manual:
mode = BuryOrSuspendMode.BURY_USER mode = BuryOrSuspend.BURY_USER
else: else:
mode = BuryOrSuspendMode.BURY_SCHED mode = BuryOrSuspend.BURY_SCHED
self.col._backend.bury_or_suspend_cards(card_ids=ids, mode=mode) self.col._backend.bury_or_suspend_cards(card_ids=ids, mode=mode)
def bury_note(self, note: Note) -> None: def bury_note(self, note: Note) -> None:
@ -1351,11 +1350,11 @@ due = (case when odue>0 then odue else due end), odue = 0, odid = 0, usn = ? whe
"please use unbury_cards_in_current_deck() instead of unburyCardsForDeck()" "please use unbury_cards_in_current_deck() instead of unburyCardsForDeck()"
) )
if type == "all": if type == "all":
mode = UnburyCurrentDeckMode.ALL mode = UnburyCurrentDeck.ALL
elif type == "manual": elif type == "manual":
mode = UnburyCurrentDeckMode.USER_ONLY mode = UnburyCurrentDeck.USER_ONLY
else: # elif type == "siblings": else: # elif type == "siblings":
mode = UnburyCurrentDeckMode.SCHED_ONLY mode = UnburyCurrentDeck.SCHED_ONLY
self.unbury_cards_in_current_deck(mode) self.unbury_cards_in_current_deck(mode)
unsuspendCards = unsuspend_cards unsuspendCards = unsuspend_cards

View file

@ -10,7 +10,7 @@ from typing import Any, Dict, List, Optional, Sequence, Tuple, Union
import anki import anki
from anki.consts import * from anki.consts import *
from anki.lang import TR, FormatTimeSpanContext from anki.lang import TR, FormatTimeSpan
from anki.utils import ids2str from anki.utils import ids2str
# Card stats # Card stats
@ -46,7 +46,7 @@ class CardStats:
return time.strftime("%Y-%m-%d", time.localtime(tm)) return time.strftime("%Y-%m-%d", time.localtime(tm))
def time(self, tm: float) -> str: def time(self, tm: float) -> str:
return self.col.format_timespan(tm, context=FormatTimeSpanContext.PRECISE) return self.col.format_timespan(tm, context=FormatTimeSpan.PRECISE)
# Collection stats # Collection stats

View file

@ -1,7 +1,7 @@
# coding: utf-8 # coding: utf-8
import pytest import pytest
from anki.collection import BuiltinSortKind, ConfigBoolKey from anki.collection import BuiltinSort, ConfigBool
from anki.consts import * from anki.consts import *
from tests.shared import getEmptyCol, isNearCutoff from tests.shared import getEmptyCol, isNearCutoff
@ -121,16 +121,14 @@ def test_findCards():
col.flush() col.flush()
assert col.findCards("", order=True)[-1] in latestCardIds assert col.findCards("", order=True)[-1] in latestCardIds
assert col.findCards("", order=True)[0] == firstCardId assert col.findCards("", order=True)[0] == firstCardId
col.set_config_bool(ConfigBoolKey.BROWSER_SORT_BACKWARDS, True) col.set_config_bool(ConfigBool.BROWSER_SORT_BACKWARDS, True)
col.flush() col.flush()
assert col.findCards("", order=True)[0] in latestCardIds assert col.findCards("", order=True)[0] in latestCardIds
assert ( assert (
col.find_cards("", order=BuiltinSortKind.CARD_DUE, reverse=False)[0] col.find_cards("", order=BuiltinSort.CARD_DUE, reverse=False)[0] == firstCardId
== firstCardId
) )
assert ( assert (
col.find_cards("", order=BuiltinSortKind.CARD_DUE, reverse=True)[0] col.find_cards("", order=BuiltinSort.CARD_DUE, reverse=True)[0] != firstCardId
!= firstCardId
) )
# model # model
assert len(col.findCards("note:basic")) == 3 assert len(col.findCards("note:basic")) == 3

View file

@ -6,7 +6,7 @@ import time
from anki import hooks from anki import hooks
from anki.consts import * from anki.consts import *
from anki.lang import without_unicode_isolation from anki.lang import without_unicode_isolation
from anki.schedv2 import UnburyCurrentDeckMode from anki.schedv2 import UnburyCurrentDeck
from anki.utils import intTime from anki.utils import intTime
from tests.shared import getEmptyCol as getEmptyColOrig from tests.shared import getEmptyCol as getEmptyColOrig
@ -612,13 +612,13 @@ def test_bury():
col.reset() col.reset()
assert not col.sched.getCard() assert not col.sched.getCard()
col.sched.unbury_cards_in_current_deck(UnburyCurrentDeckMode.USER_ONLY) col.sched.unbury_cards_in_current_deck(UnburyCurrentDeck.USER_ONLY)
c.load() c.load()
assert c.queue == QUEUE_TYPE_NEW assert c.queue == QUEUE_TYPE_NEW
c2.load() c2.load()
assert c2.queue == QUEUE_TYPE_SIBLING_BURIED assert c2.queue == QUEUE_TYPE_SIBLING_BURIED
col.sched.unbury_cards_in_current_deck(UnburyCurrentDeckMode.SCHED_ONLY) col.sched.unbury_cards_in_current_deck(UnburyCurrentDeck.SCHED_ONLY)
c2.load() c2.load()
assert c2.queue == QUEUE_TYPE_NEW assert c2.queue == QUEUE_TYPE_NEW

View file

@ -5,7 +5,7 @@ ignore = forms,hooks_gen.py
[TYPECHECK] [TYPECHECK]
ignored-modules=win32file,pywintypes,socket,win32pipe,winrt,pyaudio ignored-modules=win32file,pywintypes,socket,win32pipe,winrt,pyaudio
ignored-classes=SearchTerm ignored-classes=SearchTerm,ConfigBool
[REPORTS] [REPORTS]
output-format=colorized output-format=colorized

View file

@ -13,7 +13,7 @@ from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union,
import aqt import aqt
import aqt.forms import aqt.forms
from anki.cards import Card from anki.cards import Card
from anki.collection import Collection, ConfigBoolKey, SearchTerm from anki.collection import Collection, ConfigBool, SearchTerm
from anki.consts import * from anki.consts import *
from anki.errors import InvalidInput from anki.errors import InvalidInput
from anki.lang import without_unicode_isolation from anki.lang import without_unicode_isolation
@ -850,13 +850,13 @@ QTableView {{ gridline-color: {grid} }}
# default to descending for non-text fields # default to descending for non-text fields
if type == "noteFld": if type == "noteFld":
ord = not ord ord = not ord
self.col.set_config_bool(ConfigBoolKey.BROWSER_SORT_BACKWARDS, ord) self.col.set_config_bool(ConfigBool.BROWSER_SORT_BACKWARDS, ord)
self.col.setMod() self.col.setMod()
self.col.save() self.col.save()
self.search() self.search()
else: else:
if self.col.get_config_bool(ConfigBoolKey.BROWSER_SORT_BACKWARDS) != ord: if self.col.get_config_bool(ConfigBool.BROWSER_SORT_BACKWARDS) != ord:
self.col.set_config_bool(ConfigBoolKey.BROWSER_SORT_BACKWARDS, ord) self.col.set_config_bool(ConfigBool.BROWSER_SORT_BACKWARDS, ord)
self.col.setMod() self.col.setMod()
self.col.save() self.col.save()
self.model.reverse() self.model.reverse()
@ -869,7 +869,7 @@ QTableView {{ gridline-color: {grid} }}
hh.setSortIndicatorShown(False) hh.setSortIndicatorShown(False)
return return
idx = self.model.activeCols.index(type) idx = self.model.activeCols.index(type)
if self.col.get_config_bool(ConfigBoolKey.BROWSER_SORT_BACKWARDS): if self.col.get_config_bool(ConfigBool.BROWSER_SORT_BACKWARDS):
ord = Qt.DescendingOrder ord = Qt.DescendingOrder
else: else:
ord = Qt.AscendingOrder ord = Qt.AscendingOrder

View file

@ -7,7 +7,7 @@ import time
from typing import Any, Callable, Optional, Tuple, Union from typing import Any, Callable, Optional, Tuple, Union
from anki.cards import Card from anki.cards import Card
from anki.collection import ConfigBoolKey from anki.collection import ConfigBool
from aqt import AnkiQt, gui_hooks from aqt import AnkiQt, gui_hooks
from aqt.qt import ( from aqt.qt import (
QAbstractItemView, QAbstractItemView,
@ -94,7 +94,7 @@ class Previewer(QDialog):
both_sides_button.setToolTip(tr(TR.ACTIONS_SHORTCUT_KEY, val="B")) both_sides_button.setToolTip(tr(TR.ACTIONS_SHORTCUT_KEY, val="B"))
self.bbox.addButton(both_sides_button, QDialogButtonBox.ActionRole) self.bbox.addButton(both_sides_button, QDialogButtonBox.ActionRole)
self._show_both_sides = self.mw.col.get_config_bool( self._show_both_sides = self.mw.col.get_config_bool(
ConfigBoolKey.PREVIEW_BOTH_SIDES ConfigBool.PREVIEW_BOTH_SIDES
) )
both_sides_button.setChecked(self._show_both_sides) both_sides_button.setChecked(self._show_both_sides)
qconnect(both_sides_button.toggled, self._on_show_both_sides) qconnect(both_sides_button.toggled, self._on_show_both_sides)
@ -221,7 +221,7 @@ class Previewer(QDialog):
def _on_show_both_sides(self, toggle: bool) -> None: def _on_show_both_sides(self, toggle: bool) -> None:
self._show_both_sides = toggle self._show_both_sides = toggle
self.mw.col.set_config_bool(ConfigBoolKey.PREVIEW_BOTH_SIDES, toggle) self.mw.col.set_config_bool(ConfigBool.PREVIEW_BOTH_SIDES, toggle)
self.mw.col.setMod() self.mw.col.setMod()
if self._state == "answer" and not toggle: if self._state == "answer" and not toggle:
self._state = "question" self._state = "question"

View file

@ -9,7 +9,7 @@ from enum import Enum, auto
from typing import Any, Dict, Iterable, List, Optional, Sequence, Tuple, cast from typing import Any, Dict, Iterable, List, Optional, Sequence, Tuple, cast
import aqt import aqt
from anki.collection import ConfigBoolKey, SearchTerm from anki.collection import ConfigBool, SearchTerm
from anki.decks import DeckTreeNode from anki.decks import DeckTreeNode
from anki.errors import DeckRenameError, InvalidInput from anki.errors import DeckRenameError, InvalidInput
from anki.tags import TagTreeNode from anki.tags import TagTreeNode
@ -526,7 +526,7 @@ class SidebarTreeView(QTreeView):
root: SidebarItem, root: SidebarItem,
name: TR.V, name: TR.V,
icon: Union[str, ColoredIcon], icon: Union[str, ColoredIcon],
collapse_key: ConfigBoolKey.V, collapse_key: ConfigBool.Key.V,
type: Optional[SidebarItemType] = None, type: Optional[SidebarItemType] = None,
) -> SidebarItem: ) -> SidebarItem:
def update(expanded: bool) -> None: def update(expanded: bool) -> None:
@ -557,7 +557,7 @@ class SidebarTreeView(QTreeView):
root=root, root=root,
name=TR.BROWSING_SIDEBAR_SAVED_SEARCHES, name=TR.BROWSING_SIDEBAR_SAVED_SEARCHES,
icon=icon, icon=icon,
collapse_key=ConfigBoolKey.COLLAPSE_SAVED_SEARCHES, collapse_key=ConfigBool.COLLAPSE_SAVED_SEARCHES,
type=SidebarItemType.SAVED_SEARCH_ROOT, type=SidebarItemType.SAVED_SEARCH_ROOT,
) )
@ -584,7 +584,7 @@ class SidebarTreeView(QTreeView):
root=root, root=root,
name=TR.BROWSING_SIDEBAR_RECENT, name=TR.BROWSING_SIDEBAR_RECENT,
icon=icon, icon=icon,
collapse_key=ConfigBoolKey.COLLAPSE_RECENT, collapse_key=ConfigBool.COLLAPSE_RECENT,
type=SidebarItemType.FLAG_ROOT, type=SidebarItemType.FLAG_ROOT,
) )
type = SidebarItemType.FLAG type = SidebarItemType.FLAG
@ -646,7 +646,7 @@ class SidebarTreeView(QTreeView):
root=root, root=root,
name=TR.BROWSING_SIDEBAR_CARD_STATE, name=TR.BROWSING_SIDEBAR_CARD_STATE,
icon=icon, icon=icon,
collapse_key=ConfigBoolKey.COLLAPSE_CARD_STATE, collapse_key=ConfigBool.COLLAPSE_CARD_STATE,
type=SidebarItemType.CARD_STATE_ROOT, type=SidebarItemType.CARD_STATE_ROOT,
) )
type = SidebarItemType.CARD_STATE type = SidebarItemType.CARD_STATE
@ -693,7 +693,7 @@ class SidebarTreeView(QTreeView):
root=root, root=root,
name=TR.BROWSING_SIDEBAR_FLAGS, name=TR.BROWSING_SIDEBAR_FLAGS,
icon=icon, icon=icon,
collapse_key=ConfigBoolKey.COLLAPSE_FLAGS, collapse_key=ConfigBool.COLLAPSE_FLAGS,
type=SidebarItemType.FLAG_ROOT, type=SidebarItemType.FLAG_ROOT,
) )
type = SidebarItemType.FLAG type = SidebarItemType.FLAG
@ -771,7 +771,7 @@ class SidebarTreeView(QTreeView):
root=root, root=root,
name=TR.BROWSING_SIDEBAR_TAGS, name=TR.BROWSING_SIDEBAR_TAGS,
icon=icon, icon=icon,
collapse_key=ConfigBoolKey.COLLAPSE_TAGS, collapse_key=ConfigBool.COLLAPSE_TAGS,
type=SidebarItemType.TAG_ROOT, type=SidebarItemType.TAG_ROOT,
) )
render(root, tree.children) render(root, tree.children)
@ -810,7 +810,7 @@ class SidebarTreeView(QTreeView):
root=root, root=root,
name=TR.BROWSING_SIDEBAR_DECKS, name=TR.BROWSING_SIDEBAR_DECKS,
icon=icon, icon=icon,
collapse_key=ConfigBoolKey.COLLAPSE_DECKS, collapse_key=ConfigBool.COLLAPSE_DECKS,
type=SidebarItemType.DECK_ROOT, type=SidebarItemType.DECK_ROOT,
) )
render(root, tree.children) render(root, tree.children)
@ -824,7 +824,7 @@ class SidebarTreeView(QTreeView):
root=root, root=root,
name=TR.BROWSING_SIDEBAR_NOTETYPES, name=TR.BROWSING_SIDEBAR_NOTETYPES,
icon=icon, icon=icon,
collapse_key=ConfigBoolKey.COLLAPSE_NOTETYPES, collapse_key=ConfigBool.COLLAPSE_NOTETYPES,
type=SidebarItemType.NOTETYPE_ROOT, type=SidebarItemType.NOTETYPE_ROOT,
) )