# Path: pipelines/plugins/bash_executor.py
# class BashExecutor(BaseExecutorPlugin):
#     hook_prefix = 'bash'
#     hooks = ('execute',)
# 
#     def __init__(self, log_file=None, event_mgr=None):
#         self.log_file = log_file
#         self.event_mgr = event_mgr
# 
#         log.debug('Bash executor initiated with log_file: %s' % self.log_file)
# 
#     def _parse_args_dict(self, args_dict):
#         if 'cmd' not in args_dict:
#             raise PluginError('BashExecutor got incorrect arguments, got: {}'.format(
#                 args_dict.keys()
#             ))
#         timeout = args_dict.get('timeout') or DEFAULT_TIMEOUT
#         if not isinstance(timeout, int):
#             raise PluginError('BashExecutor got incorrect timeout argument type, got: {} expecting int'.format(
#                 type(timeout)
#             ))
# 
#         return args_dict['cmd'], timeout
# 
#     def execute(self, args_dict):
#         cmd, timeout = self._parse_args_dict(args_dict)
# 
#         if self.dry_run:
#             return TaskResult(EXECUTION_SUCCESSFUL)
# 
#         try:
#             output, return_obj = self._run_bash(cmd, timeout)
#             status = EXECUTION_SUCCESSFUL
#             msg = 'Bash task finished'
#         except BashExecuteError as e:
#             status = EXECUTION_FAILED
#             # stdout = e.stderr
#             msg = 'Bash task failed: %s' % e.msg
#             output = e.data['stdout']
# 
#         return TaskResult(status, msg, data={'output': output}, return_obj=return_obj)
# 
# 
#     def _run_bash(self, bash_input, timeout=DEFAULT_TIMEOUT):
#         log.debug('Running bash command: "{}"'.format(bash_input))
#         f = None
#         if self.log_file:
#             f = open(self.log_file, 'a+')
# 
#         output = {'stdout': '', 'last_line': ''}
#         try:
#             def process_line(line):
#                 log.debug('Got line: %s' % line)
#                 output['stdout'] += line
# 
#                 if line and line.strip():
#                     output['last_line'] = line
# 
#                 if f:
#                     f.write(line)
# 
#                 if self.event_mgr:
#                     if len(line)>0 and line[-1] == '\n':
#                         line = line[:-1]
#                     self.event_mgr.trigger('on_task_event', {'output': line})
# 
#             proc = bash(_in=bash_input, _out=process_line, _err=process_line, _timeout=timeout)
#             proc.wait()
#             log.debug('Finished: %s, %s, %s' % (proc.exit_code, proc.stdout, proc.stderr))
# 
#         except ErrorReturnCode as e:
#             log.warning('BashExec failed %s' % e.message)
#             raise BashExecuteError("Execution failed with code: %s" % e.exit_code, e.exit_code, data=output)
#         except TimeoutException as e:
#             log.debug('BashExec timed out after %s seconds' % timeout)
#             raise BashExecuteError("Task Timed Out", 1, data=output)
# 
#         return_obj = None
#         try:
#             return_obj = json.loads(output['last_line'])
#         except:
#             log.debug('Failed to parse last line of bash as json: "{}"'.format(output['last_line']))
# 
#         return output['stdout'], return_obj
# 
#     @classmethod
#     def from_dict(cls, conf_dict, event_mgr=None):
#         return cls(conf_dict.get('bash_log_file'), event_mgr)
# 
# class BashExecuteError(PluginError):
#     def __init__(self, msg, code, data={}):
#         self.msg = msg
#         self.code = code
#         self.data = data
# 
# Path: pipelines/pipeline/task.py
# class TaskResult(dict):
#     def __init__(self, status, message='', data={}, return_obj={}):
#         self['status'] = status
#         self['message'] = message
#         self['data'] = data
#         self['return_obj'] = return_obj
# 
#     @property
#     def status(self):
#         return self.get('status')
# 
#     @property
#     def message(self):
#         return self.get('message')
# 
#     @property
#     def data(self):
#         return self.get('data')
# 
#     @property
#     def return_obj(self):
#         return self.get('return_obj')
# 
#     def is_successful(self):
#         return self.status == EXECUTION_SUCCESSFUL
# 
# EXECUTION_SUCCESSFUL = 0
# 
# EXECUTION_FAILED = 1
# 
# Path: pipelines/plugin/exceptions.py
# class PluginError(RuntimeError):
#     pass


import logging
from tempfile import NamedTemporaryFile
from pipelines.plugins.bash_executor import BashExecutor, BashExecuteError
from pipelines.pipeline.task import TaskResult, EXECUTION_SUCCESSFUL, EXECUTION_FAILED
from pipelines.plugin.exceptions import PluginError
from os import path
            bash_input += 'cd {}\n'.format(workdir)

        if virtualenv:
            activate_path = path.join(virtualenv, 'bin', 'activate')
            if not path.exists(activate_path) or not path.isfile(activate_path):
                raise PluginError('Python virtualenv doesn\'t exist: {}'.format(activate_path))

            bash_input += 'source {}\n'.format(activate_path)

        filename = file

        if script:
            f = NamedTemporaryFile(delete=False)

            f.write(script)
            log.debug('Wrote script to file {}, {}'.format(f.name, script))
            filename = f.name
            f.close()

        bash_input += 'python {}'.format(filename)
        log.debug('Running python script: {}'.format(bash_input))

        if self.dry_run:
            return TaskResult(EXECUTION_SUCCESSFUL)

        return_obj=None
        try:
            stdout, return_obj = self._run_bash(bash_input)
            status = EXECUTION_SUCCESSFUL
        except BashExecuteError as e:

# Path: pipelines/plugins/bash_executor.py
# class BashExecutor(BaseExecutorPlugin):
#     hook_prefix = 'bash'
#     hooks = ('execute',)
# 
#     def __init__(self, log_file=None, event_mgr=None):
#         self.log_file = log_file
#         self.event_mgr = event_mgr
# 
#         log.debug('Bash executor initiated with log_file: %s' % self.log_file)
# 
#     def _parse_args_dict(self, args_dict):
#         if 'cmd' not in args_dict:
#             raise PluginError('BashExecutor got incorrect arguments, got: {}'.format(
#                 args_dict.keys()
#             ))
#         timeout = args_dict.get('timeout') or DEFAULT_TIMEOUT
#         if not isinstance(timeout, int):
#             raise PluginError('BashExecutor got incorrect timeout argument type, got: {} expecting int'.format(
#                 type(timeout)
#             ))
# 
#         return args_dict['cmd'], timeout
# 
#     def execute(self, args_dict):
#         cmd, timeout = self._parse_args_dict(args_dict)
# 
#         if self.dry_run:
#             return TaskResult(EXECUTION_SUCCESSFUL)
# 
#         try:
#             output, return_obj = self._run_bash(cmd, timeout)
#             status = EXECUTION_SUCCESSFUL
#             msg = 'Bash task finished'
#         except BashExecuteError as e:
#             status = EXECUTION_FAILED
#             # stdout = e.stderr
#             msg = 'Bash task failed: %s' % e.msg
#             output = e.data['stdout']
# 
#         return TaskResult(status, msg, data={'output': output}, return_obj=return_obj)
# 
# 
#     def _run_bash(self, bash_input, timeout=DEFAULT_TIMEOUT):
#         log.debug('Running bash command: "{}"'.format(bash_input))
#         f = None
#         if self.log_file:
#             f = open(self.log_file, 'a+')
# 
#         output = {'stdout': '', 'last_line': ''}
#         try:
#             def process_line(line):
#                 log.debug('Got line: %s' % line)
#                 output['stdout'] += line
# 
#                 if line and line.strip():
#                     output['last_line'] = line
# 
#                 if f:
#                     f.write(line)
# 
#                 if self.event_mgr:
#                     if len(line)>0 and line[-1] == '\n':
#                         line = line[:-1]
#                     self.event_mgr.trigger('on_task_event', {'output': line})
# 
#             proc = bash(_in=bash_input, _out=process_line, _err=process_line, _timeout=timeout)
#             proc.wait()
#             log.debug('Finished: %s, %s, %s' % (proc.exit_code, proc.stdout, proc.stderr))
# 
#         except ErrorReturnCode as e:
#             log.warning('BashExec failed %s' % e.message)
#             raise BashExecuteError("Execution failed with code: %s" % e.exit_code, e.exit_code, data=output)
#         except TimeoutException as e:
#             log.debug('BashExec timed out after %s seconds' % timeout)
#             raise BashExecuteError("Task Timed Out", 1, data=output)
# 
#         return_obj = None
#         try:
#             return_obj = json.loads(output['last_line'])
#         except:
#             log.debug('Failed to parse last line of bash as json: "{}"'.format(output['last_line']))
# 
#         return output['stdout'], return_obj
# 
#     @classmethod
#     def from_dict(cls, conf_dict, event_mgr=None):
#         return cls(conf_dict.get('bash_log_file'), event_mgr)
# 
# class BashExecuteError(PluginError):
#     def __init__(self, msg, code, data={}):
#         self.msg = msg
#         self.code = code
#         self.data = data
# 
# Path: pipelines/pipeline/task.py
# class TaskResult(dict):
#     def __init__(self, status, message='', data={}, return_obj={}):
#         self['status'] = status
#         self['message'] = message
#         self['data'] = data
#         self['return_obj'] = return_obj
# 
#     @property
#     def status(self):
#         return self.get('status')
# 
#     @property
#     def message(self):
#         return self.get('message')
# 
#     @property
#     def data(self):
#         return self.get('data')
# 
#     @property
#     def return_obj(self):
#         return self.get('return_obj')
# 
#     def is_successful(self):
#         return self.status == EXECUTION_SUCCESSFUL
# 
# EXECUTION_SUCCESSFUL = 0
# 
# EXECUTION_FAILED = 1
# 
# Path: pipelines/plugin/exceptions.py
# class PluginError(RuntimeError):
#     pass


# Path: pipelines/plugins/python_executor.py
import logging
from tempfile import NamedTemporaryFile
from pipelines.plugins.bash_executor import BashExecutor, BashExecuteError
from pipelines.pipeline.task import TaskResult, EXECUTION_SUCCESSFUL, EXECUTION_FAILED
from pipelines.plugin.exceptions import PluginError
from os import path

            bash_input += 'cd {}\n'.format(workdir)

        if virtualenv:
            activate_path = path.join(virtualenv, 'bin', 'activate')
            if not path.exists(activate_path) or not path.isfile(activate_path):
                raise PluginError('Python virtualenv doesn\'t exist: {}'.format(activate_path))

            bash_input += 'source {}\n'.format(activate_path)

        filename = file

        if script:
            f = NamedTemporaryFile(delete=False)

            f.write(script)
            log.debug('Wrote script to file {}, {}'.format(f.name, script))
            filename = f.name
            f.close()

        bash_input += 'python {}'.format(filename)
        log.debug('Running python script: {}'.format(bash_input))

        if self.dry_run:
            return TaskResult(EXECUTION_SUCCESSFUL)

        return_obj=None
        try:
            stdout, return_obj = self._run_bash(bash_input)
            status = EXECUTION_SUCCESSFUL
        except BashExecuteError as e:

            status = EXECUTION_FAILED