periplus-python-sdk 0.5.0__tar.gz → 0.6.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.
- {periplus_python_sdk-0.5.0/src/periplus_python_sdk.egg-info → periplus_python_sdk-0.6.0}/PKG-INFO +18 -21
- {periplus_python_sdk-0.5.0 → periplus_python_sdk-0.6.0}/README.md +16 -17
- {periplus_python_sdk-0.5.0 → periplus_python_sdk-0.6.0}/pyproject.toml +3 -3
- {periplus_python_sdk-0.5.0 → periplus_python_sdk-0.6.0/src/periplus_python_sdk.egg-info}/PKG-INFO +18 -21
- {periplus_python_sdk-0.5.0 → periplus_python_sdk-0.6.0}/src/periplus_python_sdk.egg-info/SOURCES.txt +3 -1
- {periplus_python_sdk-0.5.0 → periplus_python_sdk-0.6.0}/src/periplus_python_sdk.egg-info/requires.txt +1 -4
- periplus_python_sdk-0.6.0/src/periplus_sdk/sql_api.py +25 -0
- {periplus_python_sdk-0.5.0 → periplus_python_sdk-0.6.0}/tests/test_notebook.py +2 -2
- periplus_python_sdk-0.6.0/tests/test_sql_api.py +38 -0
- {periplus_python_sdk-0.5.0 → periplus_python_sdk-0.6.0}/LICENSE +0 -0
- {periplus_python_sdk-0.5.0 → periplus_python_sdk-0.6.0}/NOTICE +0 -0
- {periplus_python_sdk-0.5.0 → periplus_python_sdk-0.6.0}/setup.cfg +0 -0
- {periplus_python_sdk-0.5.0 → periplus_python_sdk-0.6.0}/src/periplus_python_sdk.egg-info/dependency_links.txt +0 -0
- {periplus_python_sdk-0.5.0 → periplus_python_sdk-0.6.0}/src/periplus_python_sdk.egg-info/entry_points.txt +0 -0
- {periplus_python_sdk-0.5.0 → periplus_python_sdk-0.6.0}/src/periplus_python_sdk.egg-info/top_level.txt +0 -0
- {periplus_python_sdk-0.5.0 → periplus_python_sdk-0.6.0}/src/periplus_sdk/__init__.py +0 -0
- {periplus_python_sdk-0.5.0 → periplus_python_sdk-0.6.0}/src/periplus_sdk/client.py +0 -0
- {periplus_python_sdk-0.5.0 → periplus_python_sdk-0.6.0}/src/periplus_sdk/dbapi.py +0 -0
- {periplus_python_sdk-0.5.0 → periplus_python_sdk-0.6.0}/src/periplus_sdk/errors.py +0 -0
- {periplus_python_sdk-0.5.0 → periplus_python_sdk-0.6.0}/src/periplus_sdk/py.typed +0 -0
- {periplus_python_sdk-0.5.0 → periplus_python_sdk-0.6.0}/src/periplus_sdk/sqlalchemy.py +0 -0
- {periplus_python_sdk-0.5.0 → periplus_python_sdk-0.6.0}/src/periplus_sdk/types.py +0 -0
- {periplus_python_sdk-0.5.0 → periplus_python_sdk-0.6.0}/tests/test_client.py +0 -0
- {periplus_python_sdk-0.5.0 → periplus_python_sdk-0.6.0}/tests/test_dbapi.py +0 -0
{periplus_python_sdk-0.5.0/src/periplus_python_sdk.egg-info → periplus_python_sdk-0.6.0}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: periplus-python-sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
4
4
|
Summary: Read-only Python client for the public Periplus query API
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Project-URL: Repository, https://github.com/elei-io/periplus
|
|
@@ -11,10 +11,8 @@ License-File: LICENSE
|
|
|
11
11
|
License-File: NOTICE
|
|
12
12
|
Requires-Dist: httpx>=0.28
|
|
13
13
|
Requires-Dist: pydantic<3,>=2.12
|
|
14
|
-
|
|
15
|
-
Requires-Dist: sqlalchemy<3,>=2.0; extra == "sqlalchemy"
|
|
14
|
+
Requires-Dist: sqlalchemy<3,>=2.0
|
|
16
15
|
Provides-Extra: notebook
|
|
17
|
-
Requires-Dist: sqlalchemy<3,>=2.0; extra == "notebook"
|
|
18
16
|
Requires-Dist: marimo[sql]>=0.24.1; extra == "notebook"
|
|
19
17
|
Dynamic: license-file
|
|
20
18
|
|
|
@@ -45,18 +43,15 @@ The client reuses HTTP connections; close it with a context manager or `close()`
|
|
|
45
43
|
Install the notebook integration from PyPI:
|
|
46
44
|
|
|
47
45
|
```sh
|
|
48
|
-
uv add "periplus-python-sdk[notebook]>=0.
|
|
46
|
+
uv add "periplus-python-sdk[notebook]>=0.6.0"
|
|
49
47
|
```
|
|
50
48
|
|
|
51
49
|
In a Python setup cell, create a SQLAlchemy engine:
|
|
52
50
|
|
|
53
51
|
```python
|
|
54
|
-
from
|
|
52
|
+
from periplus_sdk import sql_api
|
|
55
53
|
|
|
56
|
-
pp = create_engine(
|
|
57
|
-
"periplus:///public_v1",
|
|
58
|
-
connect_args={"base_url": "https://periplus.dev", "mode": "stable"},
|
|
59
|
-
)
|
|
54
|
+
pp = sql_api.create_engine("https://periplus.dev", mode="stable")
|
|
60
55
|
```
|
|
61
56
|
|
|
62
57
|
Add a SQL cell, select **pp** in its connection dropdown, and enter:
|
|
@@ -86,16 +81,18 @@ captures = mo.sql(
|
|
|
86
81
|
)
|
|
87
82
|
```
|
|
88
83
|
|
|
89
|
-
Set `mode="experimental"`
|
|
90
|
-
|
|
91
|
-
|
|
84
|
+
Set `mode="experimental"` for the experimental service. Omit the URL to use
|
|
85
|
+
`PERIPLUS_PUBLIC_URL`. Optional `timeout=140` and `schema_version="public_v1"`
|
|
86
|
+
arguments configure the client deadline and public schema. Run `pp.dispose()` when finished. This is a read-only
|
|
92
87
|
SQLAlchemy dialect for textual SQL and reflection, not a writable ORM backend.
|
|
93
88
|
Each statement has its own server snapshot; SQLAlchemy transaction blocks do not
|
|
94
89
|
provide a shared snapshot or rollback. The adapter makes no transaction requests.
|
|
95
90
|
|
|
96
91
|
A complete notebook is in `examples/notebook.py`. The integration is tested with
|
|
97
|
-
marimo 0.24.1 and SQLAlchemy 2.x.
|
|
98
|
-
|
|
92
|
+
marimo 0.24.1 and SQLAlchemy 2.x. SQLAlchemy is included in the standard SDK install; the `notebook` extra adds
|
|
93
|
+
marimo. Existing marimo environments only need `uv add "periplus-python-sdk>=0.6.0"`.
|
|
94
|
+
The returned object is a standard SQLAlchemy Engine, also usable with pandas and
|
|
95
|
+
ordinary Python scripts. Engine creation is lazy; the first query opens a connection.
|
|
99
96
|
|
|
100
97
|
## DB-API connection
|
|
101
98
|
|
|
@@ -199,10 +196,10 @@ Use `aclose()` when managing an async client's lifetime explicitly.
|
|
|
199
196
|
Install the public-v1 client from PyPI:
|
|
200
197
|
|
|
201
198
|
```sh
|
|
202
|
-
python -m pip install "periplus-python-sdk>=0.
|
|
199
|
+
python -m pip install "periplus-python-sdk>=0.6.0"
|
|
203
200
|
```
|
|
204
201
|
|
|
205
|
-
Version 0.
|
|
202
|
+
Version 0.6.0 supports the current public-v1 contract. For production, configure
|
|
206
203
|
`PERIPLUS_PUBLIC_URL=https://periplus.dev`; no API token is required.
|
|
207
204
|
Run the installed package against an available public app:
|
|
208
205
|
|
|
@@ -214,11 +211,11 @@ PERIPLUS_PUBLIC_URL=http://localhost:8080 python packages/periplus-python-sdk/ex
|
|
|
214
211
|
|
|
215
212
|
Repository CI publishes immutable releases from tags named
|
|
216
213
|
`periplus-python-sdk-v<version>`. The tag must exactly match the static version
|
|
217
|
-
in `pyproject.toml`; for example, version `0.
|
|
214
|
+
in `pyproject.toml`; for example, version `0.6.0` is released with:
|
|
218
215
|
|
|
219
216
|
```sh
|
|
220
|
-
git tag periplus-python-sdk-v0.
|
|
221
|
-
git push origin periplus-python-sdk-v0.
|
|
217
|
+
git tag periplus-python-sdk-v0.6.0
|
|
218
|
+
git push origin periplus-python-sdk-v0.6.0
|
|
222
219
|
```
|
|
223
220
|
|
|
224
221
|
PyPI publishing uses Trusted Publishing rather than a stored API token. The
|
|
@@ -228,7 +225,7 @@ that GitHub environment with required reviewers before the first release.
|
|
|
228
225
|
|
|
229
226
|
## Public v1
|
|
230
227
|
|
|
231
|
-
Install the updated SDK from PyPI with `python -m pip install "periplus-python-sdk>=0.
|
|
228
|
+
Install the updated SDK from PyPI with `python -m pip install "periplus-python-sdk>=0.6.0"`. The previously published 0.2.0 release predates this contract. `prepare` and `execute` accept keyword-only `schema_version="public_v1"` (the default); responses preserve `schema_version` separately from `source_snapshot`. Unavailable versions are rejected by the server.
|
|
232
229
|
|
|
233
230
|
## License
|
|
234
231
|
|
|
@@ -25,18 +25,15 @@ The client reuses HTTP connections; close it with a context manager or `close()`
|
|
|
25
25
|
Install the notebook integration from PyPI:
|
|
26
26
|
|
|
27
27
|
```sh
|
|
28
|
-
uv add "periplus-python-sdk[notebook]>=0.
|
|
28
|
+
uv add "periplus-python-sdk[notebook]>=0.6.0"
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
In a Python setup cell, create a SQLAlchemy engine:
|
|
32
32
|
|
|
33
33
|
```python
|
|
34
|
-
from
|
|
34
|
+
from periplus_sdk import sql_api
|
|
35
35
|
|
|
36
|
-
pp = create_engine(
|
|
37
|
-
"periplus:///public_v1",
|
|
38
|
-
connect_args={"base_url": "https://periplus.dev", "mode": "stable"},
|
|
39
|
-
)
|
|
36
|
+
pp = sql_api.create_engine("https://periplus.dev", mode="stable")
|
|
40
37
|
```
|
|
41
38
|
|
|
42
39
|
Add a SQL cell, select **pp** in its connection dropdown, and enter:
|
|
@@ -66,16 +63,18 @@ captures = mo.sql(
|
|
|
66
63
|
)
|
|
67
64
|
```
|
|
68
65
|
|
|
69
|
-
Set `mode="experimental"`
|
|
70
|
-
|
|
71
|
-
|
|
66
|
+
Set `mode="experimental"` for the experimental service. Omit the URL to use
|
|
67
|
+
`PERIPLUS_PUBLIC_URL`. Optional `timeout=140` and `schema_version="public_v1"`
|
|
68
|
+
arguments configure the client deadline and public schema. Run `pp.dispose()` when finished. This is a read-only
|
|
72
69
|
SQLAlchemy dialect for textual SQL and reflection, not a writable ORM backend.
|
|
73
70
|
Each statement has its own server snapshot; SQLAlchemy transaction blocks do not
|
|
74
71
|
provide a shared snapshot or rollback. The adapter makes no transaction requests.
|
|
75
72
|
|
|
76
73
|
A complete notebook is in `examples/notebook.py`. The integration is tested with
|
|
77
|
-
marimo 0.24.1 and SQLAlchemy 2.x.
|
|
78
|
-
|
|
74
|
+
marimo 0.24.1 and SQLAlchemy 2.x. SQLAlchemy is included in the standard SDK install; the `notebook` extra adds
|
|
75
|
+
marimo. Existing marimo environments only need `uv add "periplus-python-sdk>=0.6.0"`.
|
|
76
|
+
The returned object is a standard SQLAlchemy Engine, also usable with pandas and
|
|
77
|
+
ordinary Python scripts. Engine creation is lazy; the first query opens a connection.
|
|
79
78
|
|
|
80
79
|
## DB-API connection
|
|
81
80
|
|
|
@@ -179,10 +178,10 @@ Use `aclose()` when managing an async client's lifetime explicitly.
|
|
|
179
178
|
Install the public-v1 client from PyPI:
|
|
180
179
|
|
|
181
180
|
```sh
|
|
182
|
-
python -m pip install "periplus-python-sdk>=0.
|
|
181
|
+
python -m pip install "periplus-python-sdk>=0.6.0"
|
|
183
182
|
```
|
|
184
183
|
|
|
185
|
-
Version 0.
|
|
184
|
+
Version 0.6.0 supports the current public-v1 contract. For production, configure
|
|
186
185
|
`PERIPLUS_PUBLIC_URL=https://periplus.dev`; no API token is required.
|
|
187
186
|
Run the installed package against an available public app:
|
|
188
187
|
|
|
@@ -194,11 +193,11 @@ PERIPLUS_PUBLIC_URL=http://localhost:8080 python packages/periplus-python-sdk/ex
|
|
|
194
193
|
|
|
195
194
|
Repository CI publishes immutable releases from tags named
|
|
196
195
|
`periplus-python-sdk-v<version>`. The tag must exactly match the static version
|
|
197
|
-
in `pyproject.toml`; for example, version `0.
|
|
196
|
+
in `pyproject.toml`; for example, version `0.6.0` is released with:
|
|
198
197
|
|
|
199
198
|
```sh
|
|
200
|
-
git tag periplus-python-sdk-v0.
|
|
201
|
-
git push origin periplus-python-sdk-v0.
|
|
199
|
+
git tag periplus-python-sdk-v0.6.0
|
|
200
|
+
git push origin periplus-python-sdk-v0.6.0
|
|
202
201
|
```
|
|
203
202
|
|
|
204
203
|
PyPI publishing uses Trusted Publishing rather than a stored API token. The
|
|
@@ -208,7 +207,7 @@ that GitHub environment with required reviewers before the first release.
|
|
|
208
207
|
|
|
209
208
|
## Public v1
|
|
210
209
|
|
|
211
|
-
Install the updated SDK from PyPI with `python -m pip install "periplus-python-sdk>=0.
|
|
210
|
+
Install the updated SDK from PyPI with `python -m pip install "periplus-python-sdk>=0.6.0"`. The previously published 0.2.0 release predates this contract. `prepare` and `execute` accept keyword-only `schema_version="public_v1"` (the default); responses preserve `schema_version` separately from `source_snapshot`. Unavailable versions are rejected by the server.
|
|
212
211
|
|
|
213
212
|
## License
|
|
214
213
|
|
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
license = "Apache-2.0"
|
|
3
3
|
license-files = ["LICENSE", "NOTICE"]
|
|
4
4
|
name = "periplus-python-sdk"
|
|
5
|
-
version = "0.
|
|
5
|
+
version = "0.6.0"
|
|
6
6
|
description = "Read-only Python client for the public Periplus query API"
|
|
7
7
|
readme = "README.md"
|
|
8
8
|
requires-python = ">=3.11"
|
|
9
9
|
dependencies = [
|
|
10
10
|
"httpx>=0.28",
|
|
11
11
|
"pydantic>=2.12,<3",
|
|
12
|
+
"sqlalchemy>=2.0,<3",
|
|
12
13
|
]
|
|
13
14
|
|
|
14
15
|
[project.optional-dependencies]
|
|
15
|
-
|
|
16
|
-
notebook = ["sqlalchemy>=2.0,<3", "marimo[sql]>=0.24.1"]
|
|
16
|
+
notebook = ["marimo[sql]>=0.24.1"]
|
|
17
17
|
|
|
18
18
|
[project.entry-points."sqlalchemy.dialects"]
|
|
19
19
|
periplus = "periplus_sdk.sqlalchemy:PeriplusDialect"
|
{periplus_python_sdk-0.5.0 → periplus_python_sdk-0.6.0/src/periplus_python_sdk.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: periplus-python-sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
4
4
|
Summary: Read-only Python client for the public Periplus query API
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Project-URL: Repository, https://github.com/elei-io/periplus
|
|
@@ -11,10 +11,8 @@ License-File: LICENSE
|
|
|
11
11
|
License-File: NOTICE
|
|
12
12
|
Requires-Dist: httpx>=0.28
|
|
13
13
|
Requires-Dist: pydantic<3,>=2.12
|
|
14
|
-
|
|
15
|
-
Requires-Dist: sqlalchemy<3,>=2.0; extra == "sqlalchemy"
|
|
14
|
+
Requires-Dist: sqlalchemy<3,>=2.0
|
|
16
15
|
Provides-Extra: notebook
|
|
17
|
-
Requires-Dist: sqlalchemy<3,>=2.0; extra == "notebook"
|
|
18
16
|
Requires-Dist: marimo[sql]>=0.24.1; extra == "notebook"
|
|
19
17
|
Dynamic: license-file
|
|
20
18
|
|
|
@@ -45,18 +43,15 @@ The client reuses HTTP connections; close it with a context manager or `close()`
|
|
|
45
43
|
Install the notebook integration from PyPI:
|
|
46
44
|
|
|
47
45
|
```sh
|
|
48
|
-
uv add "periplus-python-sdk[notebook]>=0.
|
|
46
|
+
uv add "periplus-python-sdk[notebook]>=0.6.0"
|
|
49
47
|
```
|
|
50
48
|
|
|
51
49
|
In a Python setup cell, create a SQLAlchemy engine:
|
|
52
50
|
|
|
53
51
|
```python
|
|
54
|
-
from
|
|
52
|
+
from periplus_sdk import sql_api
|
|
55
53
|
|
|
56
|
-
pp = create_engine(
|
|
57
|
-
"periplus:///public_v1",
|
|
58
|
-
connect_args={"base_url": "https://periplus.dev", "mode": "stable"},
|
|
59
|
-
)
|
|
54
|
+
pp = sql_api.create_engine("https://periplus.dev", mode="stable")
|
|
60
55
|
```
|
|
61
56
|
|
|
62
57
|
Add a SQL cell, select **pp** in its connection dropdown, and enter:
|
|
@@ -86,16 +81,18 @@ captures = mo.sql(
|
|
|
86
81
|
)
|
|
87
82
|
```
|
|
88
83
|
|
|
89
|
-
Set `mode="experimental"`
|
|
90
|
-
|
|
91
|
-
|
|
84
|
+
Set `mode="experimental"` for the experimental service. Omit the URL to use
|
|
85
|
+
`PERIPLUS_PUBLIC_URL`. Optional `timeout=140` and `schema_version="public_v1"`
|
|
86
|
+
arguments configure the client deadline and public schema. Run `pp.dispose()` when finished. This is a read-only
|
|
92
87
|
SQLAlchemy dialect for textual SQL and reflection, not a writable ORM backend.
|
|
93
88
|
Each statement has its own server snapshot; SQLAlchemy transaction blocks do not
|
|
94
89
|
provide a shared snapshot or rollback. The adapter makes no transaction requests.
|
|
95
90
|
|
|
96
91
|
A complete notebook is in `examples/notebook.py`. The integration is tested with
|
|
97
|
-
marimo 0.24.1 and SQLAlchemy 2.x.
|
|
98
|
-
|
|
92
|
+
marimo 0.24.1 and SQLAlchemy 2.x. SQLAlchemy is included in the standard SDK install; the `notebook` extra adds
|
|
93
|
+
marimo. Existing marimo environments only need `uv add "periplus-python-sdk>=0.6.0"`.
|
|
94
|
+
The returned object is a standard SQLAlchemy Engine, also usable with pandas and
|
|
95
|
+
ordinary Python scripts. Engine creation is lazy; the first query opens a connection.
|
|
99
96
|
|
|
100
97
|
## DB-API connection
|
|
101
98
|
|
|
@@ -199,10 +196,10 @@ Use `aclose()` when managing an async client's lifetime explicitly.
|
|
|
199
196
|
Install the public-v1 client from PyPI:
|
|
200
197
|
|
|
201
198
|
```sh
|
|
202
|
-
python -m pip install "periplus-python-sdk>=0.
|
|
199
|
+
python -m pip install "periplus-python-sdk>=0.6.0"
|
|
203
200
|
```
|
|
204
201
|
|
|
205
|
-
Version 0.
|
|
202
|
+
Version 0.6.0 supports the current public-v1 contract. For production, configure
|
|
206
203
|
`PERIPLUS_PUBLIC_URL=https://periplus.dev`; no API token is required.
|
|
207
204
|
Run the installed package against an available public app:
|
|
208
205
|
|
|
@@ -214,11 +211,11 @@ PERIPLUS_PUBLIC_URL=http://localhost:8080 python packages/periplus-python-sdk/ex
|
|
|
214
211
|
|
|
215
212
|
Repository CI publishes immutable releases from tags named
|
|
216
213
|
`periplus-python-sdk-v<version>`. The tag must exactly match the static version
|
|
217
|
-
in `pyproject.toml`; for example, version `0.
|
|
214
|
+
in `pyproject.toml`; for example, version `0.6.0` is released with:
|
|
218
215
|
|
|
219
216
|
```sh
|
|
220
|
-
git tag periplus-python-sdk-v0.
|
|
221
|
-
git push origin periplus-python-sdk-v0.
|
|
217
|
+
git tag periplus-python-sdk-v0.6.0
|
|
218
|
+
git push origin periplus-python-sdk-v0.6.0
|
|
222
219
|
```
|
|
223
220
|
|
|
224
221
|
PyPI publishing uses Trusted Publishing rather than a stored API token. The
|
|
@@ -228,7 +225,7 @@ that GitHub environment with required reviewers before the first release.
|
|
|
228
225
|
|
|
229
226
|
## Public v1
|
|
230
227
|
|
|
231
|
-
Install the updated SDK from PyPI with `python -m pip install "periplus-python-sdk>=0.
|
|
228
|
+
Install the updated SDK from PyPI with `python -m pip install "periplus-python-sdk>=0.6.0"`. The previously published 0.2.0 release predates this contract. `prepare` and `execute` accept keyword-only `schema_version="public_v1"` (the default); responses preserve `schema_version` separately from `source_snapshot`. Unavailable versions are rejected by the server.
|
|
232
229
|
|
|
233
230
|
## License
|
|
234
231
|
|
{periplus_python_sdk-0.5.0 → periplus_python_sdk-0.6.0}/src/periplus_python_sdk.egg-info/SOURCES.txt
RENAMED
|
@@ -13,8 +13,10 @@ src/periplus_sdk/client.py
|
|
|
13
13
|
src/periplus_sdk/dbapi.py
|
|
14
14
|
src/periplus_sdk/errors.py
|
|
15
15
|
src/periplus_sdk/py.typed
|
|
16
|
+
src/periplus_sdk/sql_api.py
|
|
16
17
|
src/periplus_sdk/sqlalchemy.py
|
|
17
18
|
src/periplus_sdk/types.py
|
|
18
19
|
tests/test_client.py
|
|
19
20
|
tests/test_dbapi.py
|
|
20
|
-
tests/test_notebook.py
|
|
21
|
+
tests/test_notebook.py
|
|
22
|
+
tests/test_sql_api.py
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Notebook-friendly SQL engine over the public Periplus query API."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Literal
|
|
5
|
+
|
|
6
|
+
from sqlalchemy import create_engine as _create_engine
|
|
7
|
+
from sqlalchemy.engine import Engine, URL
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def create_engine(
|
|
11
|
+
base_url: str | None = None,
|
|
12
|
+
*,
|
|
13
|
+
mode: Literal["stable", "experimental"] = "stable",
|
|
14
|
+
timeout: float = 140,
|
|
15
|
+
schema_version: str = "public_v1",
|
|
16
|
+
) -> Engine:
|
|
17
|
+
"""Create a SQLAlchemy engine recognized by marimo and other SQL tools.
|
|
18
|
+
|
|
19
|
+
The public URL defaults to PERIPLUS_PUBLIC_URL. Connections are opened lazily;
|
|
20
|
+
dispose the engine when finished. Each query uses an independent server snapshot.
|
|
21
|
+
"""
|
|
22
|
+
return _create_engine(
|
|
23
|
+
URL.create("periplus", database=schema_version),
|
|
24
|
+
connect_args={"base_url": base_url, "mode": mode, "timeout": timeout},
|
|
25
|
+
)
|
|
@@ -9,7 +9,7 @@ from test_client import RESULT
|
|
|
9
9
|
@unittest.skipUnless(importlib.util.find_spec('sqlalchemy') and importlib.util.find_spec('marimo'), 'notebook extra required')
|
|
10
10
|
class NotebookTests(unittest.TestCase):
|
|
11
11
|
def engine(self, *, truncated=False):
|
|
12
|
-
from
|
|
12
|
+
from periplus_sdk import sql_api
|
|
13
13
|
factory = httpx.Client
|
|
14
14
|
self.requests = []
|
|
15
15
|
def handler(request):
|
|
@@ -27,7 +27,7 @@ class NotebookTests(unittest.TestCase):
|
|
|
27
27
|
patcher = patch('periplus_sdk.client.httpx.Client', side_effect=lambda **kw: factory(**kw,transport=httpx.MockTransport(handler)))
|
|
28
28
|
patcher.start()
|
|
29
29
|
self.addCleanup(patcher.stop)
|
|
30
|
-
engine = create_engine('
|
|
30
|
+
engine = sql_api.create_engine('https://public.example')
|
|
31
31
|
self.addCleanup(engine.dispose)
|
|
32
32
|
return engine
|
|
33
33
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
import unittest
|
|
4
|
+
from unittest.mock import patch
|
|
5
|
+
|
|
6
|
+
import httpx
|
|
7
|
+
from sqlalchemy import inspect, text
|
|
8
|
+
from sqlalchemy.engine import Engine
|
|
9
|
+
from periplus_sdk import sql_api
|
|
10
|
+
from test_client import RESULT
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class SQLApiTests(unittest.TestCase):
|
|
14
|
+
def test_engine_options_environment_and_queries(self):
|
|
15
|
+
factory = httpx.Client
|
|
16
|
+
for mode in ('stable', 'experimental'):
|
|
17
|
+
requests = []
|
|
18
|
+
def handler(request):
|
|
19
|
+
requests.append(request)
|
|
20
|
+
return httpx.Response(200, json=dict(RESULT, columns=['n'], types=['INTEGER'], rows=[[42]], truncated=False))
|
|
21
|
+
with self.subTest(mode=mode), patch.dict(os.environ, {'PERIPLUS_PUBLIC_URL':'https://public.example/prefix'}), patch(
|
|
22
|
+
'periplus_sdk.client.httpx.Client',
|
|
23
|
+
side_effect=lambda **kw: factory(**kw, transport=httpx.MockTransport(handler)),
|
|
24
|
+
):
|
|
25
|
+
engine = sql_api.create_engine(mode=mode, timeout=37)
|
|
26
|
+
self.assertIsInstance(engine, Engine)
|
|
27
|
+
self.assertEqual(requests, [])
|
|
28
|
+
try:
|
|
29
|
+
self.assertEqual(inspect(engine).default_schema_name, 'public_v1')
|
|
30
|
+
with engine.connect() as conn:
|
|
31
|
+
self.assertEqual(conn.connection.dbapi_connection._client._http.timeout.read,37)
|
|
32
|
+
self.assertEqual(conn.execute(text('SELECT :n AS n'), {'n':42}).fetchall(), [(42,)])
|
|
33
|
+
suffix = 'experimental/' if mode == 'experimental' else ''
|
|
34
|
+
self.assertEqual(requests[0].url.path, '/prefix/api/query/'+suffix+'exec')
|
|
35
|
+
self.assertEqual(json.loads(requests[0].content)['parameters'], [42])
|
|
36
|
+
self.assertEqual(json.loads(requests[0].content)['schema_version'], 'public_v1')
|
|
37
|
+
finally:
|
|
38
|
+
engine.dispose()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|