createdoc.py
changeset 302 3f4bdea2abbf
parent 294 0e75bd39767d
child 312 42fd5075a5d1
--- 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 <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 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<name>[a-zA-Z0-9-_.]*)\[(?P<typ>[a-zA-Z0-9-_|]*)\]:(?P<d>.*)$",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 '<Keyword("%s", "%s", "%s")>'%(self.name, self.typ, self.description)
 
 def keywords(f):
-    doc=f.__doc__
-    kwds=re.search("Keywords:\n(?P<keywords>(?P<whitespace>\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<ret>(?P<whitespace>\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__':