hse-sampletracker-client 0.1.1__tar.gz
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.
- hse_sampletracker_client-0.1.1/.gitea/workflows/ci.yml +75 -0
- hse_sampletracker_client-0.1.1/.gitignore +47 -0
- hse_sampletracker_client-0.1.1/CHANGELOG.md +37 -0
- hse_sampletracker_client-0.1.1/LICENSE.txt +18 -0
- hse_sampletracker_client-0.1.1/PKG-INFO +238 -0
- hse_sampletracker_client-0.1.1/README.md +208 -0
- hse_sampletracker_client-0.1.1/pyproject.toml +76 -0
- hse_sampletracker_client-0.1.1/src/sampletracker/__about__.py +4 -0
- hse_sampletracker_client-0.1.1/src/sampletracker/__init__.py +28 -0
- hse_sampletracker_client-0.1.1/src/sampletracker/__main__.py +9 -0
- hse_sampletracker_client-0.1.1/src/sampletracker/client.py +164 -0
- hse_sampletracker_client-0.1.1/src/sampletracker/exceptions.py +42 -0
- hse_sampletracker_client-0.1.1/src/sampletracker/models.py +248 -0
- hse_sampletracker_client-0.1.1/src/sampletracker/run.py +247 -0
- hse_sampletracker_client-0.1.1/tests/__init__.py +3 -0
- hse_sampletracker_client-0.1.1/tests/test_models.py +352 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, master]
|
|
6
|
+
tags: ['v*']
|
|
7
|
+
pull_request:
|
|
8
|
+
branches: [main, master]
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
test:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
strategy:
|
|
14
|
+
matrix:
|
|
15
|
+
python-version: ['3.10', '3.11', '3.12', '3.13', '3.14']
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
21
|
+
uses: actions/setup-python@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: ${{ matrix.python-version }}
|
|
24
|
+
|
|
25
|
+
- name: Install dependencies
|
|
26
|
+
run: |
|
|
27
|
+
python -m pip install --upgrade pip
|
|
28
|
+
pip install -e ".[dev]"
|
|
29
|
+
pip install pytest mypy build hatch
|
|
30
|
+
|
|
31
|
+
- name: Run type checking
|
|
32
|
+
run: |
|
|
33
|
+
mypy src/sampletracker --ignore-missing-imports
|
|
34
|
+
|
|
35
|
+
- name: Run tests
|
|
36
|
+
run: |
|
|
37
|
+
pytest tests/ -v
|
|
38
|
+
|
|
39
|
+
- name: Build package
|
|
40
|
+
run: |
|
|
41
|
+
hatch build
|
|
42
|
+
|
|
43
|
+
- name: Check package
|
|
44
|
+
run: |
|
|
45
|
+
pip install twine
|
|
46
|
+
twine check dist/*
|
|
47
|
+
|
|
48
|
+
publish-pypi:
|
|
49
|
+
needs: test
|
|
50
|
+
runs-on: ubuntu-latest
|
|
51
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
52
|
+
|
|
53
|
+
steps:
|
|
54
|
+
- uses: actions/checkout@v4
|
|
55
|
+
|
|
56
|
+
- name: Set up Python
|
|
57
|
+
uses: actions/setup-python@v5
|
|
58
|
+
with:
|
|
59
|
+
python-version: '3.11'
|
|
60
|
+
|
|
61
|
+
- name: Install dependencies
|
|
62
|
+
run: |
|
|
63
|
+
python -m pip install --upgrade pip
|
|
64
|
+
pip install hatch
|
|
65
|
+
|
|
66
|
+
- name: Build package
|
|
67
|
+
run: |
|
|
68
|
+
hatch build
|
|
69
|
+
|
|
70
|
+
- name: Publish to PyPI
|
|
71
|
+
env:
|
|
72
|
+
HATCH_INDEX_USER: __token__
|
|
73
|
+
HATCH_INDEX_AUTH: ${{ secrets.PYPI_APIKEY }}
|
|
74
|
+
run: |
|
|
75
|
+
hatch publish
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Local environment variables
|
|
2
|
+
.env
|
|
3
|
+
.env.local
|
|
4
|
+
|
|
5
|
+
# Python
|
|
6
|
+
__pycache__/
|
|
7
|
+
*.py[cod]
|
|
8
|
+
*$py.class
|
|
9
|
+
*.so
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
*.egg-info/
|
|
24
|
+
.installed.cfg
|
|
25
|
+
*.egg
|
|
26
|
+
|
|
27
|
+
# Virtual environments
|
|
28
|
+
venv/
|
|
29
|
+
ENV/
|
|
30
|
+
env/
|
|
31
|
+
.venv
|
|
32
|
+
|
|
33
|
+
# IDE
|
|
34
|
+
.idea/
|
|
35
|
+
.vscode/
|
|
36
|
+
*.swp
|
|
37
|
+
*.swo
|
|
38
|
+
*~
|
|
39
|
+
|
|
40
|
+
# Testing
|
|
41
|
+
.pytest_cache/
|
|
42
|
+
.coverage
|
|
43
|
+
htmlcov/
|
|
44
|
+
|
|
45
|
+
# OS
|
|
46
|
+
.DS_Store
|
|
47
|
+
Thumbs.db
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.1.0] - 2026-05-09
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Synchronous API client (`SampleTrackerClient`) for interacting with SampleTracker API
|
|
15
|
+
- Support for listing samples with pagination (`list_samples` method)
|
|
16
|
+
- Support for retrieving detailed sample information with history (`load_sample` method)
|
|
17
|
+
- Command-line interface (`sampletracker`) for listing and viewing samples
|
|
18
|
+
- Dataclass-based models with full type hints:
|
|
19
|
+
- `SampleListItem` for list responses
|
|
20
|
+
- `Sample` for detailed sample views with history
|
|
21
|
+
- `StepEvent` and `ObservationEvent` for timeline events
|
|
22
|
+
- `Parameter` for step parameters
|
|
23
|
+
- `SampleStats` for aggregated counts
|
|
24
|
+
- Comprehensive exception hierarchy for error handling:
|
|
25
|
+
- `SampleTrackerError` (base)
|
|
26
|
+
- `SampleTrackerAuthError` (401)
|
|
27
|
+
- `SampleTrackerNotFoundError` (404)
|
|
28
|
+
- `SampleTrackerValidationError` (422)
|
|
29
|
+
- `SampleTrackerRateLimitError` (429)
|
|
30
|
+
- `SampleTrackerAPIError` (generic)
|
|
31
|
+
- Environment variable configuration support (`SAMPLETRACKER_API_KEY`, `SAMPLETRACKER_BASE_URL`)
|
|
32
|
+
- Automatic `.env` file loading for CLI
|
|
33
|
+
- Bearer token authentication
|
|
34
|
+
- Support for Python 3.8 through 3.14 and PyPy
|
|
35
|
+
|
|
36
|
+
[unreleased]: https://github.com/Alexander Schramm/sampletracker/compare/v0.1.0...HEAD
|
|
37
|
+
[0.1.0]: https://github.com/Alexander Schramm/sampletracker/releases/tag/v0.1.0
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026-present Alexander Schramm <alexander.schramm96@gmail.com>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
|
6
|
+
associated documentation files (the "Software"), to deal in the Software without restriction, including
|
|
7
|
+
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
|
|
9
|
+
following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial
|
|
12
|
+
portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
|
15
|
+
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
|
|
16
|
+
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
17
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
18
|
+
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hse-sampletracker-client
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: A Pythonic client library for the SampleTracker SaaS API
|
|
5
|
+
Project-URL: Documentation, https://github.com/Alexander Schramm/sampletracker#readme
|
|
6
|
+
Project-URL: Issues, https://github.com/Alexander Schramm/sampletracker/issues
|
|
7
|
+
Project-URL: Source, https://github.com/Alexander Schramm/sampletracker
|
|
8
|
+
Author-email: Alexander Schramm <info@expectiq.com>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE.txt
|
|
11
|
+
Keywords: api,client,hse,laboratory,samples,sampletracker
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
22
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
23
|
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
24
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
|
25
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
26
|
+
Classifier: Typing :: Typed
|
|
27
|
+
Requires-Python: >=3.10
|
|
28
|
+
Requires-Dist: httpx>=0.24.0
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# HSE SampleTracker Client
|
|
32
|
+
|
|
33
|
+
[](https://pypi.org/project/hse-sampletracker-client)
|
|
34
|
+
[](https://pypi.org/project/hse-sampletracker-client)
|
|
35
|
+
[](LICENSE.txt)
|
|
36
|
+
|
|
37
|
+
A Pythonic client library for the HSE SampleTracker API - manage laboratory samples, processing steps, and observations with ease.
|
|
38
|
+
|
|
39
|
+
## Features
|
|
40
|
+
|
|
41
|
+
- **Synchronous API Client** - Simple, blocking HTTP client using `httpx`
|
|
42
|
+
- **Type Hints Throughout** - Fully typed for better IDE support and code safety
|
|
43
|
+
- **Command-Line Interface** - Interactive CLI for quick sample management
|
|
44
|
+
- **Pydantic-like Models** - Dataclass-based models with `from_dict` constructors
|
|
45
|
+
- **Comprehensive Exceptions** - Clear error hierarchy for different failure modes
|
|
46
|
+
- **Environment Configuration** - Support for `.env` files and environment variables
|
|
47
|
+
- **Pagination Support** - Built-in cursor-based pagination for listing samples
|
|
48
|
+
|
|
49
|
+
## Installation
|
|
50
|
+
|
|
51
|
+
```console
|
|
52
|
+
pip install hse-sampletracker-client
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Quick Start
|
|
56
|
+
|
|
57
|
+
### Using the Python API
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from sampletracker import SampleTrackerClient
|
|
61
|
+
|
|
62
|
+
# Create a client
|
|
63
|
+
client = SampleTrackerClient(
|
|
64
|
+
api_key="your-api-key",
|
|
65
|
+
base_url="https://your-instance.com/api/v1"
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
# List samples
|
|
69
|
+
samples = client.list_samples(limit=10)
|
|
70
|
+
for sample in samples:
|
|
71
|
+
print(f"{sample.sample_id}: {sample.name}")
|
|
72
|
+
|
|
73
|
+
# Get detailed sample information
|
|
74
|
+
sample = client.load_sample("SAMPLE-123")
|
|
75
|
+
print(f"Description: {sample.description}")
|
|
76
|
+
print(f"Steps: {sample.stats.step_count}")
|
|
77
|
+
print(f"Observations: {sample.stats.observation_count}")
|
|
78
|
+
|
|
79
|
+
# View history
|
|
80
|
+
for event in sample.history:
|
|
81
|
+
if hasattr(event, 'name'): # StepEvent
|
|
82
|
+
print(f"Step: {event.name}")
|
|
83
|
+
else: # ObservationEvent
|
|
84
|
+
print(f"Observation: {event.content}")
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Using the CLI
|
|
88
|
+
|
|
89
|
+
Set up your environment:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# Option 1: Environment variables
|
|
93
|
+
export SAMPLETRACKER_API_KEY="your-api-key"
|
|
94
|
+
export SAMPLETRACKER_BASE_URL="https://your-instance.com/api/v1"
|
|
95
|
+
|
|
96
|
+
# Option 2: Create a .env file
|
|
97
|
+
echo "SAMPLETRACKER_API_KEY=your-api-key" > .env
|
|
98
|
+
echo "SAMPLETRACKER_BASE_URL=https://your-instance.com/api/v1" >> .env
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
List samples:
|
|
102
|
+
|
|
103
|
+
```console
|
|
104
|
+
$ sampletracker list --limit 5
|
|
105
|
+
ID | Sample ID | Name | Steps | Observations
|
|
106
|
+
--------------------------------------------------------------------------------
|
|
107
|
+
1 | sample-001 | test batch | 3 | 2
|
|
108
|
+
2 | M315SO23 | test batch (Copy) | 3 | 2
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
View sample details:
|
|
112
|
+
|
|
113
|
+
```console
|
|
114
|
+
$ sampletracker view sample-001
|
|
115
|
+
Sample Details:
|
|
116
|
+
ID: 1
|
|
117
|
+
Sample ID: sample-001
|
|
118
|
+
Name: test batch
|
|
119
|
+
Description: mein erster test
|
|
120
|
+
Owner ID: 2
|
|
121
|
+
Owner Email: admin@example.com
|
|
122
|
+
Created: 2026-04-25 13:14:13.126000+00:00
|
|
123
|
+
Updated: 2026-04-25 13:14:13.126000+00:00
|
|
124
|
+
Steps: 2
|
|
125
|
+
Observations: 2
|
|
126
|
+
|
|
127
|
+
History:
|
|
128
|
+
[Step] Backen
|
|
129
|
+
Performed: 2026-04-25 13:20:00+00:00
|
|
130
|
+
Parameters:
|
|
131
|
+
- Temperatur: 210 °C
|
|
132
|
+
[Observation] Das Ding ist heiß
|
|
133
|
+
Created: 2026-04-25 13:21:06.172000+00:00
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Configuration
|
|
137
|
+
|
|
138
|
+
### Environment Variables
|
|
139
|
+
|
|
140
|
+
| Variable | Description | Required |
|
|
141
|
+
|----------|-------------|----------|
|
|
142
|
+
| `SAMPLETRACKER_API_KEY` | Your API key | Yes |
|
|
143
|
+
| `SAMPLETRACKER_BASE_URL` | API base URL | No (defaults to official SaaS) |
|
|
144
|
+
|
|
145
|
+
### .env File
|
|
146
|
+
|
|
147
|
+
Create a `.env` file in your project root:
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
SAMPLETRACKER_API_KEY=your-api-key
|
|
151
|
+
SAMPLETRACKER_BASE_URL=https://your-instance.com/api/v1
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
The CLI automatically loads variables from `.env` files in the current or parent directories.
|
|
155
|
+
|
|
156
|
+
## API Reference
|
|
157
|
+
|
|
158
|
+
### SampleTrackerClient
|
|
159
|
+
|
|
160
|
+
The main client class for interacting with the API.
|
|
161
|
+
|
|
162
|
+
```python
|
|
163
|
+
client = SampleTrackerClient(
|
|
164
|
+
api_key: str, # Your API key
|
|
165
|
+
base_url: str | None, # Optional base URL
|
|
166
|
+
timeout: float | None # Optional timeout (default: 30s)
|
|
167
|
+
)
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Methods
|
|
171
|
+
|
|
172
|
+
#### `list_samples(limit: int = 10, after_id: int | None = None) -> list[SampleListItem]`
|
|
173
|
+
|
|
174
|
+
List samples with pagination support.
|
|
175
|
+
|
|
176
|
+
- `limit`: Number of samples to return (max: 100)
|
|
177
|
+
- `after_id`: Cursor for pagination (returns samples with ID > after_id)
|
|
178
|
+
|
|
179
|
+
#### `load_sample(sample_id: str) -> Sample | None`
|
|
180
|
+
|
|
181
|
+
Get detailed information about a specific sample, including history.
|
|
182
|
+
|
|
183
|
+
Returns `None` if the sample doesn't exist.
|
|
184
|
+
|
|
185
|
+
### Models
|
|
186
|
+
|
|
187
|
+
#### SampleListItem
|
|
188
|
+
|
|
189
|
+
Lightweight model for list responses:
|
|
190
|
+
|
|
191
|
+
- `id`: Internal database ID
|
|
192
|
+
- `sample_id`: User-facing sample identifier
|
|
193
|
+
- `name`: Sample name
|
|
194
|
+
- `description`: Optional description
|
|
195
|
+
- `owner_id`: Owner's user ID
|
|
196
|
+
- `created_at`: Creation timestamp
|
|
197
|
+
- `updated_at`: Last update timestamp
|
|
198
|
+
- `step_count`: Number of processing steps
|
|
199
|
+
- `observation_count`: Number of observations
|
|
200
|
+
|
|
201
|
+
#### Sample
|
|
202
|
+
|
|
203
|
+
Detailed model with full history:
|
|
204
|
+
|
|
205
|
+
- All fields from `SampleListItem`, plus:
|
|
206
|
+
- `owner_email`: Email of the owner
|
|
207
|
+
- `history`: List of `StepEvent` and `ObservationEvent`
|
|
208
|
+
- `stats`: `SampleStats` with aggregated counts
|
|
209
|
+
|
|
210
|
+
### Exceptions
|
|
211
|
+
|
|
212
|
+
All exceptions inherit from `SampleTrackerError`:
|
|
213
|
+
|
|
214
|
+
- `SampleTrackerAuthError` - Authentication failed (401)
|
|
215
|
+
- `SampleTrackerNotFoundError` - Resource not found (404)
|
|
216
|
+
- `SampleTrackerValidationError` - Request validation failed (422)
|
|
217
|
+
- `SampleTrackerRateLimitError` - Rate limit exceeded (429)
|
|
218
|
+
- `SampleTrackerAPIError` - Other API errors
|
|
219
|
+
|
|
220
|
+
## Supported Python Versions
|
|
221
|
+
|
|
222
|
+
- Python 3.10+
|
|
223
|
+
- Python 3.11+
|
|
224
|
+
- Python 3.12+
|
|
225
|
+
- Python 3.13+
|
|
226
|
+
- Python 3.14+
|
|
227
|
+
- PyPy 3.10+
|
|
228
|
+
|
|
229
|
+
## License
|
|
230
|
+
|
|
231
|
+
`hse-sampletracker-client` is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license.
|
|
232
|
+
|
|
233
|
+
## Links
|
|
234
|
+
|
|
235
|
+
- **Documentation**: https://github.com/Alexander Schramm/sampletracker#readme
|
|
236
|
+
- **Issues**: https://github.com/Alexander Schramm/sampletracker/issues
|
|
237
|
+
- **Source**: https://github.com/Alexander Schramm/sampletracker
|
|
238
|
+
- **PyPI**: https://pypi.org/project/hse-sampletracker-client
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# HSE SampleTracker Client
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/hse-sampletracker-client)
|
|
4
|
+
[](https://pypi.org/project/hse-sampletracker-client)
|
|
5
|
+
[](LICENSE.txt)
|
|
6
|
+
|
|
7
|
+
A Pythonic client library for the HSE SampleTracker API - manage laboratory samples, processing steps, and observations with ease.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- **Synchronous API Client** - Simple, blocking HTTP client using `httpx`
|
|
12
|
+
- **Type Hints Throughout** - Fully typed for better IDE support and code safety
|
|
13
|
+
- **Command-Line Interface** - Interactive CLI for quick sample management
|
|
14
|
+
- **Pydantic-like Models** - Dataclass-based models with `from_dict` constructors
|
|
15
|
+
- **Comprehensive Exceptions** - Clear error hierarchy for different failure modes
|
|
16
|
+
- **Environment Configuration** - Support for `.env` files and environment variables
|
|
17
|
+
- **Pagination Support** - Built-in cursor-based pagination for listing samples
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```console
|
|
22
|
+
pip install hse-sampletracker-client
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
### Using the Python API
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
from sampletracker import SampleTrackerClient
|
|
31
|
+
|
|
32
|
+
# Create a client
|
|
33
|
+
client = SampleTrackerClient(
|
|
34
|
+
api_key="your-api-key",
|
|
35
|
+
base_url="https://your-instance.com/api/v1"
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
# List samples
|
|
39
|
+
samples = client.list_samples(limit=10)
|
|
40
|
+
for sample in samples:
|
|
41
|
+
print(f"{sample.sample_id}: {sample.name}")
|
|
42
|
+
|
|
43
|
+
# Get detailed sample information
|
|
44
|
+
sample = client.load_sample("SAMPLE-123")
|
|
45
|
+
print(f"Description: {sample.description}")
|
|
46
|
+
print(f"Steps: {sample.stats.step_count}")
|
|
47
|
+
print(f"Observations: {sample.stats.observation_count}")
|
|
48
|
+
|
|
49
|
+
# View history
|
|
50
|
+
for event in sample.history:
|
|
51
|
+
if hasattr(event, 'name'): # StepEvent
|
|
52
|
+
print(f"Step: {event.name}")
|
|
53
|
+
else: # ObservationEvent
|
|
54
|
+
print(f"Observation: {event.content}")
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Using the CLI
|
|
58
|
+
|
|
59
|
+
Set up your environment:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# Option 1: Environment variables
|
|
63
|
+
export SAMPLETRACKER_API_KEY="your-api-key"
|
|
64
|
+
export SAMPLETRACKER_BASE_URL="https://your-instance.com/api/v1"
|
|
65
|
+
|
|
66
|
+
# Option 2: Create a .env file
|
|
67
|
+
echo "SAMPLETRACKER_API_KEY=your-api-key" > .env
|
|
68
|
+
echo "SAMPLETRACKER_BASE_URL=https://your-instance.com/api/v1" >> .env
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
List samples:
|
|
72
|
+
|
|
73
|
+
```console
|
|
74
|
+
$ sampletracker list --limit 5
|
|
75
|
+
ID | Sample ID | Name | Steps | Observations
|
|
76
|
+
--------------------------------------------------------------------------------
|
|
77
|
+
1 | sample-001 | test batch | 3 | 2
|
|
78
|
+
2 | M315SO23 | test batch (Copy) | 3 | 2
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
View sample details:
|
|
82
|
+
|
|
83
|
+
```console
|
|
84
|
+
$ sampletracker view sample-001
|
|
85
|
+
Sample Details:
|
|
86
|
+
ID: 1
|
|
87
|
+
Sample ID: sample-001
|
|
88
|
+
Name: test batch
|
|
89
|
+
Description: mein erster test
|
|
90
|
+
Owner ID: 2
|
|
91
|
+
Owner Email: admin@example.com
|
|
92
|
+
Created: 2026-04-25 13:14:13.126000+00:00
|
|
93
|
+
Updated: 2026-04-25 13:14:13.126000+00:00
|
|
94
|
+
Steps: 2
|
|
95
|
+
Observations: 2
|
|
96
|
+
|
|
97
|
+
History:
|
|
98
|
+
[Step] Backen
|
|
99
|
+
Performed: 2026-04-25 13:20:00+00:00
|
|
100
|
+
Parameters:
|
|
101
|
+
- Temperatur: 210 °C
|
|
102
|
+
[Observation] Das Ding ist heiß
|
|
103
|
+
Created: 2026-04-25 13:21:06.172000+00:00
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Configuration
|
|
107
|
+
|
|
108
|
+
### Environment Variables
|
|
109
|
+
|
|
110
|
+
| Variable | Description | Required |
|
|
111
|
+
|----------|-------------|----------|
|
|
112
|
+
| `SAMPLETRACKER_API_KEY` | Your API key | Yes |
|
|
113
|
+
| `SAMPLETRACKER_BASE_URL` | API base URL | No (defaults to official SaaS) |
|
|
114
|
+
|
|
115
|
+
### .env File
|
|
116
|
+
|
|
117
|
+
Create a `.env` file in your project root:
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
SAMPLETRACKER_API_KEY=your-api-key
|
|
121
|
+
SAMPLETRACKER_BASE_URL=https://your-instance.com/api/v1
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
The CLI automatically loads variables from `.env` files in the current or parent directories.
|
|
125
|
+
|
|
126
|
+
## API Reference
|
|
127
|
+
|
|
128
|
+
### SampleTrackerClient
|
|
129
|
+
|
|
130
|
+
The main client class for interacting with the API.
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
client = SampleTrackerClient(
|
|
134
|
+
api_key: str, # Your API key
|
|
135
|
+
base_url: str | None, # Optional base URL
|
|
136
|
+
timeout: float | None # Optional timeout (default: 30s)
|
|
137
|
+
)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Methods
|
|
141
|
+
|
|
142
|
+
#### `list_samples(limit: int = 10, after_id: int | None = None) -> list[SampleListItem]`
|
|
143
|
+
|
|
144
|
+
List samples with pagination support.
|
|
145
|
+
|
|
146
|
+
- `limit`: Number of samples to return (max: 100)
|
|
147
|
+
- `after_id`: Cursor for pagination (returns samples with ID > after_id)
|
|
148
|
+
|
|
149
|
+
#### `load_sample(sample_id: str) -> Sample | None`
|
|
150
|
+
|
|
151
|
+
Get detailed information about a specific sample, including history.
|
|
152
|
+
|
|
153
|
+
Returns `None` if the sample doesn't exist.
|
|
154
|
+
|
|
155
|
+
### Models
|
|
156
|
+
|
|
157
|
+
#### SampleListItem
|
|
158
|
+
|
|
159
|
+
Lightweight model for list responses:
|
|
160
|
+
|
|
161
|
+
- `id`: Internal database ID
|
|
162
|
+
- `sample_id`: User-facing sample identifier
|
|
163
|
+
- `name`: Sample name
|
|
164
|
+
- `description`: Optional description
|
|
165
|
+
- `owner_id`: Owner's user ID
|
|
166
|
+
- `created_at`: Creation timestamp
|
|
167
|
+
- `updated_at`: Last update timestamp
|
|
168
|
+
- `step_count`: Number of processing steps
|
|
169
|
+
- `observation_count`: Number of observations
|
|
170
|
+
|
|
171
|
+
#### Sample
|
|
172
|
+
|
|
173
|
+
Detailed model with full history:
|
|
174
|
+
|
|
175
|
+
- All fields from `SampleListItem`, plus:
|
|
176
|
+
- `owner_email`: Email of the owner
|
|
177
|
+
- `history`: List of `StepEvent` and `ObservationEvent`
|
|
178
|
+
- `stats`: `SampleStats` with aggregated counts
|
|
179
|
+
|
|
180
|
+
### Exceptions
|
|
181
|
+
|
|
182
|
+
All exceptions inherit from `SampleTrackerError`:
|
|
183
|
+
|
|
184
|
+
- `SampleTrackerAuthError` - Authentication failed (401)
|
|
185
|
+
- `SampleTrackerNotFoundError` - Resource not found (404)
|
|
186
|
+
- `SampleTrackerValidationError` - Request validation failed (422)
|
|
187
|
+
- `SampleTrackerRateLimitError` - Rate limit exceeded (429)
|
|
188
|
+
- `SampleTrackerAPIError` - Other API errors
|
|
189
|
+
|
|
190
|
+
## Supported Python Versions
|
|
191
|
+
|
|
192
|
+
- Python 3.10+
|
|
193
|
+
- Python 3.11+
|
|
194
|
+
- Python 3.12+
|
|
195
|
+
- Python 3.13+
|
|
196
|
+
- Python 3.14+
|
|
197
|
+
- PyPy 3.10+
|
|
198
|
+
|
|
199
|
+
## License
|
|
200
|
+
|
|
201
|
+
`hse-sampletracker-client` is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license.
|
|
202
|
+
|
|
203
|
+
## Links
|
|
204
|
+
|
|
205
|
+
- **Documentation**: https://github.com/Alexander Schramm/sampletracker#readme
|
|
206
|
+
- **Issues**: https://github.com/Alexander Schramm/sampletracker/issues
|
|
207
|
+
- **Source**: https://github.com/Alexander Schramm/sampletracker
|
|
208
|
+
- **PyPI**: https://pypi.org/project/hse-sampletracker-client
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "hse-sampletracker-client"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = 'A Pythonic client library for the SampleTracker SaaS API'
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE.txt"]
|
|
13
|
+
keywords = ["sampletracker", "api", "client", "hse", "laboratory", "samples"]
|
|
14
|
+
authors = [
|
|
15
|
+
{name = "Alexander Schramm", email = "info@expectiq.com"},
|
|
16
|
+
]
|
|
17
|
+
classifiers = [
|
|
18
|
+
"Development Status :: 4 - Beta",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"License :: OSI Approved :: MIT License",
|
|
21
|
+
"Programming Language :: Python",
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Programming Language :: Python :: 3.13",
|
|
27
|
+
"Programming Language :: Python :: 3.14",
|
|
28
|
+
"Programming Language :: Python :: Implementation :: CPython",
|
|
29
|
+
"Programming Language :: Python :: Implementation :: PyPy",
|
|
30
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
31
|
+
"Topic :: Internet :: WWW/HTTP :: Dynamic Content",
|
|
32
|
+
"Typing :: Typed",
|
|
33
|
+
]
|
|
34
|
+
dependencies = [
|
|
35
|
+
"httpx>=0.24.0",
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
[project.scripts]
|
|
39
|
+
sampletracker = "sampletracker.run:main"
|
|
40
|
+
|
|
41
|
+
[project.urls]
|
|
42
|
+
Documentation = "https://github.com/Alexander Schramm/sampletracker#readme"
|
|
43
|
+
Issues = "https://github.com/Alexander Schramm/sampletracker/issues"
|
|
44
|
+
Source = "https://github.com/Alexander Schramm/sampletracker"
|
|
45
|
+
|
|
46
|
+
[tool.hatch.version]
|
|
47
|
+
path = "src/sampletracker/__about__.py"
|
|
48
|
+
|
|
49
|
+
[tool.hatch.build.targets.wheel]
|
|
50
|
+
packages = ["src/sampletracker"]
|
|
51
|
+
|
|
52
|
+
[tool.hatch.envs.types]
|
|
53
|
+
extra-dependencies = [
|
|
54
|
+
"mypy>=1.0.0",
|
|
55
|
+
]
|
|
56
|
+
[tool.hatch.envs.types.scripts]
|
|
57
|
+
check = "mypy --install-types --non-interactive {args:src/sampletracker tests}"
|
|
58
|
+
|
|
59
|
+
[tool.coverage.run]
|
|
60
|
+
source_pkgs = ["sampletracker", "tests"]
|
|
61
|
+
branch = true
|
|
62
|
+
parallel = true
|
|
63
|
+
omit = [
|
|
64
|
+
"src/sampletracker/__about__.py",
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
[tool.coverage.paths]
|
|
68
|
+
sampletracker = ["src/sampletracker", "*/sampletracker/src/sampletracker"]
|
|
69
|
+
tests = ["tests", "*/sampletracker/tests"]
|
|
70
|
+
|
|
71
|
+
[tool.coverage.report]
|
|
72
|
+
exclude_lines = [
|
|
73
|
+
"no cov",
|
|
74
|
+
"if __name__ == .__main__.:",
|
|
75
|
+
"if TYPE_CHECKING:",
|
|
76
|
+
]
|