File: styles.py

package info (click to toggle)
python-docx 0.8.11%2Bdfsg1-5
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 6,640 kB
  • sloc: xml: 25,311; python: 21,911; makefile: 168
file content (153 lines) | stat: -rw-r--r-- 5,637 bytes parent folder | download
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