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.
@@ -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