-
Notifications
You must be signed in to change notification settings - Fork 31
Add Remote clients over REST #272
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: staging
Are you sure you want to change the base?
Changes from 2 commits
899fe86
c01e0e3
1714547
2182e4b
b8132a9
600cb6d
7e134d6
afedc32
c80b217
c47b3eb
1d2b16c
a295c35
f2d40ac
2163a36
7a70852
72a580e
8055f8e
be88d86
a85854e
81952f2
e5c4ef9
7de4c3f
2570d2e
e69af21
24fb15e
f72e570
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| [[source]] | ||
| name = "pypi" | ||
| url = "https://pypi.org/simple" | ||
| verify_ssl = true | ||
|
|
||
| [packages] | ||
| aiohttp = "*" | ||
| queryweaver-client = {file = ".", editable = true} | ||
|
|
||
| [dev-packages] | ||
| pytest = "*" | ||
| pytest-asyncio = "*" | ||
|
|
||
| [requires] | ||
| python_version = "3.12" |
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| # QueryWeaver Python client | ||
|
|
||
| Lightweight Python client for interacting with a QueryWeaver server. | ||
|
|
||
| This folder contains a small package, `queryweaver_client`, that wraps the | ||
| QueryWeaver HTTP API. The package uses aiohttp for async HTTP requests and is | ||
| configured to be used with pipenv (Pipfile) or a plain virtualenv. | ||
|
|
||
| ## Getting started | ||
|
|
||
| ### Install from PyPI (end users) | ||
|
|
||
| If you just want to use the client (not develop it), install the published package from PyPI: | ||
|
|
||
| ```bash | ||
| pip install queryweaver_client | ||
| ``` | ||
|
|
||
| This installs the latest released version. For development and tests use the pipenv/venv instructions below. | ||
|
|
||
| ### Usage example | ||
|
|
||
| Basic async usage (API token auth): | ||
|
|
||
| ```python | ||
| import asyncio | ||
| from queryweaver_client import QueryWeaverClient | ||
|
|
||
| async def main(): | ||
| async with QueryWeaverClient("http://localhost:5000", api_token="YOUR_API_TOKEN") as client: | ||
| # List available databases/schemas | ||
| schemas = await client.list_schemas() | ||
| print(schemas) | ||
|
|
||
| # Connect to a database and get the final result | ||
| result = await client.connect_database("postgresql://user:pass@host/db") | ||
| print(result) | ||
|
|
||
| # Run a natural language query and get the final result | ||
| chat_data = { | ||
| "messages": [ | ||
| {"role": "user", "content": "List the top 5 customers by total_spend"} | ||
| ] | ||
| } | ||
| result = await client.query("my_database_schema", chat_data) | ||
| print(result) | ||
|
|
||
| # Run the async function | ||
| asyncio.run(main()) | ||
| ``` | ||
|
|
||
|
|
||
| ## Build from code (developers) | ||
|
|
||
|
|
||
| ### Quick install (pipenv - recommended) | ||
|
|
||
| 1. Change to the client directory: | ||
|
|
||
| ```bash | ||
| cd ./clients/python | ||
| ``` | ||
|
|
||
| 2. Install dependencies and the package into a pipenv virtualenv (editable install supported): | ||
|
|
||
| ```bash | ||
| pipenv install --dev | ||
| # Install the local package into the pipenv virtualenv in editable mode | ||
| pipenv install -e . | ||
| ``` | ||
|
|
||
| ### Running tests | ||
|
|
||
| Unit tests live in `tests/` and are lightweight (they mock network calls and do NOT | ||
| require a running QueryWeaver server). Use pytest to run them. | ||
|
|
||
| With pipenv: | ||
|
|
||
| ```bash | ||
| pipenv run pytest -q | ||
| ``` | ||
|
|
||
| With venv/pip: | ||
|
|
||
| ```bash | ||
| pytest -q | ||
| ``` | ||
|
|
||
| Run a single test file or test: | ||
|
|
||
| ```bash | ||
| pytest -q tests/test_client_basic.py | ||
| pytest -q tests/test_client_basic.py::test_connect_database_sync | ||
| ``` | ||
|
|
||
| ## Notes & troubleshooting | ||
| ----------------------- | ||
| - The `Pipfile` specifies Python 3.12; use a compatible interpreter if you need exact parity. | ||
| - If `pipenv install` fails because `pipenv` isn't available, install it (`pip install pipenv`) or use the plain venv flow above. | ||
| - The client supports two auth modes: | ||
| - API token: pass `api_token` to `QueryWeaverClient` (sent as Bearer Authorization header) | ||
| - Session cookie: construct an `aiohttp.ClientSession()` with cookies (for web OAuth session flows) and pass it to `QueryWeaverClient(session=your_session)` | ||
| - All API calls are async and must be awaited | ||
| - Use the client as an async context manager (`async with`) for proper session lifecycle management | ||
|
|
||
| ## Want more? | ||
| ----------- | ||
| If you'd like typed request/response models (pydantic), better streaming helpers, or integration tests that run against a local QueryWeaver instance (requires FalkorDB and env setup), I can add those next. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| """QueryWeaver Python client package. | ||
|
|
||
| Provides a small, dependency-light wrapper for the QueryWeaver HTTP API. | ||
| """ | ||
|
|
||
| from .client import QueryWeaverClient | ||
|
|
||
| __all__ = ["QueryWeaverClient"] |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,159 @@ | ||||||
| """QueryWeaver HTTP API client. | ||||||
|
|
||||||
| Simple wrapper around the REST API exposed by a running QueryWeaver server. | ||||||
| Supports API token authentication (Bearer) and session cookie usage. | ||||||
| """ | ||||||
| from __future__ import annotations | ||||||
|
|
||||||
| import json | ||||||
| from typing import Any, Dict, Optional | ||||||
|
|
||||||
| import aiohttp | ||||||
|
|
||||||
|
|
||||||
| class APIError(Exception): | ||||||
| """Raised for non-2xx responses from the server.""" | ||||||
|
|
||||||
|
|
||||||
| class QueryWeaverClient: | ||||||
| """Minimal QueryWeaver client. | ||||||
|
|
||||||
| Usage: | ||||||
| async with QueryWeaverClient("http://localhost:5000", api_token="...") as client: | ||||||
| await client.list_schemas() | ||||||
| result = await client.connect_database("postgresql://user:pass@host/db") | ||||||
|
|
||||||
| Authentication: | ||||||
| - api_token: sent as Bearer token in Authorization header | ||||||
| - session cookie: pass a `aiohttp.ClientSession()` with cookies set | ||||||
| """ | ||||||
|
|
||||||
| def __init__( | ||||||
| self, | ||||||
| base_url: str, | ||||||
| api_token: Optional[str] = None, | ||||||
| session: Optional[aiohttp.ClientSession] = None, | ||||||
| timeout: int = 30, | ||||||
| ) -> None: | ||||||
| self.base_url = base_url.rstrip("/") | ||||||
| self.api_token = api_token | ||||||
| self._session = session | ||||||
| self.timeout = aiohttp.ClientTimeout(total=timeout) | ||||||
|
|
||||||
| # default headers | ||||||
| self._default_headers = {"Accept": "application/json"} | ||||||
| if api_token: | ||||||
| self._default_headers["Authorization"] = f"Bearer {api_token}" | ||||||
|
|
||||||
| async def __aenter__(self): | ||||||
| if self._session is None: | ||||||
| self._session = aiohttp.ClientSession(headers=self._default_headers) | ||||||
gkorland marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| return self | ||||||
|
|
||||||
| async def __aexit__(self, exc_type, exc_val, exc_tb): | ||||||
| if self._session and not self._session.closed: | ||||||
|
||||||
| if self._session and not self._session.closed: | |
| if self._owns_session and self._session and not self._session.closed: |
gkorland marked this conversation as resolved.
Show resolved
Hide resolved
gkorland marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
gkorland marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
gkorland marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
gkorland marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| from setuptools import setup, find_packages | ||
|
|
||
| setup( | ||
| name="queryweaver-client", | ||
| version="0.1.0", | ||
| description="Lightweight Python client for QueryWeaver server", | ||
| packages=find_packages(exclude=("tests",)), | ||
| include_package_data=True, | ||
| install_requires=[ | ||
| "requests", | ||
| ], | ||
| extras_require={ | ||
| "dev": ["pytest"], | ||
gkorland marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| }, | ||
| ) | ||
Uh oh!
There was an error while loading. Please reload this page.