aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--generators/generators.py140
-rwxr-xr-xpyblog146
2 files changed, 144 insertions, 142 deletions
diff --git a/generators/generators.py b/generators/generators.py
index adfe819a..3122f9c8 100644
--- a/generators/generators.py
+++ b/generators/generators.py
@@ -18,6 +18,8 @@ import copy
import email.utils
import time
+import shutil
+
from rss import *
from config.config import *
@@ -689,3 +691,141 @@ def generate_index_and_feed():
sys.stderr.write("wrote rss.xml\n")
generate_sitemap(feed)
+
+
+# exclude_list is only inialized once to avoid constant disk IO
+@utils.static_vars(exclude_list=None)
+def generate_blog(fresh=False, report_total_errors=True):
+ """Generate the blog in BUILDDIR.
+
+ Parameters
+ ----------
+ fresh : bool
+ If True, remove all existing build artifects and start afresh;
+ otherwise, only copy or build new or modified files. Default is
+ False.
+ report_total_errors : bool
+ If True, a line will be printed to stderr at the end of build
+ (assuming the function doesn't raise early) reporting the total
+ number of errors, e.g., "build finished with 0 errors". This is
+ turned on by default, but pass False to turn it off, which will
+ result in a completely silent session if nothing changed. This
+ is useful for auto-regen, for instance.
+
+ Returns
+ -------
+ failed_builds : int
+ Number of build failures.
+
+ """
+
+ # pylint: disable=too-many-branches,too-many-locals,too-many-statements
+
+ if not os.path.isdir(SOURCEDIR):
+ raise OSError("source directory %s does not exist" % SOURCEDIR)
+ if not os.path.exists(HTMLTEMPLATE):
+ raise OSError("HTML template %s not found" % HTMLTEMPLATE)
+
+ if not os.path.isdir(BUILDDIR):
+ if os.path.exists(BUILDDIR):
+ os.remove(BUILDDIR)
+ os.mkdir(BUILDDIR, mode=0o755)
+ if fresh:
+ for name in os.listdir(BUILDDIR):
+ if name == ".git":
+ continue
+ obj = os.path.join(BUILDDIR, name)
+ if os.path.isdir(obj):
+ shutil.rmtree(obj)
+ else:
+ os.remove(obj)
+
+ # nojekyll: https://help.github.com/articles/files-that-start-with-an-underscore-are-missing/
+ if not os.path.exists(os.path.join(BUILDDIR, ".nojekyll")):
+ with open(os.path.join(BUILDDIR, ".nojekyll"), "w") as fileobj:
+ pass
+
+ if CUSTOM_DOMAIN and not os.path.exists(os.path.join(BUILDDIR, "CNAME")):
+ with open(os.path.join(BUILDDIR, "CNAME"), "w") as fileobj:
+ fileobj.write(CUSTOM_DOMAIN)
+
+ failed_builds = 0
+ generator_mtime = os.path.getmtime(GENERATORSOURCE)
+ template_mtime = os.path.getmtime(HTMLTEMPLATE)
+ fundamental_mtime = max(generator_mtime, template_mtime)
+ anything_modified = False
+
+ exclude_list = generate_blog.exclude_list # get value of static variable
+ if exclude_list is None:
+ try:
+ with open(EXCLUDELIST) as fp:
+ exclude_list = [os.path.abspath(os.path.join(SOURCEDIR, line.rstrip()))
+ for line in list(fp)
+ if line.strip() != "" and not line.startswith('#')]
+ except OSError:
+ exclude_list = []
+ generate_blog.exclude_list = exclude_list # assign to static variable for the future
+
+ for root, dirs, files in os.walk(SOURCEDIR):
+ # If root is in exclude list, skip all files and remove all subdirs from traversal list.
+ if root in exclude_list:
+ dirs[:] = []
+ continue
+
+ relroot = os.path.relpath(root, start=SOURCEDIR)
+ dstroot = os.path.join(BUILDDIR, relroot)
+ if not os.path.isdir(dstroot):
+ if os.path.exists(dstroot):
+ os.remove(dstroot)
+ os.mkdir(dstroot, mode=0o755)
+
+ for name in files:
+ if name.startswith('.') or os.path.join(root, name) in exclude_list:
+ continue
+
+ extension = name.split(".")[-1]
+ if extension not in ["css", "js", "asc", "html", "jpg", "md", "png", "svg", "ico", "txt",
+ "eot", "ttf", "woff", "woff2"]:
+ continue
+
+ relpath = os.path.join(relroot, name)
+ srcpath = os.path.join(root, name)
+ if extension == "md":
+ dstpath = os.path.join(dstroot, re.sub(r'\.md$', '.html', name))
+ else:
+ dstpath = os.path.join(dstroot, name)
+ if ((not os.path.exists(dstpath) or
+ os.path.getmtime(dstpath) <=
+ max(fundamental_mtime, os.path.getmtime(srcpath)))):
+ # new post or modified post
+ anything_modified = True
+ if srcpath == INDEXMD:
+ continue # index will be processed separately
+ if extension in ["css", "js", "asc", "html", "jpg", "png", "svg", "ico", "txt",
+ "eot", "ttf", "woff", "woff2"]:
+ sys.stderr.write("copying %s\n" % relpath)
+ shutil.copy(srcpath, dstpath)
+ elif extension == "md":
+ sys.stderr.write("compiling %s\n" % relpath)
+ pandoc_args = [
+ "pandoc", srcpath,
+ "--template", HTMLTEMPLATE,
+ "--highlight-style=pygments",
+ "-o", dstpath,
+ ]
+ try:
+ subprocess.check_call(pandoc_args)
+ except subprocess.CalledProcessError:
+ failed_builds += 1
+ sys.stderr.write("error: failed to generate %s" %
+ relpath)
+ # postprocess generated HTML file
+ utils.postprocess_html_file(dstpath)
+
+ if anything_modified:
+ generate_index_and_feed()
+ sys.stderr.write("done\n")
+
+ if report_total_errors:
+ sys.stderr.write("build finished with %d errors\n" % failed_builds)
+ return failed_builds
diff --git a/pyblog b/pyblog
index 3d443482..a3f483d5 100755
--- a/pyblog
+++ b/pyblog
@@ -51,154 +51,16 @@ from config.config import *
from generators import generators
-# exclude_list is only inialized once to avoid constant disk IO
-@utils.static_vars(exclude_list=None)
-def generate_blog(fresh=False, report_total_errors=True):
- """Generate the blog in BUILDDIR.
-
- Parameters
- ----------
- fresh : bool
- If True, remove all existing build artifects and start afresh;
- otherwise, only copy or build new or modified files. Default is
- False.
- report_total_errors : bool
- If True, a line will be printed to stderr at the end of build
- (assuming the function doesn't raise early) reporting the total
- number of errors, e.g., "build finished with 0 errors". This is
- turned on by default, but pass False to turn it off, which will
- result in a completely silent session if nothing changed. This
- is useful for auto-regen, for instance.
-
- Returns
- -------
- failed_builds : int
- Number of build failures.
-
- """
-
- # pylint: disable=too-many-branches,too-many-locals,too-many-statements
-
- if not os.path.isdir(SOURCEDIR):
- raise OSError("source directory %s does not exist" % SOURCEDIR)
- if not os.path.exists(HTMLTEMPLATE):
- raise OSError("HTML template %s not found" % HTMLTEMPLATE)
-
- if not os.path.isdir(BUILDDIR):
- if os.path.exists(BUILDDIR):
- os.remove(BUILDDIR)
- os.mkdir(BUILDDIR, mode=0o755)
- if fresh:
- for name in os.listdir(BUILDDIR):
- if name == ".git":
- continue
- obj = os.path.join(BUILDDIR, name)
- if os.path.isdir(obj):
- shutil.rmtree(obj)
- else:
- os.remove(obj)
-
- # nojekyll: https://help.github.com/articles/files-that-start-with-an-underscore-are-missing/
- if not os.path.exists(os.path.join(BUILDDIR, ".nojekyll")):
- with open(os.path.join(BUILDDIR, ".nojekyll"), "w") as fileobj:
- pass
-
- if CUSTOM_DOMAIN and not os.path.exists(os.path.join(BUILDDIR, "CNAME")):
- with open(os.path.join(BUILDDIR, "CNAME"), "w") as fileobj:
- fileobj.write(CUSTOM_DOMAIN)
-
- failed_builds = 0
- generator_mtime = os.path.getmtime(GENERATORSOURCE)
- template_mtime = os.path.getmtime(HTMLTEMPLATE)
- fundamental_mtime = max(generator_mtime, template_mtime)
- anything_modified = False
-
- exclude_list = generate_blog.exclude_list # get value of static variable
- if exclude_list is None:
- try:
- with open(EXCLUDELIST) as fp:
- exclude_list = [os.path.abspath(os.path.join(SOURCEDIR, line.rstrip()))
- for line in list(fp)
- if line.strip() != "" and not line.startswith('#')]
- except OSError:
- exclude_list = []
- generate_blog.exclude_list = exclude_list # assign to static variable for the future
-
- for root, dirs, files in os.walk(SOURCEDIR):
- # If root is in exclude list, skip all files and remove all subdirs from traversal list.
- if root in exclude_list:
- dirs[:] = []
- continue
-
- relroot = os.path.relpath(root, start=SOURCEDIR)
- dstroot = os.path.join(BUILDDIR, relroot)
- if not os.path.isdir(dstroot):
- if os.path.exists(dstroot):
- os.remove(dstroot)
- os.mkdir(dstroot, mode=0o755)
-
- for name in files:
- if name.startswith('.') or os.path.join(root, name) in exclude_list:
- continue
-
- extension = name.split(".")[-1]
- if extension not in ["css", "js", "asc", "html", "jpg", "md", "png", "svg", "ico", "txt",
- "eot", "ttf", "woff", "woff2"]:
- continue
-
- relpath = os.path.join(relroot, name)
- srcpath = os.path.join(root, name)
- if extension == "md":
- dstpath = os.path.join(dstroot, re.sub(r'\.md$', '.html', name))
- else:
- dstpath = os.path.join(dstroot, name)
- if ((not os.path.exists(dstpath) or
- os.path.getmtime(dstpath) <=
- max(fundamental_mtime, os.path.getmtime(srcpath)))):
- # new post or modified post
- anything_modified = True
- if srcpath == INDEXMD:
- continue # index will be processed separately
- if extension in ["css", "js", "asc", "html", "jpg", "png", "svg", "ico", "txt",
- "eot", "ttf", "woff", "woff2"]:
- sys.stderr.write("copying %s\n" % relpath)
- shutil.copy(srcpath, dstpath)
- elif extension == "md":
- sys.stderr.write("compiling %s\n" % relpath)
- pandoc_args = [
- "pandoc", srcpath,
- "--template", HTMLTEMPLATE,
- "--highlight-style=pygments",
- "-o", dstpath,
- ]
- try:
- subprocess.check_call(pandoc_args)
- except subprocess.CalledProcessError:
- failed_builds += 1
- sys.stderr.write("error: failed to generate %s" %
- relpath)
- # postprocess generated HTML file
- utils.postprocess_html_file(dstpath)
-
- if anything_modified:
- generators.generate_index_and_feed()
- sys.stderr.write("done\n")
-
- if report_total_errors:
- sys.stderr.write("build finished with %d errors\n" % failed_builds)
- return failed_builds
-
-
def generate(args):
"""Wrapper for generate_blog(fresh=False)."""
# pylint: disable=unused-argument
- exit(generate_blog(fresh=False))
+ exit(generators.generate_blog(fresh=False))
def regenerate(args):
"""Wrapper for generate_blog(fresh=True)."""
# pylint: disable=unused-argument
- exit(generate_blog(fresh=True))
+ exit(generators.generate_blog(fresh=True))
def sanitize(string):
@@ -502,7 +364,7 @@ def gen_deploy(args):
touch(latest_post)
sys.stderr.write("\n")
- generate_blog(fresh=True)
+ generators.generate_blog(fresh=True)
deploy(None)
@@ -570,7 +432,7 @@ def preview(args):
# watches for modifications and only regens upon changes, and it is
# completely silent when there's no change.
while not sigint_raised:
- generate_blog(fresh=False, report_total_errors=False)
+ generators.generate_blog(fresh=False, report_total_errors=False)
time.sleep(0.5)
sys.stderr.write("\nSIGINT received, cleaning up...\n")