Skip to content

Instantly share code, notes, and snippets.

@ptone
Created June 8, 2012 16:15
Show Gist options
  • Save ptone/2896536 to your computer and use it in GitHub Desktop.
Save ptone/2896536 to your computer and use it in GitHub Desktop.
generates an MRO oriented index of Django CBVs
#!/usr/bin/env python
import sys
import os
import re
sys.path[0] = os.path.normpath(os.path.join(sys.path[0], '.'))
os.environ['DJANGO_SETTINGS_MODULE'] = "dummyproj.settings"
import inspect
from pprint import pprint
# https://github.com/django/django/commit/4f306a4c27c8537ca9cd966cea1c0de84aafda9e#django/db/__init__.py
# from django.conf import settings; settings.configure()
# from django.conf import settings; settings.configure(
# DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': '/tmp/dev'
# }
# }
# )
from django.core.management import setup_environ
# from dummyproj import settings
from django.views.generic.base import View
# setup_environ(settings)
# print dir(settings)
# print settings.DATABASES
# print settings.INSTALLED_APPS
from django.views import generic
class GenericViewInfo(object):
# _ignore_types = (None, object, View)
_ignore_types = (None, object)
def __init__(self, *args, **kwargs):
self.view_methods = []
self.view_properties = []
self.method_names = []
self.property_names = []
self.seen_nodes = set()
self.method_objects = {}
def add_view_class(self, cls, is_public=False):
if cls in self._ignore_types or cls in self.seen_nodes:
return
self.seen_nodes.add(cls)
for base in cls.__bases__:
if base in self._ignore_types:
continue
self.add_view_class(base)
self.format_class_info(cls, is_public)
def format_class_info(self, cls, is_public):
properties = []
methods = []
el = escape_label
cls_str = str(cls)
dotted_path = re.search('<[\w\s]*\'([^\']*)', cls_str).groups()[0]
for (name, attr) in inspect.getmembers(cls):
# Skip private methods and attributes of parent classes
if name.startswith('_') or name not in cls.__dict__:
continue
if inspect.ismethod(attr):
argspec = inspect.formatargspec(*inspect.getargspec(attr))
if name not in self.method_names:
methods.append((name, '%s.%s' % (dotted_path, name)))
self.method_names.append(name)
self.method_objects[name] = attr
else:
if name not in self.property_names:
properties.append((name, '%s.%s' % (dotted_path, name)))
self.property_names.append(name)
self.view_methods.extend(methods)
self.view_properties.extend(properties)
def format_property_value(self, attr):
r = repr(attr)
if r.startswith('<class'):
r = attr.__name__
return r
def escape_label(txt):
return re.sub(r'([{}<>|])', r'\\\1', txt)
presentation = [
('Simple generic views',['View', 'TemplateView','RedirectView']),
('Detail Views',['DetailView',]),
('List Views',['ListView']),
('Editing views',['FormView', 'CreateView', 'UpdateView', 'DeleteView']),
('Date-based views',[
'ArchiveIndexView',
'YearArchiveView',
'MonthArchiveView',
'WeekArchiveView',
'DayArchiveView',
'TodayArchiveView',
'DateDetailView'])
]
def main():
views = [getattr(generic, v) for v in dir(generic) if v.endswith('View')]
# views = [getattr(generic, v) for v in dir(generic) if v.endswith('View') and v != 'View']
view_dict = dict([(v.__name__, v) for v in views])
# print view_dict.keys()
for section, views in presentation:
print section
print '-' * len(section)
for vname in views:
print
v = view_dict[vname]
# print v
print v.__name__
print '~' * len(v.__name__)
print '.. class:: %s()' % v.__name__
print
g = GenericViewInfo()
g.add_view_class(v, is_public=True)
# pprint g.view_methods
# sys.exit()
g.view_methods.sort()
g.view_properties.sort()
del_list = []
prop_label = "**Properties** (with optional accessor):"
print prop_label
# print '-' * len(prop_label)
print
if g.view_properties:
# print g.view_properties
l = g.view_properties
l.sort()
print
# g.view_properies.sort()
for name, p in l: #g.view_properties:
# print name
attrline = ' * :attr:`~%s`' % p
for i, item in enumerate(g.view_methods):
method_name = item[0]
if "get_%s" % name == method_name or "get_%ss" % name == method_name:
del_list.append(i)
attrline += ' [:meth:`~%s`]' % item[1]
break
print attrline
del_list.reverse()
for i in del_list:
del(g.view_methods[i])
print
# ps = '\n'.join(g.view_properties)
meth_label = "**Methods**"
print meth_label
print
# print '-' * len(meth_label)
l = g.view_methods
l.sort()
for name, view in l: #g.view_methods:
# print name
print ' * :meth:`~%s`' % view
# print inspect.getdoc(g.method_objects[view.split()[0]])
# ms = '\n\n'.join(g.view_methods)
# print ms
# print ps
if __name__ == '__main__':
main()
# a link like:
# :class:`~django.http.HttpRequest`
# links to a line like:
# .. module:: django.http
# .. class:: HttpRequest
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment