createdoc.py
author Sandro Knauß <knauss@netzguerilla.net>
Thu, 27 Sep 2012 14:13:06 +0200
branchdevel
changeset 295 dc3cc61c7f6f
parent 294 0e75bd39767d
child 312 42fd5075a5d1
permissions -rwxr-xr-x
small fixes and use iro as dbname for testing.

#!/usr/bin/env python2.7

# Copyright (c) 2012 netzguerilla.net <iro@netzguerilla.net>
# 
# This file is part of Iro.
# 
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
# #Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
# 
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

# -*- coding: utf-8 -*- 

from genshi.template import TemplateLoader
from genshi import Markup
loader = TemplateLoader('doc/tmpl', auto_reload=True)


from glob import glob
import re
import os.path
import inspect
from pkg_resources import parse_version

from docutils.core import publish_doctree, publish_from_doctree, publish_string
from docutils.utils import new_document
from docutils.writers.html4css1 import Writer,HTMLTranslator

from iro.view.xmlrpc import TwistedInterface as Current 
from iro import __version__
from createerm import createSchemaPlot, tables, tables_cls

#redering text with rest syntax
class NoHeaderHTMLTranslator(HTMLTranslator):
    def __init__(self, document):
        HTMLTranslator.__init__(self,document)
        self.body_prefix = []
        self.body_suffix = []

_w = Writer()
_w.translator_class = NoHeaderHTMLTranslator
_w.visitor_attributes = ("html_body",)

def d():
    subs = _w.interpolation_dict()
    return "%(html_body)s"%subs

_w.apply_template = d

def reSTify(s):
    d = new_document("")
    if s.tagname == "paragraph":
        d.append(s[0])
    else:
        d.append(s)

    return publish_from_doctree(d, writer=_w)




class Link():
    def __init__(self,name,title):
        self.name=name
        self.title=title

    def getLink(self):
        return self.name

    def __getitem__(self,name):
        if name == "link":
            return self.getLink()
        return AttributeError(name)

class Site(Link):
    pass


class Keyword():
    def __init__(self, name=None, typ=None, description=None):
        self.name=name
        self.typ=typ
        self.description=description

    def __repr__(self):
        return '<Keyword("%s", "%s", "%s")>'%(self.name, self.typ, self.description)

def keywords(f):
    NORMAL = 0
    TYPE = 1
    pd = publish_doctree(f.__doc__.decode('utf8'))

    kws={}
    for child in pd[1][0]:
        kw = Keyword()
        ftyp = NORMAL
        for sc in child:
            if sc.tagname == "field_name":
                p = sc.astext().split()
                if p[0] in ["param",]:
                    if len(p) == 3:             #param typ name
                        kw.name = p[2]
                        kw.typ = p[1]
                    if len(p) == 2:
                        kw.name = p[1]
                elif p[0] == "type":
                    kw = kws[p[1]]
                    ftyp=TYPE
                elif p[0] in ["return","rtyp"]:
                    break
                else:
                    raise Exception("Unknown field_name: %s"%(p[0]))
            if sc.tagname == "field_body":
                if ftyp == NORMAL:
                    kw.description = Markup(reSTify(sc[0]))
                if ftyp == TYPE:
                    kw.typ = sc[0][0]
        else:
            kws[kw.name] = kw
    return kws

def ret(f):
    NORMAL = 0
    TYPE = 1
    
    pd = publish_doctree(f.__doc__.decode('utf8'))
    for child in pd[1][0]:
        kw = Keyword(name="return")
        ftyp = NORMAL
        for sc in child:
            if sc.tagname == "field_name":
                p = sc.astext().split()
                if p[0] == "return":
                    if len(p) == 2:
                        kw.typ = p[1]
                elif p[0] == "rtype":
                    ftyp=TYPE
                elif p[0] in ["param","type"]:
                    break
                else:
                    raise Exception("Unknown field_name: %s"%(p[0]))
            if sc.tagname == "field_body":
                if ftyp == NORMAL:
                    kw.description = Markup(reSTify(sc[0]))
                if ftyp == TYPE:
                    kw.typ = sc[0][0]
        else:
            return kw
    
    raise Exception("no return description")
 
class Arg():
    def __init__(self,name,f):
        self.name=name
        k = keywords(f)
        kwd=k[name]
        self.typ=kwd.typ
        self.description=kwd.description

class Method(Link):
    def __init__(self,name,methods):
        title=name[0].upper()+name[1:]
        Link.__init__(self,name,title)
        m=methods[name]
        (args, varargs, keywords, defaults)=inspect.getargspec(m)
        a=[]
        for b in args:
            if b in ("self","session"):
                continue
            else:
                a.append(b)
        
        args = a
        self.func_line=inspect.formatargspec(args, varargs, keywords, defaults)
        pd = publish_doctree(m.__doc__)
        if pd[0].tagname == "paragraph":
            self.description = pd[0].astext()
        self.args=[Arg(a,m) for a in args]
        self.rets=[ret(m)]

class Table(Link):
    def __init__(self,cls):
        name=cls.__name__
        self.tablename=cls.__tablename__
        title=self.tablename[0].upper()+self.tablename[1:]
        Link.__init__(self,name,title)
        
        self.description = Markup(publish_string(cls.__doc__,writer=_w))

class File:
    def __init__(self,path):
        self.version = re.search("/iro-(.*).tar.gz",path).group(1)
        self.name = os.path.basename(path)


def main():
    sites=[Site("index.html","Iro"),
           Site("current.html","API Documentation"),
           Site("database.html","Datenbase Schema"),
           Site("about.html","About us"),
           ]

    files=[File(f) for f in glob("web/files/*tar.gz")]
    files.sort(key=lambda a:parse_version(a.version),reverse=True)
    code ="files/iro-%s.tar.gz"%__version__

    current_methods = dict(inspect.getmembers(Current()))
    current=[ Method(i,current_methods) for i in Current().listMethods() if i  != "listMethods" ]
    
    t = [Table(tables_cls[str(f)]) for f in tables]
    createSchemaPlot('web/images/db-schema.svg')

    gd = {"sites":sites,
          "current":current,
          "tables": t,
          "code":code,
          "files":files
        }

    for site in sites:
        print("generiere %s" % site.name)
        tmpl = loader.load(site.name)
        def a(s):
            if s == site:
                return {"class":"menu active"}
        stream = tmpl.generate(active=a, **gd)
        with open('web/'+site.name, "w") as g:
            g.write(stream.render('html', doctype='html'))

if __name__ == '__main__':
    main()