sinatra-dev 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.
- sinatra_dev/__init__.py +71 -0
- sinatra_dev/_client.py +391 -0
- sinatra_dev/_errors.py +53 -0
- sinatra_dev/_generated/__init__.py +8 -0
- sinatra_dev/_generated/api/__init__.py +1 -0
- sinatra_dev/_generated/api/me/__init__.py +1 -0
- sinatra_dev/_generated/api/me/me_get.py +156 -0
- sinatra_dev/_generated/api/me/me_revoke_token.py +173 -0
- sinatra_dev/_generated/api/messages/__init__.py +1 -0
- sinatra_dev/_generated/api/messages/messages_create.py +323 -0
- sinatra_dev/_generated/api/messages/messages_list.py +332 -0
- sinatra_dev/_generated/api/tasks/__init__.py +1 -0
- sinatra_dev/_generated/api/tasks/tasks_create.py +337 -0
- sinatra_dev/_generated/api/tasks/tasks_get.py +202 -0
- sinatra_dev/_generated/api/tasks/tasks_list.py +252 -0
- sinatra_dev/_generated/api/tasks/tasks_stop.py +231 -0
- sinatra_dev/_generated/api/tickets/__init__.py +1 -0
- sinatra_dev/_generated/api/tickets/tickets_delegate.py +273 -0
- sinatra_dev/_generated/api/tickets/tickets_search.py +265 -0
- sinatra_dev/_generated/client.py +280 -0
- sinatra_dev/_generated/errors.py +16 -0
- sinatra_dev/_generated/models/__init__.py +47 -0
- sinatra_dev/_generated/models/create_message_request.py +62 -0
- sinatra_dev/_generated/models/create_message_response.py +62 -0
- sinatra_dev/_generated/models/create_task_request.py +106 -0
- sinatra_dev/_generated/models/create_task_response.py +76 -0
- sinatra_dev/_generated/models/delegate_github_ticket.py +86 -0
- sinatra_dev/_generated/models/delegate_linear_ticket.py +78 -0
- sinatra_dev/_generated/models/delegate_ticket_response.py +62 -0
- sinatra_dev/_generated/models/error.py +168 -0
- sinatra_dev/_generated/models/me.py +86 -0
- sinatra_dev/_generated/models/me_user.py +98 -0
- sinatra_dev/_generated/models/message.py +113 -0
- sinatra_dev/_generated/models/message_list.py +91 -0
- sinatra_dev/_generated/models/pull_request.py +70 -0
- sinatra_dev/_generated/models/stop_task_response.py +62 -0
- sinatra_dev/_generated/models/task.py +201 -0
- sinatra_dev/_generated/models/task_list.py +91 -0
- sinatra_dev/_generated/models/ticket.py +147 -0
- sinatra_dev/_generated/models/ticket_search_result.py +97 -0
- sinatra_dev/_generated/models/ticket_search_result_github.py +77 -0
- sinatra_dev/_generated/models/ticket_search_result_linear.py +79 -0
- sinatra_dev/_generated/models/workspace.py +78 -0
- sinatra_dev/_generated/types.py +54 -0
- sinatra_dev/_retry.py +72 -0
- sinatra_dev/py.typed +0 -0
- sinatra_dev-0.1.0.dist-info/METADATA +184 -0
- sinatra_dev-0.1.0.dist-info/RECORD +50 -0
- sinatra_dev-0.1.0.dist-info/WHEEL +4 -0
- sinatra_dev-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Mapping
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Self, TypeVar, cast
|
|
5
|
+
|
|
6
|
+
from attrs import define as _attrs_define
|
|
7
|
+
from attrs import field as _attrs_field
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from ..models.message import Message
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
T = TypeVar("T", bound="MessageList")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@_attrs_define
|
|
17
|
+
class MessageList:
|
|
18
|
+
"""A page of a task's conversation.
|
|
19
|
+
|
|
20
|
+
Attributes:
|
|
21
|
+
messages (list[Message]): The page's entries, oldest first.
|
|
22
|
+
next_ (None | str): When it isn't `null`, more entries follow: pass it as `after` to get them. `null` on the
|
|
23
|
+
last page.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
messages: list[Message]
|
|
27
|
+
next_: None | str
|
|
28
|
+
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
|
|
29
|
+
|
|
30
|
+
def to_dict(self) -> dict[str, Any]:
|
|
31
|
+
messages = []
|
|
32
|
+
for messages_item_data in self.messages:
|
|
33
|
+
messages_item = messages_item_data.to_dict()
|
|
34
|
+
messages.append(messages_item)
|
|
35
|
+
|
|
36
|
+
next_: None | str
|
|
37
|
+
next_ = self.next_
|
|
38
|
+
|
|
39
|
+
field_dict: dict[str, Any] = {}
|
|
40
|
+
field_dict.update(self.additional_properties)
|
|
41
|
+
field_dict.update(
|
|
42
|
+
{
|
|
43
|
+
"messages": messages,
|
|
44
|
+
"next": next_,
|
|
45
|
+
}
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
return field_dict
|
|
49
|
+
|
|
50
|
+
@classmethod
|
|
51
|
+
def from_dict(cls, src_dict: Mapping[str, Any]) -> Self:
|
|
52
|
+
from ..models.message import Message
|
|
53
|
+
|
|
54
|
+
d = dict(src_dict)
|
|
55
|
+
messages = []
|
|
56
|
+
_messages = d.pop("messages")
|
|
57
|
+
for messages_item_data in _messages:
|
|
58
|
+
messages_item = Message.from_dict(messages_item_data)
|
|
59
|
+
|
|
60
|
+
messages.append(messages_item)
|
|
61
|
+
|
|
62
|
+
def _parse_next_(data: object) -> None | str:
|
|
63
|
+
if data is None:
|
|
64
|
+
return data
|
|
65
|
+
return cast(None | str, data)
|
|
66
|
+
|
|
67
|
+
next_ = _parse_next_(d.pop("next"))
|
|
68
|
+
|
|
69
|
+
message_list = cls(
|
|
70
|
+
messages=messages,
|
|
71
|
+
next_=next_,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
message_list.additional_properties = d
|
|
75
|
+
return message_list
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def additional_keys(self) -> list[str]:
|
|
79
|
+
return list(self.additional_properties.keys())
|
|
80
|
+
|
|
81
|
+
def __getitem__(self, key: str) -> Any:
|
|
82
|
+
return self.additional_properties[key]
|
|
83
|
+
|
|
84
|
+
def __setitem__(self, key: str, value: Any) -> None:
|
|
85
|
+
self.additional_properties[key] = value
|
|
86
|
+
|
|
87
|
+
def __delitem__(self, key: str) -> None:
|
|
88
|
+
del self.additional_properties[key]
|
|
89
|
+
|
|
90
|
+
def __contains__(self, key: str) -> bool:
|
|
91
|
+
return key in self.additional_properties
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Mapping
|
|
4
|
+
from typing import Any, Self, TypeVar
|
|
5
|
+
|
|
6
|
+
from attrs import define as _attrs_define
|
|
7
|
+
from attrs import field as _attrs_field
|
|
8
|
+
|
|
9
|
+
T = TypeVar("T", bound="PullRequest")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@_attrs_define
|
|
13
|
+
class PullRequest:
|
|
14
|
+
"""The pull request a task opened.
|
|
15
|
+
|
|
16
|
+
Attributes:
|
|
17
|
+
url (str): The pull request's address on GitHub.
|
|
18
|
+
merged (bool): `true` once the pull request is merged.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
url: str
|
|
22
|
+
merged: bool
|
|
23
|
+
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
|
|
24
|
+
|
|
25
|
+
def to_dict(self) -> dict[str, Any]:
|
|
26
|
+
url = self.url
|
|
27
|
+
|
|
28
|
+
merged = self.merged
|
|
29
|
+
|
|
30
|
+
field_dict: dict[str, Any] = {}
|
|
31
|
+
field_dict.update(self.additional_properties)
|
|
32
|
+
field_dict.update(
|
|
33
|
+
{
|
|
34
|
+
"url": url,
|
|
35
|
+
"merged": merged,
|
|
36
|
+
}
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
return field_dict
|
|
40
|
+
|
|
41
|
+
@classmethod
|
|
42
|
+
def from_dict(cls, src_dict: Mapping[str, Any]) -> Self:
|
|
43
|
+
d = dict(src_dict)
|
|
44
|
+
url = d.pop("url")
|
|
45
|
+
|
|
46
|
+
merged = d.pop("merged")
|
|
47
|
+
|
|
48
|
+
pull_request = cls(
|
|
49
|
+
url=url,
|
|
50
|
+
merged=merged,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
pull_request.additional_properties = d
|
|
54
|
+
return pull_request
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def additional_keys(self) -> list[str]:
|
|
58
|
+
return list(self.additional_properties.keys())
|
|
59
|
+
|
|
60
|
+
def __getitem__(self, key: str) -> Any:
|
|
61
|
+
return self.additional_properties[key]
|
|
62
|
+
|
|
63
|
+
def __setitem__(self, key: str, value: Any) -> None:
|
|
64
|
+
self.additional_properties[key] = value
|
|
65
|
+
|
|
66
|
+
def __delitem__(self, key: str) -> None:
|
|
67
|
+
del self.additional_properties[key]
|
|
68
|
+
|
|
69
|
+
def __contains__(self, key: str) -> bool:
|
|
70
|
+
return key in self.additional_properties
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Mapping
|
|
4
|
+
from typing import Any, Self, TypeVar
|
|
5
|
+
|
|
6
|
+
from attrs import define as _attrs_define
|
|
7
|
+
from attrs import field as _attrs_field
|
|
8
|
+
|
|
9
|
+
T = TypeVar("T", bound="StopTaskResponse")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@_attrs_define
|
|
13
|
+
class StopTaskResponse:
|
|
14
|
+
"""The stop was accepted.
|
|
15
|
+
|
|
16
|
+
Attributes:
|
|
17
|
+
accepted (bool): Always `true`: the task was told to stop.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
accepted: bool
|
|
21
|
+
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
|
|
22
|
+
|
|
23
|
+
def to_dict(self) -> dict[str, Any]:
|
|
24
|
+
accepted = self.accepted
|
|
25
|
+
|
|
26
|
+
field_dict: dict[str, Any] = {}
|
|
27
|
+
field_dict.update(self.additional_properties)
|
|
28
|
+
field_dict.update(
|
|
29
|
+
{
|
|
30
|
+
"accepted": accepted,
|
|
31
|
+
}
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
return field_dict
|
|
35
|
+
|
|
36
|
+
@classmethod
|
|
37
|
+
def from_dict(cls, src_dict: Mapping[str, Any]) -> Self:
|
|
38
|
+
d = dict(src_dict)
|
|
39
|
+
accepted = d.pop("accepted")
|
|
40
|
+
|
|
41
|
+
stop_task_response = cls(
|
|
42
|
+
accepted=accepted,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
stop_task_response.additional_properties = d
|
|
46
|
+
return stop_task_response
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def additional_keys(self) -> list[str]:
|
|
50
|
+
return list(self.additional_properties.keys())
|
|
51
|
+
|
|
52
|
+
def __getitem__(self, key: str) -> Any:
|
|
53
|
+
return self.additional_properties[key]
|
|
54
|
+
|
|
55
|
+
def __setitem__(self, key: str, value: Any) -> None:
|
|
56
|
+
self.additional_properties[key] = value
|
|
57
|
+
|
|
58
|
+
def __delitem__(self, key: str) -> None:
|
|
59
|
+
del self.additional_properties[key]
|
|
60
|
+
|
|
61
|
+
def __contains__(self, key: str) -> bool:
|
|
62
|
+
return key in self.additional_properties
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import datetime
|
|
4
|
+
from collections.abc import Mapping
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Self, TypeVar, cast
|
|
6
|
+
|
|
7
|
+
from attrs import define as _attrs_define
|
|
8
|
+
from attrs import field as _attrs_field
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from ..models.pull_request import PullRequest
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
T = TypeVar("T", bound="Task")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@_attrs_define
|
|
18
|
+
class Task:
|
|
19
|
+
"""A task: one piece of work Sinatra does, from any source.
|
|
20
|
+
|
|
21
|
+
Attributes:
|
|
22
|
+
id (str): The task's id. Use it as `taskId` in the task endpoints.
|
|
23
|
+
status (str): Where the task is in its life, such as `pending`, `implementing`, `replied`, `pr_open` or
|
|
24
|
+
`completed`. New statuses can appear, so don't treat the list as closed. See [Raw
|
|
25
|
+
statuses](https://docs.sinatra.dev/docs/getting-started/how-it-works#raw-statuses) for each one.
|
|
26
|
+
source (str): Where the task started: `api` for the CLI, MCP, this API or the dashboard, `linear` or
|
|
27
|
+
`github_issue` for an issue, `slack` or `telegram` for a chat. Other sources can appear, so treat an unknown
|
|
28
|
+
value as a task started elsewhere.
|
|
29
|
+
title (None | str): The task's title. `null` for a task whose issue has no title.
|
|
30
|
+
repo (None | str): `owner/name` of the task's repository. `null` until a repository is chosen.
|
|
31
|
+
pull_request (None | PullRequest): The task's pull request. `null` until one opens.
|
|
32
|
+
queued (bool): `true` while a turn waits because the workspace is already running as many tasks at a time as its
|
|
33
|
+
plan allows. The dashboard shows this as Queued.
|
|
34
|
+
created_at (datetime.datetime): When the task was created.
|
|
35
|
+
last_activity_at (datetime.datetime | None): When the task last did something. `null` if it hasn't yet.
|
|
36
|
+
url (None | str): The task's page in the Sinatra dashboard, where anyone in the workspace can follow it. On a
|
|
37
|
+
task started from the CLI, MCP, API or dashboard they can reply there too.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
id: str
|
|
41
|
+
status: str
|
|
42
|
+
source: str
|
|
43
|
+
title: None | str
|
|
44
|
+
repo: None | str
|
|
45
|
+
pull_request: None | PullRequest
|
|
46
|
+
queued: bool
|
|
47
|
+
created_at: datetime.datetime
|
|
48
|
+
last_activity_at: datetime.datetime | None
|
|
49
|
+
url: None | str
|
|
50
|
+
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
|
|
51
|
+
|
|
52
|
+
def to_dict(self) -> dict[str, Any]:
|
|
53
|
+
from ..models.pull_request import PullRequest
|
|
54
|
+
|
|
55
|
+
id = self.id
|
|
56
|
+
|
|
57
|
+
status = self.status
|
|
58
|
+
|
|
59
|
+
source = self.source
|
|
60
|
+
|
|
61
|
+
title: None | str
|
|
62
|
+
title = self.title
|
|
63
|
+
|
|
64
|
+
repo: None | str
|
|
65
|
+
repo = self.repo
|
|
66
|
+
|
|
67
|
+
pull_request: dict[str, Any] | None
|
|
68
|
+
if isinstance(self.pull_request, PullRequest):
|
|
69
|
+
pull_request = self.pull_request.to_dict()
|
|
70
|
+
else:
|
|
71
|
+
pull_request = self.pull_request
|
|
72
|
+
|
|
73
|
+
queued = self.queued
|
|
74
|
+
|
|
75
|
+
created_at = self.created_at.isoformat()
|
|
76
|
+
|
|
77
|
+
last_activity_at: None | str
|
|
78
|
+
if isinstance(self.last_activity_at, datetime.datetime):
|
|
79
|
+
last_activity_at = self.last_activity_at.isoformat()
|
|
80
|
+
else:
|
|
81
|
+
last_activity_at = self.last_activity_at
|
|
82
|
+
|
|
83
|
+
url: None | str
|
|
84
|
+
url = self.url
|
|
85
|
+
|
|
86
|
+
field_dict: dict[str, Any] = {}
|
|
87
|
+
field_dict.update(self.additional_properties)
|
|
88
|
+
field_dict.update(
|
|
89
|
+
{
|
|
90
|
+
"id": id,
|
|
91
|
+
"status": status,
|
|
92
|
+
"source": source,
|
|
93
|
+
"title": title,
|
|
94
|
+
"repo": repo,
|
|
95
|
+
"pullRequest": pull_request,
|
|
96
|
+
"queued": queued,
|
|
97
|
+
"createdAt": created_at,
|
|
98
|
+
"lastActivityAt": last_activity_at,
|
|
99
|
+
"url": url,
|
|
100
|
+
}
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
return field_dict
|
|
104
|
+
|
|
105
|
+
@classmethod
|
|
106
|
+
def from_dict(cls, src_dict: Mapping[str, Any]) -> Self:
|
|
107
|
+
from ..models.pull_request import PullRequest
|
|
108
|
+
|
|
109
|
+
d = dict(src_dict)
|
|
110
|
+
id = d.pop("id")
|
|
111
|
+
|
|
112
|
+
status = d.pop("status")
|
|
113
|
+
|
|
114
|
+
source = d.pop("source")
|
|
115
|
+
|
|
116
|
+
def _parse_title(data: object) -> None | str:
|
|
117
|
+
if data is None:
|
|
118
|
+
return data
|
|
119
|
+
return cast(None | str, data)
|
|
120
|
+
|
|
121
|
+
title = _parse_title(d.pop("title"))
|
|
122
|
+
|
|
123
|
+
def _parse_repo(data: object) -> None | str:
|
|
124
|
+
if data is None:
|
|
125
|
+
return data
|
|
126
|
+
return cast(None | str, data)
|
|
127
|
+
|
|
128
|
+
repo = _parse_repo(d.pop("repo"))
|
|
129
|
+
|
|
130
|
+
def _parse_pull_request(data: object) -> None | PullRequest:
|
|
131
|
+
if data is None:
|
|
132
|
+
return data
|
|
133
|
+
try:
|
|
134
|
+
if not isinstance(data, dict):
|
|
135
|
+
raise TypeError()
|
|
136
|
+
pull_request_type_0 = PullRequest.from_dict(data)
|
|
137
|
+
|
|
138
|
+
return pull_request_type_0
|
|
139
|
+
except (TypeError, ValueError, AttributeError, KeyError):
|
|
140
|
+
pass
|
|
141
|
+
return cast(None | PullRequest, data)
|
|
142
|
+
|
|
143
|
+
pull_request = _parse_pull_request(d.pop("pullRequest"))
|
|
144
|
+
|
|
145
|
+
queued = d.pop("queued")
|
|
146
|
+
|
|
147
|
+
created_at = datetime.datetime.fromisoformat(d.pop("createdAt"))
|
|
148
|
+
|
|
149
|
+
def _parse_last_activity_at(data: object) -> datetime.datetime | None:
|
|
150
|
+
if data is None:
|
|
151
|
+
return data
|
|
152
|
+
try:
|
|
153
|
+
if not isinstance(data, str):
|
|
154
|
+
raise TypeError()
|
|
155
|
+
last_activity_at_type_0 = datetime.datetime.fromisoformat(data)
|
|
156
|
+
|
|
157
|
+
return last_activity_at_type_0
|
|
158
|
+
except (TypeError, ValueError, AttributeError, KeyError):
|
|
159
|
+
pass
|
|
160
|
+
return cast(datetime.datetime | None, data)
|
|
161
|
+
|
|
162
|
+
last_activity_at = _parse_last_activity_at(d.pop("lastActivityAt"))
|
|
163
|
+
|
|
164
|
+
def _parse_url(data: object) -> None | str:
|
|
165
|
+
if data is None:
|
|
166
|
+
return data
|
|
167
|
+
return cast(None | str, data)
|
|
168
|
+
|
|
169
|
+
url = _parse_url(d.pop("url"))
|
|
170
|
+
|
|
171
|
+
task = cls(
|
|
172
|
+
id=id,
|
|
173
|
+
status=status,
|
|
174
|
+
source=source,
|
|
175
|
+
title=title,
|
|
176
|
+
repo=repo,
|
|
177
|
+
pull_request=pull_request,
|
|
178
|
+
queued=queued,
|
|
179
|
+
created_at=created_at,
|
|
180
|
+
last_activity_at=last_activity_at,
|
|
181
|
+
url=url,
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
task.additional_properties = d
|
|
185
|
+
return task
|
|
186
|
+
|
|
187
|
+
@property
|
|
188
|
+
def additional_keys(self) -> list[str]:
|
|
189
|
+
return list(self.additional_properties.keys())
|
|
190
|
+
|
|
191
|
+
def __getitem__(self, key: str) -> Any:
|
|
192
|
+
return self.additional_properties[key]
|
|
193
|
+
|
|
194
|
+
def __setitem__(self, key: str, value: Any) -> None:
|
|
195
|
+
self.additional_properties[key] = value
|
|
196
|
+
|
|
197
|
+
def __delitem__(self, key: str) -> None:
|
|
198
|
+
del self.additional_properties[key]
|
|
199
|
+
|
|
200
|
+
def __contains__(self, key: str) -> bool:
|
|
201
|
+
return key in self.additional_properties
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Mapping
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Self, TypeVar, cast
|
|
5
|
+
|
|
6
|
+
from attrs import define as _attrs_define
|
|
7
|
+
from attrs import field as _attrs_field
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from ..models.task import Task
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
T = TypeVar("T", bound="TaskList")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@_attrs_define
|
|
17
|
+
class TaskList:
|
|
18
|
+
"""A page of tasks.
|
|
19
|
+
|
|
20
|
+
Attributes:
|
|
21
|
+
tasks (list[Task]): The page's tasks, most recently active first.
|
|
22
|
+
next_cursor (None | str): Pass it back as `cursor` to get the next page. Treat it as opaque. `null` on the last
|
|
23
|
+
page.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
tasks: list[Task]
|
|
27
|
+
next_cursor: None | str
|
|
28
|
+
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
|
|
29
|
+
|
|
30
|
+
def to_dict(self) -> dict[str, Any]:
|
|
31
|
+
tasks = []
|
|
32
|
+
for tasks_item_data in self.tasks:
|
|
33
|
+
tasks_item = tasks_item_data.to_dict()
|
|
34
|
+
tasks.append(tasks_item)
|
|
35
|
+
|
|
36
|
+
next_cursor: None | str
|
|
37
|
+
next_cursor = self.next_cursor
|
|
38
|
+
|
|
39
|
+
field_dict: dict[str, Any] = {}
|
|
40
|
+
field_dict.update(self.additional_properties)
|
|
41
|
+
field_dict.update(
|
|
42
|
+
{
|
|
43
|
+
"tasks": tasks,
|
|
44
|
+
"nextCursor": next_cursor,
|
|
45
|
+
}
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
return field_dict
|
|
49
|
+
|
|
50
|
+
@classmethod
|
|
51
|
+
def from_dict(cls, src_dict: Mapping[str, Any]) -> Self:
|
|
52
|
+
from ..models.task import Task
|
|
53
|
+
|
|
54
|
+
d = dict(src_dict)
|
|
55
|
+
tasks = []
|
|
56
|
+
_tasks = d.pop("tasks")
|
|
57
|
+
for tasks_item_data in _tasks:
|
|
58
|
+
tasks_item = Task.from_dict(tasks_item_data)
|
|
59
|
+
|
|
60
|
+
tasks.append(tasks_item)
|
|
61
|
+
|
|
62
|
+
def _parse_next_cursor(data: object) -> None | str:
|
|
63
|
+
if data is None:
|
|
64
|
+
return data
|
|
65
|
+
return cast(None | str, data)
|
|
66
|
+
|
|
67
|
+
next_cursor = _parse_next_cursor(d.pop("nextCursor"))
|
|
68
|
+
|
|
69
|
+
task_list = cls(
|
|
70
|
+
tasks=tasks,
|
|
71
|
+
next_cursor=next_cursor,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
task_list.additional_properties = d
|
|
75
|
+
return task_list
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def additional_keys(self) -> list[str]:
|
|
79
|
+
return list(self.additional_properties.keys())
|
|
80
|
+
|
|
81
|
+
def __getitem__(self, key: str) -> Any:
|
|
82
|
+
return self.additional_properties[key]
|
|
83
|
+
|
|
84
|
+
def __setitem__(self, key: str, value: Any) -> None:
|
|
85
|
+
self.additional_properties[key] = value
|
|
86
|
+
|
|
87
|
+
def __delitem__(self, key: str) -> None:
|
|
88
|
+
del self.additional_properties[key]
|
|
89
|
+
|
|
90
|
+
def __contains__(self, key: str) -> bool:
|
|
91
|
+
return key in self.additional_properties
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Mapping
|
|
4
|
+
from typing import Any, Self, TypeVar, cast
|
|
5
|
+
|
|
6
|
+
from attrs import define as _attrs_define
|
|
7
|
+
from attrs import field as _attrs_field
|
|
8
|
+
|
|
9
|
+
T = TypeVar("T", bound="Ticket")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@_attrs_define
|
|
13
|
+
class Ticket:
|
|
14
|
+
"""An open issue you could delegate to Sinatra.
|
|
15
|
+
|
|
16
|
+
Attributes:
|
|
17
|
+
id (str): The issue's id on Sinatra's side. For GitHub it looks like `github:owner/name#42`.
|
|
18
|
+
source (str): Where the issue lives: `linear` or `github`. New sources can appear.
|
|
19
|
+
identifier (str): What to delegate it by. A Linear identifier such as `ENG-123` (send it as `id`), or a GitHub
|
|
20
|
+
`owner/name#42` (send `owner/name` as `repo` and `42` as `number`).
|
|
21
|
+
title (str): The issue's title.
|
|
22
|
+
yours (bool): `true` if the issue is assigned to you or you wrote it.
|
|
23
|
+
state (None | str): A GitHub issue's state, such as `open`. `null` for a Linear issue.
|
|
24
|
+
context (None | str): The Linear team's name, or the GitHub repository's name.
|
|
25
|
+
url (str): The issue's address on its tracker.
|
|
26
|
+
workspace_id (str): The id of the workspace that was searched.
|
|
27
|
+
workspace_label (str): The name the dashboard's ticket picker gives that workspace.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
id: str
|
|
31
|
+
source: str
|
|
32
|
+
identifier: str
|
|
33
|
+
title: str
|
|
34
|
+
yours: bool
|
|
35
|
+
state: None | str
|
|
36
|
+
context: None | str
|
|
37
|
+
url: str
|
|
38
|
+
workspace_id: str
|
|
39
|
+
workspace_label: str
|
|
40
|
+
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
|
|
41
|
+
|
|
42
|
+
def to_dict(self) -> dict[str, Any]:
|
|
43
|
+
id = self.id
|
|
44
|
+
|
|
45
|
+
source = self.source
|
|
46
|
+
|
|
47
|
+
identifier = self.identifier
|
|
48
|
+
|
|
49
|
+
title = self.title
|
|
50
|
+
|
|
51
|
+
yours = self.yours
|
|
52
|
+
|
|
53
|
+
state: None | str
|
|
54
|
+
state = self.state
|
|
55
|
+
|
|
56
|
+
context: None | str
|
|
57
|
+
context = self.context
|
|
58
|
+
|
|
59
|
+
url = self.url
|
|
60
|
+
|
|
61
|
+
workspace_id = self.workspace_id
|
|
62
|
+
|
|
63
|
+
workspace_label = self.workspace_label
|
|
64
|
+
|
|
65
|
+
field_dict: dict[str, Any] = {}
|
|
66
|
+
field_dict.update(self.additional_properties)
|
|
67
|
+
field_dict.update(
|
|
68
|
+
{
|
|
69
|
+
"id": id,
|
|
70
|
+
"source": source,
|
|
71
|
+
"identifier": identifier,
|
|
72
|
+
"title": title,
|
|
73
|
+
"yours": yours,
|
|
74
|
+
"state": state,
|
|
75
|
+
"context": context,
|
|
76
|
+
"url": url,
|
|
77
|
+
"workspaceId": workspace_id,
|
|
78
|
+
"workspaceLabel": workspace_label,
|
|
79
|
+
}
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
return field_dict
|
|
83
|
+
|
|
84
|
+
@classmethod
|
|
85
|
+
def from_dict(cls, src_dict: Mapping[str, Any]) -> Self:
|
|
86
|
+
d = dict(src_dict)
|
|
87
|
+
id = d.pop("id")
|
|
88
|
+
|
|
89
|
+
source = d.pop("source")
|
|
90
|
+
|
|
91
|
+
identifier = d.pop("identifier")
|
|
92
|
+
|
|
93
|
+
title = d.pop("title")
|
|
94
|
+
|
|
95
|
+
yours = d.pop("yours")
|
|
96
|
+
|
|
97
|
+
def _parse_state(data: object) -> None | str:
|
|
98
|
+
if data is None:
|
|
99
|
+
return data
|
|
100
|
+
return cast(None | str, data)
|
|
101
|
+
|
|
102
|
+
state = _parse_state(d.pop("state"))
|
|
103
|
+
|
|
104
|
+
def _parse_context(data: object) -> None | str:
|
|
105
|
+
if data is None:
|
|
106
|
+
return data
|
|
107
|
+
return cast(None | str, data)
|
|
108
|
+
|
|
109
|
+
context = _parse_context(d.pop("context"))
|
|
110
|
+
|
|
111
|
+
url = d.pop("url")
|
|
112
|
+
|
|
113
|
+
workspace_id = d.pop("workspaceId")
|
|
114
|
+
|
|
115
|
+
workspace_label = d.pop("workspaceLabel")
|
|
116
|
+
|
|
117
|
+
ticket = cls(
|
|
118
|
+
id=id,
|
|
119
|
+
source=source,
|
|
120
|
+
identifier=identifier,
|
|
121
|
+
title=title,
|
|
122
|
+
yours=yours,
|
|
123
|
+
state=state,
|
|
124
|
+
context=context,
|
|
125
|
+
url=url,
|
|
126
|
+
workspace_id=workspace_id,
|
|
127
|
+
workspace_label=workspace_label,
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
ticket.additional_properties = d
|
|
131
|
+
return ticket
|
|
132
|
+
|
|
133
|
+
@property
|
|
134
|
+
def additional_keys(self) -> list[str]:
|
|
135
|
+
return list(self.additional_properties.keys())
|
|
136
|
+
|
|
137
|
+
def __getitem__(self, key: str) -> Any:
|
|
138
|
+
return self.additional_properties[key]
|
|
139
|
+
|
|
140
|
+
def __setitem__(self, key: str, value: Any) -> None:
|
|
141
|
+
self.additional_properties[key] = value
|
|
142
|
+
|
|
143
|
+
def __delitem__(self, key: str) -> None:
|
|
144
|
+
del self.additional_properties[key]
|
|
145
|
+
|
|
146
|
+
def __contains__(self, key: str) -> bool:
|
|
147
|
+
return key in self.additional_properties
|