+# Copyright (C) 2013-2016 CEA/DEN, EDF R&D, OPEN CASCADE
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
import ConfigParser
import os
import logging
import re
from io import StringIO
import subprocess
+from salomeContextUtils import SalomeContextException #@UnresolvedImport
logging.basicConfig()
logConfigParser = logging.getLogger(__name__)
UNSET_KEYWORD = 'UNSET'
+def _expandSystemVariables(key, val):
+ expandedVal = os.path.expandvars(val) # expand environment variables
+ # Search for not expanded variables (i.e. non-existing environment variables)
+ pattern = re.compile('\${ ( [^}]* ) }', re.VERBOSE) # string enclosed in ${ and }
+ expandedVal = pattern.sub(r'', expandedVal) # remove matching patterns
+
+ if not "DLIM8VAR" in key: # special case: DISTENE licence key can contain double clons (::)
+ expandedVal = _trimColons(expandedVal)
+ return expandedVal
+#
+
# :TRICKY: So ugly solution...
class MultiOptSafeConfigParser(ConfigParser.SafeConfigParser):
def __init__(self):
optname = None
# no section header in the file?
elif cursect is None:
- raise MissingSectionHeaderError(fpname, lineno, line)
+ raise ConfigParser.MissingSectionHeaderError(fpname, lineno, line)
# an option line?
else:
mo = self.OPTCRE.match(line)
if pos != -1 and optval[pos-1].isspace():
optval = optval[:pos]
optval = optval.strip()
+ # ADD THESE LINES
+ splittedComments = optval.split('#')
+ s = _expandSystemVariables(optname, splittedComments[0])
+ optval = s.strip().strip("'").strip('"')
+ #if len(splittedComments) > 1:
+ # optval += " #" + " ".join(splittedComments[1:])
+ # END OF ADD
# allow empty values
if optval == '""':
optval = ''
cursect[optname][0] += ','+optval
else:
cursect[optname] = [optval]
- # END OF SUBSITUTION
+ # END OF SUBSTITUTION
else:
# valueless option handling
cursect[optname] = optval
# Input: filename, and a list of reserved keywords (environment variables)
# Output: a list of pairs (variable, value), and a dictionary associating a list of user-defined values to each reserved keywords
# Note: Does not support duplicate keys in a same section
-def parseConfigFile(filename, reserved = []):
+def parseConfigFile(filename, reserved = None):
+ if reserved is None:
+ reserved = []
config = MultiOptSafeConfigParser()
config.optionxform = str # case sensitive
logConfigParser.error("No section found in file: %s"%(filename))
return []
- return _processConfigFile(config, reserved)
+ try:
+ return __processConfigFile(config, reserved, filename)
+ except ConfigParser.InterpolationMissingOptionError, e:
+ msg = "A variable may be undefined in SALOME context file: %s\nParser error is: %s\n"%(filename, e)
+ raise SalomeContextException(msg)
#
-def _processConfigFile(config, reserved = []):
+def __processConfigFile(config, reserved = None, filename="UNKNOWN FILENAME"):
# :TODO: may detect duplicated variables in the same section (raise a warning)
# or even duplicate sections
+ if reserved is None:
+ reserved = []
unsetVariables = []
outputVariables = []
# Get raw items for each section, and make some processing for environment variables management
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)
- pattern = re.compile('\${ ( [^}]* ) }', re.VERBOSE) # string enclosed in ${ and }
- expandedVal = pattern.sub(r'', expandedVal) # remove matching patterns
- # Trim colons
- expandedVal = _trimColons(expandedVal)
+ expandedVal = _expandSystemVariables(key, val)
if key in reservedKeys:
shortKey = key[len(ADD_TO_PREFIX):]
pass # end for key,val
pass # end for section
- return unsetVariables, outputVariables, reservedValues
+ # remove duplicate values
+ outVars = []
+ for (var, values) in outputVariables:
+ vals = values.split(',')
+ vals = list(set(vals))
+ outVars.append((var, ','.join(vals)))
+
+ return unsetVariables, outVars, reservedValues
#
def _trimColons(var):
# - virtually add a section to configuration file
# - process shell keywords (if, then...)
class EnvFileConverter(object):
- def __init__(self, fp, section_name, reserved = [], outputFile=None):
+ def __init__(self, fp, section_name, reserved = None, outputFile=None):
+ if reserved is None:
+ reserved = []
self.fp = fp
self.sechead = '[' + section_name + ']\n'
self.reserved = reserved
self.outputFile = outputFile
- self.allParsedVariableNames=[]
+ self.allParsedVariableNames = []
# exclude line that begin with:
- self.exclude = [ 'if', 'then', 'fi', '#', 'echo' ]
+ self.exclude = [ 'if', 'then', 'else', 'fi', '#', 'echo', 'exit' ]
+ 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:
value = self._purgeValue(value, k)
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
#
# 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=None):
+ if reserved is None:
+ 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'