trismik 0.9.1__py3-none-any.whl → 0.9.5__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.
trismik/client.py DELETED
@@ -1,330 +0,0 @@
1
- from typing import List, Any, Optional
2
-
3
- import httpx
4
-
5
- from ._mapper import TrismikResponseMapper
6
- from ._utils import TrismikUtils
7
- from .exceptions import TrismikApiError
8
- from .types import (
9
- TrismikTest,
10
- TrismikAuth,
11
- TrismikSession,
12
- TrismikItem,
13
- TrismikResult,
14
- TrismikResponse,
15
- TrismikSessionMetadata
16
- )
17
-
18
-
19
- class TrismikClient:
20
- _serviceUrl: str = "https://trismik.e-psychometrics.com/api"
21
-
22
- def __init__(
23
- self,
24
- service_url: Optional[str] = None,
25
- api_key: Optional[str] = None,
26
- http_client: Optional[httpx.Client] | None = None,
27
- ) -> None:
28
- """
29
- Initializes a new Trismik client.
30
-
31
- Args:
32
- service_url (Optional[str]): URL of the Trismik service.
33
- api_key (Optional[str]): API key for the Trismik service.
34
- http_client (Optional[httpx.Client]): HTTP client to use for requests.
35
-
36
- Raises:
37
- TrismikError: If service_url or api_key are not provided and not found in environment.
38
- TrismikApiError: If API request fails.
39
- """
40
- self._service_url = TrismikUtils.option(
41
- service_url, self._serviceUrl, "TRISMIK_SERVICE_URL"
42
- )
43
- self._api_key = TrismikUtils.required_option(
44
- api_key, "api_key", "TRISMIK_API_KEY"
45
- )
46
- self._http_client = http_client or httpx.Client(
47
- base_url=self._service_url)
48
-
49
- def authenticate(self) -> TrismikAuth:
50
- """
51
- Authenticates with the Trismik service.
52
-
53
- Returns:
54
- TrismikAuth: Authentication token.
55
-
56
- Raises:
57
- TrismikApiError: If API request fails.
58
- """
59
- try:
60
- url = "/client/auth"
61
- body = {"apiKey": self._api_key}
62
- response = self._http_client.post(url, json=body)
63
- response.raise_for_status()
64
- json = response.json()
65
- return TrismikResponseMapper.to_auth(json)
66
- except httpx.HTTPStatusError as e:
67
- raise TrismikApiError(
68
- TrismikUtils.get_error_message(e.response)) from e
69
- except httpx.HTTPError as e:
70
- raise TrismikApiError(str(e)) from e
71
-
72
- def refresh_token(self, token: str) -> TrismikAuth:
73
- """
74
- Refreshes the authentication token.
75
-
76
- Args:
77
- token (str): Current authentication token.
78
-
79
- Returns:
80
- TrismikAuth: New authentication token.
81
-
82
- Raises:
83
- TrismikApiError: If API request fails.
84
- """
85
- try:
86
- url = "/client/token"
87
- headers = {"Authorization": f"Bearer {token}"}
88
- response = self._http_client.get(url, headers=headers)
89
- response.raise_for_status()
90
- json = response.json()
91
- return TrismikResponseMapper.to_auth(json)
92
- except httpx.HTTPStatusError as e:
93
- raise TrismikApiError(
94
- TrismikUtils.get_error_message(e.response)) from e
95
- except httpx.HTTPError as e:
96
- raise TrismikApiError(str(e)) from e
97
-
98
- def available_tests(self, token: str) -> List[TrismikTest]:
99
- """
100
- Retrieves a list of available tests.
101
-
102
- Args:
103
- token (str): Authentication token.
104
-
105
- Returns:
106
- List[TrismikTest]: List of available tests.
107
-
108
- Raises:
109
- TrismikApiError: If API request fails.
110
- """
111
- try:
112
- url = "/client/tests"
113
- headers = {"Authorization": f"Bearer {token}"}
114
- response = self._http_client.get(url, headers=headers)
115
- response.raise_for_status()
116
- json = response.json()
117
- return TrismikResponseMapper.to_tests(json)
118
- except httpx.HTTPStatusError as e:
119
- raise TrismikApiError(
120
- TrismikUtils.get_error_message(e.response)) from e
121
- except httpx.HTTPError as e:
122
- raise TrismikApiError(str(e)) from e
123
-
124
- def create_session(self, test_id: str, metadata: TrismikSessionMetadata, token: str) -> TrismikSession:
125
- """
126
- Creates a new session for a test.
127
-
128
- Args:
129
- test_id (str): ID of the test.
130
- token (str): Authentication token.
131
-
132
- Returns:
133
- TrismikSession: New session
134
-
135
- Raises:
136
- TrismikApiError: If API request fails.
137
- """
138
- try:
139
- url = "/client/sessions"
140
- headers = {"Authorization": f"Bearer {token}"}
141
- body = {"testId": test_id, "metadata": metadata.toDict() }
142
- response = self._http_client.post(url, headers=headers, json=body)
143
- response.raise_for_status()
144
- json = response.json()
145
- return TrismikResponseMapper.to_session(json)
146
- except httpx.HTTPStatusError as e:
147
- raise TrismikApiError(
148
- TrismikUtils.get_error_message(e.response)) from e
149
- except httpx.HTTPError as e:
150
- raise TrismikApiError(str(e)) from e
151
-
152
- def create_replay_session(self, previous_session_id: str, metadata: TrismikSessionMetadata, token: str) -> TrismikSession:
153
- """
154
- Creates a new session that replays exactly the question sequence of a previous session
155
-
156
- Args:
157
- previous_session_id (str): Session id of the session to replay.
158
- token (str): Authentication token.
159
-
160
- Returns:
161
- TrismikSession: New session
162
-
163
- Raises:
164
- TrismikApiError: If API request fails.
165
- """
166
- try:
167
- url = "/client/sessions/replay"
168
- headers = {"Authorization": f"Bearer {token}"}
169
- body = {"previousSessionToken": previous_session_id, "metadata": metadata.toDict(), }
170
- response = self._http_client.post(url, headers=headers, json=body)
171
- response.raise_for_status()
172
- json = response.json()
173
- return TrismikResponseMapper.to_session(json)
174
- except httpx.HTTPStatusError as e:
175
- raise TrismikApiError(
176
- TrismikUtils.get_error_message(e.response)) from e
177
- except httpx.HTTPError as e:
178
- raise TrismikApiError(str(e)) from e
179
-
180
- def add_metadata(self, session_id: str, metadata: TrismikSessionMetadata, token: str) -> None:
181
- """
182
- Adds metadata to the session, merging it with any already stored
183
-
184
- Args:
185
- session_id (str): id of the session object
186
- metadata: object cotaining the metadata to add
187
- token (str): Authentication token.
188
-
189
- Returns:
190
- None
191
-
192
- Raises:
193
- TrismikApiError: If API request fails.
194
- """
195
- try:
196
- url = f"/client/sessions/{session_id}/metadata"
197
- headers = {"Authorization": f"Bearer {token}"}
198
- body = metadata.toDict()
199
- response = self._http_client.post(url, headers=headers, json=body)
200
- response.raise_for_status()
201
- except httpx.HTTPStatusError as e:
202
- raise TrismikApiError(
203
- TrismikUtils.get_error_message(e.response)) from e
204
- except httpx.HTTPError as e:
205
- raise TrismikApiError(str(e)) from e
206
-
207
- def current_item(
208
- self,
209
- session_url: str,
210
- token: str
211
- ) -> TrismikItem:
212
- """
213
- Retrieves the current test item.
214
-
215
- Args:
216
- session_url (str): URL of the session.
217
- token (str): Authentication token.
218
-
219
- Returns:
220
- TrismikItem: Current test item.
221
-
222
- Raises:
223
- TrismikApiError: If API request fails.
224
- """
225
- try:
226
- url = f"{session_url}/item"
227
- headers = {"Authorization": f"Bearer {token}"}
228
- response = self._http_client.get(url, headers=headers)
229
- response.raise_for_status()
230
- json = response.json()
231
- return TrismikResponseMapper.to_item(json)
232
- except httpx.HTTPStatusError as e:
233
- raise TrismikApiError(
234
- TrismikUtils.get_error_message(e.response)) from e
235
- except httpx.HTTPError as e:
236
- raise TrismikApiError(str(e)) from e
237
-
238
- def respond_to_current_item(
239
- self,
240
- session_url: str,
241
- value: Any,
242
- token: str
243
- ) -> TrismikItem | None:
244
- """
245
- Responds to the current test item.
246
-
247
- Args:
248
- session_url (str): URL of the session.
249
- value (Any): Response value.
250
- token (str): Authentication token.
251
-
252
- Returns:
253
- TrismikItem | None: Next test item or None if session is finished.
254
-
255
- Raises:
256
- TrismikApiError: If API request fails.
257
- """
258
- try:
259
- url = f"{session_url}/item"
260
- body = {"value": value}
261
- headers = {"Authorization": f"Bearer {token}"}
262
- response = self._http_client.post(url, headers=headers, json=body)
263
- response.raise_for_status()
264
- if response.status_code == 204:
265
- return None
266
- else:
267
- json = response.json()
268
- return TrismikResponseMapper.to_item(json)
269
- except httpx.HTTPStatusError as e:
270
- raise TrismikApiError(
271
- TrismikUtils.get_error_message(e.response)) from e
272
- except httpx.HTTPError as e:
273
- raise TrismikApiError(str(e)) from e
274
-
275
- def results(self, session_url: str, token: str) -> List[TrismikResult]:
276
- """
277
- Retrieves the results of a session.
278
-
279
- Args:
280
- session_url (str): URL of the session.
281
- token (str): Authentication token.
282
-
283
- Returns:
284
- List[TrismikResult]: Results of the session.
285
-
286
- Raises:
287
- TrismikApiError: If API request fails.
288
- """
289
- try:
290
- url = f"{session_url}/results"
291
- headers = {"Authorization": f"Bearer {token}"}
292
- response = self._http_client.get(url, headers=headers)
293
- response.raise_for_status()
294
- json = response.json()
295
- return TrismikResponseMapper.to_results(json)
296
- except httpx.HTTPStatusError as e:
297
- raise TrismikApiError(
298
- TrismikUtils.get_error_message(e.response)) from e
299
- except httpx.HTTPError as e:
300
- raise TrismikApiError(str(e)) from e
301
-
302
- def responses(self,
303
- session_url: str,
304
- token: str
305
- ) -> List[TrismikResponse]:
306
- """
307
- Retrieves responses to session items.
308
-
309
- Args:
310
- session_url (str): URL of the session.
311
- token (str): Authentication token.
312
-
313
- Returns:
314
- List[TrismikResponse]: Responses of the session.
315
-
316
- Raises:
317
- TrismikApiError: If API request fails.
318
- """
319
- try:
320
- url = f"{session_url}/responses"
321
- headers = {"Authorization": f"Bearer {token}"}
322
- response = self._http_client.get(url, headers=headers)
323
- response.raise_for_status()
324
- json = response.json()
325
- return TrismikResponseMapper.to_responses(json)
326
- except httpx.HTTPStatusError as e:
327
- raise TrismikApiError(
328
- TrismikUtils.get_error_message(e.response)) from e
329
- except httpx.HTTPError as e:
330
- raise TrismikApiError(str(e)) from e
trismik/runner.py DELETED
@@ -1,119 +0,0 @@
1
- from datetime import datetime, timedelta
2
- from typing import List, Callable, Any, Optional
3
-
4
- from .client import TrismikClient
5
- from .types import (
6
- TrismikAuth,
7
- TrismikItem,
8
- TrismikResult,
9
- TrismikRunResults,
10
- TrismikSessionMetadata,
11
- )
12
-
13
-
14
- class TrismikRunner:
15
- def __init__(
16
- self,
17
- item_processor: Callable[[TrismikItem], Any],
18
- client: Optional[TrismikClient] = None,
19
- auth: Optional[TrismikAuth] = None,
20
- ) -> None:
21
- """
22
- Initializes a new Trismik runner.
23
-
24
- Args:
25
- item_processor (Callable[[TrismikItem], Any]): Function to process test items.
26
- client (Optional[TrismikClient]): Trismik client to use for requests.
27
- auth (Optional[TrismikAuth]): Authentication token to use for requests
28
-
29
- Raises:
30
- TrismikApiError: If API request fails.
31
- """
32
- self._item_processor = item_processor
33
- self._client = client
34
- self._auth = auth
35
-
36
- def run(self,
37
- test_id: str,
38
- session_metadata: TrismikSessionMetadata,
39
- with_responses: bool = False,
40
- ) -> TrismikRunResults:
41
- """
42
- Runs a test.
43
-
44
- Args:
45
- test_id (str): ID of the test to run.
46
- with_responses (bool): If True, responses will be included with the results.
47
-
48
- Returns:
49
- TrismikRunResults: Either just test results, or with responses.
50
-
51
- Raises:
52
- TrismikApiError: If API request fails.
53
- """
54
- self._init()
55
- self._refresh_token_if_needed()
56
- session = self._client.create_session(test_id, session_metadata, self._auth.token)
57
-
58
- self._run_session(session.url)
59
- results = self._client.results(session.url, self._auth.token)
60
-
61
- if with_responses:
62
- responses = self._client.responses(session.url, self._auth.token)
63
- return TrismikRunResults(session.id, results, responses)
64
- else:
65
- return TrismikRunResults(session.id, results)
66
-
67
- def _run_session(self, session_url: str) -> None:
68
- item = self._client.current_item(session_url, self._auth.token)
69
- while item is not None:
70
- self._refresh_token_if_needed()
71
- response = self._item_processor(item)
72
- item = self._client.respond_to_current_item(
73
- session_url, response, self._auth.token
74
- )
75
-
76
- def run_replay(self,
77
- previous_session_id: str,
78
- session_metadata: TrismikSessionMetadata,
79
- with_responses: bool = False,
80
- ) -> TrismikRunResults:
81
- """
82
- Replay the exact sequence of questions from a previous session
83
-
84
- Args:
85
- previous_session_id (str): ID of a previous session to replay
86
- with_responses (bool): If True, responses will be included with the results.
87
-
88
- Returns:
89
- TrismikRunResults: Either just test results, or with responses.
90
-
91
- Raises:
92
- TrismikApiError: If API request fails.
93
- """
94
- self._init()
95
- self._refresh_token_if_needed()
96
- session = self._client.create_replay_session(previous_session_id, session_metadata, self._auth.token)
97
-
98
- self._run_session(session.url)
99
- results = self._client.results(session.url, self._auth.token)
100
-
101
- if with_responses:
102
- responses = self._client.responses(session.url, self._auth.token)
103
- return TrismikRunResults(session.id, results, responses)
104
- else:
105
- return TrismikRunResults(session.id, results)
106
-
107
- def _init(self) -> None:
108
- if self._client is None:
109
- self._client = TrismikClient()
110
-
111
- if self._auth is None:
112
- self._auth = self._client.authenticate()
113
-
114
- def _refresh_token_if_needed(self) -> None:
115
- if self._token_needs_refresh():
116
- self._auth = self._client.refresh_token(self._auth.token)
117
-
118
- def _token_needs_refresh(self) -> bool:
119
- return self._auth.expires < (datetime.now() + timedelta(minutes=5))
trismik/runner_async.py DELETED
@@ -1,121 +0,0 @@
1
- from datetime import datetime, timedelta
2
- from typing import List, Callable, Any, Awaitable, Optional
3
-
4
- from .client_async import TrismikAsyncClient
5
- from .types import (
6
- TrismikAuth,
7
- TrismikItem,
8
- TrismikResult,
9
- TrismikRunResults,
10
- TrismikSessionMetadata,
11
- )
12
-
13
-
14
- class TrismikAsyncRunner:
15
- def __init__(
16
- self,
17
- item_processor: Callable[[TrismikItem], Awaitable[Any]],
18
- client: Optional[TrismikAsyncClient] = None,
19
- auth: Optional[TrismikAuth] = None,
20
- ) -> None:
21
- """
22
- Initializes a new Trismik runner (async version).
23
-
24
- Args:
25
- item_processor (Callable[[TrismikItem], Any]): Function to process test items.
26
- client (Optional[TrismikClient]): Trismik client to use for requests.
27
- auth (Optional[TrismikAuth]): Authentication token to use for requests
28
-
29
- Raises:
30
- TrismikApiError: If API request fails.
31
- """
32
- self._item_processor = item_processor
33
- self._client = client
34
- self._auth = auth
35
-
36
- async def run(self,
37
- test_id: str,
38
- session_metadata: TrismikSessionMetadata,
39
- with_responses: bool = False,
40
- ) -> TrismikRunResults:
41
- """
42
- Runs a test.
43
-
44
- Args:
45
- test_id (str): ID of the test to run.
46
- with_responses (bool): If True, responses will be included with the results.
47
-
48
- Returns:
49
- TrismikRunResults: Either just test results, or with responses.
50
-
51
- Raises:
52
- TrismikApiError: If API request fails.
53
- """
54
- await self._init()
55
- await self._refresh_token_if_needed()
56
- session = await self._client.create_session(test_id, session_metadata, self._auth.token)
57
-
58
- await self._run_session(session.url)
59
- results = await self._client.results(session.url, self._auth.token)
60
-
61
- if with_responses:
62
- responses = await self._client.responses(session.url,
63
- self._auth.token)
64
- return TrismikRunResults(session.id, results, responses)
65
- else:
66
- return TrismikRunResults(session.id, results)
67
-
68
- async def run_replay(self,
69
- previous_session_id: str,
70
- session_metadata: TrismikSessionMetadata,
71
- with_responses: bool = False,
72
- ) -> TrismikRunResults:
73
- """
74
- Replay the exact sequence of questions from a previous session
75
-
76
- Args:
77
- previous_session_id (str): ID of a previous session to replay
78
- with_responses (bool): If True, responses will be included with the results.
79
-
80
- Returns:
81
- TrismikRunResults: Either just test results, or with responses.
82
-
83
- Raises:
84
- TrismikApiError: If API request fails.
85
- """
86
- await self._init()
87
- await self._refresh_token_if_needed()
88
- session = await self._client.create_replay_session(previous_session_id, session_metadata, self._auth.token)
89
-
90
- await self._run_session(session.url)
91
- results = await self._client.results(session.url, self._auth.token)
92
-
93
- if with_responses:
94
- responses = await self._client.responses(session.url, self._auth.token)
95
- return TrismikRunResults(session.id, results, responses)
96
- else:
97
- return TrismikRunResults(session.id, results)
98
-
99
- async def _run_session(self, session_url: str) -> None:
100
- await self._init()
101
- await self._refresh_token_if_needed()
102
- item = await self._client.current_item(session_url, self._auth.token)
103
- while item is not None:
104
- await self._refresh_token_if_needed()
105
- response = await self._item_processor(item)
106
- item = await self._client.respond_to_current_item(
107
- session_url, response, self._auth.token)
108
-
109
- async def _init(self) -> None:
110
- if self._client is None:
111
- self._client = TrismikAsyncClient()
112
-
113
- if self._auth is None:
114
- self._auth = await self._client.authenticate()
115
-
116
- async def _refresh_token_if_needed(self) -> None:
117
- if self._token_needs_refresh():
118
- self._auth = await self._client.refresh_token(self._auth.token)
119
-
120
- def _token_needs_refresh(self) -> bool:
121
- return self._auth.expires < (datetime.now() + timedelta(minutes=5))
@@ -1,54 +0,0 @@
1
- Metadata-Version: 2.3
2
- Name: trismik
3
- Version: 0.9.1
4
- Summary:
5
- Author: Bartosz Kielczewski
6
- Author-email: bk352@cam.ac.uk
7
- Requires-Python: >=3.8
8
- Classifier: Programming Language :: Python :: 3
9
- Classifier: Programming Language :: Python :: 3.8
10
- Classifier: Programming Language :: Python :: 3.9
11
- Classifier: Programming Language :: Python :: 3.10
12
- Classifier: Programming Language :: Python :: 3.11
13
- Classifier: Programming Language :: Python :: 3.12
14
- Classifier: Programming Language :: Python :: 3.13
15
- Requires-Dist: httpx (>=0.27.2,<0.28.0)
16
- Requires-Dist: python-dateutil (>=2.9.0.post0,<3.0.0)
17
- Description-Content-Type: text/markdown
18
-
19
- Trismik Python SDK
20
- ==================
21
-
22
- This is the official Python SDK for Trismik. It provides a simple way to interact with the Trismik
23
- API.
24
-
25
- Usage
26
- -----
27
-
28
- 1. ```pip install trismik```
29
- 2. Set the following environment variable. Alternatively, put it into `.env` file
30
- in the root of your project, and load them using `python-dotenv` package:
31
-
32
- ```
33
- TRISMIK_API_KEY=<api_key>
34
- ```
35
-
36
- 3. Refer to examples:
37
- * [example_runner.py](./examples/example_runner.py) - run test using high-level `TrismikRunner`
38
- class
39
- * [example_runner_async.py](./examples/example_runner_async.py) - like above, but with async
40
- support
41
- * [example_client.py](./examples/example_client.py) - run test using `TrismikClient` directly
42
- * [example_client_async.py](./examples/example_client_async.py) - like above, but with async
43
- support
44
-
45
- Contributing
46
- ------------
47
-
48
- 1. Install [Python Poetry](https://python-poetry.org/docs/#installing-with-the-official-installer)
49
- 2. ```git clone https://github.com/trismik/trismik-python.git```, or if cloned previously:
50
- ```git pull``` to update
51
- 3. ```cd ./trismik-python```
52
- 4. ```poetry install```
53
- 5. ```poetry run pytest```
54
-
@@ -1,13 +0,0 @@
1
- trismik/__init__.py,sha256=QO0sVXOB10dK8bHsWYnlZifwoTtvD6qf2H_F4Afpiuw,486
2
- trismik/_mapper.py,sha256=ZbU1y0B1E3T-mSGcU9eCIHpFYbaH59KmDOmNrKRO8Jw,2280
3
- trismik/_utils.py,sha256=uzfAU5uU383hmqSiSKNhsmBTSnpzR1wtjZq6qO0Vgd8,1151
4
- trismik/client.py,sha256=1hPLr4jNsWloBdYJewBI1GYvxBf1RFf3rRYc_3NhPIY,11644
5
- trismik/client_async.py,sha256=ysLYvzyn-4ET-wL-9HX62Nc5SAv2XwvjMQ7j82XQf4w,11693
6
- trismik/exceptions.py,sha256=QcAH95FeZNXl4eDTCvqq3OhHrK976de1wd7bNEIfa88,322
7
- trismik/runner.py,sha256=sO0oOuA49diShLz_v80Un1nE_v_lnbJAMCAP8QNwoR0,4036
8
- trismik/runner_async.py,sha256=MR8_S-dT86olSUH2NffY3139W8H4SixY3T2yixBS524,4367
9
- trismik/types.py,sha256=ZPO7STit-mZBSJ1jlMJa2QIPxBXrT_TT9cJfsYOPZWE,3120
10
- trismik-0.9.1.dist-info/LICENSE,sha256=tgetRhapGLh7ZxfknW6Mm-WobfziPd64nAK52X5XKaw,1077
11
- trismik-0.9.1.dist-info/METADATA,sha256=2XkPjBqdZw65AyGdrctsO0r4DtRG-4D7R9Hyu9g5m7A,1793
12
- trismik-0.9.1.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
13
- trismik-0.9.1.dist-info/RECORD,,