Created
April 14, 2012 03:58
-
-
Save shimizukawa/2382005 to your computer and use it in GitHub Desktop.
sphinxのMakefileをPython化 (作りかけ4/14バージョン) あるいはmake.pyをどこまでMakefile的に書けるかの実験
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@python make.py "%1" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
# Makefile for Sphinx documentation | |
# | |
# You can set these variables from the command line. | |
SPHINXOPTS = '' | |
SPHINXBUILD = 'bin/sphinx-build' | |
PAPER = '' | |
BUILDDIR = 'build' | |
PROJECTNAME = 'freia' | |
# Internal variables. | |
PAPEROPT = ('-D latex_paper_size=' + PAPER) if PAPER else '' | |
ALLSPHINXOPTS = [ | |
'-d', BUILDDIR + '/doctrees', | |
PAPEROPT, | |
SPHINXOPTS, | |
'source', | |
] | |
import sys | |
from mk import make | |
target, sh, echo = make.target, make.sh, make.echo | |
#.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest | |
@target() | |
def help(): | |
"""to print this message""" | |
echo("""Please use `make <target>' where <target> is one of""") | |
width = max(len(c.__name__) for c in make.targets()) | |
for c in make.targets(): | |
echo(" {c.__name__:<%d} {c.__doc__}" % width) | |
@target() | |
def clean(): | |
"""to remove BUILDDIR/*""" | |
return make.rm(BUILDDIR + '/*') | |
@target() | |
def html(): | |
"""to make standalone HTML files""" | |
bdir = BUILDDIR + '/html' | |
sh(SPHINXBUILD, '-b', 'html', ALLSPHINXOPTS, bdir) | |
echo() | |
echo("Build finished. The HTML pages are in {bdir}.") | |
@target() | |
def dirhtml(): | |
"""to make HTML files named index.html in directories""" | |
bdir = BUILDDIR + '/dirhtml' | |
sh(SPHINXBUILD, '-b', 'dirhtml', ALLSPHINXOPTS, bdir) | |
echo() | |
echo("Build finished. The HTML pages are in {bdir}.") | |
@target() | |
def singlehtml(): | |
"""to make a single large HTML file""" | |
bdir = BUILDDIR + '/singlehtml' | |
sh(SPHINXBUILD, '-b', 'singlehtml', ALLSPHINXOPTS, bdir) | |
echo() | |
echo("Build finished. The HTML page is in {bdir}.") | |
@target() | |
def pickle(): | |
"""to make pickle files""" | |
bdir = BUILDDIR + '/pickle' | |
sh(SPHINXBUILD, '-b', 'pickle', ALLSPHINXOPTS, bdir) | |
echo() | |
echo("Build finished; now you can process the pickle files.") | |
@target() | |
def json(): | |
"""to make JSON files""" | |
bdir = BUILDDIR + '/json' | |
sh(SPHINXBUILD, '-b', 'json', ALLSPHINXOPTS, bdir) | |
echo() | |
echo("Build finished; now you can process the JSON files.") | |
@target() | |
def htmlhelp(): | |
"""to make HTML files and a HTML help project""" | |
bdir = BUILDDIR + '/htmlhelp' | |
sh(SPHINXBUILD, '-b', 'htmlhelp', ALLSPHINXOPTS, bdir) | |
echo() | |
echo("Build finished; now you can run HTML Help Workshop with the" | |
".hhp project file in {bdir}.") | |
@target() | |
def qthelp(): | |
"""to make HTML files and a qthelp project""" | |
bdir = BUILDDIR + '/qthelp' | |
sh(SPHINXBUILD, '-b', 'qthelp', ALLSPHINXOPTS, bdir) | |
echo() | |
echo("Build finished; now you can run `qcollectiongenerator` with the" | |
".qhcp project file in {bdir}, like this:\n" | |
"# qcollectiongenerator {bdir}/{PROJECTNAME}.qhcp" | |
"To view the help file:\n" | |
"# assistant -collectionFile {bdir}/{PROJECTNAME}.qhc") | |
@target() | |
def devhelp(): | |
"""to make HTML files and a Devhelp project""" | |
bdir = BUILDDIR + '/devhelp' | |
sh(SPHINXBUILD, '-b', 'devhelp', ALLSPHINXOPTS, bdir) | |
echo() | |
echo("Build finished.") | |
echo("To view the help file:") | |
echo("# mkdir -p $HOME/.local/share/devhelp/{PROJECTNAME}") | |
echo("# ln -s {bdir} $HOME/.local/share/devhelp/{PROJECTNAME}") | |
echo("# devhelp") | |
@target() | |
def epub(): | |
"""to make an epub""" | |
bdir = BUILDDIR + '/epub' | |
sh(SPHINXBUILD, '-b', 'epub', ALLSPHINXOPTS, bdir) | |
echo() | |
echo("Build finished. The epub file is in {bdir}.") | |
@target() | |
def latex(): | |
"""to make LaTeX files, you can set PAPER=a4 or PAPER=letter""" | |
#TODO: PAPER is envoronment? option args? | |
bdir = BUILDDIR + '/latex' | |
sh(SPHINXBUILD, '-b', 'latex', ALLSPHINXOPTS, bdir) | |
echo() | |
echo("Build finished; the LaTeX files are in {bdir}.") | |
echo("Run `make' in that directory to run these through (pdf)latex" | |
"(use `make latexpdf' here to do that automatically).") | |
@target() | |
def latexpdf(): | |
"""to make LaTeX files and run them through pdflatex""" | |
bdir = BUILDDIR + '/latex' | |
sh(SPHINXBUILD, '-b', 'latex', ALLSPHINXOPTS, bdir) | |
echo("Running LaTeX files through pdflatex...") | |
sh(make, '-C', bdir, 'all-pdf') #TODO: こうやって外部make.pyを呼び出したい | |
echo("pdflatex finished; the PDF files are in {bdir}.") | |
@target() | |
def text(): | |
"""to make text files""" | |
bdir = BUILDDIR + '/text' | |
sh(SPHINXBUILD, '-b', 'text', ALLSPHINXOPTS, bdir) | |
echo() | |
echo("Build finished. The text files are in {bdir}.") | |
@target() | |
def man(): | |
"""to make manual pages""" | |
bdir = BUILDDIR + '/man' | |
sh(SPHINXBUILD, '-b', 'man', ALLSPHINXOPTS, bdir) | |
echo() | |
echo("Build finished. The manual pages are in {bdir}.") | |
@target() | |
def changes(): | |
"""to make an overview of all changed/added/deprecated items""" | |
bdir = BUILDDIR + '/changes' | |
sh(SPHINXBUILD, '-b', 'changes', ALLSPHINXOPTS, bdir) | |
echo() | |
echo("The overview file is in {bdir}.") | |
@target() | |
def linkcheck(): | |
"""to check all external links for integrity""" | |
bdir = BUILDDIR + '/linkcheck' | |
sh(SPHINXBUILD, '-b', 'linkcheck', ALLSPHINXOPTS, bdir) | |
echo() | |
echo("Link check complete; look for any errors in the above output " | |
"or in {bdir}/output.txt.") | |
@target() | |
def doctest(): | |
"""to run all doctests embedded in the documentation (if enabled)""" | |
bdir = BUILDDIR + '/doctest' | |
sh(SPHINXBUILD, '-b', 'doctest', ALLSPHINXOPTS, bdir) | |
echo("Testing of doctests in the sources finished, look at the " | |
"results in {bdir}/output.txt.") | |
if __name__ == '__main__': | |
make.run() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Makefile for Sphinx documentation | |
# | |
# You can set these variables from the command line. | |
PYTHON = python | |
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest | |
help: | |
$(PYTHON) make.py help | |
clean: | |
$(PYTHON) make.py clean | |
html: | |
$(PYTHON) make.py html | |
dirhtml: | |
$(PYTHON) make.py dirhtml | |
singlehtml: | |
$(PYTHON) make.py singlehtml | |
pickle: | |
$(PYTHON) make.py pickle | |
json: | |
$(PYTHON) make.py json | |
htmlhelp: | |
$(PYTHON) make.py htmlhelp | |
qthelp: | |
$(PYTHON) make.py qhelp | |
devhelp: | |
$(PYTHON) make.py devhelp | |
epub: | |
$(PYTHON) make.py epub | |
latex: | |
$(PYTHON) make.py latex | |
latexpdf: | |
$(PYTHON) make.py latexpdf | |
text: | |
$(PYTHON) make.py text | |
man: | |
$(PYTHON) make.py man | |
changes: | |
$(PYTHON) make.py changes | |
linkcheck: | |
$(PYTHON) make.py linkcheck | |
doctest: | |
$(PYTHON) make.py doctest |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
from __future__ import print_function | |
import os | |
import sys | |
import glob | |
import subprocess | |
import shutil | |
def flatten(seq): | |
def _flatten(seq): | |
if isinstance(seq, (list, tuple)): | |
for s in seq: | |
for x in _flatten(s): | |
yield x | |
else: | |
yield seq | |
return filter(None, _flatten(seq)) | |
class Runner(object): | |
def __init__(self, func, depends=None, targets=None): | |
if isinstance(func, self.__class__): | |
self.func = func.func | |
self.depends = depends or func.depends or [] | |
self.targets = targets or func.targets or [] | |
else: | |
self.func = func | |
self.depends = depends or [] | |
self.targets = targets or [] | |
self.__name__ = self.func.__name__ | |
self.__doc__ = self.func.__doc__ | |
def __call__(self, *args, **kw): | |
# targets | |
if self.targets and __builtins__.all( | |
os.path.exists(target) for target in self.targets): | |
print("Skip:", self.__name__) | |
print(" all targets are exists:", self.targets) | |
return 0 | |
# depends | |
for depend in self.depends: | |
ret = make.call(depend) | |
if ret: | |
return ret | |
# main | |
print("In:", self.__name__) | |
ret = self.func(*args, **kw) | |
print("Out:", self.__name__) | |
return ret | |
class make(object): | |
"""class for namespace""" | |
__commands = {} | |
__commands_order = [] | |
#private | |
@classmethod | |
def _register(cls, func, depends=None, targets=None): | |
func = Runner(func, depends=depends, targets=targets) | |
cls.__commands[func.__name__] = func | |
if func.__name__ not in cls.__commands_order: | |
cls.__commands_order.append(func.__name__) | |
return func | |
#decorator | |
@classmethod | |
def depend(cls, *depends): | |
def inner(func): | |
return cls._register(func, depends=depends) | |
return inner | |
#decorator | |
@classmethod | |
def target(cls, *targets): | |
def inner(func): | |
return cls._register(func, targets=targets) | |
return inner | |
#utility | |
@classmethod | |
def sh(cls, *args): | |
args = flatten(args) | |
print(' '.join(args)) | |
return subprocess.check_call(args) | |
#utility | |
@classmethod | |
def rm(cls, *dirs): | |
for d in dirs: | |
for f in glob.glob(d): | |
shutil.rmtree(f, True) | |
#utility | |
@classmethod | |
def mkdir(cls, path): | |
if not os.path.exists(path): | |
os.makedirs(EGG_DIR) | |
#utility | |
@classmethod | |
def call(cls, name, args=[], kw={}): | |
return cls.__commands[name](*args, **kw) | |
#utility | |
@classmethod | |
def echo(cls, *args, **kw): | |
d = dict(sys._getframe().f_back.f_globals) | |
d.update(dict(sys._getframe().f_back.f_locals)) | |
args = [a.format(**d) for a in args] | |
print(*args, **kw) | |
#utility | |
@classmethod | |
def targets(cls): | |
return [cls.__commands[t] for t in cls.__commands_order] | |
#utility | |
@classmethod | |
def run(cls): | |
target = '' | |
if len(sys.argv) >= 2: | |
target = sys.argv[1] | |
if not target: | |
if len(cls.__commands_order): | |
target = cls.__commands_order[0] | |
else: | |
print(sys.argv[0], 'have no target.') | |
sys.exit(-1) | |
try: | |
ret = cls.call(target) | |
except: | |
print('Error in', target) | |
raise | |
if ret: | |
print('Error in', target, '::', ret) | |
if not isinstance(ret, int) and ret is not None: | |
ret = -1 | |
sys.exit(ret) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment