aboutsummaryrefslogtreecommitdiff
path: root/generators/generators.py
diff options
context:
space:
mode:
authorneodarz <neodarz@neodarz.net>2019-05-26 16:19:08 +0200
committerneodarz <neodarz@neodarz.net>2019-05-26 16:19:08 +0200
commit73ffcccec884bbb62699b1df9ed9a4eecbc21c03 (patch)
tree956e60040730548903c03c6bc905cb8ddab1dd48 /generators/generators.py
parentdbbe906685b86706b9af03dd3f9799a67613e40d (diff)
downloadmy_new_personal_website-73ffcccec884bbb62699b1df9ed9a4eecbc21c03.tar.xz
my_new_personal_website-73ffcccec884bbb62699b1df9ed9a4eecbc21c03.zip
Move generate_blog to external file
Diffstat (limited to 'generators/generators.py')
-rw-r--r--generators/generators.py140
1 files changed, 140 insertions, 0 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