pdfdancer-client-python 0.2.8__tar.gz → 0.2.10__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 (45) hide show
  1. {pdfdancer_client_python-0.2.8/src/pdfdancer_client_python.egg-info → pdfdancer_client_python-0.2.10}/PKG-INFO +1 -1
  2. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/pyproject.toml +1 -1
  3. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/src/pdfdancer/__init__.py +2 -1
  4. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/src/pdfdancer/models.py +43 -0
  5. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/src/pdfdancer/paragraph_builder.py +11 -0
  6. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/src/pdfdancer/pdfdancer_v1.py +4 -0
  7. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10/src/pdfdancer_client_python.egg-info}/PKG-INFO +1 -1
  8. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/src/pdfdancer_client_python.egg-info/SOURCES.txt +1 -1
  9. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/e2e/test_paragraph.py +59 -1
  10. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/e2e/test_pdfdancer.py +1 -1
  11. pdfdancer_client_python-0.2.10/tests/test_standard_fonts.py +164 -0
  12. pdfdancer_client_python-0.2.8/tests/test_authentication.py +0 -36
  13. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/.github/workflows/ci.yml +0 -0
  14. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/.gitignore +0 -0
  15. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/CLAUDE.md +0 -0
  16. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/README.md +0 -0
  17. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/docs/openapi.yml +0 -0
  18. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/release.py +0 -0
  19. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/requirements-dev.txt +0 -0
  20. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/requirements.txt +0 -0
  21. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/setup.cfg +0 -0
  22. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/src/pdfdancer/exceptions.py +0 -0
  23. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/src/pdfdancer/image_builder.py +0 -0
  24. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/src/pdfdancer/types.py +0 -0
  25. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/src/pdfdancer_client_python.egg-info/dependency_links.txt +0 -0
  26. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/src/pdfdancer_client_python.egg-info/requires.txt +0 -0
  27. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/src/pdfdancer_client_python.egg-info/top_level.txt +0 -0
  28. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/__init__.py +0 -0
  29. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/conftest.py +0 -0
  30. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/e2e/__init__.py +0 -0
  31. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/e2e/test_acroform.py +0 -0
  32. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/e2e/test_form_x_objects.py +0 -0
  33. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/e2e/test_image.py +0 -0
  34. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/e2e/test_line.py +0 -0
  35. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/e2e/test_page.py +0 -0
  36. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/e2e/test_path.py +0 -0
  37. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/fixtures/DancingScript-Regular.ttf +0 -0
  38. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/fixtures/JetBrainsMono-Regular.ttf +0 -0
  39. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/fixtures/ObviouslyAwesome.pdf +0 -0
  40. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/fixtures/basic-paths.pdf +0 -0
  41. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/fixtures/form-xobject-example.pdf +0 -0
  42. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/fixtures/logo-80.png +0 -0
  43. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/fixtures/mixed-form-types.pdf +0 -0
  44. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/test_models.py +0 -0
  45. {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/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.8
3
+ Version: 0.2.10
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.8"
7
+ version = "0.2.10"
8
8
  description = "Python client for PDFDancer API"
9
9
  readme = "README.md"
10
10
  authors = [
@@ -12,7 +12,7 @@ from .exceptions import (
12
12
  )
13
13
  from .models import (
14
14
  ObjectRef, Position, ObjectType, Font, Color, Image, BoundingRect, Paragraph, FormFieldRef,
15
- PositionMode, ShapeType, Point
15
+ PositionMode, ShapeType, Point, StandardFonts
16
16
  )
17
17
  from .paragraph_builder import ParagraphBuilder
18
18
 
@@ -32,6 +32,7 @@ __all__ = [
32
32
  "PositionMode",
33
33
  "ShapeType",
34
34
  "Point",
35
+ "StandardFonts",
35
36
  "PdfDancerException",
36
37
  "FontNotFoundException",
37
38
  "ValidationException",
@@ -8,6 +8,49 @@ from enum import Enum
8
8
  from typing import Optional, List, Any
9
9
 
10
10
 
11
+ class StandardFonts(Enum):
12
+ """
13
+ The 14 standard PDF fonts that are guaranteed to be available in all PDF readers.
14
+ These fonts do not need to be embedded in the PDF document.
15
+
16
+ Serif fonts (Times family):
17
+ - TIMES_ROMAN: Standard Times Roman font
18
+ - TIMES_BOLD: Bold version of Times Roman
19
+ - TIMES_ITALIC: Italic version of Times Roman
20
+ - TIMES_BOLD_ITALIC: Bold and italic version of Times Roman
21
+
22
+ Sans-serif fonts (Helvetica family):
23
+ - HELVETICA: Standard Helvetica font
24
+ - HELVETICA_BOLD: Bold version of Helvetica
25
+ - HELVETICA_OBLIQUE: Oblique (italic) version of Helvetica
26
+ - HELVETICA_BOLD_OBLIQUE: Bold and oblique version of Helvetica
27
+
28
+ Monospace fonts (Courier family):
29
+ - COURIER: Standard Courier font
30
+ - COURIER_BOLD: Bold version of Courier
31
+ - COURIER_OBLIQUE: Oblique (italic) version of Courier
32
+ - COURIER_BOLD_OBLIQUE: Bold and oblique version of Courier
33
+
34
+ Symbol and decorative fonts:
35
+ - SYMBOL: Symbol font for mathematical and special characters
36
+ - ZAPF_DINGBATS: Zapf Dingbats font for decorative symbols
37
+ """
38
+ TIMES_ROMAN = "Times-Roman"
39
+ TIMES_BOLD = "Times-Bold"
40
+ TIMES_ITALIC = "Times-Italic"
41
+ TIMES_BOLD_ITALIC = "Times-BoldItalic"
42
+ HELVETICA = "Helvetica"
43
+ HELVETICA_BOLD = "Helvetica-Bold"
44
+ HELVETICA_OBLIQUE = "Helvetica-Oblique"
45
+ HELVETICA_BOLD_OBLIQUE = "Helvetica-BoldOblique"
46
+ COURIER = "Courier"
47
+ COURIER_BOLD = "Courier-Bold"
48
+ COURIER_OBLIQUE = "Courier-Oblique"
49
+ COURIER_BOLD_OBLIQUE = "Courier-BoldOblique"
50
+ SYMBOL = "Symbol"
51
+ ZAPF_DINGBATS = "ZapfDingbats"
52
+
53
+
11
54
  class ObjectType(Enum):
12
55
  """Object type enumeration matching the Java ObjectType."""
13
56
  FORM_FIELD = "FORM_FIELD"
@@ -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
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pdfdancer-client-python
3
- Version: 0.2.8
3
+ Version: 0.2.10
4
4
  Summary: Python client for PDFDancer API
5
5
  Author-email: "The Famous Cat Ltd." <hi@thefamouscat.com>
6
6
  License: MIT
@@ -21,9 +21,9 @@ 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
26
+ tests/test_standard_fonts.py
27
27
  tests/e2e/__init__.py
28
28
  tests/e2e/test_acroform.py
29
29
  tests/e2e/test_form_x_objects.py
@@ -1,6 +1,6 @@
1
1
  import pytest
2
2
 
3
- from pdfdancer import Color
3
+ from pdfdancer import Color, StandardFonts
4
4
  from pdfdancer.pdfdancer_v1 import PDFDancer
5
5
  from tests.e2e import _require_env_and_fixture
6
6
 
@@ -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
 
@@ -167,3 +180,48 @@ def test_add_paragraph_with_custom_font3():
167
180
  .at(0, 300.1, 500) \
168
181
  .add()
169
182
  _assert_new_paragraph_exists(pdf)
183
+
184
+
185
+ def test_add_paragraph_with_standard_font_helvetica():
186
+ base_url, token, pdf_path = _require_env_and_fixture("ObviouslyAwesome.pdf")
187
+
188
+ with PDFDancer.open(pdf_path, token=token, base_url=base_url, timeout=30.0) as pdf:
189
+ pdf.new_paragraph() \
190
+ .text("Standard Font Test\nHelvetica Bold") \
191
+ .font(StandardFonts.HELVETICA_BOLD.value, 16) \
192
+ .line_spacing(1.2) \
193
+ .color(Color(255, 0, 0)) \
194
+ .at(0, 100, 100) \
195
+ .add()
196
+
197
+ lines = pdf.page(0).select_text_lines_starting_with("Standard Font Test")
198
+ assert len(lines) >= 1
199
+
200
+
201
+ def test_add_paragraph_with_standard_font_times():
202
+ base_url, token, pdf_path = _require_env_and_fixture("ObviouslyAwesome.pdf")
203
+
204
+ with PDFDancer.open(pdf_path, token=token, base_url=base_url, timeout=30.0) as pdf:
205
+ pdf.new_paragraph() \
206
+ .text("Times Roman Test") \
207
+ .font(StandardFonts.TIMES_ROMAN.value, 14) \
208
+ .at(0, 150, 150) \
209
+ .add()
210
+
211
+ lines = pdf.page(0).select_text_lines_starting_with("Times Roman Test")
212
+ assert len(lines) >= 1
213
+
214
+
215
+ def test_add_paragraph_with_standard_font_courier():
216
+ base_url, token, pdf_path = _require_env_and_fixture("ObviouslyAwesome.pdf")
217
+
218
+ with PDFDancer.open(pdf_path, token=token, base_url=base_url, timeout=30.0) as pdf:
219
+ pdf.new_paragraph() \
220
+ .text("Courier Monospace\nCode Example") \
221
+ .font(StandardFonts.COURIER_BOLD.value, 12) \
222
+ .line_spacing(1.5) \
223
+ .at(0, 200, 200) \
224
+ .add()
225
+
226
+ lines = pdf.page(0).select_text_lines_starting_with("Courier Monospace")
227
+ assert len(lines) >= 1
@@ -2,7 +2,7 @@ import os
2
2
 
3
3
  import pytest
4
4
 
5
- from e2e import _require_env_and_fixture
5
+ from tests.e2e import _require_env_and_fixture
6
6
  from pdfdancer import PDFDancer, ValidationException, HttpClientException
7
7
 
8
8
 
@@ -0,0 +1,164 @@
1
+ """
2
+ Tests for StandardFonts enum - validates all 14 standard PDF fonts.
3
+ """
4
+
5
+ import pytest
6
+
7
+ from pdfdancer import StandardFonts
8
+
9
+
10
+ class TestStandardFonts:
11
+ """Test StandardFonts enum functionality."""
12
+
13
+ def test_enum_has_14_fonts(self):
14
+ """Test that StandardFonts enum contains exactly 14 standard PDF fonts."""
15
+ assert len(StandardFonts) == 14
16
+
17
+ def test_times_family_fonts(self):
18
+ """Test Times family fonts (4 variants)."""
19
+ assert StandardFonts.TIMES_ROMAN.value == "Times-Roman"
20
+ assert StandardFonts.TIMES_BOLD.value == "Times-Bold"
21
+ assert StandardFonts.TIMES_ITALIC.value == "Times-Italic"
22
+ assert StandardFonts.TIMES_BOLD_ITALIC.value == "Times-BoldItalic"
23
+
24
+ def test_helvetica_family_fonts(self):
25
+ """Test Helvetica family fonts (4 variants)."""
26
+ assert StandardFonts.HELVETICA.value == "Helvetica"
27
+ assert StandardFonts.HELVETICA_BOLD.value == "Helvetica-Bold"
28
+ assert StandardFonts.HELVETICA_OBLIQUE.value == "Helvetica-Oblique"
29
+ assert StandardFonts.HELVETICA_BOLD_OBLIQUE.value == "Helvetica-BoldOblique"
30
+
31
+ def test_courier_family_fonts(self):
32
+ """Test Courier family fonts (4 variants)."""
33
+ assert StandardFonts.COURIER.value == "Courier"
34
+ assert StandardFonts.COURIER_BOLD.value == "Courier-Bold"
35
+ assert StandardFonts.COURIER_OBLIQUE.value == "Courier-Oblique"
36
+ assert StandardFonts.COURIER_BOLD_OBLIQUE.value == "Courier-BoldOblique"
37
+
38
+ def test_symbol_fonts(self):
39
+ """Test Symbol and ZapfDingbats fonts."""
40
+ assert StandardFonts.SYMBOL.value == "Symbol"
41
+ assert StandardFonts.ZAPF_DINGBATS.value == "ZapfDingbats"
42
+
43
+ def test_all_font_names_are_unique(self):
44
+ """Test that all font names are unique."""
45
+ font_values = [font.value for font in StandardFonts]
46
+ assert len(font_values) == len(set(font_values))
47
+
48
+ def test_all_font_enum_names_are_unique(self):
49
+ """Test that all enum names are unique."""
50
+ font_names = [font.name for font in StandardFonts]
51
+ assert len(font_names) == len(set(font_names))
52
+
53
+ def test_enum_access_by_name(self):
54
+ """Test accessing fonts by enum name."""
55
+ assert StandardFonts.TIMES_ROMAN == StandardFonts["TIMES_ROMAN"]
56
+ assert StandardFonts.HELVETICA == StandardFonts["HELVETICA"]
57
+ assert StandardFonts.COURIER == StandardFonts["COURIER"]
58
+
59
+ def test_enum_access_by_value(self):
60
+ """Test accessing fonts by their string value."""
61
+ assert StandardFonts("Times-Roman") == StandardFonts.TIMES_ROMAN
62
+ assert StandardFonts("Helvetica") == StandardFonts.HELVETICA
63
+ assert StandardFonts("Courier") == StandardFonts.COURIER
64
+
65
+ def test_font_name_format_follows_pdf_spec(self):
66
+ """Test that font names follow PDF specification format."""
67
+ # Verify specific font name formats according to PDF spec
68
+ assert StandardFonts.ZAPF_DINGBATS.value == "ZapfDingbats"
69
+ assert StandardFonts.SYMBOL.value == "Symbol"
70
+
71
+ # Base fonts (no modifiers)
72
+ assert StandardFonts.HELVETICA.value == "Helvetica"
73
+ assert StandardFonts.COURIER.value == "Courier"
74
+ assert StandardFonts.TIMES_ROMAN.value == "Times-Roman"
75
+
76
+ # Modified fonts should have hyphens
77
+ modified_fonts = [
78
+ f for f in StandardFonts
79
+ if f not in [StandardFonts.HELVETICA, StandardFonts.COURIER,
80
+ StandardFonts.SYMBOL, StandardFonts.ZAPF_DINGBATS]
81
+ ]
82
+ for font in modified_fonts:
83
+ assert "-" in font.value
84
+
85
+ def test_iteration_over_fonts(self):
86
+ """Test that we can iterate over all fonts."""
87
+ font_list = list(StandardFonts)
88
+ assert len(font_list) == 14
89
+ assert StandardFonts.TIMES_ROMAN in font_list
90
+ assert StandardFonts.HELVETICA in font_list
91
+ assert StandardFonts.COURIER in font_list
92
+ assert StandardFonts.SYMBOL in font_list
93
+ assert StandardFonts.ZAPF_DINGBATS in font_list
94
+
95
+ def test_font_enum_is_immutable(self):
96
+ """Test that font enum values cannot be modified."""
97
+ with pytest.raises(AttributeError):
98
+ StandardFonts.TIMES_ROMAN = "NewValue"
99
+
100
+ def test_times_family_count(self):
101
+ """Test that Times family has exactly 4 variants."""
102
+ times_fonts = [f for f in StandardFonts if f.value.startswith("Times")]
103
+ assert len(times_fonts) == 4
104
+
105
+ def test_helvetica_family_count(self):
106
+ """Test that Helvetica family has exactly 4 variants."""
107
+ helvetica_fonts = [f for f in StandardFonts if f.value.startswith("Helvetica")]
108
+ assert len(helvetica_fonts) == 4
109
+
110
+ def test_courier_family_count(self):
111
+ """Test that Courier family has exactly 4 variants."""
112
+ courier_fonts = [f for f in StandardFonts if f.value.startswith("Courier")]
113
+ assert len(courier_fonts) == 4
114
+
115
+ def test_symbol_family_count(self):
116
+ """Test that there are exactly 2 symbol fonts."""
117
+ symbol_fonts = [f for f in StandardFonts if f in [StandardFonts.SYMBOL, StandardFonts.ZAPF_DINGBATS]]
118
+ assert len(symbol_fonts) == 2
119
+
120
+ def test_font_value_string_representation(self):
121
+ """Test that font values are properly formatted strings."""
122
+ for font in StandardFonts:
123
+ assert isinstance(font.value, str)
124
+ assert len(font.value) > 0
125
+ # Font names should not contain spaces
126
+ assert " " not in font.value
127
+
128
+ def test_all_fonts_accessible(self):
129
+ """Test that all 14 fonts are accessible by their enum names."""
130
+ fonts = [
131
+ StandardFonts.TIMES_ROMAN,
132
+ StandardFonts.TIMES_BOLD,
133
+ StandardFonts.TIMES_ITALIC,
134
+ StandardFonts.TIMES_BOLD_ITALIC,
135
+ StandardFonts.HELVETICA,
136
+ StandardFonts.HELVETICA_BOLD,
137
+ StandardFonts.HELVETICA_OBLIQUE,
138
+ StandardFonts.HELVETICA_BOLD_OBLIQUE,
139
+ StandardFonts.COURIER,
140
+ StandardFonts.COURIER_BOLD,
141
+ StandardFonts.COURIER_OBLIQUE,
142
+ StandardFonts.COURIER_BOLD_OBLIQUE,
143
+ StandardFonts.SYMBOL,
144
+ StandardFonts.ZAPF_DINGBATS,
145
+ ]
146
+ assert len(fonts) == 14
147
+ assert len(set(fonts)) == 14 # All unique
148
+
149
+ def test_invalid_font_value_raises_error(self):
150
+ """Test that accessing an invalid font value raises ValueError."""
151
+ with pytest.raises(ValueError):
152
+ StandardFonts("InvalidFont")
153
+
154
+ def test_invalid_font_name_raises_error(self):
155
+ """Test that accessing an invalid font name raises KeyError."""
156
+ with pytest.raises(KeyError):
157
+ StandardFonts["INVALID_FONT"]
158
+
159
+ def test_font_comparison(self):
160
+ """Test that font comparison works correctly."""
161
+ assert StandardFonts.TIMES_ROMAN == StandardFonts.TIMES_ROMAN
162
+ assert StandardFonts.TIMES_ROMAN != StandardFonts.TIMES_BOLD
163
+ assert StandardFonts.HELVETICA == StandardFonts.HELVETICA
164
+ assert StandardFonts.COURIER != StandardFonts.TIMES_ROMAN
@@ -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