mirror of
https://github.com/nathom/streamrip.git
synced 2025-05-22 03:05:26 -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 os
|
||||
import re
|
||||
from functools import cache
|
||||
from pprint import pformat, pprint
|
||||
|
||||
from ruamel.yaml import YAML
|
||||
|
@ -15,6 +16,7 @@ from .constants import (
|
|||
TRACK_FORMAT,
|
||||
)
|
||||
from .exceptions import InvalidSourceError
|
||||
from .utils import safe_get
|
||||
|
||||
yaml = YAML()
|
||||
|
||||
|
@ -149,6 +151,9 @@ class Config:
|
|||
logger.debug("Config saved: %s", self._path)
|
||||
yaml.dump(info, cfg)
|
||||
|
||||
docs = ConfigDocumentation()
|
||||
docs.dump(self._path)
|
||||
|
||||
@property
|
||||
def tidal_creds(self):
|
||||
"""Return a TidalClient compatible dict of credentials."""
|
||||
|
@ -194,20 +199,17 @@ class Config:
|
|||
return f"Config({pformat(self.session)})"
|
||||
|
||||
|
||||
class ConfigDocumentationHelper:
|
||||
"""A helper class that writes documentation for the config file.
|
||||
class ConfigDocumentation:
|
||||
"""Documentation is stored in this docstring.
|
||||
qobuz:
|
||||
quality: 1: 320kbps MP3, 2: 16/44.1, 3: 24/<=96, 4: 24/>=96
|
||||
app_id: Do not change
|
||||
secrets: Do not change
|
||||
tidal:
|
||||
quality: 0, 1, 2, or 3
|
||||
user_id: Do not change
|
||||
country_code: Do not change
|
||||
access_token: Do not change
|
||||
refresh_token: Do not change
|
||||
token_expiry: Do not change
|
||||
deezer: Does not require login
|
||||
user_id: Do not change any of the fields below
|
||||
token_expiry: Tokens last 1 week after refresh. This is the Unix timestamp of the expiration time.
|
||||
deezer: Deezer doesn't require login
|
||||
quality: 0, 1, or 2
|
||||
soundcloud:
|
||||
quality: Only 0 is available
|
||||
|
@ -233,32 +235,75 @@ class ConfigDocumentationHelper:
|
|||
track: Available keys: "tracknumber", "artist", "albumartist", "composer", and "title"
|
||||
lastfm: Last.fm playlists are downloaded by searching for the titles of 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):
|
||||
self.docs = []
|
||||
doctext = self.__doc__
|
||||
# get indent level, key, and documentation
|
||||
keyval = re.compile(r"( *)([\w_]+):\s*(.*)")
|
||||
lines = (line[4:] for line in doctext.split("\n")[1:-1])
|
||||
|
||||
for line in lines:
|
||||
info = list(keyval.match(line).groups())
|
||||
if len(info) == 3:
|
||||
info[0] = len(info[0]) // 4
|
||||
else:
|
||||
info[0] = len(info[0]) // 4 # here use standard 4 spaces/tab
|
||||
else: # line doesn't start with spaces
|
||||
info.insert(0, 0)
|
||||
|
||||
self.docs.append(info)
|
||||
pprint(self.docs)
|
||||
|
||||
def write(self):
|
||||
pass
|
||||
def dump(self, path: str):
|
||||
"""Write comments to an uncommented YAML file.
|
||||
|
||||
def __setitem__(self, key, val):
|
||||
self.comments[key] = val
|
||||
:param path:
|
||||
: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):
|
||||
return self.comments[key]
|
||||
with open(path, "w") as f:
|
||||
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