mirror of
https://github.com/nathom/streamrip.git
synced 2025-05-22 11:15:30 -04:00
Add annotations in config file
This commit is contained in:
parent
0304fae688
commit
a3dda3768a
1 changed files with 65 additions and 20 deletions
|
@ -3,6 +3,7 @@ import copy
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
from functools import cache
|
||||||
from pprint import pformat, pprint
|
from pprint import pformat, pprint
|
||||||
|
|
||||||
from ruamel.yaml import YAML
|
from ruamel.yaml import YAML
|
||||||
|
@ -15,6 +16,7 @@ from .constants import (
|
||||||
TRACK_FORMAT,
|
TRACK_FORMAT,
|
||||||
)
|
)
|
||||||
from .exceptions import InvalidSourceError
|
from .exceptions import InvalidSourceError
|
||||||
|
from .utils import safe_get
|
||||||
|
|
||||||
yaml = YAML()
|
yaml = YAML()
|
||||||
|
|
||||||
|
@ -149,6 +151,9 @@ class Config:
|
||||||
logger.debug("Config saved: %s", self._path)
|
logger.debug("Config saved: %s", self._path)
|
||||||
yaml.dump(info, cfg)
|
yaml.dump(info, cfg)
|
||||||
|
|
||||||
|
docs = ConfigDocumentation()
|
||||||
|
docs.dump(self._path)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def tidal_creds(self):
|
def tidal_creds(self):
|
||||||
"""Return a TidalClient compatible dict of credentials."""
|
"""Return a TidalClient compatible dict of credentials."""
|
||||||
|
@ -194,20 +199,17 @@ class Config:
|
||||||
return f"Config({pformat(self.session)})"
|
return f"Config({pformat(self.session)})"
|
||||||
|
|
||||||
|
|
||||||
class ConfigDocumentationHelper:
|
class ConfigDocumentation:
|
||||||
"""A helper class that writes documentation for the config file.
|
"""Documentation is stored in this docstring.
|
||||||
qobuz:
|
qobuz:
|
||||||
quality: 1: 320kbps MP3, 2: 16/44.1, 3: 24/<=96, 4: 24/>=96
|
quality: 1: 320kbps MP3, 2: 16/44.1, 3: 24/<=96, 4: 24/>=96
|
||||||
app_id: Do not change
|
app_id: Do not change
|
||||||
secrets: Do not change
|
secrets: Do not change
|
||||||
tidal:
|
tidal:
|
||||||
quality: 0, 1, 2, or 3
|
quality: 0, 1, 2, or 3
|
||||||
user_id: Do not change
|
user_id: Do not change any of the fields below
|
||||||
country_code: Do not change
|
token_expiry: Tokens last 1 week after refresh. This is the Unix timestamp of the expiration time.
|
||||||
access_token: Do not change
|
deezer: Deezer doesn't require login
|
||||||
refresh_token: Do not change
|
|
||||||
token_expiry: Do not change
|
|
||||||
deezer: Does not require login
|
|
||||||
quality: 0, 1, or 2
|
quality: 0, 1, or 2
|
||||||
soundcloud:
|
soundcloud:
|
||||||
quality: Only 0 is available
|
quality: Only 0 is available
|
||||||
|
@ -233,32 +235,75 @@ class ConfigDocumentationHelper:
|
||||||
track: Available keys: "tracknumber", "artist", "albumartist", "composer", and "title"
|
track: Available keys: "tracknumber", "artist", "albumartist", "composer", and "title"
|
||||||
lastfm: Last.fm playlists are downloaded by searching for the titles of the tracks
|
lastfm: Last.fm playlists are downloaded by searching for the titles of the tracks
|
||||||
source: The source on which to search for the tracks.
|
source: The source on which to search for the tracks.
|
||||||
concurrent_downoads: Download (and convert) tracks all at once, instead of sequentially. If you are converting the tracks, and/or have fast internet, this will substantially improve processing speed.
|
concurrent_downloads: Download (and convert) tracks all at once, instead of sequentially. If you are converting the tracks, and/or have fast internet, this will substantially improve processing speed.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
comments = _set_to_none(copy.deepcopy(Config.defaults))
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.docs = []
|
self.docs = []
|
||||||
doctext = self.__doc__
|
doctext = self.__doc__
|
||||||
|
# get indent level, key, and documentation
|
||||||
keyval = re.compile(r"( *)([\w_]+):\s*(.*)")
|
keyval = re.compile(r"( *)([\w_]+):\s*(.*)")
|
||||||
lines = (line[4:] for line in doctext.split("\n")[1:-1])
|
lines = (line[4:] for line in doctext.split("\n")[1:-1])
|
||||||
|
|
||||||
for line in lines:
|
for line in lines:
|
||||||
info = list(keyval.match(line).groups())
|
info = list(keyval.match(line).groups())
|
||||||
if len(info) == 3:
|
if len(info) == 3:
|
||||||
info[0] = len(info[0]) // 4
|
info[0] = len(info[0]) // 4 # here use standard 4 spaces/tab
|
||||||
else:
|
else: # line doesn't start with spaces
|
||||||
info.insert(0, 0)
|
info.insert(0, 0)
|
||||||
|
|
||||||
self.docs.append(info)
|
self.docs.append(info)
|
||||||
pprint(self.docs)
|
|
||||||
|
|
||||||
def write(self):
|
def dump(self, path: str):
|
||||||
pass
|
"""Write comments to an uncommented YAML file.
|
||||||
|
|
||||||
def __setitem__(self, key, val):
|
:param path:
|
||||||
self.comments[key] = val
|
:type path: str
|
||||||
|
"""
|
||||||
|
is_comment = re.compile(r"^\s*#.*")
|
||||||
|
with open(path) as f:
|
||||||
|
# includes newline at the end
|
||||||
|
lines = f.readlines()
|
||||||
|
|
||||||
def __getitem__(self, key):
|
with open(path, "w") as f:
|
||||||
return self.comments[key]
|
while lines != []:
|
||||||
|
line = lines.pop(0)
|
||||||
|
found = False
|
||||||
|
to_remove = None
|
||||||
|
for level, key, doc in self.docs:
|
||||||
|
# using 1 indent = 2 spaces like ruamel.yaml
|
||||||
|
spaces = level * " "
|
||||||
|
comment = f"{spaces}# {doc}"
|
||||||
|
|
||||||
|
if is_comment.match(line):
|
||||||
|
# update comment
|
||||||
|
found = True
|
||||||
|
break
|
||||||
|
|
||||||
|
re_obj = self._get_key_regex(spaces, key)
|
||||||
|
match = re_obj.match(line)
|
||||||
|
if match is not None: # line contains the key
|
||||||
|
if doc != "":
|
||||||
|
f.write(f"{comment}\n{line}")
|
||||||
|
found = True
|
||||||
|
to_remove = [level, key, doc]
|
||||||
|
break
|
||||||
|
|
||||||
|
if not found: # field with no comment
|
||||||
|
f.write(line)
|
||||||
|
|
||||||
|
if to_remove is not None:
|
||||||
|
# key, doc pairs are unique
|
||||||
|
self.docs.remove(to_remove)
|
||||||
|
|
||||||
|
@cache
|
||||||
|
def _get_key_regex(self, spaces, key):
|
||||||
|
regex = rf"{spaces}{key}:(?:$|\s+?(.+))"
|
||||||
|
return re.compile(regex)
|
||||||
|
|
||||||
|
def strip_comments(self, path: str):
|
||||||
|
with open(path, "r") as f:
|
||||||
|
lines = [line for line in f.readlines() if not line.strip().startswith("#")]
|
||||||
|
|
||||||
|
with open(path, "w") as f:
|
||||||
|
f.write("".join(lines))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue