# Path: lighthouse/configs/monitor.py
# class ConfigFileMonitor(object):
#     """
#     Config file monitoring class.
# 
#     This class monitors the proper config directory of a target class and
#     fires given callbacks whenever a file is added, updated or removed.
#     """
# 
#     def __init__(self, target_class, base_path):
#         self.target_class = target_class
# 
#         path = [base_path]
#         if target_class.config_subdirectory:
#             path.append(target_class.config_subdirectory)
# 
#         self.file_path = os.path.join(*path)
# 
#     def start(self, on_add, on_update, on_delete):
#         """
#         Starts monitoring the file path, passing along on_(add|update|delete)
#         callbacks to a watchdog observer.
# 
#         Iterates over the files in the target path before starting the observer
#         and calls the on_created callback before starting the observer, so
#         that existing files aren't missed.
#         """
#         handler = ConfigFileChangeHandler(
#             self.target_class, on_add, on_update, on_delete
#         )
# 
#         for file_name in os.listdir(self.file_path):
#             if os.path.isdir(os.path.join(self.file_path, file_name)):
#                 continue
#             if (
#                 not self.target_class.config_subdirectory and
#                 not (
#                     file_name.endswith(".yaml") or file_name.endswith(".yml")
#                 )
#             ):
#                 continue
# 
#             handler.on_created(
#                 events.FileCreatedEvent(
#                     os.path.join(self.file_path, file_name)
#                 )
#             )
# 
#         observer = observers.Observer()
#         observer.schedule(handler, self.file_path)
#         observer.start()
# 
#         return observer
# 
# Path: lighthouse/events.py
# def wait_on_event(event, timeout=None):
#     """
#     Waits on a single threading Event, with an optional timeout.
# 
#     This is here for compatibility reasons as python 2 can't reliably wait
#     on an event without a timeout and python 3 doesn't define a `maxint`.
#     """
#     if timeout is not None:
#         event.wait(timeout)
#         return
# 
#     if six.PY2:
#         # Thanks to a bug in python 2's threading lib, we can't simply call
#         # .wait() with no timeout since it would wind up ignoring signals.
#         while not event.is_set():
#             event.wait(sys.maxint)
#     else:
#         event.wait()


import logging
import threading
from concurrent import futures
from .monitor import ConfigFileMonitor
from lighthouse.events import wait_on_event

    .. warning::
       Care must be taken that these hooks are idempotent with regards
       to the Watcher subclass instance.  Configuration changes are liable to
       happen at any time and in any order.
    """

    # the list or tuple of Configurable subclasses to watch
    watched_configurables = ()

    def __init__(self, config_dir):
        self.config_dir = config_dir

        self.observers = []
        self.configurables = {}
        for config_class in self.watched_configurables:
            self.configurables[config_class] = {}

        self.work_pool = futures.ThreadPoolExecutor(max_workers=MAX_WORKERS)
        self.thread_pool = {}

        self.shutdown = threading.Event()

    def start(self):
        """
        Iterates over the `watched_configurabes` attribute and starts a
        config file monitor for each.  The resulting observer threads are
        kept in an `observers` list attribute.
        """
        for config_class in self.watched_configurables:

# Path: lighthouse/configs/monitor.py
# class ConfigFileMonitor(object):
#     """
#     Config file monitoring class.
# 
#     This class monitors the proper config directory of a target class and
#     fires given callbacks whenever a file is added, updated or removed.
#     """
# 
#     def __init__(self, target_class, base_path):
#         self.target_class = target_class
# 
#         path = [base_path]
#         if target_class.config_subdirectory:
#             path.append(target_class.config_subdirectory)
# 
#         self.file_path = os.path.join(*path)
# 
#     def start(self, on_add, on_update, on_delete):
#         """
#         Starts monitoring the file path, passing along on_(add|update|delete)
#         callbacks to a watchdog observer.
# 
#         Iterates over the files in the target path before starting the observer
#         and calls the on_created callback before starting the observer, so
#         that existing files aren't missed.
#         """
#         handler = ConfigFileChangeHandler(
#             self.target_class, on_add, on_update, on_delete
#         )
# 
#         for file_name in os.listdir(self.file_path):
#             if os.path.isdir(os.path.join(self.file_path, file_name)):
#                 continue
#             if (
#                 not self.target_class.config_subdirectory and
#                 not (
#                     file_name.endswith(".yaml") or file_name.endswith(".yml")
#                 )
#             ):
#                 continue
# 
#             handler.on_created(
#                 events.FileCreatedEvent(
#                     os.path.join(self.file_path, file_name)
#                 )
#             )
# 
#         observer = observers.Observer()
#         observer.schedule(handler, self.file_path)
#         observer.start()
# 
#         return observer
# 
# Path: lighthouse/events.py
# def wait_on_event(event, timeout=None):
#     """
#     Waits on a single threading Event, with an optional timeout.
# 
#     This is here for compatibility reasons as python 2 can't reliably wait
#     on an event without a timeout and python 3 doesn't define a `maxint`.
#     """
#     if timeout is not None:
#         event.wait(timeout)
#         return
# 
#     if six.PY2:
#         # Thanks to a bug in python 2's threading lib, we can't simply call
#         # .wait() with no timeout since it would wind up ignoring signals.
#         while not event.is_set():
#             event.wait(sys.maxint)
#     else:
#         event.wait()


# Path: lighthouse/configs/watcher.py
import logging
import threading
from concurrent import futures
from .monitor import ConfigFileMonitor
from lighthouse.events import wait_on_event


    .. warning::
       Care must be taken that these hooks are idempotent with regards
       to the Watcher subclass instance.  Configuration changes are liable to
       happen at any time and in any order.
    """

    # the list or tuple of Configurable subclasses to watch
    watched_configurables = ()

    def __init__(self, config_dir):
        self.config_dir = config_dir

        self.observers = []
        self.configurables = {}
        for config_class in self.watched_configurables:
            self.configurables[config_class] = {}

        self.work_pool = futures.ThreadPoolExecutor(max_workers=MAX_WORKERS)
        self.thread_pool = {}

        self.shutdown = threading.Event()

    def start(self):
        """
        Iterates over the `watched_configurabes` attribute and starts a
        config file monitor for each.  The resulting observer threads are
        kept in an `observers` list attribute.
        """
        for config_class in self.watched_configurables:

            monitor = ConfigFileMonitor(config_class, self.config_dir)