# NOTE: do note write code that directly imports this module # (except when you are writing a custom configuration module.) # This is a recipe for trouble, since spyce allows the user # to specify the configuration module filename on the commandline. # Instead, use import spyce; spyce.getServer().config. import os, sys import spycePreload # Determine SPYCE_HOME dynamically. # (you can hardcode SPYCE_HOME if you really want to, but it shouldn't be necessary.) SPYCE_HOME = spycePreload.guessSpyceHome() # The spyce path determines which directories are searched for when # loading modules (with [[.import]]) and tag libraries (with [[.taglib]] # and the globaltags configuration later in this file. # # By default, the Spyce installation directory is always searched # first. Any directories in the SPYCE_PATH environment are also # searched. # # If you need to import from .py modules in nonstandard locations # (i.e., not in your python installation's library directory), # you will want to add their directories to sys.path as well, as # done here for the error module. (However, Spyce automagically # changes sys.path dynamically so you will always be able to import # modules in the same directory as your currently-processing .spy file.) # # path += ['/usr/spyce/inc/myapplication', '/var/myapp/lib'] path = [os.path.join(SPYCE_HOME, 'modules'), os.path.join(SPYCE_HOME, 'contrib', 'modules')] path.append(os.path.join(SPYCE_HOME, 'tags')) path.append(os.path.join(SPYCE_HOME, 'contrib', 'tags')) if os.environ.has_key('SPYCE_PATH'): path += os.environ['SPYCE_PATH'].split(os.pathsep) # provide originalsyspath so if someone wants to maintain a config file via # "from spyceconf import *" # he can remove the above modifications if desired. originalsyspath = list(sys.path) sys.path.extend(path) # The globaltags option specifies a group of tag libraries that will be autoloaded # as if [[.taglib name=libname from=file as=prefix]] were specified in every .spy # file. (There is no performance hit if the library is not used on a page; # the Spyce compiler optimizes it out.) # # The format is ('libname', 'file', 'prefix'). # For a 2.0-style tag library, the libname attribute is ignored. Passing None is fine. # # globaltags.append(('mytag', 'mytaglib.py', 'my')) # globaltags.append((None, 'taglib2.py', 'my2')) globaltags = [ ('core', 'core.py', 'spy'), ('form', 'form.py', 'f'), (None, 'render.spi', 'render'), ] # The default parent template is the one that is used by # if no src attribute is given, specified as an absolute url. defaultparent = "/parent.spi" # The errorhandler option sets the server-level error handler. These # errors include spyce.spyceNotFound, spyce.spyceForbidden, # spyce.spyceSyntaxError and spyce.pythonSyntaxError. (file-level # error handling is defined within Spyce scripts using the error module.) # # The server will call the error handler as errorhandler(request, response, error). # # Please look at the default function if you are considering writing your own # server error handler. import error errorhandler = error.serverHandler # The pageerror option sets the default page-level error handler. # "Page-level" means all runtime errors that occur during the # processing of a Spyce script (i.e. after the compilation phase has # completed successfully) # # The format of this option is one of: # ('string', 'MODULE', 'VARIABLE') # ('file', 'URL') # (This format is used since the error template must be transformed into # compiled spyce code, which can't be done before the configuration file # is completely loaded.) # # Please refer to the default template to see how to define your own # page-level error handlers. # # pageerrortemplate = ('file', '/error.spy') pageerrortemplate = ('string', 'error', 'defaultErrorTemplate') # The cache option affects the underlying cache mechanism that the # server uses to maintain compiled Spyce scripts. Currently, Spyce # supports two cache handlers: # # cache = 'memory' # OR # cache = 'file' # cachedir = '/tmp' # REQUIRED: directory in which to store compiled files # # Why store the cache in the filesystem instead of memory? The main # reason is if you are running under CGI or mod_python. Under # mod_python, Apache will kick off a number of separate spyce # processes; each would have its own memory cache; using the # filesystem avoids wasteful duplication. (Pointing the cachedir to a # ramdisk makes it almost as fast as a memory cache.) Under CGI of # course, the python process isn't persistent so file caching is the # only option to avoid expensive recompilation with each request. # # If you are running multiple Spyce instances on the same machine, # they cannot share the same cachedir. Give each a different cachedir, # or use the in-memory cache type. cache = 'memory' # The check_mtime option affects the caching of compiled Spyce code. # When True, Spyce will check file timestamps with each request and # recompile if they have been modified. Setting this to False can # speed up a "production server" but you will have to restart the # server and (if using a file cache) clear out the cachedir # to have changes made in the spyce code take effect. check_mtime = True # The debug option turns on a LOT of logging to stderr. debug = False # The globals section defines server-wide constants. The hashtable is # accessible as "pool" within any Spyce file (with the pool # method loaded), or as self._api.getServerGlobals() within any Spyce # module. # # globals = {'name': "My Website", 'four': 2+2} globals = {} # You may wish to pre-load various Python modules during engine initialization. # Once imported, they will be in the python module cache. # # (You may of course use normal imports at any time in this configuration script; # however, imports specified here are run after the Spyce server is # completely initialized, making it safe to access the server internals via # import spyce; spyce.getServer()...) # # imports = ['myModule', 'myModule2'] imports = [] # The root option defines the path from which Spyce requests are processed. # I.e., when a request for http://yourserver/path/foo.spy arrives, # Spyce looks for foo.spy in /path/. # # root = '/var/www/html' root = os.path.join(SPYCE_HOME, 'www') # feel free to comment this next line out if you don't have python modules (.py) in your web root sys.path.append(root) # some parts of spyce may need to create temporary files; usually the default is fine. # BUT if you do override this, be sure to also override other parts of the config # that reference it. (currently just session_store) import tempfile tmp = tempfile.gettempdir() # active tag to render form validation errors validation_render = 'render:validation' ##### # database connection ##### from sqlalchemy.ext.sqlsoup import SqlSoup # Examples: # db = SqlSoup('postgres://user:pass@localhost/dbname') # db = SqlSoup('sqlite:///my.db') # db = SqlSoup('mysql://user:pass@localhost/dbname') # # SqlSoup takes the same URLs as an SqlAlchemy Engine. See # http://www.sqlalchemy.org/docs/dbengine.myt#dbengine_establishing # for more examples. try: db = SqlSoup('sqlite:///www/demos/to-do/todo.db') except: db = None ##### # session options -- see docs/mod_session.html for details ##### import session session_store = session.DbmStore(tmp) # session_store = session.MemoryStore() session_path = '/' session_expire = 24 * 60 * 60 # seconds ##### # login options ##### # The spyce login system uses the session storage # defined above; a key called _spy_login will be added to each session. # validators must be a function that takes login and password as # arguments, and returns a pickle-able object (usually int or string) # representing the ID of the logged in user, or None if login fails. # # You'll need to supply your own to hook into your database or other # validation system; see the pyweboff config.py for an example of doing # this. def nevervalidator(login, password): return None def testvalidator(login, password): if login == 'spyce' and password == 'spyce': return 2 return None login_defaultvalidator = testvalidator # How to store login tokens. FileStorage comes with Spyce, # but it's easy to create your own Storage class if you want to put them # in your database, for instance. from _coreutil import FileStorage # It's not a good idea to put login-tokens off of www/ in production! # It's just done this way here to keep the spyce source tree relatively clean. login_storage = FileStorage(os.path.join(SPYCE_HOME, 'www', 'login-tokens')) # tags to render login form; must be visible in the globaltags search space. # These come from tags/render.spi; to make your own, just create a tag # that takes the same parameters and add the library to the globaltags list above. login_render = 'render:login' loginrequired_render = 'render:login_required' ###### # webserver options -- does not affect mod_python or *CGI configurations ###### # indexFiles specifies a list of files to look for # in a directory if directory itself is requested. # The first matching file will be selected. # If empty, a directory listing will be served instead. # # indexFiles = ['index.spy', 'index.html', 'index.txt'] indexFiles = ['index.spy', 'index.html'] # The Spyce webserver uses a threaded concurrency model. (Historically, # it also offered "no concurrency" and forking. If for some strange # reason you really want no concurrency, set minthreads=maxthreads=1. # Forking was removed entirely because it performed over 10x slower # than threading on Linux and Windows.) # # Do note that because of the Python GIL (global interpeter lock), # only one CPU of a multi-CPU machine can execute Python code at a time. # If this is your situation, mod_python may be a better option for you. minthreads = 5 maxthreads = 10 # number of pending requests to accept maxqueuesize = 50 # Restart the webserver if a python module changes. # Spyce does this by running the "real" server in a subprocess; when that # server detects changed modules, it exits and Spyce starts another one. # # Spyce will check for changes every second, or when a request # is made, whichever comes first. # # It's highly recommended to turn this off for "production" servers, # since checking each module for each request is a performance hit. check_modules_and_restart = True # The ipaddr option defines which IP addresses the server will listen on. # empty string for all. ipaddr = '' # The port option defines which TCP port the server will listen on. port = 8000 # Port that provides an interactive Python console interface to # the webserver's guts. Currently no password protection is offered; # don't expose this to the outside world! adminport = None # The mime option is a list of filenames. The files should # be definitions of mime-types for common file extensions in the # standard Apache format. # # mime: ['/etc/mime.types'] mime = [os.path.join(SPYCE_HOME, 'spyce.mime')] # The www_handlers option defines the hander used for files of # arbitrary extensions. (The None key specifies the default.) # The currently supported handlers are: # spyce - process the file at the requested path as a spyce script # directory - display directory listing # dump - transfer the file at the requested path verbatim, # providing an appropriate "Content-type" header, if it is known. # (It's difficult to use the actual instance methods here since we # don't have a handle to the WWW server object. So, we use strings # and let spyceWWW eval them later.) www_handlers = { 'spy': 'spyce', '/': 'directory', None: 'dump' } ###### # (F)CGI options ###### # Forbid direct requests to the cgi script and discard command line arguments. # # Reason: http://www.cert.org/advisories/CA-1996-11.html # # You may need to disable this for # 1) non-Apache servers that do not set the REDIRECT_STATUS environment # variable. # 2) when using the alternative #! variant of CGI configuration cgi_allow_only_redirect = False ###### # standard module customization ###### # (request module) # param filters and file filters are lists of functions that are called # for all GET and POST parameters or files, respectively. # Each callable should expect two arguments: a reference to the # request object/spyce module, and the dictionary being filtered. # (Thus, each callable in param_filters will be called twice; once for the # GET dict and once for POST. Each callable in file_filters will only be called once.) param_filters = [] file_filters = []