re-add the default to D_co

This commit is contained in:
Konstantin
2026-05-24 12:39:49 +02:00
parent b4f259fc98
commit a00158afd4
6 changed files with 28 additions and 34 deletions

View File

@@ -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")

View File

@@ -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])

View File

@@ -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):

View File

@@ -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)

View File

@@ -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

View File

@@ -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")}