Source code for flopy.mf6.utils.codegen

from itertools import chain
from os import PathLike
from pathlib import Path

__all__ = ["make_init", "make_targets", "make_all"]


def _get_template_env():
    # import here instead of module so we don't
    # expect optional deps at module init time
    import jinja2

    loader = jinja2.PackageLoader("flopy", "mf6/utils/codegen/templates/")
    env = jinja2.Environment(
        loader=loader,
        trim_blocks=True,
        lstrip_blocks=True,
        keep_trailing_newline=True,
    )

    from flopy.mf6.utils.codegen.filters import Filters

    env.filters["base"] = Filters.base
    env.filters["title"] = Filters.title
    env.filters["description"] = Filters.description
    env.filters["prefix"] = Filters.prefix
    env.filters["parent"] = Filters.parent
    env.filters["skip_init"] = Filters.skip_init
    env.filters["package_abbr"] = Filters.package_abbr
    env.filters["variables"] = Filters.variables
    env.filters["attrs"] = Filters.attrs
    env.filters["init"] = Filters.init
    env.filters["untag"] = Filters.untag
    env.filters["type"] = Filters.type
    env.filters["children"] = Filters.children
    env.filters["default_value"] = Filters.default_value
    env.filters["safe_name"] = Filters.safe_name
    env.filters["value"] = Filters.value
    env.filters["math"] = Filters.math
    env.filters["clean"] = Filters.clean

    return env


[docs]def make_init(dfns: dict, outdir: PathLike, verbose: bool = False): """Generate a Python __init__.py file for the given input definitions.""" env = _get_template_env() outdir = Path(outdir).expanduser().absolute() # import here instead of module so we don't # expect optional deps at module init time from flopy.mf6.utils.codegen.component import ComponentDescriptor components = list( chain.from_iterable(ComponentDescriptor.from_dfn(dfn) for dfn in dfns.values()) ) target_name = "__init__.py" target_path = outdir / target_name template = env.get_template(f"{target_name}.jinja") with open(target_path, "w") as f: f.write(template.render(components=components)) if verbose: print(f"Wrote {target_path}")
[docs]def make_targets(dfn, outdir: PathLike, verbose: bool = False): """Generate Python source file(s) from the given input definition.""" env = _get_template_env() outdir = Path(outdir).expanduser().absolute() # import here instead of module so we don't # expect optional deps at module init time from flopy.mf6.utils.codegen.component import ComponentDescriptor from flopy.mf6.utils.codegen.filters import Filters def _get_template_name(component_name) -> str: base = Filters.base(component_name) if base == "MFSimulationBase": return "simulation.py.jinja" elif base == "MFModel": return "model.py.jinja" elif base == "MFPackage": if component_name[0] == "exg": return "exchange.py.jinja" return "package.py.jinja" else: raise NotImplementedError(f"Unknown base class: {base}") for component in ComponentDescriptor.from_dfn(dfn): component_name = component["name"] target_path = outdir / f"mf{Filters.title(component_name)}.py" template = env.get_template(_get_template_name(component_name)) with open(target_path, "w") as f: f.write(template.render(**component)) if verbose: print(f"Wrote {target_path}")
[docs]def make_all(dfndir: Path, outdir: PathLike, verbose: bool = False, version: int = 1): """Generate Python source files from the DFN files in the given location.""" # import here instead of module so we don't # expect optional deps at module init time from flopy.mf6.utils.dfn import Dfn dfns = Dfn.load_all(dfndir, version=version) make_init(dfns, outdir, verbose) for dfn in dfns.values(): make_targets(dfn, outdir, verbose)