antonlytics 1.0.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.
- antonlytics-1.0.0/.gitignore +1 -0
- antonlytics-1.0.0/.pyre/pyre.stderr +48 -0
- antonlytics-1.0.0/PKG-INFO +370 -0
- antonlytics-1.0.0/README.md +336 -0
- antonlytics-1.0.0/antonlytics/__init__.py +119 -0
- antonlytics-1.0.0/antonlytics/_http.py +215 -0
- antonlytics-1.0.0/antonlytics/cli.py +273 -0
- antonlytics-1.0.0/antonlytics/client.py +213 -0
- antonlytics-1.0.0/antonlytics/exceptions.py +171 -0
- antonlytics-1.0.0/antonlytics/models.py +341 -0
- antonlytics-1.0.0/antonlytics/resources/__init__.py +11 -0
- antonlytics-1.0.0/antonlytics/resources/ingest.py +238 -0
- antonlytics-1.0.0/antonlytics/resources/projects.py +146 -0
- antonlytics-1.0.0/antonlytics/resources/query.py +243 -0
- antonlytics-1.0.0/examples/async_example.py +114 -0
- antonlytics-1.0.0/examples/basic.py +162 -0
- antonlytics-1.0.0/examples/query.json +24 -0
- antonlytics-1.0.0/examples/triplets.json +19 -0
- antonlytics-1.0.0/pyproject.toml +67 -0
- antonlytics-1.0.0/tests/__init__.py +0 -0
- antonlytics-1.0.0/tests/test_sdk.py +368 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.DS_Store
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
2026-04-17 17:04:00,788 [PID 17839] DEBUG Using selector: KqueueSelector
|
|
2
|
+
2026-04-17 17:04:00,789 [PID 17839] INFO Reading Pyre server configurations...
|
|
3
|
+
2026-04-17 17:04:00,789 [PID 17839] DEBUG Could not find `.pyre_configuration` in the project root.Searching for `pyproject.toml`...
|
|
4
|
+
2026-04-17 17:04:00,800 [PID 17839] ERROR Uncaught error in persistent.run
|
|
5
|
+
Traceback (most recent call last):
|
|
6
|
+
File "/Users/mohamed/.local/share/nvim/mason/packages/pyre/venv/lib/python3.9/site-packages/pyre_check/client/commands/persistent.py", line 299, in run
|
|
7
|
+
return asyncio.get_event_loop().run_until_complete(
|
|
8
|
+
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
|
|
9
|
+
return future.result()
|
|
10
|
+
File "/Users/mohamed/.local/share/nvim/mason/packages/pyre/venv/lib/python3.9/site-packages/pyre_check/client/commands/persistent.py", line 224, in run_persistent
|
|
11
|
+
initial_server_options = pyre_server_options.read_server_options(
|
|
12
|
+
File "/Users/mohamed/.local/share/nvim/mason/packages/pyre/venv/lib/python3.9/site-packages/pyre_check/client/commands/pyre_server_options.py", line 129, in read_server_options
|
|
13
|
+
return server_options_reader()
|
|
14
|
+
File "/Users/mohamed/.local/share/nvim/mason/packages/pyre/venv/lib/python3.9/site-packages/pyre_check/client/commands/pyre_server_options.py", line 114, in read
|
|
15
|
+
return PyreServerOptions.create(
|
|
16
|
+
File "/Users/mohamed/.local/share/nvim/mason/packages/pyre/venv/lib/python3.9/site-packages/pyre_check/client/commands/pyre_server_options.py", line 93, in create
|
|
17
|
+
start_arguments = start.create_server_arguments(
|
|
18
|
+
File "/Users/mohamed/.local/share/nvim/mason/packages/pyre/venv/lib/python3.9/site-packages/pyre_check/client/commands/start.py", line 311, in create_server_arguments
|
|
19
|
+
source_paths = backend_arguments.get_source_path_for_server(
|
|
20
|
+
File "/Users/mohamed/.local/share/nvim/mason/packages/pyre/venv/lib/python3.9/site-packages/pyre_check/client/backend_arguments.py", line 418, in get_source_path_for_server
|
|
21
|
+
return get_source_path(
|
|
22
|
+
File "/Users/mohamed/.local/share/nvim/mason/packages/pyre/venv/lib/python3.9/site-packages/pyre_check/client/backend_arguments.py", line 397, in get_source_path
|
|
23
|
+
raise configuration_module.InvalidConfiguration(
|
|
24
|
+
pyre_check.client.configuration.exceptions.InvalidConfiguration: Invalid configuration: Cannot find any source files to analyze. Either `source_directories` or `targets` must be specified.
|
|
25
|
+
2026-04-17 17:04:33,918 [PID 18056] DEBUG Using selector: KqueueSelector
|
|
26
|
+
2026-04-17 17:04:33,919 [PID 18056] INFO Reading Pyre server configurations...
|
|
27
|
+
2026-04-17 17:04:33,920 [PID 18056] DEBUG Could not find `.pyre_configuration` in the project root.Searching for `pyproject.toml`...
|
|
28
|
+
2026-04-17 17:04:33,931 [PID 18056] ERROR Uncaught error in persistent.run
|
|
29
|
+
Traceback (most recent call last):
|
|
30
|
+
File "/Users/mohamed/.local/share/nvim/mason/packages/pyre/venv/lib/python3.9/site-packages/pyre_check/client/commands/persistent.py", line 299, in run
|
|
31
|
+
return asyncio.get_event_loop().run_until_complete(
|
|
32
|
+
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
|
|
33
|
+
return future.result()
|
|
34
|
+
File "/Users/mohamed/.local/share/nvim/mason/packages/pyre/venv/lib/python3.9/site-packages/pyre_check/client/commands/persistent.py", line 224, in run_persistent
|
|
35
|
+
initial_server_options = pyre_server_options.read_server_options(
|
|
36
|
+
File "/Users/mohamed/.local/share/nvim/mason/packages/pyre/venv/lib/python3.9/site-packages/pyre_check/client/commands/pyre_server_options.py", line 129, in read_server_options
|
|
37
|
+
return server_options_reader()
|
|
38
|
+
File "/Users/mohamed/.local/share/nvim/mason/packages/pyre/venv/lib/python3.9/site-packages/pyre_check/client/commands/pyre_server_options.py", line 114, in read
|
|
39
|
+
return PyreServerOptions.create(
|
|
40
|
+
File "/Users/mohamed/.local/share/nvim/mason/packages/pyre/venv/lib/python3.9/site-packages/pyre_check/client/commands/pyre_server_options.py", line 93, in create
|
|
41
|
+
start_arguments = start.create_server_arguments(
|
|
42
|
+
File "/Users/mohamed/.local/share/nvim/mason/packages/pyre/venv/lib/python3.9/site-packages/pyre_check/client/commands/start.py", line 311, in create_server_arguments
|
|
43
|
+
source_paths = backend_arguments.get_source_path_for_server(
|
|
44
|
+
File "/Users/mohamed/.local/share/nvim/mason/packages/pyre/venv/lib/python3.9/site-packages/pyre_check/client/backend_arguments.py", line 418, in get_source_path_for_server
|
|
45
|
+
return get_source_path(
|
|
46
|
+
File "/Users/mohamed/.local/share/nvim/mason/packages/pyre/venv/lib/python3.9/site-packages/pyre_check/client/backend_arguments.py", line 397, in get_source_path
|
|
47
|
+
raise configuration_module.InvalidConfiguration(
|
|
48
|
+
pyre_check.client.configuration.exceptions.InvalidConfiguration: Invalid configuration: Cannot find any source files to analyze. Either `source_directories` or `targets` must be specified.
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: antonlytics
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Official Python SDK for the Antonlytics Knowledge Graph API
|
|
5
|
+
Project-URL: Homepage, https://antonlytics.com
|
|
6
|
+
Project-URL: Documentation, https://docs.antonlytics.com/sdk/python
|
|
7
|
+
Project-URL: Repository, https://github.com/antonlytics/sdk-python
|
|
8
|
+
Project-URL: Issues, https://github.com/antonlytics/sdk-python/issues
|
|
9
|
+
Author-email: Antonlytics <sdk@antonlytics.com>
|
|
10
|
+
License: MIT
|
|
11
|
+
Keywords: antonlytics,knowledge-graph,ontology,sdk,triplet
|
|
12
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.9
|
|
23
|
+
Requires-Dist: httpx>=0.25.0
|
|
24
|
+
Provides-Extra: async
|
|
25
|
+
Requires-Dist: httpx>=0.25.0; extra == 'async'
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: hatchling>=1.21.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: mypy>=1.8.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest-httpx>=0.28.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest>=7.4.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: ruff>=0.3.0; extra == 'dev'
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
|
|
35
|
+
# antonlytics
|
|
36
|
+
|
|
37
|
+
Official Python SDK for the [Antonlytics](https://antonlytics.com) Knowledge Graph API.
|
|
38
|
+
|
|
39
|
+
[](https://pypi.org/project/antonlytics/)
|
|
40
|
+
[](https://python.org)
|
|
41
|
+
[](./LICENSE)
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Install
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install antonlytics
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Quick Start
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
from antonlytics import Antonlytics, Triplet, EntityRef
|
|
57
|
+
|
|
58
|
+
anto = Antonlytics(api_key="anto_live_xxx")
|
|
59
|
+
|
|
60
|
+
# Ingest a relationship
|
|
61
|
+
anto.ingest.track(
|
|
62
|
+
project_id="proj_abc",
|
|
63
|
+
triplets=Triplet(
|
|
64
|
+
subject=EntityRef("Customer", id="c1", properties={"name": "Alice", "country": "USA"}),
|
|
65
|
+
predicate="PURCHASED",
|
|
66
|
+
object=EntityRef("Product", id="p1", properties={"title": "Laptop Pro", "price": 999}),
|
|
67
|
+
),
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
# Query the graph
|
|
71
|
+
result = (
|
|
72
|
+
anto.query.build("proj_abc")
|
|
73
|
+
.select("Customer", alias="c1")
|
|
74
|
+
.properties("name", "email", "country")
|
|
75
|
+
.eq("country", "USA")
|
|
76
|
+
.gte("age", 18)
|
|
77
|
+
.done()
|
|
78
|
+
.order_by("age", direction="desc")
|
|
79
|
+
.limit(50)
|
|
80
|
+
.run()
|
|
81
|
+
)
|
|
82
|
+
for row in result:
|
|
83
|
+
print(row["name"], row["country"])
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Configuration
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
anto = Antonlytics(
|
|
92
|
+
api_key="anto_live_...", # required — from app.antonlytics.com → API Keys
|
|
93
|
+
base_url="https://api.antonlytics.com", # optional, default shown
|
|
94
|
+
timeout=30.0, # seconds, default 30
|
|
95
|
+
max_retries=2, # auto-retry 5xx / network errors
|
|
96
|
+
debug=False, # print HTTP calls to stdout
|
|
97
|
+
)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Use as a **context manager** to ensure the connection pool is closed:
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
with Antonlytics(api_key="anto_live_xxx") as anto:
|
|
104
|
+
projects = anto.projects.list()
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Ingestion
|
|
110
|
+
|
|
111
|
+
All data enters the knowledge graph as **triplets**: `subject –[predicate]→ object`.
|
|
112
|
+
|
|
113
|
+
### `anto.ingest.track()` ← recommended
|
|
114
|
+
|
|
115
|
+
Ingest and automatically poll if async. Transparent for both sync and async batches.
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
result = anto.ingest.track(
|
|
119
|
+
"proj_abc",
|
|
120
|
+
triplets=[
|
|
121
|
+
Triplet(
|
|
122
|
+
subject=EntityRef("Customer", id="c1", properties={"name": "Alice"}),
|
|
123
|
+
predicate="PURCHASED",
|
|
124
|
+
object=EntityRef("Product", id="p1", properties={"title": "Laptop"}),
|
|
125
|
+
relationship_properties={"quantity": 2},
|
|
126
|
+
),
|
|
127
|
+
],
|
|
128
|
+
interval=1.0, # poll every 1s for async batches
|
|
129
|
+
timeout=60.0, # give up after 60s
|
|
130
|
+
on_status=lambda event: print(f"Status: {event.status}"),
|
|
131
|
+
)
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Batches **≤ 100** → processed synchronously, full results returned immediately.
|
|
135
|
+
Batches **> 100** → queued, auto-polled until done.
|
|
136
|
+
|
|
137
|
+
### `anto.ingest.batch()` — large datasets
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
anto.ingest.batch(
|
|
141
|
+
"proj_abc",
|
|
142
|
+
all_my_triplets, # any size
|
|
143
|
+
chunk_size=200, # triplets per request
|
|
144
|
+
on_chunk=lambda i, n, r: print(f"Chunk {i}/{n}"),
|
|
145
|
+
)
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### `anto.ingest.poll()` — manual async polling
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
result = anto.ingest.send("proj_abc", triplets)
|
|
152
|
+
if result.is_async:
|
|
153
|
+
event = anto.ingest.poll(
|
|
154
|
+
result.event_id,
|
|
155
|
+
timeout=120.0,
|
|
156
|
+
on_status=lambda e: print(e.status),
|
|
157
|
+
)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Query Builder
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
result = (
|
|
166
|
+
anto.query.build("proj_abc")
|
|
167
|
+
|
|
168
|
+
# First entity node
|
|
169
|
+
.select("Customer", alias="c1")
|
|
170
|
+
.properties("name", "email", "country", "age")
|
|
171
|
+
.eq("country", "USA")
|
|
172
|
+
.gte("age", 21)
|
|
173
|
+
.relates_to("PURCHASED", "p1") # join to product node below
|
|
174
|
+
.done()
|
|
175
|
+
|
|
176
|
+
# Second entity node (joined via PURCHASED)
|
|
177
|
+
.select("Product", alias="p1")
|
|
178
|
+
.properties("title", "price", "category")
|
|
179
|
+
.lte("price", 500)
|
|
180
|
+
.done()
|
|
181
|
+
|
|
182
|
+
.order_by("age", direction="desc")
|
|
183
|
+
.limit(100)
|
|
184
|
+
.name("US adults buying affordable products")
|
|
185
|
+
.run()
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
print(f"{result.total} rows in {result.execution_ms}ms")
|
|
189
|
+
for row in result:
|
|
190
|
+
print(row)
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
**Filter operators:** `eq` · `neq` · `contains` · `starts_with` · `ends_with` · `gt` · `gte` · `lt` · `lte`
|
|
194
|
+
|
|
195
|
+
### Raw query payload
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
result = anto.query.execute("proj_abc", {
|
|
199
|
+
"entities": [{"alias": "c1", "type": "Customer",
|
|
200
|
+
"filters": [{"property": "country", "operator": "eq", "value": "USA"}]}],
|
|
201
|
+
"limit": 10,
|
|
202
|
+
})
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Ontology tree
|
|
206
|
+
|
|
207
|
+
```python
|
|
208
|
+
tree = anto.query.ontology("proj_abc")
|
|
209
|
+
# { "Customer": EntityTypeDef(properties=[...], relationships=[...]), ... }
|
|
210
|
+
for name, defn in tree.items():
|
|
211
|
+
print(name, [p.name for p in defn.properties])
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Dashboard
|
|
217
|
+
|
|
218
|
+
```python
|
|
219
|
+
m = anto.dashboard.metrics("proj_abc")
|
|
220
|
+
|
|
221
|
+
print(m.summary.events_tracked)
|
|
222
|
+
print(m.summary.active_entities)
|
|
223
|
+
print(m.summary.total_relationships)
|
|
224
|
+
|
|
225
|
+
# Chart data — ready to pass to matplotlib, plotly, recharts, etc.
|
|
226
|
+
print(m.event_volume.data) # [{"date": "2026-04-01", "count": 42}, ...]
|
|
227
|
+
print(m.entity_distribution.data) # [{"name": "Customer", "value": 1200}, ...]
|
|
228
|
+
print(m.relationship_growth.data) # [{"date": "...", "new": 40, "cumulative": 400}, ...]
|
|
229
|
+
print(m.top_ontology_queries) # [{"name": "US customers", "count": 18}, ...]
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## Projects
|
|
235
|
+
|
|
236
|
+
```python
|
|
237
|
+
projects = anto.projects.list()
|
|
238
|
+
project = anto.projects.get("proj_abc")
|
|
239
|
+
created = anto.projects.create(name="My Graph", team_id="team-uuid")
|
|
240
|
+
stats = anto.projects.stats("proj_abc")
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## Async Client
|
|
246
|
+
|
|
247
|
+
```python
|
|
248
|
+
import asyncio
|
|
249
|
+
from antonlytics import AsyncAntonlytics, Triplet, EntityRef
|
|
250
|
+
|
|
251
|
+
async def main():
|
|
252
|
+
async with AsyncAntonlytics(api_key="anto_live_xxx") as anto:
|
|
253
|
+
# Parallel API calls
|
|
254
|
+
ontology, metrics, projects = await asyncio.gather(
|
|
255
|
+
anto.query.ontology("proj_abc"),
|
|
256
|
+
anto.dashboard.metrics("proj_abc"),
|
|
257
|
+
anto.projects.list(),
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
# Fluent query
|
|
261
|
+
result = await (
|
|
262
|
+
anto.query.build("proj_abc")
|
|
263
|
+
.select("Customer").eq("country", "USA").done()
|
|
264
|
+
.limit(20)
|
|
265
|
+
.run()
|
|
266
|
+
)
|
|
267
|
+
for row in result:
|
|
268
|
+
print(row)
|
|
269
|
+
|
|
270
|
+
asyncio.run(main())
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## Error Handling
|
|
276
|
+
|
|
277
|
+
```python
|
|
278
|
+
from antonlytics import (
|
|
279
|
+
AntoError, AuthenticationError, PlanLimitError,
|
|
280
|
+
NotFoundError, RateLimitError, NetworkError, TimeoutError,
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
try:
|
|
284
|
+
anto.ingest.track(...)
|
|
285
|
+
except PlanLimitError as e:
|
|
286
|
+
print(f"Plan limit hit: {e.message}")
|
|
287
|
+
# Redirect user to app.antonlytics.com/billing
|
|
288
|
+
except AuthenticationError:
|
|
289
|
+
print("API key is invalid or revoked")
|
|
290
|
+
except AntoError as e:
|
|
291
|
+
print(f"[{e.code}] HTTP {e.status}: {e.message}")
|
|
292
|
+
print(e.details)
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
| Exception | HTTP | When |
|
|
296
|
+
|---|---|---|
|
|
297
|
+
| `AuthenticationError` | 401 | Invalid API key |
|
|
298
|
+
| `PermissionError` | 403 | Key lacks permission |
|
|
299
|
+
| `NotFoundError` | 404 | Project/resource not found |
|
|
300
|
+
| `PlanLimitError` | 402 | Event or key quota exhausted |
|
|
301
|
+
| `ValidationError` | 400/422 | Bad request payload |
|
|
302
|
+
| `RateLimitError` | 429 | Too many requests |
|
|
303
|
+
| `ServerError` | 5xx | Backend error |
|
|
304
|
+
| `NetworkError` | — | DNS / connection failure |
|
|
305
|
+
| `TimeoutError` | — | Request exceeded timeout |
|
|
306
|
+
| `IngestionFailedError` | — | Async job failed |
|
|
307
|
+
| `PollTimeoutError` | — | Async job didn't finish in time |
|
|
308
|
+
| `InvalidConfigError` | — | Bad client configuration |
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
## CLI
|
|
313
|
+
|
|
314
|
+
```bash
|
|
315
|
+
# Set your API key
|
|
316
|
+
export ANTO_API_KEY=anto_live_xxx
|
|
317
|
+
|
|
318
|
+
anto projects
|
|
319
|
+
anto stats <project-id>
|
|
320
|
+
anto ontology <project-id>
|
|
321
|
+
anto ingest <project-id> ./triplets.json
|
|
322
|
+
anto query <project-id> ./query.json
|
|
323
|
+
anto dashboard <project-id>
|
|
324
|
+
anto poll <event-id>
|
|
325
|
+
|
|
326
|
+
# Environment
|
|
327
|
+
ANTO_BASE_URL=http://localhost:8000 # self-hosted
|
|
328
|
+
ANTO_DEBUG=1 # log HTTP calls
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
## Django / Flask Integration
|
|
334
|
+
|
|
335
|
+
```python
|
|
336
|
+
# settings.py (Django) or app.py (Flask)
|
|
337
|
+
from antonlytics import Antonlytics
|
|
338
|
+
|
|
339
|
+
anto = Antonlytics(
|
|
340
|
+
api_key=os.environ["ANTONLYTICS_API_KEY"],
|
|
341
|
+
base_url=os.environ.get("ANTONLYTICS_BASE_URL", "https://api.antonlytics.com"),
|
|
342
|
+
)
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
## Development
|
|
348
|
+
|
|
349
|
+
```bash
|
|
350
|
+
pip install -e ".[dev]"
|
|
351
|
+
pytest
|
|
352
|
+
mypy antonlytics
|
|
353
|
+
ruff check antonlytics
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
## Publishing to PyPI
|
|
359
|
+
|
|
360
|
+
```bash
|
|
361
|
+
pip install build twine
|
|
362
|
+
python -m build
|
|
363
|
+
twine upload dist/*
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
## License
|
|
369
|
+
|
|
370
|
+
MIT © Antonlytics
|