vaiz-sdk 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.
vaiz/__init__.py ADDED
@@ -0,0 +1,21 @@
1
+ from .client import VaizClient
2
+ from .models import (
3
+ TaskFollower,
4
+ TaskPriority,
5
+ CustomField,
6
+ CreateTaskRequest,
7
+ EditTaskRequest,
8
+ Task,
9
+ TaskResponse,
10
+ )
11
+
12
+ __all__ = [
13
+ 'VaizClient',
14
+ 'TaskFollower',
15
+ 'TaskPriority',
16
+ 'CustomField',
17
+ 'CreateTaskRequest',
18
+ 'EditTaskRequest',
19
+ 'Task',
20
+ 'TaskResponse',
21
+ ]
vaiz/api/__init__.py ADDED
@@ -0,0 +1,4 @@
1
+ from vaiz.api.base import BaseAPIClient
2
+ from vaiz.api.tasks import TasksAPIClient
3
+
4
+ __all__ = ['BaseAPIClient', 'TasksAPIClient']
vaiz/api/base.py ADDED
@@ -0,0 +1,27 @@
1
+ import requests
2
+ from typing import Dict, Any
3
+
4
+ class BaseAPIClient:
5
+ def __init__(self, api_key: str, space_id: str, base_url: str = "https://api.vaiz.com/v4", verify_ssl: bool = True):
6
+ self.api_key = api_key
7
+ self.space_id = space_id
8
+ self.base_url = base_url
9
+ self.verify_ssl = verify_ssl
10
+ self.session = requests.Session()
11
+ self.session.headers.update({
12
+ "Authorization": f"Bearer {self.api_key}",
13
+ "Content-Type": "application/json",
14
+ "current-space-id": self.space_id,
15
+ "app-version": "1.68.1",
16
+ })
17
+
18
+ def _make_request(self, endpoint: str, method: str = "POST", json_data: Dict[str, Any] = None) -> Dict[str, Any]:
19
+ url = f"{self.base_url}/{endpoint}"
20
+ print(f"Request payload: {json_data}") # Debug print
21
+ response = self.session.request(method, url, json=json_data, verify=self.verify_ssl)
22
+ if not response.ok:
23
+ print(f"Error response: {response.text}") # Debug print
24
+ response.raise_for_status()
25
+ response_data = response.json()
26
+ print(f"Response data: {response_data}") # Debug print
27
+ return response_data
vaiz/api/boards.py ADDED
@@ -0,0 +1,27 @@
1
+ from vaiz.api.base import BaseAPIClient
2
+ from vaiz.models import BoardsResponse, BoardResponse
3
+
4
+
5
+ class BoardsAPIClient(BaseAPIClient):
6
+ def get_boards(self) -> BoardsResponse:
7
+ """
8
+ Get all boards in the current space.
9
+
10
+ Returns:
11
+ BoardsResponse: The list of boards
12
+ """
13
+ response_data = self._make_request("getBoards", method="POST", json_data={})
14
+ return BoardsResponse(**response_data)
15
+
16
+ def get_board(self, board_id: str) -> BoardResponse:
17
+ """
18
+ Get a single board by its ID.
19
+
20
+ Args:
21
+ board_id (str): The ID of the board to retrieve
22
+
23
+ Returns:
24
+ BoardResponse: The board information
25
+ """
26
+ response_data = self._make_request("getBoard", method="POST", json_data={"boardId": board_id})
27
+ return BoardResponse(**response_data)
vaiz/api/profile.py ADDED
@@ -0,0 +1,14 @@
1
+ from vaiz.api.base import BaseAPIClient
2
+ from vaiz.models import ProfileResponse
3
+
4
+
5
+ class ProfileAPIClient(BaseAPIClient):
6
+ def get_profile(self) -> ProfileResponse:
7
+ """
8
+ Get the current user's profile.
9
+
10
+ Returns:
11
+ ProfileResponse: The user's profile information
12
+ """
13
+ response_data = self._make_request("getProfile", method="POST", json_data={})
14
+ return ProfileResponse(**response_data)
vaiz/api/tasks.py ADDED
@@ -0,0 +1,43 @@
1
+ from vaiz.api.base import BaseAPIClient
2
+ from vaiz.models import CreateTaskRequest, TaskResponse, EditTaskRequest
3
+
4
+
5
+ class TasksAPIClient(BaseAPIClient):
6
+ def create_task(self, task: CreateTaskRequest) -> TaskResponse:
7
+ """
8
+ Create a new task.
9
+
10
+ Args:
11
+ task (CreateTaskRequest): The task creation request containing all necessary task information
12
+
13
+ Returns:
14
+ TaskResponse: The created task information
15
+ """
16
+ response_data = self._make_request("createTask", json_data=task.model_dump(by_alias=True))
17
+ return TaskResponse(**response_data)
18
+
19
+ def edit_task(self, task: EditTaskRequest) -> TaskResponse:
20
+ """
21
+ Edit an existing task.
22
+
23
+ Args:
24
+ task (EditTaskRequest): The task edit request containing the updated task information
25
+
26
+ Returns:
27
+ TaskResponse: The updated task information
28
+ """
29
+ response_data = self._make_request("editTask", json_data=task.model_dump(by_alias=True))
30
+ return TaskResponse(**response_data)
31
+
32
+ def get_task(self, slug: str) -> TaskResponse:
33
+ """
34
+ Get task information by its slug.
35
+
36
+ Args:
37
+ slug (str): The task slug (e.g. "ABC-123")
38
+
39
+ Returns:
40
+ TaskResponse: The task information
41
+ """
42
+ response_data = self._make_request("getTask", json_data={"slug": slug})
43
+ return TaskResponse(**response_data)
vaiz/client.py ADDED
@@ -0,0 +1,14 @@
1
+ # vaiz/client.py
2
+ from vaiz.api.tasks import TasksAPIClient
3
+ from vaiz.api.boards import BoardsAPIClient
4
+ from vaiz.api.profile import ProfileAPIClient
5
+
6
+
7
+ class VaizClient(TasksAPIClient, BoardsAPIClient, ProfileAPIClient):
8
+ """
9
+ Main client for interacting with the Vaiz API.
10
+ This class inherits all task-related operations from TasksAPIClient,
11
+ board-related operations from BoardsAPIClient,
12
+ and profile-related operations from ProfileAPIClient.
13
+ """
14
+ pass
@@ -0,0 +1,19 @@
1
+ from .base import TaskFollower, TaskPriority, CustomField
2
+ from .tasks import Task, TaskResponse, CreateTaskRequest, EditTaskRequest
3
+ from vaiz.models.boards import Board, BoardsResponse, BoardResponse
4
+ from vaiz.models.profile import Profile, ProfileResponse
5
+
6
+ __all__ = [
7
+ 'TaskFollower',
8
+ 'TaskPriority',
9
+ 'CustomField',
10
+ 'CreateTaskRequest',
11
+ 'EditTaskRequest',
12
+ 'Task',
13
+ 'TaskResponse',
14
+ 'Board',
15
+ 'BoardsResponse',
16
+ 'BoardResponse',
17
+ 'Profile',
18
+ 'ProfileResponse'
19
+ ]
vaiz/models/base.py ADDED
@@ -0,0 +1,19 @@
1
+ from pydantic import BaseModel, RootModel, Field
2
+ from typing import List, Optional, Dict, Literal, Any, Union
3
+ from enum import Enum
4
+
5
+
6
+ class TaskFollower(RootModel):
7
+ root: Dict[str, Literal["creator"]]
8
+
9
+
10
+ class TaskPriority(int, Enum):
11
+ Low = 0
12
+ General = 1
13
+ Medium = 2
14
+ High = 3
15
+
16
+
17
+ class CustomField(BaseModel):
18
+ id: str
19
+ value: Union[str, List[str]]
vaiz/models/boards.py ADDED
@@ -0,0 +1,55 @@
1
+ from typing import List, Optional, Dict, Any
2
+ from pydantic import BaseModel, Field
3
+
4
+
5
+ class BoardGroup(BaseModel):
6
+ name: str
7
+ id: str = Field(..., alias="_id")
8
+
9
+
10
+ class BoardType(BaseModel):
11
+ label: str
12
+ icon: str
13
+ color: str
14
+ id: str = Field(..., alias="_id")
15
+ description: Optional[str] = None
16
+
17
+
18
+ class BoardCustomField(BaseModel):
19
+ name: str
20
+ type: str
21
+ id: str = Field(..., alias="_id")
22
+ description: Optional[str] = None
23
+ options: Optional[List[Any]] = None
24
+ hidden: Optional[bool] = None
25
+
26
+
27
+ class Board(BaseModel):
28
+ id: str = Field(..., alias="_id")
29
+ name: str
30
+ project: Optional[str] = None
31
+ creator: Optional[str] = None
32
+ archiver: Optional[str] = None
33
+ archived_at: Optional[str] = Field(None, alias="archivedAt")
34
+ created_at: Optional[str] = Field(None, alias="createdAt")
35
+ deleter: Optional[str] = None
36
+ deleted_at: Optional[str] = Field(None, alias="deletedAt")
37
+ groups: Optional[List[BoardGroup]] = None
38
+ types_list: Optional[List[BoardType]] = Field(None, alias="typesList")
39
+ custom_fields: Optional[List[BoardCustomField]] = Field(None, alias="customFields")
40
+ task_order_by_groups: Optional[Dict[str, List[str]]] = Field(None, alias="taskOrderByGroups")
41
+ updated_at: Optional[str] = Field(None, alias="updatedAt")
42
+
43
+
44
+ class BoardsPayload(BaseModel):
45
+ boards: List[Board]
46
+
47
+
48
+ class BoardsResponse(BaseModel):
49
+ type: str
50
+ payload: BoardsPayload
51
+
52
+
53
+ class BoardResponse(BaseModel):
54
+ type: str
55
+ payload: Dict[str, Board] = Field(..., alias="payload")
vaiz/models/profile.py ADDED
@@ -0,0 +1,36 @@
1
+ from pydantic import BaseModel, Field
2
+ from typing import Optional, List, Dict, Any
3
+
4
+
5
+ class ProfileEmail(BaseModel):
6
+ email: str
7
+ confirmed: bool
8
+ primary: bool
9
+
10
+
11
+ class ProfileColor(BaseModel):
12
+ color: Dict[str, Any] = {}
13
+
14
+
15
+ class Profile(BaseModel):
16
+ id: str = Field(..., alias="_id")
17
+ fullName: str
18
+ nickName: str
19
+ email: str
20
+ emails: List[ProfileEmail]
21
+ color: ProfileColor = Field(default_factory=ProfileColor)
22
+ avatarMode: int
23
+ incompleteSteps: List[str]
24
+ registeredDate: str
25
+ recoveryCodes: List[str]
26
+ passwordChangedDate: str
27
+ passwordHash: str
28
+ memberId: str
29
+ created_at: str = Field(..., alias="createdAt")
30
+ updated_at: str = Field(..., alias="updatedAt")
31
+ cData: Dict[str, Optional[str]]
32
+
33
+
34
+ class ProfileResponse(BaseModel):
35
+ type: str
36
+ payload: Dict[str, Profile] = Field(..., alias="payload")
vaiz/models/tasks.py ADDED
@@ -0,0 +1,94 @@
1
+ from pydantic import BaseModel
2
+ from typing import Dict, Any, List, Optional
3
+ from datetime import datetime
4
+ from .base import TaskPriority, CustomField
5
+
6
+
7
+ class TaskCustomField(BaseModel):
8
+ id: str
9
+ value: Any
10
+ _id: str
11
+
12
+
13
+ class Task(BaseModel):
14
+ _id: str
15
+ name: str
16
+ group: str
17
+ board: str
18
+ project: str
19
+ parentTask: Optional[str] = None
20
+ types: List[str] = []
21
+ priority: int
22
+ hrid: str
23
+ followers: Dict[str, str]
24
+ archiver: Optional[str] = None
25
+ completed: bool
26
+ assignees: List[str] = []
27
+ subtasks: List[str] = []
28
+ milestones: List[str] = []
29
+ dueStart: Optional[str] = None
30
+ dueEnd: Optional[str] = None
31
+ rightConnectors: List[str] = []
32
+ leftConnectors: List[str] = []
33
+ archivedAt: Optional[str] = None
34
+ completedAt: Optional[str] = None
35
+ customFields: List[TaskCustomField] = []
36
+ deleter: Optional[str] = None
37
+ deletedAt: Optional[str] = None
38
+ creator: str
39
+ createdAt: str
40
+ updatedAt: str
41
+ document: str
42
+ editor: Optional[str] = None
43
+ milestone: Optional[str] = None
44
+
45
+
46
+ class TaskResponse(BaseModel):
47
+ payload: Dict[str, Any]
48
+ type: str
49
+
50
+
51
+ class CreateTaskRequest(BaseModel):
52
+ name: str
53
+ group: str
54
+ board: str
55
+ project: str
56
+ parentTask: Optional[str] = None
57
+ types: List[str] = []
58
+ priority: TaskPriority = TaskPriority.General
59
+ completed: bool = False
60
+ assignees: List[str] = []
61
+ subtasks: List[str] = []
62
+ milestones: List[str] = []
63
+ dueStart: Optional[str] = None
64
+ dueEnd: Optional[str] = None
65
+ rightConnectors: List[str] = []
66
+ leftConnectors: List[str] = []
67
+ customFields: List[CustomField] = []
68
+
69
+ def model_dump(self, **kwargs):
70
+ # Remove None values from the dict
71
+ data = super().model_dump(**kwargs)
72
+ return {k: v for k, v in data.items() if v is not None}
73
+
74
+
75
+ class EditTaskRequest(BaseModel):
76
+ taskId: str
77
+ name: Optional[str] = None
78
+ parentTask: Optional[str] = None
79
+ types: Optional[List[str]] = None
80
+ priority: Optional[TaskPriority] = None
81
+ completed: Optional[bool] = None
82
+ assignees: Optional[List[str]] = None
83
+ subtasks: Optional[List[str]] = None
84
+ milestones: Optional[List[str]] = None
85
+ dueStart: Optional[str] = None
86
+ dueEnd: Optional[str] = None
87
+ rightConnectors: Optional[List[str]] = None
88
+ leftConnectors: Optional[List[str]] = None
89
+ customFields: Optional[List[CustomField]] = None
90
+
91
+ def model_dump(self, **kwargs):
92
+ # Remove None values from the dict
93
+ data = super().model_dump(**kwargs)
94
+ return {k: v for k, v in data.items() if v is not None}
@@ -0,0 +1,241 @@
1
+ Metadata-Version: 2.4
2
+ Name: vaiz-sdk
3
+ Version: 0.1.0
4
+ Summary: Official SDK for interacting with the Vaiz API
5
+ Author-email: Vaiz <mail@vaiz.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/vaizcom/vaiz-python-sdk
8
+ Project-URL: Repository, https://github.com/vaizcom/vaiz-python-sdk
9
+ Project-URL: Issues, https://github.com/vaizcom/vaiz-python-sdk/issues
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Topic :: Software Development :: Libraries
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.8
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Requires-Python: >=3.8
21
+ Description-Content-Type: text/markdown
22
+ Requires-Dist: requests>=2.31.0
23
+ Requires-Dist: pydantic>=2.0
24
+ Requires-Dist: python-dotenv>=0.9.0
25
+ Provides-Extra: dev
26
+ Requires-Dist: pytest>=8.0.0; extra == "dev"
27
+ Requires-Dist: pytest-mock>=3.12.0; extra == "dev"
28
+
29
+ # Vaiz SDK for Python
30
+
31
+ Python SDK for accessing the Vaiz platform.
32
+
33
+ ## Installation
34
+
35
+ ```bash
36
+ pip install vaiz-sdk
37
+ ```
38
+
39
+ ## Usage
40
+
41
+ ### Basic Setup
42
+
43
+ First, you need to set up your environment variables. Create a `.env` file in your project root with the following variables:
44
+
45
+ ```env
46
+ VAIZ_API_KEY=your_api_key
47
+ VAIZ_SPACE_ID=your_space_id
48
+ ```
49
+
50
+ ### Creating a Client
51
+
52
+ ```python
53
+ from vaiz import VaizClient
54
+
55
+ client = VaizClient(
56
+ api_key="your_api_key",
57
+ space_id="your_space_id",
58
+ verify_ssl=False, # Set to True in production
59
+ base_url="https://api.vaiz.local:10000/v4" # Use appropriate base URL for your environment
60
+ )
61
+ ```
62
+
63
+ ### Working with Boards
64
+
65
+ #### Get All Boards
66
+
67
+ ```python
68
+ response = client.get_boards()
69
+ ```
70
+
71
+ #### Get a Single Board
72
+
73
+ ```python
74
+ response = client.get_board("board_id")
75
+ board = response.payload["board"]
76
+ ```
77
+
78
+ ### Working with Profile
79
+
80
+ #### Get User Profile
81
+
82
+ ```python
83
+ response = client.get_profile()
84
+ profile = response.payload["profile"]
85
+ ```
86
+
87
+ ### Working with Tasks
88
+
89
+ #### Create a Task
90
+
91
+ ```python
92
+ from vaiz.models import CreateTaskRequest, TaskPriority
93
+
94
+ task = CreateTaskRequest(
95
+ name="My Task",
96
+ group="group_id",
97
+ board="board_id",
98
+ project="project_id",
99
+ priority=TaskPriority.High,
100
+ completed=False,
101
+ types=["type_id"],
102
+ subtasks=[],
103
+ milestones=[],
104
+ rightConnectors=[],
105
+ leftConnectors=[]
106
+ )
107
+
108
+ response = client.create_task(task)
109
+ ```
110
+
111
+ #### Edit a Task
112
+
113
+ ```python
114
+ from vaiz.models import EditTaskRequest
115
+
116
+ edit_task = EditTaskRequest(
117
+ taskId="task_id",
118
+ name="Updated Task Name",
119
+ assignees=["assignee_id"]
120
+ )
121
+
122
+ response = client.edit_task(edit_task)
123
+ ```
124
+
125
+ #### Get Task Information
126
+
127
+ ```python
128
+ response = client.get_task("task_id")
129
+ ```
130
+
131
+ ## Development
132
+
133
+ ### Setting Up Development Environment
134
+
135
+ 1. Create and activate a virtual environment:
136
+
137
+ ```bash
138
+ python3 -m venv venv
139
+ source venv/bin/activate # On Windows use: venv\Scripts\activate
140
+ ```
141
+
142
+ 2. Install the package in development mode:
143
+
144
+ ```bash
145
+ pip install -e .
146
+ ```
147
+
148
+ ### Testing
149
+
150
+ #### Setup
151
+
152
+ 1. Install test dependencies:
153
+
154
+ ```bash
155
+ pip install pytest pytest-mock python-dotenv
156
+ ```
157
+
158
+ 2. Create a `.env` file in the project root with your test credentials:
159
+
160
+ ```env
161
+ VAIZ_API_KEY=your_test_api_key
162
+ VAIZ_SPACE_ID=your_test_space_id
163
+ ```
164
+
165
+ The test configuration (`tests/test_config.py`) will automatically load these credentials.
166
+
167
+ #### Running Tests
168
+
169
+ Run all tests:
170
+
171
+ ```bash
172
+ PYTHONPATH=. pytest
173
+ ```
174
+
175
+ Run specific test file:
176
+
177
+ ```bash
178
+ PYTHONPATH=. pytest tests/test_client.py
179
+ ```
180
+
181
+ Run with verbose output:
182
+
183
+ ```bash
184
+ PYTHONPATH=. pytest -v
185
+ ```
186
+
187
+ Note: Setting `PYTHONPATH=.` is required to ensure Python can find the package modules during testing.
188
+
189
+ #### Writing Tests
190
+
191
+ When writing tests for the SDK:
192
+
193
+ 1. Use the test configuration from `tests/test_config.py`:
194
+
195
+ ```python
196
+ from tests.test_config import get_test_client, TEST_BOARD_ID, TEST_GROUP_ID
197
+
198
+ def test_create_task(mocker):
199
+ client = get_test_client()
200
+ # Your test code here
201
+ ```
202
+
203
+ 2. Mock external API calls using `pytest-mock`:
204
+
205
+ ```python
206
+ def test_create_task(mocker):
207
+ # Mock the API response
208
+ mock_response = mocker.Mock()
209
+ mock_response.json.return_value = {
210
+ "type": "success",
211
+ "payload": {"task": {"_id": "test_task_id"}}
212
+ }
213
+ mocker.patch('requests.post', return_value=mock_response)
214
+
215
+ # Test implementation
216
+ client = get_test_client()
217
+ # ... rest of the test
218
+ ```
219
+
220
+ 3. Test both success and error cases
221
+ 4. Include proper assertions for response data
222
+
223
+ ### Examples
224
+
225
+ The `examples/` directory contains working examples of SDK usage. You can run any example using the following command:
226
+
227
+ ```bash
228
+ python -m examples.<example_file_name>
229
+ ```
230
+
231
+ ## Contributing
232
+
233
+ 1. Fork the repository
234
+ 2. Create a feature branch
235
+ 3. Write tests for your changes
236
+ 4. Ensure all tests pass
237
+ 5. Submit a pull request
238
+
239
+ ## License
240
+
241
+ This project is licensed under the MIT License - see the LICENSE file for details.
@@ -0,0 +1,16 @@
1
+ vaiz/__init__.py,sha256=XZoRA0PeDpAE89qTSJhveE_ohddl7cKC3-DuhYlB4Sk,351
2
+ vaiz/client.py,sha256=INb5Ih1zWdMtWm3YFoUa3ktBzwnknfkb8Iif7Cb39NY,477
3
+ vaiz/api/__init__.py,sha256=5ANcTY3JTzEATofnKd8ZE603Ma37Jm09QqbQEzWhjis,129
4
+ vaiz/api/base.py,sha256=0LesFM181BY1sDwihjYJOPN_sXo1y5bUbAAyBAD2k-g,1184
5
+ vaiz/api/boards.py,sha256=hlx2hTNNuPbMvIiypgVCFmxaxp4Zb0926CiBxyAp84o,883
6
+ vaiz/api/profile.py,sha256=YpcoTm9pdvY2F4LNXqPfHuuvWAKY8zjK3UMtxx89jB8,451
7
+ vaiz/api/tasks.py,sha256=rPsJTM2X5joLq6BaMVqM4wjP_96te0AXJdxhT20aZhA,1495
8
+ vaiz/models/__init__.py,sha256=YNG1xUFL_-O7Dv2RX5VABcCX0uW0CivmJ46iVLOvrlQ,504
9
+ vaiz/models/base.py,sha256=S28GHWl_P1Y0H4sM9L-PRkj6lTDhjwH5y77M5pLBx58,371
10
+ vaiz/models/boards.py,sha256=_ryO3nN6fZzp--FEs56C_qN5ybDaRLeZHhk87YiluoY,1549
11
+ vaiz/models/profile.py,sha256=8LkBhAAppf7bSwh14bmoXy2GZpJ424iYkfvLUcnAO6E,868
12
+ vaiz/models/tasks.py,sha256=JeYjtMzKWC2HPBQVV75Jq4tSXBBlU87OGK1-FG54La0,2608
13
+ vaiz_sdk-0.1.0.dist-info/METADATA,sha256=otXxFj2XGsGBt93OYEcbwoY3749RqyTNJ0Q5WuJNgRc,5027
14
+ vaiz_sdk-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
15
+ vaiz_sdk-0.1.0.dist-info/top_level.txt,sha256=DpUEygwuEftG1YPnj8f-Zpy_p8IEZdWPCDb2P2-4q5U,5
16
+ vaiz_sdk-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ vaiz