2020-08-12 15:46:50 +00:00
|
|
|
# system
|
2020-08-12 15:18:20 +00:00
|
|
|
import logging
|
2020-08-12 15:46:50 +00:00
|
|
|
import os
|
2020-08-12 15:18:20 +00:00
|
|
|
import subprocess
|
2020-08-12 14:43:13 +00:00
|
|
|
|
2020-08-19 15:21:38 +00:00
|
|
|
# local
|
2020-08-19 15:15:00 +00:00
|
|
|
from .config import LoadedConfig
|
2020-08-12 14:43:13 +00:00
|
|
|
|
2020-08-17 09:57:08 +00:00
|
|
|
|
2020-08-19 14:10:56 +00:00
|
|
|
def _update_kwargs(**kwargs):
|
|
|
|
config = LoadedConfig.get()
|
2020-08-17 09:57:08 +00:00
|
|
|
|
2020-08-19 14:10:56 +00:00
|
|
|
# ensure there is an environment
|
|
|
|
if 'env' not in kwargs:
|
|
|
|
kwargs['env'] = {}
|
|
|
|
|
|
|
|
# add common environment from config
|
|
|
|
if config['runtime:env'] is not None:
|
|
|
|
kwargs['env'].update(config['runtime:env'])
|
|
|
|
|
|
|
|
logging.debug(f"kwargs updated: {kwargs}")
|
2020-08-17 09:57:08 +00:00
|
|
|
|
|
|
|
return kwargs
|
|
|
|
|
|
|
|
|
|
|
|
def _is_executable(filename):
|
2020-08-12 14:43:13 +00:00
|
|
|
if filename is None:
|
|
|
|
return False
|
|
|
|
|
|
|
|
return os.path.isfile(filename) and os.access(filename, os.X_OK)
|
|
|
|
|
|
|
|
|
2020-08-17 09:57:08 +00:00
|
|
|
def _find_exe_file(exe_name):
|
2020-08-12 14:43:13 +00:00
|
|
|
for path in os.environ['PATH'].split(os.pathsep):
|
|
|
|
exe_file = os.path.join(path, exe_name)
|
2020-08-17 09:57:08 +00:00
|
|
|
if _is_executable(exe_file):
|
2020-08-12 14:43:13 +00:00
|
|
|
return exe_file
|
|
|
|
|
2020-08-12 15:18:20 +00:00
|
|
|
raise FileNotFoundError(f"Executable '{exe_name}' not found in $PATH!")
|
|
|
|
|
|
|
|
|
|
|
|
class Executable:
|
|
|
|
class __Executable:
|
2020-08-12 15:39:55 +00:00
|
|
|
__exe_path = None
|
2020-08-12 15:18:20 +00:00
|
|
|
|
2020-08-17 09:57:08 +00:00
|
|
|
def __init__(self, exe_name):
|
|
|
|
self.__exe_path = _find_exe_file(exe_name)
|
2020-08-12 15:39:55 +00:00
|
|
|
|
2020-08-17 14:58:12 +00:00
|
|
|
def __build_cmd(self, args, **kwargs):
|
2020-08-12 15:39:55 +00:00
|
|
|
cmd = [self.__exe_path, *args]
|
2020-08-12 15:18:20 +00:00
|
|
|
|
|
|
|
logging.debug(f"Executable cmd{cmd}, kwargs{kwargs}")
|
|
|
|
return cmd
|
|
|
|
|
2020-08-19 14:10:56 +00:00
|
|
|
def run(self, process_args, **kwargs):
|
2020-08-12 15:18:20 +00:00
|
|
|
return subprocess.run(
|
2020-08-19 14:10:56 +00:00
|
|
|
self.__build_cmd(process_args, **_update_kwargs(**kwargs)),
|
2020-08-12 15:18:20 +00:00
|
|
|
**kwargs
|
|
|
|
)
|
|
|
|
|
2020-08-19 14:10:56 +00:00
|
|
|
def Popen(self, process_args, **kwargs):
|
2020-08-12 15:18:20 +00:00
|
|
|
return subprocess.Popen(
|
2020-08-19 14:10:56 +00:00
|
|
|
self.__build_cmd(process_args, **_update_kwargs(**kwargs)),
|
2020-08-12 15:18:20 +00:00
|
|
|
**kwargs
|
|
|
|
)
|
|
|
|
|
2020-08-19 14:10:56 +00:00
|
|
|
def run_less(self, process_args, **kwargs):
|
2020-08-13 09:34:30 +00:00
|
|
|
kwargs['stdout'] = subprocess.PIPE
|
|
|
|
kwargs['stderr'] = subprocess.DEVNULL
|
|
|
|
|
|
|
|
process = self.Popen(
|
2020-08-19 14:10:56 +00:00
|
|
|
process_args,
|
2020-08-13 09:34:30 +00:00
|
|
|
**kwargs
|
|
|
|
)
|
|
|
|
|
|
|
|
less_process = Executable('less').run(
|
|
|
|
['-R', '+G'],
|
|
|
|
stdin=process.stdout
|
|
|
|
)
|
|
|
|
|
|
|
|
process.communicate()
|
|
|
|
return less_process
|
|
|
|
|
2020-08-12 15:39:55 +00:00
|
|
|
__exe_name = None
|
|
|
|
__instances = {}
|
|
|
|
|
2020-08-17 09:57:08 +00:00
|
|
|
def __init__(self, exe_name):
|
2020-08-12 15:18:20 +00:00
|
|
|
self.__exe_name = exe_name
|
|
|
|
|
|
|
|
if exe_name not in Executable.__instances:
|
2020-08-17 09:57:08 +00:00
|
|
|
Executable.__instances[exe_name] = Executable.__Executable(exe_name)
|
2020-08-12 15:18:20 +00:00
|
|
|
|
|
|
|
def __getattr__(self, item):
|
|
|
|
return getattr(self.__instances[self.__exe_name], item)
|