File: //home/arjun/projects/env/lib64/python3.10/site-packages/docx/oxml/styles.py
"""Custom element classes related to the styles part."""
from __future__ import annotations
from docx.enum.style import WD_STYLE_TYPE
from docx.oxml.simpletypes import ST_DecimalNumber, ST_OnOff, ST_String
from docx.oxml.xmlchemy import (
BaseOxmlElement,
OptionalAttribute,
RequiredAttribute,
ZeroOrMore,
ZeroOrOne,
)
def styleId_from_name(name):
"""Return the style id corresponding to `name`, taking into account special-case
names such as 'Heading 1'."""
return {
"caption": "Caption",
"heading 1": "Heading1",
"heading 2": "Heading2",
"heading 3": "Heading3",
"heading 4": "Heading4",
"heading 5": "Heading5",
"heading 6": "Heading6",
"heading 7": "Heading7",
"heading 8": "Heading8",
"heading 9": "Heading9",
}.get(name, name.replace(" ", ""))
class CT_LatentStyles(BaseOxmlElement):
"""`w:latentStyles` element, defining behavior defaults for latent styles and
containing `w:lsdException` child elements that each override those defaults for a
named latent style."""
lsdException = ZeroOrMore("w:lsdException", successors=())
count = OptionalAttribute("w:count", ST_DecimalNumber)
defLockedState = OptionalAttribute("w:defLockedState", ST_OnOff)
defQFormat = OptionalAttribute("w:defQFormat", ST_OnOff)
defSemiHidden = OptionalAttribute("w:defSemiHidden", ST_OnOff)
defUIPriority = OptionalAttribute("w:defUIPriority", ST_DecimalNumber)
defUnhideWhenUsed = OptionalAttribute("w:defUnhideWhenUsed", ST_OnOff)
def bool_prop(self, attr_name):
"""Return the boolean value of the attribute having `attr_name`, or |False| if
not present."""
value = getattr(self, attr_name)
if value is None:
return False
return value
def get_by_name(self, name):
"""Return the `w:lsdException` child having `name`, or |None| if not found."""
found = self.xpath('w:lsdException[@w:name="%s"]' % name)
if not found:
return None
return found[0]
def set_bool_prop(self, attr_name, value):
"""Set the on/off attribute having `attr_name` to `value`."""
setattr(self, attr_name, bool(value))
class CT_LsdException(BaseOxmlElement):
"""``<w:lsdException>`` element, defining override visibility behaviors for a named
latent style."""
locked = OptionalAttribute("w:locked", ST_OnOff)
name = RequiredAttribute("w:name", ST_String)
qFormat = OptionalAttribute("w:qFormat", ST_OnOff)
semiHidden = OptionalAttribute("w:semiHidden", ST_OnOff)
uiPriority = OptionalAttribute("w:uiPriority", ST_DecimalNumber)
unhideWhenUsed = OptionalAttribute("w:unhideWhenUsed", ST_OnOff)
def delete(self):
"""Remove this `w:lsdException` element from the XML document."""
self.getparent().remove(self)
def on_off_prop(self, attr_name):
"""Return the boolean value of the attribute having `attr_name`, or |None| if
not present."""
return getattr(self, attr_name)
def set_on_off_prop(self, attr_name, value):
"""Set the on/off attribute having `attr_name` to `value`."""
setattr(self, attr_name, value)
class CT_Style(BaseOxmlElement):
"""A ``<w:style>`` element, representing a style definition."""
_tag_seq = (
"w:name",
"w:aliases",
"w:basedOn",
"w:next",
"w:link",
"w:autoRedefine",
"w:hidden",
"w:uiPriority",
"w:semiHidden",
"w:unhideWhenUsed",
"w:qFormat",
"w:locked",
"w:personal",
"w:personalCompose",
"w:personalReply",
"w:rsid",
"w:pPr",
"w:rPr",
"w:tblPr",
"w:trPr",
"w:tcPr",
"w:tblStylePr",
)
name = ZeroOrOne("w:name", successors=_tag_seq[1:])
basedOn = ZeroOrOne("w:basedOn", successors=_tag_seq[3:])
next = ZeroOrOne("w:next", successors=_tag_seq[4:])
uiPriority = ZeroOrOne("w:uiPriority", successors=_tag_seq[8:])
semiHidden = ZeroOrOne("w:semiHidden", successors=_tag_seq[9:])
unhideWhenUsed = ZeroOrOne("w:unhideWhenUsed", successors=_tag_seq[10:])
qFormat = ZeroOrOne("w:qFormat", successors=_tag_seq[11:])
locked = ZeroOrOne("w:locked", successors=_tag_seq[12:])
pPr = ZeroOrOne("w:pPr", successors=_tag_seq[17:])
rPr = ZeroOrOne("w:rPr", successors=_tag_seq[18:])
del _tag_seq
type: WD_STYLE_TYPE | None = (
OptionalAttribute( # pyright: ignore[reportGeneralTypeIssues]
"w:type", WD_STYLE_TYPE
)
)
styleId: str | None = OptionalAttribute( # pyright: ignore[reportGeneralTypeIssues]
"w:styleId", ST_String
)
default = OptionalAttribute("w:default", ST_OnOff)
customStyle = OptionalAttribute("w:customStyle", ST_OnOff)
@property
def basedOn_val(self):
"""Value of `w:basedOn/@w:val` or |None| if not present."""
basedOn = self.basedOn
if basedOn is None:
return None
return basedOn.val
@basedOn_val.setter
def basedOn_val(self, value):
if value is None:
self._remove_basedOn()
else:
self.get_or_add_basedOn().val = value
@property
def base_style(self):
"""Sibling CT_Style element this style is based on or |None| if no base style or
base style not found."""
basedOn = self.basedOn
if basedOn is None:
return None
styles = self.getparent()
base_style = styles.get_by_id(basedOn.val)
if base_style is None:
return None
return base_style
def delete(self):
"""Remove this `w:style` element from its parent `w:styles` element."""
self.getparent().remove(self)
@property
def locked_val(self):
"""Value of `w:locked/@w:val` or |False| if not present."""
locked = self.locked
if locked is None:
return False
return locked.val
@locked_val.setter
def locked_val(self, value):
self._remove_locked()
if bool(value) is True:
locked = self._add_locked()
locked.val = value
@property
def name_val(self):
"""Value of ``<w:name>`` child or |None| if not present."""
name = self.name
if name is None:
return None
return name.val
@name_val.setter
def name_val(self, value):
self._remove_name()
if value is not None:
name = self._add_name()
name.val = value
@property
def next_style(self):
"""Sibling CT_Style element identified by the value of `w:name/@w:val` or |None|
if no value is present or no style with that style id is found."""
next = self.next
if next is None:
return None
styles = self.getparent()
return styles.get_by_id(next.val) # None if not found
@property
def qFormat_val(self):
"""Value of `w:qFormat/@w:val` or |False| if not present."""
qFormat = self.qFormat
if qFormat is None:
return False
return qFormat.val
@qFormat_val.setter
def qFormat_val(self, value):
self._remove_qFormat()
if bool(value):
self._add_qFormat()
@property
def semiHidden_val(self):
"""Value of ``<w:semiHidden>`` child or |False| if not present."""
semiHidden = self.semiHidden
if semiHidden is None:
return False
return semiHidden.val
@semiHidden_val.setter
def semiHidden_val(self, value):
self._remove_semiHidden()
if bool(value) is True:
semiHidden = self._add_semiHidden()
semiHidden.val = value
@property
def uiPriority_val(self):
"""Value of ``<w:uiPriority>`` child or |None| if not present."""
uiPriority = self.uiPriority
if uiPriority is None:
return None
return uiPriority.val
@uiPriority_val.setter
def uiPriority_val(self, value):
self._remove_uiPriority()
if value is not None:
uiPriority = self._add_uiPriority()
uiPriority.val = value
@property
def unhideWhenUsed_val(self):
"""Value of `w:unhideWhenUsed/@w:val` or |False| if not present."""
unhideWhenUsed = self.unhideWhenUsed
if unhideWhenUsed is None:
return False
return unhideWhenUsed.val
@unhideWhenUsed_val.setter
def unhideWhenUsed_val(self, value):
self._remove_unhideWhenUsed()
if bool(value) is True:
unhideWhenUsed = self._add_unhideWhenUsed()
unhideWhenUsed.val = value
class CT_Styles(BaseOxmlElement):
"""``<w:styles>`` element, the root element of a styles part, i.e. styles.xml."""
_tag_seq = ("w:docDefaults", "w:latentStyles", "w:style")
latentStyles = ZeroOrOne("w:latentStyles", successors=_tag_seq[2:])
style = ZeroOrMore("w:style", successors=())
del _tag_seq
def add_style_of_type(self, name, style_type, builtin):
"""Return a newly added `w:style` element having `name` and `style_type`.
`w:style/@customStyle` is set based on the value of `builtin`.
"""
style = self.add_style()
style.type = style_type
style.customStyle = None if builtin else True
style.styleId = styleId_from_name(name)
style.name_val = name
return style
def default_for(self, style_type):
"""Return `w:style[@w:type="*{style_type}*][-1]` or |None| if not found."""
default_styles_for_type = [
s for s in self._iter_styles() if s.type == style_type and s.default
]
if not default_styles_for_type:
return None
# spec calls for last default in document order
return default_styles_for_type[-1]
def get_by_id(self, styleId: str) -> CT_Style | None:
"""`w:style` child where @styleId = `styleId`.
|None| if not found.
"""
xpath = f'w:style[@w:styleId="{styleId}"]'
return next(iter(self.xpath(xpath)), None)
def get_by_name(self, name: str) -> CT_Style | None:
"""`w:style` child with `w:name` grandchild having value `name`.
|None| if not found.
"""
xpath = 'w:style[w:name/@w:val="%s"]' % name
return next(iter(self.xpath(xpath)), None)
def _iter_styles(self):
"""Generate each of the `w:style` child elements in document order."""
return (style for style in self.xpath("w:style"))