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,124 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from kantree_cli.core.client import KantreeClient
|
|
4
|
+
from kantree_cli.core.errors import ValidationError
|
|
5
|
+
from kantree_cli.core.response import extract_object, extract_object_list
|
|
6
|
+
|
|
7
|
+
JsonObject = dict[str, Any]
|
|
8
|
+
VIEW_MODES = ("kanban", "list", "table", "calendar", "timeline")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def list_views(client: KantreeClient) -> list[JsonObject]:
|
|
12
|
+
payload = client.get_json("/views")
|
|
13
|
+
return extract_object_list(
|
|
14
|
+
payload,
|
|
15
|
+
context="`GET /views`",
|
|
16
|
+
preferred_keys=("views", "data", "items", "results"),
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def get_view(client: KantreeClient, view_id: int) -> JsonObject:
|
|
21
|
+
payload = client.get_json(f"/views/{view_id}")
|
|
22
|
+
return extract_object(
|
|
23
|
+
payload,
|
|
24
|
+
context=f"`GET /views/{view_id}`",
|
|
25
|
+
preferred_keys=("view", "data", "item", "result"),
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def create_view(
|
|
30
|
+
client: KantreeClient,
|
|
31
|
+
*,
|
|
32
|
+
name: str,
|
|
33
|
+
mode: str | None = None,
|
|
34
|
+
filter_text: str | None = None,
|
|
35
|
+
include_archived: bool | None = None,
|
|
36
|
+
include_descendants: bool | None = None,
|
|
37
|
+
) -> JsonObject:
|
|
38
|
+
payload = _view_payload(
|
|
39
|
+
name=name,
|
|
40
|
+
mode=mode,
|
|
41
|
+
filter_text=filter_text,
|
|
42
|
+
include_archived=include_archived,
|
|
43
|
+
include_descendants=include_descendants,
|
|
44
|
+
)
|
|
45
|
+
response = client.request(method="POST", path="/views", json_body=payload)
|
|
46
|
+
return extract_object(
|
|
47
|
+
response.data,
|
|
48
|
+
context="`POST /views`",
|
|
49
|
+
preferred_keys=("view", "data", "item", "result"),
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def update_view(
|
|
54
|
+
client: KantreeClient,
|
|
55
|
+
*,
|
|
56
|
+
view_id: int,
|
|
57
|
+
name: str | None = None,
|
|
58
|
+
mode: str | None = None,
|
|
59
|
+
filter_text: str | None = None,
|
|
60
|
+
clear_filter: bool = False,
|
|
61
|
+
include_archived: bool | None = None,
|
|
62
|
+
include_descendants: bool | None = None,
|
|
63
|
+
) -> JsonObject:
|
|
64
|
+
if filter_text is not None and clear_filter:
|
|
65
|
+
raise ValidationError("Use either `--filter` or `--clear-filter`, not both.")
|
|
66
|
+
payload = _view_payload(
|
|
67
|
+
name=name,
|
|
68
|
+
mode=mode,
|
|
69
|
+
filter_text=None if clear_filter else filter_text,
|
|
70
|
+
include_filter=filter_text is not None or clear_filter,
|
|
71
|
+
include_archived=include_archived,
|
|
72
|
+
include_descendants=include_descendants,
|
|
73
|
+
)
|
|
74
|
+
if not payload:
|
|
75
|
+
raise ValidationError(
|
|
76
|
+
"View update requires at least one of `--name`, `--mode`, `--filter`, "
|
|
77
|
+
"`--clear-filter`, `--include-archived`, `--no-include-archived`, "
|
|
78
|
+
"`--include-descendants`, or `--no-include-descendants`."
|
|
79
|
+
)
|
|
80
|
+
response = client.request(method="PUT", path=f"/views/{view_id}", json_body=payload)
|
|
81
|
+
return extract_object(
|
|
82
|
+
response.data,
|
|
83
|
+
context=f"`PUT /views/{view_id}`",
|
|
84
|
+
preferred_keys=("view", "data", "item", "result"),
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def delete_view(client: KantreeClient, *, view_id: int) -> Any:
|
|
89
|
+
response = client.request(method="DELETE", path=f"/views/{view_id}")
|
|
90
|
+
return response.data
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def view_summary(view: JsonObject) -> JsonObject:
|
|
94
|
+
summary: JsonObject = {
|
|
95
|
+
"id": view.get("id"),
|
|
96
|
+
"name": view.get("name", view.get("title")),
|
|
97
|
+
}
|
|
98
|
+
for key in ("mode", "filter", "include_archived", "include_descendants"):
|
|
99
|
+
if key in view:
|
|
100
|
+
summary[key] = view.get(key)
|
|
101
|
+
return summary
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _view_payload(
|
|
105
|
+
*,
|
|
106
|
+
name: str | None = None,
|
|
107
|
+
mode: str | None = None,
|
|
108
|
+
filter_text: str | None = None,
|
|
109
|
+
include_filter: bool = False,
|
|
110
|
+
include_archived: bool | None = None,
|
|
111
|
+
include_descendants: bool | None = None,
|
|
112
|
+
) -> JsonObject:
|
|
113
|
+
payload: JsonObject = {}
|
|
114
|
+
if name is not None:
|
|
115
|
+
payload["name"] = name
|
|
116
|
+
if mode is not None:
|
|
117
|
+
payload["mode"] = mode
|
|
118
|
+
if include_filter or filter_text is not None:
|
|
119
|
+
payload["filter"] = filter_text
|
|
120
|
+
if include_archived is not None:
|
|
121
|
+
payload["include_archived"] = include_archived
|
|
122
|
+
if include_descendants is not None:
|
|
123
|
+
payload["include_descendants"] = include_descendants
|
|
124
|
+
return payload
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from kantree_cli.core.client import KantreeClient
|
|
4
|
+
from kantree_cli.core.errors import ValidationError
|
|
5
|
+
from kantree_cli.core.response import (
|
|
6
|
+
extract_object,
|
|
7
|
+
extract_object_list,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
JsonObject = dict[str, Any]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def list_workspace_webhooks(client: KantreeClient, workspace_id: int) -> list[JsonObject]:
|
|
14
|
+
payload = client.get_json(f"/projects/{workspace_id}/webhooks")
|
|
15
|
+
return extract_object_list(
|
|
16
|
+
payload,
|
|
17
|
+
context=f"`GET /projects/{workspace_id}/webhooks`",
|
|
18
|
+
preferred_keys=("webhooks", "data", "items", "results"),
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def get_workspace_webhook(
|
|
23
|
+
client: KantreeClient,
|
|
24
|
+
*,
|
|
25
|
+
workspace_id: int,
|
|
26
|
+
webhook_id: int,
|
|
27
|
+
) -> JsonObject:
|
|
28
|
+
payload = client.get_json(f"/projects/{workspace_id}/webhooks/{webhook_id}")
|
|
29
|
+
return extract_object(
|
|
30
|
+
payload,
|
|
31
|
+
context=f"`GET /projects/{workspace_id}/webhooks/{webhook_id}`",
|
|
32
|
+
preferred_keys=("webhook", "data", "item", "result"),
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def create_workspace_webhook(
|
|
37
|
+
client: KantreeClient,
|
|
38
|
+
*,
|
|
39
|
+
workspace_id: int,
|
|
40
|
+
url: str,
|
|
41
|
+
events: list[str],
|
|
42
|
+
active: bool | None = None,
|
|
43
|
+
card_object_only: bool | None = None,
|
|
44
|
+
card_object_only_as_array: bool | None = None,
|
|
45
|
+
) -> JsonObject:
|
|
46
|
+
payload: JsonObject = {
|
|
47
|
+
"url": url,
|
|
48
|
+
"events": events,
|
|
49
|
+
}
|
|
50
|
+
if active is not None:
|
|
51
|
+
payload["active"] = active
|
|
52
|
+
if card_object_only is not None:
|
|
53
|
+
payload["card_object_only"] = card_object_only
|
|
54
|
+
if card_object_only_as_array is not None:
|
|
55
|
+
payload["card_object_only_as_array"] = card_object_only_as_array
|
|
56
|
+
|
|
57
|
+
response = client.request(
|
|
58
|
+
method="POST",
|
|
59
|
+
path=f"/projects/{workspace_id}/webhooks",
|
|
60
|
+
json_body=payload,
|
|
61
|
+
)
|
|
62
|
+
return extract_object(
|
|
63
|
+
response.data,
|
|
64
|
+
context=f"`POST /projects/{workspace_id}/webhooks`",
|
|
65
|
+
preferred_keys=("webhook", "data", "item", "result"),
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def update_workspace_webhook(
|
|
70
|
+
client: KantreeClient,
|
|
71
|
+
*,
|
|
72
|
+
workspace_id: int,
|
|
73
|
+
webhook_id: int,
|
|
74
|
+
url: str | None = None,
|
|
75
|
+
events: list[str] | None = None,
|
|
76
|
+
active: bool | None = None,
|
|
77
|
+
card_object_only: bool | None = None,
|
|
78
|
+
card_object_only_as_array: bool | None = None,
|
|
79
|
+
) -> JsonObject:
|
|
80
|
+
payload: JsonObject = {}
|
|
81
|
+
if url is not None:
|
|
82
|
+
payload["url"] = url
|
|
83
|
+
if events is not None:
|
|
84
|
+
payload["events"] = events
|
|
85
|
+
if active is not None:
|
|
86
|
+
payload["active"] = active
|
|
87
|
+
if card_object_only is not None:
|
|
88
|
+
payload["card_object_only"] = card_object_only
|
|
89
|
+
if card_object_only_as_array is not None:
|
|
90
|
+
payload["card_object_only_as_array"] = card_object_only_as_array
|
|
91
|
+
if not payload:
|
|
92
|
+
raise ValidationError(
|
|
93
|
+
"Webhook update requires at least one field: `--url`, `--events`, `--active`/`--inactive`, "
|
|
94
|
+
"`--card-object-only`/`--no-card-object-only`, or "
|
|
95
|
+
"`--card-object-only-as-array`/`--no-card-object-only-as-array`."
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
response = client.request(
|
|
99
|
+
method="PUT",
|
|
100
|
+
path=f"/projects/{workspace_id}/webhooks/{webhook_id}",
|
|
101
|
+
json_body=payload,
|
|
102
|
+
)
|
|
103
|
+
return extract_object(
|
|
104
|
+
response.data,
|
|
105
|
+
context=f"`PUT /projects/{workspace_id}/webhooks/{webhook_id}`",
|
|
106
|
+
preferred_keys=("webhook", "data", "item", "result"),
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def delete_workspace_webhook(
|
|
111
|
+
client: KantreeClient,
|
|
112
|
+
*,
|
|
113
|
+
workspace_id: int,
|
|
114
|
+
webhook_id: int,
|
|
115
|
+
) -> Any:
|
|
116
|
+
response = client.request(
|
|
117
|
+
method="DELETE",
|
|
118
|
+
path=f"/projects/{workspace_id}/webhooks/{webhook_id}",
|
|
119
|
+
)
|
|
120
|
+
return response.data
|