aboutsummaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/pptx/oxml/shapes/shared.py
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/pptx/oxml/shapes/shared.py
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-master.tar.gz
two version of R2R are hereHEADmaster
Diffstat (limited to '.venv/lib/python3.12/site-packages/pptx/oxml/shapes/shared.py')
-rw-r--r--.venv/lib/python3.12/site-packages/pptx/oxml/shapes/shared.py523
1 files changed, 523 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/pptx/oxml/shapes/shared.py b/.venv/lib/python3.12/site-packages/pptx/oxml/shapes/shared.py
new file mode 100644
index 00000000..d9f94569
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pptx/oxml/shapes/shared.py
@@ -0,0 +1,523 @@
+"""Common shape-related oxml objects."""
+
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Callable
+
+from pptx.dml.fill import CT_GradientFillProperties
+from pptx.enum.shapes import PP_PLACEHOLDER
+from pptx.oxml.ns import qn
+from pptx.oxml.simpletypes import (
+ ST_Angle,
+ ST_Coordinate,
+ ST_Direction,
+ ST_DrawingElementId,
+ ST_LineWidth,
+ ST_PlaceholderSize,
+ ST_PositiveCoordinate,
+ XsdBoolean,
+ XsdString,
+ XsdUnsignedInt,
+)
+from pptx.oxml.xmlchemy import (
+ BaseOxmlElement,
+ Choice,
+ OptionalAttribute,
+ OxmlElement,
+ RequiredAttribute,
+ ZeroOrOne,
+ ZeroOrOneChoice,
+)
+from pptx.util import Emu
+
+if TYPE_CHECKING:
+ from pptx.oxml.action import CT_Hyperlink
+ from pptx.oxml.shapes.autoshape import CT_CustomGeometry2D, CT_PresetGeometry2D
+ from pptx.util import Length
+
+
+class BaseShapeElement(BaseOxmlElement):
+ """Provides common behavior for shape element classes like CT_Shape, CT_Picture, etc."""
+
+ spPr: CT_ShapeProperties
+
+ @property
+ def cx(self) -> Length:
+ return self._get_xfrm_attr("cx")
+
+ @cx.setter
+ def cx(self, value):
+ self._set_xfrm_attr("cx", value)
+
+ @property
+ def cy(self) -> Length:
+ return self._get_xfrm_attr("cy")
+
+ @cy.setter
+ def cy(self, value):
+ self._set_xfrm_attr("cy", value)
+
+ @property
+ def flipH(self):
+ return bool(self._get_xfrm_attr("flipH"))
+
+ @flipH.setter
+ def flipH(self, value):
+ self._set_xfrm_attr("flipH", value)
+
+ @property
+ def flipV(self):
+ return bool(self._get_xfrm_attr("flipV"))
+
+ @flipV.setter
+ def flipV(self, value):
+ self._set_xfrm_attr("flipV", value)
+
+ def get_or_add_xfrm(self):
+ """Return the `a:xfrm` grandchild element, newly-added if not present.
+
+ This version works for `p:sp`, `p:cxnSp`, and `p:pic` elements, others will need to
+ override.
+ """
+ return self.spPr.get_or_add_xfrm()
+
+ @property
+ def has_ph_elm(self):
+ """
+ True if this shape element has a `p:ph` descendant, indicating it
+ is a placeholder shape. False otherwise.
+ """
+ return self.ph is not None
+
+ @property
+ def ph(self) -> CT_Placeholder | None:
+ """The `p:ph` descendant element if there is one, None otherwise."""
+ ph_elms = self.xpath("./*[1]/p:nvPr/p:ph")
+ if len(ph_elms) == 0:
+ return None
+ return ph_elms[0]
+
+ @property
+ def ph_idx(self) -> int:
+ """Integer value of placeholder idx attribute.
+
+ Raises |ValueError| if shape is not a placeholder.
+ """
+ ph = self.ph
+ if ph is None:
+ raise ValueError("not a placeholder shape")
+ return ph.idx
+
+ @property
+ def ph_orient(self) -> str:
+ """Placeholder orientation, e.g. 'vert'.
+
+ Raises |ValueError| if shape is not a placeholder.
+ """
+ ph = self.ph
+ if ph is None:
+ raise ValueError("not a placeholder shape")
+ return ph.orient
+
+ @property
+ def ph_sz(self) -> str:
+ """Placeholder size, e.g. ST_PlaceholderSize.HALF.
+
+ Raises `ValueError` if shape is not a placeholder.
+ """
+ ph = self.ph
+ if ph is None:
+ raise ValueError("not a placeholder shape")
+ return ph.sz
+
+ @property
+ def ph_type(self):
+ """Placeholder type, e.g. ST_PlaceholderType.TITLE ('title').
+
+ Raises `ValueError` if shape is not a placeholder.
+ """
+ ph = self.ph
+ if ph is None:
+ raise ValueError("not a placeholder shape")
+ return ph.type
+
+ @property
+ def rot(self) -> float:
+ """Float representing degrees this shape is rotated clockwise."""
+ xfrm = self.xfrm
+ if xfrm is None or xfrm.rot is None:
+ return 0.0
+ return xfrm.rot
+
+ @rot.setter
+ def rot(self, value: float):
+ self.get_or_add_xfrm().rot = value
+
+ @property
+ def shape_id(self):
+ """
+ Integer id of this shape
+ """
+ return self._nvXxPr.cNvPr.id
+
+ @property
+ def shape_name(self):
+ """
+ Name of this shape
+ """
+ return self._nvXxPr.cNvPr.name
+
+ @property
+ def txBody(self):
+ """Child `p:txBody` element, None if not present."""
+ return self.find(qn("p:txBody"))
+
+ @property
+ def x(self) -> Length:
+ return self._get_xfrm_attr("x")
+
+ @x.setter
+ def x(self, value):
+ self._set_xfrm_attr("x", value)
+
+ @property
+ def xfrm(self):
+ """The `a:xfrm` grandchild element or |None| if not found.
+
+ This version works for `p:sp`, `p:cxnSp`, and `p:pic` elements, others will need to
+ override.
+ """
+ return self.spPr.xfrm
+
+ @property
+ def y(self) -> Length:
+ return self._get_xfrm_attr("y")
+
+ @y.setter
+ def y(self, value):
+ self._set_xfrm_attr("y", value)
+
+ @property
+ def _nvXxPr(self):
+ """
+ Required non-visual shape properties element for this shape. Actual
+ name depends on the shape type, e.g. `p:nvPicPr` for picture
+ shape.
+ """
+ return self.xpath("./*[1]")[0]
+
+ def _get_xfrm_attr(self, name: str) -> Length | None:
+ xfrm = self.xfrm
+ if xfrm is None:
+ return None
+ return getattr(xfrm, name)
+
+ def _set_xfrm_attr(self, name, value):
+ xfrm = self.get_or_add_xfrm()
+ setattr(xfrm, name, value)
+
+
+class CT_ApplicationNonVisualDrawingProps(BaseOxmlElement):
+ """`p:nvPr` element."""
+
+ get_or_add_ph: Callable[[], CT_Placeholder]
+
+ ph = ZeroOrOne(
+ "p:ph",
+ successors=(
+ "a:audioCd",
+ "a:wavAudioFile",
+ "a:audioFile",
+ "a:videoFile",
+ "a:quickTimeFile",
+ "p:custDataLst",
+ "p:extLst",
+ ),
+ )
+
+
+class CT_LineProperties(BaseOxmlElement):
+ """Custom element class for <a:ln> element"""
+
+ _tag_seq = (
+ "a:noFill",
+ "a:solidFill",
+ "a:gradFill",
+ "a:pattFill",
+ "a:prstDash",
+ "a:custDash",
+ "a:round",
+ "a:bevel",
+ "a:miter",
+ "a:headEnd",
+ "a:tailEnd",
+ "a:extLst",
+ )
+ eg_lineFillProperties = ZeroOrOneChoice(
+ (
+ Choice("a:noFill"),
+ Choice("a:solidFill"),
+ Choice("a:gradFill"),
+ Choice("a:pattFill"),
+ ),
+ successors=_tag_seq[4:],
+ )
+ prstDash = ZeroOrOne("a:prstDash", successors=_tag_seq[5:])
+ custDash = ZeroOrOne("a:custDash", successors=_tag_seq[6:])
+ del _tag_seq
+ w = OptionalAttribute("w", ST_LineWidth, default=Emu(0))
+
+ @property
+ def eg_fillProperties(self):
+ """
+ Required to fulfill the interface used by dml.fill.
+ """
+ return self.eg_lineFillProperties
+
+ @property
+ def prstDash_val(self):
+ """Return value of `val` attribute of `a:prstDash` child.
+
+ Return |None| if not present.
+ """
+ prstDash = self.prstDash
+ if prstDash is None:
+ return None
+ return prstDash.val
+
+ @prstDash_val.setter
+ def prstDash_val(self, val):
+ self._remove_custDash()
+ prstDash = self.get_or_add_prstDash()
+ prstDash.val = val
+
+
+class CT_NonVisualDrawingProps(BaseOxmlElement):
+ """`p:cNvPr` custom element class."""
+
+ get_or_add_hlinkClick: Callable[[], CT_Hyperlink]
+ get_or_add_hlinkHover: Callable[[], CT_Hyperlink]
+
+ _tag_seq = ("a:hlinkClick", "a:hlinkHover", "a:extLst")
+ hlinkClick: CT_Hyperlink | None = ZeroOrOne("a:hlinkClick", successors=_tag_seq[1:])
+ hlinkHover: CT_Hyperlink | None = ZeroOrOne("a:hlinkHover", successors=_tag_seq[2:])
+ id = RequiredAttribute("id", ST_DrawingElementId)
+ name = RequiredAttribute("name", XsdString)
+ del _tag_seq
+
+
+class CT_Placeholder(BaseOxmlElement):
+ """`p:ph` custom element class."""
+
+ type: PP_PLACEHOLDER = OptionalAttribute( # pyright: ignore[reportAssignmentType]
+ "type", PP_PLACEHOLDER, default=PP_PLACEHOLDER.OBJECT
+ )
+ orient: str = OptionalAttribute( # pyright: ignore[reportAssignmentType]
+ "orient", ST_Direction, default=ST_Direction.HORZ
+ )
+ sz: str = OptionalAttribute( # pyright: ignore[reportAssignmentType]
+ "sz", ST_PlaceholderSize, default=ST_PlaceholderSize.FULL
+ )
+ idx: int = OptionalAttribute( # pyright: ignore[reportAssignmentType]
+ "idx", XsdUnsignedInt, default=0
+ )
+
+
+class CT_Point2D(BaseOxmlElement):
+ """
+ Custom element class for <a:off> element.
+ """
+
+ x: Length = RequiredAttribute("x", ST_Coordinate) # pyright: ignore[reportAssignmentType]
+ y: Length = RequiredAttribute("y", ST_Coordinate) # pyright: ignore[reportAssignmentType]
+
+
+class CT_PositiveSize2D(BaseOxmlElement):
+ """
+ Custom element class for <a:ext> element.
+ """
+
+ cx = RequiredAttribute("cx", ST_PositiveCoordinate)
+ cy = RequiredAttribute("cy", ST_PositiveCoordinate)
+
+
+class CT_ShapeProperties(BaseOxmlElement):
+ """Custom element class for `p:spPr` element.
+
+ Shared by `p:sp`, `p:cxnSp`, and `p:pic` elements as well as a few more obscure ones.
+ """
+
+ get_or_add_xfrm: Callable[[], CT_Transform2D]
+ get_or_add_ln: Callable[[], CT_LineProperties]
+ _add_prstGeom: Callable[[], CT_PresetGeometry2D]
+ _remove_custGeom: Callable[[], None]
+
+ _tag_seq = (
+ "a:xfrm",
+ "a:custGeom",
+ "a:prstGeom",
+ "a:noFill",
+ "a:solidFill",
+ "a:gradFill",
+ "a:blipFill",
+ "a:pattFill",
+ "a:grpFill",
+ "a:ln",
+ "a:effectLst",
+ "a:effectDag",
+ "a:scene3d",
+ "a:sp3d",
+ "a:extLst",
+ )
+ xfrm: CT_Transform2D | None = ZeroOrOne( # pyright: ignore[reportAssignmentType]
+ "a:xfrm", successors=_tag_seq[1:]
+ )
+ custGeom: CT_CustomGeometry2D | None = ZeroOrOne( # pyright: ignore[reportAssignmentType]
+ "a:custGeom", successors=_tag_seq[2:]
+ )
+ prstGeom: CT_PresetGeometry2D | None = ZeroOrOne( # pyright: ignore[reportAssignmentType]
+ "a:prstGeom", successors=_tag_seq[3:]
+ )
+ eg_fillProperties = ZeroOrOneChoice(
+ (
+ Choice("a:noFill"),
+ Choice("a:solidFill"),
+ Choice("a:gradFill"),
+ Choice("a:blipFill"),
+ Choice("a:pattFill"),
+ Choice("a:grpFill"),
+ ),
+ successors=_tag_seq[9:],
+ )
+ ln: CT_LineProperties | None = ZeroOrOne( # pyright: ignore[reportAssignmentType]
+ "a:ln", successors=_tag_seq[10:]
+ )
+ effectLst = ZeroOrOne("a:effectLst", successors=_tag_seq[11:])
+ del _tag_seq
+
+ @property
+ def cx(self):
+ """
+ Shape width as an instance of Emu, or None if not present.
+ """
+ cx_str_lst = self.xpath("./a:xfrm/a:ext/@cx")
+ if not cx_str_lst:
+ return None
+ return Emu(cx_str_lst[0])
+
+ @property
+ def cy(self):
+ """
+ Shape height as an instance of Emu, or None if not present.
+ """
+ cy_str_lst = self.xpath("./a:xfrm/a:ext/@cy")
+ if not cy_str_lst:
+ return None
+ return Emu(cy_str_lst[0])
+
+ @property
+ def x(self) -> Length | None:
+ """Distance between the left edge of the slide and left edge of the shape.
+
+ 0 if not present.
+ """
+ x_str_lst = self.xpath("./a:xfrm/a:off/@x")
+ if not x_str_lst:
+ return None
+ return Emu(x_str_lst[0])
+
+ @property
+ def y(self):
+ """
+ The offset of the top of the shape from the top of the slide, as an
+ instance of Emu. None if not present.
+ """
+ y_str_lst = self.xpath("./a:xfrm/a:off/@y")
+ if not y_str_lst:
+ return None
+ return Emu(y_str_lst[0])
+
+ def _new_gradFill(self):
+ return CT_GradientFillProperties.new_gradFill()
+
+
+class CT_Transform2D(BaseOxmlElement):
+ """`a:xfrm` custom element class.
+
+ NOTE: this is a composite including CT_GroupTransform2D, which appears
+ with the `a:xfrm` tag in a group shape (including a slide `p:spTree`).
+ """
+
+ _tag_seq = ("a:off", "a:ext", "a:chOff", "a:chExt")
+ off: CT_Point2D | None = ZeroOrOne( # pyright: ignore[reportAssignmentType]
+ "a:off", successors=_tag_seq[1:]
+ )
+ ext = ZeroOrOne("a:ext", successors=_tag_seq[2:])
+ chOff = ZeroOrOne("a:chOff", successors=_tag_seq[3:])
+ chExt = ZeroOrOne("a:chExt", successors=_tag_seq[4:])
+ del _tag_seq
+ rot: float | None = OptionalAttribute( # pyright: ignore[reportAssignmentType]
+ "rot", ST_Angle, default=0.0
+ )
+ flipH = OptionalAttribute("flipH", XsdBoolean, default=False)
+ flipV = OptionalAttribute("flipV", XsdBoolean, default=False)
+
+ @property
+ def x(self):
+ off = self.off
+ if off is None:
+ return None
+ return off.x
+
+ @x.setter
+ def x(self, value):
+ off = self.get_or_add_off()
+ off.x = value
+
+ @property
+ def y(self):
+ off = self.off
+ if off is None:
+ return None
+ return off.y
+
+ @y.setter
+ def y(self, value):
+ off = self.get_or_add_off()
+ off.y = value
+
+ @property
+ def cx(self):
+ ext = self.ext
+ if ext is None:
+ return None
+ return ext.cx
+
+ @cx.setter
+ def cx(self, value):
+ ext = self.get_or_add_ext()
+ ext.cx = value
+
+ @property
+ def cy(self):
+ ext = self.ext
+ if ext is None:
+ return None
+ return ext.cy
+
+ @cy.setter
+ def cy(self, value):
+ ext = self.get_or_add_ext()
+ ext.cy = value
+
+ def _new_ext(self):
+ ext = OxmlElement("a:ext")
+ ext.cx = 0
+ ext.cy = 0
+ return ext
+
+ def _new_off(self):
+ off = OxmlElement("a:off")
+ off.x = 0
+ off.y = 0
+ return off