Skip to content

Commit

Permalink
improve performance for printing LocalCollection objects (#83)
Browse files Browse the repository at this point in the history
* fix inheritance issue; switch back to ABCMeta

* remove last_modified from LocalCollection print attributes
  • Loading branch information
geo-martino authored May 26, 2024
1 parent d41b933 commit 2c1857a
Show file tree
Hide file tree
Showing 60 changed files with 173 additions and 170 deletions.
4 changes: 2 additions & 2 deletions docs/_howto/scripts/remote.new-music/p4.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from p3 import *

from musify.libraries.remote.core.enum import RemoteObjectType
from musify.libraries.remote.spotify.object import SpotifyAlbum
from musify.libraries.remote.core.object import RemoteAlbum


async def get_albums(library: RemoteLibrary, start: date, end: date) -> list[SpotifyAlbum]:
async def get_albums(library: RemoteLibrary, start: date, end: date) -> list[RemoteAlbum]:
"""
Get the albums that match the ``start`` and ``end`` date range from a given ``library``
and get the tracks on those albums if needed.
Expand Down
2 changes: 1 addition & 1 deletion docs/_howto/scripts/sync/p99.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@

asyncio.run(match_albums_to_remote(albums, remote_library.factory))
asyncio.run(sync_albums(albums, remote_library.factory))
asyncio.run(sync_local_library_with_remote(playlist, local_library, remote_library))
asyncio.run(sync_local_playlist_with_remote(playlist, local_library, remote_library))
3 changes: 3 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration

# noinspection SpellCheckingInspection
extensions = [
"sphinx.ext.autodoc",
"sphinx_rtd_theme",
Expand All @@ -27,7 +28,9 @@
"autodocsumm",
"sphinxext.opengraph",
]
# noinspection SpellCheckingInspection
autodoc_member_order = "bysource"
# noinspection SpellCheckingInspection
autodoc_default_options = {
"autosummary": True,
"members": True,
Expand Down
2 changes: 1 addition & 1 deletion docs/contributing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Setup your development environment
pip install -e '.[dev]' # installs the `test` dependencies + dependencies for linting and other development uses
pip install -e '.[docs]' # installs just the core package + the required dependencies for building documentation
6. Optionally, to ensure inhreitance diagrams in the documentation render correctly, install graphviz.
6. Optionally, to ensure inheritance diagrams in the documentation render correctly, install graphviz.
See `here <https://graphviz.org/download/>`_ for platform-specific info on how to install graphviz.

Making changes and testing
Expand Down
2 changes: 2 additions & 0 deletions docs/release-history.rst
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ Removed
* ``use_cache`` parameter from all :py:class:`.RemoteAPI` related methods.
Cache settings now handled by :py:class:`.ResponseCache`
* ThreadPoolExecutor use on :py:class:`.RemoteItemSearcher`. Now uses asynchronous logic instead.
* `last_modified` field as attribute to ignore when getting attributes
to print on `LocalCollection` to improve performance

Documentation
-------------
Expand Down
8 changes: 4 additions & 4 deletions musify/api/cache/backend/base.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import logging
from abc import ABC, abstractmethod
from collections.abc import MutableMapping, Callable, Collection, Hashable, AsyncIterable, Mapping, Awaitable
from abc import ABCMeta, abstractmethod
from collections.abc import MutableMapping, Callable, Collection, AsyncIterable, Mapping, Awaitable
from dataclasses import dataclass
from datetime import datetime, timedelta
from typing import Any, Self, AsyncContextManager
Expand All @@ -21,7 +21,7 @@


@dataclass
class RequestSettings(ABC):
class RequestSettings(metaclass=ABCMeta):
"""Settings for a request type for a given endpoint to be used to configure a repository in the cache backend."""
#: That name of the repository in the backend
name: str
Expand All @@ -47,7 +47,7 @@ def get_name(response: dict[str, Any]) -> str | None:
raise NotImplementedError


class ResponseRepository[K, V](AsyncIterable[tuple[K, V]], Awaitable, Hashable, ABC):
class ResponseRepository[K, V](AsyncIterable[tuple[K, V]], Awaitable, metaclass=ABCMeta):
"""
Represents a repository in the backend cache, providing a dict-like interface
for interacting with this repository.
Expand Down
17 changes: 10 additions & 7 deletions musify/core/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@
"""
from __future__ import annotations

from abc import ABC, abstractmethod
from collections.abc import Hashable
from abc import ABCMeta, abstractmethod
from typing import Any

from musify.core.enum import TagField
from musify.core.printer import AttributePrinter


class MusifyObject(AttributePrinter):
class MusifyObject(AttributePrinter, metaclass=ABCMeta):
"""Generic base class for any nameable and taggable object."""

__slots__ = ("_clean_tags",)
Expand Down Expand Up @@ -40,7 +39,7 @@ def __gt__(self, other: MusifyObject):
return self.name > other.name


class MusifyItem(MusifyObject, Hashable, ABC):
class MusifyItem(MusifyObject, metaclass=ABCMeta):
"""Generic class for storing an item."""

__slots__ = ()
Expand Down Expand Up @@ -76,7 +75,7 @@ def __getitem__(self, key: str) -> Any:


# noinspection PyPropertyDefinition
class MusifyItemSettable(MusifyItem, ABC):
class MusifyItemSettable(MusifyItem, metaclass=ABCMeta):
"""Generic class for storing an item that can have select properties modified."""

__slots__ = ()
Expand All @@ -91,10 +90,14 @@ def _uri_setter(self, value: str | None):
"""Set both the ``uri`` property and the ``has_uri`` property ."""
raise NotImplementedError

uri = property(lambda self: self._uri_getter(), lambda self, v: self._uri_setter(v))
uri = property(
fget=lambda self: self._uri_getter(),
fset=lambda self, v: self._uri_setter(v),
doc="URI (Uniform Resource Indicator) is the unique identifier for this item."
)


class HasLength(ABC):
class HasLength(metaclass=ABCMeta):
"""Simple protocol for an object which has a length"""

__slots__ = ()
Expand Down
4 changes: 2 additions & 2 deletions musify/core/printer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
The fundamental core printer classes for the entire package.
"""
import re
from abc import ABC, abstractmethod
from abc import ABCMeta, abstractmethod
from collections.abc import Mapping
from concurrent.futures import Future, ThreadPoolExecutor
from datetime import datetime, date
Expand All @@ -12,7 +12,7 @@
from musify.utils import to_collection


class PrettyPrinter(ABC):
class PrettyPrinter(metaclass=ABCMeta):
"""Generic base class for pretty printing. Classes can inherit this class to gain pretty print functionality."""

__slots__ = ()
Expand Down
4 changes: 2 additions & 2 deletions musify/core/result.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
"""
The fundamental core result classes for the entire package.
"""
from abc import ABC
from abc import ABCMeta
from dataclasses import dataclass


@dataclass(frozen=True)
class Result(ABC):
class Result(metaclass=ABCMeta):
"""Stores the results of an operation"""
pass
5 changes: 2 additions & 3 deletions musify/file/base.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
"""
Generic base classes and functions for file operations.
"""
from abc import ABC, abstractmethod
from collections.abc import Hashable
from abc import ABCMeta, abstractmethod
from datetime import datetime
from glob import glob
from os.path import splitext, basename, dirname, getsize, getmtime, getctime, exists, join
Expand All @@ -11,7 +10,7 @@
from musify.file.exception import InvalidFileType, FileDoesNotExistError


class File(Hashable, ABC):
class File(metaclass=ABCMeta):
"""Generic class for representing a file on a system."""

__slots__ = ()
Expand Down
6 changes: 3 additions & 3 deletions musify/libraries/core/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""
from __future__ import annotations

from abc import ABC, abstractmethod
from abc import ABCMeta, abstractmethod
from collections.abc import MutableSequence, Iterable, Mapping, Collection
from dataclasses import dataclass
from typing import Any, SupportsIndex, Self
Expand All @@ -19,7 +19,7 @@


@dataclass
class ItemGetterStrategy(ABC):
class ItemGetterStrategy(metaclass=ABCMeta):
"""Abstract base class for strategies relating to __getitem__ operations on a :py:class:`MusifyCollection`"""

key: str
Expand Down Expand Up @@ -105,7 +105,7 @@ def get_value_from_item(self, item: RemoteObject) -> str:
return item.url_ext


class MusifyCollection[T: MusifyItem](MusifyObject, HasLength, MutableSequence[T], ABC):
class MusifyCollection[T: MusifyItem](MusifyObject, MutableSequence[T], HasLength):
"""Generic class for storing a collection of musify items."""

__slots__ = ()
Expand Down
22 changes: 11 additions & 11 deletions musify/libraries/core/object.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from __future__ import annotations

import datetime
from abc import ABC, abstractmethod
from abc import ABCMeta, abstractmethod
from collections.abc import Collection, Mapping, Iterable
from copy import deepcopy
from typing import Self
Expand All @@ -15,11 +15,11 @@
from musify.libraries.remote.core.enum import RemoteObjectType


class Track(MusifyItem, HasLength, ABC):
class Track(MusifyItem, HasLength, metaclass=ABCMeta):
"""Represents a track including its metadata/tags/properties."""

__slots__ = ()
__attributes_ignore__ = "name"
__attributes_ignore__ = ("name",)

# noinspection PyPropertyDefinition
@classmethod
Expand Down Expand Up @@ -167,12 +167,12 @@ def rating(self) -> float | None:
raise NotImplementedError


class Playlist[T: Track](MusifyCollection[T], ABC):
class Playlist[T: Track](MusifyCollection[T], metaclass=ABCMeta):
"""A playlist of items and their derived properties/objects."""

__slots__ = ()
__attributes_classes__ = MusifyCollection
__attributes_ignore__ = "items"
__attributes_ignore__ = ("items",)

# noinspection PyPropertyDefinition
@classmethod
Expand Down Expand Up @@ -288,12 +288,12 @@ def __ior__(self, other: Playlist[T]) -> Self:
return self


class Library[T: Track](MusifyCollection[T], ABC):
class Library[T: Track](MusifyCollection[T], metaclass=ABCMeta):
"""A library of items and playlists and other object types."""

__slots__ = ()
__attributes_classes__ = MusifyCollection
__attributes_ignore__ = "items"
__attributes_ignore__ = ("items",)

@property
@abstractmethod
Expand Down Expand Up @@ -405,7 +405,7 @@ def get_playlists_map(
self.playlists[name].merge(playlist, reference=reference.get(name))


class Folder[T: Track](MusifyCollection[T], ABC):
class Folder[T: Track](MusifyCollection[T], metaclass=ABCMeta):
"""
A folder of items and their derived properties/objects
"""
Expand Down Expand Up @@ -472,7 +472,7 @@ def length(self):
return sum(lengths) if lengths else None


class Album[T: Track](MusifyCollection[T], ABC):
class Album[T: Track](MusifyCollection[T], metaclass=ABCMeta):
"""An album of items and their derived properties/objects."""

__slots__ = ()
Expand Down Expand Up @@ -596,7 +596,7 @@ def rating(self) -> float | None:
raise NotImplementedError


class Artist[T: (Track, Album)](MusifyCollection[T], ABC):
class Artist[T: (Track, Album)](MusifyCollection[T], metaclass=ABCMeta):
"""An artist of items and their derived properties/objects."""

__slots__ = ()
Expand Down Expand Up @@ -668,7 +668,7 @@ def rating(self) -> int | None:
raise NotImplementedError


class Genre[T: Track](MusifyCollection[T], ABC):
class Genre[T: Track](MusifyCollection[T], metaclass=ABCMeta):
"""A genre of items and their derived properties/objects."""

__slots__ = ()
Expand Down
4 changes: 2 additions & 2 deletions musify/libraries/local/base.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
"""
Core abstract classes for the :py:mod:`Local` module.
"""
from abc import ABC
from abc import ABCMeta

from musify.core.base import MusifyItemSettable
from musify.file.base import File


class LocalItem(File, MusifyItemSettable, ABC):
class LocalItem(File, MusifyItemSettable, metaclass=ABCMeta):
"""Generic base class for locally-stored items"""

__slots__ = ()
Expand Down
8 changes: 4 additions & 4 deletions musify/libraries/local/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import logging
import sys
from abc import ABC, abstractmethod
from abc import ABCMeta, abstractmethod
from collections.abc import Mapping, Collection, Iterable, Container
from concurrent.futures import ThreadPoolExecutor
from datetime import datetime
Expand All @@ -28,7 +28,7 @@
_max_str = "z" * 50


class LocalCollection[T: LocalTrack](MusifyCollection[T], ABC):
class LocalCollection[T: LocalTrack](MusifyCollection[T], metaclass=ABCMeta):
"""
Generic class for storing a collection of local tracks.
Expand All @@ -37,7 +37,7 @@ class LocalCollection[T: LocalTrack](MusifyCollection[T], ABC):
"""

__slots__ = ("logger", "remote_wrangler")
__attributes_ignore__ = ("track_paths", "track_total")
__attributes_ignore__ = ("track_total", "last_modified")

@staticmethod
def _validate_item_type(items: Any | Iterable[Any]) -> bool:
Expand Down Expand Up @@ -170,7 +170,7 @@ def merge_tracks(self, tracks: Collection[Track], tags: UnitIterable[TagField] =
self.logger.print()


class LocalCollectionFiltered[T: LocalItem](LocalCollection[T], ABC):
class LocalCollectionFiltered[T: LocalItem](LocalCollection[T], metaclass=ABCMeta):
"""
Generic class for storing and filtering on a collection of local tracks
with methods for enriching the attributes of this object from the attributes of the collection of tracks
Expand Down
Loading

0 comments on commit 2c1857a

Please sign in to comment.