Path: blob/trunk/py/selenium/webdriver/common/print_page_options.py
1864 views
# Licensed to the Software Freedom Conservancy (SFC) under one1# or more contributor license agreements. See the NOTICE file2# distributed with this work for additional information3# regarding copyright ownership. The SFC licenses this file4# to you under the Apache License, Version 2.0 (the5# "License"); you may not use this file except in compliance6# with the License. You may obtain a copy of the License at7#8# http://www.apache.org/licenses/LICENSE-2.09#10# Unless required by applicable law or agreed to in writing,11# software distributed under the License is distributed on an12# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY13# KIND, either express or implied. See the License for the14# specific language governing permissions and limitations15# under the License.161718from typing import TYPE_CHECKING, Optional1920if TYPE_CHECKING:21from typing import Literal, TypedDict2223Orientation = Literal["portrait", "landscape"]2425class _MarginOpts(TypedDict, total=False):26left: float27right: float28top: float29bottom: float3031class _PageOpts(TypedDict, total=False):32width: float33height: float3435class _PrintOpts(TypedDict, total=False):36margin: _MarginOpts37page: _PageOpts38background: bool39orientation: Orientation40scale: float41shrinkToFit: bool42pageRanges: list[str]4344else:45from typing import Any4647Orientation = str48_MarginOpts = _PageOpts = _PrintOpts = dict[str, Any]495051class _PageSettingsDescriptor:52"""Descriptor which validates `height` and 'width' of page."""5354def __init__(self, name):55self.name = name5657def __get__(self, obj, cls) -> Optional[float]:58return obj._page.get(self.name, None)5960def __set__(self, obj, value) -> None:61getattr(obj, "_validate_num_property")(self.name, value)62obj._page[self.name] = value63obj._print_options["page"] = obj._page646566class _MarginSettingsDescriptor:67"""Descriptor which validates below attributes.6869- top70- bottom71- left72- right73"""7475def __init__(self, name):76self.name = name7778def __get__(self, obj, cls) -> Optional[float]:79return obj._margin.get(self.name, None)8081def __set__(self, obj, value) -> None:82getattr(obj, "_validate_num_property")(f"Margin {self.name}", value)83obj._margin[self.name] = value84obj._print_options["margin"] = obj._margin858687class _ScaleDescriptor:88"""Scale descriptor which validates scale."""8990def __init__(self, name):91self.name = name9293def __get__(self, obj, cls) -> Optional[float]:94return obj._print_options.get(self.name)9596def __set__(self, obj, value) -> None:97getattr(obj, "_validate_num_property")(self.name, value)98if value < 0.1 or value > 2:99raise ValueError("Value of scale should be between 0.1 and 2")100obj._print_options[self.name] = value101102103class _PageOrientationDescriptor:104"""PageOrientation descriptor which validates orientation of page."""105106ORIENTATION_VALUES = ["portrait", "landscape"]107108def __init__(self, name):109self.name = name110111def __get__(self, obj, cls) -> Optional[Orientation]:112return obj._print_options.get(self.name, None)113114def __set__(self, obj, value) -> None:115if value not in self.ORIENTATION_VALUES:116raise ValueError(f"Orientation value must be one of {self.ORIENTATION_VALUES}")117obj._print_options[self.name] = value118119120class _ValidateTypeDescriptor:121"""Base Class Descriptor which validates type of any subclass attribute."""122123def __init__(self, name, expected_type: type):124self.name = name125self.expected_type = expected_type126127def __get__(self, obj, cls):128return obj._print_options.get(self.name, None)129130def __set__(self, obj, value) -> None:131if not isinstance(value, self.expected_type):132raise ValueError(f"{self.name} should be of type {self.expected_type.__name__}")133obj._print_options[self.name] = value134135136class _ValidateBackGround(_ValidateTypeDescriptor):137"""Expected type of background attribute."""138139def __init__(self, name):140super().__init__(name, bool)141142143class _ValidateShrinkToFit(_ValidateTypeDescriptor):144"""Expected type of shrink to fit attribute."""145146def __init__(self, name):147super().__init__(name, bool)148149150class _ValidatePageRanges(_ValidateTypeDescriptor):151"""Expected type of page ranges attribute."""152153def __init__(self, name):154super().__init__(name, list)155156157class PrintOptions:158page_height = _PageSettingsDescriptor("height")159"""Gets and Sets page_height:160161Usage162-----163- Get164- `self.page_height`165- Set166- `self.page_height` = `value`167168Parameters:169-----------170`value`: `float`171172Returns:173--------174- Get175- `Optional[float]`176- Set177- `None`178"""179180page_width = _PageSettingsDescriptor("width")181"""Gets and Sets page_width:182183Usage:184------185- Get186- `self.page_width`187- Set188- `self.page_width` = `value`189190Parameters:191-----------192`value`: `float`193194Returns:195--------196- Get197- `Optional[float]`198- Set199- `None`200"""201202margin_top = _MarginSettingsDescriptor("top")203"""Gets and Sets margin_top:204205Usage:206------207- Get208- `self.margin_top`209- Set210- `self.margin_top` = `value`211212Parameters:213-----------214`value`: `float`215216Returns:217--------218- Get219- `Optional[float]`220- Set221- `None`222"""223224margin_bottom = _MarginSettingsDescriptor("bottom")225"""Gets and Sets margin_bottom:226227Usage:228------229- Get230- `self.margin_bottom`231- Set232- `self.margin_bottom` = `value`233234Parameters:235-----------236`value`: `float`237238Returns:239--------240- Get241- `Optional[float]`242- Set243- `None`244"""245246margin_left = _MarginSettingsDescriptor("left")247"""Gets and Sets margin_left:248249Usage:250------251- Get252- `self.margin_left`253- Set254- `self.margin_left` = `value`255256Parameters:257-----------258`value`: `float`259260Returns:261--------262- Get263- `Optional[float]`264- Set265- `None`266"""267268margin_right = _MarginSettingsDescriptor("right")269"""Gets and Sets margin_right:270271Usage:272------273- Get274- `self.margin_right`275- Set276- `self.margin_right` = `value`277278Parameters:279-----------280`value`: `float`281282Returns:283--------284- Get285- `Optional[float]`286- Set287- `None`288"""289290scale = _ScaleDescriptor("scale")291"""Gets and Sets scale:292293Usage:294------295- Get296- `self.scale`297- Set298- `self.scale` = `value`299300Parameters:301-----------302`value`: `float`303304Returns:305--------306- Get307- `Optional[float]`308- Set309- `None`310"""311312orientation = _PageOrientationDescriptor("orientation")313"""Gets and Sets orientation:314315Usage:316------317- Get318- `self.orientation`319- Set320- `self.orientation` = `value`321322Parameters:323-----------324`value`: `Orientation`325326Returns:327--------328- Get329- `Optional[Orientation]`330- Set331- `None`332"""333334background = _ValidateBackGround("background")335"""Gets and Sets background:336337Usage:338------339- Get340- `self.background`341- Set342- `self.background` = `value`343344Parameters:345-----------346`value`: `bool`347348Returns:349--------350- Get351- `Optional[bool]`352- Set353- `None`354"""355356shrink_to_fit = _ValidateShrinkToFit("shrinkToFit")357"""Gets and Sets shrink_to_fit:358359Usage:360------361- Get362- `self.shrink_to_fit`363- Set364- `self.shrink_to_fit` = `value`365366Parameters:367-----------368`value`: `bool`369370Returns:371--------372- Get373- `Optional[bool]`374- Set375- `None`376"""377378page_ranges = _ValidatePageRanges("pageRanges")379"""Gets and Sets page_ranges:380381Usage:382------383- Get384- `self.page_ranges`385- Set386- `self.page_ranges` = `value`387388Parameters:389-----------390`value`: ` List[str]`391392Returns:393--------394- Get395- `Optional[List[str]]`396- Set397- `None`398"""399# Reference for predefined page size constants: https://www.agooddaytoprint.com/page/paper-size-chart-faq400A4 = {"height": 29.7, "width": 21.0} # size in cm401LEGAL = {"height": 35.56, "width": 21.59} # size in cm402LETTER = {"height": 27.94, "width": 21.59} # size in cm403TABLOID = {"height": 43.18, "width": 27.94} # size in cm404405def __init__(self) -> None:406self._print_options: _PrintOpts = {}407self._page: _PageOpts = {408"height": PrintOptions.A4["height"],409"width": PrintOptions.A4["width"],410} # Default page size set to A4411self._margin: _MarginOpts = {}412413def to_dict(self) -> _PrintOpts:414""":Returns: A hash of print options configured."""415return self._print_options416417def set_page_size(self, page_size: dict) -> None:418"""Sets the page size to predefined or custom dimensions.419420Parameters:421-----------422page_size: dict423A dictionary containing `height` and `width` as keys with respective values.424425Example:426--------427self.set_page_size(PageSize.A4) # A4 predefined size428self.set_page_size({"height": 15.0, "width": 20.0}) # Custom size in cm429"""430self._validate_num_property("height", page_size["height"])431self._validate_num_property("width", page_size["width"])432self._page["height"] = page_size["height"]433self._page["width"] = page_size["width"]434self._print_options["page"] = self._page435436def _validate_num_property(self, property_name: str, value: float) -> None:437"""Helper function to validate some of the properties."""438if not isinstance(value, (int, float)):439raise ValueError(f"{property_name} should be an integer or a float")440441if value < 0:442raise ValueError(f"{property_name} cannot be less than 0")443444445