pdfdancer-client-python 0.2.7__tar.gz → 0.2.9__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.

Files changed (44) hide show
  1. {pdfdancer_client_python-0.2.7/src/pdfdancer_client_python.egg-info → pdfdancer_client_python-0.2.9}/PKG-INFO +1 -1
  2. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/pyproject.toml +1 -1
  3. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/src/pdfdancer/paragraph_builder.py +11 -0
  4. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/src/pdfdancer/pdfdancer_v1.py +6 -2
  5. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9/src/pdfdancer_client_python.egg-info}/PKG-INFO +1 -1
  6. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/src/pdfdancer_client_python.egg-info/SOURCES.txt +1 -1
  7. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/tests/e2e/test_paragraph.py +14 -1
  8. pdfdancer_client_python-0.2.9/tests/e2e/test_pdfdancer.py +33 -0
  9. pdfdancer_client_python-0.2.7/tests/test_authentication.py +0 -36
  10. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/.github/workflows/ci.yml +0 -0
  11. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/.gitignore +0 -0
  12. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/CLAUDE.md +0 -0
  13. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/README.md +0 -0
  14. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/docs/openapi.yml +0 -0
  15. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/release.py +0 -0
  16. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/requirements-dev.txt +0 -0
  17. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/requirements.txt +0 -0
  18. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/setup.cfg +0 -0
  19. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/src/pdfdancer/__init__.py +0 -0
  20. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/src/pdfdancer/exceptions.py +0 -0
  21. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/src/pdfdancer/image_builder.py +0 -0
  22. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/src/pdfdancer/models.py +0 -0
  23. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/src/pdfdancer/types.py +0 -0
  24. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/src/pdfdancer_client_python.egg-info/dependency_links.txt +0 -0
  25. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/src/pdfdancer_client_python.egg-info/requires.txt +0 -0
  26. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/src/pdfdancer_client_python.egg-info/top_level.txt +0 -0
  27. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/tests/__init__.py +0 -0
  28. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/tests/conftest.py +0 -0
  29. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/tests/e2e/__init__.py +0 -0
  30. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/tests/e2e/test_acroform.py +0 -0
  31. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/tests/e2e/test_form_x_objects.py +0 -0
  32. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/tests/e2e/test_image.py +0 -0
  33. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/tests/e2e/test_line.py +0 -0
  34. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/tests/e2e/test_page.py +0 -0
  35. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/tests/e2e/test_path.py +0 -0
  36. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/tests/fixtures/DancingScript-Regular.ttf +0 -0
  37. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/tests/fixtures/JetBrainsMono-Regular.ttf +0 -0
  38. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/tests/fixtures/ObviouslyAwesome.pdf +0 -0
  39. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/tests/fixtures/basic-paths.pdf +0 -0
  40. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/tests/fixtures/form-xobject-example.pdf +0 -0
  41. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/tests/fixtures/logo-80.png +0 -0
  42. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/tests/fixtures/mixed-form-types.pdf +0 -0
  43. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/tests/test_models.py +0 -0
  44. {pdfdancer_client_python-0.2.7 → pdfdancer_client_python-0.2.9}/tests/test_openapi_compliance.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pdfdancer-client-python
3
- Version: 0.2.7
3
+ Version: 0.2.9
4
4
  Summary: Python client for PDFDancer API
5
5
  Author-email: "The Famous Cat Ltd." <hi@thefamouscat.com>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pdfdancer-client-python"
7
- version = "0.2.7"
7
+ version = "0.2.9"
8
8
  description = "Python client for PDFDancer API"
9
9
  readme = "README.md"
10
10
  authors = [
@@ -268,3 +268,14 @@ class ParagraphBuilder:
268
268
 
269
269
  def add(self):
270
270
  self._client._add_paragraph(self.build())
271
+
272
+
273
+ class ParagraphPageBuilder(ParagraphBuilder):
274
+
275
+ def __init__(self, client: 'PDFDancer', page_index: int):
276
+ super().__init__(client)
277
+ self._page_index: Optional[int] = page_index
278
+
279
+ # noinspection PyMethodOverriding
280
+ def at(self, x: float, y: float) -> 'ParagraphBuilder':
281
+ return super().at(self._page_index, x, y)
@@ -26,6 +26,7 @@ from .models import (
26
26
  FindRequest, DeleteRequest, MoveRequest, AddRequest, ModifyRequest, ModifyTextRequest, ChangeFormFieldRequest,
27
27
  ShapeType, PositionMode
28
28
  )
29
+ from .paragraph_builder import ParagraphPageBuilder
29
30
  from .types import PathObject, ParagraphObject, TextLineObject, ImageObject, FormObject, FormFieldObject
30
31
 
31
32
 
@@ -114,6 +115,9 @@ class PageClient:
114
115
  def _ref(self):
115
116
  return ObjectRef(internal_id=self.internal_id, position=self.position, type=self.object_type)
116
117
 
118
+ def new_paragraph(self):
119
+ return ParagraphPageBuilder(self.root, self.page_index)
120
+
117
121
 
118
122
  class PDFDancer:
119
123
  """
@@ -779,7 +783,7 @@ class PDFDancer:
779
783
 
780
784
  # Document Operations
781
785
 
782
- def get_pdf_file(self) -> bytes:
786
+ def get_bytes(self) -> bytes:
783
787
  """
784
788
  Downloads the current state of the PDF document with all modifications applied.
785
789
 
@@ -804,7 +808,7 @@ class PDFDancer:
804
808
  raise ValidationException("File path cannot be null or empty")
805
809
 
806
810
  try:
807
- pdf_data = self.get_pdf_file()
811
+ pdf_data = self.get_bytes()
808
812
  output_path = Path(file_path)
809
813
 
810
814
  # Create parent directories if they don't exist
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pdfdancer-client-python
3
- Version: 0.2.7
3
+ Version: 0.2.9
4
4
  Summary: Python client for PDFDancer API
5
5
  Author-email: "The Famous Cat Ltd." <hi@thefamouscat.com>
6
6
  License: MIT
@@ -21,7 +21,6 @@ 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
23
  tests/conftest.py
24
- tests/test_authentication.py
25
24
  tests/test_models.py
26
25
  tests/test_openapi_compliance.py
27
26
  tests/e2e/__init__.py
@@ -32,6 +31,7 @@ tests/e2e/test_line.py
32
31
  tests/e2e/test_page.py
33
32
  tests/e2e/test_paragraph.py
34
33
  tests/e2e/test_path.py
34
+ tests/e2e/test_pdfdancer.py
35
35
  tests/fixtures/DancingScript-Regular.ttf
36
36
  tests/fixtures/JetBrainsMono-Regular.ttf
37
37
  tests/fixtures/ObviouslyAwesome.pdf
@@ -116,6 +116,19 @@ def test_add_paragraph_with_custom_font1_1():
116
116
  _assert_new_paragraph_exists(pdf)
117
117
 
118
118
 
119
+ def test_add_paragraph_on_page_with_custom_font1_1():
120
+ base_url, token, pdf_path = _require_env_and_fixture("ObviouslyAwesome.pdf")
121
+
122
+ with PDFDancer.open(pdf_path, token=token, base_url=base_url, timeout=30.0) as pdf:
123
+ pdf.page(0).new_paragraph() \
124
+ .text("Awesomely\nObvious!") \
125
+ .font("Roboto-Regular", 14) \
126
+ .line_spacing(0.7) \
127
+ .at(300.1, 500) \
128
+ .add()
129
+ _assert_new_paragraph_exists(pdf)
130
+
131
+
119
132
  def test_add_paragraph_with_custom_font1_2():
120
133
  base_url, token, pdf_path = _require_env_and_fixture("ObviouslyAwesome.pdf")
121
134
 
@@ -161,7 +174,7 @@ def test_add_paragraph_with_custom_font3():
161
174
  with PDFDancer.open(pdf_path, token=token, base_url=base_url, timeout=30.0) as pdf:
162
175
  pdf.new_paragraph() \
163
176
  .text("Awesomely\nObvious!") \
164
- .font_file(str(ttf_path), 24) \
177
+ .font_file(ttf_path, 24) \
165
178
  .line_spacing(1.8) \
166
179
  .color(Color(0, 0, 255)) \
167
180
  .at(0, 300.1, 500) \
@@ -0,0 +1,33 @@
1
+ import os
2
+
3
+ import pytest
4
+
5
+ from tests.e2e import _require_env_and_fixture
6
+ from pdfdancer import PDFDancer, ValidationException, HttpClientException
7
+
8
+
9
+ def test_env_vars():
10
+ base_url, _, pdf_path = _require_env_and_fixture("ObviouslyAwesome.pdf")
11
+ os.environ.pop("PDFDANCER_TOKEN", None)
12
+
13
+ with pytest.raises(ValidationException) as exc_info:
14
+ with PDFDancer.open(pdf_path, base_url=base_url) as pdf:
15
+ pass
16
+ assert "Missing PDFDancer API token. Pass a token via the `token` argument or set the PDFDANCER_TOKEN environment variable." == str(
17
+ exc_info.value)
18
+
19
+ os.environ["PDFDANCER_TOKEN"] = "42"
20
+ with PDFDancer.open(pdf_path, base_url=base_url) as pdf:
21
+ pass
22
+
23
+ os.environ["PDFDANCER_BASE_URL"] = "http://www.google.com"
24
+ with pytest.raises(HttpClientException) as exc_info:
25
+ with PDFDancer.open(pdf_path) as pdf:
26
+ pass
27
+
28
+ os.environ["PDFDANCER_BASE_URL"] = "https://api.pdfdancer.com"
29
+ with pytest.raises(ValidationException) as exc_info:
30
+ with PDFDancer.open(pdf_path) as pdf:
31
+ pass
32
+ assert "Authentication with the PDFDancer API failed. Confirm that your API token is valid, has not expired" in str(
33
+ exc_info.value)
@@ -1,36 +0,0 @@
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