예제 #1
0
 def path_constructor(self, node: yaml.Node) -> str:
     """
     !path <path>
     ~/  for paths relative to your home directory
     /   for absolute paths
     anything else for paths relative to your config folder
     """
     return resolve_path(node.value, os.path.dirname(self.name))
예제 #2
0
 def path_constructor(self, node: yaml.Node) -> str:
     """
     !path <path>
     ~/  for paths relative to your home directory
     /   for absolute paths
     anything else for paths relative to your config folder
     """
     return resolve_path(node.value,
                         file_path=os.path.dirname(self.name),
                         config_dir=self.cfg_folder)
예제 #3
0
    def listdir_constructor(self, node: yaml.Node) -> list:
        """
        !listdir <path>

        Returns the contents of a directory
        """
        path = resolve_path(node.value,
                            file_path=os.path.dirname(self.name),
                            config_dir=self.cfg_folder)
        if os.path.isdir(path):
            return [os.path.join(path, item) for item in os.listdir(path)]
        return list()
예제 #4
0
 def file_contructor(self, node: yaml.Node = None) -> str:
     """
     !file <path>
     Inserts the file content as a string
     """
     if not isinstance(node.value, str):
         raise TypeError("file path must be str")
     path = resolve_path(node.value,
                         file_path=self.name,
                         config_dir=self.cfg_folder)
     with open(path) as file:
         return file.read()
예제 #5
0
    def include_file_constructor(self, node: yaml.Node = None) -> object:
        """
        !include <path>
        ~/  for paths relative to your home directory
        /   for absolute paths
        anything else for paths relative to your config folder
        """
        if not isinstance(node.value, str):
            raise TypeError(f"folder must be of type str")
        path = resolve_path(node.value, os.path.dirname(self.name))
        if not os.path.isfile(path):
            raise FileNotFoundError(path)

        return self.__class__.load(open(path, "r"))
예제 #6
0
    def include_merge_constructor(self,
                                  node: yaml.Node = None) -> (list, dict):
        """
        !include <file|folder> ...

        Merges file or folder contents

        This constructor only works if all the files' contents are of same type
        and if this type is either list or dict.
        """
        paths = node.value
        if isinstance(paths, str):
            paths = paths.split(" ")
        elif not isinstance(paths, list):
            raise TypeError(f"paths must be either of type str or list")

        paths = [
            resolve_path(path,
                         file_path=os.path.dirname(self.name),
                         config_dir=self.cfg_folder) for path in paths
        ]
        files = set()
        for path in paths:
            if os.path.isfile(path):
                files.add(path)
            elif os.path.isdir(path):
                for file in os.listdir(path):
                    if file.endswith(".yaml"):
                        files.add(os.path.join(path, file))

        loaded_files = [
            self.__class__.load(open(file, "r"), cfg_folder=self.cfg_folder)
            for file in files
        ]

        if not all(
                isinstance(loaded_file, type(loaded_files[0]))
                for loaded_file in loaded_files):
            raise yaml.YAMLError(f"Cannot join {files}, they are not all "
                                 f"of type {type(loaded_files[0]).__name__}")

        if isinstance(loaded_files[0], list):
            return list(itertools.chain(*loaded_files))
        if isinstance(loaded_files[0], dict):
            return dict(
                itertools.chain(
                    *[loaded_file.items() for loaded_file in loaded_files]))
        raise yaml.YAMLError(
            f"Unmergable type: {type(loaded_files[0]).__name__}")
예제 #7
0
    def include_file_constructor(self, node: yaml.Node = None) -> object:
        """
        !include <path>
        ~/  for paths relative to your home directory
        /   for absolute paths
        anything else for paths relative to your config folder
        """
        if not isinstance(node.value, str):
            raise TypeError(f"folder must be of type str")
        path = resolve_path(
            node.value, file_path=self.name, config_dir=self.cfg_folder)
        if not os.path.isfile(path):
            raise FileNotFoundError(path)

        return self.__class__.load(open(path, "r"), cfg_folder=self.cfg_folder)
예제 #8
0
    def include_dir_file_mapped_constructor(self,
                                            node: yaml.Node = None) -> dict:
        """
        !include_dir_file_mapped <folder>

        Loads multiple files from a folder and maps their contents
        to their filenames
        """
        if not isinstance(node.value, str):
            raise TypeError(f"folder must be of type str")
        folder = resolve_path(node.value, os.path.dirname(self.name))
        if not os.path.isdir(folder):
            raise FileNotFoundError(folder)

        return {
            os.path.splitext(file)[0]: self.__class__.load(
                open(os.path.join(folder, file), "r"))
            for file in os.listdir(folder) if file.endswith(".yaml")
        }
예제 #9
0
    def include_merge_constructor(self,
                                  node: yaml.Node = None) -> (list, dict):
        """
        !include <file|folder> ...

        Merges file or folder contents

        This constructor only works if all the files' contents are of same type
        and if this type is either list or dict.
        """
        paths = node.value
        if isinstance(paths, str):
            paths = paths.split(" ")
        elif not isinstance(paths, list):
            raise TypeError(f"paths must be either of type str or list")
        paths = [resolve_path(path, os.path.dirname(self.name))
                 for path in paths]
        files = set()
        for path in paths:
            if os.path.isfile(path):
                files.add(path)
            elif os.path.isdir(path):
                for file in os.listdir(path):
                    if file.endswith(".yaml"):
                        files.add(os.path.join(path, file))

        loaded_files = [self.__class__.load(open(file, "r")) for file in files]

        if not all(isinstance(loaded_file, type(loaded_files[0]))
                   for loaded_file in loaded_files):
            raise yaml.YAMLError(
                f"Cannot join {files}, they are not all "
                f"of type {type(loaded_files[0]).__name__}")

        if isinstance(loaded_files[0], list):
            return list(itertools.chain(*loaded_files))
        if isinstance(loaded_files[0], dict):
            return dict(itertools.chain(
                *[loaded_file.items() for loaded_file in loaded_files]))
        raise yaml.YAMLError(
            f"Unmergable type: {type(loaded_files[0]).__name__}")
예제 #10
0
    def include_dir_file_mapped_constructor(self,
                                            node: yaml.Node = None) -> dict:
        """
        !include_dir_file_mapped <folder>

        Loads multiple files from a folder and maps their contents
        to their filenames
        """
        if not isinstance(node.value, str):
            raise TypeError(f"folder must be of type str")
        folder = resolve_path(node.value,
                              file_path=os.path.dirname(self.name),
                              config_dir=self.cfg_folder)
        if not os.path.isdir(folder):
            raise FileNotFoundError(folder)

        return {
            os.path.splitext(file)[0]:
            self.__class__.load(open(os.path.join(folder, file), "r"),
                                cfg_folder=self.cfg_folder)
            for file in os.listdir(folder) if file.endswith(".yaml")
        }
예제 #11
0
    async def init(self) -> None:
        """Initialises the module"""
        self.cfg = await self.core.cfg.register_domain(
            "auth", schema=CONFIG_SCHEMA)
        self.core.event_engine.register(
            "http_add_main_middlewares")(self.add_middlewares)
        self.core.event_engine.register(
            "http_add_api_middlewares")(self.add_middlewares)
        self.core.event_engine.register(
            "http_add_api_routes")(self.add_api_routes)

        self.static_folder = resolve_path(
            "@/www", config_dir=self.core.cfg_dir)

        self.auth_manager = AuthManager(self.core)
        self.flow_manager = FlowManager(
            self.auth_manager, self.cfg["login-flows"])

        self.auth_providers = {
            cfg["type"]: AUTH_PROVIDERS[cfg["type"]](self.auth_manager, cfg)
            for cfg in self.cfg["providers"]
        }
예제 #12
0
    async def init(self) -> None:
        """Initialise the logbook module"""
        self.cfg = await self.core.cfg.register_domain(
            "logbook",
            self,
            schema=CONFIG_SCHEMA,
            allow_reload=False,
            default={
                "db-path": (
                    "sqlite:///" + resolve_path(
                        '@/homecontrol.db', config_dir=self.core.cfg_dir))
            }
        )
        self.engine = sqlalchemy.create_engine(
            self.cfg["db-path"], strategy="threadlocal")
        models.Base.metadata.create_all(self.engine)

        self.get_session = sessionmaker(bind=self.engine)

        self.core.event_engine.register("state_change")(self.on_state_change)
        self.core.event_engine.register("*")(self.on_event)
        self.core.event_engine.register(
            "http_add_api_routes")(self.add_api_routes)