Skip to content

Commit 9a84937

Browse files
simplified __convert_to_local_value by replacing complex conditional with singledispatch
1 parent 578bc2a commit 9a84937

File tree

1 file changed

+70
-45
lines changed

1 file changed

+70
-45
lines changed

py/selenium/webdriver/common/bidi/script.py

Lines changed: 70 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import datetime
1919
import math
2020
from dataclasses import dataclass
21+
from functools import singledispatchmethod
2122
from typing import Any, Optional
2223

2324
from selenium.common.exceptions import WebDriverException
@@ -232,6 +233,70 @@ def from_json(cls, json: dict[str, Any]) -> "RealmDestroyed":
232233
return cls(realm=json["realm"])
233234

234235

236+
class _SupportedTypes:
237+
def __init__(self, script):
238+
self.script = script
239+
240+
@singledispatchmethod
241+
def _type(self, value):
242+
# default case for str and other types, convert to string
243+
return {"type": "string", "value": str(value)}
244+
245+
@_type.register
246+
def _(self, value: None):
247+
return {"type": "null"}
248+
249+
@_type.register
250+
def _(self, value: bool):
251+
return {"type": "boolean", "value": value}
252+
253+
@_type.register
254+
def _(self, value: set):
255+
return {"type": "set", "value": [self.script.convert_to_local_value(item) for item in value]}
256+
257+
@_type.register
258+
def _(self, value: list | tuple):
259+
return {"type": "array", "value": [self.script.convert_to_local_value(item) for item in value]}
260+
261+
@_type.register
262+
def _(self, value: dict):
263+
value = [
264+
[self.script.convert_to_local_value(k), self.script.convert_to_local_value(v)] for k, v in value.items()
265+
]
266+
return {"type": "object", "value": value}
267+
268+
@_type.register
269+
def _(self, value: int):
270+
JS_MAX_SAFE_INTEGER = 9007199254740991
271+
if value > JS_MAX_SAFE_INTEGER or value < -JS_MAX_SAFE_INTEGER:
272+
return {"type": "bigint", "value": str(value)}
273+
return {"type": "number", "value": value}
274+
275+
@_type.register
276+
def _(self, value: float):
277+
if math.isnan(value):
278+
return {"type": "number", "value": "NaN"}
279+
elif math.isinf(value):
280+
if value > 0:
281+
return {"type": "number", "value": "Infinity"}
282+
else:
283+
return {"type": "number", "value": "-Infinity"}
284+
elif value == 0.0 and math.copysign(1.0, value) < 0:
285+
return {"type": "number", "value": "-0"}
286+
return {"type": "number", "value": value}
287+
288+
@_type.register
289+
def _(self, value: datetime.datetime):
290+
# Convert Python datetime to JavaScript Date (ISO 8601 format)
291+
return {"type": "date", "value": value.isoformat() + "Z" if value.tzinfo is None else value.isoformat()}
292+
293+
@_type.register
294+
def _(self, value: datetime.date):
295+
# Convert Python date to JavaScript Date
296+
dt = datetime.datetime.combine(value, datetime.time.min).replace(tzinfo=datetime.timezone.utc)
297+
return {"type": "date", "value": dt.isoformat()}
298+
299+
235300
class Script:
236301
"""BiDi implementation of the script module."""
237302

@@ -334,51 +399,11 @@ def __convert_to_local_value(self, value) -> dict:
334399
"""
335400
Converts a Python value to BiDi LocalValue format.
336401
"""
337-
if value is None:
338-
return {"type": "null"}
339-
elif isinstance(value, bool):
340-
return {"type": "boolean", "value": value}
341-
elif isinstance(value, (int, float)):
342-
if isinstance(value, float):
343-
if math.isnan(value):
344-
return {"type": "number", "value": "NaN"}
345-
elif math.isinf(value):
346-
if value > 0:
347-
return {"type": "number", "value": "Infinity"}
348-
else:
349-
return {"type": "number", "value": "-Infinity"}
350-
elif value == 0.0 and math.copysign(1.0, value) < 0:
351-
return {"type": "number", "value": "-0"}
352-
353-
JS_MAX_SAFE_INTEGER = 9007199254740991
354-
if isinstance(value, int) and (value > JS_MAX_SAFE_INTEGER or value < -JS_MAX_SAFE_INTEGER):
355-
return {"type": "bigint", "value": str(value)}
356-
357-
return {"type": "number", "value": value}
358-
359-
elif isinstance(value, str):
360-
return {"type": "string", "value": value}
361-
elif isinstance(value, datetime.datetime):
362-
# Convert Python datetime to JavaScript Date (ISO 8601 format)
363-
return {"type": "date", "value": value.isoformat() + "Z" if value.tzinfo is None else value.isoformat()}
364-
elif isinstance(value, datetime.date):
365-
# Convert Python date to JavaScript Date
366-
dt = datetime.datetime.combine(value, datetime.time.min).replace(tzinfo=datetime.timezone.utc)
367-
return {"type": "date", "value": dt.isoformat()}
368-
elif isinstance(value, set):
369-
return {"type": "set", "value": [self.__convert_to_local_value(item) for item in value]}
370-
elif isinstance(value, (list, tuple)):
371-
return {"type": "array", "value": [self.__convert_to_local_value(item) for item in value]}
372-
elif isinstance(value, dict):
373-
return {
374-
"type": "object",
375-
"value": [
376-
[self.__convert_to_local_value(k), self.__convert_to_local_value(v)] for k, v in value.items()
377-
],
378-
}
379-
else:
380-
# For other types, convert to string
381-
return {"type": "string", "value": str(value)}
402+
supported_types = _SupportedTypes(self)
403+
return getattr(supported_types, "_type")(value)
404+
405+
def convert_to_local_value(self, value) -> dict:
406+
return self.__convert_to_local_value(value)
382407

383408
# low-level APIs for script module
384409
def _add_preload_script(

0 commit comments

Comments
 (0)