"""Configuration system for CherryPy."""importConfigParserimportcherrypyfromcherrypyimport_cputil,_cperrorfromcherrypy.libimportautoreload# This configMap dict holds the settings metadata for all cherrypy objects.# Keys are URL paths, and values are dicts.configMap={}defaultGlobal={'server.socketPort':8080,'server.socketHost':'','server.socketFile':'','server.socketQueueSize':5,'server.protocolVersion':'HTTP/1.0','server.logToScreen':True,'server.logFile':'','server.reverseDNS':False,'server.threadPool':0,'server.environment':"development",}environments={"development":{'autoreload.on':True,'logDebugInfoFilter.on':True,'server.logFileNotFound':True,'server.showTracebacks':True,},"staging":{'autoreload.on':False,'logDebugInfoFilter.on':False,'server.logFileNotFound':False,'server.showTracebacks':False,},"production":{'autoreload.on':False,'logDebugInfoFilter.on':False,'server.logFileNotFound':False,'server.showTracebacks':False,},}defupdate(updateMap=None,file=None,overwrite=True):"""Update configMap from a dictionary or a config file. If overwrite is False then the update will not modify values already defined in the configMap. """ifupdateMapisNone:updateMap={}iffile:iffilenotinautoreload.reloadFiles:autoreload.reloadFiles.append(file)updateMap=updateMap.copy()updateMap.update(dict_from_config_file(file))# Load new conf into cherrypy.configMapforsection,valueMapinupdateMap.iteritems():# Handle shortcut syntax for "global" section# example: update({'server.socketPort': 80})ifnotisinstance(valueMap,dict):valueMap={section:valueMap}section='global'bucket=configMap.setdefault(section,{})ifoverwrite:bucket.update(valueMap)else:forkey,valueinvalueMap.iteritems():bucket.setdefault(key,value)defreset(useDefaults=True):"""Clear configuration and restore defaults"""configMap.clear()ifuseDefaults:update(defaultGlobal)reset()defget(key,defaultValue=None,returnSection=False,path=None):"""Return the configuration value corresponding to key If specified, return defaultValue on lookup failure. If returnSection is specified, return the path to the value, instead of the value itself. """# Look, ma, no Python function calls! Uber-fast.ifpathisNone:try:path=cherrypy.request.objectPathexceptAttributeError:# There's no request.objectPath yet, so use the global settings.path="global"whileTrue:ifpath=="":path="/"try:result=configMap[path][key]breakexceptKeyError:passtry:# Check for a server.environment entry at this node.env=configMap[path]["server.environment"]result=environments[env][key]breakexceptKeyError:passifpath=="global":result=defaultValuebreak# Move one node up the tree and try again.ifpath=="/":path="global"else:path=path[:path.rfind("/")]ifreturnSection:returnpathelse:returnresultdefgetAll(key):"""Lookup key in the current node and all of its parent nodes as a list of path, value pairs. """# Needed by the session filtertry:results=[('global',configMap['global'][key])]exceptKeyError:results=[]try:path=cherrypy.request.objectPathexceptAttributeError:returnresultspathList=path.split('/')forninxrange(1,len(pathList)):path='/'+'/'.join(pathList[0:n+1])try:results.append((path,configMap[path][key]))exceptKeyError:passreturnresultsclassCaseSensitiveConfigParser(ConfigParser.ConfigParser):"""Sub-class of ConfigParser that keeps the case of options and that raises an exception if the file cannot be read. """defoptionxform(self,optionstr):returnoptionstrdefread(self,filenames):ifisinstance(filenames,basestring):filenames=[filenames]forfilenameinfilenames:# try:# fp = open(filename)# except IOError:# continuefp=open(filename)try:self._read(fp,filename)finally:fp.close()defdict_from_config_file(configFile):"""Convert an INI file to a dictionary"""# Parse config fileconfigParser=CaseSensitiveConfigParser()ifhasattr(configFile,'read'):configParser.readfp(configFile)else:configParser.read(configFile)# Load INI file into a dictresult={}forsectioninconfigParser.sections():ifsectionnotinresult:result[section]={}foroptioninconfigParser.options(section):value=configParser.get(section,option)try:value=_cputil.unrepr(value)except_cperror.WrongUnreprValue,s:msg=("section: %s, option: %s, value: %s"%(repr(section),repr(option),repr(value)))raise_cperror.WrongConfigValue(msg)result[section][option]=valuereturnresultdefoutputConfigMap():"""Log server configuration parameters"""cherrypy.log("Server parameters:",'CONFIG')serverVars=['server.environment','server.logToScreen','server.logFile','server.protocolVersion','server.socketHost','server.socketPort','server.socketFile','server.reverseDNS','server.socketQueueSize','server.threadPool']forvarinserverVars:cherrypy.log(" %s: %s"%(var,get(var)),'CONFIG')