55from typing import TYPE_CHECKING , Callable
66
77from docx .enum .dml import MSO_THEME_COLOR
8- from docx .enum .text import WD_COLOR , WD_UNDERLINE
9- from docx .oxml .ns import nsdecls , qn
8+ from docx .enum .text import WD_COLOR_INDEX , WD_UNDERLINE
9+ from docx .oxml .ns import nsdecls
1010from docx .oxml .parser import parse_xml
1111from docx .oxml .simpletypes import (
1212 ST_HexColor ,
2323
2424if TYPE_CHECKING :
2525 from docx .oxml .shared import CT_OnOff , CT_String
26+ from docx .shared import Length
2627
2728
2829class CT_Color (BaseOxmlElement ):
@@ -33,32 +34,50 @@ class CT_Color(BaseOxmlElement):
3334
3435
3536class CT_Fonts (BaseOxmlElement ):
36- """``<w:rFonts>`` element, specifying typeface name for the various language
37- types."""
37+ """`<w:rFonts>` element.
3838
39- ascii = OptionalAttribute ("w:ascii" , ST_String )
40- hAnsi = OptionalAttribute ("w:hAnsi" , ST_String )
39+ Specifies typeface name for the various language types.
40+ """
41+
42+ ascii : str | None = OptionalAttribute ( # pyright: ignore[reportGeneralTypeIssues]
43+ "w:ascii" , ST_String
44+ )
45+ hAnsi : str | None = OptionalAttribute ( # pyright: ignore[reportGeneralTypeIssues]
46+ "w:hAnsi" , ST_String
47+ )
4148
4249
4350class CT_Highlight (BaseOxmlElement ):
4451 """`w:highlight` element, specifying font highlighting/background color."""
4552
46- val = RequiredAttribute ("w:val" , WD_COLOR )
53+ val : WD_COLOR_INDEX = RequiredAttribute ( # pyright: ignore[reportGeneralTypeIssues]
54+ "w:val" , WD_COLOR_INDEX
55+ )
4756
4857
4958class CT_HpsMeasure (BaseOxmlElement ):
50- """Used for `` <w:sz>` ` element and others, specifying font size in half-points."""
59+ """Used for `<w:sz>` element and others, specifying font size in half-points."""
5160
52- val = RequiredAttribute ("w:val" , ST_HpsMeasure )
61+ val : Length = RequiredAttribute ( # pyright: ignore[reportGeneralTypeIssues]
62+ "w:val" , ST_HpsMeasure
63+ )
5364
5465
5566class CT_RPr (BaseOxmlElement ):
56- """`` <w:rPr>` ` element, containing the properties for a run."""
67+ """`<w:rPr>` element, containing the properties for a run."""
5768
58- _add_u : Callable [[], CT_Underline ]
69+ get_or_add_highlight : Callable [[], CT_Highlight ]
70+ get_or_add_rFonts : Callable [[], CT_Fonts ]
71+ get_or_add_sz : Callable [[], CT_HpsMeasure ]
72+ get_or_add_vertAlign : Callable [[], CT_VerticalAlignRun ]
5973 _add_rStyle : Callable [..., CT_String ]
60- _remove_u : Callable [[], None ]
74+ _add_u : Callable [[], CT_Underline ]
75+ _remove_highlight : Callable [[], None ]
76+ _remove_rFonts : Callable [[], None ]
6177 _remove_rStyle : Callable [[], None ]
78+ _remove_sz : Callable [[], None ]
79+ _remove_u : Callable [[], None ]
80+ _remove_vertAlign : Callable [[], None ]
6281
6382 _tag_seq = (
6483 "w:rStyle" ,
@@ -104,7 +123,9 @@ class CT_RPr(BaseOxmlElement):
104123 rStyle : CT_String | None = ZeroOrOne ( # pyright: ignore[reportGeneralTypeIssues]
105124 "w:rStyle" , successors = _tag_seq [1 :]
106125 )
107- rFonts = ZeroOrOne ("w:rFonts" , successors = _tag_seq [2 :])
126+ rFonts : CT_Fonts | None = ZeroOrOne ( # pyright: ignore[reportGeneralTypeIssues]
127+ "w:rFonts" , successors = _tag_seq [2 :]
128+ )
108129 b : CT_OnOff | None = ZeroOrOne ( # pyright: ignore[reportGeneralTypeIssues]
109130 "w:b" , successors = _tag_seq [3 :]
110131 )
@@ -124,12 +145,22 @@ class CT_RPr(BaseOxmlElement):
124145 vanish = ZeroOrOne ("w:vanish" , successors = _tag_seq [17 :])
125146 webHidden = ZeroOrOne ("w:webHidden" , successors = _tag_seq [18 :])
126147 color = ZeroOrOne ("w:color" , successors = _tag_seq [19 :])
127- sz = ZeroOrOne ("w:sz" , successors = _tag_seq [24 :])
128- highlight = ZeroOrOne ("w:highlight" , successors = _tag_seq [26 :])
148+ sz : CT_HpsMeasure | None = ZeroOrOne ( # pyright: ignore[reportGeneralTypeIssues]
149+ "w:sz" , successors = _tag_seq [24 :]
150+ )
151+ highlight : CT_Highlight | None = (
152+ ZeroOrOne ( # pyright: ignore[reportGeneralTypeIssues]
153+ "w:highlight" , successors = _tag_seq [26 :]
154+ )
155+ )
129156 u : CT_Underline | None = ZeroOrOne ( # pyright: ignore[reportGeneralTypeIssues]
130157 "w:u" , successors = _tag_seq [27 :]
131158 )
132- vertAlign = ZeroOrOne ("w:vertAlign" , successors = _tag_seq [32 :])
159+ vertAlign : CT_VerticalAlignRun | None = (
160+ ZeroOrOne ( # pyright: ignore[reportGeneralTypeIssues]
161+ "w:vertAlign" , successors = _tag_seq [32 :]
162+ )
163+ )
133164 rtl = ZeroOrOne ("w:rtl" , successors = _tag_seq [33 :])
134165 cs = ZeroOrOne ("w:cs" , successors = _tag_seq [34 :])
135166 specVanish = ZeroOrOne ("w:specVanish" , successors = _tag_seq [38 :])
@@ -141,24 +172,26 @@ def _new_color(self):
141172 return parse_xml ('<w:color %s w:val="000000"/>' % nsdecls ("w" ))
142173
143174 @property
144- def highlight_val (self ):
145- """Value of `w:highlight/@val` attribute, specifying a font's highlight color,
146- or `None` if the text is not highlighted."""
175+ def highlight_val (self ) -> WD_COLOR_INDEX | None :
176+ """Value of `./w:highlight/@val`.
177+
178+ Specifies font's highlight color, or `None` if the text is not highlighted.
179+ """
147180 highlight = self .highlight
148181 if highlight is None :
149182 return None
150183 return highlight .val
151184
152185 @highlight_val .setter
153- def highlight_val (self , value ) :
186+ def highlight_val (self , value : WD_COLOR_INDEX | None ) -> None :
154187 if value is None :
155188 self ._remove_highlight ()
156189 return
157190 highlight = self .get_or_add_highlight ()
158191 highlight .val = value
159192
160193 @property
161- def rFonts_ascii (self ):
194+ def rFonts_ascii (self ) -> str | None :
162195 """The value of `w:rFonts/@w:ascii` or |None| if not present.
163196
164197 Represents the assigned typeface name. The rFonts element also specifies other
@@ -171,23 +204,23 @@ def rFonts_ascii(self):
171204 return rFonts .ascii
172205
173206 @rFonts_ascii .setter
174- def rFonts_ascii (self , value ) :
207+ def rFonts_ascii (self , value : str | None ) -> None :
175208 if value is None :
176209 self ._remove_rFonts ()
177210 return
178211 rFonts = self .get_or_add_rFonts ()
179212 rFonts .ascii = value
180213
181214 @property
182- def rFonts_hAnsi (self ):
215+ def rFonts_hAnsi (self ) -> str | None :
183216 """The value of `w:rFonts/@w:hAnsi` or |None| if not present."""
184217 rFonts = self .rFonts
185218 if rFonts is None :
186219 return None
187220 return rFonts .hAnsi
188221
189222 @rFonts_hAnsi .setter
190- def rFonts_hAnsi (self , value ):
223+ def rFonts_hAnsi (self , value : str | None ):
191224 if value is None and self .rFonts is None :
192225 return
193226 rFonts = self .get_or_add_rFonts ()
@@ -215,8 +248,8 @@ def style(self, style: str | None) -> None:
215248 self .rStyle .val = style
216249
217250 @property
218- def subscript (self ):
219- """|True| if `w:vertAlign/@w:val` is ' subscript' .
251+ def subscript (self ) -> bool | None :
252+ """|True| if `./ w:vertAlign/@w:val` is " subscript" .
220253
221254 |False| if `w:vertAlign/@w:val` contains any other value. |None| if
222255 `w:vertAlign` is not present.
@@ -229,18 +262,20 @@ def subscript(self):
229262 return False
230263
231264 @subscript .setter
232- def subscript (self , value ) :
265+ def subscript (self , value : bool | None ) -> None :
233266 if value is None :
234267 self ._remove_vertAlign ()
235268 elif bool (value ) is True :
236269 self .get_or_add_vertAlign ().val = ST_VerticalAlignRun .SUBSCRIPT
237- elif self .vertAlign is None :
238- return
239- elif self .vertAlign .val == ST_VerticalAlignRun .SUBSCRIPT :
270+ # -- assert bool(value) is False --
271+ elif (
272+ self .vertAlign is not None
273+ and self .vertAlign .val == ST_VerticalAlignRun .SUBSCRIPT
274+ ):
240275 self ._remove_vertAlign ()
241276
242277 @property
243- def superscript (self ):
278+ def superscript (self ) -> bool | None :
244279 """|True| if `w:vertAlign/@w:val` is 'superscript'.
245280
246281 |False| if `w:vertAlign/@w:val` contains any other value. |None| if
@@ -254,34 +289,36 @@ def superscript(self):
254289 return False
255290
256291 @superscript .setter
257- def superscript (self , value ):
292+ def superscript (self , value : bool | None ):
258293 if value is None :
259294 self ._remove_vertAlign ()
260295 elif bool (value ) is True :
261296 self .get_or_add_vertAlign ().val = ST_VerticalAlignRun .SUPERSCRIPT
262- elif self .vertAlign is None :
263- return
264- elif self .vertAlign .val == ST_VerticalAlignRun .SUPERSCRIPT :
297+ # -- assert bool(value) is False --
298+ elif (
299+ self .vertAlign is not None
300+ and self .vertAlign .val == ST_VerticalAlignRun .SUPERSCRIPT
301+ ):
265302 self ._remove_vertAlign ()
266303
267304 @property
268- def sz_val (self ):
305+ def sz_val (self ) -> Length | None :
269306 """The value of `w:sz/@w:val` or |None| if not present."""
270307 sz = self .sz
271308 if sz is None :
272309 return None
273310 return sz .val
274311
275312 @sz_val .setter
276- def sz_val (self , value ):
313+ def sz_val (self , value : Length | None ):
277314 if value is None :
278315 self ._remove_sz ()
279316 return
280317 sz = self .get_or_add_sz ()
281318 sz .val = value
282319
283320 @property
284- def u_val (self ) -> bool | WD_UNDERLINE | None :
321+ def u_val (self ) -> WD_UNDERLINE | None :
285322 """Value of `w:u/@val`, or None if not present.
286323
287324 Values `WD_UNDERLINE.SINGLE` and `WD_UNDERLINE.NONE` are mapped to `True` and
@@ -293,7 +330,7 @@ def u_val(self) -> bool | WD_UNDERLINE | None:
293330 return u .val
294331
295332 @u_val .setter
296- def u_val (self , value : bool | WD_UNDERLINE | None ):
333+ def u_val (self , value : WD_UNDERLINE | None ):
297334 self ._remove_u ()
298335 if value is not None :
299336 self ._add_u ().val = value
@@ -314,38 +351,18 @@ def _set_bool_val(self, name: str, value: bool | None):
314351
315352
316353class CT_Underline (BaseOxmlElement ):
317- """`` <w:u>` ` element, specifying the underlining style for a run."""
354+ """`<w:u>` element, specifying the underlining style for a run."""
318355
319- @property
320- def val (self ) -> bool | WD_UNDERLINE | None :
321- """The underline type corresponding to the ``w:val`` attribute value."""
322- val = self .get (qn ("w:val" ))
323- underline = WD_UNDERLINE .from_xml (val )
324- return (
325- None
326- if underline == WD_UNDERLINE .INHERITED
327- else True
328- if underline == WD_UNDERLINE .SINGLE
329- else False
330- if underline == WD_UNDERLINE .NONE
331- else underline
356+ val : WD_UNDERLINE | None = (
357+ OptionalAttribute ( # pyright: ignore[reportGeneralTypeIssues]
358+ "w:val" , WD_UNDERLINE
332359 )
333-
334- @val .setter
335- def val (self , value : bool | WD_UNDERLINE | None ):
336- # works fine without these two mappings, but only because True == 1
337- # and False == 0, which happen to match the mapping for WD_UNDERLINE
338- # .SINGLE and .NONE respectively.
339- if value is True :
340- value = WD_UNDERLINE .SINGLE
341- elif value is False :
342- value = WD_UNDERLINE .NONE
343-
344- val = WD_UNDERLINE .to_xml (value )
345- self .set (qn ("w:val" ), val )
360+ )
346361
347362
348363class CT_VerticalAlignRun (BaseOxmlElement ):
349- """`` <w:vertAlign>` ` element, specifying subscript or superscript."""
364+ """`<w:vertAlign>` element, specifying subscript or superscript."""
350365
351- val = RequiredAttribute ("w:val" , ST_VerticalAlignRun )
366+ val : str = RequiredAttribute ( # pyright: ignore[reportGeneralTypeIssues]
367+ "w:val" , ST_VerticalAlignRun
368+ )
0 commit comments