Skip to content

Commit 98d9886

Browse files
authored
Merge pull request #3 from Zipstack/feat/update-response-dict
feat: Updated response dict to use snake case
2 parents ac1ae41 + 4feac34 commit 98d9886

22 files changed

+672
-32
lines changed

.github/workflows/ci_test.yaml

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
name: Run tox tests
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
types: [opened, synchronize, reopened, ready_for_review]
9+
branches: [main]
10+
11+
jobs:
12+
test:
13+
if: github.event.pull_request.draft == false
14+
runs-on: ubuntu-latest
15+
16+
steps:
17+
- name: Checkout repository
18+
uses: actions/checkout@v3
19+
20+
- name: Set up Python
21+
uses: actions/setup-python@v4
22+
with:
23+
python-version: '3.9'
24+
25+
- name: Cache tox environments
26+
uses: actions/cache@v3
27+
with:
28+
path: .tox/
29+
key: ${{ runner.os }}-tox-${{ hashFiles('**/pyproject.toml', '**/tox.ini') }}
30+
restore-keys: |
31+
${{ runner.os }}-tox-
32+
- name: Install tox
33+
run: pip install tox
34+
35+
- name: Create test env
36+
shell: bash
37+
run: |
38+
cp tests/sample.env tests/.env
39+
sed -i "s|LLMWHISPERER_API_KEY=|LLMWHISPERER_API_KEY=${{ secrets.LLMWHISPERER_API_KEY }}|" tests/.env
40+
41+
- name: Run tox
42+
id: tox
43+
run: |
44+
tox
45+
- name: Render the report to the PR
46+
uses: marocchino/sticky-pull-request-comment@v2
47+
with:
48+
header: llmw-py-client-test-report
49+
recreate: true
50+
path: llmw-py-client-report.md
51+
52+
- name: Output reports to the job summary when tests fail
53+
shell: bash
54+
run: |
55+
if [ -f "llmw-py-client-report.md" ]; then
56+
{
57+
echo "<details><summary>Worker Test Report</summary>"
58+
echo ""
59+
cat "llmw-py-client-report.md"
60+
echo ""
61+
echo "</details>"
62+
} >> "$GITHUB_STEP_SUMMARY"
63+
fi

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ coverage.xml
5050
.hypothesis/
5151
.pytest_cache/
5252
cover/
53+
*-report.md
5354

5455
# Translations
5556
*.mo

.pre-commit-config.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ repos:
1212
rev: v4.5.0
1313
hooks:
1414
- id: trailing-whitespace
15+
# TODO: Exclude tests/test_data directory
16+
exclude: ^tests/test_data/
1517
exclude_types:
1618
- "markdown"
1719
- id: end-of-file-fixer

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pip install llmwhisperer-client
2323
First, import the `LLMWhispererClient` from the `client` module:
2424

2525
```python
26-
from llmwhisperer.client import LLMWhispererClient
26+
from unstract.llmwhisperer.client import LLMWhispererClient
2727
```
2828

2929
Then, create an instance of the `LLMWhispererClient`:
@@ -105,7 +105,7 @@ try:
105105
pages_to_extract="1,2",
106106
timeout=2,
107107
)
108-
if result["statusCode"] == 202:
108+
if result["status_code"] == 202:
109109
print("Timeout occured. Whisper request accepted.")
110110
print(f"Whisper hash: {result['whisper-hash']}")
111111
while True:

pdm.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ lint = [
5050

5151
[tool.pdm.version]
5252
source = "file"
53-
path = "src/llmwhisperer/__init__.py"
53+
path = "src/unstract/llmwhisperer/__init__.py"
5454

5555
[tool.isort]
5656
line_length = 120
@@ -75,6 +75,6 @@ log_level = "INFO"
7575
log_cli = true
7676

7777
[tool.pdm.scripts]
78-
test.cmd = "pytest"
78+
test.cmd = "pytest -s -v"
7979
test.env_file = "tests/.env"
8080
test.help = "Runs pytests for LLM Whisperer client"

src/llmwhisperer/__init__.py renamed to src/unstract/llmwhisperer/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
__version__ = "0.1.1"
1+
__version__ = "0.2.0"
2+
3+
from .client import LLMWhispererClient # noqa: F401
4+
25

36
def get_sdk_version():
47
"""Returns the SDK version."""

src/llmwhisperer/client.py renamed to src/unstract/llmwhisperer/client.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
import requests
2424

25-
from llmwhisperer.utils import LLMWhispererUtils
25+
from unstract.llmwhisperer.utils import LLMWhispererUtils
2626

2727
BASE_URL = "https://llmwhisperer-api.unstract.com/v1"
2828

@@ -141,7 +141,7 @@ def get_usage_info(self) -> dict:
141141
response = s.send(prepared, timeout=self.api_timeout)
142142
if response.status_code != 200:
143143
err = json.loads(response.text)
144-
err["statusCode"] = response.status_code
144+
err["status_code"] = response.status_code
145145
raise LLMWhispererClientException(err)
146146
return json.loads(response.text)
147147

@@ -213,15 +213,15 @@ def whisper(
213213
if url == "" and file_path == "":
214214
raise LLMWhispererClientException(
215215
{
216-
"statusCode": -1,
216+
"status_code": -1,
217217
"message": "Either url or file_path must be provided",
218218
}
219219
)
220220

221221
if timeout < 0 or timeout > 200:
222222
raise LLMWhispererClientException(
223223
{
224-
"statusCode": -1,
224+
"status_code": -1,
225225
"message": "timeout must be between 0 and 200",
226226
}
227227
)
@@ -243,14 +243,14 @@ def whisper(
243243
response = s.send(prepared, timeout=self.api_timeout)
244244
if response.status_code != 200 and response.status_code != 202:
245245
message = json.loads(response.text)
246-
message["statusCode"] = response.status_code
246+
message["status_code"] = response.status_code
247247
raise LLMWhispererClientException(message)
248248
if response.status_code == 202:
249249
message = json.loads(response.text)
250-
message["statusCode"] = response.status_code
250+
message["status_code"] = response.status_code
251251
return message
252252
return {
253-
"statusCode": response.status_code,
253+
"status_code": response.status_code,
254254
"extracted_text": response.text,
255255
"whisper_hash": response.headers["whisper-hash"],
256256
}
@@ -269,7 +269,7 @@ def whisper_status(self, whisper_hash: str) -> dict:
269269
270270
Returns:
271271
dict: A dictionary containing the status of the whisper operation. The keys in the
272-
dictionary include 'statusCode' and the status details.
272+
dictionary include 'status_code' and the status details.
273273
274274
Raises:
275275
LLMWhispererClientException: If the API request fails, it raises an exception with
@@ -285,10 +285,10 @@ def whisper_status(self, whisper_hash: str) -> dict:
285285
response = s.send(prepared, timeout=self.api_timeout)
286286
if response.status_code != 200:
287287
err = json.loads(response.text)
288-
err["statusCode"] = response.status_code
288+
err["status_code"] = response.status_code
289289
raise LLMWhispererClientException(err)
290290
message = json.loads(response.text)
291-
message["statusCode"] = response.status_code
291+
message["status_code"] = response.status_code
292292
return message
293293

294294
def whisper_retrieve(self, whisper_hash: str) -> dict:
@@ -320,11 +320,11 @@ def whisper_retrieve(self, whisper_hash: str) -> dict:
320320
response = s.send(prepared, timeout=self.api_timeout)
321321
if response.status_code != 200:
322322
err = json.loads(response.text)
323-
err["statusCode"] = response.status_code
323+
err["status_code"] = response.status_code
324324
raise LLMWhispererClientException(err)
325325

326326
return {
327-
"statusCode": response.status_code,
327+
"status_code": response.status_code,
328328
"extracted_text": response.text,
329329
}
330330

@@ -366,8 +366,8 @@ def highlight_data(self, whisper_hash: str, search_text: str) -> dict:
366366
response = s.send(prepared, timeout=self.api_timeout)
367367
if response.status_code != 200:
368368
err = json.loads(response.text)
369-
err["statusCode"] = response.status_code
369+
err["status_code"] = response.status_code
370370
raise LLMWhispererClientException(err)
371371
result = json.loads(response.text)
372-
result["statusCode"] = response.status_code
372+
result["status_code"] = response.status_code
373373
return result
File renamed without changes.

tests/test_client.py renamed to tests/client_test.py

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,17 @@
11
import logging
2+
import os
23
import unittest
4+
from pathlib import Path
35

46
import pytest
57

6-
from llmwhisperer.client import LLMWhispererClient
8+
from unstract.llmwhisperer import LLMWhispererClient
79

810
logger = logging.getLogger(__name__)
911

1012

11-
@pytest.fixture
12-
def llm_whisperer_client():
13-
# Create an instance of the client
14-
client = LLMWhispererClient()
15-
return client
16-
17-
18-
def test_get_usage_info(llm_whisperer_client):
19-
usage_info = llm_whisperer_client.get_usage_info()
13+
def test_get_usage_info(client):
14+
usage_info = client.get_usage_info()
2015
logger.info(usage_info)
2116
assert isinstance(usage_info, dict), "usage_info should be a dictionary"
2217
expected_keys = [
@@ -30,6 +25,38 @@ def test_get_usage_info(llm_whisperer_client):
3025
assert set(usage_info.keys()) == set(expected_keys), f"usage_info {usage_info} does not contain the expected keys"
3126

3227

28+
@pytest.mark.parametrize(
29+
"processing_mode, output_mode, input_file",
30+
[
31+
("ocr", "line-printer", "restaurant_invoice_photo.pdf"),
32+
("ocr", "line-printer", "credit_card.pdf"),
33+
("ocr", "line-printer", "handwritten-form.pdf"),
34+
("ocr", "text", "restaurant_invoice_photo.pdf"),
35+
("text", "line-printer", "restaurant_invoice_photo.pdf"),
36+
("text", "text", "handwritten-form.pdf"),
37+
],
38+
)
39+
def test_whisper(client, data_dir, processing_mode, output_mode, input_file):
40+
file_path = os.path.join(data_dir, input_file)
41+
response = client.whisper(
42+
processing_mode=processing_mode,
43+
output_mode=output_mode,
44+
file_path=file_path,
45+
timeout=200,
46+
)
47+
logger.debug(response)
48+
49+
exp_basename = f"{Path(input_file).stem}.{processing_mode}.{output_mode}.txt"
50+
exp_file = os.path.join(data_dir, "expected", exp_basename)
51+
with open(exp_file, encoding="utf-8") as f:
52+
exp = f.read()
53+
54+
assert isinstance(response, dict)
55+
assert response["status_code"] == 200
56+
assert response["extracted_text"] == exp
57+
58+
59+
# TODO: Review and port to pytest based tests
3360
class TestLLMWhispererClient(unittest.TestCase):
3461
@unittest.skip("Skipping test_whisper")
3562
def test_whisper(self):

0 commit comments

Comments
 (0)