Source code for rail_pz_service.common.common_options

"""Common options for pz-rail-service CLIs"""

from collections.abc import Callable
from enum import Enum, auto
from functools import partial
from typing import Any

import click
from click.decorators import FC


[docs] class DictParamType(click.ParamType): # pragma: no cover """Represents the dictionary type of a CLI parameter. Validates and converts values from the command line string or Python into a Python dict. - All key-value pairs must be separated by one semicolon. - Key and value must be separated by one colon - Converts sequences separeted by dots into a list: list value items must be separated by commas. - Converts numbers to int. Usage >>> @click.option("--param", default=None, type=DictParamType()) ... def command(param): ... ... CLI: command --param='page:1; name:Items; rules:1, 2, three; extra:A,;' Example ------- >>> param_value = 'page:1; name:Items; rules:1, 2, three; extra:A,;' >>> DictParamType().convert(param_value, None, None) {'page': 1, 'name': 'Items', 'rules': [1, 2, 'three'], 'extra': ['A']}` """ name = "dictionary"
[docs] def convert( # pylint: disable=inconsistent-return-statements self, value: Any, param: click.Parameter | None, ctx: click.Context | None, ) -> dict: """Converts CLI value to the dictionary structure. Parameters ---------- value: Any The value to convert. param: (click.Parameter | None) The parameter that is using this type to convert its value. ctx: (click.Context | None) The current context that arrived at this value. Returns ------- dict: The validated and converted dictionary. Raises ------ click.BadParameter: If the validation is failed. """ if isinstance(value, dict): return value try: keyvalue_pairs = value.rstrip(";").split(";") result_dict = {} for pair in keyvalue_pairs: key, value = (item.strip() for item in pair.split(":")) result_dict[key] = value return result_dict except ValueError: self.fail( "All key-value pairs must be separated by one semicolon. " "Key and value must be separated by one colon. " "List value items must be separated by one comma. " f"Key-value: {pair}.", param, ctx, )
[docs] class EnumChoice(click.Choice): """A version of click.Choice specialized for enum types.""" def __init__(self: "EnumChoice", enum: type[Enum], *, case_sensitive: bool = True) -> None: self._enum = enum super().__init__(list(enum.__members__.keys()), case_sensitive=case_sensitive)
[docs] def convert( self: "EnumChoice", value: Any, param: click.Parameter | None, ctx: click.Context | None, ) -> Enum: converted_str = super().convert(value, param, ctx) return self._enum.__members__[converted_str]
[docs] class OutputEnum(Enum): """Options for output format""" yaml = auto() # pylint: disable=invalid-name json = auto() # pylint: disable=invalid-name
[docs] class PartialOption: """Wrap partially specified click.option decorator for convenient reuse.""" def __init__(self: "PartialOption", *param_decls: str, **attrs: Any) -> None: self._partial = partial(click.option, *param_decls, cls=click.Option, **attrs) def __call__(self: "PartialOption", *param_decls: str, **attrs: Any) -> Callable[[FC], FC]: return self._partial(*param_decls, **attrs)
config = PartialOption( "--config", type=DictParamType(), help="Estimator configuration parameters", ) data = PartialOption( "--data", type=DictParamType(), help="Dict of magnitudes", ) row_id = PartialOption( "--row-id", type=int, help="ID of object in database table", ) output = PartialOption( "--output", "-o", type=EnumChoice(OutputEnum), help="Output format. Summary table if not specified.", ) name = PartialOption( "--name", type=str, help="Name for a particular DB row", ) algo_name = PartialOption( "--algo-name", type=str, help="Name of associated algorithm", ) class_name = PartialOption( "--class-name", type=str, help="Name of python class to associate to a particular DB object", ) dataset_name = PartialOption( "--dataset-name", type=str, help="Name of associated dataset", ) estimator_name = PartialOption( "--estimator-name", type=str, help="Name of associated estimator", ) catalog_tag_name = PartialOption( "--catalog-tag-name", type=str, help="Name of associated catalog tag", ) filename = PartialOption( "--filename", type=click.Path(), help="Filename for downloaded files", ) model_name = PartialOption( "--model-name", type=str, help="Name of associated model", ) index = PartialOption( "--index", type=int, help="Index of object inside dataset", ) n_objects = PartialOption( "--n-objects", type=int, help="Number of object in dataset", ) path = PartialOption( "--path", type=click.Path(), help="Name for a particular DB row", ) validate_file = PartialOption( "--validate-file", is_flag=True, default=False, help="Validate files when uploading", )