import logging
import re
from io import StringIO
+import subprocess
logging.basicConfig()
logConfigParser = logging.getLogger(__name__)
-RESERVED_PREFIX = 'ADD_TO_'
+ADD_TO_PREFIX = 'ADD_TO_'
+UNSET_KEYWORD = 'UNSET'
# :TRICKY: So ugly solution...
# copied from python 2.6.8 Lib.ConfigParser.py
# modified (see code comments) to handle duplicate keys
- def _read(self, fp, name):
+ def _read(self, fp, fpname):
"""Parse a sectioned setup file.
The sections in setup file contains a title line at the top,
# raised at the end of the file and will contain a
# list of all bogus lines
if not e:
- e = ParsingError(fpname)
+ e = ConfigParser.ParsingError(fpname)
e.append(lineno, repr(line))
# if any parsing errors occurred, raise an exception
if e:
logConfigParser.error("No section found in file: %s"%(filename))
return []
- return _processConfigFile(config, reserved)
+ return __processConfigFile(config, reserved, filename)
#
-def _processConfigFile(config, reserved = []):
+def __processConfigFile(config, reserved = [], filename="UNKNOWN FILENAME"):
# :TODO: may detect duplicated variables in the same section (raise a warning)
# or even duplicate sections
+ unsetVariables = []
outputVariables = []
# Get raw items for each section, and make some processing for environment variables management
- reservedKeys = [RESERVED_PREFIX+str(x) for x in reserved] # produce [ 'ADD_TO_reserved_1', 'ADD_TO_reserved_2', ..., ADD_TO_reserved_n ]
+ reservedKeys = [ADD_TO_PREFIX+str(x) for x in reserved] # produce [ 'ADD_TO_reserved_1', 'ADD_TO_reserved_2', ..., ADD_TO_reserved_n ]
reservedValues = dict([str(i),[]] for i in reserved) # create a dictionary in which keys are the 'ADD_TO_reserved_i' and associated values are empty lists: { 'reserved_1':[], 'reserved_2':[], ..., reserved_n:[] }
sections = config.sections()
for section in sections:
for key,val in entries:
if key in reserved:
logConfigParser.error("Invalid use of reserved variable: %s in file: %s"%(key, filename))
+ elif key == UNSET_KEYWORD:
+ unsetVariables += val.replace(',', ' ').split()
else:
expandedVal = os.path.expandvars(val) # expand environment variables
# Search for not expanded variables (i.e. non-existing environment variables)
expandedVal = _trimColons(expandedVal)
if key in reservedKeys:
- shortKey = key[len(RESERVED_PREFIX):]
+ shortKey = key[len(ADD_TO_PREFIX):]
vals = expandedVal.split(',')
reservedValues[shortKey] += vals
# remove left&right spaces on each element
pass # end for key,val
pass # end for section
- return outputVariables, reservedValues
+ return unsetVariables, outputVariables, reservedValues
#
def _trimColons(var):
self.outputFile = outputFile
self.allParsedVariableNames=[]
# exclude line that begin with:
- self.exclude = [ 'if', 'then', 'fi', '#' ]
+ self.exclude = [ 'if', 'then', 'else', 'fi', '#', 'echo' ]
+ self.exclude.append('$gconfTool') # QUICK FIX :TODO: provide method to extend this variable
# discard the following keywords if at the beginning of line:
self.discard = [ 'export' ]
+ # the following keywords imply a special processing if at the beginning of line:
+ self.special = [ 'unset' ]
def readline(self):
if self.sechead:
return '\n'
# look for substrinsg beginning with sharp charcter ('#')
line = re.sub(r'#.*$', r'', line)
+ # line to be pre-processed? (beginning by a keyword of self.special)
+ for k in self.special:
+ if k == "unset" and line.startswith(k):
+ line = line[len(k):]
+ line = line.strip(' \t\n\r')
+ line = UNSET_KEYWORD + ": " + line
# line to be pre-processed? (beginning by a keyword of self.discard)
for k in self.discard:
if line.startswith(k):
if line.startswith(k) and "=" in line:
variable, value = line.split('=')
value = self._purgeValue(value, k)
- line = RESERVED_PREFIX + k + ": " + value
+ line = ADD_TO_PREFIX + k + ": " + value
# Update list of variable names
+ # :TODO: define excludeBlock variable (similar to exclude) and provide method to extend it
+ if "cleandup()" in line:
+ print "WARNING: parseConfigFile.py: skip cleandup and look for '# PRODUCT environment'"
+ while True:
+ line = self.fp.readline()
+ if "# PRODUCT environment" in line:
+ print "WARNING: parseConfigFile.py: '# PRODUCT environment' found"
+ break
+ while "clean " in line[0:6]: #skip clean calls with ending ";" crash
+ line = self.fp.readline()
+ # Extract variable=value
if "=" in line:
- variable, value = line.split('=')
+ try:
+ variable, value = line.split('=')
+ except: #avoid error for complicated sh line xx=`...=...`, but warning
+ print "WARNING: parseConfigFile.py: line with multiples '=' character are hazardous: '"+line+"'"
+ variable, value = line.split('=',1)
+ pass
+
+ # Self-extending variables that are not in reserved keywords
+ # Example: FOO=something:${FOO}
+ # In this case, remove the ${FOO} in value
+ if variable in value:
+ value = self._purgeValue(value, variable)
+ line = "%s=%s"%(variable,value)
+
self.allParsedVariableNames.append(variable)
- # Self-extending variables that are not in reserved keywords
- # Example: FOO=something:${FOO}
- # :TODO:
+ # End of extraction
+
+ if not line:
+ return line
+
#
# replace "${FOO}" and "$FOO" and ${FOO} and $FOO by %(FOO)s if FOO is
# defined in current file (i.e. it is not an external environment variable)
key = r'\$\{?'+k+'\}?'
pattern = re.compile(key, re.VERBOSE)
line = pattern.sub(r'%('+k+')s', line)
- # Remove quotes
- pattern = re.compile(r'\"', re.VERBOSE)
- line = pattern.sub(r'', line)
+ # Remove quotes (if line does not contain whitespaces)
+ try:
+ variable, value = line.split('=', 1)
+ except ValueError:
+ variable, value = line.split(':', 1)
+ if not ' ' in value.strip():
+ pattern = re.compile(r'\"', re.VERBOSE)
+ line = pattern.sub(r'', line)
#
+
# Replace `shell_command` by its result
def myrep(obj):
obj = re.sub('`', r'', obj.group(0)) # remove quotes
- import subprocess
- res = subprocess.Popen([obj], stdout=subprocess.PIPE).communicate()[0]
+ obj = obj.split()
+ res = subprocess.Popen(obj, stdout=subprocess.PIPE).communicate()[0]
res = res.strip(' \t\n\r') # trim whitespaces
return res
#
#
# Convert .sh environment file to configuration file format
-def convertEnvFileToConfigFile(envFilename, configFilename):
- #reserved=['PATH', 'LD_LIBRARY_PATH', 'PYTHONPATH']
- reserved=['PATH', 'LD_LIBRARY_PATH', 'PYTHONPATH', 'MANPATH', 'R_LIBS', 'PV_PLUGIN_PATH']
+def convertEnvFileToConfigFile(envFilename, configFilename, reserved=[]):
+ logConfigParser.debug('convert env file %s to %s'%(envFilename, configFilename))
fileContents = open(envFilename, 'r').read()
pattern = re.compile('\n[\n]+', re.VERBOSE) # multiple '\n'
config = MultiOptSafeConfigParser()
config.optionxform = str # case sensitive
config.readfp(EnvFileConverter(finput, 'SALOME Configuration', reserved, outputFile=foutput))
+
foutput.close()
logConfigParser.info('Configuration file generated: %s'%configFilename)