From 9a8493718ad4896a45e20f95eff474713ab86700 Mon Sep 17 00:00:00 2001 From: sandeepsuryaprasad Date: Tue, 1 Jul 2025 22:34:28 +0530 Subject: [PATCH 1/5] simplified __convert_to_local_value by replacing complex conditional with singledispatch --- py/selenium/webdriver/common/bidi/script.py | 115 ++++++++++++-------- 1 file changed, 70 insertions(+), 45 deletions(-) diff --git a/py/selenium/webdriver/common/bidi/script.py b/py/selenium/webdriver/common/bidi/script.py index 74b8a3568ac3a..b402bb67d4242 100644 --- a/py/selenium/webdriver/common/bidi/script.py +++ b/py/selenium/webdriver/common/bidi/script.py @@ -18,6 +18,7 @@ import datetime import math from dataclasses import dataclass +from functools import singledispatchmethod from typing import Any, Optional from selenium.common.exceptions import WebDriverException @@ -232,6 +233,70 @@ def from_json(cls, json: dict[str, Any]) -> "RealmDestroyed": return cls(realm=json["realm"]) +class _SupportedTypes: + def __init__(self, script): + self.script = script + + @singledispatchmethod + def _type(self, value): + # default case for str and other types, convert to string + return {"type": "string", "value": str(value)} + + @_type.register + def _(self, value: None): + return {"type": "null"} + + @_type.register + def _(self, value: bool): + return {"type": "boolean", "value": value} + + @_type.register + def _(self, value: set): + return {"type": "set", "value": [self.script.convert_to_local_value(item) for item in value]} + + @_type.register + def _(self, value: list | tuple): + return {"type": "array", "value": [self.script.convert_to_local_value(item) for item in value]} + + @_type.register + def _(self, value: dict): + value = [ + [self.script.convert_to_local_value(k), self.script.convert_to_local_value(v)] for k, v in value.items() + ] + return {"type": "object", "value": value} + + @_type.register + def _(self, value: int): + JS_MAX_SAFE_INTEGER = 9007199254740991 + if value > JS_MAX_SAFE_INTEGER or value < -JS_MAX_SAFE_INTEGER: + return {"type": "bigint", "value": str(value)} + return {"type": "number", "value": value} + + @_type.register + def _(self, value: float): + if math.isnan(value): + return {"type": "number", "value": "NaN"} + elif math.isinf(value): + if value > 0: + return {"type": "number", "value": "Infinity"} + else: + return {"type": "number", "value": "-Infinity"} + elif value == 0.0 and math.copysign(1.0, value) < 0: + return {"type": "number", "value": "-0"} + return {"type": "number", "value": value} + + @_type.register + def _(self, value: datetime.datetime): + # Convert Python datetime to JavaScript Date (ISO 8601 format) + return {"type": "date", "value": value.isoformat() + "Z" if value.tzinfo is None else value.isoformat()} + + @_type.register + def _(self, value: datetime.date): + # Convert Python date to JavaScript Date + dt = datetime.datetime.combine(value, datetime.time.min).replace(tzinfo=datetime.timezone.utc) + return {"type": "date", "value": dt.isoformat()} + + class Script: """BiDi implementation of the script module.""" @@ -334,51 +399,11 @@ def __convert_to_local_value(self, value) -> dict: """ Converts a Python value to BiDi LocalValue format. """ - if value is None: - return {"type": "null"} - elif isinstance(value, bool): - return {"type": "boolean", "value": value} - elif isinstance(value, (int, float)): - if isinstance(value, float): - if math.isnan(value): - return {"type": "number", "value": "NaN"} - elif math.isinf(value): - if value > 0: - return {"type": "number", "value": "Infinity"} - else: - return {"type": "number", "value": "-Infinity"} - elif value == 0.0 and math.copysign(1.0, value) < 0: - return {"type": "number", "value": "-0"} - - JS_MAX_SAFE_INTEGER = 9007199254740991 - if isinstance(value, int) and (value > JS_MAX_SAFE_INTEGER or value < -JS_MAX_SAFE_INTEGER): - return {"type": "bigint", "value": str(value)} - - return {"type": "number", "value": value} - - elif isinstance(value, str): - return {"type": "string", "value": value} - elif isinstance(value, datetime.datetime): - # Convert Python datetime to JavaScript Date (ISO 8601 format) - return {"type": "date", "value": value.isoformat() + "Z" if value.tzinfo is None else value.isoformat()} - elif isinstance(value, datetime.date): - # Convert Python date to JavaScript Date - dt = datetime.datetime.combine(value, datetime.time.min).replace(tzinfo=datetime.timezone.utc) - return {"type": "date", "value": dt.isoformat()} - elif isinstance(value, set): - return {"type": "set", "value": [self.__convert_to_local_value(item) for item in value]} - elif isinstance(value, (list, tuple)): - return {"type": "array", "value": [self.__convert_to_local_value(item) for item in value]} - elif isinstance(value, dict): - return { - "type": "object", - "value": [ - [self.__convert_to_local_value(k), self.__convert_to_local_value(v)] for k, v in value.items() - ], - } - else: - # For other types, convert to string - return {"type": "string", "value": str(value)} + supported_types = _SupportedTypes(self) + return getattr(supported_types, "_type")(value) + + def convert_to_local_value(self, value) -> dict: + return self.__convert_to_local_value(value) # low-level APIs for script module def _add_preload_script( From 03476453c894ef97e858d6c11a911b2bdf17ae86 Mon Sep 17 00:00:00 2001 From: sandeepsuryaprasad Date: Wed, 2 Jul 2025 07:29:08 +0530 Subject: [PATCH 2/5] fixed linting --- py/selenium/webdriver/common/bidi/script.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/py/selenium/webdriver/common/bidi/script.py b/py/selenium/webdriver/common/bidi/script.py index b402bb67d4242..304f18930ae63 100644 --- a/py/selenium/webdriver/common/bidi/script.py +++ b/py/selenium/webdriver/common/bidi/script.py @@ -19,7 +19,7 @@ import math from dataclasses import dataclass from functools import singledispatchmethod -from typing import Any, Optional +from typing import Any, Optional, Union from selenium.common.exceptions import WebDriverException from selenium.webdriver.common.bidi.common import command_builder @@ -255,7 +255,7 @@ def _(self, value: set): return {"type": "set", "value": [self.script.convert_to_local_value(item) for item in value]} @_type.register - def _(self, value: list | tuple): + def _(self, value: Union[list, tuple]): return {"type": "array", "value": [self.script.convert_to_local_value(item) for item in value]} @_type.register From 10760e795a64a90e014c02e833627efc1e24b569 Mon Sep 17 00:00:00 2001 From: sandeepsuryaprasad Date: Wed, 2 Jul 2025 20:48:11 +0530 Subject: [PATCH 3/5] updated --- py/selenium/webdriver/common/bidi/script.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/py/selenium/webdriver/common/bidi/script.py b/py/selenium/webdriver/common/bidi/script.py index 304f18930ae63..0df50180cdfc1 100644 --- a/py/selenium/webdriver/common/bidi/script.py +++ b/py/selenium/webdriver/common/bidi/script.py @@ -19,7 +19,7 @@ import math from dataclasses import dataclass from functools import singledispatchmethod -from typing import Any, Optional, Union +from typing import Any, Optional, List, Tuple from selenium.common.exceptions import WebDriverException from selenium.webdriver.common.bidi.common import command_builder @@ -255,7 +255,11 @@ def _(self, value: set): return {"type": "set", "value": [self.script.convert_to_local_value(item) for item in value]} @_type.register - def _(self, value: Union[list, tuple]): + def _(self, value: List): + return {"type": "array", "value": [self.script.convert_to_local_value(item) for item in value]} + + @_type.register + def _(self, value: Tuple): return {"type": "array", "value": [self.script.convert_to_local_value(item) for item in value]} @_type.register From d7c0708c310b30b787bc471b44e8fab87bd942fb Mon Sep 17 00:00:00 2001 From: sandeepsuryaprasad Date: Wed, 2 Jul 2025 21:16:04 +0530 Subject: [PATCH 4/5] testing --- py/selenium/webdriver/common/bidi/script.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/py/selenium/webdriver/common/bidi/script.py b/py/selenium/webdriver/common/bidi/script.py index 0df50180cdfc1..7e04f9b4ff412 100644 --- a/py/selenium/webdriver/common/bidi/script.py +++ b/py/selenium/webdriver/common/bidi/script.py @@ -255,11 +255,11 @@ def _(self, value: set): return {"type": "set", "value": [self.script.convert_to_local_value(item) for item in value]} @_type.register - def _(self, value: List): + def _(self, value: list): return {"type": "array", "value": [self.script.convert_to_local_value(item) for item in value]} @_type.register - def _(self, value: Tuple): + def _(self, value: tuple): return {"type": "array", "value": [self.script.convert_to_local_value(item) for item in value]} @_type.register From e3e98e04d5868ac801a1cfe207199e2eca4cf54d Mon Sep 17 00:00:00 2001 From: sandeepsuryaprasad Date: Wed, 2 Jul 2025 21:37:47 +0530 Subject: [PATCH 5/5] testing --- py/selenium/webdriver/common/bidi/script.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/py/selenium/webdriver/common/bidi/script.py b/py/selenium/webdriver/common/bidi/script.py index 7e04f9b4ff412..aa96902227682 100644 --- a/py/selenium/webdriver/common/bidi/script.py +++ b/py/selenium/webdriver/common/bidi/script.py @@ -19,7 +19,7 @@ import math from dataclasses import dataclass from functools import singledispatchmethod -from typing import Any, Optional, List, Tuple +from typing import Any, Optional from selenium.common.exceptions import WebDriverException from selenium.webdriver.common.bidi.common import command_builder @@ -257,7 +257,7 @@ def _(self, value: set): @_type.register def _(self, value: list): return {"type": "array", "value": [self.script.convert_to_local_value(item) for item in value]} - + @_type.register def _(self, value: tuple): return {"type": "array", "value": [self.script.convert_to_local_value(item) for item in value]}