Skip to content

Commit 5e10986

Browse files
authored
Merge pull request #8 from wherobots/max/params
feat: pass through advanced parameters
2 parents fc9a3be + 74aa363 commit 5e10986

4 files changed

Lines changed: 85 additions & 12 deletions

File tree

README.md

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ $ pip install git+https://github.com/wherobots/wherobots-python-dbapi-driver
2121

2222
## Usage
2323

24+
### Basic usage
25+
26+
Basic usage follows the typical pattern of establishing the connection,
27+
acquiring a cursor, and executing SQL queries through it:
28+
2429
```python
2530
from wherobots.db import connect
2631
from wherobots.db.region import Region
@@ -36,8 +41,8 @@ with connect(
3641
print(results)
3742
```
3843

39-
The `Cursor` also supports the context manager protocol, so you can use
40-
it within a `with` statement when needed:
44+
The `Cursor` supports the context manager protocol, so you can use it
45+
within a `with` statement when needed:
4146

4247
```python
4348
with connect(...) as conn:
@@ -49,3 +54,30 @@ with connect(...) as conn:
4954
It also implements the `close()` method, as suggested by the PEP-2049
5055
specification, to support situations where the cursor is wrapped in a
5156
`contextmanager.closing()`.
57+
58+
### Runtime and region selection
59+
60+
You can chose the Wherobots runtime you want to use using the `runtime`
61+
parameter, passing in one of the `Runtime` enum values. For more
62+
information on runtime sizing and selection, please consult the
63+
[Wherobots product documentation](https://docs.wherobots.com).
64+
65+
The only supported Wherobots compute region for now is `aws-us-west-2`,
66+
in AWS's Oregon (`us-west-2`) region.
67+
68+
### Advanced parameters
69+
70+
The `connect()` method takes some additional parameters that advanced
71+
users may find useful:
72+
73+
* `results_format`: one of the `ResultsFormat` enum values;
74+
Arrow encoding is the default and most efficient format for
75+
receiving query results.
76+
* `data_compression`: one of the `DataCompression` enum values; Brotli
77+
compression is the default and the most efficient compression
78+
algorithm for receiving query results.
79+
* `geometry_representation`: one of the `GeometryRepresentation` enum
80+
values; selects the encoding of geometry columns returned to the
81+
client application. The default is EWKT (string) and the most
82+
convenient for human inspection while still being usable by
83+
libraries like Shapely.

wherobots/db/connection.py

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import json
22
import logging
3+
import textwrap
34
import threading
45
import uuid
56
from dataclasses import dataclass
@@ -18,13 +19,11 @@
1819
ExecutionState,
1920
ResultsFormat,
2021
DataCompression,
22+
GeometryRepresentation,
2123
)
2224
from wherobots.db.cursor import Cursor
2325
from wherobots.db.errors import NotSupportedError, OperationalError
2426

25-
_DEFAULT_RESULTS_FORMAT = ResultsFormat.ARROW
26-
_DEFAULT_DATA_COMPRESSION = DataCompression.BROTLI
27-
2827

2928
@dataclass
3029
class Query:
@@ -53,9 +52,16 @@ def __init__(
5352
self,
5453
ws: websockets.sync.client.ClientConnection,
5554
read_timeout: float = DEFAULT_READ_TIMEOUT_SECONDS,
55+
results_format: ResultsFormat | None = None,
56+
data_compression: DataCompression | None = None,
57+
geometry_representation: GeometryRepresentation | None = None,
5658
):
5759
self.__ws = ws
5860
self.__read_timeout = read_timeout
61+
self.__results_format = results_format
62+
self.__data_compression = data_compression
63+
self.__geometry_representation = geometry_representation
64+
5965
self.__queries: dict[str, Query] = {}
6066
self.__thread = threading.Thread(
6167
target=self.__main_loop, daemon=True, name="wherobots-connection"
@@ -155,9 +161,7 @@ def __listen(self):
155161
query.handler(reader.read_pandas())
156162
else:
157163
query.handler(
158-
OperationalError(
159-
f"Unsupported results format {result_format}"
160-
)
164+
OperationalError(f"Unsupported results format {result_format}")
161165
)
162166
elif kind == EventKind.ERROR:
163167
query.state = ExecutionState.FAILED
@@ -167,7 +171,9 @@ def __listen(self):
167171
logging.warning("Received unknown %s event!", kind)
168172

169173
def __send(self, message: dict[str, Any]) -> None:
170-
self.__ws.send(json.dumps(message))
174+
request = json.dumps(message)
175+
logging.debug("Request: %s", request)
176+
self.__ws.send(request)
171177

172178
def __recv(self) -> dict[str, Any]:
173179
frame = self.__ws.recv(timeout=self.__read_timeout)
@@ -194,6 +200,10 @@ def __execute_sql(self, sql: str, handler: Callable[[Any], None]) -> str:
194200
state=ExecutionState.EXECUTION_REQUESTED,
195201
handler=handler,
196202
)
203+
204+
logging.info(
205+
"Executing SQL query %s: %s", execution_id, textwrap.shorten(sql, width=60)
206+
)
197207
self.__send(request)
198208
return execution_id
199209

@@ -205,9 +215,14 @@ def __request_results(self, execution_id: str) -> None:
205215
request = {
206216
"kind": RequestKind.RETRIEVE_RESULTS.value,
207217
"execution_id": execution_id,
208-
"format": _DEFAULT_RESULTS_FORMAT.value,
209-
"compression": _DEFAULT_DATA_COMPRESSION.value,
210218
}
219+
if self.__results_format:
220+
request["format"] = self.__results_format.value
221+
if self.__data_compression:
222+
request["compression"] = self.__data_compression.value
223+
if self.__geometry_representation:
224+
request["geometry"] = self.__geometry_representation.value
225+
211226
query.state = ExecutionState.RESULTS_REQUESTED
212227
logging.info("Requesting results from %s ...", execution_id)
213228
self.__send(request)

wherobots/db/constants.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,11 @@ class ResultsFormat(LowercaseStrEnum):
5858

5959
class DataCompression(LowercaseStrEnum):
6060
BROTLI = auto()
61+
62+
63+
class GeometryRepresentation(LowercaseStrEnum):
64+
WKT = auto()
65+
WKB = auto()
66+
EWKT = auto()
67+
EWKB = auto()
68+
GEOJSON = auto()

wherobots/db/driver.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
DEFAULT_READ_TIMEOUT_SECONDS,
1919
DEFAULT_SESSION_WAIT_TIMEOUT_SECONDS,
2020
MAX_MESSAGE_SIZE,
21+
ResultsFormat,
22+
DataCompression,
23+
GeometryRepresentation,
2124
)
2225
from .errors import (
2326
InterfaceError,
@@ -40,6 +43,9 @@ def connect(
4043
region: Region = None,
4144
wait_timeout: float = DEFAULT_SESSION_WAIT_TIMEOUT_SECONDS,
4245
read_timeout: float = DEFAULT_READ_TIMEOUT_SECONDS,
46+
results_format: ResultsFormat | None = None,
47+
data_compression: DataCompression | None = None,
48+
geometry_representation: GeometryRepresentation | None = None,
4349
) -> Connection:
4450
if not token and not api_key:
4551
raise ValueError("At least one of `token` or `api_key` is required")
@@ -113,6 +119,9 @@ def get_session_uri() -> str:
113119
uri=http_to_ws(session_uri),
114120
headers=headers,
115121
read_timeout=read_timeout,
122+
results_format=results_format,
123+
data_compression=data_compression,
124+
geometry_representation=geometry_representation,
116125
)
117126

118127

@@ -129,6 +138,9 @@ def connect_direct(
129138
uri: str,
130139
headers: dict[str, str] = None,
131140
read_timeout: float = DEFAULT_READ_TIMEOUT_SECONDS,
141+
results_format: ResultsFormat | None = None,
142+
data_compression: DataCompression | None = None,
143+
geometry_representation: GeometryRepresentation | None = None,
132144
) -> Connection:
133145
q = queue.SimpleQueue()
134146

@@ -156,4 +168,10 @@ def create_ws_connection():
156168
if isinstance(result, Exception):
157169
raise InterfaceError("Failed to connect to SQL session!") from result
158170

159-
return Connection(result, read_timeout)
171+
return Connection(
172+
result,
173+
read_timeout=read_timeout,
174+
results_format=results_format,
175+
data_compression=data_compression,
176+
geometry_representation=geometry_representation,
177+
)

0 commit comments

Comments
 (0)