Add annotations in config file

This commit is contained in:
nathom 2021-04-14 18:30:27 -07:00
parent 0304fae688
commit a3dda3768a

View file

@ -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))