From 0cacda596cd3a4797ab10e196edeab3321138871 Mon Sep 17 00:00:00 2001 From: Paul Natsuo Kishimoto Date: Mon, 30 Oct 2023 16:41:22 +0100 Subject: [PATCH] Add .util.click.exec_cb for --nodes, --regions CLI options --- message_ix_models/util/click.py | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/message_ix_models/util/click.py b/message_ix_models/util/click.py index c6a1004dcf..e5a2905f32 100644 --- a/message_ix_models/util/click.py +++ b/message_ix_models/util/click.py @@ -5,7 +5,7 @@ import logging from datetime import datetime from pathlib import Path -from typing import List, Optional, Union +from typing import Callable, List, Optional, Union import click from click import Argument, Choice, Option @@ -59,6 +59,32 @@ def _callback(context, param, value): return _callback +def exec_cb(expression: str) -> Callable: + """Return a callback that :func:`exec`-utes an `expression`. + + The `expression` is executed in a limited context that has only two names available: + + - :py:`context`: the :class:`.Context` instance. + - :py:`value`: the value passed to the :mod:`click.Parameter`. + + Example + ------- + >>> @click.command + ... @click.option( + ... "--myopt", callback=exec_cb("context.my_mod.my_opt = value + 3") + ... ) + ... def cmd(...): + ... ... + """ + + def _cb(context: Union[click.Context, Context], param, value): + ctx = context.obj if isinstance(context, click.Context) else context + exec(expression, {}, {"context": ctx, "value": value}) + return value + + return _cb + + def format_sys_argv() -> str: """Format :data:`sys.argv` in a readable manner.""" import sys @@ -159,6 +185,7 @@ def unique_id() -> str: "nodes": Option( ["--nodes"], help="Code list to use for 'node' dimension.", + callback=exec_cb("context.model.regions = value"), type=Choice(codelists("node")), ), "output_model": Option( @@ -178,6 +205,7 @@ def unique_id() -> str: "regions": Option( ["--regions"], help="Code list to use for 'node' dimension.", + callback=exec_cb("context.model.regions = value"), type=Choice(codelists("node")), ), "rep_out_path": Option(