mirror of
https://github.com/beetbox/beets.git
synced 2026-07-16 19:00:49 -04:00
re-add the default to D_co
This commit is contained in:
@@ -68,7 +68,7 @@ if TYPE_CHECKING:
|
||||
from .query import FieldQueryType, Query, SQLiteType
|
||||
from .sort import FieldSort, Sort
|
||||
|
||||
D_co = TypeVar("D_co", bound="Database", covariant=True)
|
||||
D_co = TypeVar("D_co", bound="Database", covariant=True, default="Database")
|
||||
|
||||
FlexAttrs = dict[str, str]
|
||||
|
||||
@@ -788,7 +788,7 @@ class Model(ABC, Generic[D_co]):
|
||||
# Database controller and supporting interfaces.
|
||||
|
||||
|
||||
AnyModel = TypeVar("AnyModel", bound=Model["Database"])
|
||||
AnyModel = TypeVar("AnyModel", bound=Model)
|
||||
|
||||
|
||||
class Results(Generic[AnyModel]):
|
||||
@@ -1122,13 +1122,11 @@ class Database:
|
||||
the backend.
|
||||
"""
|
||||
|
||||
_models: Sequence[type[Model[Database]]] = ()
|
||||
_models: Sequence[type[Model]] = ()
|
||||
"""The Model subclasses representing tables in this database.
|
||||
"""
|
||||
|
||||
_migrations: Sequence[
|
||||
tuple[type[Migration[Database]], Sequence[type[Model[Database]]]]
|
||||
] = ()
|
||||
_migrations: Sequence[tuple[type[Migration], Sequence[type[Model]]]] = ()
|
||||
"""Migrations that are to be performed for the configured models."""
|
||||
|
||||
supports_extensions = hasattr(sqlite3.Connection, "enable_load_extension")
|
||||
|
||||
@@ -35,7 +35,7 @@ from . import pathutils
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Iterator, MutableSequence
|
||||
|
||||
from beets.dbcore.db import Database, Model
|
||||
from beets.dbcore.db import Model
|
||||
|
||||
P = TypeVar("P", default=Any)
|
||||
else:
|
||||
@@ -103,7 +103,7 @@ class Query(ABC):
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def match(self, obj: Model[Database]):
|
||||
def match(self, obj: Model):
|
||||
"""Check whether this query matches a given Model. Can be used to
|
||||
perform queries on arbitrary sets of Model.
|
||||
"""
|
||||
@@ -170,7 +170,7 @@ class FieldQuery(Query, Generic[P]):
|
||||
"""Determine whether the value matches the pattern."""
|
||||
raise NotImplementedError
|
||||
|
||||
def match(self, obj: Model[Database]) -> bool:
|
||||
def match(self, obj: Model) -> bool:
|
||||
return self.value_match(self.pattern, obj.get(self.field_name))
|
||||
|
||||
def __repr__(self) -> str:
|
||||
@@ -212,7 +212,7 @@ class NoneQuery(FieldQuery[None]):
|
||||
def col_clause(self) -> tuple[str, Sequence[SQLiteType]]:
|
||||
return f"{self.field} IS NULL", ()
|
||||
|
||||
def match(self, obj: Model[Database]) -> bool:
|
||||
def match(self, obj: Model) -> bool:
|
||||
return obj.get(self.field_name) is None
|
||||
|
||||
def __repr__(self) -> str:
|
||||
@@ -342,7 +342,7 @@ class PathQuery(FieldQuery[bytes]):
|
||||
and os.path.exists(util.normpath(query_part))
|
||||
)
|
||||
|
||||
def match(self, obj: Model[Database]) -> bool:
|
||||
def match(self, obj: Model) -> bool:
|
||||
"""Check whether a model object's path matches this query.
|
||||
|
||||
Performs either an exact match against the pattern or checks if the path
|
||||
@@ -468,7 +468,7 @@ class NumericQuery(FieldQuery[str]):
|
||||
self.rangemin = self._convert(parts[0])
|
||||
self.rangemax = self._convert(parts[1])
|
||||
|
||||
def match(self, obj: Model[Database]) -> bool:
|
||||
def match(self, obj: Model) -> bool:
|
||||
if self.field_name not in obj:
|
||||
return False
|
||||
value = obj[self.field_name]
|
||||
@@ -601,7 +601,7 @@ class AndQuery(MutableCollectionQuery):
|
||||
def clause(self) -> tuple[str | None, Sequence[SQLiteType]]:
|
||||
return self.clause_with_joiner("and")
|
||||
|
||||
def match(self, obj: Model[Database]) -> bool:
|
||||
def match(self, obj: Model) -> bool:
|
||||
return all(q.match(obj) for q in self.subqueries)
|
||||
|
||||
|
||||
@@ -611,7 +611,7 @@ class OrQuery(MutableCollectionQuery):
|
||||
def clause(self) -> tuple[str | None, Sequence[SQLiteType]]:
|
||||
return self.clause_with_joiner("or")
|
||||
|
||||
def match(self, obj: Model[Database]) -> bool:
|
||||
def match(self, obj: Model) -> bool:
|
||||
return any(q.match(obj) for q in self.subqueries)
|
||||
|
||||
|
||||
@@ -637,7 +637,7 @@ class NotQuery(Query):
|
||||
# is handled by match() for slow queries.
|
||||
return clause, subvals
|
||||
|
||||
def match(self, obj: Model[Database]) -> bool:
|
||||
def match(self, obj: Model) -> bool:
|
||||
return not self.subquery.match(obj)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
@@ -656,7 +656,7 @@ class TrueQuery(Query):
|
||||
def clause(self) -> tuple[str, Sequence[SQLiteType]]:
|
||||
return "1", ()
|
||||
|
||||
def match(self, obj: Model[Database]) -> bool:
|
||||
def match(self, obj: Model) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
@@ -666,7 +666,7 @@ class FalseQuery(Query):
|
||||
def clause(self) -> tuple[str, Sequence[SQLiteType]]:
|
||||
return "0", ()
|
||||
|
||||
def match(self, obj: Model[Database]) -> bool:
|
||||
def match(self, obj: Model) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
@@ -856,7 +856,7 @@ class DateQuery(FieldQuery[str]):
|
||||
start, end = _parse_periods(pattern)
|
||||
self.interval = DateInterval.from_periods(start, end)
|
||||
|
||||
def match(self, obj: Model[Database]) -> bool:
|
||||
def match(self, obj: Model) -> bool:
|
||||
if self.field_name not in obj:
|
||||
return False
|
||||
timestamp = float(obj[self.field_name])
|
||||
|
||||
@@ -18,7 +18,7 @@ from __future__ import annotations
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from beets.dbcore.db import AnyModel, Database, Model
|
||||
from beets.dbcore.db import AnyModel, Model
|
||||
|
||||
|
||||
class Sort:
|
||||
@@ -128,7 +128,7 @@ class FieldSort(Sort):
|
||||
# comparisons with None fail. We should also support flexible
|
||||
# attributes with different types without falling over.
|
||||
|
||||
def key(obj: Model[Database]) -> Any:
|
||||
def key(obj: Model) -> Any:
|
||||
field_val = obj.get(self.field, None)
|
||||
if field_val is None:
|
||||
if _type := obj._types.get(self.field):
|
||||
|
||||
@@ -20,7 +20,7 @@ if TYPE_CHECKING:
|
||||
from beets.library import Library
|
||||
|
||||
|
||||
class MultiValueFieldMigration(Migration["Library"]):
|
||||
class MultiValueFieldMigration(Migration):
|
||||
"""Backfill multi-valued field from legacy single-string values."""
|
||||
|
||||
str_field: ClassVar[str]
|
||||
@@ -39,7 +39,7 @@ class MultiValueFieldMigration(Migration["Library"]):
|
||||
return str_value
|
||||
|
||||
def _migrate_data(
|
||||
self, model_cls: type[Model[Library]], current_fields: set[str]
|
||||
self, model_cls: type[Model], current_fields: set[str]
|
||||
) -> None:
|
||||
"""Migrate legacy single-valued field to multi-valued field."""
|
||||
str_field, list_field = self.str_field, self.list_field
|
||||
@@ -136,14 +136,12 @@ class LyricsRow(NamedTuple):
|
||||
lyrics: str
|
||||
|
||||
|
||||
class LyricsMetadataInFlexFieldsMigration(Migration["Library"]):
|
||||
class LyricsMetadataInFlexFieldsMigration(Migration):
|
||||
"""Move legacy inline lyrics metadata into dedicated flexible fields."""
|
||||
|
||||
CHUNK_SIZE = 100
|
||||
|
||||
def _migrate_data(
|
||||
self, model_cls: type[Model[Library]], _: set[str]
|
||||
) -> None:
|
||||
def _migrate_data(self, model_cls: type[Model], _: set[str]) -> None:
|
||||
"""Migrate legacy lyrics to move metadata to flex attributes."""
|
||||
table = model_cls._table
|
||||
flex_table = model_cls._flex_table
|
||||
@@ -220,14 +218,12 @@ class LyricsMetadataInFlexFieldsMigration(Migration["Library"]):
|
||||
ui.print_(f"Migration complete: {migrated} of {total} {table} updated")
|
||||
|
||||
|
||||
class RelativePathMigration(Migration["Library"]):
|
||||
class RelativePathMigration(Migration):
|
||||
"""Migrate path field to contain value relative to the music directory."""
|
||||
|
||||
db: Library
|
||||
|
||||
def _migrate_field(
|
||||
self, model_cls: type[Model[Library]], field: str
|
||||
) -> None:
|
||||
def _migrate_field(self, model_cls: type[Model], field: str) -> None:
|
||||
table = model_cls._table
|
||||
|
||||
with self.db.transaction() as tx:
|
||||
@@ -261,7 +257,7 @@ class RelativePathMigration(Migration["Library"]):
|
||||
)
|
||||
|
||||
def _migrate_data(
|
||||
self, model_cls: type[Model[Library]], current_fields: set[str]
|
||||
self, model_cls: type[Model], current_fields: set[str]
|
||||
) -> None:
|
||||
for field in {"path", "artpath"} & current_fields:
|
||||
self._migrate_field(model_cls, field)
|
||||
|
||||
@@ -8,7 +8,7 @@ from .color import colorize
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Iterable
|
||||
|
||||
from beets.dbcore.db import Database, FormattedMapping
|
||||
from beets.dbcore.db import FormattedMapping
|
||||
from beets.library.models import LibModel
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ def _multi_value_diff(field: str, oldset: set[str], newset: set[str]) -> str:
|
||||
|
||||
|
||||
def _field_diff(
|
||||
field: str, old: FormattedMapping[Database], new: FormattedMapping[Database]
|
||||
field: str, old: FormattedMapping, new: FormattedMapping
|
||||
) -> str | None:
|
||||
"""Given two Model objects and their formatted views, format their values
|
||||
for `field` and highlight changes among them. Return a human-readable
|
||||
|
||||
@@ -154,7 +154,7 @@ class DatabaseFixtureTwoModels(dbcore.Database):
|
||||
_models = (ModelFixture2, AnotherModelFixture)
|
||||
|
||||
|
||||
class ModelFixtureWithGetters(dbcore.Model[dbcore.Database]):
|
||||
class ModelFixtureWithGetters(dbcore.Model):
|
||||
@classmethod
|
||||
def _getters(cls):
|
||||
return {"aComputedField": (lambda s: "thing")}
|
||||
|
||||
Reference in New Issue
Block a user