pdfdancer-client-python 0.2.2__py3-none-any.whl → 0.2.4__py3-none-any.whl
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.
- pdfdancer/pdfdancer_v1.py +53 -4
- {pdfdancer_client_python-0.2.2.dist-info → pdfdancer_client_python-0.2.4.dist-info}/METADATA +14 -13
- {pdfdancer_client_python-0.2.2.dist-info → pdfdancer_client_python-0.2.4.dist-info}/RECORD +5 -5
- {pdfdancer_client_python-0.2.2.dist-info → pdfdancer_client_python-0.2.4.dist-info}/WHEEL +0 -0
- {pdfdancer_client_python-0.2.2.dist-info → pdfdancer_client_python-0.2.4.dist-info}/top_level.txt +0 -0
pdfdancer/pdfdancer_v1.py
CHANGED
|
@@ -6,6 +6,7 @@ Provides session-based PDF manipulation operations with strict validation.
|
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
import json
|
|
9
|
+
import os
|
|
9
10
|
from pathlib import Path
|
|
10
11
|
from typing import List, Optional, Union, BinaryIO
|
|
11
12
|
|
|
@@ -116,11 +117,39 @@ class PDFDancer:
|
|
|
116
117
|
@classmethod
|
|
117
118
|
def open(cls,
|
|
118
119
|
pdf_data: Union[bytes, Path, str, BinaryIO],
|
|
119
|
-
token: str,
|
|
120
|
-
base_url: str =
|
|
120
|
+
token: Optional[str] = None,
|
|
121
|
+
base_url: Optional[str] = None,
|
|
121
122
|
timeout: float = 30.0) -> "PDFDancer":
|
|
123
|
+
"""
|
|
124
|
+
Create a client session, falling back to environment variables when needed.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
pdf_data: PDF payload supplied directly or via filesystem handles.
|
|
128
|
+
token: Override for the API token; falls back to `PDFDANCER_TOKEN` environement variable.
|
|
129
|
+
base_url: Override for the API base URL; falls back to `PDFDANCER_BASE_URL`
|
|
130
|
+
or defaults to `https://api.pdfdancer.com`.
|
|
131
|
+
timeout: HTTP read timeout in seconds.
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
A ready-to-use `PDFDancer` client instance.
|
|
135
|
+
"""
|
|
136
|
+
resolved_token = token.strip() if token and token.strip() else None
|
|
137
|
+
if resolved_token is None:
|
|
138
|
+
env_token = os.getenv("PDFDANCER_TOKEN")
|
|
139
|
+
resolved_token = env_token.strip() if env_token and env_token.strip() else None
|
|
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
|
+
|
|
147
|
+
env_base_url = os.getenv("PDFDANCER_BASE_URL")
|
|
148
|
+
resolved_base_url = base_url or (env_base_url.strip() if env_base_url and env_base_url.strip() else None)
|
|
149
|
+
if resolved_base_url is None:
|
|
150
|
+
resolved_base_url = "https://api.pdfdancer.com"
|
|
122
151
|
|
|
123
|
-
return PDFDancer(
|
|
152
|
+
return PDFDancer(resolved_token, pdf_data, resolved_base_url, timeout)
|
|
124
153
|
|
|
125
154
|
def __init__(self, token: str, pdf_data: Union[bytes, Path, str, BinaryIO],
|
|
126
155
|
base_url: str, read_timeout: float = 0):
|
|
@@ -236,6 +265,22 @@ class PDFDancer:
|
|
|
236
265
|
# If JSON parsing fails, return response content or status
|
|
237
266
|
return response.text or f"HTTP {response.status_code}"
|
|
238
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
|
+
|
|
239
284
|
def _create_session(self) -> str:
|
|
240
285
|
"""
|
|
241
286
|
Creates a new PDF processing session by uploading the PDF data.
|
|
@@ -251,6 +296,7 @@ class PDFDancer:
|
|
|
251
296
|
timeout=self._read_timeout if self._read_timeout > 0 else None
|
|
252
297
|
)
|
|
253
298
|
|
|
299
|
+
self._handle_authentication_error(response)
|
|
254
300
|
response.raise_for_status()
|
|
255
301
|
session_id = response.text.strip()
|
|
256
302
|
|
|
@@ -260,6 +306,7 @@ class PDFDancer:
|
|
|
260
306
|
return session_id
|
|
261
307
|
|
|
262
308
|
except requests.exceptions.RequestException as e:
|
|
309
|
+
self._handle_authentication_error(getattr(e, 'response', None))
|
|
263
310
|
error_message = self._extract_error_message(getattr(e, 'response', None))
|
|
264
311
|
raise HttpClientException(f"Failed to create session: {error_message}",
|
|
265
312
|
response=getattr(e, 'response', None), cause=e) from None
|
|
@@ -293,10 +340,12 @@ class PDFDancer:
|
|
|
293
340
|
except (json.JSONDecodeError, KeyError):
|
|
294
341
|
pass
|
|
295
342
|
|
|
343
|
+
self._handle_authentication_error(response)
|
|
296
344
|
response.raise_for_status()
|
|
297
345
|
return response
|
|
298
346
|
|
|
299
347
|
except requests.exceptions.RequestException as e:
|
|
348
|
+
self._handle_authentication_error(getattr(e, 'response', None))
|
|
300
349
|
error_message = self._extract_error_message(getattr(e, 'response', None))
|
|
301
350
|
raise HttpClientException(f"API request failed: {error_message}", response=getattr(e, 'response', None),
|
|
302
351
|
cause=e) from None
|
|
@@ -811,7 +860,7 @@ class PDFDancer:
|
|
|
811
860
|
|
|
812
861
|
# Builder Pattern Support
|
|
813
862
|
|
|
814
|
-
def
|
|
863
|
+
def _paragraph_builder(self) -> 'ParagraphBuilder':
|
|
815
864
|
"""
|
|
816
865
|
Creates a new ParagraphBuilder for fluent paragraph construction.
|
|
817
866
|
Returns:
|
{pdfdancer_client_python-0.2.2.dist-info → pdfdancer_client_python-0.2.4.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pdfdancer-client-python
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: Python client for PDFDancer API
|
|
5
5
|
Author-email: "The Famous Cat Ltd." <hi@thefamouscat.com>
|
|
6
6
|
License: MIT
|
|
@@ -63,7 +63,7 @@ client._delete(paragraphs[0])
|
|
|
63
63
|
client._move(images[0], Position.at_page_coordinates(0, 100, 200))
|
|
64
64
|
|
|
65
65
|
# Builder pattern (mirrors Java ParagraphBuilder)
|
|
66
|
-
paragraph = (client.
|
|
66
|
+
paragraph = (client._paragraph_builder()
|
|
67
67
|
.from_string("Hello World")
|
|
68
68
|
.with_font(Font("Arial", 12))
|
|
69
69
|
.with_color(Color(255, 0, 0))
|
|
@@ -141,25 +141,26 @@ result = client.modify_text_line(ref, "new text")
|
|
|
141
141
|
```
|
|
142
142
|
|
|
143
143
|
### Builder Pattern
|
|
144
|
+
|
|
144
145
|
```python
|
|
145
146
|
# Java: client.paragraphBuilder()
|
|
146
|
-
builder = client.
|
|
147
|
+
builder = client._paragraph_builder()
|
|
147
148
|
|
|
148
149
|
# Fluent interface (mirrors Java ParagraphBuilder)
|
|
149
150
|
paragraph = (builder
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
151
|
+
.from_string("Text content") # Java: fromString()
|
|
152
|
+
.with_font(Font("Arial", 12)) # Java: withFont()
|
|
153
|
+
.with_color(Color(255, 0, 0)) # Java: withColor()
|
|
154
|
+
.with_line_spacing(1.5) # Java: withLineSpacing()
|
|
155
|
+
.with_position(position) # Java: withPosition()
|
|
156
|
+
.build()) # Java: build()
|
|
156
157
|
|
|
157
158
|
# Font file registration (Java: withFont(File, double))
|
|
158
159
|
paragraph = (builder
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
160
|
+
.with_font_file("custom.ttf", 14.0) # Java: withFont(File, double)
|
|
161
|
+
.from_string("Custom font text")
|
|
162
|
+
.with_position(position)
|
|
163
|
+
.build())
|
|
163
164
|
```
|
|
164
165
|
|
|
165
166
|
### Position API
|
|
@@ -3,9 +3,9 @@ pdfdancer/exceptions.py,sha256=Y5zwNVZprsv2hvKX304cXWobJt11nrEhCzLklu2wiO8,1567
|
|
|
3
3
|
pdfdancer/image_builder.py,sha256=Omxc2LcieJ1MbvWBXR5_sfia--eAucTUe0KWgr22HYo,842
|
|
4
4
|
pdfdancer/models.py,sha256=SmkKScr47uVs6FCWUAVIg6rucYrYHvbIxZngyA50XyI,15498
|
|
5
5
|
pdfdancer/paragraph_builder.py,sha256=bAfwX9U2YT1UGX9EKkPnGYvGK3SQP3X1ocxlgyLE_rU,8872
|
|
6
|
-
pdfdancer/pdfdancer_v1.py,sha256=
|
|
6
|
+
pdfdancer/pdfdancer_v1.py,sha256=Pgv-2L0pYQdOUVK2nUntrGB6hCDKUOMWHYuN8loBM3Q,35540
|
|
7
7
|
pdfdancer/types.py,sha256=lcYnqCFgnrGpplSPCxKh3X9AZ3-9t-lJqMH5ZLew_I4,8188
|
|
8
|
-
pdfdancer_client_python-0.2.
|
|
9
|
-
pdfdancer_client_python-0.2.
|
|
10
|
-
pdfdancer_client_python-0.2.
|
|
11
|
-
pdfdancer_client_python-0.2.
|
|
8
|
+
pdfdancer_client_python-0.2.4.dist-info/METADATA,sha256=a-sAoRCXslorLigW0Vxbmhqzg5krpQ3b9WpHyi_8FM8,9253
|
|
9
|
+
pdfdancer_client_python-0.2.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
10
|
+
pdfdancer_client_python-0.2.4.dist-info/top_level.txt,sha256=ICwSVRpcCKrdBF9QlaX9Y0e_N3Nk1p7QVxadGOnbxeY,10
|
|
11
|
+
pdfdancer_client_python-0.2.4.dist-info/RECORD,,
|
|
File without changes
|
{pdfdancer_client_python-0.2.2.dist-info → pdfdancer_client_python-0.2.4.dist-info}/top_level.txt
RENAMED
|
File without changes
|