summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--paste/deploy/loadwsgi.py54
-rw-r--r--tests/sample_configs/test_func.ini13
-rw-r--r--tests/test_func_loader.py32
3 files changed, 99 insertions, 0 deletions
diff --git a/paste/deploy/loadwsgi.py b/paste/deploy/loadwsgi.py
index bae77ae..6b373d0 100644
--- a/paste/deploy/loadwsgi.py
+++ b/paste/deploy/loadwsgi.py
@@ -278,6 +278,14 @@ def _loadegg(object_type, uri, spec, name, relative_to,
_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
############################################################
@@ -428,6 +436,20 @@ class ConfigLoader(_Loader):
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,
@@ -596,6 +618,38 @@ class EggLoader(_Loader):
% (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
+ try:
+ self.module_path, self.func_name = self.spec.split(':')
+ except ValueError:
+ raise LookupError("Configuration not in format module:function")
+ self.module_name = self.module_path.split('.', 1)[-1]
+
+ def get_context(self, object_type, name=None, global_conf=None):
+ module = __import__(self.module_path, {}, {}, [self.module_name], 0)
+ obj = module
+ for part in self.func_name.split('.'):
+ obj = getattr(obj, part)
+ 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,
diff --git a/tests/sample_configs/test_func.ini b/tests/sample_configs/test_func.ini
new file mode 100644
index 0000000..a0d28c4
--- /dev/null
+++ b/tests/sample_configs/test_func.ini
@@ -0,0 +1,13 @@
+[application:main]
+use = call:fakeapp.apps:make_basic_app
+
+[application:other]
+use = call:fakeapp.apps:make_basic_app2
+
+[composit:remote_addr]
+use = call:fakeapp.apps:make_remote_addr
+app.1 = main
+addr.1 = 127.0.0.1
+
+app.2 = other
+addr.2 = 0.0.0.0 \ No newline at end of file
diff --git a/tests/test_func_loader.py b/tests/test_func_loader.py
new file mode 100644
index 0000000..a04632d
--- /dev/null
+++ b/tests/test_func_loader.py
@@ -0,0 +1,32 @@
+from paste.deploy import loadapp, loadfilter, appconfig
+from fixture import *
+import fakeapp.apps
+
+here = os.path.abspath(os.path.dirname(__file__))
+
+def test_main():
+ app = loadapp('config:sample_configs/test_func.ini',
+ relative_to=here)
+ assert app is fakeapp.apps.basic_app
+ app = loadapp('config:sample_configs/test_func.ini#main',
+ relative_to=here)
+ assert app is fakeapp.apps.basic_app
+ app = loadapp('config:sample_configs/test_func.ini',
+ relative_to=here, name='main')
+ assert app is fakeapp.apps.basic_app
+ app = loadapp('config:sample_configs/test_func.ini#ignored',
+ relative_to=here, name='main')
+ assert app is fakeapp.apps.basic_app
+
+def test_other():
+ app = loadapp('config:sample_configs/test_func.ini#other',
+ relative_to=here)
+ assert app is fakeapp.apps.basic_app2
+
+
+def test_composit():
+ app = loadapp('config:sample_configs/test_func.ini#remote_addr',
+ relative_to=here)
+ assert isinstance(app, fakeapp.apps.RemoteAddrDispatch)
+ assert app.map['127.0.0.1'] is fakeapp.apps.basic_app
+ assert app.map['0.0.0.0'] is fakeapp.apps.basic_app2