Module tf.tools.pdocs
Expand source code Browse git
import sys
import os
from shutil import rmtree, copytree, copyfile
from subprocess import run, call, Popen, PIPE
import errno
import time
import unicodedata
from ..core.files import fileOpen
SITE = "site"
REMOTE = "origin"
BRANCH = "gh-pages"
# COPIED FROM MKDOCS AND MODIFIED
def console(*args):
sys.stderr.write(" ".join(args) + "\n")
sys.stderr.flush()
def _enc(text):
if isinstance(text, bytes):
return text
return text.encode()
def _dec(text):
if isinstance(text, bytes):
return text.decode("utf-8")
return text
def _write(pipe, data):
try:
pipe.stdin.write(data)
except OSError as e:
if e.errno != errno.EPIPE:
raise
def _normalize_path(path):
# Fix UNICODE pathnames on OS X
# See: https://stackoverflow.com/a/5582439/44289
if sys.platform == "darwin":
return unicodedata.normalize("NFKC", _dec(path))
return path
def _try_rebase(remote, branch):
cmd = ["git", "rev-list", "--max-count=1", "{}/{}".format(remote, branch)]
p = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
(rev, _) = p.communicate()
if p.wait() != 0:
return True
cmd = ["git", "update-ref", "refs/heads/%s" % branch, _dec(rev.strip())]
if call(cmd) != 0:
return False
return True
def _get_config(key):
p = Popen(["git", "config", key], stdin=PIPE, stdout=PIPE)
(value, _) = p.communicate()
return value.decode("utf-8").strip()
def _get_prev_commit(branch):
cmd = ["git", "rev-list", "--max-count=1", branch, "--"]
p = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
(rev, _) = p.communicate()
if p.wait() != 0:
return None
return rev.decode("utf-8").strip()
def _mk_when(timestamp=None):
if timestamp is None:
timestamp = int(time.time())
currtz = "%+05d" % (-1 * time.timezone / 36) # / 3600 * 100
return "{} {}".format(timestamp, currtz)
def _start_commit(pipe, branch, message):
uname = _dec(_get_config("user.name"))
email = _dec(_get_config("user.email"))
_write(pipe, _enc("commit refs/heads/%s\n" % branch))
_write(pipe, _enc("committer {} <{}> {}\n".format(uname, email, _mk_when())))
_write(pipe, _enc("data %d\n%s\n" % (len(message), message)))
head = _get_prev_commit(branch)
if head:
_write(pipe, _enc("from %s\n" % head))
_write(pipe, _enc("deleteall\n"))
def _add_file(pipe, srcpath, tgtpath):
with fileOpen(srcpath, mode="rb") as handle:
if os.access(srcpath, os.X_OK):
_write(pipe, _enc("M 100755 inline %s\n" % tgtpath))
else:
_write(pipe, _enc("M 100644 inline %s\n" % tgtpath))
data = handle.read()
_write(pipe, _enc("data %d\n" % len(data)))
_write(pipe, _enc(data))
_write(pipe, _enc("\n"))
def _add_nojekyll(pipe):
_write(pipe, _enc("M 100644 inline .nojekyll\n"))
_write(pipe, _enc("data 0\n"))
_write(pipe, _enc("\n"))
def _gitpath(fname):
norm = os.path.normpath(fname)
return "/".join(norm.split(os.path.sep))
def _ghp_import():
if not _try_rebase(REMOTE, BRANCH):
print("Failed to rebase %s branch.", BRANCH)
console(f"copy docs to the {BRANCH} branch")
cmd = ["git", "fast-import", "--date-format=raw", "--quiet"]
kwargs = {"stdin": PIPE}
if sys.version_info >= (3, 2, 0):
kwargs["universal_newlines"] = False
pipe = Popen(cmd, **kwargs)
_start_commit(pipe, BRANCH, "docs update")
for path, _, fnames in os.walk(SITE):
for fn in fnames:
fpath = os.path.join(path, fn)
fpath = _normalize_path(fpath)
gpath = _gitpath(os.path.relpath(fpath, start=SITE))
_add_file(pipe, fpath, gpath)
_add_nojekyll(pipe)
_write(pipe, _enc("\n"))
pipe.stdin.close()
if pipe.wait() != 0:
sys.stdout.write(_enc("Failed to process commit.\n"))
console(f"push {BRANCH} branch to GitHub")
cmd = ["git", "push", REMOTE, BRANCH]
proc = Popen(cmd, stdout=PIPE, stderr=PIPE)
(out, err) = proc.communicate()
result = proc.wait() == 0
return result, _dec(err)
def _gh_deploy(org, repo, pkg):
(result, error) = _ghp_import()
if not result:
print("Failed to deploy to GitHub with error: \n%s", error)
raise SystemExit(1)
else:
url = f"https://{org}.github.io/{repo}/{pkg}"
print("Your documentation should shortly be available at: " + url)
# END COPIED FROM MKDOCS AND MODIFIED
TEMPLATE_LOC = "{}/docs/templates"
def getCommand(pkg, asString=False):
templateLoc = TEMPLATE_LOC.format(pkg)
pdoc3 = [
"pdoc3",
"--force",
"--html",
"--output-dir",
SITE,
"--template-dir",
templateLoc,
]
return " ".join(pdoc3) if asString else pdoc3
def pdoc3serve(pkg):
"""Build the docs into site and serve them."""
proc = Popen([*getCommand(pkg), "--http", ":", pkg])
time.sleep(1)
run(f"open http://localhost:8080/{pkg}", shell=True)
try:
proc.wait()
except KeyboardInterrupt:
pass
proc.terminate()
def pdoc3(pkg):
"""Build the docs into site."""
console("Build docs")
if os.path.exists(SITE):
console(f"Remove previous build ({SITE})")
rmtree(SITE)
console("Generate docs with pdoc3")
run(f"{getCommand(pkg, asString=True)} {pkg}", shell=True)
# console("Move docs into place")
# run(f"mv {SITE}/{pkg}/* {SITE}", shell=True)
# rmtree(f"{SITE}/{pkg}")
console("Copy over the images")
copytree(f"{pkg}/docs/images", f"{SITE}/{pkg}/images", dirs_exist_ok=True)
console("Copy over the stats")
copytree(f"{pkg}/docs/stats", f"{SITE}/{pkg}/stats", dirs_exist_ok=True)
# a link from the old docs URL to the new one
copyfile(f"{pkg}/docs/index.html", f"{SITE}/index.html")
def servePdocs(pkg):
run("python -m http.server 9000", cwd=SITE, shell=True)
def shipDocs(org, repo, pkg, pdoc=True):
"""Build the docs into site and ship them."""
if pdoc:
pdoc3(pkg)
_gh_deploy(org, repo, pkg)
Functions
def console(*args)
def getCommand(pkg, asString=False)
def pdoc3(pkg)
-
Build the docs into site.
def pdoc3serve(pkg)
-
Build the docs into site and serve them.
def servePdocs(pkg)
def shipDocs(org, repo, pkg, pdoc=True)
-
Build the docs into site and ship them.