-
Notifications
You must be signed in to change notification settings - Fork 22
Expand file tree
/
Copy pathtgshell.py
More file actions
147 lines (113 loc) · 5.02 KB
/
tgshell.py
File metadata and controls
147 lines (113 loc) · 5.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import os, sys
import tg
from gearbox.command import Command
from paste.deploy import loadapp
class ShellCommand(Command):
"""Opens an interactive shell with a PasteDeploy loadable app loaded
The optional CONFIG_FILE argument specifies the config file to use for
the interactive shell. CONFIG_FILE defaults to 'development.ini'.
This allows you to test your mapper, models, and simulate web requests
using ``WebTest``.
Example::
$ gearbox tgshell -c my-development.ini
"""
def get_description(self):
return "Opens an interactive shell with a TurboGears2 app loaded"
def get_parser(self, prog_name):
parser = super(ShellCommand, self).get_parser(prog_name)
parser.add_argument('-d', '--disable-ipython',
action='store_true',
dest='disable_ipython',
help="Don't use IPython if it is available")
parser.add_argument("-c", "--config",
help='application config file to read (default: development.ini)',
dest='config_file', default="development.ini")
parser.add_argument('script',
nargs='?',
help='script to run, if omitted will open an interactive session')
return parser
def take_action(self, opts):
config_file = opts.config_file
config_name = 'config:%s' % config_file
here_dir = os.getcwd()
locs = dict(__name__="tgshell")
# Load locals and populate with objects for use in shell
sys.path.insert(0, here_dir)
# Load the wsgi app first so that everything is initialized right
wsgiapp = loadapp(config_name, relative_to=here_dir)
# Make available the tg.request and other global variables
req = tg.Request.blank('/_test_vars', environ={'paste.testing_variables': {}})
tresponse = req.send(wsgiapp)
pkg_name = tg.config['package_name']
# Start the rest of our imports now that the app is loaded
model_module = pkg_name + '.model'
helpers_module = pkg_name + '.lib.helpers'
base_module = pkg_name + '.lib.base'
if self._can_import(model_module):
locs['model'] = sys.modules[model_module]
if self._can_import(helpers_module):
locs['h'] = sys.modules[helpers_module]
exec('import tg', locs)
exec('from tg import app_globals, config, request, response, '
'session, tmpl_context, url', locs)
locs.pop('__builtins__', None)
# Import all objects from the base module
__import__(base_module)
base = sys.modules[base_module]
base_public = [__name for __name in dir(base) if not\
__name.startswith('_') or __name == '_']
locs.update((name, getattr(base, name)) for name in base_public)
locs.update(dict(wsgiapp=wsgiapp))
try:
from webtest import TestApp
except ImportError:
pass
else:
# As WebTest is available, provide the webtest wrapped app.
locs.update(dict(app=TestApp(wsgiapp)))
if opts.script:
self._run_script(opts.script, locs)
else:
self._run_shell(base_module, locs, opts.disable_ipython)
def _run_script(self, script, locs):
script_path = os.path.abspath(script)
if not os.path.exists(script_path):
raise IOError('Unable to open %s script' % script_path)
import code
i = code.InteractiveInterpreter(locals=locs)
i.runsource(open(script_path).read(), script_path, 'exec')
def _run_shell(self, base_module, locs, disable_ipython):
banner = " All objects from %s are available\n" % base_module
banner += " Additional Objects:\n"
banner += " %-10s - %s\n" % ('wsgiapp',
"This project's WSGI App instance")
if 'app' in locs:
banner += " %-10s - %s\n" % ('app',
'WebTest.TestApp wrapped around wsgiapp')
try:
if disable_ipython:
raise ImportError()
from IPython import start_ipython
from IPython.terminal.ipapp import load_default_config
config = load_default_config()
config.TerminalInteractiveShell.banner1 = banner
start_ipython(argv=[], user_ns=locs, config=config)
return
except ImportError:
import code
py_prefix = sys.platform.startswith('java') and 'J' or 'P'
newbanner = "TurboGears2 Interactive Shell\n%sython %s\n\n" % \
(py_prefix, sys.version)
banner = newbanner + banner
shell = code.InteractiveConsole(locals=locs)
try:
import readline
except ImportError:
pass
shell.interact(banner)
def _can_import(self, name):
try:
__import__(name)
return True
except ImportError:
return False