diff options
| author | Chris McDonough <chrism@plope.com> | 2011-10-05 09:05:00 -0400 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2011-10-05 09:05:00 -0400 |
| commit | 33796033414d4460381531e713622a21401972a6 (patch) | |
| tree | 8a6eb9ddf16474f2aea9f145aebfeb9b22729905 | |
| parent | 0e0cb766f9b8c49ce53123fe9d13d0184196e9b1 (diff) | |
| download | pyramid-33796033414d4460381531e713622a21401972a6.tar.gz pyramid-33796033414d4460381531e713622a21401972a6.tar.bz2 pyramid-33796033414d4460381531e713622a21401972a6.zip | |
turn all paster commands into scripts
| -rw-r--r-- | pyramid/paster.py | 562 | ||||
| -rw-r--r-- | pyramid/scaffolds/alchemy/development.ini_tmpl | 2 | ||||
| -rw-r--r-- | pyramid/scaffolds/alchemy/production.ini_tmpl | 2 | ||||
| -rw-r--r-- | pyramid/scaffolds/routesalchemy/development.ini_tmpl | 2 | ||||
| -rw-r--r-- | pyramid/scaffolds/routesalchemy/production.ini_tmpl | 2 | ||||
| -rw-r--r-- | pyramid/scaffolds/starter/development.ini_tmpl | 2 | ||||
| -rw-r--r-- | pyramid/scaffolds/starter/production.ini_tmpl | 2 | ||||
| -rw-r--r-- | pyramid/scaffolds/zodb/development.ini_tmpl | 2 | ||||
| -rw-r--r-- | pyramid/scaffolds/zodb/production.ini_tmpl | 2 | ||||
| -rw-r--r-- | pyramid/scripts/proutes.py | 75 | ||||
| -rw-r--r-- | pyramid/scripts/pshell.py | 200 | ||||
| -rw-r--r-- | pyramid/scripts/ptweens.py | 87 | ||||
| -rw-r--r-- | pyramid/scripts/pviews.py | 256 | ||||
| -rw-r--r-- | pyramid/tests/test_paster.py | 1011 | ||||
| -rw-r--r-- | pyramid/tests/test_scripts.py | 1037 | ||||
| -rw-r--r-- | setup.py | 11 |
16 files changed, 1668 insertions, 1587 deletions
diff --git a/pyramid/paster.py b/pyramid/paster.py index 1c06ca79b..3fec6c556 100644 --- a/pyramid/paster.py +++ b/pyramid/paster.py @@ -1,20 +1,9 @@ import os -import sys -from code import interact import zope.deprecation from paste.deploy import loadapp -from glue.command import Command -from pyramid.interfaces import IMultiView -from pyramid.interfaces import ITweens - -from pyramid.compat import print_ -from pyramid.compat import configparser from pyramid.scripting import prepare -from pyramid.util import DottedNameResolver -from pyramid.tweens import MAIN -from pyramid.tweens import INGRESS from pyramid.scaffolds import PyramidTemplate # bw compat PyramidTemplate = PyramidTemplate # pyflakes @@ -90,554 +79,3 @@ def bootstrap(config_uri, request=None): env['app'] = app return env -class PCommand(Command): - bootstrap = (bootstrap,) # testing - verbose = 3 - - def __init__(self, *arg, **kw): - # needs to be in constructor to support Jython (used to be at class - # scope as ``usage = '\n' + __doc__``. - self.usage = '\n' + self.__doc__ - Command.__init__(self, *arg, **kw) - -class PShellCommand(PCommand): - """Open an interactive shell with a :app:`Pyramid` app loaded. - - This command accepts one positional argument: - - ``config_uri`` -- specifies the PasteDeploy config file to use for the - interactive shell. The format is ``inifile#name``. If the name is left - off, ``main`` will be assumed. - - Example:: - - $ glue pshell myapp.ini#main - - .. note:: If you do not point the loader directly at the section of the - ini file containing your :app:`Pyramid` application, the - command will attempt to find the app for you. If you are - loading a pipeline that contains more than one :app:`Pyramid` - application within it, the loader will use the last one. - - """ - summary = "Open an interactive shell with a Pyramid application loaded" - - min_args = 1 - max_args = 1 - - parser = Command.standard_parser(simulate=True) - parser.add_option('-d', '--disable-ipython', - action='store_true', - dest='disable_ipython', - help="Don't use IPython even if it is available") - parser.add_option('--setup', - dest='setup', - help=("A callable that will be passed the environment " - "before it is made available to the shell. This " - "option will override the 'setup' key in the " - "[pshell] ini section.")) - - ConfigParser = configparser.ConfigParser # testing - - loaded_objects = {} - object_help = {} - setup = None - - def pshell_file_config(self, filename): - config = self.ConfigParser() - config.read(filename) - try: - items = config.items('pshell') - except configparser.NoSectionError: - return - - resolver = DottedNameResolver(None) - self.loaded_objects = {} - self.object_help = {} - self.setup = None - for k, v in items: - if k == 'setup': - self.setup = v - else: - self.loaded_objects[k] = resolver.maybe_resolve(v) - self.object_help[k] = v - - def command(self, shell=None): - config_uri = self.args[0] - config_file = config_uri.split('#', 1)[0] - self.logging_file_config(config_file) - self.pshell_file_config(config_file) - - # bootstrap the environ - env = self.bootstrap[0](config_uri) - - # remove the closer from the env - closer = env.pop('closer') - - # setup help text for default environment - env_help = dict(env) - env_help['app'] = 'The WSGI application.' - env_help['root'] = 'Root of the default resource tree.' - env_help['registry'] = 'Active Pyramid registry.' - env_help['request'] = 'Active request object.' - env_help['root_factory'] = ( - 'Default root factory used to create `root`.') - - # override use_script with command-line options - if self.options.setup: - self.setup = self.options.setup - - if self.setup: - # store the env before muddling it with the script - orig_env = env.copy() - - # call the setup callable - resolver = DottedNameResolver(None) - setup = resolver.maybe_resolve(self.setup) - setup(env) - - # remove any objects from default help that were overidden - for k, v in env.iteritems(): - if k not in orig_env or env[k] != orig_env[k]: - env_help[k] = v - - # load the pshell section of the ini file - env.update(self.loaded_objects) - - # eliminate duplicates from env, allowing custom vars to override - for k in self.loaded_objects: - if k in env_help: - del env_help[k] - - # generate help text - help = '' - if env_help: - help += 'Environment:' - for var in sorted(env_help.keys()): - help += '\n %-12s %s' % (var, env_help[var]) - - if self.object_help: - help += '\n\nCustom Variables:' - for var in sorted(self.object_help.keys()): - help += '\n %-12s %s' % (var, self.object_help[var]) - - if shell is None and not self.options.disable_ipython: - shell = self.make_ipython_v0_11_shell() - if shell is None: - shell = self.make_ipython_v0_10_shell() - - if shell is None: - shell = self.make_default_shell() - - try: - shell(env, help) - finally: - closer() - - def make_default_shell(self, interact=interact): - def shell(env, help): - cprt = 'Type "help" for more information.' - banner = "Python %s on %s\n%s" % (sys.version, sys.platform, cprt) - banner += '\n\n' + help + '\n' - interact(banner, local=env) - return shell - - def make_ipython_v0_11_shell(self, IPShellFactory=None): - if IPShellFactory is None: # pragma: no cover - try: - from IPython.frontend.terminal.embed import ( - InteractiveShellEmbed) - IPShellFactory = InteractiveShellEmbed - except ImportError: - return None - def shell(env, help): - IPShell = IPShellFactory(banner2=help + '\n', user_ns=env) - IPShell() - return shell - - def make_ipython_v0_10_shell(self, IPShellFactory=None): - if IPShellFactory is None: # pragma: no cover - try: - from IPython.Shell import IPShellEmbed - IPShellFactory = IPShellEmbed - except ImportError: - return None - def shell(env, help): - IPShell = IPShellFactory(argv=[], user_ns=env) - IPShell.set_banner(IPShell.IP.BANNER + '\n' + help + '\n') - IPShell() - return shell - -BFGShellCommand = PShellCommand # b/w compat forever - -class PRoutesCommand(PCommand): - """Print all URL dispatch routes used by a Pyramid application in the - order in which they are evaluated. Each route includes the name of the - route, the pattern of the route, and the view callable which will be - invoked when the route is matched. - - This command accepts one positional argument: - - ``config_uri`` -- specifies the PasteDeploy config file to use for the - interactive shell. The format is ``inifile#name``. If the name is left - off, ``main`` will be assumed. - - Example:: - - $ glue proutes myapp.ini#main - - """ - summary = "Print all URL dispatch routes related to a Pyramid application" - min_args = 1 - max_args = 1 - stdout = sys.stdout - - parser = Command.standard_parser(simulate=True) - - def _get_mapper(self, registry): - from pyramid.config import Configurator - config = Configurator(registry = registry) - return config.get_routes_mapper() - - def out(self, msg): # pragma: no cover - print_(msg) - - def command(self): - from pyramid.interfaces import IRouteRequest - from pyramid.interfaces import IViewClassifier - from pyramid.interfaces import IView - from zope.interface import Interface - config_uri = self.args[0] - env = self.bootstrap[0](config_uri) - registry = env['registry'] - mapper = self._get_mapper(registry) - if mapper is not None: - routes = mapper.get_routes() - fmt = '%-15s %-30s %-25s' - if not routes: - return - self.out(fmt % ('Name', 'Pattern', 'View')) - self.out( - fmt % ('-'*len('Name'), '-'*len('Pattern'), '-'*len('View'))) - for route in routes: - request_iface = registry.queryUtility(IRouteRequest, - name=route.name) - view_callable = None - if (request_iface is None) or (route.factory is not None): - self.out(fmt % (route.name, route.pattern, '<unknown>')) - else: - view_callable = registry.adapters.lookup( - (IViewClassifier, request_iface, Interface), - IView, name='', default=None) - self.out(fmt % (route.name, route.pattern, view_callable)) - - -class PViewsCommand(PCommand): - """Print, for a given URL, the views that might match. Underneath each - potentially matching route, list the predicates required. Underneath - each route+predicate set, print each view that might match and its - predicates. - - This command accepts two positional arguments: - - ``config_uri`` -- specifies the PasteDeploy config file to use for the - interactive shell. The format is ``inifile#name``. If the name is left - off, ``main`` will be assumed. - - ``url`` -- specifies the URL that will be used to find matching views. - - Example:: - - $ glue proutes myapp.ini#main url - - """ - summary = "Print all views in an application that might match a URL" - min_args = 2 - max_args = 2 - stdout = sys.stdout - - parser = Command.standard_parser(simulate=True) - - def out(self, msg): # pragma: no cover - print_(msg) - - def _find_multi_routes(self, mapper, request): - infos = [] - path = request.environ['PATH_INFO'] - # find all routes that match path, regardless of predicates - for route in mapper.get_routes(): - match = route.match(path) - if match is not None: - info = {'match':match, 'route':route} - infos.append(info) - return infos - - def _find_view(self, url, registry): - """ - Accept ``url`` and ``registry``; create a :term:`request` and - find a :app:`Pyramid` view based on introspection of :term:`view - configuration` within the application registry; return the view. - """ - from zope.interface import providedBy - from zope.interface import implementer - from pyramid.interfaces import IRequest - from pyramid.interfaces import IRootFactory - from pyramid.interfaces import IRouteRequest - from pyramid.interfaces import IRequestFactory - from pyramid.interfaces import IRoutesMapper - from pyramid.interfaces import IView - from pyramid.interfaces import IViewClassifier - from pyramid.interfaces import ITraverser - from pyramid.request import Request - from pyramid.traversal import DefaultRootFactory - from pyramid.traversal import ResourceTreeTraverser - - q = registry.queryUtility - root_factory = q(IRootFactory, default=DefaultRootFactory) - routes_mapper = q(IRoutesMapper) - request_factory = q(IRequestFactory, default=Request) - - adapters = registry.adapters - request = None - - @implementer(IMultiView) - class RoutesMultiView(object): - - def __init__(self, infos, context_iface, root_factory, request): - self.views = [] - for info in infos: - match, route = info['match'], info['route'] - if route is not None: - request_iface = registry.queryUtility( - IRouteRequest, - name=route.name, - default=IRequest) - view = adapters.lookup( - (IViewClassifier, request_iface, context_iface), - IView, name='', default=None) - if view is None: - continue - view.__request_attrs__ = {} - view.__request_attrs__['matchdict'] = match - view.__request_attrs__['matched_route'] = route - root_factory = route.factory or root_factory - root = root_factory(request) - traverser = adapters.queryAdapter(root, ITraverser) - if traverser is None: - traverser = ResourceTreeTraverser(root) - tdict = traverser(request) - view.__request_attrs__.update(tdict) - if not hasattr(view, '__view_attr__'): - view.__view_attr__ = '' - self.views.append((None, view, None)) - - - # create the request - environ = { - 'wsgi.url_scheme':'http', - 'SERVER_NAME':'localhost', - 'SERVER_PORT':'8080', - 'REQUEST_METHOD':'GET', - 'PATH_INFO':url, - } - request = request_factory(environ) - context = None - routes_multiview = None - attrs = request.__dict__ - attrs['registry'] = registry - request_iface = IRequest - - # find the root object - if routes_mapper is not None: - infos = self._find_multi_routes(routes_mapper, request) - if len(infos) == 1: - info = infos[0] - match, route = info['match'], info['route'] - if route is not None: - attrs['matchdict'] = match - attrs['matched_route'] = route - request.environ['bfg.routes.matchdict'] = match - request_iface = registry.queryUtility( - IRouteRequest, - name=route.name, - default=IRequest) - root_factory = route.factory or root_factory - if len(infos) > 1: - routes_multiview = infos - - root = root_factory(request) - attrs['root'] = root - - # find a context - traverser = adapters.queryAdapter(root, ITraverser) - if traverser is None: - traverser = ResourceTreeTraverser(root) - tdict = traverser(request) - context, view_name, subpath, traversed, vroot, vroot_path =( - tdict['context'], tdict['view_name'], tdict['subpath'], - tdict['traversed'], tdict['virtual_root'], - tdict['virtual_root_path']) - attrs.update(tdict) - - # find a view callable - context_iface = providedBy(context) - if routes_multiview is None: - view = adapters.lookup( - (IViewClassifier, request_iface, context_iface), - IView, name=view_name, default=None) - else: - view = RoutesMultiView(infos, context_iface, root_factory, request) - - # routes are not registered with a view name - if view is None: - view = adapters.lookup( - (IViewClassifier, request_iface, context_iface), - IView, name='', default=None) - # we don't want a multiview here - if IMultiView.providedBy(view): - view = None - - if view is not None: - view.__request_attrs__ = attrs - - return view - - def output_route_attrs(self, attrs, indent): - route = attrs['matched_route'] - self.out("%sroute name: %s" % (indent, route.name)) - self.out("%sroute pattern: %s" % (indent, route.pattern)) - self.out("%sroute path: %s" % (indent, route.path)) - self.out("%ssubpath: %s" % (indent, '/'.join(attrs['subpath']))) - predicates = ', '.join([p.__text__ for p in route.predicates]) - if predicates != '': - self.out("%sroute predicates (%s)" % (indent, predicates)) - - def output_view_info(self, view_wrapper, level=1): - indent = " " * level - name = getattr(view_wrapper, '__name__', '') - module = getattr(view_wrapper, '__module__', '') - attr = getattr(view_wrapper, '__view_attr__', None) - request_attrs = getattr(view_wrapper, '__request_attrs__', {}) - if attr is not None: - view_callable = "%s.%s.%s" % (module, name, attr) - else: - attr = view_wrapper.__class__.__name__ - if attr == 'function': - attr = name - view_callable = "%s.%s" % (module, attr) - self.out('') - if 'matched_route' in request_attrs: - self.out("%sRoute:" % indent) - self.out("%s------" % indent) - self.output_route_attrs(request_attrs, indent) - permission = getattr(view_wrapper, '__permission__', None) - if not IMultiView.providedBy(view_wrapper): - # single view for this route, so repeat call without route data - del request_attrs['matched_route'] - self.output_view_info(view_wrapper, level+1) - else: - self.out("%sView:" % indent) - self.out("%s-----" % indent) - self.out("%s%s" % (indent, view_callable)) - permission = getattr(view_wrapper, '__permission__', None) - if permission is not None: - self.out("%srequired permission = %s" % (indent, permission)) - predicates = getattr(view_wrapper, '__predicates__', None) - if predicates is not None: - predicate_text = ', '.join([p.__text__ for p in predicates]) - self.out("%sview predicates (%s)" % (indent, predicate_text)) - - def command(self): - config_uri, url = self.args - if not url.startswith('/'): - url = '/%s' % url - env = self.bootstrap[0](config_uri) - registry = env['registry'] - view = self._find_view(url, registry) - self.out('') - self.out("URL = %s" % url) - self.out('') - if view is not None: - self.out(" context: %s" % view.__request_attrs__['context']) - self.out(" view name: %s" % view.__request_attrs__['view_name']) - if IMultiView.providedBy(view): - for dummy, view_wrapper, dummy in view.views: - self.output_view_info(view_wrapper) - if IMultiView.providedBy(view_wrapper): - for dummy, mv_view_wrapper, dummy in view_wrapper.views: - self.output_view_info(mv_view_wrapper, level=2) - else: - if view is not None: - self.output_view_info(view) - else: - self.out(" Not found.") - self.out('') - - -class PTweensCommand(PCommand): - """Print all implicit and explicit :term:`tween` objects used by a - Pyramid application. The handler output includes whether the system is - using an explicit tweens ordering (will be true when the - ``pyramid.tweens`` setting is used) or an implicit tweens ordering (will - be true when the ``pyramid.tweens`` setting is *not* used). - - This command accepts one positional argument: - - ``config_uri`` -- specifies the PasteDeploy config file to use for the - interactive shell. The format is ``inifile#name``. If the name is left - off, ``main`` will be assumed. - - Example:: - - $ glue ptweens myapp.ini#main - - """ - summary = "Print all tweens related to a Pyramid application" - min_args = 1 - max_args = 1 - stdout = sys.stdout - - parser = Command.standard_parser(simulate=True) - - def _get_tweens(self, registry): - from pyramid.config import Configurator - config = Configurator(registry = registry) - return config.registry.queryUtility(ITweens) - - def out(self, msg): # pragma: no cover - print_(msg) - - def show_chain(self, chain): - fmt = '%-10s %-65s' - self.out(fmt % ('Position', 'Name')) - self.out(fmt % ('-'*len('Position'), '-'*len('Name'))) - self.out(fmt % ('-', INGRESS)) - for pos, (name, _) in enumerate(chain): - self.out(fmt % (pos, name)) - self.out(fmt % ('-', MAIN)) - - def command(self): - config_uri = self.args[0] - env = self.bootstrap[0](config_uri) - registry = env['registry'] - tweens = self._get_tweens(registry) - if tweens is not None: - explicit = tweens.explicit - if explicit: - self.out('"pyramid.tweens" config value set ' - '(explicitly ordered tweens used)') - self.out('') - self.out('Explicit Tween Chain (used)') - self.out('') - self.show_chain(tweens.explicit) - self.out('') - self.out('Implicit Tween Chain (not used)') - self.out('') - self.show_chain(tweens.implicit()) - else: - self.out('"pyramid.tweens" config value NOT set ' - '(implicitly ordered tweens used)') - self.out('') - self.out('Implicit Tween Chain') - self.out('') - self.show_chain(tweens.implicit()) diff --git a/pyramid/scaffolds/alchemy/development.ini_tmpl b/pyramid/scaffolds/alchemy/development.ini_tmpl index b7c06aff3..d804a0b0e 100644 --- a/pyramid/scaffolds/alchemy/development.ini_tmpl +++ b/pyramid/scaffolds/alchemy/development.ini_tmpl @@ -13,7 +13,7 @@ pyramid.includes = pyramid_debugtoolbar sqlalchemy.url = sqlite:///%(here)s/{{project}}.db [server:main] -use = egg:glue#wsgiref +use = egg:pyramid#wsgiref host = 0.0.0.0 port = 6543 diff --git a/pyramid/scaffolds/alchemy/production.ini_tmpl b/pyramid/scaffolds/alchemy/production.ini_tmpl index dc17e8338..7350ce25f 100644 --- a/pyramid/scaffolds/alchemy/production.ini_tmpl +++ b/pyramid/scaffolds/alchemy/production.ini_tmpl @@ -12,7 +12,7 @@ pyramid.includes = pyramid_tm sqlalchemy.url = sqlite:///%(here)s/{{project}}.db [server:main] -use = egg:glue#wsgiref +use = egg:pyramid#wsgiref host = 0.0.0.0 port = 6543 diff --git a/pyramid/scaffolds/routesalchemy/development.ini_tmpl b/pyramid/scaffolds/routesalchemy/development.ini_tmpl index b7c06aff3..d804a0b0e 100644 --- a/pyramid/scaffolds/routesalchemy/development.ini_tmpl +++ b/pyramid/scaffolds/routesalchemy/development.ini_tmpl @@ -13,7 +13,7 @@ pyramid.includes = pyramid_debugtoolbar sqlalchemy.url = sqlite:///%(here)s/{{project}}.db [server:main] -use = egg:glue#wsgiref +use = egg:pyramid#wsgiref host = 0.0.0.0 port = 6543 diff --git a/pyramid/scaffolds/routesalchemy/production.ini_tmpl b/pyramid/scaffolds/routesalchemy/production.ini_tmpl index dc17e8338..7350ce25f 100644 --- a/pyramid/scaffolds/routesalchemy/production.ini_tmpl +++ b/pyramid/scaffolds/routesalchemy/production.ini_tmpl @@ -12,7 +12,7 @@ pyramid.includes = pyramid_tm sqlalchemy.url = sqlite:///%(here)s/{{project}}.db [server:main] -use = egg:glue#wsgiref +use = egg:pyramid#wsgiref host = 0.0.0.0 port = 6543 diff --git a/pyramid/scaffolds/starter/development.ini_tmpl b/pyramid/scaffolds/starter/development.ini_tmpl index c47fcec22..4d3a80286 100644 --- a/pyramid/scaffolds/starter/development.ini_tmpl +++ b/pyramid/scaffolds/starter/development.ini_tmpl @@ -10,7 +10,7 @@ pyramid.default_locale_name = en pyramid.includes = pyramid_debugtoolbar [server:main] -use = egg:glue#wsgiref +use = egg:pyramid#wsgiref host = 0.0.0.0 port = 6543 diff --git a/pyramid/scaffolds/starter/production.ini_tmpl b/pyramid/scaffolds/starter/production.ini_tmpl index 0634072c0..931cfa510 100644 --- a/pyramid/scaffolds/starter/production.ini_tmpl +++ b/pyramid/scaffolds/starter/production.ini_tmpl @@ -9,7 +9,7 @@ pyramid.debug_templates = false pyramid.default_locale_name = en [server:main] -use = egg:glue#wsgiref +use = egg:pyramid#wsgiref host = 0.0.0.0 port = 6543 diff --git a/pyramid/scaffolds/zodb/development.ini_tmpl b/pyramid/scaffolds/zodb/development.ini_tmpl index 661e042a2..eb2b0d3de 100644 --- a/pyramid/scaffolds/zodb/development.ini_tmpl +++ b/pyramid/scaffolds/zodb/development.ini_tmpl @@ -14,7 +14,7 @@ tm.attempts = 3 zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 [server:main] -use = egg:glue#wsgiref +use = egg:pyramid#wsgiref host = 0.0.0.0 port = 6543 diff --git a/pyramid/scaffolds/zodb/production.ini_tmpl b/pyramid/scaffolds/zodb/production.ini_tmpl index 2378f9751..7c91ea0df 100644 --- a/pyramid/scaffolds/zodb/production.ini_tmpl +++ b/pyramid/scaffolds/zodb/production.ini_tmpl @@ -13,7 +13,7 @@ tm.attempts = 3 zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 [server:main] -use = egg:glue#wsgiref +use = egg:pyramid#wsgiref host = 0.0.0.0 port = 6543 diff --git a/pyramid/scripts/proutes.py b/pyramid/scripts/proutes.py new file mode 100644 index 000000000..0dab9acda --- /dev/null +++ b/pyramid/scripts/proutes.py @@ -0,0 +1,75 @@ +import optparse +import sys + +from pyramid.compat import print_ +from pyramid.paster import bootstrap + +def main(argv=sys.argv): + command = PRoutesCommand(argv) + command.run() + +class PRoutesCommand(object): + """Print all URL dispatch routes used by a Pyramid application in the + order in which they are evaluated. Each route includes the name of the + route, the pattern of the route, and the view callable which will be + invoked when the route is matched. + + This command accepts one positional argument: + + ``config_uri`` -- specifies the PasteDeploy config file to use for the + interactive shell. The format is ``inifile#name``. If the name is left + off, ``main`` will be assumed. + + Example:: + + $ proutes myapp.ini#main + + """ + bootstrap = (bootstrap,) + summary = "Print all URL dispatch routes related to a Pyramid application" + min_args = 1 + max_args = 1 + stdout = sys.stdout + + parser = optparse.OptionParser() + + def __init__(self, argv): + self.options, self.args = self.parser.parse_args(argv[1:]) + + def _get_mapper(self, registry): + from pyramid.config import Configurator + config = Configurator(registry = registry) + return config.get_routes_mapper() + + def out(self, msg): # pragma: no cover + print_(msg) + + def run(self): + from pyramid.interfaces import IRouteRequest + from pyramid.interfaces import IViewClassifier + from pyramid.interfaces import IView + from zope.interface import Interface + config_uri = self.args[0] + env = self.bootstrap[0](config_uri) + registry = env['registry'] + mapper = self._get_mapper(registry) + if mapper is not None: + routes = mapper.get_routes() + fmt = '%-15s %-30s %-25s' + if not routes: + return + self.out(fmt % ('Name', 'Pattern', 'View')) + self.out( + fmt % ('-'*len('Name'), '-'*len('Pattern'), '-'*len('View'))) + for route in routes: + request_iface = registry.queryUtility(IRouteRequest, + name=route.name) + view_callable = None + if (request_iface is None) or (route.factory is not None): + self.out(fmt % (route.name, route.pattern, '<unknown>')) + else: + view_callable = registry.adapters.lookup( + (IViewClassifier, request_iface, Interface), + IView, name='', default=None) + self.out(fmt % (route.name, route.pattern, view_callable)) + diff --git a/pyramid/scripts/pshell.py b/pyramid/scripts/pshell.py new file mode 100644 index 000000000..85c7e16ea --- /dev/null +++ b/pyramid/scripts/pshell.py @@ -0,0 +1,200 @@ +from code import interact +import optparse +import os +import sys +from logging.config import fileConfig + +from pyramid.compat import configparser +from pyramid.util import DottedNameResolver +from pyramid.paster import bootstrap + +def main(argv=sys.argv): + command = PShellCommand(argv) + return command.run() + +class PShellCommand(object): + """Open an interactive shell with a :app:`Pyramid` app loaded. + + This command accepts one positional argument: + + ``config_uri`` -- specifies the PasteDeploy config file to use for the + interactive shell. The format is ``inifile#name``. If the name is left + off, ``main`` will be assumed. + + Example:: + + $ pshell myapp.ini#main + + .. note:: If you do not point the loader directly at the section of the + ini file containing your :app:`Pyramid` application, the + command will attempt to find the app for you. If you are + loading a pipeline that contains more than one :app:`Pyramid` + application within it, the loader will use the last one. + + """ + bootstrap = (bootstrap,) # for testing + summary = "Open an interactive shell with a Pyramid application loaded" + + min_args = 1 + max_args = 1 + + parser = optparse.OptionParser() + parser.add_option('-d', '--disable-ipython', + action='store_true', + dest='disable_ipython', + help="Don't use IPython even if it is available") + parser.add_option('--setup', + dest='setup', + help=("A callable that will be passed the environment " + "before it is made available to the shell. This " + "option will override the 'setup' key in the " + "[pshell] ini section.")) + + ConfigParser = configparser.ConfigParser # testing + + loaded_objects = {} + object_help = {} + setup = None + + def __init__(self, argv): + self.options, self.args = self.parser.parse_args(argv[1:]) + + def pshell_file_config(self, filename): + config = self.ConfigParser() + config.read(filename) + try: + items = config.items('pshell') + except configparser.NoSectionError: + return + + resolver = DottedNameResolver(None) + self.loaded_objects = {} + self.object_help = {} + self.setup = None + for k, v in items: + if k == 'setup': + self.setup = v + else: + self.loaded_objects[k] = resolver.maybe_resolve(v) + self.object_help[k] = v + + def run(self, shell=None): + config_uri = self.args[0] + config_file = config_uri.split('#', 1)[0] + self.logging_file_config(config_file) + self.pshell_file_config(config_file) + + # bootstrap the environ + env = self.bootstrap[0](config_uri) + + # remove the closer from the env + closer = env.pop('closer') + + # setup help text for default environment + env_help = dict(env) + env_help['app'] = 'The WSGI application.' + env_help['root'] = 'Root of the default resource tree.' + env_help['registry'] = 'Active Pyramid registry.' + env_help['request'] = 'Active request object.' + env_help['root_factory'] = ( + 'Default root factory used to create `root`.') + + # override use_script with command-line options + if self.options.setup: + self.setup = self.options.setup + + if self.setup: + # store the env before muddling it with the script + orig_env = env.copy() + + # call the setup callable + resolver = DottedNameResolver(None) + setup = resolver.maybe_resolve(self.setup) + setup(env) + + # remove any objects from default help that were overidden + for k, v in env.iteritems(): + if k not in orig_env or env[k] != orig_env[k]: + env_help[k] = v + + # load the pshell section of the ini file + env.update(self.loaded_objects) + + # eliminate duplicates from env, allowing custom vars to override + for k in self.loaded_objects: + if k in env_help: + del env_help[k] + + # generate help text + help = '' + if env_help: + help += 'Environment:' + for var in sorted(env_help.keys()): + help += '\n %-12s %s' % (var, env_help[var]) + + if self.object_help: + help += '\n\nCustom Variables:' + for var in sorted(self.object_help.keys()): + help += '\n %-12s %s' % (var, self.object_help[var]) + + if shell is None and not self.options.disable_ipython: + shell = self.make_ipython_v0_11_shell() + if shell is None: + shell = self.make_ipython_v0_10_shell() + + if shell is None: + shell = self.make_default_shell() + + try: + shell(env, help) + finally: + closer() + + def make_default_shell(self, interact=interact): + def shell(env, help): + cprt = 'Type "help" for more information.' + banner = "Python %s on %s\n%s" % (sys.version, sys.platform, cprt) + banner += '\n\n' + help + '\n' + interact(banner, local=env) + return shell + + def make_ipython_v0_11_shell(self, IPShellFactory=None): + if IPShellFactory is None: # pragma: no cover + try: + from IPython.frontend.terminal.embed import ( + InteractiveShellEmbed) + IPShellFactory = InteractiveShellEmbed + except ImportError: + return None + def shell(env, help): + IPShell = IPShellFactory(banner2=help + '\n', user_ns=env) + IPShell() + return shell + + def make_ipython_v0_10_shell(self, IPShellFactory=None): + if IPShellFactory is None: # pragma: no cover + try: + from IPython.Shell import IPShellEmbed + IPShellFactory = IPShellEmbed + except ImportError: + return None + def shell(env, help): + IPShell = IPShellFactory(argv=[], user_ns=env) + IPShell.set_banner(IPShell.IP.BANNER + '\n' + help + '\n') + IPShell() + return shell + + def logging_file_config(self, config_file): + """ + Setup logging via the logging module's fileConfig function with the + specified ``config_file``, if applicable. + + ConfigParser defaults are specified for the special ``__file__`` + and ``here`` variables, similar to PasteDeploy config loading. + """ + parser = configparser.ConfigParser() + parser.read([config_file]) + if parser.has_section('loggers'): + config_file = os.path.abspath(config_file) + fileConfig(config_file, dict(__file__=config_file, + here=os.path.dirname(config_file))) diff --git a/pyramid/scripts/ptweens.py b/pyramid/scripts/ptweens.py new file mode 100644 index 000000000..56d8b422b --- /dev/null +++ b/pyramid/scripts/ptweens.py @@ -0,0 +1,87 @@ +import optparse +import sys + +from pyramid.interfaces import ITweens + +from pyramid.tweens import MAIN +from pyramid.tweens import INGRESS +from pyramid.paster import bootstrap + +from pyramid.compat import print_ + +def main(argv=sys.argv): + command = PTweensCommand(argv) + command.run() + +class PTweensCommand(object): + """Print all implicit and explicit :term:`tween` objects used by a + Pyramid application. The handler output includes whether the system is + using an explicit tweens ordering (will be true when the + ``pyramid.tweens`` setting is used) or an implicit tweens ordering (will + be true when the ``pyramid.tweens`` setting is *not* used). + + This command accepts one positional argument: + + ``config_uri`` -- specifies the PasteDeploy config file to use for the + interactive shell. The format is ``inifile#name``. If the name is left + off, ``main`` will be assumed. + + Example:: + + $ ptweens myapp.ini#main + + """ + summary = "Print all tweens related to a Pyramid application" + min_args = 1 + max_args = 1 + stdout = sys.stdout + + parser = optparse.OptionParser() + + bootstrap = (bootstrap,) # testing + + def __init__(self, argv): + self.options, self.args = self.parser.parse_args(argv[1:]) + + def _get_tweens(self, registry): + from pyramid.config import Configurator + config = Configurator(registry = registry) + return config.registry.queryUtility(ITweens) + + def out(self, msg): # pragma: no cover + print_(msg) + + def show_chain(self, chain): + fmt = '%-10s %-65s' + self.out(fmt % ('Position', 'Name')) + self.out(fmt % ('-'*len('Position'), '-'*len('Name'))) + self.out(fmt % ('-', INGRESS)) + for pos, (name, _) in enumerate(chain): + self.out(fmt % (pos, name)) + self.out(fmt % ('-', MAIN)) + + def run(self): + config_uri = self.args[0] + env = self.bootstrap[0](config_uri) + registry = env['registry'] + tweens = self._get_tweens(registry) + if tweens is not None: + explicit = tweens.explicit + if explicit: + self.out('"pyramid.tweens" config value set ' + '(explicitly ordered tweens used)') + self.out('') + self.out('Explicit Tween Chain (used)') + self.out('') + self.show_chain(tweens.explicit) + self.out('') + self.out('Implicit Tween Chain (not used)') + self.out('') + self.show_chain(tweens.implicit()) + else: + self.out('"pyramid.tweens" config value NOT set ' + '(implicitly ordered tweens used)') + self.out('') + self.out('Implicit Tween Chain') + self.out('') + self.show_chain(tweens.implicit()) diff --git a/pyramid/scripts/pviews.py b/pyramid/scripts/pviews.py new file mode 100644 index 000000000..69baaee87 --- /dev/null +++ b/pyramid/scripts/pviews.py @@ -0,0 +1,256 @@ +import optparse +import sys + +from pyramid.compat import print_ +from pyramid.interfaces import IMultiView +from pyramid.paster import bootstrap + +def main(argv=sys.argv): + command = PViewsCommand(argv) + command.run() + +class PViewsCommand(object): + """Print, for a given URL, the views that might match. Underneath each + potentially matching route, list the predicates required. Underneath + each route+predicate set, print each view that might match and its + predicates. + + This command accepts two positional arguments: + + ``config_uri`` -- specifies the PasteDeploy config file to use for the + interactive shell. The format is ``inifile#name``. If the name is left + off, ``main`` will be assumed. + + ``url`` -- specifies the URL that will be used to find matching views. + + Example:: + + $ proutes myapp.ini#main url + + """ + summary = "Print all views in an application that might match a URL" + min_args = 2 + max_args = 2 + stdout = sys.stdout + + parser = optparse.OptionParser() + + bootstrap = (bootstrap,) # testing + + def __init__(self, argv): + self.options, self.args = self.parser.parse_args(argv[1:]) + + def out(self, msg): # pragma: no cover + print_(msg) + + def _find_multi_routes(self, mapper, request): + infos = [] + path = request.environ['PATH_INFO'] + # find all routes that match path, regardless of predicates + for route in mapper.get_routes(): + match = route.match(path) + if match is not None: + info = {'match':match, 'route':route} + infos.append(info) + return infos + + def _find_view(self, url, registry): + """ + Accept ``url`` and ``registry``; create a :term:`request` and + find a :app:`Pyramid` view based on introspection of :term:`view + configuration` within the application registry; return the view. + """ + from zope.interface import providedBy + from zope.interface import implementer + from pyramid.interfaces import IRequest + from pyramid.interfaces import IRootFactory + from pyramid.interfaces import IRouteRequest + from pyramid.interfaces import IRequestFactory + from pyramid.interfaces import IRoutesMapper + from pyramid.interfaces import IView + from pyramid.interfaces import IViewClassifier + from pyramid.interfaces import ITraverser + from pyramid.request import Request + from pyramid.traversal import DefaultRootFactory + from pyramid.traversal import ResourceTreeTraverser + + q = registry.queryUtility + root_factory = q(IRootFactory, default=DefaultRootFactory) + routes_mapper = q(IRoutesMapper) + request_factory = q(IRequestFactory, default=Request) + + adapters = registry.adapters + request = None + + @implementer(IMultiView) + class RoutesMultiView(object): + + def __init__(self, infos, context_iface, root_factory, request): + self.views = [] + for info in infos: + match, route = info['match'], info['route'] + if route is not None: + request_iface = registry.queryUtility( + IRouteRequest, + name=route.name, + default=IRequest) + view = adapters.lookup( + (IViewClassifier, request_iface, context_iface), + IView, name='', default=None) + if view is None: + continue + view.__request_attrs__ = {} + view.__request_attrs__['matchdict'] = match + view.__request_attrs__['matched_route'] = route + root_factory = route.factory or root_factory + root = root_factory(request) + traverser = adapters.queryAdapter(root, ITraverser) + if traverser is None: + traverser = ResourceTreeTraverser(root) + tdict = traverser(request) + view.__request_attrs__.update(tdict) + if not hasattr(view, '__view_attr__'): + view.__view_attr__ = '' + self.views.append((None, view, None)) + + + # create the request + environ = { + 'wsgi.url_scheme':'http', + 'SERVER_NAME':'localhost', + 'SERVER_PORT':'8080', + 'REQUEST_METHOD':'GET', + 'PATH_INFO':url, + } + request = request_factory(environ) + context = None + routes_multiview = None + attrs = request.__dict__ + attrs['registry'] = registry + request_iface = IRequest + + # find the root object + if routes_mapper is not None: + infos = self._find_multi_routes(routes_mapper, request) + if len(infos) == 1: + info = infos[0] + match, route = info['match'], info['route'] + if route is not None: + attrs['matchdict'] = match + attrs['matched_route'] = route + request.environ['bfg.routes.matchdict'] = match + request_iface = registry.queryUtility( + IRouteRequest, + name=route.name, + default=IRequest) + root_factory = route.factory or root_factory + if len(infos) > 1: + routes_multiview = infos + + root = root_factory(request) + attrs['root'] = root + + # find a context + traverser = adapters.queryAdapter(root, ITraverser) + if traverser is None: + traverser = ResourceTreeTraverser(root) + tdict = traverser(request) + context, view_name, subpath, traversed, vroot, vroot_path =( + tdict['context'], tdict['view_name'], tdict['subpath'], + tdict['traversed'], tdict['virtual_root'], + tdict['virtual_root_path']) + attrs.update(tdict) + + # find a view callable + context_iface = providedBy(context) + if routes_multiview is None: + view = adapters.lookup( + (IViewClassifier, request_iface, context_iface), + IView, name=view_name, default=None) + else: + view = RoutesMultiView(infos, context_iface, root_factory, request) + + # routes are not registered with a view name + if view is None: + view = adapters.lookup( + (IViewClassifier, request_iface, context_iface), + IView, name='', default=None) + # we don't want a multiview here + if IMultiView.providedBy(view): + view = None + + if view is not None: + view.__request_attrs__ = attrs + + return view + + def output_route_attrs(self, attrs, indent): + route = attrs['matched_route'] + self.out("%sroute name: %s" % (indent, route.name)) + self.out("%sroute pattern: %s" % (indent, route.pattern)) + self.out("%sroute path: %s" % (indent, route.path)) + self.out("%ssubpath: %s" % (indent, '/'.join(attrs['subpath']))) + predicates = ', '.join([p.__text__ for p in route.predicates]) + if predicates != '': + self.out("%sroute predicates (%s)" % (indent, predicates)) + + def output_view_info(self, view_wrapper, level=1): + indent = " " * level + name = getattr(view_wrapper, '__name__', '') + module = getattr(view_wrapper, '__module__', '') + attr = getattr(view_wrapper, '__view_attr__', None) + request_attrs = getattr(view_wrapper, '__request_attrs__', {}) + if attr is not None: + view_callable = "%s.%s.%s" % (module, name, attr) + else: + attr = view_wrapper.__class__.__name__ + if attr == 'function': + attr = name + view_callable = "%s.%s" % (module, attr) + self.out('') + if 'matched_route' in request_attrs: + self.out("%sRoute:" % indent) + self.out("%s------" % indent) + self.output_route_attrs(request_attrs, indent) + permission = getattr(view_wrapper, '__permission__', None) + if not IMultiView.providedBy(view_wrapper): + # single view for this route, so repeat call without route data + del request_attrs['matched_route'] + self.output_view_info(view_wrapper, level+1) + else: + self.out("%sView:" % indent) + self.out("%s-----" % indent) + self.out("%s%s" % (indent, view_callable)) + permission = getattr(view_wrapper, '__permission__', None) + if permission is not None: + self.out("%srequired permission = %s" % (indent, permission)) + predicates = getattr(view_wrapper, '__predicates__', None) + if predicates is not None: + predicate_text = ', '.join([p.__text__ for p in predicates]) + self.out("%sview predicates (%s)" % (indent, predicate_text)) + + def run(self): + config_uri, url = self.args + if not url.startswith('/'): + url = '/%s' % url + env = self.bootstrap[0](config_uri) + registry = env['registry'] + view = self._find_view(url, registry) + self.out('') + self.out("URL = %s" % url) + self.out('') + if view is not None: + self.out(" context: %s" % view.__request_attrs__['context']) + self.out(" view name: %s" % view.__request_attrs__['view_name']) + if IMultiView.providedBy(view): + for dummy, view_wrapper, dummy in view.views: + self.output_view_info(view_wrapper) + if IMultiView.providedBy(view_wrapper): + for dummy, mv_view_wrapper, dummy in view_wrapper.views: + self.output_view_info(mv_view_wrapper, level=2) + else: + if view is not None: + self.output_view_info(view) + else: + self.out(" Not found.") + self.out('') diff --git a/pyramid/tests/test_paster.py b/pyramid/tests/test_paster.py index a697b5691..0182ea08b 100644 --- a/pyramid/tests/test_paster.py +++ b/pyramid/tests/test_paster.py @@ -1,834 +1,5 @@ import unittest -from pyramid.testing import skip_on -@skip_on('py3') -class TestPShellCommand(unittest.TestCase): - def _getTargetClass(self): - from pyramid.paster import PShellCommand - return PShellCommand - - def _makeOne(self, patch_bootstrap=True, patch_config=True, - patch_args=True, patch_options=True): - cmd = self._getTargetClass()('pshell') - if patch_bootstrap: - self.bootstrap = DummyBootstrap() - cmd.bootstrap = (self.bootstrap,) - if patch_config: - self.config_factory = DummyConfigParserFactory() - cmd.ConfigParser = self.config_factory - if patch_args: - self.args = ('/foo/bar/myapp.ini#myapp',) - cmd.args = self.args - if patch_options: - class Options(object): pass - self.options = Options() - self.options.disable_ipython = True - self.options.setup = None - cmd.options = self.options - return cmd - - def test_make_default_shell(self): - command = self._makeOne() - interact = DummyInteractor() - shell = command.make_default_shell(interact) - shell({'foo': 'bar'}, 'a help message') - self.assertEqual(interact.local, {'foo': 'bar'}) - self.assertTrue('a help message' in interact.banner) - - def test_make_ipython_v0_11_shell(self): - command = self._makeOne() - ipshell_factory = DummyIPShellFactory() - shell = command.make_ipython_v0_11_shell(ipshell_factory) - shell({'foo': 'bar'}, 'a help message') - self.assertEqual(ipshell_factory.kw['user_ns'], {'foo': 'bar'}) - self.assertTrue('a help message' in ipshell_factory.kw['banner2']) - self.assertTrue(ipshell_factory.shell.called) - - def test_make_ipython_v0_10_shell(self): - command = self._makeOne() - ipshell_factory = DummyIPShellFactory() - shell = command.make_ipython_v0_10_shell(ipshell_factory) - shell({'foo': 'bar'}, 'a help message') - self.assertEqual(ipshell_factory.kw['argv'], []) - self.assertEqual(ipshell_factory.kw['user_ns'], {'foo': 'bar'}) - self.assertTrue('a help message' in ipshell_factory.shell.banner) - self.assertTrue(ipshell_factory.shell.called) - - def test_command_loads_default_shell(self): - command = self._makeOne() - shell = DummyShell() - command.make_ipython_v0_11_shell = lambda: None - command.make_ipython_v0_10_shell = lambda: None - command.make_default_shell = lambda: shell - command.command() - self.assertTrue(self.config_factory.parser) - self.assertEqual(self.config_factory.parser.filename, - '/foo/bar/myapp.ini') - self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') - self.assertEqual(shell.env, { - 'app':self.bootstrap.app, 'root':self.bootstrap.root, - 'registry':self.bootstrap.registry, - 'request':self.bootstrap.request, - 'root_factory':self.bootstrap.root_factory, - }) - self.assertTrue(self.bootstrap.closer.called) - self.assertTrue(shell.help) - - def test_command_loads_default_shell_with_ipython_disabled(self): - command = self._makeOne() - shell = DummyShell() - bad_shell = DummyShell() - command.make_ipython_v0_11_shell = lambda: bad_shell - command.make_ipython_v0_10_shell = lambda: bad_shell - command.make_default_shell = lambda: shell - command.options.disable_ipython = True - command.command() - self.assertTrue(self.config_factory.parser) - self.assertEqual(self.config_factory.parser.filename, - '/foo/bar/myapp.ini') - self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') - self.assertEqual(shell.env, { - 'app':self.bootstrap.app, 'root':self.bootstrap.root, - 'registry':self.bootstrap.registry, - 'request':self.bootstrap.request, - 'root_factory':self.bootstrap.root_factory, - }) - self.assertEqual(bad_shell.env, {}) - self.assertTrue(self.bootstrap.closer.called) - self.assertTrue(shell.help) - - def test_command_loads_ipython_v0_11(self): - command = self._makeOne() - shell = DummyShell() - command.make_ipython_v0_11_shell = lambda: shell - command.make_ipython_v0_10_shell = lambda: None - command.make_default_shell = lambda: None - command.options.disable_ipython = False - command.command() - self.assertTrue(self.config_factory.parser) - self.assertEqual(self.config_factory.parser.filename, - '/foo/bar/myapp.ini') - self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') - self.assertEqual(shell.env, { - 'app':self.bootstrap.app, 'root':self.bootstrap.root, - 'registry':self.bootstrap.registry, - 'request':self.bootstrap.request, - 'root_factory':self.bootstrap.root_factory, - }) - self.assertTrue(self.bootstrap.closer.called) - self.assertTrue(shell.help) - - def test_command_loads_ipython_v0_10(self): - command = self._makeOne() - shell = DummyShell() - command.make_ipython_v0_11_shell = lambda: None - command.make_ipython_v0_10_shell = lambda: shell - command.make_default_shell = lambda: None - command.options.disable_ipython = False - command.command() - self.assertTrue(self.config_factory.parser) - self.assertEqual(self.config_factory.parser.filename, - '/foo/bar/myapp.ini') - self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') - self.assertEqual(shell.env, { - 'app':self.bootstrap.app, 'root':self.bootstrap.root, - 'registry':self.bootstrap.registry, - 'request':self.bootstrap.request, - 'root_factory':self.bootstrap.root_factory, - }) - self.assertTrue(self.bootstrap.closer.called) - self.assertTrue(shell.help) - - def test_command_loads_custom_items(self): - command = self._makeOne() - model = Dummy() - self.config_factory.items = [('m', model)] - shell = DummyShell() - command.command(shell) - self.assertTrue(self.config_factory.parser) - self.assertEqual(self.config_factory.parser.filename, - '/foo/bar/myapp.ini') - self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') - self.assertEqual(shell.env, { - 'app':self.bootstrap.app, 'root':self.bootstrap.root, - 'registry':self.bootstrap.registry, - 'request':self.bootstrap.request, - 'root_factory':self.bootstrap.root_factory, - 'm':model, - }) - self.assertTrue(self.bootstrap.closer.called) - self.assertTrue(shell.help) - - def test_command_setup(self): - command = self._makeOne() - def setup(env): - env['a'] = 1 - env['root'] = 'root override' - self.config_factory.items = [('setup', setup)] - shell = DummyShell() - command.command(shell) - self.assertTrue(self.config_factory.parser) - self.assertEqual(self.config_factory.parser.filename, - '/foo/bar/myapp.ini') - self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') - self.assertEqual(shell.env, { - 'app':self.bootstrap.app, 'root':'root override', - 'registry':self.bootstrap.registry, - 'request':self.bootstrap.request, - 'root_factory':self.bootstrap.root_factory, - 'a':1, - }) - self.assertTrue(self.bootstrap.closer.called) - self.assertTrue(shell.help) - - def test_command_loads_check_variable_override_order(self): - command = self._makeOne() - model = Dummy() - def setup(env): - env['a'] = 1 - env['m'] = 'model override' - env['root'] = 'root override' - self.config_factory.items = [('setup', setup), ('m', model)] - shell = DummyShell() - command.command(shell) - self.assertTrue(self.config_factory.parser) - self.assertEqual(self.config_factory.parser.filename, - '/foo/bar/myapp.ini') - self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') - self.assertEqual(shell.env, { - 'app':self.bootstrap.app, 'root':'root override', - 'registry':self.bootstrap.registry, - 'request':self.bootstrap.request, - 'root_factory':self.bootstrap.root_factory, - 'a':1, 'm':model, - }) - self.assertTrue(self.bootstrap.closer.called) - self.assertTrue(shell.help) - - def test_command_loads_setup_from_options(self): - command = self._makeOne() - def setup(env): - env['a'] = 1 - env['root'] = 'root override' - model = Dummy() - self.config_factory.items = [('setup', 'abc'), - ('m', model)] - command.options.setup = setup - shell = DummyShell() - command.command(shell) - self.assertTrue(self.config_factory.parser) - self.assertEqual(self.config_factory.parser.filename, - '/foo/bar/myapp.ini') - self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') - self.assertEqual(shell.env, { - 'app':self.bootstrap.app, 'root':'root override', - 'registry':self.bootstrap.registry, - 'request':self.bootstrap.request, - 'root_factory':self.bootstrap.root_factory, - 'a':1, 'm':model, - }) - self.assertTrue(self.bootstrap.closer.called) - self.assertTrue(shell.help) - - def test_command_custom_section_override(self): - command = self._makeOne() - dummy = Dummy() - self.config_factory.items = [('app', dummy), ('root', dummy), - ('registry', dummy), ('request', dummy)] - shell = DummyShell() - command.command(shell) - self.assertTrue(self.config_factory.parser) - self.assertEqual(self.config_factory.parser.filename, - '/foo/bar/myapp.ini') - self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') - self.assertEqual(shell.env, { - 'app':dummy, 'root':dummy, 'registry':dummy, 'request':dummy, - 'root_factory':self.bootstrap.root_factory, - }) - self.assertTrue(self.bootstrap.closer.called) - self.assertTrue(shell.help) - -@skip_on('py3') -class TestPRoutesCommand(unittest.TestCase): - def _getTargetClass(self): - from pyramid.paster import PRoutesCommand - return PRoutesCommand - - def _makeOne(self): - cmd = self._getTargetClass()('proutes') - cmd.bootstrap = (DummyBootstrap(),) - cmd.args = ('/foo/bar/myapp.ini#myapp',) - return cmd - - def test_no_routes(self): - command = self._makeOne() - mapper = DummyMapper() - command._get_mapper = lambda *arg: mapper - L = [] - command.out = L.append - result = command.command() - self.assertEqual(result, None) - self.assertEqual(L, []) - - def test_no_mapper(self): - command = self._makeOne() - command._get_mapper = lambda *arg:None - L = [] - command.out = L.append - result = command.command() - self.assertEqual(result, None) - self.assertEqual(L, []) - - def test_single_route_no_route_registered(self): - command = self._makeOne() - route = DummyRoute('a', '/a') - mapper = DummyMapper(route) - command._get_mapper = lambda *arg: mapper - L = [] - command.out = L.append - result = command.command() - self.assertEqual(result, None) - self.assertEqual(len(L), 3) - self.assertEqual(L[-1].split(), ['a', '/a', '<unknown>']) - - def test_single_route_no_views_registered(self): - from zope.interface import Interface - from pyramid.registry import Registry - from pyramid.interfaces import IRouteRequest - registry = Registry() - def view():pass - class IMyRoute(Interface): - pass - registry.registerUtility(IMyRoute, IRouteRequest, name='a') - command = self._makeOne() - route = DummyRoute('a', '/a') - mapper = DummyMapper(route) - command._get_mapper = lambda *arg: mapper - L = [] - command.out = L.append - command.bootstrap = (DummyBootstrap(registry=registry),) - result = command.command() - self.assertEqual(result, None) - self.assertEqual(len(L), 3) - self.assertEqual(L[-1].split()[:3], ['a', '/a', 'None']) - - def test_single_route_one_view_registered(self): - from zope.interface import Interface - from pyramid.registry import Registry - from pyramid.interfaces import IRouteRequest - from pyramid.interfaces import IViewClassifier - from pyramid.interfaces import IView - registry = Registry() - def view():pass - class IMyRoute(Interface): - pass - registry.registerAdapter(view, - (IViewClassifier, IMyRoute, Interface), - IView, '') - registry.registerUtility(IMyRoute, IRouteRequest, name='a') - command = self._makeOne() - route = DummyRoute('a', '/a') - mapper = DummyMapper(route) - command._get_mapper = lambda *arg: mapper - L = [] - command.out = L.append - command.bootstrap = (DummyBootstrap(registry=registry),) - result = command.command() - self.assertEqual(result, None) - self.assertEqual(len(L), 3) - self.assertEqual(L[-1].split()[:4], ['a', '/a', '<function', 'view']) - - def test_single_route_one_view_registered_with_factory(self): - from zope.interface import Interface - from pyramid.registry import Registry - from pyramid.interfaces import IRouteRequest - from pyramid.interfaces import IViewClassifier - from pyramid.interfaces import IView - registry = Registry() - def view():pass - class IMyRoot(Interface): - pass - class IMyRoute(Interface): - pass - registry.registerAdapter(view, - (IViewClassifier, IMyRoute, IMyRoot), - IView, '') - registry.registerUtility(IMyRoute, IRouteRequest, name='a') - command = self._makeOne() - def factory(request): pass - route = DummyRoute('a', '/a', factory=factory) - mapper = DummyMapper(route) - command._get_mapper = lambda *arg: mapper - L = [] - command.out = L.append - command.bootstrap = (DummyBootstrap(registry=registry),) - result = command.command() - self.assertEqual(result, None) - self.assertEqual(len(L), 3) - self.assertEqual(L[-1].split()[:3], ['a', '/a', '<unknown>']) - - def test__get_mapper(self): - from pyramid.registry import Registry - from pyramid.urldispatch import RoutesMapper - command = self._makeOne() - registry = Registry() - result = command._get_mapper(registry) - self.assertEqual(result.__class__, RoutesMapper) - -@skip_on('py3') -class TestPViewsCommand(unittest.TestCase): - def _getTargetClass(self): - from pyramid.paster import PViewsCommand - return PViewsCommand - - def _makeOne(self, registry=None): - cmd = self._getTargetClass()('pviews') - cmd.bootstrap = (DummyBootstrap(registry=registry),) - cmd.args = ('/foo/bar/myapp.ini#myapp',) - return cmd - - def _register_mapper(self, registry, routes): - from pyramid.interfaces import IRoutesMapper - mapper = DummyMapper(*routes) - registry.registerUtility(mapper, IRoutesMapper) - - def test__find_view_no_match(self): - from pyramid.registry import Registry - registry = Registry() - self._register_mapper(registry, []) - command = self._makeOne(registry) - result = command._find_view('/a', registry) - self.assertEqual(result, None) - - def test__find_view_no_match_multiview_registered(self): - from zope.interface import implementer - from zope.interface import providedBy - from pyramid.interfaces import IRequest - from pyramid.interfaces import IViewClassifier - from pyramid.interfaces import IMultiView - from pyramid.traversal import DefaultRootFactory - from pyramid.registry import Registry - registry = Registry() - @implementer(IMultiView) - class View1(object): - pass - request = DummyRequest({'PATH_INFO':'/a'}) - root = DefaultRootFactory(request) - root_iface = providedBy(root) - registry.registerAdapter(View1(), - (IViewClassifier, IRequest, root_iface), - IMultiView) - self._register_mapper(registry, []) - command = self._makeOne(registry=registry) - result = command._find_view('/x', registry) - self.assertEqual(result, None) - - def test__find_view_traversal(self): - from zope.interface import providedBy - from pyramid.interfaces import IRequest - from pyramid.interfaces import IViewClassifier - from pyramid.interfaces import IView - from pyramid.traversal import DefaultRootFactory - from pyramid.registry import Registry - registry = Registry() - def view1(): pass - request = DummyRequest({'PATH_INFO':'/a'}) - root = DefaultRootFactory(request) - root_iface = providedBy(root) - registry.registerAdapter(view1, - (IViewClassifier, IRequest, root_iface), - IView, name='a') - self._register_mapper(registry, []) - command = self._makeOne(registry=registry) - result = command._find_view('/a', registry) - self.assertEqual(result, view1) - - def test__find_view_traversal_multiview(self): - from zope.interface import implementer - from zope.interface import providedBy - from pyramid.interfaces import IRequest - from pyramid.interfaces import IViewClassifier - from pyramid.interfaces import IMultiView - from pyramid.traversal import DefaultRootFactory - from pyramid.registry import Registry - registry = Registry() - @implementer(IMultiView) - class View1(object): - pass - request = DummyRequest({'PATH_INFO':'/a'}) - root = DefaultRootFactory(request) - root_iface = providedBy(root) - view = View1() - registry.registerAdapter(view, - (IViewClassifier, IRequest, root_iface), - IMultiView, name='a') - self._register_mapper(registry, []) - command = self._makeOne(registry=registry) - result = command._find_view('/a', registry) - self.assertEqual(result, view) - - def test__find_view_route_no_multiview(self): - from zope.interface import Interface - from zope.interface import implementer - from pyramid.interfaces import IRouteRequest - from pyramid.interfaces import IViewClassifier - from pyramid.interfaces import IView - from pyramid.registry import Registry - registry = Registry() - def view():pass - class IMyRoot(Interface): - pass - class IMyRoute(Interface): - pass - registry.registerAdapter(view, - (IViewClassifier, IMyRoute, IMyRoot), - IView, '') - registry.registerUtility(IMyRoute, IRouteRequest, name='a') - @implementer(IMyRoot) - class Factory(object): - def __init__(self, request): - pass - routes = [DummyRoute('a', '/a', factory=Factory, matchdict={}), - DummyRoute('b', '/b', factory=Factory)] - self._register_mapper(registry, routes) - command = self._makeOne(registry=registry) - result = command._find_view('/a', registry) - self.assertEqual(result, view) - - def test__find_view_route_multiview_no_view_registered(self): - from zope.interface import Interface - from zope.interface import implementer - from pyramid.interfaces import IRouteRequest - from pyramid.interfaces import IMultiView - from pyramid.interfaces import IRootFactory - from pyramid.registry import Registry - registry = Registry() - def view1():pass - def view2():pass - class IMyRoot(Interface): - pass - class IMyRoute1(Interface): - pass - class IMyRoute2(Interface): - pass - registry.registerUtility(IMyRoute1, IRouteRequest, name='a') - registry.registerUtility(IMyRoute2, IRouteRequest, name='b') - @implementer(IMyRoot) - class Factory(object): - def __init__(self, request): - pass - registry.registerUtility(Factory, IRootFactory) - routes = [DummyRoute('a', '/a', matchdict={}), - DummyRoute('b', '/a', matchdict={})] - self._register_mapper(registry, routes) - command = self._makeOne(registry=registry) - result = command._find_view('/a', registry) - self.assertTrue(IMultiView.providedBy(result)) - - def test__find_view_route_multiview(self): - from zope.interface import Interface - from zope.interface import implementer - from pyramid.interfaces import IRouteRequest - from pyramid.interfaces import IViewClassifier - from pyramid.interfaces import IView - from pyramid.interfaces import IMultiView - from pyramid.interfaces import IRootFactory - from pyramid.registry import Registry - registry = Registry() - def view1():pass - def view2():pass - class IMyRoot(Interface): - pass - class IMyRoute1(Interface): - pass - class IMyRoute2(Interface): - pass - registry.registerAdapter(view1, - (IViewClassifier, IMyRoute1, IMyRoot), - IView, '') - registry.registerAdapter(view2, - (IViewClassifier, IMyRoute2, IMyRoot), - IView, '') - registry.registerUtility(IMyRoute1, IRouteRequest, name='a') - registry.registerUtility(IMyRoute2, IRouteRequest, name='b') - @implementer(IMyRoot) - class Factory(object): - def __init__(self, request): - pass - registry.registerUtility(Factory, IRootFactory) - routes = [DummyRoute('a', '/a', matchdict={}), - DummyRoute('b', '/a', matchdict={})] - self._register_mapper(registry, routes) - command = self._makeOne(registry=registry) - result = command._find_view('/a', registry) - self.assertTrue(IMultiView.providedBy(result)) - self.assertEqual(len(result.views), 2) - self.assertTrue((None, view1, None) in result.views) - self.assertTrue((None, view2, None) in result.views) - - def test__find_multi_routes_all_match(self): - command = self._makeOne() - def factory(request): pass - routes = [DummyRoute('a', '/a', factory=factory, matchdict={}), - DummyRoute('b', '/a', factory=factory, matchdict={})] - mapper = DummyMapper(*routes) - request = DummyRequest({'PATH_INFO':'/a'}) - result = command._find_multi_routes(mapper, request) - self.assertEqual(result, [{'match':{}, 'route':routes[0]}, - {'match':{}, 'route':routes[1]}]) - - def test__find_multi_routes_some_match(self): - command = self._makeOne() - def factory(request): pass - routes = [DummyRoute('a', '/a', factory=factory), - DummyRoute('b', '/a', factory=factory, matchdict={})] - mapper = DummyMapper(*routes) - request = DummyRequest({'PATH_INFO':'/a'}) - result = command._find_multi_routes(mapper, request) - self.assertEqual(result, [{'match':{}, 'route':routes[1]}]) - - def test__find_multi_routes_none_match(self): - command = self._makeOne() - def factory(request): pass - routes = [DummyRoute('a', '/a', factory=factory), - DummyRoute('b', '/a', factory=factory)] - mapper = DummyMapper(*routes) - request = DummyRequest({'PATH_INFO':'/a'}) - result = command._find_multi_routes(mapper, request) - self.assertEqual(result, []) - - def test_views_command_not_found(self): - from pyramid.registry import Registry - registry = Registry() - command = self._makeOne(registry=registry) - L = [] - command.out = L.append - command._find_view = lambda arg1, arg2: None - command.args = ('/foo/bar/myapp.ini#myapp', '/a') - result = command.command() - self.assertEqual(result, None) - self.assertEqual(L[1], 'URL = /a') - self.assertEqual(L[3], ' Not found.') - - def test_views_command_not_found_url_starts_without_slash(self): - from pyramid.registry import Registry - registry = Registry() - command = self._makeOne(registry=registry) - L = [] - command.out = L.append - command._find_view = lambda arg1, arg2: None - command.args = ('/foo/bar/myapp.ini#myapp', 'a') - result = command.command() - self.assertEqual(result, None) - self.assertEqual(L[1], 'URL = /a') - self.assertEqual(L[3], ' Not found.') - - def test_views_command_single_view_traversal(self): - from pyramid.registry import Registry - registry = Registry() - command = self._makeOne(registry=registry) - L = [] - command.out = L.append - view = DummyView(context='context', view_name='a') - command._find_view = lambda arg1, arg2: view - command.args = ('/foo/bar/myapp.ini#myapp', '/a') - result = command.command() - self.assertEqual(result, None) - self.assertEqual(L[1], 'URL = /a') - self.assertEqual(L[3], ' context: context') - self.assertEqual(L[4], ' view name: a') - self.assertEqual(L[8], ' pyramid.tests.test_paster.DummyView') - - def test_views_command_single_view_function_traversal(self): - from pyramid.registry import Registry - registry = Registry() - command = self._makeOne(registry=registry) - L = [] - command.out = L.append - def view(): pass - view.__request_attrs__ = {'context': 'context', 'view_name': 'a'} - command._find_view = lambda arg1, arg2: view - command.args = ('/foo/bar/myapp.ini#myapp', '/a') - result = command.command() - self.assertEqual(result, None) - self.assertEqual(L[1], 'URL = /a') - self.assertEqual(L[3], ' context: context') - self.assertEqual(L[4], ' view name: a') - self.assertEqual(L[8], ' pyramid.tests.test_paster.view') - - def test_views_command_single_view_traversal_with_permission(self): - from pyramid.registry import Registry - registry = Registry() - command = self._makeOne(registry=registry) - L = [] - command.out = L.append - view = DummyView(context='context', view_name='a') - view.__permission__ = 'test' - command._find_view = lambda arg1, arg2: view - command.args = ('/foo/bar/myapp.ini#myapp', '/a') - result = command.command() - self.assertEqual(result, None) - self.assertEqual(L[1], 'URL = /a') - self.assertEqual(L[3], ' context: context') - self.assertEqual(L[4], ' view name: a') - self.assertEqual(L[8], ' pyramid.tests.test_paster.DummyView') - self.assertEqual(L[9], ' required permission = test') - - def test_views_command_single_view_traversal_with_predicates(self): - from pyramid.registry import Registry - registry = Registry() - command = self._makeOne(registry=registry) - L = [] - command.out = L.append - def predicate(): pass - predicate.__text__ = "predicate = x" - view = DummyView(context='context', view_name='a') - view.__predicates__ = [predicate] - command._find_view = lambda arg1, arg2: view - command.args = ('/foo/bar/myapp.ini#myapp', '/a') - result = command.command() - self.assertEqual(result, None) - self.assertEqual(L[1], 'URL = /a') - self.assertEqual(L[3], ' context: context') - self.assertEqual(L[4], ' view name: a') - self.assertEqual(L[8], ' pyramid.tests.test_paster.DummyView') - self.assertEqual(L[9], ' view predicates (predicate = x)') - - def test_views_command_single_view_route(self): - from pyramid.registry import Registry - registry = Registry() - command = self._makeOne(registry=registry) - L = [] - command.out = L.append - route = DummyRoute('a', '/a', matchdict={}) - view = DummyView(context='context', view_name='a', - matched_route=route, subpath='') - command._find_view = lambda arg1, arg2: view - command.args = ('/foo/bar/myapp.ini#myapp', '/a') - result = command.command() - self.assertEqual(result, None) - self.assertEqual(L[1], 'URL = /a') - self.assertEqual(L[3], ' context: context') - self.assertEqual(L[4], ' view name: a') - self.assertEqual(L[6], ' Route:') - self.assertEqual(L[8], ' route name: a') - self.assertEqual(L[9], ' route pattern: /a') - self.assertEqual(L[10], ' route path: /a') - self.assertEqual(L[11], ' subpath: ') - self.assertEqual(L[15], ' pyramid.tests.test_paster.DummyView') - - def test_views_command_multi_view_nested(self): - from pyramid.registry import Registry - registry = Registry() - command = self._makeOne(registry=registry) - L = [] - command.out = L.append - view1 = DummyView(context='context', view_name='a1') - view1.__name__ = 'view1' - view1.__view_attr__ = 'call' - multiview1 = DummyMultiView(view1, context='context', view_name='a1') - multiview2 = DummyMultiView(multiview1, context='context', - view_name='a') - command._find_view = lambda arg1, arg2: multiview2 - command.args = ('/foo/bar/myapp.ini#myapp', '/a') - result = command.command() - self.assertEqual(result, None) - self.assertEqual(L[1], 'URL = /a') - self.assertEqual(L[3], ' context: context') - self.assertEqual(L[4], ' view name: a') - self.assertEqual(L[8], ' pyramid.tests.test_paster.DummyMultiView') - self.assertEqual(L[12], ' pyramid.tests.test_paster.view1.call') - - def test_views_command_single_view_route_with_route_predicates(self): - from pyramid.registry import Registry - registry = Registry() - command = self._makeOne(registry=registry) - L = [] - command.out = L.append - def predicate(): pass - predicate.__text__ = "predicate = x" - route = DummyRoute('a', '/a', matchdict={}, predicate=predicate) - view = DummyView(context='context', view_name='a', - matched_route=route, subpath='') - command._find_view = lambda arg1, arg2: view - command.args = ('/foo/bar/myapp.ini#myapp', '/a') - result = command.command() - self.assertEqual(result, None) - self.assertEqual(L[1], 'URL = /a') - self.assertEqual(L[3], ' context: context') - self.assertEqual(L[4], ' view name: a') - self.assertEqual(L[6], ' Route:') - self.assertEqual(L[8], ' route name: a') - self.assertEqual(L[9], ' route pattern: /a') - self.assertEqual(L[10], ' route path: /a') - self.assertEqual(L[11], ' subpath: ') - self.assertEqual(L[12], ' route predicates (predicate = x)') - self.assertEqual(L[16], ' pyramid.tests.test_paster.DummyView') - - def test_views_command_multiview(self): - from pyramid.registry import Registry - registry = Registry() - command = self._makeOne(registry=registry) - L = [] - command.out = L.append - view = DummyView(context='context') - view.__name__ = 'view' - view.__view_attr__ = 'call' - multiview = DummyMultiView(view, context='context', view_name='a') - command._find_view = lambda arg1, arg2: multiview - command.args = ('/foo/bar/myapp.ini#myapp', '/a') - result = command.command() - self.assertEqual(result, None) - self.assertEqual(L[1], 'URL = /a') - self.assertEqual(L[3], ' context: context') - self.assertEqual(L[4], ' view name: a') - self.assertEqual(L[8], ' pyramid.tests.test_paster.view.call') - - def test_views_command_multiview_with_permission(self): - from pyramid.registry import Registry - registry = Registry() - command = self._makeOne(registry=registry) - L = [] - command.out = L.append - view = DummyView(context='context') - view.__name__ = 'view' - view.__view_attr__ = 'call' - view.__permission__ = 'test' - multiview = DummyMultiView(view, context='context', view_name='a') - command._find_view = lambda arg1, arg2: multiview - command.args = ('/foo/bar/myapp.ini#myapp', '/a') - result = command.command() - self.assertEqual(result, None) - self.assertEqual(L[1], 'URL = /a') - self.assertEqual(L[3], ' context: context') - self.assertEqual(L[4], ' view name: a') - self.assertEqual(L[8], ' pyramid.tests.test_paster.view.call') - self.assertEqual(L[9], ' required permission = test') - - def test_views_command_multiview_with_predicates(self): - from pyramid.registry import Registry - registry = Registry() - command = self._makeOne(registry=registry) - L = [] - command.out = L.append - def predicate(): pass - predicate.__text__ = "predicate = x" - view = DummyView(context='context') - view.__name__ = 'view' - view.__view_attr__ = 'call' - view.__predicates__ = [predicate] - multiview = DummyMultiView(view, context='context', view_name='a') - command._find_view = lambda arg1, arg2: multiview - command.args = ('/foo/bar/myapp.ini#myapp', '/a') - result = command.command() - self.assertEqual(result, None) - self.assertEqual(L[1], 'URL = /a') - self.assertEqual(L[3], ' context: context') - self.assertEqual(L[4], ' view name: a') - self.assertEqual(L[8], ' pyramid.tests.test_paster.view.call') - self.assertEqual(L[9], ' view predicates (predicate = x)') - -@skip_on('py3') class TestGetApp(unittest.TestCase): def _callFUT(self, config_file, section_name, loadapp): from pyramid.paster import get_app @@ -864,7 +35,6 @@ class TestGetApp(unittest.TestCase): self.assertEqual(loadapp.relative_to, os.getcwd()) self.assertEqual(result, app) -@skip_on('py3') class TestBootstrap(unittest.TestCase): def _callFUT(self, config_uri, request=None): from pyramid.paster import bootstrap @@ -904,70 +74,9 @@ class TestBootstrap(unittest.TestCase): self.assertEqual(result['root'], self.root) self.assert_('closer' in result) -@skip_on('py3') -class TestPTweensCommand(unittest.TestCase): - def _getTargetClass(self): - from pyramid.paster import PTweensCommand - return PTweensCommand - - def _makeOne(self): - cmd = self._getTargetClass()('ptweens') - cmd.bootstrap = (DummyBootstrap(),) - cmd.args = ('/foo/bar/myapp.ini#myapp',) - return cmd - - def test_command_no_tweens(self): - command = self._makeOne() - command._get_tweens = lambda *arg: None - L = [] - command.out = L.append - result = command.command() - self.assertEqual(result, None) - self.assertEqual(L, []) - - def test_command_implicit_tweens_only(self): - command = self._makeOne() - tweens = DummyTweens([('name', 'item')], None) - command._get_tweens = lambda *arg: tweens - L = [] - command.out = L.append - result = command.command() - self.assertEqual(result, None) - self.assertEqual( - L[0], - '"pyramid.tweens" config value NOT set (implicitly ordered tweens ' - 'used)') - - def test_command_implicit_and_explicit_tweens(self): - command = self._makeOne() - tweens = DummyTweens([('name', 'item')], [('name2', 'item2')]) - command._get_tweens = lambda *arg: tweens - L = [] - command.out = L.append - result = command.command() - self.assertEqual(result, None) - self.assertEqual( - L[0], - '"pyramid.tweens" config value set (explicitly ordered tweens used)') - - def test__get_tweens(self): - command = self._makeOne() - registry = DummyRegistry() - self.assertEqual(command._get_tweens(registry), None) - -class DummyTweens(object): - def __init__(self, implicit, explicit): - self._implicit = implicit - self.explicit = explicit - self.name_to_alias = {} - def implicit(self): - return self._implicit - class Dummy: pass -dummy_root = Dummy() - class DummyRegistry(object): settings = {} def queryUtility(self, iface, default=None, name=''): @@ -975,35 +84,6 @@ class DummyRegistry(object): dummy_registry = DummyRegistry() -class DummyShell(object): - env = {} - help = '' - - def __call__(self, env, help): - self.env = env - self.help = help - -class DummyInteractor: - def __call__(self, banner, local): - self.banner = banner - self.local = local - -class DummyIPShell(object): - IP = Dummy() - IP.BANNER = 'foo' - - def set_banner(self, banner): - self.banner = banner - - def __call__(self): - self.called = True - -class DummyIPShellFactory(object): - def __call__(self, **kw): - self.kw = kw - self.shell = DummyIPShell() - return self.shell - class DummyLoadApp: def __init__(self, app): self.app = app @@ -1018,28 +98,6 @@ class DummyApp: def __init__(self): self.registry = dummy_registry -class DummyMapper(object): - def __init__(self, *routes): - self.routes = routes - - def get_routes(self): - return self.routes - -class DummyRoute(object): - def __init__(self, name, pattern, factory=None, - matchdict=None, predicate=None): - self.name = name - self.path = pattern - self.pattern = pattern - self.factory = factory - self.matchdict = matchdict - self.predicates = [] - if predicate is not None: - self.predicates = [predicate] - - def match(self, route): - return self.matchdict - class DummyRequest: application_url = 'http://example.com:5432' script_name = '' @@ -1047,72 +105,3 @@ class DummyRequest: self.environ = environ self.matchdict = {} -class DummyView(object): - def __init__(self, **attrs): - self.__request_attrs__ = attrs - -from zope.interface import implementer -from pyramid.interfaces import IMultiView -@implementer(IMultiView) -class DummyMultiView(object): - - def __init__(self, *views, **attrs): - self.views = [(None, view, None) for view in views] - self.__request_attrs__ = attrs - -class DummyConfigParser(object): - def __init__(self, result): - self.result = result - - def read(self, filename): - self.filename = filename - - def items(self, section): - self.section = section - if self.result is None: - from ConfigParser import NoSectionError - raise NoSectionError(section) - return self.result - -class DummyConfigParserFactory(object): - items = None - - def __call__(self): - self.parser = DummyConfigParser(self.items) - return self.parser - -class DummyCloser(object): - def __call__(self): - self.called = True - -class DummyBootstrap(object): - def __init__(self, app=None, registry=None, request=None, root=None, - root_factory=None, closer=None): - self.app = app or DummyApp() - if registry is None: - registry = DummyRegistry() - self.registry = registry - if request is None: - request = DummyRequest({}) - self.request = request - if root is None: - root = Dummy() - self.root = root - if root_factory is None: - root_factory = Dummy() - self.root_factory = root_factory - if closer is None: - closer = DummyCloser() - self.closer = closer - - def __call__(self, *a, **kw): - self.a = a - self.kw = kw - return { - 'app': self.app, - 'registry': self.registry, - 'request': self.request, - 'root': self.root, - 'root_factory': self.root_factory, - 'closer': self.closer, - } diff --git a/pyramid/tests/test_scripts.py b/pyramid/tests/test_scripts.py new file mode 100644 index 000000000..82f4b2c52 --- /dev/null +++ b/pyramid/tests/test_scripts.py @@ -0,0 +1,1037 @@ +import unittest + +class TestPShellCommand(unittest.TestCase): + def _getTargetClass(self): + from pyramid.scripts.pshell import PShellCommand + return PShellCommand + + def _makeOne(self, patch_bootstrap=True, patch_config=True, + patch_args=True, patch_options=True): + cmd = self._getTargetClass()([]) + if patch_bootstrap: + self.bootstrap = DummyBootstrap() + cmd.bootstrap = (self.bootstrap,) + if patch_config: + self.config_factory = DummyConfigParserFactory() + cmd.ConfigParser = self.config_factory + if patch_args: + self.args = ('/foo/bar/myapp.ini#myapp',) + cmd.args = self.args + if patch_options: + class Options(object): pass + self.options = Options() + self.options.disable_ipython = True + self.options.setup = None + cmd.options = self.options + return cmd + + def test_make_default_shell(self): + command = self._makeOne() + interact = DummyInteractor() + shell = command.make_default_shell(interact) + shell({'foo': 'bar'}, 'a help message') + self.assertEqual(interact.local, {'foo': 'bar'}) + self.assertTrue('a help message' in interact.banner) + + def test_make_ipython_v0_11_shell(self): + command = self._makeOne() + ipshell_factory = DummyIPShellFactory() + shell = command.make_ipython_v0_11_shell(ipshell_factory) + shell({'foo': 'bar'}, 'a help message') + self.assertEqual(ipshell_factory.kw['user_ns'], {'foo': 'bar'}) + self.assertTrue('a help message' in ipshell_factory.kw['banner2']) + self.assertTrue(ipshell_factory.shell.called) + + def test_make_ipython_v0_10_shell(self): + command = self._makeOne() + ipshell_factory = DummyIPShellFactory() + shell = command.make_ipython_v0_10_shell(ipshell_factory) + shell({'foo': 'bar'}, 'a help message') + self.assertEqual(ipshell_factory.kw['argv'], []) + self.assertEqual(ipshell_factory.kw['user_ns'], {'foo': 'bar'}) + self.assertTrue('a help message' in ipshell_factory.shell.banner) + self.assertTrue(ipshell_factory.shell.called) + + def test_command_loads_default_shell(self): + command = self._makeOne() + shell = DummyShell() + command.make_ipython_v0_11_shell = lambda: None + command.make_ipython_v0_10_shell = lambda: None + command.make_default_shell = lambda: shell + command.run() + self.assertTrue(self.config_factory.parser) + self.assertEqual(self.config_factory.parser.filename, + '/foo/bar/myapp.ini') + self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') + self.assertEqual(shell.env, { + 'app':self.bootstrap.app, 'root':self.bootstrap.root, + 'registry':self.bootstrap.registry, + 'request':self.bootstrap.request, + 'root_factory':self.bootstrap.root_factory, + }) + self.assertTrue(self.bootstrap.closer.called) + self.assertTrue(shell.help) + + def test_command_loads_default_shell_with_ipython_disabled(self): + command = self._makeOne() + shell = DummyShell() + bad_shell = DummyShell() + command.make_ipython_v0_11_shell = lambda: bad_shell + command.make_ipython_v0_10_shell = lambda: bad_shell + command.make_default_shell = lambda: shell + command.options.disable_ipython = True + command.run() + self.assertTrue(self.config_factory.parser) + self.assertEqual(self.config_factory.parser.filename, + '/foo/bar/myapp.ini') + self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') + self.assertEqual(shell.env, { + 'app':self.bootstrap.app, 'root':self.bootstrap.root, + 'registry':self.bootstrap.registry, + 'request':self.bootstrap.request, + 'root_factory':self.bootstrap.root_factory, + }) + self.assertEqual(bad_shell.env, {}) + self.assertTrue(self.bootstrap.closer.called) + self.assertTrue(shell.help) + + def test_command_loads_ipython_v0_11(self): + command = self._makeOne() + shell = DummyShell() + command.make_ipython_v0_11_shell = lambda: shell + command.make_ipython_v0_10_shell = lambda: None + command.make_default_shell = lambda: None + command.options.disable_ipython = False + command.run() + self.assertTrue(self.config_factory.parser) + self.assertEqual(self.config_factory.parser.filename, + '/foo/bar/myapp.ini') + self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') + self.assertEqual(shell.env, { + 'app':self.bootstrap.app, 'root':self.bootstrap.root, + 'registry':self.bootstrap.registry, + 'request':self.bootstrap.request, + 'root_factory':self.bootstrap.root_factory, + }) + self.assertTrue(self.bootstrap.closer.called) + self.assertTrue(shell.help) + + def test_command_loads_ipython_v0_10(self): + command = self._makeOne() + shell = DummyShell() + command.make_ipython_v0_11_shell = lambda: None + command.make_ipython_v0_10_shell = lambda: shell + command.make_default_shell = lambda: None + command.options.disable_ipython = False + command.run() + self.assertTrue(self.config_factory.parser) + self.assertEqual(self.config_factory.parser.filename, + '/foo/bar/myapp.ini') + self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') + self.assertEqual(shell.env, { + 'app':self.bootstrap.app, 'root':self.bootstrap.root, + 'registry':self.bootstrap.registry, + 'request':self.bootstrap.request, + 'root_factory':self.bootstrap.root_factory, + }) + self.assertTrue(self.bootstrap.closer.called) + self.assertTrue(shell.help) + + def test_command_loads_custom_items(self): + command = self._makeOne() + model = Dummy() + self.config_factory.items = [('m', model)] + shell = DummyShell() + command.run(shell) + self.assertTrue(self.config_factory.parser) + self.assertEqual(self.config_factory.parser.filename, + '/foo/bar/myapp.ini') + self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') + self.assertEqual(shell.env, { + 'app':self.bootstrap.app, 'root':self.bootstrap.root, + 'registry':self.bootstrap.registry, + 'request':self.bootstrap.request, + 'root_factory':self.bootstrap.root_factory, + 'm':model, + }) + self.assertTrue(self.bootstrap.closer.called) + self.assertTrue(shell.help) + + def test_command_setup(self): + command = self._makeOne() + def setup(env): + env['a'] = 1 + env['root'] = 'root override' + self.config_factory.items = [('setup', setup)] + shell = DummyShell() + command.run(shell) + self.assertTrue(self.config_factory.parser) + self.assertEqual(self.config_factory.parser.filename, + '/foo/bar/myapp.ini') + self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') + self.assertEqual(shell.env, { + 'app':self.bootstrap.app, 'root':'root override', + 'registry':self.bootstrap.registry, + 'request':self.bootstrap.request, + 'root_factory':self.bootstrap.root_factory, + 'a':1, + }) + self.assertTrue(self.bootstrap.closer.called) + self.assertTrue(shell.help) + + def test_command_loads_check_variable_override_order(self): + command = self._makeOne() + model = Dummy() + def setup(env): + env['a'] = 1 + env['m'] = 'model override' + env['root'] = 'root override' + self.config_factory.items = [('setup', setup), ('m', model)] + shell = DummyShell() + command.run(shell) + self.assertTrue(self.config_factory.parser) + self.assertEqual(self.config_factory.parser.filename, + '/foo/bar/myapp.ini') + self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') + self.assertEqual(shell.env, { + 'app':self.bootstrap.app, 'root':'root override', + 'registry':self.bootstrap.registry, + 'request':self.bootstrap.request, + 'root_factory':self.bootstrap.root_factory, + 'a':1, 'm':model, + }) + self.assertTrue(self.bootstrap.closer.called) + self.assertTrue(shell.help) + + def test_command_loads_setup_from_options(self): + command = self._makeOne() + def setup(env): + env['a'] = 1 + env['root'] = 'root override' + model = Dummy() + self.config_factory.items = [('setup', 'abc'), + ('m', model)] + command.options.setup = setup + shell = DummyShell() + command.run(shell) + self.assertTrue(self.config_factory.parser) + self.assertEqual(self.config_factory.parser.filename, + '/foo/bar/myapp.ini') + self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') + self.assertEqual(shell.env, { + 'app':self.bootstrap.app, 'root':'root override', + 'registry':self.bootstrap.registry, + 'request':self.bootstrap.request, + 'root_factory':self.bootstrap.root_factory, + 'a':1, 'm':model, + }) + self.assertTrue(self.bootstrap.closer.called) + self.assertTrue(shell.help) + + def test_command_custom_section_override(self): + command = self._makeOne() + dummy = Dummy() + self.config_factory.items = [('app', dummy), ('root', dummy), + ('registry', dummy), ('request', dummy)] + shell = DummyShell() + command.run(shell) + self.assertTrue(self.config_factory.parser) + self.assertEqual(self.config_factory.parser.filename, + '/foo/bar/myapp.ini') + self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') + self.assertEqual(shell.env, { + 'app':dummy, 'root':dummy, 'registry':dummy, 'request':dummy, + 'root_factory':self.bootstrap.root_factory, + }) + self.assertTrue(self.bootstrap.closer.called) + self.assertTrue(shell.help) + +class TestPRoutesCommand(unittest.TestCase): + def _getTargetClass(self): + from pyramid.scripts.proutes import PRoutesCommand + return PRoutesCommand + + def _makeOne(self): + cmd = self._getTargetClass()([]) + cmd.bootstrap = (DummyBootstrap(),) + cmd.args = ('/foo/bar/myapp.ini#myapp',) + return cmd + + def test_no_routes(self): + command = self._makeOne() + mapper = DummyMapper() + command._get_mapper = lambda *arg: mapper + L = [] + command.out = L.append + result = command.run() + self.assertEqual(result, None) + self.assertEqual(L, []) + + def test_no_mapper(self): + command = self._makeOne() + command._get_mapper = lambda *arg:None + L = [] + command.out = L.append + result = command.run() + self.assertEqual(result, None) + self.assertEqual(L, []) + + def test_single_route_no_route_registered(self): + command = self._makeOne() + route = DummyRoute('a', '/a') + mapper = DummyMapper(route) + command._get_mapper = lambda *arg: mapper + L = [] + command.out = L.append + result = command.run() + self.assertEqual(result, None) + self.assertEqual(len(L), 3) + self.assertEqual(L[-1].split(), ['a', '/a', '<unknown>']) + + def test_single_route_no_views_registered(self): + from zope.interface import Interface + from pyramid.registry import Registry + from pyramid.interfaces import IRouteRequest + registry = Registry() + def view():pass + class IMyRoute(Interface): + pass + registry.registerUtility(IMyRoute, IRouteRequest, name='a') + command = self._makeOne() + route = DummyRoute('a', '/a') + mapper = DummyMapper(route) + command._get_mapper = lambda *arg: mapper + L = [] + command.out = L.append + command.bootstrap = (DummyBootstrap(registry=registry),) + result = command.run() + self.assertEqual(result, None) + self.assertEqual(len(L), 3) + self.assertEqual(L[-1].split()[:3], ['a', '/a', 'None']) + + def test_single_route_one_view_registered(self): + from zope.interface import Interface + from pyramid.registry import Registry + from pyramid.interfaces import IRouteRequest + from pyramid.interfaces import IViewClassifier + from pyramid.interfaces import IView + registry = Registry() + def view():pass + class IMyRoute(Interface): + pass + registry.registerAdapter(view, + (IViewClassifier, IMyRoute, Interface), + IView, '') + registry.registerUtility(IMyRoute, IRouteRequest, name='a') + command = self._makeOne() + route = DummyRoute('a', '/a') + mapper = DummyMapper(route) + command._get_mapper = lambda *arg: mapper + L = [] + command.out = L.append + command.bootstrap = (DummyBootstrap(registry=registry),) + result = command.run() + self.assertEqual(result, None) + self.assertEqual(len(L), 3) + self.assertEqual(L[-1].split()[:4], ['a', '/a', '<function', 'view']) + + def test_single_route_one_view_registered_with_factory(self): + from zope.interface import Interface + from pyramid.registry import Registry + from pyramid.interfaces import IRouteRequest + from pyramid.interfaces import IViewClassifier + from pyramid.interfaces import IView + registry = Registry() + def view():pass + class IMyRoot(Interface): + pass + class IMyRoute(Interface): + pass + registry.registerAdapter(view, + (IViewClassifier, IMyRoute, IMyRoot), + IView, '') + registry.registerUtility(IMyRoute, IRouteRequest, name='a') + command = self._makeOne() + def factory(request): pass + route = DummyRoute('a', '/a', factory=factory) + mapper = DummyMapper(route) + command._get_mapper = lambda *arg: mapper + L = [] + command.out = L.append + command.bootstrap = (DummyBootstrap(registry=registry),) + result = command.run() + self.assertEqual(result, None) + self.assertEqual(len(L), 3) + self.assertEqual(L[-1].split()[:3], ['a', '/a', '<unknown>']) + + def test__get_mapper(self): + from pyramid.registry import Registry + from pyramid.urldispatch import RoutesMapper + command = self._makeOne() + registry = Registry() + result = command._get_mapper(registry) + self.assertEqual(result.__class__, RoutesMapper) + +class TestPViewsCommand(unittest.TestCase): + def _getTargetClass(self): + from pyramid.scripts.pviews import PViewsCommand + return PViewsCommand + + def _makeOne(self, registry=None): + cmd = self._getTargetClass()([]) + cmd.bootstrap = (DummyBootstrap(registry=registry),) + cmd.args = ('/foo/bar/myapp.ini#myapp',) + return cmd + + def _register_mapper(self, registry, routes): + from pyramid.interfaces import IRoutesMapper + mapper = DummyMapper(*routes) + registry.registerUtility(mapper, IRoutesMapper) + + def test__find_view_no_match(self): + from pyramid.registry import Registry + registry = Registry() + self._register_mapper(registry, []) + command = self._makeOne(registry) + result = command._find_view('/a', registry) + self.assertEqual(result, None) + + def test__find_view_no_match_multiview_registered(self): + from zope.interface import implementer + from zope.interface import providedBy + from pyramid.interfaces import IRequest + from pyramid.interfaces import IViewClassifier + from pyramid.interfaces import IMultiView + from pyramid.traversal import DefaultRootFactory + from pyramid.registry import Registry + registry = Registry() + @implementer(IMultiView) + class View1(object): + pass + request = DummyRequest({'PATH_INFO':'/a'}) + root = DefaultRootFactory(request) + root_iface = providedBy(root) + registry.registerAdapter(View1(), + (IViewClassifier, IRequest, root_iface), + IMultiView) + self._register_mapper(registry, []) + command = self._makeOne(registry=registry) + result = command._find_view('/x', registry) + self.assertEqual(result, None) + + def test__find_view_traversal(self): + from zope.interface import providedBy + from pyramid.interfaces import IRequest + from pyramid.interfaces import IViewClassifier + from pyramid.interfaces import IView + from pyramid.traversal import DefaultRootFactory + from pyramid.registry import Registry + registry = Registry() + def view1(): pass + request = DummyRequest({'PATH_INFO':'/a'}) + root = DefaultRootFactory(request) + root_iface = providedBy(root) + registry.registerAdapter(view1, + (IViewClassifier, IRequest, root_iface), + IView, name='a') + self._register_mapper(registry, []) + command = self._makeOne(registry=registry) + result = command._find_view('/a', registry) + self.assertEqual(result, view1) + + def test__find_view_traversal_multiview(self): + from zope.interface import implementer + from zope.interface import providedBy + from pyramid.interfaces import IRequest + from pyramid.interfaces import IViewClassifier + from pyramid.interfaces import IMultiView + from pyramid.traversal import DefaultRootFactory + from pyramid.registry import Registry + registry = Registry() + @implementer(IMultiView) + class View1(object): + pass + request = DummyRequest({'PATH_INFO':'/a'}) + root = DefaultRootFactory(request) + root_iface = providedBy(root) + view = View1() + registry.registerAdapter(view, + (IViewClassifier, IRequest, root_iface), + IMultiView, name='a') + self._register_mapper(registry, []) + command = self._makeOne(registry=registry) + result = command._find_view('/a', registry) + self.assertEqual(result, view) + + def test__find_view_route_no_multiview(self): + from zope.interface import Interface + from zope.interface import implementer + from pyramid.interfaces import IRouteRequest + from pyramid.interfaces import IViewClassifier + from pyramid.interfaces import IView + from pyramid.registry import Registry + registry = Registry() + def view():pass + class IMyRoot(Interface): + pass + class IMyRoute(Interface): + pass + registry.registerAdapter(view, + (IViewClassifier, IMyRoute, IMyRoot), + IView, '') + registry.registerUtility(IMyRoute, IRouteRequest, name='a') + @implementer(IMyRoot) + class Factory(object): + def __init__(self, request): + pass + routes = [DummyRoute('a', '/a', factory=Factory, matchdict={}), + DummyRoute('b', '/b', factory=Factory)] + self._register_mapper(registry, routes) + command = self._makeOne(registry=registry) + result = command._find_view('/a', registry) + self.assertEqual(result, view) + + def test__find_view_route_multiview_no_view_registered(self): + from zope.interface import Interface + from zope.interface import implementer + from pyramid.interfaces import IRouteRequest + from pyramid.interfaces import IMultiView + from pyramid.interfaces import IRootFactory + from pyramid.registry import Registry + registry = Registry() + def view1():pass + def view2():pass + class IMyRoot(Interface): + pass + class IMyRoute1(Interface): + pass + class IMyRoute2(Interface): + pass + registry.registerUtility(IMyRoute1, IRouteRequest, name='a') + registry.registerUtility(IMyRoute2, IRouteRequest, name='b') + @implementer(IMyRoot) + class Factory(object): + def __init__(self, request): + pass + registry.registerUtility(Factory, IRootFactory) + routes = [DummyRoute('a', '/a', matchdict={}), + DummyRoute('b', '/a', matchdict={})] + self._register_mapper(registry, routes) + command = self._makeOne(registry=registry) + result = command._find_view('/a', registry) + self.assertTrue(IMultiView.providedBy(result)) + + def test__find_view_route_multiview(self): + from zope.interface import Interface + from zope.interface import implementer + from pyramid.interfaces import IRouteRequest + from pyramid.interfaces import IViewClassifier + from pyramid.interfaces import IView + from pyramid.interfaces import IMultiView + from pyramid.interfaces import IRootFactory + from pyramid.registry import Registry + registry = Registry() + def view1():pass + def view2():pass + class IMyRoot(Interface): + pass + class IMyRoute1(Interface): + pass + class IMyRoute2(Interface): + pass + registry.registerAdapter(view1, + (IViewClassifier, IMyRoute1, IMyRoot), + IView, '') + registry.registerAdapter(view2, + (IViewClassifier, IMyRoute2, IMyRoot), + IView, '') + registry.registerUtility(IMyRoute1, IRouteRequest, name='a') + registry.registerUtility(IMyRoute2, IRouteRequest, name='b') + @implementer(IMyRoot) + class Factory(object): + def __init__(self, request): + pass + registry.registerUtility(Factory, IRootFactory) + routes = [DummyRoute('a', '/a', matchdict={}), + DummyRoute('b', '/a', matchdict={})] + self._register_mapper(registry, routes) + command = self._makeOne(registry=registry) + result = command._find_view('/a', registry) + self.assertTrue(IMultiView.providedBy(result)) + self.assertEqual(len(result.views), 2) + self.assertTrue((None, view1, None) in result.views) + self.assertTrue((None, view2, None) in result.views) + + def test__find_multi_routes_all_match(self): + command = self._makeOne() + def factory(request): pass + routes = [DummyRoute('a', '/a', factory=factory, matchdict={}), + DummyRoute('b', '/a', factory=factory, matchdict={})] + mapper = DummyMapper(*routes) + request = DummyRequest({'PATH_INFO':'/a'}) + result = command._find_multi_routes(mapper, request) + self.assertEqual(result, [{'match':{}, 'route':routes[0]}, + {'match':{}, 'route':routes[1]}]) + + def test__find_multi_routes_some_match(self): + command = self._makeOne() + def factory(request): pass + routes = [DummyRoute('a', '/a', factory=factory), + DummyRoute('b', '/a', factory=factory, matchdict={})] + mapper = DummyMapper(*routes) + request = DummyRequest({'PATH_INFO':'/a'}) + result = command._find_multi_routes(mapper, request) + self.assertEqual(result, [{'match':{}, 'route':routes[1]}]) + + def test__find_multi_routes_none_match(self): + command = self._makeOne() + def factory(request): pass + routes = [DummyRoute('a', '/a', factory=factory), + DummyRoute('b', '/a', factory=factory)] + mapper = DummyMapper(*routes) + request = DummyRequest({'PATH_INFO':'/a'}) + result = command._find_multi_routes(mapper, request) + self.assertEqual(result, []) + + def test_views_command_not_found(self): + from pyramid.registry import Registry + registry = Registry() + command = self._makeOne(registry=registry) + L = [] + command.out = L.append + command._find_view = lambda arg1, arg2: None + command.args = ('/foo/bar/myapp.ini#myapp', '/a') + result = command.run() + self.assertEqual(result, None) + self.assertEqual(L[1], 'URL = /a') + self.assertEqual(L[3], ' Not found.') + + def test_views_command_not_found_url_starts_without_slash(self): + from pyramid.registry import Registry + registry = Registry() + command = self._makeOne(registry=registry) + L = [] + command.out = L.append + command._find_view = lambda arg1, arg2: None + command.args = ('/foo/bar/myapp.ini#myapp', 'a') + result = command.run() + self.assertEqual(result, None) + self.assertEqual(L[1], 'URL = /a') + self.assertEqual(L[3], ' Not found.') + + def test_views_command_single_view_traversal(self): + from pyramid.registry import Registry + registry = Registry() + command = self._makeOne(registry=registry) + L = [] + command.out = L.append + view = DummyView(context='context', view_name='a') + command._find_view = lambda arg1, arg2: view + command.args = ('/foo/bar/myapp.ini#myapp', '/a') + result = command.run() + self.assertEqual(result, None) + self.assertEqual(L[1], 'URL = /a') + self.assertEqual(L[3], ' context: context') + self.assertEqual(L[4], ' view name: a') + self.assertEqual(L[8], ' pyramid.tests.test_scripts.DummyView') + + def test_views_command_single_view_function_traversal(self): + from pyramid.registry import Registry + registry = Registry() + command = self._makeOne(registry=registry) + L = [] + command.out = L.append + def view(): pass + view.__request_attrs__ = {'context': 'context', 'view_name': 'a'} + command._find_view = lambda arg1, arg2: view + command.args = ('/foo/bar/myapp.ini#myapp', '/a') + result = command.run() + self.assertEqual(result, None) + self.assertEqual(L[1], 'URL = /a') + self.assertEqual(L[3], ' context: context') + self.assertEqual(L[4], ' view name: a') + self.assertEqual(L[8], ' pyramid.tests.test_scripts.view') + + def test_views_command_single_view_traversal_with_permission(self): + from pyramid.registry import Registry + registry = Registry() + command = self._makeOne(registry=registry) + L = [] + command.out = L.append + view = DummyView(context='context', view_name='a') + view.__permission__ = 'test' + command._find_view = lambda arg1, arg2: view + command.args = ('/foo/bar/myapp.ini#myapp', '/a') + result = command.run() + self.assertEqual(result, None) + self.assertEqual(L[1], 'URL = /a') + self.assertEqual(L[3], ' context: context') + self.assertEqual(L[4], ' view name: a') + self.assertEqual(L[8], ' pyramid.tests.test_scripts.DummyView') + self.assertEqual(L[9], ' required permission = test') + + def test_views_command_single_view_traversal_with_predicates(self): + from pyramid.registry import Registry + registry = Registry() + command = self._makeOne(registry=registry) + L = [] + command.out = L.append + def predicate(): pass + predicate.__text__ = "predicate = x" + view = DummyView(context='context', view_name='a') + view.__predicates__ = [predicate] + command._find_view = lambda arg1, arg2: view + command.args = ('/foo/bar/myapp.ini#myapp', '/a') + result = command.run() + self.assertEqual(result, None) + self.assertEqual(L[1], 'URL = /a') + self.assertEqual(L[3], ' context: context') + self.assertEqual(L[4], ' view name: a') + self.assertEqual(L[8], ' pyramid.tests.test_scripts.DummyView') + self.assertEqual(L[9], ' view predicates (predicate = x)') + + def test_views_command_single_view_route(self): + from pyramid.registry import Registry + registry = Registry() + command = self._makeOne(registry=registry) + L = [] + command.out = L.append + route = DummyRoute('a', '/a', matchdict={}) + view = DummyView(context='context', view_name='a', + matched_route=route, subpath='') + command._find_view = lambda arg1, arg2: view + command.args = ('/foo/bar/myapp.ini#myapp', '/a') + result = command.run() + self.assertEqual(result, None) + self.assertEqual(L[1], 'URL = /a') + self.assertEqual(L[3], ' context: context') + self.assertEqual(L[4], ' view name: a') + self.assertEqual(L[6], ' Route:') + self.assertEqual(L[8], ' route name: a') + self.assertEqual(L[9], ' route pattern: /a') + self.assertEqual(L[10], ' route path: /a') + self.assertEqual(L[11], ' subpath: ') + self.assertEqual(L[15], ' pyramid.tests.test_scripts.DummyView') + + def test_views_command_multi_view_nested(self): + from pyramid.registry import Registry + registry = Registry() + command = self._makeOne(registry=registry) + L = [] + command.out = L.append + view1 = DummyView(context='context', view_name='a1') + view1.__name__ = 'view1' + view1.__view_attr__ = 'call' + multiview1 = DummyMultiView(view1, context='context', view_name='a1') + multiview2 = DummyMultiView(multiview1, context='context', + view_name='a') + command._find_view = lambda arg1, arg2: multiview2 + command.args = ('/foo/bar/myapp.ini#myapp', '/a') + result = command.run() + self.assertEqual(result, None) + self.assertEqual(L[1], 'URL = /a') + self.assertEqual(L[3], ' context: context') + self.assertEqual(L[4], ' view name: a') + self.assertEqual(L[8], ' pyramid.tests.test_scripts.DummyMultiView') + self.assertEqual(L[12], ' pyramid.tests.test_scripts.view1.call') + + def test_views_command_single_view_route_with_route_predicates(self): + from pyramid.registry import Registry + registry = Registry() + command = self._makeOne(registry=registry) + L = [] + command.out = L.append + def predicate(): pass + predicate.__text__ = "predicate = x" + route = DummyRoute('a', '/a', matchdict={}, predicate=predicate) + view = DummyView(context='context', view_name='a', + matched_route=route, subpath='') + command._find_view = lambda arg1, arg2: view + command.args = ('/foo/bar/myapp.ini#myapp', '/a') + result = command.run() + self.assertEqual(result, None) + self.assertEqual(L[1], 'URL = /a') + self.assertEqual(L[3], ' context: context') + self.assertEqual(L[4], ' view name: a') + self.assertEqual(L[6], ' Route:') + self.assertEqual(L[8], ' route name: a') + self.assertEqual(L[9], ' route pattern: /a') + self.assertEqual(L[10], ' route path: /a') + self.assertEqual(L[11], ' subpath: ') + self.assertEqual(L[12], ' route predicates (predicate = x)') + self.assertEqual(L[16], ' pyramid.tests.test_scripts.DummyView') + + def test_views_command_multiview(self): + from pyramid.registry import Registry + registry = Registry() + command = self._makeOne(registry=registry) + L = [] + command.out = L.append + view = DummyView(context='context') + view.__name__ = 'view' + view.__view_attr__ = 'call' + multiview = DummyMultiView(view, context='context', view_name='a') + command._find_view = lambda arg1, arg2: multiview + command.args = ('/foo/bar/myapp.ini#myapp', '/a') + result = command.run() + self.assertEqual(result, None) + self.assertEqual(L[1], 'URL = /a') + self.assertEqual(L[3], ' context: context') + self.assertEqual(L[4], ' view name: a') + self.assertEqual(L[8], ' pyramid.tests.test_scripts.view.call') + + def test_views_command_multiview_with_permission(self): + from pyramid.registry import Registry + registry = Registry() + command = self._makeOne(registry=registry) + L = [] + command.out = L.append + view = DummyView(context='context') + view.__name__ = 'view' + view.__view_attr__ = 'call' + view.__permission__ = 'test' + multiview = DummyMultiView(view, context='context', view_name='a') + command._find_view = lambda arg1, arg2: multiview + command.args = ('/foo/bar/myapp.ini#myapp', '/a') + result = command.run() + self.assertEqual(result, None) + self.assertEqual(L[1], 'URL = /a') + self.assertEqual(L[3], ' context: context') + self.assertEqual(L[4], ' view name: a') + self.assertEqual(L[8], ' pyramid.tests.test_scripts.view.call') + self.assertEqual(L[9], ' required permission = test') + + def test_views_command_multiview_with_predicates(self): + from pyramid.registry import Registry + registry = Registry() + command = self._makeOne(registry=registry) + L = [] + command.out = L.append + def predicate(): pass + predicate.__text__ = "predicate = x" + view = DummyView(context='context') + view.__name__ = 'view' + view.__view_attr__ = 'call' + view.__predicates__ = [predicate] + multiview = DummyMultiView(view, context='context', view_name='a') + command._find_view = lambda arg1, arg2: multiview + command.args = ('/foo/bar/myapp.ini#myapp', '/a') + result = command.run() + self.assertEqual(result, None) + self.assertEqual(L[1], 'URL = /a') + self.assertEqual(L[3], ' context: context') + self.assertEqual(L[4], ' view name: a') + self.assertEqual(L[8], ' pyramid.tests.test_scripts.view.call') + self.assertEqual(L[9], ' view predicates (predicate = x)') + +class TestPTweensCommand(unittest.TestCase): + def _getTargetClass(self): + from pyramid.scripts.ptweens import PTweensCommand + return PTweensCommand + + def _makeOne(self): + cmd = self._getTargetClass()([]) + cmd.bootstrap = (DummyBootstrap(),) + cmd.args = ('/foo/bar/myapp.ini#myapp',) + return cmd + + def test_command_no_tweens(self): + command = self._makeOne() + command._get_tweens = lambda *arg: None + L = [] + command.out = L.append + result = command.run() + self.assertEqual(result, None) + self.assertEqual(L, []) + + def test_command_implicit_tweens_only(self): + command = self._makeOne() + tweens = DummyTweens([('name', 'item')], None) + command._get_tweens = lambda *arg: tweens + L = [] + command.out = L.append + result = command.run() + self.assertEqual(result, None) + self.assertEqual( + L[0], + '"pyramid.tweens" config value NOT set (implicitly ordered tweens ' + 'used)') + + def test_command_implicit_and_explicit_tweens(self): + command = self._makeOne() + tweens = DummyTweens([('name', 'item')], [('name2', 'item2')]) + command._get_tweens = lambda *arg: tweens + L = [] + command.out = L.append + result = command.run() + self.assertEqual(result, None) + self.assertEqual( + L[0], + '"pyramid.tweens" config value set (explicitly ordered tweens used)') + + def test__get_tweens(self): + command = self._makeOne() + registry = DummyRegistry() + self.assertEqual(command._get_tweens(registry), None) + +class DummyTweens(object): + def __init__(self, implicit, explicit): + self._implicit = implicit + self.explicit = explicit + self.name_to_alias = {} + def implicit(self): + return self._implicit + +class Dummy: + pass + +dummy_root = Dummy() + +class DummyRegistry(object): + settings = {} + def queryUtility(self, iface, default=None, name=''): + return default + +dummy_registry = DummyRegistry() + +class DummyShell(object): + env = {} + help = '' + + def __call__(self, env, help): + self.env = env + self.help = help + +class DummyInteractor: + def __call__(self, banner, local): + self.banner = banner + self.local = local + +class DummyIPShell(object): + IP = Dummy() + IP.BANNER = 'foo' + + def set_banner(self, banner): + self.banner = banner + + def __call__(self): + self.called = True + +class DummyIPShellFactory(object): + def __call__(self, **kw): + self.kw = kw + self.shell = DummyIPShell() + return self.shell + +class DummyLoadApp: + def __init__(self, app): + self.app = app + + def __call__(self, config_name, name=None, relative_to=None): + self.config_name = config_name + self.section_name = name + self.relative_to = relative_to + return self.app + +class DummyApp: + def __init__(self): + self.registry = dummy_registry + +class DummyMapper(object): + def __init__(self, *routes): + self.routes = routes + + def get_routes(self): + return self.routes + +class DummyRoute(object): + def __init__(self, name, pattern, factory=None, + matchdict=None, predicate=None): + self.name = name + self.path = pattern + self.pattern = pattern + self.factory = factory + self.matchdict = matchdict + self.predicates = [] + if predicate is not None: + self.predicates = [predicate] + + def match(self, route): + return self.matchdict + +class DummyRequest: + application_url = 'http://example.com:5432' + script_name = '' + def __init__(self, environ): + self.environ = environ + self.matchdict = {} + +class DummyView(object): + def __init__(self, **attrs): + self.__request_attrs__ = attrs + +from zope.interface import implementer +from pyramid.interfaces import IMultiView +@implementer(IMultiView) +class DummyMultiView(object): + + def __init__(self, *views, **attrs): + self.views = [(None, view, None) for view in views] + self.__request_attrs__ = attrs + +class DummyConfigParser(object): + def __init__(self, result): + self.result = result + + def read(self, filename): + self.filename = filename + + def items(self, section): + self.section = section + if self.result is None: + from ConfigParser import NoSectionError + raise NoSectionError(section) + return self.result + +class DummyConfigParserFactory(object): + items = None + + def __call__(self): + self.parser = DummyConfigParser(self.items) + return self.parser + +class DummyCloser(object): + def __call__(self): + self.called = True + +class DummyBootstrap(object): + def __init__(self, app=None, registry=None, request=None, root=None, + root_factory=None, closer=None): + self.app = app or DummyApp() + if registry is None: + registry = DummyRegistry() + self.registry = registry + if request is None: + request = DummyRequest({}) + self.request = request + if root is None: + root = Dummy() + self.root = root + if root_factory is None: + root_factory = Dummy() + self.root_factory = root_factory + if closer is None: + closer = DummyCloser() + self.closer = closer + + def __call__(self, *a, **kw): + self.a = a + self.kw = kw + return { + 'app': self.app, + 'registry': self.registry, + 'request': self.request, + 'root': self.root, + 'root_factory': self.root_factory, + 'closer': self.closer, + } @@ -39,7 +39,7 @@ install_requires=[ 'zope.deprecation >= 3.5.0', # py3 compat 'venusian >= 1.0a1', # ``onerror`` 'translationstring >= 0.4', # py3 compat - 'glue', + 'PasteDeploy >= 1.5.0', # py3 compat ] tests_require = install_requires + [ @@ -89,15 +89,14 @@ setup(name='pyramid', zodb=pyramid.scaffolds:ZODBProjectTemplate routesalchemy=pyramid.scaffolds:RoutesAlchemyProjectTemplate alchemy=pyramid.scaffolds:AlchemyProjectTemplate - [glue.command] - pshell=pyramid.paster:PShellCommand - proutes=pyramid.paster:PRoutesCommand - pviews=pyramid.paster:PViewsCommand - ptweens=pyramid.paster:PTweensCommand [console_scripts] bfg2pyramid = pyramid.fixers.fix_bfg_imports:main pcreate = pyramid.scripts.pcreate:main pserve = pyramid.scripts.pserve:main + pshell = pyramid.scripts.pshell:main + proutes = pyramid.scripts.proutes:main + pviews = pyramid.scripts.pviews:main + ptweens = pyramid.scripts.ptweens:main [paste.server_runner] wsgiref = pyramid.scripts.pserve:wsgiref_server_runner """ |
