Coverage for /usr/local/lib/python3.10/site-packages/opal_common-0.0.0-py3.10.egg/opal_common/confi/cli.py: 12%

37 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-10-10 11:54 +0000

1from typing import Callable, Dict, List 

2 

3import click 

4import typer 

5from opal_common.confi.types import ConfiEntry 

6from typer.main import Typer 

7 

8 

9def create_click_cli(confi_entries: Dict[str, ConfiEntry], callback: Callable): 

10 cli = callback 

11 for key, entry in confi_entries.items(): 

12 option_kwargs = entry.get_cli_option_kwargs() 

13 # make the key fit cmd-style (i.e. kebab-case) 

14 adjusted_key = entry.key.lower().replace("_", "-") 

15 keys = [f"--{adjusted_key}", entry.key] 

16 # add flag if given (i.e '-t' option) 

17 if entry.flags is not None: 

18 keys.extend(entry.flags) 

19 # use lower case as the key, and as is (no prefix, and no case altering) as the name 

20 # see https://click.palletsprojects.com/en/7.x/options/#name-your-options 

21 cli = click.option(*keys, **option_kwargs)(cli) 

22 # pass context 

23 cli = click.pass_context(cli) 

24 # wrap in group 

25 cli = click.group(invoke_without_command=True)(cli) 

26 return cli 

27 

28 

29def get_cli_object_for_config_objects( 

30 config_objects: list, 

31 typer_app: Typer = None, 

32 help: str = None, 

33 on_start: Callable = None, 

34): 

35 # callback to save CLI results back to objects 

36 def callback(ctx, **kwargs): 

37 if callable(on_start): 

38 on_start(ctx, **kwargs) 

39 

40 for key, value in kwargs.items(): 

41 # find the confi-object which the key belongs to and ... 

42 for config_obj in config_objects: 

43 if key in config_obj.entries: 

44 # ... update that object with the new value 

45 setattr(config_obj, key, value) 

46 config_obj._entries[key].value = value 

47 

48 if help is not None: 

49 callback.__doc__ = help 

50 # Create a merged config-entires map 

51 entries = {} 

52 for config_obj in config_objects: 

53 entries.update(config_obj.entries) 

54 # convert to a click-cli group 

55 click_group = create_click_cli(entries, callback) 

56 # add the typer app into our click group 

57 if typer_app is not None: 

58 typer_click_object = typer.main.get_command(typer_app) 

59 # add the app commands directly to out click app 

60 for name, cmd in typer_click_object.commands.items(): 

61 click_group.add_command(cmd, name) 

62 return click_group