Add annotation for LibModel.length property

This commit is contained in:
Šarūnas Nejus 2025-08-26 12:24:33 +01:00
parent 9ed6ca613d
commit b38a4f59c7
No known key found for this signature in database
GPG key ID: DD28F6704DBE3435
2 changed files with 14 additions and 16 deletions

View file

@ -40,6 +40,7 @@ class LibModel(dbcore.Model["Library"]):
# Config key that specifies how an instance should be formatted. # Config key that specifies how an instance should be formatted.
_format_config_key: str _format_config_key: str
path: bytes path: bytes
length: float
@cached_classproperty @cached_classproperty
def _types(cls) -> dict[str, types.Type]: def _types(cls) -> dict[str, types.Type]:
@ -617,7 +618,7 @@ class Album(LibModel):
item.try_sync(write, move) item.try_sync(write, move)
@cached_property @cached_property
def length(self) -> float: def length(self) -> float: # type: ignore[override] # still writable since we override __setattr__
"""Return the total length of all items in this album in seconds.""" """Return the total length of all items in this album in seconds."""
return sum(item.length for item in self.items()) return sum(item.length for item in self.items())

View file

@ -5,7 +5,7 @@ from __future__ import annotations
import random import random
from itertools import groupby, islice from itertools import groupby, islice
from operator import attrgetter from operator import attrgetter
from typing import TYPE_CHECKING, Any, Iterable, Sequence, Union from typing import TYPE_CHECKING, Any, Iterable
from beets.plugins import BeetsPlugin from beets.plugins import BeetsPlugin
from beets.ui import Subcommand, print_ from beets.ui import Subcommand, print_
@ -13,9 +13,7 @@ from beets.ui import Subcommand, print_
if TYPE_CHECKING: if TYPE_CHECKING:
import optparse import optparse
from beets.library import Album, Item, Library from beets.library import LibModel, Library
T = Union[Item, Album]
def random_func(lib: Library, opts: optparse.Values, args: list[str]): def random_func(lib: Library, opts: optparse.Values, args: list[str]):
@ -25,7 +23,7 @@ def random_func(lib: Library, opts: optparse.Values, args: list[str]):
# Print a random subset. # Print a random subset.
for obj in random_objs( for obj in random_objs(
objs=list(objs), objs=objs,
number=opts.number, number=opts.number,
time_minutes=opts.time, time_minutes=opts.time,
equal_chance=opts.equal_chance, equal_chance=opts.equal_chance,
@ -76,9 +74,8 @@ NOT_FOUND_SENTINEL = object()
def _equal_chance_permutation( def _equal_chance_permutation(
objs: Sequence[T], objs: Iterable[LibModel], field: str = "albumartist"
field: str = "albumartist", ) -> Iterable[LibModel]:
) -> Iterable[T]:
"""Generate (lazily) a permutation of the objects where every group """Generate (lazily) a permutation of the objects where every group
with equal values for `field` have an equal chance of appearing in with equal values for `field` have an equal chance of appearing in
any given position. any given position.
@ -86,7 +83,7 @@ def _equal_chance_permutation(
# Group the objects by artist so we can sample from them. # Group the objects by artist so we can sample from them.
key = attrgetter(field) key = attrgetter(field)
def get_attr(obj: T) -> Any: def get_attr(obj: LibModel) -> Any:
try: try:
return key(obj) return key(obj)
except AttributeError: except AttributeError:
@ -94,7 +91,7 @@ def _equal_chance_permutation(
sorted(objs, key=get_attr) sorted(objs, key=get_attr)
groups: dict[str | object, list[T]] = { groups: dict[str | object, list[LibModel]] = {
NOT_FOUND_SENTINEL: [], NOT_FOUND_SENTINEL: [],
} }
for k, values in groupby(objs, key=get_attr): for k, values in groupby(objs, key=get_attr):
@ -112,9 +109,9 @@ def _equal_chance_permutation(
def _take_time( def _take_time(
iter: Iterable[T], iter: Iterable[LibModel],
secs: float, secs: float,
) -> Iterable[T]: ) -> Iterable[LibModel]:
"""Return a list containing the first values in `iter`, which should """Return a list containing the first values in `iter`, which should
be Item or Album objects, that add up to the given amount of time in be Item or Album objects, that add up to the given amount of time in
seconds. seconds.
@ -128,12 +125,12 @@ def _take_time(
def random_objs( def random_objs(
objs: Sequence[T], objs: Iterable[LibModel],
number: int = 1, number: int = 1,
time_minutes: float | None = None, time_minutes: float | None = None,
equal_chance: bool = False, equal_chance: bool = False,
equal_chance_field: str = "albumartist", equal_chance_field: str = "albumartist",
) -> Iterable[T]: ) -> Iterable[LibModel]:
"""Get a random subset of items, optionally constrained by time or count. """Get a random subset of items, optionally constrained by time or count.
Args: Args:
@ -147,7 +144,7 @@ def random_objs(
""" """
# Permute the objects either in a straightforward way or an # Permute the objects either in a straightforward way or an
# artist-balanced way. # artist-balanced way.
perm: Iterable[T] perm: Iterable[LibModel]
if equal_chance: if equal_chance:
perm = _equal_chance_permutation(objs, field=equal_chance_field) perm = _equal_chance_permutation(objs, field=equal_chance_field)
else: else: