omniql 0.5.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.
omniql-0.5.0/PKG-INFO ADDED
@@ -0,0 +1,30 @@
1
+ Metadata-Version: 2.4
2
+ Name: omniql
3
+ Version: 0.5.0
4
+ Summary: A standardized, multi-database query language (OQL) for Python.
5
+ Author-email: Uttam Mahata <uttam-mahata-cs@outlook.com>
6
+ License: Apache License 2.0
7
+ Requires-Python: >=3.8
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: cffi>=1.0.0
10
+
11
+ # OmniQL for Python
12
+
13
+ A standardized, multi-database query language (OQL) for Python.
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ pip install omniql
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ ```python
24
+ import asyncio
25
+ from omniql import OmniEngine, Query
26
+
27
+ async def main():
28
+ engine = OmniEngine()
29
+ # ...
30
+ ```
omniql-0.5.0/README.md ADDED
@@ -0,0 +1,20 @@
1
+ # OmniQL for Python
2
+
3
+ A standardized, multi-database query language (OQL) for Python.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install omniql
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```python
14
+ import asyncio
15
+ from omniql import OmniEngine, Query
16
+
17
+ async def main():
18
+ engine = OmniEngine()
19
+ # ...
20
+ ```
@@ -0,0 +1,273 @@
1
+ """
2
+ OmniQL Python Binding
3
+ =====================
4
+
5
+ A native extension built with CFFI that wraps the OmniQL shared library
6
+ (``libomniql.so`` / ``omniql.dll``) and exposes an asyncio-compatible API.
7
+
8
+ Build the native library first::
9
+
10
+ go build -buildmode=c-shared -o libomniql.so ../../pkg/ffi
11
+
12
+ Then install the Python package::
13
+
14
+ pip install .
15
+
16
+ Example usage::
17
+
18
+ import asyncio
19
+ from omniql import OmniEngine, Query
20
+
21
+ async def main():
22
+ engine = OmniEngine()
23
+
24
+ # 1. Register a driver and bind a target to it.
25
+ driver_name = await engine.register_sqlite_driver(":memory:")
26
+ await engine.route("analytics_data", driver_name)
27
+
28
+ # 2. Execute a query.
29
+ result = await engine.execute(
30
+ Query(
31
+ target="analytics_data",
32
+ action="FIND",
33
+ filter={
34
+ "category": {"$in": ["electronics", "books"]},
35
+ "price": {"$lt": 500},
36
+ },
37
+ options={"limit": 20},
38
+ )
39
+ )
40
+ print(result.data)
41
+
42
+ asyncio.run(main())
43
+ """
44
+
45
+ from __future__ import annotations
46
+
47
+ import asyncio
48
+ import json
49
+ import os
50
+ import threading
51
+ from dataclasses import dataclass, field, asdict
52
+ from typing import Any, Dict, List, Optional
53
+
54
+ import cffi # type: ignore
55
+
56
+ # ---------------------------------------------------------------------------
57
+ # Load the native library via CFFI
58
+ # ---------------------------------------------------------------------------
59
+
60
+ _ffi = cffi.FFI()
61
+ _ffi.cdef(
62
+ """
63
+ int OmniQL_NewEngine(void);
64
+ void OmniQL_FreeEngine(int handle);
65
+ char * OmniQL_Execute(int handle, const char *queryJson);
66
+ char * OmniQL_RegisterSchema(int handle, const char *schemaJson);
67
+ char * OmniQL_Route(int handle, const char *target, const char *driverName);
68
+ char * OmniQL_RegisterSQLiteDriver(int handle, const char *dsn);
69
+ char * OmniQL_RegisterPostgresDriver(int handle, const char *connStr);
70
+ char * OmniQL_RegisterMongoDriver(int handle, const char *uri, const char *dbName);
71
+ void OmniQL_Free(char *ptr);
72
+ """
73
+ )
74
+
75
+ _LIB_SEARCH_PATHS = [
76
+ os.path.join(os.path.dirname(__file__), "libomniql.so"),
77
+ os.path.join(os.path.dirname(__file__), "omniql.dll"),
78
+ os.path.join(os.path.dirname(__file__), "libomniql.dylib"),
79
+ "libomniql.so",
80
+ "omniql.dll",
81
+ "libomniql.dylib",
82
+ ]
83
+
84
+
85
+ def _load_lib():
86
+ for path in _LIB_SEARCH_PATHS:
87
+ if os.path.exists(path):
88
+ return _ffi.dlopen(path)
89
+ raise OSError(
90
+ "OmniQL native library not found. "
91
+ "Build it with: go build -buildmode=c-shared -o libomniql.so ../../pkg/ffi"
92
+ )
93
+
94
+
95
+ _lib = _load_lib()
96
+
97
+
98
+ # ---------------------------------------------------------------------------
99
+ # Python data classes
100
+ # ---------------------------------------------------------------------------
101
+
102
+
103
+ @dataclass
104
+ class QueryOptions:
105
+ limit: int = 0
106
+ skip: int = 0
107
+ sort: Dict[str, int] = field(default_factory=dict)
108
+ fields: Dict[str, Any] = field(default_factory=dict)
109
+
110
+
111
+ @dataclass
112
+ class Query:
113
+ """An OQL query object."""
114
+
115
+ target: str
116
+ action: str = "FIND"
117
+ filter: Dict[str, Any] = field(default_factory=dict)
118
+ document: Dict[str, Any] = field(default_factory=dict)
119
+ options: QueryOptions = field(default_factory=QueryOptions)
120
+
121
+ def to_dict(self) -> dict:
122
+ return asdict(self)
123
+
124
+
125
+ @dataclass
126
+ class OmniMeta:
127
+ total: int = 0
128
+ returned: int = 0
129
+ driver: str = ""
130
+ target: str = ""
131
+
132
+
133
+ @dataclass
134
+ class OmniError:
135
+ code: str = ""
136
+ message: str = ""
137
+
138
+
139
+ @dataclass
140
+ class OmniResult:
141
+ """The standardised OmniJSON response."""
142
+
143
+ data: List[Dict[str, Any]] = field(default_factory=list)
144
+ meta: OmniMeta = field(default_factory=OmniMeta)
145
+ error: Optional[OmniError] = None
146
+
147
+ @classmethod
148
+ def from_dict(cls, d: dict) -> "OmniResult":
149
+ meta = OmniMeta(**d.get("meta", {}))
150
+ err_data = d.get("error")
151
+ err = OmniError(**err_data) if err_data else None
152
+ return cls(data=d.get("data", []), meta=meta, error=err)
153
+
154
+
155
+ # ---------------------------------------------------------------------------
156
+ # OmniEngine
157
+ # ---------------------------------------------------------------------------
158
+
159
+
160
+ class OmniEngine:
161
+ """High-level wrapper around the native OmniQL Core Engine.
162
+
163
+ The engine is thread-safe and supports asyncio via
164
+ :meth:`execute` (async) or :meth:`execute_sync` (synchronous).
165
+ """
166
+
167
+ def __init__(self) -> None:
168
+ self._handle: int = _lib.OmniQL_NewEngine()
169
+ self._lock = threading.Lock()
170
+
171
+ def __del__(self) -> None:
172
+ try:
173
+ _lib.OmniQL_FreeEngine(self._handle)
174
+ except Exception:
175
+ pass
176
+
177
+ # ------------------------------------------------------------------
178
+ # Synchronous API
179
+ # ------------------------------------------------------------------
180
+
181
+ def execute_sync(self, query: Query) -> OmniResult:
182
+ """Execute a query synchronously and return the result."""
183
+ query_json = json.dumps(query.to_dict()).encode("utf-8")
184
+ with self._lock:
185
+ raw = _lib.OmniQL_Execute(self._handle, query_json)
186
+ try:
187
+ response = json.loads(_ffi.string(raw).decode("utf-8"))
188
+ finally:
189
+ _lib.OmniQL_Free(raw)
190
+ return OmniResult.from_dict(response)
191
+
192
+ def register_schema_sync(self, schema: dict) -> None:
193
+ """Register a collection schema synchronously."""
194
+ schema_json = json.dumps(schema).encode("utf-8")
195
+ with self._lock:
196
+ raw = _lib.OmniQL_RegisterSchema(self._handle, schema_json)
197
+ _lib.OmniQL_Free(raw)
198
+
199
+ def route_sync(self, target: str, driver_name: str) -> None:
200
+ """Bind a target collection/table to a driver name synchronously."""
201
+ with self._lock:
202
+ raw = _lib.OmniQL_Route(self._handle, target.encode(), driver_name.encode())
203
+ _lib.OmniQL_Free(raw)
204
+
205
+ def register_sqlite_driver_sync(self, dsn: str) -> str:
206
+ """Register a SQLite driver synchronously. Returns the driver name."""
207
+ with self._lock:
208
+ raw = _lib.OmniQL_RegisterSQLiteDriver(self._handle, dsn.encode())
209
+ try:
210
+ result = json.loads(_ffi.string(raw).decode())
211
+ return result.get("driver", "sqlite")
212
+ finally:
213
+ _lib.OmniQL_Free(raw)
214
+
215
+ def register_postgres_driver_sync(self, conn_str: str) -> str:
216
+ """Register a PostgreSQL driver synchronously. Returns the driver name."""
217
+ with self._lock:
218
+ raw = _lib.OmniQL_RegisterPostgresDriver(self._handle, conn_str.encode())
219
+ try:
220
+ result = json.loads(_ffi.string(raw).decode())
221
+ return result.get("driver", "postgres")
222
+ finally:
223
+ _lib.OmniQL_Free(raw)
224
+
225
+ def register_mongo_driver_sync(self, uri: str, db_name: str) -> str:
226
+ """Register a MongoDB driver synchronously. Returns the driver name."""
227
+ with self._lock:
228
+ raw = _lib.OmniQL_RegisterMongoDriver(self._handle, uri.encode(), db_name.encode())
229
+ try:
230
+ result = json.loads(_ffi.string(raw).decode())
231
+ return result.get("driver", "mongo")
232
+ finally:
233
+ _lib.OmniQL_Free(raw)
234
+
235
+ # ------------------------------------------------------------------
236
+ # Asyncio API
237
+ # ------------------------------------------------------------------
238
+
239
+ def _get_loop(self) -> asyncio.AbstractEventLoop:
240
+ try:
241
+ return asyncio.get_running_loop()
242
+ except RuntimeError:
243
+ return asyncio.get_event_loop()
244
+
245
+ async def execute(self, query: Query) -> OmniResult:
246
+ """Execute a query asynchronously (runs in a thread-pool executor)."""
247
+ loop = self._get_loop()
248
+ return await loop.run_in_executor(None, self.execute_sync, query)
249
+
250
+ async def register_schema(self, schema: dict) -> None:
251
+ """Register a schema asynchronously."""
252
+ loop = self._get_loop()
253
+ await loop.run_in_executor(None, self.register_schema_sync, schema)
254
+
255
+ async def route(self, target: str, driver_name: str) -> None:
256
+ """Bind a target collection/table to a driver name asynchronously."""
257
+ loop = self._get_loop()
258
+ await loop.run_in_executor(None, self.route_sync, target, driver_name)
259
+
260
+ async def register_sqlite_driver(self, dsn: str) -> str:
261
+ """Register a SQLite driver asynchronously. Returns the driver name."""
262
+ loop = self._get_loop()
263
+ return await loop.run_in_executor(None, self.register_sqlite_driver_sync, dsn)
264
+
265
+ async def register_postgres_driver(self, conn_str: str) -> str:
266
+ """Register a PostgreSQL driver asynchronously. Returns the driver name."""
267
+ loop = self._get_loop()
268
+ return await loop.run_in_executor(None, self.register_postgres_driver_sync, conn_str)
269
+
270
+ async def register_mongo_driver(self, uri: str, db_name: str) -> str:
271
+ """Register a MongoDB driver asynchronously. Returns the driver name."""
272
+ loop = self._get_loop()
273
+ return await loop.run_in_executor(None, self.register_mongo_driver_sync, uri, db_name)
Binary file
Binary file
Binary file
@@ -0,0 +1,30 @@
1
+ Metadata-Version: 2.4
2
+ Name: omniql
3
+ Version: 0.5.0
4
+ Summary: A standardized, multi-database query language (OQL) for Python.
5
+ Author-email: Uttam Mahata <uttam-mahata-cs@outlook.com>
6
+ License: Apache License 2.0
7
+ Requires-Python: >=3.8
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: cffi>=1.0.0
10
+
11
+ # OmniQL for Python
12
+
13
+ A standardized, multi-database query language (OQL) for Python.
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ pip install omniql
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ ```python
24
+ import asyncio
25
+ from omniql import OmniEngine, Query
26
+
27
+ async def main():
28
+ engine = OmniEngine()
29
+ # ...
30
+ ```
@@ -0,0 +1,15 @@
1
+ README.md
2
+ pyproject.toml
3
+ ./omniql/__init__.py
4
+ ./omniql/libomniql.dylib
5
+ ./omniql/libomniql.so
6
+ ./omniql/omniql.dll
7
+ omniql/__init__.py
8
+ omniql/libomniql.dylib
9
+ omniql/libomniql.so
10
+ omniql/omniql.dll
11
+ omniql.egg-info/PKG-INFO
12
+ omniql.egg-info/SOURCES.txt
13
+ omniql.egg-info/dependency_links.txt
14
+ omniql.egg-info/requires.txt
15
+ omniql.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ cffi>=1.0.0
@@ -0,0 +1 @@
1
+ omniql
@@ -0,0 +1,24 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "cffi>=1.0.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "omniql"
7
+ version = "0.5.0"
8
+ description = "A standardized, multi-database query language (OQL) for Python."
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ license = {text = "Apache License 2.0"}
12
+ authors = [
13
+ {name = "Uttam Mahata", email = "uttam-mahata-cs@outlook.com"},
14
+ ]
15
+ dependencies = [
16
+ "cffi>=1.0.0",
17
+ ]
18
+
19
+ [tool.setuptools]
20
+ packages = ["omniql"]
21
+ package-dir = {"" = "."}
22
+
23
+ [tool.setuptools.package-data]
24
+ omniql = ["*.so", "*.dll", "*.dylib"]
omniql-0.5.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+