From: Mike Bayer Date: Fri, 20 Oct 2006 18:46:26 +0000 (+0000) Subject: got linking of classes to work. but what a mess the doc code is now. X-Git-Tag: rel_0_3_0~22 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=705ee2cfa36b589b7cf8c5bb510d3211013acc8e;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git got linking of classes to work. but what a mess the doc code is now. --- diff --git a/doc/build/compile_docstrings.py b/doc/build/compile_docstrings.py index fdc3bd672e..ad1497f5dd 100644 --- a/doc/build/compile_docstrings.py +++ b/doc/build/compile_docstrings.py @@ -21,15 +21,13 @@ objects = [] def make_doc(obj, classes=None, functions=None): objects.append(docstring.ObjectDoc(obj, classes=classes, functions=functions)) -# basically, if you see make_doc(obj=XXX) and thats it, we have separated out the public interface. otherwise -# still a work in progress. make_doc(obj=sql) make_doc(obj=schema) make_doc(obj=engine) make_doc(obj=engine.url) make_doc(obj=orm, classes=[orm.MapperExtension]) -make_doc(obj=orm.mapperlib, classes=[orm.mapperlib.Mapper, orm.mapperlib.SelectionContext]) -make_doc(obj=orm.query, classes=[orm.query.Query, orm.query.QueryContext]) +make_doc(obj=orm.mapperlib, classes=[orm.mapperlib.Mapper]) +make_doc(obj=orm.query, classes=[orm.query.Query, orm.query.QueryContext, orm.query.SelectionContext]) make_doc(obj=orm.session, classes=[orm.session.Session, orm.session.SessionTransaction]) make_doc(obj=pool, classes=[pool.DBProxy, pool.Pool, pool.QueuePool, pool.SingletonThreadPool]) make_doc(obj=sessioncontext) diff --git a/doc/build/components/doclib.myt b/doc/build/components/doclib.myt index cbbd7df466..12efa1dabb 100644 --- a/doc/build/components/doclib.myt +++ b/doc/build/components/doclib.myt @@ -4,146 +4,147 @@ import sys, string, re # datastructure that will store the whole contents of the documentation class TOCElement: - def __init__(self, filename, name, description, parent = None, ext = None, header = None, last_updated = 0): - self.filename = filename - self.name = name - self.parent = parent - self.path = self._create_path() - self.header = header - - if self.parent is not None: - self.root = parent.root - self.root.pathlookup[self.path] = self - - if self.parent.filename != self.filename: - self.root.filelookup[self.filename] = self - self.isTop = True - else: - self.root = self - self.pathlookup = {} - self.pathlookup[''] = self - self.filelookup = {} - self.filelookup[filename] = self - - if ext is not None: - self.ext = ext - else: - self.ext = self.root.ext - - self.last_updated = last_updated - self.description = description - self.content = None - self.previous = None - self.next = None - self.children = [] - if parent: - if len(parent.children): - self.previous = parent.children[-1] - parent.children[-1].next = self - parent.children.append(self) - if last_updated > parent.last_updated: - parent.last_updated = self.last_updated - - def get_file(self, name): - name = re.sub("\.\w+$", "", name) - return self.root.filelookup[name] - - def lookup(self, path): - return self.root.pathlookup[path] - - def get_link(self, includefile = True, anchor = True): - if includefile: - if anchor: - return "%s%s#%s" % (self.filename, self.ext, self.path) - else: - return "%s%s" % (self.filename, self.ext) - else: - if anchor: - return "#" + self.path - else: - return "" - - - def _create_path(self): - elem = self - tokens = [] - while elem.parent is not None: - tokens.insert(0, elem.name) - elem = elem.parent - path = string.join(tokens, '_') - return path + def __init__(self, filename, name, description, parent = None, ext = None, header = None, last_updated = 0, htmldescription=None, altlink=None): + self.filename = filename + self.name = name + self.parent = parent + self.path = self._create_path() + self.header = header + self.altlink = altlink + if self.parent is not None: + self.root = parent.root + self.root.pathlookup[self.path] = self + + if self.parent.filename != self.filename: + self.root.filelookup[self.filename] = self + self.isTop = True + else: + self.root = self + self.pathlookup = {} + self.pathlookup[''] = self + self.filelookup = {} + self.filelookup[filename] = self + + if ext is not None: + self.ext = ext + else: + self.ext = self.root.ext + + self.last_updated = last_updated + self.description = description + self.htmldescription = htmldescription + self.content = None + self.previous = None + self.next = None + self.children = [] + if parent: + if len(parent.children): + self.previous = parent.children[-1] + parent.children[-1].next = self + parent.children.append(self) + if last_updated > parent.last_updated: + parent.last_updated = self.last_updated + + def get_file(self, name): + name = re.sub("\.\w+$", "", name) + return self.root.filelookup[name] + + def lookup(self, path): + return self.root.pathlookup[path] + + def get_link(self, includefile = True, anchor = True): + if includefile: + if anchor: + return "%s%s#%s" % (self.filename, self.ext, self.path) + else: + return "%s%s" % (self.filename, self.ext) + else: + if anchor: + return "#" + self.path + else: + return "" + + + def _create_path(self): + elem = self + tokens = [] + while elem.parent is not None: + tokens.insert(0, elem.name) + elem = elem.parent + path = string.join(tokens, '_') + return path <%python scope="request"> - current = Value() - filename = Value() + current = Value() + filename = Value() <%args scope="request"> - paged = 'yes' + paged = 'yes' <%python scope="init"> - try: - a = r - isdynamic = True - ext = ".myt" - except: - isdynamic = False - ext = ".html" - - request_comp = m.request_comp() - - if isdynamic and not m.interpreter.attributes.get('docs_static_cache', False): - page_cache = True - else: - page_cache = False - - # for dynamic page, cache the output of the final page - - if page_cache: - if m.cache_self(key="doc_%s" % paged, component = request_comp): - return - - list_comp = m.fetch_next() - files = request_comp.attributes['files'] - title = request_comp.attributes.setdefault('title', "Documentation") - version = request_comp.attributes['version'] - wrapper = request_comp.attributes['wrapper'] - index = request_comp.attributes['index'] - onepage = request_comp.attributes['onepage'] - - - - def buildtoc(): - root = TOCElement("", "root", "root element", ext = ext) - current.assign(root) - - for file in files: - filename.assign(file) - comp = m.fetch_component(file + ".myt") - - main = m.scomp(comp) - - return root - - if not page_cache: - # non-dynamic (i.e. command-line) page, cache the datastructure so successive - # pages are fast (disables auto-recompiling) - cache = m.get_cache(list_comp) - - toc = cache.get_value('toc', createfunc = buildtoc) - - else: - toc = buildtoc() - - last_updated = toc.last_updated - m.comp(wrapper, isdynamic=isdynamic, ext = ext, toc = toc, comp = request_comp, onepage = onepage, paged = paged, title = title, version = version, index=index, last_updated = last_updated) + try: + a = r + isdynamic = True + ext = ".myt" + except: + isdynamic = False + ext = ".html" + + request_comp = m.request_comp() + + if isdynamic and not m.interpreter.attributes.get('docs_static_cache', False): + page_cache = True + else: + page_cache = False + + # for dynamic page, cache the output of the final page + + if page_cache: + if m.cache_self(key="doc_%s" % paged, component = request_comp): + return + + list_comp = m.fetch_next() + files = request_comp.attributes['files'] + title = request_comp.attributes.setdefault('title', "Documentation") + version = request_comp.attributes['version'] + wrapper = request_comp.attributes['wrapper'] + index = request_comp.attributes['index'] + onepage = request_comp.attributes['onepage'] + + + + def buildtoc(): + root = TOCElement("", "root", "root element", ext = ext) + current.assign(root) + + for file in files: + filename.assign(file) + comp = m.fetch_component(file + ".myt") + + main = m.scomp(comp) + + return root + + if not page_cache: + # non-dynamic (i.e. command-line) page, cache the datastructure so successive + # pages are fast (disables auto-recompiling) + cache = m.get_cache(list_comp) + + toc = cache.get_value('toc', createfunc = buildtoc) + + else: + toc = buildtoc() + + last_updated = toc.last_updated + m.comp(wrapper, isdynamic=isdynamic, ext = ext, toc = toc, comp = request_comp, onepage = onepage, paged = paged, title = title, version = version, index=index, last_updated = last_updated) @@ -152,25 +153,27 @@ class TOCElement: <%method item> - <%doc>stores an item in the table of contents - <%args> - # name should be a URL friendly name used for hyperlinking the section - name - - # description is the heading for the item - description - - escapedesc = False - - header = None - - <%python scope="init"> - if escapedesc: - description = m.apply_escapes(description, ['h']) - - current(TOCElement(filename(), name, description, current(), header = header, last_updated = m.caller.component_source.last_modified)) - current().content = m.content() - current(current().parent) + <%doc>stores an item in the table of contents + <%args> + # name should be a URL friendly name used for hyperlinking the section + name + + # description is the heading for the item + description + + htmldescription = None + escapedesc = False + + header = None + altlink=None + + <%python scope="init"> + if escapedesc: + description = m.apply_escapes(description, ['h']) + + current(TOCElement(filename(), name, description, current(), header = header, last_updated = m.caller.component_source.last_modified, htmldescription=htmldescription, altlink=altlink)) + current().content = m.content() + current(current().parent) diff --git a/doc/build/components/formatting.myt b/doc/build/components/formatting.myt index 9894b25cd6..ee9fb3958d 100644 --- a/doc/build/components/formatting.myt +++ b/doc/build/components/formatting.myt @@ -89,14 +89,13 @@ % if not omitheader: +% if item.altlink: + +% %
-% if not omitheader: -

<% item.description %>

-% -
<%python> regexp = re.compile(r"__FORMAT:LINK{(?:\@path=(.+?))?(?:\@xtra=(.+?))?(?:\@text=(.+?))?(?:\@href=(.+?))?(?:\@class=(.+?))?}") @@ -130,6 +129,15 @@ re2 = re.compile(r"'''PYESC(.+?)PYESC'''", re.S) content = regexp.sub(link, item.content) content = re2.sub(lambda m: m.group(1), content) + description = regexp.sub(link, item.htmldescription or item.description) + + +% if not omitheader: +

<% description %>

+% +
+ +<%python> #m.write(item.content) m.write(content) diff --git a/doc/build/components/pydoc.myt b/doc/build/components/pydoc.myt index 3314fa447a..bf7a6952a0 100644 --- a/doc/build/components/pydoc.myt +++ b/doc/build/components/pydoc.myt @@ -1,13 +1,31 @@ <%global> - import docstring + import docstring, string, sys <%method obj_doc> <%args> obj + +<%python> +if obj.isclass: + s = [] + links = [] + for elem in obj.inherits: + if isinstance(elem, docstring.ObjectDoc): + links.append("%s" % (str(elem.id), elem.name)) + s.append(elem.name) + else: + links.append(str(elem)) + s.append(str(elem)) + description = "class " + obj.classname + "(%s)" % (','.join(s)) + htmldescription = "class " + obj.classname + "(%s)" % (','.join(links)) +else: + description = obj.description + htmldescription = obj.description -<&|doclib.myt:item, name=obj.name, description=obj.description &> + +<&|doclib.myt:item, name=obj.name, description=description, htmldescription=htmldescription, altlink=str(obj.id) &> <&|formatting.myt:formatplain&><% obj.doc %> % if not obj.isclass and obj.functions: diff --git a/doc/build/lib/docstring.py b/doc/build/lib/docstring.py index 8f771c20ef..b6879c7ade 100644 --- a/doc/build/lib/docstring.py +++ b/doc/build/lib/docstring.py @@ -2,8 +2,17 @@ import re, types, string, inspect """sucks a module and its contents into a simple documentation object, suitable for pickling""" -class ObjectDoc(object): +allobjects = {} + +class AbstractDoc(object): + def __init__(self, obj): + allobjects[id(obj)] = self + self.id = id(obj) + self.allobjects = allobjects + +class ObjectDoc(AbstractDoc): def __init__(self, obj, functions=None, classes=None): + super(ObjectDoc, self).__init__(obj) self.isclass = isinstance(obj, types.ClassType) or isinstance(obj, types.TypeType) self.name= obj.__name__ functions = functions @@ -52,6 +61,7 @@ class ObjectDoc(object): if self.isclass: self.description = "class " + self.name + self.classname = self.name if hasattr(obj, '__mro__'): l = [] mro = list(obj.__mro__[1:]) @@ -62,6 +72,9 @@ class ObjectDoc(object): del l[l.index(y)] l.insert(0, x) self.description += "(" + string.join([x.__name__ for x in l], ',') + ")" + self._inherits = [(id(x), x.__name__) for x in l] + else: + self._inherits = [] else: self.description = "module " + self.name @@ -82,12 +95,20 @@ class ObjectDoc(object): self.classes = [] for class_ in classes: self.classes.append(ObjectDoc(class_)) - + + def _get_inherits(self): + for item in self._inherits: + if item[0] in self.allobjects: + yield self.allobjects[item[0]] + else: + yield item[1] + inherits = property(_get_inherits) def accept_visitor(self, visitor): visitor.visit_object(self) -class FunctionDoc(object): +class FunctionDoc(AbstractDoc): def __init__(self, func): + super(FunctionDoc, self).__init__(func) argspec = inspect.getargspec(func) argnames = argspec[0] varargs = argspec[1] @@ -110,8 +131,9 @@ class FunctionDoc(object): def accept_visitor(self, visitor): visitor.visit_function(self) -class PropertyDoc(object): +class PropertyDoc(AbstractDoc): def __init__(self, name, prop): + super(PropertyDoc, self).__init__(prop) self.doc = prop.__doc__ self.name = name + " = property()" self.link = name