"""quixote.config

Quixote configuration information.  This module provides both the
default configuration values, and some code that Quixote uses for
dealing with configuration info.  You should not edit the configuration
values in this file, since your edits will be lost if you upgrade to a
newer Quixote version in the future.  However, this is the canonical
source of information about Quixote configuration variables, and editing
the defaults here is harmless if you're just playing around and don't
care what happens in the future.
"""

__revision__ = "$Id: config.py,v 1.20 2001/01/10 22:23:07 nascheme Exp $"


# Note that the default values here generally prefer convenience and
# verbosity over security.  The assumption is that Quixote is more
# likely to be installed by web developers who want to play around with
# it than web administrators who just want it to go to work on day 1.
# Third-party Quixote applications should ship with more secure
# defaults, so that end-users can install Quixote and that application
# and not have to worry about security implications of the Quixote
# configuration.  If you want to be sure to run a tight ship, consider
# changing DISPLAY_EXCEPTIONS and SECURE_ERRORS.


# The root namespace is the Python namespace that will handle all
# requests to this Quixote application.  This is usually the name of a
# package or module, but could be a class instance or module object --
# any Python namespace!  (Allowing strings is a special case.)
ROOT_NAMESPACE = 'quixote.demo'

# Prefix of URLs that will be directed to Quixote.  This just tells
# Quixote where this application lives in your web site's URL-space;
# you'll also have to configure your web server so that requests to this
# URL go to the FCGI/CGI script for this Quixote application.
URL_PREFIX = '/q'

# E-mail address to send errors to; None to send no mail at all.  This
# should probably be the email address of your web administrator.
ERROR_EMAIL = None
#ERROR_EMAIL = 'akuchlin@mems-exchange.org'

# Filename for logging debugging output; None for no debug log file.
DEBUG_LOG = None
#DEBUG_LOG = "/www/log/quixote-debug.log"

# Function called when there is an unhandled exception.  The signature of
# the function needs to be:
#
#   error_handler(request, exception, error_message) -> string".
#
# If this is set to None Quixote's default error handler is used.
ERROR_HANDLER = None

# Filename for logging error messages; if None, error messages will be
# sent to standard error, so should wind up in the Web server's error
# log file.
ERROR_LOG = None

# If true, exceptions will also be returned to the browser; otherwise, a
# generic error display will be used.  It is convenient to enable this on
# development servers.  On publicly accessible servers it should be
# disabled for security reasons.
DISPLAY_EXCEPTIONS = 0

# If true, then any "resource not found" errors will result in a
# consistent, terse, mostly-useless message.  If false, then the
# exact cause of failure will be returned.
SECURE_ERRORS = 1

# If true, Quixote will service exactly one request at a time, and
# then exit.  This makes no difference when you're running as a
# straight CGI script, but it makes it easier to debug while running
# as a FastCGI script.
RUN_ONCE = 0

# Automaticly redirect paths referencing non-callable objects to a path
# with a trailing slash.  This is convienent for external users of the
# site and but should be disabled for development.  Internal links on the
# site should not require redirects.  They are costly, especially on high
# latency links like dialup lines.
FIX_TRAILING_SLASH = 1


# Session-related variables
# =========================

# Domain to specify in setting cookies to hold the session ID
COOKIE_DOMAIN = ".example.com"

# Name and path of the cookie that will hold the ID
COOKIE_NAME = "Qsession"
COOKIE_PATH = "/"


# -- End config variables ----------------------------------------------
# (no user serviceable parts after this point)

# Note that this module is designed to not export any names apart from
# the above config variables and the following Config class -- hence,
# all imports are done in local scopes.  This allows application config
# modules to safely say "from quixote.config import *".

class Config:
    """Holds all Quixote configuration variables -- see above for
    documentation of them.  The naming convention is simple:
    downcase the above variables to get the names of instance
    attributes of this class.
    """

    config_vars = [
        'root_namespace',
        'url_prefix',
        'error_email',
        'debug_log',
        'display_exceptions',
        'secure_errors',
        'error_log',
        'error_handler',
        'run_once',
        'fix_trailing_slash',
        'cookie_domain',
        'cookie_name',
        'cookie_path',
        ]


    def __init__ (self):
        for var in self.config_vars:
            setattr(self, var, None)

    def __setattr__ (self, attr, val):
        if not attr in self.config_vars:
            raise AttributeError, "no such configuration variable: %s" % `attr`
        self.__dict__[attr] = val


    def dump (self, file=None):
        import sys
        if file is None:
            file = sys.stdout
        file.write("<%s.%s instance at %x>:\n" %
                   (self.__class__.__module__,
                    self.__class__.__name__,
                    id(self)))
        for var in self.config_vars:
            file.write("  %s = %s\n" % (var, `getattr(self, var)`))


    def _set_from_dict (self, dict):
        import string, re
        ucstring_re = re.compile(r'^[A-Z_]+$')

        for (var, val) in dict.items():
            if ucstring_re.match(var):
                setattr(self, string.lower(var), val)

    def read_file (self, filename):
        """Read configuration from a file.  Any variables already
        defined in this Config instance, but not in the file, are  
        unchanged, so you can use this to build up a configuration  
        by accumulating data from several config files.
        """
        # The config file is Python code -- makes life easy.
        config_vars = {}
        try:
            execfile(filename, config_vars)
        except IOError, exc:
            if exc.filename is None:    # arg! execfile() loses filename
                exc.filename = filename
            raise exc

        self._set_from_dict(config_vars)

    def read_from_module (self, modname):
        """Read configuration info from a Python module (default
        is the module where the Config class is defined, ie.
        quixote.config).  Also accumulates config data, just like
        'read_file()'.
        """
        import sys
        __import__(modname)
        module = sys.modules[modname]
        self._set_from_dict(vars(module))

    def read_default (self):
        self.read_from_module("quixote.config")

# class Config


# The default config object.  This is initialized with all the default
# values from the config variables at the top of this file, ie. if
# ROOT_NAMESPACE is set to "quixote.demo", then config.root_namespace
# will also be "quixote.demo".  If application FCGI/CGI scripts need to
# override any of these defaults, they can do so by direct manipulation
# of this config object, or by reading a config file:
#   from quixote.config import config
#   config.read_file("myapp.conf")
# or, equivalently,
#   from quixote.init import read_config_file
#   read_config_file("myapp.conf")

config = Config()
config.read_default()
