Skip to content

Commit

Permalink
Feat/supress sub config repr (#285)
Browse files Browse the repository at this point in the history
feat
- improve config repr

fix
- playlist builder to ack PlaylistFilter enum and making the playlist config a config attribute
- have all CLI args present when instantiating configs so validation works properly
- scripts updated to work with config refactor

test    
- coverage for config_formatter
- fix fixture usage after config reformat
- ignore coverage on YAML representer
  • Loading branch information
a-rich authored Jan 5, 2025
1 parent 3c3219a commit f9e168f
Show file tree
Hide file tree
Showing 31 changed files with 507 additions and 147 deletions.
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ line-length = 79
source = ["src"]
omit = ["src/djtools/__main__.py"]

[tool.coverage.report]
exclude_lines = [
"pragma: no cover"
]

[tool.pylint.DESIGN]
disable = [
"abstract-class-instantiated",
Expand Down
2 changes: 1 addition & 1 deletion scripts/collection/cluster_tracks.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@

from djtools.collection.base_collection import Collection
from djtools.collection.base_playlist import Playlist
from djtools.collection.helpers import PLATFORM_REGISTRY
from djtools.collection.base_track import Track
from djtools.collection.platform_registry import PLATFORM_REGISTRY
from djtools.configs import build_config


Expand Down
14 changes: 8 additions & 6 deletions scripts/collection/get_tags_from_spotify.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

from djtools.configs.helpers import build_config
from djtools.collection.base_track import Track
from djtools.collection.helpers import PLATFORM_REGISTRY
from djtools.collection.platform_registry import PLATFORM_REGISTRY
from djtools.spotify.helpers import filter_results, get_spotify_client


Expand Down Expand Up @@ -140,12 +140,12 @@ def filter_tracks(

# Build config, instantiate collection, and get tracks.
config = build_config(args.config)
collection = PLATFORM_REGISTRY[config.platform]["collection"](
path=args.collection or config.collection_path
collection = PLATFORM_REGISTRY[config.collection.platform]["collection"](
path=args.collection or config.collection.collection_path
)
tracks = filter_tracks(collection.get_tracks(), args.date_filter)
spotify = get_spotify_client(config)
playlist_class = PLATFORM_REGISTRY[config.platform]["playlist"]
playlist_class = PLATFORM_REGISTRY[config.collection.platform]["playlist"]

# Add tags from Spotify.
if args.mode == "bulk":
Expand Down Expand Up @@ -233,7 +233,9 @@ def filter_tracks(
"Response must contain either 'n' or 'y' -- try again!"
)

playlist_class = PLATFORM_REGISTRY[config.platform]["playlist"]
playlist_class = PLATFORM_REGISTRY[config.collection.platform][
"playlist"
]
for name, set_tracks in [
("No matches", no_matches),
("Same", same_tracks),
Expand All @@ -244,4 +246,4 @@ def filter_tracks(
)
collection.add_playlist(playlist)

collection.serialize(path=args.output or config.collection_path)
collection.serialize(path=args.output or config.collection.collection_path)
2 changes: 1 addition & 1 deletion scripts/collection/remove_files_not_in_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from pathlib import Path

from djtools.configs import build_config
from djtools.collection.helpers import PLATFORM_REGISTRY
from djtools.collection.platform_registry import PLATFORM_REGISTRY


# pylint: disable=missing-function-docstring
Expand Down
2 changes: 1 addition & 1 deletion scripts/collection/remove_tags_from_comments.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from tqdm import tqdm

from djtools.configs.helpers import build_config
from djtools.collection.helpers import PLATFORM_REGISTRY
from djtools.collection.platform_registry import PLATFORM_REGISTRY


def remove_tags_thread(track, tag_regex, remove_tags):
Expand Down
2 changes: 1 addition & 1 deletion scripts/collection/sort_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import re

from djtools.configs import build_config
from djtools.collection.helpers import PLATFORM_REGISTRY
from djtools.collection.platform_registry import PLATFORM_REGISTRY


TAG_ORDERINGS = (
Expand Down
16 changes: 8 additions & 8 deletions scripts/collection/update_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from subprocess import Popen

from djtools.configs import build_config
from djtools.collection.helpers import PLATFORM_REGISTRY
from djtools.collection.platform_registry import PLATFORM_REGISTRY


if __name__ == "__main__":
Expand Down Expand Up @@ -58,10 +58,10 @@
if args.collection:
collection_path = Path(args.collection)
else:
collection_path = config.collection_path
collection_path = config.collection.collection_path

# Load collection and get a dict of tracks keyed by location.
collection = PLATFORM_REGISTRY[config.platform]["collection"](
collection = PLATFORM_REGISTRY[config.collection.platform]["collection"](
path=collection_path
)
tracks = {
Expand All @@ -76,8 +76,8 @@
remote_master_collection = args.master_collection
else:
remote_master_collection = (
f"{config.bucket_url}/dj/collections/"
f"{args.master_collection_user}/{config.platform}_collection"
f"{config.sync.bucket_url}/dj/collections/"
f"{args.master_collection_user}/{config.collection.platform.value}_collection"
)

# Download the master collection and get a dict of its tracks too.
Expand All @@ -87,9 +87,9 @@
cmd.append("--recursive")
with Popen(cmd) as proc:
proc.wait()
master_collection = PLATFORM_REGISTRY[config.platform]["collection"](
path=master_collection_path
)
master_collection = PLATFORM_REGISTRY[config.collection.platform][
"collection"
](path=master_collection_path)
master_tracks = master_collection.get_tracks()
master_tracks = {
track.get_location().as_posix(): track
Expand Down
6 changes: 3 additions & 3 deletions scripts/collection/update_library_playlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def filter_tracks(
def find_track(track: Track, config: BaseConfig, spotify: Spotify):
title = track._Name
artist = track.get_artists()
threshold = config.spotify_playlist_fuzz_ratio
threshold = config.spotify.spotify_playlist_fuzz_ratio
query = f"track:{title} artist:{artist}"
try:
results = spotify.search(q=query, type="track", limit=50)
Expand All @@ -129,7 +129,7 @@ def main(config_path: Path, date_filter: datetime, playlist_name: str):
spotify = get_spotify_client(config)
playlist_ids = get_playlist_ids()

collection = RekordboxCollection(config.collection_path)
collection = RekordboxCollection(config.collection.collection_path)
tracks = filter_tracks(collection.get_tracks(), date_filter)
tracks = sorted(tracks.values(), key=lambda x: x.get_date_added())

Expand All @@ -152,7 +152,7 @@ def main(config_path: Path, date_filter: datetime, playlist_name: str):
playlist_ids = populate_playlist(
playlist_name=playlist_name,
playlist_ids=playlist_ids,
spotify_username=config.spotify_username,
spotify_username=config.spotify.spotify_username,
spotify=spotify,
tracks=chunk,
verbosity=config.verbosity,
Expand Down
2 changes: 1 addition & 1 deletion scripts/collection/user_vibe_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

from djtools.configs import build_config
from djtools.collection.base_collection import Collection
from djtools.collection.helpers import PLATFORM_REGISTRY
from djtools.collection.platform_registry import PLATFORM_REGISTRY


def analyze_collection_vibes(
Expand Down
2 changes: 1 addition & 1 deletion src/djtools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def main():
# Test ci
logger, log_file = initialize_logger()
config = build_config()
logger.setLevel(config.log_level)
logger.setLevel(config.log_level.value)

# Run "collection", "spotify", "sync", and "utils" package operations if
# any of the flags to do so are present in the config.
Expand Down
84 changes: 73 additions & 11 deletions src/djtools/collection/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
"""

import logging
from enum import Enum
from pathlib import Path
from typing import List, Literal, Optional, Union
from typing import List, Optional, Union

import yaml
from jinja2 import Environment, FileSystemLoader, TemplateNotFound
Expand All @@ -17,25 +18,86 @@
logger = logging.getLogger(__name__)


class PlaylistFilters(Enum):
"""PlaylistFilters enum."""

COMPLEX_TRACK_FILTER = "ComplexTrackFilter"
HIPHOP_FILTER = "HipHopFilter"
MINIMAL_DEEP_TECH_FILTER = "MinimalDeepTechFilter"
TRANSITION_TRACK_FILTER = "TransitionTrackFilter"


def playlist_filter_representer(dumper, data):
# pylint: disable=missing-function-docstring
return dumper.represent_scalar( # pragma: no cover
"!PlaylistFilters", data.value
)


def playlist_filter_constructor(loader, node):
# pylint: disable=missing-function-docstring
return PlaylistFilters(loader.construct_scalar(node)) # pragma: no cover


yaml.add_representer(PlaylistFilters, playlist_filter_representer)
yaml.add_constructor("!PlaylistFilters", playlist_filter_constructor)


class PlaylistRemainder(Enum):
"""PlaylistRemainder enum."""

FOLDER = "folder"
PLAYLIST = "playlist"


def playlist_remainder_representer(dumper, data):
# pylint: disable=missing-function-docstring
return dumper.represent_scalar("!PlaylistRemainder", data.value)


def playlist_remainder_constructor(loader, node):
# pylint: disable=missing-function-docstring
return PlaylistRemainder(loader.construct_scalar(node))


yaml.add_representer(PlaylistRemainder, playlist_remainder_representer)
yaml.add_constructor("!PlaylistRemainder", playlist_remainder_constructor)


class RegisteredPlatforms(Enum):
"""RegisteredPlatforms enum."""

REKORDBOX = "rekordbox"


def registered_platforms_representer(dumper, data):
# pylint: disable=missing-function-docstring
return dumper.represent_scalar("!RegisteredPlatforms", data.value)


def registered_platforms_constructor(loader, node):
# pylint: disable=missing-function-docstring
return RegisteredPlatforms(loader.construct_scalar(node))


yaml.add_representer(RegisteredPlatforms, registered_platforms_representer)
yaml.add_constructor("!RegisteredPlatforms", registered_platforms_constructor)


class CollectionConfig(BaseConfigFormatter):
"""Configuration object for the collection package."""

collection_path: Optional[Path] = None
collection_playlist_filters: List[
Literal[
"HipHopFilter",
"MinimalDeepTechFilter",
"ComplexTrackFilter",
"TransitionTrackFilter",
]
] = []
collection_playlist_filters: List[PlaylistFilters] = []
collection_playlists: bool = False
collection_playlists_remainder: Literal["folder", "playlist"] = "folder"
collection_playlists_remainder: PlaylistRemainder = (
PlaylistRemainder.FOLDER
)
copy_playlists: List[str] = []
copy_playlists_destination: Optional[Path] = None
minimum_combiner_playlist_tracks: Optional[PositiveInt] = None
minimum_tag_playlist_tracks: Optional[PositiveInt] = None
platform: Literal["rekordbox"] = "rekordbox"
platform: RegisteredPlatforms = RegisteredPlatforms.REKORDBOX
shuffle_playlists: List[str] = []
playlist_config: Optional["PlaylistConfig"] = None

Expand Down
3 changes: 2 additions & 1 deletion src/djtools/collection/platform_registry.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""This module contains the platform registry for supported DJ software."""

from djtools.collection.config import RegisteredPlatforms
from djtools.collection.rekordbox_collection import RekordboxCollection
from djtools.collection.rekordbox_playlist import RekordboxPlaylist
from djtools.collection.rekordbox_track import RekordboxTrack
Expand All @@ -9,7 +10,7 @@
# platform name must be registered with references to their Collection,
# Playlist, and Track implementations.
PLATFORM_REGISTRY = {
"rekordbox": {
RegisteredPlatforms.REKORDBOX: {
"collection": RekordboxCollection,
"playlist": RekordboxPlaylist,
"track": RekordboxTrack,
Expand Down
16 changes: 9 additions & 7 deletions src/djtools/collection/playlist_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
from typing import Optional, Type

from djtools.collection import playlist_filters
from djtools.collection.config import PlaylistConfig, PlaylistConfigContent
from djtools.collection.config import (
PlaylistConfigContent,
PlaylistRemainder,
)
from djtools.collection.helpers import (
add_selectors_to_tags,
aggregate_playlists,
Expand Down Expand Up @@ -76,10 +79,6 @@ def collection_playlists(config: BaseConfig, path: Optional[Path] = None):
config: Configuration object.
path: Path to write the new collection to.
"""
config.collection.playlist_config = PlaylistConfig(
**config.collection.playlist_config or {}
)

# Check if the playlist config is populated before continuing.
if not (
config.collection.playlist_config.tags
Expand Down Expand Up @@ -115,7 +114,7 @@ def collection_playlists(config: BaseConfig, path: Optional[Path] = None):

# List of PlaylistFilter implementations to run against built playlists.
filters = [
getattr(playlist_filters, playlist_filter)()
getattr(playlist_filters, playlist_filter.value)()
for playlist_filter in config.collection.collection_playlist_filters
]

Expand Down Expand Up @@ -154,7 +153,10 @@ def collection_playlists(config: BaseConfig, path: Optional[Path] = None):
# and create either an "Other" folder of playlists or simply an "Other"
# playlist.
other_tags = sorted(set(tags_tracks).difference(seen_tags))
if config.collection.collection_playlists_remainder == "folder":
if (
config.collection.collection_playlists_remainder
== PlaylistRemainder.FOLDER
):
auto_playlists.append(
build_tag_playlists(
PlaylistConfigContent(
Expand Down
8 changes: 5 additions & 3 deletions src/djtools/configs/cli_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
import json
from argparse import Action, ArgumentParser, Namespace, RawTextHelpFormatter
from pathlib import Path
from typing import Dict, List, Literal, Optional, Union
from typing import Dict, List, Optional, Union

from djtools.utils.config import TrimInitialSilenceMode


def get_arg_parser() -> ArgumentParser:
Expand Down Expand Up @@ -568,8 +570,8 @@ def _parse_json(_json: str) -> Dict:

def _parse_trim_initial_silence(
arg: str,
) -> Union[int, Literal["auto", "smart"]]:
if arg in {"auto", "smart"}:
) -> Union[int, TrimInitialSilenceMode]:
if isinstance(arg, TrimInitialSilenceMode):
return arg

try:
Expand Down
Loading

0 comments on commit f9e168f

Please sign in to comment.