PyPDFForm 5.2.5__tar.gz → 5.3.0__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.
Files changed (86) hide show
  1. {pypdfform-5.2.5 → pypdfform-5.3.0}/PKG-INFO +2 -1
  2. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/__init__.py +1 -1
  3. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/cli/common.py +43 -25
  4. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/cli/create.py +24 -15
  5. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/cli/entry.py +1 -1
  6. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/cli/root.py +10 -8
  7. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/cli/update.py +21 -18
  8. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm.egg-info/PKG-INFO +2 -1
  9. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm.egg-info/requires.txt +1 -0
  10. {pypdfform-5.2.5 → pypdfform-5.3.0}/pyproject.toml +5 -1
  11. {pypdfform-5.2.5 → pypdfform-5.3.0}/LICENSE +0 -0
  12. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/cli/__init__.py +0 -0
  13. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/cli/inspect.py +0 -0
  14. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/cli/remove.py +0 -0
  15. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/cli/schemas/__init__.py +0 -0
  16. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/cli/schemas/create.py +0 -0
  17. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/cli/schemas/update.py +0 -0
  18. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/__init__.py +0 -0
  19. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/adapter.py +0 -0
  20. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/annotations/__init__.py +0 -0
  21. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/annotations/base.py +0 -0
  22. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/annotations/link.py +0 -0
  23. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/annotations/stamp.py +0 -0
  24. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/annotations/text.py +0 -0
  25. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/annotations/text_markup.py +0 -0
  26. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/assets/__init__.py +0 -0
  27. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/assets/bedrock.py +0 -0
  28. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/assets/blank.py +0 -0
  29. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/constants.py +0 -0
  30. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/coordinate.py +0 -0
  31. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/deprecation.py +0 -0
  32. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/egress.py +0 -0
  33. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/filler.py +0 -0
  34. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/font.py +0 -0
  35. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/hooks.py +0 -0
  36. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/image.py +0 -0
  37. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/middleware/__init__.py +0 -0
  38. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/middleware/base.py +0 -0
  39. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/middleware/checkbox.py +0 -0
  40. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/middleware/dropdown.py +0 -0
  41. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/middleware/image.py +0 -0
  42. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/middleware/radio.py +0 -0
  43. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/middleware/signature.py +0 -0
  44. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/middleware/text.py +0 -0
  45. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/patterns.py +0 -0
  46. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/raw/__init__.py +0 -0
  47. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/raw/circle.py +0 -0
  48. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/raw/ellipse.py +0 -0
  49. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/raw/image.py +0 -0
  50. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/raw/line.py +0 -0
  51. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/raw/rect.py +0 -0
  52. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/raw/text.py +0 -0
  53. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/template.py +0 -0
  54. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/types.py +0 -0
  55. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/utils.py +0 -0
  56. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/watermark.py +0 -0
  57. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/widgets/__init__.py +0 -0
  58. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/widgets/base.py +0 -0
  59. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/widgets/checkbox.py +0 -0
  60. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/widgets/dropdown.py +0 -0
  61. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/widgets/image.py +0 -0
  62. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/widgets/radio.py +0 -0
  63. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/widgets/signature.py +0 -0
  64. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/widgets/text.py +0 -0
  65. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm/lib/wrapper.py +0 -0
  66. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm.egg-info/SOURCES.txt +0 -0
  67. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm.egg-info/dependency_links.txt +0 -0
  68. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm.egg-info/entry_points.txt +0 -0
  69. {pypdfform-5.2.5 → pypdfform-5.3.0}/PyPDFForm.egg-info/top_level.txt +0 -0
  70. {pypdfform-5.2.5 → pypdfform-5.3.0}/README.md +0 -0
  71. {pypdfform-5.2.5 → pypdfform-5.3.0}/setup.cfg +0 -0
  72. {pypdfform-5.2.5 → pypdfform-5.3.0}/tests/test_bulk_create_fields.py +0 -0
  73. {pypdfform-5.2.5 → pypdfform-5.3.0}/tests/test_create_widget.py +0 -0
  74. {pypdfform-5.2.5 → pypdfform-5.3.0}/tests/test_draw_elements.py +0 -0
  75. {pypdfform-5.2.5 → pypdfform-5.3.0}/tests/test_dropdown.py +0 -0
  76. {pypdfform-5.2.5 → pypdfform-5.3.0}/tests/test_extract_middleware_attributes.py +0 -0
  77. {pypdfform-5.2.5 → pypdfform-5.3.0}/tests/test_fill_max_length_text_field.py +0 -0
  78. {pypdfform-5.2.5 → pypdfform-5.3.0}/tests/test_font_widths.py +0 -0
  79. {pypdfform-5.2.5 → pypdfform-5.3.0}/tests/test_functional.py +0 -0
  80. {pypdfform-5.2.5 → pypdfform-5.3.0}/tests/test_generate_appearance_streams.py +0 -0
  81. {pypdfform-5.2.5 → pypdfform-5.3.0}/tests/test_js.py +0 -0
  82. {pypdfform-5.2.5 → pypdfform-5.3.0}/tests/test_need_appearances.py +0 -0
  83. {pypdfform-5.2.5 → pypdfform-5.3.0}/tests/test_paragraph.py +0 -0
  84. {pypdfform-5.2.5 → pypdfform-5.3.0}/tests/test_signature.py +0 -0
  85. {pypdfform-5.2.5 → pypdfform-5.3.0}/tests/test_use_full_widget_name.py +0 -0
  86. {pypdfform-5.2.5 → pypdfform-5.3.0}/tests/test_widget_attr_trigger.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyPDFForm
3
- Version: 5.2.5
3
+ Version: 5.3.0
4
4
  Summary: The Python library & CLI for PDF forms.
5
5
  Author: Jinge Li
6
6
  License-Expression: MIT
@@ -33,6 +33,7 @@ Requires-Dist: reportlab<6.0.0,>=4.5.1
33
33
  Provides-Extra: cli
34
34
  Requires-Dist: typer<1.0.0,>=0.26.1; extra == "cli"
35
35
  Requires-Dist: jsonschema<5.0.0,>=4.26.0; extra == "cli"
36
+ Requires-Dist: PyYAML<7.0.0,>=6.0.3; extra == "cli"
36
37
  Provides-Extra: dev
37
38
  Requires-Dist: coverage<8.0.0,>=7.14.1; extra == "dev"
38
39
  Requires-Dist: mike<3.0.0,>=2.2.0; extra == "dev"
@@ -18,7 +18,7 @@ from Python code or from the command line.
18
18
 
19
19
  import logging
20
20
 
21
- __version__ = "5.2.5"
21
+ __version__ = "5.3.0"
22
22
 
23
23
  from .lib.annotations import Annotations
24
24
  from .lib.assets.blank import BlankPage
@@ -2,8 +2,8 @@
2
2
  """
3
3
  This module provides shared helpers for PyPDFForm CLI commands.
4
4
 
5
- It contains utilities for loading JSON command input, registering custom fonts
6
- once per command invocation, and converting grouped JSON element definitions
5
+ It contains utilities for loading structured command input, registering custom
6
+ fonts once per command invocation, and converting grouped element definitions
7
7
  into the objects expected by `PdfWrapper` methods.
8
8
  """
9
9
 
@@ -12,6 +12,7 @@ from pathlib import Path
12
12
  from typing import Annotated, Any, NoReturn
13
13
 
14
14
  import typer
15
+ import yaml
15
16
  from jsonschema import ValidationError, validate
16
17
 
17
18
  from .. import PdfWrapper
@@ -62,15 +63,15 @@ FIELD_NAMES = Annotated[
62
63
  ]
63
64
 
64
65
 
65
- def json_file_option(help_text: str):
66
+ def data_file_option(help_text: str):
66
67
  """
67
- Creates the common validated JSON file option.
68
+ Creates the common validated structured data file option.
68
69
 
69
70
  Args:
70
71
  help_text (str): Help text to display for the option.
71
72
 
72
73
  Returns:
73
- typer.Option: A configured `--file` / `-f` option for JSON file input.
74
+ typer.Option: A configured `--file` / `-f` option for file input.
74
75
  """
75
76
  return typer.Option(
76
77
  "--file",
@@ -109,7 +110,7 @@ def cli_bad_parameter(
109
110
 
110
111
  def _validation_error_path(exc: ValidationError) -> str:
111
112
  """
112
- Builds a dotted JSON path for a validation error.
113
+ Builds a dotted input data path for a validation error.
113
114
 
114
115
  Args:
115
116
  exc (ValidationError): The JSON schema validation error.
@@ -120,28 +121,45 @@ def _validation_error_path(exc: ValidationError) -> str:
120
121
  return ".".join(str(each) for each in exc.absolute_path)
121
122
 
122
123
 
123
- def load_json_file(data: Path, schema: dict, param_hint: str) -> Any:
124
+ def _input_file_kind(data: Path) -> str:
124
125
  """
125
- Loads a JSON CLI input file and validates it against a schema.
126
+ Gets the structured data format to use for a CLI input file.
126
127
 
127
128
  Args:
128
- data (Path): JSON file path.
129
+ data (Path): Input file path.
130
+
131
+ Returns:
132
+ str: The upper-case format name for user-facing messages.
133
+ """
134
+ if data.suffix.lower() in {".yaml", ".yml"}:
135
+ return "YAML"
136
+
137
+ return "JSON"
138
+
139
+
140
+ def load_data_file(data: Path, schema: dict, param_hint: str) -> Any:
141
+ """
142
+ Loads a YAML or JSON CLI input file and validates it against a schema.
143
+
144
+ Args:
145
+ data (Path): YAML or JSON file path.
129
146
  schema (dict): JSON schema to validate against.
130
- param_hint (str): CLI parameter associated with the JSON file.
147
+ param_hint (str): CLI parameter associated with the input file.
131
148
 
132
149
  Returns:
133
- Any: Parsed and validated JSON input.
150
+ Any: Parsed and validated input data.
134
151
 
135
152
  Raises:
136
153
  typer.BadParameter: Raised when the file cannot be loaded or validation
137
154
  fails.
138
155
  """
156
+ input_kind = _input_file_kind(data)
139
157
  try:
140
158
  with open(data, "r", encoding="utf-8") as f:
141
- input_data = json.load(f)
142
- except (OSError, json.JSONDecodeError) as exc:
159
+ input_data = yaml.safe_load(f) if input_kind == "YAML" else json.load(f)
160
+ except (OSError, json.JSONDecodeError, yaml.YAMLError) as exc:
143
161
  cli_bad_parameter(
144
- f"Invalid JSON file: {exc}",
162
+ f"Invalid {input_kind} file: {exc}",
145
163
  param_hint=param_hint,
146
164
  cause=exc,
147
165
  )
@@ -152,7 +170,7 @@ def load_json_file(data: Path, schema: dict, param_hint: str) -> Any:
152
170
  error_path = _validation_error_path(exc)
153
171
  location = f" at {error_path}" if error_path else ""
154
172
  cli_bad_parameter(
155
- f"Invalid JSON file{location}: {exc.message}",
173
+ f"Invalid {input_kind} file{location}: {exc.message}",
156
174
  param_hint=param_hint,
157
175
  cause=exc,
158
176
  )
@@ -191,15 +209,15 @@ def handle_font_registration(
191
209
  """
192
210
  Registers a custom font referenced by CLI input.
193
211
 
194
- CLI JSON files may provide a file path in a `font` parameter. This helper
212
+ CLI input files may provide a file path in a `font` parameter. This helper
195
213
  registers each unique font path on the supplied `PdfWrapper` once, assigns
196
214
  it a generated internal font name, and mutates `params["font"]` to that
197
215
  registered name so downstream field or element constructors can use it.
198
216
 
199
217
  Args:
200
218
  obj (PdfWrapper): The wrapper for the PDF currently being modified.
201
- params (dict): The element or widget parameters loaded from JSON. This
202
- dictionary is mutated when it contains a `font` key.
219
+ params (dict): The element or widget parameters loaded from the input
220
+ file. This dictionary is mutated when it contains a `font` key.
203
221
  registered_font (dict): Mapping of source font paths to generated
204
222
  `PdfWrapper` font names for the current command invocation.
205
223
  """
@@ -222,9 +240,9 @@ def create_elements_from_file(
222
240
  output: Path | None = None,
223
241
  ) -> None:
224
242
  """
225
- Creates PDF elements from grouped JSON definitions.
243
+ Creates PDF elements from grouped file definitions.
226
244
 
227
- The input JSON is expected to group element definitions by type, such as
245
+ The input data is expected to group element definitions by type, such as
228
246
  `text`, `image`, or `highlight`. Each group key is resolved through
229
247
  `element_map`, each item is constructed after optional font registration,
230
248
  and the resulting objects are passed to `method_name` on `PdfWrapper`.
@@ -232,21 +250,21 @@ def create_elements_from_file(
232
250
 
233
251
  Args:
234
252
  pdf (Path): The path to the input PDF file.
235
- data (Path): The path to the JSON file containing grouped element
253
+ data (Path): The path to the input file containing grouped element
236
254
  definitions.
237
- element_map (dict): Mapping from JSON group names to element classes or
238
- callables used to construct each object.
255
+ element_map (dict): Mapping from input group names to element classes
256
+ or callables used to construct each object.
239
257
  schema (dict): JSON schema used to validate the grouped definitions.
240
258
  method_name (str): Name of the `PdfWrapper` method that accepts the
241
259
  constructed elements, such as `bulk_create_fields`, `draw`, or
242
260
  `annotate`.
243
261
  ctx (typer.Context): Typer context containing global wrapper options in
244
262
  `ctx.obj`.
245
- param_hint (str): CLI parameter associated with the JSON file.
263
+ param_hint (str): CLI parameter associated with the input file.
246
264
  output (Path, optional): Path where the modified PDF should be saved. If
247
265
  omitted, the input PDF is overwritten. Defaults to None.
248
266
  """
249
- input_data = load_json_file(data, schema, param_hint)
267
+ input_data = load_data_file(data, schema, param_hint)
250
268
 
251
269
  obj = PdfWrapper(str(pdf), **ctx.obj)
252
270
  ungrouped_input = []
@@ -4,8 +4,8 @@ This module defines CLI commands for creating PDF files and PDF content.
4
4
 
5
5
  It exposes the `create` command group for blank PDFs, extracted page ranges,
6
6
  merged PDFs, form fields, raw drawn elements, annotations, and coordinate grid
7
- views. Commands in this module translate command-line arguments or grouped JSON
8
- input into `PdfWrapper`, `BlankPage`, `Fields`, `RawElements`, and
7
+ views. Commands in this module translate command-line arguments or grouped
8
+ YAML/JSON input into `PdfWrapper`, `BlankPage`, `Fields`, `RawElements`, and
9
9
  `Annotations` operations.
10
10
  """
11
11
 
@@ -21,7 +21,7 @@ from .common import (
21
21
  REQUIRED_OUTPUT_PDF,
22
22
  cli_bad_parameter,
23
23
  create_elements_from_file,
24
- json_file_option,
24
+ data_file_option,
25
25
  )
26
26
  from .schemas.create import ANNOTATION_SCHEMA, FIELD_SCHEMA, RAW_SCHEMA
27
27
 
@@ -194,13 +194,15 @@ def merge(
194
194
  def field(
195
195
  ctx: typer.Context,
196
196
  pdf: INPUT_PDF,
197
- data: Annotated[Path, json_file_option("JSON file with form field definitions.")],
197
+ data: Annotated[
198
+ Path, data_file_option("YAML or JSON file with form field definitions.")
199
+ ],
198
200
  output: OPTIONAL_OUTPUT_PDF = None,
199
201
  ) -> None:
200
202
  """
201
- Add form fields described by grouped JSON definitions.
203
+ Add form fields described by grouped YAML or JSON definitions.
202
204
 
203
- The command maps JSON groups such as `text`, `check`, and `signature` to
205
+ The command maps input groups such as `text`, `check`, and `signature` to
204
206
  PyPDFForm field classes, validates the input file against the CLI field
205
207
  schema, creates the corresponding field objects, and calls
206
208
  `PdfWrapper.bulk_create_fields` before writing the modified PDF.
@@ -209,7 +211,8 @@ def field(
209
211
  ctx (typer.Context): Typer context containing global `PdfWrapper`
210
212
  options in `ctx.obj`.
211
213
  pdf (Path): Input PDF path.
212
- data (Path): JSON file containing grouped form field definitions.
214
+ data (Path): YAML or JSON file containing grouped form field
215
+ definitions.
213
216
  output (Path, optional): Output PDF path. If omitted, the input PDF is
214
217
  overwritten. Defaults to None.
215
218
  """
@@ -240,13 +243,15 @@ def field(
240
243
  def raw(
241
244
  ctx: typer.Context,
242
245
  pdf: INPUT_PDF,
243
- data: Annotated[Path, json_file_option("JSON file with raw element definitions.")],
246
+ data: Annotated[
247
+ Path, data_file_option("YAML or JSON file with raw element definitions.")
248
+ ],
244
249
  output: OPTIONAL_OUTPUT_PDF = None,
245
250
  ) -> None:
246
251
  """
247
- Draw raw elements described by grouped JSON definitions.
252
+ Draw raw elements described by grouped YAML or JSON definitions.
248
253
 
249
- The command maps JSON groups such as `text`, `image`, and `rectangle` to
254
+ The command maps input groups such as `text`, `image`, and `rectangle` to
250
255
  raw element classes, validates the input file against the CLI raw element
251
256
  schema, creates the corresponding drawable objects, and calls
252
257
  `PdfWrapper.draw` before writing the modified PDF.
@@ -255,7 +260,8 @@ def raw(
255
260
  ctx (typer.Context): Typer context containing global `PdfWrapper`
256
261
  options in `ctx.obj`.
257
262
  pdf (Path): Input PDF path.
258
- data (Path): JSON file containing grouped raw element definitions.
263
+ data (Path): YAML or JSON file containing grouped raw element
264
+ definitions.
259
265
  output (Path, optional): Output PDF path. If omitted, the input PDF is
260
266
  overwritten. Defaults to None.
261
267
  """
@@ -286,13 +292,15 @@ def raw(
286
292
  def annotation(
287
293
  ctx: typer.Context,
288
294
  pdf: INPUT_PDF,
289
- data: Annotated[Path, json_file_option("JSON file with annotation definitions.")],
295
+ data: Annotated[
296
+ Path, data_file_option("YAML or JSON file with annotation definitions.")
297
+ ],
290
298
  output: OPTIONAL_OUTPUT_PDF = None,
291
299
  ) -> None:
292
300
  """
293
- Add annotations described by grouped JSON definitions.
301
+ Add annotations described by grouped YAML or JSON definitions.
294
302
 
295
- The command maps JSON groups such as `text`, `link`, and `highlight` to
303
+ The command maps input groups such as `text`, `link`, and `highlight` to
296
304
  annotation classes, validates the input file against the CLI annotation
297
305
  schema, creates the corresponding annotation objects, and calls
298
306
  `PdfWrapper.annotate` before writing the modified PDF.
@@ -301,7 +309,8 @@ def annotation(
301
309
  ctx (typer.Context): Typer context containing global `PdfWrapper`
302
310
  options in `ctx.obj`.
303
311
  pdf (Path): Input PDF path.
304
- data (Path): JSON file containing grouped annotation definitions.
312
+ data (Path): YAML or JSON file containing grouped annotation
313
+ definitions.
305
314
  output (Path, optional): Output PDF path. If omitted, the input PDF is
306
315
  overwritten. Defaults to None.
307
316
  """
@@ -10,7 +10,7 @@ of an import traceback when those optional dependencies are absent.
10
10
  import importlib
11
11
  import sys
12
12
 
13
- CLI_DEPENDENCIES = {"jsonschema", "typer"}
13
+ CLI_DEPENDENCIES = {"jsonschema", "typer", "yaml"}
14
14
  CLI_INSTALL_HINT = 'pipx install "PyPDFForm[cli]"'
15
15
  CLI_ENV_INSTALL_HINT = "pip install 'PyPDFForm[cli]'"
16
16
 
@@ -8,7 +8,7 @@ commands. The root callback collects global flags in the Typer context so each
8
8
  subcommand can initialize `PdfWrapper` with consistent settings.
9
9
 
10
10
  Commands:
11
- - `fill`: Fill an existing PDF form from JSON data.
11
+ - `fill`: Fill an existing PDF form from YAML or JSON data.
12
12
  - `create`: Create PDFs, fields, annotations, raw elements, and grid views.
13
13
  - `inspect`: Print form metadata and field data as JSON.
14
14
  - `update`: Modify PDF metadata, field names, properties, geometry, and scripts.
@@ -21,7 +21,7 @@ from typing import Annotated
21
21
  import typer
22
22
 
23
23
  from .. import PdfWrapper, Widgets, __version__
24
- from .common import INPUT_PDF, OPTIONAL_OUTPUT_PDF, json_file_option, load_json_file
24
+ from .common import INPUT_PDF, OPTIONAL_OUTPUT_PDF, data_file_option, load_data_file
25
25
  from .create import create_cli
26
26
  from .inspect import inspect_cli
27
27
  from .remove import remove_cli
@@ -145,12 +145,14 @@ def main(
145
145
 
146
146
  @cli_app.command(
147
147
  no_args_is_help=True,
148
- help="Fill a PDF form with JSON data.",
148
+ help="Fill a PDF form with YAML or JSON data.",
149
149
  )
150
150
  def fill(
151
151
  ctx: typer.Context,
152
152
  pdf: INPUT_PDF,
153
- data: Annotated[Path, json_file_option("JSON file with form field values.")],
153
+ data: Annotated[
154
+ Path, data_file_option("YAML or JSON file with form field values.")
155
+ ],
154
156
  output: OPTIONAL_OUTPUT_PDF = None,
155
157
  flatten: Annotated[
156
158
  bool,
@@ -158,11 +160,11 @@ def fill(
158
160
  ] = None,
159
161
  ) -> None:
160
162
  """
161
- Fill an existing PDF form from a validated JSON file.
163
+ Fill an existing PDF form from a validated YAML or JSON file.
162
164
 
163
165
  The command loads the input PDF with the global options stored by the root
164
166
  callback, expands the generated schema so image and signature widgets can
165
- accept path objects, validates the JSON input, normalizes image and
167
+ accept path objects, validates the input file, normalizes image and
166
168
  signature values, and writes the filled PDF to the requested output path or
167
169
  back to the input file.
168
170
 
@@ -170,7 +172,7 @@ def fill(
170
172
  ctx (typer.Context): Typer context containing global `PdfWrapper`
171
173
  options in `ctx.obj`.
172
174
  pdf (Path): Input PDF form path.
173
- data (Path): JSON file containing form field values.
175
+ data (Path): YAML or JSON file containing form field values.
174
176
  output (Path, optional): Output PDF path. If omitted, the input PDF is
175
177
  overwritten. Defaults to None.
176
178
  flatten (bool, optional): Whether to flatten form fields after filling.
@@ -196,7 +198,7 @@ def fill(
196
198
  ]
197
199
  }
198
200
 
199
- input_data = load_json_file(data, schema, "--file")
201
+ input_data = load_data_file(data, schema, "--file")
200
202
  for k, each in obj.widgets.items():
201
203
  if (
202
204
  k in input_data
@@ -5,8 +5,8 @@ This module defines CLI commands for updating existing PDF files.
5
5
  It exposes the `update` command group for metadata changes, PDF version
6
6
  changes, field bounds edits, field renames, field property updates, and
7
7
  document-level JavaScript actions. Commands in this module load command-line or
8
- JSON input, apply the matching `PdfWrapper` operation, and write the modified
9
- PDF to either the requested output path or the original file.
8
+ YAML/JSON input, apply the matching `PdfWrapper` operation, and write the
9
+ modified PDF to either the requested output path or the original file.
10
10
  """
11
11
 
12
12
  from enum import Enum
@@ -22,10 +22,10 @@ from .common import (
22
22
  INPUT_PDF,
23
23
  OPTIONAL_OUTPUT_PDF,
24
24
  cli_bad_parameter,
25
+ data_file_option,
25
26
  get_widget,
26
27
  handle_font_registration,
27
- json_file_option,
28
- load_json_file,
28
+ load_data_file,
29
29
  )
30
30
  from .schemas.update import FIELD_SCHEMA, RENAME_SCHEMA
31
31
 
@@ -186,18 +186,20 @@ def bounds(
186
186
 
187
187
  @update_cli.command(
188
188
  no_args_is_help=True,
189
- help="Rename form fields from JSON.",
189
+ help="Rename form fields from YAML or JSON.",
190
190
  )
191
191
  def rename(
192
192
  ctx: typer.Context,
193
193
  pdf: INPUT_PDF,
194
- data: Annotated[Path, json_file_option("JSON file with form field renames.")],
194
+ data: Annotated[
195
+ Path, data_file_option("YAML or JSON file with form field renames.")
196
+ ],
195
197
  output: OPTIONAL_OUTPUT_PDF = None,
196
198
  ) -> None:
197
199
  """
198
- Rename form fields using a validated JSON mapping file.
200
+ Rename form fields using a validated YAML or JSON mapping file.
199
201
 
200
- The command rejects full widget name mode, validates the JSON file against
202
+ The command rejects full widget name mode, validates the input file against
201
203
  the rename schema, resolves each existing field, queues the requested key
202
204
  updates on the `PdfWrapper`, commits the rename operations, and writes the
203
205
  modified PDF to the requested output path or back to the input file.
@@ -206,13 +208,14 @@ def rename(
206
208
  ctx (typer.Context): Typer context containing global `PdfWrapper`
207
209
  options in `ctx.obj`.
208
210
  pdf (Path): Input PDF path.
209
- data (Path): JSON file containing form field rename definitions.
211
+ data (Path): YAML or JSON file containing form field rename
212
+ definitions.
210
213
  output (Path, optional): Output PDF path. If omitted, the input PDF is
211
214
  overwritten. Defaults to None.
212
215
 
213
216
  Raises:
214
217
  typer.BadParameter: Raised when full widget name mode is enabled, the
215
- JSON file is invalid, or a requested field does not exist.
218
+ input file is invalid, or a requested field does not exist.
216
219
  """
217
220
  if ctx.obj.get("use_full_widget_name"):
218
221
  cli_bad_parameter(
@@ -221,7 +224,7 @@ def rename(
221
224
  param_hint="--use-full-widget-name",
222
225
  )
223
226
 
224
- input_data = load_json_file(data, RENAME_SCHEMA, "--file")
227
+ input_data = load_data_file(data, RENAME_SCHEMA, "--file")
225
228
 
226
229
  obj = PdfWrapper(str(pdf), **ctx.obj)
227
230
  for item in input_data:
@@ -234,20 +237,20 @@ def rename(
234
237
 
235
238
  @update_cli.command(
236
239
  no_args_is_help=True,
237
- help="Update form field properties from JSON.",
240
+ help="Update form field properties from YAML or JSON.",
238
241
  )
239
242
  def field(
240
243
  ctx: typer.Context,
241
244
  pdf: INPUT_PDF,
242
245
  data: Annotated[
243
- Path, json_file_option("JSON file with form field property updates.")
246
+ Path, data_file_option("YAML or JSON file with form field property updates.")
244
247
  ],
245
248
  output: OPTIONAL_OUTPUT_PDF = None,
246
249
  ) -> None:
247
250
  """
248
- Update form field properties from a validated JSON file.
251
+ Update form field properties from a validated YAML or JSON file.
249
252
 
250
- The command validates the JSON input against the field update schema, loads
253
+ The command validates the input file against the field update schema, loads
251
254
  the PDF with the global CLI options stored in `ctx.obj`, resolves each
252
255
  field name, registers any referenced fonts once per invocation, assigns the
253
256
  requested widget properties, and writes the modified PDF to the requested
@@ -257,15 +260,15 @@ def field(
257
260
  ctx (typer.Context): Typer context containing global `PdfWrapper`
258
261
  options in `ctx.obj`.
259
262
  pdf (Path): Input PDF path.
260
- data (Path): JSON file containing form field property updates.
263
+ data (Path): YAML or JSON file containing form field property updates.
261
264
  output (Path, optional): Output PDF path. If omitted, the input PDF is
262
265
  overwritten. Defaults to None.
263
266
 
264
267
  Raises:
265
- typer.BadParameter: Raised when the JSON file is invalid or a requested
268
+ typer.BadParameter: Raised when the input file is invalid or a requested
266
269
  field does not exist.
267
270
  """
268
- input_data = load_json_file(data, FIELD_SCHEMA, "--file")
271
+ input_data = load_data_file(data, FIELD_SCHEMA, "--file")
269
272
 
270
273
  obj = PdfWrapper(str(pdf), **ctx.obj)
271
274
  registered_font = {}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyPDFForm
3
- Version: 5.2.5
3
+ Version: 5.3.0
4
4
  Summary: The Python library & CLI for PDF forms.
5
5
  Author: Jinge Li
6
6
  License-Expression: MIT
@@ -33,6 +33,7 @@ Requires-Dist: reportlab<6.0.0,>=4.5.1
33
33
  Provides-Extra: cli
34
34
  Requires-Dist: typer<1.0.0,>=0.26.1; extra == "cli"
35
35
  Requires-Dist: jsonschema<5.0.0,>=4.26.0; extra == "cli"
36
+ Requires-Dist: PyYAML<7.0.0,>=6.0.3; extra == "cli"
36
37
  Provides-Extra: dev
37
38
  Requires-Dist: coverage<8.0.0,>=7.14.1; extra == "dev"
38
39
  Requires-Dist: mike<3.0.0,>=2.2.0; extra == "dev"
@@ -8,6 +8,7 @@ reportlab<6.0.0,>=4.5.1
8
8
  [cli]
9
9
  typer<1.0.0,>=0.26.1
10
10
  jsonschema<5.0.0,>=4.26.0
11
+ PyYAML<7.0.0,>=6.0.3
11
12
 
12
13
  [dev]
13
14
  coverage<8.0.0,>=7.14.1
@@ -43,7 +43,11 @@ Documentation = "https://chinapandaman.github.io/PyPDFForm/"
43
43
 
44
44
  [project.optional-dependencies]
45
45
  # update `CLI_DEPENDENCIES` in `PyPDFForm/cli/entry.py` when changing cli dependencies
46
- cli = ["typer>=0.26.1,<1.0.0", "jsonschema>=4.26.0,<5.0.0"]
46
+ cli = [
47
+ "typer>=0.26.1,<1.0.0",
48
+ "jsonschema>=4.26.0,<5.0.0",
49
+ "PyYAML>=6.0.3,<7.0.0",
50
+ ]
47
51
  dev = [
48
52
  "coverage>=7.14.1,<8.0.0",
49
53
  "mike>=2.2.0,<3.0.0",
File without changes
File without changes
File without changes
File without changes