From 4301c05debde4e1de0c857b99d41df5ce1da4f32 Mon Sep 17 00:00:00 2001 From: Alex Gray Date: Tue, 16 Mar 2021 20:15:39 -0400 Subject: [PATCH 1/3] subprocess for any version of pythhon --- retemplate/__init__.py | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/retemplate/__init__.py b/retemplate/__init__.py index a6f024d..dc62465 100644 --- a/retemplate/__init__.py +++ b/retemplate/__init__.py @@ -226,10 +226,7 @@ def get_value(self, key, **kwargs): # Clean these args up a bit for i in range(0, len(subp_args)): subp_args[i] = subp_args[i].strip() - - logging.debug('Running command: {}'.format(' '.join(subp_args))) - proc = subprocess.run(subp_args, capture_output=True) - output = proc.stdout.decode('utf-8').strip() + output, _ = self.exec_process(' '.join(subp_args)) return output except Exception as ex: logging.error('Failed to get local execution data. Error: {}'.format(ex)) @@ -368,6 +365,20 @@ def process(self, tpl): prerender.append(line) return '\n'.join(prerender) + def exec_process(self, cmd): + ''' + Shells out an external process and gets the stdout/stderr and returncoce. + ''' + logging.debug('Running command: {}'.format(cmd)) + p = subprocess.Popen(cmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True, + shell=True) + output = p.communicate()[0] + returncode = p.returncode + return output, returncode + def render(self): ''' Renders a template in three phases: @@ -439,7 +450,7 @@ def write_file(self, content): shutil.chown(self.target, user=owner, group=group) if chmod: logging.info('Setting mode of {} to {}'.format(self.target, chmod)) - subprocess.run([ 'chmod', self.settings['chmod'], self.target ]) + self.exec_process(' '.join([ 'chmod', self.settings['chmod'], self.target ])) return True except IOError: logging.error('Cannot write target file {}'.format(self.target)) @@ -459,9 +470,9 @@ def execute_onchange(self): logging.info('Running onchange command \'{}\' for target {}'.format(onchange, self.target)) try: - proc = subprocess.run(onchange.split(' '), capture_output=True) - logging.debug('onchange command exited: {}'.format(proc.returncode)) - logging.debug('onchange command output: {}'.format(proc.stdout)) + output, returncode = self.exec_process(onchange) + logging.debug('onchange command exited: {}'.format(returncode)) + logging.debug('onchange command output: {}'.format(output)) except subprocess.CalledProcessError as ex: logging.error('[{}] Couldn\'t call process {}'.format(target, onchange)) logging.error(ex) From aa4bd526f1c14de316762397487797d73840acd6 Mon Sep 17 00:00:00 2001 From: Alex Gray Date: Tue, 16 Mar 2021 20:39:16 -0400 Subject: [PATCH 2/3] put it in a class so other classes can use it --- retemplate/__init__.py | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/retemplate/__init__.py b/retemplate/__init__.py index dc62465..bba2980 100644 --- a/retemplate/__init__.py +++ b/retemplate/__init__.py @@ -203,6 +203,25 @@ def get_value(self, key): raise RetrievalError +class ProcessExecutor(): + ''' + A simple class to encapsulate the execution of external function calls. + ''' + + def exec_process(cmd): + ''' + Shells out an external process and gets the stdout/stderr and returncoce. + ''' + logging.debug('Running command: {}'.format(cmd)) + p = subprocess.Popen(cmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True, + shell=True) + output = p.communicate()[0] + returncode = p.returncode + return output, returncode + class LocalExecutionStore(DataStore): ''' A DataStore that issues a terminal command and uses its standard output as a template value. @@ -226,7 +245,7 @@ def get_value(self, key, **kwargs): # Clean these args up a bit for i in range(0, len(subp_args)): subp_args[i] = subp_args[i].strip() - output, _ = self.exec_process(' '.join(subp_args)) + output, _ = ProcessExecutor.exec_process(' '.join(subp_args)) return output except Exception as ex: logging.error('Failed to get local execution data. Error: {}'.format(ex)) @@ -365,20 +384,6 @@ def process(self, tpl): prerender.append(line) return '\n'.join(prerender) - def exec_process(self, cmd): - ''' - Shells out an external process and gets the stdout/stderr and returncoce. - ''' - logging.debug('Running command: {}'.format(cmd)) - p = subprocess.Popen(cmd, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - universal_newlines=True, - shell=True) - output = p.communicate()[0] - returncode = p.returncode - return output, returncode - def render(self): ''' Renders a template in three phases: @@ -450,7 +455,7 @@ def write_file(self, content): shutil.chown(self.target, user=owner, group=group) if chmod: logging.info('Setting mode of {} to {}'.format(self.target, chmod)) - self.exec_process(' '.join([ 'chmod', self.settings['chmod'], self.target ])) + ProcessExecutor.exec_process(' '.join([ 'chmod', self.settings['chmod'], self.target ])) return True except IOError: logging.error('Cannot write target file {}'.format(self.target)) @@ -470,7 +475,7 @@ def execute_onchange(self): logging.info('Running onchange command \'{}\' for target {}'.format(onchange, self.target)) try: - output, returncode = self.exec_process(onchange) + output, returncode = ProcessExecutor.exec_process(onchange) logging.debug('onchange command exited: {}'.format(returncode)) logging.debug('onchange command output: {}'.format(output)) except subprocess.CalledProcessError as ex: From 9ab04022eb4c524f2c1269f85fa36851f0d46d60 Mon Sep 17 00:00:00 2001 From: Alex Gray Date: Tue, 16 Mar 2021 21:26:50 -0400 Subject: [PATCH 3/3] add strips --- retemplate/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/retemplate/__init__.py b/retemplate/__init__.py index bba2980..3a8e13f 100644 --- a/retemplate/__init__.py +++ b/retemplate/__init__.py @@ -351,9 +351,9 @@ def preprocess(self, tpl): if match: groups = match.groups() if groups[1].startswith('rtpl://'): - self.vars[groups[0]] = self.resolve_value(groups[1]) + self.vars[groups[0]] = self.resolve_value(groups[1]).strip() else: - self.vars[groups[0]] = groups[1] + self.vars[groups[0]] = groups[1].strip() # Now update all future lines so they get parsed right for j in range(i, len(lines)): for var in self.vars: