Coverage for /Users/OORDCOR/Documents/code/bump-my-version/bumpversion/show.py: 0%
71 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-10 08:09 -0600
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-10 08:09 -0600
1"""Functions for displaying information about the version."""
2import dataclasses
3from io import StringIO
4from pprint import pprint
5from typing import Any, Optional
7from bumpversion.bump import get_next_version
8from bumpversion.config import Config
9from bumpversion.exceptions import BadInputError
10from bumpversion.ui import print_error, print_info
11from bumpversion.utils import get_context, recursive_sort_dict
14def output_default(value: dict) -> None:
15 """Output the value with key=value or just value if there is only one item."""
16 if len(value) == 1:
17 print_info(next(iter(value.values())))
18 else:
19 buffer = StringIO()
20 pprint(value, stream=buffer, sort_dicts=True) # noqa: T203
21 print_info(buffer.getvalue())
24def output_yaml(value: dict) -> None:
25 """Output the value as yaml."""
26 from bumpversion.yaml_dump import dump
28 print_info(dump(recursive_sort_dict(value)))
31def output_json(value: dict) -> None:
32 """Output the value as json."""
33 import json
35 def default_encoder(obj: Any) -> str:
36 if dataclasses.is_dataclass(obj):
37 return str(obj)
38 elif isinstance(obj, type):
39 return obj.__name__
40 raise TypeError(f"Object of type {type(obj), str(obj)} is not JSON serializable")
42 print_info(json.dumps(value, sort_keys=True, indent=2, default=default_encoder))
45OUTPUTTERS = {
46 "yaml": output_yaml,
47 "json": output_json,
48 "default": output_default,
49}
52def resolve_name(obj: Any, name: str, default: Any = None, err_on_missing: bool = False) -> Any:
53 """
54 Get a key or attr ``name`` from obj or default value.
56 Copied and modified from Django Template variable resolutions
58 Resolution methods:
60 - Mapping key lookup
61 - Attribute lookup
62 - Sequence index
64 Args:
65 obj: The object to access
66 name: A dotted name to the value, such as ``mykey.0.name``
67 default: If the name cannot be resolved from the object, return this value
68 err_on_missing: Raise a `BadInputError` if the name cannot be resolved
70 Returns:
71 The value at the resolved name or the default value.
73 Raises:
74 BadInputError: If we cannot resolve the name and `err_on_missing` is `True`
76 # noqa: DAR401
77 """
78 lookups = name.split(".")
79 current = obj
80 try: # catch-all for unexpected failures
81 for bit in lookups:
82 try: # dictionary lookup
83 current = current[bit]
84 # ValueError/IndexError are for numpy.array lookup on
85 # numpy < 1.9 and 1.9+ respectively
86 except (TypeError, AttributeError, KeyError, ValueError, IndexError):
87 try: # attribute lookup
88 current = getattr(current, bit)
89 except (TypeError, AttributeError):
90 # Reraise if the exception was raised by a @property
91 if bit in dir(current):
92 raise
93 try: # list-index lookup
94 current = current[int(bit)]
95 except (
96 IndexError, # list index out of range
97 ValueError, # invalid literal for int()
98 KeyError, # current is a dict without `int(bit)` key
99 TypeError,
100 ): # un-subscript-able object
101 return default
102 return current
103 except Exception as e: # noqa: BLE001 # pragma: no cover
104 if err_on_missing:
105 raise BadInputError(f"Could not resolve '{name}'") from e
106 else:
107 return default
110def log_list(config: Config, version_part: Optional[str], new_version: Optional[str]) -> None:
111 """Output configuration with new version."""
112 ctx = get_context(config)
113 if version_part:
114 version = config.version_config.parse(config.current_version)
115 next_version = get_next_version(version, config, version_part, new_version)
116 next_version_str = config.version_config.serialize(next_version, ctx)
118 print_info(f"new_version={next_version_str}")
120 config_dict = recursive_sort_dict(config.model_dump(exclude={"scm_info", "parts"}))
121 for key, value in config_dict.items():
122 print_info(f"{key}={value}")
125def do_show(*args, config: Config, format_: str = "default", increment: Optional[str] = None) -> None:
126 """Show current version or configuration information."""
127 config_dict = config.model_dump()
128 ctx = get_context(config)
130 if increment:
131 version = config.version_config.parse(config.current_version)
132 next_version = get_next_version(version, config, increment, None)
133 next_version_str = config.version_config.serialize(next_version, ctx)
134 config_dict["new_version"] = next_version_str
136 try:
137 if "all" in args or not args:
138 show_items = config_dict
139 else:
140 show_items = {key: resolve_name(config_dict, key) for key in args}
142 OUTPUTTERS.get(format_, OUTPUTTERS["default"])(show_items)
143 except BadInputError as e:
144 print_error(e.message)