move to Pylons 0.9.7 and related packages

This commit is contained in:
Jan Dittberner 2009-03-08 23:52:49 +01:00
parent 787f6050d4
commit 30b74165c6
28 changed files with 199 additions and 173 deletions

3
.gitignore vendored
View file

@ -1,4 +1,5 @@
*~ *~
*.pyc *.pyc
data data
pyalchemybiz.db development.db
pyalchemybiz/public/js/jquery.js

View file

@ -1,2 +1,3 @@
include pyalchemybiz/config/deployment.ini_tmpl
recursive-include pyalchemybiz/public * recursive-include pyalchemybiz/public *
recursive-include pyalchemybiz/templates * recursive-include pyalchemybiz/templates *

View file

@ -12,12 +12,14 @@ error_email_from = paste@localhost
[server:main] [server:main]
use = egg:Paste#http use = egg:Paste#http
host = 0.0.0.0 host = 127.0.0.1
port = 5000 port = 5000
[app:main] [app:main]
use = egg:pyalchemybiz use = egg:pyalchemybiz
full_stack = true full_stack = true
static_files = true
cache_dir = %(here)s/data cache_dir = %(here)s/data
beaker.session.key = pyalchemybiz beaker.session.key = pyalchemybiz
beaker.session.secret = somesecret beaker.session.secret = somesecret
@ -28,26 +30,24 @@ beaker.session.secret = somesecret
#beaker.cache.data_dir = %(here)s/data/cache #beaker.cache.data_dir = %(here)s/data/cache
#beaker.session.data_dir = %(here)s/data/sessions #beaker.session.data_dir = %(here)s/data/sessions
# WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* # SQLAlchemy database URL
# Debug mode will enable the interactive debugging tool, allowing ANYONE to sqlalchemy.url = sqlite:///%(here)s/development.db
# execute malicious code after an exception is raised. sqlalchemy.echo = true
#set debug = false
# Specify the database for SQLAlchemy to use.
# %(here)s may include a ':' character on Windows environments; this can
# invalidate the URI when specifying a SQLite db via path name
sqlalchemy.default.url = sqlite:///%(here)s/pyalchemybiz.db
sqlalchemy.default.echo = true
sqlalchemy.convert_unicode = true sqlalchemy.convert_unicode = true
# settings for sqlalchemy-migrate # settings for sqlalchemy-migrate
migrate.repo.version = 2 migrate.repo.version = 2
migrate.repo.dir = %(here)s/data/dbrepo migrate.repo.dir = %(here)s/data/dbrepo
# WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT*
# Debug mode will enable the interactive debugging tool, allowing ANYONE to
# execute malicious code after an exception is raised.
#set debug = false
# Logging configuration # Logging configuration
[loggers] [loggers]
keys = root, pyalchemybiz keys = root, routes, pyalchemybiz, sqlalchemy
[handlers] [handlers]
keys = console keys = console
@ -59,11 +59,25 @@ keys = generic
level = INFO level = INFO
handlers = console handlers = console
[logger_routes]
level = INFO
handlers =
qualname = routes.middleware
# "level = DEBUG" logs the route matched and routing variables.
[logger_pyalchemybiz] [logger_pyalchemybiz]
level = DEBUG level = DEBUG
handlers = handlers =
qualname = pyalchemybiz qualname = pyalchemybiz
[logger_sqlalchemy]
level = INFO
handlers =
qualname = sqlalchemy.engine
# "level = INFO" logs SQL queries.
# "level = DEBUG" logs SQL queries and results.
# "level = WARN" logs neither. (Recommended for production systems.)
[handler_console] [handler_console]
class = StreamHandler class = StreamHandler
args = (sys.stderr,) args = (sys.stderr,)

View file

@ -8,5 +8,12 @@ You can generate your documentation in HTML format by running this command::
setup.py pudge setup.py pudge
For this to work you will need to download and install ``buildutils`` and For this to work you will need to download and install `buildutils`_,
``pudge``. `pudge`_, and `pygments`_. The ``pudge`` command is disabled by
default; to ativate it in your project, run::
setup.py addcommand -p buildutils.pudge_command
.. _buildutils: http://pypi.python.org/pypi/buildutils
.. _pudge: http://pudge.lesscode.org/
.. _pygments: http://pygments.org/

View file

@ -1,6 +1,6 @@
Metadata-Version: 1.0 Metadata-Version: 1.0
Name: pyalchemybiz Name: pyalchemybiz
Version: 0.1dev-r6 Version: 0.1dev
Summary: python based small business suite. Summary: python based small business suite.
Home-page: http://www.dittberner.info/projects/pyalchemybiz Home-page: http://www.dittberner.info/projects/pyalchemybiz
Author: Jan Dittberner Author: Jan Dittberner

View file

@ -18,11 +18,12 @@ pyalchemybiz.egg-info/PKG-INFO
pyalchemybiz.egg-info/SOURCES.txt pyalchemybiz.egg-info/SOURCES.txt
pyalchemybiz.egg-info/dependency_links.txt pyalchemybiz.egg-info/dependency_links.txt
pyalchemybiz.egg-info/entry_points.txt pyalchemybiz.egg-info/entry_points.txt
pyalchemybiz.egg-info/paste_deploy_config.ini_tmpl pyalchemybiz.egg-info/not-zip-safe
pyalchemybiz.egg-info/paster_plugins.txt pyalchemybiz.egg-info/paster_plugins.txt
pyalchemybiz.egg-info/requires.txt pyalchemybiz.egg-info/requires.txt
pyalchemybiz.egg-info/top_level.txt pyalchemybiz.egg-info/top_level.txt
pyalchemybiz/config/__init__.py pyalchemybiz/config/__init__.py
pyalchemybiz/config/deployment.ini_tmpl
pyalchemybiz/config/environment.py pyalchemybiz/config/environment.py
pyalchemybiz/config/middleware.py pyalchemybiz/config/middleware.py
pyalchemybiz/config/routing.py pyalchemybiz/config/routing.py
@ -40,9 +41,13 @@ pyalchemybiz/model/customer.py
pyalchemybiz/model/meta.py pyalchemybiz/model/meta.py
pyalchemybiz/model/person.py pyalchemybiz/model/person.py
pyalchemybiz/model/product.py pyalchemybiz/model/product.py
pyalchemybiz/templates/base.mako pyalchemybiz/templates/base/base.mako
pyalchemybiz/templates/customer.mako pyalchemybiz/templates/base/customer.mako
pyalchemybiz/templates/index.mako pyalchemybiz/templates/derived/customer/edit.mako
pyalchemybiz/templates/derived/customer/list.mako
pyalchemybiz/templates/derived/customer/new.mako
pyalchemybiz/templates/derived/customer/view.mako
pyalchemybiz/templates/derived/index/index.mako
pyalchemybiz/tests/__init__.py pyalchemybiz/tests/__init__.py
pyalchemybiz/tests/test_models.py pyalchemybiz/tests/test_models.py
pyalchemybiz/tests/functional/__init__.py pyalchemybiz/tests/functional/__init__.py

View file

@ -0,0 +1 @@

View file

@ -1,2 +1,2 @@
PasteScript
Pylons Pylons
WebHelpers

View file

@ -1,3 +1,5 @@
Pylons>=0.9.6.2 Pylons>=0.9.7
SQLAlchemy>=0.4.7 SQLAlchemy>=0.5.2,<0.6
sqlalchemy-migrate>=0.4.5 sqlalchemy-migrate>=0.5.2,<0.6
Mako
FormBuild>=2.0,<3

View file

@ -17,6 +17,8 @@ port = 5000
[app:main] [app:main]
use = egg:pyalchemybiz use = egg:pyalchemybiz
full_stack = true full_stack = true
static_files = true
cache_dir = %(here)s/data cache_dir = %(here)s/data
beaker.session.key = pyalchemybiz beaker.session.key = pyalchemybiz
beaker.session.secret = ${app_instance_secret} beaker.session.secret = ${app_instance_secret}
@ -28,22 +30,14 @@ app_instance_uuid = ${app_instance_uuid}
#beaker.cache.data_dir = %(here)s/data/cache #beaker.cache.data_dir = %(here)s/data/cache
#beaker.session.data_dir = %(here)s/data/sessions #beaker.session.data_dir = %(here)s/data/sessions
# SQLAlchemy database URL
sqlalchemy.url = sqlite:///production.db
# WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* # WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT*
# Debug mode will enable the interactive debugging tool, allowing ANYONE to # Debug mode will enable the interactive debugging tool, allowing ANYONE to
# execute malicious code after an exception is raised. # execute malicious code after an exception is raised.
set debug = false set debug = false
# Specify the database for SQLAlchemy to use.
# %(here)s may include a ':' character on Windows environments; this can
# invalidate the URI when specifying a SQLite db via path name
#sqlalchemy.default.url = sqlite:///%(here)s/pyalchemybiz.db
#sqlalchemy.default.echo = false
sqlalchemy.default.convert_unicode = true
# settings for sqlalchemy-migrate
migrate.repo.version = 2
migrate.repo.dir = %(here)s/data/dbrepo
# Logging configuration # Logging configuration
[loggers] [loggers]

View file

@ -1,9 +1,11 @@
"""Pylons environment configuration""" """Pylons environment configuration"""
import os import os
from mako.lookup import TemplateLookup
from pylons import config from pylons import config
from pylons.error import handle_mako_error
from sqlalchemy import engine_from_config from sqlalchemy import engine_from_config
from sqlalchemy.exceptions import NoSuchTableError from sqlalchemy.exc import NoSuchTableError
from migrate.versioning.api import db_version from migrate.versioning.api import db_version
from pyalchemybiz.model import init_model from pyalchemybiz.model import init_model
@ -12,6 +14,7 @@ import pyalchemybiz.lib.app_globals as app_globals
import pyalchemybiz.lib.helpers import pyalchemybiz.lib.helpers
from pyalchemybiz.config.routing import make_map from pyalchemybiz.config.routing import make_map
from pyalchemybiz.model import init_model
def load_environment(global_conf, app_conf): def load_environment(global_conf, app_conf):
"""Configure the Pylons environment via the ``pylons.config`` """Configure the Pylons environment via the ``pylons.config``
@ -25,31 +28,36 @@ def load_environment(global_conf, app_conf):
templates=[os.path.join(root, 'templates')]) templates=[os.path.join(root, 'templates')])
# Initialize config with the basic options # Initialize config with the basic options
config.init_app(global_conf, app_conf, package='pyalchemybiz', config.init_app(global_conf, app_conf, package='pyalchemybiz', paths=paths)
template_engine='mako', paths=paths)
config['routes.map'] = make_map() config['routes.map'] = make_map()
config['pylons.g'] = app_globals.Globals() config['pylons.app_globals'] = app_globals.Globals()
config['pylons.h'] = pyalchemybiz.lib.helpers config['pylons.h'] = pyalchemybiz.lib.helpers
# Customize templating options via this variable # Create the Mako TemplateLookup, with the default auto-escaping
tmpl_options = config['buffet.template_options'] config['pylons.app_globals'].mako_lookup = TemplateLookup(
directories=paths['templates'],
error_handler=handle_mako_error,
module_directory=os.path.join(app_conf['cache_dir'], 'templates'),
input_encoding='utf-8', default_filters=['escape'],
imports=['from webhelpers.html import escape'])
# CONFIGURATION OPTIONS HERE (note: all config options will override # Setup the SQLAlchemy database engine
# any Pylons config options) engine = engine_from_config(config, 'sqlalchemy.')
engine = \
engine_from_config(config, 'sqlalchemy.default.')
try: try:
init_model(engine) init_model(engine)
except Exception: except NoSuchTableError:
# special handling for calls in websetup.py # special handling for calls in websetup.py
import inspect import inspect
frame = inspect.currentframe() frame = inspect.currentframe()
try: try:
functions = [current[3] for current in \ functions = [current[3] for current in \
inspect.getouterframes(frame)] inspect.getouterframes(frame)]
if functions[1] != 'setup_config': if functions[1] != 'setup_app':
raise raise
finally: finally:
del frame del frame
# CONFIGURATION OPTIONS HERE (note: all config options will override
# any Pylons config options)

View file

@ -1,19 +1,17 @@
"""Pylons middleware initialization""" """Pylons middleware initialization"""
from beaker.middleware import CacheMiddleware, SessionMiddleware
from paste.cascade import Cascade from paste.cascade import Cascade
from paste.registry import RegistryManager from paste.registry import RegistryManager
from paste.urlparser import StaticURLParser from paste.urlparser import StaticURLParser
from paste.deploy.converters import asbool from paste.deploy.converters import asbool
from pylons import config from pylons import config
from pylons.error import error_template from pylons.middleware import ErrorHandler, StatusCodeRedirect
from pylons.middleware import error_mapper, ErrorDocuments, ErrorHandler, \
StaticJavascripts
from pylons.wsgiapp import PylonsApp from pylons.wsgiapp import PylonsApp
from routes.middleware import RoutesMiddleware
from pyalchemybiz.config.environment import load_environment from pyalchemybiz.config.environment import load_environment
def make_app(global_conf, full_stack=True, static_files=True, **app_conf):
def make_app(global_conf, full_stack=True, **app_conf):
"""Create a Pylons WSGI application and return it """Create a Pylons WSGI application and return it
``global_conf`` ``global_conf``
@ -21,15 +19,20 @@ def make_app(global_conf, full_stack=True, **app_conf):
the [DEFAULT] section of the Paste ini file. the [DEFAULT] section of the Paste ini file.
``full_stack`` ``full_stack``
Whether or not this application provides a full WSGI stack (by Whether this application provides a full WSGI stack (by default,
default, meaning it handles its own exceptions and errors). meaning it handles its own exceptions and errors). Disable
Disable full_stack when this application is "managed" by full_stack when this application is "managed" by another WSGI
another WSGI middleware. middleware.
``static_files``
Whether this application serves its own static files; disable
when another web server is responsible for serving them.
``app_conf`` ``app_conf``
The application's local configuration. Normally specified in the The application's local configuration. Normally specified in
[app:<name>] section of the Paste ini file (where <name> the [app:<name>] section of the Paste ini file (where <name>
defaults to main). defaults to main).
""" """
# Configure the Pylons environment # Configure the Pylons environment
load_environment(global_conf, app_conf) load_environment(global_conf, app_conf)
@ -37,22 +40,30 @@ def make_app(global_conf, full_stack=True, **app_conf):
# The Pylons WSGI app # The Pylons WSGI app
app = PylonsApp() app = PylonsApp()
# Routing/Session/Cache Middleware
app = RoutesMiddleware(app, config['routes.map'])
app = SessionMiddleware(app, config)
app = CacheMiddleware(app, config)
# CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares)
if asbool(full_stack): if asbool(full_stack):
# Handle Python exceptions # Handle Python exceptions
app = ErrorHandler(app, global_conf, error_template=error_template, app = ErrorHandler(app, global_conf, **config['pylons.errorware'])
**config['pylons.errorware'])
# Display error documents for 401, 403, 404 status codes (and # Display error documents for 401, 403, 404 status codes (and
# 500 when debug is disabled) # 500 when debug is disabled)
app = ErrorDocuments(app, global_conf, mapper=error_mapper, **app_conf) if asbool(config['debug']):
app = StatusCodeRedirect(app)
else:
app = StatusCodeRedirect(app, [400, 401, 403, 404, 500])
# Establish the Registry for this application # Establish the Registry for this application
app = RegistryManager(app) app = RegistryManager(app)
# Static files if asbool(static_files):
javascripts_app = StaticJavascripts() # Serve static files
static_app = StaticURLParser(config['pylons.paths']['static_files']) static_app = StaticURLParser(config['pylons.paths']['static_files'])
app = Cascade([static_app, javascripts_app, app]) app = Cascade([static_app, app])
return app return app

View file

@ -7,19 +7,21 @@ refer to the routes manual at http://routes.groovie.org/docs/
from pylons import config from pylons import config
from routes import Mapper from routes import Mapper
def make_map(): def make_map():
"""Create, configure and return the routes Mapper""" """Create, configure and return the routes Mapper"""
map = Mapper(directory=config['pylons.paths']['controllers'], map = Mapper(directory=config['pylons.paths']['controllers'],
always_scan=config['debug']) always_scan=config['debug'])
map.minimization = False
# The ErrorController route (handles 404/500 error pages); it should # The ErrorController route (handles 404/500 error pages); it should
# likely stay at the top, ensuring it can always be resolved # likely stay at the top, ensuring it can always be resolved
map.connect('error/:action/:id', controller='error') map.connect('/error/{action}', controller='error')
map.connect('/error/{action}/{id}', controller='error')
# CUSTOM ROUTES HERE # CUSTOM ROUTES HERE
map.connect('', controller='index', action='index')
map.connect(':controller/:action/:id') map.connect('/', controller='index', action='index')
map.connect('*url', controller='template', action='view') map.connect('/{controller}/{action}')
map.connect('/{controller}/{action}/{id}')
return map return map

View file

@ -1,13 +1,15 @@
import cgi import cgi
import os.path
from paste.urlparser import StaticURLParser from paste.urlparser import PkgResourcesParser
from pylons.middleware import error_document_template, media_path from pylons import request
from pylons.controllers.util import forward
from pyalchemybiz.lib.base import * from pylons.middleware import error_document_template
from webhelpers.html.builder import literal
from pyalchemybiz.lib.base import BaseController
class ErrorController(BaseController): class ErrorController(BaseController):
"""Generates error documents as and when they are required. """Generates error documents as and when they are required.
The ErrorDocuments middleware forwards to ErrorController when error The ErrorDocuments middleware forwards to ErrorController when error
@ -20,24 +22,25 @@ class ErrorController(BaseController):
def document(self): def document(self):
"""Render the error document""" """Render the error document"""
resp = request.environ.get('pylons.original_response')
content = literal(resp.body) or cgi.escape(request.GET.get('message', ''))
page = error_document_template % \ page = error_document_template % \
dict(prefix=request.environ.get('SCRIPT_NAME', ''), dict(prefix=request.environ.get('SCRIPT_NAME', ''),
code=cgi.escape(request.params.get('code', '')), code=cgi.escape(request.GET.get('code', str(resp.status_int))),
message=cgi.escape(request.params.get('message', ''))) message=content)
return page return page
def img(self, id): def img(self, id):
"""Serve Pylons' stock images""" """Serve Pylons' stock images"""
return self._serve_file(os.path.join(media_path, 'img'), id) return self._serve_file('/'.join(['media/img', id]))
def style(self, id): def style(self, id):
"""Serve Pylons' stock stylesheets""" """Serve Pylons' stock stylesheets"""
return self._serve_file(os.path.join(media_path, 'style'), id) return self._serve_file('/'.join(['media/style', id]))
def _serve_file(self, root, path): def _serve_file(self, path):
"""Call Paste's FileApp (a WSGI application) to serve the file """Call Paste's FileApp (a WSGI application) to serve the file
at the specified path at the specified path
""" """
static = StaticURLParser(root)
request.environ['PATH_INFO'] = '/%s' % path request.environ['PATH_INFO'] = '/%s' % path
return static(request.environ, self.start_response) return forward(PkgResourcesParser('pylons', 'pylons'))

View file

@ -1,6 +1,8 @@
import logging import logging
from pyalchemybiz.lib.base import * from pyalchemybiz.lib.base import *
from pylons.i18n.translation import ugettext, _, set_lang, get_lang
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View file

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

View file

@ -1,40 +1,37 @@
"""The base Controller API """The base Controller API
Provides the BaseController class for subclassing, and other objects Provides the BaseController class for subclassing.
utilized by Controllers.
""" """
from pylons import c, cache, config, g, request, response, session from pylons import c, cache, config, g, request, response, session
from pylons.controllers import WSGIController from pylons.controllers import WSGIController
from pylons.controllers.util import abort, etag_cache, redirect_to from pylons.controllers.util import abort, etag_cache, redirect_to
from pylons.decorators import jsonify, validate from pylons.decorators import jsonify, validate
from pylons.i18n import _, ungettext, N_, add_fallback, set_lang from pylons.i18n.translation import _, ugettext, add_fallback
from pylons.templating import render from pylons.templating import render_mako as render
import pyalchemybiz.lib.helpers as h import pyalchemybiz.lib.helpers as h
from pyalchemybiz.model import meta from pyalchemybiz.model import meta
class BaseController(WSGIController): class BaseController(WSGIController):
def __call__(self, environ, start_response): def __before__(self):
"""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']
# set language environment # set language environment
for lang in request.languages: for lang in request.languages:
try: try:
add_fallback(lang) add_fallback(lang)
except: except:
pass pass
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']
# connect to database # connect to database
try: try:
return WSGIController.__call__(self, environ, start_response) return WSGIController.__call__(self, environ, start_response)
finally: finally:
meta.Session.remove() meta.Session.remove()
# Include the '_' function in the public names
__all__ = [__name for __name in locals().keys() if not __name.startswith('_') \
or __name == '_']

View file

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

View file

@ -1,14 +1,15 @@
"""SQLAlchemy Metadata and Session object""" """SQLAlchemy Metadata and Session object"""
from sqlalchemy import MetaData from sqlalchemy import MetaData
from sqlalchemy.orm import scoped_session, sessionmaker
__all__ = ['engine', 'metadata', 'Session'] __all__ = ['Session', 'engine', 'metadata']
# SQLAlchemy database engine. Updated by model.init_model(). # SQLAlchemy database engine. Updated by model.init_model()
engine = None engine = None
# SQLAlchemy session manager. Updated by model.init_model(). # SQLAlchemy session manager. Updated by model.init_model()
Session = None Session = scoped_session(sessionmaker())
# Global metadata. If you have multiple databases with overlapping table # Global metadata. If you have multiple databases with overlapping table
# names, you'll need a metadata for each database. # names, you'll need a metadata for each database
metadata = MetaData() metadata = MetaData()

View file

View file

View file

@ -6,7 +6,7 @@
<head> <head>
<title>${self.title()}</title> <title>${self.title()}</title>
${h.stylesheet_link('/pyalchemybiz.css')} ${h.stylesheet_link('/pyalchemybiz.css')}
${h.javascript_link('/javascripts/jquery.js', '/javascripts/pyalchemybiz.js')} ${h.javascript_link('/js/jquery.js', '/js/pyalchemybiz.js')}
${self.head()} ${self.head()}
</head> </head>
<body> <body>

View file

@ -2,7 +2,7 @@
<ul id="customers"> <ul id="customers">
% for customer in c.customers: % for customer in c.customers:
<li>${customer | h} [${h.link_to(_('view customer'), h.url_for(id=customer.id, action='view'))}] [${h.link_to(_('edit customer'), h.url_for(id=customer.id, action="edit"))}] [${h.link_to(_('delete customer'), h.url_for(id=customer.id, action="delete"))}]</li> <li>${customer} [${h.link_to(_('view customer'), h.url_for(id=customer.id, action='view'))}] [${h.link_to(_('edit customer'), h.url_for(id=customer.id, action="edit"))}] [${h.link_to(_('delete customer'), h.url_for(id=customer.id, action="delete"))}]</li>
% endfor % endfor
</ul> </ul>

View file

@ -1,41 +1,36 @@
"""Pylons application test package """Pylons application test package
When the test runner finds and executes tests within this directory, This package assumes the Pylons environment is already loaded, such as
this file will be loaded to setup the test environment. when this script is imported from the `nosetests --with-pylons=test.ini`
command.
It registers the root directory of the project in sys.path and This module initializes the application via ``websetup`` (`paster
pkg_resources, in case the project hasn't been installed with setup-app`) and provides the base testing objects.
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 from unittest import TestCase
import pkg_resources
import paste.fixture
import paste.script.appinstall
from paste.deploy import loadapp from paste.deploy import loadapp
from routes import url_for from paste.script.appinstall import SetupCommand
from pylons import config, url
from routes.util import URLGenerator
from webtest import TestApp
__all__ = ['url_for', 'TestController'] import pylons.test
here_dir = os.path.dirname(os.path.abspath(__file__)) __all__ = ['environ', 'url', 'TestController']
conf_dir = os.path.dirname(os.path.dirname(here_dir))
sys.path.insert(0, conf_dir) # Invoke websetup with the current config file
pkg_resources.working_set.add_entry(conf_dir) SetupCommand('setup-app').run([config['__file__']])
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])
environ = {}
class TestController(TestCase): class TestController(TestCase):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
wsgiapp = loadapp('config:test.ini', relative_to=conf_dir) if pylons.test.pylonsapp:
self.app = paste.fixture.TestApp(wsgiapp) wsgiapp = pylons.test.pylonsapp
else:
wsgiapp = loadapp('config:%s' % config['__file__'])
self.app = TestApp(wsgiapp)
url._push_object(URLGenerator(config['routes.map'], environ))
TestCase.__init__(self, *args, **kwargs) TestCase.__init__(self, *args, **kwargs)

View file

@ -13,14 +13,13 @@ from pyalchemybiz.config.environment import load_environment
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
def setup_config(command, filename, section, vars): def setup_app(command, conf, vars):
"""Place any commands to setup pyalchemybiz here""" """Place any commands to setup pyalchemybiz here"""
conf = appconfig('config:' + filename)
load_environment(conf.global_conf, conf.local_conf) load_environment(conf.global_conf, conf.local_conf)
repoversion = int(config.get('migrate.repo.version')) repoversion = int(config.get('migrate.repo.version'))
repodir = config.get('migrate.repo.dir') repodir = config.get('migrate.repo.dir')
dburl = config.get('sqlalchemy.default.url') dburl = config.get('sqlalchemy.url')
# Populate the DB on 'paster setup-app' # Populate the DB on 'paster setup-app'

View file

@ -5,36 +5,8 @@ tag_svn_revision = true
[easy_install] [easy_install]
find_links = http://www.pylonshq.com/download/ find_links = http://www.pylonshq.com/download/
[pudge] [nosetests]
theme = pythonpaste.org with-pylons = test.ini
# Add extra doc files here with spaces between them
docs = docs/index.txt
# Doc Settings
doc_base = docs/
dest = docs/html
# Add extra modules here separated with commas
modules = pyalchemybiz
title = Pyalchemybiz
organization = Pylons
# Highlight code-block sections with Pygments
highlighter = pygments
# Optionally add extra links
#organization_url = http://pylonshq.com/
#trac_url = http://pylonshq.com/project
settings = no_about=true
# Optionally add extra settings
# link1=/community/ Community
# link2=/download/ Download
[publish]
doc-dir=docs/html
make-dirs=1
# Babel configuration # Babel configuration
[compile_catalog] [compile_catalog]

View file

@ -7,21 +7,32 @@ except ImportError:
setup( setup(
name='pyalchemybiz', name='pyalchemybiz',
version="0.1", version='0.1',
description='python based small business suite.', description='python based small business suite.',
author='Jan Dittberner', author='Jan Dittberner',
author_email='jan@dittberner.info', author_email='jan@dittberner.info',
url='http://www.dittberner.info/projects/pyalchemybiz', url='http://www.dittberner.info/projects/pyalchemybiz',
install_requires=["Pylons>=0.9.7", "SQLAlchemy>=0.5.2", install_requires=[
"sqlalchemy-migrate>=0.5.2"], "Pylons>=0.9.7",
"SQLAlchemy>=0.5.2,<0.6",
"sqlalchemy-migrate>=0.5.2,<0.6",
"Mako",
"FormBuild>=2.0,<3",
],
setup_requires=[
"PasteScript>=1.6.3",
"Babel>=0.9.1",
],
packages=find_packages(exclude=['ez_setup']), packages=find_packages(exclude=['ez_setup']),
include_package_data=True, include_package_data=True,
test_suite='nose.collector', test_suite='nose.collector',
package_data={'pyalchemybiz': ['i18n/*/LC_MESSAGES/*.mo']}, package_data={'pyalchemybiz': ['i18n/*/LC_MESSAGES/*.mo']},
message_extractors = {'pyalchemybiz': [ message_extractors = {'pyalchemybiz': [
('**.py', 'python', None), ('**.py', 'python', None),
('templates/**.mako', 'mako', None), ('templates/**.mako', 'mako', {'input_encoding': 'utf-8'}),
('public/**', 'ignore', None)]}, ('public/**', 'ignore', None)]},
zip_safe=False,
paster_plugins=['PasteScript', 'Pylons'],
entry_points=""" entry_points="""
[paste.app_factory] [paste.app_factory]
main = pyalchemybiz.config.middleware:make_app main = pyalchemybiz.config.middleware:make_app

View file

@ -12,7 +12,7 @@ error_email_from = paste@localhost
[server:main] [server:main]
use = egg:Paste#http use = egg:Paste#http
host = 0.0.0.0 host = 127.0.0.1
port = 5000 port = 5000
[app:main] [app:main]