setup Pylons infrastructure

paster create -t pylons ...
paster controller ddportfolio
add support for sphinx
This commit is contained in:
Jan Dittberner 2009-01-20 22:39:05 +01:00
parent 0c5816154b
commit 9c800c0ed8
27 changed files with 689 additions and 35 deletions

View file

@ -1 +0,0 @@
#

View file

View file

@ -0,0 +1,33 @@
"""Pylons environment configuration"""
import os
from pylons import config
import ddportfolioservice.lib.app_globals as app_globals
import ddportfolioservice.lib.helpers
from ddportfolioservice.config.routing import make_map
def load_environment(global_conf, app_conf):
"""Configure the Pylons environment via the ``pylons.config``
object
"""
# Pylons paths
root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
paths = dict(root=root,
controllers=os.path.join(root, 'controllers'),
static_files=os.path.join(root, 'public'),
templates=[os.path.join(root, 'templates')])
# Initialize config with the basic options
config.init_app(global_conf, app_conf, package='ddportfolioservice',
template_engine='mako', paths=paths)
config['routes.map'] = make_map()
config['pylons.g'] = app_globals.Globals()
config['pylons.h'] = ddportfolioservice.lib.helpers
# Customize templating options via this variable
tmpl_options = config['buffet.template_options']
# CONFIGURATION OPTIONS HERE (note: all config options will override
# any Pylons config options)

View file

@ -0,0 +1,57 @@
"""Pylons middleware initialization"""
from paste.cascade import Cascade
from paste.registry import RegistryManager
from paste.urlparser import StaticURLParser
from paste.deploy.converters import asbool
from pylons import config
from pylons.error import error_template
from pylons.middleware import error_mapper, ErrorDocuments, ErrorHandler, \
StaticJavascripts
from pylons.wsgiapp import PylonsApp
from ddportfolioservice.config.environment import load_environment
def make_app(global_conf, full_stack=True, **app_conf):
"""Create a Pylons WSGI application and return it
``global_conf``
The inherited configuration for this application. Normally from
the [DEFAULT] section of the Paste ini file.
``full_stack``
Whether or not this application provides a full WSGI stack (by
default, meaning it handles its own exceptions and errors).
Disable full_stack when this application is "managed" by
another WSGI middleware.
``app_conf``
The application's local configuration. Normally specified in the
[app:<name>] section of the Paste ini file (where <name>
defaults to main).
"""
# Configure the Pylons environment
load_environment(global_conf, app_conf)
# The Pylons WSGI app
app = PylonsApp()
# CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares)
if asbool(full_stack):
# Handle Python exceptions
app = ErrorHandler(app, global_conf, error_template=error_template,
**config['pylons.errorware'])
# Display error documents for 401, 403, 404 status codes (and
# 500 when debug is disabled)
app = ErrorDocuments(app, global_conf, mapper=error_mapper, **app_conf)
# Establish the Registry for this application
app = RegistryManager(app)
# Static files
javascripts_app = StaticJavascripts()
static_app = StaticURLParser(config['pylons.paths']['static_files'])
app = Cascade([static_app, javascripts_app, app])
return app

View file

@ -0,0 +1,24 @@
"""Routes configuration
The more specific and detailed routes should be defined first so they
may take precedent over the more generic routes. For more information
refer to the routes manual at http://routes.groovie.org/docs/
"""
from pylons import config
from routes import Mapper
def make_map():
"""Create, configure and return the routes Mapper"""
map = Mapper(directory=config['pylons.paths']['controllers'],
always_scan=config['debug'])
# The ErrorController route (handles 404/500 error pages); it should
# likely stay at the top, ensuring it can always be resolved
map.connect('error/:action/:id', controller='error')
# CUSTOM ROUTES HERE
map.connect('', controller='ddportfolio', action='index')
map.connect(':controller/:action/:id')
map.connect('*url', controller='template', action='view')
return map

View file

@ -0,0 +1,13 @@
import logging
from ddportfolioservice.lib.base import *
log = logging.getLogger(__name__)
class DdportfolioController(BaseController):
def index(self):
# Return a rendered template
# return render('/some/template.mako')
# or, Return a response
return 'Hello World'

View file

@ -0,0 +1,41 @@
import cgi
import os.path
from paste.urlparser import StaticURLParser
from pylons.middleware import error_document_template, media_path
from ddportfolioservice.lib.base import *
class ErrorController(BaseController):
"""Generates error documents as and when they are required.
The ErrorDocuments middleware forwards to ErrorController when error
related status codes are returned from the application.
This behaviour can be altered by changing the parameters to the
ErrorDocuments middleware in your config/middleware.py file.
"""
def document(self):
"""Render the error document"""
page = error_document_template % \
dict(prefix=request.environ.get('SCRIPT_NAME', ''),
code=cgi.escape(request.params.get('code', '')),
message=cgi.escape(request.params.get('message', '')))
return page
def img(self, id):
"""Serve Pylons' stock images"""
return self._serve_file(os.path.join(media_path, 'img'), id)
def style(self, id):
"""Serve Pylons' stock stylesheets"""
return self._serve_file(os.path.join(media_path, 'style'), id)
def _serve_file(self, root, path):
"""Call Paste's FileApp (a WSGI application) to serve the file
at the specified path
"""
static = StaticURLParser(root)
request.environ['PATH_INFO'] = '/%s' % path
return static(request.environ, self.start_response)

View file

@ -0,0 +1,27 @@
from ddportfolioservice.lib.base import *
class TemplateController(BaseController):
def view(self, url):
"""By default, the final controller tried to fulfill the request
when no other routes match. It may be used to display a template
when all else fails, e.g.::
def view(self, url):
return render('/%s' % url)
Or if you're using Mako and want to explicitly send a 404 (Not
Found) response code when the requested template doesn't exist::
import mako.exceptions
def view(self, url):
try:
return render('/%s' % url)
except mako.exceptions.TopLevelLookupException:
abort(404)
By default this controller aborts the request with a 404 (Not
Found)
"""
abort(404)

View file

View file

@ -0,0 +1,14 @@
"""The application's Globals object"""
from pylons import config
class Globals(object):
"""Globals acts as a container for objects available throughout the
life of the application
"""
def __init__(self):
"""One instance of Globals is created during application
initialization and is available during requests via the 'g'
variable
"""
pass

View file

@ -0,0 +1,27 @@
"""The base Controller API
Provides the BaseController class for subclassing, and other objects
utilized by Controllers.
"""
from pylons import c, cache, config, g, request, response, session
from pylons.controllers import WSGIController
from pylons.controllers.util import abort, etag_cache, redirect_to
from pylons.decorators import jsonify, validate
from pylons.i18n import _, ungettext, N_
from pylons.templating import render
import ddportfolioservice.lib.helpers as h
import ddportfolioservice.model as model
class BaseController(WSGIController):
def __call__(self, environ, start_response):
"""Invoke the Controller"""
# WSGIController.__call__ dispatches to the Controller method
# the request is routed to. This routing information is
# available in environ['pylons.routes_dict']
return WSGIController.__call__(self, environ, start_response)
# Include the '_' function in the public names
__all__ = [__name for __name in locals().keys() if not __name.startswith('_') \
or __name == '_']

View file

@ -0,0 +1,6 @@
"""Helper functions
Consists of functions to typically be used within templates, but also
available to Controllers. This module is available to both as 'h'.
"""
from webhelpers import *

View file

View file

@ -0,0 +1,40 @@
"""Pylons application test package
When the test runner finds and executes tests within this directory,
this file will be loaded to setup the test environment.
It registers the root directory of the project in sys.path and
pkg_resources, in case the project hasn't been installed with
setuptools. It also initializes the application via websetup (paster
setup-app) with the project's test.ini configuration file.
"""
import os
import sys
from unittest import TestCase
import pkg_resources
import paste.fixture
import paste.script.appinstall
from paste.deploy import loadapp
from routes import url_for
__all__ = ['url_for', 'TestController']
here_dir = os.path.dirname(os.path.abspath(__file__))
conf_dir = os.path.dirname(os.path.dirname(here_dir))
sys.path.insert(0, conf_dir)
pkg_resources.working_set.add_entry(conf_dir)
pkg_resources.require('Paste')
pkg_resources.require('PasteScript')
test_file = os.path.join(conf_dir, 'test.ini')
cmd = paste.script.appinstall.SetupCommand('setup-app')
cmd.run([test_file])
class TestController(TestCase):
def __init__(self, *args, **kwargs):
wsgiapp = loadapp('config:test.ini', relative_to=conf_dir)
self.app = paste.fixture.TestApp(wsgiapp)
TestCase.__init__(self, *args, **kwargs)

View file

@ -0,0 +1,7 @@
from ddportfolioservice.tests import *
class TestDdportfolioController(TestController):
def test_index(self):
response = self.app.get(url_for(controller='ddportfolio'))
# Test response...

View file

View file

@ -0,0 +1,14 @@
"""Setup the ddportfolioservice application"""
import logging
from paste.deploy import appconfig
from pylons import config
from ddportfolioservice.config.environment import load_environment
log = logging.getLogger(__name__)
def setup_config(command, filename, section, vars):
"""Place any commands to setup ddportfolioservice here"""
conf = appconfig('config:' + filename)
load_environment(conf.global_conf, conf.local_conf)