On Thursday 06 December 2001 15:40, Geoffrey Talvola wrote: > At 03:34 PM 12/6/01 -0800, Tavis Rudd wrote: > >The keyword 'class' might be a bit misleading as we're not > > promissing 1-to-1 mappings to actual classes, but that's no big > > deal either. In fact, we can use anything that supports > > __getatrr__ and __setattr__ for the settings containers: modules, > > classes, objects, etc. This is much cleaner than dictionaries! > > I agree, I definitely prefer regular Python assignments over > dictionaries. But it would be nice to allow both, if only to ease > the transition.
I've attached a copy of the old .webkit_config_annotated file translated to the proposed format. It seems to work with all versions of Python, not just 2.1 and up. This file contains all the settings and is more complicated than the average user will need so I've also attached an example of what typical config might look like. The SettingsContainer baseclass is used to make sure that settings that are in fact meant to be classes aren't handled as SettingsContainers. In practice a shorter name might be better. Finally, I've attached some simple functions that can be used to get settings out of the SettingsContainers recursively and turn them into dictionaries. > I'm not sure I agree that it should search for the config file at > all. Explicit is better than implicit, and in this case I think > it's better to know exactly where your config settings are coming > from, by specifying it right on the command line. You can always > use a bash or .bat wrapper to avoid having to retype it every time. Hmm, I agree, although it should be able to detect a webware_config module or package sitting in the dir that the script is called from. Ok, now back to that PSP stuff ;) Tavis
from Webware.Utils.SettingsManager import SettingsContainer True = 1 False = 0 ################################################## ## WEBKIT SETTINGS # base classes to inherit settings from class _ErrorHandling(SettingsContainer): """These settings are inherited by the AppServer and all the Applications below.""" printErrorsToConsole = True userErrorMsg = "The site is having technical difficulties with this page. " \ "The problem has been logged and will be fixed as soon as " \ "possible. Sorry!" logErrors = False errorLogFilename = 'Errors.csv' saveErrorMsgs = False errorMsgsDir = 'ErrorMsgs' HTTP404ErrorMsg = """Content-type: text/html\n\n <html> <body text="black" bgcolor="white"> <h1>404 Error</h1> <p> <h2>Page Not Available On This Server</h2> <p> The page you requested, <b>%s</b>, was not found on this server. <hr> Webware Application Server </body></html> """ emailErrors = False errorEmailServer = 'mail.-.com' errorEmailTo = '[EMAIL PROTECTED]' errorEmailFrom = '[EMAIL PROTECTED]' errorEmailSubject = 'A Webware Error Occurred' errorEmailExtraHeaders = {} class _ApplicationDefaults(_ErrorHandling): """Default settings that are inherited by all the applications running in the AppServer. """ servletRootPath = '' # There is no default for this one. # the 'python:' prefix means 'parse as a Python literal' directoryFiles = ['index','Main', 'default'] extensionsToIgnore = ['.pyc','.pyo','.py~', '.bak', '.tmpl', '.py_bak'] useCascadingExtensions = True # When dropping the extensions from filenames in requests the existing Webware # will raise an exception if there are multiple files with different extensions # for the requested basename. This version allows you to specify a list of # extensions to cascade through and use the first one found. If you list .html # before .py in your list of extensions and a request can map to 'file.html' or # 'file.py', 'file.html' will be returned rather than raising an exception. extensionCascadeOrder = [ '.html', '.py','.psp', '.tmpl'] # If you specify a list of extensions, only files with those extensions will be served. extensionsToServeFilter = None cacheStaticFiles = True # should static files be cached in memory updateStaticFiles = True # should static files be monitored for file updates usePrivateSessions = True # use separate SessIDToken & session pool for each Application sessionIdToken = '_WEBWARE_SID_' # the default when 'usePrivateSessions' is False sessionTimeout = 60 #min sessionStore = 'Dynamic' # File, or Memory class WebKit(SettingsContainer): """These are the settings All settings at the top-level are used by the 'MultiPortServer'.""" workingDir = '.' recordPID = True # Record the Process ID? PIDFile = 'webware.pid' # Path is relative to 'workingDir' above recordRunSettings = True # Record extended info. on the current process runSettingsFile = 'webware_run_settings.txt' # related to the previous setting startupNotice = '' enableCOM = False # This provides the same functionality as ComKit. class Services(SettingsContainer): """Each service is bound to separate port. """ class MonitorService(SettingsContainer): """Monitors the AppServer from a separate process and restarts it if it fails.""" on = False # should it be run? - overridden by commandline -m flag checkInterval = 10 # secs autoRestartTimeout = 0 # min - this might be buggy delayBeforeRestart = 5 # secs delayAfterRestart = 4 # secs logOnSuccess = False # should successful monitor checks be logged class AdminServer(SettingsContainer): """An adminstration service that runs alongside the AppServer in the main process. Currently, it sole function is to provide status updates to the MonitorService. It is implemented as a subclass of the AppServer class so it has great potential for extended admin facilities in the future.""" hostName = 'localhost' port = 8085 allowRemoteShutdown = False class HTTPServer(_ErrorHandling): """The builtin HTTPServer """ serverString = 'WebKit HTTP Server' hostName = 'localhost' port = 8087 threads = 10 class AppServer(_ErrorHandling): """The main AppServer. """ hostName = 'localhost' port = 8086 threads = 10 # How many threads in pool that processed requests usePoll = False # Use poll() system call for dispatching instead of select() eventCheckInterval = 100 # sys.setEventCheckInterval() pollTimeout = 2 # How long to block for during each poll() or select() call listenQueueLimit = 1024 # Max number of connections queued to be accepted connQueueLimit = 150 # Max number of connections accepted and queued for processing class Applications(SettingsContainer): class MyApp(_ApplicationDefaults): servletRootPath = '/home/tavis/Webware/MyApp' class MyOtherApp(_ApplicationDefaults): servletRootPath = '/home/tavis/Webware/MyOtherApp' DEFAULT_APP = MyApp # same as the default 'context'
from Webware.Utils.SettingsManager import SettingsContainer True = 1 False = 0 ################################################## ## WEBKIT SETTINGS class WebKit(SettingsContainer): class Services(SettingsContainer): class AppServer(SettingsContainer): hostName = 'localhost' port = 8086 class Applications(SettingsContainer): class MyApp(SettingsContainer): servletRootPath = '/home/tavis/Webware/MyApp' class MyOtherApp(SettingsContainer): servletRootPath = '/home/tavis/Webware/MyOtherApp' DEFAULT_APP = MyApp # same as the default 'context'
from Webware.Utils.SettingsManager import SettingsContainer from types import ClassType, ModuleType, InstanceType def isContainer(thing): return type(thing) == ModuleType or ( type(thing) == ClassType and issubclass(thing, SettingsContainer) ) def getAllAttrs(container): attrs = container.__dict__.copy() for base in container.__bases__: for k, v in base.__dict__.items(): if not attrs.has_key(k): attrs[k] = v return attrs def extractSettings(container): S = {} if type(container) == ModuleType: attrs = vars(container) else: attrs = getAllAttrs(container) for k, v in attrs.items(): if k.startswith('__'): continue if isContainer(v): S[k] = extractSettings(v) else: S[k] = v return S