1
+ # pyright: reportImportCycles=false
2
+
1
3
"""Simple-type classes, corresponding to ST_* schema items.
2
4
3
5
These provide validation and format translation for values stored in XML element
7
9
8
10
from __future__ import annotations
9
11
10
- from typing import TYPE_CHECKING , Any
12
+ from typing import TYPE_CHECKING , Any , Tuple
11
13
12
14
from docx .exceptions import InvalidXmlError
13
15
from docx .shared import Emu , Pt , RGBColor , Twips
14
16
15
17
if TYPE_CHECKING :
16
- from docx import types as t
17
18
from docx .shared import Length
18
19
19
20
20
21
class BaseSimpleType :
21
22
"""Base class for simple-types."""
22
23
23
24
@classmethod
24
- def from_xml (cls , xml_value : str ):
25
+ def from_xml (cls , xml_value : str ) -> Any :
25
26
return cls .convert_from_xml (xml_value )
26
27
27
28
@classmethod
28
- def to_xml (cls , value ) :
29
+ def to_xml (cls , value : Any ) -> str :
29
30
cls .validate (value )
30
31
str_value = cls .convert_to_xml (value )
31
32
return str_value
32
33
33
34
@classmethod
34
- def convert_from_xml (cls , str_value : str ) -> t . AbstractSimpleTypeMember :
35
+ def convert_from_xml (cls , str_value : str ) -> Any :
35
36
return int (str_value )
36
37
37
38
@classmethod
38
- def validate_int (cls , value ):
39
+ def convert_to_xml (cls , value : Any ) -> str :
40
+ ...
41
+
42
+ @classmethod
43
+ def validate (cls , value : Any ) -> None :
44
+ ...
45
+
46
+ @classmethod
47
+ def validate_int (cls , value : object ):
39
48
if not isinstance (value , int ):
40
49
raise TypeError ("value must be <type 'int'>, got %s" % type (value ))
41
50
42
51
@classmethod
43
- def validate_int_in_range (cls , value , min_inclusive , max_inclusive ):
52
+ def validate_int_in_range (
53
+ cls , value : int , min_inclusive : int , max_inclusive : int
54
+ ) -> None :
44
55
cls .validate_int (value )
45
56
if value < min_inclusive or value > max_inclusive :
46
57
raise ValueError (
@@ -57,15 +68,15 @@ def validate_string(cls, value: Any) -> str:
57
68
58
69
class BaseIntType (BaseSimpleType ):
59
70
@classmethod
60
- def convert_from_xml (cls , str_value ) :
71
+ def convert_from_xml (cls , str_value : str ) -> int :
61
72
return int (str_value )
62
73
63
74
@classmethod
64
- def convert_to_xml (cls , value ) :
75
+ def convert_to_xml (cls , value : int ) -> str :
65
76
return str (value )
66
77
67
78
@classmethod
68
- def validate (cls , value ) :
79
+ def validate (cls , value : Any ) -> None :
69
80
cls .validate_int (value )
70
81
71
82
@@ -84,34 +95,38 @@ def validate(cls, value: str):
84
95
85
96
86
97
class BaseStringEnumerationType (BaseStringType ):
98
+ _members : Tuple [str , ...]
99
+
87
100
@classmethod
88
- def validate (cls , value ) :
101
+ def validate (cls , value : Any ) -> None :
89
102
cls .validate_string (value )
90
103
if value not in cls ._members :
91
104
raise ValueError ("must be one of %s, got '%s'" % (cls ._members , value ))
92
105
93
106
94
107
class XsdAnyUri (BaseStringType ):
95
- """There's a regular expression this is supposed to meet but so far thinking
96
- spending cycles on validating wouldn't be worth it for the number of programming
97
- errors it would catch."""
108
+ """There's a regex in the spec this is supposed to meet...
109
+
110
+ but current assessment is that spending cycles on validating wouldn't be worth it
111
+ for the number of programming errors it would catch.
112
+ """
98
113
99
114
100
115
class XsdBoolean (BaseSimpleType ):
101
116
@classmethod
102
- def convert_from_xml (cls , str_value ) :
117
+ def convert_from_xml (cls , str_value : str ) -> bool :
103
118
if str_value not in ("1" , "0" , "true" , "false" ):
104
119
raise InvalidXmlError (
105
120
"value must be one of '1', '0', 'true' or 'false', got '%s'" % str_value
106
121
)
107
122
return str_value in ("1" , "true" )
108
123
109
124
@classmethod
110
- def convert_to_xml (cls , value ) :
125
+ def convert_to_xml (cls , value : bool ) -> str :
111
126
return {True : "1" , False : "0" }[value ]
112
127
113
128
@classmethod
114
- def validate (cls , value ) :
129
+ def validate (cls , value : Any ) -> None :
115
130
if value not in (True , False ):
116
131
raise TypeError (
117
132
"only True or False (and possibly None) may be assigned, got"
@@ -130,13 +145,13 @@ class XsdId(BaseStringType):
130
145
131
146
class XsdInt (BaseIntType ):
132
147
@classmethod
133
- def validate (cls , value ) :
148
+ def validate (cls , value : Any ) -> None :
134
149
cls .validate_int_in_range (value , - 2147483648 , 2147483647 )
135
150
136
151
137
152
class XsdLong (BaseIntType ):
138
153
@classmethod
139
- def validate (cls , value ) :
154
+ def validate (cls , value : Any ) -> None :
140
155
cls .validate_int_in_range (value , - 9223372036854775808 , 9223372036854775807 )
141
156
142
157
@@ -157,13 +172,13 @@ class XsdToken(BaseStringType):
157
172
158
173
class XsdUnsignedInt (BaseIntType ):
159
174
@classmethod
160
- def validate (cls , value ) :
175
+ def validate (cls , value : Any ) -> None :
161
176
cls .validate_int_in_range (value , 0 , 4294967295 )
162
177
163
178
164
179
class XsdUnsignedLong (BaseIntType ):
165
180
@classmethod
166
- def validate (cls , value ) :
181
+ def validate (cls , value : Any ) -> None :
167
182
cls .validate_int_in_range (value , 0 , 18446744073709551615 )
168
183
169
184
@@ -178,7 +193,7 @@ def validate(cls, value: str) -> None:
178
193
179
194
class ST_BrType (XsdString ):
180
195
@classmethod
181
- def validate (cls , value ) :
196
+ def validate (cls , value : Any ) -> None :
182
197
cls .validate_string (value )
183
198
valid_values = ("page" , "column" , "textWrapping" )
184
199
if value not in valid_values :
@@ -187,19 +202,19 @@ def validate(cls, value):
187
202
188
203
class ST_Coordinate (BaseIntType ):
189
204
@classmethod
190
- def convert_from_xml (cls , str_value ) :
205
+ def convert_from_xml (cls , str_value : str ) -> Length :
191
206
if "i" in str_value or "m" in str_value or "p" in str_value :
192
207
return ST_UniversalMeasure .convert_from_xml (str_value )
193
208
return Emu (int (str_value ))
194
209
195
210
@classmethod
196
- def validate (cls , value ) :
211
+ def validate (cls , value : Any ) -> None :
197
212
ST_CoordinateUnqualified .validate (value )
198
213
199
214
200
215
class ST_CoordinateUnqualified (XsdLong ):
201
216
@classmethod
202
- def validate (cls , value ) :
217
+ def validate (cls , value : Any ) -> None :
203
218
cls .validate_int_in_range (value , - 27273042329600 , 27273042316900 )
204
219
205
220
@@ -213,19 +228,23 @@ class ST_DrawingElementId(XsdUnsignedInt):
213
228
214
229
class ST_HexColor (BaseStringType ):
215
230
@classmethod
216
- def convert_from_xml (cls , str_value ):
231
+ def convert_from_xml ( # pyright: ignore[reportIncompatibleMethodOverride]
232
+ cls , str_value : str
233
+ ) -> RGBColor | str :
217
234
if str_value == "auto" :
218
235
return ST_HexColorAuto .AUTO
219
236
return RGBColor .from_string (str_value )
220
237
221
238
@classmethod
222
- def convert_to_xml (cls , value ):
239
+ def convert_to_xml ( # pyright: ignore[reportIncompatibleMethodOverride]
240
+ cls , value : RGBColor
241
+ ) -> str :
223
242
"""Keep alpha hex numerals all uppercase just for consistency."""
224
243
# expecting 3-tuple of ints in range 0-255
225
244
return "%02X%02X%02X" % value
226
245
227
246
@classmethod
228
- def validate (cls , value ) :
247
+ def validate (cls , value : Any ) -> None :
229
248
# must be an RGBColor object ---
230
249
if not isinstance (value , RGBColor ):
231
250
raise ValueError (
@@ -269,7 +288,7 @@ class ST_Merge(XsdStringEnumeration):
269
288
270
289
class ST_OnOff (XsdBoolean ):
271
290
@classmethod
272
- def convert_from_xml (cls , str_value ) :
291
+ def convert_from_xml (cls , str_value : str ) -> bool :
273
292
if str_value not in ("1" , "0" , "true" , "false" , "on" , "off" ):
274
293
raise InvalidXmlError (
275
294
"value must be one of '1', '0', 'true', 'false', 'on', or 'o"
@@ -280,11 +299,11 @@ def convert_from_xml(cls, str_value):
280
299
281
300
class ST_PositiveCoordinate (XsdLong ):
282
301
@classmethod
283
- def convert_from_xml (cls , str_value ) :
302
+ def convert_from_xml (cls , str_value : str ) -> Length :
284
303
return Emu (int (str_value ))
285
304
286
305
@classmethod
287
- def validate (cls , value ) :
306
+ def validate (cls , value : Any ) -> None :
288
307
cls .validate_int_in_range (value , 0 , 27273042316900 )
289
308
290
309
@@ -294,13 +313,13 @@ class ST_RelationshipId(XsdString):
294
313
295
314
class ST_SignedTwipsMeasure (XsdInt ):
296
315
@classmethod
297
- def convert_from_xml (cls , str_value ) :
316
+ def convert_from_xml (cls , str_value : str ) -> Length :
298
317
if "i" in str_value or "m" in str_value or "p" in str_value :
299
318
return ST_UniversalMeasure .convert_from_xml (str_value )
300
319
return Twips (int (str_value ))
301
320
302
321
@classmethod
303
- def convert_to_xml (cls , value ) :
322
+ def convert_to_xml (cls , value : int | Length ) -> str :
304
323
emu = Emu (value )
305
324
twips = emu .twips
306
325
return str (twips )
@@ -312,7 +331,7 @@ class ST_String(XsdString):
312
331
313
332
class ST_TblLayoutType (XsdString ):
314
333
@classmethod
315
- def validate (cls , value ) :
334
+ def validate (cls , value : Any ) -> None :
316
335
cls .validate_string (value )
317
336
valid_values = ("fixed" , "autofit" )
318
337
if value not in valid_values :
@@ -321,7 +340,7 @@ def validate(cls, value):
321
340
322
341
class ST_TblWidth (XsdString ):
323
342
@classmethod
324
- def validate (cls , value ) :
343
+ def validate (cls , value : Any ) -> None :
325
344
cls .validate_string (value )
326
345
valid_values = ("auto" , "dxa" , "nil" , "pct" )
327
346
if value not in valid_values :
@@ -330,13 +349,13 @@ def validate(cls, value):
330
349
331
350
class ST_TwipsMeasure (XsdUnsignedLong ):
332
351
@classmethod
333
- def convert_from_xml (cls , str_value ) :
352
+ def convert_from_xml (cls , str_value : str ) -> Length :
334
353
if "i" in str_value or "m" in str_value or "p" in str_value :
335
354
return ST_UniversalMeasure .convert_from_xml (str_value )
336
355
return Twips (int (str_value ))
337
356
338
357
@classmethod
339
- def convert_to_xml (cls , value ) :
358
+ def convert_to_xml (cls , value : int | Length ) -> str :
340
359
emu = Emu (value )
341
360
twips = emu .twips
342
361
return str (twips )
0 commit comments