Add various TODOs.
This commit is contained in:
parent
49c7cc9a05
commit
018a651d28
1 changed files with 38 additions and 9 deletions
|
@ -5,19 +5,14 @@ import tomllib
|
||||||
from datetime import datetime, time
|
from datetime import datetime, time
|
||||||
from apscheduler.triggers.cron import CronTrigger
|
from apscheduler.triggers.cron import CronTrigger
|
||||||
|
|
||||||
# setup logging
|
# Setup Logging. NOTE: Declaration as a global variable is necessary to ensure correct functionality across multiple modules.
|
||||||
logger = logging.getLogger("wallman")
|
logger = logging.getLogger("wallman")
|
||||||
|
|
||||||
class ConfigError(Exception):
|
class ConfigError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class _ConfigLib:
|
class _ConfigLib:
|
||||||
def _initialize_config(self) -> dict:
|
# Initializes the most important config values. TODO: Add handling for the empty config case
|
||||||
chdir(str(getenv("HOME")) + "/.config/wallman/")
|
|
||||||
with open("wallman.toml", "rb") as config_file:
|
|
||||||
data = tomllib.load(config_file)
|
|
||||||
return data
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.config_file: dict = self._initialize_config() # Full config
|
self.config_file: dict = self._initialize_config() # Full config
|
||||||
# Dictionaries
|
# Dictionaries
|
||||||
|
@ -29,10 +24,11 @@ class _ConfigLib:
|
||||||
self.config_wallpapers_per_set: int = self.config_general["wallpapers_per_set"]
|
self.config_wallpapers_per_set: int = self.config_general["wallpapers_per_set"]
|
||||||
self.config_total_changing_times: int = len(self.config_changing_times)
|
self.config_total_changing_times: int = len(self.config_changing_times)
|
||||||
self.config_log_level: str = self.config_general.get("loglevel", "INFO").upper()
|
self.config_log_level: str = self.config_general.get("loglevel", "INFO").upper()
|
||||||
|
# HACK: Add a function to handle these try/except blocks cleanlier.
|
||||||
try:
|
try:
|
||||||
self.config_notify: bool = self.config_general["notify"]
|
self.config_notify: bool = self.config_general["notify"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
self.config_notify = False
|
self.config_notify: bool = False
|
||||||
logger.warning("'notify' is not set in dictionary general in the config file, defaulting to 'false'.")
|
logger.warning("'notify' is not set in dictionary general in the config file, defaulting to 'false'.")
|
||||||
try:
|
try:
|
||||||
self.config_systray = self.config_general["systray"]
|
self.config_systray = self.config_general["systray"]
|
||||||
|
@ -40,12 +36,20 @@ class _ConfigLib:
|
||||||
self.config_systray = True
|
self.config_systray = True
|
||||||
logger.warning("'systray' is not set in the dictionary general in the config file, defaulting to 'true'.")
|
logger.warning("'systray' is not set in the dictionary general in the config file, defaulting to 'true'.")
|
||||||
|
|
||||||
|
|
||||||
# Setup logging
|
# Setup logging
|
||||||
self._set_log_level()
|
self._set_log_level()
|
||||||
|
# Setup systray.
|
||||||
if self.config_systray:
|
if self.config_systray:
|
||||||
self._initialize_systray()
|
self._initialize_systray()
|
||||||
|
|
||||||
|
# Read config. TODO: Add error handling for the config not found case.
|
||||||
|
def _initialize_config(self) -> dict:
|
||||||
|
chdir(str(getenv("HOME")) + "/.config/wallman/")
|
||||||
|
with open("wallman.toml", "rb") as config_file:
|
||||||
|
data = tomllib.load(config_file)
|
||||||
|
return data
|
||||||
|
|
||||||
|
# HACK on this to avoid double importing of wallman_systray due to variable scope. Idea: Global variable or Variable that is inherited?
|
||||||
def _initialize_systray(self):
|
def _initialize_systray(self):
|
||||||
try:
|
try:
|
||||||
import wallman_systray
|
import wallman_systray
|
||||||
|
@ -69,6 +73,7 @@ class _ConfigLib:
|
||||||
raise ConfigError("An error occured and no fallback wallpaper has been set, exiting...")
|
raise ConfigError("An error occured and no fallback wallpaper has been set, exiting...")
|
||||||
|
|
||||||
class ConfigValidity(_ConfigLib):
|
class ConfigValidity(_ConfigLib):
|
||||||
|
# TODO: Add handling for the empty config case.
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
|
@ -96,6 +101,8 @@ class ConfigValidity(_ConfigLib):
|
||||||
raise ConfigError("Please provide an amount of changing_times equal to wallpapers_per_set, exiting...")
|
raise ConfigError("Please provide an amount of changing_times equal to wallpapers_per_set, exiting...")
|
||||||
|
|
||||||
def _check_general_validity(self) -> bool:
|
def _check_general_validity(self) -> bool:
|
||||||
|
# FIXME!
|
||||||
|
# HACK: Adjust it to check for the actually required variables existing rather than check if a number of options is set, which is highly error prone.
|
||||||
if len(self.config_general) < 3:
|
if len(self.config_general) < 3:
|
||||||
try:
|
try:
|
||||||
self._set_fallback_wallpaper()
|
self._set_fallback_wallpaper()
|
||||||
|
@ -116,6 +123,7 @@ class ConfigValidity(_ConfigLib):
|
||||||
if wallpaper_set in self.config_file:
|
if wallpaper_set in self.config_file:
|
||||||
logger.debug(f"The dictionary {wallpaper_set} has been found in config.")
|
logger.debug(f"The dictionary {wallpaper_set} has been found in config.")
|
||||||
return True
|
return True
|
||||||
|
# TODO split this into smaller pieces. This goes too deep.
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
self._set_fallback_wallpaper()
|
self._set_fallback_wallpaper()
|
||||||
|
@ -143,6 +151,8 @@ class ConfigValidity(_ConfigLib):
|
||||||
raise ConfigError(f"Dictionary {wallpaper_set} does not have the correct amount of entries, exciting...")
|
raise ConfigError(f"Dictionary {wallpaper_set} does not have the correct amount of entries, exciting...")
|
||||||
|
|
||||||
def validate_config(self) -> bool:
|
def validate_config(self) -> bool:
|
||||||
|
# NOTE: Consider changing this to exit(-1)
|
||||||
|
# HACK: Consider using different exit codes for different errors to help users debug.
|
||||||
if not self._check_fallback_wallpaper():
|
if not self._check_fallback_wallpaper():
|
||||||
pass
|
pass
|
||||||
if not self._check_wallpapers_per_set_and_changing_times():
|
if not self._check_wallpapers_per_set_and_changing_times():
|
||||||
|
@ -156,22 +166,28 @@ class ConfigValidity(_ConfigLib):
|
||||||
logger.debug("The config file has been validated successfully (No Errors)")
|
logger.debug("The config file has been validated successfully (No Errors)")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
# TODO: Improve modularity. See notes inside the class for more details.
|
||||||
|
# TODO: Ensure functionality and if needed add handling for the 1 wallpaper per set case.
|
||||||
class WallpaperLogic(_ConfigLib):
|
class WallpaperLogic(_ConfigLib):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
# NOTE: This looks a bit ugly. Consider pros and cons of adding this into _ConfigLib
|
||||||
self.chosen_wallpaper_set = False
|
self.chosen_wallpaper_set = False
|
||||||
|
|
||||||
|
# NOTE: This function could be in a different file because it's not needed in the case only 1 wallpaper per set is needed.
|
||||||
# Returns a list of a split string that contains a changing time from the config file
|
# Returns a list of a split string that contains a changing time from the config file
|
||||||
def _clean_times(self, desired_time) -> list:
|
def _clean_times(self, desired_time) -> list:
|
||||||
unclean_times = list(self.config_changing_times.values())[desired_time]
|
unclean_times = list(self.config_changing_times.values())[desired_time]
|
||||||
return unclean_times.split(":")
|
return unclean_times.split(":")
|
||||||
|
|
||||||
|
# NOTE: This could be in a different file because it's not needed in the "Only one wallpaper set" case.
|
||||||
def _choose_wallpaper_set(self) -> None:
|
def _choose_wallpaper_set(self) -> None:
|
||||||
from random import choice as choose_from
|
from random import choice as choose_from
|
||||||
self.chosen_wallpaper_set = choose_from(self.config_used_sets)
|
self.chosen_wallpaper_set = choose_from(self.config_used_sets)
|
||||||
self.wallpaper_list = list(self.config_file[self.chosen_wallpaper_set].values())
|
self.wallpaper_list = list(self.config_file[self.chosen_wallpaper_set].values())
|
||||||
logger.debug(f"Chose wallpaper set {self.chosen_wallpaper_set}")
|
logger.debug(f"Chose wallpaper set {self.chosen_wallpaper_set}")
|
||||||
|
|
||||||
|
# NOTE: Same as _clean_times()
|
||||||
# Verify if a given time is in a given range
|
# Verify if a given time is in a given range
|
||||||
def _time_in_range(self, start, end, x) -> bool:
|
def _time_in_range(self, start, end, x) -> bool:
|
||||||
if start <= end:
|
if start <= end:
|
||||||
|
@ -179,6 +195,7 @@ class WallpaperLogic(_ConfigLib):
|
||||||
else:
|
else:
|
||||||
return start <= x or x < end
|
return start <= x or x < end
|
||||||
|
|
||||||
|
# NOTE: Potentially add handling for this to be also usable for notify_user and add logging if notify_user fails. Consider adding an argument that is where it's called from and handle accordingly.
|
||||||
def _check_system_exitcode(self, code) -> bool:
|
def _check_system_exitcode(self, code) -> bool:
|
||||||
if code != 0:
|
if code != 0:
|
||||||
try:
|
try:
|
||||||
|
@ -194,10 +211,15 @@ class WallpaperLogic(_ConfigLib):
|
||||||
logger.info(f"The wallpaper {self.wallpaper_list[self.current_time_range]} has been set.")
|
logger.info(f"The wallpaper {self.wallpaper_list[self.current_time_range]} has been set.")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
# NOTE: Add error handling in case libnotify is not installed or notify-send fails for any other reason.
|
||||||
|
# TODO: Add a check whether config[notify] is true or not.
|
||||||
def _notify_user(self):
|
def _notify_user(self):
|
||||||
system("notify-send 'Wallman' 'A new Wallpaper has been set.'")
|
system("notify-send 'Wallman' 'A new Wallpaper has been set.'")
|
||||||
logger.debug("Sent desktop notification.")
|
logger.debug("Sent desktop notification.")
|
||||||
|
|
||||||
|
# TODO: Clean this up. It's way too large and way too intimidating.
|
||||||
|
# NOTE: This could be in a different for the case that the user only wants 1 wallpaper per set.
|
||||||
|
# TODO: Add an way for the user to choose if the wallpaper should scale, fill or otherwise. This needs to be editable in the config file.
|
||||||
def set_wallpaper_by_time(self) -> bool:
|
def set_wallpaper_by_time(self) -> bool:
|
||||||
# Ensure use of a consistent wallpaper set
|
# Ensure use of a consistent wallpaper set
|
||||||
if self.chosen_wallpaper_set is False:
|
if self.chosen_wallpaper_set is False:
|
||||||
|
@ -206,11 +228,14 @@ class WallpaperLogic(_ConfigLib):
|
||||||
self.current_time_range = time_range # Store current time for better debugging output
|
self.current_time_range = time_range # Store current time for better debugging output
|
||||||
clean_time = self._clean_times(time_range)
|
clean_time = self._clean_times(time_range)
|
||||||
clean_time_two = self._clean_times(time_range + 1)
|
clean_time_two = self._clean_times(time_range + 1)
|
||||||
|
# HACK on this to make it more readable. This function call is way too long. Consider storing these in a bunch of temporary variables, though keep function length in mind.
|
||||||
|
# HACK on this to see if this logic can be simplified. It's very ugly to check it that way.
|
||||||
# Check if the current time is between a given and the following changing time and if so, set that wallpaper. If not, keep trying.
|
# Check if the current time is between a given and the following changing time and if so, set that wallpaper. If not, keep trying.
|
||||||
if self._time_in_range(time(int(clean_time[0]), int(clean_time[1]), int(clean_time[2])), time(int(clean_time_two[0]), int(clean_time_two[1]), int(clean_time_two[2])), datetime.now().time()):
|
if self._time_in_range(time(int(clean_time[0]), int(clean_time[1]), int(clean_time[2])), time(int(clean_time_two[0]), int(clean_time_two[1]), int(clean_time_two[2])), datetime.now().time()):
|
||||||
system(f"feh --bg-scale --no-fehbg --quiet {self.wallpaper_list[time_range]}")
|
system(f"feh --bg-scale --no-fehbg --quiet {self.wallpaper_list[time_range]}")
|
||||||
exitcode = system(f"feh --bg-scale --no-fehbg --quiet {self.wallpaper_list[time_range]}")
|
exitcode = system(f"feh --bg-scale --no-fehbg --quiet {self.wallpaper_list[time_range]}")
|
||||||
has_wallpaper_been_set = self._check_system_exitcode(exitcode)
|
has_wallpaper_been_set = self._check_system_exitcode(exitcode)
|
||||||
|
# TODO: Add this check to _notify_user.
|
||||||
if self.config_notify:
|
if self.config_notify:
|
||||||
self._notify_user()
|
self._notify_user()
|
||||||
return has_wallpaper_been_set
|
return has_wallpaper_been_set
|
||||||
|
@ -224,11 +249,13 @@ class WallpaperLogic(_ConfigLib):
|
||||||
self._notify_user()
|
self._notify_user()
|
||||||
return has_wallpaper_been_set
|
return has_wallpaper_been_set
|
||||||
|
|
||||||
|
# NOTE: Consider avoiding nested functions.
|
||||||
def schedule_wallpapers(self):
|
def schedule_wallpapers(self):
|
||||||
def _schedule_background_wallpapers():
|
def _schedule_background_wallpapers():
|
||||||
from apscheduler.schedulers.background import BackgroundScheduler
|
from apscheduler.schedulers.background import BackgroundScheduler
|
||||||
scheduler = BackgroundScheduler()
|
scheduler = BackgroundScheduler()
|
||||||
# Create a scheduled job for every changing time
|
# Create a scheduled job for every changing time
|
||||||
|
# NOTE: This should be a function.
|
||||||
for changing_time in range(len(self.config_changing_times)):
|
for changing_time in range(len(self.config_changing_times)):
|
||||||
clean_time = self._clean_times(changing_time)
|
clean_time = self._clean_times(changing_time)
|
||||||
scheduler.add_job(self.set_wallpaper_by_time, trigger=CronTrigger(hour=clean_time[0], minute=clean_time[1], second=clean_time[2]))
|
scheduler.add_job(self.set_wallpaper_by_time, trigger=CronTrigger(hour=clean_time[0], minute=clean_time[1], second=clean_time[2]))
|
||||||
|
@ -240,6 +267,7 @@ class WallpaperLogic(_ConfigLib):
|
||||||
from apscheduler.schedulers.blocking import BlockingScheduler
|
from apscheduler.schedulers.blocking import BlockingScheduler
|
||||||
scheduler = BlockingScheduler()
|
scheduler = BlockingScheduler()
|
||||||
# Create a scheduled job for every changing time
|
# Create a scheduled job for every changing time
|
||||||
|
# NOTE: Thisshould be a function.
|
||||||
for changing_time in range(len(self.config_changing_times)):
|
for changing_time in range(len(self.config_changing_times)):
|
||||||
clean_time = self._clean_times(changing_time)
|
clean_time = self._clean_times(changing_time)
|
||||||
scheduler.add_job(self.set_wallpaper_by_time, trigger=CronTrigger(hour=clean_time[0], minute=clean_time[1], second=clean_time[2]))
|
scheduler.add_job(self.set_wallpaper_by_time, trigger=CronTrigger(hour=clean_time[0], minute=clean_time[1], second=clean_time[2]))
|
||||||
|
@ -247,6 +275,7 @@ class WallpaperLogic(_ConfigLib):
|
||||||
scheduler.start()
|
scheduler.start()
|
||||||
|
|
||||||
if self.config_systray:
|
if self.config_systray:
|
||||||
|
# NOTE: The wallman_systray impomrt should be handled differently. See the note in Config_Validity.
|
||||||
import wallman_systray as systray
|
import wallman_systray as systray
|
||||||
from functools import partial
|
from functools import partial
|
||||||
scheduler = _schedule_background_wallpapers()
|
scheduler = _schedule_background_wallpapers()
|
||||||
|
|
Loading…
Reference in a new issue