Coverage for volexport/cli_utils.py: 79%
65 statements
« prev ^ index » next coverage.py v7.10.7, created at 2025-09-28 12:48 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2025-09-28 12:48 +0000
1import click
2import json
3import yaml
4import pprint
5import functools
6from decimal import Decimal
7from typing import Optional
8from logging import getLogger
10_log = getLogger(__name__)
13def set_verbose(verbose: Optional[bool]):
14 from logging import basicConfig
16 fmt = "%(asctime)s %(levelname)s %(name)s %(message)s"
17 level = "INFO"
18 if verbose:
19 level = "DEBUG"
20 elif verbose is not None:
21 level = "WARNING"
22 basicConfig(level=level, format=fmt)
25def verbose_option(func):
26 """set log level:
28 - --verbose -> DEBUG
29 - --quiet -> WARNING
30 - (no option) -> INFO
31 """
33 @functools.wraps(func)
34 def wrap(verbose, *args, **kwargs):
35 set_verbose(verbose)
36 return func(*args, **kwargs)
38 return click.option("--verbose/--quiet", default=None, help="log level")(wrap)
41def output_format(func):
42 """set output format:
44 - --format json -> JSON
45 - --format pjson -> indented JSON
46 - --format yaml -> YAML
47 - --format pprint -> python pprint.pprint()
48 """
50 @click.option("--format", type=click.Choice(["json", "pjson", "yaml", "pprint"]), default="json", show_default=True)
51 @functools.wraps(func)
52 def wrap(format, *args, **kwargs):
53 res = func(*args, **kwargs)
54 if format == "json":
55 click.echo(json.dumps(res, ensure_ascii=False))
56 elif format == "pjson":
57 click.echo(json.dumps(res, indent=2, ensure_ascii=False))
58 elif format == "yaml":
59 click.echo(yaml.dump(res, allow_unicode=True, encoding="utf-8"))
60 elif format == "pprint": 60 ↛ 63line 60 didn't jump to line 63 because the condition on line 60 was always true
61 click.echo(pprint.pformat(res))
62 else:
63 raise NotImplementedError(f"unknown format: {format}")
65 return wrap
68class SizeType(click.ParamType):
69 """size parameter
71 - xxxS (sector) -> x512
72 - xxxK (kilo) -> x1024
73 - xxxM (mega) -> x1024x1024
74 - xxxG (giga) -> x1024x1024x1024
75 - xxxT (tera) -> x1024x1024x1024x1024
76 - xxxP (peta) -> x1024x1024x1024x1024x1024
77 - xxxE (exa) -> x1024x1024x1024x1024x1024x1024
78 """
80 name = "size"
82 def convert(self, value: str, param, ctx):
83 factor = Decimal(1)
84 if value.endswith("S"): 84 ↛ 85line 84 didn't jump to line 85 because the condition on line 84 was never true
85 factor = Decimal(512) # sector
86 value = value.removesuffix("S")
87 if value.endswith("K"): 87 ↛ 88line 87 didn't jump to line 88 because the condition on line 87 was never true
88 factor = factor * Decimal(1024)
89 value = value.removesuffix("K")
90 elif value.endswith("M"):
91 factor = factor * Decimal(1024**2)
92 value = value.removesuffix("M")
93 elif value.endswith("G"):
94 factor = factor * Decimal(1024**3)
95 value = value.removesuffix("G")
96 elif value.endswith("T"): 96 ↛ 99line 96 didn't jump to line 99 because the condition on line 96 was always true
97 factor = factor * Decimal(1024**4)
98 value = value.removesuffix("T")
99 elif value.endswith("P"):
100 factor = factor * Decimal(1024**5)
101 value = value.removesuffix("P")
102 elif value.endswith("E"):
103 factor = factor * Decimal(1024**6)
104 value = value.removesuffix("E")
105 return int(Decimal(value) * factor)