pdfdancer-client-python 0.3.11__py3-none-any.whl → 0.3.12__py3-none-any.whl

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.
pdfdancer/__init__.py CHANGED
@@ -55,7 +55,7 @@ from .paragraph_builder import ParagraphBuilder
55
55
  from .path_builder import BezierBuilder, LineBuilder, PathBuilder
56
56
  from .text_line_builder import TextLineBuilder
57
57
 
58
- __version__ = "0.3.11"
58
+ __version__ = "0.3.12"
59
59
  __all__ = [
60
60
  "PDFDancer",
61
61
  "ParagraphBuilder",
pdfdancer/pdfdancer_v1.py CHANGED
@@ -134,7 +134,7 @@ DEFAULT_RETRY_BACKOFF_FACTOR = float(
134
134
 
135
135
 
136
136
  def _dict_to_replacements(
137
- replacements: Dict[str, Union[str, dict]]
137
+ replacements: Dict[str, Union[str, dict]],
138
138
  ) -> List[TemplateReplacement]:
139
139
  """Convert dict-based replacements to TemplateReplacement list."""
140
140
  result = []
@@ -2292,6 +2292,37 @@ class PDFDancer:
2292
2292
  targets = [RedactTarget(obj.internal_id, replacement) for obj in objects]
2293
2293
  return self._redact(targets, replacement, placeholder_color)
2294
2294
 
2295
+ def clear_clipping(self, object_ref: ObjectRef) -> bool:
2296
+ """
2297
+ Clear clipping on a single PDF object.
2298
+
2299
+ Args:
2300
+ object_ref: Reference to the object whose clipping should be removed
2301
+
2302
+ Returns:
2303
+ True when the server cleared clipping successfully
2304
+ """
2305
+ return self._clear_clipping(object_ref)
2306
+
2307
+ def _clear_clipping(self, object_ref: ObjectRef) -> bool:
2308
+ """
2309
+ Internal helper to clear clipping from a single object.
2310
+ """
2311
+ if object_ref is None:
2312
+ raise ValidationException("Object reference cannot be null")
2313
+
2314
+ response = self._make_request(
2315
+ "PUT",
2316
+ "/pdf/clipping/clear",
2317
+ data={"objectRef": object_ref.to_dict()},
2318
+ )
2319
+ result = bool(response.json())
2320
+
2321
+ if result:
2322
+ self._invalidate_snapshots()
2323
+
2324
+ return result
2325
+
2295
2326
  # Template Replacement Operations
2296
2327
 
2297
2328
  def _apply_replacements(
@@ -2506,19 +2537,21 @@ class PDFDancer:
2506
2537
  data["pathIds"] = path_ids
2507
2538
  if region is not None:
2508
2539
  data["region"] = {
2509
- "x": region.x, "y": region.y,
2510
- "width": region.width, "height": region.height,
2540
+ "x": region.x,
2541
+ "y": region.y,
2542
+ "width": region.width,
2543
+ "height": region.height,
2511
2544
  }
2512
- response = self._make_request(
2513
- "POST", "/pdf/path-group/create", data=data
2514
- )
2545
+ response = self._make_request("POST", "/pdf/path-group/create", data=data)
2515
2546
  self._invalidate_snapshots()
2516
2547
  return PathGroupInfo.from_dict(response.json())
2517
2548
 
2518
2549
  def _move_path_group(self, page_index, group_id, x, y):
2519
2550
  data = {
2520
- "pageIndex": page_index, "groupId": group_id,
2521
- "x": x, "y": y,
2551
+ "pageIndex": page_index,
2552
+ "groupId": group_id,
2553
+ "x": x,
2554
+ "y": y,
2522
2555
  }
2523
2556
  response = self._make_request("PUT", "/pdf/path-group/move", data=data)
2524
2557
  self._invalidate_snapshots()
@@ -2526,13 +2559,12 @@ class PDFDancer:
2526
2559
 
2527
2560
  def _transform_path_group(self, page_index, group_id, transform_type, **kwargs):
2528
2561
  data = {
2529
- "pageIndex": page_index, "groupId": group_id,
2562
+ "pageIndex": page_index,
2563
+ "groupId": group_id,
2530
2564
  "transformType": transform_type,
2531
2565
  }
2532
2566
  data.update({k: v for k, v in kwargs.items() if v is not None})
2533
- response = self._make_request(
2534
- "PUT", "/pdf/path-group/transform", data=data
2535
- )
2567
+ response = self._make_request("PUT", "/pdf/path-group/transform", data=data)
2536
2568
  self._invalidate_snapshots()
2537
2569
  return response.json()
2538
2570
 
@@ -2552,15 +2584,16 @@ class PDFDancer:
2552
2584
  if width <= 0 or height <= 0:
2553
2585
  raise ValidationException("Width and height must be positive")
2554
2586
  return self._transform_path_group(
2555
- page_index, group_id, "RESIZE",
2556
- targetWidth=width, targetHeight=height,
2587
+ page_index,
2588
+ group_id,
2589
+ "RESIZE",
2590
+ targetWidth=width,
2591
+ targetHeight=height,
2557
2592
  )
2558
2593
 
2559
2594
  def _remove_path_group(self, page_index, group_id):
2560
2595
  data = {"pageIndex": page_index, "groupId": group_id}
2561
- response = self._make_request(
2562
- "DELETE", "/pdf/path-group/remove", data=data
2563
- )
2596
+ response = self._make_request("DELETE", "/pdf/path-group/remove", data=data)
2564
2597
  self._invalidate_snapshots()
2565
2598
  return response.json()
2566
2599
 
@@ -2568,12 +2601,52 @@ class PDFDancer:
2568
2601
  from .models import PathGroupInfo
2569
2602
  from .types import PathGroupObject
2570
2603
 
2571
- response = self._make_request(
2572
- "GET", f"/pdf/page/{page_index}/path-groups"
2573
- )
2604
+ response = self._make_request("GET", f"/pdf/page/{page_index}/path-groups")
2574
2605
  infos = [PathGroupInfo.from_dict(d) for d in response.json()]
2575
2606
  return [PathGroupObject(self, page_index, info) for info in infos]
2576
2607
 
2608
+ def clear_path_group_clipping(self, page_number: int, group_id: str) -> bool:
2609
+ """
2610
+ Clear clipping for a grouped set of paths.
2611
+
2612
+ Args:
2613
+ page_number: 1-based page number containing the path group
2614
+ group_id: Identifier returned by `group_paths(...)`
2615
+
2616
+ Returns:
2617
+ True when the server cleared clipping successfully
2618
+ """
2619
+ return self._clear_path_group_clipping(page_number, group_id)
2620
+
2621
+ def _clear_path_group_clipping(self, page_number: int, group_id: str) -> bool:
2622
+ """
2623
+ Internal helper to clear clipping from a path group using the v1 API.
2624
+ """
2625
+ if page_number is None:
2626
+ raise ValidationException("page_number cannot be null")
2627
+ if not isinstance(page_number, int):
2628
+ raise ValidationException(
2629
+ f"page_number must be an integer, got {type(page_number)}"
2630
+ )
2631
+ if page_number < 1:
2632
+ raise ValidationException(
2633
+ f"page_number must be >= 1 (1-based indexing), got {page_number}"
2634
+ )
2635
+ if group_id is None or not str(group_id).strip():
2636
+ raise ValidationException("group_id cannot be null or empty")
2637
+
2638
+ response = self._make_request(
2639
+ "PUT",
2640
+ "/pdf/path-group/clipping/clear",
2641
+ data={"pageNumber": page_number, "groupId": str(group_id).strip()},
2642
+ )
2643
+ result = bool(response.json())
2644
+
2645
+ if result:
2646
+ self._invalidate_snapshots()
2647
+
2648
+ return result
2649
+
2577
2650
  def new_paragraph(self) -> ParagraphBuilder:
2578
2651
  return ParagraphBuilder(self)
2579
2652
 
pdfdancer/types.py CHANGED
@@ -65,6 +65,10 @@ class PDFObjectBase:
65
65
  Position.at_page_coordinates(self.position.page_number, x, y),
66
66
  )
67
67
 
68
+ def clear_clipping(self) -> bool:
69
+ """Detach any active clipping path from this object."""
70
+ return self._client.clear_clipping(self.object_ref())
71
+
68
72
  def redact(self, replacement: str = "[REDACTED]") -> bool:
69
73
  """Redact this object from the PDF document."""
70
74
  from .models import RedactTarget
@@ -329,21 +333,22 @@ class PathGroupObject:
329
333
  return True
330
334
 
331
335
  def rotate(self, degrees: float) -> bool:
332
- self._client._rotate_path_group(
333
- self._page_index, self.group_id, degrees
334
- )
336
+ self._client._rotate_path_group(self._page_index, self.group_id, degrees)
335
337
  return True
336
338
 
337
339
  def resize(self, width: float, height: float) -> bool:
338
- self._client._resize_path_group(
339
- self._page_index, self.group_id, width, height
340
- )
340
+ self._client._resize_path_group(self._page_index, self.group_id, width, height)
341
341
  return True
342
342
 
343
343
  def remove(self) -> bool:
344
344
  self._client._remove_path_group(self._page_index, self.group_id)
345
345
  return True
346
346
 
347
+ def clear_clipping(self) -> bool:
348
+ return self._client.clear_path_group_clipping(
349
+ self._page_index + 1, self.group_id
350
+ )
351
+
347
352
  def __repr__(self):
348
353
  return f"PathGroupObject(group_id={self.group_id!r}, path_count={self.path_count}, page_index={self._page_index})"
349
354
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pdfdancer-client-python
3
- Version: 0.3.11
3
+ Version: 0.3.12
4
4
  Summary: Python client for PDFDancer API
5
5
  Author-email: "The Famous Cat Ltd." <hi@thefamouscat.com>
6
6
  License:
@@ -359,7 +359,7 @@ with PDFDancer.open("contract.pdf") as pdf:
359
359
  ```
360
360
 
361
361
  Selectors return typed objects (`ParagraphObject`, `TextLineObject`, `ImageObject`, `FormFieldObject`, `PageClient`, …)
362
- with helpers such as `delete()`, `move_to(x, y)`, `redact()`, or `edit()` depending on the object type.
362
+ with helpers such as `delete()`, `move_to(x, y)`, `clear_clipping()`, `redact()`, or `edit()` depending on the object type.
363
363
 
364
364
  **Singular selection methods** return the first match (or `None`) for convenience:
365
365
 
@@ -1,4 +1,4 @@
1
- pdfdancer/__init__.py,sha256=qWqBV3h56VKzL7lzH9SZ-N09qNR-nwuBxpquBtswOKE,2884
1
+ pdfdancer/__init__.py,sha256=DiYQ2gDQ4kYu8eUXc7Z-0vgdoeBi0Cek5jusrq0LYVE,2884
2
2
  pdfdancer/exceptions.py,sha256=U6kD3NvcdNt05_OU11Tml5dXGtlodEtYC9zcV4fHXkc,2270
3
3
  pdfdancer/fingerprint.py,sha256=eL3PHPgv-knMya7s95RXg3qzzpkAA1aevxqb6tuOb34,3061
4
4
  pdfdancer/image_builder.py,sha256=aBxMFAMFzzbGTjlVH0hi94mA81cH8tp37Pk84HRPV00,1892
@@ -6,12 +6,12 @@ pdfdancer/models.py,sha256=nrR8ssEIz7BttWCMv7F0oriTego5Jh-h-34GvJmoni8,60462
6
6
  pdfdancer/page_builder.py,sha256=ARWLRtlrLGbES-0nbiigTOsRVmodRX0DNK8YIAkA9Ig,3850
7
7
  pdfdancer/paragraph_builder.py,sha256=OmhzYazMnq0n0rhrjWcKbo0LQfEC7BZoiLB29ycF630,20504
8
8
  pdfdancer/path_builder.py,sha256=safKb_IeHRWlQbyBTIXfcoBfXxUZhuzYvBIob5Tbp-8,23938
9
- pdfdancer/pdfdancer_v1.py,sha256=qGfgRG247wz-4i8H-jADvbl0vkKMlLdZdH-xVwOFIIY,135917
9
+ pdfdancer/pdfdancer_v1.py,sha256=JaiB47v_zgUwb7OtnmnVDt4jroxB5Bh6sGQpAU8ZIBg,138359
10
10
  pdfdancer/text_line_builder.py,sha256=8jYknV4hw0fyzwX0OI_oLvnh5aMmCV3jXaVkmYLu6MQ,10273
11
- pdfdancer/types.py,sha256=5AK8xmPhlvACy_HoF7DtHADy_praBHFmL2QnVwSgBVU,24676
12
- pdfdancer_client_python-0.3.11.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
13
- pdfdancer_client_python-0.3.11.dist-info/licenses/NOTICE,sha256=xaC4l-IChAmtViNDie8ZWzUk0O6XRMyzOl0zLmVZ2HE,232
14
- pdfdancer_client_python-0.3.11.dist-info/METADATA,sha256=ZF4o1QezR6BB7_xkUVMRoWnmKKt7JFH6PjLp4JpJBVw,28736
15
- pdfdancer_client_python-0.3.11.dist-info/WHEEL,sha256=YCfwYGOYMi5Jhw2fU4yNgwErybb2IX5PEwBKV4ZbdBo,91
16
- pdfdancer_client_python-0.3.11.dist-info/top_level.txt,sha256=ICwSVRpcCKrdBF9QlaX9Y0e_N3Nk1p7QVxadGOnbxeY,10
17
- pdfdancer_client_python-0.3.11.dist-info/RECORD,,
11
+ pdfdancer/types.py,sha256=w0dJ6JcHgm62BFDzZTx7v10GymjNaZw8x8lKfg-U2zA,24949
12
+ pdfdancer_client_python-0.3.12.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
13
+ pdfdancer_client_python-0.3.12.dist-info/licenses/NOTICE,sha256=xaC4l-IChAmtViNDie8ZWzUk0O6XRMyzOl0zLmVZ2HE,232
14
+ pdfdancer_client_python-0.3.12.dist-info/METADATA,sha256=8uO4RQWyE64otUm9cY_Vj9gZsBH5-JpajgDcvijv_JM,28756
15
+ pdfdancer_client_python-0.3.12.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
16
+ pdfdancer_client_python-0.3.12.dist-info/top_level.txt,sha256=ICwSVRpcCKrdBF9QlaX9Y0e_N3Nk1p7QVxadGOnbxeY,10
17
+ pdfdancer_client_python-0.3.12.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (82.0.0)
2
+ Generator: setuptools (82.0.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5