python-pptx2 2.17.0__py3-none-any.whl → 2.19.0__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.
- pptx2/__init__.py +1 -1
- pptx2/_agent_friendly.py +210 -0
- pptx2/diagrams.py +51 -0
- pptx2/shapes/shapetree.py +224 -46
- pptx2/skill/references/basics.md +13 -0
- {python_pptx2-2.17.0.dist-info → python_pptx2-2.19.0.dist-info}/METADATA +1 -1
- {python_pptx2-2.17.0.dist-info → python_pptx2-2.19.0.dist-info}/RECORD +11 -10
- {python_pptx2-2.17.0.dist-info → python_pptx2-2.19.0.dist-info}/WHEEL +0 -0
- {python_pptx2-2.17.0.dist-info → python_pptx2-2.19.0.dist-info}/entry_points.txt +0 -0
- {python_pptx2-2.17.0.dist-info → python_pptx2-2.19.0.dist-info}/licenses/LICENSE +0 -0
- {python_pptx2-2.17.0.dist-info → python_pptx2-2.19.0.dist-info}/top_level.txt +0 -0
pptx2/__init__.py
CHANGED
pptx2/_agent_friendly.py
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
"""Agent-friendly kwarg normalization for the one-call shape helpers.
|
|
2
|
+
|
|
3
|
+
Code generators (LLM-trained models among them) reliably spell keyword
|
|
4
|
+
arguments the way *other* libraries spell them — matplotlib's
|
|
5
|
+
``fontfamily``/``fontsize``/``ha``/``va``, CSS-flavored ``text-align``,
|
|
6
|
+
``colour`` — and die on ``TypeError: unexpected keyword argument``. This
|
|
7
|
+
module absorbs that whole error class for the ergonomic helpers
|
|
8
|
+
(``add_text`` / ``add_equation`` / ``add_arrow``) in three layers:
|
|
9
|
+
|
|
10
|
+
1. **Synonyms** — a fixed map from common spellings onto each canonical
|
|
11
|
+
argument (``halign`` → ``align``, ``font_size`` → ``size_pt`` …).
|
|
12
|
+
2. **Fuzzy matching** — a near-miss kwarg (``algn``, ``colr``) is resolved
|
|
13
|
+
to its closest canonical or synonym when unambiguous.
|
|
14
|
+
3. **Didactic errors** — anything still unknown raises a ``TypeError``
|
|
15
|
+
that names the closest candidate and lists every accepted kwarg, so a
|
|
16
|
+
model reading the traceback self-corrects in one step.
|
|
17
|
+
|
|
18
|
+
An alias may *substitute* for its canonical but never contradict it:
|
|
19
|
+
passing two different values for the same logical argument is a genuine
|
|
20
|
+
caller bug and still raises.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
import difflib
|
|
26
|
+
import functools
|
|
27
|
+
import inspect
|
|
28
|
+
|
|
29
|
+
# Canonical kwarg -> spellings other ecosystems use for the same thing.
|
|
30
|
+
SYNONYMS: dict[str, tuple[str, ...]] = {
|
|
31
|
+
"text": ("txt", "string", "content", "label", "caption", "value"),
|
|
32
|
+
"font": (
|
|
33
|
+
"font_family", "fontfamily", "font_name", "fontname", "typeface", "family", "face",
|
|
34
|
+
),
|
|
35
|
+
"size_pt": ("size", "font_size", "fontsize", "pt_size", "point_size"),
|
|
36
|
+
"align": ("halign", "ha", "horizontal_align", "horizontal_alignment", "text_align", "text_alignment"),
|
|
37
|
+
"anchor": ("valign", "va", "vertical_align", "vertical_alignment", "v_align"),
|
|
38
|
+
"color": (
|
|
39
|
+
"colour", "font_color", "font_colour", "text_color", "text_colour",
|
|
40
|
+
"fg_color", "line_color", "stroke_color",
|
|
41
|
+
),
|
|
42
|
+
"weight_pt": ("weight", "line_weight", "width_pt", "stroke_width"),
|
|
43
|
+
"bold": ("font_bold", "is_bold"),
|
|
44
|
+
"italic": ("font_italic", "is_italic", "oblique"),
|
|
45
|
+
"word_wrap": ("wrap", "wrap_text", "text_wrap"),
|
|
46
|
+
"margin_pt": ("margin", "padding", "padding_pt", "inset", "inset_pt"),
|
|
47
|
+
"latex": ("tex", "formula", "equation", "expression", "math"),
|
|
48
|
+
"left": ("x",),
|
|
49
|
+
"top": ("y",),
|
|
50
|
+
"width": ("w",),
|
|
51
|
+
"height": ("h",),
|
|
52
|
+
"start": ("begin", "start_point", "start_shape", "from", "source"),
|
|
53
|
+
"end": ("to", "end_point", "end_shape", "target"),
|
|
54
|
+
"image_file": ("image", "img", "path", "file", "filename", "image_path", "file_path"),
|
|
55
|
+
"steps": ("items", "stages", "nodes", "boxes"),
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
_ALIAS_TO_CANONICAL: dict[str, str] = {
|
|
59
|
+
alias: canonical
|
|
60
|
+
for canonical, aliases in SYNONYMS.items()
|
|
61
|
+
for alias in aliases
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
_FUZZY_CUTOFF = 0.85
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _did_you_mean(name: str, candidates: list[str], known: "list[str] | tuple[str, ...]") -> str | None:
|
|
68
|
+
"""Return the canonical arg *name* points at, or None.
|
|
69
|
+
|
|
70
|
+
Near-misses that hit both a canonical and one of its own aliases
|
|
71
|
+
(``algn`` → ``align`` and ``halign``) are NOT ambiguous — they agree —
|
|
72
|
+
so candidates are collapsed to their canonical form before the
|
|
73
|
+
ambiguity check.
|
|
74
|
+
"""
|
|
75
|
+
if not candidates:
|
|
76
|
+
return None
|
|
77
|
+
matches = difflib.get_close_matches(name, candidates, n=3, cutoff=_FUZZY_CUTOFF)
|
|
78
|
+
distinct = set()
|
|
79
|
+
for m in matches:
|
|
80
|
+
canonical = m if m in known else _ALIAS_TO_CANONICAL.get(m)
|
|
81
|
+
if canonical in known:
|
|
82
|
+
distinct.add(canonical)
|
|
83
|
+
if len(distinct) == 1:
|
|
84
|
+
return distinct.pop()
|
|
85
|
+
return None
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def absorb_agent_kwargs(
|
|
89
|
+
method: str,
|
|
90
|
+
kwargs: dict,
|
|
91
|
+
canonical_names: "list[str] | tuple[str, ...]",
|
|
92
|
+
extra_synonyms: "dict[str, tuple[str, ...]] | None" = None,
|
|
93
|
+
pass_through_unknown: bool = False,
|
|
94
|
+
) -> dict:
|
|
95
|
+
"""Map alias / near-miss *kwargs* onto canonical names; raise else.
|
|
96
|
+
|
|
97
|
+
*canonical_names* lists the kwargs the method actually understands
|
|
98
|
+
(including any already-bound explicit parameters). *extra_synonyms*
|
|
99
|
+
adds call-site-specific spellings (e.g. ``{"cx": ("width", "w")}``
|
|
100
|
+
for ``add_chart``). Returns a dict containing only canonical names
|
|
101
|
+
— unless *pass_through_unknown* is set (for functions that accept
|
|
102
|
+
``**kwargs`` themselves), in which case unabsorbable names are
|
|
103
|
+
passed through verbatim. A synonym that matches a canonical the
|
|
104
|
+
caller already supplied with a *different* value raises
|
|
105
|
+
``TypeError``; equal values are fine.
|
|
106
|
+
"""
|
|
107
|
+
known = list(canonical_names)
|
|
108
|
+
alias_map = dict(_ALIAS_TO_CANONICAL)
|
|
109
|
+
if extra_synonyms:
|
|
110
|
+
for canonical, aliases in extra_synonyms.items():
|
|
111
|
+
for alias in aliases:
|
|
112
|
+
alias_map[alias] = canonical
|
|
113
|
+
alias_space = [a for a in alias_map if a not in known]
|
|
114
|
+
candidates = known + alias_space
|
|
115
|
+
|
|
116
|
+
resolved: dict = {}
|
|
117
|
+
for name, value in kwargs.items():
|
|
118
|
+
if name in known or name in resolved:
|
|
119
|
+
if name in resolved and resolved[name] != value:
|
|
120
|
+
raise TypeError(
|
|
121
|
+
f"{method}(): got {name!r} twice with different values "
|
|
122
|
+
f"({resolved[name]!r} vs {value!r})"
|
|
123
|
+
)
|
|
124
|
+
resolved[name] = value
|
|
125
|
+
continue
|
|
126
|
+
canonical = alias_map.get(name)
|
|
127
|
+
if canonical is not None and canonical not in known:
|
|
128
|
+
# The alias resolves to an argument this method doesn't take
|
|
129
|
+
# (e.g. ``to=`` on add_text); fall through to the fuzzy/error
|
|
130
|
+
# path rather than silently dropping the value.
|
|
131
|
+
canonical = None
|
|
132
|
+
if canonical is None:
|
|
133
|
+
canonical = _did_you_mean(name, candidates, known)
|
|
134
|
+
if canonical is None:
|
|
135
|
+
if pass_through_unknown:
|
|
136
|
+
resolved[name] = value
|
|
137
|
+
continue
|
|
138
|
+
raise TypeError(
|
|
139
|
+
f"{method}(): got an unexpected keyword argument {name!r}. "
|
|
140
|
+
f"Accepted: {', '.join(sorted(known))} "
|
|
141
|
+
f"(synonyms like font_family/halign/valign/colour are fine)"
|
|
142
|
+
)
|
|
143
|
+
if canonical in resolved and resolved[canonical] != value:
|
|
144
|
+
raise TypeError(
|
|
145
|
+
f"{method}(): {name!r} and the value already given for "
|
|
146
|
+
f"{canonical!r} disagree ({value!r} vs {resolved[canonical]!r}); "
|
|
147
|
+
f"pass one spelling only"
|
|
148
|
+
)
|
|
149
|
+
resolved[canonical] = value
|
|
150
|
+
return resolved
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def agent_friendly(extra_synonyms=None):
|
|
154
|
+
"""Decorator: make a method/function absorb alias and fuzzy kwargs.
|
|
155
|
+
|
|
156
|
+
Wrap any public helper so its keyword arguments get the full
|
|
157
|
+
treatment from :func:`absorb_agent_kwargs` — global synonyms,
|
|
158
|
+
per-call *extra_synonyms*, fuzzy near-misses, and didactic errors —
|
|
159
|
+
without touching its body. Usable bare (``@agent_friendly``) or
|
|
160
|
+
with per-method synonyms. A keyword that repeats a value already
|
|
161
|
+
bound positionally (through a synonym or exact name) is dropped when
|
|
162
|
+
equal and raises ``TypeError`` when it contradicts::
|
|
163
|
+
|
|
164
|
+
@agent_friendly({"cx": ("width", "w"), "cy": ("height", "h")})
|
|
165
|
+
def add_chart(self, x, y, cx, cy, chart_type, chart_data): ...
|
|
166
|
+
"""
|
|
167
|
+
if callable(extra_synonyms): # used bare: @agent_friendly above def
|
|
168
|
+
return _decorate_friendly(extra_synonyms, None)
|
|
169
|
+
|
|
170
|
+
def decorator(func):
|
|
171
|
+
return _decorate_friendly(func, extra_synonyms)
|
|
172
|
+
|
|
173
|
+
return decorator
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def _decorate_friendly(func, extra_synonyms):
|
|
177
|
+
sig = inspect.signature(func)
|
|
178
|
+
has_self = bool(sig.parameters) and next(iter(sig.parameters)) in ("self", "cls")
|
|
179
|
+
param_list = [
|
|
180
|
+
p
|
|
181
|
+
for p in sig.parameters.values()
|
|
182
|
+
if p.kind not in (inspect.Parameter.VAR_POSITIONAL, inspect.Parameter.VAR_KEYWORD)
|
|
183
|
+
and p.name not in ("self", "cls")
|
|
184
|
+
]
|
|
185
|
+
known = tuple(p.name for p in param_list)
|
|
186
|
+
takes_var_kw = any(
|
|
187
|
+
p.kind == inspect.Parameter.VAR_KEYWORD for p in sig.parameters.values()
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
@functools.wraps(func)
|
|
191
|
+
def wrapper(*args, **kwargs):
|
|
192
|
+
if kwargs:
|
|
193
|
+
kwargs = absorb_agent_kwargs(
|
|
194
|
+
func.__name__, kwargs, known, extra_synonyms,
|
|
195
|
+
pass_through_unknown=takes_var_kw,
|
|
196
|
+
)
|
|
197
|
+
offset = 1 if has_self else 0
|
|
198
|
+
for i, p in enumerate(param_list[: len(args) - offset]):
|
|
199
|
+
if p.name in kwargs:
|
|
200
|
+
if kwargs[p.name] != args[offset + i]:
|
|
201
|
+
raise TypeError(
|
|
202
|
+
f"{func.__name__}(): {p.name} given positionally "
|
|
203
|
+
f"({args[offset + i]!r}) and by keyword "
|
|
204
|
+
f"({kwargs[p.name]!r}) with different values"
|
|
205
|
+
)
|
|
206
|
+
del kwargs[p.name]
|
|
207
|
+
return func(*args, **kwargs)
|
|
208
|
+
|
|
209
|
+
return wrapper
|
|
210
|
+
|
pptx2/diagrams.py
CHANGED
|
@@ -32,6 +32,7 @@ import math
|
|
|
32
32
|
from dataclasses import dataclass, field
|
|
33
33
|
from typing import TYPE_CHECKING, Any, Sequence
|
|
34
34
|
|
|
35
|
+
from pptx2._agent_friendly import agent_friendly
|
|
35
36
|
from pptx2.enum.shapes import MSO_SHAPE
|
|
36
37
|
from pptx2.geometry import BBox
|
|
37
38
|
from pptx2.util import Emu, Inches, Pt
|
|
@@ -245,6 +246,14 @@ def _card(
|
|
|
245
246
|
# ----------------------------------------------------------------------------- pipelines
|
|
246
247
|
|
|
247
248
|
|
|
249
|
+
@agent_friendly(
|
|
250
|
+
{
|
|
251
|
+
"text_color": ("color", "colour", "fg_color", "text_colour"),
|
|
252
|
+
"accent": ("accent_color", "primary", "primary_color"),
|
|
253
|
+
"fill": ("fill_color", "background", "bg"),
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
)
|
|
248
257
|
def horizontal_pipeline(
|
|
249
258
|
slide,
|
|
250
259
|
bbox: BBox,
|
|
@@ -312,6 +321,14 @@ def horizontal_pipeline(
|
|
|
312
321
|
return PipelineResult(cards=cards, arrows=arrows)
|
|
313
322
|
|
|
314
323
|
|
|
324
|
+
@agent_friendly(
|
|
325
|
+
{
|
|
326
|
+
"text_color": ("color", "colour", "fg_color", "text_colour"),
|
|
327
|
+
"accent": ("accent_color", "primary", "primary_color"),
|
|
328
|
+
"fill": ("fill_color", "background", "bg"),
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
)
|
|
315
332
|
def vertical_pipeline(
|
|
316
333
|
slide,
|
|
317
334
|
bbox: BBox,
|
|
@@ -371,6 +388,15 @@ def vertical_pipeline(
|
|
|
371
388
|
# ----------------------------------------------------------------------------- hub
|
|
372
389
|
|
|
373
390
|
|
|
391
|
+
@agent_friendly(
|
|
392
|
+
{
|
|
393
|
+
"text_color": ("color", "colour", "fg_color", "text_colour"),
|
|
394
|
+
"accent": ("accent_color", "primary", "primary_color"),
|
|
395
|
+
"fill": ("fill_color", "background", "bg"),
|
|
396
|
+
"spokes": ("items", "stages", "nodes"),
|
|
397
|
+
"centre": ("center", "hub", "hub_label", "title"),
|
|
398
|
+
}
|
|
399
|
+
)
|
|
374
400
|
def hub_and_spoke(
|
|
375
401
|
slide,
|
|
376
402
|
bbox: BBox,
|
|
@@ -479,6 +505,14 @@ def hub_and_spoke(
|
|
|
479
505
|
# ----------------------------------------------------------------------------- cycle
|
|
480
506
|
|
|
481
507
|
|
|
508
|
+
@agent_friendly(
|
|
509
|
+
{
|
|
510
|
+
"text_color": ("color", "colour", "fg_color", "text_colour"),
|
|
511
|
+
"accent": ("accent_color", "primary", "primary_color"),
|
|
512
|
+
"fill": ("fill_color", "background", "bg"),
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
)
|
|
482
516
|
def cycle(
|
|
483
517
|
slide,
|
|
484
518
|
bbox: BBox,
|
|
@@ -553,6 +587,15 @@ def cycle(
|
|
|
553
587
|
# ----------------------------------------------------------------------------- decision tree
|
|
554
588
|
|
|
555
589
|
|
|
590
|
+
@agent_friendly(
|
|
591
|
+
{
|
|
592
|
+
"text_color": ("color", "colour", "fg_color", "text_colour"),
|
|
593
|
+
"accent": ("accent_color", "primary", "primary_color"),
|
|
594
|
+
"fill": ("fill_color", "background", "bg"),
|
|
595
|
+
"branches": ("items", "nodes", "children", "steps"),
|
|
596
|
+
"root": ("root_label", "title", "center"),
|
|
597
|
+
}
|
|
598
|
+
)
|
|
556
599
|
def decision_tree(
|
|
557
600
|
slide,
|
|
558
601
|
bbox: BBox,
|
|
@@ -675,6 +718,14 @@ def decision_tree(
|
|
|
675
718
|
# ----------------------------------------------------------------------------- columns
|
|
676
719
|
|
|
677
720
|
|
|
721
|
+
@agent_friendly(
|
|
722
|
+
{
|
|
723
|
+
"text_color": ("color", "colour", "fg_color", "text_colour"),
|
|
724
|
+
"accent": ("accent_color", "primary", "primary_color"),
|
|
725
|
+
"fill": ("fill_color", "background", "bg"),
|
|
726
|
+
"columns": ("items", "cols", "sections"),
|
|
727
|
+
}
|
|
728
|
+
)
|
|
678
729
|
def comparison_columns(
|
|
679
730
|
slide,
|
|
680
731
|
bbox: BBox,
|
pptx2/shapes/shapetree.py
CHANGED
|
@@ -34,6 +34,7 @@ from pptx2.shapes.placeholder import (
|
|
|
34
34
|
TablePlaceholder,
|
|
35
35
|
)
|
|
36
36
|
from pptx2.shared import ParentedElementProxy
|
|
37
|
+
from pptx2._agent_friendly import agent_friendly
|
|
37
38
|
from pptx2.util import Emu, _coerce_emu, lazyproperty
|
|
38
39
|
|
|
39
40
|
if TYPE_CHECKING:
|
|
@@ -557,24 +558,6 @@ class _BaseShapes(ParentedElementProxy):
|
|
|
557
558
|
return BaseShapeFactory(shape_elm, self)
|
|
558
559
|
|
|
559
560
|
|
|
560
|
-
def _resolve_alias(method: str, arg: str, canonical, alias):
|
|
561
|
-
"""Return *canonical*, falling back to its *alias* kwarg (both nullable).
|
|
562
|
-
|
|
563
|
-
Code generators (matplotlib-trained models among them) habitually spell
|
|
564
|
-
``font`` as ``font_family`` and ``anchor`` as ``valign``; accepting the
|
|
565
|
-
alias removes a whole class of one-keyword-away TypeErrors. Passing
|
|
566
|
-
both with different values is a genuine caller bug and still raises.
|
|
567
|
-
"""
|
|
568
|
-
if canonical is not None:
|
|
569
|
-
if alias is not None and alias != canonical:
|
|
570
|
-
raise TypeError(
|
|
571
|
-
f"{method}(): pass either {arg}= or its alias, not two "
|
|
572
|
-
f"different values ({canonical!r} vs {alias!r})"
|
|
573
|
-
)
|
|
574
|
-
return canonical
|
|
575
|
-
return alias
|
|
576
|
-
|
|
577
|
-
|
|
578
561
|
class _BaseGroupShapes(_BaseShapes):
|
|
579
562
|
"""Base class for shape-trees that can add shapes."""
|
|
580
563
|
|
|
@@ -585,6 +568,7 @@ class _BaseGroupShapes(_BaseShapes):
|
|
|
585
568
|
super(_BaseGroupShapes, self).__init__(grpSp, parent)
|
|
586
569
|
self._grpSp = grpSp
|
|
587
570
|
|
|
571
|
+
@agent_friendly({"cx": ("width", "w"), "cy": ("height", "h"), "chart_data": ("data", "chartdata"), "chart_type": ("type", "charttype")})
|
|
588
572
|
def add_chart(
|
|
589
573
|
self,
|
|
590
574
|
chart_type: XL_CHART_TYPE,
|
|
@@ -619,6 +603,7 @@ class _BaseGroupShapes(_BaseShapes):
|
|
|
619
603
|
_apply_horizontal_bar_default(shape, chart_type)
|
|
620
604
|
return cast("Chart", shape)
|
|
621
605
|
|
|
606
|
+
@agent_friendly({"connector_type": ("type", "kind", "connector"), "begin_x": ("x1", "start_x"), "begin_y": ("y1", "start_y"), "end_x": ("x2", "to_x"), "end_y": ("y2", "to_y")})
|
|
622
607
|
def add_connector(
|
|
623
608
|
self,
|
|
624
609
|
connector_type: MSO_CONNECTOR_TYPE,
|
|
@@ -639,6 +624,7 @@ class _BaseGroupShapes(_BaseShapes):
|
|
|
639
624
|
self._recalculate_extents()
|
|
640
625
|
return cast(Connector, self._shape_factory(cxnSp))
|
|
641
626
|
|
|
627
|
+
@agent_friendly({"shapes": ("items", "members")})
|
|
642
628
|
def add_group_shape(self, shapes: Iterable[BaseShape] = ()) -> GroupShape:
|
|
643
629
|
"""Return a |GroupShape| object newly appended to this shape tree.
|
|
644
630
|
|
|
@@ -657,6 +643,7 @@ class _BaseGroupShapes(_BaseShapes):
|
|
|
657
643
|
grpSp.recalculate_extents()
|
|
658
644
|
return cast(GroupShape, self._shape_factory(grpSp))
|
|
659
645
|
|
|
646
|
+
@agent_friendly
|
|
660
647
|
def add_ole_object(
|
|
661
648
|
self,
|
|
662
649
|
object_file: str | IO[bytes],
|
|
@@ -718,6 +705,7 @@ class _BaseGroupShapes(_BaseShapes):
|
|
|
718
705
|
self._recalculate_extents()
|
|
719
706
|
return cast(GraphicFrame, self._shape_factory(graphicFrame))
|
|
720
707
|
|
|
708
|
+
@agent_friendly
|
|
721
709
|
def add_picture(
|
|
722
710
|
self,
|
|
723
711
|
image_file: str | os.PathLike[str] | IO[bytes],
|
|
@@ -780,6 +768,7 @@ class _BaseGroupShapes(_BaseShapes):
|
|
|
780
768
|
picture.top = Emu(ct + new_top)
|
|
781
769
|
return picture
|
|
782
770
|
|
|
771
|
+
@agent_friendly({"svg_file": ("svg", "svg_path", "svg_source")})
|
|
783
772
|
def add_svg_picture(
|
|
784
773
|
self,
|
|
785
774
|
svg_file,
|
|
@@ -843,6 +832,7 @@ class _BaseGroupShapes(_BaseShapes):
|
|
|
843
832
|
self._recalculate_extents()
|
|
844
833
|
return cast(Picture, self._shape_factory(pic))
|
|
845
834
|
|
|
835
|
+
@agent_friendly({"autoshape_type_id": ("shape_type", "autoshape_type", "shape", "preset_shape")})
|
|
846
836
|
def add_shape(
|
|
847
837
|
self,
|
|
848
838
|
autoshape_type_id: MSO_SHAPE,
|
|
@@ -881,6 +871,7 @@ class _BaseGroupShapes(_BaseShapes):
|
|
|
881
871
|
shape.top = Emu(ct + new_top)
|
|
882
872
|
return shape
|
|
883
873
|
|
|
874
|
+
@agent_friendly
|
|
884
875
|
def add_textbox(
|
|
885
876
|
self,
|
|
886
877
|
left: Length,
|
|
@@ -918,53 +909,115 @@ class _BaseGroupShapes(_BaseShapes):
|
|
|
918
909
|
*bbox_or_positional,
|
|
919
910
|
text: str = "",
|
|
920
911
|
font: str | None = None,
|
|
921
|
-
font_family: str | None = None,
|
|
922
912
|
size_pt: float | None = None,
|
|
923
913
|
bold: bool | None = None,
|
|
924
914
|
italic: bool | None = None,
|
|
925
915
|
color=None,
|
|
926
916
|
align: str | None = None,
|
|
927
917
|
anchor: str | None = None,
|
|
928
|
-
valign: str | None = None,
|
|
929
918
|
margin_pt: float | tuple[float, float, float, float] | None = None,
|
|
930
919
|
word_wrap: bool | None = True,
|
|
920
|
+
**kwargs,
|
|
931
921
|
) -> Shape:
|
|
932
922
|
"""Add a textbox carrying *text* with one-call styling.
|
|
933
923
|
|
|
934
|
-
Accepts either a :class:`~pptx2.geometry.BBox` positionally
|
|
935
|
-
|
|
924
|
+
Accepts either a :class:`~pptx2.geometry.BBox` positionally, the
|
|
925
|
+
four ``(left, top, width, height)`` lengths positionally, *or* the
|
|
926
|
+
same four as keyword arguments (``x`` / ``y`` / ``w`` / ``h``
|
|
927
|
+
synonyms included)::
|
|
936
928
|
|
|
937
929
|
slide.shapes.add_text(bbox, text="Hello", size_pt=24, bold=True,
|
|
938
930
|
color="#0B5CFF", align="center")
|
|
939
931
|
slide.shapes.add_text(Inches(1), Inches(2), Inches(4), Inches(1),
|
|
940
932
|
text="Hello")
|
|
933
|
+
slide.shapes.add_text(x=Inches(1), y=Inches(2), w=Inches(4),
|
|
934
|
+
h=Inches(1), text="Hello")
|
|
941
935
|
|
|
942
936
|
Keyword args:
|
|
943
937
|
|
|
938
|
+
* ``text`` — the string (``label`` / ``content`` synonyms work).
|
|
944
939
|
* ``font`` — typeface name (e.g. ``"Inter"``); ``None`` inherits.
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
* ``size_pt`` — font size in points; ``None`` inherits.
|
|
940
|
+
* ``size_pt`` — font size in points (synonyms: ``size``,
|
|
941
|
+
``font_size``, ``fontsize``).
|
|
948
942
|
* ``bold`` / ``italic`` — ``True``/``False``/``None``.
|
|
949
943
|
* ``color`` — any "color-like" (``"#RRGGBB"``, ``RGBColor``,
|
|
950
|
-
``(r, g, b)``).
|
|
944
|
+
``(r, g, b)``); ``colour`` / ``text_color`` synonyms work.
|
|
951
945
|
* ``align`` — ``"left"`` / ``"center"`` / ``"right"`` /
|
|
952
|
-
``"justify"``; ``
|
|
946
|
+
``"justify"``; ``halign`` is a synonym.
|
|
953
947
|
* ``anchor`` — vertical anchor: ``"top"`` / ``"middle"`` (also
|
|
954
|
-
``"mid"`` / ``"center"``) / ``"bottom"``; ``
|
|
955
|
-
|
|
948
|
+
``"mid"`` / ``"center"``) / ``"bottom"``; ``valign`` is a
|
|
949
|
+
synonym.
|
|
956
950
|
* ``margin_pt`` — uniform margin in points, or a 4-tuple
|
|
957
951
|
``(top, right, bottom, left)``.
|
|
958
952
|
* ``word_wrap`` — defaults to ``True``.
|
|
959
953
|
|
|
954
|
+
Misspelled or cross-library kwargs are absorbed when unambiguous
|
|
955
|
+
(``font_family`` → ``font``, ``fontsize`` → ``size_pt``, ``algn``
|
|
956
|
+
→ ``align`` …); anything unrecognizable raises a ``TypeError``
|
|
957
|
+
naming the accepted arguments.
|
|
958
|
+
|
|
960
959
|
Returns the textbox :class:`Shape` so further mutation works as
|
|
961
960
|
normal.
|
|
962
961
|
"""
|
|
962
|
+
from pptx2._agent_friendly import absorb_agent_kwargs
|
|
963
963
|
from pptx2._textstyle import apply_margins, apply_text_style, coerce_anchor
|
|
964
964
|
from pptx2.geometry import BBox
|
|
965
965
|
|
|
966
|
-
|
|
967
|
-
|
|
966
|
+
if kwargs:
|
|
967
|
+
kwargs = absorb_agent_kwargs(
|
|
968
|
+
"add_text",
|
|
969
|
+
kwargs,
|
|
970
|
+
(
|
|
971
|
+
"text", "font", "size_pt", "bold", "italic", "color",
|
|
972
|
+
"align", "anchor", "margin_pt", "word_wrap",
|
|
973
|
+
"left", "top", "width", "height",
|
|
974
|
+
),
|
|
975
|
+
)
|
|
976
|
+
geo_names = ("left", "top", "width", "height")
|
|
977
|
+
if any(g in kwargs for g in geo_names):
|
|
978
|
+
if bbox_or_positional:
|
|
979
|
+
raise TypeError(
|
|
980
|
+
"add_text(): got both positional geometry and geometry "
|
|
981
|
+
"keyword arguments; pass one form only"
|
|
982
|
+
)
|
|
983
|
+
if not all(g in kwargs for g in geo_names):
|
|
984
|
+
missing = [g for g in geo_names if g not in kwargs]
|
|
985
|
+
raise TypeError(
|
|
986
|
+
"add_text(): geometry keywords need all of "
|
|
987
|
+
f"left/top/width/height; missing {', '.join(missing)}"
|
|
988
|
+
)
|
|
989
|
+
bbox_or_positional = tuple(kwargs[g] for g in geo_names)
|
|
990
|
+
defaults = {
|
|
991
|
+
"text": "", "font": None, "size_pt": None, "bold": None,
|
|
992
|
+
"italic": None, "color": None, "align": None, "anchor": None,
|
|
993
|
+
"margin_pt": None, "word_wrap": True,
|
|
994
|
+
}
|
|
995
|
+
given = {
|
|
996
|
+
"text": text, "font": font, "size_pt": size_pt, "bold": bold,
|
|
997
|
+
"italic": italic, "color": color, "align": align,
|
|
998
|
+
"anchor": anchor, "margin_pt": margin_pt,
|
|
999
|
+
"word_wrap": word_wrap,
|
|
1000
|
+
}
|
|
1001
|
+
for name in defaults:
|
|
1002
|
+
if name not in kwargs:
|
|
1003
|
+
continue
|
|
1004
|
+
value = kwargs[name]
|
|
1005
|
+
if given[name] != defaults[name] and given[name] != value:
|
|
1006
|
+
raise TypeError(
|
|
1007
|
+
f"add_text(): {name!r} given twice with different "
|
|
1008
|
+
f"values ({given[name]!r} vs {value!r})"
|
|
1009
|
+
)
|
|
1010
|
+
given[name] = value
|
|
1011
|
+
text = given["text"]
|
|
1012
|
+
font = given["font"]
|
|
1013
|
+
size_pt = given["size_pt"]
|
|
1014
|
+
bold = given["bold"]
|
|
1015
|
+
italic = given["italic"]
|
|
1016
|
+
color = given["color"]
|
|
1017
|
+
align = given["align"]
|
|
1018
|
+
anchor = given["anchor"]
|
|
1019
|
+
margin_pt = given["margin_pt"]
|
|
1020
|
+
word_wrap = given["word_wrap"]
|
|
968
1021
|
|
|
969
1022
|
if len(bbox_or_positional) == 1 and isinstance(bbox_or_positional[0], BBox):
|
|
970
1023
|
box = bbox_or_positional[0]
|
|
@@ -1009,21 +1062,21 @@ class _BaseGroupShapes(_BaseShapes):
|
|
|
1009
1062
|
def add_equation(
|
|
1010
1063
|
self,
|
|
1011
1064
|
*bbox_or_positional,
|
|
1012
|
-
latex: str,
|
|
1065
|
+
latex: str | None = None,
|
|
1013
1066
|
display: bool = True,
|
|
1014
1067
|
font: str | None = None,
|
|
1015
|
-
font_family: str | None = None,
|
|
1016
1068
|
size_pt: float | None = None,
|
|
1017
1069
|
color=None,
|
|
1018
1070
|
align: str | None = "center",
|
|
1019
1071
|
anchor: str | None = "middle",
|
|
1020
|
-
valign: str | None = None,
|
|
1021
1072
|
margin_pt: float | tuple[float, float, float, float] | None = None,
|
|
1073
|
+
**kwargs,
|
|
1022
1074
|
) -> Shape:
|
|
1023
1075
|
"""Add a text box containing a native PowerPoint equation from LaTeX.
|
|
1024
1076
|
|
|
1025
|
-
Accepts either a :class:`~pptx2.geometry.BBox
|
|
1026
|
-
``(left, top, width, height)
|
|
1077
|
+
Accepts either a :class:`~pptx2.geometry.BBox`, the four
|
|
1078
|
+
``(left, top, width, height)`` lengths positionally, or the same
|
|
1079
|
+
four as keyword arguments (``x`` / ``y`` / ``w`` / ``h`` included)::
|
|
1027
1080
|
|
|
1028
1081
|
slide.shapes.add_equation(bbox, latex=r"\\frac{a}{b}", size_pt=28)
|
|
1029
1082
|
slide.shapes.add_equation(
|
|
@@ -1036,16 +1089,74 @@ class _BaseGroupShapes(_BaseShapes):
|
|
|
1036
1089
|
equation editor.
|
|
1037
1090
|
|
|
1038
1091
|
Keyword args match :meth:`add_text` for *font* / *size_pt* /
|
|
1039
|
-
*color* / *align* / *anchor* / *margin_pt*
|
|
1040
|
-
``
|
|
1041
|
-
|
|
1042
|
-
|
|
1092
|
+
*color* / *align* / *anchor* / *margin_pt*, and *latex* accepts
|
|
1093
|
+
the ``tex`` / ``formula`` / ``equation`` synonyms. Misspelled or
|
|
1094
|
+
cross-library kwargs are absorbed when unambiguous (see
|
|
1095
|
+
:meth:`add_text`). *display* (default |True|) emits a display-math
|
|
1096
|
+
paragraph; set |False| for inline OMML.
|
|
1043
1097
|
"""
|
|
1098
|
+
from pptx2._agent_friendly import absorb_agent_kwargs
|
|
1044
1099
|
from pptx2._textstyle import apply_margins, coerce_align, coerce_anchor
|
|
1045
1100
|
from pptx2.geometry import BBox
|
|
1046
1101
|
|
|
1047
|
-
|
|
1048
|
-
|
|
1102
|
+
if kwargs:
|
|
1103
|
+
kwargs = absorb_agent_kwargs(
|
|
1104
|
+
"add_equation",
|
|
1105
|
+
kwargs,
|
|
1106
|
+
(
|
|
1107
|
+
"latex", "display", "font", "size_pt", "color", "align",
|
|
1108
|
+
"anchor", "margin_pt", "left", "top", "width", "height",
|
|
1109
|
+
),
|
|
1110
|
+
)
|
|
1111
|
+
geo_names = ("left", "top", "width", "height")
|
|
1112
|
+
if any(g in kwargs for g in geo_names):
|
|
1113
|
+
if bbox_or_positional:
|
|
1114
|
+
raise TypeError(
|
|
1115
|
+
"add_equation(): got both positional geometry and "
|
|
1116
|
+
"geometry keyword arguments; pass one form only"
|
|
1117
|
+
)
|
|
1118
|
+
if not all(g in kwargs for g in geo_names):
|
|
1119
|
+
missing = [g for g in geo_names if g not in kwargs]
|
|
1120
|
+
raise TypeError(
|
|
1121
|
+
"add_equation(): geometry keywords need all of "
|
|
1122
|
+
f"left/top/width/height; missing {', '.join(missing)}"
|
|
1123
|
+
)
|
|
1124
|
+
bbox_or_positional = tuple(kwargs[g] for g in geo_names)
|
|
1125
|
+
defaults = {
|
|
1126
|
+
"latex": None, "display": True, "font": None, "size_pt": None,
|
|
1127
|
+
"color": None, "align": "center", "anchor": "middle",
|
|
1128
|
+
"margin_pt": None,
|
|
1129
|
+
}
|
|
1130
|
+
given = {
|
|
1131
|
+
"latex": latex, "display": display, "font": font,
|
|
1132
|
+
"size_pt": size_pt, "color": color, "align": align,
|
|
1133
|
+
"anchor": anchor, "margin_pt": margin_pt,
|
|
1134
|
+
}
|
|
1135
|
+
for name in defaults:
|
|
1136
|
+
if name not in kwargs:
|
|
1137
|
+
continue
|
|
1138
|
+
value = kwargs[name]
|
|
1139
|
+
if given[name] != defaults[name] and given[name] != value:
|
|
1140
|
+
raise TypeError(
|
|
1141
|
+
f"add_equation(): {name!r} given twice with different "
|
|
1142
|
+
f"values ({given[name]!r} vs {value!r})"
|
|
1143
|
+
)
|
|
1144
|
+
given[name] = value
|
|
1145
|
+
latex = given["latex"]
|
|
1146
|
+
display = given["display"]
|
|
1147
|
+
font = given["font"]
|
|
1148
|
+
size_pt = given["size_pt"]
|
|
1149
|
+
color = given["color"]
|
|
1150
|
+
align = given["align"]
|
|
1151
|
+
anchor = given["anchor"]
|
|
1152
|
+
margin_pt = given["margin_pt"]
|
|
1153
|
+
|
|
1154
|
+
if latex is None:
|
|
1155
|
+
raise TypeError(
|
|
1156
|
+
"add_equation() missing required argument: 'latex' "
|
|
1157
|
+
"(synonyms 'tex' / 'formula' / 'equation' accepted)"
|
|
1158
|
+
)
|
|
1159
|
+
|
|
1049
1160
|
|
|
1050
1161
|
if len(bbox_or_positional) == 1 and isinstance(bbox_or_positional[0], BBox):
|
|
1051
1162
|
box = bbox_or_positional[0]
|
|
@@ -1080,8 +1191,8 @@ class _BaseGroupShapes(_BaseShapes):
|
|
|
1080
1191
|
|
|
1081
1192
|
def add_arrow(
|
|
1082
1193
|
self,
|
|
1083
|
-
start,
|
|
1084
|
-
end,
|
|
1194
|
+
start=None,
|
|
1195
|
+
end=None,
|
|
1085
1196
|
*,
|
|
1086
1197
|
head: str | None = "triangle",
|
|
1087
1198
|
tail: str | None = None,
|
|
@@ -1094,6 +1205,7 @@ class _BaseGroupShapes(_BaseShapes):
|
|
|
1094
1205
|
inset_pt: float = 0.0,
|
|
1095
1206
|
end_side: str = "auto",
|
|
1096
1207
|
start_side: str = "auto",
|
|
1208
|
+
**kwargs,
|
|
1097
1209
|
) -> Connector:
|
|
1098
1210
|
"""Add an arrow connector with proper arrowhead and inset routing.
|
|
1099
1211
|
|
|
@@ -1116,12 +1228,18 @@ class _BaseGroupShapes(_BaseShapes):
|
|
|
1116
1228
|
|
|
1117
1229
|
``style`` is ``"solid"`` / ``"dashed"`` / ``"dotted"``.
|
|
1118
1230
|
|
|
1119
|
-
``route`` is ``"straight"`` (default), ``"elbow"``, or
|
|
1120
|
-
|
|
1231
|
+
``route`` is ``"straight"`` (default), ``"elbow"``, or ``"curved"``
|
|
1232
|
+
— picks the underlying
|
|
1121
1233
|
:class:`~pptx2.enum.shapes.MSO_CONNECTOR_TYPE`.
|
|
1122
1234
|
|
|
1235
|
+
Keyword synonyms are absorbed: ``begin`` / ``from`` / ``source``
|
|
1236
|
+
for ``start``, ``to`` / ``target`` for ``end``, ``stroke_color`` /
|
|
1237
|
+
``colour`` for ``color``, ``weight`` / ``line_weight`` for
|
|
1238
|
+
``weight_pt`` — see :meth:`add_text` for the full aliasing story.
|
|
1239
|
+
|
|
1123
1240
|
Returns the :class:`Connector` so callers can tweak further.
|
|
1124
1241
|
"""
|
|
1242
|
+
from pptx2._agent_friendly import absorb_agent_kwargs
|
|
1125
1243
|
from pptx2._color import coerce_color
|
|
1126
1244
|
from pptx2.enum.dml import (
|
|
1127
1245
|
MSO_LINE_DASH_STYLE,
|
|
@@ -1131,6 +1249,64 @@ class _BaseGroupShapes(_BaseShapes):
|
|
|
1131
1249
|
from pptx2.enum.shapes import MSO_CONNECTOR_TYPE
|
|
1132
1250
|
from pptx2.util import Pt
|
|
1133
1251
|
|
|
1252
|
+
if kwargs:
|
|
1253
|
+
kwargs = absorb_agent_kwargs(
|
|
1254
|
+
"add_arrow",
|
|
1255
|
+
kwargs,
|
|
1256
|
+
(
|
|
1257
|
+
"start", "end", "head", "tail", "head_size", "tail_size",
|
|
1258
|
+
"color", "weight_pt", "style", "route", "inset_pt",
|
|
1259
|
+
"end_side", "start_side",
|
|
1260
|
+
),
|
|
1261
|
+
)
|
|
1262
|
+
defaults = {
|
|
1263
|
+
"head": "triangle", "tail": None, "head_size": "medium",
|
|
1264
|
+
"tail_size": "medium", "color": None, "weight_pt": 1.5,
|
|
1265
|
+
"style": "solid", "route": "straight", "inset_pt": 0.0,
|
|
1266
|
+
"end_side": "auto", "start_side": "auto",
|
|
1267
|
+
}
|
|
1268
|
+
given = {
|
|
1269
|
+
"head": head, "tail": tail, "head_size": head_size,
|
|
1270
|
+
"tail_size": tail_size, "color": color, "weight_pt": weight_pt,
|
|
1271
|
+
"style": style, "route": route, "inset_pt": inset_pt,
|
|
1272
|
+
"end_side": end_side, "start_side": start_side,
|
|
1273
|
+
}
|
|
1274
|
+
for name in defaults:
|
|
1275
|
+
if name not in kwargs:
|
|
1276
|
+
continue
|
|
1277
|
+
value = kwargs[name]
|
|
1278
|
+
if given[name] != defaults[name] and given[name] != value:
|
|
1279
|
+
raise TypeError(
|
|
1280
|
+
f"add_arrow(): {name!r} given twice with different "
|
|
1281
|
+
f"values ({given[name]!r} vs {value!r})"
|
|
1282
|
+
)
|
|
1283
|
+
given[name] = value
|
|
1284
|
+
head = given["head"]
|
|
1285
|
+
tail = given["tail"]
|
|
1286
|
+
head_size = given["head_size"]
|
|
1287
|
+
tail_size = given["tail_size"]
|
|
1288
|
+
color = given["color"]
|
|
1289
|
+
weight_pt = given["weight_pt"]
|
|
1290
|
+
style = given["style"]
|
|
1291
|
+
route = given["route"]
|
|
1292
|
+
inset_pt = given["inset_pt"]
|
|
1293
|
+
end_side = given["end_side"]
|
|
1294
|
+
start_side = given["start_side"]
|
|
1295
|
+
# start/end synonyms (from=/to=/begin=/source=/target=)
|
|
1296
|
+
if "start" in kwargs:
|
|
1297
|
+
start = kwargs["start"]
|
|
1298
|
+
if "end" in kwargs:
|
|
1299
|
+
end = kwargs["end"]
|
|
1300
|
+
if start is None or end is None:
|
|
1301
|
+
raise TypeError(
|
|
1302
|
+
"add_arrow() missing required argument(s): "
|
|
1303
|
+
+ ", ".join(
|
|
1304
|
+
name for name, value in (("start", start), ("end", end))
|
|
1305
|
+
if value is None
|
|
1306
|
+
)
|
|
1307
|
+
+ " (synonyms begin/from/source and to/target accepted)"
|
|
1308
|
+
)
|
|
1309
|
+
|
|
1134
1310
|
_CONNECTOR = {
|
|
1135
1311
|
"straight": MSO_CONNECTOR_TYPE.STRAIGHT,
|
|
1136
1312
|
"elbow": MSO_CONNECTOR_TYPE.ELBOW,
|
|
@@ -1331,6 +1507,7 @@ class _BaseGroupShapes(_BaseShapes):
|
|
|
1331
1507
|
sp = self._spTree.add_textbox(id_, name, x, y, cx, cy)
|
|
1332
1508
|
return sp
|
|
1333
1509
|
|
|
1510
|
+
@agent_friendly({"cols": ("columns", "num_cols", "col_count"), "rows": ("num_rows", "row_count")})
|
|
1334
1511
|
def add_table(
|
|
1335
1512
|
self,
|
|
1336
1513
|
rows: int,
|
|
@@ -1382,6 +1559,7 @@ class _BaseGroupShapes(_BaseShapes):
|
|
|
1382
1559
|
tbl.vert_banding = False
|
|
1383
1560
|
return shape
|
|
1384
1561
|
|
|
1562
|
+
@agent_friendly({"movie_file": ("video", "video_file", "movie", "path", "file")})
|
|
1385
1563
|
def add_movie(
|
|
1386
1564
|
self,
|
|
1387
1565
|
movie_file: str | IO[bytes],
|
pptx2/skill/references/basics.md
CHANGED
|
@@ -449,3 +449,16 @@ print(slide.notes) # "" when the slide has no notes
|
|
|
449
449
|
`start_slide_index` claims every slide from that position to the deck
|
|
450
450
|
end. `move` raises `IndexError` out of range; `reorder` raises
|
|
451
451
|
`ValueError` unless given a clean permutation.
|
|
452
|
+
|
|
453
|
+
### Forgiving keyword arguments
|
|
454
|
+
|
|
455
|
+
Every shape helper (`add_text`, `add_shape`, `add_picture`,
|
|
456
|
+
`add_table`, `add_chart`, `add_textbox`, `add_connector`, `add_movie`,
|
|
457
|
+
`add_arrow`, `add_equation`, ...) and the diagram recipes
|
|
458
|
+
(`horizontal_pipeline`, `hub_and_spoke`, ...) absorb cross-library and
|
|
459
|
+
near-miss kwargs: `font_family=`, `halign=`/`valign=`, `fontsize=`,
|
|
460
|
+
`colour`, `x,y,w,h` geometry keywords, `shape_type=`, `image=`,
|
|
461
|
+
`columns=`, `data=`, `begin=`/`to=`, `items=`/`nodes=` ... Synonyms
|
|
462
|
+
substitute, never contradict (two different values for the same
|
|
463
|
+
logical argument still raise), and a truly unknown kwarg raises a
|
|
464
|
+
`TypeError` listing every accepted name.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-pptx2
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.19.0
|
|
4
4
|
Summary: Create, read, and update PowerPoint 2007+ (.pptx) files. Fork of power-pptx / python-pptx, published as python-pptx2.
|
|
5
5
|
Author: Matěj Štágl
|
|
6
6
|
Author-email: stagl@wattlescript.org
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
pptx2/__init__.py,sha256=
|
|
1
|
+
pptx2/__init__.py,sha256=SyJ-yjsqXoYHIjHWLRvKdyYTilNWX5KpkyHWIepB8HA,4076
|
|
2
|
+
pptx2/_agent_friendly.py,sha256=wYh9LmVuZMVlwOxzyd1mw0NmtPKQ2cTC21Y1Ww8ehO8,8834
|
|
2
3
|
pptx2/_color.py,sha256=Ureg4dSEdHbwpVZ5eJIyt0kLx_W3mGftmznejth_oLQ,2889
|
|
3
4
|
pptx2/_slide_importer.py,sha256=Ot3lW20eS7fMKsaGaeqPyeS9zVzt5D1WkovwozWwbYY,27033
|
|
4
5
|
pptx2/_svg.py,sha256=pMURsUQaJ9-dqRl4nEZKt1VECNpA8Ghp4EwNRWcBG-c,5973
|
|
@@ -9,7 +10,7 @@ pptx2/action.py,sha256=BiDtM80P6oFsNOtLIT1nX82LXEvaGOg4Usaf5CA7kNY,9648
|
|
|
9
10
|
pptx2/animation.py,sha256=g0OxAkCoGu0QEx3QB9Yu4BOnGLjD3tcLpKoYBAtUW6s,83756
|
|
10
11
|
pptx2/api.py,sha256=n98a5qUhVxSwZ_yG_aXxtDCxtnEp37LPsSIsYsbwsfA,1841
|
|
11
12
|
pptx2/audit.py,sha256=xg1QAs-ByW3xwBEcJ-Y9ptYe2WHKmVuVWAgRKQZfcr8,11276
|
|
12
|
-
pptx2/diagrams.py,sha256=
|
|
13
|
+
pptx2/diagrams.py,sha256=4NmdFBg367hRjfFh7pQCVivScspmyvPnp94IyncJgCc,26277
|
|
13
14
|
pptx2/exc.py,sha256=k6p-e9h5cKal09-sAv3E1QTXmVDuF8FqewW1CKFQmfw,1276
|
|
14
15
|
pptx2/formats.py,sha256=w0b8YXBjBbPhDu1UV9-1iUJdL62d9_gcQSp9sHKVr_s,5081
|
|
15
16
|
pptx2/geometry.py,sha256=X1tzwqTxXCMPPRpZhHSax6PKGy_-64MAudMI9h3ILJk,15221
|
|
@@ -136,12 +137,12 @@ pptx2/shapes/graphfrm.py,sha256=mwA9Wb4WRKBy6sA7KzOZFl3aHlpN-TmWRcE-kiMoqRI,1189
|
|
|
136
137
|
pptx2/shapes/group.py,sha256=xlcGi3MAzBHX2IM16IATxRgw8NwsPFzTMVbRPYQ7OKg,11036
|
|
137
138
|
pptx2/shapes/picture.py,sha256=U7rwiy7OXn0RgFSEdh07bdhIplWsI82OjFk-mt975J0,14938
|
|
138
139
|
pptx2/shapes/placeholder.py,sha256=9tIeNscnV46hWyMr8ZSiZO3TZr-tt4kZgx6BRB0tCvc,17838
|
|
139
|
-
pptx2/shapes/shapetree.py,sha256=
|
|
140
|
+
pptx2/shapes/shapetree.py,sha256=ZXO1mE2-sMF8Era-EA4mT61Mcj2Hfsr8v-7xOZM_oBw,91287
|
|
140
141
|
pptx2/skill/SKILL.md,sha256=6w7sWflZvhYYIzBsXLjx2uVKqB0793ZTvoZ_SUfzQxg,23668
|
|
141
142
|
pptx2/skill/__init__.py,sha256=bUkfMETwf3K6J7GSE-tLQjdNziS_JceunComLiLIeGI,2665
|
|
142
143
|
pptx2/skill/__main__.py,sha256=ohMLGy1jbjKV5_FqY6aGj4tm_isJ6fznvqUKiE1H6s8,1777
|
|
143
144
|
pptx2/skill/references/animations.md,sha256=ca02l5XCtOQpD-uSCItQixGaW0yONIY0P55yy-T-J1Q,5875
|
|
144
|
-
pptx2/skill/references/basics.md,sha256=
|
|
145
|
+
pptx2/skill/references/basics.md,sha256=O2ODa85fIK6mkom4aK2ehb2laEsogmtQ31RF5ckh6B0,14806
|
|
145
146
|
pptx2/skill/references/charts.md,sha256=skCS4Kn1j49mlIQJYDAkcu2VHc3S1mzwqkGT3ZE94wg,8119
|
|
146
147
|
pptx2/skill/references/compose.md,sha256=AfFwqAyQ9ggR140laqRDIUE3OcmTtXpIZH1oPcTOunA,8088
|
|
147
148
|
pptx2/skill/references/design.md,sha256=ne3xVyIwqpkhEkd8XK74QEija040eHve5zBHBx9LeNo,11706
|
|
@@ -170,9 +171,9 @@ pptx2/text/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
170
171
|
pptx2/text/fonts.py,sha256=ECa9HuBfeTqOi-uJTz_bu7eurC7e1_64RTwDatxmkpk,16498
|
|
171
172
|
pptx2/text/layout.py,sha256=k8bqod6GyshHJtfoqFtH9W-eHTI43IB0e6SLT1ibSUU,12815
|
|
172
173
|
pptx2/text/text.py,sha256=LPqF1B4GSQNSnSlVMm1v7pgtHCymOJPTUG_Kdt5_ou4,55039
|
|
173
|
-
python_pptx2-2.
|
|
174
|
-
python_pptx2-2.
|
|
175
|
-
python_pptx2-2.
|
|
176
|
-
python_pptx2-2.
|
|
177
|
-
python_pptx2-2.
|
|
178
|
-
python_pptx2-2.
|
|
174
|
+
python_pptx2-2.19.0.dist-info/licenses/LICENSE,sha256=hLdud18ZPS9iSG3kBCBLiGYzj4A6zedCHiDejIDBXNg,1230
|
|
175
|
+
python_pptx2-2.19.0.dist-info/METADATA,sha256=ttj2GNUUnqaxdWQqPvqwfN4lOn6KcRzMWtcBt1UnnCA,14374
|
|
176
|
+
python_pptx2-2.19.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
177
|
+
python_pptx2-2.19.0.dist-info/entry_points.txt,sha256=UpD1_pA-2BPeN0iDeD-u4NZ_yC78TvBdWu3V1xLsSRE,105
|
|
178
|
+
python_pptx2-2.19.0.dist-info/top_level.txt,sha256=NDdhJ4rOySlDU-cw4g-bQMoZCiy41WszlRXmIiReSRs,6
|
|
179
|
+
python_pptx2-2.19.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|