Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
SeleniumHQ
GitHub Repository: SeleniumHQ/Selenium
Path: blob/trunk/py/selenium/webdriver/common/print_page_options.py
1864 views
1
# Licensed to the Software Freedom Conservancy (SFC) under one
2
# or more contributor license agreements. See the NOTICE file
3
# distributed with this work for additional information
4
# regarding copyright ownership. The SFC licenses this file
5
# to you under the Apache License, Version 2.0 (the
6
# "License"); you may not use this file except in compliance
7
# with the License. You may obtain a copy of the License at
8
#
9
# http://www.apache.org/licenses/LICENSE-2.0
10
#
11
# Unless required by applicable law or agreed to in writing,
12
# software distributed under the License is distributed on an
13
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
# KIND, either express or implied. See the License for the
15
# specific language governing permissions and limitations
16
# under the License.
17
18
19
from typing import TYPE_CHECKING, Optional
20
21
if TYPE_CHECKING:
22
from typing import Literal, TypedDict
23
24
Orientation = Literal["portrait", "landscape"]
25
26
class _MarginOpts(TypedDict, total=False):
27
left: float
28
right: float
29
top: float
30
bottom: float
31
32
class _PageOpts(TypedDict, total=False):
33
width: float
34
height: float
35
36
class _PrintOpts(TypedDict, total=False):
37
margin: _MarginOpts
38
page: _PageOpts
39
background: bool
40
orientation: Orientation
41
scale: float
42
shrinkToFit: bool
43
pageRanges: list[str]
44
45
else:
46
from typing import Any
47
48
Orientation = str
49
_MarginOpts = _PageOpts = _PrintOpts = dict[str, Any]
50
51
52
class _PageSettingsDescriptor:
53
"""Descriptor which validates `height` and 'width' of page."""
54
55
def __init__(self, name):
56
self.name = name
57
58
def __get__(self, obj, cls) -> Optional[float]:
59
return obj._page.get(self.name, None)
60
61
def __set__(self, obj, value) -> None:
62
getattr(obj, "_validate_num_property")(self.name, value)
63
obj._page[self.name] = value
64
obj._print_options["page"] = obj._page
65
66
67
class _MarginSettingsDescriptor:
68
"""Descriptor which validates below attributes.
69
70
- top
71
- bottom
72
- left
73
- right
74
"""
75
76
def __init__(self, name):
77
self.name = name
78
79
def __get__(self, obj, cls) -> Optional[float]:
80
return obj._margin.get(self.name, None)
81
82
def __set__(self, obj, value) -> None:
83
getattr(obj, "_validate_num_property")(f"Margin {self.name}", value)
84
obj._margin[self.name] = value
85
obj._print_options["margin"] = obj._margin
86
87
88
class _ScaleDescriptor:
89
"""Scale descriptor which validates scale."""
90
91
def __init__(self, name):
92
self.name = name
93
94
def __get__(self, obj, cls) -> Optional[float]:
95
return obj._print_options.get(self.name)
96
97
def __set__(self, obj, value) -> None:
98
getattr(obj, "_validate_num_property")(self.name, value)
99
if value < 0.1 or value > 2:
100
raise ValueError("Value of scale should be between 0.1 and 2")
101
obj._print_options[self.name] = value
102
103
104
class _PageOrientationDescriptor:
105
"""PageOrientation descriptor which validates orientation of page."""
106
107
ORIENTATION_VALUES = ["portrait", "landscape"]
108
109
def __init__(self, name):
110
self.name = name
111
112
def __get__(self, obj, cls) -> Optional[Orientation]:
113
return obj._print_options.get(self.name, None)
114
115
def __set__(self, obj, value) -> None:
116
if value not in self.ORIENTATION_VALUES:
117
raise ValueError(f"Orientation value must be one of {self.ORIENTATION_VALUES}")
118
obj._print_options[self.name] = value
119
120
121
class _ValidateTypeDescriptor:
122
"""Base Class Descriptor which validates type of any subclass attribute."""
123
124
def __init__(self, name, expected_type: type):
125
self.name = name
126
self.expected_type = expected_type
127
128
def __get__(self, obj, cls):
129
return obj._print_options.get(self.name, None)
130
131
def __set__(self, obj, value) -> None:
132
if not isinstance(value, self.expected_type):
133
raise ValueError(f"{self.name} should be of type {self.expected_type.__name__}")
134
obj._print_options[self.name] = value
135
136
137
class _ValidateBackGround(_ValidateTypeDescriptor):
138
"""Expected type of background attribute."""
139
140
def __init__(self, name):
141
super().__init__(name, bool)
142
143
144
class _ValidateShrinkToFit(_ValidateTypeDescriptor):
145
"""Expected type of shrink to fit attribute."""
146
147
def __init__(self, name):
148
super().__init__(name, bool)
149
150
151
class _ValidatePageRanges(_ValidateTypeDescriptor):
152
"""Expected type of page ranges attribute."""
153
154
def __init__(self, name):
155
super().__init__(name, list)
156
157
158
class PrintOptions:
159
page_height = _PageSettingsDescriptor("height")
160
"""Gets and Sets page_height:
161
162
Usage
163
-----
164
- Get
165
- `self.page_height`
166
- Set
167
- `self.page_height` = `value`
168
169
Parameters:
170
-----------
171
`value`: `float`
172
173
Returns:
174
--------
175
- Get
176
- `Optional[float]`
177
- Set
178
- `None`
179
"""
180
181
page_width = _PageSettingsDescriptor("width")
182
"""Gets and Sets page_width:
183
184
Usage:
185
------
186
- Get
187
- `self.page_width`
188
- Set
189
- `self.page_width` = `value`
190
191
Parameters:
192
-----------
193
`value`: `float`
194
195
Returns:
196
--------
197
- Get
198
- `Optional[float]`
199
- Set
200
- `None`
201
"""
202
203
margin_top = _MarginSettingsDescriptor("top")
204
"""Gets and Sets margin_top:
205
206
Usage:
207
------
208
- Get
209
- `self.margin_top`
210
- Set
211
- `self.margin_top` = `value`
212
213
Parameters:
214
-----------
215
`value`: `float`
216
217
Returns:
218
--------
219
- Get
220
- `Optional[float]`
221
- Set
222
- `None`
223
"""
224
225
margin_bottom = _MarginSettingsDescriptor("bottom")
226
"""Gets and Sets margin_bottom:
227
228
Usage:
229
------
230
- Get
231
- `self.margin_bottom`
232
- Set
233
- `self.margin_bottom` = `value`
234
235
Parameters:
236
-----------
237
`value`: `float`
238
239
Returns:
240
--------
241
- Get
242
- `Optional[float]`
243
- Set
244
- `None`
245
"""
246
247
margin_left = _MarginSettingsDescriptor("left")
248
"""Gets and Sets margin_left:
249
250
Usage:
251
------
252
- Get
253
- `self.margin_left`
254
- Set
255
- `self.margin_left` = `value`
256
257
Parameters:
258
-----------
259
`value`: `float`
260
261
Returns:
262
--------
263
- Get
264
- `Optional[float]`
265
- Set
266
- `None`
267
"""
268
269
margin_right = _MarginSettingsDescriptor("right")
270
"""Gets and Sets margin_right:
271
272
Usage:
273
------
274
- Get
275
- `self.margin_right`
276
- Set
277
- `self.margin_right` = `value`
278
279
Parameters:
280
-----------
281
`value`: `float`
282
283
Returns:
284
--------
285
- Get
286
- `Optional[float]`
287
- Set
288
- `None`
289
"""
290
291
scale = _ScaleDescriptor("scale")
292
"""Gets and Sets scale:
293
294
Usage:
295
------
296
- Get
297
- `self.scale`
298
- Set
299
- `self.scale` = `value`
300
301
Parameters:
302
-----------
303
`value`: `float`
304
305
Returns:
306
--------
307
- Get
308
- `Optional[float]`
309
- Set
310
- `None`
311
"""
312
313
orientation = _PageOrientationDescriptor("orientation")
314
"""Gets and Sets orientation:
315
316
Usage:
317
------
318
- Get
319
- `self.orientation`
320
- Set
321
- `self.orientation` = `value`
322
323
Parameters:
324
-----------
325
`value`: `Orientation`
326
327
Returns:
328
--------
329
- Get
330
- `Optional[Orientation]`
331
- Set
332
- `None`
333
"""
334
335
background = _ValidateBackGround("background")
336
"""Gets and Sets background:
337
338
Usage:
339
------
340
- Get
341
- `self.background`
342
- Set
343
- `self.background` = `value`
344
345
Parameters:
346
-----------
347
`value`: `bool`
348
349
Returns:
350
--------
351
- Get
352
- `Optional[bool]`
353
- Set
354
- `None`
355
"""
356
357
shrink_to_fit = _ValidateShrinkToFit("shrinkToFit")
358
"""Gets and Sets shrink_to_fit:
359
360
Usage:
361
------
362
- Get
363
- `self.shrink_to_fit`
364
- Set
365
- `self.shrink_to_fit` = `value`
366
367
Parameters:
368
-----------
369
`value`: `bool`
370
371
Returns:
372
--------
373
- Get
374
- `Optional[bool]`
375
- Set
376
- `None`
377
"""
378
379
page_ranges = _ValidatePageRanges("pageRanges")
380
"""Gets and Sets page_ranges:
381
382
Usage:
383
------
384
- Get
385
- `self.page_ranges`
386
- Set
387
- `self.page_ranges` = `value`
388
389
Parameters:
390
-----------
391
`value`: ` List[str]`
392
393
Returns:
394
--------
395
- Get
396
- `Optional[List[str]]`
397
- Set
398
- `None`
399
"""
400
# Reference for predefined page size constants: https://www.agooddaytoprint.com/page/paper-size-chart-faq
401
A4 = {"height": 29.7, "width": 21.0} # size in cm
402
LEGAL = {"height": 35.56, "width": 21.59} # size in cm
403
LETTER = {"height": 27.94, "width": 21.59} # size in cm
404
TABLOID = {"height": 43.18, "width": 27.94} # size in cm
405
406
def __init__(self) -> None:
407
self._print_options: _PrintOpts = {}
408
self._page: _PageOpts = {
409
"height": PrintOptions.A4["height"],
410
"width": PrintOptions.A4["width"],
411
} # Default page size set to A4
412
self._margin: _MarginOpts = {}
413
414
def to_dict(self) -> _PrintOpts:
415
""":Returns: A hash of print options configured."""
416
return self._print_options
417
418
def set_page_size(self, page_size: dict) -> None:
419
"""Sets the page size to predefined or custom dimensions.
420
421
Parameters:
422
-----------
423
page_size: dict
424
A dictionary containing `height` and `width` as keys with respective values.
425
426
Example:
427
--------
428
self.set_page_size(PageSize.A4) # A4 predefined size
429
self.set_page_size({"height": 15.0, "width": 20.0}) # Custom size in cm
430
"""
431
self._validate_num_property("height", page_size["height"])
432
self._validate_num_property("width", page_size["width"])
433
self._page["height"] = page_size["height"]
434
self._page["width"] = page_size["width"]
435
self._print_options["page"] = self._page
436
437
def _validate_num_property(self, property_name: str, value: float) -> None:
438
"""Helper function to validate some of the properties."""
439
if not isinstance(value, (int, float)):
440
raise ValueError(f"{property_name} should be an integer or a float")
441
442
if value < 0:
443
raise ValueError(f"{property_name} cannot be less than 0")
444
445