github.com/hwaf/hwaf@v0.0.0-20140814122253-5465f73b20f1/py-hwaftools/orch/mungers.py (about)

     1  #!/usr/bin/env python
     2  '''
     3  This module primarily provides the functions:
     4  
     5   - construct :: create mungers from configuration items
     6   - apply :: apply a list of mungers to an environment
     7  
     8  In this module "environment munging" or "munge" refers to mutating a
     9  dictionary of environment variables.  
    10  
    11  A munger is a callable object with the signature:
    12  
    13    munger(**environ) --> new_environ
    14  
    15  The returned environment is a copy an so mungers may be chained via apply().
    16  
    17  Mungers are constructed from key/value configuration items like:
    18  
    19    <prefix><name> = <command><delim><payload>
    20  
    21  Where:
    22  
    23   - prefix :: indicates some domain ("export_", "buildenv_").  Note it includes any separator character(s)
    24   - name :: a <command>-specific label.  For commands setting specific environment variables it provides the variable name.  For shell commands it is ignored (but may be used for ordering).
    25   - command :: one of "append", "prepend", "set" or "shell".  If not of this set then "set" is assumed and no <delim> is expected
    26   - delim :: A single character delimiter used for "append" and "prepend" commands and otherwise required but ignored (unless no command given as above)
    27   - payload :: the value to apply to the command.  For "shell" commands it is a shell command line, for all else it is an environment variable value.
    28  
    29  '''
    30  
    31  import os
    32  import tempfile
    33  
    34  from . import util
    35  
    36  def split_var_munger_command(cmdstr, cmd):
    37      'cmd<delim><string> --> (<delim>,<string>'
    38      rest = cmdstr[len(cmd):]
    39      return rest[0], rest[1:]
    40  
    41  def update_var(name, cmdstr, **environ):
    42      '''
    43      A munger body which will apply the cmdstr to the named environment
    44      variable to the given environ keywords and return the result.
    45      '''
    46      #print 'munger: apply: %s: "%s"' % (name, cmdstr)
    47  
    48      oldval = environ.get(name)
    49      if cmdstr.startswith('append'):
    50          delim,val = split_var_munger_command(cmdstr, 'append')
    51          newval = oldval + delim + val if oldval else val
    52      elif cmdstr.startswith('prepend'):
    53          delim,val = split_var_munger_command(cmdstr, 'prepend')
    54          newval = val + delim + oldval if oldval else val
    55      elif cmdstr.startswith('set'):
    56          delim,val = split_var_munger_command(cmdstr, 'set')
    57          newval = val
    58      else: 
    59          newval = cmdstr
    60      environ[name] = newval
    61      return environ
    62              
    63  
    64  # by default, rely on this being in the PATH
    65  env_executable = "env"
    66  def cmd_munger(cmd, **environ):
    67      '''
    68      A munger body which will execute the shell cmd in the given
    69      environment and return the post-execution environment.  This is
    70      done by parsing the output to the "env" command as set by the
    71      "env_executable" variable.
    72      '''
    73      #print 'munger: apply: "%s"' % cmd
    74      #print 'PATH=%s' % environ.get('PATH','')
    75      fd, fname = tempfile.mkstemp()
    76      cmd += ' && %s > %s' % (env_executable, fname)
    77      util.check_output(cmd, shell=True, env=environ)
    78      os.close(fd)
    79      envtext = open(fname).read()
    80      ret = dict()
    81      for k,v in util.envvars(envtext).items():
    82          ret[k.strip()] = v.strip()
    83      return ret
    84  
    85  def make_munger(name, cmdstr):
    86      '''
    87      Dispatch based on the command of the cmdstr (<command><delim><payload>).
    88  
    89      Returns a munger object.
    90      '''
    91      #print 'munger: %s: "%s"' % (name, cmdstr) 
    92          
    93      if cmdstr.startswith('shell'):
    94          delim, cmdline = split_var_munger_command(cmdstr, 'shell')
    95          return lambda **environ: cmd_munger(cmdline, **environ)
    96      return lambda **environ: update_var(name, cmdstr, **environ)
    97  
    98  def construct(prefix, **pkg_kwds):
    99      '''
   100      Any package configuration items with keys starting with prefix are
   101      interpreted as munging commands.
   102      '''
   103  
   104      ret = list()
   105      for key, cmdstr in pkg_kwds.items():
   106          if not key.startswith(prefix):
   107              continue
   108          name = key[len(prefix):]
   109          m = make_munger(name, cmdstr)
   110          ret.append(m)
   111      return ret
   112  
   113  def apply(mungers, **environ):
   114      '''
   115      Run the given environment through the given mungers and return the result.
   116  
   117      If no keyword arguments are given the current process environment
   118      (os.environ) is used as a starting environment..
   119      '''
   120      if not environ:
   121          environ = dict(os.environ)
   122      for m in mungers:
   123          environ = m(**environ)
   124      return environ