summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--paste/default_config.conf8
-rw-r--r--paste/errormiddleware.py (renamed from paste/error_middleware.py)0
-rw-r--r--paste/makeapp.py37
-rw-r--r--paste/pyconfig.py187
-rwxr-xr-xpaste/server.py48
-rw-r--r--paste/tests/fixture.py72
-rw-r--r--paste/tests/test_error_middleware.py2
-rw-r--r--paste/webkit/conf_setup.py24
8 files changed, 176 insertions, 202 deletions
diff --git a/paste/default_config.conf b/paste/default_config.conf
index bf9ad00..d92dcff 100644
--- a/paste/default_config.conf
+++ b/paste/default_config.conf
@@ -3,3 +3,11 @@
index_names = ['index', 'Index', 'main', 'Main']
sys_path = []
framework = 'default'
+# The first middleware in this list is wrapped most closely around
+# the application:
+middleware = []
+port = 8080
+host = 'localhost'
+verbose = False
+quiet = False
+reload = False
diff --git a/paste/error_middleware.py b/paste/errormiddleware.py
index d5c2b02..d5c2b02 100644
--- a/paste/error_middleware.py
+++ b/paste/errormiddleware.py
diff --git a/paste/makeapp.py b/paste/makeapp.py
new file mode 100644
index 0000000..34d1e1c
--- /dev/null
+++ b/paste/makeapp.py
@@ -0,0 +1,37 @@
+"""
+Helper functions for framework build_application functions.
+"""
+
+from paste.util import import_string
+from paste import lint
+from paste import errormiddleware
+from paste import configmiddleware
+
+def apply_conf_middleware(app, conf, first_middleware=()):
+ """
+ Applies any middleware that the configuration specifies,
+ returning the wrapped configuration.
+
+ If first_middleware is given, this middleware is applied most
+ closely to the application (before configuration middleware).
+ """
+ all_middleware = list(first_middleware)
+ all_middleware.extend(conf.get('middleware', []))
+ for middleware in all_middleware:
+ # @@: Should this use plugins too?
+ if isinstance(middleware, (str, unicode)):
+ middleware = import_string.eval_import(middleware)
+ app = middleware(app)
+ if conf.get('lint', False):
+ app = lint.middleware(app)
+ return app
+
+def apply_default_middleware(app, conf):
+ """
+ Applies middleware that is generally always used.
+ """
+ app = errormiddleware.ErrorMiddleware(app)
+ if conf.get('lint', False):
+ app = lint.middleware(app)
+ app = configmiddleware.config_middleware(app, conf)
+ return app
diff --git a/paste/pyconfig.py b/paste/pyconfig.py
index 2f408f9..d798f6e 100644
--- a/paste/pyconfig.py
+++ b/paste/pyconfig.py
@@ -139,88 +139,23 @@ class Config(UserDict.DictMixin):
self.namespaces.insert(default, d)
else:
self.namespaces.insert(0, d)
-
- def load_commandline(self, items, bool_options, aliases={}, default=False):
- """
- Loads options from the command line. bool_options take no arguments,
- everything else is supposed to take arguments. aliases is a mapping
- of arguments to other arguments. All -'s are turned to _, like
- --config-file=... becomes config_file. Any extra arguments are
- returned as a list.
- """
- options = {}
- args = []
- while items:
- if items[0] == '--':
- args.extend(items[1:])
- break
- elif items[0].startswith('--'):
- name = items[0][2:]
- value = None
- if '=' in name:
- name, value = name.split('=', 1)
- name = aliases.get(name, name)
- if (name in bool_options
- or name.replace('-', '_') in bool_options):
- if value is not None:
- raise BadCommandLine(
- "%s does not take any arguments"
- % items[0])
- options[name] = True
- items.pop(0)
- continue
- if value is None:
- if len(items) <= 1:
- raise BadCommandLine(
- "%s takes an argument, but no argument given"
- % items[0])
- value = items[1]
- items.pop(0)
- items.pop(0)
- value = self.convert_commandline(value)
- options[name] = value
- elif items[0].startswith('-'):
- orig = items[0]
- name = items[0][1:]
- items.pop(0)
- if '=' in name:
- raise BadCommandLine(
- "Single-character options may not have arguments (%r)"
- % orig)
- for i in range(len(name)):
- op_name = aliases.get(name[i], name[i])
- if op_name in bool_options:
- options[op_name] = True
- else:
- if i != len(name)-1:
- raise BadCommandLine(
- "-%s takes an argument, it cannot be followed "
- "by other options (in %s)"
- % (name[i], orig))
- if not items:
- raise BadCommandLine(
- "-%s takes an argument, but no argument given"
- % name[i])
- value = self.convert_commandline(items[0])
- items.pop(0)
- options[op_name] = value
- break
- else:
- args.append(items[0])
- items.pop(0)
- for key in options.keys():
- options[key.replace('-', '_')] = options[key]
- self.load_dict(options, default)
+
+ def load_commandline(self, *args, **kw):
+ options, args = parse_commandline(*args, **kw)
+ self.load_dict(options)
return args
- def convert_commandline(self, value):
- try:
- return int(value)
- except ValueError:
- pass
- return value
+ def update_sys_path(self):
+ update_sys_path(self.get('sys_path'), self.get('verbose'))
+
+def setup_config(filename, add_config=None, conf=None):
+ """
+ Load the configuration with all default configs also applied,
+ and, apply sys_path.
-def setup_config(filename, add_config=None):
+ If add_config is given, this configuration (a dictionary or
+ filename) is loaded before the filename is loaded.
+ """
conf = Config(with_default=True)
if add_config:
if isinstance(add_config, (str, unicode)):
@@ -235,6 +170,8 @@ def setup_config(filename, add_config=None):
return conf
def update_sys_path(paths, verbose):
+ if paths is None:
+ return
if isinstance(paths, (str, unicode)):
paths = [paths]
for path in paths:
@@ -243,7 +180,97 @@ def update_sys_path(paths, verbose):
if verbose:
print 'Adding %s to path' % path
sys.path.insert(0, path)
-
+
+def parse_commandline(items, bool_options, aliases={}, default=False):
+ """
+ Parses options from the command line. bool_options take no
+ arguments, everything else is supposed to take arguments. aliases
+ is a mapping of arguments to other arguments. All -'s are turned
+ to _, like --config-file=... becomes config_file. Any extra
+ arguments are returned as a list.
+ """
+ options = {}
+ args = []
+ while items:
+ if items[0] == '--':
+ args.extend(items[1:])
+ break
+ elif items[0].startswith('--'):
+ name = items[0][2:]
+ value = None
+ if '=' in name:
+ name, value = name.split('=', 1)
+ name = aliases.get(name, name)
+ if (name in bool_options
+ or name.replace('-', '_') in bool_options):
+ if value is not None:
+ raise BadCommandLine(
+ "%s does not take any arguments"
+ % items[0])
+ # For things like -vv (extra verbose)
+ if options.get(name):
+ options[name] += 1
+ else:
+ options[name] = True
+ items.pop(0)
+ continue
+ if value is None:
+ if len(items) <= 1:
+ raise BadCommandLine(
+ "%s takes an argument, but no argument given"
+ % items[0])
+ value = items[1]
+ items.pop(0)
+ items.pop(0)
+ value = convert_commandline(value)
+ options[name] = value
+ elif items[0].startswith('-'):
+ orig = items[0]
+ name = items[0][1:]
+ items.pop(0)
+ if '=' in name:
+ raise BadCommandLine(
+ "Single-character options may not have arguments (%r)"
+ % orig)
+ for i in range(len(name)):
+ op_name = aliases.get(name[i], name[i])
+ if op_name in bool_options:
+ options[op_name] = True
+ else:
+ if i != len(name)-1:
+ raise BadCommandLine(
+ "-%s takes an argument, it cannot be followed "
+ "by other options (in %s)"
+ % (name[i], orig))
+ if not items:
+ raise BadCommandLine(
+ "-%s takes an argument, but no argument given"
+ % name[i])
+ value = convert_commandline(items[0])
+ items.pop(0)
+ options[op_name] = value
+ break
+ else:
+ args.append(items[0])
+ items.pop(0)
+ for key in options.keys():
+ options[key.replace('-', '_')] = options[key]
+ return options, args
+
+def convert_commandline(value):
+ """
+ Converts command-line strings to Python objects; just converting
+ integer strings to integers now.
+ """
+ # @@: In most cases we should anticipate string options and parse
+ # them appropriately, instead of this conversion which cannot be
+ # context-sensitive
+ try:
+ return int(value)
+ except ValueError:
+ pass
+ return value
+
class DispatchingConfig(object):
"""
diff --git a/paste/server.py b/paste/server.py
index 4b6c49c..a910cdd 100755
--- a/paste/server.py
+++ b/paste/server.py
@@ -29,10 +29,6 @@ OPTIONS
import sys
import os
-from paste import reloader
-from paste import wsgilib
-from paste import CONFIG
-from paste.util import plugin
# This way you can run this out of a checkout, and we'll fix up
# the path...
@@ -53,18 +49,11 @@ if os.path.dirname(here) != paste_path:
'Warning: server.py is running out of %s, but paste is loaded '
'out of %s\n' % (here, paste_path))
-from paste.pyconfig import Config
-from paste.configmiddleware import config_middleware
-from paste.webkit import wsgiwebkit
-from paste.util import thirdparty
-
-default_ops = {
- 'port': 8080,
- 'host': 'localhost',
- 'verbose': False,
- 'quiet': False,
- 'reload': False,
- }
+from paste import reloader
+from paste import wsgilib
+from paste import CONFIG
+from paste.util import plugin
+from paste import pyconfig
reloader_environ_key = 'WSGI_RELOADER_SHOULD_RUN'
@@ -72,10 +61,8 @@ default_config_fn = os.path.join(os.path.dirname(__file__),
'default_config.conf')
def load_commandline(args, allow_reload=True):
- conf = Config()
- # We use conf.verbose early, so we set it now:
- conf.load_dict(default_ops, default=True)
- args = conf.load_commandline(
+ conf = pyconfig.Config(with_default=True)
+ conf.load_commandline(
args, bool_options=['help', 'verbose', 'reload', 'debug', 'quiet',
'no_verbose'],
aliases={'h': 'help', 'v': 'verbose', 'f': 'config_file',
@@ -85,14 +72,10 @@ def load_commandline(args, allow_reload=True):
return None, 0
if conf.get('no_verbose'):
conf['verbose'] = False
- load_conf(conf, default_config_fn, True)
- reloader.watch_file(default_config_fn)
if not conf.get('no_server_conf') and os.path.exists('server.conf'):
load_conf(conf, 'server.conf', True)
- reloader.watch_file('server.conf')
if conf.get('config_file'):
load_conf(conf, conf['config_file'], True)
- reloader.watch_file(conf['config_file'])
if conf['quiet']:
conf['verbose'] = False
server = conf.get('server')
@@ -111,8 +94,7 @@ def load_commandline(args, allow_reload=True):
return restart_with_reloader(conf)
except KeyboardInterrupt:
return None, 0
- if conf.get('sys_path'):
- update_sys_path(conf['sys_path'], conf['verbose'])
+ conf.update_sys_path()
app = make_app(conf)
return conf, app
@@ -154,16 +136,6 @@ def load_conf(conf, filename, default=False):
if conf['verbose']:
print 'Loading configuration from %s' % filename
conf.load(filename, default=default)
-
-def update_sys_path(paths, verbose):
- if isinstance(paths, (str, unicode)):
- paths = [paths]
- for path in paths:
- path = os.path.abspath(path)
- if path not in sys.path:
- if verbose:
- print 'Adding %s to path' % path
- sys.path.insert(0, path)
def help():
program = sys.argv[0]
@@ -177,10 +149,6 @@ def make_app(conf):
framework_name,
'_framework')
app = framework.build_application(conf)
- if conf.get('lint'):
- import lint
- app = lint.middleware(app)
- app = config_middleware(app, conf)
return app
def restart_with_reloader(conf):
diff --git a/paste/tests/fixture.py b/paste/tests/fixture.py
index a312a52..a6245e2 100644
--- a/paste/tests/fixture.py
+++ b/paste/tests/fixture.py
@@ -50,68 +50,6 @@ class DummyMethod(object):
def __call__(self, *args, **kw):
return self.return_value
-
-# These have to be rewritten, since py.test has changed;
-# but we're not using them now anyway.
-
-# class ParamCollector(PyCollector):
-
-# def collect_function(self, extpy):
-# if not extpy.check(func=1, basestarts='test_'):
-# return
-# func = extpy.resolve()
-# if hasattr(func, 'params'):
-# params = func.params
-# for i, param in enumerate(params):
-# item = self.Item(extpy, *param)
-# item.name = item.name + '.%i' % i
-# yield item
-# else:
-# yield self.Item(extpy)
-
-# class DoctestCollector(PyCollector):
-
-# def __init__(self, extpy_or_module):
-# if isinstance(extpy_or_module, types.ModuleType):
-# self.module = extpy_or_module
-# self.extpy = None
-# else:
-# self.extpy = extpy_or_module
-# self.module = self.extpy.getpymodule()
-
-# def __call__(self, extpy):
-# # we throw it away, because this has been set up to explicitly
-# # check another module; maybe this isn't clean
-# if self.extpy is None:
-# self.extpy = extpy
-# return self
-
-# def __iter__(self):
-# finder = doctest.DocTestFinder()
-# tests = finder.find(self.module)
-# for t in tests:
-# yield DoctestItem(self.extpy, t)
-
-# class DoctestItem(DoctestCollector.Item):
-
-# def __init__(self, extpy, doctestitem, *args):
-# self.extpy = extpy
-# self.doctestitem = doctestitem
-# self.name = extpy.basename
-# self.args = args
-
-# def execute(self, driver):
-# runner = doctest.DocTestRunner()
-# driver.setup_path(self.extpy)
-# target, teardown = driver.setup_method(self.extpy)
-# try:
-# (failed, tried), run_output = capture_stdout(runner.run, self.doctestitem)
-# if failed:
-# raise self.Failed(msg=run_output, tbindex=-2)
-
-# finally:
-# if teardown:
-# teardown(target)
def capture_stdout(func, *args, **kw):
newstdout = StringIO()
@@ -154,7 +92,6 @@ def sorted(l):
l.sort()
return l
-
def fake_request(application, path_info='', use_lint=True, **environ):
"""
Runs the application in a fake environment, returning a response object
@@ -332,6 +269,9 @@ class AppError(Exception):
class TestApp(object):
+ # for py.test
+ disabled = True
+
def __init__(self, app, config={}, namespace=None):
self.app = app
self.config = config
@@ -486,6 +426,9 @@ class TestApp(object):
class TestResponse(object):
+ # for py.test
+ disabled = True
+
def __init__(self, test_app, status, headers, body, errors,
total_time):
self.test_app = test_app
@@ -600,6 +543,9 @@ class TestResponse(object):
class TestRequest(object):
+ # for py.test
+ disabled = True
+
def __init__(self, url, environ):
self.url = url
self.environ = environ
diff --git a/paste/tests/test_error_middleware.py b/paste/tests/test_error_middleware.py
index f7731ae..603e724 100644
--- a/paste/tests/test_error_middleware.py
+++ b/paste/tests/test_error_middleware.py
@@ -1,5 +1,5 @@
from fixture import *
-from paste.error_middleware import ErrorMiddleware
+from paste.errormiddleware import ErrorMiddleware
from paste import lint
def do_request(app, expect_status=500):
diff --git a/paste/webkit/conf_setup.py b/paste/webkit/conf_setup.py
index 1599997..656bea6 100644
--- a/paste/webkit/conf_setup.py
+++ b/paste/webkit/conf_setup.py
@@ -1,11 +1,10 @@
import sys
import os
+from paste import makeapp
from paste import urlparser
from paste import session
from paste import recursive
from paste import httpexceptions
-from paste import lint
-from paste import error_middleware
def build_application(conf):
if not 'publish_dir' in conf:
@@ -13,25 +12,14 @@ def build_application(conf):
sys.exit(2)
directory = conf['publish_dir']
install_fake_webware = conf.get('install_fake_webware', True)
- use_lint = conf.get('lint', False)
if install_fake_webware:
_install_fake_webware()
app = urlparser.URLParser(directory, os.path.basename(directory))
- if use_lint:
- app = lint.middleware(app)
- app = httpexceptions.middleware(app)
- if use_lint:
- app = lint.middleware(app)
- print session
- app = session.SessionMiddleware(app)
- if use_lint:
- app = lint.middleware(app)
- app = recursive.RecursiveMiddleware(app)
- if use_lint:
- app = lint.middleware(app)
- app = error_middleware.ErrorMiddleware(app)
- # I'll skip the use of lint on recursive, because it doesn't modify
- # its output much at all
+ app = makeapp.apply_conf_middleware(
+ app, conf,
+ [httpexceptions.middleware, session.SessionMiddleware,
+ recursive.RecursiveMiddleware])
+ app = makeapp.apply_default_middleware(app, conf)
return app
def install_fake_webware():