Source code for ska_sdp_piper.app.executable_pipeline
import importlib.util
import logging
import os
import sys
from importlib.machinery import SourceFileLoader
from pathlib import Path
from ..piper.exceptions import PipelineNotFoundException
from ..piper.named_instance import NamedInstance
from .constants import MAIN_ENTRY_POINT, SHEBANG_HEADER
logger = logging.getLogger(__name__)
[docs]
class ExecutablePipeline:
"""
Creates an executable instance from the pipeline definition
Attributes
----------
_script_path: str
Path to the pipeline definition
installable_pipeline: module
The pipeline definition loaded as a module
executable_content: str
The content of the executable file
"""
def __init__(self, pipeline_name, script_path=None):
"""
Initialise a executable pipeline object
Parameters
---------
script_path: str
Path to the pipeline definition
"""
self._pipeline_name = pipeline_name
self._script_path = script_path or self.__executable_script_path()
self.installable_pipeline = None
self.executable_content = None
[docs]
def validate_pipeline(self):
"""
Validates if the pipeline definition is syntactically correct python
code.
Raises
------
Compilation error based on python interpretor.
PipelineNotFoundException if the provided pipeline name
doesn't exist
"""
logger.info(f"Validating {self._script_path}")
if not os.path.exists(self._script_path):
raise FileNotFoundError(self._script_path)
_module_name = "installable_pipeline"
spec = importlib.util.spec_from_loader(
_module_name, SourceFileLoader(_module_name, self._script_path)
)
self.installable_pipeline = importlib.util.module_from_spec(spec)
sys.modules[_module_name] = self.installable_pipeline
spec.loader.exec_module(self.installable_pipeline)
valid_pipeline = NamedInstance.get_instance(self._pipeline_name)
if valid_pipeline is None:
raise PipelineNotFoundException(
f"Pipeline {self._pipeline_name} not"
f" found in {self._script_path}"
)
def __prepare_executable(self):
"""
Prepares the content of the executable script file
"""
file_content = ""
logger.info("Preparing executable")
with open(self._script_path, "r") as script_file:
file_content = script_file.readlines()
self.executable_content = (
SHEBANG_HEADER.format(executable=sys.executable)
+ "".join(file_content)
+ MAIN_ENTRY_POINT.format(pipeline_name=self._pipeline_name)
)
[docs]
def install(self):
"""
Installs the executable script containing the executable script.
The path is taken from the executable path obtained from sys.executable
The script file is created with a execute privilage to user and group
"""
self.__prepare_executable()
logger.info("Installing executable")
executable_path = self.__executable_script_path()
with open(executable_path, "w") as outfile:
outfile.write(self.executable_content)
os.chmod(executable_path, 0o750)
logger.info(f"Installed {executable_path}")
[docs]
def uninstall(self):
"""
Removes the executable pipeline from the executable path.
"""
executable_path = self.__executable_script_path()
logger.info(f"Deleting {executable_path}")
os.remove(executable_path)
def __executable_script_path(self):
"""
Returns
------
the absolute path of the executable.
The path is derived from sys.executable
"""
executable_root = Path(sys.executable).parent.absolute()
return f"{executable_root}/{self._pipeline_name}"