snowleopard 0.3.0__tar.gz → 0.3.2__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.
- snowleopard-0.3.2/.claude/settings.local.json +17 -0
- {snowleopard-0.3.0 → snowleopard-0.3.2}/PKG-INFO +1 -1
- {snowleopard-0.3.0 → snowleopard-0.3.2}/src/snowleopard/__init__.py +5 -1
- {snowleopard-0.3.0 → snowleopard-0.3.2}/src/snowleopard/async_client.py +3 -8
- {snowleopard-0.3.0 → snowleopard-0.3.2}/src/snowleopard/cli.py +2 -5
- {snowleopard-0.3.0 → snowleopard-0.3.2}/src/snowleopard/client.py +2 -6
- {snowleopard-0.3.0 → snowleopard-0.3.2}/src/snowleopard/client_base.py +12 -9
- snowleopard-0.3.2/src/snowleopard/error.py +32 -0
- {snowleopard-0.3.0 → snowleopard-0.3.2}/src/snowleopard/models.py +1 -0
- snowleopard-0.3.0/src/snowleopard/error.py +0 -10
- {snowleopard-0.3.0 → snowleopard-0.3.2}/.gitignore +0 -0
- {snowleopard-0.3.0 → snowleopard-0.3.2}/CONTRIBUTING.md +0 -0
- {snowleopard-0.3.0 → snowleopard-0.3.2}/LICENSE +0 -0
- {snowleopard-0.3.0 → snowleopard-0.3.2}/README.md +0 -0
- {snowleopard-0.3.0 → snowleopard-0.3.2}/pyproject.toml +0 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(mkdir:*)",
|
|
5
|
+
"Bash(uv add:*)",
|
|
6
|
+
"Bash(uv run pytest:*)",
|
|
7
|
+
"WebFetch(domain:www.python-httpx.org)",
|
|
8
|
+
"Bash(python -c:*)",
|
|
9
|
+
"Bash(uv run python:*)",
|
|
10
|
+
"WebFetch(domain:github.com)",
|
|
11
|
+
"Bash(uv run snowy response --help:*)",
|
|
12
|
+
"Bash(uv run:*)"
|
|
13
|
+
],
|
|
14
|
+
"deny": [],
|
|
15
|
+
"ask": []
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -4,10 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
from snowleopard.async_client import AsyncSnowLeopardClient
|
|
6
6
|
from snowleopard.client import SnowLeopardClient
|
|
7
|
+
from snowleopard.error import APIBadRequest, SnowLeopardHTTPError, SLException
|
|
7
8
|
|
|
8
|
-
__version__ = "0.3.
|
|
9
|
+
__version__ = "0.3.2"
|
|
9
10
|
|
|
10
11
|
__all__ = [
|
|
11
12
|
"SnowLeopardClient",
|
|
12
13
|
"AsyncSnowLeopardClient",
|
|
14
|
+
"SLException",
|
|
15
|
+
"APIBadRequest",
|
|
16
|
+
"SnowLeopardHTTPError",
|
|
13
17
|
]
|
|
@@ -7,8 +7,7 @@ from typing import AsyncGenerator, Optional, Dict, Any
|
|
|
7
7
|
|
|
8
8
|
import httpx
|
|
9
9
|
from snowleopard.client_base import SLClientBase
|
|
10
|
-
from snowleopard.
|
|
11
|
-
from snowleopard.models import APIError, parse, ResponseDataObjects, RetrieveResponseObjects
|
|
10
|
+
from snowleopard.models import parse, ResponseDataObjects, RetrieveResponseObjects
|
|
12
11
|
|
|
13
12
|
|
|
14
13
|
class AsyncSnowLeopardClient(SLClientBase):
|
|
@@ -50,13 +49,9 @@ class AsyncSnowLeopardClient(SLClientBase):
|
|
|
50
49
|
self._build_path(datafile_id, "response"),
|
|
51
50
|
json=self._build_request_body(user_query, known_data),
|
|
52
51
|
) as resp:
|
|
53
|
-
|
|
54
|
-
resp.raise_for_status()
|
|
52
|
+
self._raise_for_status(resp)
|
|
55
53
|
async for line in resp.aiter_lines():
|
|
56
|
-
|
|
57
|
-
if isinstance(resultObj, APIError) and resp.status_code == 400:
|
|
58
|
-
raise APIBadRequest(resultObj.description)
|
|
59
|
-
yield resultObj
|
|
54
|
+
yield parse(json.loads(line))
|
|
60
55
|
|
|
61
56
|
async def __aenter__(self):
|
|
62
57
|
await self.client.__aenter__()
|
|
@@ -10,7 +10,7 @@ from typing import List, Optional, Dict, Any
|
|
|
10
10
|
|
|
11
11
|
from httpx import HTTPStatusError
|
|
12
12
|
from snowleopard import __version__, SnowLeopardClient
|
|
13
|
-
from snowleopard.error import APIBadRequest
|
|
13
|
+
from snowleopard.error import APIBadRequest, SLException
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
def _create_parser() -> argparse.ArgumentParser:
|
|
@@ -113,12 +113,9 @@ def _response(parsed_args):
|
|
|
113
113
|
datafile_id=parsed_args.datafile,
|
|
114
114
|
):
|
|
115
115
|
print(json.dumps(dataclasses.asdict(chunk)))
|
|
116
|
-
except
|
|
116
|
+
except SLException as e:
|
|
117
117
|
print(f"error: {str(e)}", file=sys.stderr)
|
|
118
118
|
hadErrors = True
|
|
119
|
-
except HTTPStatusError as e:
|
|
120
|
-
print(str(e), file=sys.stderr)
|
|
121
|
-
hadErrors = True
|
|
122
119
|
if hadErrors:
|
|
123
120
|
sys.exit(1)
|
|
124
121
|
|
|
@@ -7,8 +7,7 @@ from typing import Optional, Generator, Dict, Any
|
|
|
7
7
|
|
|
8
8
|
import httpx
|
|
9
9
|
from snowleopard.client_base import SLClientBase
|
|
10
|
-
from snowleopard.
|
|
11
|
-
from snowleopard.models import APIError, parse, RetrieveResponseObjects, ResponseDataObjects
|
|
10
|
+
from snowleopard.models import parse, RetrieveResponseObjects, ResponseDataObjects
|
|
12
11
|
|
|
13
12
|
|
|
14
13
|
class SnowLeopardClient(SLClientBase):
|
|
@@ -50,12 +49,9 @@ class SnowLeopardClient(SLClientBase):
|
|
|
50
49
|
url=self._build_path(datafile_id, "response"),
|
|
51
50
|
json=self._build_request_body(user_query, known_data),
|
|
52
51
|
) as resp:
|
|
53
|
-
|
|
54
|
-
resp.raise_for_status()
|
|
52
|
+
self._raise_for_status(resp)
|
|
55
53
|
for line in resp.iter_lines():
|
|
56
54
|
resultObj = parse(json.loads(line))
|
|
57
|
-
if isinstance(resultObj, APIError) and resp.status_code == 400:
|
|
58
|
-
raise APIBadRequest(resultObj.description)
|
|
59
55
|
yield resultObj
|
|
60
56
|
|
|
61
57
|
def __enter__(self):
|
|
@@ -9,8 +9,8 @@ from typing import Optional, Dict, Any
|
|
|
9
9
|
|
|
10
10
|
import httpx
|
|
11
11
|
|
|
12
|
-
from snowleopard.error import APIBadRequest
|
|
13
|
-
from snowleopard.models import
|
|
12
|
+
from snowleopard.error import APIBadRequest, SnowLeopardHTTPError
|
|
13
|
+
from snowleopard.models import parse
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
@dataclass
|
|
@@ -103,14 +103,17 @@ class SLClientBase:
|
|
|
103
103
|
return body
|
|
104
104
|
|
|
105
105
|
@staticmethod
|
|
106
|
-
def
|
|
107
|
-
|
|
106
|
+
def _raise_for_status(resp):
|
|
107
|
+
try:
|
|
108
108
|
resp.raise_for_status()
|
|
109
|
+
except httpx.HTTPStatusError as e:
|
|
110
|
+
raise SnowLeopardHTTPError(e.response.status_code, e.response) from e
|
|
111
|
+
|
|
112
|
+
def _parse_retrieve(self, resp):
|
|
113
|
+
if resp.status_code != 409:
|
|
114
|
+
self._raise_for_status(resp)
|
|
109
115
|
try:
|
|
110
|
-
|
|
116
|
+
return parse(resp.json())
|
|
111
117
|
except Exception:
|
|
112
|
-
|
|
118
|
+
self._raise_for_status(resp)
|
|
113
119
|
raise
|
|
114
|
-
if isinstance(resultObj, APIError) and resp.status_code == 400:
|
|
115
|
-
raise APIBadRequest(resultObj.description)
|
|
116
|
-
return resultObj
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# copyright 2026 Snow Leopard, Inc
|
|
3
|
+
# released under the MIT license - see LICENSE file
|
|
4
|
+
|
|
5
|
+
import httpx
|
|
6
|
+
|
|
7
|
+
class SLException(Exception):
|
|
8
|
+
pass
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class APIBadRequest(SLException):
|
|
12
|
+
"""Raised when the request is invalid due to bad input.
|
|
13
|
+
|
|
14
|
+
This is raised for client-side validation errors, such as an empty or
|
|
15
|
+
whitespace-only query string.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class SnowLeopardHTTPError(SLException):
|
|
20
|
+
"""Raised when the SnowLeopard API returns an unexpected HTTP error status."""
|
|
21
|
+
|
|
22
|
+
status_code: int
|
|
23
|
+
response: httpx.Response
|
|
24
|
+
|
|
25
|
+
def __init__(self, status_code: int, response: httpx.Response):
|
|
26
|
+
self.status_code = status_code
|
|
27
|
+
self.response = response
|
|
28
|
+
try:
|
|
29
|
+
body = response.text[:500]
|
|
30
|
+
except Exception:
|
|
31
|
+
body = "<response body unavailable>"
|
|
32
|
+
super().__init__(f"SnowLeopard API error (HTTP {status_code}): {body}")
|
|
@@ -99,6 +99,7 @@ class ResponseStatus(StrEnum):
|
|
|
99
99
|
SUCCESS = "SUCCESS"
|
|
100
100
|
BAD_REQUEST = "BAD_REQUEST"
|
|
101
101
|
NOT_FOUND_IN_SCHEMA = "NOT_FOUND_IN_SCHEMA"
|
|
102
|
+
UNABLE_TO_UNDERSTAND_QUESTION = "UNABLE_TO_UNDERSTAND_QUESTION"
|
|
102
103
|
UNKNOWN = "UNKNOWN"
|
|
103
104
|
INTERNAL_SERVER_ERROR = "INTERNAL_SERVER_ERROR"
|
|
104
105
|
AUTHORIZATION_FAILED = "AUTHORIZATION_FAILED"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|