Commits

Anonymous committed fc97c96

Changed the config API

Comments (0)

Files changed (20)

 
 import _cputil, ConfigParser, cpg
 
+# Default config options
+configMap = {
+        'server': {
+            'protocolVersion': 'HTTP/1.0',
+            'logToScreen': True,
+            'logFile': '',
+            'socketHost': '',
+            'socketPort': 8080,
+            'socketFile': '',
+            'reverseDNS': False,
+            'socketQueueSize': 5,
+            'protocolVersion': 'HTTP/1.0',
+            'threadPool': 0,
+            'environment': 'dev'},
+        'session': {
+            'storageType': 'ram',
+            'timeout': 60,
+            'cleanUpDelay': 60,
+            'cookieName': 'CherryPySession',
+            'storageFileDir': '',
+        },
+        'staticContent': {}
+    }
+
+def update(updateMap = None, file = None):
+    if updateMap is not None:
+        for section, valueMap in updateMap.items():
+            if section not in configMap:
+                configMap[section] = valueMap
+            else:
+                for key, value in valueMap.items():
+                    configMap[section][key] = value
+    if file is not None:
+        _load(file)
+
+def get(section, attrName = None, defaultValue = None):
+    if attrName:
+        return configMap.get(section, {}).get(attrName, defaultValue)
+    else:
+        return configMap.get(section, defaultValue)
+
+def getForPath(attrNam, defaultValue = None):
+    raise "TODO"
+
 class CaseSensitiveConfigParser(ConfigParser.ConfigParser):
-    """ Sub-class of ConfigParser that keeps the case of options """
+    """ Sub-class of ConfigParser that keeps the case of options and
+        that raises an exception if the file cannot be read
+    """
     def optionxform(self, optionstr):
         return optionstr
+    def read(self, filenames):
+        if isinstance(filenames, basestring):
+            filenames = [filenames]
+        for filename in filenames:
+            # try:
+            #     fp = open(filename)
+            # except IOError:
+            #     continue
+            fp = open(filename)
+            self._read(fp, filename)
+            fp.close()
 
 # Known options to cast:
 cast = {
     }
 }
         
-def loadConfigFile(configFile = None):
+def _load(configFile = None):
     """ Convert an INI file to a dictionary """
     _cpLogMessage = _cputil.getSpecialFunction('_cpLogMessage')
 
 
     # Load INI file into cpg.configMap
     for section in configParser.sections():
-        if section not in cpg.configMap:
-            cpg.configMap[section] = {}
+        if section not in configMap:
+            configMap[section] = {}
         for option in configParser.options(section):
             # Check if we need to cast options
             funcName = cast.get(section, {}).get(option, 'get')
             value = getattr(configParser, funcName)(section, option)
-            cpg.configMap[section][option] = value
+            configMap[section][option] = value
 
 def outputConfigMap():
     _cpLogMessage = _cputil.getSpecialFunction('_cpLogMessage')
     _cpLogMessage("Server parameters:", 'CONFIG')
-    _cpLogMessage("  server.logToScreen: %s" % cpg.getConfig('server', 'logToScreen'), 'CONFIG')
-    _cpLogMessage("  server.logFile: %s" % cpg.getConfig('server', 'logFile'), 'CONFIG')
-    _cpLogMessage("  server.protocolVersion: %s" % cpg.getConfig('server', 'protocolVersion'), 'CONFIG')
-    _cpLogMessage("  server.socketHost: %s" % cpg.getConfig('server', 'socketHost'), 'CONFIG')
-    _cpLogMessage("  server.socketPort: %s" % cpg.getConfig('server', 'socketPort'), 'CONFIG')
-    _cpLogMessage("  server.socketFile: %s" % cpg.getConfig('server', 'socketFile'), 'CONFIG')
-    _cpLogMessage("  server.reverseDNS: %s" % cpg.getConfig('server', 'reverseDNS'), 'CONFIG')
-    _cpLogMessage("  server.socketQueueSize: %s" % cpg.getConfig('server', 'socketQueueSize'), 'CONFIG')
-    _cpLogMessage("  server.threadPool: %s" % cpg.getConfig('server', 'threadPool'), 'CONFIG')
-    _cpLogMessage("  session.storageType: %s" % cpg.getConfig('session', 'storageType'), 'CONFIG')
-    if cpg.getConfig('session', 'storageType'):
-        _cpLogMessage("  session.timeout: %s min" % cpg.getConfig('session', 'timeout'), 'CONFIG')
-        _cpLogMessage("  session.cleanUpDelay: %s min" % cpg.getConfig('session', 'cleanUpDelay'), 'CONFIG')
-        _cpLogMessage("  session.cookieName: %s" % cpg.getConfig('session', 'cookieName'), 'CONFIG')
-        _cpLogMessage("  session.storageFileDir: %s" % cpg.getConfig('session', 'storageFileDir'), 'CONFIG')
-    _cpLogMessage("  staticContent: %s" % cpg.getConfig('staticContent'), 'CONFIG')
+    _cpLogMessage("  server.logToScreen: %s" % cpg.config.get('server', 'logToScreen'), 'CONFIG')
+    _cpLogMessage("  server.logFile: %s" % cpg.config.get('server', 'logFile'), 'CONFIG')
+    _cpLogMessage("  server.protocolVersion: %s" % cpg.config.get('server', 'protocolVersion'), 'CONFIG')
+    _cpLogMessage("  server.socketHost: %s" % cpg.config.get('server', 'socketHost'), 'CONFIG')
+    _cpLogMessage("  server.socketPort: %s" % cpg.config.get('server', 'socketPort'), 'CONFIG')
+    _cpLogMessage("  server.socketFile: %s" % cpg.config.get('server', 'socketFile'), 'CONFIG')
+    _cpLogMessage("  server.reverseDNS: %s" % cpg.config.get('server', 'reverseDNS'), 'CONFIG')
+    _cpLogMessage("  server.socketQueueSize: %s" % cpg.config.get('server', 'socketQueueSize'), 'CONFIG')
+    _cpLogMessage("  server.threadPool: %s" % cpg.config.get('server', 'threadPool'), 'CONFIG')
+    _cpLogMessage("  session.storageType: %s" % cpg.config.get('session', 'storageType'), 'CONFIG')
+    if cpg.config.get('session', 'storageType'):
+        _cpLogMessage("  session.timeout: %s min" % cpg.config.get('session', 'timeout'), 'CONFIG')
+        _cpLogMessage("  session.cleanUpDelay: %s min" % cpg.config.get('session', 'cleanUpDelay'), 'CONFIG')
+        _cpLogMessage("  session.cookieName: %s" % cpg.config.get('session', 'cookieName'), 'CONFIG')
+        _cpLogMessage("  session.storageFileDir: %s" % cpg.config.get('session', 'storageFileDir'), 'CONFIG')
+    _cpLogMessage("  staticContent: %s" % cpg.config.get('staticContent'), 'CONFIG')
 
 def dummy():
     # Check that parameters are correct and that they don't conflict with each other
     s = nowStr + ' ' + context + ' ' + level + ' ' + msg
     if logToScreen:
         print s
-    if cpg.getConfig('server', 'logFile'):
-        f = open(cpg.getConfig('server','logFile'), 'ab')
+    if cpg.config.get('server', 'logFile'):
+        f = open(cpg.config.get('server','logFile'), 'ab')
         f.write(s + '\n')
         f.close()
 
     """ Save session data if needed """
 
     if threadPool is None:
-        threadPool = cpg.getConfig('server', 'threadPool')
+        threadPool = cpg.config.get('server', 'threadPool')
     if sessionStorageType is None:
-        sessionStorageType = cpg.getConfig('session', 'storageType')
+        sessionStorageType = cpg.config.get('session', 'storageType')
     if sessionStorageFileDir is None:
-        sessionStorageFileDir = cpg.getConfig('session', 'storageFileDir')
+        sessionStorageFileDir = cpg.config.get('session', 'storageFileDir')
 
     t = time.localtime(expirationTime)
     if sessionStorageType == 'file':
     """
 
     if threadPool is None:
-        threadPool = cpg.getConfig('server', 'threadPool')
+        threadPool = cpg.config.get('server', 'threadPool')
     if sessionStorageType is None:
-        sessionStorageType = cpg.getConfig('session', 'storageType')
+        sessionStorageType = cpg.config.get('session', 'storageType')
     if sessionStorageFileDir is None:
-        sessionStorageFileDir = cpg.getConfig('session', 'storageFileDir')
+        sessionStorageFileDir = cpg.config.get('session', 'storageFileDir')
 
     if sessionStorageType == "ram":
         if cpg._sessionMap.has_key(sessionId):
     """ Clean up old sessions """
 
     if threadPool is None:
-        threadPool = cpg.getConfig('server', 'threadPool')
+        threadPool = cpg.config.get('server', 'threadPool')
     if sessionStorageType is None:
-        sessionStorageType = cpg.getConfig('session', 'storageType')
+        sessionStorageType = cpg.config.get('session', 'storageType')
     if sessionStorageFileDir is None:
-        sessionStorageFileDir = cpg.getConfig('session', 'storageFileDir')
+        sessionStorageFileDir = cpg.config.get('session', 'storageFileDir')
 
     # Clean up old session data
     now = time.time()
 
     # If sessions are stored in files and we
     # use threading, we need a lock on the file
-    if (cpg.getConfig('server', 'threadPool') > 1) and \
-            cpg.getConfig('session', 'storageType') == 'file':
+    if (cpg.config.get('server', 'threadPool') > 1) and \
+            cpg.config.get('session', 'storageType') == 'file':
         cpg._sessionFileLock = threading.RLock()
 
 
-    if cpg.getConfig('server', 'socketFile'):
+    if cpg.config.get('server', 'socketFile'):
         # AF_UNIX socket
         # TODO: Handle threading here
         class MyCherryHTTPServer(CherryHTTPServer): address_family = socket.AF_UNIX
     else:
         # AF_INET socket
-        if cpg.getConfig('server', 'threadPool') > 1:
+        if cpg.config.get('server', 'threadPool') > 1:
             MyCherryHTTPServer = PooledThreadServer
         else:
             MyCherryHTTPServer = CherryHTTPServer
 
-    MyCherryHTTPServer.request_queue_size = cpg.getConfig('server', 'socketQueueSize')
+    MyCherryHTTPServer.request_queue_size = cpg.config.get('server', 'socketQueueSize')
 
     # Set protocol_version
-    CherryHTTPRequestHandler.protocol_version = cpg.getConfig('server', 'protocolVersion')
+    CherryHTTPRequestHandler.protocol_version = cpg.config.get('server', 'protocolVersion')
 
     run_server(CherryHTTPRequestHandler, MyCherryHTTPServer, \
-        (cpg.getConfig('server', 'socketHost'), cpg.getConfig('server', 'socketPort')), \
-        cpg.getConfig('server', 'socketFile'))
+        (cpg.config.get('server', 'socketHost'), cpg.config.get('server', 'socketPort')), \
+        cpg.config.get('server', 'socketFile'))
 
 def run_server(HandlerClass, ServerClass, server_address, socketFile):
     """Run the HTTP request handler class."""
 
-    if cpg.getConfig('server', 'socketFile'):
-        try: os.unlink(cpg.getConfig('server', 'socketFile')) # So we can reuse the socket
+    if cpg.config.get('server', 'socketFile'):
+        try: os.unlink(cpg.config.get('server', 'socketFile')) # So we can reuse the socket
         except: pass
-        server_address = cpg.getConfig('server', 'socketFile')
-    if cpg.getConfig('server', 'threadPool') > 1:
-        myCherryHTTPServer = ServerClass(server_address, cpg.getConfig('server', 'threadPool'), HandlerClass)
+        server_address = cpg.config.get('server', 'socketFile')
+    if cpg.config.get('server', 'threadPool') > 1:
+        myCherryHTTPServer = ServerClass(server_address, cpg.config.get('server', 'threadPool'), HandlerClass)
     else:
         myCherryHTTPServer = ServerClass(server_address, HandlerClass)
     cpg._server = myCherryHTTPServer
-    if cpg.getConfig('server', 'socketFile'):
+    if cpg.config.get('server', 'socketFile'):
         try: os.chmod(socketFile, 0777) # So everyone can access the socket
         except: pass
     global _cpLogMessage
     _cpLogMessage = _cputil.getSpecialFunction('_cpLogMessage')
 
     servingWhat = "HTTP"
-    if cpg.getConfig('server', 'socketPort'): 
+    if cpg.config.get('server', 'socketPort'): 
         onWhat = ("socket: ('%s', %s)" % 
-                 (cpg.getConfig('server', 'socketHost'), cpg.getConfig('server', 'socketPort')))
-    else: onWhat = "socket file: %s" % cpg.getConfig('server', 'socketFile')
+                 (cpg.config.get('server', 'socketHost'), cpg.config.get('server', 'socketPort')))
+    else: onWhat = "socket file: %s" % cpg.config.get('server', 'socketFile')
     _cpLogMessage("Serving %s on %s" % (servingWhat, onWhat), 'HTTP')
 
     try:
 
     def address_string(self):
         """ Try to do a reverse DNS based on [server]reverseDNS in the config file """
-        if cpg.getConfig('server', 'reverseDNS'):
+        if cpg.config.get('server', 'reverseDNS'):
             return BaseHTTPServer.BaseHTTPRequestHandler.address_string(self)
         else:
             return self.client_address[0]
     year, month, day, hh, mm, ss, wd, y, z = time.gmtime(now)
     date = "%s, %02d %3s %4d %02d:%02d:%02d GMT" % (weekdayname[wd], day, monthname[month], year, hh, mm, ss)
     cpg.response.headerMap = {
-        "protocolVersion": cpg.getConfig('server', 'protocolVersion'),
+        "protocolVersion": cpg.config.get('server', 'protocolVersion'),
         "Status": "200 OK",
         "Content-Type": "text/html",
         "Server": "CherryPy/" + cpg.__version__,
             _cputil.getSpecialFunction('_cpOnError')()
 
             # Still save session data
-            if cpg.getConfig('session', 'storageType') and not cpg.request.isStatic:
-                sessionId = cpg.response.simpleCookie[cpg.getConfig('session', 'cookieName')].value
-                expirationTime = time.time() + cpg.getConfig('session', 'timeout') * 60
+            if cpg.config.get('session', 'storageType') and not cpg.request.isStatic:
+                sessionId = cpg.response.simpleCookie[cpg.config.get('session', 'cookieName')].value
+                expirationTime = time.time() + cpg.config.get('session', 'timeout') * 60
                 _cputil.getSpecialFunction('_cpSaveSessionData')(sessionId, cpg.request.sessionMap, expirationTime)
 
             wfile.write('%s %s\r\n' % (cpg.response.headerMap['protocolVersion'], cpg.response.headerMap['Status']))
             bodyFile = StringIO.StringIO()
             traceback.print_exc(file = bodyFile)
             body = bodyFile.getvalue()
-            wfile.write('%s 200 OK\r\n' % cpg.getConfig('server', 'protocolVersion'))
+            wfile.write('%s 200 OK\r\n' % cpg.config.get('server', 'protocolVersion'))
             wfile.write('Content-Type: text/plain\r\n')
             wfile.write('Content-Length: %s\r\n' % len(body))
             wfile.write('\r\n')
         cpg.response.headerMap['Content-Length'] = len(cpg.response.body[0])
 
     # Save session data
-    if cpg.getConfig('session', 'storageType') and not cpg.request.isStatic:
-        sessionId = cpg.response.simpleCookie[cpg.getConfig('session', 'cookieName')].value
-        expirationTime = time.time() + cpg.getConfig('session', 'timeout') * 60
+    if cpg.config.get('session', 'storageType') and not cpg.request.isStatic:
+        sessionId = cpg.response.simpleCookie[cpg.config.get('session', 'cookieName')].value
+        expirationTime = time.time() + cpg.config.get('session', 'timeout') * 60
         _cputil.getSpecialFunction('_cpSaveSessionData')(sessionId, cpg.request.sessionMap, expirationTime)
 
     wfile.write('%s %s\r\n' % (cpg.response.headerMap['protocolVersion'], cpg.response.headerMap['Status']))
 def handleRequest(wfile):
     # Clean up expired sessions if needed:
     now = time.time()
-    if (cpg.getConfig('session', 'storageType') and 
-        cpg.getConfig('session', 'cleanUpDelay') and 
-        (cpg._lastSessionCleanUpTime + cpg.getConfig('session', 'cleanUpDelay') * 60) <= now):
+    if (cpg.config.get('session', 'storageType') and 
+        cpg.config.get('session', 'cleanUpDelay') and 
+        (cpg._lastSessionCleanUpTime + cpg.config.get('session', 'cleanUpDelay') * 60) <= now):
         cpg._lastSessionCleanUpTime = now
         _cputil.getSpecialFunction('_cpCleanUpOldSessions')()
 
     path = urllib.unquote(path) # Replace quoted chars (eg %20) from url
 
     # Handle static directories
-    for urlDir, fsDir in cpg.getConfig('staticContent').items():
+    for urlDir, fsDir in cpg.config.get('staticContent').items():
         if path == urlDir or path[:len(urlDir)+1]==urlDir+'/':
 
             cpg.request.isStatic = 1
                 if cpg.request.headerMap['If-Modified-Since'] == strModifTime:
                     cpg.response.headerMap = {
                         'Status': 304, 
-                        'protocolVersion': cpg.getConfig('server', 'protocolVersion'),
+                        'protocolVersion': cpg.config.get('server', 'protocolVersion'),
                         'Date': cpg.response.headerMap['Date']}
                     cpg.response.body = []
                     sendResponse(wfile)
             return
 
     # Get session data
-    if cpg.getConfig('session', 'storageType') and not cpg.request.isStatic:
+    if cpg.config.get('session', 'storageType') and not cpg.request.isStatic:
         now = time.time()
         # First, get sessionId from cookie
-        try: sessionId = cpg.request.simpleCookie[cpg.getConfig('session', 'cookieName')].value
+        try: sessionId = cpg.request.simpleCookie[cpg.config.get('session', 'cookieName')].value
         except: sessionId=None
         if sessionId:
             # Load session data from wherever it was stored
             sessionId = generateSessionId()
             cpg.request.sessionMap['_sessionId'] = sessionId
 
-        cpg.response.simpleCookie[cpg.getConfig('session', 'cookieName')] = sessionId
-        cpg.response.simpleCookie[cpg.getConfig('session', 'cookieName')]['path'] = '/'
-        cpg.response.simpleCookie[cpg.getConfig('session', 'cookieName')]['version'] = 1
+        cpg.response.simpleCookie[cpg.config.get('session', 'cookieName')] = sessionId
+        cpg.response.simpleCookie[cpg.config.get('session', 'cookieName')]['path'] = '/'
+        cpg.response.simpleCookie[cpg.config.get('session', 'cookieName')]['version'] = 1
 
     try:
         func, objectPathList, virtualPathList = mapPathToObject()
 """
 
 import cpg
-import _cpconfig
 
 # binds the config to internal names. this is required to allow unit
 # testing; we simply put test values here instead of the defaults.
     # set default test values
     import StringIO
     testConfigFile = StringIO.StringIO(testConfigText)
-    configMap = _cpconfig.loadConfigFile(testConfigFile)
+    configMap = {}
     defaultConfigMap = testDefaultConfigMap
     cpgTree = testCpgTree
     reservedAttrNames = ['configMap','defaultConfigMap']
     func.exposed = True
     return func
 
-# Default config options
-defaultConfigMap = {
-        'server': {
-            'protocolVersion': 'HTTP/1.0',
-            'logToScreen': True,
-            'logFile': '',
-            'socketHost': '',
-            'socketPort': 8080,
-            'socketFile': '',
-            'reverseDNS': False,
-            'socketQueueSize': 5,
-            'protocolVersion': 'HTTP/1.0',
-            'threadPool': 0,
-            'environment': 'dev'},
-        'session': {
-            'storageType': 'ram',
-            'timeout': 60,
-            'cleanUpDelay': 60,
-            'cookieName': 'CherryPySession',
-            'storageFileDir': '',
-        },
-        'staticContent': {}
-    }
 
-configMap = {}
 
-import _cpmagicattr
+
 import sys,os,os.path
 sys.path.insert(0,os.path.normpath(os.path.join(os.getcwd(),'../../')))
 """
-    f.write(includePathsToSysPath+code.replace('cpg.config.loadConfigFile', beforeStart + 'cpg.config.loadConfigFile'))
+    f.write(includePathsToSysPath+code.replace('cpg.config.update', beforeStart + 'cpg.config.update'))
     f.close()
 
 def checkPageResult(testName, infoMap, code, testList, failedList, extraConfig = '', extraRequestHeader = []):

test/testFilter1.py

         yield europoundUnicode
     index.exposed = True
 cpg.root = Root()
-cpg.config.loadConfigFile('testsite.cfg')
+cpg.config.update(file = 'testsite.cfg')
 cpg.server.start()
 """
 config = ""

test/testObjectMapping.py

 cpg.root.dir1.dir2 = Dir2()
 cpg.root.dir1.dir2.dir3 = Dir3()
 cpg.root.dir1.dir2.dir3.dir4 = Dir4()
-cpg.config.loadConfigFile('testsite.cfg')
+cpg.config.update(file = 'testsite.cfg')
 cpg.server.start()
 """
 

test/testStaticContent.py

 from cherrypy import cpg
 class Root: pass
 cpg.root = Root()
-cpg.config.loadConfigFile('testsite.cfg')
+cpg.config.update(file = 'testsite.cfg')
 cpg.server.start()
 """
 

test/testVirtualHostFilter.py

 cpg.root = Root()
 cpg.root.site1 = Site1()
 cpg.root.site2 = Site2()
-cpg.config.loadConfigFile('testsite.cfg')
+cpg.config.update(file = 'testsite.cfg')
 cpg.server.start()
 """
 

tutorial/01_helloworld.py

 cpg.root = HelloWorld()
 
 # Start the CherryPy server using the configuration file tutorial.conf.
-cpg.config.loadConfigFile('tutorial.conf')
+cpg.config.update(file = 'tutorial.conf')
 cpg.server.start()
 

tutorial/02_expose_methods.py

     showMessage.exposed = True
 
 cpg.root = HelloWorld()
-cpg.config.loadConfigFile('tutorial.conf')
+cpg.config.update(file = 'tutorial.conf')
 cpg.server.start()

tutorial/03_get_and_post.py

 
 
 cpg.root = WelcomePage()
-cpg.config.loadConfigFile('tutorial.conf')
+cpg.config.update(file = 'tutorial.conf')
 cpg.server.start()

tutorial/04_complex_site.py

 # no reason why you shouldn't let your root object take care of
 # creating all contained request handler objects.
 
-cpg.config.loadConfigFile('tutorial.conf')
+cpg.config.update(file = 'tutorial.conf')
 cpg.server.start()

tutorial/05_derived_objects.py

 
 cpg.root = HomePage()
 
-cpg.config.loadConfigFile('tutorial.conf')
+cpg.config.update(file = 'tutorial.conf')
 cpg.server.start()

tutorial/06_aspects.py

 
 cpg.root = HomePage()
 
-cpg.config.loadConfigFile('tutorial.conf')
+cpg.config.update(file = 'tutorial.conf')
 cpg.server.start()

tutorial/07_default_method.py

 
 cpg.root = UsersPage()
 
-cpg.config.loadConfigFile('tutorial.conf')
+cpg.config.update(file = 'tutorial.conf')
 cpg.server.start()

tutorial/08_sessions.py

 
 cpg.root = HitCounter()
 
-cpg.config.loadConfigFile('tutorial.conf')
+cpg.config.update(file = 'tutorial.conf')
 cpg.server.start()

tutorial/09_generators_and_yield.py

     index.exposed = True
 
 cpg.root = GeneratorDemo()
-cpg.config.loadConfigFile('tutorial.conf')
+cpg.config.update(file = 'tutorial.conf')
 cpg.server.start()