rgrid-python 4.5.3__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.
grid_py/_edit.py ADDED
@@ -0,0 +1,756 @@
1
+ """Display-list edit operations for grid_py (port of R's grid edit/get/set/add/remove).
2
+
3
+ This module provides the ``grid_*`` family of functions that operate on the
4
+ current display list, mirroring the R functions ``grid.edit``, ``grid.get``,
5
+ ``grid.set``, ``grid.add``, ``grid.remove``, and their ``grep``-defaulting
6
+ convenience aliases ``grid.gedit``, ``grid.gget``, ``grid.gremove``.
7
+
8
+ These functions locate grobs on the display list by :class:`~._path.GPath`
9
+ and apply modifications (edit attributes, replace, add children, or remove
10
+ grobs) with optional regex matching.
11
+
12
+ References
13
+ ----------
14
+ R source: ``src/library/grid/R/edit.R``, ``src/library/grid/R/grob.R``
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import copy
20
+ import re
21
+ import warnings
22
+ from typing import Any, Dict, List, Optional, Union
23
+
24
+ from ._grob import (
25
+ GEdit,
26
+ GEditList,
27
+ GList,
28
+ GTree,
29
+ Grob,
30
+ apply_edit,
31
+ apply_edits,
32
+ edit_grob,
33
+ is_grob,
34
+ )
35
+ from ._path import GPath
36
+ from ._display_list import DisplayList, DLDrawGrob
37
+ from ._state import get_state
38
+
39
+ __all__ = [
40
+ "grid_edit",
41
+ "grid_get",
42
+ "grid_set",
43
+ "grid_add",
44
+ "grid_remove",
45
+ "grid_gedit",
46
+ "grid_gget",
47
+ "grid_gremove",
48
+ ]
49
+
50
+
51
+ # ---------------------------------------------------------------------------
52
+ # Internal helpers
53
+ # ---------------------------------------------------------------------------
54
+
55
+
56
+ def _ensure_gpath(gpath: Union[str, GPath]) -> GPath:
57
+ """Convert *gpath* to a :class:`GPath` if it is a string.
58
+
59
+ Parameters
60
+ ----------
61
+ gpath : str or GPath
62
+ A grob path specification.
63
+
64
+ Returns
65
+ -------
66
+ GPath
67
+
68
+ Raises
69
+ ------
70
+ TypeError
71
+ If *gpath* is neither a string nor a :class:`GPath`.
72
+ """
73
+ if isinstance(gpath, str):
74
+ return GPath(gpath)
75
+ if isinstance(gpath, GPath):
76
+ return gpath
77
+ raise TypeError(f"invalid gPath: expected str or GPath, got {type(gpath).__name__}")
78
+
79
+
80
+ def _name_match(pattern: str, candidates: List[str], grep: bool) -> Optional[int]:
81
+ """Return the index (0-based) of the first matching candidate, or ``None``.
82
+
83
+ Parameters
84
+ ----------
85
+ pattern : str
86
+ The name or regex pattern to match.
87
+ candidates : list[str]
88
+ The candidate names to search.
89
+ grep : bool
90
+ If ``True``, use regex matching; otherwise, exact matching.
91
+
92
+ Returns
93
+ -------
94
+ int or None
95
+ The 0-based index of the first match, or ``None`` if no match.
96
+ """
97
+ for i, name in enumerate(candidates):
98
+ if grep:
99
+ if re.search(pattern, name):
100
+ return i
101
+ else:
102
+ if pattern == name:
103
+ return i
104
+ return None
105
+
106
+
107
+ def _find_dl_grobs(
108
+ dl: DisplayList,
109
+ gpath: GPath,
110
+ strict: bool,
111
+ grep: Union[bool, List[bool]],
112
+ global_: bool,
113
+ ) -> List[tuple]:
114
+ """Find grob(s) on the display list matching *gpath*.
115
+
116
+ Parameters
117
+ ----------
118
+ dl : DisplayList
119
+ The display list to search.
120
+ gpath : GPath
121
+ Path identifying the target grob(s).
122
+ strict : bool
123
+ If ``True``, the path must match exactly from the root of each grob.
124
+ grep : bool or list[bool]
125
+ Whether to use regex matching at each path level.
126
+ global_ : bool
127
+ If ``True``, find all matches; otherwise, stop at first match.
128
+
129
+ Returns
130
+ -------
131
+ list[tuple]
132
+ Each tuple is ``(dl_index, grob_reference)`` for a matching grob.
133
+ """
134
+ if isinstance(grep, bool):
135
+ grep_flags = [grep] * gpath.n
136
+ else:
137
+ grep_flags = list(grep)
138
+ while len(grep_flags) < gpath.n:
139
+ grep_flags.append(grep_flags[-1] if grep_flags else False)
140
+
141
+ matches: list[tuple] = []
142
+
143
+ for idx, item in enumerate(dl):
144
+ if not isinstance(item, DLDrawGrob) or item.grob is None:
145
+ continue
146
+ grob = item.grob
147
+ found = _match_grob_path(grob, gpath, strict, grep_flags)
148
+ if found is not None:
149
+ matches.append((idx, found))
150
+ if not global_:
151
+ break
152
+
153
+ return matches
154
+
155
+
156
+ def _match_grob_path(
157
+ grob: Any,
158
+ gpath: GPath,
159
+ strict: bool,
160
+ grep_flags: List[bool],
161
+ ) -> Optional[Any]:
162
+ """Attempt to match *gpath* against *grob* and its children.
163
+
164
+ Parameters
165
+ ----------
166
+ grob : Grob
167
+ The grob to match against.
168
+ gpath : GPath
169
+ The target path.
170
+ strict : bool
171
+ Require exact depth matching.
172
+ grep_flags : list[bool]
173
+ Per-level regex flags.
174
+
175
+ Returns
176
+ -------
177
+ Grob or None
178
+ The matched grob, or ``None`` if no match.
179
+ """
180
+ if not is_grob(grob):
181
+ return None
182
+
183
+ components = gpath.components
184
+
185
+ # Single-level path: match grob name directly
186
+ if len(components) == 1:
187
+ pattern = components[0]
188
+ use_grep = grep_flags[0]
189
+ if use_grep:
190
+ if re.search(pattern, grob.name):
191
+ return grob
192
+ else:
193
+ if pattern == grob.name:
194
+ return grob
195
+ # If not strict, search children recursively
196
+ if not strict and isinstance(grob, GTree):
197
+ for child_name in grob._children_order:
198
+ child = grob._children[child_name]
199
+ result = _match_grob_path(child, gpath, strict, grep_flags)
200
+ if result is not None:
201
+ return result
202
+ return None
203
+
204
+ # Multi-level path: first component must match this grob (or a descendant if not strict)
205
+ pattern = components[0]
206
+ use_grep = grep_flags[0]
207
+ rest_path = GPath(*components[1:])
208
+ rest_flags = grep_flags[1:]
209
+
210
+ matched_here = False
211
+ if use_grep:
212
+ matched_here = bool(re.search(pattern, grob.name))
213
+ else:
214
+ matched_here = pattern == grob.name
215
+
216
+ if matched_here and isinstance(grob, GTree):
217
+ for child_name in grob._children_order:
218
+ child = grob._children[child_name]
219
+ result = _match_grob_path(child, rest_path, strict, rest_flags)
220
+ if result is not None:
221
+ return result
222
+
223
+ # If not strict, skip this level and try children with the full path
224
+ if not strict and isinstance(grob, GTree):
225
+ for child_name in grob._children_order:
226
+ child = grob._children[child_name]
227
+ result = _match_grob_path(child, gpath, strict, grep_flags)
228
+ if result is not None:
229
+ return result
230
+
231
+ return None
232
+
233
+
234
+ def _redraw_display_list() -> None:
235
+ """Replay the display list to refresh the output.
236
+
237
+ Calls :meth:`DisplayList.replay` on the current state's display list.
238
+ """
239
+ state = get_state()
240
+ dl = state.display_list
241
+ if hasattr(dl, "replay"):
242
+ dl.replay(state)
243
+
244
+
245
+ # ---------------------------------------------------------------------------
246
+ # Public API -- grid.edit / grid.gedit
247
+ # ---------------------------------------------------------------------------
248
+
249
+
250
+ def grid_edit(
251
+ gPath: Union[str, GPath],
252
+ *,
253
+ strict: bool = False,
254
+ grep: bool = False,
255
+ global_: bool = False,
256
+ allDevices: bool = False,
257
+ redraw: bool = True,
258
+ **kwargs: Any,
259
+ ) -> None:
260
+ """Edit grob(s) on the display list matching *gPath*.
261
+
262
+ Locates grobs whose names match *gPath* on the current display list and
263
+ applies the attribute changes specified in *kwargs*. This is the Python
264
+ equivalent of R's ``grid.edit()``.
265
+
266
+ Parameters
267
+ ----------
268
+ gPath : str or GPath
269
+ A grob-path specification identifying the grob(s) to edit.
270
+ strict : bool, optional
271
+ If ``True``, the path must match exactly from the root.
272
+ grep : bool, optional
273
+ If ``True``, path components are treated as regex patterns.
274
+ global_ : bool, optional
275
+ If ``True``, edit *all* matching grobs; otherwise only the first.
276
+ allDevices : bool, optional
277
+ If ``True``, apply the edit to all open devices. Not yet
278
+ implemented -- raises :class:`NotImplementedError`.
279
+ redraw : bool, optional
280
+ If ``True`` (default), redraw after the edit.
281
+ **kwargs
282
+ Attribute name-value pairs to apply to the matched grob(s).
283
+
284
+ Raises
285
+ ------
286
+ NotImplementedError
287
+ If *allDevices* is ``True``.
288
+ TypeError
289
+ If *gPath* is invalid.
290
+ """
291
+ if allDevices:
292
+ raise NotImplementedError("allDevices is not yet implemented")
293
+
294
+ gpath = _ensure_gpath(gPath)
295
+
296
+ if not isinstance(grep, bool):
297
+ raise TypeError("invalid 'grep' value")
298
+ grep_flags = [grep] * gpath.n
299
+
300
+ state = get_state()
301
+ dl = state.display_list
302
+
303
+ matches = _find_dl_grobs(dl, gpath, strict, grep_flags, global_)
304
+ for dl_idx, matched_grob in matches:
305
+ for key, value in kwargs.items():
306
+ if hasattr(matched_grob, key) or hasattr(matched_grob, f"_{key}"):
307
+ setattr(matched_grob, key, value)
308
+ elif key == "gp":
309
+ matched_grob._gp = value
310
+ elif key == "name":
311
+ matched_grob._name = str(value) if value is not None else None
312
+ elif key == "vp":
313
+ matched_grob._vp = Grob._check_vp(value)
314
+ else:
315
+ warnings.warn(f"slot '{key}' not found on grob", stacklevel=2)
316
+
317
+ if redraw and matches:
318
+ _redraw_display_list()
319
+
320
+
321
+ def grid_gedit(
322
+ gPath: Union[str, GPath],
323
+ *,
324
+ strict: bool = False,
325
+ global_: bool = True,
326
+ allDevices: bool = False,
327
+ redraw: bool = True,
328
+ **kwargs: Any,
329
+ ) -> None:
330
+ """Edit grobs on the display list with ``grep=True`` (convenience alias).
331
+
332
+ This is the Python equivalent of R's ``grid.gedit()``, which is
333
+ ``grid.edit()`` with ``grep=True`` and ``global_=True`` as defaults.
334
+
335
+ Parameters
336
+ ----------
337
+ gPath : str or GPath
338
+ A grob-path specification (regex matching enabled).
339
+ strict : bool, optional
340
+ If ``True``, require exact depth matching.
341
+ global_ : bool, optional
342
+ If ``True`` (default), edit all matching grobs.
343
+ allDevices : bool, optional
344
+ Not yet implemented.
345
+ redraw : bool, optional
346
+ If ``True`` (default), redraw after the edit.
347
+ **kwargs
348
+ Attribute name-value pairs to apply.
349
+ """
350
+ grid_edit(
351
+ gPath,
352
+ strict=strict,
353
+ grep=True,
354
+ global_=global_,
355
+ allDevices=allDevices,
356
+ redraw=redraw,
357
+ **kwargs,
358
+ )
359
+
360
+
361
+ # ---------------------------------------------------------------------------
362
+ # Public API -- grid.get / grid.gget
363
+ # ---------------------------------------------------------------------------
364
+
365
+
366
+ def grid_get(
367
+ gPath: Union[str, GPath],
368
+ strict: bool = False,
369
+ grep: bool = False,
370
+ global_: bool = False,
371
+ allDevices: bool = False,
372
+ ) -> Union[Grob, List[Grob], None]:
373
+ """Get grob(s) from the display list matching *gPath*.
374
+
375
+ Returns the grob(s) whose names match *gPath*. This is the Python
376
+ equivalent of R's ``grid.get()``.
377
+
378
+ Parameters
379
+ ----------
380
+ gPath : str or GPath
381
+ A grob-path specification.
382
+ strict : bool, optional
383
+ If ``True``, require exact depth matching.
384
+ grep : bool, optional
385
+ If ``True``, use regex matching on path components.
386
+ global_ : bool, optional
387
+ If ``True``, return a list of all matching grobs; otherwise,
388
+ return the first match (or ``None``).
389
+ allDevices : bool, optional
390
+ Not yet implemented.
391
+
392
+ Returns
393
+ -------
394
+ Grob or list[Grob] or None
395
+ The matched grob(s). If *global_* is ``False``, a single
396
+ :class:`~._grob.Grob` or ``None``. If *global_* is ``True``,
397
+ a list (possibly empty).
398
+
399
+ Raises
400
+ ------
401
+ NotImplementedError
402
+ If *allDevices* is ``True``.
403
+ TypeError
404
+ If *gPath* is invalid or *grep* is not boolean.
405
+ """
406
+ if allDevices:
407
+ raise NotImplementedError("allDevices is not yet implemented")
408
+
409
+ gpath = _ensure_gpath(gPath)
410
+
411
+ if not isinstance(grep, bool):
412
+ raise TypeError("invalid 'grep' value")
413
+ grep_flags = [grep] * gpath.n
414
+
415
+ state = get_state()
416
+ dl = state.display_list
417
+
418
+ matches = _find_dl_grobs(dl, gpath, strict, grep_flags, global_)
419
+
420
+ if global_:
421
+ return [copy.deepcopy(m[1]) for m in matches]
422
+ if matches:
423
+ return copy.deepcopy(matches[0][1])
424
+ return None
425
+
426
+
427
+ def grid_gget(
428
+ gPath: Union[str, GPath],
429
+ strict: bool = False,
430
+ allDevices: bool = False,
431
+ ) -> Union[Grob, List[Grob], None]:
432
+ """Get grobs from the display list with ``grep=True`` (convenience alias).
433
+
434
+ This is the Python equivalent of R's ``grid.gget()``, which is
435
+ ``grid.get()`` with ``grep=True`` and ``global_=True`` as defaults.
436
+
437
+ Parameters
438
+ ----------
439
+ gPath : str or GPath
440
+ A grob-path specification (regex matching enabled).
441
+ strict : bool, optional
442
+ If ``True``, require exact depth matching.
443
+ allDevices : bool, optional
444
+ Not yet implemented.
445
+
446
+ Returns
447
+ -------
448
+ Grob or list[Grob] or None
449
+ The matched grob(s).
450
+ """
451
+ return grid_get(
452
+ gPath,
453
+ strict=strict,
454
+ grep=True,
455
+ global_=True,
456
+ allDevices=allDevices,
457
+ )
458
+
459
+
460
+ # ---------------------------------------------------------------------------
461
+ # Public API -- grid.set
462
+ # ---------------------------------------------------------------------------
463
+
464
+
465
+ def grid_set(
466
+ gPath: Union[str, GPath],
467
+ newGrob: Grob,
468
+ strict: bool = False,
469
+ grep: bool = False,
470
+ redraw: bool = True,
471
+ ) -> None:
472
+ """Set (replace) a grob on the display list.
473
+
474
+ Locates the first grob matching *gPath* on the display list and replaces
475
+ it with *newGrob*. This is the Python equivalent of R's ``grid.set()``.
476
+
477
+ Parameters
478
+ ----------
479
+ gPath : str or GPath
480
+ A grob-path specification identifying the grob to replace.
481
+ newGrob : Grob
482
+ The replacement grob.
483
+ strict : bool, optional
484
+ If ``True``, require exact depth matching.
485
+ grep : bool, optional
486
+ If ``True``, use regex matching on path components.
487
+ redraw : bool, optional
488
+ If ``True`` (default), redraw after the replacement.
489
+
490
+ Raises
491
+ ------
492
+ TypeError
493
+ If *gPath* is invalid or *grep* is not boolean.
494
+ ValueError
495
+ If *gPath* does not match any grob on the display list.
496
+ """
497
+ gpath = _ensure_gpath(gPath)
498
+
499
+ if not isinstance(grep, bool):
500
+ raise TypeError("invalid 'grep' value")
501
+ grep_flags = [grep] * gpath.n
502
+
503
+ state = get_state()
504
+ dl = state.display_list
505
+
506
+ matches = _find_dl_grobs(dl, gpath, strict, grep_flags, False)
507
+ if not matches:
508
+ raise ValueError("gPath does not specify a valid child")
509
+
510
+ dl_idx, _old = matches[0]
511
+ # Replace the grob in the display list item
512
+ item = dl[dl_idx]
513
+ if isinstance(item, DLDrawGrob):
514
+ item.grob = newGrob
515
+ item.params["grob"] = newGrob
516
+
517
+ if redraw:
518
+ _redraw_display_list()
519
+
520
+
521
+ # ---------------------------------------------------------------------------
522
+ # Public API -- grid.add
523
+ # ---------------------------------------------------------------------------
524
+
525
+
526
+ def grid_add(
527
+ grob: Grob,
528
+ gPath: Optional[Union[str, GPath]] = None,
529
+ strict: bool = False,
530
+ grep: bool = False,
531
+ global_: bool = False,
532
+ allDevices: bool = False,
533
+ redraw: bool = True,
534
+ ) -> None:
535
+ """Add a grob to a gTree on the display list.
536
+
537
+ If *gPath* is ``None``, *grob* is appended as a new top-level entry on
538
+ the display list. Otherwise, the grob is added as a child of the
539
+ gTree identified by *gPath*. This is the Python equivalent of R's
540
+ ``grid.add()``.
541
+
542
+ Parameters
543
+ ----------
544
+ grob : Grob
545
+ The grob to add.
546
+ gPath : str, GPath, or None, optional
547
+ Path to the parent gTree. ``None`` adds to the top level.
548
+ strict : bool, optional
549
+ If ``True``, require exact depth matching.
550
+ grep : bool, optional
551
+ If ``True``, use regex matching on path components.
552
+ global_ : bool, optional
553
+ If ``True``, add to all matching gTrees; otherwise only the first.
554
+ allDevices : bool, optional
555
+ Not yet implemented.
556
+ redraw : bool, optional
557
+ If ``True`` (default), redraw after the addition.
558
+
559
+ Raises
560
+ ------
561
+ NotImplementedError
562
+ If *allDevices* is ``True``.
563
+ TypeError
564
+ If *gPath* is invalid or *grep* is not boolean.
565
+ """
566
+ if allDevices:
567
+ raise NotImplementedError("allDevices is not yet implemented")
568
+
569
+ state = get_state()
570
+ dl = state.display_list
571
+
572
+ if gPath is None:
573
+ # Add as a new top-level entry
574
+ dl.record(DLDrawGrob(grob=grob))
575
+ else:
576
+ gpath = _ensure_gpath(gPath)
577
+ if not isinstance(grep, bool):
578
+ raise TypeError("invalid 'grep' value")
579
+ grep_flags = [grep] * gpath.n
580
+
581
+ matches = _find_dl_grobs(dl, gpath, strict, grep_flags, global_)
582
+ for _dl_idx, matched_grob in matches:
583
+ if isinstance(matched_grob, GTree):
584
+ matched_grob.add_child(grob)
585
+ else:
586
+ warnings.warn(
587
+ f"gPath matched a non-gTree grob '{matched_grob.name}'; "
588
+ "cannot add child",
589
+ stacklevel=2,
590
+ )
591
+
592
+ if redraw:
593
+ _redraw_display_list()
594
+
595
+
596
+ # ---------------------------------------------------------------------------
597
+ # Public API -- grid.remove / grid.gremove
598
+ # ---------------------------------------------------------------------------
599
+
600
+
601
+ def grid_remove(
602
+ gPath: Union[str, GPath],
603
+ warn: bool = True,
604
+ strict: bool = False,
605
+ grep: bool = False,
606
+ global_: bool = False,
607
+ allDevices: bool = False,
608
+ redraw: bool = True,
609
+ ) -> None:
610
+ """Remove grob(s) from the display list.
611
+
612
+ Locates grobs matching *gPath* and removes them. For single-component
613
+ paths the grob is removed directly from the display list. For
614
+ multi-component paths the leaf grob is removed from its parent gTree.
615
+ This is the Python equivalent of R's ``grid.remove()``.
616
+
617
+ Parameters
618
+ ----------
619
+ gPath : str or GPath
620
+ Path identifying the grob(s) to remove.
621
+ warn : bool, optional
622
+ If ``True`` (default), warn when the path does not match.
623
+ strict : bool, optional
624
+ If ``True``, require exact depth matching.
625
+ grep : bool, optional
626
+ If ``True``, use regex matching on path components.
627
+ global_ : bool, optional
628
+ If ``True``, remove all matching grobs; otherwise only the first.
629
+ allDevices : bool, optional
630
+ Not yet implemented.
631
+ redraw : bool, optional
632
+ If ``True`` (default), redraw after the removal.
633
+
634
+ Raises
635
+ ------
636
+ NotImplementedError
637
+ If *allDevices* is ``True``.
638
+ TypeError
639
+ If *gPath* is invalid or *grep* is not boolean.
640
+ """
641
+ if allDevices:
642
+ raise NotImplementedError("allDevices is not yet implemented")
643
+
644
+ gpath = _ensure_gpath(gPath)
645
+
646
+ if not isinstance(grep, bool):
647
+ raise TypeError("invalid 'grep' value")
648
+ grep_flags = [grep] * gpath.n
649
+
650
+ state = get_state()
651
+ dl = state.display_list
652
+
653
+ if gpath.n == 1:
654
+ # Remove directly from the display list
655
+ pattern = gpath.name
656
+ use_grep = grep_flags[0]
657
+ removed_any = False
658
+ items = dl.get_items()
659
+ indices_to_remove: list[int] = []
660
+
661
+ for idx, item in enumerate(items):
662
+ if not isinstance(item, DLDrawGrob) or item.grob is None:
663
+ continue
664
+ matched = False
665
+ if use_grep:
666
+ matched = bool(re.search(pattern, item.grob.name))
667
+ else:
668
+ matched = pattern == item.grob.name
669
+ if matched:
670
+ indices_to_remove.append(idx)
671
+ removed_any = True
672
+ if not global_:
673
+ break
674
+
675
+ # Remove in reverse order to preserve indices
676
+ for idx in reversed(indices_to_remove):
677
+ dl._items.pop(idx)
678
+
679
+ if not removed_any and warn:
680
+ warnings.warn(
681
+ f"gPath ({gpath}) not found on the display list",
682
+ stacklevel=2,
683
+ )
684
+ else:
685
+ # Multi-level: remove leaf from parent gTree
686
+ parent_path = GPath(*gpath.components[:-1])
687
+ leaf_name = gpath.name
688
+ leaf_grep = grep_flags[-1]
689
+ parent_grep_flags = grep_flags[:-1]
690
+
691
+ matches = _find_dl_grobs(dl, parent_path, strict, parent_grep_flags, global_)
692
+ removed_any = False
693
+
694
+ for _dl_idx, parent_grob in matches:
695
+ if not isinstance(parent_grob, GTree):
696
+ continue
697
+ # Find matching child(ren) to remove
698
+ names_to_remove: list[str] = []
699
+ for child_name in parent_grob._children_order:
700
+ if leaf_grep:
701
+ if re.search(leaf_name, child_name):
702
+ names_to_remove.append(child_name)
703
+ else:
704
+ if leaf_name == child_name:
705
+ names_to_remove.append(child_name)
706
+ if not global_ and names_to_remove:
707
+ break
708
+
709
+ for name in names_to_remove:
710
+ parent_grob.remove_child(name)
711
+ removed_any = True
712
+
713
+ if not removed_any and warn:
714
+ warnings.warn(
715
+ f"gPath ({gpath}) not found",
716
+ stacklevel=2,
717
+ )
718
+
719
+ if redraw:
720
+ _redraw_display_list()
721
+
722
+
723
+ def grid_gremove(
724
+ gPath: Union[str, GPath],
725
+ warn: bool = True,
726
+ strict: bool = False,
727
+ allDevices: bool = False,
728
+ redraw: bool = True,
729
+ ) -> None:
730
+ """Remove grobs with ``grep=True`` (convenience alias).
731
+
732
+ This is the Python equivalent of R's ``grid.gremove()``, which is
733
+ ``grid.remove()`` with ``grep=True`` and ``global_=True`` as defaults.
734
+
735
+ Parameters
736
+ ----------
737
+ gPath : str or GPath
738
+ Path identifying the grob(s) to remove (regex matching enabled).
739
+ warn : bool, optional
740
+ If ``True`` (default), warn when the path does not match.
741
+ strict : bool, optional
742
+ If ``True``, require exact depth matching.
743
+ allDevices : bool, optional
744
+ Not yet implemented.
745
+ redraw : bool, optional
746
+ If ``True`` (default), redraw after the removal.
747
+ """
748
+ grid_remove(
749
+ gPath,
750
+ warn=warn,
751
+ strict=strict,
752
+ grep=True,
753
+ global_=True,
754
+ allDevices=allDevices,
755
+ redraw=redraw,
756
+ )