Skip to content

Commit acfa8ca

Browse files
titusfortnerclaude
andcommitted
[py] Use lazy imports in webdriver __init__.py
Replace eager imports of all browser modules with lazy loading via __getattr__. This enables future modularization of the Bazel build and improves import performance for users who only use a subset of browsers. The public API is fully backwards compatible - all existing import patterns continue to work identically. Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent f40b8ba commit acfa8ca

File tree

1 file changed

+55
-30
lines changed

1 file changed

+55
-30
lines changed

py/selenium/webdriver/__init__.py

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

18+
import importlib
1819
import logging
1920
import os
2021

@@ -25,38 +26,62 @@
2526
if not logger.handlers:
2627
logger.addHandler(logging.StreamHandler())
2728

28-
from selenium.webdriver.chrome.options import Options as ChromeOptions
29-
from selenium.webdriver.chrome.service import Service as ChromeService
30-
from selenium.webdriver.chrome.webdriver import WebDriver as Chrome
31-
from selenium.webdriver.common.action_chains import ActionChains
32-
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
33-
from selenium.webdriver.common.keys import Keys
34-
from selenium.webdriver.common.proxy import Proxy
35-
from selenium.webdriver.edge.options import Options as EdgeOptions
36-
from selenium.webdriver.edge.service import Service as EdgeService
37-
from selenium.webdriver.edge.webdriver import WebDriver as ChromiumEdge
38-
from selenium.webdriver.edge.webdriver import WebDriver as Edge
39-
from selenium.webdriver.firefox.firefox_profile import FirefoxProfile
40-
from selenium.webdriver.firefox.options import Options as FirefoxOptions
41-
from selenium.webdriver.firefox.service import Service as FirefoxService
42-
from selenium.webdriver.firefox.webdriver import WebDriver as Firefox
43-
from selenium.webdriver.ie.options import Options as IeOptions
44-
from selenium.webdriver.ie.service import Service as IeService
45-
from selenium.webdriver.ie.webdriver import WebDriver as Ie
46-
from selenium.webdriver.remote.webdriver import WebDriver as Remote
47-
from selenium.webdriver.safari.options import Options as SafariOptions
48-
from selenium.webdriver.safari.service import Service as SafariService
49-
from selenium.webdriver.safari.webdriver import WebDriver as Safari
50-
from selenium.webdriver.webkitgtk.options import Options as WebKitGTKOptions
51-
from selenium.webdriver.webkitgtk.service import Service as WebKitGTKService
52-
from selenium.webdriver.webkitgtk.webdriver import WebDriver as WebKitGTK
53-
from selenium.webdriver.wpewebkit.options import Options as WPEWebKitOptions
54-
from selenium.webdriver.wpewebkit.service import Service as WPEWebKitService
55-
from selenium.webdriver.wpewebkit.webdriver import WebDriver as WPEWebKit
56-
5729
__version__ = "4.41.0.202601181916"
5830

59-
# We need an explicit __all__ because the above won't otherwise be exported.
31+
# Lazy import mapping: name -> (module_path, attribute_name)
32+
_LAZY_IMPORTS = {
33+
# Chrome
34+
"Chrome": ("selenium.webdriver.chrome.webdriver", "WebDriver"),
35+
"ChromeOptions": ("selenium.webdriver.chrome.options", "Options"),
36+
"ChromeService": ("selenium.webdriver.chrome.service", "Service"),
37+
# Edge
38+
"Edge": ("selenium.webdriver.edge.webdriver", "WebDriver"),
39+
"ChromiumEdge": ("selenium.webdriver.edge.webdriver", "WebDriver"),
40+
"EdgeOptions": ("selenium.webdriver.edge.options", "Options"),
41+
"EdgeService": ("selenium.webdriver.edge.service", "Service"),
42+
# Firefox
43+
"Firefox": ("selenium.webdriver.firefox.webdriver", "WebDriver"),
44+
"FirefoxOptions": ("selenium.webdriver.firefox.options", "Options"),
45+
"FirefoxProfile": ("selenium.webdriver.firefox.firefox_profile", "FirefoxProfile"),
46+
"FirefoxService": ("selenium.webdriver.firefox.service", "Service"),
47+
# IE
48+
"Ie": ("selenium.webdriver.ie.webdriver", "WebDriver"),
49+
"IeOptions": ("selenium.webdriver.ie.options", "Options"),
50+
"IeService": ("selenium.webdriver.ie.service", "Service"),
51+
# Safari
52+
"Safari": ("selenium.webdriver.safari.webdriver", "WebDriver"),
53+
"SafariOptions": ("selenium.webdriver.safari.options", "Options"),
54+
"SafariService": ("selenium.webdriver.safari.service", "Service"),
55+
# Remote
56+
"Remote": ("selenium.webdriver.remote.webdriver", "WebDriver"),
57+
# WebKitGTK
58+
"WebKitGTK": ("selenium.webdriver.webkitgtk.webdriver", "WebDriver"),
59+
"WebKitGTKOptions": ("selenium.webdriver.webkitgtk.options", "Options"),
60+
"WebKitGTKService": ("selenium.webdriver.webkitgtk.service", "Service"),
61+
# WPEWebKit
62+
"WPEWebKit": ("selenium.webdriver.wpewebkit.webdriver", "WebDriver"),
63+
"WPEWebKitOptions": ("selenium.webdriver.wpewebkit.options", "Options"),
64+
"WPEWebKitService": ("selenium.webdriver.wpewebkit.service", "Service"),
65+
# Common utilities
66+
"ActionChains": ("selenium.webdriver.common.action_chains", "ActionChains"),
67+
"DesiredCapabilities": ("selenium.webdriver.common.desired_capabilities", "DesiredCapabilities"),
68+
"Keys": ("selenium.webdriver.common.keys", "Keys"),
69+
"Proxy": ("selenium.webdriver.common.proxy", "Proxy"),
70+
}
71+
72+
73+
def __getattr__(name):
74+
if name in _LAZY_IMPORTS:
75+
module_path, attr_name = _LAZY_IMPORTS[name]
76+
module = importlib.import_module(module_path)
77+
return getattr(module, attr_name)
78+
raise AttributeError(f"module 'selenium.webdriver' has no attribute {name!r}")
79+
80+
81+
def __dir__():
82+
return list(__all__) + list(globals().keys())
83+
84+
6085
__all__ = [
6186
"ActionChains",
6287
"Chrome",

0 commit comments

Comments
 (0)