docs/api/paster.rst | ●●●●● patch | view | raw | blame | history | |
docs/narr/project.rst | ●●●●● patch | view | raw | blame | history | |
docs/narr/urldispatch.rst | ●●●●● patch | view | raw | blame | history | |
docs/narr/viewconfig.rst | ●●●●● patch | view | raw | blame | history | |
pyramid/paster.py | ●●●●● patch | view | raw | blame | history | |
pyramid/tests/test_paster.py | ●●●●● patch | view | raw | blame | history |
docs/api/paster.rst
@@ -5,9 +5,12 @@ .. module:: pyramid.paster .. function:: get_app(config_file, name) .. function:: get_app(config_file, name=None) Return the WSGI application named ``name`` in the PasteDeploy config file ``config_file``. If the ``name`` is None, this will attempt to parse the name from the ``config_file`` string expecting the format ``ini_file#name``. If no name is found, the name will default to "main". docs/narr/project.rst
@@ -258,8 +258,9 @@ :app:`Pyramid` project's :term:`resource` and :term:`view` objects from a Python prompt. To do so, use your virtualenv's ``paster pshell`` command. The first argument to ``pshell`` is the path to your application's ``.ini`` file. The second is the ``app`` section name inside the ``.ini`` file which The argument to ``pshell`` follows the format ``config_file#section_name`` where ``config_file`` is the path to your application's ``.ini`` file and ``section_name`` is the ``app`` section name inside the ``.ini`` file which points to *your application* as opposed to any other section within the ``.ini`` file. For example, if your application ``.ini`` file might have a ``[app:MyProject]`` section that looks like so: @@ -280,16 +281,21 @@ .. code-block:: text [chrism@vitaminf shellenv]$ ../bin/paster pshell development.ini MyProject [chrism@vitaminf shellenv]$ ../bin/paster pshell development.ini#MyProject Python 2.4.5 (#1, Aug 29 2008, 12:27:37) [GCC 4.0.1 (Apple Inc. build 5465)] on darwin Type "help" for more information. "root" is the Pyramid app root object, "registry" is the Pyramid registry object. Default Variables: app The WSGI Application root The root of the default resource tree. registry The Pyramid registry object. settings The Pyramid settings object. >>> root <myproject.resources.MyResource object at 0x445270> >>> registry <Registry myproject> >>> registry.settings['debug_notfound'] >>> settings['debug_notfound'] False >>> from myproject.views import my_view >>> from pyramid.request import Request @@ -297,31 +303,16 @@ >>> my_view(r) {'project': 'myproject'} Two names are made available to the pshell user as globals: ``root`` and ``registry``. ``root`` is the the object returned by the default :term:`root factory` in your application. ``registry`` is the :term:`application registry` object associated with your project's application (often accessed within view code as ``request.registry``). The WSGI application that is loaded will be available in the shell as the ``app`` global. Also, if the application that is loaded is the :app:`Pyramid` app with no surrounding middleware, the ``root`` object returned by the default :term:`root factory`, ``registry``, and ``settings`` will be available. If you have `IPython <http://en.wikipedia.org/wiki/IPython>`_ installed in the interpreter you use to invoke the ``paster`` command, the ``pshell`` command will use an IPython interactive shell instead of a standard Python interpreter shell. If you don't want this to happen, even if you have IPython installed, you can pass the ``--disable-ipython`` flag to the ``pshell`` command to use a standard Python interpreter shell unconditionally. .. code-block:: text [chrism@vitaminf shellenv]$ ../bin/paster pshell --disable-ipython \ development.ini MyProject You should always use a section name argument that refers to the actual ``app`` section within the Paste configuration file that points at your :app:`Pyramid` application *without any middleware wrapping*. In particular, a section name is inappropriate as the second argument to ``pshell`` if the configuration section it names is a ``pipeline`` rather than an ``app``. For example, if you have the following ``.ini`` file content: The interactive shell will not be able to load some of the globals like ``root``, ``registry`` and ``settings`` if the section name specified when loading ``pshell`` is not referencing your :app:`Pyramid` application directly. For example, if you have the following ``.ini`` file content: .. code-block:: ini :linenos: @@ -341,12 +332,51 @@ Use ``MyProject`` instead of ``main`` as the section name argument to ``pshell`` against the above ``.ini`` file (e.g. ``paster pshell development.ini MyProject``). If you use ``main`` instead, an error will occur. Use the most specific reference to your application within the ``.ini`` file possible as the section name argument. development.ini#MyProject``). Press ``Ctrl-D`` to exit the interactive shell (or ``Ctrl-Z`` on Windows). Extending the Shell ~~~~~~~~~~~~~~~~~~~ It is sometimes convenient when using the interactive shell often to have some variables significant to your application already loaded as globals when you start the ``pshell``. To facilitate this, ``pshell`` will look for a special ``[pshell]`` section in your INI file and expose the subsequent key/value pairs to the shell. For example, you want to expose your model to the shell, along with the database session so that you can mutate the model on an actual database. Here, we'll assume your model is stored in the ``myapp.models`` package. .. code-block:: ini :linenos: [pshell] m = myapp.models session = myapp.models.DBSession t = transaction When this INI file is loaded, the extra variables ``m``, ``session`` and ``t`` will be available for use immediately. This happens regardless of whether the ``registry`` and other special variables are loaded. IPython ~~~~~~~ If you have `IPython <http://en.wikipedia.org/wiki/IPython>`_ installed in the interpreter you use to invoke the ``paster`` command, the ``pshell`` command will use an IPython interactive shell instead of a standard Python interpreter shell. If you don't want this to happen, even if you have IPython installed, you can pass the ``--disable-ipython`` flag to the ``pshell`` command to use a standard Python interpreter shell unconditionally. .. code-block:: text [chrism@vitaminf shellenv]$ ../bin/paster pshell --disable-ipython \ development.ini#MyProject .. index:: single: running an application single: paster serve docs/narr/urldispatch.rst
@@ -1084,16 +1084,17 @@ You can use the ``paster proutes`` command in a terminal window to print a summary of routes related to your application. Much like the ``paster pshell`` command (see :ref:`interactive_shell`), the ``paster proutes`` command accepts two arguments. The first argument to ``proutes`` is the path to your application's ``.ini`` file. The second is the ``app`` section name inside the ``.ini`` file which points to your application. command accepts one argument with the format ``config_file#section_name``. The ``config_file`` is the path to your application's ``.ini`` file, and ``section_name`` is the ``app`` section name inside the ``.ini`` file which points to your application. For example: .. code-block:: text :linenos: [chrism@thinko MyProject]$ ../bin/paster proutes development.ini MyProject [chrism@thinko MyProject]$ ../bin/paster proutes development.ini#MyProject Name Pattern View ---- ------- ---- home / <function my_view> docs/narr/viewconfig.rst
@@ -795,10 +795,11 @@ configuration details in your head, even if you defined all the views yourself. You can use the ``paster pviews`` command in a terminal window to print a summary of matching routes and views for a given URL in your application. The ``paster pviews`` command accepts three arguments. The first argument to ``pviews`` is the path to your application's ``.ini`` file. The second is the ``app`` section name inside the ``.ini`` file which points to your application. The third is the URL to test for matching views. application. The ``paster pviews`` command accepts two arguments. The first argument to ``pviews`` is the path to your application's ``.ini`` file and section name inside the ``.ini`` file which points to your application. This should be of the format ``config_file#section_name``. The second argument is the URL to test for matching views. Here is an example for a simple view configuration using :term:`traversal`: @@ -829,7 +830,7 @@ .. code-block:: text :linenos: $ ../bin/paster pviews development.ini shootout /about $ ../bin/paster pviews development.ini#shootout /about URL = /about pyramid/paster.py
@@ -1,4 +1,6 @@ import ConfigParser import os import re import sys from code import interact @@ -8,6 +10,7 @@ from paste.script.command import Command from pyramid.scripting import get_root from pyramid.util import DottedNameResolver from pyramid.scaffolds import PyramidTemplate # bw compat zope.deprecation.deprecated( @@ -15,12 +18,22 @@ 'pyramid.scaffolds.PyramidTemplate in Pyramid 1.1'), ) def get_app(config_file, name, loadapp=loadapp): def get_app(config_file, name=None, loadapp=loadapp): """ Return the WSGI application named ``name`` in the PasteDeploy config file ``config_file``""" config_name = 'config:%s' % config_file config file ``config_file``. If the ``name`` is None, this will attempt to parse the name from the ``config_file`` string expecting the format ``ini_file#name``. If no name is found, the name will default to "main".""" if '#' in config_file: path, section = config_file.split('#', 1) else: path, section = config_file, 'main' if name: section = name config_name = 'config:%s' % path here_dir = os.getcwd() app = loadapp(config_name, name=name, relative_to=here_dir) app = loadapp(config_name, name=section, relative_to=here_dir) return app _marker = object() @@ -42,17 +55,15 @@ class PShellCommand(PCommand): """Open an interactive shell with a :app:`Pyramid` app loaded. This command accepts two positional arguments: This command accepts one positional argument: ``config_file`` -- specifies the PasteDeploy config file to use for the interactive shell. ``section_name`` -- specifies the section name in the PasteDeploy config file that represents the application. ``config_file#section_name`` -- specifies the PasteDeploy config file to use for the interactive shell. If the section_name is left off, ``main`` will be assumed. Example:: $ paster pshell myapp.ini main $ paster pshell myapp.ini#main .. note:: You should use a ``section_name`` that refers to the actual ``app`` section in the config file that points at @@ -62,14 +73,30 @@ """ summary = "Open an interactive shell with a Pyramid application loaded" min_args = 2 max_args = 2 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") ConfigParser = ConfigParser.ConfigParser # testing def pshell_file_config(self, filename): resolver = DottedNameResolver(None) self.loaded_objects = {} self.object_help = {} config = self.ConfigParser() config.read(filename) try: items = config.items('pshell') except ConfigParser.NoSectionError: return for k, v in items: self.loaded_objects[k] = resolver.maybe_resolve(v) self.object_help[k] = v def command(self, IPShell=_marker): # IPShell passed to command method is for testing purposes @@ -78,14 +105,59 @@ from IPython.Shell import IPShell except ImportError: IPShell = None cprt =('Type "help" for more information. "root" is the Pyramid app ' 'root object, "registry" is the Pyramid registry object.') cprt =('Type "help" for more information.') banner = "Python %s on %s\n%s" % (sys.version, sys.platform, cprt) config_file, section_name = self.args app_spec = self.args[0] config_file = app_spec.split('#', 1)[0] self.logging_file_config(config_file) app = self.get_app(config_file, section_name, loadapp=self.loadapp[0]) root, closer = self.get_root(app) shell_globals = {'root':root, 'registry':app.registry} app = self.get_app(app_spec, loadapp=self.loadapp[0]) # load default globals shell_globals = { 'app': app, } default_variables = {'app': 'The WSGI Application'} if hasattr(app, 'registry'): root, closer = self.get_root(app) shell_globals.update({'root':root, 'registry':app.registry, 'settings': app.registry.settings}) default_variables.update({ 'root': 'The root of the default resource tree.', 'registry': 'The Pyramid registry object.', 'settings': 'The Pyramid settings object.', }) warning = '' else: # warn the user that this isn't actually the Pyramid app warning = """\n WARNING: You have loaded a generic WSGI application, therefore the "root" and "registry" are not available. To correct this, run "pshell" again and specify the INI section containing your Pyramid application.""" closer = lambda: None # load the pshell section of the ini file self.pshell_file_config(config_file) shell_globals.update(self.loaded_objects) # eliminate duplicates from default_variables for k in self.loaded_objects: if k in default_variables: del default_variables[k] # append the loaded variables if default_variables: banner += '\n\nDefault Variables:' for var, txt in default_variables.iteritems(): banner += '\n %-12s %s' % (var, txt) if self.object_help: banner += '\n\nCustom Variables:' for var in sorted(self.object_help.keys()): banner += '\n %-12s %s' % (var, self.object_help[var]) # append the warning banner += warning banner += '\n' if (IPShell is None) or self.options.disable_ipython: try: @@ -108,17 +180,15 @@ route, the pattern of the route, and the view callable which will be invoked when the route is matched. This command accepts two positional arguments: This command accepts one positional argument: ``config_file`` -- specifies the PasteDeploy config file to use for the interactive shell. ``section_name`` -- specifies the section name in the PasteDeploy config file that represents the application. ``config_file#section_name`` -- specifies the PasteDeploy config file to use for the interactive shell. If the section_name is left off, ``main`` will be assumed. Example:: $ paster proutes myapp.ini main $ paster proutes myapp.ini#main .. note:: You should use a ``section_name`` that refers to the actual ``app`` section in the config file that points at @@ -126,8 +196,8 @@ command will almost certainly fail. """ summary = "Print all URL dispatch routes related to a Pyramid application" min_args = 2 max_args = 2 min_args = 1 max_args = 1 stdout = sys.stdout parser = Command.standard_parser(simulate=True) @@ -146,8 +216,8 @@ from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IView from zope.interface import Interface config_file, section_name = self.args app = self.get_app(config_file, section_name, loadapp=self.loadapp[0]) app_spec = self.args[0] app = self.get_app(app_spec, loadapp=self.loadapp[0]) registry = app.registry mapper = self._get_mapper(app) if mapper is not None: @@ -179,19 +249,17 @@ each route+predicate set, print each view that might match and its predicates. This command accepts three positional arguments: This command accepts two positional arguments: ``config_file`` -- specifies the PasteDeploy config file to use for the interactive shell. ``section_name`` -- specifies the section name in the PasteDeploy config file that represents the application. ``config_file#section_name`` -- specifies the PasteDeploy config file to use for the interactive shell. If the section_name is left off, ``main`` will be assumed. ``url`` -- specifies the URL that will be used to find matching views. Example:: $ paster proutes myapp.ini main url $ paster proutes myapp.ini#main url .. note:: You should use a ``section_name`` that refers to the actual ``app`` section in the config file that points at @@ -199,8 +267,8 @@ command will almost certainly fail. """ summary = "Print all views in an application that might match a URL" min_args = 3 max_args = 3 min_args = 2 max_args = 2 stdout = sys.stdout parser = Command.standard_parser(simulate=True) @@ -395,10 +463,10 @@ self.out("%sview predicates (%s)" % (indent, predicate_text)) def command(self): config_file, section_name, url = self.args app_spec, url = self.args if not url.startswith('/'): url = '/%s' % url app = self.get_app(config_file, section_name, loadapp=self.loadapp[0]) app = self.get_app(app_spec, loadapp=self.loadapp[0]) registry = app.registry view = self._find_view(url, registry) self.out('') pyramid/tests/test_paster.py
@@ -15,7 +15,8 @@ loadapp = DummyLoadApp(app) command.interact = (interact,) command.loadapp = (loadapp,) command.args = ('/foo/bar/myapp.ini', 'myapp') command.ConfigParser = makeDummyConfigParser({}) command.args = ('/foo/bar/myapp.ini#myapp',) class Options(object): pass command.options = Options() command.options.disable_ipython = False @@ -27,8 +28,10 @@ pushed = app.threadlocal_manager.pushed[0] self.assertEqual(pushed['registry'], dummy_registry) self.assertEqual(pushed['request'].registry, dummy_registry) self.assertEqual(interact.local, {'root':dummy_root, 'registry':dummy_registry}) self.assertEqual(interact.local, {'app':app, 'root':dummy_root, 'registry':dummy_registry, 'settings':dummy_registry.settings}) self.assertTrue(interact.banner) self.assertEqual(len(app.threadlocal_manager.popped), 1) @@ -39,7 +42,8 @@ loadapp = DummyLoadApp(app) command.interact = (interact,) command.loadapp = (loadapp,) command.args = ('/foo/bar/myapp.ini', 'myapp') command.ConfigParser = makeDummyConfigParser({}) command.args = ('/foo/bar/myapp.ini#myapp',) class Options(object): pass command.options = Options() command.options.disable_ipython = True @@ -51,8 +55,10 @@ pushed = app.threadlocal_manager.pushed[0] self.assertEqual(pushed['registry'], dummy_registry) self.assertEqual(pushed['request'].registry, dummy_registry) self.assertEqual(interact.local, {'root':dummy_root, 'registry':dummy_registry}) self.assertEqual(interact.local, {'app':app, 'root':dummy_root, 'registry':dummy_registry, 'settings':dummy_registry.settings}) self.assertTrue(interact.banner) self.assertEqual(len(app.threadlocal_manager.popped), 1) @@ -61,8 +67,9 @@ app = DummyApp() loadapp = DummyLoadApp(app) command.loadapp = (loadapp,) command.ConfigParser = makeDummyConfigParser({}) dummy_shell_factory = DummyIPShellFactory() command.args = ('/foo/bar/myapp.ini', 'myapp') command.args = ('/foo/bar/myapp.ini#myapp',) class Options(object): pass command.options = Options() command.options.disable_ipython = False @@ -75,7 +82,9 @@ self.assertEqual(pushed['registry'], dummy_registry) self.assertEqual(pushed['request'].registry, dummy_registry) self.assertEqual(dummy_shell_factory.shell.local_ns, {'root':dummy_root, 'registry':dummy_registry}) {'app':app, 'root':dummy_root, 'registry':dummy_registry, 'settings':dummy_registry.settings}) self.assertEqual(dummy_shell_factory.shell.global_ns, {}) self.assertTrue('\n\n' in dummy_shell_factory.shell.IP.BANNER) self.assertEqual(len(app.threadlocal_manager.popped), 1) @@ -92,7 +101,8 @@ interact = DummyInteractor() app = DummyApp() command.interact = (interact,) command.args = ('/foo/bar/myapp.ini', 'myapp') command.ConfigParser = makeDummyConfigParser({}) command.args = ('/foo/bar/myapp.ini#myapp',) class Options(object): pass command.options = Options() command.options.disable_ipython =True @@ -101,11 +111,13 @@ pushed = app.threadlocal_manager.pushed[0] self.assertEqual(pushed['registry'], dummy_registry) self.assertEqual(pushed['request'].registry, dummy_registry) self.assertEqual(interact.local, {'root':dummy_root, 'registry':dummy_registry}) self.assertEqual(interact.local, {'app': app, 'root':dummy_root, 'registry':dummy_registry, 'settings':dummy_registry.settings}) self.assertTrue(interact.banner) self.assertEqual(len(app.threadlocal_manager.popped), 1) self.assertEqual(apped, [(('/foo/bar/myapp.ini', 'myapp'), self.assertEqual(apped, [(('/foo/bar/myapp.ini#myapp',), {'loadapp': loadapp})]) def test_command_get_root_hookable(self): @@ -115,13 +127,14 @@ loadapp = DummyLoadApp(app) command.interact = (interact,) command.loadapp = (loadapp,) command.ConfigParser = makeDummyConfigParser({}) root = Dummy() apps = [] def get_root(app): apps.append(app) return root, lambda *arg: None command.get_root =get_root command.args = ('/foo/bar/myapp.ini', 'myapp') command.args = ('/foo/bar/myapp.ini#myapp',) class Options(object): pass command.options = Options() command.options.disable_ipython =True @@ -130,10 +143,107 @@ self.assertEqual(loadapp.section_name, 'myapp') self.assertTrue(loadapp.relative_to) self.assertEqual(len(app.threadlocal_manager.pushed), 0) self.assertEqual(interact.local, {'root':root, 'registry':dummy_registry}) self.assertEqual(interact.local, {'app':app, 'root':root, 'registry':dummy_registry, 'settings':dummy_registry.settings}) self.assertTrue(interact.banner) self.assertEqual(apps, [app]) def test_command_loads_custom_items(self): command = self._makeOne() interact = DummyInteractor() app = DummyApp() loadapp = DummyLoadApp(app) command.interact = (interact,) command.loadapp = (loadapp,) model = Dummy() command.ConfigParser = makeDummyConfigParser([('m', model)]) command.args = ('/foo/bar/myapp.ini#myapp',) class Options(object): pass command.options = Options() command.options.disable_ipython = False command.command(IPShell=None) self.assertEqual(loadapp.config_name, 'config:/foo/bar/myapp.ini') self.assertEqual(loadapp.section_name, 'myapp') self.assertTrue(loadapp.relative_to) self.assertEqual(len(app.threadlocal_manager.pushed), 1) pushed = app.threadlocal_manager.pushed[0] self.assertEqual(pushed['registry'], dummy_registry) self.assertEqual(pushed['request'].registry, dummy_registry) self.assertEqual(interact.local, {'app':app, 'root':dummy_root, 'registry':dummy_registry, 'settings':dummy_registry.settings, 'm': model}) self.assertTrue(interact.banner) self.assertEqual(len(app.threadlocal_manager.popped), 1) def test_command_no_custom_section(self): command = self._makeOne() interact = DummyInteractor() app = DummyApp() loadapp = DummyLoadApp(app) command.interact = (interact,) command.loadapp = (loadapp,) command.ConfigParser = makeDummyConfigParser(None) command.args = ('/foo/bar/myapp.ini#myapp',) class Options(object): pass command.options = Options() command.options.disable_ipython = False command.command(IPShell=None) self.assertEqual(loadapp.config_name, 'config:/foo/bar/myapp.ini') self.assertEqual(loadapp.section_name, 'myapp') self.assertTrue(loadapp.relative_to) self.assertEqual(len(app.threadlocal_manager.pushed), 1) pushed = app.threadlocal_manager.pushed[0] self.assertEqual(pushed['registry'], dummy_registry) self.assertEqual(pushed['request'].registry, dummy_registry) self.assertEqual(interact.local, {'app':app, 'root':dummy_root, 'registry':dummy_registry, 'settings':dummy_registry.settings}) self.assertTrue(interact.banner) self.assertEqual(len(app.threadlocal_manager.popped), 1) def test_command_custom_section_override(self): command = self._makeOne() interact = DummyInteractor() app = Dummy() loadapp = DummyLoadApp(app) command.interact = (interact,) command.loadapp = (loadapp,) model = Dummy() command.ConfigParser = makeDummyConfigParser([('app', model)]) command.args = ('/foo/bar/myapp.ini#myapp',) class Options(object): pass command.options = Options() command.options.disable_ipython = False command.command(IPShell=None) self.assertEqual(loadapp.config_name, 'config:/foo/bar/myapp.ini') self.assertEqual(loadapp.section_name, 'myapp') self.assertTrue(loadapp.relative_to) self.assertEqual(interact.local, {'app':model}) self.assertTrue(interact.banner) def test_command_generic_wsgi_app(self): command = self._makeOne() interact = DummyInteractor() app = Dummy() loadapp = DummyLoadApp(app) command.interact = (interact,) command.loadapp = (loadapp,) command.ConfigParser = makeDummyConfigParser(None) command.args = ('/foo/bar/myapp.ini#myapp',) class Options(object): pass command.options = Options() command.options.disable_ipython = False command.command(IPShell=None) self.assertEqual(loadapp.config_name, 'config:/foo/bar/myapp.ini') self.assertEqual(loadapp.section_name, 'myapp') self.assertTrue(loadapp.relative_to) self.assertEqual(interact.local, {'app':app}) self.assertTrue(interact.banner) class TestPRoutesCommand(unittest.TestCase): def _getTargetClass(self): @@ -152,7 +262,7 @@ app = DummyApp() loadapp = DummyLoadApp(app) command.loadapp = (loadapp,) command.args = ('/foo/bar/myapp.ini', 'myapp') command.args = ('/foo/bar/myapp.ini#myapp',) result = command.command() self.assertEqual(result, None) self.assertEqual(L, []) @@ -165,7 +275,7 @@ app = DummyApp() loadapp = DummyLoadApp(app) command.loadapp = (loadapp,) command.args = ('/foo/bar/myapp.ini', 'myapp') command.args = ('/foo/bar/myapp.ini#myapp',) result = command.command() self.assertEqual(result, None) self.assertEqual(L, []) @@ -180,7 +290,7 @@ app = DummyApp() loadapp = DummyLoadApp(app) command.loadapp = (loadapp,) command.args = ('/foo/bar/myapp.ini', 'myapp') command.args = ('/foo/bar/myapp.ini#myapp',) result = command.command() self.assertEqual(result, None) self.assertEqual(len(L), 3) @@ -205,7 +315,7 @@ app.registry = registry loadapp = DummyLoadApp(app) command.loadapp = (loadapp,) command.args = ('/foo/bar/myapp.ini', 'myapp') command.args = ('/foo/bar/myapp.ini#myapp',) result = command.command() self.assertEqual(result, None) self.assertEqual(len(L), 3) @@ -235,7 +345,7 @@ app.registry = registry loadapp = DummyLoadApp(app) command.loadapp = (loadapp,) command.args = ('/foo/bar/myapp.ini', 'myapp') command.args = ('/foo/bar/myapp.ini#myapp',) result = command.command() self.assertEqual(result, None) self.assertEqual(len(L), 3) @@ -268,7 +378,7 @@ app.registry = registry loadapp = DummyLoadApp(app) command.loadapp = (loadapp,) command.args = ('/foo/bar/myapp.ini', 'myapp') command.args = ('/foo/bar/myapp.ini#myapp',) result = command.command() self.assertEqual(result, None) self.assertEqual(len(L), 3) @@ -511,7 +621,7 @@ app.registry = registry loadapp = DummyLoadApp(app) command.loadapp = (loadapp,) command.args = ('/foo/bar/myapp.ini', 'myapp', '/a') command.args = ('/foo/bar/myapp.ini#myapp', '/a') result = command.command() self.assertEqual(result, None) self.assertEqual(L[1], 'URL = /a') @@ -528,7 +638,7 @@ app.registry = registry loadapp = DummyLoadApp(app) command.loadapp = (loadapp,) command.args = ('/foo/bar/myapp.ini', 'myapp', 'a') command.args = ('/foo/bar/myapp.ini#myapp', 'a') result = command.command() self.assertEqual(result, None) self.assertEqual(L[1], 'URL = /a') @@ -546,7 +656,7 @@ app.registry = registry loadapp = DummyLoadApp(app) command.loadapp = (loadapp,) command.args = ('/foo/bar/myapp.ini', 'myapp', '/a') command.args = ('/foo/bar/myapp.ini#myapp', '/a') result = command.command() self.assertEqual(result, None) self.assertEqual(L[1], 'URL = /a') @@ -567,7 +677,7 @@ app.registry = registry loadapp = DummyLoadApp(app) command.loadapp = (loadapp,) command.args = ('/foo/bar/myapp.ini', 'myapp', '/a') command.args = ('/foo/bar/myapp.ini#myapp', '/a') result = command.command() self.assertEqual(result, None) self.assertEqual(L[1], 'URL = /a') @@ -588,7 +698,7 @@ app.registry = registry loadapp = DummyLoadApp(app) command.loadapp = (loadapp,) command.args = ('/foo/bar/myapp.ini', 'myapp', '/a') command.args = ('/foo/bar/myapp.ini#myapp', '/a') result = command.command() self.assertEqual(result, None) self.assertEqual(L[1], 'URL = /a') @@ -612,7 +722,7 @@ app.registry = registry loadapp = DummyLoadApp(app) command.loadapp = (loadapp,) command.args = ('/foo/bar/myapp.ini', 'myapp', '/a') command.args = ('/foo/bar/myapp.ini#myapp', '/a') result = command.command() self.assertEqual(result, None) self.assertEqual(L[1], 'URL = /a') @@ -635,7 +745,7 @@ app.registry = registry loadapp = DummyLoadApp(app) command.loadapp = (loadapp,) command.args = ('/foo/bar/myapp.ini', 'myapp', '/a') command.args = ('/foo/bar/myapp.ini#myapp', '/a') result = command.command() self.assertEqual(result, None) self.assertEqual(L[1], 'URL = /a') @@ -665,7 +775,7 @@ app.registry = registry loadapp = DummyLoadApp(app) command.loadapp = (loadapp,) command.args = ('/foo/bar/myapp.ini', 'myapp', '/a') command.args = ('/foo/bar/myapp.ini#myapp', '/a') result = command.command() self.assertEqual(result, None) self.assertEqual(L[1], 'URL = /a') @@ -690,7 +800,7 @@ app.registry = registry loadapp = DummyLoadApp(app) command.loadapp = (loadapp,) command.args = ('/foo/bar/myapp.ini', 'myapp', '/a') command.args = ('/foo/bar/myapp.ini#myapp', '/a') result = command.command() self.assertEqual(result, None) self.assertEqual(L[1], 'URL = /a') @@ -719,7 +829,7 @@ app.registry = registry loadapp = DummyLoadApp(app) command.loadapp = (loadapp,) command.args = ('/foo/bar/myapp.ini', 'myapp', '/a') command.args = ('/foo/bar/myapp.ini#myapp', '/a') result = command.command() self.assertEqual(result, None) self.assertEqual(L[1], 'URL = /a') @@ -743,7 +853,7 @@ app.registry = registry loadapp = DummyLoadApp(app) command.loadapp = (loadapp,) command.args = ('/foo/bar/myapp.ini', 'myapp', '/a') command.args = ('/foo/bar/myapp.ini#myapp', '/a') result = command.command() self.assertEqual(result, None) self.assertEqual(L[1], 'URL = /a') @@ -770,7 +880,7 @@ app.registry = registry loadapp = DummyLoadApp(app) command.loadapp = (loadapp,) command.args = ('/foo/bar/myapp.ini', 'myapp', '/a') command.args = ('/foo/bar/myapp.ini#myapp', '/a') result = command.command() self.assertEqual(result, None) self.assertEqual(L[1], 'URL = /a') @@ -796,6 +906,26 @@ result = self._callFUT('/foo/bar/myapp.ini', 'myapp', loadapp) self.assertEqual(loadapp.config_name, 'config:/foo/bar/myapp.ini') self.assertEqual(loadapp.section_name, 'myapp') self.assertEqual(loadapp.relative_to, os.getcwd()) self.assertEqual(result, app) def test_it_with_hash(self): import os app = DummyApp() loadapp = DummyLoadApp(app) result = self._callFUT('/foo/bar/myapp.ini#myapp', None, loadapp) self.assertEqual(loadapp.config_name, 'config:/foo/bar/myapp.ini') self.assertEqual(loadapp.section_name, 'myapp') self.assertEqual(loadapp.relative_to, os.getcwd()) self.assertEqual(result, app) def test_it_with_hash_and_name_override(self): import os app = DummyApp() loadapp = DummyLoadApp(app) result = self._callFUT('/foo/bar/myapp.ini#myapp', 'yourapp', loadapp) self.assertEqual(loadapp.config_name, 'config:/foo/bar/myapp.ini') self.assertEqual(loadapp.section_name, 'yourapp') self.assertEqual(loadapp.relative_to, os.getcwd()) self.assertEqual(result, app) @@ -824,6 +954,7 @@ dummy_root = Dummy() class DummyRegistry(object): settings = {} def queryUtility(self, iface, default=None, name=''): return default @@ -905,3 +1036,15 @@ self.views = [(None, view, None) for view in views] self.__request_attrs__ = attrs def makeDummyConfigParser(items): class DummyConfigParser(object): def read(self, filename): self.filename = filename def items(self, section): self.section = section if items is None: from ConfigParser import NoSectionError raise NoSectionError, section return items return DummyConfigParser