From a00158afd48b906adad74d082f2ee2b9dc1d3fa3 Mon Sep 17 00:00:00 2001 From: Konstantin <78656278+amogus07@users.noreply.github.com> Date: Sun, 24 May 2026 12:39:49 +0200 Subject: [PATCH] re-add the default to D_co --- beets/dbcore/db.py | 10 ++++------ beets/dbcore/query.py | 24 ++++++++++++------------ beets/dbcore/sort.py | 4 ++-- beets/library/migrations.py | 18 +++++++----------- beets/util/diff.py | 4 ++-- test/test_dbcore.py | 2 +- 6 files changed, 28 insertions(+), 34 deletions(-) diff --git a/beets/dbcore/db.py b/beets/dbcore/db.py index d33b2738d..2c7764530 100755 --- a/beets/dbcore/db.py +++ b/beets/dbcore/db.py @@ -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") diff --git a/beets/dbcore/query.py b/beets/dbcore/query.py index 5e8255740..f949c81e6 100644 --- a/beets/dbcore/query.py +++ b/beets/dbcore/query.py @@ -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]) diff --git a/beets/dbcore/sort.py b/beets/dbcore/sort.py index 476a95e4d..1b0419b47 100644 --- a/beets/dbcore/sort.py +++ b/beets/dbcore/sort.py @@ -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): diff --git a/beets/library/migrations.py b/beets/library/migrations.py index 93cf9cec9..c25d97dfd 100644 --- a/beets/library/migrations.py +++ b/beets/library/migrations.py @@ -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) diff --git a/beets/util/diff.py b/beets/util/diff.py index 38ac8c480..0a7e54929 100644 --- a/beets/util/diff.py +++ b/beets/util/diff.py @@ -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 diff --git a/test/test_dbcore.py b/test/test_dbcore.py index 23cc43aa6..f6fe1b572 100644 --- a/test/test_dbcore.py +++ b/test/test_dbcore.py @@ -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")}