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