1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
# encoding: utf-8
"""Styles object, container for all objects in the styles part"""
from __future__ import absolute_import, division, print_function, unicode_literals
from warnings import warn
from docx.shared import ElementProxy
from docx.styles import BabelFish
from docx.styles.latent import LatentStyles
from docx.styles.style import BaseStyle, StyleFactory
class Styles(ElementProxy):
"""Provides access to the styles defined in a document.
Accessed using the :attr:`.Document.styles` property. Supports ``len()``, iteration,
and dictionary-style access by style name.
"""
__slots__ = ()
def __contains__(self, name):
"""
Enables `in` operator on style name.
"""
internal_name = BabelFish.ui2internal(name)
for style in self._element.style_lst:
if style.name_val == internal_name:
return True
return False
def __getitem__(self, key):
"""
Enables dictionary-style access by UI name. Lookup by style id is
deprecated, triggers a warning, and will be removed in a near-future
release.
"""
style_elm = self._element.get_by_name(BabelFish.ui2internal(key))
if style_elm is not None:
return StyleFactory(style_elm)
style_elm = self._element.get_by_id(key)
if style_elm is not None:
msg = (
'style lookup by style_id is deprecated. Use style name as '
'key instead.'
)
warn(msg, UserWarning, stacklevel=2)
return StyleFactory(style_elm)
raise KeyError("no style with name '%s'" % key)
def __iter__(self):
return (StyleFactory(style) for style in self._element.style_lst)
def __len__(self):
return len(self._element.style_lst)
def add_style(self, name, style_type, builtin=False):
"""
Return a newly added style object of *style_type* and identified
by *name*. A builtin style can be defined by passing True for the
optional *builtin* argument.
"""
style_name = BabelFish.ui2internal(name)
if style_name in self:
raise ValueError("document already contains style '%s'" % name)
style = self._element.add_style_of_type(
style_name, style_type, builtin
)
return StyleFactory(style)
def default(self, style_type):
"""
Return the default style for *style_type* or |None| if no default is
defined for that type (not common).
"""
style = self._element.default_for(style_type)
if style is None:
return None
return StyleFactory(style)
def get_by_id(self, style_id, style_type):
"""Return the style of *style_type* matching *style_id*.
Returns the default for *style_type* if *style_id* is not found or is |None|, or
if the style having *style_id* is not of *style_type*.
"""
if style_id is None:
return self.default(style_type)
return self._get_by_id(style_id, style_type)
def get_style_id(self, style_or_name, style_type):
"""
Return the id of the style corresponding to *style_or_name*, or
|None| if *style_or_name* is |None|. If *style_or_name* is not
a style object, the style is looked up using *style_or_name* as
a style name, raising |ValueError| if no style with that name is
defined. Raises |ValueError| if the target style is not of
*style_type*.
"""
if style_or_name is None:
return None
elif isinstance(style_or_name, BaseStyle):
return self._get_style_id_from_style(style_or_name, style_type)
else:
return self._get_style_id_from_name(style_or_name, style_type)
@property
def latent_styles(self):
"""
A |LatentStyles| object providing access to the default behaviors for
latent styles and the collection of |_LatentStyle| objects that
define overrides of those defaults for a particular named latent
style.
"""
return LatentStyles(self._element.get_or_add_latentStyles())
def _get_by_id(self, style_id, style_type):
"""
Return the style of *style_type* matching *style_id*. Returns the
default for *style_type* if *style_id* is not found or if the style
having *style_id* is not of *style_type*.
"""
style = self._element.get_by_id(style_id)
if style is None or style.type != style_type:
return self.default(style_type)
return StyleFactory(style)
def _get_style_id_from_name(self, style_name, style_type):
"""
Return the id of the style of *style_type* corresponding to
*style_name*. Returns |None| if that style is the default style for
*style_type*. Raises |ValueError| if the named style is not found in
the document or does not match *style_type*.
"""
return self._get_style_id_from_style(self[style_name], style_type)
def _get_style_id_from_style(self, style, style_type):
"""
Return the id of *style*, or |None| if it is the default style of
*style_type*. Raises |ValueError| if style is not of *style_type*.
"""
if style.type != style_type:
raise ValueError(
"assigned style is type %s, need type %s" %
(style.type, style_type)
)
if style == self.default(style_type):
return None
return style.style_id
|