Updated doreah toolkit

This commit is contained in:
Krateng 2019-03-29 18:40:55 +01:00
parent b8e4158336
commit 5cd6752510
3 changed files with 168 additions and 147 deletions

29
doreah/_internal.py Normal file
View File

@ -0,0 +1,29 @@
import os
## decorator to set default arguments that are only evaluated at runtime
def defaultarguments(defaultdict,**defaultargs):
def decorator(func): #actual decorator function
def newfunc(*args,**kwargs):
realargs = {}
# evaluate default values at runtime
for k in defaultargs:
realargs[k] = defaultdict[defaultargs[k]]
# overwrite given arguments of function
realargs.update(kwargs)
# execute function with correct arguments
return func(*args,**realargs)
return newfunc
return decorator
## opens file, creates it if necessary (including all folders)
def gopen(filepath,mode):
directory = os.path.dirname(filepath)
os.makedirs(directory, exist_ok=True)
return open(filepath,mode)

View File

@ -1,6 +1,11 @@
import os import os
import shutil import shutil
from ._internal import defaultarguments
_config = {}
# set configuration # set configuration
# defaultextension unused # defaultextension unused
# files list of all files that will be used for configuration. high indicies overwrite low indicies # files list of all files that will be used for configuration. high indicies overwrite low indicies
@ -9,186 +14,173 @@ import shutil
# onlytext interpret everything as a string. if False, strings can be put into quotes to avoid confusion # onlytext interpret everything as a string. if False, strings can be put into quotes to avoid confusion
def config(defaultextension=".ini",files=["settings.ini","settings.conf","configuration.ini","configuration.conf"], def config(defaultextension=".ini",files=["settings.ini","settings.conf","configuration.ini","configuration.conf"],
comment=["#","//"],category=("[","]"),onlytext=False): comment=["#","//"],category=("[","]"),onlytext=False):
global _defaultextension, _files, _comment, _category, _onlytext
_defaultextension = defaultextension
_files = files
_comment = comment
_category = category
_onlytext = onlytext
global _config
_config["defaultextension"] = defaultextension
_config["files"] = files
_config["comment"] = comment
_config["category"] = category
_config["onlytext"] = onlytext
global Settings, get_settings, update_settings, update # initial config on import, set everything to default
config()
# manager object so we can read settings once and retain them
class Settings:
def __init__(self,**kwargs):
self.settings = get_settings(**kwargs)
def get(self,*keys):
result = (self.settings.get(k) for k in keys)
if len(result) == 1: result = result[0]
return result
def _interpret(text): def _interpret(text):
if _onlytext: return text if _config["onlytext"]: return text
if text.lower() in ["true","yes"]: return True if text.lower() in ["true","yes"]: return True
if text.lower() in ["false","no"]: return False if text.lower() in ["false","no"]: return False
if text.lower() in ["none","nan","n/a",""]: return None if text.lower() in ["none","nan","n/a",""]: return None
if text.startswith("'") and text.endswith("'"): return text[1:-1] if text.startswith("'") and text.endswith("'"): return text[1:-1]
if text.startswith('"') and text.endswith('"'): return text[1:-1] if text.startswith('"') and text.endswith('"'): return text[1:-1]
try: try:
return int(text) return int(text)
except: except:
pass pass
try: try:
return float(text) return float(text)
except: except:
pass pass
return text return text
# get settings # get settings
# keys list of requested keys. if present, will return list of according values, if not, will return dict of key-value pairs # keys list of requested keys. if present, will return list of according values, if not, will return dict of key-value pairs
# files which files to parse. later files (higher indicies) will overload earlier ones # files which files to parse. later files (higher indicies) will overload earlier ones
# prefix only request keys with a certain prefix. key filter will still be applied if present # prefix only request keys with a certain prefix. key filter will still be applied if present
# cut_prefix return keys without the prefix # cut_prefix return keys without the prefix
# category return only keys of specific category # category return only keys of specific category
# raw do not interpret data type, only return strings # raw do not interpret data type, only return strings
def get_settings(*keys,files=_files,prefix="",cut_prefix=False,category=None,raw=False): @defaultarguments(_config,files="files")
def get_settings(*keys,files,prefix="",cut_prefix=False,category=None,raw=False):
allsettings = {} allsettings = {}
for f in files: for f in files:
if not os.path.exists(f): continue if not os.path.exists(f): continue
# if category is specified, ignore all entries by default and switch when we encounter the right heading # if category is specified, ignore all entries by default and switch when we encounter the right heading
ignore = False if category is None else True ignore = False if category is None else True
with open(f) as file: with open(f) as file:
lines = file.readlines() lines = file.readlines()
for l in lines: for l in lines:
# clean up line
l = l.replace("\n","")
for symbol in _comment:
l = l.split(symbol)[0]
l = l.strip()
# check if valid settings entry
if l == "": continue
if l.startswith(_category[0]):
# ignore category headers if we don't care
if category is None: continue
# otherwise, find out if this is the category we want
else:
if l.endswith(_category[1]):
cat = l[len(_category[0]):-len(_category[1])]
ignore = not (cat == category) #if this is the right heading, set ignore to false
continue
if ignore: continue
if "=" not in l: continue
# read
(key,val) = l.split("=")
key = key.strip()
val = val.strip() if raw else _interpret(val.strip())
if key.startswith(prefix):
# return keys without the common prefix
if cut_prefix:
allsettings[key[len(prefix):]] = val
# return full keys
else:
allsettings[key] = val
# no arguments means all settings
if len(keys) == 0:
return allsettings
# specific keys requested
else:
if len(keys) == 1: return allsettings.get(keys[0])
else: return [allsettings.get(k) for k in keys]
def update_settings(file,settings,create_new=False):
if not os.path.exists(file): open(file,"w").close()
with open(file,"r") as origfile:
lines = origfile.readlines()
newlines = []
for origline in lines:
l = origline
# clean up line # clean up line
l = l.replace("\n","") l = l.replace("\n","")
for symbol in _comment: for symbol in _config["comment"]:
l = l.split(symbol)[0] l = l.split(symbol)[0]
l = l.strip() l = l.strip()
# check if valid settings entry # check if valid settings entry
if l == "": if l == "": continue
newlines.append(origline) if l.startswith(_config["category"][0]):
continue # ignore category headers if we don't care
if l.startswith(_category[0]): if category is None: continue
newlines.append(origline) # otherwise, find out if this is the category we want
continue else:
if "=" not in l: if l.endswith(_config["category"][1]):
newlines.append(origline) cat = l[len(_config["category"][0]):-len(_config["category"][1])]
continue ignore = not (cat == category) #if this is the right heading, set ignore to false
continue
if ignore: continue
if "=" not in l: continue
# read # read
(key,val) = l.split("=") (key,val) = l.split("=")
key = key.strip() key = key.strip()
val = val.strip() val = val.strip() if raw else _interpret(val.strip())
if key.startswith(prefix):
# return keys without the common prefix
if cut_prefix:
allsettings[key[len(prefix):]] = val
# return full keys
else:
allsettings[key] = val
# no arguments means all settings
if len(keys) == 0:
return allsettings
# specific keys requested
else:
if len(keys) == 1: return allsettings.get(keys[0])
else: return [allsettings.get(k) for k in keys]
if key not in settings: def update_settings(file,settings,create_new=False):
newlines.append(origline)
continue
else: if not os.path.exists(file): open(file,"w").close()
#print("Found key")
newline = origline.split("=",1)
#print({"linepart":newline[1],"keytoreplace":val,"new":settings[key]})
newline[1] = newline[1].replace(val,str(settings[key]),1)
newline = "=".join(newline)
newlines.append(newline)
del settings[key] with open(file,"r") as origfile:
lines = origfile.readlines()
if create_new: newlines = []
# settings that were not present in the file
for key in settings:
newlines.append(key + " = " + settings[key] + "\n")
with open(file,"w") as newfile: for origline in lines:
newfile.write("".join(newlines)) l = origline
# clean up line
l = l.replace("\n","")
for symbol in _config["comment"]:
l = l.split(symbol)[0]
l = l.strip()
# check if valid settings entry
if l == "":
newlines.append(origline)
continue
if l.startswith(_config["category"][0]):
newlines.append(origline)
continue
if "=" not in l:
newlines.append(origline)
continue
# read
(key,val) = l.split("=")
key = key.strip()
val = val.strip()
if key not in settings:
newlines.append(origline)
continue
# updates a user settings file to a newer format from a default file without overwriting user's settings
def update(source="default_settings.ini",target="settings.ini"):
if not os.path.exists(target):
shutil.copyfile(source,target)
else: else:
usersettings = get_settings(files=[target],raw=True) #print("Found key")
shutil.copyfile(source,target) newline = origline.split("=",1)
update_settings(target,usersettings) #print({"linepart":newline[1],"keytoreplace":val,"new":settings[key]})
newline[1] = newline[1].replace(val,str(settings[key]),1)
newline = "=".join(newline)
newlines.append(newline)
del settings[key]
if create_new:
# settings that were not present in the file
for key in settings:
newlines.append(key + " = " + settings[key] + "\n")
with open(file,"w") as newfile:
newfile.write("".join(newlines))
# initial config on import, set everything to default
config()
# updates a user settings file to a newer format from a default file without overwriting user's settings
def update(source="default_settings.ini",target="settings.ini"):
if not os.path.exists(target):
shutil.copyfile(source,target)
else:
usersettings = get_settings(files=[target],raw=True)
shutil.copyfile(source,target)
update_settings(target,usersettings)

View File

@ -10,4 +10,4 @@ LASTFM_API_KEY = "ASK" # "ASK" signifies that the user has not yet indicated to
[Cache] [Cache]
CACHE_EXPIRE_NEGATIVE = 30 # after how many days negative results should be tried again CACHE_EXPIRE_NEGATIVE = 30 # after how many days negative results should be tried again
CACHE_EXPIRE_POSITIVE = none # after how many days positive results should be refreshed CACHE_EXPIRE_POSITIVE = 300 # after how many days positive results should be refreshed