Skip to content

Commit 68c3db0

Browse files
committed
refactor ui to fix import cycle and continue adding type annotations
1 parent 5f3dd17 commit 68c3db0

File tree

15 files changed

+1913
-1643
lines changed

15 files changed

+1913
-1643
lines changed

beets/dbcore/db.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ def _queries(cls) -> dict[str, type[Query]]:
322322
@cached_classproperty
323323
def _relation(cls) -> type[Model[D]]:
324324
"""The model that this model is closely related to."""
325-
return cls
325+
return cls # type: ignore[return-value]
326326

327327
@cached_classproperty
328328
def relation_join(cls) -> str:
@@ -419,15 +419,15 @@ def _check_db(self, need_id: bool = True) -> D:
419419

420420
return self._db
421421

422-
def copy(self) -> Model:
422+
def copy(self) -> Model[D]:
423423
"""Create a copy of the model object.
424424
425425
The field values and other state is duplicated, but the new copy
426426
remains associated with the same database as the old object.
427427
(A simple `copy.deepcopy` will not work because it would try to
428428
duplicate the SQLite connection.)
429429
"""
430-
new = self.__class__()
430+
new: Model[D] = type(self)()
431431
new._db = self._db
432432
new._values_fixed = self._values_fixed.copy()
433433
new._values_flex = self._values_flex.copy()
@@ -535,7 +535,7 @@ def update(self, values):
535535
for key, value in values.items():
536536
self[key] = value
537537

538-
def items(self) -> Iterator[tuple[str, Any]]:
538+
def items(self) -> Iterator[tuple[str, AnyModel]]:
539539
"""Iterate over (key, value) pairs that this object contains.
540540
Computed fields are not included.
541541
"""
@@ -1013,7 +1013,7 @@ class Database:
10131013
data is written in a transaction.
10141014
"""
10151015

1016-
def __init__(self, path, timeout: float = 5.0):
1016+
def __init__(self, path: bytes | str, timeout: float | int = 5.0) -> None:
10171017
if sqlite3.threadsafety == 0:
10181018
raise RuntimeError(
10191019
"sqlite3 must be compiled with multi-threading support"
@@ -1026,8 +1026,8 @@ def __init__(self, path, timeout: float = 5.0):
10261026
if hasattr(sqlite3, "enable_callback_tracebacks"):
10271027
sqlite3.enable_callback_tracebacks(True)
10281028

1029-
self.path = path
1030-
self.timeout = timeout
1029+
self.path: bytes | str = path
1030+
self.timeout: float = float(timeout)
10311031

10321032
self._connections: dict[int, sqlite3.Connection] = {}
10331033
self._tx_stacks: defaultdict[int, list[Transaction]] = defaultdict(list)

beets/dbcore/queryparse.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,12 @@
4040

4141
PARSE_QUERY_PART_REGEX = re.compile(
4242
# Non-capturing optional segment for the keyword.
43-
r"(-|\^)?" # Negation prefixes. # noqa: ISC003
44-
+ r"(?:"
45-
+ r"(\S+?)" # The field key.
46-
+ r"(?<!\\):" # Unescaped :
47-
+ r")?"
48-
+ r"(.*)", # The term itself.
43+
r"(-|\^)?" # Negation prefixes.
44+
r"(?:"
45+
r"(\S+?)" # The field key.
46+
r"(?<!\\):" # Unescaped :
47+
r")?"
48+
r"(.*)", # The term itself.
4949
re.I, # Case-insensitive.
5050
)
5151

beets/library/library.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,12 @@
1313
from .queries import PF_KEY_DEFAULT, parse_query_parts, parse_query_string
1414

1515
if TYPE_CHECKING:
16+
from collections.abc import Iterable
17+
from re import Pattern
18+
1619
from beets.dbcore import Results
1720
from beets.dbcore.query import Query, Sort
21+
from beets.util.functemplate import Template
1822

1923
if not sys.version_info < (3, 12):
2024
pass # pyright: ignore[reportUnreachable]
@@ -29,18 +33,20 @@ class Library(dbcore.Database):
2933

3034
def __init__(
3135
self,
32-
path="library.blb",
36+
path: bytes | str = "library.blb",
3337
directory: str | None = None,
34-
path_formats=((PF_KEY_DEFAULT, "$artist/$album/$track $title"),),
35-
replacements=None,
36-
):
37-
timeout = beets.config["timeout"].as_number()
38+
path_formats: Iterable[tuple[str, str | Template]] = (
39+
(PF_KEY_DEFAULT, "$artist/$album/$track $title"),
40+
),
41+
replacements: list[tuple[Pattern[str], str]] | None = None,
42+
) -> None:
43+
timeout: int | float = beets.config["timeout"].as_number()
3844
super().__init__(path, timeout=timeout)
3945

4046
self.directory = normpath(directory or platformdirs.user_music_path())
4147

42-
self.path_formats = path_formats
43-
self.replacements = replacements
48+
self.path_formats: Iterable[tuple[str, str | Template]] = path_formats
49+
self.replacements: list[tuple[Pattern[str], str]] | None = replacements
4450

4551
# Used for template substitution performance.
4652
self._memotable: dict[tuple[str, ...], str] = {}
@@ -91,7 +97,7 @@ def _fetch(
9197
model_cls: type[AnyLibModel],
9298
query: list[str] | Query | str | tuple[str] | None = None,
9399
sort: Sort | None = None,
94-
) -> Results[AnyLibModel]:
100+
) -> Results[AnyLibModel, dbcore.Database]:
95101
"""Parse a query and fetch.
96102
97103
If an order specification is present in the query string

beets/library/models.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,9 +1206,9 @@ def move(
12061206

12071207
def destination(
12081208
self,
1209-
relative_to_libdir=False,
1210-
basedir=None,
1211-
path_formats=None,
1209+
relative_to_libdir: bool = False,
1210+
basedir: bytes | None = None,
1211+
path_formats: Iterable[tuple[str, str | Template]] | None = None,
12121212
) -> bytes:
12131213
"""Return the path in the library directory designated for the item
12141214
(i.e., where the file ought to be).
@@ -1218,12 +1218,14 @@ def destination(
12181218
is true, returns just the fragment of the path underneath the library
12191219
base directory.
12201220
"""
1221-
db = self._check_db()
1221+
db: Library = self._check_db()
12221222
basedir = basedir or db.directory
12231223
path_formats = path_formats or db.path_formats
12241224

12251225
# Use a path format based on a query, falling back on the
12261226
# default.
1227+
query: str | Query
1228+
path_format: Template | str
12271229
for query, path_format in path_formats:
12281230
if query == PF_KEY_DEFAULT:
12291231
continue

beets/library/queries.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import beets
77
from beets import dbcore, logging, plugins
8+
from beets.util import PathLike
89

910
if TYPE_CHECKING:
1011
from typing_extensions import LiteralString
@@ -59,7 +60,7 @@ def parse_query_parts(
5960

6061

6162
def parse_query_string(
62-
s: str, model_cls: type[LibModel]
63+
s: PathLike, model_cls: type[LibModel]
6364
) -> tuple[dbcore.Query, Sort]:
6465
"""Given a beets query string, return the `Query` and `Sort` they
6566
represent.

beets/metadata_plugins.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
from confuse import NotFoundError
1717
from typing_extensions import NotRequired
1818

19-
from beets.util import cached_classproperty
2019
from beets.util.id_extractors import extract_release_id
2120

2221
from .plugins import BeetsPlugin, find_plugins, notify_info_yielded, send
@@ -95,15 +94,12 @@ class MetadataSourcePlugin(BeetsPlugin, metaclass=abc.ABCMeta):
9594
and tracks, and to retrieve album and track information by ID.
9695
"""
9796

98-
DEFAULT_DATA_SOURCE_MISMATCH_PENALTY = 0.5
97+
DEFAULT_DATA_SOURCE_MISMATCH_PENALTY: float = 0.5
98+
data_source: str = NotImplemented
99+
"""The data source name for this plugin.
99100
100-
@cached_classproperty
101-
def data_source(cls) -> str:
102-
"""The data source name for this plugin.
103-
104-
This is inferred from the plugin name.
105-
"""
106-
return cls.__name__.replace("Plugin", "") # type: ignore[attr-defined]
101+
This is inferred from the plugin name.
102+
"""
107103

108104
@cached_property
109105
def data_source_mismatch_penalty(self) -> float:
@@ -112,15 +108,19 @@ def data_source_mismatch_penalty(self) -> float:
112108
except NotFoundError:
113109
return self.config["data_source_mismatch_penalty"].as_number()
114110

115-
def __init__(self, *args, **kwargs) -> None:
116-
super().__init__(*args, **kwargs)
111+
def __init__(self, name: str | None = None) -> None:
112+
super().__init__(name)
117113
self.config.add(
118114
{
119115
"search_limit": 5,
120116
"data_source_mismatch_penalty": self.DEFAULT_DATA_SOURCE_MISMATCH_PENALTY, # noqa: E501
121117
}
122118
)
123119

120+
def __init_subclass__(cls) -> None:
121+
super().__init_subclass__()
122+
cls.data_source = cls.__name__.replace("Plugin", "") # type: ignore[attr-defined]
123+
124124
@abc.abstractmethod
125125
def album_for_id(self, album_id: str) -> AlbumInfo | None:
126126
"""Return :py:class:`AlbumInfo` object or None if no matching release was

beets/plugins.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,14 @@
3333

3434
import beets
3535
from beets import logging
36-
from beets.dbcore import Query
3736
from beets.util import unique_list
3837

3938
if TYPE_CHECKING:
4039
from collections.abc import Callable, Iterable, Sequence
4140

4241
from confuse import ConfigView
4342

44-
from beets.dbcore import Type
43+
from beets.dbcore import Query, Type
4544
from beets.dbcore.queryparse import Prefixes
4645
from beets.importer import ImportSession, ImportTask
4746
from beets.library import Album, Item, Library

0 commit comments

Comments
 (0)