synthigy 0.1.0__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.
- synthigy/__init__.py +164 -0
- synthigy/async_client.py +2049 -0
- synthigy/auth.py +262 -0
- synthigy/backfill.py +45 -0
- synthigy/codegen.py +819 -0
- synthigy/compose.py +88 -0
- synthigy/errors.py +122 -0
- synthigy/events.py +294 -0
- synthigy/facade.py +476 -0
- synthigy/filters.py +35 -0
- synthigy/ops.py +77 -0
- synthigy/py.typed +0 -0
- synthigy/selection.py +71 -0
- synthigy/util.py +54 -0
- synthigy-0.1.0.dist-info/METADATA +310 -0
- synthigy-0.1.0.dist-info/RECORD +20 -0
- synthigy-0.1.0.dist-info/WHEEL +5 -0
- synthigy-0.1.0.dist-info/entry_points.txt +2 -0
- synthigy-0.1.0.dist-info/licenses/LICENSE +21 -0
- synthigy-0.1.0.dist-info/top_level.txt +1 -0
synthigy/__init__.py
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"""Synthigy SDK — thin, stdlib-only client for the /data endpoint.
|
|
2
|
+
|
|
3
|
+
ONE ENGINE: the async-native `AsyncClient` (async_client.py) is the whole
|
|
4
|
+
implementation. The blocking `Client` is a facade over it driving a single
|
|
5
|
+
background event-loop thread (facade.py) — same API as always for
|
|
6
|
+
scripts, seeds and notebooks; async apps use the `aconnect`/`aclient`
|
|
7
|
+
surface natively.
|
|
8
|
+
|
|
9
|
+
THE INVARIANT: one process, one client, one backend. `connect(...)` installs
|
|
10
|
+
a module-wide default (destroying any previous one, server-restart style);
|
|
11
|
+
the module-level verbs operate on it. Identity is multiplexed per-call via
|
|
12
|
+
`acting_as=`, never a second connect. Constructing `Client` directly is the
|
|
13
|
+
escape hatch (tests).
|
|
14
|
+
|
|
15
|
+
import synthigy
|
|
16
|
+
from synthigy import eq, rel
|
|
17
|
+
|
|
18
|
+
synthigy.connect(endpoint="http://localhost:7887",
|
|
19
|
+
client_id="my-service", client_secret=SECRET)
|
|
20
|
+
|
|
21
|
+
users = synthigy.search("User", {"active": eq(True), "_limit": 10},
|
|
22
|
+
{"name": None, "roles": {"name": None}},
|
|
23
|
+
acting_as=user_xid)
|
|
24
|
+
|
|
25
|
+
Async-first (BFFs, FastAPI/uvicorn services):
|
|
26
|
+
|
|
27
|
+
synthigy.aconnect(endpoint=..., client_id=..., client_secret=SECRET)
|
|
28
|
+
rows = await synthigy.aclient().search("User", ..., acting_as=user_xid)
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
from . import ops # noqa: F401
|
|
32
|
+
from .async_client import AsyncClient # noqa: F401
|
|
33
|
+
from .compose import compose_forest, compose_tree # noqa: F401
|
|
34
|
+
from .errors import SynthigyError # noqa: F401
|
|
35
|
+
from .facade import Client
|
|
36
|
+
from .filters import ( # noqa: F401
|
|
37
|
+
and_, eq, gt, gte, ilike, in_, is_not_null, is_null, like, lt, lte, neq,
|
|
38
|
+
nin, not_, or_,
|
|
39
|
+
)
|
|
40
|
+
from .selection import fields, normalize_selection, rel # noqa: F401
|
|
41
|
+
from .util import new_xid # noqa: F401
|
|
42
|
+
|
|
43
|
+
_default_client = None
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def connect(endpoint, **config):
|
|
47
|
+
"""Create a client and install it as the module default. Any previous
|
|
48
|
+
default is destroyed first (watches close, SSE drops)."""
|
|
49
|
+
global _default_client
|
|
50
|
+
prev = _default_client
|
|
51
|
+
_default_client = Client(endpoint, **config)
|
|
52
|
+
if prev:
|
|
53
|
+
prev.close()
|
|
54
|
+
return _default_client
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def disconnect():
|
|
58
|
+
"""Destroy and uninstall the default client. No-op when not connected."""
|
|
59
|
+
global _default_client
|
|
60
|
+
prev = _default_client
|
|
61
|
+
_default_client = None
|
|
62
|
+
if prev:
|
|
63
|
+
prev.close()
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def get_client():
|
|
67
|
+
"""The installed default client, or None."""
|
|
68
|
+
return _default_client
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _dflt():
|
|
72
|
+
if _default_client is None:
|
|
73
|
+
raise SynthigyError("not connected — call synthigy.connect() first",
|
|
74
|
+
"NOT_CONNECTED")
|
|
75
|
+
return _default_client
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
# ── module-default ASYNC client (twin of connect/disconnect) ─────────────
|
|
79
|
+
|
|
80
|
+
_default_async_client = None
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def aconnect(endpoint, **config):
|
|
84
|
+
"""Create an AsyncClient and install it as the module default — the
|
|
85
|
+
async twin of connect(); same one-process-one-client invariant.
|
|
86
|
+
Generated async typed ops (codegen) run on this default. A previous
|
|
87
|
+
default is closed detachedly when an event loop is running."""
|
|
88
|
+
global _default_async_client
|
|
89
|
+
prev = _default_async_client
|
|
90
|
+
_default_async_client = AsyncClient(endpoint, **config)
|
|
91
|
+
if prev:
|
|
92
|
+
import asyncio
|
|
93
|
+
try:
|
|
94
|
+
asyncio.get_running_loop()
|
|
95
|
+
asyncio.ensure_future(prev.close())
|
|
96
|
+
except RuntimeError:
|
|
97
|
+
pass # no loop — nothing live to tear down
|
|
98
|
+
return _default_async_client
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
async def adisconnect():
|
|
102
|
+
"""Close and uninstall the default async client. No-op when absent."""
|
|
103
|
+
global _default_async_client
|
|
104
|
+
prev = _default_async_client
|
|
105
|
+
_default_async_client = None
|
|
106
|
+
if prev:
|
|
107
|
+
await prev.close()
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def aclient():
|
|
111
|
+
"""The installed default AsyncClient (raises NOT_CONNECTED if none)."""
|
|
112
|
+
if _default_async_client is None:
|
|
113
|
+
raise SynthigyError("not connected — call synthigy.aconnect() first",
|
|
114
|
+
"NOT_CONNECTED")
|
|
115
|
+
return _default_async_client
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
# CRUD + XSQL
|
|
119
|
+
def search(*a, **kw): return _dflt().search(*a, **kw)
|
|
120
|
+
def get(*a, **kw): return _dflt().get(*a, **kw)
|
|
121
|
+
def sync(*a, **kw): return _dflt().sync(*a, **kw)
|
|
122
|
+
def stack(*a, **kw): return _dflt().stack(*a, **kw)
|
|
123
|
+
def slice(*a, **kw): return _dflt().slice(*a, **kw) # noqa: A001
|
|
124
|
+
def delete(*a, **kw): return _dflt().delete(*a, **kw)
|
|
125
|
+
def purge(*a, **kw): return _dflt().purge(*a, **kw)
|
|
126
|
+
def sql_template(*a, **kw): return _dflt().sql_template(*a, **kw)
|
|
127
|
+
def query(*a, **kw): return _dflt().query(*a, **kw)
|
|
128
|
+
def search_tree(*a, **kw): return _dflt().search_tree(*a, **kw)
|
|
129
|
+
def get_tree(*a, **kw): return _dflt().get_tree(*a, **kw)
|
|
130
|
+
def exec_(*a, **kw): return _dflt().exec_(*a, **kw)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
# Introspection
|
|
134
|
+
def schema(*a, **kw): return _dflt().schema(*a, **kw)
|
|
135
|
+
def lint(*a, **kw): return _dflt().lint(*a, **kw)
|
|
136
|
+
def onboard(*a, **kw): return _dflt().onboard(*a, **kw)
|
|
137
|
+
def onboard_complete(*a, **kw): return _dflt().onboard_complete(*a, **kw)
|
|
138
|
+
def deployed_model(*a, **kw): return _dflt().deployed_model(*a, **kw)
|
|
139
|
+
def runtime_model(*a, **kw): return _dflt().runtime_model(*a, **kw)
|
|
140
|
+
def token(*a, **kw): return _dflt().token(*a, **kw)
|
|
141
|
+
def history(): return _dflt().history
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
# Streaming
|
|
145
|
+
def listen(*a, **kw): return _dflt().listen(*a, **kw)
|
|
146
|
+
def observe(*a, **kw): return _dflt().observe(*a, **kw)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
# Live data (watch layer)
|
|
150
|
+
def watch(*a, **kw): return _dflt().watch(*a, **kw)
|
|
151
|
+
def watch_schema(*a, **kw): return _dflt().watch_schema(*a, **kw)
|
|
152
|
+
def watch_query(*a, **kw): return _dflt().watch_query(*a, **kw)
|
|
153
|
+
def watch_query_xsql(*a, **kw): return _dflt().watch_query_xsql(*a, **kw)
|
|
154
|
+
def watch_sql_template(*a, **kw): return _dflt().watch_sql_template(*a, **kw)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
# Subscriptions (advanced — prefer the watch family)
|
|
158
|
+
def subscribe(*a, **kw): return _dflt().subscribe(*a, **kw)
|
|
159
|
+
def unsubscribe(*a, **kw): return _dflt().unsubscribe(*a, **kw)
|
|
160
|
+
def subscribe_model(*a, **kw): return _dflt().subscribe_model(*a, **kw)
|
|
161
|
+
def unsubscribe_model(*a, **kw): return _dflt().unsubscribe_model(*a, **kw)
|
|
162
|
+
def set_subscriptions(*a, **kw): return _dflt().set_subscriptions(*a, **kw)
|
|
163
|
+
def clear_subscriptions(*a, **kw): return _dflt().clear_subscriptions(*a, **kw)
|
|
164
|
+
def subscriptions(*a, **kw): return _dflt().subscriptions(*a, **kw)
|