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.
- {pdfdancer_client_python-0.2.8/src/pdfdancer_client_python.egg-info → pdfdancer_client_python-0.2.10}/PKG-INFO +1 -1
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/pyproject.toml +1 -1
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/src/pdfdancer/__init__.py +2 -1
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/src/pdfdancer/models.py +43 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/src/pdfdancer/paragraph_builder.py +11 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/src/pdfdancer/pdfdancer_v1.py +4 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10/src/pdfdancer_client_python.egg-info}/PKG-INFO +1 -1
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/src/pdfdancer_client_python.egg-info/SOURCES.txt +1 -1
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/e2e/test_paragraph.py +59 -1
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/e2e/test_pdfdancer.py +1 -1
- pdfdancer_client_python-0.2.10/tests/test_standard_fonts.py +164 -0
- pdfdancer_client_python-0.2.8/tests/test_authentication.py +0 -36
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/.github/workflows/ci.yml +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/.gitignore +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/CLAUDE.md +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/README.md +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/docs/openapi.yml +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/release.py +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/requirements-dev.txt +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/requirements.txt +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/setup.cfg +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/src/pdfdancer/exceptions.py +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/src/pdfdancer/image_builder.py +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/src/pdfdancer/types.py +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/src/pdfdancer_client_python.egg-info/dependency_links.txt +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/src/pdfdancer_client_python.egg-info/requires.txt +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/src/pdfdancer_client_python.egg-info/top_level.txt +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/__init__.py +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/conftest.py +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/e2e/__init__.py +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/e2e/test_acroform.py +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/e2e/test_form_x_objects.py +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/e2e/test_image.py +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/e2e/test_line.py +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/e2e/test_page.py +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/e2e/test_path.py +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/fixtures/DancingScript-Regular.ttf +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/fixtures/JetBrainsMono-Regular.ttf +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/fixtures/ObviouslyAwesome.pdf +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/fixtures/basic-paths.pdf +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/fixtures/form-xobject-example.pdf +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/fixtures/logo-80.png +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/fixtures/mixed-form-types.pdf +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/test_models.py +0 -0
- {pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/test_openapi_compliance.py +0 -0
|
@@ -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"
|
{pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/src/pdfdancer/paragraph_builder.py
RENAMED
|
@@ -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)
|
{pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/src/pdfdancer/pdfdancer_v1.py
RENAMED
|
@@ -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
|
"""
|
|
@@ -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
|
{pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/e2e/test_paragraph.py
RENAMED
|
@@ -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
|
|
@@ -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
|
|
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.8 → pdfdancer_client_python-0.2.10}/src/pdfdancer/exceptions.py
RENAMED
|
File without changes
|
{pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/src/pdfdancer/image_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
|
|
File without changes
|
{pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/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
|
{pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/fixtures/ObviouslyAwesome.pdf
RENAMED
|
File without changes
|
{pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/fixtures/basic-paths.pdf
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/fixtures/mixed-form-types.pdf
RENAMED
|
File without changes
|
|
File without changes
|
{pdfdancer_client_python-0.2.8 → pdfdancer_client_python-0.2.10}/tests/test_openapi_compliance.py
RENAMED
|
File without changes
|