devnomads-cli 0.5.1__tar.gz → 0.5.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (20) hide show
  1. {devnomads_cli-0.5.1 → devnomads_cli-0.5.2}/PKG-INFO +1 -1
  2. {devnomads_cli-0.5.1 → devnomads_cli-0.5.2}/devnomads_cli.egg-info/PKG-INFO +1 -1
  3. {devnomads_cli-0.5.1 → devnomads_cli-0.5.2}/dncli.py +33 -5
  4. {devnomads_cli-0.5.1 → devnomads_cli-0.5.2}/pyproject.toml +1 -1
  5. {devnomads_cli-0.5.1 → devnomads_cli-0.5.2}/tests/test_helpers.py +34 -3
  6. {devnomads_cli-0.5.1 → devnomads_cli-0.5.2}/LICENSE +0 -0
  7. {devnomads_cli-0.5.1 → devnomads_cli-0.5.2}/README.md +0 -0
  8. {devnomads_cli-0.5.1 → devnomads_cli-0.5.2}/devnomads_cli.egg-info/SOURCES.txt +0 -0
  9. {devnomads_cli-0.5.1 → devnomads_cli-0.5.2}/devnomads_cli.egg-info/dependency_links.txt +0 -0
  10. {devnomads_cli-0.5.1 → devnomads_cli-0.5.2}/devnomads_cli.egg-info/entry_points.txt +0 -0
  11. {devnomads_cli-0.5.1 → devnomads_cli-0.5.2}/devnomads_cli.egg-info/requires.txt +0 -0
  12. {devnomads_cli-0.5.1 → devnomads_cli-0.5.2}/devnomads_cli.egg-info/top_level.txt +0 -0
  13. {devnomads_cli-0.5.1 → devnomads_cli-0.5.2}/setup.cfg +0 -0
  14. {devnomads_cli-0.5.1 → devnomads_cli-0.5.2}/tests/test_cert.py +0 -0
  15. {devnomads_cli-0.5.1 → devnomads_cli-0.5.2}/tests/test_cli.py +0 -0
  16. {devnomads_cli-0.5.1 → devnomads_cli-0.5.2}/tests/test_config.py +0 -0
  17. {devnomads_cli-0.5.1 → devnomads_cli-0.5.2}/tests/test_generate.py +0 -0
  18. {devnomads_cli-0.5.1 → devnomads_cli-0.5.2}/tests/test_generated_cli.py +0 -0
  19. {devnomads_cli-0.5.1 → devnomads_cli-0.5.2}/tests/test_hook.py +0 -0
  20. {devnomads_cli-0.5.1 → devnomads_cli-0.5.2}/tests/test_transfer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devnomads-cli
3
- Version: 0.5.1
3
+ Version: 0.5.2
4
4
  Summary: Manage your DevNomads services from the command line
5
5
  Author-email: DevNomads <support@devnomads.nl>
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devnomads-cli
3
- Version: 0.5.1
3
+ Version: 0.5.2
4
4
  Summary: Manage your DevNomads services from the command line
5
5
  Author-email: DevNomads <support@devnomads.nl>
6
6
  License: MIT
@@ -211,16 +211,44 @@ def render(
211
211
  out_console.print(str(data), soft_wrap=True)
212
212
 
213
213
 
214
+ def _summarize_item(item: dict[str, Any]) -> str:
215
+ """Compact one-line ``key=value`` view of an object's scalar fields for a
216
+ table cell. Nested lists/objects collapse to a count so the line stays
217
+ short; None and empty fields are dropped."""
218
+
219
+ parts = []
220
+ for key, val in item.items():
221
+ if val is None or val == "":
222
+ continue
223
+ if isinstance(val, bool):
224
+ parts.append(f"{key}={'yes' if val else 'no'}")
225
+ elif isinstance(val, dict):
226
+ if val:
227
+ parts.append(f"{key}={{{len(val)}}}")
228
+ elif isinstance(val, list):
229
+ if val:
230
+ parts.append(f"{key}=[{len(val)}]")
231
+ else:
232
+ parts.append(f"{key}={val}")
233
+ return " ".join(parts)
234
+
235
+
214
236
  def _cell(value: Any) -> str:
215
237
  if value is None:
216
238
  return ""
217
239
  if isinstance(value, bool):
218
240
  return "yes" if value else "no"
219
- if isinstance(value, list) and not any(
220
- isinstance(item, (dict, list)) for item in value
221
- ):
222
- return ", ".join(str(item) for item in value)
223
- if isinstance(value, (dict, list)):
241
+ if isinstance(value, dict):
242
+ return _summarize_item(value)
243
+ if isinstance(value, list):
244
+ if not value:
245
+ return ""
246
+ if all(isinstance(item, dict) for item in value):
247
+ # a list of objects (instances, mailboxes, ips, ...) -> one
248
+ # readable line per item instead of an unreadable JSON blob.
249
+ return "\n".join(_summarize_item(item) for item in value)
250
+ if not any(isinstance(item, (dict, list)) for item in value):
251
+ return ", ".join(str(item) for item in value)
224
252
  return json.dumps(value)
225
253
  return str(value)
226
254
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "devnomads-cli"
3
- version = "0.5.1"
3
+ version = "0.5.2"
4
4
  description = "Manage your DevNomads services from the command line"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -167,11 +167,42 @@ def test_cell():
167
167
  assert _cell(True) == "yes"
168
168
  assert _cell(False) == "no"
169
169
  assert _cell(42) == "42"
170
- assert _cell({"a": 1}) == '{"a": 1}'
171
- # scalar lists read as comma-separated values, nested ones stay JSON
170
+ # a bare object renders as a compact key=value summary
171
+ assert _cell({"a": 1}) == "a=1"
172
+ # scalar lists read as comma-separated values
172
173
  assert _cell(["instance_7:80", "instance_8:80"]) == "instance_7:80, instance_8:80"
173
174
  assert _cell([]) == ""
174
- assert _cell([{"a": 1}]) == '[{"a": 1}]'
175
+
176
+
177
+ def test_cell_list_of_objects_is_summarized():
178
+ # one readable line per item, not a raw JSON blob
179
+ ips = [
180
+ {"type": "v4", "address": "185.223.163.238"},
181
+ {"type": "v6", "address": "2a10:8c80:0:138::1"},
182
+ ]
183
+ assert _cell(ips) == (
184
+ "type=v4 address=185.223.163.238\ntype=v6 address=2a10:8c80:0:138::1"
185
+ )
186
+
187
+
188
+ def test_cell_summary_drops_empty_and_counts_nested():
189
+ item = {
190
+ "id": 7,
191
+ "image": "geleijn-it/website",
192
+ "ended_at": None,
193
+ "has_pending_changes": 0,
194
+ "volumes": [{"id": 10}],
195
+ "meta": {},
196
+ }
197
+ # None dropped, 0 kept, non-empty nested list shown as a count, empty dict dropped
198
+ assert (
199
+ _cell([item])
200
+ == "id=7 image=geleijn-it/website has_pending_changes=0 volumes=[1]"
201
+ )
202
+
203
+
204
+ def test_cell_mixed_list_stays_json():
205
+ assert _cell([{"a": 1}, "scalar"]) == '[{"a": 1}, "scalar"]'
175
206
 
176
207
 
177
208
  def test_flatten_row_merges_nested_objects():
File without changes
File without changes
File without changes