create builder infrastructure
This commit is contained in:
parent
ba8f7d6df1
commit
f63f1a61ea
35
builders.py
Normal file
35
builders.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import functools
|
||||||
|
|
||||||
|
def _lazy_evaluable(func):
|
||||||
|
"""
|
||||||
|
Decorator which makes a function lazy-evaluable: that is, when it's
|
||||||
|
initially called, it returns a zero-argument lambda with the arguments
|
||||||
|
initially passed wrapped up in it. Calling that lambda has the effect
|
||||||
|
of executing the function.
|
||||||
|
|
||||||
|
We use this in TZK to allow the user to use function calls in her config
|
||||||
|
to define the build steps, while not requiring her to write a bunch of
|
||||||
|
ugly and confusing lambda:'s in the config. The functions that will be called
|
||||||
|
are prepared during the config and executed later.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@functools.wraps(func)
|
||||||
|
def new_func(*args, **kwargs):
|
||||||
|
my_args = args
|
||||||
|
my_kwargs = kwargs
|
||||||
|
@functools.wraps(new_func)
|
||||||
|
def inner():
|
||||||
|
func(*my_args, **my_kwargs)
|
||||||
|
return inner
|
||||||
|
return new_func
|
||||||
|
|
||||||
|
# Now a more descriptive name that doesn't expose inner workings
|
||||||
|
# if the user wants to write her own builder.
|
||||||
|
tzk_builder = _lazy_evaluable
|
||||||
|
|
||||||
|
@tzk_builder
|
||||||
|
def printer(username: str):
|
||||||
|
if username == 'Maud':
|
||||||
|
raise Exception("No Mauds allowed!")
|
||||||
|
print(f"Hallelujah, {username} built a wiki!")
|
||||||
|
printer.name = "Display the user's name"
|
@ -16,9 +16,10 @@ class ConfigurationManager:
|
|||||||
if child.is_file() and child.name.endswith('.py'):
|
if child.is_file() and child.name.endswith('.py'):
|
||||||
mod_name = child.name.rsplit('.', 1)[0]
|
mod_name = child.name.rsplit('.', 1)[0]
|
||||||
if mod_name == 'tzk_config':
|
if mod_name == 'tzk_config':
|
||||||
|
sys.path.insert(0, Path("__file__").parent)
|
||||||
sys.path.insert(0, str(self.config_path))
|
sys.path.insert(0, str(self.config_path))
|
||||||
self.conf_mod = importlib.import_module(mod_name)
|
self.conf_mod = importlib.import_module(mod_name)
|
||||||
del sys.path[0]
|
del sys.path[0:1]
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
fail(
|
fail(
|
||||||
|
47
tzk.py
47
tzk.py
@ -3,6 +3,7 @@ import argparse
|
|||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
|
import traceback
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from config import cm
|
from config import cm
|
||||||
@ -146,6 +147,52 @@ class InitCommand(CliCommand):
|
|||||||
tw.install(args.wiki_name, args.tiddlywiki_version_spec, args.author)
|
tw.install(args.wiki_name, args.tiddlywiki_version_spec, args.author)
|
||||||
|
|
||||||
|
|
||||||
|
class BuildCommand(CliCommand):
|
||||||
|
cmd = "build"
|
||||||
|
help = ("Build another wiki or derivative product, "
|
||||||
|
"such as a public version of the wiki, "
|
||||||
|
"from this TZK repository.")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setup_arguments(cls, parser: argparse.ArgumentParser) -> None:
|
||||||
|
parser.add_argument(
|
||||||
|
"product",
|
||||||
|
metavar="PRODUCT",
|
||||||
|
help="Name of the product you want to build (defined in your config file).",
|
||||||
|
)
|
||||||
|
|
||||||
|
def _precheck(self, product: str) -> None:
|
||||||
|
if cm.products is None:
|
||||||
|
fail("No 'products' dictionary is defined in your config file.")
|
||||||
|
if product not in cm.products:
|
||||||
|
fail(f"No '{product}' product found in the products dictionary "
|
||||||
|
f"in your config file. (Available: {', '.join(cm.products.keys())})")
|
||||||
|
if not cm.products[product]:
|
||||||
|
fail(f"No build steps are defined in the '{product}' product "
|
||||||
|
f"in your config file.")
|
||||||
|
|
||||||
|
def execute(self, args: argparse.Namespace) -> None:
|
||||||
|
self._precheck(args.product)
|
||||||
|
|
||||||
|
steps = cm.products[args.product]
|
||||||
|
print(f"tzk: Starting build of product '{args.product}'.")
|
||||||
|
print(f"tzk: Found {len(steps)} build steps.")
|
||||||
|
|
||||||
|
for idx, step in enumerate(steps, 1):
|
||||||
|
if hasattr(step, 'name'):
|
||||||
|
print(f"\ntzk: Step {idx}/{len(steps)}: {step.name}")
|
||||||
|
else:
|
||||||
|
print(f"\ntzk: Step {idx}/{len(steps)}")
|
||||||
|
try:
|
||||||
|
step()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"\ntzk: Build of product '{args.product}' failed on step {failed}. "
|
||||||
|
f"The original error follows:")
|
||||||
|
traceback.print_exc()
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
print(f"\ntzk: Build of product '{args.product}' completed successfully.")
|
||||||
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
subparsers = parser.add_subparsers()
|
subparsers = parser.add_subparsers()
|
||||||
|
Loading…
Reference in New Issue
Block a user