[cig-commits] r6208 - in cs/pythia/trunk/opal: . conf contrib/auth/handlers core sites utils/translation views

leif at geodynamics.org leif at geodynamics.org
Thu Mar 8 19:41:46 PST 2007


Author: leif
Date: 2007-03-08 19:41:45 -0800 (Thu, 08 Mar 2007)
New Revision: 6208

Added:
   cs/pythia/trunk/opal/sites/
   cs/pythia/trunk/opal/sites/WebSite.py
   cs/pythia/trunk/opal/sites/__init__.py
Removed:
   cs/pythia/trunk/opal/conf/global_settings.py
Modified:
   cs/pythia/trunk/opal/conf/__init__.py
   cs/pythia/trunk/opal/contrib/auth/handlers/modpython.py
   cs/pythia/trunk/opal/core/management.py
   cs/pythia/trunk/opal/utils/translation/trans_real.py
   cs/pythia/trunk/opal/views/debug.py
Log:
Pyrized top-level settings.  Instead of editing 'settings.py' (and
setting the environment variable DJANGO_SETTINGS_MODULE to point to
it), Opal can now be configured using an "opal.cfg" file (just like
any Pyre app).

In our next episode: urls.urlpatterns and web app configuration
(models, views) redone The Leif Way.


Modified: cs/pythia/trunk/opal/conf/__init__.py
===================================================================
--- cs/pythia/trunk/opal/conf/__init__.py	2007-03-09 00:26:17 UTC (rev 6207)
+++ cs/pythia/trunk/opal/conf/__init__.py	2007-03-09 03:41:45 UTC (rev 6208)
@@ -1,139 +1,22 @@
-"""
-Settings and configuration for Django.
 
-Values will be read from the module specified by the DJANGO_SETTINGS_MODULE environment
-variable, and then from opal.conf.global_settings; see the global settings file for
-a list of all possible variables.
-"""
+from opal.sites import WebSite
 
-import os
-from opal.conf import global_settings
+def getWebSite():
+    import pyre.inventory
+    site = WebSite()
+    registry = site.createRegistry()
+    site.registry = registry
+    curator = pyre.inventory.curator(site.name)
+    curator.config(registry)
+    site.setCurator(curator)
+    curator.depositories += site.inventory.getDepositories()
+    site.initializeConfiguration()
+    site.applyConfiguration()
+    site.init()
+    return site
 
-ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
+settings = getWebSite()
 
-class LazySettings(object):
-    """
-    A lazy proxy for either global Django settings or a custom settings object.
-    The user can manually configure settings prior to using them. Otherwise,
-    Django uses the settings module pointed to by DJANGO_SETTINGS_MODULE.
-    """
-    def __init__(self):
-        # _target must be either None or something that supports attribute
-        # access (getattr, hasattr, etc).
-        self._target = None
-
-    def __getattr__(self, name):
-        if self._target is None:
-            self._import_settings()
-        if name == '__members__':
-            # Used to implement dir(obj), for example.
-            return self._target.get_all_members()
-        return getattr(self._target, name)
-
-    def __setattr__(self, name, value):
-        if name == '_target':
-            # Assign directly to self.__dict__, because otherwise we'd call
-            # __setattr__(), which would be an infinite loop.
-            self.__dict__['_target'] = value
-        else:
-            setattr(self._target, name, value)
-
-    def _import_settings(self):
-        """
-        Load the settings module pointed to by the environment variable. This
-        is used the first time we need any settings at all, if the user has not
-        previously configured the settings manually.
-        """
-        try:
-            settings_module = os.environ[ENVIRONMENT_VARIABLE]
-            if not settings_module: # If it's set but is an empty string.
-                raise KeyError
-        except KeyError:
-            raise EnvironmentError, "Environment variable %s is undefined." % ENVIRONMENT_VARIABLE
-
-        self._target = Settings(settings_module)
-
-    def configure(self, default_settings=global_settings, **options):
-        """
-        Called to manually configure the settings. The 'default_settings'
-        parameter sets where to retrieve any unspecified values from (its
-        argument must support attribute access (__getattr__)).
-        """
-        if self._target != None:
-            raise EnvironmentError, 'Settings already configured.'
-        holder = UserSettingsHolder(default_settings)
-        for name, value in options.items():
-            setattr(holder, name, value)
-        self._target = holder
-
-class Settings(object):
-    def __init__(self, settings_module):
-        # update this dict from global settings (but only for ALL_CAPS settings)
-        for setting in dir(global_settings):
-            if setting == setting.upper():
-                setattr(self, setting, getattr(global_settings, setting))
-
-        # store the settings module in case someone later cares
-        self.SETTINGS_MODULE = settings_module
-
-        try:
-            mod = __import__(self.SETTINGS_MODULE, '', '', [''])
-        except ImportError, e:
-            raise EnvironmentError, "Could not import settings '%s' (Is it on sys.path? Does it have syntax errors?): %s" % (self.SETTINGS_MODULE, e)
-
-        # Settings that should be converted into tuples if they're mistakenly entered
-        # as strings.
-        tuple_settings = ("INSTALLED_APPS", "TEMPLATE_DIRS")
-
-        for setting in dir(mod):
-            if setting == setting.upper():
-                setting_value = getattr(mod, setting)
-                if setting in tuple_settings and type(setting_value) == str:
-                    setting_value = (setting_value,) # In case the user forgot the comma.
-                setattr(self, setting, setting_value)
-
-        # Expand entries in INSTALLED_APPS like "opal.contrib.*" to a list
-        # of all those apps.
-        new_installed_apps = []
-        for app in self.INSTALLED_APPS:
-            if app.endswith('.*'):
-                appdir = os.path.dirname(__import__(app[:-2], '', '', ['']).__file__)
-                for d in os.listdir(appdir):
-                    if d.isalpha() and os.path.isdir(os.path.join(appdir, d)):
-                        new_installed_apps.append('%s.%s' % (app[:-2], d))
-            else:
-                new_installed_apps.append(app)
-        self.INSTALLED_APPS = new_installed_apps
-
-        # move the time zone info into os.environ
-        os.environ['TZ'] = self.TIME_ZONE
-
-    def get_all_members(self):
-        return dir(self)
-
-class UserSettingsHolder(object):
-    """
-    Holder for user configured settings.
-    """
-    # SETTINGS_MODULE doesn't make much sense in the manually configured
-    # (standalone) case.
-    SETTINGS_MODULE = None
-
-    def __init__(self, default_settings):
-        """
-        Requests for configuration variables not in this class are satisfied
-        from the module specified in default_settings (if possible).
-        """
-        self.default_settings = default_settings
-
-    def __getattr__(self, name):
-        return getattr(self.default_settings, name)
-
-    def get_all_members(self):
-        return dir(self) + dir(self.default_settings)
-
-settings = LazySettings()
-
 # This function replaces itself with opal.utils.translation.gettext() the
 # first time it's run. This is necessary because the import of
 # opal.utils.translation requires a working settings module, and loading it

Deleted: cs/pythia/trunk/opal/conf/global_settings.py
===================================================================
--- cs/pythia/trunk/opal/conf/global_settings.py	2007-03-09 00:26:17 UTC (rev 6207)
+++ cs/pythia/trunk/opal/conf/global_settings.py	2007-03-09 03:41:45 UTC (rev 6208)
@@ -1,297 +0,0 @@
-# Default Django settings. Override these with settings in the module
-# pointed-to by the DJANGO_SETTINGS_MODULE environment variable.
-
-# This is defined here as a do-nothing function because we can't import
-# opal.utils.translation -- that module depends on the settings.
-gettext_noop = lambda s: s
-
-####################
-# CORE             #
-####################
-
-DEBUG = False
-TEMPLATE_DEBUG = False
-
-# Whether to use the "Etag" header. This saves bandwidth but slows down performance.
-USE_ETAGS = False
-
-# People who get code error notifications.
-# In the format (('Full Name', 'email at domain.com'), ('Full Name', 'anotheremail at domain.com'))
-ADMINS = ()
-
-# Tuple of IP addresses, as strings, that:
-#   * See debug comments, when DEBUG is true
-#   * Receive x-headers
-INTERNAL_IPS = ()
-
-# Local time zone for this installation. All choices can be found here:
-# http://www.postgresql.org/docs/current/static/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE
-TIME_ZONE = 'America/Chicago'
-
-# Language code for this installation. All choices can be found here:
-# http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes
-# http://blogs.law.harvard.edu/tech/stories/storyReader$15
-LANGUAGE_CODE = 'en-us'
-
-# Languages we provide translations for, out of the box. The language name
-# should be the utf-8 encoded local name for the language.
-LANGUAGES = (
-    ('ar', gettext_noop('Arabic')),
-    ('bn', gettext_noop('Bengali')),
-    ('cs', gettext_noop('Czech')),
-    ('cy', gettext_noop('Welsh')),
-    ('da', gettext_noop('Danish')),
-    ('de', gettext_noop('German')),
-    ('el', gettext_noop('Greek')),
-    ('en', gettext_noop('English')),
-    ('es', gettext_noop('Spanish')),
-    ('es_AR', gettext_noop('Argentinean Spanish')),
-    ('fr', gettext_noop('French')),
-    ('gl', gettext_noop('Galician')),
-    ('hu', gettext_noop('Hungarian')),
-    ('he', gettext_noop('Hebrew')),
-    ('is', gettext_noop('Icelandic')),
-    ('it', gettext_noop('Italian')),
-    ('ja', gettext_noop('Japanese')),
-    ('nl', gettext_noop('Dutch')),
-    ('no', gettext_noop('Norwegian')),
-    ('pt-br', gettext_noop('Brazilian')),
-    ('ro', gettext_noop('Romanian')),
-    ('ru', gettext_noop('Russian')),
-    ('sk', gettext_noop('Slovak')),
-    ('sl', gettext_noop('Slovenian')),
-    ('sr', gettext_noop('Serbian')),
-    ('sv', gettext_noop('Swedish')),
-    ('ta', gettext_noop('Tamil')),
-    ('uk', gettext_noop('Ukrainian')),
-    ('zh-cn', gettext_noop('Simplified Chinese')),
-    ('zh-tw', gettext_noop('Traditional Chinese')),
-)
-
-# Languages using BiDi (right-to-left) layout
-LANGUAGES_BIDI = ("he", "ar")
-
-# If you set this to False, Django will make some optimizations so as not
-# to load the internationalization machinery.
-USE_I18N = True
-
-# Not-necessarily-technical managers of the site. They get broken link
-# notifications and other various e-mails.
-MANAGERS = ADMINS
-
-# Default content type and charset to use for all HttpResponse objects, if a
-# MIME type isn't manually specified. These are used to construct the
-# Content-Type header.
-DEFAULT_CONTENT_TYPE = 'text/html'
-DEFAULT_CHARSET = 'utf-8'
-
-# E-mail address that error messages come from.
-SERVER_EMAIL = 'root at localhost'
-
-# Whether to send broken-link e-mails.
-SEND_BROKEN_LINK_EMAILS = False
-
-# Database connection info.
-DATABASE_ENGINE = ''           # 'postgresql', 'mysql', 'sqlite3' or 'ado_mssql'.
-DATABASE_NAME = ''             # Or path to database file if using sqlite3.
-DATABASE_USER = ''             # Not used with sqlite3.
-DATABASE_PASSWORD = ''         # Not used with sqlite3.
-DATABASE_HOST = ''             # Set to empty string for localhost. Not used with sqlite3.
-DATABASE_PORT = ''             # Set to empty string for default. Not used with sqlite3.
-
-# Host for sending e-mail.
-EMAIL_HOST = 'localhost'
-
-# Port for sending e-mail.
-EMAIL_PORT = 25
-
-# Optional SMTP authentication information for EMAIL_HOST.
-EMAIL_HOST_USER = ''
-EMAIL_HOST_PASSWORD = ''
-
-# List of strings representing installed apps.
-INSTALLED_APPS = ()
-
-# List of locations of the template source files, in search order.
-TEMPLATE_DIRS = ()
-
-# List of callables that know how to import templates from various sources.
-# See the comments in django/core/template/loader.py for interface
-# documentation.
-TEMPLATE_LOADERS = (
-    'opal.template.loaders.filesystem.load_template_source',
-    'opal.template.loaders.app_directories.load_template_source',
-#     'opal.template.loaders.eggs.load_template_source',
-)
-
-# List of processors used by RequestContext to populate the context.
-# Each one should be a callable that takes the request object as its
-# only parameter and returns a dictionary to add to the context.
-TEMPLATE_CONTEXT_PROCESSORS = (
-    'opal.core.context_processors.auth',
-    'opal.core.context_processors.debug',
-    'opal.core.context_processors.i18n',
-#    'opal.core.context_processors.request',
-)
-
-# Output to use in template system for invalid (e.g. misspelled) variables.
-TEMPLATE_STRING_IF_INVALID = ''
-
-# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
-# trailing slash.
-# Examples: "http://foo.com/media/", "/media/".
-ADMIN_MEDIA_PREFIX = '/media/'
-
-# Default e-mail address to use for various automated correspondence from
-# the site managers.
-DEFAULT_FROM_EMAIL = 'webmaster at localhost'
-
-# Subject-line prefix for email messages send with opal.core.mail.mail_admins
-# or ...mail_managers.  Make sure to include the trailing space.
-EMAIL_SUBJECT_PREFIX = '[Django] '
-
-# Whether to append trailing slashes to URLs.
-APPEND_SLASH = True
-
-# Whether to prepend the "www." subdomain to URLs that don't have it.
-PREPEND_WWW = False
-
-# List of compiled regular expression objects representing User-Agent strings
-# that are not allowed to visit any page, systemwide. Use this for bad
-# robots/crawlers. Here are a few examples:
-#     import re
-#     DISALLOWED_USER_AGENTS = (
-#         re.compile(r'^NaverBot.*'),
-#         re.compile(r'^EmailSiphon.*'),
-#         re.compile(r'^SiteSucker.*'),
-#         re.compile(r'^sohu-search')
-#     )
-DISALLOWED_USER_AGENTS = ()
-
-ABSOLUTE_URL_OVERRIDES = {}
-
-# Tuple of strings representing allowed prefixes for the {% ssi %} tag.
-# Example: ('/home/html', '/var/www')
-ALLOWED_INCLUDE_ROOTS = ()
-
-# If this is a admin settings module, this should be a list of
-# settings modules (in the format 'foo.bar.baz') for which this admin
-# is an admin.
-ADMIN_FOR = ()
-
-# 404s that may be ignored.
-IGNORABLE_404_STARTS = ('/cgi-bin/', '/_vti_bin', '/_vti_inf')
-IGNORABLE_404_ENDS = ('mail.pl', 'mailform.pl', 'mail.cgi', 'mailform.cgi', 'favicon.ico', '.php')
-
-# A secret key for this particular Django installation. Used in secret-key
-# hashing algorithms. Set this in your settings, or Django will complain
-# loudly.
-SECRET_KEY = ''
-
-# Path to the "jing" executable -- needed to validate XMLFields
-JING_PATH = "/usr/bin/jing"
-
-# Absolute path to the directory that holds media.
-# Example: "/home/media/media.lawrence.com/"
-MEDIA_ROOT = ''
-
-# URL that handles the media served from MEDIA_ROOT.
-# Example: "http://media.lawrence.com"
-MEDIA_URL = ''
-
-# Default formatting for date objects. See all available format strings here:
-# http://www.djangoproject.com/documentation/templates/#now
-DATE_FORMAT = 'N j, Y'
-
-# Default formatting for datetime objects. See all available format strings here:
-# http://www.djangoproject.com/documentation/templates/#now
-DATETIME_FORMAT = 'N j, Y, P'
-
-# Default formatting for time objects. See all available format strings here:
-# http://www.djangoproject.com/documentation/templates/#now
-TIME_FORMAT = 'P'
-
-# Default formatting for date objects when only the year and month are relevant.
-# See all available format strings here:
-# http://www.djangoproject.com/documentation/templates/#now
-YEAR_MONTH_FORMAT = 'F Y'
-
-# Default formatting for date objects when only the month and day are relevant.
-# See all available format strings here:
-# http://www.djangoproject.com/documentation/templates/#now
-MONTH_DAY_FORMAT = 'F j'
-
-# Whether to enable Psyco, which optimizes Python code. Requires Psyco.
-# http://psyco.sourceforge.net/
-ENABLE_PSYCO = False
-
-# Do you want to manage transactions manually?
-# Hint: you really don't!
-TRANSACTIONS_MANAGED = False
-
-##############
-# MIDDLEWARE #
-##############
-
-# List of middleware classes to use.  Order is important; in the request phase,
-# this middleware classes will be applied in the order given, and in the
-# response phase the middleware will be applied in reverse order.
-MIDDLEWARE_CLASSES = (
-    'opal.contrib.sessions.middleware.SessionMiddleware',
-    'opal.contrib.auth.middleware.AuthenticationMiddleware',
-#     'opal.middleware.http.ConditionalGetMiddleware',
-#     'opal.middleware.gzip.GZipMiddleware',
-    'opal.middleware.common.CommonMiddleware',
-    'opal.middleware.doc.XViewMiddleware',
-)
-
-############
-# SESSIONS #
-############
-
-SESSION_COOKIE_NAME = 'sessionid'         # Cookie name. This can be whatever you want.
-SESSION_COOKIE_AGE = 60 * 60 * 24 * 7 * 2 # Age of cookie, in seconds (default: 2 weeks).
-SESSION_COOKIE_DOMAIN = None              # A string like ".lawrence.com", or None for standard domain cookie.
-SESSION_SAVE_EVERY_REQUEST = False        # Whether to save the session data on every request.
-SESSION_EXPIRE_AT_BROWSER_CLOSE = False   # Whether sessions expire when a user closes his browser.
-
-#########
-# CACHE #
-#########
-
-# The cache backend to use.  See the docstring in opal.core.cache for the
-# possible values.
-CACHE_BACKEND = 'simple://'
-CACHE_MIDDLEWARE_KEY_PREFIX = ''
-
-####################
-# COMMENTS         #
-####################
-
-COMMENTS_ALLOW_PROFANITIES = False
-
-# The group ID that designates which users are banned.
-# Set to None if you're not using it.
-COMMENTS_BANNED_USERS_GROUP = None
-
-# The group ID that designates which users can moderate comments.
-# Set to None if you're not using it.
-COMMENTS_MODERATORS_GROUP = None
-
-# The group ID that designates the users whose comments should be e-mailed to MANAGERS.
-# Set to None if you're not using it.
-COMMENTS_SKETCHY_USERS_GROUP = None
-
-# The system will e-mail MANAGERS the first COMMENTS_FIRST_FEW comments by each
-# user. Set this to 0 if you want to disable it.
-COMMENTS_FIRST_FEW = 0
-
-# A tuple of IP addresses that have been banned from participating in various
-# Django-powered features.
-BANNED_IPS = ()
-
-##################
-# AUTHENTICATION #
-##################
-
-AUTHENTICATION_BACKENDS = ('opal.contrib.auth.backends.ModelBackend',)

Modified: cs/pythia/trunk/opal/contrib/auth/handlers/modpython.py
===================================================================
--- cs/pythia/trunk/opal/contrib/auth/handlers/modpython.py	2007-03-09 00:26:17 UTC (rev 6207)
+++ cs/pythia/trunk/opal/contrib/auth/handlers/modpython.py	2007-03-09 03:41:45 UTC (rev 6208)
@@ -17,9 +17,6 @@
     permission_name = options.get('DjangoPermissionName', None)
     staff_only = _str_to_bool(options.get('DjangoRequireStaffStatus', "on"))
     superuser_only = _str_to_bool(options.get('DjangoRequireSuperuserStatus', "off"))
-    settings_module = options.get('DJANGO_SETTINGS_MODULE', None)
-    if settings_module:
-        os.environ['DJANGO_SETTINGS_MODULE'] = settings_module
 
     from opal.contrib.auth.models import User
 

Modified: cs/pythia/trunk/opal/core/management.py
===================================================================
--- cs/pythia/trunk/opal/core/management.py	2007-03-09 00:26:17 UTC (rev 6207)
+++ cs/pythia/trunk/opal/core/management.py	2007-03-09 03:41:45 UTC (rev 6208)
@@ -533,29 +533,6 @@
     "Converts a module namespace to a Python dictionary. Used by get_settings_diff."
     return dict([(k, repr(v)) for k, v in module.__dict__.items() if not omittable(k)])
 
-def diffsettings():
-    """
-    Displays differences between the current settings.py and Django's
-    default settings. Settings that don't appear in the defaults are
-    followed by "###".
-    """
-    # Inspired by Postfix's "postconf -n".
-    from opal.conf import settings, global_settings
-
-    user_settings = _module_to_dict(settings)
-    default_settings = _module_to_dict(global_settings)
-
-    output = []
-    keys = user_settings.keys()
-    keys.sort()
-    for key in keys:
-        if key not in default_settings:
-            output.append("%s = %s  ###" % (key, user_settings[key]))
-        elif user_settings[key] != default_settings[key]:
-            output.append("%s = %s" % (key, user_settings[key]))
-    print '\n'.join(output)
-diffsettings.args = ""
-
 def install(app):
     "Executes the equivalent of 'get_sql_all' in the current database."
     from opal.db import connection, transaction
@@ -1033,7 +1010,7 @@
         from opal.conf import settings
         print "Validating models..."
         validate()
-        print "\nDjango version %s, using settings %r" % (get_version(), settings.SETTINGS_MODULE)
+        print "\nOpal version %s" % get_version()
         print "Development server is running at http://%s:%s/" % (addr, port)
         print "Quit the server with %s." % quit_command
         try:
@@ -1139,7 +1116,6 @@
     'adminindex': get_admin_index,
     'createcachetable' : createcachetable,
     'dbshell': dbshell,
-    'diffsettings': diffsettings,
     'inspectdb': inspectdb,
     'install': install,
     'reset': reset,
@@ -1163,7 +1139,6 @@
     'adminindex',
     'createcachetable',
     'dbshell',
-    'diffsettings',
     'install',
     'reset',
     'sqlindexes',
@@ -1201,8 +1176,6 @@
 
     # Parse the command-line arguments. optparse handles the dirty work.
     parser = DjangoOptionParser(usage=get_usage(action_mapping), version=get_version())
-    parser.add_option('--settings',
-        help='Python path to settings module, e.g. "myproject.settings.main". If this isn\'t provided, the DJANGO_SETTINGS_MODULE environment variable will be used.')
     parser.add_option('--pythonpath',
         help='Lets you manually add a directory the Python path, e.g. "/home/djangoprojects/myproject".')
     parser.add_option('--plain', action='store_true', dest='plain',
@@ -1212,8 +1185,6 @@
     options, args = parser.parse_args(argv[1:])
 
     # Take care of options.
-    if options.settings:
-        os.environ['DJANGO_SETTINGS_MODULE'] = options.settings
     if options.pythonpath:
         sys.path.insert(0, options.pythonpath)
 
@@ -1235,7 +1206,7 @@
 
     if action == 'shell':
         action_mapping[action](options.plain is True)
-    elif action in ('syncdb', 'validate', 'diffsettings', 'dbshell'):
+    elif action in ('syncdb', 'validate', 'dbshell'):
         action_mapping[action]()
     elif action == 'inspectdb':
         try:
@@ -1295,9 +1266,6 @@
     project_module = __import__(project_name, '', '', [''])
     sys.path.pop()
 
-    # Set DJANGO_SETTINGS_MODULE appropriately.
-    os.environ['DJANGO_SETTINGS_MODULE'] = '%s.settings' % project_name
-
     action_mapping = DEFAULT_ACTION_MAPPING.copy()
 
     # Remove the "startproject" command from the action_mapping, because that's

Added: cs/pythia/trunk/opal/sites/WebSite.py
===================================================================
--- cs/pythia/trunk/opal/sites/WebSite.py	2007-03-09 00:26:17 UTC (rev 6207)
+++ cs/pythia/trunk/opal/sites/WebSite.py	2007-03-09 03:41:45 UTC (rev 6208)
@@ -0,0 +1,336 @@
+#!/usr/bin/env python
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+#                      California Institute of Technology
+#                        (C) 2007  All Rights Reserved
+#
+# {LicenseText}
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+
+
+from pyre.components import Component
+
+
+# This is defined here as a do-nothing function because we can't import
+# opal.utils.translation -- that module depends on the settings.
+gettext_noop = lambda s: s
+
+
+class WebSite(Component):
+
+
+    name = "opal"
+
+
+    import pyre.inventory as pyre
+
+
+    ####################
+    # CORE             #
+    ####################
+
+    DEBUG = pyre.bool("debug", default=False)
+    TEMPLATE_DEBUG = pyre.bool("template-debug", default=False)
+
+    USE_ETAGS = pyre.bool("use-etags", default=False)
+    USE_ETAGS.meta['tip'] = """Whether to use the "Etag" header. This saves bandwidth but slows down performance."""
+
+    ADMINS = pyre.list("admins")
+    ADMINS.meta['tip'] = """People who get code error notifications."""
+
+    INTERNAL_IPS = pyre.list("internal-ips")
+    INTERNAL_IPS.meta['tip'] = """IP addresses that see debug comments (when 'debug' is true) and receive x-headers"""
+
+    TIME_ZONE = pyre.str("time-zone", default="America/Chicago")
+    TIME_ZONE.meta['tip'] = """Local time zone for this installation."""
+
+    LANGUAGE_CODE = pyre.str("language-code", default="en-us")
+    LANGUAGE_CODE.meta['tip'] = """Language code for this installation."""
+
+    # Languages we provide translations for, out of the box. The language name
+    # should be the utf-8 encoded local name for the language.
+    LANGUAGES = (
+        ('ar', gettext_noop('Arabic')),
+        ('bn', gettext_noop('Bengali')),
+        ('cs', gettext_noop('Czech')),
+        ('cy', gettext_noop('Welsh')),
+        ('da', gettext_noop('Danish')),
+        ('de', gettext_noop('German')),
+        ('el', gettext_noop('Greek')),
+        ('en', gettext_noop('English')),
+        ('es', gettext_noop('Spanish')),
+        ('es_AR', gettext_noop('Argentinean Spanish')),
+        ('fr', gettext_noop('French')),
+        ('gl', gettext_noop('Galician')),
+        ('hu', gettext_noop('Hungarian')),
+        ('he', gettext_noop('Hebrew')),
+        ('is', gettext_noop('Icelandic')),
+        ('it', gettext_noop('Italian')),
+        ('ja', gettext_noop('Japanese')),
+        ('nl', gettext_noop('Dutch')),
+        ('no', gettext_noop('Norwegian')),
+        ('pt-br', gettext_noop('Brazilian')),
+        ('ro', gettext_noop('Romanian')),
+        ('ru', gettext_noop('Russian')),
+        ('sk', gettext_noop('Slovak')),
+        ('sl', gettext_noop('Slovenian')),
+        ('sr', gettext_noop('Serbian')),
+        ('sv', gettext_noop('Swedish')),
+        ('ta', gettext_noop('Tamil')),
+        ('uk', gettext_noop('Ukrainian')),
+        ('zh-cn', gettext_noop('Simplified Chinese')),
+        ('zh-tw', gettext_noop('Traditional Chinese')),
+    )
+
+    # Languages using BiDi (right-to-left) layout
+    LANGUAGES_BIDI = ("he", "ar")
+
+    USE_I18N = pyre.bool("use-I18N", default=True)
+    USE_I18N.meta['tip'] = """If you set this to False, Opal will make some optimizations so as not to load the internationalization machinery."""
+
+    MANAGERS = pyre.list("managers")
+    MANAGERS.meta['tip'] = """Not-necessarily-technical managers of the site. They get broken link notifications and other various e-mails."""
+
+    DEFAULT_CONTENT_TYPE = pyre.str("default-content-type", default="text/html")
+    DEFAULT_CONTENT_TYPE.meta['tip'] = """Default content type to use for all HttpResponse objects, if a MIME type isn't manually specified. Used to construct the Content-Type header."""
+    
+    DEFAULT_CHARSET = pyre.str("default-charset", default="utf-8")
+    DEFAULT_CHARSET.meta['tip'] = """Default charset to use for all HttpResponse objects, if a MIME type isn't manually specified. Used to construct the Content-Type header."""
+
+    SERVER_EMAIL = pyre.str("server-email", default="root at localhost")
+    SERVER_EMAIL.meta['tip'] = """E-mail address that error messages come from."""
+
+    SEND_BROKEN_LINK_EMAILS = pyre.bool("send-broken-link-emails", default=False)
+    SEND_BROKEN_LINK_EMAILS.meta['tip'] = """Whether to send broken-link e-mails."""
+
+    # Database connection info.
+    ### Perhaps this should be a facility.
+    DATABASE_ENGINE    = pyre.str("database-engine",
+                                  validator=pyre.choice(['postgresql', 'mysql', 'sqlite3', 'ado_mssql']))
+    DATABASE_NAME      = pyre.str("database-name")        # Or path to database file if using sqlite3.
+    DATABASE_USER      = pyre.str("database-user")        # Not used with sqlite3.
+    DATABASE_PASSWORD  = pyre.str("database-password")    # Not used with sqlite3.
+    DATABASE_HOST      = pyre.str("database-host")        # Set to empty string for localhost. Not used with sqlite3.
+    DATABASE_PORT      = pyre.str("database-port")        # Set to empty string for default. Not used with sqlite3.
+
+    EMAIL_HOST = pyre.str("email-host", default="localhost")
+    EMAIL_HOST.meta['tip'] = """Host for sending e-mail."""
+
+    EMAIL_PORT = pyre.int("email-port", default=25)
+    EMAIL_PORT.meta['tip'] = """Port for sending e-mail."""
+
+    EMAIL_HOST_USER = pyre.str("email-host-user")
+    EMAIL_HOST_USER.meta['tip'] = """Optional SMTP authentication information for 'email-host'."""
+    
+    EMAIL_HOST_PASSWORD = pyre.str("email-host-password")
+    EMAIL_HOST_PASSWORD.meta['tip'] = """Optional SMTP authentication information for 'email-host'."""
+
+    ### This should be done with egg metadata.
+    INSTALLED_APPS = pyre.list("installed-apps")
+    INSTALLED_APPS.meta['tip'] = """List of strings representing installed apps."""
+
+    TEMPLATE_DIRS = pyre.list("template-dirs")
+    TEMPLATE_DIRS.meta['tip'] = """List of locations of the template source files, in search order."""
+
+    ### This should be done with egg metadata.
+    TEMPLATE_LOADERS = pyre.list("template-loaders", default=[
+        'opal.template.loaders.filesystem.load_template_source',
+        'opal.template.loaders.app_directories.load_template_source',
+        #'opal.template.loaders.eggs.load_template_source',
+        ])
+    TEMPLATE_LOADERS.meta['tip'] = """List of callables that know how to import templates from various sources. See the comments in opal/core/template/loader.py for interface documentation."""
+
+    ### This should be done with egg metadata.
+    TEMPLATE_CONTEXT_PROCESSORS = pyre.list("template-context-processors", default=[
+        'opal.core.context_processors.auth',
+        'opal.core.context_processors.debug',
+        'opal.core.context_processors.i18n',
+        #'opal.core.context_processors.request',
+        ])
+    TEMPLATE_CONTEXT_PROCESSORS.meta['tip'] = """List of processors used by RequestContext to populate the context. Each one should be a callable that takes the request object as its only parameter and returns a dictionary to add to the context."""
+
+    TEMPLATE_STRING_IF_INVALID = pyre.str("template-string-if-invalid")
+    TEMPLATE_STRING_IF_INVALID.meta['tip'] = """Output to use in template system for invalid (e.g. misspelled) variables."""
+
+    ADMIN_MEDIA_PREFIX = pyre.str("admin-media-prefix", default="/media/")
+    ADMIN_MEDIA_PREFIX.meta['tip'] = """URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a trailing slash. Examples: "http://foo.com/media/", "/media/"."""
+
+    DEFAULT_FROM_EMAIL = pyre.str("default-from-email", default="webmaster at localhost")
+    DEFAULT_FROM_EMAIL.meta['tip'] = """Default e-mail address to use for various automated correspondence from the site managers."""
+
+    EMAIL_SUBJECT_PREFIX = pyre.str("email-subject-prefix", default="[Opal] ")
+    EMAIL_SUBJECT_PREFIX.meta['tip'] = """Subject-line prefix for email messages send with opal.core.mail.mail_admins or ...mail_managers.  Make sure to include the trailing space."""
+
+    ### I hate this one.  It should depend upon the object being accessed.
+    APPEND_SLASH = pyre.bool("append-slash", default=True)
+    APPEND_SLASH.meta['tip'] = """Whether to append trailing slashes to URLs."""
+
+    PREPEND_WWW = pyre.bool("prepend-www", default=False)
+    PREPEND_WWW.meta['tip'] = """Whether to prepend the "www." subdomain to URLs that don't have it."""
+
+    # List of compiled regular expression objects representing User-Agent strings
+    # that are not allowed to visit any page, systemwide. Use this for bad
+    # robots/crawlers. Here are a few examples:
+    #     import re
+    #     DISALLOWED_USER_AGENTS = (
+    #         re.compile(r'^NaverBot.*'),
+    #         re.compile(r'^EmailSiphon.*'),
+    #         re.compile(r'^SiteSucker.*'),
+    #         re.compile(r'^sohu-search')
+    #     )
+    DISALLOWED_USER_AGENTS = ()
+
+    ABSOLUTE_URL_OVERRIDES = {}
+
+    ALLOWED_INCLUDE_ROOTS = pyre.list("allowed-include-roots")
+    ALLOWED_INCLUDE_ROOTS.meta['tip'] = """List of strings representing allowed prefixes for the {% ssi %} tag. Example: ['/home/html', '/var/www']"""
+
+    ADMIN_FOR = pyre.list("admin-for")
+    ADMIN_FOR.meta['tip'] = """If this is a admin settings module, this should be a list of settings modules (in the format 'foo.bar.baz') for which this admin is an admin."""
+
+    IGNORABLE_404_STARTS = pyre.list("ignorable-404-starts", default=['/cgi-bin/', '/_vti_bin', '/_vti_inf'])
+    IGNORABLE_404_STARTS.meta['tip'] = """404s that may be ignored."""
+    
+    IGNORABLE_404_ENDS = pyre.list("ignorable-404-ends", default=['mail.pl', 'mailform.pl', 'mail.cgi', 'mailform.cgi', 'favicon.ico', '.php'])
+    IGNORABLE_404_ENDS.meta['tip'] = """404s that may be ignored."""
+
+    SECRET_KEY = pyre.str("secret-key")
+    SECRET_KEY.meta['tip'] = """A secret key for this particular Opal installation. Used in secret-key hashing algorithms. Set this in your settings, or Opal will complain loudly."""
+
+    JING_PATH = pyre.str("jing-path", default="/usr/bin/jing")
+    JING_PATH.meta['tip'] = """Path to the "jing" executable -- needed to validate XMLFields."""
+
+    MEDIA_ROOT = pyre.str("media-root")
+    MEDIA_ROOT.meta['tip'] = """Absolute path to the directory that holds media. Example: "/home/media/media.lawrence.com/"."""
+
+    MEDIA_URL = pyre.str("media-url")
+    MEDIA_URL.meta['tip'] = """URL that handles the media served from 'media-root'. Example: "http://media.lawrence.com"."""
+
+    DATE_FORMAT = pyre.str("date-format", default="N j, Y")
+    DATE_FORMAT.meta['tip'] = """Default formatting for date objects. See all available format strings here: http://www.djangoproject.com/documentation/templates/#now"""
+
+    DATETIME_FORMAT = pyre.str("datetime-format", default="N j, Y, P")
+    DATETIME_FORMAT.meta['tip'] = """Default formatting for datetime objects. See all available format strings here: http://www.djangoproject.com/documentation/templates/#now"""
+
+    TIME_FORMAT = pyre.str("time-format", default="P")
+    TIME_FORMAT.meta['tip'] = """Default formatting for time objects. See all available format strings here: http://www.djangoproject.com/documentation/templates/#now"""
+
+    YEAR_MONTH_FORMAT = pyre.str("year-month-format", default="F Y")
+    YEAR_MONTH_FORMAT.meta['tip'] = """Default formatting for date objects when only the year and month are relevant. See all available format strings here: http://www.djangoproject.com/documentation/templates/#now"""
+
+    MONTH_DAY_FORMAT = pyre.str("month-day-format", default="F j")
+    MONTH_DAY_FORMAT.meta['tip'] = """Default formatting for date objects when only the month and day are relevant. See all available format strings here: http://www.djangoproject.com/documentation/templates/#now"""
+
+    ENABLE_PSYCO = pyre.bool("enable-psyco", default=False)
+    ENABLE_PSYCO.meta['tip'] = """Whether to enable Psyco, which optimizes Python code. Requires Psyco. http://psyco.sourceforge.net/"""
+
+    TRANSACTIONS_MANAGED = pyre.bool("transactions-managed", default=False)
+    TRANSACTIONS_MANAGED.meta['tip'] = """Do you want to manage transactions manually? Hint: you really don't!"""
+
+
+    ##############
+    # MIDDLEWARE #
+    ##############
+
+    MIDDLEWARE_CLASSES = pyre.list("middleware-classes", default=[
+        'opal.contrib.sessions.middleware.SessionMiddleware',
+        'opal.contrib.auth.middleware.AuthenticationMiddleware',
+        #'opal.middleware.http.ConditionalGetMiddleware',
+        #'opal.middleware.gzip.GZipMiddleware',
+        'opal.middleware.common.CommonMiddleware',
+        'opal.middleware.doc.XViewMiddleware',
+    ])
+    MIDDLEWARE_CLASSES.meta['tip'] = """List of middleware classes to use. Order is important; in the request phase, this middleware classes will be applied in the order given, and in the response phase the middleware will be applied in reverse order."""
+
+
+    ############
+    # SESSIONS #
+    ############
+
+    SESSION_COOKIE_NAME = pyre.str("session-cookie-name", default="sessionid")
+    SESSION_COOKIE_NAME.meta['tip'] = """Cookie name. This can be whatever you want."""
+
+    from pyre.units.time import day
+    session_cookie_age = pyre.dimensional("session-cookie-age", default=(14 * day))
+    session_cookie_age.meta['tip'] = """Age of cookie (default: 2 weeks)."""
+    
+    session_cookie_domain = pyre.str("session-cookie-domain")
+    session_cookie_domain.meta['tip'] = """A string like ".lawrence.com". Leave blank for standard domain cookie."""
+    
+    SESSION_SAVE_EVERY_REQUEST = pyre.bool("session-save-every-request", default=False)
+    SESSION_SAVE_EVERY_REQUEST.meta['tip'] = """Whether to save the session data on every request."""
+    
+    SESSION_EXPIRE_AT_BROWSER_CLOSE = pyre.bool("session-expire-at-browser-close", default=False)
+    SESSION_EXPIRE_AT_BROWSER_CLOSE.meta['tip'] = """Whether sessions expire when a user closes his browser."""
+
+
+    #########
+    # CACHE #
+    #########
+
+    CACHE_BACKEND = pyre.str("cache-backend", default="simple://")
+    CACHE_BACKEND.meta['tip'] = """The cache backend to use.  See the docstring in opal.core.cache for the possible values."""
+    
+    CACHE_MIDDLEWARE_KEY_PREFIX = pyre.str("cache-middleware-key-prefix")
+
+
+    ####################
+    # COMMENTS         #
+    ####################
+
+    COMMENTS_ALLOW_PROFANITIES = pyre.bool("comments-allow-profanities", default=False)
+
+    # The group ID that designates which users are banned.
+    # Set to None if you're not using it.
+    COMMENTS_BANNED_USERS_GROUP = None
+
+    # The group ID that designates which users can moderate comments.
+    # Set to None if you're not using it.
+    COMMENTS_MODERATORS_GROUP = None
+
+    # The group ID that designates the users whose comments should be e-mailed to MANAGERS.
+    # Set to None if you're not using it.
+    COMMENTS_SKETCHY_USERS_GROUP = None
+
+    COMMENTS_FIRST_FEW = pyre.int("comments-first-few", default=0)
+    COMMENTS_FIRST_FEW.meta['tip'] = """The system will e-mail 'managers' the first 'comments-first-few' comments by each user. Set this to 0 if you want to disable it."""
+
+    BANNED_IPS = pyre.list("banned-ips")
+    BANNED_IPS.meta['tip'] = """A tuple of IP addresses that have been banned from participating in various Opal-powered features."""
+
+
+    ##################
+    # AUTHENTICATION #
+    ##################
+
+    AUTHENTICATION_BACKENDS = pyre.list("authentication-backends", default=[
+        'opal.contrib.auth.backends.ModelBackend',
+        ])
+
+
+    #########
+    # ????? #
+    #########
+
+    SITE_ID = pyre.int("site-id", default=1)
+    ROOT_URLCONF = pyre.str("root-urlconf", default="not.yet.implemented")
+
+
+    def _configure(self):
+        super(WebSite, self)._configure()
+
+        # convert to seconds
+        from pyre.units.time import second
+        self.SESSION_COOKIE_AGE = self.session_cookie_age / second
+
+        self.SESSION_COOKIE_DOMAIN = None
+        if self.session_cookie_domain != "":
+            self.SESSION_COOKIE_DOMAIN = self.session_cookie_domain
+
+        return
+
+
+# end of file

Added: cs/pythia/trunk/opal/sites/__init__.py
===================================================================
--- cs/pythia/trunk/opal/sites/__init__.py	2007-03-09 00:26:17 UTC (rev 6207)
+++ cs/pythia/trunk/opal/sites/__init__.py	2007-03-09 03:41:45 UTC (rev 6208)
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+#                      California Institute of Technology
+#                        (C) 2007  All Rights Reserved
+#
+# {LicenseText}
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+
+
+from WebSite import WebSite
+
+
+# end of file

Modified: cs/pythia/trunk/opal/utils/translation/trans_real.py
===================================================================
--- cs/pythia/trunk/opal/utils/translation/trans_real.py	2007-03-09 00:26:17 UTC (rev 6207)
+++ cs/pythia/trunk/opal/utils/translation/trans_real.py	2007-03-09 03:41:45 UTC (rev 6208)
@@ -117,7 +117,7 @@
 
     globalpath = os.path.join(os.path.dirname(sys.modules[settings.__module__].__file__), 'locale')
 
-    if settings.SETTINGS_MODULE is not None:
+    if False: #settings.SETTINGS_MODULE is not None:
         parts = settings.SETTINGS_MODULE.split('.')
         project = __import__(parts[0], {}, {}, [])
         projectpath = os.path.join(os.path.dirname(project.__file__), 'locale')

Modified: cs/pythia/trunk/opal/views/debug.py
===================================================================
--- cs/pythia/trunk/opal/views/debug.py	2007-03-09 00:26:17 UTC (rev 6207)
+++ cs/pythia/trunk/opal/views/debug.py	2007-03-09 03:41:45 UTC (rev 6208)
@@ -156,7 +156,7 @@
     "Create an empty URLconf 404 error response."
     t = Template(EMPTY_URLCONF_TEMPLATE)
     c = Context({
-        'project_name': settings.SETTINGS_MODULE.split('.')[0]
+        'project_name': settings.name
     })
     return HttpResponseNotFound(t.render(c), mimetype='text/html')
 
@@ -509,7 +509,6 @@
   </table>
 
   <h3 id="settings-info">Settings</h3>
-  <h4>Using settings module <code>{{ settings.SETTINGS_MODULE }}</code></h4>
   <table class="req">
     <thead>
       <tr>



More information about the cig-commits mailing list