Skip to content

Commit 09a4b24

Browse files
authored
[py] Upgrade type hints (SeleniumHQ#15784)
- Upgrade type hints to Python 3.9+ syntax throughout codebase - Replace legacy List, Dict, Tuple, etc. with built-in generics (e.g., list, dict, tuple) - Move type hints to use collections.abc where appropriate
1 parent 79a0939 commit 09a4b24

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+201
-205
lines changed

py/selenium/common/exceptions.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
# under the License.
1717
"""Exceptions that may happen in all the webdriver code."""
1818

19-
from typing import Optional, Sequence
19+
from collections.abc import Sequence
20+
from typing import Optional
2021

2122
SUPPORT_MSG = "For documentation on this error, please visit:"
2223
ERROR_URL = "https://www.selenium.dev/documentation/webdriver/troubleshooting/errors"

py/selenium/types.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@
1616
# under the License.
1717
"""Selenium type definitions."""
1818

19-
from typing import IO, Any, Iterable, Type, Union
19+
from collections.abc import Iterable
20+
from typing import IO, Any, Union
2021

2122
AnyKey = Union[str, int, float]
22-
WaitExcTypes = Iterable[Type[Exception]]
23+
WaitExcTypes = Iterable[type[Exception]]
2324

2425
# Service Types
2526
SubprocessStdAlias = Union[int, str, IO[Any]]

py/selenium/webdriver/chrome/service.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
# under the License.
1717

1818

19-
from typing import List, Mapping, Optional
19+
from collections.abc import Mapping
20+
from typing import Optional
2021

2122
from selenium.types import SubprocessStdAlias
2223
from selenium.webdriver.chromium import service
@@ -37,7 +38,7 @@ def __init__(
3738
self,
3839
executable_path: Optional[str] = None,
3940
port: int = 0,
40-
service_args: Optional[List[str]] = None,
41+
service_args: Optional[list[str]] = None,
4142
log_output: Optional[SubprocessStdAlias] = None,
4243
env: Optional[Mapping[str, str]] = None,
4344
**kwargs,

py/selenium/webdriver/chromium/options.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
import base64
1919
import os
20-
from typing import BinaryIO, Dict, List, Optional, Union
20+
from typing import BinaryIO, Optional, Union
2121

2222
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
2323
from selenium.webdriver.common.options import ArgOptions
@@ -29,9 +29,9 @@ class ChromiumOptions(ArgOptions):
2929
def __init__(self) -> None:
3030
super().__init__()
3131
self._binary_location: str = ""
32-
self._extension_files: List[str] = []
33-
self._extensions: List[str] = []
34-
self._experimental_options: Dict[str, Union[str, int, dict, List[str]]] = {}
32+
self._extension_files: list[str] = []
33+
self._extensions: list[str] = []
34+
self._experimental_options: dict[str, Union[str, int, dict, list[str]]] = {}
3535
self._debugger_address: Optional[str] = None
3636

3737
@property
@@ -68,7 +68,7 @@ def debugger_address(self, value: str) -> None:
6868
self._debugger_address = value
6969

7070
@property
71-
def extensions(self) -> List[str]:
71+
def extensions(self) -> list[str]:
7272
""":Returns: A list of encoded extensions that will be loaded."""
7373

7474
def _decode(file_data: BinaryIO) -> str:
@@ -117,7 +117,7 @@ def experimental_options(self) -> dict:
117117
""":Returns: A dictionary of experimental options for chromium."""
118118
return self._experimental_options
119119

120-
def add_experimental_option(self, name: str, value: Union[str, int, dict, List[str]]) -> None:
120+
def add_experimental_option(self, name: str, value: Union[str, int, dict, list[str]]) -> None:
121121
"""Adds an experimental option which is passed to chromium.
122122
123123
:Args:

py/selenium/webdriver/chromium/service.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@
1414
# KIND, either express or implied. See the License for the
1515
# specific language governing permissions and limitations
1616
# under the License.
17+
from collections.abc import Mapping
1718
from io import IOBase
18-
from typing import List, Mapping, Optional
19+
from typing import Optional
1920

2021
from selenium.types import SubprocessStdAlias
2122
from selenium.webdriver.common import service
@@ -37,7 +38,7 @@ def __init__(
3738
self,
3839
executable_path: Optional[str] = None,
3940
port: int = 0,
40-
service_args: Optional[List[str]] = None,
41+
service_args: Optional[list[str]] = None,
4142
log_output: Optional[SubprocessStdAlias] = None,
4243
env: Optional[Mapping[str, str]] = None,
4344
driver_path_env_key: Optional[str] = None,
@@ -63,5 +64,5 @@ def __init__(
6364
**kwargs,
6465
)
6566

66-
def command_line_args(self) -> List[str]:
67+
def command_line_args(self) -> list[str]:
6768
return [f"--port={self.port}"] + self.service_args

py/selenium/webdriver/common/actions/action_builder.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# specific language governing permissions and limitations
1616
# under the License.
1717

18-
from typing import List, Optional, Union
18+
from typing import Optional, Union
1919

2020
from selenium.webdriver.remote.command import Command
2121

@@ -61,11 +61,11 @@ def get_device_with(self, name: str) -> Optional[Union["WheelInput", "PointerInp
6161
return next(filter(lambda x: x == name, self.devices), None)
6262

6363
@property
64-
def pointer_inputs(self) -> List[PointerInput]:
64+
def pointer_inputs(self) -> list[PointerInput]:
6565
return [device for device in self.devices if device.type == interaction.POINTER]
6666

6767
@property
68-
def key_inputs(self) -> List[KeyInput]:
68+
def key_inputs(self) -> list[KeyInput]:
6969
return [device for device in self.devices if device.type == interaction.KEY]
7070

7171
@property

py/selenium/webdriver/common/actions/input_device.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@
1616
# under the License.
1717

1818
import uuid
19-
from typing import Any, List, Optional
19+
from typing import Any, Optional
2020

2121

2222
class InputDevice:
2323
"""Describes the input device being used for the action."""
2424

2525
def __init__(self, name: Optional[str] = None):
2626
self.name = name or uuid.uuid4()
27-
self.actions: List[Any] = []
27+
self.actions: list[Any] = []
2828

2929
def add_action(self, action: Any) -> None:
3030
""""""

py/selenium/webdriver/common/actions/interaction.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
# KIND, either express or implied. See the License for the
1515
# specific language governing permissions and limitations
1616
# under the License.
17-
from typing import Dict, Union
17+
from typing import Union
1818

1919
KEY = "key"
2020
POINTER = "pointer"
@@ -41,5 +41,5 @@ def __init__(self, source, duration: float = 0) -> None:
4141
super().__init__(source)
4242
self.duration = duration
4343

44-
def encode(self) -> Dict[str, Union[str, int]]:
44+
def encode(self) -> dict[str, Union[str, int]]:
4545
return {"type": self.PAUSE, "duration": int(self.duration * 1000)}

py/selenium/webdriver/common/actions/pointer_input.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# specific language governing permissions and limitations
1616
# under the License.
1717

18-
from typing import Any, Dict, Optional, Union
18+
from typing import Any, Optional, Union
1919

2020
from selenium.common.exceptions import InvalidArgumentException
2121
from selenium.webdriver.remote.webelement import WebElement
@@ -66,7 +66,7 @@ def create_pause(self, pause_duration: Union[int, float] = 0) -> None:
6666
def encode(self):
6767
return {"type": self.type, "parameters": {"pointerType": self.kind}, "id": self.name, "actions": self.actions}
6868

69-
def _convert_keys(self, actions: Dict[str, Any]):
69+
def _convert_keys(self, actions: dict[str, Any]):
7070
out = {}
7171
for k, v in actions.items():
7272
if v is None:

py/selenium/webdriver/common/bidi/browser.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
# specific language governing permissions and limitations
1616
# under the License.
1717

18-
from typing import Dict, List
1918

2019
from selenium.webdriver.common.bidi.common import command_builder
2120

@@ -114,7 +113,7 @@ def is_active(self) -> bool:
114113
return self.active
115114

116115
@classmethod
117-
def from_dict(cls, data: Dict) -> "ClientWindowInfo":
116+
def from_dict(cls, data: dict) -> "ClientWindowInfo":
118117
"""Creates a ClientWindowInfo instance from a dictionary.
119118
120119
Parameters:
@@ -154,7 +153,7 @@ def create_user_context(self) -> str:
154153
result = self.conn.execute(command_builder("browser.createUserContext", {}))
155154
return result["userContext"]
156155

157-
def get_user_contexts(self) -> List[str]:
156+
def get_user_contexts(self) -> list[str]:
158157
"""Gets all user contexts.
159158
160159
Returns:
@@ -181,7 +180,7 @@ def remove_user_context(self, user_context_id: str) -> None:
181180
params = {"userContext": user_context_id}
182181
self.conn.execute(command_builder("browser.removeUserContext", params))
183182

184-
def get_client_windows(self) -> List[ClientWindowInfo]:
183+
def get_client_windows(self) -> list[ClientWindowInfo]:
185184
"""Gets all client windows.
186185
187186
Returns:

py/selenium/webdriver/common/bidi/browsing_context.py

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# specific language governing permissions and limitations
1616
# under the License.
1717

18-
from typing import Dict, List, Optional, Union
18+
from typing import Optional, Union
1919

2020
from selenium.webdriver.common.bidi.common import command_builder
2121

@@ -55,7 +55,7 @@ def __init__(
5555
self.url = url
5656

5757
@classmethod
58-
def from_json(cls, json: Dict) -> "NavigationInfo":
58+
def from_json(cls, json: dict) -> "NavigationInfo":
5959
"""Creates a NavigationInfo instance from a dictionary.
6060
6161
Parameters:
@@ -81,7 +81,7 @@ def __init__(
8181
self,
8282
context: str,
8383
url: str,
84-
children: Optional[List["BrowsingContextInfo"]],
84+
children: Optional[list["BrowsingContextInfo"]],
8585
parent: Optional[str] = None,
8686
user_context: Optional[str] = None,
8787
original_opener: Optional[str] = None,
@@ -96,7 +96,7 @@ def __init__(
9696
self.client_window = client_window
9797

9898
@classmethod
99-
def from_json(cls, json: Dict) -> "BrowsingContextInfo":
99+
def from_json(cls, json: dict) -> "BrowsingContextInfo":
100100
"""Creates a BrowsingContextInfo instance from a dictionary.
101101
102102
Parameters:
@@ -137,7 +137,7 @@ def __init__(
137137
self.suggested_filename = suggested_filename
138138

139139
@classmethod
140-
def from_json(cls, json: Dict) -> "DownloadWillBeginParams":
140+
def from_json(cls, json: dict) -> "DownloadWillBeginParams":
141141
"""Creates a DownloadWillBeginParams instance from a dictionary.
142142
143143
Parameters:
@@ -175,7 +175,7 @@ def __init__(
175175
self.default_value = default_value
176176

177177
@classmethod
178-
def from_json(cls, json: Dict) -> "UserPromptOpenedParams":
178+
def from_json(cls, json: dict) -> "UserPromptOpenedParams":
179179
"""Creates a UserPromptOpenedParams instance from a dictionary.
180180
181181
Parameters:
@@ -211,7 +211,7 @@ def __init__(
211211
self.user_text = user_text
212212

213213
@classmethod
214-
def from_json(cls, json: Dict) -> "UserPromptClosedParams":
214+
def from_json(cls, json: dict) -> "UserPromptClosedParams":
215215
"""Creates a UserPromptClosedParams instance from a dictionary.
216216
217217
Parameters:
@@ -242,7 +242,7 @@ def __init__(
242242
self.url = url
243243

244244
@classmethod
245-
def from_json(cls, json: Dict) -> "HistoryUpdatedParams":
245+
def from_json(cls, json: dict) -> "HistoryUpdatedParams":
246246
"""Creates a HistoryUpdatedParams instance from a dictionary.
247247
248248
Parameters:
@@ -267,7 +267,7 @@ def __init__(self, event_class: str, **kwargs):
267267
self.params = kwargs
268268

269269
@classmethod
270-
def from_json(cls, json: Dict) -> "BrowsingContextEvent":
270+
def from_json(cls, json: dict) -> "BrowsingContextEvent":
271271
"""Creates a BrowsingContextEvent instance from a dictionary.
272272
273273
Parameters:
@@ -323,8 +323,8 @@ def capture_screenshot(
323323
self,
324324
context: str,
325325
origin: str = "viewport",
326-
format: Optional[Dict] = None,
327-
clip: Optional[Dict] = None,
326+
format: Optional[dict] = None,
327+
clip: Optional[dict] = None,
328328
) -> str:
329329
"""Captures an image of the given navigable, and returns it as a Base64-encoded string.
330330
@@ -398,7 +398,7 @@ def get_tree(
398398
self,
399399
max_depth: Optional[int] = None,
400400
root: Optional[str] = None,
401-
) -> List[BrowsingContextInfo]:
401+
) -> list[BrowsingContextInfo]:
402402
"""Returns a tree of all descendent navigables including the given parent itself, or all top-level contexts
403403
when no parent is provided.
404404
@@ -445,11 +445,11 @@ def handle_user_prompt(
445445
def locate_nodes(
446446
self,
447447
context: str,
448-
locator: Dict,
448+
locator: dict,
449449
max_node_count: Optional[int] = None,
450-
serialization_options: Optional[Dict] = None,
451-
start_nodes: Optional[List[Dict]] = None,
452-
) -> List[Dict]:
450+
serialization_options: Optional[dict] = None,
451+
start_nodes: Optional[list[dict]] = None,
452+
) -> list[dict]:
453453
"""Returns a list of all nodes matching the specified locator.
454454
455455
Parameters:
@@ -480,7 +480,7 @@ def navigate(
480480
context: str,
481481
url: str,
482482
wait: Optional[str] = None,
483-
) -> Dict:
483+
) -> dict:
484484
"""Navigates a navigable to the given URL.
485485
486486
Parameters:
@@ -504,10 +504,10 @@ def print(
504504
self,
505505
context: str,
506506
background: bool = False,
507-
margin: Optional[Dict] = None,
507+
margin: Optional[dict] = None,
508508
orientation: str = "portrait",
509-
page: Optional[Dict] = None,
510-
page_ranges: Optional[List[Union[int, str]]] = None,
509+
page: Optional[dict] = None,
510+
page_ranges: Optional[list[Union[int, str]]] = None,
511511
scale: float = 1.0,
512512
shrink_to_fit: bool = True,
513513
) -> str:
@@ -551,7 +551,7 @@ def reload(
551551
context: str,
552552
ignore_cache: Optional[bool] = None,
553553
wait: Optional[str] = None,
554-
) -> Dict:
554+
) -> dict:
555555
"""Reloads a navigable.
556556
557557
Parameters:
@@ -576,9 +576,9 @@ def reload(
576576
def set_viewport(
577577
self,
578578
context: Optional[str] = None,
579-
viewport: Optional[Dict] = None,
579+
viewport: Optional[dict] = None,
580580
device_pixel_ratio: Optional[float] = None,
581-
user_contexts: Optional[List[str]] = None,
581+
user_contexts: Optional[list[str]] = None,
582582
) -> None:
583583
"""Modifies specific viewport characteristics on the given top-level traversable.
584584
@@ -605,7 +605,7 @@ def set_viewport(
605605

606606
self.conn.execute(command_builder("browsingContext.setViewport", params))
607607

608-
def traverse_history(self, context: str, delta: int) -> Dict:
608+
def traverse_history(self, context: str, delta: int) -> dict:
609609
"""Traverses the history of a given navigable by a delta.
610610
611611
Parameters:
@@ -665,7 +665,7 @@ def _callback(event_data):
665665

666666
return callback_id
667667

668-
def add_event_handler(self, event: str, callback: callable, contexts: Optional[List[str]] = None) -> int:
668+
def add_event_handler(self, event: str, callback: callable, contexts: Optional[list[str]] = None) -> int:
669669
"""Add an event handler to the browsing context.
670670
671671
Parameters:

0 commit comments

Comments
 (0)