Skip to content

Style Props

Mixin class for Style properties methods.

Classes:

Name Description
StyleProps

Mixin for Style properties methods.

StyleProps

Bases: StyleBase

Mixin for Style properties methods.

This class provides methods for getting, setting, and deleting properties associated with various style areas within an ODF document. It leverages StyleBase for fundamental style functionalities.

Methods:

Name Description
del_properties

Delete the given properties from the specified area.

get_list_style_properties

Get list style properties as a dictionary with enhanced values.

get_properties

Get the mapping of all properties of this style.

get_text_properties

Get text properties of style as a dictionary with enhanced values.

set_properties

Set the properties of the “area” type of this style.

Attributes:

Name Type Description
AREAS set[str]
Source code in odfdo/style_props.py
 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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
class StyleProps(StyleBase):
    """Mixin for Style properties methods.

    This class provides methods for getting, setting, and deleting properties
    associated with various style areas within an ODF document. It leverages
    `StyleBase` for fundamental style functionalities.
    """

    AREAS: ClassVar[set[str]] = {
        "chart",
        "drawing-page",
        "graphic",
        "header-footer",
        "list-level",
        "page-layout",
        "paragraph",
        "ruby",
        "section",
        "table",
        "table-cell",
        "table-column",
        "table-row",
        "text",
    }

    def _check_area(self, area: str | None) -> str:
        """Validate the provided area or use the style's family as default.

        Args:
            area: The area to check. If None, uses the style's family.

        Returns:
            str: The validated area.

        Raises:
            ValueError: If the area is not a recognized type.
        """
        if area is None:
            area = self.family
        if area not in StyleProps.AREAS:
            raise ValueError(f"Unexpected area value: {area!r}")
        return area

    def get_properties(self, area: str | None = None) -> PropDict | None:
        """Get the mapping of all properties of this style.

        By default, retrieves properties of the same family as the style (e.g.,
        paragraph properties for a paragraph style). Specify the `area` to get
        properties from a different area (e.g., text properties of a paragraph style).

        Args:
            area: The specific area of properties to retrieve
                (e.g., 'text', 'paragraph').

        Returns:
            dict[str, str | dict] | None: A dictionary of properties, or None if no properties are found.
        """
        try:
            area = self._check_area(area)
        except ValueError:
            return None
        element = self.get_element(f"style:{area}-properties")
        if element is None:
            return None
        properties: PropDict = dict(element.attributes)
        # Nested properties are nested dictionaries
        for child in element.children:
            properties[child.tag] = dict(child.attributes)
        return properties

    @staticmethod
    def _update_boolean_styles(props: dict[str, str | bool]) -> None:
        """Update a dictionary of style properties with boolean values for common text attributes.

        This static method adds or updates 'color', 'background_color', 'italic',
        'bold', 'fixed', 'underline', and 'strike' keys in the provided `props`
        dictionary based on existing OpenDocument style attributes.

        Args:
            props: The dictionary of style properties to update.
        """
        strike = props.get("style:text-line-through-style", "")
        if strike == "none":
            strike = ""
        underline = props.get("style:text-underline-style", "")
        if underline == "none":
            underline = ""
        props.update(
            {
                "color": props.get("fo:color") or "",
                "background_color": props.get("fo:background-color") or "",
                "italic": props.get("fo:font-style", "") == "italic",
                "bold": props.get("fo:font-weight", "") == "bold",
                "fixed": props.get("style:font-pitch", "") == "fixed",
                "underline": bool(underline),
                "strike": bool(strike),
            }
        )

    def get_list_style_properties(self) -> dict[str, str | bool]:
        """Get list style properties as a dictionary with enhanced values.

        Enhanced values returned:
        - "color": str
        - "background_color": str
        - "italic": bool
        - "bold": bool
        - "fixed": bool
        - "underline": bool
        - "strike": bool

        Returns:
            dict[str, str | bool]: A dictionary containing list style properties.
        """
        return self.get_text_properties()

    def get_text_properties(self) -> dict[str, str | bool]:
        """Get text properties of style as a dictionary with enhanced values.

        Enhanced values returned:
        - "color": str
        - "background_color": str
        - "italic": bool
        - "bold": bool
        - "fixed": bool
        - "underline": bool
        - "strike": bool

        Returns:
            dict[str, str | bool]: A dictionary containing text properties.
        """
        props = self.get_properties(area="text") or {}
        self._update_boolean_styles(props)  # type: ignore[arg-type]
        return props  # type: ignore[return-value]

    @staticmethod
    def _apply_valid_properties(
        properties_element: Element,
        area: str,
        properties: PropDict,
    ) -> None:
        # first filter only valid known properties
        allowed = STYLE_ATTRIBUTES.get(area)
        if allowed:
            for key, value in properties.items():
                if key in allowed or (
                    USE_LO_EXTENSIONS
                    and ":" in key
                    and key.split(":", 1)[0] in _OFFICE_PREFIX_EXTENSIONS_NAMES
                ):
                    if isinstance(value, (str, bool, tuple)):
                        properties_element.set_attribute(key, value)
                else:
                    msg = f"{key!r} property not allowed in <{properties_element.tag}>"
                    warn(msg, stacklevel=2)
        else:
            for key, value in properties.items():
                if isinstance(value, (str, bool, tuple)):
                    properties_element.set_attribute(key, value)

    def set_properties(
        self,
        properties: PropDict | None = None,
        style: StyleBase | None = None,
        area: str | None = None,
        **kwargs: Any,
    ) -> None:
        """Set the properties of the "area" type of this style.

        Properties are given either as a dict or as named arguments (or both).
        The area is identical to the style family by default. If the
        properties element is missing, it is created.

        Instead of properties, you can pass a style with properties of the
        same area. These will be copied.

        Args:
            properties (dict, optional): A dictionary of properties to set.
            style (StyleBase, optional): Another StyleBase object from which
                to copy properties.
            area (str, optional): The specific area of properties to set
                (e.g., 'paragraph', 'text').
            **kwargs: Arbitrary keyword arguments representing properties to set.
        """
        area = self._check_area(area)
        if properties is None:
            properties = {}
        element = self.get_element(f"style:{area}-properties")
        if element is None:
            element = Element.from_tag(f"style:{area}-properties")
            self.append(element)
        working_properties: PropDict
        if properties or kwargs:
            working_properties = _expand_properties_dict(
                _merge_dicts(properties, kwargs)
            )
        elif style is not None:
            style_props = style.get_properties(area=area)
            if style_props is None:
                return
            working_properties = style_props
        else:
            working_properties = {}
        for key, value in working_properties.items():
            if value is None:
                with contextlib.suppress(KeyError):
                    element.del_attribute(key)
        self._apply_valid_properties(element, area, working_properties)

    def del_properties(
        self,
        properties: list[str] | None = None,
        area: str | None = None,
    ) -> None:
        """Delete the given properties from the specified `area`.

        Properties can be specified either as a list argument or as positional
        arguments. Properties are removed only from the given area, which
        defaults to the style's family.

        Args:
            properties: A list of property names to delete.
            area: The specific area from which to delete properties.
        """
        area = self._check_area(area)
        if properties is None:
            properties = []
        element = self.get_element(f"style:{area}-properties")
        if element is None:
            raise ValueError(
                f"The Properties element is non-existent for: style:{area}-properties"
            )
        for key in _expand_properties_list(properties):
            with contextlib.suppress(KeyError):
                element.del_attribute(key)

AREAS class-attribute

AREAS: set[str] = {
    "chart",
    "drawing-page",
    "graphic",
    "header-footer",
    "list-level",
    "page-layout",
    "paragraph",
    "ruby",
    "section",
    "table",
    "table-cell",
    "table-column",
    "table-row",
    "text",
}

_apply_valid_properties staticmethod

_apply_valid_properties(
    properties_element: Element,
    area: str,
    properties: PropDict,
) -> None
Source code in odfdo/style_props.py
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
@staticmethod
def _apply_valid_properties(
    properties_element: Element,
    area: str,
    properties: PropDict,
) -> None:
    # first filter only valid known properties
    allowed = STYLE_ATTRIBUTES.get(area)
    if allowed:
        for key, value in properties.items():
            if key in allowed or (
                USE_LO_EXTENSIONS
                and ":" in key
                and key.split(":", 1)[0] in _OFFICE_PREFIX_EXTENSIONS_NAMES
            ):
                if isinstance(value, (str, bool, tuple)):
                    properties_element.set_attribute(key, value)
            else:
                msg = f"{key!r} property not allowed in <{properties_element.tag}>"
                warn(msg, stacklevel=2)
    else:
        for key, value in properties.items():
            if isinstance(value, (str, bool, tuple)):
                properties_element.set_attribute(key, value)

_check_area

_check_area(area: str | None) -> str

Validate the provided area or use the style’s family as default.

Parameters:

Name Type Description Default
area str | None

The area to check. If None, uses the style’s family.

required

Returns:

Name Type Description
str str

The validated area.

Raises:

Type Description
ValueError

If the area is not a recognized type.

Source code in odfdo/style_props.py
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
def _check_area(self, area: str | None) -> str:
    """Validate the provided area or use the style's family as default.

    Args:
        area: The area to check. If None, uses the style's family.

    Returns:
        str: The validated area.

    Raises:
        ValueError: If the area is not a recognized type.
    """
    if area is None:
        area = self.family
    if area not in StyleProps.AREAS:
        raise ValueError(f"Unexpected area value: {area!r}")
    return area

_update_boolean_styles staticmethod

_update_boolean_styles(
    props: dict[str, str | bool],
) -> None

Update a dictionary of style properties with boolean values for common text attributes.

This static method adds or updates ‘color’, ‘background_color’, ‘italic’, ‘bold’, ‘fixed’, ‘underline’, and ‘strike’ keys in the provided props dictionary based on existing OpenDocument style attributes.

Parameters:

Name Type Description Default
props dict[str, str | bool]

The dictionary of style properties to update.

required
Source code in odfdo/style_props.py
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
@staticmethod
def _update_boolean_styles(props: dict[str, str | bool]) -> None:
    """Update a dictionary of style properties with boolean values for common text attributes.

    This static method adds or updates 'color', 'background_color', 'italic',
    'bold', 'fixed', 'underline', and 'strike' keys in the provided `props`
    dictionary based on existing OpenDocument style attributes.

    Args:
        props: The dictionary of style properties to update.
    """
    strike = props.get("style:text-line-through-style", "")
    if strike == "none":
        strike = ""
    underline = props.get("style:text-underline-style", "")
    if underline == "none":
        underline = ""
    props.update(
        {
            "color": props.get("fo:color") or "",
            "background_color": props.get("fo:background-color") or "",
            "italic": props.get("fo:font-style", "") == "italic",
            "bold": props.get("fo:font-weight", "") == "bold",
            "fixed": props.get("style:font-pitch", "") == "fixed",
            "underline": bool(underline),
            "strike": bool(strike),
        }
    )

del_properties

del_properties(
    properties: list[str] | None = None,
    area: str | None = None,
) -> None

Delete the given properties from the specified area.

Properties can be specified either as a list argument or as positional arguments. Properties are removed only from the given area, which defaults to the style’s family.

Parameters:

Name Type Description Default
properties list[str] | None

A list of property names to delete.

None
area str | None

The specific area from which to delete properties.

None
Source code in odfdo/style_props.py
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
def del_properties(
    self,
    properties: list[str] | None = None,
    area: str | None = None,
) -> None:
    """Delete the given properties from the specified `area`.

    Properties can be specified either as a list argument or as positional
    arguments. Properties are removed only from the given area, which
    defaults to the style's family.

    Args:
        properties: A list of property names to delete.
        area: The specific area from which to delete properties.
    """
    area = self._check_area(area)
    if properties is None:
        properties = []
    element = self.get_element(f"style:{area}-properties")
    if element is None:
        raise ValueError(
            f"The Properties element is non-existent for: style:{area}-properties"
        )
    for key in _expand_properties_list(properties):
        with contextlib.suppress(KeyError):
            element.del_attribute(key)

get_list_style_properties

get_list_style_properties() -> dict[str, str | bool]

Get list style properties as a dictionary with enhanced values.

Enhanced values returned: - “color”: str - “background_color”: str - “italic”: bool - “bold”: bool - “fixed”: bool - “underline”: bool - “strike”: bool

Returns:

Type Description
dict[str, str | bool]

dict[str, str | bool]: A dictionary containing list style properties.

Source code in odfdo/style_props.py
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
def get_list_style_properties(self) -> dict[str, str | bool]:
    """Get list style properties as a dictionary with enhanced values.

    Enhanced values returned:
    - "color": str
    - "background_color": str
    - "italic": bool
    - "bold": bool
    - "fixed": bool
    - "underline": bool
    - "strike": bool

    Returns:
        dict[str, str | bool]: A dictionary containing list style properties.
    """
    return self.get_text_properties()

get_properties

get_properties(area: str | None = None) -> PropDict | None

Get the mapping of all properties of this style.

By default, retrieves properties of the same family as the style (e.g., paragraph properties for a paragraph style). Specify the area to get properties from a different area (e.g., text properties of a paragraph style).

Parameters:

Name Type Description Default
area str | None

The specific area of properties to retrieve (e.g., ‘text’, ‘paragraph’).

None

Returns:

Type Description
PropDict | None

dict[str, str | dict] | None: A dictionary of properties, or None if no properties are found.

Source code in odfdo/style_props.py
 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
def get_properties(self, area: str | None = None) -> PropDict | None:
    """Get the mapping of all properties of this style.

    By default, retrieves properties of the same family as the style (e.g.,
    paragraph properties for a paragraph style). Specify the `area` to get
    properties from a different area (e.g., text properties of a paragraph style).

    Args:
        area: The specific area of properties to retrieve
            (e.g., 'text', 'paragraph').

    Returns:
        dict[str, str | dict] | None: A dictionary of properties, or None if no properties are found.
    """
    try:
        area = self._check_area(area)
    except ValueError:
        return None
    element = self.get_element(f"style:{area}-properties")
    if element is None:
        return None
    properties: PropDict = dict(element.attributes)
    # Nested properties are nested dictionaries
    for child in element.children:
        properties[child.tag] = dict(child.attributes)
    return properties

get_text_properties

get_text_properties() -> dict[str, str | bool]

Get text properties of style as a dictionary with enhanced values.

Enhanced values returned: - “color”: str - “background_color”: str - “italic”: bool - “bold”: bool - “fixed”: bool - “underline”: bool - “strike”: bool

Returns:

Type Description
dict[str, str | bool]

dict[str, str | bool]: A dictionary containing text properties.

Source code in odfdo/style_props.py
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
def get_text_properties(self) -> dict[str, str | bool]:
    """Get text properties of style as a dictionary with enhanced values.

    Enhanced values returned:
    - "color": str
    - "background_color": str
    - "italic": bool
    - "bold": bool
    - "fixed": bool
    - "underline": bool
    - "strike": bool

    Returns:
        dict[str, str | bool]: A dictionary containing text properties.
    """
    props = self.get_properties(area="text") or {}
    self._update_boolean_styles(props)  # type: ignore[arg-type]
    return props  # type: ignore[return-value]

set_properties

set_properties(
    properties: PropDict | None = None,
    style: StyleBase | None = None,
    area: str | None = None,
    **kwargs: Any,
) -> None

Set the properties of the “area” type of this style.

Properties are given either as a dict or as named arguments (or both). The area is identical to the style family by default. If the properties element is missing, it is created.

Instead of properties, you can pass a style with properties of the same area. These will be copied.

Parameters:

Name Type Description Default
properties dict

A dictionary of properties to set.

None
style StyleBase

Another StyleBase object from which to copy properties.

None
area str

The specific area of properties to set (e.g., ‘paragraph’, ‘text’).

None
**kwargs Any

Arbitrary keyword arguments representing properties to set.

{}
Source code in odfdo/style_props.py
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
def set_properties(
    self,
    properties: PropDict | None = None,
    style: StyleBase | None = None,
    area: str | None = None,
    **kwargs: Any,
) -> None:
    """Set the properties of the "area" type of this style.

    Properties are given either as a dict or as named arguments (or both).
    The area is identical to the style family by default. If the
    properties element is missing, it is created.

    Instead of properties, you can pass a style with properties of the
    same area. These will be copied.

    Args:
        properties (dict, optional): A dictionary of properties to set.
        style (StyleBase, optional): Another StyleBase object from which
            to copy properties.
        area (str, optional): The specific area of properties to set
            (e.g., 'paragraph', 'text').
        **kwargs: Arbitrary keyword arguments representing properties to set.
    """
    area = self._check_area(area)
    if properties is None:
        properties = {}
    element = self.get_element(f"style:{area}-properties")
    if element is None:
        element = Element.from_tag(f"style:{area}-properties")
        self.append(element)
    working_properties: PropDict
    if properties or kwargs:
        working_properties = _expand_properties_dict(
            _merge_dicts(properties, kwargs)
        )
    elif style is not None:
        style_props = style.get_properties(area=area)
        if style_props is None:
            return
        working_properties = style_props
    else:
        working_properties = {}
    for key, value in working_properties.items():
        if value is None:
            with contextlib.suppress(KeyError):
                element.del_attribute(key)
    self._apply_valid_properties(element, area, working_properties)