Skip to content
Browse files

PEP8 gardening

  • Loading branch information...
1 parent 8e71df8 commit 114171f54f2a6bb75d0cc5cd427ddd2a30f43d06 @bbangert bbangert committed
View
9 pylons/__init__.py
@@ -11,6 +11,7 @@
__all__ = ['app_globals', 'cache', 'config', 'request', 'response',
'session', 'tmpl_context', 'url', 'Request', 'Response']
+
def __figure_version():
try:
from pkg_resources import require
@@ -19,14 +20,14 @@ def __figure_version():
# or has an .egg-info directory present (i.e. wont work with raw
# SVN checkout)
info = require('pylons')[0]
- if os.path.normcase(os.path.realpath(os.path.dirname(
- os.path.dirname(__file__)))) == info.location:
- return info.version
+ if os.path.normcase(os.path.realpath(os.path.dirname(
+ os.path.dirname(__file__)))) == info.location:
+ return info.version
else:
return '(not installed)'
except:
return '(not installed)'
-
+
__version__ = __figure_version()
app_globals = StackedObjectProxy(name="app_globals")
View
40 pylons/commands.py
@@ -16,7 +16,7 @@
Open an interactive shell with the Pylons app loaded
Example usage::
-
+
~/sample$ paster controller account
Creating /Users/ben/sample/sample/controllers/account.py
Creating /Users/ben/sample/sample/tests/functional/test_account.py
@@ -26,12 +26,12 @@
:command:`paster` is a command line script (from the PasteScript
package) that allows the creation of context sensitive commands.
- :command:`paster` looks in the current directory for a
+ :command:`paster` looks in the current directory for a
``.egg-info`` directory, then loads the ``paster_plugins.txt``
file.
Using setuptools entry points, :command:`paster` looks for
- functions registered with setuptools as
+ functions registered with setuptools as
:func:`paste.paster_command`. These are defined in the entry_points
block in each packages :file:`setup.py` module.
@@ -54,6 +54,7 @@
__all__ = ['ControllerCommand', 'RestControllerCommand', 'ShellCommand']
+
def can_import(name):
"""Attempt to __import__ the specified package/module, returning
True when succeeding, otherwise False"""
@@ -120,11 +121,11 @@ def validate_name(name):
return True
-def check_controller_existence(base_package, directory, name):
+def check_controller_existence(base_package, directory, name):
"""Check if given controller already exists in project."""
filename = os.path.join(base_package, 'controllers', directory,
name + '.py')
- if os.path.exists(filename):
+ if os.path.exists(filename):
raise BadCommand('Controller %s already exists.' %
os.path.join(directory, name))
@@ -203,15 +204,15 @@ def command(self):
if not fullname.startswith(os.sep):
fullname = os.sep + fullname
testname = fullname.replace(os.sep, '_')[1:]
-
+
module_dir = directory.replace('/', os.path.sep)
check_controller_existence(base_package, module_dir, name)
-
+
file_op.template_vars.update(
{'name': controller_name,
'fname': os.path.join(directory, name).replace('\\', '/'),
'tmpl_name': name,
- 'package':base_package,
+ 'package': base_package,
'importstatement': importstatement})
file_op.copy_file(template='controller.py_tmpl',
dest=os.path.join('controllers', directory),
@@ -294,7 +295,7 @@ def command(self):
if base_package.lower() == pluralname.lower():
raise BadCommand(
'Your controller name should not be the same as '
- 'the package name %r.'% base_package)
+ 'the package name %r.' % base_package)
# Validate the name
for name in [pluralname]:
name = name.replace('-', '_')
@@ -309,11 +310,10 @@ def command(self):
base_package)
if defines_render(base_package):
importstatement += ', render'
-
-
+
module_dir = pluraldirectory.replace('/', os.path.sep)
check_controller_existence(base_package, module_dir, name)
-
+
# Setup the controller
fullname = os.path.join(pluraldirectory, pluralname)
controller_name = util.class_name_from_module_name(
@@ -327,7 +327,7 @@ def command(self):
if pluraldirectory:
nameprefix = pluraldirectory.replace(os.path.sep, '_') + '_'
path = pluraldirectory + '/'
-
+
controller_c = ''
if nameprefix:
controller_c = ", controller='%s', \n\t" % \
@@ -343,10 +343,10 @@ def command(self):
'singularname': singularname,
'name': controller_name,
'nameprefix': nameprefix,
- 'package':base_package,
- 'path':path,
+ 'package': base_package,
+ 'path': path,
'resource_command': command.replace('\n\t', '\n%s#%s' % \
- (' '*4, ' '*9)),
+ (' ' * 4, ' ' * 9)),
'fname': os.path.join(pluraldirectory, pluralname),
'importstatement': importstatement})
@@ -419,7 +419,7 @@ def command(self):
if not self.options.quiet:
# Configure logging from the config file
self.logging_file_config(config_file)
-
+
# Load the wsgi app first so that everything is initialized right
wsgiapp = loadapp(config_name, relative_to=here_dir)
test_app = paste.fixture.TestApp(wsgiapp)
@@ -486,7 +486,7 @@ def command(self):
if not self.options.quiet:
# Configure logging from the config file
self.logging_file_config(config_file)
-
+
# Load locals and populate with objects for use in shell
sys.path.insert(0, here_dir)
@@ -507,7 +507,7 @@ def command(self):
# Restore the state of the Pylons special objects
# (StackedObjectProxies)
paste.registry.restorer.restoration_begin(request_id)
-
+
# Determine the package name from the pylons.config object
pkg_name = pylons.config['pylons.package']
@@ -532,7 +532,7 @@ def command(self):
exec ('from pylons.controllers.util import abort, redirect') in locs
exec 'from pylons.i18n import _, ungettext, N_' in locs
locs.pop('__builtins__', None)
-
+
# Import all objects from the base module
__import__(base_module)
View
41 pylons/configuration.py
@@ -34,6 +34,7 @@
config = DispatchingConfig()
+
class PylonsConfig(dict):
"""Pylons configuration object
@@ -71,11 +72,11 @@ class PylonsConfig(dict):
``pylons.request_options``
A dict of Content-Type related default settings for new
instances of :class:`~pylons.controllers.util.Request`. May
- contain the values ``charset`` and ``errors`` and
+ contain the values ``charset`` and ``errors`` and
``decode_param_names``. Overrides the Pylons default values
specified by the ``request_defaults`` dict.
``pylons.response_options``
- A dict of Content-Type related default settings for new
+ A dict of Content-Type related default settings for new
instances of :class:`~pylons.controllers.util.Response`. May
contain the values ``content_type``, ``charset`` and
``errors``. Overrides the Pylons default values specified by
@@ -83,7 +84,7 @@ class PylonsConfig(dict):
``routes.map``
Mapper object used for Routing. Yes, it is possible to add
routes after your application has started running.
-
+
"""
defaults = {
'debug': False,
@@ -101,18 +102,18 @@ class PylonsConfig(dict):
'pylons.strict_tmpl_context': True,
'pylons.tmpl_context_attach_args': False,
}
-
+
def init_app(self, global_conf, app_conf, package=None, paths=None):
"""Initialize configuration for the application
-
+
.. note
- This *must* be called at least once, as soon as possible
+ This *must* be called at least once, as soon as possible
to setup all the configuration options.
-
+
``global_conf``
Several options are expected to be set for a Pylons web
- application. They will be loaded from the global_config
- which has the main Paste options. If ``debug`` is not
+ application. They will be loaded from the global_config
+ which has the main Paste options. If ``debug`` is not
enabled as a global config option, the following option
*must* be set:
@@ -120,7 +121,7 @@ def init_app(self, global_conf, app_conf, package=None, paths=None):
The optional config options in this case are:
- * smtp_server - The SMTP server to use, defaults to
+ * smtp_server - The SMTP server to use, defaults to
'localhost'
* error_log - A logfile to write the error to
* error_subject_prefix - The prefix of the error email
@@ -128,19 +129,19 @@ def init_app(self, global_conf, app_conf, package=None, paths=None):
* from_address - Whom the error email should be from
``app_conf``
Defaults supplied via the [app:main] section from the Paste
- config file. ``load_config`` only cares about whether a
+ config file. ``load_config`` only cares about whether a
'prefix' option is set, if so it will update Routes to
ensure URL's take that into account.
``package``
- The name of the application package, to be stored in the
+ The name of the application package, to be stored in the
app_conf.
-
+
.. versionchanged:: 1.0
``template_engine`` option is no longer supported.
-
+
"""
log.debug("Initializing configuration, package: '%s'", package)
-
+
conf = global_conf.copy()
conf.update(app_conf)
conf.update(dict(app_conf=app_conf, global_conf=global_conf))
@@ -148,14 +149,14 @@ def init_app(self, global_conf, app_conf, package=None, paths=None):
if paths:
conf['pylons.paths'] = paths
-
+
conf['pylons.package'] = package
-
+
conf['debug'] = asbool(conf.get('debug'))
-
+
# Load the MIMETypes with its default types
MIMETypes.init()
-
+
# Ensure all the keys from defaults are present, load them if not
for key, val in copy.deepcopy(PylonsConfig.defaults).iteritems():
conf.setdefault(key, val)
@@ -190,7 +191,7 @@ def init_app(self, global_conf, app_conf, package=None, paths=None):
conf['app_conf'].get('cache_dir'))
# Save our errorware values
conf['pylons.errorware'] = errorware
-
+
# Load conf dict into self
self.update(conf)
View
63 pylons/controllers/core.py
@@ -15,16 +15,16 @@
class WSGIController(object):
"""WSGI Controller that follows WSGI spec for calling and return
values
-
- The Pylons WSGI Controller handles incoming web requests that are
+
+ The Pylons WSGI Controller handles incoming web requests that are
dispatched from the PylonsBaseWSGIApp. These requests result in a
new instance of the WSGIController being created, which is then
called with the dict options from the Routes match. The standard
WSGI response is then returned with start_response called as per
the WSGI spec.
-
+
Special WSGIController methods you may define:
-
+
``__before__``
This method is called before your action is, and should be used
for setting up variables/objects, restricting access to other
@@ -37,17 +37,17 @@ class WSGIController(object):
:class:`~webob.exc.HTTPException` (such as those raised by
``redirect_to`` and ``abort``) are expected; e.g. ``__after__``
will be called on redirects.
-
+
Each action to be called is inspected with :meth:`_inspect_call` so
that it is only passed the arguments in the Routes match dict that
it asks for. The arguments passed into the action can be customized
by overriding the :meth:`_get_method_args` function which is
expected to return a dict.
-
+
In the event that an action is not found to handle the request, the
Controller will raise an "Action Not Found" error if in debug mode,
otherwise a ``404 Not Found`` error will be returned.
-
+
"""
_pylons_log_debug = False
@@ -55,24 +55,24 @@ def _perform_call(self, func, args):
"""Hide the traceback for everything above this method"""
__traceback_hide__ = 'before_and_this'
return func(**args)
-
+
def _inspect_call(self, func):
"""Calls a function with arguments from
:meth:`_get_method_args`
-
+
Given a function, inspect_call will inspect the function args
and call it with no further keyword args than it asked for.
-
+
If the function has been decorated, it is assumed that the
decorator preserved the function signature.
-
+
"""
# Check to see if the class has a cache of argspecs yet
try:
cached_argspecs = self.__class__._cached_argspecs
except AttributeError:
self.__class__._cached_argspecs = cached_argspecs = {}
-
+
# function could be callable
func_key = getattr(func, 'im_func', func.__call__)
try:
@@ -80,12 +80,12 @@ def _inspect_call(self, func):
except KeyError:
argspec = cached_argspecs[func_key] = inspect.getargspec(func_key)
kargs = self._get_method_args()
-
+
log_debug = self._pylons_log_debug
c = self._py_object.tmpl_context
environ = self._py_object.request.environ
args = None
-
+
if argspec[2]:
if self._py_object.config['pylons.tmpl_context_attach_args']:
for k, val in kargs.iteritems():
@@ -111,26 +111,26 @@ def _inspect_call(self, func):
func.__name__, httpe.__class__.__name__,
httpe.wsgi_response.code, exc_info=True)
result = httpe
-
+
# Store the exception in the environ
environ['pylons.controller.exception'] = httpe
-
+
# 304 Not Modified's shouldn't have a content-type set
if result.wsgi_response.status_int == 304:
result.wsgi_response.headers.pop('Content-Type', None)
result._exception = True
return result
-
+
def _get_method_args(self):
"""Retrieve the method arguments to use with inspect call
-
+
By default, this uses Routes to retrieve the arguments,
override this method to customize the arguments your controller
actions are called with.
-
+
This method should return a dict.
-
+
"""
req = self._py_object.request
kargs = req.environ['pylons.routes_dict'].copy()
@@ -138,7 +138,7 @@ def _get_method_args(self):
kargs['start_response'] = self.start_response
kargs['pylons'] = self._py_object
return kargs
-
+
def _dispatch_call(self):
"""Handles dispatching the request to the function using
Routes"""
@@ -160,7 +160,7 @@ def _dispatch_call(self):
if action_method != 'start_response' and callable(func):
# Store function used to handle request
req.environ['pylons.action_method'] = func
-
+
response = self._inspect_call(func)
else:
if log_debug:
@@ -171,11 +171,11 @@ def _dispatch_call(self):
else:
response = HTTPNotFound()
return response
-
+
def __call__(self, environ, start_response):
"""The main call handler that is called to return a response"""
log_debug = self._pylons_log_debug
-
+
# Keep a local reference to the req/response objects
self._py_object = environ['pylons.pylons']
@@ -191,10 +191,11 @@ def __call__(self, environ, start_response):
pass
start_response_called = []
+
def repl_start_response(status, headers, exc_info=None):
response = self._py_object.response
start_response_called.append(None)
-
+
# Copy the headers from the global response
if log_debug:
log.debug("Merging pylons.response headers into "
@@ -204,12 +205,12 @@ def repl_start_response(status, headers, exc_info=None):
header[0].startswith('X-'))
return start_response(status, headers, exc_info)
self.start_response = repl_start_response
-
+
if hasattr(self, '__before__'):
response = self._inspect_call(self.__before__)
if hasattr(response, '_exception'):
return response(environ, self.start_response)
-
+
response = self._dispatch_call()
if not start_response_called:
self.start_response = start_response
@@ -253,22 +254,22 @@ def repl_start_response(status, headers, exc_info=None):
"setting it as pylons.response.app_iter")
py_response.app_iter = response
response = py_response
-
+
if hasattr(self, '__after__'):
after = self._inspect_call(self.__after__)
if hasattr(after, '_exception'):
after.wsgi_response = True
response = after
-
+
if hasattr(response, 'wsgi_response'):
# Copy the response object into the testing vars if we're testing
if 'paste.testing_variables' in environ:
environ['paste.testing_variables']['response'] = response
if log_debug:
log.debug("Calling Response object to return WSGI data")
-
+
return response(environ, self.start_response)
-
+
if log_debug:
log.debug("Response assumed to be WSGI content, returning "
"un-touched")
View
21 pylons/controllers/jsonrpc.py
@@ -43,16 +43,17 @@ def as_dict(self):
JSONRPC_PARSE_ERROR = JSONRPCError(-32700, "Parse error")
-JSONRPC_INVALID_REQUEST = JSONRPCError( -32600, "Invalid Request")
-JSONRPC_METHOD_NOT_FOUND = JSONRPCError( -32601, "Method not found")
-JSONRPC_INVALID_PARAMS = JSONRPCError( -32602, "Invalid params")
-JSONRPC_INTERNAL_ERROR = JSONRPCError( -32603, "Internal error")
+JSONRPC_INVALID_REQUEST = JSONRPCError(-32600, "Invalid Request")
+JSONRPC_METHOD_NOT_FOUND = JSONRPCError(-32601, "Method not found")
+JSONRPC_INVALID_PARAMS = JSONRPCError(-32602, "Invalid params")
+JSONRPC_INTERNAL_ERROR = JSONRPCError(-32603, "Internal error")
_reserved_errors = dict(parse_error=JSONRPC_PARSE_ERROR,
invalid_request=JSONRPC_INVALID_REQUEST,
method_not_found=JSONRPC_METHOD_NOT_FOUND,
invalid_params=JSONRPC_INVALID_PARAMS,
internal_error=JSONRPC_INTERNAL_ERROR)
+
def jsonrpc_error(req_id, error):
"""Generate a Response object with a JSON-RPC error body. Used to
raise top-level pre-defined errors that happen outside the
@@ -63,6 +64,7 @@ def jsonrpc_error(req_id, error):
id=req_id,
error=err.as_dict())))
+
class JSONRPCController(WSGIController):
"""
A WSGI-speaking JSON-RPC 2.0 controller class
@@ -121,7 +123,7 @@ def __call__(self, environ, start_response):
self._error = None
try:
self._func = self._find_method()
- except AttributeError, e:
+ except AttributeError:
err = jsonrpc_error(self._req_id, 'method_not_found')
return err(environ, start_response)
@@ -149,6 +151,7 @@ def __call__(self, environ, start_response):
status = []
headers = []
exc_info = []
+
def change_content(new_status, new_headers, new_exc_info=None):
status.append(new_status)
headers.extend(new_headers)
@@ -201,16 +204,16 @@ def _find_method(self):
"""Return method named by `self._req_method` in controller if able"""
log.debug('Trying to find JSON-RPC method: %s', self._req_method)
if self._req_method.startswith('_'):
- raise AttributeError, "Method not allowed"
+ raise AttributeError("Method not allowed")
try:
func = getattr(self, self._req_method, None)
except UnicodeEncodeError:
# XMLRPCController catches this, not sure why.
- raise AttributeError, ("Problem decoding unicode in requested "
- "method name.")
+ raise AttributeError("Problem decoding unicode in requested "
+ "method name.")
if isinstance(func, types.MethodType):
return func
else:
- raise AttributeError, "No such method: %s" % self._req_method
+ raise AttributeError("No such method: %s" % self._req_method)
View
79 pylons/controllers/util.py
@@ -10,7 +10,7 @@
Functions available:
-:func:`abort`, :func:`forward`, :func:`etag_cache`,
+:func:`abort`, :func:`forward`, :func:`etag_cache`,
:func:`mimetype` and :func:`redirect`
"""
import base64
@@ -33,8 +33,7 @@
import pylons
-__all__ = ['abort', 'etag_cache', 'redirect', 'redirect_to', 'Request',
- 'Response']
+__all__ = ['abort', 'etag_cache', 'redirect', 'Request', 'Response']
log = logging.getLogger(__name__)
@@ -43,34 +42,34 @@
class Request(WebObRequest):
"""WebOb Request subclass
-
+
The WebOb :class:`webob.Request` has no charset, or other defaults. This subclass
- adds defaults, along with several methods for backwards
+ adds defaults, along with several methods for backwards
compatibility with paste.wsgiwrappers.WSGIRequest.
-
- """
+
+ """
def determine_browser_charset(self):
"""Legacy method to return the
:attr:`webob.Request.accept_charset`"""
return self.accept_charset
-
+
def languages(self):
return self.accept_language.best_matches(self.language)
languages = property(languages)
-
+
def match_accept(self, mimetypes):
return self.accept.first_match(mimetypes)
-
+
def signed_cookie(self, name, secret):
"""Extract a signed cookie of ``name`` from the request
-
+
The cookie is expected to have been created with
``Response.signed_cookie``, and the ``secret`` should be the
same as the one used to sign it.
-
+
Any failure in the signature of the data will result in None
being returned.
-
+
"""
cookie = self.str_cookies.get(name)
if not cookie:
@@ -80,17 +79,16 @@ def signed_cookie(self, name, secret):
except binascii.Error:
# Badly formed data can make base64 die
return None
-
sig = hmac.new(secret, pickled, sha1).hexdigest()
-
+
# Avoid timing attacks
invalid_bits = 0
if len(sig) != len(input_sig):
return None
-
+
for a, b in zip(sig, input_sig):
invalid_bits += a != b
-
+
if invalid_bits:
return None
else:
@@ -99,34 +97,34 @@ def signed_cookie(self, name, secret):
class Response(WebObResponse):
"""WebOb Response subclass
-
+
The WebOb Response has no default content type, or error defaults.
- This subclass adds defaults, along with several methods for
+ This subclass adds defaults, along with several methods for
backwards compatibility with paste.wsgiwrappers.WSGIResponse.
-
+
"""
content = WebObResponse.body
-
+
def determine_charset(self):
return self.charset
-
+
def has_header(self, header):
return header in self.headers
-
+
def get_content(self):
return self.body
-
+
def wsgi_response(self):
return self.status, self.headers, self.body
-
+
def signed_cookie(self, name, data, secret=None, **kwargs):
"""Save a signed cookie with ``secret`` signature
-
+
Saves a signed cookie of the pickled data. All other keyword
arguments that ``WebOb.set_cookie`` accepts are usable and
passed to the WebOb set_cookie method after creating the signed
cookie value.
-
+
"""
pickled = pickle.dumps(data, pickle.HIGHEST_PROTOCOL)
sig = hmac.new(secret, pickled, sha1).hexdigest()
@@ -135,29 +133,28 @@ def signed_cookie(self, name, data, secret=None, **kwargs):
def etag_cache(key=None):
"""Use the HTTP Entity Tag cache for Browser side caching
-
+
If a "If-None-Match" header is found, and equivilant to ``key``,
then a ``304`` HTTP message will be returned with the ETag to tell
the browser that it should use its current cache of the page.
-
+
Otherwise, the ETag header will be added to the response headers.
-
Suggested use is within a Controller Action like so:
-
+
.. code-block:: python
-
+
import pylons
-
+
class YourController(BaseController):
def index(self):
etag_cache(key=1)
return render('/splash.mako')
-
+
.. note::
This works because etag_cache will raise an HTTPNotModified
exception if the ETag received matches the key provided.
-
+
"""
if_none_matches = IF_NONE_MATCH.findall(
pylons.request.environ.get('HTTP_IF_NONE_MATCH', ''))
@@ -175,11 +172,11 @@ def index(self):
def forward(wsgi_app):
"""Forward the request to a WSGI application. Returns its response.
-
+
.. code-block:: python
-
+
return forward(FileApp('filename'))
-
+
"""
environ = pylons.request.environ
controller = environ.get('pylons.controller')
@@ -191,13 +188,13 @@ def forward(wsgi_app):
def abort(status_code=None, detail="", headers=None, comment=None):
"""Aborts the request immediately by returning an HTTP exception
-
+
In the event that the status_code is a 300 series error, the detail
attribute will be used as the Location header should one not be
specified in the headers attribute.
-
+
"""
- exc = status_map[status_code](detail=detail, headers=headers,
+ exc = status_map[status_code](detail=detail, headers=headers,
comment=comment)
log.debug("Aborting request, status: %s, detail: %r, headers: %r, "
"comment: %r", status_code, detail, headers, comment)
View
48 pylons/controllers/xmlrpc.py
@@ -14,12 +14,13 @@
log = logging.getLogger(__name__)
XMLRPC_MAPPING = ((basestring, 'string'), (list, 'array'), (bool, 'boolean'),
- (int, 'int'), (float, 'double'), (dict, 'struct'),
+ (int, 'int'), (float, 'double'), (dict, 'struct'),
(xmlrpclib.DateTime, 'dateTime.iso8601'),
(xmlrpclib.Binary, 'base64'))
+
def xmlrpc_sig(args):
- """Returns a list of the function signature in string format based on a
+ """Returns a list of the function signature in string format based on a
tuple provided by xmlrpclib."""
signature = []
for param in args:
@@ -38,28 +39,28 @@ def xmlrpc_fault(code, message):
class XMLRPCController(WSGIController):
"""XML-RPC Controller that speaks WSGI
-
- This controller handles XML-RPC responses and complies with the
+
+ This controller handles XML-RPC responses and complies with the
`XML-RPC Specification <http://www.xmlrpc.com/spec>`_ as well as
the `XML-RPC Introspection
- <http://scripts.incutio.com/xmlrpc/introspection.html>`_
+ <http://scripts.incutio.com/xmlrpc/introspection.html>`_
specification.
-
+
By default, methods with names containing a dot are translated to
use an underscore. For example, the `system.methodHelp` is handled
by the method :meth:`system_methodHelp`.
-
+
Methods in the XML-RPC controller will be called with the method
given in the XMLRPC body. Methods may be annotated with a signature
attribute to declare the valid arguments and return types.
-
+
For example::
-
+
class MyXML(XMLRPCController):
def userstatus(self):
return 'basic string'
userstatus.signature = [ ['string'] ]
-
+
def userinfo(self, username, age=None):
user = LookUpUser(username)
response = {'username':user.name}
@@ -68,16 +69,16 @@ def userinfo(self, username, age=None):
return response
userinfo.signature = [['struct', 'string'],
['struct', 'string', 'int']]
-
+
Since XML-RPC methods can take different sets of data, each set of
valid arguments is its own list. The first value in the list is the
type of the return argument. The rest of the arguments are the
types of the data that must be passed in.
-
+
In the last method in the example above, since the method can
optionally take an integer value both sets of valid parameter lists
should be provided.
-
+
Valid types that can be checked in the signature and their
corresponding Python types::
@@ -89,7 +90,7 @@ def userinfo(self, username, age=None):
'struct' - dict
'dateTime.iso8601' - xmlrpclib.DateTime
'base64' - xmlrpclib.Binary
-
+
The class variable ``allow_none`` is passed to xmlrpclib.dumps;
enabling it allows translating ``None`` to XML (an extension to the
XML-RPC specification)
@@ -97,7 +98,7 @@ def userinfo(self, username, age=None):
.. note::
Requiring a signature is optional.
-
+
"""
allow_none = False
max_body_length = 4194304
@@ -146,7 +147,7 @@ def __call__(self, environ, start_response):
params = xmlrpc_sig(rpc_args)
for sig in func.signature:
# Next sig if we don't have the same amount of args
- if len(sig)-1 != len(rpc_args):
+ if len(sig) - 1 != len(rpc_args):
continue
# If the params match, we're valid
@@ -171,12 +172,13 @@ def __call__(self, environ, start_response):
kargs['start_response'] = start_response
self.rpc_kargs = kargs
self._func = func
-
+
# Now that we know the method is valid, and the args are valid,
# we can dispatch control to the default WSGIController
status = []
headers = []
exc_info = []
+
def change_content(new_status, new_headers, new_exc_info=None):
status.append(new_status)
headers.extend(new_headers)
@@ -218,19 +220,19 @@ def _find_method(self, name):
def _find_method_name(self, name):
"""Locate a method in the controller by the appropriate name
-
- By default, this translates method names like
+
+ By default, this translates method names like
'system.methodHelp' into 'system_methodHelp'.
-
+
"""
return name.replace('.', '_')
def _publish_method_name(self, name):
"""Translate an internal method name to a publicly viewable one
-
+
By default, this translates internal method names like
'blog_view' into 'blog.view'.
-
+
"""
return name.replace('_', '.')
@@ -253,7 +255,7 @@ def system_methodSignature(self, name):
The first value of each array is the return value of the
method. The result is an array to indicate multiple signatures
a method may be capable of.
-
+
"""
method = self._find_method(self._find_method_name(name))
if method:
View
21 pylons/decorators/__init__.py
@@ -7,7 +7,6 @@
"""
import logging
-import sys
import warnings
import formencode
@@ -22,6 +21,7 @@
log = logging.getLogger(__name__)
+
class JSONEncoder(simplejson.JSONEncoder):
def default(self, obj):
encoder = getattr(obj, '__json__', None)
@@ -37,7 +37,7 @@ def jsonify(func, *args, **kwargs):
Given a function that will return content, this decorator will turn
the result into JSON, with a content-type of 'application/json' and
output it.
-
+
"""
pylons = get_pylons(args)
pylons.response.headers['Content-Type'] = 'application/json; charset=utf-8'
@@ -69,13 +69,13 @@ def validate(schema=None, validators=None, form=None, variable_decode=False,
``schema``
Refers to a FormEncode Schema object to use during validation.
``form``
- Method used to display the form, which will be used to get the
+ Method used to display the form, which will be used to get the
HTML representation of the form for error filling.
``variable_decode``
Boolean to indicate whether FormEncode's variable decode
function should be run on the form input before validation.
``dict_char``
- Passed through to FormEncode. Toggles the form field naming
+ Passed through to FormEncode. Toggles the form field naming
scheme used to determine what is used to represent a dict. This
option is only applicable when used with variable_decode=True.
``list_char``
@@ -85,7 +85,7 @@ def validate(schema=None, validators=None, form=None, variable_decode=False,
``post_only``
Boolean that indicates whether or not GET (query) variables
should be included during validation.
-
+
.. warning::
``post_only`` applies to *where* the arguments to be
validated come from. It does *not* restrict the form to
@@ -112,21 +112,22 @@ def update(self, id):
"""
if state is None:
state = PylonsFormEncodeState
+
def wrapper(func, self, *args, **kwargs):
"""Decorator Wrapper function"""
request = self._py_object.request
errors = {}
-
+
# Skip the validation if on_get is False and its a GET
if not on_get and request.environ['REQUEST_METHOD'] == 'GET':
return func(self, *args, **kwargs)
-
+
# If they want post args only, use just the post args
if post_only:
params = request.POST
else:
params = request.params
-
+
params = params.mixed()
if variable_decode:
log.debug("Running variable_decode on params")
@@ -181,7 +182,7 @@ def wrapper(func, self, *args, **kwargs):
def pylons_formencode_gettext(value):
"""Translates a string ``value`` using pylons gettext first and if
that fails, formencode gettext.
-
+
This allows to "merge" localized error messages from built-in
FormEncode's validators with application-specific validators.
@@ -209,6 +210,6 @@ class PylonsFormEncodeState(object):
them instead of gathering and translating everything from scratch.
To allow this, we pass as ``_`` a function which looks up
translation both in application and formencode message catalogs.
-
+
"""
_ = staticmethod(pylons_formencode_gettext)
View
29 pylons/decorators/cache.py
@@ -7,13 +7,14 @@
from paste.deploy.converters import asbool
from pylons.decorators.util import get_pylons
-
+
log = logging.getLogger(__name__)
+
def beaker_cache(key="cache_default", expire="never", type=None,
query_args=False,
cache_headers=('content-type', 'content-length'),
- invalidate_on_startup=False,
+ invalidate_on_startup=False,
cache_response=True, **b_kwargs):
"""Cache decorator utilizing Beaker. Caches action or other
function that returns a pickle-able object as a result.
@@ -26,7 +27,7 @@ def beaker_cache(key="cache_default", expire="never", type=None,
string - Use kwargs[key] as key
list - Use [kwargs[k] for k in list] as key
``expire``
- Time in seconds before cache expires, or the string "never".
+ Time in seconds before cache expires, or the string "never".
Defaults to "never"
``type``
Type of cache to use: dbm, memory, file, memcached, or None for
@@ -42,7 +43,7 @@ def beaker_cache(key="cache_default", expire="never", type=None,
``cache_response``
Determines whether the response at the time beaker_cache is used
should be cached or not, defaults to True.
-
+
.. note::
When cache_response is set to False, the cache_headers
argument is ignored as none of the response is cached.
@@ -72,7 +73,7 @@ def wrapper(func, *args, **kwargs):
key_dict.update(_make_dict_from_args(func, args))
if query_args:
key_dict.update(pylons.request.GET.mixed())
-
+
if key != "cache_default":
if isinstance(key, list):
key_dict = dict((k, key_dict[k]) for k in key)
@@ -88,21 +89,21 @@ def wrapper(func, *args, **kwargs):
if type:
b_kwargs['type'] = type
-
+
cache_obj = getattr(pylons.app_globals, 'cache', None)
if not cache_obj:
cache_obj = getattr(pylons, 'cache', None)
if not cache_obj:
raise Exception('No CacheMiddleware or cache object on '
' app_globals was found')
-
+
my_cache = cache_obj.get_cache(namespace, **b_kwargs)
-
+
if expire == "never":
cache_expire = None
else:
cache_expire = expire
-
+
def create_func():
log.debug("Creating new cache copy with key: %s, type: %s",
cache_key, type)
@@ -113,7 +114,7 @@ def create_func():
full_response = dict(headers=headers, status=status,
cookies=None, content=result)
return full_response
-
+
response = my_cache.get_value(cache_key, createfunc=create_func,
expiretime=cache_expire,
starttime=starttime)
@@ -126,15 +127,16 @@ def create_func():
return response['content']
return decorator(wrapper)
+
def create_cache_key(func, key_dict=None, self=None):
"""Get a cache namespace and key used by the beaker_cache decorator.
-
+
Example::
from pylons import cache
from pylons.decorators.cache import create_cache_key
namespace, key = create_cache_key(MyController.some_method)
cache.get_cache(namespace).remove(key)
-
+
"""
kls = None
if hasattr(func, 'im_func'):
@@ -149,12 +151,13 @@ def create_cache_key(func, key_dict=None, self=None):
if not kls and self:
kls = getattr(self, '__class__', None)
-
+
if kls:
return '%s.%s' % (kls.__module__, kls.__name__), cache_key
else:
return func.__module__, cache_key
+
def _make_dict_from_args(func, args):
"""Inspects function for name of args"""
args_keys = {}
View
6 pylons/decorators/rest.py
@@ -10,6 +10,7 @@
log = logging.getLogger(__name__)
+
def restrict(*methods):
"""Restricts access to the function depending on HTTP method
@@ -23,7 +24,7 @@ class SomeController(BaseController):
@rest.restrict('GET')
def comment(self, id):
-
+
"""
def check_methods(func, *args, **kwargs):
"""Wrapper for restrict"""
@@ -33,6 +34,7 @@ def check_methods(func, *args, **kwargs):
return func(*args, **kwargs)
return decorator(check_methods)
+
def dispatch_on(**method_map):
"""Dispatches to alternate controller methods based on HTTP method
@@ -55,7 +57,7 @@ def comment(self):
def create_comment(self, id):
# Do something if its a post to comment
-
+
"""
def dispatcher(func, self, *args, **kwargs):
"""Wrapper for dispatch_on"""
View
1 pylons/decorators/secure.py
@@ -20,6 +20,7 @@
"http://en.wikipedia.org/wiki/Cross-site_request_forgery for more "
"information.")
+
def authenticated_form(params):
submitted_token = params.get(secure_form.token_key)
return submitted_token is not None and \
View
1 pylons/decorators/util.py
@@ -2,6 +2,7 @@
import pylons
from pylons.controllers import WSGIController
+
def get_pylons(decorator_args):
"""Return the `pylons` object: either the :mod`~pylons` module or
the :attr:`~WSGIController._py_object` equivalent, searching a
View
3 pylons/error.py
@@ -13,12 +13,13 @@
__all__ = ['handle_mako_error']
+
def handle_mako_error(context, exc):
try:
exc.is_mako_exception = True
except:
pass
- raise exc, None, sys.exc_info()[2]
+ raise (exc, None, sys.exc_info()[2])
def myghty_html_data(exc_value):
View
7 pylons/i18n/translation.py
@@ -15,17 +15,18 @@
'ngettext', 'set_lang', 'ugettext', 'ungettext', 'LanguageError',
'N_']
+
class LanguageError(Exception):
"""Exception raised when a problem occurs with changing languages"""
pass
class LazyString(object):
- """Has a number of lazily evaluated functions replicating a
+ """Has a number of lazily evaluated functions replicating a
string. Just override the eval() method to produce the actual value.
This method copied from TurboGears.
-
+
"""
def __init__(self, func, *args, **kwargs):
self.func = func
@@ -101,7 +102,7 @@ def ugettext(value):
Mark a string to be localized as follows::
_('This should be in lots of languages')
-
+
"""
return pylons.translator.ugettext(value)
_ = ugettext
View
3 pylons/log.py
@@ -11,6 +11,7 @@
__all__ = ['WSGIErrorsHandler']
+
class WSGIErrorsHandler(logging.Handler):
"""A handler class that writes logging records to
@@ -71,7 +72,7 @@ def emit(self, record):
try:
msg = self.format(record)
fs = "%s\n"
- if not hasattr(types, "UnicodeType"): #if no unicode support...
+ if not hasattr(types, "UnicodeType"): # if no unicode support
stream.write(fs % msg)
else:
try:
View
54 pylons/middleware.py
@@ -13,7 +13,7 @@
from pylons.error import template_error_formatters
from pylons.util import call_wsgi_application
-__all__ = ['ErrorHandler', 'StaticJavascripts', 'error_document_template',
+__all__ = ['ErrorHandler', 'error_document_template',
'footer_html', 'head_html', 'media_path']
log = logging.getLogger(__name__)
@@ -84,14 +84,15 @@
report_libs = ['pylons', 'genshi', 'sqlalchemy']
+
def DebugHandler(app, global_conf, **kwargs):
- footer = footer_html % (kwargs.get('traceback_host',
+ footer = footer_html % (kwargs.get('traceback_host',
'pylonshq.com'),
pylons.__version__)
py_media = dict(pylons=media_path)
- app = EvalException(app, global_conf,
+ app = EvalException(app, global_conf,
templating_formatters=template_error_formatters,
- media_paths=py_media, head_html=head_html,
+ media_paths=py_media, head_html=head_html,
footer_html=footer,
libraries=report_libs)
return app
@@ -99,25 +100,25 @@ def DebugHandler(app, global_conf, **kwargs):
def ErrorHandler(app, global_conf, **errorware):
"""ErrorHandler Toggle
-
+
If debug is enabled, this function will return the app wrapped in
the WebError ``EvalException`` middleware which displays
interactive debugging sessions when a traceback occurs.
-
+
Otherwise, the app will be wrapped in the WebError
``ErrorMiddleware``, and the ``errorware`` dict will be passed into
it. The ``ErrorMiddleware`` handles sending an email to the address
listed in the .ini file, under ``email_to``.
-
+
"""
if asbool(global_conf.get('debug')):
- footer = footer_html % (pylons.config.get('traceback_host',
+ footer = footer_html % (pylons.config.get('traceback_host',
'pylonshq.com'),
pylons.__version__)
py_media = dict(pylons=media_path)
- app = EvalException(app, global_conf,
+ app = EvalException(app, global_conf,
templating_formatters=template_error_formatters,
- media_paths=py_media, head_html=head_html,
+ media_paths=py_media, head_html=head_html,
footer_html=footer,
libraries=report_libs)
else:
@@ -127,37 +128,37 @@ def ErrorHandler(app, global_conf, **errorware):
class StatusCodeRedirect(object):
"""Internally redirects a request based on status code
-
- StatusCodeRedirect watches the response of the app it wraps. If the
+
+ StatusCodeRedirect watches the response of the app it wraps. If the
response is an error code in the errors sequence passed the request
will be re-run with the path URL set to the path passed in.
-
- This operation is non-recursive and the output of the second
+
+ This operation is non-recursive and the output of the second
request will be used no matter what it is.
-
- Should an application wish to bypass the error response (ie, to
- purposely return a 401), set
+
+ Should an application wish to bypass the error response (ie, to
+ purposely return a 401), set
``environ['pylons.status_code_redirect'] = True`` in the application.
-
+
"""
def __init__(self, app, errors=(400, 401, 403, 404),
path='/error/document'):
"""Initialize the ErrorRedirect
-
+
``errors``
A sequence (list, tuple) of error code integers that should
be caught.
``path``
- The path to set for the next request down to the
- application.
-
+ The path to set for the next request down to the
+ application.
+
"""
self.app = app
self.error_path = path
-
+
# Transform errors to str for comparison
self.errors = tuple([str(x) for x in errors])
-
+
def __call__(self, environ, start_response):
status, headers, app_iter, exc_info = call_wsgi_application(
self.app, environ, catch_exc_info=True)
@@ -167,11 +168,11 @@ def __call__(self, environ, start_response):
environ['pylons.original_response'] = Response(
status=status, headerlist=headers, app_iter=app_iter)
environ['pylons.original_request'] = Request(environ)
-
+
# Create a new environ to avoid touching the original request data
new_environ = environ.copy()
new_environ['PATH_INFO'] = self.error_path
-
+
newstatus, headers, app_iter, exc_info = call_wsgi_application(
self.app, new_environ, catch_exc_info=True)
start_response(status, headers, exc_info)
@@ -207,6 +208,7 @@ def __call__(self, environ, start_response):
</html>
""")
+
def debugger_filter_factory(global_conf, **kwargs):
def filter(app):
return DebugHandler(app, global_conf, **kwargs)
View
89 pylons/templating.py
@@ -24,11 +24,11 @@
unicode).
.. admonition :: Tip
-
+
:data:`tmpl_context` (template context) is abbreviated to :data:`c`
instead of its full name since it will likely be used extensively
and it's much faster to use :data:`c`. Of course, for users that
- can't tolerate one-letter variables, feel free to not import
+ can't tolerate one-letter variables, feel free to not import
:data:`tmpl_context` as :data:`c` since both names are available in
templates as well.
@@ -49,7 +49,7 @@ def index(self):
And the accompanying Mako template:
.. code-block:: mako
-
+
Hello ${c.first name}, I see your lastname is ${c.last_name}!
Your controller will have additional default imports for commonly used
@@ -88,7 +88,7 @@ def index(self):
Configuring the template language
---------------------------------
-The template engine is created in the projects
+The template engine is created in the projects
``config/environment.py`` and attached to the ``app_globals`` (g)
instance. Configuration options can be directly passed into the
template engine, and are used by the render functions.
@@ -107,27 +107,28 @@ def index(self):
import pylons
-__all__ = ['render_genshi', 'render_jinja2', 'render_mako', 'render_response']
+__all__ = ['render_genshi', 'render_jinja2', 'render_mako']
PYLONS_VARS = ['c', 'app_globals', 'config', 'h', 'render', 'request',
'session', 'translator', 'ungettext', '_', 'N_']
log = logging.getLogger(__name__)
+
def pylons_globals():
"""Create and return a dictionary of global Pylons variables
-
+
Render functions should call this to retrieve a list of global
Pylons variables that should be included in the global template
namespace if possible.
-
+
Pylons variables that are returned in the dictionary:
- ``c``, ``h``, ``_``, ``N_``, config, request, response,
+ ``c``, ``h``, ``_``, ``N_``, config, request, response,
translator, ungettext, ``url``
-
+
If SessionMiddleware is being used, ``session`` will also be
available in the template namespace.
-
+
"""
conf = pylons.config._current_obj()
c = pylons.tmpl_context._current_obj()
@@ -146,7 +147,7 @@ def pylons_globals():
_=pylons.i18n._,
N_=pylons.i18n.N_
)
-
+
# If the session was overriden to be None, don't populate the session
# var
econf = pylons.config['pylons.environ_config']
@@ -161,12 +162,12 @@ def cached_template(template_name, render_func, ns_options=(),
cache_key=None, cache_type=None, cache_expire=None,
**kwargs):
"""Cache and render a template
-
+
Cache a template to the namespace ``template_name``, along with a
specific key if provided.
-
+
Basic Options
-
+
``template_name``
Name of the template, which is used as the template namespace.
``render_func``
@@ -179,9 +180,9 @@ def cached_template(template_name, render_func, ns_options=(),
language supports the 'fragment' option, the namespace should
include it so that the cached copy for a template is not the
same as the fragment version of it.
-
+
Caching options (uses Beaker caching middleware)
-
+
``cache_key``
Key to cache this copy of the template under.
``cache_type``
@@ -191,11 +192,11 @@ def cached_template(template_name, render_func, ns_options=(),
Time in seconds to cache this template with this ``cache_key``
for. Or use 'never' to designate that the cache should never
expire.
-
+
The minimum key required to trigger caching is
``cache_expire='never'`` which will cache the template forever
seconds with no key.
-
+
"""
# If one of them is not None then the user did set something
if cache_key is not None or cache_expire is not None or cache_type \
@@ -204,41 +205,41 @@ def cached_template(template_name, render_func, ns_options=(),
if not cache_type:
cache_type = 'dbm'
if not cache_key:
- cache_key = 'default'
+ cache_key = 'default'
if cache_expire == 'never':
cache_expire = None
namespace = template_name
for name in ns_options:
namespace += str(kwargs.get(name))
cache = pylons.cache.get_cache(namespace, type=cache_type)
- content = cache.get_value(cache_key, createfunc=render_func,
+ content = cache.get_value(cache_key, createfunc=render_func,
expiretime=cache_expire)
return content
else:
return render_func()
-def render_mako(template_name, extra_vars=None, cache_key=None,
+def render_mako(template_name, extra_vars=None, cache_key=None,
cache_type=None, cache_expire=None):
"""Render a template with Mako
-
+
Accepts the cache options ``cache_key``, ``cache_type``, and
``cache_expire``.
-
- """
+
+ """
# Create a render callable for the cache function
def render_template():
# Pull in extra vars if needed
globs = extra_vars or {}
-
+
# Second, get the globals
globs.update(pylons_globals())
# Grab a template reference
template = globs['app_globals'].mako_lookup.get_template(template_name)
-
+
return literal(template.render_unicode(**globs))
-
+
return cached_template(template_name, render_template, cache_key=cache_key,
cache_type=cache_type, cache_expire=cache_expire)
@@ -246,80 +247,80 @@ def render_template():
def render_mako_def(template_name, def_name, cache_key=None,
cache_type=None, cache_expire=None, **kwargs):
"""Render a def block within a Mako template
-
+
Takes the template name, and the name of the def within it to call.
If the def takes arguments, they should be passed in as keyword
arguments.
-
+
Example::
-
+
# To call the def 'header' within the 'layout.mako' template
# with a title argument
render_mako_def('layout.mako', 'header', title='Testing')
-
+
Also accepts the cache options ``cache_key``, ``cache_type``, and
``cache_expire``.
-
+
"""
# Create a render callable for the cache function
def render_template():
# Pull in extra vars if needed
globs = kwargs or {}
-
+
# Second, get the globals
globs.update(pylons_globals())
# Grab a template reference
template = globs['app_globals'].mako_lookup.get_template(
template_name).get_def(def_name)
-
+
return literal(template.render_unicode(**globs))
-
+
return cached_template(template_name, render_template, cache_key=cache_key,
cache_type=cache_type, cache_expire=cache_expire)
-def render_genshi(template_name, extra_vars=None, cache_key=None,
+def render_genshi(template_name, extra_vars=None, cache_key=None,
cache_type=None, cache_expire=None, method='xhtml'):
"""Render a template with Genshi
-
+
Accepts the cache options ``cache_key``, ``cache_type``, and
``cache_expire`` in addition to method which are passed to Genshi's
render function.
-
+
"""
# Create a render callable for the cache function
def render_template():
# Pull in extra vars if needed
globs = extra_vars or {}
-
+
# Second, get the globals
globs.update(pylons_globals())
# Grab a template reference
template = globs['app_globals'].genshi_loader.load(template_name)
-
+
return literal(template.generate(**globs).render(method=method,
encoding=None))
-
+
return cached_template(template_name, render_template, cache_key=cache_key,
cache_type=cache_type, cache_expire=cache_expire,
ns_options=('method'), method=method)
-def render_jinja2(template_name, extra_vars=None, cache_key=None,
+def render_jinja2(template_name, extra_vars=None, cache_key=None,
cache_type=None, cache_expire=None):
"""Render a template with Jinja2
Accepts the cache options ``cache_key``, ``cache_type``, and
``cache_expire``.
- """
+ """
# Create a render callable for the cache function
def render_template():
# Pull in extra vars if needed
globs = extra_vars or {}
-
+
# Second, get the globals
globs.update(pylons_globals())
View
8 pylons/test.py
@@ -28,6 +28,7 @@
pylonsapp = None
+
class PylonsPlugin(nose.plugins.Plugin):
"""Nose plugin extension
@@ -72,17 +73,16 @@ def begin(self):
pkg_resources.working_set.add_entry(path)
self.app = pylonsapp = loadapp('config:' + self.config_file,
relative_to=path)
-
+
# Setup the config and app_globals, only works if we can get
# to the config object
conf = getattr(pylonsapp, 'config')
if conf:
pylons.config._push_object(conf)
-
+
if 'pylons.app_globals' in conf:
pylons.app_globals._push_object(conf['pylons.app_globals'])
-
+
# Initialize a translator for tests that utilize i18n
translator = _get_translator(pylons.config.get('lang'))
pylons.translator._push_object(translator)
-
View
9 pylons/testutil.py
@@ -12,6 +12,7 @@
from pylons.controllers.util import Request, Response
from pylons.util import ContextObj, PylonsContext
+
class ControllerWrap(object):
def __init__(self, controller):
self.controller = controller
@@ -21,6 +22,7 @@ def __call__(self, environ, start_response):
app.start_response = None
return app(environ, start_response)
+
class SetupCacheGlobal(object):
def __init__(self, app, environ, setup_g=True, setup_cache=False,
setup_session=False):
@@ -59,14 +61,15 @@ def __call__(self, environ, start_response):
# Update the environ
req = Request(environ, charset=request_defaults['charset'],
unicode_errors=request_defaults['errors'],
- decode_param_names=request_defaults['decode_param_names'])
+ decode_param_names=request_defaults['decode_param_names']
+ )
req.language = request_defaults['language']
-
+
response = Response(
content_type=response_defaults['content_type'],
charset=response_defaults['charset'])
response.headers.update(response_defaults['headers'])
-
+
environ.update(self.environ)
py_obj.config = pylons.config._current_obj()
py_obj.request = req
View
8 pylons/url.py
@@ -4,16 +4,18 @@
from pylons.interfaces import IRoutesMapper
+
def route_url(route_name, request, *elements, **kw):
try:
reg = request.registry
except AttributeError:
- reg = get_current_registry() # b/c
+ reg = get_current_registry() # b/c
mapper = reg.getUtility(IRoutesMapper)
route = mapper.routes.get(route_name)
if route and 'custom_url_generator' in route.__dict__:
- route_name, request, elements, kw = route.custom_url_generator(route_name, request, *elements, **kw)
+ route_name, request, elements, kw = route.custom_url_generator(
+ route_name, request, *elements, **kw)
anchor = ''
qs = ''
app_url = None
@@ -30,7 +32,7 @@ def route_url(route_name, request, *elements, **kw):
if '_app_url' in kw:
app_url = kw.pop('_app_url')
- path = mapper.generate(route_name, kw) # raises KeyError if generate fails
+ path = mapper.generate(route_name, kw) # raises KeyError if generate fails
if elements:
suffix = _join_elements(elements)
View
26 pylons/util.py
@@ -24,6 +24,7 @@
log = logging.getLogger(__name__)
+
def call_wsgi_application(application, environ, catch_exc_info=False):
"""
Call the given WSGI application, returning ``(status_string,
@@ -36,10 +37,11 @@ def call_wsgi_application(application, environ, catch_exc_info=False):
be None, but won't be if there was an exception. If you don't
do this and there was an exception, the exception will be
raised directly.
-
+
"""
captured = []
output = []
+
def start_response(status, headers, exc_info=None):
if exc_info is not None and not catch_exc_info:
raise exc_info[0], exc_info[1], exc_info[2]
@@ -82,11 +84,11 @@ def class_name_from_module_name(module_name):
class PylonsContext(object):
"""Pylons context object
-
+
All the Pylons Stacked Object Proxies are also stored here, for use
in generators and async based operation where the globals can't be
used.
-
+
This object is attached in
:class:`~pylons.controllers.core.WSGIController` instances as
:attr:`~WSGIController._py_object`. For example::
@@ -95,7 +97,7 @@ class MyController(WSGIController):
def index(self):
pyobj = self._py_object
return "Environ is %s" % pyobj.request.environ
-
+
"""
pass
@@ -138,13 +140,13 @@ class PylonsTemplate(Template):
summary = 'Pylons application template'
egg_plugins = ['PasteScript', 'Pylons']
vars = [
- var('template_engine', 'mako/genshi/jinja2/etc: Template language',
+ var('template_engine', 'mako/genshi/jinja2/etc: Template language',
default='mako'),
var('sqlalchemy', 'True/False: Include SQLAlchemy configuration',
default=False),
]
ensure_names = ['description', 'author', 'author_email', 'url']
-
+
def pre(self, command, output_dir, vars):
"""Called before template is applied."""
package_logger = vars['package']
@@ -177,33 +179,38 @@ class MinimalPylonsTemplate(PylonsTemplate):
_template_dir = ('pylons', 'templates/minimal_project')
summary = 'Pylons minimal application template'
vars = [
- var('template_engine', 'mako/genshi/jinja2/etc: Template language',
+ var('template_engine', 'mako/genshi/jinja2/etc: Template language',
default='mako'),
]
+
class LegacyPylonsTemplate(PylonsTemplate):
_template_dir = ('pylons', 'templates/legacy_project')
summary = 'Pylons legacy application template'
vars = [
- var('template_engine', 'mako/genshi/jinja2/etc: Template language',
+ var('template_engine', 'mako/genshi/jinja2/etc: Template language',
default='mako'),
]
+
class NewPylonsTemplate(PylonsTemplate):
_template_dir = ('pylons', 'templates/new_project')
summary = 'Pylons "newstyle" application template'
vars = []
-
+
+
class NewMinimalPylonsTemplate(PylonsTemplate):
_template_dir = ('pylons', 'templates/newminimal_project')
summary = 'Pylons "newstyle" minimal application template'
vars = []
+
class NewSQLAlchemyTemplate(PylonsTemplate):
_template_dir = ('pylons', 'templates/newsqla_project')
summary = 'Pylons "newstyle" SQLAlchemy template'
vars = []
+
class PylonsInstaller(Installer):
use_cheetah = False
config_file = 'config/deployment.ini_tmpl'
@@ -228,5 +235,6 @@ def config_content(self, command, vars):
# Legacy support for the old location in egg-info
return super(PylonsInstaller, self).config_content(command, vars)
+
def resolve_dotted(name):
return pkg_resources.EntryPoint.parse('x=%s' % name).load(False)
View
116 pylons/wsgiapp.py
@@ -24,6 +24,7 @@
log = logging.getLogger(__name__)
+
class PylonsApp(object):
"""Pylons WSGI Application
@@ -32,24 +33,24 @@ class PylonsApp(object):
available. By itself, this Pylons web application does little more
than dispatch to a controller and setup the context object, the