diff -r eb04ac3a8327 -r 3f4bdea2abbf createdoc.py --- a/createdoc.py Wed Dec 21 22:07:48 2011 +0100 +++ b/createdoc.py Thu Sep 27 17:15:46 2012 +0200 @@ -1,14 +1,73 @@ #!/usr/bin/env python2.7 + +# Copyright (c) 2012 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 iro.user import User as Current -from iro.newuser import User as New +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) + @@ -30,108 +89,145 @@ class Keyword(): - def __init__(self,name,typ,description): + def __init__(self, name=None, typ=None, description=None): self.name=name self.typ=typ self.description=description -def section(text): - ret={} - li=[] - kw=None - for line in text.split("\n"): - if re.match("^\s*$",line): - continue - - if line[0] not in (" ","\t"): - if kw: - ret[kw.name]=kw - li.append(kw) - l=re.match(r"^(?P[a-zA-Z0-9-_.]*)\[(?P[a-zA-Z0-9-_|]*)\]:(?P.*)$",line) - kw=Keyword(name=l.group("name"),typ=l.group("typ"),description=l.group("d")) - else: - kw.description+="\n"+line.strip() - if kw: - ret[kw.name]=kw - li.append(kw) - return ret,li - - + def __repr__(self): + return ''%(self.name, self.typ, self.description) def keywords(f): - doc=f.__doc__ - kwds=re.search("Keywords:\n(?P(?P\s*)(.+\n)*)\n",doc) - k=kwds.group("keywords") - #get rid of beginning whitespaces - k=re.sub(re.compile(r"^"+kwds.group("whitespace"),re.M),"",k) - return section(k) + 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): - doc=f.__doc__ - kwds=re.search("Return:\n(?P(?P\s*)(.+\n)*)\n",doc) - k=kwds.group("ret") - #get rid of beginning whitespaces - k=re.sub(re.compile(r"^"+kwds.group("whitespace"),re.M),"",k) - return section(k) - - - + 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) + 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) - args= [b for b in args if b is not "self"] + 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) - self.description = m.__doc__.split("\n")[0] + 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) + 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("new.html","geplante API Documentation"), - Site("impressum.html","Impressum"), + Site("database.html","Datenbase Schema"), + Site("about.html","About us"), ] - current_methods = dict(inspect.getmembers(Current(None,None))) - current=[ - Method("startSMS",current_methods), - Method("startFAX",current_methods), - Method("startMail",current_methods), - - Method("status",current_methods), - Method("stop",current_methods), - - Method("getProvider",current_methods), - Method("getDefaultProvider",current_methods), - ] + 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__ - new_methods = dict(inspect.getmembers(New())) - newm=[ - Method("sms",new_methods), - Method("fax",new_methods), - Method("mail",new_methods), - - Method("status",new_methods), - Method("stop",new_methods), - - Method("routes",new_methods), - Method("defaultRoute",new_methods), - ] + 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) @@ -139,8 +235,8 @@ def a(s): if s == site: return {"class":"menu active"} - stream = tmpl.generate(sites=sites,active=a,current=current,new=newm) - with open('doc/'+site.name, "w") as g: + stream = tmpl.generate(active=a, **gd) + with open('web/'+site.name, "w") as g: g.write(stream.render('html', doctype='html')) if __name__ == '__main__':