Spaces:
Paused
Paused
File size: 9,657 Bytes
cb1a5c9 | 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 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 | """Run-related proxy objects for python-docx, Run in particular."""
from __future__ import annotations
from typing import IO, TYPE_CHECKING, Iterator, cast
from docx.drawing import Drawing
from docx.enum.style import WD_STYLE_TYPE
from docx.enum.text import WD_BREAK
from docx.oxml.drawing import CT_Drawing
from docx.oxml.text.pagebreak import CT_LastRenderedPageBreak
from docx.shape import InlineShape
from docx.shared import StoryChild
from docx.styles.style import CharacterStyle
from docx.text.font import Font
from docx.text.pagebreak import RenderedPageBreak
if TYPE_CHECKING:
import docx.types as t
from docx.enum.text import WD_UNDERLINE
from docx.oxml.text.run import CT_R, CT_Text
from docx.shared import Length
class Run(StoryChild):
"""Proxy object wrapping `<w:r>` element.
Several of the properties on Run take a tri-state value, |True|, |False|, or |None|.
|True| and |False| correspond to on and off respectively. |None| indicates the
property is not specified directly on the run and its effective value is taken from
the style hierarchy.
"""
def __init__(self, r: CT_R, parent: t.ProvidesStoryPart):
super().__init__(parent)
self._r = self._element = self.element = r
def add_break(self, break_type: WD_BREAK = WD_BREAK.LINE):
"""Add a break element of `break_type` to this run.
`break_type` can take the values `WD_BREAK.LINE`, `WD_BREAK.PAGE`, and
`WD_BREAK.COLUMN` where `WD_BREAK` is imported from `docx.enum.text`.
`break_type` defaults to `WD_BREAK.LINE`.
"""
type_, clear = {
WD_BREAK.LINE: (None, None),
WD_BREAK.PAGE: ("page", None),
WD_BREAK.COLUMN: ("column", None),
WD_BREAK.LINE_CLEAR_LEFT: ("textWrapping", "left"),
WD_BREAK.LINE_CLEAR_RIGHT: ("textWrapping", "right"),
WD_BREAK.LINE_CLEAR_ALL: ("textWrapping", "all"),
}[break_type]
br = self._r.add_br()
if type_ is not None:
br.type = type_
if clear is not None:
br.clear = clear
def add_picture(
self,
image_path_or_stream: str | IO[bytes],
width: int | Length | None = None,
height: int | Length | None = None,
) -> InlineShape:
"""Return |InlineShape| containing image identified by `image_path_or_stream`.
The picture is added to the end of this run.
`image_path_or_stream` can be a path (a string) or a file-like object containing
a binary image.
If neither width nor height is specified, the picture appears at
its native size. If only one is specified, it is used to compute a scaling
factor that is then applied to the unspecified dimension, preserving the aspect
ratio of the image. The native size of the picture is calculated using the dots-
per-inch (dpi) value specified in the image file, defaulting to 72 dpi if no
value is specified, as is often the case.
"""
inline = self.part.new_pic_inline(image_path_or_stream, width, height)
self._r.add_drawing(inline)
return InlineShape(inline)
def add_tab(self) -> None:
"""Add a ``<w:tab/>`` element at the end of the run, which Word interprets as a
tab character."""
self._r.add_tab()
def add_text(self, text: str):
"""Returns a newly appended |_Text| object (corresponding to a new ``<w:t>``
child element) to the run, containing `text`.
Compare with the possibly more friendly approach of assigning text to the
:attr:`Run.text` property.
"""
t = self._r.add_t(text)
return _Text(t)
@property
def bold(self) -> bool | None:
"""Read/write tri-state value.
When |True|, causes the text of the run to appear in bold face. When |False|,
the text unconditionally appears non-bold. When |None| the bold setting for this
run is inherited from the style hierarchy.
"""
return self.font.bold
@bold.setter
def bold(self, value: bool | None):
self.font.bold = value
def clear(self):
"""Return reference to this run after removing all its content.
All run formatting is preserved.
"""
self._r.clear_content()
return self
@property
def contains_page_break(self) -> bool:
"""`True` when one or more rendered page-breaks occur in this run.
Note that "hard" page-breaks inserted by the author are not included. A hard
page-break gives rise to a rendered page-break in the right position so if those
were included that page-break would be "double-counted".
It would be very rare for multiple rendered page-breaks to occur in a single
run, but it is possible.
"""
return bool(self._r.lastRenderedPageBreaks)
@property
def font(self) -> Font:
"""The |Font| object providing access to the character formatting properties for
this run, such as font name and size."""
return Font(self._element)
@property
def italic(self) -> bool | None:
"""Read/write tri-state value.
When |True|, causes the text of the run to appear in italics. When |False|, the
text unconditionally appears non-italic. When |None| the italic setting for this
run is inherited from the style hierarchy.
"""
return self.font.italic
@italic.setter
def italic(self, value: bool | None):
self.font.italic = value
def iter_inner_content(self) -> Iterator[str | Drawing | RenderedPageBreak]:
"""Generate the content-items in this run in the order they appear.
NOTE: only content-types currently supported by `python-docx` are generated. In
this version, that is text and rendered page-breaks. Drawing is included but
currently only provides access to its XML element (CT_Drawing) on its
`._drawing` attribute. `Drawing` attributes and methods may be expanded in
future releases.
There are a number of element-types that can appear inside a run, but most of
those (w:br, w:cr, w:noBreakHyphen, w:t, w:tab) have a clear plain-text
equivalent. Any contiguous range of such elements is generated as a single
`str`. Rendered page-break and drawing elements are generated individually. Any
other elements are ignored.
"""
for item in self._r.inner_content_items:
if isinstance(item, str):
yield item
elif isinstance(item, CT_LastRenderedPageBreak):
yield RenderedPageBreak(item, self)
elif isinstance(item, CT_Drawing): # pyright: ignore[reportUnnecessaryIsInstance]
yield Drawing(item, self)
@property
def style(self) -> CharacterStyle:
"""Read/write.
A |CharacterStyle| object representing the character style applied to this run.
The default character style for the document (often `Default Character Font`) is
returned if the run has no directly-applied character style. Setting this
property to |None| removes any directly-applied character style.
"""
style_id = self._r.style
return cast(CharacterStyle, self.part.get_style(style_id, WD_STYLE_TYPE.CHARACTER))
@style.setter
def style(self, style_or_name: str | CharacterStyle | None):
style_id = self.part.get_style_id(style_or_name, WD_STYLE_TYPE.CHARACTER)
self._r.style = style_id
@property
def text(self) -> str:
"""String formed by concatenating the text equivalent of each run.
Each `<w:t>` element adds the text characters it contains. A `<w:tab/>` element
adds a `\\t` character. A `<w:cr/>` or `<w:br>` element each add a `\\n`
character. Note that a `<w:br>` element can indicate a page break or column
break as well as a line break. Only line-break `<w:br>` elements translate to
a `\\n` character. Others are ignored. All other content child elements, such as
`<w:drawing>`, are ignored.
Assigning text to this property has the reverse effect, translating each `\\t`
character to a `<w:tab/>` element and each `\\n` or `\\r` character to a
`<w:cr/>` element. Any existing run content is replaced. Run formatting is
preserved.
"""
return self._r.text
@text.setter
def text(self, text: str):
self._r.text = text
@property
def underline(self) -> bool | WD_UNDERLINE | None:
"""The underline style for this |Run|.
Value is one of |None|, |True|, |False|, or a member of :ref:`WdUnderline`.
A value of |None| indicates the run has no directly-applied underline value and
so will inherit the underline value of its containing paragraph. Assigning
|None| to this property removes any directly-applied underline value.
A value of |False| indicates a directly-applied setting of no underline,
overriding any inherited value.
A value of |True| indicates single underline.
The values from :ref:`WdUnderline` are used to specify other outline styles such
as double, wavy, and dotted.
"""
return self.font.underline
@underline.setter
def underline(self, value: bool):
self.font.underline = value
class _Text:
"""Proxy object wrapping `<w:t>` element."""
def __init__(self, t_elm: CT_Text):
super(_Text, self).__init__()
self._t = t_elm
|