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
4054 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
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) -> float | None:
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) -> float | None:
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) -> float | None:
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) -> Orientation | None:
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
- Get: `self.page_height`
164
- Set: `self.page_height = value`
165
166
Args:
167
value: float value for page height.
168
169
Returns:
170
- Get: Optional[float]
171
- Set: None
172
"""
173
174
page_width = _PageSettingsDescriptor("width")
175
"""Gets and Sets page_width:
176
177
Usage:
178
- Get: `self.page_width`
179
- Set: `self.page_width = value`
180
181
Args:
182
value: float value for page width.
183
184
Returns:
185
- Get: Optional[float]
186
- Set: None
187
"""
188
189
margin_top = _MarginSettingsDescriptor("top")
190
"""Gets and Sets margin_top:
191
192
Usage:
193
- Get: `self.margin_top`
194
- Set: `self.margin_top = value`
195
196
Args:
197
value: float value for top margin.
198
199
Returns:
200
- Get: Optional[float]
201
- Set: None
202
"""
203
204
margin_bottom = _MarginSettingsDescriptor("bottom")
205
"""Gets and Sets margin_bottom:
206
207
Usage:
208
- Get: `self.margin_bottom`
209
- Set: `self.margin_bottom = value`
210
211
Args:
212
value: float value for bottom margin.
213
214
Returns:
215
- Get: Optional[float]
216
- Set: None
217
"""
218
219
margin_left = _MarginSettingsDescriptor("left")
220
"""Gets and Sets margin_left:
221
222
Usage:
223
- Get: `self.margin_left`
224
- Set: `self.margin_left = value`
225
226
Args:
227
value: float value for left margin.
228
229
Returns:
230
- Get: Optional[float]
231
- Set: None
232
"""
233
234
margin_right = _MarginSettingsDescriptor("right")
235
"""Gets and Sets margin_right:
236
237
Usage:
238
- Get: `self.margin_right`
239
- Set: `self.margin_right = value`
240
241
Args:
242
value: float value for right margin.
243
244
Returns:
245
- Get: Optional[float]
246
- Set: None
247
"""
248
249
scale = _ScaleDescriptor("scale")
250
"""Gets and Sets scale:
251
252
Usage:
253
- Get: `self.scale`
254
- Set: `self.scale = value`
255
256
Args:
257
value: float value for scale (between 0.1 and 2).
258
259
Returns:
260
- Get: Optional[float]
261
- Set: None
262
"""
263
264
orientation = _PageOrientationDescriptor("orientation")
265
"""Gets and Sets orientation:
266
267
Usage:
268
- Get: `self.orientation`
269
- Set: `self.orientation = value`
270
271
Args:
272
value: Orientation value ("portrait" or "landscape").
273
274
Returns:
275
- Get: Optional[Orientation]
276
- Set: None
277
"""
278
279
background = _ValidateBackGround("background")
280
"""Gets and Sets background:
281
282
Usage:
283
- Get: `self.background`
284
- Set: `self.background = value`
285
286
Args:
287
value: bool value for background printing.
288
289
Returns:
290
- Get: Optional[bool]
291
- Set: None
292
"""
293
294
shrink_to_fit = _ValidateShrinkToFit("shrinkToFit")
295
"""Gets and Sets shrink_to_fit:
296
297
Usage:
298
- Get: `self.shrink_to_fit`
299
- Set: `self.shrink_to_fit = value`
300
301
Args:
302
value: bool value for shrink to fit.
303
304
Returns:
305
- Get: Optional[bool]
306
- Set: None
307
"""
308
309
page_ranges = _ValidatePageRanges("pageRanges")
310
"""Gets and Sets page_ranges:
311
312
Usage:
313
- Get: `self.page_ranges`
314
- Set: `self.page_ranges = value`
315
316
Args:
317
value: list of page range strings.
318
319
Returns:
320
- Get: Optional[List[str]]
321
- Set: None
322
"""
323
# Reference for predefined page size constants: https://www.agooddaytoprint.com/page/paper-size-chart-faq
324
A4 = {"height": 29.7, "width": 21.0} # size in cm
325
LEGAL = {"height": 35.56, "width": 21.59} # size in cm
326
LETTER = {"height": 27.94, "width": 21.59} # size in cm
327
TABLOID = {"height": 43.18, "width": 27.94} # size in cm
328
329
def __init__(self) -> None:
330
self._print_options: _PrintOpts = {}
331
self._page: _PageOpts = {
332
"height": PrintOptions.A4["height"],
333
"width": PrintOptions.A4["width"],
334
} # Default page size set to A4
335
self._margin: _MarginOpts = {}
336
337
def to_dict(self) -> _PrintOpts:
338
"""Returns a hash of print options configured."""
339
return self._print_options
340
341
def set_page_size(self, page_size: dict) -> None:
342
"""Sets the page size to predefined or custom dimensions.
343
344
Args:
345
page_size: A dictionary containing 'height' and 'width' keys with
346
respective values in cm.
347
348
Example:
349
self.set_page_size(PageSize.A4) # A4 predefined size
350
self.set_page_size({"height": 15.0, "width": 20.0}) # Custom size
351
"""
352
self._validate_num_property("height", page_size["height"])
353
self._validate_num_property("width", page_size["width"])
354
self._page["height"] = page_size["height"]
355
self._page["width"] = page_size["width"]
356
self._print_options["page"] = self._page
357
358
def _validate_num_property(self, property_name: str, value: float) -> None:
359
"""Helper function to validate some of the properties."""
360
if not isinstance(value, (int, float)):
361
raise ValueError(f"{property_name} should be an integer or a float")
362
363
if value < 0:
364
raise ValueError(f"{property_name} cannot be less than 0")
365
366