Skip to content

Commit e03c1a2

Browse files
export-form-data: Enumerate export formats, shore up test coverage
Assisted-by: Codex
1 parent 222f14e commit e03c1a2

4 files changed

Lines changed: 304 additions & 29 deletions

File tree

src/pdfrest/client.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2887,7 +2887,12 @@ def export_form_data(
28872887
extra_body: Body | None = None,
28882888
timeout: TimeoutTypes | None = None,
28892889
) -> PdfRestFileBasedResponse:
2890-
"""Export form data from a PDF with form fields to an external data file."""
2890+
"""Export form data from a PDF into an external data file.
2891+
2892+
`data_format` support depends on detected form type:
2893+
- AcroForm PDFs: `xfdf`, `fdf`, `xml`
2894+
- XFA PDFs: `xfd`, `xdp`, `xml`
2895+
"""
28912896

28922897
payload: dict[str, Any] = {
28932898
"files": file,
@@ -4647,7 +4652,12 @@ async def export_form_data(
46474652
extra_body: Body | None = None,
46484653
timeout: TimeoutTypes | None = None,
46494654
) -> PdfRestFileBasedResponse:
4650-
"""Asynchronously export form data from a PDF into a data file."""
4655+
"""Asynchronously export form data from a PDF into a data file.
4656+
4657+
`data_format` support depends on detected form type:
4658+
- AcroForm PDFs: `xfdf`, `fdf`, `xml`
4659+
- XFA PDFs: `xfd`, `xdp`, `xml`
4660+
"""
46514661

46524662
payload: dict[str, Any] = {
46534663
"files": file,

src/pdfrest/types/public.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,8 @@ class PdfMergeSource(TypedDict, total=False):
168168
JpegColorModel = Literal["rgb", "cmyk", "gray"]
169169
TiffColorModel = Literal["rgb", "rgba", "cmyk", "lab", "gray"]
170170
GraphicSmoothing = Literal["none", "all", "text", "line", "image"]
171+
# Server accepts all values here, but enforces form-type subsets at runtime:
172+
# AcroForm -> xfdf/fdf/xml, XFA -> xfd/xdp/xml.
171173
ExportDataFormat = Literal["fdf", "xfdf", "xml", "xdp", "xfd"]
172174

173175
SummaryFormat = Literal[

tests/live/test_live_export_form_data.py

Lines changed: 182 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
from pdfrest import AsyncPdfRestClient, PdfRestApiError, PdfRestClient
66
from pdfrest.models import PdfRestFile
7+
from pdfrest.types import ExportDataFormat
78

89
from ..resources import get_test_resource_path
910

@@ -24,84 +25,251 @@ def uploaded_pdf_with_forms(
2425
@pytest.mark.parametrize(
2526
"data_format",
2627
[
27-
pytest.param("xml", id="xml"),
28+
pytest.param("fdf", id="fdf"),
2829
pytest.param("xfdf", id="xfdf"),
30+
pytest.param("xml", id="xml"),
2931
],
3032
)
31-
def test_live_export_form_data(
33+
def test_live_export_form_data_acroform(
3234
pdfrest_api_key: str,
3335
pdfrest_live_base_url: str,
3436
uploaded_pdf_with_forms: PdfRestFile,
35-
data_format: str,
37+
data_format: ExportDataFormat,
3638
) -> None:
3739
with PdfRestClient(
3840
api_key=pdfrest_api_key,
3941
base_url=pdfrest_live_base_url,
4042
) as client:
4143
response = client.export_form_data(
4244
uploaded_pdf_with_forms,
43-
data_format=data_format, # type: ignore[arg-type]
45+
data_format=data_format,
4446
output=f"exported-{data_format}",
4547
)
4648

4749
assert response.output_files
4850
output_file = response.output_file
4951
assert output_file.name.startswith(f"exported-{data_format}")
50-
assert str(response.input_id) == str(uploaded_pdf_with_forms.id)
52+
assert output_file.type
53+
assert output_file.size > 0
54+
assert response.warning is None
55+
assert str(uploaded_pdf_with_forms.id) in {
56+
str(file_id) for file_id in response.input_ids
57+
}
58+
59+
60+
@pytest.fixture(scope="module")
61+
def uploaded_xfa_pdf(
62+
pdfrest_api_key: str,
63+
pdfrest_live_base_url: str,
64+
) -> PdfRestFile:
65+
resource = get_test_resource_path("xfa.pdf")
66+
with PdfRestClient(
67+
api_key=pdfrest_api_key,
68+
base_url=pdfrest_live_base_url,
69+
) as client:
70+
return client.files.create_from_paths([resource])[0]
71+
72+
73+
@pytest.mark.parametrize(
74+
"data_format",
75+
[
76+
pytest.param("xfd", id="xfd"),
77+
pytest.param("xdp", id="xdp"),
78+
pytest.param("xml", id="xml"),
79+
],
80+
)
81+
def test_live_export_form_data_xfa(
82+
pdfrest_api_key: str,
83+
pdfrest_live_base_url: str,
84+
uploaded_xfa_pdf: PdfRestFile,
85+
data_format: ExportDataFormat,
86+
) -> None:
87+
with PdfRestClient(
88+
api_key=pdfrest_api_key,
89+
base_url=pdfrest_live_base_url,
90+
) as client:
91+
response = client.export_form_data(
92+
uploaded_xfa_pdf,
93+
data_format=data_format,
94+
output=f"exported-xfa-{data_format}",
95+
)
96+
97+
assert response.output_files
98+
output_file = response.output_file
99+
assert output_file.name.startswith(f"exported-xfa-{data_format}")
100+
assert output_file.type
101+
assert output_file.size > 0
102+
assert response.warning is None
103+
assert str(uploaded_xfa_pdf.id) in {str(file_id) for file_id in response.input_ids}
51104

52105

53106
@pytest.mark.asyncio
54-
async def test_live_async_export_form_data_success(
107+
@pytest.mark.parametrize(
108+
"data_format",
109+
[
110+
pytest.param("fdf", id="fdf"),
111+
pytest.param("xfdf", id="xfdf"),
112+
pytest.param("xml", id="xml"),
113+
],
114+
)
115+
async def test_live_async_export_form_data_acroform(
55116
pdfrest_api_key: str,
56117
pdfrest_live_base_url: str,
57118
uploaded_pdf_with_forms: PdfRestFile,
119+
data_format: ExportDataFormat,
58120
) -> None:
59121
async with AsyncPdfRestClient(
60122
api_key=pdfrest_api_key,
61123
base_url=pdfrest_live_base_url,
62124
) as client:
63125
response = await client.export_form_data(
64126
uploaded_pdf_with_forms,
65-
data_format="xml",
66-
output="async-exported",
127+
data_format=data_format,
128+
output=f"async-acro-{data_format}",
129+
)
130+
131+
assert response.output_files
132+
output_file = response.output_file
133+
assert output_file.name.startswith(f"async-acro-{data_format}")
134+
assert output_file.type
135+
assert output_file.size > 0
136+
assert response.warning is None
137+
assert str(uploaded_pdf_with_forms.id) in {
138+
str(file_id) for file_id in response.input_ids
139+
}
140+
141+
142+
@pytest.mark.asyncio
143+
@pytest.mark.parametrize(
144+
"data_format",
145+
[
146+
pytest.param("xfd", id="xfd"),
147+
pytest.param("xdp", id="xdp"),
148+
pytest.param("xml", id="xml"),
149+
],
150+
)
151+
async def test_live_async_export_form_data_xfa(
152+
pdfrest_api_key: str,
153+
pdfrest_live_base_url: str,
154+
uploaded_xfa_pdf: PdfRestFile,
155+
data_format: ExportDataFormat,
156+
) -> None:
157+
async with AsyncPdfRestClient(
158+
api_key=pdfrest_api_key,
159+
base_url=pdfrest_live_base_url,
160+
) as client:
161+
response = await client.export_form_data(
162+
uploaded_xfa_pdf,
163+
data_format=data_format,
164+
output=f"async-xfa-{data_format}",
67165
)
68166

69167
assert response.output_files
70168
output_file = response.output_file
71-
assert output_file.name.startswith("async-exported")
72-
assert str(response.input_id) == str(uploaded_pdf_with_forms.id)
169+
assert output_file.name.startswith(f"async-xfa-{data_format}")
170+
assert output_file.type
171+
assert output_file.size > 0
172+
assert response.warning is None
173+
assert str(uploaded_xfa_pdf.id) in {str(file_id) for file_id in response.input_ids}
73174

74175

176+
@pytest.mark.parametrize(
177+
"invalid_format",
178+
[
179+
pytest.param("xdp", id="xdp"),
180+
pytest.param("xfd", id="xfd"),
181+
],
182+
)
75183
def test_live_export_form_data_invalid_format_for_pdf_type(
76184
pdfrest_api_key: str,
77185
pdfrest_live_base_url: str,
78186
uploaded_pdf_with_forms: PdfRestFile,
187+
invalid_format: ExportDataFormat,
79188
) -> None:
80189
with (
81190
PdfRestClient(
82191
api_key=pdfrest_api_key,
83192
base_url=pdfrest_live_base_url,
84193
) as client,
85-
pytest.raises(PdfRestApiError, match=r"(?i)data_format"),
194+
pytest.raises(PdfRestApiError, match=r"(?i)(acroform|data_format)"),
86195
):
87196
client.export_form_data(
88197
uploaded_pdf_with_forms,
89-
data_format="xdp", # type: ignore[arg-type]
198+
data_format=invalid_format,
90199
)
91200

92201

93202
@pytest.mark.asyncio
203+
@pytest.mark.parametrize(
204+
"invalid_format",
205+
[
206+
pytest.param("xdp", id="xdp"),
207+
pytest.param("xfd", id="xfd"),
208+
],
209+
)
94210
async def test_live_async_export_form_data_invalid_format_for_pdf_type(
95211
pdfrest_api_key: str,
96212
pdfrest_live_base_url: str,
97213
uploaded_pdf_with_forms: PdfRestFile,
214+
invalid_format: ExportDataFormat,
98215
) -> None:
99216
async with AsyncPdfRestClient(
100217
api_key=pdfrest_api_key,
101218
base_url=pdfrest_live_base_url,
102219
) as client:
103-
with pytest.raises(PdfRestApiError, match=r"(?i)data_format"):
220+
with pytest.raises(PdfRestApiError, match=r"(?i)(acroform|data_format)"):
104221
await client.export_form_data(
105222
uploaded_pdf_with_forms,
106-
data_format="xdp", # type: ignore[arg-type]
223+
data_format=invalid_format,
224+
)
225+
226+
227+
@pytest.mark.parametrize(
228+
"invalid_format",
229+
[
230+
pytest.param("xfdf", id="xfdf"),
231+
pytest.param("fdf", id="fdf"),
232+
],
233+
)
234+
def test_live_export_form_data_invalid_format_for_xfa(
235+
pdfrest_api_key: str,
236+
pdfrest_live_base_url: str,
237+
uploaded_xfa_pdf: PdfRestFile,
238+
invalid_format: ExportDataFormat,
239+
) -> None:
240+
with (
241+
PdfRestClient(
242+
api_key=pdfrest_api_key,
243+
base_url=pdfrest_live_base_url,
244+
) as client,
245+
pytest.raises(PdfRestApiError, match=r"(?i)(xfa|data_format)"),
246+
):
247+
client.export_form_data(
248+
uploaded_xfa_pdf,
249+
data_format=invalid_format,
250+
)
251+
252+
253+
@pytest.mark.asyncio
254+
@pytest.mark.parametrize(
255+
"invalid_format",
256+
[
257+
pytest.param("xfdf", id="xfdf"),
258+
pytest.param("fdf", id="fdf"),
259+
],
260+
)
261+
async def test_live_async_export_form_data_invalid_format_for_xfa(
262+
pdfrest_api_key: str,
263+
pdfrest_live_base_url: str,
264+
uploaded_xfa_pdf: PdfRestFile,
265+
invalid_format: ExportDataFormat,
266+
) -> None:
267+
async with AsyncPdfRestClient(
268+
api_key=pdfrest_api_key,
269+
base_url=pdfrest_live_base_url,
270+
) as client:
271+
with pytest.raises(PdfRestApiError, match=r"(?i)(xfa|data_format)"):
272+
await client.export_form_data(
273+
uploaded_xfa_pdf,
274+
data_format=invalid_format,
107275
)

0 commit comments

Comments
 (0)