Skip to content

Instantly share code, notes, and snippets.

@shimizukawa
Created April 14, 2012 03:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shimizukawa/2382005 to your computer and use it in GitHub Desktop.
Save shimizukawa/2382005 to your computer and use it in GitHub Desktop.
sphinxのMakefileをPython化 (作りかけ4/14バージョン) あるいはmake.pyをどこまでMakefile的に書けるかの実験
@python make.py "%1"
# -*- 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()
# 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
# -*- 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