diff --git a/beets/autotag/__init__.py b/beets/autotag/__init__.py index 319f7f522..8fa5a6864 100644 --- a/beets/autotag/__init__.py +++ b/beets/autotag/__init__.py @@ -18,7 +18,7 @@ from __future__ import annotations import warnings from importlib import import_module -from typing import TYPE_CHECKING, Union +from typing import TYPE_CHECKING from beets import config, logging @@ -117,8 +117,8 @@ SPECIAL_FIELDS = { def _apply_metadata( - info: Union[AlbumInfo, TrackInfo], - db_obj: Union[Album, Item], + info: AlbumInfo | TrackInfo, + db_obj: Album | Item, nullable_fields: Sequence[str] = [], ): """Set the db_obj's metadata to match the info.""" diff --git a/beets/dbcore/db.py b/beets/dbcore/db.py index afae6e906..cc172d0d8 100755 --- a/beets/dbcore/db.py +++ b/beets/dbcore/db.py @@ -26,9 +26,16 @@ import threading import time from abc import ABC from collections import defaultdict -from collections.abc import Generator, Iterable, Iterator, Mapping, Sequence +from collections.abc import ( + Callable, + Generator, + Iterable, + Iterator, + Mapping, + Sequence, +) from sqlite3 import Connection, sqlite_version_info -from typing import TYPE_CHECKING, Any, AnyStr, Callable, Generic +from typing import TYPE_CHECKING, Any, AnyStr, Generic from typing_extensions import TypeVar # default value support from unidecode import unidecode diff --git a/beets/importer/session.py b/beets/importer/session.py index 46277837e..83c5ad4e3 100644 --- a/beets/importer/session.py +++ b/beets/importer/session.py @@ -15,7 +15,7 @@ from __future__ import annotations import os import time -from typing import TYPE_CHECKING, Sequence +from typing import TYPE_CHECKING from beets import config, dbcore, library, logging, plugins, util from beets.importer.tasks import Action @@ -25,6 +25,8 @@ from . import stages as stagefuncs from .state import ImportState if TYPE_CHECKING: + from collections.abc import Sequence + from beets.util import PathBytes from .tasks import ImportTask diff --git a/beets/importer/stages.py b/beets/importer/stages.py index d99b742a2..5474053d0 100644 --- a/beets/importer/stages.py +++ b/beets/importer/stages.py @@ -16,7 +16,7 @@ from __future__ import annotations import itertools import logging -from typing import TYPE_CHECKING, Callable +from typing import TYPE_CHECKING from beets import config, plugins from beets.util import MoveOperation, displayable_path, pipeline @@ -30,6 +30,8 @@ from .tasks import ( ) if TYPE_CHECKING: + from collections.abc import Callable + from beets import library from .session import ImportSession diff --git a/beets/importer/tasks.py b/beets/importer/tasks.py index 710f4da50..9f60d7619 100644 --- a/beets/importer/tasks.py +++ b/beets/importer/tasks.py @@ -20,9 +20,10 @@ import re import shutil import time from collections import defaultdict +from collections.abc import Callable, Iterable, Sequence from enum import Enum from tempfile import mkdtemp -from typing import TYPE_CHECKING, Any, Callable, Iterable, Sequence +from typing import TYPE_CHECKING, Any import mediafile diff --git a/beets/logging.py b/beets/logging.py index 3ed5e5a84..8dab1cea6 100644 --- a/beets/logging.py +++ b/beets/logging.py @@ -37,7 +37,7 @@ from logging import ( RootLogger, StreamHandler, ) -from typing import TYPE_CHECKING, Any, Mapping, TypeVar, Union, overload +from typing import TYPE_CHECKING, Any, TypeVar, Union, overload __all__ = [ "DEBUG", @@ -54,6 +54,8 @@ __all__ = [ ] if TYPE_CHECKING: + from collections.abc import Mapping + T = TypeVar("T") from types import TracebackType diff --git a/beets/metadata_plugins.py b/beets/metadata_plugins.py index b865167e4..f42e8f690 100644 --- a/beets/metadata_plugins.py +++ b/beets/metadata_plugins.py @@ -10,7 +10,7 @@ from __future__ import annotations import abc import re from functools import cache, cached_property -from typing import TYPE_CHECKING, Generic, Literal, Sequence, TypedDict, TypeVar +from typing import TYPE_CHECKING, Generic, Literal, TypedDict, TypeVar import unidecode from confuse import NotFoundError @@ -22,7 +22,7 @@ from beets.util.id_extractors import extract_release_id from .plugins import BeetsPlugin, find_plugins, notify_info_yielded, send if TYPE_CHECKING: - from collections.abc import Iterable + from collections.abc import Iterable, Sequence from .autotag.hooks import AlbumInfo, Item, TrackInfo diff --git a/beets/ui/__init__.py b/beets/ui/__init__.py index 294b466d6..12eb6d005 100644 --- a/beets/ui/__init__.py +++ b/beets/ui/__init__.py @@ -32,7 +32,7 @@ import warnings from difflib import SequenceMatcher from functools import cache from itertools import chain -from typing import Any, Callable, Literal +from typing import TYPE_CHECKING, Any, Literal import confuse @@ -42,6 +42,9 @@ from beets.dbcore import query as db_query from beets.util import as_string from beets.util.functemplate import template +if TYPE_CHECKING: + from collections.abc import Callable + # On Windows platforms, use colorama to support "ANSI" terminal colors. if sys.platform == "win32": try: diff --git a/beets/util/__init__.py b/beets/util/__init__.py index fc05e4997..892c11167 100644 --- a/beets/util/__init__.py +++ b/beets/util/__init__.py @@ -29,7 +29,7 @@ import tempfile import traceback import warnings from collections import Counter -from collections.abc import Sequence +from collections.abc import Callable, Sequence from contextlib import suppress from enum import Enum from functools import cache @@ -41,7 +41,6 @@ from typing import ( TYPE_CHECKING, Any, AnyStr, - Callable, ClassVar, Generic, NamedTuple, diff --git a/beets/util/artresizer.py b/beets/util/artresizer.py index 5ecde5140..72007d0b5 100644 --- a/beets/util/artresizer.py +++ b/beets/util/artresizer.py @@ -26,7 +26,7 @@ import subprocess from abc import ABC, abstractmethod from enum import Enum from itertools import chain -from typing import Any, ClassVar, Mapping +from typing import TYPE_CHECKING, Any, ClassVar from urllib.parse import urlencode from beets import logging, util @@ -37,6 +37,9 @@ from beets.util import ( syspath, ) +if TYPE_CHECKING: + from collections.abc import Mapping + PROXY_URL = "https://images.weserv.nl/" log = logging.getLogger("beets") diff --git a/beets/util/hidden.py b/beets/util/hidden.py index d2c66fac0..0a71c91fd 100644 --- a/beets/util/hidden.py +++ b/beets/util/hidden.py @@ -20,10 +20,9 @@ import os import stat import sys from pathlib import Path -from typing import Union -def is_hidden(path: Union[bytes, Path]) -> bool: +def is_hidden(path: bytes | Path) -> bool: """ Determine whether the given path is treated as a 'hidden file' by the OS. """ diff --git a/beets/util/pipeline.py b/beets/util/pipeline.py index bd2c49316..2ed593904 100644 --- a/beets/util/pipeline.py +++ b/beets/util/pipeline.py @@ -36,10 +36,13 @@ from __future__ import annotations import queue import sys from threading import Lock, Thread -from typing import Callable, Generator, TypeVar +from typing import TYPE_CHECKING, TypeVar from typing_extensions import TypeVarTuple, Unpack +if TYPE_CHECKING: + from collections.abc import Callable, Generator + BUBBLE = "__PIPELINE_BUBBLE__" POISON = "__PIPELINE_POISON__" diff --git a/beetsplug/beatport.py b/beetsplug/beatport.py index c07cce72f..718e0730e 100644 --- a/beetsplug/beatport.py +++ b/beetsplug/beatport.py @@ -19,14 +19,7 @@ from __future__ import annotations import json import re from datetime import datetime, timedelta -from typing import ( - TYPE_CHECKING, - Iterable, - Iterator, - Literal, - Sequence, - overload, -) +from typing import TYPE_CHECKING, Literal, overload import confuse from requests_oauthlib import OAuth1Session @@ -42,6 +35,8 @@ from beets.autotag.hooks import AlbumInfo, TrackInfo from beets.metadata_plugins import MetadataSourcePlugin if TYPE_CHECKING: + from collections.abc import Iterable, Iterator, Sequence + from beets.importer import ImportSession from beets.library import Item diff --git a/beetsplug/bpd/__init__.py b/beetsplug/bpd/__init__.py index 1a4f505dd..0359259b7 100644 --- a/beetsplug/bpd/__init__.py +++ b/beetsplug/bpd/__init__.py @@ -283,7 +283,7 @@ class BaseServer: if not self.ctrl_sock: self.ctrl_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.ctrl_sock.connect((self.ctrl_host, self.ctrl_port)) - self.ctrl_sock.sendall((f"{message}\n").encode("utf-8")) + self.ctrl_sock.sendall((f"{message}\n").encode()) def _send_event(self, event): """Notify subscribed connections of an event.""" diff --git a/beetsplug/chroma.py b/beetsplug/chroma.py index 192310fb8..1e9835789 100644 --- a/beetsplug/chroma.py +++ b/beetsplug/chroma.py @@ -18,8 +18,8 @@ autotagger. Requires the pyacoustid library. import re from collections import defaultdict +from collections.abc import Iterable from functools import cached_property, partial -from typing import Iterable import acoustid import confuse diff --git a/beetsplug/deezer.py b/beetsplug/deezer.py index 3eaca1e05..ef27dddc7 100644 --- a/beetsplug/deezer.py +++ b/beetsplug/deezer.py @@ -18,7 +18,7 @@ from __future__ import annotations import collections import time -from typing import TYPE_CHECKING, Literal, Sequence +from typing import TYPE_CHECKING, Literal import requests @@ -32,6 +32,8 @@ from beets.metadata_plugins import ( ) if TYPE_CHECKING: + from collections.abc import Sequence + from beets.library import Item, Library from ._typing import JSONDict diff --git a/beetsplug/discogs.py b/beetsplug/discogs.py index be1cf97fa..29600a676 100644 --- a/beetsplug/discogs.py +++ b/beetsplug/discogs.py @@ -27,7 +27,7 @@ import time import traceback from functools import cache from string import ascii_lowercase -from typing import TYPE_CHECKING, Sequence, cast +from typing import TYPE_CHECKING, cast import confuse from discogs_client import Client, Master, Release @@ -43,7 +43,7 @@ from beets.autotag.hooks import AlbumInfo, TrackInfo from beets.metadata_plugins import MetadataSourcePlugin if TYPE_CHECKING: - from collections.abc import Callable, Iterable + from collections.abc import Callable, Iterable, Sequence from beets.library import Item diff --git a/beetsplug/fetchart.py b/beetsplug/fetchart.py index 37e7426f6..e6bd05119 100644 --- a/beetsplug/fetchart.py +++ b/beetsplug/fetchart.py @@ -23,7 +23,7 @@ from collections import OrderedDict from contextlib import closing from enum import Enum from functools import cached_property -from typing import TYPE_CHECKING, AnyStr, ClassVar, Literal, Tuple, Type +from typing import TYPE_CHECKING, AnyStr, ClassVar, Literal import confuse import requests @@ -86,7 +86,7 @@ class Candidate: path: None | bytes = None, url: None | str = None, match: None | MetadataMatch = None, - size: None | Tuple[int, int] = None, + size: None | tuple[int, int] = None, ): self._log = log self.path = path @@ -682,7 +682,7 @@ class GoogleImages(RemoteArtSource): """ if not (album.albumartist and album.album): return - search_string = f"{album.albumartist},{album.album}".encode("utf-8") + search_string = f"{album.albumartist},{album.album}".encode() try: response = self.request( @@ -1293,7 +1293,7 @@ class CoverArtUrl(RemoteArtSource): # All art sources. The order they will be tried in is specified by the config. -ART_SOURCES: set[Type[ArtSource]] = { +ART_SOURCES: set[type[ArtSource]] = { FileSystem, CoverArtArchive, ITunesStore, diff --git a/beetsplug/importsource.py b/beetsplug/importsource.py index 1c686d334..19b2530ba 100644 --- a/beetsplug/importsource.py +++ b/beetsplug/importsource.py @@ -19,7 +19,7 @@ class ImportSourcePlugin(BeetsPlugin): def __init__(self): """Initialize the plugin and read configuration.""" - super(ImportSourcePlugin, self).__init__() + super().__init__() self.config.add( { "suggest_removal": False, diff --git a/beetsplug/lastgenre/__init__.py b/beetsplug/lastgenre/__init__.py index 3b04e65d6..ea0ab951a 100644 --- a/beetsplug/lastgenre/__init__.py +++ b/beetsplug/lastgenre/__init__.py @@ -28,7 +28,7 @@ import os import traceback from functools import singledispatchmethod from pathlib import Path -from typing import TYPE_CHECKING, Union +from typing import TYPE_CHECKING import pylast import yaml @@ -352,7 +352,7 @@ class LastGenrePlugin(plugins.BeetsPlugin): combined = old + new return self._resolve_genres(combined) - def _get_genre(self, obj: LibModel) -> tuple[Union[str, None], ...]: + def _get_genre(self, obj: LibModel) -> tuple[str | None, ...]: """Get the final genre string for an Album or Item object. `self.sources` specifies allowed genre sources. Starting with the first diff --git a/beetsplug/lyrics.py b/beetsplug/lyrics.py index 76854f0e9..677467776 100644 --- a/beetsplug/lyrics.py +++ b/beetsplug/lyrics.py @@ -28,7 +28,7 @@ from html import unescape from http import HTTPStatus from itertools import groupby from pathlib import Path -from typing import TYPE_CHECKING, Iterable, Iterator, NamedTuple +from typing import TYPE_CHECKING, NamedTuple from urllib.parse import quote, quote_plus, urlencode, urlparse import langdetect @@ -42,6 +42,8 @@ from beets.autotag.distance import string_dist from beets.util.config import sanitize_choices if TYPE_CHECKING: + from collections.abc import Iterable, Iterator + from beets.importer import ImportTask from beets.library import Item, Library from beets.logging import BeetsLogger as Logger diff --git a/beetsplug/mbpseudo.py b/beetsplug/mbpseudo.py index 448aef365..9cfa99969 100644 --- a/beetsplug/mbpseudo.py +++ b/beetsplug/mbpseudo.py @@ -19,7 +19,7 @@ from __future__ import annotations import itertools import traceback from copy import deepcopy -from typing import TYPE_CHECKING, Any, Iterable, Sequence +from typing import TYPE_CHECKING, Any import mediafile import musicbrainzngs @@ -40,6 +40,8 @@ from beetsplug.musicbrainz import ( ) if TYPE_CHECKING: + from collections.abc import Iterable, Sequence + from beets.autotag import AlbumMatch from beets.library import Item from beetsplug._typing import JSONDict diff --git a/beetsplug/musicbrainz.py b/beetsplug/musicbrainz.py index 29bbc26d0..3b49107ad 100644 --- a/beetsplug/musicbrainz.py +++ b/beetsplug/musicbrainz.py @@ -21,7 +21,7 @@ from collections import Counter from contextlib import suppress from functools import cached_property from itertools import product -from typing import TYPE_CHECKING, Any, Iterable, Sequence +from typing import TYPE_CHECKING, Any from urllib.parse import urljoin import musicbrainzngs @@ -34,6 +34,7 @@ from beets.metadata_plugins import MetadataSourcePlugin from beets.util.id_extractors import extract_release_id if TYPE_CHECKING: + from collections.abc import Iterable, Sequence from typing import Literal from beets.library import Item diff --git a/beetsplug/replaygain.py b/beetsplug/replaygain.py index 3e777d977..a8c887caa 100644 --- a/beetsplug/replaygain.py +++ b/beetsplug/replaygain.py @@ -28,7 +28,7 @@ from abc import ABC, abstractmethod from dataclasses import dataclass from multiprocessing.pool import ThreadPool from threading import Event, Thread -from typing import TYPE_CHECKING, Any, Callable, TypeVar +from typing import TYPE_CHECKING, Any, TypeVar from beets import ui from beets.plugins import BeetsPlugin @@ -36,7 +36,7 @@ from beets.util import command_output, displayable_path, syspath if TYPE_CHECKING: import optparse - from collections.abc import Sequence + from collections.abc import Callable, Sequence from logging import Logger from confuse import ConfigView diff --git a/beetsplug/spotify.py b/beetsplug/spotify.py index a8126b852..b3c653682 100644 --- a/beetsplug/spotify.py +++ b/beetsplug/spotify.py @@ -27,7 +27,7 @@ import re import threading import time import webbrowser -from typing import TYPE_CHECKING, Any, Literal, Sequence, Union +from typing import TYPE_CHECKING, Any, Literal, Union import confuse import requests @@ -43,6 +43,8 @@ from beets.metadata_plugins import ( ) if TYPE_CHECKING: + from collections.abc import Sequence + from beets.library import Library from beetsplug._typing import JSONDict diff --git a/extra/release.py b/extra/release.py index e16814960..0c11415a9 100755 --- a/extra/release.py +++ b/extra/release.py @@ -6,18 +6,18 @@ from __future__ import annotations import re import subprocess +from collections.abc import Callable from contextlib import redirect_stdout from datetime import datetime, timezone from functools import partial from io import StringIO from pathlib import Path -from typing import Callable, NamedTuple +from typing import NamedTuple, TypeAlias import click import tomli from packaging.version import Version, parse from sphinx.ext import intersphinx -from typing_extensions import TypeAlias from docs.conf import rst_epilog diff --git a/test/plugins/test_aura.py b/test/plugins/test_aura.py index f4535c738..7e840008e 100644 --- a/test/plugins/test_aura.py +++ b/test/plugins/test_aura.py @@ -1,7 +1,7 @@ import os from http import HTTPStatus from pathlib import Path -from typing import Any, Optional +from typing import Any import pytest from flask.testing import Client @@ -58,9 +58,7 @@ class TestAuraResponse: def get_response_data(self, client: Client, item): """Return a callback accepting `endpoint` and `params` parameters.""" - def get( - endpoint: str, params: dict[str, str] - ) -> Optional[dict[str, Any]]: + def get(endpoint: str, params: dict[str, str]) -> dict[str, Any] | None: """Add additional `params` and GET the given endpoint. `include` parameter is added to every call to check that the diff --git a/test/plugins/test_ftintitle.py b/test/plugins/test_ftintitle.py index 56c82b9d2..b4259666d 100644 --- a/test/plugins/test_ftintitle.py +++ b/test/plugins/test_ftintitle.py @@ -14,7 +14,7 @@ """Tests for the 'ftintitle' plugin.""" -from typing import Dict, Generator, Optional, Tuple, Union +from collections.abc import Generator import pytest @@ -39,7 +39,7 @@ def env() -> Generator[FtInTitlePluginFunctional, None, None]: def set_config( env: FtInTitlePluginFunctional, - cfg: Optional[Dict[str, Union[str, bool, list[str]]]], + cfg: dict[str, str | bool | list[str]] | None, ) -> None: cfg = {} if cfg is None else cfg defaults = { @@ -57,7 +57,7 @@ def add_item( path: str, artist: str, title: str, - albumartist: Optional[str], + albumartist: str | None, ) -> Item: return env.add_item( path=path, @@ -250,10 +250,10 @@ def add_item( ) def test_ftintitle_functional( env: FtInTitlePluginFunctional, - cfg: Optional[Dict[str, Union[str, bool, list[str]]]], - cmd_args: Tuple[str, ...], - given: Tuple[str, str, Optional[str]], - expected: Tuple[str, str], + cfg: dict[str, str | bool | list[str]] | None, + cmd_args: tuple[str, ...], + given: tuple[str, str, str | None], + expected: tuple[str, str], ) -> None: set_config(env, cfg) ftintitle.FtInTitlePlugin() @@ -287,7 +287,7 @@ def test_ftintitle_functional( def test_find_feat_part( artist: str, albumartist: str, - expected: Optional[str], + expected: str | None, ) -> None: assert ftintitle.find_feat_part(artist, albumartist) == expected @@ -307,7 +307,7 @@ def test_find_feat_part( ) def test_split_on_feat( given: str, - expected: Tuple[str, Optional[str]], + expected: tuple[str, str | None], ) -> None: assert ftintitle.split_on_feat(given) == expected @@ -359,7 +359,7 @@ def test_contains_feat(given: str, expected: bool) -> None: ], ) def test_custom_words( - given: str, custom_words: Optional[list[str]], expected: bool + given: str, custom_words: list[str] | None, expected: bool ) -> None: if custom_words is None: custom_words = [] diff --git a/test/plugins/test_hook.py b/test/plugins/test_hook.py index 3392d6881..033e1ea64 100644 --- a/test/plugins/test_hook.py +++ b/test/plugins/test_hook.py @@ -19,13 +19,13 @@ import os import sys import unittest from contextlib import contextmanager -from typing import TYPE_CHECKING, Callable +from typing import TYPE_CHECKING from beets import plugins from beets.test.helper import PluginTestCase, capture_log if TYPE_CHECKING: - from collections.abc import Iterator + from collections.abc import Callable, Iterator class HookTestCase(PluginTestCase): diff --git a/test/plugins/test_importfeeds.py b/test/plugins/test_importfeeds.py index 53da87172..3f51eca76 100644 --- a/test/plugins/test_importfeeds.py +++ b/test/plugins/test_importfeeds.py @@ -1,6 +1,5 @@ import datetime import os -import os.path from beets.library import Album, Item from beets.test.helper import PluginTestCase diff --git a/test/test_sort.py b/test/test_sort.py index 25d993e30..460aa07b8 100644 --- a/test/test_sort.py +++ b/test/test_sort.py @@ -14,7 +14,7 @@ """Various tests for querying the library database.""" -from mock import patch +from unittest.mock import patch import beets.library from beets import config, dbcore