From 828384c14b07aa4f50a70f44f789ce4b1b1e34f6 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Wed, 6 Jul 2011 01:32:52 -0500 Subject: Added [pshell] support to INI files and the ability to load generic wsgi apps. Generic WSGI apps can now be loaded without exposing the 'registry' and 'root' objects. When an app is loaded, extra variables will be exposed to the environment from a special [pshell] section of the INI file. These variables are of the format "name = asset.path.to.object". --- pyramid/paster.py | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 89 insertions(+), 4 deletions(-) diff --git a/pyramid/paster.py b/pyramid/paster.py index f670ae618..9683da043 100644 --- a/pyramid/paster.py +++ b/pyramid/paster.py @@ -1,13 +1,16 @@ import os +import re import sys from code import interact import zope.deprecation from paste.deploy import loadapp +from paste.script.command import BadCommand 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( @@ -79,6 +82,45 @@ class PShellCommand(PCommand): dest='disable_ipython', help="Don't use IPython even if it is available") + _pshell_section_re = re.compile(r'^\s*\[\s*pshell\s*\]\s*$') + _section_re = re.compile(r'^\s*\[') + + def pshell_file_config(self, filename): + vars = { + 'here': os.path.dirname(filename), + '__file__': filename, + } + f = open(filename) + lines = f.readlines() + f.close() + lineno = 1 + # find the pshell section + while lines: + if self._pshell_section_re.search(lines[0]): + lines.pop(0) + break + lines.pop(0) + lineno += 1 + # parse pshell section for key/value pairs + resolver = DottedNameResolver(None) + self.loaded_objects = {} + self.object_help = {} + for line in lines: + lineno += 1 + line = line.strip() + if not line or line.startswith('#'): + continue + if self._section_re.search(line): + break + if '=' not in line: + raise BadCommand('Missing = in %s at %s: %r' + % (filename, lineno, line)) + name, value = line.split('=', 1) + name = name.strip() + value = value.strip() % vars + self.loaded_objects[name] = resolver.maybe_resolve(value) + self.object_help[name] = value + def command(self, IPShell=_marker): # IPShell passed to command method is for testing purposes if IPShell is _marker: # pragma: no cover @@ -86,15 +128,58 @@ class PShellCommand(PCommand): 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) app_spec = self.args[0] config_file = app_spec.split('#', 1)[0] self.logging_file_config(config_file) app = self.get_app(app_spec, loadapp=self.loadapp[0]) - root, closer = self.get_root(app) - shell_globals = {'root':root, 'registry':app.registry} + + # 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}) + 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: -- cgit v1.2.3