trismik 0.9.0__py3-none-any.whl → 0.9.4__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,172 @@
1
+ Metadata-Version: 2.3
2
+ Name: trismik
3
+ Version: 0.9.4
4
+ Summary:
5
+ Author: Bartosz Kielczewski
6
+ Author-email: bk352@cam.ac.uk
7
+ Requires-Python: >=3.9
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.9
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Provides-Extra: examples
15
+ Requires-Dist: accelerate (>=1.7.0,<2.0.0) ; extra == "examples"
16
+ Requires-Dist: notebook (>=7.4.4,<8.0.0) ; extra == "examples"
17
+ Requires-Dist: openai (>=1.81.0,<2.0.0) ; extra == "examples"
18
+ Requires-Dist: torch (>=2.7.0,<3.0.0) ; extra == "examples"
19
+ Requires-Dist: torchaudio (>=2.7.0,<3.0.0) ; extra == "examples"
20
+ Requires-Dist: torchvision (>=0.22.0,<1.0.0) ; extra == "examples"
21
+ Requires-Dist: transformers (>=4.51.3,<5.0.0) ; extra == "examples"
22
+ Description-Content-Type: text/markdown
23
+
24
+ <h1 align="center"> Trismik SDK</h1>
25
+
26
+ <p align="center">
27
+ <img alt="PyPI - Version" src="https://img.shields.io/pypi/v/trismik">
28
+ <img alt="Python Version" src="https://img.shields.io/badge/python-3.9%2B-blue">
29
+ <img alt="License" src="https://img.shields.io/badge/license-MIT-green">
30
+ </p>
31
+
32
+ ## Table of Contents
33
+ - [Overview](#overview)
34
+ - [Quick Start](#quick-start)
35
+ - [Installation](#installation)
36
+ - [API Key Setup](#api-key-setup)
37
+ - [Basic Usage](#basic-usage)
38
+ - [Interpreting Results](#interpreting-results)
39
+ - [Theta (θ)](#theta-θ)
40
+ - [Other Metrics](#other-metrics)
41
+ - [Contributing](#contributing)
42
+ - [License](#license)
43
+
44
+ ## Overview
45
+
46
+ [**Trismik**](https://trismik.com) is a Cambridge, UK based startup offering adversarial testing for LLMs. The APIs we provide through this library allow you to call our adaptive test engine and evaluate LLMs up to 95% faster (and cheaper!) than traditional evaluation techniques.
47
+
48
+ Our **adaptive testing** algorithm allows to estimate the precision of the model by looking only at a small portion of a dataset. Through this library, we provide access to a number of open source datasets over several dimensions (reasoning, toxicity, tool use...) to speed up model testing in several scenarios, like foundation model training, supervised fine tuning, prompt engineering, and so on.
49
+
50
+ ## Quick Start
51
+
52
+ ### Installation
53
+
54
+ To use our API, you need to get an API key first. Please register on [dashboard.trismik.com](https://dashboard.trismik.com) and obtain an API key.
55
+
56
+ Trismik is available via [pypi](https://pypi.org/project/trismik/). To install Trismik, run the following in your terminal (in a virtualenv, if you use one):
57
+
58
+ ```bash
59
+ pip install trismik
60
+ ```
61
+
62
+ ### API Key Setup
63
+
64
+ You can provide your API key in one of the following ways:
65
+
66
+ 1. **Environment Variable**:
67
+ ```bash
68
+ export TRISMIK_API_KEY="your-api-key"
69
+ ```
70
+
71
+ 2. **`.env` File**:
72
+ ```bash
73
+ # .env
74
+ TRISMIK_API_KEY=your-api-key
75
+ ```
76
+ Then load it with `python-dotenv`:
77
+ ```python
78
+ from dotenv import load_dotenv
79
+ load_dotenv()
80
+ ```
81
+
82
+ 3. **Direct Initialization**:
83
+ ```python
84
+ client = TrismikAsyncClient(api_key="YOUR_API_KEY")
85
+ ```
86
+
87
+ ### Basic Usage
88
+
89
+ Running a test is straightforward:
90
+
91
+ 1. Implement a method that wraps model inference over a dataset item
92
+ 2. Create an `AdaptiveTest` instance
93
+ 3. Run the test!
94
+
95
+ Here's a basic example:
96
+
97
+ ```python
98
+ def model_inference(item: TrismikItem) -> Any:
99
+ model_output = ... # call your model here
100
+ return model_output
101
+
102
+
103
+ # Initialize the test runner
104
+ runner = AdaptiveTest(model_inference)
105
+
106
+ # Run the test
107
+ results = await runner.run_async(
108
+ "MMLUPro2025", # or any dataset we support
109
+ with_responses=True,
110
+ run_metadata=sample_metadata,
111
+ )
112
+
113
+ # Print the test output
114
+ for result in results:
115
+ print(f"{result.trait} ({result.name}): {result.value}")
116
+ ```
117
+
118
+ ### Examples
119
+
120
+ You can find more examples in the `examples` folder:
121
+ - [`example_transformers.py`](examples/example_transformers.py) - Example using Hugging Face Transformers models
122
+ - [`example_openai.py`](examples/example_openai.py) - Example using OpenAI models
123
+ - [`example_adaptive_test.py`](examples/example_adaptive_test.py) - Example of adaptive testing configuration
124
+
125
+ To run the examples, you will need to clone this repo, navigate to the
126
+ source folder, and then run:
127
+
128
+ ```bash
129
+ poetry install --with examples
130
+ poetry run python examples/example_adaptive_test.py # or any other example
131
+ ```
132
+
133
+ ## Interpreting Results
134
+
135
+ ### Theta (θ)
136
+
137
+ Our adversarial test returns several values; however, you will be interested mainly in `theta`. Theta ($\theta$) is our metric; it measures the ability of the model on a certain dataset, and it can be used as a proxy to approximate the original metric used on that dataset. For example, on an accuracy-based dataset, a high theta correlates with a high accuracy, and low theta correlates with low accuracy.
138
+
139
+ To interpret a theta score, consider that $\theta=0$ corresponds to a 50% chance for a model to get an answer right - in other words, to an accuracy of 50%.
140
+ A negative theta means that the model will give more bad answers then good ones, while a positive theta means that the model will give more good answers then bad answers.
141
+ While theta is unbounded in our implementation (i.e. $-\infty < \theta < \infty$), in practice we have that for most cases $\theta$ will take values between -3 and 3.
142
+
143
+ Compared to classical benchmark testing, the estimated accuracy from adaptive testing uses fewer but more informative items while avoiding noise from overly easy or difficult questions. This makes it a more efficient and stable measure, especially on very large datasets.
144
+
145
+ ### Other Metrics
146
+
147
+ - **Standard Deviation (`std`)**:
148
+ - A measure of the uncertainty or error in the theta estimate
149
+ - A smaller `std` indicates a more precise estimate
150
+ - You should see a `std` around or below 0.25
151
+
152
+ - **Correct Responses (`responsesCorrect`)**:
153
+ - The number of correct answers delivered by the model
154
+
155
+ - **Important note**: A higher number of correct answers does not necessarily
156
+ correlate with a high theta. Our algorithm navigates the dataset to find a
157
+ balance of “hard” and “easy” items for your model, so by the end of the test,
158
+ it encounters a representative mix of inputs it can and cannot handle. In
159
+ practice, expect responsesCorrect to be roughly half of responsesTotal.
160
+
161
+ - **Total Responses (`responsesTotal`)**:
162
+ - The number of items processed before reaching a stable theta.
163
+ - Expected range: 60 ≤ responses_total ≤ 80
164
+
165
+ ## Contributing
166
+
167
+ See `CONTRIBUTING.md`.
168
+
169
+ ## License
170
+
171
+ This library is licensed under the MIT license. See `LICENSE` file.
172
+
@@ -0,0 +1,12 @@
1
+ trismik/__init__.py,sha256=20SwXrda9YsgykaoPohwz6foj2FkraniPA-GTQS9m00,197
2
+ trismik/_mapper.py,sha256=A1mik1jlF7hm9oyq5Of-BZtA16MVhVJv1AI_20PKv2k,10315
3
+ trismik/_utils.py,sha256=WZ7x0EaG7PdXdFZMIs1wzgwqiPQm59QDDmQzBKYGCEg,3753
4
+ trismik/adaptive_test.py,sha256=hLGdf0jgLmJJ55I9c5QjaEd1bCA8QNfhJJoOBkF38ik,20002
5
+ trismik/client_async.py,sha256=ZOvAH-nTnh_S3mrpLuprxtByZBasTnNCysBwUPwXMb0,12523
6
+ trismik/exceptions.py,sha256=2wb4_K7GdDf00s3xUaiSfw6718ZV3Eaa4M2lYbiEZl4,1945
7
+ trismik/settings.py,sha256=FCP-d8ZEiYWUTWoa9nOVzSwTOLvg8y0pU08dAseiOwY,412
8
+ trismik/types.py,sha256=OS0npQV6FgN5DRE1Ebd4tY1Z8_R_K6SSzRdHvKdosug,6240
9
+ trismik-0.9.4.dist-info/LICENSE,sha256=tgetRhapGLh7ZxfknW6Mm-WobfziPd64nAK52X5XKaw,1077
10
+ trismik-0.9.4.dist-info/METADATA,sha256=2N19pz_qSvCRolCF_2Cw7TaScnXRopj7gy87KlXiyoQ,6619
11
+ trismik-0.9.4.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
12
+ trismik-0.9.4.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.9.0
2
+ Generator: poetry-core 2.1.3
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
trismik/client.py DELETED
@@ -1,274 +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
- )
16
-
17
-
18
- class TrismikClient:
19
- _serviceUrl: str = "https://trismik.e-psychometrics.com/api"
20
-
21
- def __init__(
22
- self,
23
- service_url: Optional[str] = None,
24
- api_key: Optional[str] = None,
25
- http_client: Optional[httpx.Client] | None = None,
26
- ) -> None:
27
- """
28
- Initializes a new Trismik client.
29
-
30
- Args:
31
- service_url (Optional[str]): URL of the Trismik service.
32
- api_key (Optional[str]): API key for the Trismik service.
33
- http_client (Optional[httpx.Client]): HTTP client to use for requests.
34
-
35
- Raises:
36
- TrismikError: If service_url or api_key are not provided and not found in environment.
37
- TrismikApiError: If API request fails.
38
- """
39
- self._service_url = TrismikUtils.option(
40
- service_url, self._serviceUrl, "TRISMIK_SERVICE_URL"
41
- )
42
- self._api_key = TrismikUtils.required_option(
43
- api_key, "api_key", "TRISMIK_API_KEY"
44
- )
45
- self._http_client = http_client or httpx.Client(
46
- base_url=self._service_url)
47
-
48
- def authenticate(self) -> TrismikAuth:
49
- """
50
- Authenticates with the Trismik service.
51
-
52
- Returns:
53
- TrismikAuth: Authentication token.
54
-
55
- Raises:
56
- TrismikApiError: If API request fails.
57
- """
58
- try:
59
- url = "/client/auth"
60
- body = {"apiKey": self._api_key}
61
- response = self._http_client.post(url, json=body)
62
- response.raise_for_status()
63
- json = response.json()
64
- return TrismikResponseMapper.to_auth(json)
65
- except httpx.HTTPStatusError as e:
66
- raise TrismikApiError(
67
- TrismikUtils.get_error_message(e.response)) from e
68
- except httpx.HTTPError as e:
69
- raise TrismikApiError(str(e)) from e
70
-
71
- def refresh_token(self, token: str) -> TrismikAuth:
72
- """
73
- Refreshes the authentication token.
74
-
75
- Args:
76
- token (str): Current authentication token.
77
-
78
- Returns:
79
- TrismikAuth: New authentication token.
80
-
81
- Raises:
82
- TrismikApiError: If API request fails.
83
- """
84
- try:
85
- url = "/client/token"
86
- headers = {"Authorization": f"Bearer {token}"}
87
- response = self._http_client.get(url, headers=headers)
88
- response.raise_for_status()
89
- json = response.json()
90
- return TrismikResponseMapper.to_auth(json)
91
- except httpx.HTTPStatusError as e:
92
- raise TrismikApiError(
93
- TrismikUtils.get_error_message(e.response)) from e
94
- except httpx.HTTPError as e:
95
- raise TrismikApiError(str(e)) from e
96
-
97
- def available_tests(self, token: str) -> List[TrismikTest]:
98
- """
99
- Retrieves a list of available tests.
100
-
101
- Args:
102
- token (str): Authentication token.
103
-
104
- Returns:
105
- List[TrismikTest]: List of available tests.
106
-
107
- Raises:
108
- TrismikApiError: If API request fails.
109
- """
110
- try:
111
- url = "/client/tests"
112
- headers = {"Authorization": f"Bearer {token}"}
113
- response = self._http_client.get(url, headers=headers)
114
- response.raise_for_status()
115
- json = response.json()
116
- return TrismikResponseMapper.to_tests(json)
117
- except httpx.HTTPStatusError as e:
118
- raise TrismikApiError(
119
- TrismikUtils.get_error_message(e.response)) from e
120
- except httpx.HTTPError as e:
121
- raise TrismikApiError(str(e)) from e
122
-
123
- def create_session(self, test_id: str, token: str) -> TrismikSession:
124
- """
125
- Creates a new session for a test.
126
-
127
- Args:
128
- test_id (str): ID of the test.
129
- token (str): Authentication token.
130
-
131
- Returns:
132
- TrismikSession: New session
133
-
134
- Raises:
135
- TrismikApiError: If API request fails.
136
- """
137
- try:
138
- url = "/client/sessions"
139
- headers = {"Authorization": f"Bearer {token}"}
140
- body = {"testId": test_id, }
141
- response = self._http_client.post(url, headers=headers, json=body)
142
- response.raise_for_status()
143
- json = response.json()
144
- return TrismikResponseMapper.to_session(json)
145
- except httpx.HTTPStatusError as e:
146
- raise TrismikApiError(
147
- TrismikUtils.get_error_message(e.response)) from e
148
- except httpx.HTTPError as e:
149
- raise TrismikApiError(str(e)) from e
150
-
151
- def current_item(
152
- self,
153
- session_url: str,
154
- token: str
155
- ) -> TrismikItem:
156
- """
157
- Retrieves the current test item.
158
-
159
- Args:
160
- session_url (str): URL of the session.
161
- token (str): Authentication token.
162
-
163
- Returns:
164
- TrismikItem: Current test item.
165
-
166
- Raises:
167
- TrismikApiError: If API request fails.
168
- """
169
- try:
170
- url = f"{session_url}/item"
171
- headers = {"Authorization": f"Bearer {token}"}
172
- response = self._http_client.get(url, headers=headers)
173
- response.raise_for_status()
174
- json = response.json()
175
- return TrismikResponseMapper.to_item(json)
176
- except httpx.HTTPStatusError as e:
177
- raise TrismikApiError(
178
- TrismikUtils.get_error_message(e.response)) from e
179
- except httpx.HTTPError as e:
180
- raise TrismikApiError(str(e)) from e
181
-
182
- def respond_to_current_item(
183
- self,
184
- session_url: str,
185
- value: Any,
186
- token: str
187
- ) -> TrismikItem | None:
188
- """
189
- Responds to the current test item.
190
-
191
- Args:
192
- session_url (str): URL of the session.
193
- value (Any): Response value.
194
- token (str): Authentication token.
195
-
196
- Returns:
197
- TrismikItem | None: Next test item or None if session is finished.
198
-
199
- Raises:
200
- TrismikApiError: If API request fails.
201
- """
202
- try:
203
- url = f"{session_url}/item"
204
- body = {"value": value}
205
- headers = {"Authorization": f"Bearer {token}"}
206
- response = self._http_client.post(url, headers=headers, json=body)
207
- response.raise_for_status()
208
- if response.status_code == 204:
209
- return None
210
- else:
211
- json = response.json()
212
- return TrismikResponseMapper.to_item(json)
213
- except httpx.HTTPStatusError as e:
214
- raise TrismikApiError(
215
- TrismikUtils.get_error_message(e.response)) from e
216
- except httpx.HTTPError as e:
217
- raise TrismikApiError(str(e)) from e
218
-
219
- def results(self, session_url: str, token: str) -> List[TrismikResult]:
220
- """
221
- Retrieves the results of a session.
222
-
223
- Args:
224
- session_url (str): URL of the session.
225
- token (str): Authentication token.
226
-
227
- Returns:
228
- List[TrismikResult]: Results of the session.
229
-
230
- Raises:
231
- TrismikApiError: If API request fails.
232
- """
233
- try:
234
- url = f"{session_url}/results"
235
- headers = {"Authorization": f"Bearer {token}"}
236
- response = self._http_client.get(url, headers=headers)
237
- response.raise_for_status()
238
- json = response.json()
239
- return TrismikResponseMapper.to_results(json)
240
- except httpx.HTTPStatusError as e:
241
- raise TrismikApiError(
242
- TrismikUtils.get_error_message(e.response)) from e
243
- except httpx.HTTPError as e:
244
- raise TrismikApiError(str(e)) from e
245
-
246
- def responses(self,
247
- session_url: str,
248
- token: str
249
- ) -> List[TrismikResponse]:
250
- """
251
- Retrieves responses to session items.
252
-
253
- Args:
254
- session_url (str): URL of the session.
255
- token (str): Authentication token.
256
-
257
- Returns:
258
- List[TrismikResponse]: Responses of the session.
259
-
260
- Raises:
261
- TrismikApiError: If API request fails.
262
- """
263
- try:
264
- url = f"{session_url}/responses"
265
- headers = {"Authorization": f"Bearer {token}"}
266
- response = self._http_client.get(url, headers=headers)
267
- response.raise_for_status()
268
- json = response.json()
269
- return TrismikResponseMapper.to_responses(json)
270
- except httpx.HTTPStatusError as e:
271
- raise TrismikApiError(
272
- TrismikUtils.get_error_message(e.response)) from e
273
- except httpx.HTTPError as e:
274
- raise TrismikApiError(str(e)) from e
trismik/runner.py DELETED
@@ -1,85 +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
- TrismikResultsAndResponses,
10
- )
11
-
12
-
13
- class TrismikRunner:
14
- def __init__(
15
- self,
16
- item_processor: Callable[[TrismikItem], Any],
17
- client: Optional[TrismikClient] = None,
18
- auth: Optional[TrismikAuth] = None,
19
- ) -> None:
20
- """
21
- Initializes a new Trismik runner.
22
-
23
- Args:
24
- item_processor (Callable[[TrismikItem], Any]): Function to process test items.
25
- client (Optional[TrismikClient]): Trismik client to use for requests.
26
- auth (Optional[TrismikAuth]): Authentication token to use for requests
27
-
28
- Raises:
29
- TrismikApiError: If API request fails.
30
- """
31
- self._item_processor = item_processor
32
- self._client = client
33
- self._auth = auth
34
-
35
- def run(self,
36
- test_id: str,
37
- with_responses: bool = False,
38
- ) -> List[TrismikResult] | TrismikResultsAndResponses:
39
- """
40
- Runs a test.
41
-
42
- Args:
43
- test_id (str): ID of the test to run.
44
- with_responses (bool): If True, responses will be included with the results.
45
-
46
- Returns:
47
- List[TrismikResult] | TrismikResultsAndResponses: Either just test results, or with responses.
48
-
49
- Raises:
50
- TrismikApiError: If API request fails.
51
- """
52
- self._init()
53
- self._refresh_token_if_needed()
54
- session = self._client.create_session(test_id, self._auth.token)
55
- self._run_session(session.url)
56
- results = self._client.results(session.url, self._auth.token)
57
-
58
- if with_responses:
59
- responses = self._client.responses(session.url, self._auth.token)
60
- return TrismikResultsAndResponses(results, responses)
61
- else:
62
- return results
63
-
64
- def _run_session(self, session_url: str) -> None:
65
- item = self._client.current_item(session_url, self._auth.token)
66
- while item is not None:
67
- self._refresh_token_if_needed()
68
- response = self._item_processor(item)
69
- item = self._client.respond_to_current_item(
70
- session_url, response, self._auth.token
71
- )
72
-
73
- def _init(self) -> None:
74
- if self._client is None:
75
- self._client = TrismikClient()
76
-
77
- if self._auth is None:
78
- self._auth = self._client.authenticate()
79
-
80
- def _refresh_token_if_needed(self) -> None:
81
- if self._token_needs_refresh():
82
- self._auth = self._client.refresh_token(self._auth.token)
83
-
84
- def _token_needs_refresh(self) -> bool:
85
- return self._auth.expires < (datetime.now() + timedelta(minutes=5))
trismik/runner_async.py DELETED
@@ -1,87 +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
- TrismikResultsAndResponses,
10
- )
11
-
12
-
13
- class TrismikAsyncRunner:
14
- def __init__(
15
- self,
16
- item_processor: Callable[[TrismikItem], Awaitable[Any]],
17
- client: Optional[TrismikAsyncClient] = None,
18
- auth: Optional[TrismikAuth] = None,
19
- ) -> None:
20
- """
21
- Initializes a new Trismik runner (async version).
22
-
23
- Args:
24
- item_processor (Callable[[TrismikItem], Any]): Function to process test items.
25
- client (Optional[TrismikClient]): Trismik client to use for requests.
26
- auth (Optional[TrismikAuth]): Authentication token to use for requests
27
-
28
- Raises:
29
- TrismikApiError: If API request fails.
30
- """
31
- self._item_processor = item_processor
32
- self._client = client
33
- self._auth = auth
34
-
35
- async def run(self,
36
- test_id: str,
37
- with_responses: bool = False,
38
- ) -> List[TrismikResult] | TrismikResultsAndResponses:
39
- """
40
- Runs a test.
41
-
42
- Args:
43
- test_id (str): ID of the test to run.
44
- with_responses (bool): If True, responses will be included with the results.
45
-
46
- Returns:
47
- List[TrismikResult] | TrismikResultsAndResponses: Either just test results, or with responses.
48
-
49
- Raises:
50
- TrismikApiError: If API request fails.
51
- """
52
- await self._init()
53
- await self._refresh_token_if_needed()
54
- session = await self._client.create_session(test_id, self._auth.token)
55
- await self._run_session(session.url)
56
- results = await self._client.results(session.url, self._auth.token)
57
-
58
- if with_responses:
59
- responses = await self._client.responses(session.url,
60
- self._auth.token)
61
- return TrismikResultsAndResponses(results, responses)
62
- else:
63
- return results
64
-
65
- async def _run_session(self, session_url: str) -> None:
66
- await self._init()
67
- await self._refresh_token_if_needed()
68
- item = await self._client.current_item(session_url, self._auth.token)
69
- while item is not None:
70
- await self._refresh_token_if_needed()
71
- response = await self._item_processor(item)
72
- item = await self._client.respond_to_current_item(
73
- session_url, response, self._auth.token)
74
-
75
- async def _init(self) -> None:
76
- if self._client is None:
77
- self._client = TrismikAsyncClient()
78
-
79
- if self._auth is None:
80
- self._auth = await self._client.authenticate()
81
-
82
- async def _refresh_token_if_needed(self) -> None:
83
- if self._token_needs_refresh():
84
- self._auth = await self._client.refresh_token(self._auth.token)
85
-
86
- def _token_needs_refresh(self) -> bool:
87
- return self._auth.expires < (datetime.now() + timedelta(minutes=5))
@@ -1,60 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: trismik
3
- Version: 0.9.0
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
- Requires-Dist: httpx (>=0.27.2,<0.28.0)
15
- Requires-Dist: python-dateutil (>=2.9.0.post0,<3.0.0)
16
- Description-Content-Type: text/markdown
17
-
18
- Trismik Python SDK
19
- ==================
20
-
21
- This is the official Python SDK for Trismik. It provides a simple way to interact with the Trismik
22
- API.
23
-
24
- Usage
25
- -----
26
-
27
- 1. ```pip install trismik```
28
- 2. Set the following environment variable. Alternatively, put it into `.env` file
29
- in the root of your project, and load them using `python-dotenv` package:
30
-
31
- ```
32
- TRISMIK_API_KEY=<api_key>
33
- ```
34
-
35
- 3. Refer to examples:
36
- * [example_runner.py](./examples/example_runner.py) - run test using high-level `TrismikRunner`
37
- class
38
- * [example_runner_async.py](./examples/example_runner_async.py) - like above, but with async
39
- support
40
- * [example_client.py](./examples/example_client.py) - run test using `TrismikClient` directly
41
- * [example_client_async.py](./examples/example_client_async.py) - like above, but with async
42
- support
43
-
44
- Contributing
45
- ------------
46
-
47
- 1. Install [Python Poetry](https://python-poetry.org/docs/#installing-with-the-official-installer)
48
- 2. ```git clone https://github.com/trismik/trismik-python.git```, or if cloned previously:
49
- ```git pull``` to update
50
- 3. ```cd ./trismik-python```
51
- 4. ```poetry install```
52
- 5. ```poetry run pytest```
53
-
54
- Publishing to TestPyPi
55
- ----------------------
56
-
57
- 1. ```poetry config repositories.testpypi https://test.pypi.org/legacy/```
58
- 2. ```poetry config pypi-token.testpypi <token>```
59
- 3. ```poetry publish --build --repository testpypi```
60
-