ktr-cli 0.1.0__py3-none-any.whl
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.
- kantree_cli/__init__.py +3 -0
- kantree_cli/cli.py +7922 -0
- kantree_cli/core/__init__.py +1 -0
- kantree_cli/core/client.py +230 -0
- kantree_cli/core/config.py +226 -0
- kantree_cli/core/context.py +141 -0
- kantree_cli/core/errors.py +32 -0
- kantree_cli/core/output.py +64 -0
- kantree_cli/core/response.py +86 -0
- kantree_cli/services/__init__.py +1 -0
- kantree_cli/services/cards.py +726 -0
- kantree_cli/services/importers.py +304 -0
- kantree_cli/services/kql.py +43 -0
- kantree_cli/services/resolver.py +236 -0
- kantree_cli/services/search.py +67 -0
- kantree_cli/services/views.py +124 -0
- kantree_cli/services/webhooks.py +120 -0
- kantree_cli/services/workspaces.py +1300 -0
- ktr_cli-0.1.0.dist-info/METADATA +173 -0
- ktr_cli-0.1.0.dist-info/RECORD +22 -0
- ktr_cli-0.1.0.dist-info/WHEEL +4 -0
- ktr_cli-0.1.0.dist-info/entry_points.txt +4 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
from typing import Any, Callable
|
|
2
|
+
|
|
3
|
+
from kantree_cli.core.errors import ValidationError
|
|
4
|
+
|
|
5
|
+
JsonObject = dict[str, Any]
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def extract_object_list(
|
|
9
|
+
payload: Any,
|
|
10
|
+
*,
|
|
11
|
+
context: str,
|
|
12
|
+
preferred_keys: tuple[str, ...],
|
|
13
|
+
) -> list[JsonObject]:
|
|
14
|
+
if isinstance(payload, list):
|
|
15
|
+
return normalize_object_list(payload, context=context)
|
|
16
|
+
|
|
17
|
+
if isinstance(payload, dict):
|
|
18
|
+
for key in preferred_keys:
|
|
19
|
+
maybe_list = payload.get(key)
|
|
20
|
+
if isinstance(maybe_list, list):
|
|
21
|
+
return normalize_object_list(maybe_list, context=context)
|
|
22
|
+
|
|
23
|
+
raise ValidationError(f"Unexpected response payload for {context}: expected a list.")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def extract_object(
|
|
27
|
+
payload: Any,
|
|
28
|
+
*,
|
|
29
|
+
context: str,
|
|
30
|
+
preferred_keys: tuple[str, ...],
|
|
31
|
+
require_id_field: bool = True,
|
|
32
|
+
object_check: Callable[[JsonObject], bool] | None = None,
|
|
33
|
+
) -> JsonObject:
|
|
34
|
+
if isinstance(payload, dict):
|
|
35
|
+
if require_id_field and "id" in payload:
|
|
36
|
+
return payload
|
|
37
|
+
if object_check is not None and object_check(payload):
|
|
38
|
+
return payload
|
|
39
|
+
for key in preferred_keys:
|
|
40
|
+
maybe_object = payload.get(key)
|
|
41
|
+
if isinstance(maybe_object, dict):
|
|
42
|
+
return maybe_object
|
|
43
|
+
|
|
44
|
+
raise ValidationError(f"Unexpected response payload for {context}: expected an object.")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def normalize_object_list(items: list[Any], *, context: str) -> list[JsonObject]:
|
|
48
|
+
normalized: list[JsonObject] = []
|
|
49
|
+
for index, item in enumerate(items):
|
|
50
|
+
if not isinstance(item, dict):
|
|
51
|
+
raise ValidationError(f"Unexpected item type at index {index} for {context}.")
|
|
52
|
+
normalized.append(item)
|
|
53
|
+
return normalized
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def next_page_header_value(headers: dict[str, str]) -> int | None:
|
|
57
|
+
raw_next_page = headers.get("X-Kantree-NextPage")
|
|
58
|
+
if raw_next_page is None:
|
|
59
|
+
raw_next_page = headers.get("x-kantree-nextpage")
|
|
60
|
+
if raw_next_page is None:
|
|
61
|
+
return None
|
|
62
|
+
|
|
63
|
+
normalized = raw_next_page.strip()
|
|
64
|
+
if not normalized:
|
|
65
|
+
return None
|
|
66
|
+
|
|
67
|
+
parsed = _parse_int(normalized)
|
|
68
|
+
if parsed is None or parsed < 1:
|
|
69
|
+
return None
|
|
70
|
+
return parsed
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _parse_int(value: Any) -> int | None:
|
|
74
|
+
if isinstance(value, bool):
|
|
75
|
+
return None
|
|
76
|
+
if isinstance(value, int):
|
|
77
|
+
return value
|
|
78
|
+
if isinstance(value, str):
|
|
79
|
+
stripped = value.strip()
|
|
80
|
+
if not stripped:
|
|
81
|
+
return None
|
|
82
|
+
try:
|
|
83
|
+
return int(stripped)
|
|
84
|
+
except ValueError:
|
|
85
|
+
return None
|
|
86
|
+
return None
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Service helpers for command-level workflows."""
|