import py from py.plugin.pytest_restdoc import convert_rest_html, strip_html_header html = py.xml.html class css: #pagetitle = "pagetitle" contentspace = "contentspace" menubar = "menubar" navspace = "navspace" versioninfo = "versioninfo" class Page(object): doctype = ('\n') googlefragment = """ """ def __init__(self, project, title, targetpath, stylesheeturl=None, type="text/html", encoding="ISO-8859-1"): self.project = project self.title = project.prefix_title + title self.targetpath = targetpath self.stylesheeturl = stylesheeturl self.type = type self.encoding = encoding self.body = html.body() self.head = html.head() self._root = html.html(self.head, self.body) self.fill() def a_href(self, name, url, **kwargs): return html.a(name, class_="menu", href=url, **kwargs) def a_docref(self, name, relhtmlpath): docpath = self.project.docpath return html.div(html.a(name, class_="menu", href=relpath(self.targetpath.strpath, docpath.join(relhtmlpath).strpath))) def a_apigenref(self, name, relhtmlpath): apipath = self.project.apigenpath return html.a(name, class_="menu", href=relpath(self.targetpath.strpath, apipath.join(relhtmlpath).strpath)) def fill_menubar(self): items = [ self.a_docref("INSTALL", "install.html"), self.a_docref("CONTACT", "contact.html"), self.a_docref("CHANGELOG", "changelog.html"), self.a_docref("FAQ", "faq.html"), html.div( html.h3("py.test:"), self.a_docref("Index", "test/index.html"), self.a_docref("Quickstart", "test/quickstart.html"), self.a_docref("Features", "test/features.html"), self.a_docref("Plugins", "test/plugin/index.html"), self.a_docref("Funcargs", "test/funcargs.html"), self.a_docref("Customize", "test/customize.html"), self.a_docref("Tutorials", "test/talks.html"), ), html.div( html.h3("supporting APIs:"), self.a_docref("Index", "index.html"), self.a_docref("py.path", "path.html"), self.a_docref("py.code", "code.html"), ) #self.a_docref("py.code", "code.html"), #self.a_apigenref("api", "api/index.html"), #self.a_apigenref("source", "source/index.html"), #self.a_href("source", "http://bitbucket.org/hpk42/py-trunk/src/"), ] self.menubar = html.div(id=css.menubar, *[ html.div(item) for item in items]) version = py.version announcelink = self.a_docref("%s ANN" % version, "announce/release-%s.html" %(version,)) self.menubar.insert(0, html.div(announcelink)) #self.a_href("%s-%s" % (self.title, py.version), # "http://pypi.python.org/pypi/py/%s" % version, #id="versioninfo", def fill(self): content_type = "%s;charset=%s" %(self.type, self.encoding) self.head.append(html.title(self.title)) self.head.append(html.meta(name="Content-Type", content=content_type)) if self.stylesheeturl: self.head.append( html.link(href=self.stylesheeturl, media="screen", rel="stylesheet", type="text/css")) self.fill_menubar() self.body.append(html.div( self.project.logo, self.menubar, id=css.navspace, )) #self.body.append(html.div(self.title, id=css.pagetitle)) self.contentspace = html.div(id=css.contentspace) self.body.append(self.contentspace) def unicode(self, doctype=True): page = self._root.unicode() page = page.replace("", self.googlefragment + "") if doctype: return self.doctype + page else: return page class PyPage(Page): def get_menubar(self): menubar = super(PyPage, self).get_menubar() # base layout menubar.append( html.a("issue", href="https://codespeak.net/issue/py-dev/", class_="menu"), ) return menubar def getrealname(username): try: import uconf except ImportError: return username try: user = uconf.system.User(username) except KeyboardInterrupt: raise try: return user.realname or username except KeyError: return username class Project: mydir = py.path.local(__file__).dirpath() title = "py lib" prefix_title = "" # we have a logo already containing "py lib" encoding = 'latin1' logo = html.div( html.a( html.img(alt="py lib", id='pyimg', height=114/2, width=154/2, src="http://codespeak.net/img/pylib.png"), href="http://pylib.org")) Page = PyPage def __init__(self, sourcepath=None): if sourcepath is None: sourcepath = self.mydir self.setpath(sourcepath) def setpath(self, sourcepath, docpath=None, apigenpath=None, stylesheet=None): self.sourcepath = sourcepath if docpath is None: docpath = sourcepath self.docpath = docpath if apigenpath is None: apigenpath = docpath self.apigenpath = apigenpath if stylesheet is None: p = sourcepath.join("style.css") if p.check(): self.stylesheet = p else: self.stylesheet = None else: p = sourcepath.join(stylesheet) if p.check(): stylesheet = p self.stylesheet = stylesheet #assert self.stylesheet self.apigen_relpath = relpath( self.docpath.strpath + '/', self.apigenpath.strpath + '/') def get_content(self, txtpath, encoding): return unicode(txtpath.read(), encoding) def get_htmloutputpath(self, txtpath): reloutputpath = txtpath.new(ext='.html').relto(self.sourcepath) return self.docpath.join(reloutputpath) def process(self, txtpath): encoding = self.encoding content = self.get_content(txtpath, encoding) outputpath = self.get_htmloutputpath(txtpath) stylesheet = self.stylesheet if isinstance(stylesheet, py.path.local): if not self.docpath.join(stylesheet.basename).check(): docpath.ensure(dir=True) stylesheet.copy(docpath) stylesheet = relpath(outputpath.strpath, self.docpath.join(stylesheet.basename).strpath) content = convert_rest_html(content, txtpath, stylesheet=stylesheet, encoding=encoding) content = strip_html_header(content, encoding=encoding) title = txtpath.purebasename if txtpath.dirpath().basename == "test": title = "py.test " + title # title = "[%s] %s" % (txtpath.purebasename, py.version) page = self.Page(self, title, outputpath, stylesheeturl=stylesheet) try: modified = py.process.cmdexec( "hg tip --template 'modified {date|shortdate}'" ) except py.process.cmdexec.Error: modified = " " #page.body.append(html.div(modified, id="docinfoline")) page.contentspace.append(py.xml.raw(content)) outputpath.ensure().write(page.unicode().encode(encoding)) # XXX this function comes from apigen/linker.py, put it # somewhere in py lib import os def relpath(p1, p2, sep=os.path.sep, back='..', normalize=True): """ create a relative path from p1 to p2 sep is the seperator used for input and (depending on the setting of 'normalize', see below) output back is the string used to indicate the parent directory when 'normalize' is True, any backslashes (\) in the path will be replaced with forward slashes, resulting in a consistent output on Windows and the rest of the world paths to directories must end on a / (URL style) """ if normalize: p1 = p1.replace(sep, '/') p2 = p2.replace(sep, '/') sep = '/' # XXX would be cool to be able to do long filename # expansion and drive # letter fixes here, and such... iow: windows sucks :( if (p1.startswith(sep) ^ p2.startswith(sep)): raise ValueError("mixed absolute relative path: %r -> %r" %(p1, p2)) fromlist = p1.split(sep) tolist = p2.split(sep) # AA # AA BB -> AA/BB # # AA BB # AA CC -> CC # # AA BB # AA -> ../AA diffindex = 0 for x1, x2 in zip(fromlist, tolist): if x1 != x2: break diffindex += 1 commonindex = diffindex - 1 fromlist_diff = fromlist[diffindex:] tolist_diff = tolist[diffindex:] if not fromlist_diff: return sep.join(tolist[commonindex:]) backcount = len(fromlist_diff) if tolist_diff: return sep.join([back,]*(backcount-1) + tolist_diff) return sep.join([back,]*(backcount) + tolist[commonindex:])