# Copyright (c) 2018 The Regents of the University of Michigan
# All rights reserved.
# This software is licensed under the BSD 3-Clause License.
"""FlowProject module templates.
These templates can be initialized via the init() function defined
in this module and the main 'flow' command line interface.
"""
import errno
import logging
import os
import sys
import jinja2
logger = logging.getLogger(__name__)
TEMPLATES = {
"minimal": [
("project.py", "project_minimal.pyt"),
],
"example": [
("project.py", "project_example.pyt"),
],
"testing": [
("project.py", "project_testing.pyt"),
],
}
[docs]
def init(alias=None, template=None, path=None):
"""Initialize a templated :class:`~.FlowProject` module.
Parameters
----------
alias : str
Python identifier used as a file name for the template output. Uses
``"project"`` if None. (Default value = None)
template : str
Name of the template to use. Built-in templates are:
* ``"minimal"``
* ``"example"``
* ``"testing"``
Uses ``"minimal"`` if None. (Default value = None)
path : str
Directory where the output file is placed. Uses the current working
directory if None. (Default value = None)
Returns
-------
list
List of file names created.
"""
if alias is None:
alias = "project"
elif not alias.isidentifier():
raise ValueError(
f"The alias '{alias}' is not a valid Python identifier and therefore "
"cannot be used as a FlowProject alias."
)
if template is None:
template = "minimal"
if os.path.splitext(alias)[1]:
raise RuntimeError("Please provide a name without suffix!")
project_class_name = alias.capitalize()
if not project_class_name.endswith("Project"):
project_class_name += "Project"
template_environment = jinja2.Environment(
loader=jinja2.ChoiceLoader(
[
jinja2.FileSystemLoader("templates"),
jinja2.PackageLoader("flow", "templates"),
]
),
trim_blocks=True,
lstrip_blocks=True,
)
context = {}
context["alias"] = alias
context["project_class_name"] = project_class_name
# render all templates
codes = {}
for fn, fn_template in TEMPLATES[template]:
fn_ = fn.format(alias=alias) # some of the filenames may depend on the alias
template = template_environment.get_template(fn_template)
codes[fn_] = template.render(**context)
# create files
files_created = []
for fn, code in codes.items():
try:
if path is not None:
fn = os.path.join(path, fn)
with open(fn, "x") as fw:
fw.write(code + "\n")
except OSError as error:
error_message = (
f"Error while creating FlowProject module with name '{alias}': "
)
if error.errno == errno.EEXIST:
error_message += f"a file named '{fn}' already exists!"
else:
error_message += f"'{error}'."
raise OSError(error_message)
else:
files_created.append(fn)
print(f"Created file '{fn}'.", file=sys.stderr)
return files_created