Skip to content

Commit 923208f

Browse files
committed
[py] implement configurable configuration class for the http client
1 parent e586190 commit 923208f

File tree

9 files changed

+219
-45
lines changed

9 files changed

+219
-45
lines changed

py/selenium/webdriver/chrome/remote_connection.py

+3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
from selenium.webdriver import DesiredCapabilities
2020
from selenium.webdriver.chromium.remote_connection import ChromiumRemoteConnection
21+
from selenium.webdriver.remote.client_config import ClientConfig
2122

2223

2324
class ChromeRemoteConnection(ChromiumRemoteConnection):
@@ -28,11 +29,13 @@ def __init__(
2829
remote_server_addr: str,
2930
keep_alive: bool = True,
3031
ignore_proxy: typing.Optional[bool] = False,
32+
client_config: ClientConfig = None,
3133
) -> None:
3234
super().__init__(
3335
remote_server_addr=remote_server_addr,
3436
vendor_prefix="goog",
3537
browser_name=ChromeRemoteConnection.browser_name,
3638
keep_alive=keep_alive,
3739
ignore_proxy=ignore_proxy,
40+
client_config=client_config,
3841
)

py/selenium/webdriver/chromium/remote_connection.py

+8-2
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-
17+
from selenium.webdriver.remote.client_config import ClientConfig
1818
from selenium.webdriver.remote.remote_connection import RemoteConnection
1919

2020

@@ -26,8 +26,14 @@ def __init__(
2626
browser_name: str,
2727
keep_alive: bool = True,
2828
ignore_proxy: bool = False,
29+
client_config: ClientConfig = None,
2930
) -> None:
30-
super().__init__(remote_server_addr, keep_alive, ignore_proxy)
31+
super().__init__(
32+
remote_server_addr=remote_server_addr,
33+
keep_alive=keep_alive,
34+
ignore_proxy=ignore_proxy,
35+
client_config=client_config,
36+
)
3137
self.browser_name = browser_name
3238
commands = self._remote_commands(vendor_prefix)
3339
for key, value in commands.items():

py/selenium/webdriver/common/options.py

+10
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
# specific language governing permissions and limitations
1616
# under the License.
1717
import typing
18+
import warnings
1819
from abc import ABCMeta
1920
from abc import abstractmethod
2021
from enum import Enum
@@ -432,6 +433,15 @@ def add_argument(self, argument):
432433
def ignore_local_proxy_environment_variables(self) -> None:
433434
"""By calling this you will ignore HTTP_PROXY and HTTPS_PROXY from
434435
being picked up and used."""
436+
warnings.warn(
437+
"using ignore_local_proxy_environment_variables in Options has been deprecated, "
438+
"instead, create a Proxy instance with ProxyType.DIRECT to ignore proxy settings, "
439+
"pass the proxy instance into a ClientConfig constructor, "
440+
"pass the client config instance into the Webdriver constructor",
441+
DeprecationWarning,
442+
stacklevel=2,
443+
)
444+
435445
self._ignore_local_proxy = True
436446

437447
def to_capabilities(self):

py/selenium/webdriver/edge/remote_connection.py

+3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
from selenium.webdriver import DesiredCapabilities
2020
from selenium.webdriver.chromium.remote_connection import ChromiumRemoteConnection
21+
from selenium.webdriver.remote.client_config import ClientConfig
2122

2223

2324
class EdgeRemoteConnection(ChromiumRemoteConnection):
@@ -28,11 +29,13 @@ def __init__(
2829
remote_server_addr: str,
2930
keep_alive: bool = True,
3031
ignore_proxy: typing.Optional[bool] = False,
32+
client_config: ClientConfig = None,
3133
) -> None:
3234
super().__init__(
3335
remote_server_addr=remote_server_addr,
3436
vendor_prefix="goog",
3537
browser_name=EdgeRemoteConnection.browser_name,
3638
keep_alive=keep_alive,
3739
ignore_proxy=ignore_proxy,
40+
client_config=client_config,
3841
)

py/selenium/webdriver/firefox/remote_connection.py

+15-2
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,29 @@
1414
# KIND, either express or implied. See the License for the
1515
# specific language governing permissions and limitations
1616
# under the License.
17+
import typing
1718

1819
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
20+
from selenium.webdriver.remote.client_config import ClientConfig
1921
from selenium.webdriver.remote.remote_connection import RemoteConnection
2022

2123

2224
class FirefoxRemoteConnection(RemoteConnection):
2325
browser_name = DesiredCapabilities.FIREFOX["browserName"]
2426

25-
def __init__(self, remote_server_addr, keep_alive=True, ignore_proxy=False) -> None:
26-
super().__init__(remote_server_addr, keep_alive, ignore_proxy)
27+
def __init__(
28+
self,
29+
remote_server_addr: str,
30+
keep_alive: bool = True,
31+
ignore_proxy: typing.Optional[bool] = False,
32+
client_config: ClientConfig = None,
33+
) -> None:
34+
super().__init__(
35+
remote_server_addr=remote_server_addr,
36+
keep_alive=keep_alive,
37+
ignore_proxy=ignore_proxy,
38+
client_config=client_config,
39+
)
2740

2841
self._commands["GET_CONTEXT"] = ("GET", "/session/$sessionId/moz/context")
2942
self._commands["SET_CONTEXT"] = ("POST", "/session/$sessionId/moz/context")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# Licensed to the Software Freedom Conservancy (SFC) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The SFC licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
import os
18+
from urllib import parse
19+
20+
from selenium.webdriver.common.proxy import Proxy
21+
from selenium.webdriver.common.proxy import ProxyType
22+
23+
24+
class ClientConfig:
25+
def __init__(
26+
self,
27+
remote_server_addr: str,
28+
keep_alive: bool = True,
29+
proxy=None,
30+
) -> None:
31+
self.remote_server_addr = remote_server_addr
32+
self.keep_alive = keep_alive
33+
self.proxy = proxy
34+
35+
@property
36+
def remote_server_addr(self) -> str:
37+
return self._remote_server_addr
38+
39+
@remote_server_addr.setter
40+
def remote_server_addr(self, value: str):
41+
self._remote_server_addr = value
42+
43+
@property
44+
def keep_alive(self) -> bool:
45+
""":Returns: The keep alive value."""
46+
return self._keep_alive
47+
48+
@keep_alive.setter
49+
def keep_alive(self, value: bool) -> None:
50+
"""Toggles the keep alive value.
51+
52+
:Args:
53+
- value: whether to keep the http connection alive
54+
"""
55+
self._keep_alive = value
56+
57+
@property
58+
def proxy(self) -> Proxy:
59+
""":Returns: The proxy used for communicating to the driver/server."""
60+
61+
if self._proxy is None or self._proxy.proxyType == ProxyType.SYSTEM:
62+
self._proxy.sslProxy = os.environ.get("https_proxy", os.environ.get("HTTPS_PROXY"))
63+
self._proxy.httpProxy = os.environ.get("http_proxy", os.environ.get("HTTP_PROXY"))
64+
65+
return self._proxy
66+
67+
@proxy.setter
68+
def proxy(self, proxy: Proxy) -> None:
69+
"""Provides the information for communicating with the driver or
70+
server.
71+
72+
:Args:
73+
- value: the proxy information to use to communicate with the driver or server
74+
"""
75+
self._proxy = proxy
76+
77+
def get_proxy_url(self):
78+
if self.proxy.proxy_type == ProxyType.DIRECT:
79+
return None
80+
elif self.proxy.proxy_type == ProxyType.SYSTEM:
81+
_no_proxy = os.environ.get("no_proxy", os.environ.get("NO_PROXY"))
82+
if _no_proxy:
83+
for npu in _no_proxy.split(","):
84+
npu = npu.strip()
85+
if npu == "*":
86+
return None
87+
n_url = parse.urlparse(npu)
88+
remote_add = parse.urlparse(self.remote_server_addr)
89+
if n_url.netloc:
90+
if remote_add.netloc == n_url.netloc:
91+
return None
92+
else:
93+
if n_url.path in remote_add.netloc:
94+
return None
95+
if self.remote_server_addr.startswith("https://"):
96+
return os.environ.get("https_proxy", os.environ.get("HTTPS_PROXY"))
97+
if self.remote_server_addr.startswith("http://"):
98+
return os.environ.get("http_proxy", os.environ.get("HTTP_PROXY"))
99+
elif self.proxy.proxy_type == ProxyType.MANUAL:
100+
if self.remote_server_addr.startswith("https://"):
101+
return self.proxy.sslProxy
102+
elif self.remote_server_addr.startswith("http://"):
103+
return self.proxy.http_proxy
104+
else:
105+
return None
106+
else:
107+
return None

py/selenium/webdriver/remote/remote_connection.py

+41-35
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import platform
2121
import socket
2222
import string
23+
import warnings
2324
from base64 import b64encode
2425
from urllib import parse
2526

@@ -29,6 +30,7 @@
2930
from selenium import __version__
3031

3132
from . import utils
33+
from .client_config import ClientConfig
3234
from .command import Command
3335
from .errorhandler import ErrorCode
3436

@@ -211,12 +213,6 @@ def get_remote_connection_headers(cls, parsed_url, keep_alive=False):
211213

212214
return headers
213215

214-
def _get_proxy_url(self):
215-
if self._url.startswith("https://"):
216-
return os.environ.get("https_proxy", os.environ.get("HTTPS_PROXY"))
217-
if self._url.startswith("http://"):
218-
return os.environ.get("http_proxy", os.environ.get("HTTP_PROXY"))
219-
220216
def _identify_http_proxy_auth(self):
221217
url = self._proxy_url
222218
url = url[url.find(":") + 3 :]
@@ -248,31 +244,42 @@ def _get_connection_manager(self):
248244

249245
return urllib3.PoolManager(**pool_manager_init_args)
250246

251-
def __init__(self, remote_server_addr: str, keep_alive: bool = False, ignore_proxy: bool = False):
252-
self.keep_alive = keep_alive
253-
self._url = remote_server_addr
254-
255-
# Env var NO_PROXY will override this part of the code
256-
_no_proxy = os.environ.get("no_proxy", os.environ.get("NO_PROXY"))
257-
if _no_proxy:
258-
for npu in _no_proxy.split(","):
259-
npu = npu.strip()
260-
if npu == "*":
261-
ignore_proxy = True
262-
break
263-
n_url = parse.urlparse(npu)
264-
remote_add = parse.urlparse(self._url)
265-
if n_url.netloc:
266-
if remote_add.netloc == n_url.netloc:
267-
ignore_proxy = True
268-
break
269-
else:
270-
if n_url.path in remote_add.netloc:
271-
ignore_proxy = True
272-
break
273-
274-
self._proxy_url = self._get_proxy_url() if not ignore_proxy else None
275-
if keep_alive:
247+
def __init__(
248+
self,
249+
remote_server_addr: str,
250+
keep_alive: bool = True,
251+
ignore_proxy: bool = False,
252+
client_config: ClientConfig = None,
253+
):
254+
self._client_config = client_config or ClientConfig()
255+
256+
if remote_server_addr:
257+
warnings.warn(
258+
"setting keep_alive in RemoteConnection() is deprecated, " "set in ClientConfig instance insttead",
259+
DeprecationWarning,
260+
stacklevel=2,
261+
)
262+
self._client_config.remote_server_addr = remote_server_addr
263+
264+
if not keep_alive:
265+
warnings.warn(
266+
"setting keep_alive in RemoteConnection() is deprecated, " "set in ClientConfig instance insttead",
267+
DeprecationWarning,
268+
stacklevel=2,
269+
)
270+
self._client_config.keep_alive = keep_alive
271+
272+
if ignore_proxy:
273+
warnings.warn(
274+
"setting keep_alive in RemoteConnection() is deprecated, " "set in ClientConfig instance insttead",
275+
DeprecationWarning,
276+
stacklevel=2,
277+
)
278+
self._proxy_url = None
279+
else:
280+
self._proxy_url = self._client_config.get_proxy_url()
281+
282+
if self._client_config.keep_alive:
276283
self._conn = self._get_connection_manager()
277284
self._commands = remote_commands
278285

@@ -296,7 +303,7 @@ def execute(self, command, params):
296303
for word in substitute_params:
297304
del params[word]
298305
data = utils.dump_json(params)
299-
url = f"{self._url}{path}"
306+
url = f"{self._client_config.remote_server_addr}{path}"
300307
return self._request(command_info[0], url, body=data)
301308

302309
def _request(self, method, url, body=None):
@@ -312,12 +319,11 @@ def _request(self, method, url, body=None):
312319
"""
313320
LOGGER.debug("%s %s %s", method, url, body)
314321
parsed_url = parse.urlparse(url)
315-
headers = self.get_remote_connection_headers(parsed_url, self.keep_alive)
316-
response = None
322+
headers = self.get_remote_connection_headers(parsed_url, self._client_config.keep_alive)
317323
if body and method not in ("POST", "PUT"):
318324
body = None
319325

320-
if self.keep_alive:
326+
if self._client_config.keep_alive:
321327
response = self._conn.request(method, url, body=body, headers=headers)
322328
statuscode = response.status
323329
else:

0 commit comments

Comments
 (0)