Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

formatter: add {:sanitize} to return song or song [feat] #2237

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions py3status/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,3 +270,31 @@
MARKUP_LANGUAGES = ["pango", "none"]

ON_ERROR_VALUES = ["hide", "show"]

SANITIZE_TITLES = "|".join(
[
"bonus",
"demo",
"edit",
"explicit",
"extended",
"feat",
"mono",
"remaster",
"stereo",
"version",
]
)

SANITIZE_PATTERNS = {
# Match brackets with their content containing any metadata word.
# (Remastered 2017)
# [Single]
# (Bonus Track)
"inside_brackets": r"([\(\[][^)\]]*?({})[^)\]]*?[\)\]])".format(SANITIZE_TITLES),
# Match string after hyphen, comma, semicolon or slash containing any metadata word.
# - Remastered 2012
# / Radio Edit
# ; Remastered
"after_delimiter": r"([\-,;/])([^\-,;/])*({}).*".format(SANITIZE_TITLES),
}
29 changes: 28 additions & 1 deletion py3status/formatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from urllib.parse import parse_qsl

from py3status.composite import Composite
from py3status.constants import COLOR_NAMES, COLOR_NAMES_EXCLUDED
from py3status.constants import COLOR_NAMES, COLOR_NAMES_EXCLUDED, SANITIZE_PATTERNS


def expand_color(color, default=None, passthrough=False, block=None):
Expand Down Expand Up @@ -296,10 +296,35 @@ class Placeholder:
Class representing a {placeholder}
"""

sanitized_regex_cache = {}
sanitized_string_cache = {}

def __init__(self, key, format):
self.key = key
self.format = format

def _sanitize(self, string):
"""
Remove redundant metadata from string and return it
"""
try:
return self.sanitized_string_cache[string]
except KeyError:
cache_key = string
Comment on lines +310 to +313
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed? The composites may could be cached. Maybe regex cache only... Something to look into.


# add compiled sanitized regexes to the cache
if not self.sanitized_regex_cache:
for sanitize_key, sanitize_value in SANITIZE_PATTERNS.items():
self.sanitized_regex_cache[sanitize_key] = re.compile(sanitize_value, re.IGNORECASE)

# sanitize the strings
for pattern in self.sanitized_regex_cache.values():
string = re.sub(pattern, "", string).strip()

# add sanitized strings to the cache
self.sanitized_string_cache[cache_key] = string
return string

def get(self, get_params, block):
"""
return the correct value for the placeholder
Expand Down Expand Up @@ -327,6 +352,8 @@ def get(self, get_params, block):
value = float(value)
if "d" in self.format:
value = int(float(value))
if "sanitize" in self.format:
value = self._sanitize(value)
output = f"{{[{self.key}]{self.format}}}"
value = output.format({self.key: value})
value_ = float(value)
Expand Down
54 changes: 0 additions & 54 deletions py3status/modules/spotify.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,6 @@
(default 'Spotify not running')
format_stopped: define output if spotify is not playing
(default 'Spotify stopped')
sanitize_titles: whether to remove meta data from album/track title
(default True)
sanitize_words: which meta data to remove
*(default ['bonus', 'demo', 'edit', 'explicit', 'extended',
'feat', 'mono', 'remaster', 'stereo', 'version'])*

Format placeholders:
{album} album name
Expand Down Expand Up @@ -60,7 +55,6 @@
{'color': '#FF0000', 'full_text': 'Spotify stopped'}
"""

import re
from datetime import timedelta
from time import sleep

Expand All @@ -82,47 +76,10 @@ class Py3status:
format = "{artist} : {title}"
format_down = "Spotify not running"
format_stopped = "Spotify stopped"
sanitize_titles = True
sanitize_words = [
"bonus",
"demo",
"edit",
"explicit",
"extended",
"feat",
"mono",
"remaster",
"stereo",
"version",
]

def _spotify_cmd(self, action):
return SPOTIFY_CMD.format(dbus_client=self.dbus_client, cmd=action)

def post_config_hook(self):
""" """
# Match string after hyphen, comma, semicolon or slash containing any metadata word
# examples:
# - Remastered 2012
# / Radio Edit
# ; Remastered
self.after_delimiter = self._compile_re(r"([\-,;/])([^\-,;/])*(META_WORDS_HERE).*")

# Match brackets with their content containing any metadata word
# examples:
# (Remastered 2017)
# [Single]
# (Bonus Track)
self.inside_brackets = self._compile_re(r"([\(\[][^)\]]*?(META_WORDS_HERE)[^)\]]*?[\)\]])")

def _compile_re(self, expression):
"""
Compile given regular expression for current sanitize words
"""
meta_words = "|".join(self.sanitize_words)
expression = expression.replace("META_WORDS_HERE", meta_words)
return re.compile(expression, re.IGNORECASE)

def _get_playback_status(self):
"""
Get the playback status. One of: "Playing", "Paused" or "Stopped".
Expand All @@ -145,9 +102,6 @@ def _get_text(self):
microtime = metadata.get("mpris:length")
rtime = str(timedelta(seconds=microtime // 1_000_000))
title = metadata.get("xesam:title")
if self.sanitize_titles:
album = self._sanitize_title(album)
title = self._sanitize_title(title)

playback_status = self._get_playback_status()
if playback_status == "Playing":
Expand Down Expand Up @@ -176,14 +130,6 @@ def _get_text(self):
except Exception:
return (self.format_down, self.py3.COLOR_OFFLINE or self.py3.COLOR_BAD)

def _sanitize_title(self, title):
"""
Remove redundant metadata from title and return it
"""
title = re.sub(self.inside_brackets, "", title)
title = re.sub(self.after_delimiter, "", title)
return title.strip()

def spotify(self):
"""
Get the current "artist - title" and return it.
Expand Down
Loading