"""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.29 2001/09/04 20:52:17 gward Exp $"


# Note that the default values here are geared towards a production
# environment, preferring security and performance over verbosity and
# debug-ability.  If you just want to get a Quixote application
# up-and-running in a production environment, these settings are mostly
# right; all you really need to customize are URL_PREFIX, ERROR_EMAIL,
# and ERROR_LOG.  If you need to test/debug/develop a Quixote
# application, though, you'll probably want to also change DEBUG_LOG,
# DISPLAY_EXCEPTIONS, SECURE_ERRORS, and maybe RUN_ONCE.  Again, you
# shouldn't edit this file unless you don't care what happens in the
# future (in particular, an upgrade to Quixote would clobber your
# edits).


# 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 are handled by the driver script for this Quixote application.
URL_PREFIX = '/q'

# E-mail address to send application 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 = 'webmaster@example.com'

# Filename for writing the Quixote access log; None for no access log.
ACCESS_LOG = None
#ACCESS_LOG = "/www/log/quixote-access.log"

# Filename for logging debugging output; None for no debug log file.
# (Anything that application code prints to stdout is debug output.)
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

# Automatically 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

# Compress large pages using gzip if the client accepts that encoding.
COMPRESS_PAGES = 0


# 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 = "QX_session"
COOKIE_PATH = "/"


# Mail-related variables
# ======================
# These are only used by the quixote.sendmail module, which is
# provided for use by Quixote applications that need to send
# e-mail.  This is a common task for web apps, but by no means
# universal.
#
# E-mail addresses can be specified either as a lone string
# containing a bare e-mail address ("addr-spec" in the RFC 822
# grammar), or as an (address, real_name) tuple.

# MAIL_FROM is used as the default for the "From" header and the SMTP
# sender for all outgoing e-mail.  If you don't set it, your application
# will crash the first time it tries to send e-mail without an explicit
# "From" address.
MAIL_FROM = None     # eg. "webmaster@example.com"
                     # or  ("webmaster@example.com", "Example Webmaster")

# E-mail is sent by connecting to an SMTP server on MAIL_SERVER.  This
# server must be configured to relay outgoing e-mail from the current
# host (ie., the host where your Quixote application runs, most likely
# your web server) to anywhere on the Internet.  If you don't know what
# this means, talk to your system administrator.
MAIL_SERVER = "localhost"

# If MAIL_DEBUG_ADDR is set, then all e-mail will actually be sent to
# this address rather than the intended recipients.  This should be a
# single, bare e-mail address.
MAIL_DEBUG_ADDR = None   # eg. "developers@example.com"


# -- 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 = [
        'url_prefix',
        'error_email',
        'access_log', 
        'debug_log',
        'display_exceptions',
        'secure_errors',
        'error_log',
        'error_handler',
        'run_once',
        'fix_trailing_slash',
        'compress_pages',
        'cookie_domain',
        'cookie_name',
        'cookie_path',
        'mail_from',
        'mail_server',
        'mail_debug_addr',
        ]


    def __init__ (self, read_defaults=1):
        for var in self.config_vars:
            setattr(self, var, None)
        if read_defaults:
            self.read_defaults()

    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_defaults (self):
        self.read_from_module("quixote.config")

# class Config

