Turn the actual query into a macro

This commit is contained in:
Benson Chu 2026-04-04 13:38:11 -05:00
parent ddcbe8fbab
commit 75afd293bd
3 changed files with 22 additions and 23 deletions

View file

@ -59,7 +59,7 @@ beetslabels:
# labels:
playlists:
- name: exercise
query: ["effortless"]
query: ["label:effortless"]
smartplaylist:
relative_to: ~/Music/0beets_playlists

View file

@ -16,7 +16,7 @@ Prefixes = dict[str, FieldQueryType]
import re
from .labels import HasLabelQuery, labels_command, LABELS_FIELD_NAME, LabelValueSort
from .playlists import initialize_playlists, InPlaylistQuery, PlaylistValueSort
from .playlists import initialize_playlists, expand_playlist_query, PlaylistValueSort
class LabelValueSortsDict(dict):
"""Custom dict that returns LabelValueSort for any label:* key."""
@ -46,6 +46,23 @@ def parse_sorted_query_override(
"""Given a list of strings, create the `Query` and `Sort` that they
represent.
"""
# First, expand any playlist: macros
expanded_parts = []
for part in parts:
if part.startswith('playlist:') and not re.match(r"[+-]$", part):
playlist_name = part[len("playlist:"):]
if playlist_name in playlist_config:
expanded_parts.extend(expand_playlist_query(playlist_name))
else:
# Unknown playlist, pass through (will likely cause an error later)
expanded_parts.append(part)
else:
expanded_parts.append(part)
# Use the expanded parts for the rest of the parsing
parts = expanded_parts
# Separate query token and sort token.
query_parts = []
sort_parts = []
@ -94,7 +111,6 @@ class BeetsLabelsPlugin(BeetsPlugin):
def __init__(self):
super().__init__()
self.item_queries = {"label": HasLabelQuery}
self.item_queries = {"playlist": InPlaylistQuery}
playlists_config = self.config['playlists'].get()
initialize_playlists(playlists_config)

View file

@ -8,31 +8,14 @@ import json
playlist_config = {}
def expand_playlist_query(playlist_name):
return playlist_config[playlist_name]
def initialize_playlists(playlists):
for playlist in playlists:
playlist_config[playlist["name"]] = \
playlist["query"]
class InPlaylistQuery(FieldQuery):
def __init__(self, _, pattern: str, __):
super().__init__(LABELS_FIELD_NAME, pattern, False)
@classmethod
def value_match(self, pattern, jsonstr):
if jsonstr is not None:
playlist = pattern
labels = json.loads(jsonstr)
if playlist in labels:
# This song has been explicitly added to the playlist
return True
for label in playlist_config[playlist]:
if label in labels:
return True
return False
class PlaylistValueSort(SlowFieldSort):
def __init__(self, field, ascending=True, case_insensitive=True):
super().__init__(field, ascending, case_insensitive)