/usr/share/pyshared/piston/doc.py is in python-django-piston 0.2.3-1ubuntu1.
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 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 194 195 | import inspect, handler
from piston.handler import typemapper
from piston.handler import handler_tracker
from django.core.urlresolvers import get_resolver, get_callable, get_script_prefix
from django.shortcuts import render_to_response
from django.template import RequestContext
def generate_doc(handler_cls):
"""
Returns a `HandlerDocumentation` object
for the given handler. Use this to generate
documentation for your API.
"""
if isinstance(type(handler_cls), handler.HandlerMetaClass):
raise ValueError("Give me handler, not %s" % type(handler_cls))
return HandlerDocumentation(handler_cls)
class HandlerMethod(object):
def __init__(self, method, stale=False):
self.method = method
self.stale = stale
def iter_args(self):
args, _, _, defaults = inspect.getargspec(self.method)
for idx, arg in enumerate(args):
if arg in ('self', 'request', 'form'):
continue
didx = len(args)-idx
if defaults and len(defaults) >= didx:
yield (arg, str(defaults[-didx]))
else:
yield (arg, None)
@property
def signature(self, parse_optional=True):
spec = ""
for argn, argdef in self.iter_args():
spec += argn
if argdef:
spec += '=%s' % argdef
spec += ', '
spec = spec.rstrip(", ")
if parse_optional:
return spec.replace("=None", "=<optional>")
return spec
@property
def doc(self):
return inspect.getdoc(self.method)
@property
def name(self):
return self.method.__name__
@property
def http_name(self):
if self.name == 'read':
return 'GET'
elif self.name == 'create':
return 'POST'
elif self.name == 'delete':
return 'DELETE'
elif self.name == 'update':
return 'PUT'
def __repr__(self):
return "<Method: %s>" % self.name
class HandlerDocumentation(object):
def __init__(self, handler):
self.handler = handler
def get_methods(self, include_default=False):
for method in "read create update delete".split():
met = getattr(self.handler, method, None)
if not met:
continue
stale = inspect.getmodule(met.im_func) is not inspect.getmodule(self.handler)
if not self.handler.is_anonymous:
if met and (not stale or include_default):
yield HandlerMethod(met, stale)
else:
if not stale or met.__name__ == "read" \
and 'GET' in self.allowed_methods:
yield HandlerMethod(met, stale)
def get_all_methods(self):
return self.get_methods(include_default=True)
@property
def is_anonymous(self):
return self.handler.is_anonymous
def get_model(self):
return getattr(self, 'model', None)
@property
def has_anonymous(self):
return self.handler.anonymous
@property
def anonymous(self):
if self.has_anonymous:
return HandlerDocumentation(self.handler.anonymous)
@property
def doc(self):
return self.handler.__doc__
@property
def name(self):
return self.handler.__name__
@property
def allowed_methods(self):
return self.handler.allowed_methods
def get_resource_uri_template(self):
"""
URI template processor.
See http://bitworking.org/projects/URI-Templates/
"""
def _convert(template, params=[]):
"""URI template converter"""
paths = template % dict([p, "{%s}" % p] for p in params)
return u'%s%s' % (get_script_prefix(), paths)
try:
resource_uri = self.handler.resource_uri()
components = [None, [], {}]
for i, value in enumerate(resource_uri):
components[i] = value
lookup_view, args, kwargs = components
lookup_view = get_callable(lookup_view, True)
possibilities = get_resolver(None).reverse_dict.getlist(lookup_view)
for possibility, pattern in possibilities:
for result, params in possibility:
if args:
if len(args) != len(params):
continue
return _convert(result, params)
else:
if set(kwargs.keys()) != set(params):
continue
return _convert(result, params)
except:
return None
resource_uri_template = property(get_resource_uri_template)
def __repr__(self):
return u'<Documentation for "%s">' % self.name
def documentation_view(request):
"""
Generic documentation view. Generates documentation
from the handlers you've defined.
"""
docs = [ ]
for handler in handler_tracker:
docs.append(generate_doc(handler))
def _compare(doc1, doc2):
#handlers and their anonymous counterparts are put next to each other.
name1 = doc1.name.replace("Anonymous", "")
name2 = doc2.name.replace("Anonymous", "")
return cmp(name1, name2)
docs.sort(_compare)
return render_to_response('documentation.html',
{ 'docs': docs }, RequestContext(request))
|