# -*- coding: utf-8 -*-
"""The scaffolder engine."""
import logging
import os
from typing import Iterator
from typing import Type
from l2tscaffolder.definitions import manager
from l2tscaffolder.lib import errors
from l2tscaffolder.lib import file_handler
from l2tscaffolder.scaffolders import interface as scaffolder_interface
[docs]class ScaffolderEngine:
"""The engine, responsible for file handling and setting up scaffolders."""
def __init__(self):
"""Initializes the engine."""
super(ScaffolderEngine, self).__init__()
self._attributes = {}
self._definition = ''
self._definition_root_path = ''
self._file_handler = file_handler.FileHandler()
self._file_name_prefix = ''
self._scaffolder = None
self.module_name = ''
def _RaiseIfNotReady(self):
"""Checks to see if all attributes are set to start generating files.
Raises:
errors.EngineNotConfigured: when the engine is not fully configured.
"""
if not self._definition_root_path:
raise errors.EngineNotConfigured(
'The path to the project root is not properly configured.')
if not self.module_name:
raise errors.EngineNotConfigured('Module name has not been configured.')
if not self._scaffolder:
raise errors.EngineNotConfigured('Scaffolder object not yet set.')
try:
self._scaffolder.RaiseIfNotReady()
except errors.ScaffolderNotConfigured as exception:
raise errors.EngineNotConfigured(exception)
[docs] def GenerateFiles(self) -> Iterator[str]:
"""Generates needed files.
Raises:
errors.EngineNotConfigured: when not all attributes have been configured.
Yields:
str: the full path to a file that was generated and written to disk.
"""
self._RaiseIfNotReady()
self._scaffolder.SetOutputName(self._file_name_prefix)
for file_source, file_destination in self._scaffolder.GetFilesToCopy():
if os.path.isfile(file_source):
full_path = os.path.join(self._definition_root_path, file_destination)
try:
written_file = self._file_handler.CopyFile(file_source, full_path)
yield written_file
except errors.FileHandlingError as exception:
logging.error(
'Unable to copy file: {0:s} to {1:s} with error: {2!s}'.format(
file_source, full_path, exception))
for file_path, content in self._scaffolder.GenerateFiles():
full_path = os.path.join(self._definition_root_path, file_path)
yield self._file_handler.AddContent(full_path, content)
for file_path, content in self._scaffolder.GetInitFileChanges():
full_path = os.path.join(self._definition_root_path, file_path)
self._file_handler.AddImportToInit(full_path, content)
yield full_path
[docs] def SetModuleName(self, module_name: str):
"""Sets the module name as chosen by the user.
Args:
module_name (str): name of the module to be generated by the scaffolder.
"""
file_name_prefix = module_name.replace(' ', '_')
file_name_prefix = file_name_prefix.lower()
module_name = file_name_prefix.replace('_', ' ')
module_name = module_name.title()
module_name = module_name.replace(' ', '')
self._file_name_prefix = file_name_prefix
self.module_name = module_name
[docs] def SetScaffolder(self, scaffolder: scaffolder_interface.Scaffolder):
"""Stores and initializes the scaffolder object in the engine.
Args:
scaffolder (scaffolder_interface.Scaffolder): the scaffolder class
that the engine will use to generate files.
"""
self._scaffolder = scaffolder
[docs] def SetProjectRootPath(self, root_path: str):
"""Sets the path to the root of the project tree.
Raises:
errors.NoValidDefinition: when root path is not identified as a valid
definition path.
"""
for definition in manager.DefinitionManager.GetDefinitionObjects():
if definition.ValidatePath(root_path):
self._definition = definition.NAME
self._definition_root_path = root_path
return
raise errors.NoValidDefinition('No valid definition has been identified.')
[docs] def StoreScaffolderAttribute(
self, name: str, value: object, value_type: Type):
"""Stores an attribute read from the CLI.
Args:
name (str): the attribute name.
value (object): the attribute value.
value_type (type): the attribute type.
Raises:
KeyError: if the attribute name is already defined.
ScaffolderNotConfigured: if the scaffolder has not yet been set.
ValueError: if the value is not of the correct type.
"""
if not self._scaffolder:
raise errors.ScaffolderNotConfigured('Scaffolder has not yet been set.')
self._scaffolder.SetAttribute(name, value, value_type)