From b98df634d6550ad53cb1812c4dfd0386e5d5ec71 Mon Sep 17 00:00:00 2001
From: David Trattnig <david@subsquare.at>
Date: Fri, 29 Jul 2022 19:53:45 +0200
Subject: [PATCH] Style: Lint Docstrings in `src` using Flake8 #111

---
 .flake8                                 |   5 +-
 src/aura_engine/app.py                  |  11 +-
 src/aura_engine/base/api.py             |  41 +++++--
 src/aura_engine/base/config.py          |  41 ++++---
 src/aura_engine/base/exceptions.py      |  36 ++++++
 src/aura_engine/base/logger.py          |  31 +++---
 src/aura_engine/base/utils.py           |  47 +++++---
 src/aura_engine/channels.py             |  38 ++++---
 src/aura_engine/control.py              |  73 +++++++------
 src/aura_engine/engine.py               | 137 ++++++++++++++---------
 src/aura_engine/events.py               |  57 ++++++----
 src/aura_engine/mixer.py                |  82 ++++++++------
 src/aura_engine/plugins/clock.py        |  20 ++--
 src/aura_engine/plugins/mailer.py       |  45 ++++----
 src/aura_engine/plugins/monitor.py      |  70 +++++++-----
 src/aura_engine/resources.py            |  51 +++++----
 src/aura_engine/scheduling/api.py       |  61 +++++------
 src/aura_engine/scheduling/models.py    | 139 ++++++++++--------------
 src/aura_engine/scheduling/programme.py |  67 +++++++-----
 src/aura_engine/scheduling/scheduler.py | 100 +++++++++--------
 src/aura_engine/scheduling/utils.py     |  41 +++----
 21 files changed, 694 insertions(+), 499 deletions(-)

diff --git a/.flake8 b/.flake8
index 30084f6d..bcbff465 100644
--- a/.flake8
+++ b/.flake8
@@ -1,5 +1,6 @@
 [flake8]
 max-line-length = 99
 docstring-convention=google
-exclude = python, run.py, tests/*
-ignore = E121,E123,E126,E203,E226,E24,E704,W503,N802,D
+exclude = python, tests/*, __init__.py, src/aura_engine/client/*, meta.py
+ignore = E121,E123,E126,E203,E226,E24,E704,W503,N802,\
+    D105,D107,D200,D202
diff --git a/src/aura_engine/app.py b/src/aura_engine/app.py
index 84ce861a..36c49168 100755
--- a/src/aura_engine/app.py
+++ b/src/aura_engine/app.py
@@ -18,6 +18,10 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
+"""
+Entrypoint to run the Engine.
+"""
+
 import logging
 import signal
 import sys
@@ -35,6 +39,7 @@ config = AuraConfig()
 
 
 def configure_flask():
+    """Initialize Flask."""
     app.config["SQLALCHEMY_DATABASE_URI"] = config.get_database_uri()
     app.config["BABEL_DEFAULT_LOCALE"] = "de"
     app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
@@ -57,7 +62,7 @@ class EngineRunner:
 
     def __init__(self):
         """
-        Constructor
+        Constructor.
         """
         self.config = config
         AuraLogger(self.config)
@@ -65,14 +70,14 @@ class EngineRunner:
 
     def run(self):
         """
-        Starts Engine Core.
+        Start Engine Core.
         """
 
         self.engine = Engine()
 
     def recreate_db(self):
         """
-        Initializes the database and deletes any existing content.
+        Initialize the database and deletes any existing content.
         """
         from scheduling.models import AuraDatabaseModel
 
diff --git a/src/aura_engine/base/api.py b/src/aura_engine/base/api.py
index 3ce61c29..50fce613 100644
--- a/src/aura_engine/base/api.py
+++ b/src/aura_engine/base/api.py
@@ -17,6 +17,10 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
+"""
+A collection of AURA API tools.
+"""
+
 import json
 import logging
 
@@ -45,7 +49,25 @@ class SimpleApi:
         self.logger = logging.getLogger(logger_name)
 
     def exception_handler(func):
-        def handle_response(*args, **kwargs):
+        """
+        Decorate functions with `@exception_handler` to handle API exceptions in a simple way.
+
+        Args:
+            func (_type_): The decorated function
+
+        """
+
+        def handle_response(*args, **kwargs) -> dict:
+            """Process the decorator response.
+
+            Returns:
+                dict: {
+                    "response": requests.Response object
+                    "error": String with error message
+                    "exception": The actual exception
+                }
+
+            """
             fn = func.__name__.upper()
             msg_template = f"during {fn} at '{args[1]}'"
             error = None
@@ -89,7 +111,8 @@ class SimpleApi:
             data (dict): The dictionary
 
         Returns:
-            (dict):
+            (dict): The cleaned dictionary
+
         """
         data = data.copy()
         for key, value in list(data.items()):
@@ -101,13 +124,14 @@ class SimpleApi:
 
     def build_json(self, data: dict, clean_data=True) -> str:
         """
-        Builds a JSON String from a dictionary
+        Build a JSON String from a dictionary.
 
         Args:
             data (dict): Dictionary holding the data
 
         Returns:
             str: JSON String
+
         """
         if clean_data:
             data = self.clean_dictionary(data)
@@ -129,6 +153,7 @@ class SimpleApi:
                 "error": str,
                 "exception": Exception
             }
+
         """
         # TODO Add JSON unmarshalling
         return requests.get(url)
@@ -136,7 +161,7 @@ class SimpleApi:
     @exception_handler
     def post(self, url: str, data: dict, headers: dict = None):
         """
-        POST to an URL
+        POST to an URL.
 
         Args:
             url (str): The URL of the request
@@ -149,6 +174,7 @@ class SimpleApi:
                 "error": str,
                 "exception": Exception
             }
+
         """
         if not headers:
             headers = SimpleApi.default_headers
@@ -158,7 +184,7 @@ class SimpleApi:
     @exception_handler
     def put(self, url: str, data: dict, headers: dict = None) -> requests.Response:
         """
-        PUT to an URL
+        PUT to an URL.
 
         Args:
             url (str): The URL of the request
@@ -171,6 +197,7 @@ class SimpleApi:
                 "error": str,
                 "exception": Exception
             }
+
         """
         if not headers:
             headers = SimpleApi.default_headers
@@ -180,13 +207,13 @@ class SimpleApi:
 
 class LiquidsoapUtil:
     """
-    Utilities specific to Liquidsoap
+    Utilities specific to Liquidsoap.
     """
 
     @staticmethod
     def json_to_dict(data: str) -> dict:
         """
-        Converts a Liquidsoap JSON String to dictionary
+        Convert a Liquidsoap JSON String to dictionary.
         """
         data = data.replace("+", " ")
         data = data.replace("-", " ")
diff --git a/src/aura_engine/base/config.py b/src/aura_engine/base/config.py
index 7a95d636..de68fe4e 100644
--- a/src/aura_engine/base/config.py
+++ b/src/aura_engine/base/config.py
@@ -17,6 +17,10 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
+"""
+Dealing with configuration data.
+"""
+
 import logging
 import os
 import os.path
@@ -27,8 +31,6 @@ from pathlib import Path
 
 class AuraConfig:
     """
-    AuraConfig Class
-
     Holds the Engine Configuration as in the file `engine.ini`.
     """
 
@@ -38,12 +40,14 @@ class AuraConfig:
 
     def __init__(self, ini_path="/etc/aura/engine.ini"):
         """
-        Initializes the configuration, defaults to `/etc/aura/engine.ini`.
+        Initialize the configuration, defaults to `/etc/aura/engine.ini`.
+
         If this file doesn't exist it uses `./config/engine.ini` from
         the project directory.
 
         Args:
-            ini_path(String):      The path to the configuration file `engine.ini`
+            ini_path(String): The path to the configuration file `engine.ini`
+
         """
         self.logger = logging.getLogger("AuraEngine")
         config_file = Path(ini_path)
@@ -64,17 +68,18 @@ class AuraConfig:
     @staticmethod
     def config():
         """
-        Retrieves the global instances of the configuration.
+        Retrieve the global instances of the configuration.
         """
         return AuraConfig.instance
 
     def set(self, key, value):
         """
-        Setter for some specific config property.
+        Set specific config property.
 
         Args:
-            key (String):   key
-            default (*):    value
+            key (String): key
+            default (*): value
+
         """
         try:
             self.__dict__[key] = int(value)
@@ -83,11 +88,12 @@ class AuraConfig:
 
     def get(self, key, default=None):
         """
-        Getter for some specific config property.
+        Get for some specific config property.
 
         Args:
-            key (String):   key
-            default (*):    value
+            key (String): key
+            default (*): value
+
         """
         if key not in self.__dict__:
             if default:
@@ -105,7 +111,7 @@ class AuraConfig:
 
     def get_database_uri(self):
         """
-        Retrieves the database connection string.
+        Retrieve the database connection string.
         """
         db_name = str(self.get("db_name"))
         db_type = str(self.get("db_type"))
@@ -129,7 +135,7 @@ class AuraConfig:
 
     def load_config(self):
         """
-        Set config defaults and load settings from file
+        Set config defaults and load settings from file.
         """
         if not os.path.isfile(self.ini_path):
             self.logger.critical(self.ini_path + " not found  :(")
@@ -155,8 +161,9 @@ class AuraConfig:
 
     def to_abs_path(self, path):
         """
-        Transforms any given (relative) path to an absolute paths
-        derived from the project root.
+        Transform any given (relative) path to an absolute paths.
+
+        Starting at the project root.
         """
         if path.startswith("/"):
             return path
@@ -165,12 +172,12 @@ class AuraConfig:
 
     def abs_audio_store_path(self):
         """
-        Returns the absolute path to the audio store, based on the `audio_source_folder` setting.
+        Return the absolute path to the audio store, based on the `audio_source_folder` setting.
         """
         return self.to_abs_path(self.get("audio_source_folder"))
 
     def abs_playlist_path(self):
         """
-        Returns the absolute path to the playlist folder
+        Return the absolute path to the playlist folder.
         """
         return self.to_abs_path(self.get("audio_playlist_folder"))
diff --git a/src/aura_engine/base/exceptions.py b/src/aura_engine/base/exceptions.py
index fca60ad9..8cbb5fde 100644
--- a/src/aura_engine/base/exceptions.py
+++ b/src/aura_engine/base/exceptions.py
@@ -17,14 +17,26 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
+"""
+A collection of exceptions.
+"""
+
 # Scheduler Exceptions
 
 
 class NoProgrammeLoadedException(Exception):
+    """
+    Exception thrown when no programme data could be loaded.
+    """
+
     pass
 
 
 class NoActiveTimeslotException(Exception):
+    """
+    Exception thrown when there is no timeslot active.
+    """
+
     pass
 
 
@@ -32,18 +44,34 @@ class NoActiveTimeslotException(Exception):
 
 
 class LoadSourceException(Exception):
+    """
+    Exception thrown when some source could not be loaded.
+    """
+
     pass
 
 
 class InvalidChannelException(Exception):
+    """
+    Exception thrown when the given channel is invalid.
+    """
+
     pass
 
 
 class PlaylistException(Exception):
+    """
+    Exception thrown when the playlist is invalid.
+    """
+
     pass
 
 
 class NoActiveEntryException(Exception):
+    """
+    Exception thrown when there is no playlist entry active.
+    """
+
     pass
 
 
@@ -51,8 +79,16 @@ class NoActiveEntryException(Exception):
 
 
 class LQConnectionError(Exception):
+    """
+    Exception thrown when there is a connection problem with Liquidsoap.
+    """
+
     pass
 
 
 class LQStreamException(Exception):
+    """
+    Exception thrown when there is a problem with an audio stream in Liquidsoap.
+    """
+
     pass
diff --git a/src/aura_engine/base/logger.py b/src/aura_engine/base/logger.py
index fb7de93f..0e364b34 100644
--- a/src/aura_engine/base/logger.py
+++ b/src/aura_engine/base/logger.py
@@ -17,19 +17,20 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
+"""
+Logging all the noise.
+"""
+
 import logging
 
 
 class AuraLogger:
     """
-    AuraLogger Class
-
-    Logger for all Aura Engine components. The default
-    logger is `AuraEngine`. Other loggers are defined
-    by passing a custom name on instantiation.
+    Logger for all Aura Engine components.
 
-    The logger respects the log-level as defined in the
-    engine's configuration file.
+    The default logger is `AuraEngine`. Other loggers are defined by passing a custom name on
+    instantiation. The logger respects the log-level as defined in the engine's configuration
+    file.
     """
 
     config = None
@@ -37,11 +38,12 @@ class AuraLogger:
 
     def __init__(self, config, name="AuraEngine"):
         """
-        Constructor to create a new logger defined by
-        the passed name.
+        Initialize the logger.
 
         Args:
-            name (String):  The name of the logger
+            config (AuraConfig): The configuration file
+            name (String): The name of the logger
+
         """
         self.config = config
         lvl = self.get_log_level()
@@ -49,7 +51,7 @@ class AuraLogger:
 
     def get_log_level(self):
         """
-        Retrieves the configured log level (default=INFO).
+        Retrieve the configured log level (default=INFO).
         """
         lvl = self.config.get("log_level")
 
@@ -66,11 +68,12 @@ class AuraLogger:
 
     def create_logger(self, name, lvl):
         """
-        Creates the logger instance for the given name.
+        Create the logger instance for the given name.
 
         Args:
-            name (String):  The name of the logger
-            lvl (Enum):     The logging level
+            name (String): The name of the logger
+            lvl (Enum): The logging level
+
         """
         self.logger = logging.getLogger(name)
         self.logger.setLevel(lvl)
diff --git a/src/aura_engine/base/utils.py b/src/aura_engine/base/utils.py
index c8e94dec..738d2318 100644
--- a/src/aura_engine/base/utils.py
+++ b/src/aura_engine/base/utils.py
@@ -17,6 +17,10 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
+"""
+A collection of all kinds of simplifications.
+"""
+
 import datetime
 import time
 from enum import Enum
@@ -30,7 +34,7 @@ class SimpleUtil:
     @staticmethod
     def to_datetime(datetime_str: str):
         """
-        Converts a timezone aware date-time string into `datetime`.
+        Convert a timezone aware date-time string into `datetime`.
         """
         if datetime_str:
             return datetime.datetime.fromisoformat(datetime_str)
@@ -39,53 +43,58 @@ class SimpleUtil:
     @staticmethod
     def fmt_time(timestamp):
         """
-        Formats a UNIX timestamp to a String displaying time in the format '%H:%M:%S'.
+        Format a UNIX timestamp to a String displaying time in the format '%H:%M:%S'.
 
         Args:
-            (Integer) timestamp:    Unix epoch
+            (Integer) timestamp: Unix epoch
 
         Returns:
             (String): Displaying the time
+
         """
         return datetime.datetime.fromtimestamp(timestamp).strftime("%H:%M:%S")
 
     @staticmethod
     def nano_to_seconds(nanoseconds):
         """
-        Converts nano-seconds to seconds
+        Convert nano-seconds to seconds.
 
         Args:
             (Integer) nanoseconds
 
         Returns:
             (Float): seconds
+
         """
         return float(nanoseconds / 1000000000)
 
     @staticmethod
     def seconds_to_nano(seconds):
         """
-        Converts seconds to nano-seconds
+        Convert seconds to nano-seconds.
 
         Args:
             (Integer) seconds
 
         Returns:
             (Float): nanoseconds
+
         """
         return int(seconds * 1000000000)
 
     @staticmethod
     def timestamp(date_and_time=None):
         """
-        Transforms the given `datetime` into a UNIX epoch timestamp.
+        Transform the given `datetime` into a UNIX epoch timestamp.
+
         If no parameter is passed, the current timestamp is returned.
 
         Args:
-            (Datetime) date_and_time:    the date and time to transform.
+            (Datetime) date_and_time: The date and time to transform.
 
         Returns:
             (Integer): timestamp in seconds.
+
         """
         if not date_and_time:
             date_and_time = datetime.datetime.now()
@@ -94,13 +103,14 @@ class SimpleUtil:
     @staticmethod
     def strike(text):
         """
-        Creates a strikethrough version of the given text.
+        Create a strikethrough version of the given text.
 
         Args:
-            (String) text:  the text to strike.
+            (String) text: The text to strike.
 
         Returns:
-            (String):       the striked text.
+            (String): the striked text.
+
         """
         result = ""
         for c in str(text):
@@ -110,56 +120,56 @@ class SimpleUtil:
     @staticmethod
     def bold(text):
         """
-        Creates a bold version of the given text.
+        Create a bold version of the given text.
         """
         return TerminalColors.BOLD.value + text + TerminalColors.ENDC.value
 
     @staticmethod
     def underline(text):
         """
-        Creates a underlined version of the given text.
+        Create a underlined version of the given text.
         """
         return TerminalColors.UNDERLINE.value + text + TerminalColors.ENDC.value
 
     @staticmethod
     def blue(text):
         """
-        Creates a blue version of the given text.
+        Create a blue version of the given text.
         """
         return TerminalColors.BLUE.value + text + TerminalColors.ENDC.value
 
     @staticmethod
     def red(text):
         """
-        Creates a red version of the given text.
+        Create a red version of the given text.
         """
         return TerminalColors.RED.value + text + TerminalColors.ENDC.value
 
     @staticmethod
     def pink(text):
         """
-        Creates a red version of the given text.
+        Create a red version of the given text.
         """
         return TerminalColors.PINK.value + text + TerminalColors.ENDC.value
 
     @staticmethod
     def yellow(text):
         """
-        Creates a yellow version of the given text.
+        Create a yellow version of the given text.
         """
         return TerminalColors.YELLOW.value + text + TerminalColors.ENDC.value
 
     @staticmethod
     def green(text):
         """
-        Creates a red version of the given text.
+        Create a red version of the given text.
         """
         return TerminalColors.GREEN.value + text + TerminalColors.ENDC.value
 
     @staticmethod
     def cyan(text):
         """
-        Creates a cyan version of the given text.
+        Create a cyan version of the given text.
         """
         return TerminalColors.CYAN.value + text + TerminalColors.ENDC.value
 
@@ -170,6 +180,7 @@ class DotDict(dict):
 
     Args:
         dict (_type_): The dictionary
+
     """
 
     __getattr__ = dict.get
diff --git a/src/aura_engine/channels.py b/src/aura_engine/channels.py
index b6dd5b6a..f8057975 100644
--- a/src/aura_engine/channels.py
+++ b/src/aura_engine/channels.py
@@ -17,6 +17,10 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
+"""
+Configuration and helpers for channel types.
+"""
+
 from enum import Enum
 
 from aura_engine.base.utils import SimpleUtil as SU
@@ -63,7 +67,7 @@ class ChannelResolver:
     @staticmethod
     def channel_by_string(channel: str):
         """
-        Returns the channel enum for a given channel string from Liquidsoap.
+        Return the channel enum for a given channel string from Liquidsoap.
         """
         if not channel:
             return None
@@ -100,7 +104,7 @@ class ChannelResolver:
     @staticmethod
     def live_channel_for_resource(channel: str):
         """
-        Returns the channel enum for a given live channel string from Tank.
+        Return the channel enum for a given live channel string from Tank.
         """
         if not channel:
             return None
@@ -151,10 +155,12 @@ class ChannelType(Enum):
 
     @property
     def channels(self):
+        """Retrieve all channels for given type."""
         return self.value["channels"]
 
     @property
     def numeric(self):
+        """Retrieve numeric representation of channel type for given type."""
         return self.value["numeric"]
 
     def __str__(self):
@@ -162,6 +168,8 @@ class ChannelType(Enum):
 
 
 class EntryPlayState(Enum):
+    """Play-state of a playlist entry."""
+
     UNKNOWN = "unknown"
     LOADING = "loading"
     READY = "ready_to_play"
@@ -170,6 +178,8 @@ class EntryPlayState(Enum):
 
 
 class LiquidsoapResponse(Enum):
+    """Response values from Liquidsoap."""
+
     # There are some weird variations of responses coming
     SUCCESS = ["Done", "Done!", "Donee!", "OK"]
     STREAM_STATUS_POLLING = "polling"
@@ -189,11 +199,11 @@ class ChannelRouter:
 
     def __init__(self, config, logger):
         """
-        Constructor
+        Constructor.
 
         Args:
-            config (AuraConfig):    The configuration
-            logger (Logger):        The logger
+            config (AuraConfig): The configuration
+            logger (Logger): The logger
         """
         self.config = config
         self.logger = logger
@@ -215,19 +225,19 @@ class ChannelRouter:
 
     def set_active(self, channel_type, channel):
         """
-        Set the channel for the given resource type active
+        Set the channel for the given resource type active.
         """
         self.active_channels[channel_type] = channel
 
     def get_active(self, channel_type):
         """
-        Retrieves the active channel for the given resource type
+        Retrieve the active channel for the given resource type.
         """
         return self.active_channels[channel_type]
 
     def type_of_channel(self, channel):
         """
-        Retrieves a `ChannelType` for the given `Channel`.
+        Retrieve a `ChannelType` for the given `Channel`.
         """
         if channel in ChannelType.QUEUE.channels:
             return ChannelType.QUEUE
@@ -242,7 +252,7 @@ class ChannelRouter:
 
     def is_any_queue(self, channel):
         """
-        Evaluates if the channel is of any queue type.
+        Evaluate if the channel is of any queue type.
         """
         if (
             self.type_of_channel(channel) == ChannelType.QUEUE
@@ -253,7 +263,7 @@ class ChannelRouter:
 
     def type_for_resource(self, resource_type):
         """
-        Retrieves a `ChannelType` for the given `ResourceType`.
+        Retrieve a `ChannelType` for the given `ResourceType`.
 
         Only default mappings can be evaluatated. Custom variations
         like fallback channels are not respected.
@@ -262,15 +272,17 @@ class ChannelRouter:
 
     def channel_swap(self, channel_type):
         """
-        Returns the currently inactive channel for a given type. For example if currently some
-        file on channel QUEUE A is playing, the channel QUEUE B is returned for being used
-        to queue new entries.
+        Return the currently inactive channel for a given type.
+
+        For example if currently some file on channel QUEUE A is playing, the channel QUEUE B is
+        returned for being used to queue new entries.
 
         Args:
             entry_type (ResourceType): The resource type such es file, stream or live source
 
         Returns:
             (Channel, Channel): The previous and new channel
+
         """
         previous_channel = self.active_channels[channel_type]
         new_channel = None
diff --git a/src/aura_engine/control.py b/src/aura_engine/control.py
index 60c4d847..0c52eddc 100644
--- a/src/aura_engine/control.py
+++ b/src/aura_engine/control.py
@@ -17,6 +17,10 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
+"""
+Remote-control the Engine with these services.
+"""
+
 import json
 import logging
 import socket
@@ -45,11 +49,7 @@ class EngineControlInterface:
 
     def __init__(self, engine, event_dispatcher):
         """
-        Constructor
-
-        Args:
-            config (AuraConfig):    Engine configuration
-            logger (AuraLogger):    The logger
+        Intialize the ECI.
         """
         self.engine = engine
         self.config = AuraConfig.config()
@@ -62,7 +62,7 @@ class EngineControlInterface:
 
     def terminate(self):
         """
-        Terminates the instance and all related objects.
+        Terminate the instance and all related objects.
         """
         if self.sci:
             self.sci.terminate()
@@ -88,7 +88,7 @@ class SocketControlInterface:
 
     def __init__(self, event_dispatcher):
         """
-        Constructor
+        Constructor.
 
         Args:
             config (AuraConfig):    Engine configuration
@@ -111,7 +111,7 @@ class SocketControlInterface:
     @staticmethod
     def get_instance(event_dispatcher):
         """
-        Returns the Singleton.
+        Return the Singleton.
         """
         if not SocketControlInterface.instance:
             SocketControlInterface.instance = SocketControlInterface(event_dispatcher)
@@ -119,7 +119,7 @@ class SocketControlInterface:
 
     def run(self, logger, host, port):
         """
-        Starts the socket server
+        Start the socket server.
         """
         while True:
             try:
@@ -183,6 +183,9 @@ class SocketControlInterface:
             logger.error(SU.red(f"[ECI] Missing action in request: {data}"))
 
     def terminate(self):
+        """
+        Call when a shutdown signal is received.
+        """
         SocketControlInterface.instance = None
         self.server.close()
         self.logger.info(SU.yellow("[ECI] Shutting down..."))
@@ -219,15 +222,15 @@ class EngineExecutor(Timer):
         param=None,
     ):
         """
-        Constructor
+        Constructor.
 
         Args:
-            timer_type (String):            Prefix used for the `timer_id` to make it unique
-            parent_timer (EngineExeuctor):  Parent action which is a prerequisite for this timer
-            due_time (Float):               When timer should be executed.
+            timer_type (String): Prefix used for the `timer_id` to make it unique
+            parent_timer (EngineExeuctor): Parent action which is a prerequisite for this timer
+            due_time (Float): When timer should be executed.
                 For values <= 0 execution happens immediately in a threaded way
-            func (function):                The function to be called
-            param (object):                 Parameter passt to the function
+            func (function): The function to be called
+            param (object): Parameter passt to the function
         """
         self._lock = Lock()
         from aura_engine.engine import Engine
@@ -274,11 +277,12 @@ class EngineExecutor(Timer):
 
     def wait_for_parent(self):
         """
-        @private
+        Child timers are dependent on their parents.
+
+        So let's wait until parents are done with their stuff => finished execution.
+        Checks the parent state to befinished every 0.2 seconds.
 
-        Child timers are dependent on their parents. So let's wait until parents are
-        done with their stuff => finished execution. Checks the parent state to be
-        finished every 0.2 seconds.
+        @private
         """
         if self.parent_timer:
             while self.parent_timer.is_alive():
@@ -291,11 +295,11 @@ class EngineExecutor(Timer):
 
     def exec_now(self):
         """
-        @private
-
         Immediate execution within a thread. It is not stored in the timer store.
 
         It also assigns the `timer_id` as the thread name.
+
+        @private
         """
         self.direct_exec = True
         self.wait_for_parent()
@@ -304,12 +308,14 @@ class EngineExecutor(Timer):
 
     def exec_timed(self):
         """
-        @private
+        Do timed execution in a thread.
 
-        Timed execution in a thread. This method instroduces a slight delay to ensure
-        the thread is properly initialized before starting it.
+        This method instroduces a slight delay to ensure the thread is properly initialized before
+        starting it.
 
         It also assigns the `timer_id` as the thread name.
+
+        @private
         """
 
         def wrapper_func(param=None):
@@ -327,9 +333,7 @@ class EngineExecutor(Timer):
 
     def update_store(self):
         """
-        @private
-
-        Adds the instance to the store and cancels any previously existing commands.
+        Add the instance to the store and cancels any previously existing commands.
 
         If a timer with the given ID is already existing but also already executed,
         then it is not added to the store. In such case the method returns `False`.
@@ -337,6 +341,9 @@ class EngineExecutor(Timer):
         Returns:
             (Boolean):  True if the timer has been added to the store. False if the
                         timer is already existing but dead.
+
+        @private
+
         """
         with self._lock:
             existing_command = None
@@ -369,9 +376,9 @@ class EngineExecutor(Timer):
 
     def is_alive(self):
         """
-        @private
+        Return true if the command is still due to be executed.
 
-        Returns true if the command is still due to be executed.
+        @private
         """
         if self.direct_exec:
             return False
@@ -381,14 +388,14 @@ class EngineExecutor(Timer):
 
     def __str__(self):
         """
-        String representation of the timer.
+        Make a String representation of the timer.
         """
         return f"[{self.timer_id}] exec at {str(self.dt)} (alive: {self.is_alive()})"
 
     @staticmethod
     def remove_stale_timers():
         """
-        Removes timers from store which have been executed and are older than 3 hours.
+        Remove timers from store which have been executed and are older than 3 hours.
         """
         timers = EngineExecutor.timer_store.values()
         del_keys = []
@@ -408,14 +415,14 @@ class EngineExecutor(Timer):
     @staticmethod
     def command_history():
         """
-        Returns a list of recent active and inactive timers to the logger.
+        Return a list of recent active and inactive timers to the logger.
         """
         return EngineExecutor.timer_store.values()
 
     @staticmethod
     def log_commands():
         """
-        Prints a list of recent active and inactive timers to the logger.
+        Print a list of recent active and inactive timers to the logger.
         """
         msg = SU.blue("\n [ ENGINE COMMAND QUEUE ]\n")
         EngineExecutor.remove_stale_timers()
diff --git a/src/aura_engine/engine.py b/src/aura_engine/engine.py
index 8330c4e1..8b082853 100644
--- a/src/aura_engine/engine.py
+++ b/src/aura_engine/engine.py
@@ -17,6 +17,10 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
+"""
+The Engine.
+"""
+
 import json
 import logging
 import time
@@ -70,7 +74,7 @@ class Engine:
 
     def __init__(self):
         """
-        Constructor
+        Initialize the engine.
         """
         if Engine.instance:
             raise Exception("Engine is already running!")
@@ -84,8 +88,9 @@ class Engine:
 
     def start(self):
         """
-        Starts the engine. Called when the connection to the sound-system implementation
-        has been established.
+        Start the engine.
+
+        Called when the connection to the sound-system implementation has been established.
         """
         self.event_dispatcher = EngineEventDispatcher(self)
         self.eci = EngineControlInterface(self, self.event_dispatcher)
@@ -113,7 +118,7 @@ class Engine:
 
     def is_connected(self):
         """
-        Checks if there's a valid connection to Liquidsoap.
+        Check if there's a valid connection to Liquidsoap.
         """
         has_connection = False
         try:
@@ -128,7 +133,7 @@ class Engine:
 
     def update_playout_state(self):
         """
-        Retrieves the state of all inputs and outputs.
+        Retrieve the state of all inputs and outputs.
         """
         state = self.connector.send_lqc_command("engine", "state")
         state = DotDict(LU.json_to_dict(state))
@@ -156,13 +161,13 @@ class Engine:
 
     def get_playout_state(self):
         """
-        Retrieves the state of Engine Core
+        Retrieve the state of Engine Core.
         """
         return self.playout_state
 
     def engine_update_config(self):
         """
-        Update the config of playout with the current values
+        Update the config of playout with the current values.
         """
         playout_config = {
             "fallback_show_id": int(self.config.get("fallback_show_id")),
@@ -178,6 +183,7 @@ class Engine:
 
         Returns:
             dict: Dictionary with `engine-core` and `liquidsoap` version
+
         """
         # FIXME Should be in one call
         core_version = self.connector.send_lqc_command("engine", "version")
@@ -186,7 +192,7 @@ class Engine:
 
     def uptime(self):
         """
-        Retrieves the uptime of Liquidsoap.
+        Retrieve the uptime of Liquidsoap.
         """
         self.connector.enable_transaction()
         data = self.connector.send_lqc_command("uptime", "")
@@ -196,6 +202,8 @@ class Engine:
     @staticmethod
     def engine_time():
         """
+        Get the engine perspective on time.
+
         Liquidsoap is slow in executing commands, therefore it's needed to schedule
         actions by (n) seconds in advance, as defined in the configuration file by
         the property `engine_latency_offset`. it's important to note that this method
@@ -204,19 +212,20 @@ class Engine:
 
         Returns:
             (Integer):  the Unix epoch timestamp including the offset
+
         """
         return SU.timestamp() + Engine.engine_time_offset
 
     @staticmethod
     def get_instance():
         """
-        Returns the one and only engine.
+        Return the one and only engine.
         """
         return Engine.instance
 
     def terminate(self):
         """
-        Terminates the engine and all related processes.
+        Terminate the engine and all related processes.
         """
         if self.scheduler:
             self.scheduler.terminate()
@@ -244,10 +253,12 @@ class Player:
 
     def __init__(self, connector, event_dispatcher):
         """
-        Constructor
+        Initialize the player.
 
         Args:
-            config (AuraConfig):    The configuration
+            connector (Connector): Connector for the playout
+            event_dispatcher (EventDispather): Dispatcher for issuing events
+
         """
         self.config = AuraConfig.config()
         self.logger = logging.getLogger("AuraEngine")
@@ -269,7 +280,8 @@ class Player:
         `entry.state`.
 
         Args:
-            entries ([Entry]):    An array holding filesystem entries
+            entries ([Entry]): An array holding filesystem entries
+
         """
         entry.status = EntryPlayState.LOADING
         self.logger.info("Loading entry '%s'" % entry)
@@ -316,18 +328,21 @@ class Player:
 
     def preload_group(self, entries, channel_type=ChannelType.QUEUE):
         """
-        Pre-Load multiple filesystem entries at once. This call is required before the
-        actual `play(..)` can happen. Due to their nature, non-filesystem entries cannot be queued
-        using this method. In this case use `preload(self, entry)` instead. This method also allows
-        queuing of very short files, such as jingles.
+        Pre-Load multiple filesystem entries at once.
+
+        This call is required before the actual `play(..)` can happen. Due to their nature,
+        non-filesystem entries cannot be queued using this method. In this case use
+        `preload(self, entry)` instead. This method also allows queuing of very short files, such
+        as jingles.
 
         It's important to note, that his method is blocking until loading has finished. If this
         method is called asynchronously, the progress on the preloading state can be looked up in
         `entry.state`.
 
         Args:
-            entries ([Entry]):          An array holding filesystem entries
+            entries ([Entry]): An array holding filesystem entries
             channel_type (ChannelType): The type of channel where it should be queued (optional)
+
         """
         channels = None
 
@@ -355,20 +370,20 @@ class Player:
 
     def play(self, entry, transition):
         """
-        Plays a new `Entry`. In case of a new timeslot (or some intended, immediate transition),
-        a clean channel is selected and transitions between old and new channel is performed.
+        Play a new `Entry`.
+
+        In case of a new timeslot (or some intended, immediate transition), a clean channel is
+        selected and transitions between old and new channel is performed.
 
         This method expects that the entry is pre-loaded using `preload(..)` or
-        `preload_group(self, entries)` before being played.
-        In case the pre-loading has happened for a group of entries, only the first entry of the
-        group needs to be passed.
+        `preload_group(self, entries)` before being played. In case the pre-loading has happened
+        for a group of entries, only the first entry of the group needs to be passed.
 
         Args:
-            entry (PlaylistEntry):          The audio source to be played
-            transition (TransitionType):
-                The type of transition to use e.g. fade-in or instant volume level.
-            queue (Boolean):
-                If `True` the entry is queued if the `ChannelType` does allow so;
+            entry (PlaylistEntry): The audio source to be played
+            transition (TransitionType): The type of transition to use e.g. fade-in or instant
+                volume level.
+            queue (Boolean): If `True` the entry is queued if the `ChannelType` does allow so;
                 otherwise a new channel of the same type is activated
 
         """
@@ -406,7 +421,7 @@ class Player:
 
     def stop(self, channel: Channel, transition: TransitionType):
         """
-        Stops the currently playing channel.
+        Stop the currently playing channel.
 
         Args:
             channel (Channel): The channel to stop playing or fade-out
@@ -433,13 +448,14 @@ class Player:
 
     def stream_load_entry(self, entry):
         """
-        Loads the given stream entry and updates the entries's status codes.
+        Load the given stream entry and updates the entries's status codes.
 
         Args:
-            entry (Entry):  The entry to be pre-loaded
+            entry (Entry): The entry to be pre-loaded
 
         Returns:
             (Boolean):  `True` if successful
+
         """
         self.stream_load(entry.channel, entry.source)
         time.sleep(1)
@@ -462,15 +478,18 @@ class Player:
 
     def stream_load(self, channel, url):
         """
-        Preloads the stream URL on the given channel. Note this method is blocking
-        some serious amount of time; hence it is worth being called asynchronously.
+        Preload the stream URL on the given channel.
+
+        Note this method is blocking some serious amount of time; hence it is worth being called
+        asynchronously.
 
         Args:
             channel (Channel): The stream channel
-            url (String):      The stream URL
+            url (String): The stream URL
 
         Returns:
-            (Boolean):  `True` if successful
+            (Boolean): `True` if successful
+
         """
         result = None
 
@@ -498,16 +517,18 @@ class Player:
 
     def stream_is_ready(self, channel, url):
         """
-        Checks if the stream on the given channel is ready to play. Note this method is blocking
-        some serious amount of time even when successful; hence it is worth being called
-        asynchronously.
+        Check if the stream on the given channel is ready to play.
+
+        Note this method is blocking some serious amount of time even when successful; hence it is
+        worth being called asynchronously.
 
         Args:
             channel (Channel): The stream channel
-            url (String):      The stream URL
+            url (String): The stream URL
 
         Returns:
-            (Boolean):  `True` if successful
+            (Boolean): `True` if successful
+
         """
         result = None
 
@@ -542,7 +563,7 @@ class Player:
 
     def queue_push(self, channel, source, metadata):
         """
-        Adds an filesystem URI to the given `ChannelType.QUEUE` channel.
+        Add an filesystem URI to the given `ChannelType.QUEUE` channel.
 
         Args:
             channel (Channel): The channel to push the file to
@@ -550,7 +571,8 @@ class Player:
             metadata (dict): additional meta data to be wrapped with the URI
 
         Returns:
-            (Boolean):  `True` if successful
+            (Boolean): `True` if successful
+
         """
         if (
             channel not in ChannelType.QUEUE.channels
@@ -581,14 +603,15 @@ class Player:
 
     def queue_seek(self, channel, seconds_to_seek):
         """
-        Forwards the player of the given `ChannelType.QUEUE` channel by (n) seconds.
+        Pre-roll the player of the given `ChannelType.QUEUE` channel by (n) seconds.
 
         Args:
             channel (Channel): The channel to push the file to
-            seconds_to_seeks (Float):   The seconds to skip
+            seconds_to_seeks (Float): The seconds to skip
 
         Returns:
-            (String):   Liquidsoap response
+            (String): Liquidsoap response
+
         """
         if (
             channel not in ChannelType.QUEUE.channels
@@ -605,15 +628,17 @@ class Player:
 
     def queue_clear(self, channel: Channel):
         """
-        Dear queue channels, please leave the room as you
-        would like to find it: Every queue needs to be empty,
-        before it can receive new items. Otherwise old times
+        Clear any tracks left in the queue.
+
+        Dear queue channels, please leave the room as you would like to find it:
+        Every queue needs to be empty, before it can receive new items. Otherwise old tracks
         continue to play, when such 'dirty' channel is selected.
 
-        Note, the channel is cleared asynchronously.
+        The channel is cleared asynchronously.
 
         Args:
             channel (Channel): The channel to clear
+
         """
         if not self.channel_router.is_any_queue(channel):
             raise InvalidChannelException
@@ -652,14 +677,15 @@ class Player:
 
     def playlist_set_uri(self, channel, playlist_uri):
         """
-        Sets the URI of a playlist.
+        Set the URI of a playlist.
 
         Args:
             channel (Channel): The channel to push the file to
             playlist_uri (String): The path to the playlist
 
         Returns:
-            (String):   Liquidsoap response
+            (String): Liquidsoap response
+
         """
         self.logger.info(SU.pink("Setting URI of playlist '%s' to '%s'" % (channel, playlist_uri)))
 
@@ -672,13 +698,14 @@ class Player:
 
     def playlist_clear_uri(self, channel):
         """
-        Clears the URI of a playlist.
+        Clear the URI of a playlist.
 
         Args:
             channel (Channel): The channel to push the file to
 
         Returns:
-            (String):   Liquidsoap response
+            (String): Liquidsoap response
+
         """
         self.logger.info(SU.pink("Clearing URI of playlist '%s'" % (channel)))
 
@@ -691,10 +718,12 @@ class Player:
 
 
 class EngineSplash:
+    """Print the splash and version information on boot."""
+
     @staticmethod
     def splash_screen(component, version):
         """
-        Prints the engine logo and version info.
+        Print the engine logo and version info.
         """
         return """\n
              █████╗ ██╗   ██╗██████╗  █████╗     ███████╗███╗   ██╗ ██████╗ ██╗███╗   ██╗███████╗
diff --git a/src/aura_engine/events.py b/src/aura_engine/events.py
index f9c1b181..10d5b32d 100644
--- a/src/aura_engine/events.py
+++ b/src/aura_engine/events.py
@@ -17,6 +17,10 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
+"""
+Event binding and propagation.
+"""
+
 import datetime
 import logging
 from threading import Thread
@@ -44,28 +48,28 @@ class EventBinding:
 
     def __init__(self, dispatcher, instance):
         """
-        Constructor
+        Initialize the dispatcher.
         """
         self.dispatcher = dispatcher
         self.instance = instance
 
     def subscribe(self, event_type):
         """
-        Subscribes the instance to some event identified by the `event_type` string.
+        Subscribe the the instance to some event identified by the `event_type` string.
         """
         self.dispatcher.subscribe(self.instance, event_type)
         return self
 
     def get_instance(self):
         """
-        Returns the object within that binding.
+        Return the object within that binding.
         """
         return self.instance
 
 
 class EngineEventDispatcher:
     """
-    Executes handlers for engine events.
+    Execute handlers for engine events.
     """
 
     logger = None
@@ -78,7 +82,7 @@ class EngineEventDispatcher:
 
     def __init__(self, engine):
         """
-        Constructor
+        Initialize the event dispatcher.
         """
         self.subscriber_registry = dict()
         self.logger = logging.getLogger("AuraEngine")
@@ -106,14 +110,16 @@ class EngineEventDispatcher:
 
     def attach(self, clazz):
         """
-        Creates an instance of the given Class.
+        Create an instance of the given `Class`.
         """
         instance = clazz(self.engine)
         return EventBinding(self, instance)
 
     def subscribe(self, instance, event_type):
         """
-        Subscribes to some event type. Preferably use it via `EventBinding.subscribe(..)`.
+        Subscribe to some event type.
+
+        Preferably use it via `EventBinding.subscribe(..)`.
         """
         if event_type not in self.subscriber_registry:
             self.subscriber_registry[event_type] = []
@@ -121,7 +127,7 @@ class EngineEventDispatcher:
 
     def call_event(self, event_type, *args):
         """
-        Calls all subscribers for the given event type.
+        Call all subscribers for the given event type.
         """
         if event_type not in self.subscriber_registry:
             return
@@ -142,7 +148,7 @@ class EngineEventDispatcher:
 
     def on_initialized(self):
         """
-        Called when the engine is initialized, just before
+        Call when the engine is initialized, just before it is ready.
 
         Important: Subsequent events are called synchronously, hence blocking.
         """
@@ -154,8 +160,10 @@ class EngineEventDispatcher:
 
     def on_boot(self):
         """
-        Called when the engine is starting up. This happens after the initialization step.
-        Connection to Liquidsoap should be available here.
+        Call when the engine is starting up.
+
+        This happens after the initialization step. Connection to Liquidsoap should be available
+        here.
 
         Important: Subsequent events are called synchronously, hence blocking.
         """
@@ -164,7 +172,7 @@ class EngineEventDispatcher:
 
     def on_ready(self):
         """
-        Called when the engine has finished booting and is ready to play.
+        Call when the engine has finished booting and is ready to play.
         """
 
         def func(self, param):
@@ -177,7 +185,7 @@ class EngineEventDispatcher:
 
     def on_timeslot_start(self, timeslot):
         """
-        Called when a timeslot starts.
+        Call when a timeslot starts.
         """
 
         def func(self, timeslot):
@@ -189,7 +197,7 @@ class EngineEventDispatcher:
 
     def on_timeslot_end(self, timeslot):
         """
-        Called when a timeslot ends.
+        Call when a timeslot ends.
         """
 
         def func(self, timeslot):
@@ -201,14 +209,16 @@ class EngineEventDispatcher:
 
     def on_play(self, entry):
         """
-        Event Handler which is called by the engine when some play command to Liquidsoap is issued.
+        Call by the engine when some play command to Liquidsoap is issued.
+
         This does not indicate that Liquidsoap started playing actually, only that the command has
         been issued. To get the metadata update issued by Liquidsoap use `on_metadata` instead.
 
         This event is not issued when media is played by Liquidsoap in fallback scenarios.
 
         Args:
-            entry (PlaylistEntry):
+            entry (PlaylistEntry): The entry to play
+
         """
 
         def func(self, entry):
@@ -223,7 +233,7 @@ class EngineEventDispatcher:
 
     def on_stop(self, channel):
         """
-        The passed channel has stopped playing.
+        Call when the passed channel has stopped playing.
         """
 
         def func(self, channel):
@@ -235,8 +245,9 @@ class EngineEventDispatcher:
 
     def on_fallback_active(self, timeslot, fallback_name):
         """
-        Called when a fallback is activated for the given timeslot,
-        since no default playlist is available.
+        Call when a fallback is activated for the given timeslot.
+
+        This means there is no proper playlist scheduled.
         """
 
         def func(self, timeslot, fallback_type):
@@ -248,7 +259,7 @@ class EngineEventDispatcher:
 
     def on_queue(self, entries):
         """
-        One or more entries have been queued and are currently pre-loaded.
+        Call when One or more entries have been queued and are currently being pre-loaded.
         """
 
         def func(self, entries):
@@ -260,7 +271,7 @@ class EngineEventDispatcher:
 
     def on_sick(self, data):
         """
-        Called when the engine is in some unhealthy state.
+        Call when the engine is in some unhealthy state.
         """
 
         def func(self, data):
@@ -272,7 +283,7 @@ class EngineEventDispatcher:
 
     def on_resurrect(self, data):
         """
-        Called when the engine turned healthy again after being sick.
+        Call when the engine turned healthy again after being sick.
         """
 
         def func(self, data):
@@ -284,7 +295,7 @@ class EngineEventDispatcher:
 
     def on_critical(self, subject, message, data=None):
         """
-        Called when some critical event occurs
+        Call when some critical event occurs.
         """
 
         def func(self, subject, message, data):
diff --git a/src/aura_engine/mixer.py b/src/aura_engine/mixer.py
index 937eaf4e..c68b995d 100644
--- a/src/aura_engine/mixer.py
+++ b/src/aura_engine/mixer.py
@@ -17,6 +17,10 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
+"""
+The virtual mixer as it is realized using Liquidsoap.
+"""
+
 import logging
 import time
 from enum import Enum
@@ -42,7 +46,7 @@ class MixerUtil:
     @staticmethod
     def channel_status_dict(status):
         """
-        Transforms a channel status string to a dictionary.
+        Transform a channel status string to a dictionary.
         """
         s = {}
         pairs = status.split(" ")
@@ -67,10 +71,11 @@ class Mixer:
 
     def __init__(self, config, mixer_id, connector):
         """
-        Constructor
+        Initialize the mixer object.
 
         Args:
-            config (AuraConfig):    The configuration
+            config (AuraConfig): The configuration
+
         """
         self.config = config
         self.logger = logging.getLogger("AuraEngine")
@@ -86,8 +91,12 @@ class Mixer:
 
     def mixer_initialize(self):
         """
-        - Pull all faders down to volume 0.
-        - Initialize default channels per type
+        Initialize the mixer.
+
+        It does:
+            - Pull all faders down to volume 0.
+            - Initialize default channels per type
+
         """
         self.connector.enable_transaction()
         time.sleep(1)  # TODO Check is this is still required
@@ -100,7 +109,7 @@ class Mixer:
 
     def mixer_status(self):
         """
-        Returns the state of all mixer channels
+        Return the state of all mixer channels.
         """
         cnt = 0
         inputstate = {}
@@ -117,7 +126,7 @@ class Mixer:
 
     def mixer_outputs(self):
         """
-        Retrieves the state of all inputs and outputs.
+        Retrieve the state of all inputs and outputs.
         """
         outputs = self.connector.send_lqc_command(self.mixer_id.value, "mixer_outputs")
         outputs = LU.json_to_dict(outputs)
@@ -125,7 +134,7 @@ class Mixer:
 
     def mixer_channels(self):
         """
-        Retrieves all mixer channels
+        Retrieve all mixer channels.
         """
         if self.channels is None or len(self.channels) == 0:
             self.channels = self.connector.send_lqc_command(self.mixer_id.value, "mixer_inputs")
@@ -133,7 +142,7 @@ class Mixer:
 
     def mixer_channels_selected(self):
         """
-        Retrieves all selected channels of the mixer.
+        Retrieve all selected channels of the mixer.
         """
         cnt = 0
         activeinputs = []
@@ -152,7 +161,7 @@ class Mixer:
 
     def mixer_channels_except(self, input_type):
         """
-        Retrieves all mixer channels except the ones of the given type.
+        Retrieve all mixer channels except the ones of the given type.
         """
         try:
             activemixer_copy = self.mixer_channels().copy()
@@ -168,7 +177,7 @@ class Mixer:
 
     def mixer_channels_reload(self):
         """
-        Reloads all mixer channels.
+        Reload all mixer channels.
         """
         self.channels = None
         return self.mixer_channels()
@@ -179,13 +188,14 @@ class Mixer:
 
     def channel_number(self, channel):
         """
-        Returns the channel number for the given channel ID.
+        Return the channel number for the given channel ID.
 
         Args:
-            channel (Channel):  The channel
+            channel (Channel): The channel
 
         Returns:
             (Integer): The channel number
+
         """
         channels = self.mixer_channels()
         index = channels.index(channel)
@@ -198,26 +208,28 @@ class Mixer:
 
     def channel_status(self, channel_number):
         """
-        Retrieves the status of a channel identified by the channel number.
+        Retrieve the status of a channel identified by the channel number.
 
         Args:
-            channel_number (Integer):   The channel number
+            channel_number (Integer): The channel number
 
         Returns:
-            (String):   Channel status info as a String
+            (String): Channel status info as a String
+
         """
         return self.connector.send_lqc_command(self.mixer_id.value, "mixer_status", channel_number)
 
     def channel_select(self, channel, select):
         """
-        Selects/deselects some mixer channel
+        Select or deselect some mixer channel.
 
         Args:
             pos (Integer): The channel number
             select (Boolean): Select or deselect
 
         Returns:
-            (String):   Liquidsoap server response
+            (String): Liquidsoap server response
+
         """
         channels = self.mixer_channels()
 
@@ -235,16 +247,19 @@ class Mixer:
 
     def channel_activate(self, channel, activate):
         """
+        Activate a channel.
+
         Combined call of following to save execution time:
           - Select some mixer channel
           - Increase the volume to 100,
 
         Args:
-            pos (Integer):  The channel number
+            channel (Channel): The channel number
             activate (Boolean): Activate or deactivate
 
         Returns:
-            (String):   Liquidsoap server response
+            (String): Liquidsoap server response
+
         """
         channels = self.mixer_channels()
 
@@ -262,7 +277,7 @@ class Mixer:
 
     def channel_current_volume(self, channel):
         """
-        Retrieves the current volume of the channel.
+        Retrieve the current volume of the channel.
         """
         channel_number = self.channel_number(channel.value)
         status = self.channel_status(channel_number)
@@ -276,11 +291,12 @@ class Mixer:
 
     def channel_volume(self, channel, volume):
         """
-        Set volume of a channel
+        Set volume of a channel.
 
         Args:
-            channel (Channel):      The channel
-            volume  (Integer)       Volume between 0 and 100
+            channel (Channel): The channel
+            volume (Integer): Volume between 0 and 100
+
         """
         channel = str(channel)
         try:
@@ -330,14 +346,15 @@ class Mixer:
 
     def fade_in(self, channel, volume):
         """
-        Performs a fade-in for the given channel.
+        Perform a fade-in for the given channel.
 
         Args:
-            channel (Channel):  The channel to fade
-            volume (Integer):   The target volume
+            channel (Channel): The channel to fade
+            volume (Integer): The target volume
 
         Returns:
-            (Boolean):  `True` if successful
+            (Boolean): `True` if successful
+
         """
         try:
             current_volume = self.channel_current_volume(channel)
@@ -393,14 +410,15 @@ class Mixer:
 
     def fade_out(self, channel, volume=None):
         """
-        Performs a fade-out for the given channel starting at its current volume.
+        Perform a fade-out for the given channel starting at its current volume.
 
         Args:
-            channel (Channel):  The channel to fade
-            volume (Integer):   The start volume
+            channel (Channel): The channel to fade
+            volume (Integer): The start volume
 
         Returns:
-            (Boolean):  `True` if successful
+            (Boolean): `True` if successful
+
         """
         try:
             current_volume = self.channel_current_volume(channel)
diff --git a/src/aura_engine/plugins/clock.py b/src/aura_engine/plugins/clock.py
index 61005cb4..07fc73e0 100644
--- a/src/aura_engine/plugins/clock.py
+++ b/src/aura_engine/plugins/clock.py
@@ -17,6 +17,10 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
+"""
+Update the clock information stored in Engine API.
+"""
+
 import logging
 from datetime import datetime, timedelta
 
@@ -28,8 +32,7 @@ from aura_engine.resources import ResourceUtil
 
 class ClockInfoHandler:
     """
-    Sends current studio clock information to the `engine-api` REST endpoint,
-    whenever a new play command is issued.
+    Sends current studio clock information to the Engine API endpoint.
     """
 
     logger = None
@@ -51,14 +54,14 @@ class ClockInfoHandler:
             return
 
     def on_scheduler_cycle(self, programme):
+        """Call when a new scheduling cycle has been started."""
         # TODO clock updates should also be triggered on scheduler update cycles
         # This will be part of the coming "default station playlist" logic
         pass
 
     def on_fallback_active(self, timeslot, fallback_name):
         """
-        Called when a fallback is activated for the given timeslot,
-        since no default playlist is available.
+        Call when a fallback is activated.
         """
         if timeslot:
             # Only update the current show to the fallback show,
@@ -93,6 +96,7 @@ class ClockInfoHandler:
     def on_play(self, _):
         """
         Event Handler which is called by the engine when some play command to Liquidsoap is issued.
+
         This does not indicate that Liquidsoap started playing actually, only that the command has
         been issued. Naturally this happens slightly before single tracks play audio.
 
@@ -100,6 +104,7 @@ class ClockInfoHandler:
 
         Args:
             entry (PlaylistEntry):
+
         """
         active_playlist_type, active_playlist = self.engine.scheduler.get_active_playlist()
         active_type_id = active_playlist_type.get("id")
@@ -109,7 +114,7 @@ class ClockInfoHandler:
 
     def post_clock_info(self, active_type, active_playlist, active_timeslot, upcoming_timeslots):
         """
-        Posts current information on timeslots and playlist to the Engine API clock endpoint.
+        Post current information on timeslots and playlist to the Engine API clock endpoint.
         """
         next_timeslot = None
 
@@ -128,7 +133,7 @@ class ClockInfoHandler:
 
     def build_timeslot(self, timeslot, playlist_type: int = 0) -> dict:
         """
-        Transforms a `Timeslot` object to a dictionary digestable by the clock API endpoint.
+        Transform a `Timeslot` object to a dictionary digestable by the clock API endpoint.
 
         # FIXME API: Rename "fallback_type" to something more generic like "playlist_type"
 
@@ -143,6 +148,7 @@ class ClockInfoHandler:
 
         Returns:
             timeslot (dict): JSON representation of the timeslot
+
         """
         if not timeslot:
             return
@@ -159,7 +165,7 @@ class ClockInfoHandler:
 
     def build_playlist(self, playlist) -> dict:
         """
-        Transforms a `Playlist` object to a dictionary digestable by the clock API endpoint.
+        Transform a `Playlist` object to a dictionary digestable by the clock API endpoint.
         """
         if not playlist:
             return None
diff --git a/src/aura_engine/plugins/mailer.py b/src/aura_engine/plugins/mailer.py
index 6d4dcd0a..eabbe20d 100644
--- a/src/aura_engine/plugins/mailer.py
+++ b/src/aura_engine/plugins/mailer.py
@@ -17,6 +17,10 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
+"""
+Send Email notifications.
+"""
+
 import logging
 import smtplib
 from email.message import EmailMessage
@@ -33,7 +37,7 @@ class MailingException(Exception):
 
 class AuraMailer:
     """
-    Event handler to send emails to Aura administrators and programme coordinators.
+    Event handler to send emails to AURA administrators and programme coordinators.
     """
 
     logger = None
@@ -42,12 +46,6 @@ class AuraMailer:
     previous_timeslot = None
 
     def __init__(self, engine):
-        """
-        Constructor
-
-        Args:
-        engine (Engine):    The Engine
-        """
         self.logger = logging.getLogger("AuraEngine")
         self.engine = engine
         self.mail = MailService()
@@ -58,8 +56,7 @@ class AuraMailer:
 
     def on_fallback_active(self, timeslot, fallback_type):
         """
-        Called when a fallback is activated for the given timeslot,
-        since no default playlist is available.
+        Call when a fallback is activated for the given timeslot.
         """
         show = "EMPTY TIMESLOT"
         show_id = ""
@@ -82,7 +79,7 @@ class AuraMailer:
 
     def on_sick(self, data):
         """
-        Called when the engine is in some unhealthy state.
+        Call when the engine is in some unhealthy state.
         """
         subject = "ERROR - Engine turned into some INVALID STATE!"
         message = "There's an issue with your AURA Engine '%s':\n\n%s" % (
@@ -93,7 +90,7 @@ class AuraMailer:
 
     def on_resurrect(self, data):
         """
-        Called when the engine turned healthy again after being sick.
+        Call when the engine turned healthy again after being sick.
         """
         subject = "OK - Engine became healthy again"
         message = "Good news, things seem fine again with your AURA Engine '%s':\n\n%s" % (
@@ -104,7 +101,7 @@ class AuraMailer:
 
     def on_critical(self, subject, message, data=None):
         """
-        Callend when some critical event occurs
+        Call when some critical event occurs.
         """
         if not data:
             data = ""
@@ -124,9 +121,6 @@ class MailService:
     coordinator_mails_enabled = None
 
     def __init__(self):
-        """
-        Constructor
-        """
         self.config = AuraConfig.config()
         self.logger = logging.getLogger("AuraEngine")
         self.admin_mails = self.config.get("admin_mail")
@@ -140,11 +134,12 @@ class MailService:
 
     def notify_admin(self, subject, body):
         """
-        Sends an email to the administrator(s) as defined in the configuration.
+        Send an email to the administrator(s) as defined in the configuration.
 
         Args:
-            subject (String):   The email subject
-            body (String):      The email body text
+            subject (String): The email subject
+            body (String): The email body text
+
         """
         if self.admin_mails_enabled == "false":
             self.logger.warning(
@@ -159,11 +154,12 @@ class MailService:
 
     def notify_coordinator(self, subject, body):
         """
-        Sends an email to the programme coordinator(s) as defined in the configuration.
+        Send an email to the programme coordinator(s) as defined in the configuration.
 
         Args:
-            subject (String):   The email subject
-            body (String):      The email body text
+            subject (String): The email subject
+            body (String): The email body text
+
         """
         if self.coordinator_mails_enabled == "false":
             self.logger.warning(
@@ -181,11 +177,12 @@ class MailService:
 
     def send(self, mail_to, subject, body):
         """
-        Sends an email to the given address.
+        Send an email to the given address.
 
         Args:
-            subject (String):   The email's subject
-            body (String):      The email's body text
+            subject (String): The email's subject
+            body (String): The email's body text
+
         """
         mail_server = self.config.get("mail_server")
         mail_port = self.config.get("mail_server_port")
diff --git a/src/aura_engine/plugins/monitor.py b/src/aura_engine/plugins/monitor.py
index b1d6e9e9..1f881c46 100644
--- a/src/aura_engine/plugins/monitor.py
+++ b/src/aura_engine/plugins/monitor.py
@@ -17,6 +17,15 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
+"""
+Monitor the scheduling and playout status.
+
+In case of irregularities:
+    - Send heartbeats
+    - Send health updates to Engine API
+    - Log health updates
+"""
+
 import datetime
 import json
 import logging
@@ -33,24 +42,28 @@ import aura_engine.meta as meta
 from aura_engine.base.config import AuraConfig
 from aura_engine.base.utils import SimpleUtil as SU
 
-# Exceptions
-
 
 class EngineMalfunctionException(Exception):
-    pass
-
+    """
+    Exception thrown when Engine turns into an status invalid for proper playout.
+    """
 
-# Status Codes
+    pass
 
 
 class MonitorResponseCode(Enum):
+    """
+    Enumeration with status types.
+    """
+
     OK = "OK"
     INVALID_STATE = "INVALID-STATE"
 
 
 class AuraMonitor:
-    """
-    Engine Monitoring is in charge of:
+    """Monitoring of the Engine.
+
+    It is in charge of:
 
     - Checking the overall status of all components and external API endpoints
     - Checking the vital parts, which are minimal requirements for running the engine
@@ -73,7 +86,7 @@ class AuraMonitor:
 
     def __init__(self, engine):
         """
-        Initialize Monitoring
+        Initialize Monitoring.
         """
         self.logger = logging.getLogger("AuraEngine")
         self.config = AuraConfig.config()
@@ -105,7 +118,7 @@ class AuraMonitor:
 
     def on_boot(self):
         """
-        Called when the engine is booting.
+        Call when the engine is booting.
         """
         # Start Monitoring
         is_valid = self.has_valid_status(False)
@@ -121,13 +134,13 @@ class AuraMonitor:
 
     def on_sick(self, data):
         """
-        Called when the engine is in some unhealthy state.
+        Call when the engine is in some unhealthy state.
         """
         self.post_health(data, False)
 
     def on_resurrect(self, data):
         """
-        Called when the engine turned healthy again after being sick.
+        Call when the engine turned healthy again after being sick.
         """
         self.post_health(data, True)
 
@@ -137,19 +150,20 @@ class AuraMonitor:
 
     def get_status(self):
         """
-        Retrieves the current monitoring status.
+        Retrieve the current monitoring status.
         """
         return self.status
 
     def has_valid_status(self, update_vitality_only):
         """
-        Checks if the current status is valid to run engine. By default it
-        does not request new status information, rather using the cached one.
-        To request new data either call `get_status()` before or use the
-        `update_vital` parameter.
+        Check if the current status is valid to run engine.
+
+        By default it does not request new status information, rather using the cached one.
+        To request new data either call `get_status()` before or use the `update_vital` parameter.
 
         Args:
             update_vitality_only (bool): Refreshs only the vital parts required for the heartbeat
+
         """
         is_valid = False
 
@@ -219,7 +233,7 @@ class AuraMonitor:
 
     def update_status(self):
         """
-        Requests the current status of all components
+        Request the current status of all components.
         """
         self.status["engine"]["version"] = meta.__version__
 
@@ -248,7 +262,7 @@ class AuraMonitor:
 
     def update_vitality_status(self):
         """
-        Refreshes the vital status info which are required for the engine to survive.
+        Refresh the vital status info which are required for the engine to survive.
         """
         self.engine.player.connector.enable_transaction()
         self.status["lqs"]["status"] = self.engine.update_playout_state()
@@ -263,6 +277,8 @@ class AuraMonitor:
 
     def heartbeat(self):
         """
+        Send heartbeat tick.
+
         Every `heartbeat_frequency` seconds the current vitality status is checked. If it is okay,
         a heartbeat is sent to the configured server.
         """
@@ -303,7 +319,7 @@ class AuraMonitor:
 
     def validate_url_connection(self, url):
         """
-        Checks if connection to passed URL is successful.
+        Check if connection to passed URL is successful.
         """
         try:
             request = urllib.request.Request(url)
@@ -316,7 +332,7 @@ class AuraMonitor:
 
     def validate_directory(self, dir_path):
         """
-        Checks if a given directory is existing and holds content
+        Check if a given directory is existing and holds content.
         """
         status = dict()
         status["path"] = dir_path
@@ -335,13 +351,14 @@ class AuraMonitor:
 
     def get_url_response(self, url):
         """
-        Fetches JSON data from the given URL.
+        Fetch JSON data from the given URL.
 
         Args:
-            url (String):       The API endpoint to call
+            url (String): The API endpoint to call
 
         Returns:
-            (dict[]):           A Python object representing the JSON structure
+            (dict[]): A Python object representing the JSON structure
+
         """
         data = None
 
@@ -357,15 +374,16 @@ class AuraMonitor:
 
     def get_engine_id(self):
         """
-        Retrieves a String identifier consisting of IP and Hostname to differentiate
-        the engine in mails and status broadcasts.
+        Retrieve a String identifier consisting of IP and Hostname.
+
+        This is used to differentiate the engine in mails and status broadcasts.
         """
         host = platform.node()
         return "%s (%s)" % (self.get_ip(), host)
 
     def get_ip(self):
         """
-        Returns the IP of the Engine instance.
+        Return the IP of the Engine instance.
         """
         try:
             s = socket(AF_INET, SOCK_DGRAM)
diff --git a/src/aura_engine/resources.py b/src/aura_engine/resources.py
index bd3339f7..d1141d48 100644
--- a/src/aura_engine/resources.py
+++ b/src/aura_engine/resources.py
@@ -17,6 +17,10 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
+"""
+Utilities and mappings for media resources.
+"""
+
 from enum import Enum
 
 
@@ -52,10 +56,12 @@ class ResourceClass(Enum):
 
     @property
     def types(self):
+        """Retrieve allowed types of the resource class."""
         return self.value["types"]
 
     @property
     def numeric(self):
+        """Retrieve a numeric representation of the resource class."""
         return self.value["numeric"]
 
     def __str__(self):
@@ -70,13 +76,14 @@ class ResourceUtil(Enum):
     @staticmethod
     def get_content_type(uri):
         """
-        Returns the content type identified by the passed URI.
+        Return the content type identified by the passed URI.
 
         Args:
-            uri (String):   The URI of the source
+            uri (String): The URI of the source
 
         Returns:
             (ResourceType)
+
         """
         if uri.startswith(ResourceType.STREAM_HTTP.value):
             return ResourceType.STREAM_HTTP
@@ -90,13 +97,14 @@ class ResourceUtil(Enum):
     @staticmethod
     def get_content_class(content_type):
         """
-        Returns the content class identified by the passed type.
+        Return the content class identified by the passed type.
 
         Args:
-            content_type (ContentType):   The content type
+            content_type (ContentType): The content type
 
         Returns:
             (ResourceType)
+
         """
         if content_type in ResourceClass.FILE.types:
             return ResourceClass.FILE
@@ -110,13 +118,14 @@ class ResourceUtil(Enum):
     @staticmethod
     def generate_m3u_file(target_file, audio_store_path, entries, entry_extension):
         """
-        Writes a M3U file based on the given playlist object.
+        Write a M3U file based on the given playlist object.
 
         Args:
-            target_file (File):         The M3U playlist to write
-            audio_store_path (String):  Folder containing the source files
-            entries (PlaylistEntry):    Entries of the playlist
-            entry_extension (String):   The file extension of the playlist entries
+            target_file (File): The M3U playlist to write
+            audio_store_path (String): Folder containing the source files
+            entries (PlaylistEntry): Entries of the playlist
+            entry_extension (String): The file extension of the playlist entries
+
         """
         file = open(target_file, "w")
         fb = ["#EXTM3U"]
@@ -137,20 +146,22 @@ class ResourceUtil(Enum):
     @staticmethod
     def source_to_filepath(base_dir, source, source_extension):
         """
-        Converts a file-system URI starting with "file://" to an actual,
-        absolute path to the file, appending the extension as provided
-        in "source_extension".
+        Create path from URI and extension.
+
+        Convert a file-system URI starting with "file://" to an actual, absolute path to the file,
+        appending the extension as provided in "source_extension".
 
-        If the path starts with an "/", it indicates that it is already an
-        absolute path including a valid extension.
+        If the path starts with an "/", it indicates that it is already an absolute path including
+        a valid extension.
 
         Args:
-            basi_dir (String):          The location of the audio store.
-            source (String):             The URI of the file
-            source_extension (String):  The file extension of audio sources
+            basi_dir (String): The location of the audio store.
+            source (String): The URI of the file
+            source_extension (String): The file extension of audio sources
 
         Returns:
             path (String):  Absolute file path
+
         """
         path = source[7:]
         if path.startswith("/"):
@@ -161,7 +172,7 @@ class ResourceUtil(Enum):
     @staticmethod
     def get_entries_string(entries):
         """
-        Returns a list of entries as String for logging purposes.
+        Return a list of entries as String for logging purposes.
         """
         s = ""
         if isinstance(entries, list):
@@ -176,7 +187,7 @@ class ResourceUtil(Enum):
     @staticmethod
     def lqs_annotate(uri: str, annotations: dict) -> str:
         """
-        Wraps the given URI with the passed annotation dictionary.
+        Wrap the given URI with the passed annotation dictionary.
         """
         metadata = ""
         for k, v in annotations.items():
@@ -190,7 +201,7 @@ class ResourceUtil(Enum):
         assign_track_start: bool = False,
     ) -> dict:
         """
-        Generates Liquidsoap track metadata based on an entry.
+        Generate Liquidsoap track metadata based on an entry.
         """
         content_type = ResourceUtil.get_content_type(entry.source)
         content_class = ResourceUtil.get_content_class(content_type)
diff --git a/src/aura_engine/scheduling/api.py b/src/aura_engine/scheduling/api.py
index 7cffc1a6..6ba42cb6 100644
--- a/src/aura_engine/scheduling/api.py
+++ b/src/aura_engine/scheduling/api.py
@@ -17,6 +17,10 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
+"""
+Collection of tools for AURA API handling.
+"""
+
 import logging
 import queue
 import threading
@@ -29,8 +33,10 @@ from aura_engine.scheduling.utils import TimeslotFilter
 
 class ApiFetcher(threading.Thread):
     """
-    Fetches the timeslots, playlists and playlist entries as JSON
-    via the API endpoints of Steering and Tank.
+    Get data from AURA REST APIs.
+
+    Retrieve timeslots, playlists and playlist entries as JSON via the API endpoints of Steering
+    and Tank.
     """
 
     config = None
@@ -47,9 +53,6 @@ class ApiFetcher(threading.Thread):
     tank_secret = None
 
     def __init__(self, config):
-        """
-        Constructor
-        """
         self.config = config
         self.logger = logging.getLogger("AuraEngine")
         self.steering_calendar_url = self.config.get("api_steering_calendar")
@@ -61,11 +64,11 @@ class ApiFetcher(threading.Thread):
         threading.Thread.__init__(self)
 
     def run(self):
-        """
-        Fetch timeslot data from the API.
+        """Fetch timeslot data from the API.
 
         Returns
             Timeslot ([dict]):  An array of retrieved timeslots dictionary
+
         """
         try:
             fetched_timeslots = self.fetch()
@@ -91,15 +94,11 @@ class ApiFetcher(threading.Thread):
     #
 
     def get_fetched_data(self):
-        """
-        Retrieves the fetched data from the queue.
-        """
+        """Retrieve fetched data from the queue."""
         return self.queue.get()
 
     def fetch(self):
-        """
-        Retrieve all required data from the API.
-        """
+        """Retrieve all required data from the API."""
         return_data = []
 
         self.logger.debug("Fetching timeslots from STEERING")
@@ -145,11 +144,11 @@ class ApiFetcher(threading.Thread):
         return return_data
 
     def fetch_timeslot_data(self):
-        """
-        Fetches timeslot data from Steering.
+        """Fetch timeslot data from Steering.
 
         Returns:
             ([Timeslot]):   An array of timeslots
+
         """
         response = None
         timeslots = None
@@ -187,8 +186,8 @@ class ApiFetcher(threading.Thread):
         return self.polish_timeslots(timeslots)
 
     def fetch_playlists(self):
-        """
-        Fetches all playlists including fallback playlists for every timeslot.
+        """Fetch all playlists including fallback playlists for every timeslot.
+
         This method used the class member `fetched_timeslot_data`` to iterate
         over and extend timeslot data.
         """
@@ -232,15 +231,15 @@ class ApiFetcher(threading.Thread):
             self.logger.error("Error while fetching playlists from API endpoints: " + str(e), e)
 
     def fetch_playlist(self, playlist_id, fetched_playlists):
-        """
-        Fetches the playlist for a given timeslot.
+        """Fetch the playlist for a given timeslot.
 
         Args:
-            playlist_id (String):       The ID of the playlist
+            playlist_id (String): The ID of the playlist
             fetched_playlists ([dict]): Previously fetched playlists to avoid re-fetching
 
         Returns:
-            (Playlist):             Playlist for `playlist_id`
+            (Playlist): Playlist for `playlist_id`
+
         """
         if not playlist_id:
             return None
@@ -282,15 +281,15 @@ class ApiFetcher(threading.Thread):
         return playlist
 
     def get_playlist_id(self, timeslot, id_name):
-        """
-        Extracts the playlist ID for a given playlist (fallback) type.
+        """Extract the playlist ID for a given playlist (fallback) type.
 
         Args:
-            timeslot (dict):    The timeslot dictionary
-            id_name (String):   The dictionary key holding the playlist ID
+            timeslot (dict): The timeslot dictionary
+            id_name (String): The dictionary key holding the playlist ID
 
         Returns:
-            (Integer):  The playlist ID
+            (Integer): The playlist ID
+
         """
         if id_name not in timeslot:
             return None
@@ -305,9 +304,9 @@ class ApiFetcher(threading.Thread):
         return playlist_id
 
     def polish_timeslots(self, timeslots):
-        """
-        Removes all timeslots which are not relevant for further processing,
-        and transparent timeslot ID assignment for more expressive use.
+        """Remove all timeslots which are not relevant for further processing.
+
+        Also, add transparent timeslot ID assignment for more expressive use.
         """
         count_before = len(timeslots)
         timeslots = TimeslotFilter.filter_24h(timeslots)
@@ -323,8 +322,6 @@ class ApiFetcher(threading.Thread):
         return timeslots
 
     def terminate(self):
-        """
-        Terminates the thread.
-        """
+        """Terminate the thread."""
         self.logger.info(SU.yellow("[ApiFetcher] Shutting down..."))
         self.stop_event.set()
diff --git a/src/aura_engine/scheduling/models.py b/src/aura_engine/scheduling/models.py
index 0daf8180..35449a3e 100644
--- a/src/aura_engine/scheduling/models.py
+++ b/src/aura_engine/scheduling/models.py
@@ -17,6 +17,10 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
+"""
+Holds all database models based on SQLAlchemy.
+"""
+
 import datetime
 import logging
 import sys
@@ -49,11 +53,13 @@ Base.metadata.bind = engine
 
 
 class DB:
+    """Database object."""
+
     Model = Base
 
     @classmethod
     def set_flask_db(cls, db):
-        """configure an "flask_sqlalchemy.SQLAlchemy" object for future usage via 'DB.session'
+        """Configure an "flask_sqlalchemy.SQLAlchemy" object for future usage via 'DB.session.'.
 
         The SQLAlchemy object should be created once during startup (`SQLAlchemy(flask_app)`).
         It provides a request-based database session, which can be accessed via 'DB.session'.
@@ -63,7 +69,7 @@ class DB:
     @classmethod
     @property
     def session(cls):
-        """return the database session provided for this request"""
+        """Return the database session provided for this request."""
         try:
             flask_db = cls._flask_db
         except AttributeError:
@@ -76,8 +82,7 @@ class DB:
 
 
 class AuraDatabaseModel:
-    """
-    AuraDataBaseModel.
+    """AuraDataBaseModel.
 
     Holding all tables and relationships for the engine.
     """
@@ -85,14 +90,11 @@ class AuraDatabaseModel:
     logger = None
 
     def __init__(self):
-        """
-        Constructor.
-        """
         self.logger = logging.getLogger("AuraEngine")
 
     def store(self, add=False, commit=False):
         """
-        Store to the database
+        Store to the database.
         """
         if add:
             DB.session.add(self)
@@ -103,7 +105,7 @@ class AuraDatabaseModel:
 
     def delete(self, commit=False):
         """
-        Delete from the database
+        Delete from the database.
         """
         DB.session.delete(self)
         if commit:
@@ -111,7 +113,7 @@ class AuraDatabaseModel:
 
     def refresh(self):
         """
-        Refreshes the correct record
+        Refresh the correct record.
         """
         DB.session.expire(self)
         DB.session.refresh(self)
@@ -122,10 +124,11 @@ class AuraDatabaseModel:
     @staticmethod
     def init_database():
         """
-        Initializes the database tables if they are not existing.
+        Initialize the database tables if they are not existing.
 
         Raises:
             sqlalchemy.exc.ProgrammingError:    In case the DB model is invalid
+
         """
         try:
             Playlist.is_empty()
@@ -148,7 +151,7 @@ class AuraDatabaseModel:
     @staticmethod
     def recreate_db(systemexit=False):
         """
-        Deletes all tables and re-creates the database.
+        Delete all tables and re-creates the database.
         """
         Base.metadata.drop_all()
         Base.metadata.create_all()
@@ -180,6 +183,7 @@ class Timeslot(DB.Model, AuraDatabaseModel):
             (includes silence detection)
         station_fallback (Playlist):    Defined in the original AURA API but not implemented, as
             station fallbacks are handled locally
+
     """
 
     __tablename__ = "timeslot"
@@ -278,25 +282,27 @@ class Timeslot(DB.Model, AuraDatabaseModel):
 
     @staticmethod
     def for_datetime(date_time):
-        """
-        Select a timeslot at the given datetime.
+        """Select a timeslot at the given datetime.
 
         Args:
             date_time (datetime): date and time when the timeslot starts
+
         """
         return DB.session.query(Timeslot).filter(Timeslot.timeslot_start == date_time).first()
 
     @staticmethod
     def get_timeslots(date_from=datetime.date.today()):
-        """
+        """Get timeslots starting with given date.
+
         Select all timeslots starting from `date_from` or from today if no
         parameter is passed.
 
         Args:
-            date_from (datetime):   Select timeslots from this date and time on
+            date_from (datetime): Select timeslots from this date and time on
 
         Returns:
-            ([Timeslot]):           List of timeslots
+            ([Timeslot]): List of timeslots
+
         """
         timeslots = (
             DB.session.query(Timeslot)
@@ -308,22 +314,16 @@ class Timeslot(DB.Model, AuraDatabaseModel):
 
     @hybrid_property
     def start_unix(self):
-        """
-        Start time of the timeslot in UNIX time.
-        """
+        """Start time of the timeslot in UNIX time."""
         return time.mktime(self.timeslot_start.timetuple())
 
     @hybrid_property
     def end_unix(self):
-        """
-        End time of the timeslot in UNIX time.
-        """
+        """End time of the timeslot in UNIX time."""
         return time.mktime(self.timeslot_end.timetuple())
 
     def as_dict(self):
-        """
-        Returns the timeslot as a dictionary for serialization.
-        """
+        """Return the timeslot as a dictionary for serialization."""
         playlist = self.playlist
 
         return {
@@ -348,9 +348,6 @@ class Timeslot(DB.Model, AuraDatabaseModel):
         }
 
     def __str__(self):
-        """
-        String representation of the object.
-        """
         time_start = SimpleUtil.fmt_time(self.start_unix)
         time_end = SimpleUtil.fmt_time(self.end_unix)
         return "ID#%s [Show: %s, ShowID: %s | %s - %s ]" % (
@@ -368,9 +365,7 @@ class Timeslot(DB.Model, AuraDatabaseModel):
 
 
 class Playlist(DB.Model, AuraDatabaseModel):
-    """
-    The playlist containing playlist entries.
-    """
+    """The playlist containing playlist entries."""
 
     __tablename__ = "playlist"
 
@@ -394,19 +389,19 @@ class Playlist(DB.Model, AuraDatabaseModel):
 
     @staticmethod
     def select_playlist_for_timeslot(start_date: datetime.datetime, playlist_id):
-        """
-        Retrieves the playlist for the given timeslot identified by `start_date` and `playlist_id`
+        """Retrieve the playlist for the given timeslot identified by `start_date` and `playlist_id`.
 
         Args:
-            start_date (datetime):  Date and time when the playlist is scheduled
-            playlist_id (Integer):  The ID of the playlist
+            start_date (datetime): Date and time when the playlist is scheduled
+            playlist_id (Integer): The ID of the playlist
 
         Returns:
-            (Playlist):             The playlist, if existing for timeslot
+            (Playlist): The playlist, if existing for timeslot
 
         Raises:
-            Exception:              In case there a inconsistent database state, such es multiple
+            Exception: In case there a inconsistent database state, such es multiple
                 playlists for given date/time.
+
         """
         playlist = None
         playlists = DB.session.query(Playlist).filter(Playlist.timeslot_start == start_date).all()
@@ -420,13 +415,14 @@ class Playlist(DB.Model, AuraDatabaseModel):
     @staticmethod
     def select_playlist(playlist_id):
         """
-        Retrieves all paylists for that given playlist ID.
+        Retrieve all paylists for that given playlist ID.
 
         Args:
-            playlist_id (Integer):  The ID of the playlist
+            playlist_id (Integer): The ID of the playlist
 
         Returns:
-            (Array<Playlist>):      An array holding the playlists
+            (Array<Playlist>): An array holding the playlists
+
         """
         return (
             DB.session.query(Playlist)
@@ -437,9 +433,7 @@ class Playlist(DB.Model, AuraDatabaseModel):
 
     @staticmethod
     def is_empty():
-        """
-        Checks if the given is empty
-        """
+        """Check if the given is empty."""
         try:
             return not DB.session.query(Playlist).one_or_none()
         except sa.orm.exc.MultipleResultsFound:
@@ -447,25 +441,21 @@ class Playlist(DB.Model, AuraDatabaseModel):
 
     @hybrid_property
     def start_unix(self):
-        """
-        Start time of the playlist in UNIX time.
-        """
+        """Start time of the playlist in UNIX time."""
         return time.mktime(self.timeslot_start.timetuple())
 
     @hybrid_property
     def end_unix(self):
-        """
-        End time of the playlist in UNIX time.
-        """
+        """End time of the playlist in UNIX time."""
         return time.mktime(self.timeslot_start.timetuple()) + self.duration
 
     @hybrid_property
     def duration(self):
-        """
-        Returns the total length of the playlist in seconds.
+        """Return the total length of the playlist in seconds.
 
         Returns:
             (Integer):  Length in seconds
+
         """
         total = 0
 
@@ -474,9 +464,6 @@ class Playlist(DB.Model, AuraDatabaseModel):
         return total
 
     def __str__(self):
-        """
-        String representation of the object.
-        """
         time_start = SimpleUtil.fmt_time(self.start_unix)
         time_end = SimpleUtil.fmt_time(self.end_unix)
         return "ID#%s [items: %s | %s - %s]" % (
@@ -493,9 +480,7 @@ class Playlist(DB.Model, AuraDatabaseModel):
 
 
 class PlaylistEntry(DB.Model, AuraDatabaseModel):
-    """
-    Playlist entries are the individual items of a playlist such as audio files.
-    """
+    """Playlist entries are the individual items of a playlist such as audio files."""
 
     __tablename__ = "playlist_entry"
 
@@ -522,9 +507,7 @@ class PlaylistEntry(DB.Model, AuraDatabaseModel):
 
     @staticmethod
     def select_playlistentry_for_playlist(artificial_playlist_id, entry_num):
-        """
-        Selects one entry identified by `playlist_id` and `entry_num`.
-        """
+        """Select one entry identified by `playlist_id` and `entry_num`."""
         return (
             DB.session.query(PlaylistEntry)
             .filter(
@@ -536,9 +519,7 @@ class PlaylistEntry(DB.Model, AuraDatabaseModel):
 
     @staticmethod
     def delete_entry(artificial_playlist_id, entry_num):
-        """
-        Deletes the playlist entry and associated metadata.
-        """
+        """Delete the playlist entry and associated metadata."""
         entry = PlaylistEntry.select_playlistentry_for_playlist(artificial_playlist_id, entry_num)
         metadata = PlaylistEntryMetaData.select_metadata_for_entry(entry.artificial_id)
         metadata.delete()
@@ -547,9 +528,7 @@ class PlaylistEntry(DB.Model, AuraDatabaseModel):
 
     @staticmethod
     def count_entries(artificial_playlist_id):
-        """
-        Returns the count of all entries.
-        """
+        """Return the count of all entries."""
         result = (
             DB.session.query(PlaylistEntry)
             .filter(PlaylistEntry.artificial_playlist_id == artificial_playlist_id)
@@ -559,25 +538,29 @@ class PlaylistEntry(DB.Model, AuraDatabaseModel):
 
     @hybrid_property
     def entry_end(self):
+        """Entry end datetime."""
         return self.entry_start + datetime.timedelta(seconds=self.duration)
 
     @hybrid_property
     def start_unix(self):
+        """Entry start as UNIX time."""
         return time.mktime(self.entry_start.timetuple())
 
     @hybrid_property
     def end_unix(self):
+        """Entry end as UNIX time."""
         return time.mktime(self.entry_end.timetuple())
 
     def get_content_type(self):
+        """Get content type for the given source URI."""
         return ResourceUtil.get_content_type(self.source)
 
     def get_prev_entries(self):
-        """
-        Retrieves all previous entries as part of the current entry's playlist.
+        """Retrieve all previous entries as part of the current entry's playlist.
 
         Returns:
             (List):     List of PlaylistEntry
+
         """
         prev_entries = []
         for entry in self.playlist.entries:
@@ -586,15 +569,15 @@ class PlaylistEntry(DB.Model, AuraDatabaseModel):
         return prev_entries
 
     def get_next_entries(self, timeslot_sensitive=True):
-        """
-        Retrieves all following entries as part of the current entry's playlist.
+        r"""Retrieve all following entries as part of the current entry's playlist.
 
         Args:
-            timeslot_sensitive (Boolean):   If `True` entries which start after \
+            timeslot_sensitive (Boolean): If `True` entries which start after \
                 the end of the timeslot are excluded
 
         Returns:
-            (List):     List of PlaylistEntry
+            (List): List of PlaylistEntry
+
         """
         next_entries = []
         for entry in self.playlist.entries:
@@ -607,9 +590,7 @@ class PlaylistEntry(DB.Model, AuraDatabaseModel):
         return next_entries
 
     def as_dict(self):
-        """
-        Returns the entry as a dictionary for serialization.
-        """
+        """Return the entry as a dictionary for serialization."""
         if self.meta_data:
             return {
                 "id": self.artificial_id,
@@ -621,9 +602,6 @@ class PlaylistEntry(DB.Model, AuraDatabaseModel):
         return None
 
     def __str__(self):
-        """
-        String representation of the object.
-        """
         time_start = SimpleUtil.fmt_time(self.start_unix)
         time_end = SimpleUtil.fmt_time(self.end_unix)
         track = self.source[-25:]
@@ -662,6 +640,9 @@ class PlaylistEntryMetaData(DB.Model, AuraDatabaseModel):
 
     @staticmethod
     def select_metadata_for_entry(artificial_playlistentry_id):
+        """
+        Select a metadata entry.
+        """
         return (
             DB.session.query(PlaylistEntryMetaData)
             .filter(PlaylistEntryMetaData.artificial_entry_id == artificial_playlistentry_id)
diff --git a/src/aura_engine/scheduling/programme.py b/src/aura_engine/scheduling/programme.py
index db79ef94..63ac1a49 100644
--- a/src/aura_engine/scheduling/programme.py
+++ b/src/aura_engine/scheduling/programme.py
@@ -17,6 +17,10 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
+"""
+Services representing and dealing with the programme timetable.
+"""
+
 import logging
 from datetime import datetime
 
@@ -46,20 +50,17 @@ class ProgrammeService:
     programme_store = None
 
     def __init__(self):
-        """
-        Constructor
-        """
         self.config = AuraConfig.config()
         self.logger = logging.getLogger("AuraEngine")
         self.programme_store = ProgrammeStore()
 
     def refresh(self):
         """
-        Fetch the latest programme from `ProgrammeStore` which stores it to the database.
+        Do fetch the latest programme from `ProgrammeStore` which stores it to the database.
+
         After that, the programme is in turn loaded from the database and stored in
         `self.timeslots`.
         """
-
         # Fetch programme from API endpoints
         self.logger.debug("Trying to fetch new programme from API endpoints...")
 
@@ -115,10 +116,11 @@ class ProgrammeService:
 
     def get_current_entry(self):
         """
-        Retrieves the current `PlaylistEntry` which should be played as per programme.
+        Retrieve the current `PlaylistEntry` which should be played as per programme.
 
         Returns:
             (PlaylistEntry): The track which is (or should) currently being played
+
         """
         now_unix = Engine.engine_time()
 
@@ -162,10 +164,11 @@ class ProgrammeService:
 
     def get_current_timeslot(self):
         """
-        Retrieves the timeslot currently to be played.
+        Retrieve the timeslot currently to be played.
 
         Returns:
             (Timeslot): The current timeslot
+
         """
         current_timeslot = None
         now_unix = Engine.engine_time()
@@ -181,13 +184,15 @@ class ProgrammeService:
 
     def get_current_playlist(self, timeslot):
         """
-        Retrieves the playlist to be scheduled. If no specific playlist is assigned,
-        the default schedule or show playlist is returned. This method does not
-        respect any defined fallback playlists.
+        Retrieve the playlist to be scheduled.
+
+        If no specific playlist is assigned, the default schedule or show playlist is returned.
+        This method does not respect any defined fallback playlists.
 
         Returns:
             (dict, Playlist): A dictionary holding the playlist type, the currently assigned
                 playlist
+
         """
         playlist_type = Playlist.TYPE_TIMESLOT
         playlist = timeslot.playlist
@@ -202,7 +207,7 @@ class ProgrammeService:
 
     def get_next_timeslots(self, max_count=0):
         """
-        Retrieves the timeslots to be played after the current one.
+        Retrieve the timeslots to be played after the current one.
 
         Args:
             max_count (Integer): Maximum of timeslots to return, if `0` all existing ones are
@@ -210,6 +215,7 @@ class ProgrammeService:
 
         Returns:
             ([Timeslot]): The next timeslots
+
         """
         now_unix = Engine.engine_time()
         next_timeslots = []
@@ -228,7 +234,7 @@ class ProgrammeService:
 
     def is_timeslot_in_window(self, timeslot):
         """
-        Checks if the timeslot is within the scheduling window.
+        Check if the timeslot is within the scheduling window.
         """
         now_unix = Engine.engine_time()
         window_start = self.config.get("scheduling_window_start")
@@ -244,7 +250,7 @@ class ProgrammeService:
 
     def terminate(self):
         """
-        Called when thread is stopped or a signal to terminate is received.
+        Call this when the thread is stopped or a signal to terminate is received.
         """
         self.logger.info(SU.yellow("[ProgrammeService] Shutting down..."))
         if self.api_fetcher:
@@ -253,9 +259,10 @@ class ProgrammeService:
 
 class ProgrammeStore:
     """
-    The `ProgrammeStore` service retrieves all current schedules and related
-    playlists including audio files from the configured API endpoints and stores
-    it in the local database.
+    The `ProgrammeStore` service retrieves all current schedules and related playlists.
+
+    This includes audio files from the configured API endpoints and stores it in the local
+    database.
 
     To perform the API queries it utilizes the ApiFetcher class.
     """
@@ -265,16 +272,13 @@ class ProgrammeStore:
     m3u_processor = None
 
     def __init__(self):
-        """
-        Initializes the class.
-        """
         self.config = AuraConfig.config()
         self.logger = logging.getLogger("AuraEngine")
         self.m3u_processor = M3UPlaylistProcessor()
 
     def load_timeslots(self):
         """
-        Loads the programme from the database.
+        Load the programme from the database.
         """
         timeslots = None
         try:
@@ -288,7 +292,7 @@ class ProgrammeStore:
 
     def store_timeslots(self, fetched_timeslots):
         """
-        Stores the fetched timeslots to the database.
+        Store the fetched timeslots to the database.
         """
         timeslots = []
 
@@ -349,7 +353,7 @@ class ProgrammeStore:
 
     def update_deleted_timeslots(self, fetched_timeslots):
         """
-        Checks if some timeslot has been deleted remotely, so delete it locally too.
+        Check if some timeslot has been deleted remotely, so delete it locally too.
 
         Attention: This method has no effect if only a single existing timeslot got
         deleted, i.e. zero timeslots got returned, because this could simply indicate
@@ -359,6 +363,7 @@ class ProgrammeStore:
 
         Args:
             fetched_timeslots ([dict]): List of timeslot dictionaries from the API
+
         """
         now_unix = SU.timestamp()
         scheduling_window_start = self.config.get("scheduling_window_start")
@@ -403,10 +408,11 @@ class ProgrammeStore:
 
     def store_timeslot(self, timeslot):
         """
-        Stores the given timeslot to the database.
+        Store the given timeslot to the database.
 
         Args:
-            timeslot (Timeslot):    The timeslot
+            timeslot (Timeslot): The timeslot
+
         """
         timeslot_start = SU.to_datetime(timeslot["start"])
         timeslot_db = Timeslot.for_datetime(timeslot_start)
@@ -452,7 +458,7 @@ class ProgrammeStore:
 
     def store_playlist(self, timeslot_db, playlist_id, fetched_playlist):
         """
-        Stores the Playlist to the database.
+        Store the Playlist to the database.
         """
         if not playlist_id or not fetched_playlist:
             self.logger.debug(f"Playlist ID#{playlist_id} is not available!")
@@ -487,7 +493,7 @@ class ProgrammeStore:
 
     def store_playlist_entries(self, timeslot_db, playlist_db, fetched_playlist):
         """
-        Stores the playlist entries to the database.
+        Store the playlist entries to the database.
         """
         entry_num = 0
         time_marker = playlist_db.start_unix
@@ -531,7 +537,8 @@ class ProgrammeStore:
 
     def delete_orphaned_entries(self, playlist_db, entries):
         """
-        Deletes all playlist entries which are beyond the current playlist's `entry_count`.
+        Delete all playlist entries which are beyond the current playlist's `entry_count`.
+
         Such entries might be existing due to a remotely changed playlist, which now has
         less entries than before.
         """
@@ -550,11 +557,15 @@ class ProgrammeStore:
 
     def expand_entry_duration(self, timeslot_db, entries):
         """
+        Expand entry to the timeslot gap left.
+
         If some playlist entry doesn't have a duration assigned, its duration is expanded to the
         remaining duration of the playlist (= timeslot duration minus playlist entries with
         duration).
+
         If there is more than one entry without duration, such entries are removed from the
         playlist.
+
         """
         total_seconds = (timeslot_db.timeslot_end - timeslot_db.timeslot_start).total_seconds()
         total_duration = SU.seconds_to_nano(total_seconds)
@@ -584,7 +595,7 @@ class ProgrammeStore:
 
     def store_playlist_entry_metadata(self, entry_db, metadata):
         """
-        Stores the meta-data for a PlaylistEntry.
+        Store the meta-data for a PlaylistEntry.
         """
         metadata_db = PlaylistEntryMetaData.select_metadata_for_entry(entry_db.artificial_id)
         havetoadd = False
diff --git a/src/aura_engine/scheduling/scheduler.py b/src/aura_engine/scheduling/scheduler.py
index 24c93941..cfbafc02 100644
--- a/src/aura_engine/scheduling/scheduler.py
+++ b/src/aura_engine/scheduling/scheduler.py
@@ -17,6 +17,10 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
+"""
+The scheduler.
+"""
+
 import logging
 import threading
 import time
@@ -34,8 +38,7 @@ from aura_engine.scheduling.utils import TimeslotRenderer
 
 
 class AuraScheduler(threading.Thread):
-    """
-    Aura Scheduler Class
+    """The programme scheduler.
 
     - Retrieves data from Steering and Tank
     - Executes engine actions in an automated fashion
@@ -53,14 +56,6 @@ class AuraScheduler(threading.Thread):
     is_engine_ready: bool = None
 
     def __init__(self, engine):
-        """
-        Constructor
-
-        Args:
-            config (AuraConfig):        Reads the engine configuration
-            engine (Engine):            The engine to play the schedule on
-            func_on_init (Function):    The function to be called when the scheduler is initialized
-        """
         self.config = AuraConfig.config()
         self.logger = logging.getLogger("AuraEngine")
         self.programme = ProgrammeService()
@@ -80,7 +75,8 @@ class AuraScheduler(threading.Thread):
         self.start()
 
     def run(self):
-        """
+        """Execute the scheduler.
+
         Called when thread is started via `start()`. It does the following:
 
             1. `self.fetch_new_programme()` periodically from the API depending on the
@@ -120,7 +116,8 @@ class AuraScheduler(threading.Thread):
     #
 
     def on_ready(self):
-        """
+        """Handle `on_ready` event.
+
         Called when the engine has finished booting and is ready to play.
         """
         self.is_initialized = True
@@ -134,7 +131,8 @@ class AuraScheduler(threading.Thread):
             pass
 
     def on_play(self, entry):
-        """
+        """Handle `on_play` event.
+
         Event Handler which is called by the engine when some play command to Liquidsoap is issued.
         This does not indicate that Liquidsoap started playing actually, only that the command has
         been issued. To get the metadata update issued by Liquidsoap use `on_metadata` instead.
@@ -143,6 +141,7 @@ class AuraScheduler(threading.Thread):
 
         Args:
             entry (PlaylistEntry):
+
         """
         if entry.channel in ChannelType.FALLBACK_QUEUE.channels:
             return
@@ -155,19 +154,20 @@ class AuraScheduler(threading.Thread):
 
     def get_programme(self):
         """
-        Returns the current programme.
+        Return the current programme.
         """
         return self.programme
 
     def play_active_entry(self):
-        """
+        """Play currently active playlist entry, as per programme.
+
         Plays the entry scheduled for the very current moment and forwards to the scheduled
-        position in time.
-        Usually called when the Engine boots.
+        position in time. Usually called when the Engine boots.
 
         Raises:
-            (NoActiveTimeslotException):    If there's no timeslot in the programme, within the
+            (NoActiveTimeslotException): If there's no timeslot in the programme, within the
                 scheduling window
+
         """
         sleep_offset = 10
         active_timeslot = self.programme.get_current_timeslot()
@@ -227,13 +227,14 @@ class AuraScheduler(threading.Thread):
             self.logger.critical("Unknown Entry Type: %s" % active_entry)
 
     def get_active_playlist(self):
-        """
-        Retrieves the currently playing playlist. If there is no specific playlist for this
-        timeslots, then any "default playlist" available on the timeslot or show level, is
-        returned.
+        """Retrieve the currently playing playlist.
+
+        If there is no specific playlist for this timeslots, then any "default playlist" available
+        on the timeslot or show level, is returned.
 
         Returns:
             (Dict, Playlist): A dictionary holding the playlist type and the resolved playlist
+
         """
         timeslot = self.programme.get_current_timeslot()
         if timeslot:
@@ -242,23 +243,25 @@ class AuraScheduler(threading.Thread):
 
     def resolve_playlist(self, timeslot):
         """
-        Retrieves the planned or default playlist for the given timeslot.
+        Retrieve the planned or default playlist for the given timeslot.
 
         Args:
             timeslot (Timeslot)
 
         Returns:
             (Dict, Playlist): A dictionary holding the playlist type and the resolved playlist
+
         """
         playlist_type, playlist = self.programme.get_current_playlist(timeslot)
         return (playlist_type, playlist)
 
     def queue_programme(self):
         """
-        Queues the current programme (playlists as per timeslot) by creating
-        timed commands to the sound-system to enable the individual tracks of playlists.
-        """
+        Queue the current programme.
 
+        Playlists of every timeslot are queued by creating timed commands to the sound-system to
+        enable the individual tracks of playlists.
+        """
         # Get a clean set of the timeslots within the scheduling window
         timeslots = self.programme.get_next_timeslots()
         timeslots = self.filter_scheduling_window(timeslots)
@@ -277,8 +280,9 @@ class AuraScheduler(threading.Thread):
 
     def queue_startup_entries(self):
         """
-        Queues all entries after the one currently playing upon startup. Don't use
-        this method in any other scenario, as it doesn't respect the scheduling window.
+        Queue all entries after the one currently playing upon startup.
+
+        Don't use this method in any other scenario, as it doesn't respect the scheduling window.
         """
         current_timeslot = self.programme.get_current_timeslot()
 
@@ -294,9 +298,7 @@ class AuraScheduler(threading.Thread):
                     self.queue_playlist_entries(current_timeslot, rest_of_playlist, False, True)
 
     def queue_playlist_entries(self, timeslot, entries, fade_in, fade_out):
-        """
-        Creates sound-system player commands for all playlist items to be executed at the scheduled
-        time.
+        """Create player commands for all playlist items to be executed at the scheduled time.
 
         Since each scheduled playlist can consist of multiple entry types such as *file*, *live*,
         and *stream*, the play-out of the timeslot is actually a bit more complex.
@@ -319,13 +321,14 @@ class AuraScheduler(threading.Thread):
             this stage at all.
 
         Args:
-            timeslot (Timeslot):        The timeslot this entries belong to
-            entries ([PlaylistEntry]):  The playlist entries to be scheduled for playout
-            fade_in (Boolean):          Fade-in at the beginning of the set of entries
-            fade_out (Boolean):         Fade-out at the end of the set of entries
+            timeslot (Timeslot): The timeslot this entries belong to
+            entries ([PlaylistEntry]): The playlist entries to be scheduled for playout
+            fade_in (Boolean): Fade-in at the beginning of the set of entries
+            fade_out (Boolean): Fade-out at the end of the set of entries
 
         Returns:
-            (String):                   Formatted string to display playlist entries in log
+            (String): Formatted string to display playlist entries in log
+
         """
         entry_groups = []
         entry_groups.append([])
@@ -362,7 +365,8 @@ class AuraScheduler(threading.Thread):
             self.logger.warn(SU.red("Nothing to schedule ..."))
 
     def filter_scheduling_window(self, timeslots):
-        """
+        """Filter only timeslots within the scheduling window.
+
         Ignore timeslots which are before the start of scheduling window
         (start of timeslot - `scheduling_window_start`) or after the end of the scheduling window
         (end of timeslot -`scheduling_window_end`).
@@ -405,7 +409,7 @@ class AuraScheduler(threading.Thread):
 
     def terminate(self):
         """
-        Called when thread is stopped or a signal to terminate is received.
+        Call this method when thread is stopped or a signal to terminate is received.
         """
         self.logger.info(SU.yellow("[Scheduler] Shutting down..."))
         self.programme.terminate()
@@ -426,12 +430,11 @@ class TimeslotCommand(EngineExecutor):
     config: AuraConfig = None
 
     def __init__(self, engine: Engine, timeslot):
-        """
-        Constructor
+        """Initialize the timeslot command.
 
         Args:
-            engine (Engine):        The engine
-            timeslot (Timeslot):    The timeslot which is starting at this time
+            engine (Engine): The engine
+            timeslot (Timeslot): The timeslot which is starting at this time
         """
         self.config = AuraConfig()
         self.engine = engine
@@ -468,14 +471,16 @@ class TimeslotCommand(EngineExecutor):
 
     def do_start_timeslot(self, timeslot):
         """
-        Initiates the start of the timeslot.
+        Indicate the start of the timeslot by sending a `on_timeslot_start` event.
         """
         self.logger.info(SU.cyan(f"=== on_timeslot_start('{timeslot}') ==="))
         self.engine.event_dispatcher.on_timeslot_start(timeslot)
 
     def do_end_timeslot(self, timeslot):
         """
-        Initiates the end of the timeslot.
+        Indicate the start of the timeslot by sending a `on_timeslot_end` event.
+
+        Also resetting the used channel.
         """
         self.logger.info(SU.cyan(f"=== on_timeslot_end('{timeslot}') ==="))
         self.engine.event_dispatcher.on_timeslot_end(timeslot)
@@ -497,12 +502,11 @@ class PlayCommand(EngineExecutor):
     config: AuraConfig = None
 
     def __init__(self, engine: Engine, entries):
-        """
-        Constructor
+        """Initialize the play command.
 
         Args:
-            engine (Engine):            The engine
-            entries (PlaylistEntry):    One or more playlist entries to be started
+            engine (Engine): The engine
+            entries (PlaylistEntry): One or more playlist entries to be started
         """
         self.config = AuraConfig()
         self.engine = engine
diff --git a/src/aura_engine/scheduling/utils.py b/src/aura_engine/scheduling/utils.py
index 47cd6000..49f1526a 100644
--- a/src/aura_engine/scheduling/utils.py
+++ b/src/aura_engine/scheduling/utils.py
@@ -17,6 +17,10 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
+"""
+A collection of utilities used for scheduling.
+"""
+
 import logging
 from datetime import datetime
 from enum import Enum
@@ -42,8 +46,9 @@ class TimeslotFilter:
 
     @staticmethod
     def filter_24h(timeslots):
-        """
-        Removes entries 24h in the future and 12 hours in the past.
+        """Filter timeslot of the last 24 hours.
+
+        Remove entries 24h in the future and 12 hours in the past.
         Note: This might influence resuming (in case of a crash)
         single timeslots which are longer than 12 hours long.
         Think e.g. live broadcasts.
@@ -64,8 +69,9 @@ class TimeslotFilter:
 
     @staticmethod
     def filter_past(timeslots):
-        """
-        Removes all timeslot dictionaries from the past, except the one which is
+        """Filter old timeslots.
+
+        Remove all timeslot dictionaries from the past, except the one which is
         currently playing.
         """
         items = []
@@ -96,16 +102,13 @@ class M3UPlaylistProcessor:
     playlist_folder = None
 
     def __init__(self):
-        """
-        Constructor
-        """
         self.config = AuraConfig.config()
         self.logger = logging.getLogger("AuraEngine")
         self.playlist_folder = self.config.abs_playlist_path()
 
     def spread(self, entries):
         """
-        Converts a playlist with M3U entries and renders them as individual playlist entries.
+        Convert a playlist with M3U entries and renders them as individual playlist entries.
         """
         if not self.playlist_folder:
             return entries
@@ -165,20 +168,19 @@ class TimeslotRenderer:
     programme = None
 
     def __init__(self, scheduler):
-        """
-        Constructor
-        """
         self.logger = logging.getLogger("AuraEngine")
         self.scheduler = scheduler
         self.programme = scheduler.get_programme()
 
     def get_ascii_timeslots(self):
         """
-        Creates a printable version of the current programme (playlists and entries as per
-        timeslot)
+        Create a printable version of the current programme.
+
+        The output contains playlists and entries as per timeslot.
 
         Returns:
             (String):   An ASCII representation of the current and next timeslots
+
         """
         active_timeslot = self.programme.get_current_timeslot()
 
@@ -289,7 +291,7 @@ class TimeslotRenderer:
 
     def build_playlist_string(self, entries):
         """
-        Returns a stringified list of entries
+        Return a stringified list of entries.
         """
         s = ""
         is_out_of_timeslot = False
@@ -307,7 +309,7 @@ class TimeslotRenderer:
 
     def build_entry_string(self, prefix, entry, strike):
         """
-        Returns an stringified entry.
+        Return an stringified entry.
         """
         s = ""
         if entry.queue_state == EntryQueueState.CUT:
@@ -323,14 +325,15 @@ class TimeslotRenderer:
 
     def preprocess_entries(self, entries, cut_oos):
         """
-        Analyses and marks entries which are going to be cut or excluded.
+        Analyse and marks entries which are going to be cut or excluded.
 
         Args:
-            entries ([PlaylistEntry]):  The playlist entries to be scheduled for playout
-            cut_oos (Boolean):  If `True` entries which are 'out of timeslot' are not returned
+            entries ([PlaylistEntry]): The playlist entries to be scheduled for playout
+            cut_oos (Boolean): If `True` entries which are 'out of timeslot' are not returned
 
         Returns:
-            ([PlaylistEntry]):  The list of processed playlist entries
+            ([PlaylistEntry]): The list of processed playlist entries
+
         """
         clean_entries = []
 
-- 
GitLab