truesight-sdk 0.1.0__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.
- truesight_sdk-0.1.0/.gitignore +66 -0
- truesight_sdk-0.1.0/PKG-INFO +200 -0
- truesight_sdk-0.1.0/README.md +168 -0
- truesight_sdk-0.1.0/pyproject.toml +84 -0
- truesight_sdk-0.1.0/src/truesight_sdk/__init__.py +54 -0
- truesight_sdk-0.1.0/src/truesight_sdk/_version.py +1 -0
- truesight_sdk-0.1.0/src/truesight_sdk/batching.py +155 -0
- truesight_sdk-0.1.0/src/truesight_sdk/client.py +222 -0
- truesight_sdk-0.1.0/src/truesight_sdk/errors.py +91 -0
- truesight_sdk-0.1.0/src/truesight_sdk/models.py +116 -0
- truesight_sdk-0.1.0/src/truesight_sdk/query.py +141 -0
- truesight_sdk-0.1.0/tests/__init__.py +0 -0
- truesight_sdk-0.1.0/tests/integration/__init__.py +0 -0
- truesight_sdk-0.1.0/tests/integration/test_e2e.py +78 -0
- truesight_sdk-0.1.0/tests/test_batching.py +133 -0
- truesight_sdk-0.1.0/tests/test_client.py +229 -0
- truesight_sdk-0.1.0/tests/test_errors.py +56 -0
- truesight_sdk-0.1.0/tests/test_models.py +95 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Rust
|
|
2
|
+
/target/
|
|
3
|
+
**/*.rs.bk
|
|
4
|
+
*.pdb
|
|
5
|
+
|
|
6
|
+
# Node
|
|
7
|
+
node_modules/
|
|
8
|
+
dist/
|
|
9
|
+
build/
|
|
10
|
+
*.tsbuildinfo
|
|
11
|
+
|
|
12
|
+
# Environment
|
|
13
|
+
.env
|
|
14
|
+
.env.local
|
|
15
|
+
.env.*.local
|
|
16
|
+
!.env.example
|
|
17
|
+
|
|
18
|
+
# IDE
|
|
19
|
+
.idea/
|
|
20
|
+
.vscode/
|
|
21
|
+
*.swp
|
|
22
|
+
*.swo
|
|
23
|
+
*~
|
|
24
|
+
|
|
25
|
+
# OS
|
|
26
|
+
.DS_Store
|
|
27
|
+
Thumbs.db
|
|
28
|
+
|
|
29
|
+
# Gradle / KMM
|
|
30
|
+
.gradle/
|
|
31
|
+
sdks/kmm/build/
|
|
32
|
+
sdks/kmm/**/build/
|
|
33
|
+
sdks/kmm/local.properties
|
|
34
|
+
sdks/kmm/.kotlin/
|
|
35
|
+
**/*.klib
|
|
36
|
+
|
|
37
|
+
# Python SDK
|
|
38
|
+
sdks/python/.venv/
|
|
39
|
+
sdks/python/dist/
|
|
40
|
+
sdks/python/build/
|
|
41
|
+
**/*.egg-info/
|
|
42
|
+
sdks/python/.pytest_cache/
|
|
43
|
+
sdks/python/.mypy_cache/
|
|
44
|
+
sdks/python/.ruff_cache/
|
|
45
|
+
**/__pycache__/
|
|
46
|
+
|
|
47
|
+
# Database
|
|
48
|
+
*.db
|
|
49
|
+
*.sqlite
|
|
50
|
+
|
|
51
|
+
# Logs
|
|
52
|
+
*.log
|
|
53
|
+
|
|
54
|
+
# Docker volumes
|
|
55
|
+
clickhouse_data/
|
|
56
|
+
postgres_data/
|
|
57
|
+
|
|
58
|
+
# Lock files (pnpm is canonical, npm lock is SDK-local)
|
|
59
|
+
# sdks/web/package-lock.json is committed for npm publish
|
|
60
|
+
|
|
61
|
+
# Superpowers brainstorm artifacts
|
|
62
|
+
.superpowers/
|
|
63
|
+
|
|
64
|
+
# Claude Code
|
|
65
|
+
.claude/
|
|
66
|
+
.gstack/
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: truesight-sdk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Server-side Python SDK for TrueSight analytics ingestion
|
|
5
|
+
Project-URL: Homepage, https://github.com/komorebitech/cf-truesight
|
|
6
|
+
Project-URL: Source, https://github.com/komorebitech/cf-truesight/tree/master/sdks/python
|
|
7
|
+
Project-URL: Issues, https://github.com/komorebitech/cf-truesight/issues
|
|
8
|
+
Author-email: Cityflo Engineering <tech@cityflo.com>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
Keywords: analytics,cityflo,event-tracking,truesight
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Requires-Dist: requests>=2.28
|
|
24
|
+
Requires-Dist: urllib3>=2.0
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: responses>=0.25; extra == 'dev'
|
|
29
|
+
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
30
|
+
Requires-Dist: types-requests; extra == 'dev'
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
|
|
33
|
+
# truesight-sdk
|
|
34
|
+
|
|
35
|
+
Server-side Python SDK for [TrueSight](https://github.com/komorebitech/cf-truesight) analytics ingestion.
|
|
36
|
+
|
|
37
|
+
Designed for backends that emit events on behalf of authenticated users (Django, Flask, FastAPI, Airflow DAGs, management commands). Sync by design — if you need async, wrap calls in your own task queue.
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pip install truesight-sdk
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Python 3.10+.
|
|
46
|
+
|
|
47
|
+
## Quick Start
|
|
48
|
+
|
|
49
|
+
### Single event
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
from truesight_sdk import TrueSightClient
|
|
53
|
+
|
|
54
|
+
client = TrueSightClient(
|
|
55
|
+
api_key="ts_server_live_...",
|
|
56
|
+
base_url="https://ingest.truesight.example.com",
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
client.track(
|
|
60
|
+
event_name="Purchased Lite Pack",
|
|
61
|
+
user_id=str(customer.pk),
|
|
62
|
+
properties={"plan_slug": "5-30-days", "amount": 1200},
|
|
63
|
+
)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### User profile update (identify)
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
client.identify(
|
|
70
|
+
user_id=str(customer.pk),
|
|
71
|
+
email=customer.email,
|
|
72
|
+
properties={
|
|
73
|
+
"home_locality": "Andheri",
|
|
74
|
+
"favourite_route": "M1",
|
|
75
|
+
"weekly_subscription_active": True,
|
|
76
|
+
},
|
|
77
|
+
)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
This upserts the user's row in `truesight.user_profiles` (latest-write-wins merge of the `properties` blob) and also appends a `$identify` event to the stream for history.
|
|
81
|
+
|
|
82
|
+
### Batched ingestion (Airflow / cron / bulk syncs)
|
|
83
|
+
|
|
84
|
+
For workloads that emit many events in a tight loop, use `BatchingClient` to amortize HTTP overhead:
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
from truesight_sdk import BatchingClient, TrueSightClient
|
|
88
|
+
|
|
89
|
+
inner = TrueSightClient(api_key="ts_server_live_...", base_url="...")
|
|
90
|
+
|
|
91
|
+
with BatchingClient(inner, batch_size=100, flush_interval_seconds=5.0) as batcher:
|
|
92
|
+
for customer in qs.iterator():
|
|
93
|
+
batcher.identify(
|
|
94
|
+
user_id=str(customer.pk),
|
|
95
|
+
properties=build_profile(customer),
|
|
96
|
+
)
|
|
97
|
+
# Buffers drain on context exit.
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`BatchingClient` is thread-safe; multiple producer threads can call `track()` / `identify()` concurrently.
|
|
101
|
+
|
|
102
|
+
### Reading events (admin queries)
|
|
103
|
+
|
|
104
|
+
The SDK also wraps TrueSight's admin event-query endpoint for read-path consumers:
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from truesight_sdk import AdminQueryClient
|
|
108
|
+
|
|
109
|
+
reader = AdminQueryClient(admin_token="...", base_url="https://admin.truesight.example.com")
|
|
110
|
+
|
|
111
|
+
page = reader.fetch_events(
|
|
112
|
+
project_id="b219fb11-9a63-4843-8126-a3dc05b330a5",
|
|
113
|
+
event_name="Purchased Lite Pack",
|
|
114
|
+
from_=datetime(2026, 5, 1, tzinfo=timezone.utc),
|
|
115
|
+
to=datetime(2026, 5, 28, tzinfo=timezone.utc),
|
|
116
|
+
limit=500,
|
|
117
|
+
)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## API Keys
|
|
121
|
+
|
|
122
|
+
Server keys are scoped — they can only call `/v1/server/*` endpoints. Issue one via the CLI:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
truesight projects api-keys create --scope server --label "<your service>"
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
The plaintext key is returned **once** at creation time. Store it in your secrets manager.
|
|
129
|
+
|
|
130
|
+
## Error Handling
|
|
131
|
+
|
|
132
|
+
All errors subclass `TrueSightError`:
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
from truesight_sdk import (
|
|
136
|
+
AuthError, # 401 — bad / revoked key
|
|
137
|
+
Forbidden, # 403 — wrong scope for this endpoint
|
|
138
|
+
ValidationError, # 400/422 — payload rejected
|
|
139
|
+
RateLimited, # 429 — slow down (after SDK's own retry budget)
|
|
140
|
+
ServerError, # 5xx — TrueSight is degraded (after retries)
|
|
141
|
+
TrueSightError, # base class — catch this to handle any SDK error
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
try:
|
|
145
|
+
client.track("x", user_id="42")
|
|
146
|
+
except RateLimited:
|
|
147
|
+
schedule_retry(...)
|
|
148
|
+
except TrueSightError as exc:
|
|
149
|
+
log.exception("truesight ingest failed", request_id=exc.request_id)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Every error carries `status_code`, `request_id` (when the server returned one), and `response_body` for log correlation.
|
|
153
|
+
|
|
154
|
+
## Retry Idempotency
|
|
155
|
+
|
|
156
|
+
The SDK auto-generates a fresh `event_id` (UUIDv4) for every event when one isn't supplied. If you need retry idempotency (e.g. inside a Celery task that may run twice), pass an explicit `event_id` stable across retries:
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
from truesight_sdk import TrackEvent
|
|
160
|
+
from uuid import uuid5, NAMESPACE_URL
|
|
161
|
+
|
|
162
|
+
stable_id = uuid5(NAMESPACE_URL, f"booking-confirmed:{booking.pk}")
|
|
163
|
+
client.track_batch([
|
|
164
|
+
TrackEvent(
|
|
165
|
+
event_name="Booking Confirmed",
|
|
166
|
+
user_id=str(booking.customer_id),
|
|
167
|
+
event_id=stable_id,
|
|
168
|
+
properties={"booking_id": booking.pk},
|
|
169
|
+
),
|
|
170
|
+
])
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
The server dedups on `(project_id, event_id)` via ClickHouse's `ReplacingMergeTree`, so retries with the same id collapse to a single row.
|
|
174
|
+
|
|
175
|
+
## Development
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
# Install in dev mode
|
|
179
|
+
pip install -e ".[dev]"
|
|
180
|
+
|
|
181
|
+
# Run unit tests (no network)
|
|
182
|
+
pytest
|
|
183
|
+
|
|
184
|
+
# Run integration tests against a local TrueSight stack
|
|
185
|
+
export TRUESIGHT_BASE_URL=http://localhost:8080
|
|
186
|
+
export TRUESIGHT_API_KEY=ts_server_test_...
|
|
187
|
+
pytest -m integration
|
|
188
|
+
|
|
189
|
+
# Lint + typecheck
|
|
190
|
+
ruff check src/ tests/
|
|
191
|
+
mypy src/
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Versioning
|
|
195
|
+
|
|
196
|
+
Semver. `0.x` is pre-1.0 — the public API may shift between minor versions; pin the minor version until `1.0`.
|
|
197
|
+
|
|
198
|
+
## License
|
|
199
|
+
|
|
200
|
+
MIT — see top-level repo.
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# truesight-sdk
|
|
2
|
+
|
|
3
|
+
Server-side Python SDK for [TrueSight](https://github.com/komorebitech/cf-truesight) analytics ingestion.
|
|
4
|
+
|
|
5
|
+
Designed for backends that emit events on behalf of authenticated users (Django, Flask, FastAPI, Airflow DAGs, management commands). Sync by design — if you need async, wrap calls in your own task queue.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install truesight-sdk
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Python 3.10+.
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
### Single event
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
from truesight_sdk import TrueSightClient
|
|
21
|
+
|
|
22
|
+
client = TrueSightClient(
|
|
23
|
+
api_key="ts_server_live_...",
|
|
24
|
+
base_url="https://ingest.truesight.example.com",
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
client.track(
|
|
28
|
+
event_name="Purchased Lite Pack",
|
|
29
|
+
user_id=str(customer.pk),
|
|
30
|
+
properties={"plan_slug": "5-30-days", "amount": 1200},
|
|
31
|
+
)
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### User profile update (identify)
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
client.identify(
|
|
38
|
+
user_id=str(customer.pk),
|
|
39
|
+
email=customer.email,
|
|
40
|
+
properties={
|
|
41
|
+
"home_locality": "Andheri",
|
|
42
|
+
"favourite_route": "M1",
|
|
43
|
+
"weekly_subscription_active": True,
|
|
44
|
+
},
|
|
45
|
+
)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
This upserts the user's row in `truesight.user_profiles` (latest-write-wins merge of the `properties` blob) and also appends a `$identify` event to the stream for history.
|
|
49
|
+
|
|
50
|
+
### Batched ingestion (Airflow / cron / bulk syncs)
|
|
51
|
+
|
|
52
|
+
For workloads that emit many events in a tight loop, use `BatchingClient` to amortize HTTP overhead:
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
from truesight_sdk import BatchingClient, TrueSightClient
|
|
56
|
+
|
|
57
|
+
inner = TrueSightClient(api_key="ts_server_live_...", base_url="...")
|
|
58
|
+
|
|
59
|
+
with BatchingClient(inner, batch_size=100, flush_interval_seconds=5.0) as batcher:
|
|
60
|
+
for customer in qs.iterator():
|
|
61
|
+
batcher.identify(
|
|
62
|
+
user_id=str(customer.pk),
|
|
63
|
+
properties=build_profile(customer),
|
|
64
|
+
)
|
|
65
|
+
# Buffers drain on context exit.
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`BatchingClient` is thread-safe; multiple producer threads can call `track()` / `identify()` concurrently.
|
|
69
|
+
|
|
70
|
+
### Reading events (admin queries)
|
|
71
|
+
|
|
72
|
+
The SDK also wraps TrueSight's admin event-query endpoint for read-path consumers:
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
from truesight_sdk import AdminQueryClient
|
|
76
|
+
|
|
77
|
+
reader = AdminQueryClient(admin_token="...", base_url="https://admin.truesight.example.com")
|
|
78
|
+
|
|
79
|
+
page = reader.fetch_events(
|
|
80
|
+
project_id="b219fb11-9a63-4843-8126-a3dc05b330a5",
|
|
81
|
+
event_name="Purchased Lite Pack",
|
|
82
|
+
from_=datetime(2026, 5, 1, tzinfo=timezone.utc),
|
|
83
|
+
to=datetime(2026, 5, 28, tzinfo=timezone.utc),
|
|
84
|
+
limit=500,
|
|
85
|
+
)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## API Keys
|
|
89
|
+
|
|
90
|
+
Server keys are scoped — they can only call `/v1/server/*` endpoints. Issue one via the CLI:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
truesight projects api-keys create --scope server --label "<your service>"
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
The plaintext key is returned **once** at creation time. Store it in your secrets manager.
|
|
97
|
+
|
|
98
|
+
## Error Handling
|
|
99
|
+
|
|
100
|
+
All errors subclass `TrueSightError`:
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
from truesight_sdk import (
|
|
104
|
+
AuthError, # 401 — bad / revoked key
|
|
105
|
+
Forbidden, # 403 — wrong scope for this endpoint
|
|
106
|
+
ValidationError, # 400/422 — payload rejected
|
|
107
|
+
RateLimited, # 429 — slow down (after SDK's own retry budget)
|
|
108
|
+
ServerError, # 5xx — TrueSight is degraded (after retries)
|
|
109
|
+
TrueSightError, # base class — catch this to handle any SDK error
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
try:
|
|
113
|
+
client.track("x", user_id="42")
|
|
114
|
+
except RateLimited:
|
|
115
|
+
schedule_retry(...)
|
|
116
|
+
except TrueSightError as exc:
|
|
117
|
+
log.exception("truesight ingest failed", request_id=exc.request_id)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Every error carries `status_code`, `request_id` (when the server returned one), and `response_body` for log correlation.
|
|
121
|
+
|
|
122
|
+
## Retry Idempotency
|
|
123
|
+
|
|
124
|
+
The SDK auto-generates a fresh `event_id` (UUIDv4) for every event when one isn't supplied. If you need retry idempotency (e.g. inside a Celery task that may run twice), pass an explicit `event_id` stable across retries:
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
from truesight_sdk import TrackEvent
|
|
128
|
+
from uuid import uuid5, NAMESPACE_URL
|
|
129
|
+
|
|
130
|
+
stable_id = uuid5(NAMESPACE_URL, f"booking-confirmed:{booking.pk}")
|
|
131
|
+
client.track_batch([
|
|
132
|
+
TrackEvent(
|
|
133
|
+
event_name="Booking Confirmed",
|
|
134
|
+
user_id=str(booking.customer_id),
|
|
135
|
+
event_id=stable_id,
|
|
136
|
+
properties={"booking_id": booking.pk},
|
|
137
|
+
),
|
|
138
|
+
])
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
The server dedups on `(project_id, event_id)` via ClickHouse's `ReplacingMergeTree`, so retries with the same id collapse to a single row.
|
|
142
|
+
|
|
143
|
+
## Development
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
# Install in dev mode
|
|
147
|
+
pip install -e ".[dev]"
|
|
148
|
+
|
|
149
|
+
# Run unit tests (no network)
|
|
150
|
+
pytest
|
|
151
|
+
|
|
152
|
+
# Run integration tests against a local TrueSight stack
|
|
153
|
+
export TRUESIGHT_BASE_URL=http://localhost:8080
|
|
154
|
+
export TRUESIGHT_API_KEY=ts_server_test_...
|
|
155
|
+
pytest -m integration
|
|
156
|
+
|
|
157
|
+
# Lint + typecheck
|
|
158
|
+
ruff check src/ tests/
|
|
159
|
+
mypy src/
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Versioning
|
|
163
|
+
|
|
164
|
+
Semver. `0.x` is pre-1.0 — the public API may shift between minor versions; pin the minor version until `1.0`.
|
|
165
|
+
|
|
166
|
+
## License
|
|
167
|
+
|
|
168
|
+
MIT — see top-level repo.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "truesight-sdk"
|
|
7
|
+
description = "Server-side Python SDK for TrueSight analytics ingestion"
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
license = "MIT"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
authors = [
|
|
12
|
+
{ name = "Cityflo Engineering", email = "tech@cityflo.com" },
|
|
13
|
+
]
|
|
14
|
+
keywords = ["analytics", "truesight", "event-tracking", "cityflo"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 4 - Beta",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.10",
|
|
21
|
+
"Programming Language :: Python :: 3.11",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Programming Language :: Python :: 3.13",
|
|
24
|
+
"Programming Language :: Python :: 3.14",
|
|
25
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
26
|
+
"Typing :: Typed",
|
|
27
|
+
]
|
|
28
|
+
dependencies = [
|
|
29
|
+
"requests>=2.28",
|
|
30
|
+
"urllib3>=2.0",
|
|
31
|
+
]
|
|
32
|
+
dynamic = ["version"]
|
|
33
|
+
|
|
34
|
+
[project.urls]
|
|
35
|
+
Homepage = "https://github.com/komorebitech/cf-truesight"
|
|
36
|
+
Source = "https://github.com/komorebitech/cf-truesight/tree/master/sdks/python"
|
|
37
|
+
Issues = "https://github.com/komorebitech/cf-truesight/issues"
|
|
38
|
+
|
|
39
|
+
[project.optional-dependencies]
|
|
40
|
+
dev = [
|
|
41
|
+
"pytest>=8.0",
|
|
42
|
+
"responses>=0.25",
|
|
43
|
+
"ruff>=0.6",
|
|
44
|
+
"mypy>=1.10",
|
|
45
|
+
"types-requests",
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
[tool.hatch.version]
|
|
49
|
+
path = "src/truesight_sdk/_version.py"
|
|
50
|
+
|
|
51
|
+
[tool.hatch.build.targets.wheel]
|
|
52
|
+
packages = ["src/truesight_sdk"]
|
|
53
|
+
|
|
54
|
+
[tool.hatch.build.targets.sdist]
|
|
55
|
+
include = [
|
|
56
|
+
"/src",
|
|
57
|
+
"/tests",
|
|
58
|
+
"/README.md",
|
|
59
|
+
"/pyproject.toml",
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
[tool.ruff]
|
|
63
|
+
line-length = 100
|
|
64
|
+
target-version = "py310"
|
|
65
|
+
|
|
66
|
+
[tool.ruff.lint]
|
|
67
|
+
select = ["E", "F", "I", "N", "UP", "B", "SIM", "RUF"]
|
|
68
|
+
ignore = ["E501"]
|
|
69
|
+
|
|
70
|
+
[tool.mypy]
|
|
71
|
+
python_version = "3.10"
|
|
72
|
+
strict = true
|
|
73
|
+
warn_unreachable = true
|
|
74
|
+
disallow_untyped_decorators = false
|
|
75
|
+
|
|
76
|
+
[[tool.mypy.overrides]]
|
|
77
|
+
module = ["responses.*"]
|
|
78
|
+
ignore_missing_imports = true
|
|
79
|
+
|
|
80
|
+
[tool.pytest.ini_options]
|
|
81
|
+
testpaths = ["tests"]
|
|
82
|
+
markers = [
|
|
83
|
+
"integration: integration test that requires a running TrueSight instance (skipped unless TRUESIGHT_BASE_URL is set)",
|
|
84
|
+
]
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""TrueSight Python SDK — server-side analytics ingestion.
|
|
2
|
+
|
|
3
|
+
This SDK targets server-to-server use cases (Django/Flask/FastAPI backends,
|
|
4
|
+
Airflow DAGs, management commands) that emit events on behalf of authenticated
|
|
5
|
+
users. It is intentionally sync; if you need an async wrapper, wire it up via
|
|
6
|
+
your own task queue (e.g. Celery).
|
|
7
|
+
|
|
8
|
+
Quick start:
|
|
9
|
+
|
|
10
|
+
from truesight_sdk import TrueSightClient
|
|
11
|
+
|
|
12
|
+
client = TrueSightClient(
|
|
13
|
+
api_key="ts_server_live_...",
|
|
14
|
+
base_url="https://ingest.truesight.example.com",
|
|
15
|
+
)
|
|
16
|
+
client.track(
|
|
17
|
+
event_name="Purchased Lite Pack",
|
|
18
|
+
user_id=str(customer.pk),
|
|
19
|
+
properties={"plan_slug": "5-30-days", "amount": 1200},
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
For bulk-sync workloads (Airflow DAGs, nightly profile syncs), use
|
|
23
|
+
``BatchingClient`` to amortize HTTP overhead across many events.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
from truesight_sdk._version import __version__
|
|
27
|
+
from truesight_sdk.batching import BatchingClient
|
|
28
|
+
from truesight_sdk.client import TrueSightClient
|
|
29
|
+
from truesight_sdk.errors import (
|
|
30
|
+
AuthError,
|
|
31
|
+
Forbidden,
|
|
32
|
+
RateLimited,
|
|
33
|
+
ServerError,
|
|
34
|
+
TrueSightError,
|
|
35
|
+
ValidationError,
|
|
36
|
+
)
|
|
37
|
+
from truesight_sdk.models import EventType, IdentifyEvent, TrackEvent
|
|
38
|
+
from truesight_sdk.query import AdminQueryClient
|
|
39
|
+
|
|
40
|
+
__all__ = [
|
|
41
|
+
"AdminQueryClient",
|
|
42
|
+
"AuthError",
|
|
43
|
+
"BatchingClient",
|
|
44
|
+
"EventType",
|
|
45
|
+
"Forbidden",
|
|
46
|
+
"IdentifyEvent",
|
|
47
|
+
"RateLimited",
|
|
48
|
+
"ServerError",
|
|
49
|
+
"TrackEvent",
|
|
50
|
+
"TrueSightClient",
|
|
51
|
+
"TrueSightError",
|
|
52
|
+
"ValidationError",
|
|
53
|
+
"__version__",
|
|
54
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|