/usr/lib/python2.7/dist-packages/pecan/routing.py is in python-pecan 0.6.1-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 | import warnings
from inspect import getargspec
from webob import exc
from .secure import handle_security, cross_boundary
from .util import iscontroller
__all__ = ['lookup_controller', 'find_object']
class PecanNotFound(Exception):
pass
class NonCanonicalPath(Exception):
'''
Exception Raised when a non-canonical path is encountered when 'walking'
the URI. This is typically a ``POST`` request which requires a trailing
slash.
'''
def __init__(self, controller, remainder):
self.controller = controller
self.remainder = remainder
def lookup_controller(obj, remainder, request=None):
'''
Traverses the requested url path and returns the appropriate controller
object, including default routes.
Handles common errors gracefully.
'''
if request is None:
warnings.warn(
(
"The function signature for %s.lookup_controller is changing "
"in the next version of pecan.\nPlease update to: "
"`lookup_controller(self, obj, remainder, request)`." % (
__name__,
)
),
DeprecationWarning
)
notfound_handlers = []
while True:
try:
obj, remainder = find_object(obj, remainder, notfound_handlers,
request)
handle_security(obj)
return obj, remainder
except (exc.HTTPNotFound, PecanNotFound):
while notfound_handlers:
name, obj, remainder = notfound_handlers.pop()
if name == '_default':
# Notfound handler is, in fact, a controller, so stop
# traversal
return obj, remainder
else:
# Notfound handler is an internal redirect, so continue
# traversal
result = handle_lookup_traversal(obj, remainder)
if result:
# If no arguments are passed to the _lookup, yet the
# argspec requires at least one, raise a 404
if (
remainder == ['']
and len(obj._pecan['argspec'].args) > 1
):
raise exc.HTTPNotFound
obj_, remainder_ = result
return lookup_controller(obj_, remainder_, request)
else:
raise exc.HTTPNotFound
def handle_lookup_traversal(obj, args):
try:
result = obj(*args)
if result:
prev_obj = obj
obj, remainder = result
# crossing controller boundary
cross_boundary(prev_obj, obj)
return result
except TypeError as te:
msg = 'Got exception calling lookup(): %s (%s)'
warnings.warn(
msg % (te, te.args),
RuntimeWarning
)
def find_object(obj, remainder, notfound_handlers, request):
'''
'Walks' the url path in search of an action for which a controller is
implemented and returns that controller object along with what's left
of the remainder.
'''
prev_obj = None
while True:
if obj is None:
raise PecanNotFound
if iscontroller(obj):
return obj, remainder
# are we traversing to another controller
cross_boundary(prev_obj, obj)
try:
next_obj, rest = remainder[0], remainder[1:]
if next_obj == '':
index = getattr(obj, 'index', None)
if iscontroller(index):
return index, rest
except IndexError:
# the URL has hit an index method without a trailing slash
index = getattr(obj, 'index', None)
if iscontroller(index):
raise NonCanonicalPath(index, [])
default = getattr(obj, '_default', None)
if iscontroller(default):
notfound_handlers.append(('_default', default, remainder))
lookup = getattr(obj, '_lookup', None)
if iscontroller(lookup):
notfound_handlers.append(('_lookup', lookup, remainder))
route = getattr(obj, '_route', None)
if iscontroller(route):
if len(getargspec(route).args) == 2:
warnings.warn(
(
"The function signature for %s.%s._route is changing "
"in the next version of pecan.\nPlease update to: "
"`def _route(self, args, request)`." % (
obj.__class__.__module__,
obj.__class__.__name__
)
),
DeprecationWarning
)
next_obj, next_remainder = route(remainder)
else:
next_obj, next_remainder = route(remainder, request)
cross_boundary(route, next_obj)
return next_obj, next_remainder
if not remainder:
raise PecanNotFound
prev_obj = obj
remainder = rest
obj = getattr(obj, next_obj, None)
|