pdfdancer-client-python 0.2.3__tar.gz → 0.2.4__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.
Potentially problematic release.
This version of pdfdancer-client-python might be problematic. Click here for more details.
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/.gitignore +1 -0
- {pdfdancer_client_python-0.2.3/src/pdfdancer_client_python.egg-info → pdfdancer_client_python-0.2.4}/PKG-INFO +1 -1
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/pyproject.toml +1 -1
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/src/pdfdancer/pdfdancer_v1.py +26 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4/src/pdfdancer_client_python.egg-info}/PKG-INFO +1 -1
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/src/pdfdancer_client_python.egg-info/SOURCES.txt +1 -0
- pdfdancer_client_python-0.2.4/tests/test_authentication.py +36 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/.github/workflows/ci.yml +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/CLAUDE.md +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/README.md +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/docs/openapi.yml +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/release.py +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/requirements-dev.txt +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/requirements.txt +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/setup.cfg +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/src/pdfdancer/__init__.py +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/src/pdfdancer/exceptions.py +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/src/pdfdancer/image_builder.py +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/src/pdfdancer/models.py +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/src/pdfdancer/paragraph_builder.py +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/src/pdfdancer/types.py +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/src/pdfdancer_client_python.egg-info/dependency_links.txt +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/src/pdfdancer_client_python.egg-info/requires.txt +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/src/pdfdancer_client_python.egg-info/top_level.txt +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/tests/__init__.py +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/tests/e2e/__init__.py +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/tests/e2e/test_acroform.py +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/tests/e2e/test_form_x_objects.py +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/tests/e2e/test_image.py +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/tests/e2e/test_line.py +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/tests/e2e/test_page.py +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/tests/e2e/test_paragraph.py +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/tests/e2e/test_path.py +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/tests/fixtures/DancingScript-Regular.ttf +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/tests/fixtures/JetBrainsMono-Regular.ttf +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/tests/fixtures/ObviouslyAwesome.pdf +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/tests/fixtures/basic-paths.pdf +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/tests/fixtures/form-xobject-example.pdf +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/tests/fixtures/logo-80.png +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/tests/fixtures/mixed-form-types.pdf +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/tests/test_models.py +0 -0
- {pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/tests/test_openapi_compliance.py +0 -0
{pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/src/pdfdancer/pdfdancer_v1.py
RENAMED
|
@@ -138,6 +138,12 @@ class PDFDancer:
|
|
|
138
138
|
env_token = os.getenv("PDFDANCER_TOKEN")
|
|
139
139
|
resolved_token = env_token.strip() if env_token and env_token.strip() else None
|
|
140
140
|
|
|
141
|
+
if resolved_token is None:
|
|
142
|
+
raise ValidationException(
|
|
143
|
+
"Missing PDFDancer API token. Pass a token via the `token` argument "
|
|
144
|
+
"or set the PDFDANCER_TOKEN environment variable."
|
|
145
|
+
)
|
|
146
|
+
|
|
141
147
|
env_base_url = os.getenv("PDFDANCER_BASE_URL")
|
|
142
148
|
resolved_base_url = base_url or (env_base_url.strip() if env_base_url and env_base_url.strip() else None)
|
|
143
149
|
if resolved_base_url is None:
|
|
@@ -259,6 +265,22 @@ class PDFDancer:
|
|
|
259
265
|
# If JSON parsing fails, return response content or status
|
|
260
266
|
return response.text or f"HTTP {response.status_code}"
|
|
261
267
|
|
|
268
|
+
def _handle_authentication_error(self, response: Optional[requests.Response]) -> None:
|
|
269
|
+
"""
|
|
270
|
+
Translate authentication failures into a clear, actionable validation error.
|
|
271
|
+
"""
|
|
272
|
+
if response is None:
|
|
273
|
+
return
|
|
274
|
+
|
|
275
|
+
if response.status_code in (401, 403):
|
|
276
|
+
details = self._extract_error_message(response)
|
|
277
|
+
raise ValidationException(
|
|
278
|
+
"Authentication with the PDFDancer API failed. "
|
|
279
|
+
"Confirm that your API token is valid, has not expired, and is supplied via "
|
|
280
|
+
"the `token` argument or the PDFDANCER_TOKEN environment variable. "
|
|
281
|
+
f"Server response: {details}"
|
|
282
|
+
)
|
|
283
|
+
|
|
262
284
|
def _create_session(self) -> str:
|
|
263
285
|
"""
|
|
264
286
|
Creates a new PDF processing session by uploading the PDF data.
|
|
@@ -274,6 +296,7 @@ class PDFDancer:
|
|
|
274
296
|
timeout=self._read_timeout if self._read_timeout > 0 else None
|
|
275
297
|
)
|
|
276
298
|
|
|
299
|
+
self._handle_authentication_error(response)
|
|
277
300
|
response.raise_for_status()
|
|
278
301
|
session_id = response.text.strip()
|
|
279
302
|
|
|
@@ -283,6 +306,7 @@ class PDFDancer:
|
|
|
283
306
|
return session_id
|
|
284
307
|
|
|
285
308
|
except requests.exceptions.RequestException as e:
|
|
309
|
+
self._handle_authentication_error(getattr(e, 'response', None))
|
|
286
310
|
error_message = self._extract_error_message(getattr(e, 'response', None))
|
|
287
311
|
raise HttpClientException(f"Failed to create session: {error_message}",
|
|
288
312
|
response=getattr(e, 'response', None), cause=e) from None
|
|
@@ -316,10 +340,12 @@ class PDFDancer:
|
|
|
316
340
|
except (json.JSONDecodeError, KeyError):
|
|
317
341
|
pass
|
|
318
342
|
|
|
343
|
+
self._handle_authentication_error(response)
|
|
319
344
|
response.raise_for_status()
|
|
320
345
|
return response
|
|
321
346
|
|
|
322
347
|
except requests.exceptions.RequestException as e:
|
|
348
|
+
self._handle_authentication_error(getattr(e, 'response', None))
|
|
323
349
|
error_message = self._extract_error_message(getattr(e, 'response', None))
|
|
324
350
|
raise HttpClientException(f"API request failed: {error_message}", response=getattr(e, 'response', None),
|
|
325
351
|
cause=e) from None
|
|
@@ -20,6 +20,7 @@ src/pdfdancer_client_python.egg-info/dependency_links.txt
|
|
|
20
20
|
src/pdfdancer_client_python.egg-info/requires.txt
|
|
21
21
|
src/pdfdancer_client_python.egg-info/top_level.txt
|
|
22
22
|
tests/__init__.py
|
|
23
|
+
tests/test_authentication.py
|
|
23
24
|
tests/test_models.py
|
|
24
25
|
tests/test_openapi_compliance.py
|
|
25
26
|
tests/e2e/__init__.py
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
from pdfdancer import ValidationException
|
|
5
|
+
from pdfdancer.pdfdancer_v1 import PDFDancer
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_open_without_token_reports_actionable_message():
|
|
9
|
+
with pytest.raises(ValidationException) as exc_info:
|
|
10
|
+
PDFDancer.open(pdf_data=b"%PDF", token="")
|
|
11
|
+
|
|
12
|
+
message = str(exc_info.value)
|
|
13
|
+
assert "Missing PDFDancer API token" in message
|
|
14
|
+
assert "PDFDANCER_TOKEN" in message
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def test_create_session_unauthorized_reports_guidance(monkeypatch):
|
|
18
|
+
class FakeResponse:
|
|
19
|
+
status_code = 401
|
|
20
|
+
text = "Unauthorized"
|
|
21
|
+
|
|
22
|
+
def json(self):
|
|
23
|
+
return {"message": "Unauthorized"}
|
|
24
|
+
|
|
25
|
+
def fake_post(self, *args, **kwargs):
|
|
26
|
+
return FakeResponse()
|
|
27
|
+
|
|
28
|
+
monkeypatch.setattr(requests.Session, "post", fake_post)
|
|
29
|
+
|
|
30
|
+
with pytest.raises(ValidationException) as exc_info:
|
|
31
|
+
PDFDancer(token="bad-token", pdf_data=b"%PDF", base_url="https://api.example.com")
|
|
32
|
+
|
|
33
|
+
message = str(exc_info.value)
|
|
34
|
+
assert "Authentication with the PDFDancer API failed" in message
|
|
35
|
+
assert "Server response: Unauthorized" in message
|
|
36
|
+
assert "PDFDANCER_TOKEN" in message
|
|
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
|
{pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/src/pdfdancer/image_builder.py
RENAMED
|
File without changes
|
|
File without changes
|
{pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/src/pdfdancer/paragraph_builder.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/tests/e2e/test_form_x_objects.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/tests/fixtures/ObviouslyAwesome.pdf
RENAMED
|
File without changes
|
{pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/tests/fixtures/basic-paths.pdf
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/tests/fixtures/mixed-form-types.pdf
RENAMED
|
File without changes
|
|
File without changes
|
{pdfdancer_client_python-0.2.3 → pdfdancer_client_python-0.2.4}/tests/test_openapi_compliance.py
RENAMED
|
File without changes
|