289 lines
10 KiB
Python
289 lines
10 KiB
Python
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 = ('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"'
|
|
' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n')
|
|
googlefragment = """
|
|
<script type="text/javascript">
|
|
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
|
|
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
|
|
</script>
|
|
<script type="text/javascript">
|
|
try {
|
|
var pageTracker = _gat._getTracker("UA-7597274-3");
|
|
pageTracker._trackPageview();
|
|
} catch(err) {}</script>
|
|
"""
|
|
|
|
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("</body>", self.googlefragment + "</body>")
|
|
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:])
|