Imported from SVN by Bitbucket
This commit is contained in:
18
PasteDeploy-1.5.0-py2.6.egg/paste/__init__.py
Executable file
18
PasteDeploy-1.5.0-py2.6.egg/paste/__init__.py
Executable file
@@ -0,0 +1,18 @@
|
||||
# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
|
||||
# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
|
||||
try:
|
||||
import pkg_resources
|
||||
pkg_resources.declare_namespace(__name__)
|
||||
except ImportError:
|
||||
# don't prevent use of paste if pkg_resources isn't installed
|
||||
from pkgutil import extend_path
|
||||
__path__ = extend_path(__path__, __name__)
|
||||
|
||||
try:
|
||||
import modulefinder
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
for p in __path__:
|
||||
modulefinder.AddPackagePath(__name__, p)
|
||||
|
||||
3
PasteDeploy-1.5.0-py2.6.egg/paste/deploy/__init__.py
Executable file
3
PasteDeploy-1.5.0-py2.6.egg/paste/deploy/__init__.py
Executable file
@@ -0,0 +1,3 @@
|
||||
# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
|
||||
# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
|
||||
from paste.deploy.loadwsgi import *
|
||||
30
PasteDeploy-1.5.0-py2.6.egg/paste/deploy/compat.py
Executable file
30
PasteDeploy-1.5.0-py2.6.egg/paste/deploy/compat.py
Executable file
@@ -0,0 +1,30 @@
|
||||
# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
|
||||
# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
|
||||
"""Python 2<->3 compatibility module"""
|
||||
import sys
|
||||
|
||||
|
||||
def print_(template, *args, **kwargs):
|
||||
template = str(template)
|
||||
if args:
|
||||
template = template % args
|
||||
elif kwargs:
|
||||
template = template % kwargs
|
||||
sys.stdout.writelines(template)
|
||||
|
||||
if sys.version_info < (3, 0):
|
||||
basestring = basestring
|
||||
from ConfigParser import ConfigParser
|
||||
from urllib import unquote
|
||||
iteritems = lambda d: d.iteritems()
|
||||
|
||||
def reraise(t, e, tb):
|
||||
exec('raise t, e, tb', dict(t=t, e=e, tb=tb))
|
||||
else:
|
||||
basestring = str
|
||||
from configparser import ConfigParser
|
||||
from urllib.parse import unquote
|
||||
iteritems = lambda d: d.items()
|
||||
|
||||
def reraise(t, e, tb):
|
||||
exec('raise e from tb', dict(e=e, tb=tb))
|
||||
305
PasteDeploy-1.5.0-py2.6.egg/paste/deploy/config.py
Executable file
305
PasteDeploy-1.5.0-py2.6.egg/paste/deploy/config.py
Executable file
@@ -0,0 +1,305 @@
|
||||
# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
|
||||
# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
|
||||
"""Paste Configuration Middleware and Objects"""
|
||||
import threading
|
||||
import re
|
||||
|
||||
# Loaded lazily
|
||||
wsgilib = None
|
||||
local = None
|
||||
|
||||
__all__ = ['DispatchingConfig', 'CONFIG', 'ConfigMiddleware', 'PrefixMiddleware']
|
||||
|
||||
|
||||
def local_dict():
|
||||
global config_local, local
|
||||
try:
|
||||
return config_local.wsgi_dict
|
||||
except NameError:
|
||||
config_local = threading.local()
|
||||
config_local.wsgi_dict = result = {}
|
||||
return result
|
||||
except AttributeError:
|
||||
config_local.wsgi_dict = result = {}
|
||||
return result
|
||||
|
||||
|
||||
class DispatchingConfig(object):
|
||||
|
||||
"""
|
||||
This is a configuration object that can be used globally,
|
||||
imported, have references held onto. The configuration may differ
|
||||
by thread (or may not).
|
||||
|
||||
Specific configurations are registered (and deregistered) either
|
||||
for the process or for threads.
|
||||
"""
|
||||
|
||||
# @@: What should happen when someone tries to add this
|
||||
# configuration to itself? Probably the conf should become
|
||||
# resolved, and get rid of this delegation wrapper
|
||||
|
||||
_constructor_lock = threading.Lock()
|
||||
|
||||
def __init__(self):
|
||||
self._constructor_lock.acquire()
|
||||
try:
|
||||
self.dispatching_id = 0
|
||||
while 1:
|
||||
self._local_key = 'paste.processconfig_%i' % self.dispatching_id
|
||||
if not self._local_key in local_dict():
|
||||
break
|
||||
self.dispatching_id += 1
|
||||
finally:
|
||||
self._constructor_lock.release()
|
||||
self._process_configs = []
|
||||
|
||||
def push_thread_config(self, conf):
|
||||
"""
|
||||
Make ``conf`` the active configuration for this thread.
|
||||
Thread-local configuration always overrides process-wide
|
||||
configuration.
|
||||
|
||||
This should be used like::
|
||||
|
||||
conf = make_conf()
|
||||
dispatching_config.push_thread_config(conf)
|
||||
try:
|
||||
... do stuff ...
|
||||
finally:
|
||||
dispatching_config.pop_thread_config(conf)
|
||||
"""
|
||||
local_dict().setdefault(self._local_key, []).append(conf)
|
||||
|
||||
def pop_thread_config(self, conf=None):
|
||||
"""
|
||||
Remove a thread-local configuration. If ``conf`` is given,
|
||||
it is checked against the popped configuration and an error
|
||||
is emitted if they don't match.
|
||||
"""
|
||||
self._pop_from(local_dict()[self._local_key], conf)
|
||||
|
||||
def _pop_from(self, lst, conf):
|
||||
popped = lst.pop()
|
||||
if conf is not None and popped is not conf:
|
||||
raise AssertionError(
|
||||
"The config popped (%s) is not the same as the config "
|
||||
"expected (%s)"
|
||||
% (popped, conf))
|
||||
|
||||
def push_process_config(self, conf):
|
||||
"""
|
||||
Like push_thread_config, but applies the configuration to
|
||||
the entire process.
|
||||
"""
|
||||
self._process_configs.append(conf)
|
||||
|
||||
def pop_process_config(self, conf=None):
|
||||
self._pop_from(self._process_configs, conf)
|
||||
|
||||
def __getattr__(self, attr):
|
||||
conf = self.current_conf()
|
||||
if conf is None:
|
||||
raise AttributeError(
|
||||
"No configuration has been registered for this process "
|
||||
"or thread")
|
||||
return getattr(conf, attr)
|
||||
|
||||
def current_conf(self):
|
||||
thread_configs = local_dict().get(self._local_key)
|
||||
if thread_configs:
|
||||
return thread_configs[-1]
|
||||
elif self._process_configs:
|
||||
return self._process_configs[-1]
|
||||
else:
|
||||
return None
|
||||
|
||||
def __getitem__(self, key):
|
||||
# I thought __getattr__ would catch this, but apparently not
|
||||
conf = self.current_conf()
|
||||
if conf is None:
|
||||
raise TypeError(
|
||||
"No configuration has been registered for this process "
|
||||
"or thread")
|
||||
return conf[key]
|
||||
|
||||
def __contains__(self, key):
|
||||
# I thought __getattr__ would catch this, but apparently not
|
||||
return key in self
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
# I thought __getattr__ would catch this, but apparently not
|
||||
conf = self.current_conf()
|
||||
conf[key] = value
|
||||
|
||||
CONFIG = DispatchingConfig()
|
||||
|
||||
|
||||
class ConfigMiddleware(object):
|
||||
|
||||
"""
|
||||
A WSGI middleware that adds a ``paste.config`` key to the request
|
||||
environment, as well as registering the configuration temporarily
|
||||
(for the length of the request) with ``paste.CONFIG``.
|
||||
"""
|
||||
|
||||
def __init__(self, application, config):
|
||||
"""
|
||||
This delegates all requests to `application`, adding a *copy*
|
||||
of the configuration `config`.
|
||||
"""
|
||||
self.application = application
|
||||
self.config = config
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
global wsgilib
|
||||
if wsgilib is None:
|
||||
import pkg_resources
|
||||
pkg_resources.require('Paste')
|
||||
from paste import wsgilib
|
||||
popped_config = None
|
||||
if 'paste.config' in environ:
|
||||
popped_config = environ['paste.config']
|
||||
conf = environ['paste.config'] = self.config.copy()
|
||||
app_iter = None
|
||||
CONFIG.push_thread_config(conf)
|
||||
try:
|
||||
app_iter = self.application(environ, start_response)
|
||||
finally:
|
||||
if app_iter is None:
|
||||
# An error occurred...
|
||||
CONFIG.pop_thread_config(conf)
|
||||
if popped_config is not None:
|
||||
environ['paste.config'] = popped_config
|
||||
if type(app_iter) in (list, tuple):
|
||||
# Because it is a concrete iterator (not a generator) we
|
||||
# know the configuration for this thread is no longer
|
||||
# needed:
|
||||
CONFIG.pop_thread_config(conf)
|
||||
if popped_config is not None:
|
||||
environ['paste.config'] = popped_config
|
||||
return app_iter
|
||||
else:
|
||||
def close_config():
|
||||
CONFIG.pop_thread_config(conf)
|
||||
new_app_iter = wsgilib.add_close(app_iter, close_config)
|
||||
return new_app_iter
|
||||
|
||||
|
||||
def make_config_filter(app, global_conf, **local_conf):
|
||||
conf = global_conf.copy()
|
||||
conf.update(local_conf)
|
||||
return ConfigMiddleware(app, conf)
|
||||
|
||||
make_config_middleware = ConfigMiddleware.__doc__
|
||||
|
||||
|
||||
class PrefixMiddleware(object):
|
||||
"""Translate a given prefix into a SCRIPT_NAME for the filtered
|
||||
application.
|
||||
|
||||
PrefixMiddleware provides a way to manually override the root prefix
|
||||
(SCRIPT_NAME) of your application for certain, rare situations.
|
||||
|
||||
When running an application under a prefix (such as '/james') in
|
||||
FastCGI/apache, the SCRIPT_NAME environment variable is automatically
|
||||
set to to the appropriate value: '/james'. Pylons' URL generating
|
||||
functions, such as url_for, always take the SCRIPT_NAME value into account.
|
||||
|
||||
One situation where PrefixMiddleware is required is when an application
|
||||
is accessed via a reverse proxy with a prefix. The application is accessed
|
||||
through the reverse proxy via the the URL prefix '/james', whereas the
|
||||
reverse proxy forwards those requests to the application at the prefix '/'.
|
||||
|
||||
The reverse proxy, being an entirely separate web server, has no way of
|
||||
specifying the SCRIPT_NAME variable; it must be manually set by a
|
||||
PrefixMiddleware instance. Without setting SCRIPT_NAME, url_for will
|
||||
generate URLs such as: '/purchase_orders/1', when it should be
|
||||
generating: '/james/purchase_orders/1'.
|
||||
|
||||
To filter your application through a PrefixMiddleware instance, add the
|
||||
following to the '[app:main]' section of your .ini file:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
filter-with = proxy-prefix
|
||||
|
||||
[filter:proxy-prefix]
|
||||
use = egg:PasteDeploy#prefix
|
||||
prefix = /james
|
||||
|
||||
The name ``proxy-prefix`` simply acts as an identifier of the filter
|
||||
section; feel free to rename it.
|
||||
|
||||
Also, unless disabled, the ``X-Forwarded-Server`` header will be
|
||||
translated to the ``Host`` header, for cases when that header is
|
||||
lost in the proxying. Also ``X-Forwarded-Host``,
|
||||
``X-Forwarded-Scheme``, and ``X-Forwarded-Proto`` are translated.
|
||||
|
||||
If ``force_port`` is set, SERVER_PORT and HTTP_HOST will be
|
||||
rewritten with the given port. You can use a number, string (like
|
||||
'80') or the empty string (whatever is the default port for the
|
||||
scheme). This is useful in situations where there is port
|
||||
forwarding going on, and the server believes itself to be on a
|
||||
different port than what the outside world sees.
|
||||
|
||||
You can also use ``scheme`` to explicitly set the scheme (like
|
||||
``scheme = https``).
|
||||
"""
|
||||
def __init__(self, app, global_conf=None, prefix='/',
|
||||
translate_forwarded_server=True,
|
||||
force_port=None, scheme=None):
|
||||
self.app = app
|
||||
self.prefix = prefix.rstrip('/')
|
||||
self.translate_forwarded_server = translate_forwarded_server
|
||||
self.regprefix = re.compile("^%s(.*)$" % self.prefix)
|
||||
self.force_port = force_port
|
||||
self.scheme = scheme
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
url = environ['PATH_INFO']
|
||||
url = re.sub(self.regprefix, r'\1', url)
|
||||
if not url:
|
||||
url = '/'
|
||||
environ['PATH_INFO'] = url
|
||||
environ['SCRIPT_NAME'] = self.prefix
|
||||
if self.translate_forwarded_server:
|
||||
if 'HTTP_X_FORWARDED_SERVER' in environ:
|
||||
environ['SERVER_NAME'] = environ['HTTP_HOST'] = environ.pop('HTTP_X_FORWARDED_SERVER').split(',')[0]
|
||||
if 'HTTP_X_FORWARDED_HOST' in environ:
|
||||
environ['HTTP_HOST'] = environ.pop('HTTP_X_FORWARDED_HOST').split(',')[0]
|
||||
if 'HTTP_X_FORWARDED_FOR' in environ:
|
||||
environ['REMOTE_ADDR'] = environ.pop('HTTP_X_FORWARDED_FOR')
|
||||
if 'HTTP_X_FORWARDED_SCHEME' in environ:
|
||||
environ['wsgi.url_scheme'] = environ.pop('HTTP_X_FORWARDED_SCHEME')
|
||||
elif 'HTTP_X_FORWARDED_PROTO' in environ:
|
||||
environ['wsgi.url_scheme'] = environ.pop('HTTP_X_FORWARDED_PROTO')
|
||||
if self.force_port is not None:
|
||||
host = environ.get('HTTP_HOST', '').split(':', 1)[0]
|
||||
if self.force_port:
|
||||
host = '%s:%s' % (host, self.force_port)
|
||||
environ['SERVER_PORT'] = str(self.force_port)
|
||||
else:
|
||||
if environ['wsgi.url_scheme'] == 'http':
|
||||
port = '80'
|
||||
else:
|
||||
port = '443'
|
||||
environ['SERVER_PORT'] = port
|
||||
environ['HTTP_HOST'] = host
|
||||
if self.scheme is not None:
|
||||
environ['wsgi.url_scheme'] = self.scheme
|
||||
return self.app(environ, start_response)
|
||||
|
||||
|
||||
def make_prefix_middleware(
|
||||
app, global_conf, prefix='/',
|
||||
translate_forwarded_server=True,
|
||||
force_port=None, scheme=None):
|
||||
from paste.deploy.converters import asbool
|
||||
translate_forwarded_server = asbool(translate_forwarded_server)
|
||||
return PrefixMiddleware(
|
||||
app, prefix=prefix,
|
||||
translate_forwarded_server=translate_forwarded_server,
|
||||
force_port=force_port, scheme=scheme)
|
||||
|
||||
make_prefix_middleware.__doc__ = PrefixMiddleware.__doc__
|
||||
36
PasteDeploy-1.5.0-py2.6.egg/paste/deploy/converters.py
Executable file
36
PasteDeploy-1.5.0-py2.6.egg/paste/deploy/converters.py
Executable file
@@ -0,0 +1,36 @@
|
||||
# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
|
||||
# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
|
||||
from paste.deploy.compat import basestring
|
||||
|
||||
|
||||
def asbool(obj):
|
||||
if isinstance(obj, basestring):
|
||||
obj = obj.strip().lower()
|
||||
if obj in ['true', 'yes', 'on', 'y', 't', '1']:
|
||||
return True
|
||||
elif obj in ['false', 'no', 'off', 'n', 'f', '0']:
|
||||
return False
|
||||
else:
|
||||
raise ValueError("String is not true/false: %r" % obj)
|
||||
return bool(obj)
|
||||
|
||||
|
||||
def asint(obj):
|
||||
try:
|
||||
return int(obj)
|
||||
except (TypeError, ValueError):
|
||||
raise ValueError("Bad integer value: %r" % obj)
|
||||
|
||||
|
||||
def aslist(obj, sep=None, strip=True):
|
||||
if isinstance(obj, basestring):
|
||||
lst = obj.split(sep)
|
||||
if strip:
|
||||
lst = [v.strip() for v in lst]
|
||||
return lst
|
||||
elif isinstance(obj, (list, tuple)):
|
||||
return obj
|
||||
elif obj is None:
|
||||
return []
|
||||
else:
|
||||
return [obj]
|
||||
725
PasteDeploy-1.5.0-py2.6.egg/paste/deploy/loadwsgi.py
Executable file
725
PasteDeploy-1.5.0-py2.6.egg/paste/deploy/loadwsgi.py
Executable file
@@ -0,0 +1,725 @@
|
||||
# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
|
||||
# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
|
||||
from __future__ import with_statement
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
|
||||
import pkg_resources
|
||||
|
||||
from paste.deploy.compat import ConfigParser, unquote, iteritems
|
||||
from paste.deploy.util import fix_call, lookup_object
|
||||
|
||||
__all__ = ['loadapp', 'loadserver', 'loadfilter', 'appconfig']
|
||||
|
||||
|
||||
############################################################
|
||||
## Utility functions
|
||||
############################################################
|
||||
|
||||
|
||||
def import_string(s):
|
||||
return pkg_resources.EntryPoint.parse("x=" + s).load(False)
|
||||
|
||||
|
||||
def _aslist(obj):
|
||||
"""
|
||||
Turn object into a list; lists and tuples are left as-is, None
|
||||
becomes [], and everything else turns into a one-element list.
|
||||
"""
|
||||
if obj is None:
|
||||
return []
|
||||
elif isinstance(obj, (list, tuple)):
|
||||
return obj
|
||||
else:
|
||||
return [obj]
|
||||
|
||||
|
||||
def _flatten(lst):
|
||||
"""
|
||||
Flatten a nested list.
|
||||
"""
|
||||
if not isinstance(lst, (list, tuple)):
|
||||
return [lst]
|
||||
result = []
|
||||
for item in lst:
|
||||
result.extend(_flatten(item))
|
||||
return result
|
||||
|
||||
|
||||
class NicerConfigParser(ConfigParser):
|
||||
|
||||
def __init__(self, filename, *args, **kw):
|
||||
ConfigParser.__init__(self, *args, **kw)
|
||||
self.filename = filename
|
||||
if hasattr(self, '_interpolation'):
|
||||
self._interpolation = self.InterpolateWrapper(self._interpolation)
|
||||
|
||||
read_file = getattr(ConfigParser, 'read_file', ConfigParser.readfp)
|
||||
|
||||
def defaults(self):
|
||||
"""Return the defaults, with their values interpolated (with the
|
||||
defaults dict itself)
|
||||
|
||||
Mainly to support defaults using values such as %(here)s
|
||||
"""
|
||||
defaults = ConfigParser.defaults(self).copy()
|
||||
for key, val in iteritems(defaults):
|
||||
defaults[key] = self.get('DEFAULT', key) or val
|
||||
return defaults
|
||||
|
||||
def _interpolate(self, section, option, rawval, vars):
|
||||
# Python < 3.2
|
||||
try:
|
||||
return ConfigParser._interpolate(
|
||||
self, section, option, rawval, vars)
|
||||
except Exception:
|
||||
e = sys.exc_info()[1]
|
||||
args = list(e.args)
|
||||
args[0] = 'Error in file %s: %s' % (self.filename, e)
|
||||
e.args = tuple(args)
|
||||
e.message = args[0]
|
||||
raise
|
||||
|
||||
class InterpolateWrapper(object):
|
||||
# Python >= 3.2
|
||||
def __init__(self, original):
|
||||
self._original = original
|
||||
|
||||
def __getattr__(self, name):
|
||||
return getattr(self._original, name)
|
||||
|
||||
def before_get(self, parser, section, option, value, defaults):
|
||||
try:
|
||||
return self._original.before_get(parser, section, option,
|
||||
value, defaults)
|
||||
except Exception:
|
||||
e = sys.exc_info()[1]
|
||||
args = list(e.args)
|
||||
args[0] = 'Error in file %s: %s' % (parser.filename, e)
|
||||
e.args = tuple(args)
|
||||
e.message = args[0]
|
||||
raise
|
||||
|
||||
|
||||
############################################################
|
||||
## Object types
|
||||
############################################################
|
||||
|
||||
|
||||
class _ObjectType(object):
|
||||
|
||||
name = None
|
||||
egg_protocols = None
|
||||
config_prefixes = None
|
||||
|
||||
def __init__(self):
|
||||
# Normalize these variables:
|
||||
self.egg_protocols = [_aslist(p) for p in _aslist(self.egg_protocols)]
|
||||
self.config_prefixes = [_aslist(p) for p in _aslist(self.config_prefixes)]
|
||||
|
||||
def __repr__(self):
|
||||
return '<%s protocols=%r prefixes=%r>' % (
|
||||
self.name, self.egg_protocols, self.config_prefixes)
|
||||
|
||||
def invoke(self, context):
|
||||
assert context.protocol in _flatten(self.egg_protocols)
|
||||
return fix_call(context.object,
|
||||
context.global_conf, **context.local_conf)
|
||||
|
||||
|
||||
class _App(_ObjectType):
|
||||
|
||||
name = 'application'
|
||||
egg_protocols = ['paste.app_factory', 'paste.composite_factory',
|
||||
'paste.composit_factory']
|
||||
config_prefixes = [['app', 'application'], ['composite', 'composit'],
|
||||
'pipeline', 'filter-app']
|
||||
|
||||
def invoke(self, context):
|
||||
if context.protocol in ('paste.composit_factory',
|
||||
'paste.composite_factory'):
|
||||
return fix_call(context.object,
|
||||
context.loader, context.global_conf,
|
||||
**context.local_conf)
|
||||
elif context.protocol == 'paste.app_factory':
|
||||
return fix_call(context.object, context.global_conf, **context.local_conf)
|
||||
else:
|
||||
assert 0, "Protocol %r unknown" % context.protocol
|
||||
|
||||
APP = _App()
|
||||
|
||||
|
||||
class _Filter(_ObjectType):
|
||||
name = 'filter'
|
||||
egg_protocols = [['paste.filter_factory', 'paste.filter_app_factory']]
|
||||
config_prefixes = ['filter']
|
||||
|
||||
def invoke(self, context):
|
||||
if context.protocol == 'paste.filter_factory':
|
||||
return fix_call(context.object,
|
||||
context.global_conf, **context.local_conf)
|
||||
elif context.protocol == 'paste.filter_app_factory':
|
||||
def filter_wrapper(wsgi_app):
|
||||
# This should be an object, so it has a nicer __repr__
|
||||
return fix_call(context.object,
|
||||
wsgi_app, context.global_conf,
|
||||
**context.local_conf)
|
||||
return filter_wrapper
|
||||
else:
|
||||
assert 0, "Protocol %r unknown" % context.protocol
|
||||
|
||||
FILTER = _Filter()
|
||||
|
||||
|
||||
class _Server(_ObjectType):
|
||||
name = 'server'
|
||||
egg_protocols = [['paste.server_factory', 'paste.server_runner']]
|
||||
config_prefixes = ['server']
|
||||
|
||||
def invoke(self, context):
|
||||
if context.protocol == 'paste.server_factory':
|
||||
return fix_call(context.object,
|
||||
context.global_conf, **context.local_conf)
|
||||
elif context.protocol == 'paste.server_runner':
|
||||
def server_wrapper(wsgi_app):
|
||||
# This should be an object, so it has a nicer __repr__
|
||||
return fix_call(context.object,
|
||||
wsgi_app, context.global_conf,
|
||||
**context.local_conf)
|
||||
return server_wrapper
|
||||
else:
|
||||
assert 0, "Protocol %r unknown" % context.protocol
|
||||
|
||||
SERVER = _Server()
|
||||
|
||||
|
||||
# Virtual type: (@@: There's clearly something crufty here;
|
||||
# this probably could be more elegant)
|
||||
class _PipeLine(_ObjectType):
|
||||
name = 'pipeline'
|
||||
|
||||
def invoke(self, context):
|
||||
app = context.app_context.create()
|
||||
filters = [c.create() for c in context.filter_contexts]
|
||||
filters.reverse()
|
||||
for filter in filters:
|
||||
app = filter(app)
|
||||
return app
|
||||
|
||||
PIPELINE = _PipeLine()
|
||||
|
||||
|
||||
class _FilterApp(_ObjectType):
|
||||
name = 'filter_app'
|
||||
|
||||
def invoke(self, context):
|
||||
next_app = context.next_context.create()
|
||||
filter = context.filter_context.create()
|
||||
return filter(next_app)
|
||||
|
||||
FILTER_APP = _FilterApp()
|
||||
|
||||
|
||||
class _FilterWith(_App):
|
||||
name = 'filtered_with'
|
||||
|
||||
def invoke(self, context):
|
||||
filter = context.filter_context.create()
|
||||
filtered = context.next_context.create()
|
||||
if context.next_context.object_type is APP:
|
||||
return filter(filtered)
|
||||
else:
|
||||
# filtering a filter
|
||||
def composed(app):
|
||||
return filter(filtered(app))
|
||||
return composed
|
||||
|
||||
FILTER_WITH = _FilterWith()
|
||||
|
||||
|
||||
############################################################
|
||||
## Loaders
|
||||
############################################################
|
||||
|
||||
|
||||
def loadapp(uri, name=None, **kw):
|
||||
return loadobj(APP, uri, name=name, **kw)
|
||||
|
||||
|
||||
def loadfilter(uri, name=None, **kw):
|
||||
return loadobj(FILTER, uri, name=name, **kw)
|
||||
|
||||
|
||||
def loadserver(uri, name=None, **kw):
|
||||
return loadobj(SERVER, uri, name=name, **kw)
|
||||
|
||||
|
||||
def appconfig(uri, name=None, relative_to=None, global_conf=None):
|
||||
context = loadcontext(APP, uri, name=name,
|
||||
relative_to=relative_to,
|
||||
global_conf=global_conf)
|
||||
return context.config()
|
||||
|
||||
_loaders = {}
|
||||
|
||||
|
||||
def loadobj(object_type, uri, name=None, relative_to=None,
|
||||
global_conf=None):
|
||||
context = loadcontext(
|
||||
object_type, uri, name=name, relative_to=relative_to,
|
||||
global_conf=global_conf)
|
||||
return context.create()
|
||||
|
||||
|
||||
def loadcontext(object_type, uri, name=None, relative_to=None,
|
||||
global_conf=None):
|
||||
if '#' in uri:
|
||||
if name is None:
|
||||
uri, name = uri.split('#', 1)
|
||||
else:
|
||||
# @@: Ignore fragment or error?
|
||||
uri = uri.split('#', 1)[0]
|
||||
if name is None:
|
||||
name = 'main'
|
||||
if ':' not in uri:
|
||||
raise LookupError("URI has no scheme: %r" % uri)
|
||||
scheme, path = uri.split(':', 1)
|
||||
scheme = scheme.lower()
|
||||
if scheme not in _loaders:
|
||||
raise LookupError(
|
||||
"URI scheme not known: %r (from %s)"
|
||||
% (scheme, ', '.join(_loaders.keys())))
|
||||
return _loaders[scheme](
|
||||
object_type,
|
||||
uri, path, name=name, relative_to=relative_to,
|
||||
global_conf=global_conf)
|
||||
|
||||
|
||||
def _loadconfig(object_type, uri, path, name, relative_to,
|
||||
global_conf):
|
||||
isabs = os.path.isabs(path)
|
||||
# De-Windowsify the paths:
|
||||
path = path.replace('\\', '/')
|
||||
if not isabs:
|
||||
if not relative_to:
|
||||
raise ValueError(
|
||||
"Cannot resolve relative uri %r; no relative_to keyword "
|
||||
"argument given" % uri)
|
||||
relative_to = relative_to.replace('\\', '/')
|
||||
if relative_to.endswith('/'):
|
||||
path = relative_to + path
|
||||
else:
|
||||
path = relative_to + '/' + path
|
||||
if path.startswith('///'):
|
||||
path = path[2:]
|
||||
path = unquote(path)
|
||||
loader = ConfigLoader(path)
|
||||
if global_conf:
|
||||
loader.update_defaults(global_conf, overwrite=False)
|
||||
return loader.get_context(object_type, name, global_conf)
|
||||
|
||||
_loaders['config'] = _loadconfig
|
||||
|
||||
|
||||
def _loadegg(object_type, uri, spec, name, relative_to,
|
||||
global_conf):
|
||||
loader = EggLoader(spec)
|
||||
return loader.get_context(object_type, name, global_conf)
|
||||
|
||||
_loaders['egg'] = _loadegg
|
||||
|
||||
|
||||
def _loadfunc(object_type, uri, spec, name, relative_to,
|
||||
global_conf):
|
||||
|
||||
loader = FuncLoader(spec)
|
||||
return loader.get_context(object_type, name, global_conf)
|
||||
|
||||
_loaders['call'] = _loadfunc
|
||||
|
||||
############################################################
|
||||
## Loaders
|
||||
############################################################
|
||||
|
||||
|
||||
class _Loader(object):
|
||||
|
||||
def get_app(self, name=None, global_conf=None):
|
||||
return self.app_context(
|
||||
name=name, global_conf=global_conf).create()
|
||||
|
||||
def get_filter(self, name=None, global_conf=None):
|
||||
return self.filter_context(
|
||||
name=name, global_conf=global_conf).create()
|
||||
|
||||
def get_server(self, name=None, global_conf=None):
|
||||
return self.server_context(
|
||||
name=name, global_conf=global_conf).create()
|
||||
|
||||
def app_context(self, name=None, global_conf=None):
|
||||
return self.get_context(
|
||||
APP, name=name, global_conf=global_conf)
|
||||
|
||||
def filter_context(self, name=None, global_conf=None):
|
||||
return self.get_context(
|
||||
FILTER, name=name, global_conf=global_conf)
|
||||
|
||||
def server_context(self, name=None, global_conf=None):
|
||||
return self.get_context(
|
||||
SERVER, name=name, global_conf=global_conf)
|
||||
|
||||
_absolute_re = re.compile(r'^[a-zA-Z]+:')
|
||||
|
||||
def absolute_name(self, name):
|
||||
"""
|
||||
Returns true if the name includes a scheme
|
||||
"""
|
||||
if name is None:
|
||||
return False
|
||||
return self._absolute_re.search(name)
|
||||
|
||||
|
||||
class ConfigLoader(_Loader):
|
||||
|
||||
def __init__(self, filename):
|
||||
self.filename = filename = filename.strip()
|
||||
defaults = {
|
||||
'here': os.path.dirname(os.path.abspath(filename)),
|
||||
'__file__': os.path.abspath(filename)
|
||||
}
|
||||
self.parser = NicerConfigParser(filename, defaults=defaults)
|
||||
self.parser.optionxform = str # Don't lower-case keys
|
||||
with open(filename) as f:
|
||||
self.parser.read_file(f)
|
||||
|
||||
def update_defaults(self, new_defaults, overwrite=True):
|
||||
for key, value in iteritems(new_defaults):
|
||||
if not overwrite and key in self.parser._defaults:
|
||||
continue
|
||||
self.parser._defaults[key] = value
|
||||
|
||||
def get_context(self, object_type, name=None, global_conf=None):
|
||||
if self.absolute_name(name):
|
||||
return loadcontext(object_type, name,
|
||||
relative_to=os.path.dirname(self.filename),
|
||||
global_conf=global_conf)
|
||||
section = self.find_config_section(
|
||||
object_type, name=name)
|
||||
if global_conf is None:
|
||||
global_conf = {}
|
||||
else:
|
||||
global_conf = global_conf.copy()
|
||||
defaults = self.parser.defaults()
|
||||
global_conf.update(defaults)
|
||||
local_conf = {}
|
||||
global_additions = {}
|
||||
get_from_globals = {}
|
||||
for option in self.parser.options(section):
|
||||
if option.startswith('set '):
|
||||
name = option[4:].strip()
|
||||
global_additions[name] = global_conf[name] = (
|
||||
self.parser.get(section, option))
|
||||
elif option.startswith('get '):
|
||||
name = option[4:].strip()
|
||||
get_from_globals[name] = self.parser.get(section, option)
|
||||
else:
|
||||
if option in defaults:
|
||||
# @@: It's a global option (?), so skip it
|
||||
continue
|
||||
local_conf[option] = self.parser.get(section, option)
|
||||
for local_var, glob_var in get_from_globals.items():
|
||||
local_conf[local_var] = global_conf[glob_var]
|
||||
if object_type in (APP, FILTER) and 'filter-with' in local_conf:
|
||||
filter_with = local_conf.pop('filter-with')
|
||||
else:
|
||||
filter_with = None
|
||||
if 'require' in local_conf:
|
||||
for spec in local_conf['require'].split():
|
||||
pkg_resources.require(spec)
|
||||
del local_conf['require']
|
||||
if section.startswith('filter-app:'):
|
||||
context = self._filter_app_context(
|
||||
object_type, section, name=name,
|
||||
global_conf=global_conf, local_conf=local_conf,
|
||||
global_additions=global_additions)
|
||||
elif section.startswith('pipeline:'):
|
||||
context = self._pipeline_app_context(
|
||||
object_type, section, name=name,
|
||||
global_conf=global_conf, local_conf=local_conf,
|
||||
global_additions=global_additions)
|
||||
elif 'use' in local_conf:
|
||||
context = self._context_from_use(
|
||||
object_type, local_conf, global_conf, global_additions,
|
||||
section)
|
||||
else:
|
||||
context = self._context_from_explicit(
|
||||
object_type, local_conf, global_conf, global_additions,
|
||||
section)
|
||||
if filter_with is not None:
|
||||
filter_with_context = LoaderContext(
|
||||
obj=None,
|
||||
object_type=FILTER_WITH,
|
||||
protocol=None,
|
||||
global_conf=global_conf, local_conf=local_conf,
|
||||
loader=self)
|
||||
filter_with_context.filter_context = self.filter_context(
|
||||
name=filter_with, global_conf=global_conf)
|
||||
filter_with_context.next_context = context
|
||||
return filter_with_context
|
||||
return context
|
||||
|
||||
def _context_from_use(self, object_type, local_conf, global_conf,
|
||||
global_additions, section):
|
||||
use = local_conf.pop('use')
|
||||
context = self.get_context(
|
||||
object_type, name=use, global_conf=global_conf)
|
||||
context.global_conf.update(global_additions)
|
||||
context.local_conf.update(local_conf)
|
||||
if '__file__' in global_conf:
|
||||
# use sections shouldn't overwrite the original __file__
|
||||
context.global_conf['__file__'] = global_conf['__file__']
|
||||
# @@: Should loader be overwritten?
|
||||
context.loader = self
|
||||
|
||||
if context.protocol is None:
|
||||
# Determine protocol from section type
|
||||
section_protocol = section.split(':', 1)[0]
|
||||
if section_protocol in ('application', 'app'):
|
||||
context.protocol = 'paste.app_factory'
|
||||
elif section_protocol in ('composit', 'composite'):
|
||||
context.protocol = 'paste.composit_factory'
|
||||
else:
|
||||
# This will work with 'server' and 'filter', otherwise it
|
||||
# could fail but there is an error message already for
|
||||
# bad protocols
|
||||
context.protocol = 'paste.%s_factory' % context_protocol
|
||||
|
||||
return context
|
||||
|
||||
def _context_from_explicit(self, object_type, local_conf, global_conf,
|
||||
global_addition, section):
|
||||
possible = []
|
||||
for protocol_options in object_type.egg_protocols:
|
||||
for protocol in protocol_options:
|
||||
if protocol in local_conf:
|
||||
possible.append((protocol, local_conf[protocol]))
|
||||
break
|
||||
if len(possible) > 1:
|
||||
raise LookupError(
|
||||
"Multiple protocols given in section %r: %s"
|
||||
% (section, possible))
|
||||
if not possible:
|
||||
raise LookupError(
|
||||
"No loader given in section %r" % section)
|
||||
found_protocol, found_expr = possible[0]
|
||||
del local_conf[found_protocol]
|
||||
value = import_string(found_expr)
|
||||
context = LoaderContext(
|
||||
value, object_type, found_protocol,
|
||||
global_conf, local_conf, self)
|
||||
return context
|
||||
|
||||
def _filter_app_context(self, object_type, section, name,
|
||||
global_conf, local_conf, global_additions):
|
||||
if 'next' not in local_conf:
|
||||
raise LookupError(
|
||||
"The [%s] section in %s is missing a 'next' setting"
|
||||
% (section, self.filename))
|
||||
next_name = local_conf.pop('next')
|
||||
context = LoaderContext(None, FILTER_APP, None, global_conf,
|
||||
local_conf, self)
|
||||
context.next_context = self.get_context(
|
||||
APP, next_name, global_conf)
|
||||
if 'use' in local_conf:
|
||||
context.filter_context = self._context_from_use(
|
||||
FILTER, local_conf, global_conf, global_additions,
|
||||
section)
|
||||
else:
|
||||
context.filter_context = self._context_from_explicit(
|
||||
FILTER, local_conf, global_conf, global_additions,
|
||||
section)
|
||||
return context
|
||||
|
||||
def _pipeline_app_context(self, object_type, section, name,
|
||||
global_conf, local_conf, global_additions):
|
||||
if 'pipeline' not in local_conf:
|
||||
raise LookupError(
|
||||
"The [%s] section in %s is missing a 'pipeline' setting"
|
||||
% (section, self.filename))
|
||||
pipeline = local_conf.pop('pipeline').split()
|
||||
if local_conf:
|
||||
raise LookupError(
|
||||
"The [%s] pipeline section in %s has extra "
|
||||
"(disallowed) settings: %s"
|
||||
% (', '.join(local_conf.keys())))
|
||||
context = LoaderContext(None, PIPELINE, None, global_conf,
|
||||
local_conf, self)
|
||||
context.app_context = self.get_context(
|
||||
APP, pipeline[-1], global_conf)
|
||||
context.filter_contexts = [
|
||||
self.get_context(FILTER, name, global_conf)
|
||||
for name in pipeline[:-1]]
|
||||
return context
|
||||
|
||||
def find_config_section(self, object_type, name=None):
|
||||
"""
|
||||
Return the section name with the given name prefix (following the
|
||||
same pattern as ``protocol_desc`` in ``config``. It must have the
|
||||
given name, or for ``'main'`` an empty name is allowed. The
|
||||
prefix must be followed by a ``:``.
|
||||
|
||||
Case is *not* ignored.
|
||||
"""
|
||||
possible = []
|
||||
for name_options in object_type.config_prefixes:
|
||||
for name_prefix in name_options:
|
||||
found = self._find_sections(
|
||||
self.parser.sections(), name_prefix, name)
|
||||
if found:
|
||||
possible.extend(found)
|
||||
break
|
||||
if not possible:
|
||||
raise LookupError(
|
||||
"No section %r (prefixed by %s) found in config %s"
|
||||
% (name,
|
||||
' or '.join(map(repr, _flatten(object_type.config_prefixes))),
|
||||
self.filename))
|
||||
if len(possible) > 1:
|
||||
raise LookupError(
|
||||
"Ambiguous section names %r for section %r (prefixed by %s) "
|
||||
"found in config %s"
|
||||
% (possible, name,
|
||||
' or '.join(map(repr, _flatten(object_type.config_prefixes))),
|
||||
self.filename))
|
||||
return possible[0]
|
||||
|
||||
def _find_sections(self, sections, name_prefix, name):
|
||||
found = []
|
||||
if name is None:
|
||||
if name_prefix in sections:
|
||||
found.append(name_prefix)
|
||||
name = 'main'
|
||||
for section in sections:
|
||||
if section.startswith(name_prefix + ':'):
|
||||
if section[len(name_prefix) + 1:].strip() == name:
|
||||
found.append(section)
|
||||
return found
|
||||
|
||||
|
||||
class EggLoader(_Loader):
|
||||
|
||||
def __init__(self, spec):
|
||||
self.spec = spec
|
||||
|
||||
def get_context(self, object_type, name=None, global_conf=None):
|
||||
if self.absolute_name(name):
|
||||
return loadcontext(object_type, name,
|
||||
global_conf=global_conf)
|
||||
entry_point, protocol, ep_name = self.find_egg_entry_point(
|
||||
object_type, name=name)
|
||||
return LoaderContext(
|
||||
entry_point,
|
||||
object_type,
|
||||
protocol,
|
||||
global_conf or {}, {},
|
||||
self,
|
||||
distribution=pkg_resources.get_distribution(self.spec),
|
||||
entry_point_name=ep_name)
|
||||
|
||||
def find_egg_entry_point(self, object_type, name=None):
|
||||
"""
|
||||
Returns the (entry_point, protocol) for the with the given
|
||||
``name``.
|
||||
"""
|
||||
if name is None:
|
||||
name = 'main'
|
||||
possible = []
|
||||
for protocol_options in object_type.egg_protocols:
|
||||
for protocol in protocol_options:
|
||||
pkg_resources.require(self.spec)
|
||||
entry = pkg_resources.get_entry_info(
|
||||
self.spec,
|
||||
protocol,
|
||||
name)
|
||||
if entry is not None:
|
||||
possible.append((entry.load(), protocol, entry.name))
|
||||
break
|
||||
if not possible:
|
||||
# Better exception
|
||||
dist = pkg_resources.get_distribution(self.spec)
|
||||
raise LookupError(
|
||||
"Entry point %r not found in egg %r (dir: %s; protocols: %s; "
|
||||
"entry_points: %s)"
|
||||
% (name, self.spec,
|
||||
dist.location,
|
||||
', '.join(_flatten(object_type.egg_protocols)),
|
||||
', '.join(_flatten([
|
||||
(pkg_resources.get_entry_info(self.spec, prot, name) or {}).keys()
|
||||
for prot in protocol_options] or '(no entry points)'))))
|
||||
if len(possible) > 1:
|
||||
raise LookupError(
|
||||
"Ambiguous entry points for %r in egg %r (protocols: %s)"
|
||||
% (name, self.spec, ', '.join(_flatten(protocol_options))))
|
||||
return possible[0]
|
||||
|
||||
|
||||
class FuncLoader(_Loader):
|
||||
""" Loader that supports specifying functions inside modules, without
|
||||
using eggs at all. Configuration should be in the format:
|
||||
use = call:my.module.path:function_name
|
||||
|
||||
Dot notation is supported in both the module and function name, e.g.:
|
||||
use = call:my.module.path:object.method
|
||||
"""
|
||||
def __init__(self, spec):
|
||||
self.spec = spec
|
||||
if not ':' in spec:
|
||||
raise LookupError("Configuration not in format module:function")
|
||||
|
||||
def get_context(self, object_type, name=None, global_conf=None):
|
||||
obj = lookup_object(self.spec)
|
||||
return LoaderContext(
|
||||
obj,
|
||||
object_type,
|
||||
None, # determine protocol from section type
|
||||
global_conf or {},
|
||||
{},
|
||||
self,
|
||||
)
|
||||
|
||||
|
||||
class LoaderContext(object):
|
||||
|
||||
def __init__(self, obj, object_type, protocol,
|
||||
global_conf, local_conf, loader,
|
||||
distribution=None, entry_point_name=None):
|
||||
self.object = obj
|
||||
self.object_type = object_type
|
||||
self.protocol = protocol
|
||||
#assert protocol in _flatten(object_type.egg_protocols), (
|
||||
# "Bad protocol %r; should be one of %s"
|
||||
# % (protocol, ', '.join(map(repr, _flatten(object_type.egg_protocols)))))
|
||||
self.global_conf = global_conf
|
||||
self.local_conf = local_conf
|
||||
self.loader = loader
|
||||
self.distribution = distribution
|
||||
self.entry_point_name = entry_point_name
|
||||
|
||||
def create(self):
|
||||
return self.object_type.invoke(self)
|
||||
|
||||
def config(self):
|
||||
conf = AttrDict(self.global_conf)
|
||||
conf.update(self.local_conf)
|
||||
conf.local_conf = self.local_conf
|
||||
conf.global_conf = self.global_conf
|
||||
conf.context = self
|
||||
return conf
|
||||
|
||||
|
||||
class AttrDict(dict):
|
||||
"""
|
||||
A dictionary that can be assigned to.
|
||||
"""
|
||||
pass
|
||||
36
PasteDeploy-1.5.0-py2.6.egg/paste/deploy/paster_templates.py
Executable file
36
PasteDeploy-1.5.0-py2.6.egg/paste/deploy/paster_templates.py
Executable file
@@ -0,0 +1,36 @@
|
||||
# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
|
||||
# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
|
||||
import os
|
||||
|
||||
from paste.script.templates import Template
|
||||
|
||||
from paste.deploy.compat import print_
|
||||
|
||||
|
||||
class PasteDeploy(Template):
|
||||
|
||||
_template_dir = 'paster_templates/paste_deploy'
|
||||
summary = "A web application deployed through paste.deploy"
|
||||
|
||||
egg_plugins = ['PasteDeploy']
|
||||
|
||||
required_templates = ['PasteScript#basic_package']
|
||||
|
||||
def post(self, command, output_dir, vars):
|
||||
for prereq in ['PasteDeploy']:
|
||||
command.insert_into_file(
|
||||
os.path.join(output_dir, 'setup.py'),
|
||||
'Extra requirements',
|
||||
'%r,\n' % prereq,
|
||||
indent=True)
|
||||
command.insert_into_file(
|
||||
os.path.join(output_dir, 'setup.py'),
|
||||
'Entry points',
|
||||
(' [paste.app_factory]\n'
|
||||
' main = %(package)s.wsgiapp:make_app\n') % vars,
|
||||
indent=False)
|
||||
if command.verbose:
|
||||
print_('*' * 72)
|
||||
print_('* Run "paster serve docs/devel_config.ini" to run the sample application')
|
||||
print_('* on http://localhost:8080')
|
||||
print_('*' * 72)
|
||||
@@ -0,0 +1,24 @@
|
||||
import cgi
|
||||
|
||||
from paste.deploy import CONFIG
|
||||
|
||||
|
||||
def application(environ, start_response):
|
||||
# Note that usually you wouldn't be writing a pure WSGI
|
||||
# application, you might be using some framework or
|
||||
# environment. But as an example...
|
||||
start_response('200 OK', [('Content-type', 'text/html')])
|
||||
greeting = CONFIG['greeting']
|
||||
content = [
|
||||
'<html><head><title>%s</title></head>\n' % greeting,
|
||||
'<body><h1>%s!</h1>\n' % greeting,
|
||||
'<table border=1>\n',
|
||||
]
|
||||
items = environ.items()
|
||||
items.sort()
|
||||
for key, value in items:
|
||||
content.append('<tr><td>%s</td><td>%s</td></tr>\n'
|
||||
% (key, cgi.escape(repr(value))))
|
||||
content.append('</table></body></html>')
|
||||
return content
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
from paste.deploy.config import ConfigMiddleware
|
||||
|
||||
import sampleapp
|
||||
|
||||
|
||||
def make_app(
|
||||
global_conf,
|
||||
# Optional and required configuration parameters
|
||||
# can go here, or just **kw; greeting is required:
|
||||
greeting,
|
||||
**kw):
|
||||
# This is a WSGI application:
|
||||
app = sampleapp.application
|
||||
# Here we merge all the keys into one configuration
|
||||
# dictionary; you don't have to do this, but this
|
||||
# can be convenient later to add ad hoc configuration:
|
||||
conf = global_conf.copy()
|
||||
conf.update(kw)
|
||||
conf['greeting'] = greeting
|
||||
# ConfigMiddleware means that paste.deploy.CONFIG will,
|
||||
# during this request (threadsafe) represent the
|
||||
# configuration dictionary we set up:
|
||||
app = ConfigMiddleware(app, conf)
|
||||
return app
|
||||
@@ -0,0 +1,22 @@
|
||||
[filter-app:main]
|
||||
# This puts the interactive debugger in place:
|
||||
use = egg:Paste#evalerror
|
||||
next = devel
|
||||
|
||||
[app:devel]
|
||||
# This application is meant for interactive development
|
||||
use = egg:${project}
|
||||
debug = true
|
||||
# You can add other configuration values:
|
||||
greeting = Aloha!
|
||||
|
||||
[app:test]
|
||||
# While this version of the configuration is for non-iteractive
|
||||
# tests (unit tests)
|
||||
use = devel
|
||||
|
||||
[server:main]
|
||||
use = egg:Paste#http
|
||||
# Change to 0.0.0.0 to make public:
|
||||
host = 127.0.0.1
|
||||
port = 8080
|
||||
74
PasteDeploy-1.5.0-py2.6.egg/paste/deploy/util.py
Executable file
74
PasteDeploy-1.5.0-py2.6.egg/paste/deploy/util.py
Executable file
@@ -0,0 +1,74 @@
|
||||
# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
|
||||
# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
|
||||
import inspect
|
||||
import sys
|
||||
|
||||
from paste.deploy.compat import reraise
|
||||
|
||||
|
||||
def fix_type_error(exc_info, callable, varargs, kwargs):
|
||||
"""
|
||||
Given an exception, this will test if the exception was due to a
|
||||
signature error, and annotate the error with better information if
|
||||
so.
|
||||
|
||||
Usage::
|
||||
|
||||
try:
|
||||
val = callable(*args, **kw)
|
||||
except TypeError:
|
||||
exc_info = fix_type_error(None, callable, args, kw)
|
||||
raise exc_info[0], exc_info[1], exc_info[2]
|
||||
"""
|
||||
if exc_info is None:
|
||||
exc_info = sys.exc_info()
|
||||
if (exc_info[0] != TypeError
|
||||
or str(exc_info[1]).find('arguments') == -1
|
||||
or getattr(exc_info[1], '_type_error_fixed', False)):
|
||||
return exc_info
|
||||
exc_info[1]._type_error_fixed = True
|
||||
argspec = inspect.formatargspec(*inspect.getargspec(callable))
|
||||
args = ', '.join(map(_short_repr, varargs))
|
||||
if kwargs and args:
|
||||
args += ', '
|
||||
if kwargs:
|
||||
kwargs = kwargs.items()
|
||||
kwargs.sort()
|
||||
args += ', '.join(['%s=...' % n for n, v in kwargs])
|
||||
gotspec = '(%s)' % args
|
||||
msg = '%s; got %s, wanted %s' % (exc_info[1], gotspec, argspec)
|
||||
exc_info[1].args = (msg,)
|
||||
return exc_info
|
||||
|
||||
|
||||
def _short_repr(v):
|
||||
v = repr(v)
|
||||
if len(v) > 12:
|
||||
v = v[:8] + '...' + v[-4:]
|
||||
return v
|
||||
|
||||
|
||||
def fix_call(callable, *args, **kw):
|
||||
"""
|
||||
Call ``callable(*args, **kw)`` fixing any type errors that come out.
|
||||
"""
|
||||
try:
|
||||
val = callable(*args, **kw)
|
||||
except TypeError:
|
||||
exc_info = fix_type_error(None, callable, args, kw)
|
||||
reraise(*exc_info)
|
||||
return val
|
||||
|
||||
|
||||
def lookup_object(spec):
|
||||
"""
|
||||
Looks up a module or object from a some.module:func_name specification.
|
||||
To just look up a module, omit the colon and everything after it.
|
||||
"""
|
||||
parts, target = spec.split(':') if ':' in spec else (spec, None)
|
||||
module = __import__(parts)
|
||||
|
||||
for part in parts.split('.')[1:] + ([target] if target else []):
|
||||
module = getattr(module, part)
|
||||
|
||||
return module
|
||||
Reference in New Issue
Block a user