-
Notifications
You must be signed in to change notification settings - Fork 882
/
paster.py
193 lines (159 loc) · 7.29 KB
/
paster.py
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
import os
import sys
from code import interact
from paste.deploy import loadapp
from paste.script.command import Command
from paste.script.templates import Template
from paste.util.template import paste_script_template_renderer
from pyramid.scripting import get_root
class PyramidTemplate(Template):
def pre(self, command, output_dir, vars): # pragma: no cover
vars['random_string'] = os.urandom(20).encode('hex')
package_logger = vars['package']
if package_logger == 'root':
# Rename the app logger in the rare case a project is named 'root'
package_logger = 'app'
vars['package_logger'] = package_logger
return Template.pre(self, command, output_dir, vars)
class StarterProjectTemplate(PyramidTemplate):
_template_dir = 'paster_templates/starter'
summary = 'pyramid starter project'
template_renderer = staticmethod(paste_script_template_renderer)
class ZODBProjectTemplate(PyramidTemplate):
_template_dir = 'paster_templates/zodb'
summary = 'pyramid ZODB starter project'
template_renderer = staticmethod(paste_script_template_renderer)
class RoutesAlchemyProjectTemplate(PyramidTemplate):
_template_dir = 'paster_templates/routesalchemy'
summary = 'pyramid SQLAlchemy project using url dispatch (no traversal)'
template_renderer = staticmethod(paste_script_template_renderer)
class AlchemyProjectTemplate(PyramidTemplate):
_template_dir = 'paster_templates/alchemy'
summary = 'pyramid SQLAlchemy project using traversal'
template_renderer = staticmethod(paste_script_template_renderer)
def get_app(config_file, name, loadapp=loadapp):
""" Return the WSGI application named ``name`` in the PasteDeploy
config file ``config_file``"""
config_name = 'config:%s' % config_file
here_dir = os.getcwd()
app = loadapp(config_name, name=name, relative_to=here_dir)
return app
_marker = object()
class PCommand(Command):
get_app = staticmethod(get_app) # hook point
get_root = staticmethod(get_root) # hook point
group_name = 'pyramid'
interact = (interact,) # for testing
loadapp = (loadapp,) # for 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 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.
Example::
$ 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
your Pyramid app without any middleware wrapping, or this
command will almost certainly fail.
"""
summary = "Open an interactive shell with a pyramid app loaded"
min_args = 2
max_args = 2
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")
def command(self, IPShell=_marker):
if IPShell is _marker:
try: #pragma no cover
from IPython.Shell import IPShell
except ImportError: #pragma no cover
IPShell = None
cprt =('Type "help" for more information. "root" is the Pyramid app '
'root object, "registry" is the Pyramid registry object.')
banner = "Python %s on %s\n%s" % (sys.version, sys.platform, cprt)
config_file, section_name = self.args
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}
if IPShell is not None and not self.options.disable_ipython:
try:
shell = IPShell(argv=[], user_ns=shell_globals)
shell.IP.BANNER = shell.IP.BANNER + '\n\n' + banner
shell.mainloop()
finally:
closer()
else:
try:
self.interact[0](banner, local=shell_globals)
finally:
closer()
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 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.
Example::
$ 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
your Pyramid app without any middleware wrapping, or this
command will almost certainly fail.
"""
summary = "Print all URL dispatch routes related to a Pyramid application"
min_args = 2
max_args = 2
stdout = sys.stdout
parser = Command.standard_parser(simulate=True)
def _get_mapper(self, app):
from pyramid.config import Configurator
registry = app.registry
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_file, section_name = self.args
app = self.get_app(config_file, section_name, loadapp=self.loadapp[0])
registry = app.registry
mapper = self._get_mapper(app)
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))