python-pptx2 2.16.0__py3-none-any.whl → 2.17.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 CHANGED
@@ -57,7 +57,7 @@ from pptx2.parts.slide import (
57
57
  if TYPE_CHECKING:
58
58
  from pptx2.opc.package import Part
59
59
 
60
- __version__ = "2.16.0"
60
+ __version__ = "2.17.0"
61
61
 
62
62
  sys.modules["pptx2.exceptions"] = exceptions
63
63
  del sys
pptx2/_textstyle.py CHANGED
@@ -28,6 +28,7 @@ ALIGN_MAP = {
28
28
  ANCHOR_MAP = {
29
29
  "top": MSO_VERTICAL_ANCHOR.TOP,
30
30
  "middle": MSO_VERTICAL_ANCHOR.MIDDLE,
31
+ "mid": MSO_VERTICAL_ANCHOR.MIDDLE,
31
32
  "center": MSO_VERTICAL_ANCHOR.MIDDLE,
32
33
  "centre": MSO_VERTICAL_ANCHOR.MIDDLE,
33
34
  "bottom": MSO_VERTICAL_ANCHOR.BOTTOM,
pptx2/audit.py CHANGED
@@ -41,7 +41,8 @@ __all__ = ["AuditReport", "audit"]
41
41
 
42
42
 
43
43
  # Fonts that ship with stock Windows / macOS / Office installs. Used as
44
- # a (very conservative) safe-list for the font_warnings probe.
44
+ # a (very conservative) safe-list for the font_warnings probe. Aptos and
45
+ # family are the Microsoft 365 default theme fonts since 2024.
45
46
  _COMMON_FONTS = frozenset(
46
47
  name.lower()
47
48
  for name in (
@@ -51,9 +52,17 @@ _COMMON_FONTS = frozenset(
51
52
  "Lucida Console", "Palatino", "Palatino Linotype", "Symbol",
52
53
  "Wingdings", "Wingdings 2", "Wingdings 3", "Webdings",
53
54
  "Inter", "Roboto", "Open Sans", "Lato", "Noto Sans",
55
+ "Aptos", "Aptos Display", "Aptos Narrow", "Aptos Serif", "Aptos Mono",
56
+ "Aptos Symbols",
54
57
  )
55
58
  )
56
59
 
60
+ # Environment variable merged into the safe-list on every audit() call, so
61
+ # rendering environments (sandboxes, CI) can declare their font inventory
62
+ # once instead of every caller passing ``extra_safe_fonts``. Comma- or
63
+ # semicolon-separated font names.
64
+ _SAFE_FONTS_ENV_VAR = "PPTX2_SAFE_FONTS"
65
+
57
66
 
58
67
  @dataclass
59
68
  class AuditReport:
@@ -188,12 +197,24 @@ def audit(
188
197
  environment genuinely ships the font — e.g. ``DejaVu Sans`` in a
189
198
  sandbox whose font policy standardizes on it, or a corporate font
190
199
  you embed in every deck.
200
+
201
+ The ``PPTX2_SAFE_FONTS`` environment variable (comma- or
202
+ semicolon-separated font names) is merged into the safe-list on
203
+ every call, so an environment can declare its font inventory once
204
+ for all callers.
191
205
  """
206
+ import os
207
+
192
208
  from pptx2.shapes.picture import Picture
193
209
 
194
210
  safe_fonts = _COMMON_FONTS
195
- if extra_safe_fonts is not None:
196
- safe_fonts = _COMMON_FONTS | frozenset(f.lower() for f in extra_safe_fonts)
211
+ extra_names = list(extra_safe_fonts) if extra_safe_fonts else []
212
+ for env_raw in os.environ.get(_SAFE_FONTS_ENV_VAR, "").replace(";", ",").split(","):
213
+ env_name = env_raw.strip()
214
+ if env_name:
215
+ extra_names.append(env_name)
216
+ if extra_names:
217
+ safe_fonts = _COMMON_FONTS | frozenset(f.lower() for f in extra_names)
197
218
 
198
219
  report = AuditReport()
199
220
  slides = list(prs.slides)
pptx2/shapes/shapetree.py CHANGED
@@ -557,6 +557,24 @@ class _BaseShapes(ParentedElementProxy):
557
557
  return BaseShapeFactory(shape_elm, self)
558
558
 
559
559
 
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
+
560
578
  class _BaseGroupShapes(_BaseShapes):
561
579
  """Base class for shape-trees that can add shapes."""
562
580
 
@@ -900,12 +918,14 @@ class _BaseGroupShapes(_BaseShapes):
900
918
  *bbox_or_positional,
901
919
  text: str = "",
902
920
  font: str | None = None,
921
+ font_family: str | None = None,
903
922
  size_pt: float | None = None,
904
923
  bold: bool | None = None,
905
924
  italic: bool | None = None,
906
925
  color=None,
907
926
  align: str | None = None,
908
927
  anchor: str | None = None,
928
+ valign: str | None = None,
909
929
  margin_pt: float | tuple[float, float, float, float] | None = None,
910
930
  word_wrap: bool | None = True,
911
931
  ) -> Shape:
@@ -922,14 +942,17 @@ class _BaseGroupShapes(_BaseShapes):
922
942
  Keyword args:
923
943
 
924
944
  * ``font`` — typeface name (e.g. ``"Inter"``); ``None`` inherits.
945
+ ``font_family`` is accepted as an alias (matplotlib habits die
946
+ hard).
925
947
  * ``size_pt`` — font size in points; ``None`` inherits.
926
948
  * ``bold`` / ``italic`` — ``True``/``False``/``None``.
927
949
  * ``color`` — any "color-like" (``"#RRGGBB"``, ``RGBColor``,
928
950
  ``(r, g, b)``).
929
951
  * ``align`` — ``"left"`` / ``"center"`` / ``"right"`` /
930
952
  ``"justify"``; ``None`` inherits.
931
- * ``anchor`` — vertical anchor: ``"top"`` / ``"middle"`` /
932
- ``"bottom"``; ``None`` inherits.
953
+ * ``anchor`` — vertical anchor: ``"top"`` / ``"middle"`` (also
954
+ ``"mid"`` / ``"center"``) / ``"bottom"``; ``None`` inherits.
955
+ ``valign`` is accepted as an alias.
933
956
  * ``margin_pt`` — uniform margin in points, or a 4-tuple
934
957
  ``(top, right, bottom, left)``.
935
958
  * ``word_wrap`` — defaults to ``True``.
@@ -940,6 +963,9 @@ class _BaseGroupShapes(_BaseShapes):
940
963
  from pptx2._textstyle import apply_margins, apply_text_style, coerce_anchor
941
964
  from pptx2.geometry import BBox
942
965
 
966
+ font = _resolve_alias("add_text", "font", font, font_family)
967
+ anchor = _resolve_alias("add_text", "anchor", anchor, valign)
968
+
943
969
  if len(bbox_or_positional) == 1 and isinstance(bbox_or_positional[0], BBox):
944
970
  box = bbox_or_positional[0]
945
971
  left, top, width, height = box.left, box.top, box.width, box.height
@@ -986,10 +1012,12 @@ class _BaseGroupShapes(_BaseShapes):
986
1012
  latex: str,
987
1013
  display: bool = True,
988
1014
  font: str | None = None,
1015
+ font_family: str | None = None,
989
1016
  size_pt: float | None = None,
990
1017
  color=None,
991
1018
  align: str | None = "center",
992
1019
  anchor: str | None = "middle",
1020
+ valign: str | None = None,
993
1021
  margin_pt: float | tuple[float, float, float, float] | None = None,
994
1022
  ) -> Shape:
995
1023
  """Add a text box containing a native PowerPoint equation from LaTeX.
@@ -1008,13 +1036,17 @@ class _BaseGroupShapes(_BaseShapes):
1008
1036
  equation editor.
1009
1037
 
1010
1038
  Keyword args match :meth:`add_text` for *font* / *size_pt* /
1011
- *color* / *align* / *anchor* / *margin_pt*. *display* (default
1039
+ *color* / *align* / *anchor* / *margin_pt* (including the
1040
+ ``font_family`` / ``valign`` aliases). *display* (default
1012
1041
  |True|) emits a display-math paragraph; set |False| for inline
1013
1042
  OMML.
1014
1043
  """
1015
1044
  from pptx2._textstyle import apply_margins, coerce_align, coerce_anchor
1016
1045
  from pptx2.geometry import BBox
1017
1046
 
1047
+ font = _resolve_alias("add_equation", "font", font, font_family)
1048
+ anchor = _resolve_alias("add_equation", "anchor", anchor, valign)
1049
+
1018
1050
  if len(bbox_or_positional) == 1 and isinstance(bbox_or_positional[0], BBox):
1019
1051
  box = bbox_or_positional[0]
1020
1052
  left, top, width, height = box.left, box.top, box.width, box.height
@@ -187,6 +187,13 @@ drown in noise:
187
187
  report = audit(prs, extra_safe_fonts=["DejaVu Sans", "Noto Sans CJK JP"])
188
188
  ```
189
189
 
190
+ Or declare the inventory once for every caller via the environment
191
+ (merged into the safe-list on each `audit()`):
192
+
193
+ ```bash
194
+ export PPTX2_SAFE_FONTS="DejaVu Sans; Noto Sans CJK JP"
195
+ ```
196
+
190
197
  ## Save-time hooks (via `from_spec`)
191
198
 
192
199
  If you build the deck through `pptx2.compose.from_spec`, the spec dict
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-pptx2
3
- Version: 2.16.0
3
+ Version: 2.17.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,14 +1,14 @@
1
- pptx2/__init__.py,sha256=oll9FR8kNjyIlQOq779hfSOGTze8MSlZKQCJypny4zk,4076
1
+ pptx2/__init__.py,sha256=lLf03V_PykqZkDfLk7wwFUMFnN9JnqDoW3ziwibWXfE,4076
2
2
  pptx2/_color.py,sha256=Ureg4dSEdHbwpVZ5eJIyt0kLx_W3mGftmznejth_oLQ,2889
3
3
  pptx2/_slide_importer.py,sha256=Ot3lW20eS7fMKsaGaeqPyeS9zVzt5D1WkovwozWwbYY,27033
4
4
  pptx2/_svg.py,sha256=pMURsUQaJ9-dqRl4nEZKt1VECNpA8Ghp4EwNRWcBG-c,5973
5
5
  pptx2/_template_applier.py,sha256=H1pu7bgUMUhJzTvABuQFT7zkjSWas5NfdJIipamCvXw,12699
6
- pptx2/_textstyle.py,sha256=ysxPcW9LNuimD83Vjg7dc35SYMdGRdCmuib5Zm7Xcns,6315
6
+ pptx2/_textstyle.py,sha256=INb0JvqeHwP7cmlxoRe65ImV3vR_AbUKMFKEWOUfAr4,6354
7
7
  pptx2/accessibility.py,sha256=SDVPX6FK77B3OXBMvr65qowzJFVzcRsnMybjVMQ0oi4,11981
8
8
  pptx2/action.py,sha256=BiDtM80P6oFsNOtLIT1nX82LXEvaGOg4Usaf5CA7kNY,9648
9
9
  pptx2/animation.py,sha256=g0OxAkCoGu0QEx3QB9Yu4BOnGLjD3tcLpKoYBAtUW6s,83756
10
10
  pptx2/api.py,sha256=n98a5qUhVxSwZ_yG_aXxtDCxtnEp37LPsSIsYsbwsfA,1841
11
- pptx2/audit.py,sha256=jXNZgHTY8B1zrDPFigvr2QVFvzXMEJOL-vk5UyeJoIk,10332
11
+ pptx2/audit.py,sha256=xg1QAs-ByW3xwBEcJ-Y9ptYe2WHKmVuVWAgRKQZfcr8,11276
12
12
  pptx2/diagrams.py,sha256=5NqGg-CMj6ZYoEsI9pBD1UHmwQhSAK8oAFYD89NPsVg,24654
13
13
  pptx2/exc.py,sha256=k6p-e9h5cKal09-sAv3E1QTXmVDuF8FqewW1CKFQmfw,1276
14
14
  pptx2/formats.py,sha256=w0b8YXBjBbPhDu1UV9-1iUJdL62d9_gcQSp9sHKVr_s,5081
@@ -136,7 +136,7 @@ pptx2/shapes/graphfrm.py,sha256=mwA9Wb4WRKBy6sA7KzOZFl3aHlpN-TmWRcE-kiMoqRI,1189
136
136
  pptx2/shapes/group.py,sha256=xlcGi3MAzBHX2IM16IATxRgw8NwsPFzTMVbRPYQ7OKg,11036
137
137
  pptx2/shapes/picture.py,sha256=U7rwiy7OXn0RgFSEdh07bdhIplWsI82OjFk-mt975J0,14938
138
138
  pptx2/shapes/placeholder.py,sha256=9tIeNscnV46hWyMr8ZSiZO3TZr-tt4kZgx6BRB0tCvc,17838
139
- pptx2/shapes/shapetree.py,sha256=dTUwD0inXLHV0P6woJZFeF_BGE0YmgKfAt35hzKOoqA,81431
139
+ pptx2/shapes/shapetree.py,sha256=bbrwutelMOcRX8pT88qRLvPyE3x6avIhripnUGalH1I,82851
140
140
  pptx2/skill/SKILL.md,sha256=6w7sWflZvhYYIzBsXLjx2uVKqB0793ZTvoZ_SUfzQxg,23668
141
141
  pptx2/skill/__init__.py,sha256=bUkfMETwf3K6J7GSE-tLQjdNziS_JceunComLiLIeGI,2665
142
142
  pptx2/skill/__main__.py,sha256=ohMLGy1jbjKV5_FqY6aGj4tm_isJ6fznvqUKiE1H6s8,1777
@@ -148,7 +148,7 @@ pptx2/skill/references/design.md,sha256=ne3xVyIwqpkhEkd8XK74QEija040eHve5zBHBx9L
148
148
  pptx2/skill/references/effects.md,sha256=B4Z_rbxm5CjVeLt8rJZ-UydLPq62FgcDP32CZ1KUrvY,7668
149
149
  pptx2/skill/references/end-to-end-deck.md,sha256=6ApwoK1wJ--Oeadyjy4Iq3E0czyPBME6RYAAWQijhNU,8021
150
150
  pptx2/skill/references/geometry-and-arrows.md,sha256=kiy2KIpzcrWbfUH0tWgfdaHRH4k0QPNu0SEkk7JAKNE,10163
151
- pptx2/skill/references/lint.md,sha256=AbSkRYNrqqurpWs1BDAjzEZd8y4TsyLU3xfc4ifuhe8,10160
151
+ pptx2/skill/references/lint.md,sha256=VAWhb9hlump9Fkw3JGZQEODGc13HhthJuigu-bvC-lA,10344
152
152
  pptx2/skill/references/math.md,sha256=C8j5FcjpJgBacKwetL6HfdM2d3zRaTAcLrkyYVP-9H8,2572
153
153
  pptx2/skill/references/picture-effects.md,sha256=NCGIqICQOd7DfEif8m_OY5teS75NVQU_micGysgsi1w,3735
154
154
  pptx2/skill/references/render.md,sha256=4mUI5sYbkY5sT_oCA5YEcuQG2ddzvs_gPe4XEiSL3WQ,4671
@@ -170,9 +170,9 @@ pptx2/text/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
170
170
  pptx2/text/fonts.py,sha256=ECa9HuBfeTqOi-uJTz_bu7eurC7e1_64RTwDatxmkpk,16498
171
171
  pptx2/text/layout.py,sha256=k8bqod6GyshHJtfoqFtH9W-eHTI43IB0e6SLT1ibSUU,12815
172
172
  pptx2/text/text.py,sha256=LPqF1B4GSQNSnSlVMm1v7pgtHCymOJPTUG_Kdt5_ou4,55039
173
- python_pptx2-2.16.0.dist-info/licenses/LICENSE,sha256=hLdud18ZPS9iSG3kBCBLiGYzj4A6zedCHiDejIDBXNg,1230
174
- python_pptx2-2.16.0.dist-info/METADATA,sha256=mu4Raf9xAgpmy7-ZoBz_Vw0-jWSV7b2yTHJzb2Vn4xQ,14374
175
- python_pptx2-2.16.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
176
- python_pptx2-2.16.0.dist-info/entry_points.txt,sha256=UpD1_pA-2BPeN0iDeD-u4NZ_yC78TvBdWu3V1xLsSRE,105
177
- python_pptx2-2.16.0.dist-info/top_level.txt,sha256=NDdhJ4rOySlDU-cw4g-bQMoZCiy41WszlRXmIiReSRs,6
178
- python_pptx2-2.16.0.dist-info/RECORD,,
173
+ python_pptx2-2.17.0.dist-info/licenses/LICENSE,sha256=hLdud18ZPS9iSG3kBCBLiGYzj4A6zedCHiDejIDBXNg,1230
174
+ python_pptx2-2.17.0.dist-info/METADATA,sha256=mx9AhEC2xmYL-p2zCSn6iHbmj4GaBnNVBBg81sHNg88,14374
175
+ python_pptx2-2.17.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
176
+ python_pptx2-2.17.0.dist-info/entry_points.txt,sha256=UpD1_pA-2BPeN0iDeD-u4NZ_yC78TvBdWu3V1xLsSRE,105
177
+ python_pptx2-2.17.0.dist-info/top_level.txt,sha256=NDdhJ4rOySlDU-cw4g-bQMoZCiy41WszlRXmIiReSRs,6
178
+ python_pptx2-2.17.0.dist-info/RECORD,,