-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit 9b31456
committed
Pin Python dependencies in requirements.txt
- Pinned the following dependencies for consistency and stability:
- pytest==7.3.0
- trio==0.22.0
- pytest-trio==0.8.0
- pytest-rerunfailures==10.2
- flake8==6.1.0
- requests==2.32.3
This ensures consistent behavior across environments and avoids issues
from unexpected updates or breaking changes. Verified with ============================= test session starts ==============================
platform darwin -- Python 3.12.4, pytest-7.3.0, pluggy-1.0.0
rootdir: /Users/Vinay/Documents/SeleniumRepo/seleniumhq.github.io
plugins: rerunfailures-10.2, trio-0.8.0, anyio-4.2.0
collected 153 items
examples/python/tests/actions_api/test_actions.py .. [ 1%]
examples/python/tests/actions_api/test_keys.py ..... [ 4%]
examples/python/tests/actions_api/test_mouse.py ............ [ 12%]
examples/python/tests/actions_api/test_pen.py .. [ 13%]
examples/python/tests/actions_api/test_wheel.py ..... [ 16%]
examples/python/tests/bidi/test_bidi_logging.py .... [ 19%]
examples/python/tests/bidi/cdp/test_cdp.py . [ 20%]
examples/python/tests/bidi/cdp/test_logs.py .. [ 21%]
examples/python/tests/bidi/cdp/test_network.py ... [ 23%]
examples/python/tests/bidi/cdp/test_script.py F [ 24%]
examples/python/tests/browsers/test_chrome.py ...F.........s. [ 33%]
examples/python/tests/browsers/test_edge.py ...F.........s. [ 43%]
examples/python/tests/browsers/test_firefox.py ........FFFF... [ 53%]
examples/python/tests/browsers/test_internet_explorer.py sssssssssssss [ 62%]
examples/python/tests/browsers/test_safari.py ..s [ 64%]
examples/python/tests/drivers/test_http_client.py F. [ 65%]
examples/python/tests/drivers/test_options.py .............. [ 74%]
examples/python/tests/drivers/test_remote_webdriver.py ... [ 76%]
examples/python/tests/drivers/test_service.py ... [ 78%]
examples/python/tests/elements/test_file_upload.py . [ 79%]
examples/python/tests/elements/test_information.py . [ 79%]
examples/python/tests/elements/test_interaction.py . [ 80%]
examples/python/tests/interactions/test_alerts.py ... [ 82%]
examples/python/tests/interactions/test_print_options.py ....... [ 86%]
examples/python/tests/interactions/test_prints_page.py . [ 87%]
examples/python/tests/interactions/test_virtual_authenticator.py ....... [ 92%]
... [ 94%]
examples/python/tests/support/test_select_list.py ... [ 96%]
examples/python/tests/troubleshooting/test_logging.py . [ 96%]
examples/python/tests/waits/test_waits.py ..... [100%]
=================================== FAILURES ===================================
________________________________ test_mutation _________________________________
driver = <selenium.webdriver.chrome.webdriver.WebDriver (session="515c6a21ab4301c18bbe46871e7bf148")>
@pytest.mark.trio
async def test_mutation(driver):
async with driver.bidi_connection() as session:
> async with Log(driver, session).mutation_events() as event:
examples/python/tests/bidi/cdp/test_script.py:11:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/opt/anaconda3/lib/python3.12/contextlib.py:217: in __aexit__
await anext(self.gen)
/opt/anaconda3/lib/python3.12/site-packages/selenium/webdriver/common/log.py:93: in mutation_events
elements: list = self.driver.find_elements(By.CSS_SELECTOR, f"*[data-__webdriver_id={payload['target']}]")
/opt/anaconda3/lib/python3.12/site-packages/selenium/webdriver/remote/webdriver.py:792: in find_elements
return self.execute(Command.FIND_ELEMENTS, {"using": by, "value": value})["value"] or []
/opt/anaconda3/lib/python3.12/site-packages/selenium/webdriver/remote/webdriver.py:384: in execute
self.error_handler.check_response(response)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x111e254c0>
response = {'status': 400, 'value': '{"value":{"error":"invalid selector","message":"invalid selector\\nfrom javascript error: {\...00019107f2e4 _pthread_start + 136\\n19 libsystem_pthread.dylib 0x000000019107a0fc thread_start + 8\\n"}}'}
def check_response(self, response: Dict[str, Any]) -> None:
"""Checks that a JSON response from the WebDriver does not have an
error.
:Args:
- response - The JSON response from the WebDriver server as a dictionary
object.
:Raises: If the response contains an error message.
"""
status = response.get("status", None)
if not status or status == ErrorCode.SUCCESS:
return
value = None
message = response.get("message", "")
screen: str = response.get("screen", "")
stacktrace = None
if isinstance(status, int):
value_json = response.get("value", None)
if value_json and isinstance(value_json, str):
import json
try:
value = json.loads(value_json)
if len(value) == 1:
value = value["value"]
status = value.get("error", None)
if not status:
status = value.get("status", ErrorCode.UNKNOWN_ERROR)
message = value.get("value") or value.get("message")
if not isinstance(message, str):
value = message
message = message.get("message")
else:
message = value.get("message", None)
except ValueError:
pass
exception_class: Type[WebDriverException]
e = ErrorCode()
error_codes = [item for item in dir(e) if not item.startswith("__")]
for error_code in error_codes:
error_info = getattr(ErrorCode, error_code)
if isinstance(error_info, list) and status in error_info:
exception_class = getattr(ExceptionMapping, error_code, WebDriverException)
break
else:
exception_class = WebDriverException
if not value:
value = response["value"]
if isinstance(value, str):
raise exception_class(value)
if message == "" and "message" in value:
message = value["message"]
screen = None # type: ignore[assignment]
if "screen" in value:
screen = value["screen"]
stacktrace = None
st_value = value.get("stackTrace") or value.get("stacktrace")
if st_value:
if isinstance(st_value, str):
stacktrace = st_value.split("\n")
else:
stacktrace = []
try:
for frame in st_value:
line = frame.get("lineNumber", "")
file = frame.get("fileName", "<anonymous>")
if line:
file = f"{file}:{line}"
meth = frame.get("methodName", "<anonymous>")
if "className" in frame:
meth = f"{frame['className']}.{meth}"
msg = " at %s (%s)"
msg = msg % (meth, file)
stacktrace.append(msg)
except TypeError:
pass
if exception_class == UnexpectedAlertPresentException:
alert_text = None
if "data" in value:
alert_text = value["data"].get("text")
elif "alert" in value:
alert_text = value["alert"].get("text")
raise exception_class(message, screen, stacktrace, alert_text) # type: ignore[call-arg] # mypy is not smart enough here
> raise exception_class(message, screen, stacktrace)
E selenium.common.exceptions.InvalidSelectorException: Message: invalid selector
E from javascript error: {"status":32,"value":"An invalid or illegal selector was specified"}
E (Session info: chrome=131.0.6778.205); For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#invalid-selector-exception
E Stacktrace:
E 0 chromedriver 0x0000000102d9f184 cxxbridge1$str$ptr + 3626716
E 1 chromedriver 0x0000000102d979d4 cxxbridge1$str$ptr + 3596076
E 2 chromedriver 0x0000000102804968 cxxbridge1$string$len + 89228
E 3 chromedriver 0x000000010280984c cxxbridge1$string$len + 109424
E 4 chromedriver 0x000000010280b89c cxxbridge1$string$len + 117696
E 5 chromedriver 0x000000010280b944 cxxbridge1$string$len + 117864
E 6 chromedriver 0x0000000102848a94 cxxbridge1$string$len + 368056
E 7 chromedriver 0x00000001028825b4 cxxbridge1$string$len + 604376
E 8 chromedriver 0x000000010283d568 cxxbridge1$string$len + 321676
E 9 chromedriver 0x000000010283e1b8 cxxbridge1$string$len + 324828
E 10 chromedriver 0x0000000102d6a9ac cxxbridge1$str$ptr + 3411716
E 11 chromedriver 0x0000000102d6dccc cxxbridge1$str$ptr + 3424804
E 12 chromedriver 0x0000000102d5186c cxxbridge1$str$ptr + 3308996
E 13 chromedriver 0x0000000102d6e58c cxxbridge1$str$ptr + 3427044
E 14 chromedriver 0x0000000102d4309c cxxbridge1$str$ptr + 3249652
E 15 chromedriver 0x0000000102d884b8 cxxbridge1$str$ptr + 3533328
E 16 chromedriver 0x0000000102d88634 cxxbridge1$str$ptr + 3533708
E 17 chromedriver 0x0000000102d97648 cxxbridge1$str$ptr + 3595168
E 18 libsystem_pthread.dylib 0x000000019107f2e4 _pthread_start + 136
E 19 libsystem_pthread.dylib 0x000000019107a0fc thread_start + 8
/opt/anaconda3/lib/python3.12/site-packages/selenium/webdriver/remote/errorhandler.py:232: InvalidSelectorException
______________________________ test_add_extension ______________________________
def test_add_extension():
options = webdriver.ChromeOptions()
extension_file_path = os.path.abspath("tests/extensions/webextensions-selenium-example.crx")
> options.add_extension(extension_file_path)
examples/python/tests/browsers/test_chrome.py:40:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <selenium.webdriver.chrome.options.Options object at 0x111e09d30>
extension = '/Users/Vinay/Documents/SeleniumRepo/seleniumhq.github.io/tests/extensions/webextensions-selenium-example.crx'
def add_extension(self, extension: str) -> None:
"""Adds the path to the extension to a list that will be used to
extract it to the ChromeDriver.
:Args:
- extension: path to the \\*.crx file
"""
if extension:
extension_to_add = os.path.abspath(os.path.expanduser(extension))
if os.path.exists(extension_to_add):
self._extension_files.append(extension_to_add)
else:
> raise OSError("Path to the extension doesn't exist")
E OSError: Path to the extension doesn't exist
/opt/anaconda3/lib/python3.12/site-packages/selenium/webdriver/chromium/options.py:103: OSError
______________________________ test_add_extension ______________________________
def test_add_extension():
options = webdriver.EdgeOptions()
extension_file_path = os.path.abspath("tests/extensions/webextensions-selenium-example.crx")
> options.add_extension(extension_file_path)
examples/python/tests/browsers/test_edge.py:40:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <selenium.webdriver.edge.options.Options object at 0x111e0a2d0>
extension = '/Users/Vinay/Documents/SeleniumRepo/seleniumhq.github.io/tests/extensions/webextensions-selenium-example.crx'
def add_extension(self, extension: str) -> None:
"""Adds the path to the extension to a list that will be used to
extract it to the ChromeDriver.
:Args:
- extension: path to the \\*.crx file
"""
if extension:
extension_to_add = os.path.abspath(os.path.expanduser(extension))
if os.path.exists(extension_to_add):
self._extension_files.append(extension_to_add)
else:
> raise OSError("Path to the extension doesn't exist")
E OSError: Path to the extension doesn't exist
/opt/anaconda3/lib/python3.12/site-packages/selenium/webdriver/chromium/options.py:103: OSError
______________________________ test_install_addon ______________________________
firefox_driver = <selenium.webdriver.firefox.webdriver.WebDriver (session="9c05f940-a875-49b3-8de1-d4d892150f37")>
addon_path_xpi = '/Users/Vinay/Documents/SeleniumRepo/seleniumhq.github.io/tests/extensions/webextensions-selenium-example.xpi'
def test_install_addon(firefox_driver, addon_path_xpi):
driver = firefox_driver
> driver.install_addon(addon_path_xpi)
examples/python/tests/browsers/test_firefox.py:94:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <selenium.webdriver.firefox.webdriver.WebDriver (session="9c05f940-a875-49b3-8de1-d4d892150f37")>
path = '/Users/Vinay/Documents/SeleniumRepo/seleniumhq.github.io/tests/extensions/webextensions-selenium-example.xpi'
temporary = False
def install_addon(self, path, temporary=False) -> str:
"""Installs Firefox addon.
Returns identifier of installed addon. This identifier can later
be used to uninstall addon.
:param temporary: allows you to load browser extensions temporarily during a session
:param path: Absolute path to the addon that will be installed.
:Usage:
::
driver.install_addon('/path/to/firebug.xpi')
"""
if os.path.isdir(path):
fp = BytesIO()
# filter all trailing slash found in path
path = os.path.normpath(path)
# account for trailing slash that will be added by os.walk()
path_root = len(path) + 1
with zipfile.ZipFile(fp, "w", zipfile.ZIP_DEFLATED) as zipped:
for base, _, files in os.walk(path):
for fyle in files:
filename = os.path.join(base, fyle)
zipped.write(filename, filename[path_root:])
addon = base64.b64encode(fp.getvalue()).decode("UTF-8")
else:
> with open(path, "rb") as file:
E FileNotFoundError: [Errno 2] No such file or directory: '/Users/Vinay/Documents/SeleniumRepo/seleniumhq.github.io/tests/extensions/webextensions-selenium-example.xpi'
/opt/anaconda3/lib/python3.12/site-packages/selenium/webdriver/firefox/webdriver.py:141: FileNotFoundError
_____________________________ test_uninstall_addon _____________________________
firefox_driver = <selenium.webdriver.firefox.webdriver.WebDriver (session="acfdd1d4-bdbe-4904-b9ea-5d8273f8ae00")>
addon_path_xpi = '/Users/Vinay/Documents/SeleniumRepo/seleniumhq.github.io/tests/extensions/webextensions-selenium-example.xpi'
def test_uninstall_addon(firefox_driver, addon_path_xpi):
driver = firefox_driver
> id = driver.install_addon(addon_path_xpi)
examples/python/tests/browsers/test_firefox.py:105:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <selenium.webdriver.firefox.webdriver.WebDriver (session="acfdd1d4-bdbe-4904-b9ea-5d8273f8ae00")>
path = '/Users/Vinay/Documents/SeleniumRepo/seleniumhq.github.io/tests/extensions/webextensions-selenium-example.xpi'
temporary = False
def install_addon(self, path, temporary=False) -> str:
"""Installs Firefox addon.
Returns identifier of installed addon. This identifier can later
be used to uninstall addon.
:param temporary: allows you to load browser extensions temporarily during a session
:param path: Absolute path to the addon that will be installed.
:Usage:
::
driver.install_addon('/path/to/firebug.xpi')
"""
if os.path.isdir(path):
fp = BytesIO()
# filter all trailing slash found in path
path = os.path.normpath(path)
# account for trailing slash that will be added by os.walk()
path_root = len(path) + 1
with zipfile.ZipFile(fp, "w", zipfile.ZIP_DEFLATED) as zipped:
for base, _, files in os.walk(path):
for fyle in files:
filename = os.path.join(base, fyle)
zipped.write(filename, filename[path_root:])
addon = base64.b64encode(fp.getvalue()).decode("UTF-8")
else:
> with open(path, "rb") as file:
E FileNotFoundError: [Errno 2] No such file or directory: '/Users/Vinay/Documents/SeleniumRepo/seleniumhq.github.io/tests/extensions/webextensions-selenium-example.xpi'
/opt/anaconda3/lib/python3.12/site-packages/selenium/webdriver/firefox/webdriver.py:141: FileNotFoundError
____________________ test_install_unsigned_addon_directory _____________________
firefox_driver = <selenium.webdriver.firefox.webdriver.WebDriver (session="6210c6b0-47e2-4ea4-83ba-ccb5513b4a96")>
addon_path_dir = '/Users/Vinay/Documents/SeleniumRepo/seleniumhq.github.io/tests/extensions/webextensions-selenium-example'
def test_install_unsigned_addon_directory(firefox_driver, addon_path_dir):
driver = firefox_driver
> driver.install_addon(addon_path_dir, temporary=True)
examples/python/tests/browsers/test_firefox.py:115:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <selenium.webdriver.firefox.webdriver.WebDriver (session="6210c6b0-47e2-4ea4-83ba-ccb5513b4a96")>
path = '/Users/Vinay/Documents/SeleniumRepo/seleniumhq.github.io/tests/extensions/webextensions-selenium-example'
temporary = True
def install_addon(self, path, temporary=False) -> str:
"""Installs Firefox addon.
Returns identifier of installed addon. This identifier can later
be used to uninstall addon.
:param temporary: allows you to load browser extensions temporarily during a session
:param path: Absolute path to the addon that will be installed.
:Usage:
::
driver.install_addon('/path/to/firebug.xpi')
"""
if os.path.isdir(path):
fp = BytesIO()
# filter all trailing slash found in path
path = os.path.normpath(path)
# account for trailing slash that will be added by os.walk()
path_root = len(path) + 1
with zipfile.ZipFile(fp, "w", zipfile.ZIP_DEFLATED) as zipped:
for base, _, files in os.walk(path):
for fyle in files:
filename = os.path.join(base, fyle)
zipped.write(filename, filename[path_root:])
addon = base64.b64encode(fp.getvalue()).decode("UTF-8")
else:
> with open(path, "rb") as file:
E FileNotFoundError: [Errno 2] No such file or directory: '/Users/Vinay/Documents/SeleniumRepo/seleniumhq.github.io/tests/extensions/webextensions-selenium-example'
/opt/anaconda3/lib/python3.12/site-packages/selenium/webdriver/firefox/webdriver.py:141: FileNotFoundError
_________________ test_install_unsigned_addon_directory_slash __________________
firefox_driver = <selenium.webdriver.firefox.webdriver.WebDriver (session="676fa6a5-8e2f-4776-b853-3a933f218d25")>
addon_path_dir_slash = '/Users/Vinay/Documents/SeleniumRepo/seleniumhq.github.io/tests/extensions/webextensions-selenium-example'
def test_install_unsigned_addon_directory_slash(firefox_driver, addon_path_dir_slash):
driver = firefox_driver
> driver.install_addon(addon_path_dir_slash, temporary=True)
examples/python/tests/browsers/test_firefox.py:126:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <selenium.webdriver.firefox.webdriver.WebDriver (session="676fa6a5-8e2f-4776-b853-3a933f218d25")>
path = '/Users/Vinay/Documents/SeleniumRepo/seleniumhq.github.io/tests/extensions/webextensions-selenium-example'
temporary = True
def install_addon(self, path, temporary=False) -> str:
"""Installs Firefox addon.
Returns identifier of installed addon. This identifier can later
be used to uninstall addon.
:param temporary: allows you to load browser extensions temporarily during a session
:param path: Absolute path to the addon that will be installed.
:Usage:
::
driver.install_addon('/path/to/firebug.xpi')
"""
if os.path.isdir(path):
fp = BytesIO()
# filter all trailing slash found in path
path = os.path.normpath(path)
# account for trailing slash that will be added by os.walk()
path_root = len(path) + 1
with zipfile.ZipFile(fp, "w", zipfile.ZIP_DEFLATED) as zipped:
for base, _, files in os.walk(path):
for fyle in files:
filename = os.path.join(base, fyle)
zipped.write(filename, filename[path_root:])
addon = base64.b64encode(fp.getvalue()).decode("UTF-8")
else:
> with open(path, "rb") as file:
E FileNotFoundError: [Errno 2] No such file or directory: '/Users/Vinay/Documents/SeleniumRepo/seleniumhq.github.io/tests/extensions/webextensions-selenium-example'
/opt/anaconda3/lib/python3.12/site-packages/selenium/webdriver/firefox/webdriver.py:141: FileNotFoundError
_____________________ test_start_remote_with_client_config _____________________
sock = <socket.socket [closed] fd=-1, family=30, type=1, proto=6>
keyfile = None, certfile = None, cert_reqs = None
ca_certs = '/Users/Vinay/Documents/SeleniumRepo/seleniumhq.github.io/tests/resources/tls.crt'
server_hostname = 'localhost', ssl_version = None, ciphers = None
ssl_context = <ssl.SSLContext object at 0x111ee5250>, ca_cert_dir = None
key_password = None, ca_cert_data = None, tls_in_tls = False
def ssl_wrap_socket(
sock: socket.socket,
keyfile: str | None = None,
certfile: str | None = None,
cert_reqs: int | None = None,
ca_certs: str | None = None,
server_hostname: str | None = None,
ssl_version: int | None = None,
ciphers: str | None = None,
ssl_context: ssl.SSLContext | None = None,
ca_cert_dir: str | None = None,
key_password: str | None = None,
ca_cert_data: None | str | bytes = None,
tls_in_tls: bool = False,
) -> ssl.SSLSocket | SSLTransportType:
"""
All arguments except for server_hostname, ssl_context, tls_in_tls, ca_cert_data and
ca_cert_dir have the same meaning as they do when using
:func:`ssl.create_default_context`, :meth:`ssl.SSLContext.load_cert_chain`,
:meth:`ssl.SSLContext.set_ciphers` and :meth:`ssl.SSLContext.wrap_socket`.
:param server_hostname:
When SNI is supported, the expected hostname of the certificate
:param ssl_context:
A pre-made :class:`SSLContext` object. If none is provided, one will
be created using :func:`create_urllib3_context`.
:param ciphers:
A string of ciphers we wish the client to support.
:param ca_cert_dir:
A directory containing CA certificates in multiple separate files, as
supported by OpenSSL's -CApath flag or the capath argument to
SSLContext.load_verify_locations().
:param key_password:
Optional password if the keyfile is encrypted.
:param ca_cert_data:
Optional string containing CA certificates in PEM format suitable for
passing as the cadata parameter to SSLContext.load_verify_locations()
:param tls_in_tls:
Use SSLTransport to wrap the existing socket.
"""
context = ssl_context
if context is None:
# Note: This branch of code and all the variables in it are only used in tests.
# We should consider deprecating and removing this code.
context = create_urllib3_context(ssl_version, cert_reqs, ciphers=ciphers)
if ca_certs or ca_cert_dir or ca_cert_data:
try:
> context.load_verify_locations(ca_certs, ca_cert_dir, ca_cert_data)
E FileNotFoundError: [Errno 2] No such file or directory
/opt/anaconda3/lib/python3.12/site-packages/urllib3/util/ssl_.py:447: FileNotFoundError
The above exception was the direct cause of the following exception:
self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x111ee3aa0>
method = 'POST', url = '/session'
body = '{"capabilities": {"firstMatch": [{}], "alwaysMatch": {"browserName": "chrome", "pageLoadStrategy": "normal", "goog:chromeOptions": {"extensions": [], "args": []}}}}'
headers = HTTPHeaderDict({'Accept': 'application/json', 'Content-Type': 'application/json;charset=UTF-8', 'User-Agent': 'selenium/4.27.1 (python mac)', 'Connection': 'keep-alive', 'Authorization': 'Basic YWRtaW46bXlTdHJvbmdQYXNzd29yZA=='})
retries = Retry(total=0, connect=2, read=2, redirect=2, status=None)
redirect = False, assert_same_host = False, timeout = None, pool_timeout = None
release_conn = True, chunked = False, body_pos = None, preload_content = True
decode_content = True, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/session', query=None, fragment=None)
destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False
def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.
.. note::
More commonly, it's appropriate to use a convenience method
such as :meth:`request`.
.. note::
`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.
:param method:
HTTP request method (such as GET, POST, PUT, etc.)
:param url:
The URL to perform the request on.
:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.
:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.
:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.
If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.
If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.
:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.
:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.
:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.
:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.
:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.
:param bool preload_content:
If True, the response's body will be preloaded into memory.
:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.
:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.
:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.
:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme
if headers is None:
headers = self.headers
if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)
if release_conn is None:
release_conn = preload_content
# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)
# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)
conn = None
# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn
http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)
# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]
# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None
# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False
# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)
try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)
conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]
# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise
# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None
# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)
/opt/anaconda3/lib/python3.12/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x111ee3aa0>
conn = <urllib3.connection.HTTPSConnection object at 0x111ee2630>
method = 'POST', url = '/session'
body = '{"capabilities": {"firstMatch": [{}], "alwaysMatch": {"browserName": "chrome", "pageLoadStrategy": "normal", "goog:chromeOptions": {"extensions": [], "args": []}}}}'
headers = HTTPHeaderDict({'Accept': 'application/json', 'Content-Type': 'application/json;charset=UTF-8', 'User-Agent': 'selenium/4.27.1 (python mac)', 'Connection': 'keep-alive', 'Authorization': 'Basic YWRtaW46bXlTdHJvbmdQYXNzd29yZA=='})
retries = Retry(total=0, connect=2, read=2, redirect=2, status=None)
timeout = Timeout(connect=None, read=None, total=None), chunked = False
response_conn = None, preload_content = True, decode_content = True
enforce_content_length = True
def _make_request(
self,
conn: BaseHTTPConnection,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | None = None,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
chunked: bool = False,
response_conn: BaseHTTPConnection | None = None,
preload_content: bool = True,
decode_content: bool = True,
enforce_content_length: bool = True,
) -> BaseHTTPResponse:
"""
Perform a request on a given urllib connection object taken from our
pool.
:param conn:
a connection from one of our connection pools
:param method:
HTTP request method (such as GET, POST, PUT, etc.)
:param url:
The URL to perform the request on.
:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.
:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.
:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.
Pass ``None`` to retry until you receive a response. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.
If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.
:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.
:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.
:param chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.
:param response_conn:
Set this to ``None`` if you will handle releasing the connection or
set the connection to have the response release it.
:param preload_content:
If True, the response's body will be preloaded during construction.
:param decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.
:param enforce_content_length:
Enforce content length checking. Body returned by server must match
value of Content-Length header, if present. Otherwise, raise error.
"""
self.num_requests += 1
timeout_obj = self._get_timeout(timeout)
timeout_obj.start_connect()
conn.timeout = Timeout.resolve_default_timeout(timeout_obj.connect_timeout)
try:
# Trigger any extra validation we need to do.
try:
self._validate_conn(conn)
except (SocketTimeout, BaseSSLError) as e:
self._raise_timeout(err=e, url=url, timeout_value=conn.timeout)
raise
# _validate_conn() starts the connection to an HTTPS proxy
# so we need to wrap errors with 'ProxyError' here too.
except (
OSError,
NewConnectionError,
TimeoutError,
BaseSSLError,
CertificateError,
SSLError,
) as e:
new_e: Exception = e
if isinstance(e, (BaseSSLError, CertificateError)):
new_e = SSLError(e)
# If the connection didn't successfully connect to it's proxy
# then there
if isinstance(
new_e, (OSError, NewConnectionError, TimeoutError, SSLError)
) and (conn and conn.proxy and not conn.has_connected_to_proxy):
new_e = _wrap_proxy_error(new_e, conn.proxy.scheme)
> raise new_e
/opt/anaconda3/lib/python3.12/site-packages/urllib3/connectionpool.py:490:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x111ee3aa0>
conn = <urllib3.connection.HTTPSConnection object at 0x111ee2630>
method = 'POST', url = '/session'
body = '{"capabilities": {"firstMatch": [{}], "alwaysMatch": {"browserName": "chrome", "pageLoadStrategy": "normal", "goog:chromeOptions": {"extensions": [], "args": []}}}}'
headers = HTTPHeaderDict({'Accept': 'application/json', 'Content-Type': 'application/json;charset=UTF-8', 'User-Agent': 'selenium/4.27.1 (python mac)', 'Connection': 'keep-alive', 'Authorization': 'Basic YWRtaW46bXlTdHJvbmdQYXNzd29yZA=='})
retries = Retry(total=0, connect=2, read=2, redirect=2, status=None)
timeout = Timeout(connect=None, read=None, total=None), chunked = False
response_conn = None, preload_content = True, decode_content = True
enforce_content_length = True
def _make_request(
self,
conn: BaseHTTPConnection,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | None = None,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
chunked: bool = False,
response_conn: BaseHTTPConnection | None = None,
preload_content: bool = True,
decode_content: bool = True,
enforce_content_length: bool = True,
) -> BaseHTTPResponse:
"""
Perform a request on a given urllib connection object taken from our
pool.
:param conn:
a connection from one of our connection pools
:param method:
HTTP request method (such as GET, POST, PUT, etc.)
:param url:
The URL to perform the request on.
:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.
:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.
:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.
Pass ``None`` to retry until you receive a response. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.
If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.
:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.
:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.
:param chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.
:param response_conn:
Set this to ``None`` if you will handle releasing the connection or
set the connection to have the response release it.
:param preload_content:
If True, the response's body will be preloaded during construction.
:param decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.
:param enforce_content_length:
Enforce content length checking. Body returned by server must match
value of Content-Length header, if present. Otherwise, raise error.
"""
self.num_requests += 1
timeout_obj = self._get_timeout(timeout)
timeout_obj.start_connect()
conn.timeout = Timeout.resolve_default_timeout(timeout_obj.connect_timeout)
try:
# Trigger any extra validation we need to do.
try:
> self._validate_conn(conn)
/opt/anaconda3/lib/python3.12/site-packages/urllib3/connectionpool.py:466:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x111ee3aa0>
conn = <urllib3.connection.HTTPSConnection object at 0x111ee2630>
def _validate_conn(self, conn: BaseHTTPConnection) -> None:
"""
Called right before a request is made, after the socket is created.
"""
super()._validate_conn(conn)
# Force connect early to allow us to validate the connection.
if conn.is_closed:
> conn.connect()
/opt/anaconda3/lib/python3.12/site-packages/urllib3/connectionpool.py:1095:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <urllib3.connection.HTTPSConnection object at 0x111ee2630>
def connect(self) -> None:
# Today we don't need to be doing this step before the /actual/ socket
# connection, however in the future we'll need to decide whether to
# create a new socket or re-use an existing "shared" socket as a part
# of the HTTP/2 handshake dance.
if self._tunnel_host is not None and self._tunnel_port is not None:
probe_http2_host = self._tunnel_host
probe_http2_port = self._tunnel_port
else:
probe_http2_host = self.host
probe_http2_port = self.port
# Check if the target origin supports HTTP/2.
# If the value comes back as 'None' it means that the current thread
# is probing for HTTP/2 support. Otherwise, we're waiting for another
# probe to complete, or we get a value right away.
target_supports_http2: bool | None
if "h2" in ssl_.ALPN_PROTOCOLS:
target_supports_http2 = http2_probe.acquire_and_get(
host=probe_http2_host, port=probe_http2_port
)
else:
# If HTTP/2 isn't going to be offered it doesn't matter if
# the target supports HTTP/2. Don't want to make a probe.
target_supports_http2 = False
if self._connect_callback is not None:
self._connect_callback(
"before connect",
thread_id=threading.get_ident(),
target_supports_http2=target_supports_http2,
)
try:
sock: socket.socket | ssl.SSLSocket
self.sock = sock = self._new_conn()
server_hostname: str = self.host
tls_in_tls = False
# Do we need to establish a tunnel?
if self._tunnel_host is not None:
# We're tunneling to an HTTPS origin so need to do TLS-in-TLS.
if self._tunnel_scheme == "https":
# _connect_tls_proxy will verify and assign proxy_is_verified
self.sock = sock = self._connect_tls_proxy(self.host, sock)
tls_in_tls = True
elif self._tunnel_scheme == "http":
self.proxy_is_verified = False
# If we're tunneling it means we're connected to our proxy.
self._has_connected_to_proxy = True
self._tunnel()
# Override the host with the one we're requesting data from.
server_hostname = self._tunnel_host
if self.server_hostname is not None:
server_hostname = self.server_hostname
is_time_off = datetime.date.today() < RECENT_DATE
if is_time_off:
warnings.warn(
(
f"System time is way off (before {RECENT_DATE}). This will probably "
"lead to SSL verification errors"
),
SystemTimeWarning,
)
# Remove trailing '.' from fqdn hostnames to allow certificate validation
server_hostname_rm_dot = server_hostname.rstrip(".")
> sock_and_verified = _ssl_wrap_socket_and_match_hostname(
sock=sock,
cert_reqs=self.cert_reqs,
ssl_version=self.ssl_version,
ssl_minimum_version=self.ssl_minimum_version,
ssl_maximum_version=self.ssl_maximum_version,
ca_certs=self.ca_certs,
ca_cert_dir=self.ca_cert_dir,
ca_cert_data=self.ca_cert_data,
cert_file=self.cert_file,
key_file=self.key_file,
key_password=self.key_password,
server_hostname=server_hostname_rm_dot,
ssl_context=self.ssl_context,
tls_in_tls=tls_in_tls,
assert_hostname=self.assert_hostname,
assert_fingerprint=self.assert_fingerprint,
)
/opt/anaconda3/lib/python3.12/site-packages/urllib3/connection.py:730:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
sock = <socket.socket [closed] fd=-1, family=30, type=1, proto=6>
def _ssl_wrap_socket_and_match_hostname(
sock: socket.socket,
*,
cert_reqs: None | str | int,
ssl_version: None | str | int,
ssl_minimum_version: int | None,
ssl_maximum_version: int | None,
cert_file: str | None,
key_file: str | None,
key_password: str | None,
ca_certs: str | None,
ca_cert_dir: str | None,
ca_cert_data: None | str | bytes,
assert_hostname: None | str | typing.Literal[False],
assert_fingerprint: str | None,
server_hostname: str | None,
ssl_context: ssl.SSLContext | None,
tls_in_tls: bool = False,
) -> _WrappedAndVerifiedSocket:
"""Logic for constructing an SSLContext from all TLS parameters, passing
that down into ssl_wrap_socket, and then doing certificate verification
either via hostname or fingerprint. This function exists to guarantee
that both proxies and targets have the same behavior when connecting via TLS.
"""
default_ssl_context = False
if ssl_context is None:
default_ssl_context = True
context = create_urllib3_context(
ssl_version=resolve_ssl_version(ssl_version),
ssl_minimum_version=ssl_minimum_version,
ssl_maximum_version=ssl_maximum_version,
cert_reqs=resolve_cert_reqs(cert_reqs),
)
else:
context = ssl_context
context.verify_mode = resolve_cert_reqs(cert_reqs)
# In some cases, we want to verify hostnames ourselves
if (
# `ssl` can't verify fingerprints or alternate hostnames
assert_fingerprint
or assert_hostname
# assert_hostname can be set to False to disable hostname checking
or assert_hostname is False
# We still support OpenSSL 1.0.2, which prevents us from verifying
# hostnames easily: https://github.com/pyca/pyopenssl/pull/933
or ssl_.IS_PYOPENSSL
or not ssl_.HAS_NEVER_CHECK_COMMON_NAME
):
context.check_hostname = False
# Try to load OS default certs if none are given. We need to do the hasattr() check
# for custom pyOpenSSL SSLContext objects because they don't support
# load_default_certs().
if (
not ca_certs
and not ca_cert_dir
and not ca_cert_data
and default_ssl_context
and hasattr(context, "load_default_certs")
):
context.load_default_certs()
# Ensure that IPv6 addresses are in the proper format and don't have a
# scope ID. Python's SSL module fails to recognize scoped IPv6 addresses
# and interprets them as DNS hostnames.
if server_hostname is not None:
normalized = server_hostname.strip("[]")
if "%" in normalized:
normalized = normalized[: normalized.rfind("%")]
if is_ipaddress(normalized):
server_hostname = normalized
> ssl_sock = ssl_wrap_socket(
sock=sock,
keyfile=key_file,
certfile=cert_file,
key_password=key_password,
ca_certs=ca_certs,
ca_cert_dir=ca_cert_dir,
ca_cert_data=ca_cert_data,
server_hostname=server_hostname,
ssl_context=context,
tls_in_tls=tls_in_tls,
)
/opt/anaconda3/lib/python3.12/site-packages/urllib3/connection.py:909:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
sock = <socket.socket [closed] fd=-1, family=30, type=1, proto=6>
keyfile = None, certfile = None, cert_reqs = None
ca_certs = '/Users/Vinay/Documents/SeleniumRepo/seleniumhq.github.io/tests/resources/tls.crt'
server_hostname = 'localhost', ssl_version = None, ciphers = None
ssl_context = <ssl.SSLContext object at 0x111ee5250>, ca_cert_dir = None
key_password = None, ca_cert_data = None, tls_in_tls = False
def ssl_wrap_socket(
sock: socket.socket,
keyfile: str | None = None,
certfile: str | None = None,
cert_reqs: int | None = None,
ca_certs: str | None = None,
server_hostname: str | None = None,
ssl_version: int | None = None,
ciphers: str | None = None,
ssl_context: ssl.SSLContext | None = None,
ca_cert_dir: str | None = None,
key_password: str | None = None,
ca_cert_data: None | str | bytes = None,
tls_in_tls: bool = False,
) -> ssl.SSLSocket | SSLTransportType:
"""
All arguments except for server_hostname, ssl_context, tls_in_tls, ca_cert_data and
ca_cert_dir have the same meaning as they do when using
:func:`ssl.create_default_context`, :meth:`ssl.SSLContext.load_cert_chain`,
:meth:`ssl.SSLContext.set_ciphers` and :meth:`ssl.SSLContext.wrap_socket`.
:param server_hostname:
When SNI is supported, the expected hostname of the certificate
:param ssl_context:
A pre-made :class:`SSLContext` object. If none is provided, one will
be created using :func:`create_urllib3_context`.
:param ciphers:
A string of ciphers we wish the client to support.
:param ca_cert_dir:
A directory containing CA certificates in multiple separate files, as
supported by OpenSSL's -CApath flag or the capath argument to
SSLContext.load_verify_locations().
:param key_password:
Optional password if the keyfile is encrypted.
:param ca_cert_data:
Optional string containing CA certificates in PEM format suitable for
passing as the cadata parameter to SSLContext.load_verify_locations()
:param tls_in_tls:
Use SSLTransport to wrap the existing socket.
"""
context = ssl_context
if context is None:
# Note: This branch of code and all the variables in it are only used in tests.
# We should consider deprecating and removing this code.
context = create_urllib3_context(ssl_version, cert_reqs, ciphers=ciphers)
if ca_certs or ca_cert_dir or ca_cert_data:
try:
context.load_verify_locations(ca_certs, ca_cert_dir, ca_cert_data)
except OSError as e:
> raise SSLError(e) from e
E urllib3.exceptions.SSLError: [Errno 2] No such file or directory
/opt/anaconda3/lib/python3.12/site-packages/urllib3/util/ssl_.py:449: SSLError
The above exception was the direct cause of the following exception:
grid_server = 'https://localhost:55939'
@pytest.mark.skipif(sys.platform == "win32", reason="Gets stuck on Windows, passes locally")
def test_start_remote_with_client_config(grid_server):
proxy = Proxy({"proxyType": ProxyType.AUTODETECT})
retries = Retry(connect=2, read=2, redirect=2)
timeout = Timeout(connect=300, read=3600)
client_config = ClientConfig(remote_server_addr=grid_server,
proxy=proxy,
init_args_for_pool_manager={
"init_args_for_pool_manager": {"retries": retries, "timeout": timeout}},
ca_certs=_get_resource_path("tls.crt"),
username="admin", password="myStrongPassword")
options = webdriver.ChromeOptions()
> driver = webdriver.Remote(command_executor=grid_server, options=options, client_config=client_config)
examples/python/tests/drivers/test_http_client.py:23:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/opt/anaconda3/lib/python3.12/site-packages/selenium/webdriver/remote/webdriver.py:241: in __init__
self.start_session(capabilities)
/opt/anaconda3/lib/python3.12/site-packages/selenium/webdriver/remote/webdriver.py:329: in start_session
response = self.execute(Command.NEW_SESSION, caps)["value"]
/opt/anaconda3/lib/python3.12/site-packages/selenium/webdriver/remote/webdriver.py:382: in execute
response = self.command_executor.execute(driver_command, params)
/opt/anaconda3/lib/python3.12/site-packages/selenium/webdriver/remote/remote_connection.py:404: in execute
return self._request(command_info[0], url, body=data)
/opt/anaconda3/lib/python3.12/site-packages/selenium/webdriver/remote/remote_connection.py:428: in _request
response = self._conn.request(method, url, body=body, headers=headers, timeout=self._client_config.timeout)
/opt/anaconda3/lib/python3.12/site-packages/urllib3/_request_methods.py:143: in request
return self.request_encode_body(
/opt/anaconda3/lib/python3.12/site-packages/urllib3/_request_methods.py:278: in request_encode_body
return self.urlopen(method, url, **extra_kw)
/opt/anaconda3/lib/python3.12/site-packages/urllib3/poolmanager.py:443: in urlopen
response = conn.urlopen(method, u.request_uri, **kw)
/opt/anaconda3/lib/python3.12/site-packages/urllib3/connectionpool.py:873: in urlopen
return self.urlopen(
/opt/anaconda3/lib/python3.12/site-packages/urllib3/connectionpool.py:873: in urlopen
return self.urlopen(
/opt/anaconda3/lib/python3.12/site-packages/urllib3/connectionpool.py:873: in urlopen
return self.urlopen(
/opt/anaconda3/lib/python3.12/site-packages/urllib3/connectionpool.py:873: in urlopen
return self.urlopen(
/opt/anaconda3/lib/python3.12/site-packages/urllib3/connectionpool.py:873: in urlopen
return self.urlopen(
/opt/anaconda3/lib/python3.12/site-packages/urllib3/connectionpool.py:873: in urlopen
return self.urlopen(
/opt/anaconda3/lib/python3.12/site-packages/urllib3/connectionpool.py:873: in urlopen
return self.urlopen(
/opt/anaconda3/lib/python3.12/site-packages/urllib3/connectionpool.py:873: in urlopen
return self.urlopen(
/opt/anaconda3/lib/python3.12/site-packages/urllib3/connectionpool.py:873: in urlopen
return self.urlopen(
/opt/anaconda3/lib/python3.12/site-packages/urllib3/connectionpool.py:873: in urlopen
return self.urlopen(
/opt/anaconda3/lib/python3.12/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = Retry(total=0, connect=2, read=2, redirect=2, status=None)
method = 'POST', url = '/session', response = None
error = SSLError(FileNotFoundError(2, 'No such file or directory'))
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x111ee3aa0>
_stacktrace = <traceback object at 0x111ed9a00>
def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.
:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.
:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)
total = self.total
if total is not None:
total -= 1
connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None
if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1
elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1
elif error:
# Other retry?
if other is not None:
other -= 1
elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status
else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status
history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)
new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)
if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='localhost', port=55939): Max retries exceeded with url: /session (Caused by SSLError(FileNotFoundError(2, 'No such file or directory')))
/opt/anaconda3/lib/python3.12/site-packages/urllib3/util/retry.py:519: MaxRetryError
---------------------------- Captured stdout setup -----------------------------
HTTPSConnectionPool(host='localhost', port=55939): Max retries exceeded with url: /status (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x111ee1580>: Failed to establish a new connection: [Errno 61] Connection refused'))
HTTPSConnectionPool(host='localhost', port=55939): Max retries exceeded with url: /status (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x111f20260>: Failed to establish a new connection: [Errno 61] Connection refused'))
HTTPSConnectionPool(host='localhost', port=55939): Max retries exceeded with url: /sta…1 parent df6fabb commit 9b31456Copy full SHA for 9b31456
File tree
Expand file treeCollapse file tree
1 file changed
+6
-6
lines changedFilter options
- examples/python
Expand file treeCollapse file tree
1 file changed
+6
-6
lines changedexamples/python/requirements.txt
Copy file name to clipboard+6-6Lines changed: 6 additions & 6 deletions
Original file line number | Diff line number | Diff line change | |
---|---|---|---|
| |||
1 | 1 |
| |
2 |
| - | |
3 |
| - | |
4 |
| - | |
5 |
| - | |
6 |
| - | |
7 |
| - | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + |
0 commit comments