Updated script that can be controled by Nodejs web app
This commit is contained in:
16
lib/python3.13/site-packages/selenium/webdriver/ie/__init__.py
Executable file
16
lib/python3.13/site-packages/selenium/webdriver/ie/__init__.py
Executable file
@ -0,0 +1,16 @@
|
||||
# Licensed to the Software Freedom Conservancy (SFC) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The SFC licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
406
lib/python3.13/site-packages/selenium/webdriver/ie/options.py
Executable file
406
lib/python3.13/site-packages/selenium/webdriver/ie/options.py
Executable file
@ -0,0 +1,406 @@
|
||||
# Licensed to the Software Freedom Conservancy (SFC) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The SFC licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
from enum import Enum
|
||||
from typing import Any
|
||||
from typing import Dict
|
||||
|
||||
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
|
||||
from selenium.webdriver.common.options import ArgOptions
|
||||
|
||||
|
||||
class ElementScrollBehavior(Enum):
|
||||
TOP = 0
|
||||
BOTTOM = 1
|
||||
|
||||
|
||||
class _IeOptionsDescriptor:
|
||||
"""_IeOptionsDescriptor is an implementation of Descriptor Protocol:
|
||||
|
||||
: Any look-up or assignment to the below attributes in `Options` class will be intercepted
|
||||
by `__get__` and `__set__` method respectively.
|
||||
|
||||
- `browser_attach_timeout`
|
||||
- `element_scroll_behavior`
|
||||
- `ensure_clean_session`
|
||||
- `file_upload_dialog_timeout`
|
||||
- `force_create_process_api`
|
||||
- `force_shell_windows_api`
|
||||
- `full_page_screenshot`
|
||||
- `ignore_protected_mode_settings`
|
||||
- `ignore_zoom_level`
|
||||
- `initial_browser_url`
|
||||
- `native_events`
|
||||
- `persistent_hover`
|
||||
- `require_window_focus`
|
||||
- `use_per_process_proxy`
|
||||
- `use_legacy_file_upload_dialog_handling`
|
||||
- `attach_to_edge_chrome`
|
||||
- `edge_executable_path`
|
||||
|
||||
|
||||
: When an attribute lookup happens,
|
||||
Example:
|
||||
`self. browser_attach_timeout`
|
||||
`__get__` method does a dictionary look up in the dictionary `_options` in `Options` class
|
||||
and returns the value of key `browserAttachTimeout`
|
||||
: When an attribute assignment happens,
|
||||
Example:
|
||||
`self.browser_attach_timeout` = 30
|
||||
`__set__` method sets/updates the value of the key `browserAttachTimeout` in `_options`
|
||||
dictionary in `Options` class.
|
||||
"""
|
||||
|
||||
def __init__(self, name, expected_type):
|
||||
self.name = name
|
||||
self.expected_type = expected_type
|
||||
|
||||
def __get__(self, obj, cls):
|
||||
return obj._options.get(self.name)
|
||||
|
||||
def __set__(self, obj, value) -> None:
|
||||
if not isinstance(value, self.expected_type):
|
||||
raise ValueError(f"{self.name} should be of type {self.expected_type.__name__}")
|
||||
|
||||
if self.name == "elementScrollBehavior" and value not in [
|
||||
ElementScrollBehavior.TOP,
|
||||
ElementScrollBehavior.BOTTOM,
|
||||
]:
|
||||
raise ValueError("Element Scroll Behavior out of range.")
|
||||
obj._options[self.name] = value
|
||||
|
||||
|
||||
class Options(ArgOptions):
|
||||
KEY = "se:ieOptions"
|
||||
SWITCHES = "ie.browserCommandLineSwitches"
|
||||
|
||||
BROWSER_ATTACH_TIMEOUT = "browserAttachTimeout"
|
||||
ELEMENT_SCROLL_BEHAVIOR = "elementScrollBehavior"
|
||||
ENSURE_CLEAN_SESSION = "ie.ensureCleanSession"
|
||||
FILE_UPLOAD_DIALOG_TIMEOUT = "ie.fileUploadDialogTimeout"
|
||||
FORCE_CREATE_PROCESS_API = "ie.forceCreateProcessApi"
|
||||
FORCE_SHELL_WINDOWS_API = "ie.forceShellWindowsApi"
|
||||
FULL_PAGE_SCREENSHOT = "ie.enableFullPageScreenshot"
|
||||
IGNORE_PROTECTED_MODE_SETTINGS = "ignoreProtectedModeSettings"
|
||||
IGNORE_ZOOM_LEVEL = "ignoreZoomSetting"
|
||||
INITIAL_BROWSER_URL = "initialBrowserUrl"
|
||||
NATIVE_EVENTS = "nativeEvents"
|
||||
PERSISTENT_HOVER = "enablePersistentHover"
|
||||
REQUIRE_WINDOW_FOCUS = "requireWindowFocus"
|
||||
USE_PER_PROCESS_PROXY = "ie.usePerProcessProxy"
|
||||
USE_LEGACY_FILE_UPLOAD_DIALOG_HANDLING = "ie.useLegacyFileUploadDialogHandling"
|
||||
ATTACH_TO_EDGE_CHROME = "ie.edgechromium"
|
||||
EDGE_EXECUTABLE_PATH = "ie.edgepath"
|
||||
IGNORE_PROCESS_MATCH = "ie.ignoreprocessmatch"
|
||||
|
||||
# Creating descriptor objects for each of the above IE options
|
||||
browser_attach_timeout = _IeOptionsDescriptor(BROWSER_ATTACH_TIMEOUT, int)
|
||||
"""Gets and Sets `browser_attach_timeout`
|
||||
|
||||
Usage
|
||||
-----
|
||||
- Get
|
||||
- `self.browser_attach_timeout`
|
||||
- Set
|
||||
- `self.browser_attach_timeout` = `value`
|
||||
|
||||
Parameters
|
||||
----------
|
||||
`value`: `int` (Timeout) in milliseconds
|
||||
"""
|
||||
|
||||
element_scroll_behavior = _IeOptionsDescriptor(ELEMENT_SCROLL_BEHAVIOR, Enum)
|
||||
"""Gets and Sets `element_scroll_behavior`
|
||||
|
||||
Usage
|
||||
-----
|
||||
- Get
|
||||
- `self.element_scroll_behavior`
|
||||
- Set
|
||||
- `self.element_scroll_behavior` = `value`
|
||||
|
||||
Parameters
|
||||
----------
|
||||
`value`: `int` either 0 - Top, 1 - Bottom
|
||||
"""
|
||||
|
||||
ensure_clean_session = _IeOptionsDescriptor(ENSURE_CLEAN_SESSION, bool)
|
||||
"""Gets and Sets `ensure_clean_session`
|
||||
|
||||
Usage
|
||||
-----
|
||||
- Get
|
||||
- `self.ensure_clean_session`
|
||||
- Set
|
||||
- `self.ensure_clean_session` = `value`
|
||||
|
||||
Parameters
|
||||
----------
|
||||
`value`: `bool`
|
||||
"""
|
||||
|
||||
file_upload_dialog_timeout = _IeOptionsDescriptor(FILE_UPLOAD_DIALOG_TIMEOUT, int)
|
||||
"""Gets and Sets `file_upload_dialog_timeout`
|
||||
|
||||
Usage
|
||||
-----
|
||||
- Get
|
||||
- `self.file_upload_dialog_timeout`
|
||||
- Set
|
||||
- `self.file_upload_dialog_timeout` = `value`
|
||||
|
||||
Parameters
|
||||
----------
|
||||
`value`: `int` (Timeout) in milliseconds
|
||||
"""
|
||||
|
||||
force_create_process_api = _IeOptionsDescriptor(FORCE_CREATE_PROCESS_API, bool)
|
||||
"""Gets and Sets `force_create_process_api`
|
||||
|
||||
Usage
|
||||
-----
|
||||
- Get
|
||||
- `self.force_create_process_api`
|
||||
- Set
|
||||
- `self.force_create_process_api` = `value`
|
||||
|
||||
Parameters
|
||||
----------
|
||||
`value`: `bool`
|
||||
"""
|
||||
|
||||
force_shell_windows_api = _IeOptionsDescriptor(FORCE_SHELL_WINDOWS_API, bool)
|
||||
"""Gets and Sets `force_shell_windows_api`
|
||||
|
||||
Usage
|
||||
-----
|
||||
- Get
|
||||
- `self.force_shell_windows_api`
|
||||
- Set
|
||||
- `self.force_shell_windows_api` = `value`
|
||||
|
||||
Parameters
|
||||
----------
|
||||
`value`: `bool`
|
||||
"""
|
||||
|
||||
full_page_screenshot = _IeOptionsDescriptor(FULL_PAGE_SCREENSHOT, bool)
|
||||
"""Gets and Sets `full_page_screenshot`
|
||||
|
||||
Usage
|
||||
-----
|
||||
- Get
|
||||
- `self.full_page_screenshot`
|
||||
- Set
|
||||
- `self.full_page_screenshot` = `value`
|
||||
|
||||
Parameters
|
||||
----------
|
||||
`value`: `bool`
|
||||
"""
|
||||
|
||||
ignore_protected_mode_settings = _IeOptionsDescriptor(IGNORE_PROTECTED_MODE_SETTINGS, bool)
|
||||
"""Gets and Sets `ignore_protected_mode_settings`
|
||||
|
||||
Usage
|
||||
-----
|
||||
- Get
|
||||
- `self.ignore_protected_mode_settings`
|
||||
- Set
|
||||
- `self.ignore_protected_mode_settings` = `value`
|
||||
|
||||
Parameters
|
||||
----------
|
||||
`value`: `bool`
|
||||
"""
|
||||
|
||||
ignore_zoom_level = _IeOptionsDescriptor(IGNORE_ZOOM_LEVEL, bool)
|
||||
"""Gets and Sets `ignore_zoom_level`
|
||||
|
||||
Usage
|
||||
-----
|
||||
- Get
|
||||
- `self.ignore_zoom_level`
|
||||
- Set
|
||||
- `self.ignore_zoom_level` = `value`
|
||||
|
||||
Parameters
|
||||
----------
|
||||
`value`: `bool`
|
||||
"""
|
||||
|
||||
initial_browser_url = _IeOptionsDescriptor(INITIAL_BROWSER_URL, str)
|
||||
"""Gets and Sets `initial_browser_url`
|
||||
|
||||
Usage
|
||||
-----
|
||||
- Get
|
||||
- `self.initial_browser_url`
|
||||
- Set
|
||||
- `self.initial_browser_url` = `value`
|
||||
|
||||
Parameters
|
||||
----------
|
||||
`value`: `str`
|
||||
"""
|
||||
|
||||
native_events = _IeOptionsDescriptor(NATIVE_EVENTS, bool)
|
||||
"""Gets and Sets `native_events`
|
||||
|
||||
Usage
|
||||
-----
|
||||
- Get
|
||||
- `self.native_events`
|
||||
- Set
|
||||
- `self.native_events` = `value`
|
||||
|
||||
Parameters
|
||||
----------
|
||||
`value`: `bool`
|
||||
"""
|
||||
|
||||
persistent_hover = _IeOptionsDescriptor(PERSISTENT_HOVER, bool)
|
||||
"""Gets and Sets `persistent_hover`
|
||||
|
||||
Usage
|
||||
-----
|
||||
- Get
|
||||
- `self.persistent_hover`
|
||||
- Set
|
||||
- `self.persistent_hover` = `value`
|
||||
|
||||
Parameters
|
||||
----------
|
||||
`value`: `bool`
|
||||
"""
|
||||
|
||||
require_window_focus = _IeOptionsDescriptor(REQUIRE_WINDOW_FOCUS, bool)
|
||||
"""Gets and Sets `require_window_focus`
|
||||
|
||||
Usage
|
||||
-----
|
||||
- Get
|
||||
- `self.require_window_focus`
|
||||
- Set
|
||||
- `self.require_window_focus` = `value`
|
||||
|
||||
Parameters
|
||||
----------
|
||||
`value`: `bool`
|
||||
"""
|
||||
|
||||
use_per_process_proxy = _IeOptionsDescriptor(USE_PER_PROCESS_PROXY, bool)
|
||||
"""Gets and Sets `use_per_process_proxy`
|
||||
|
||||
Usage
|
||||
-----
|
||||
- Get
|
||||
- `self.use_per_process_proxy`
|
||||
- Set
|
||||
- `self.use_per_process_proxy` = `value`
|
||||
|
||||
Parameters
|
||||
----------
|
||||
`value`: `bool`
|
||||
"""
|
||||
|
||||
use_legacy_file_upload_dialog_handling = _IeOptionsDescriptor(USE_LEGACY_FILE_UPLOAD_DIALOG_HANDLING, bool)
|
||||
"""Gets and Sets `use_legacy_file_upload_dialog_handling`
|
||||
|
||||
Usage
|
||||
-----
|
||||
- Get
|
||||
- `self.use_legacy_file_upload_dialog_handling`
|
||||
- Set
|
||||
- `self.use_legacy_file_upload_dialog_handling` = `value`
|
||||
|
||||
Parameters
|
||||
----------
|
||||
`value`: `bool`
|
||||
"""
|
||||
|
||||
attach_to_edge_chrome = _IeOptionsDescriptor(ATTACH_TO_EDGE_CHROME, bool)
|
||||
"""Gets and Sets `attach_to_edge_chrome`
|
||||
|
||||
Usage
|
||||
-----
|
||||
- Get
|
||||
- `self.attach_to_edge_chrome`
|
||||
- Set
|
||||
- `self.attach_to_edge_chrome` = `value`
|
||||
|
||||
Parameters
|
||||
----------
|
||||
`value`: `bool`
|
||||
"""
|
||||
|
||||
edge_executable_path = _IeOptionsDescriptor(EDGE_EXECUTABLE_PATH, str)
|
||||
"""Gets and Sets `edge_executable_path`
|
||||
|
||||
Usage
|
||||
-----
|
||||
- Get
|
||||
- `self.edge_executable_path`
|
||||
- Set
|
||||
- `self.edge_executable_path` = `value`
|
||||
|
||||
Parameters
|
||||
----------
|
||||
`value`: `str`
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self._options: Dict[str, Any] = {}
|
||||
self._additional: Dict[str, Any] = {}
|
||||
|
||||
@property
|
||||
def options(self) -> dict:
|
||||
""":Returns: A dictionary of browser options."""
|
||||
return self._options
|
||||
|
||||
@property
|
||||
def additional_options(self) -> dict:
|
||||
""":Returns: The additional options."""
|
||||
return self._additional
|
||||
|
||||
def add_additional_option(self, name: str, value) -> None:
|
||||
"""Adds an additional option not yet added as a safe option for IE.
|
||||
|
||||
:Args:
|
||||
- name: name of the option to add
|
||||
- value: value of the option to add
|
||||
"""
|
||||
self._additional[name] = value
|
||||
|
||||
def to_capabilities(self) -> dict:
|
||||
"""Marshals the IE options to the correct object."""
|
||||
caps = self._caps
|
||||
|
||||
opts = self._options.copy()
|
||||
if self._arguments:
|
||||
opts[self.SWITCHES] = " ".join(self._arguments)
|
||||
|
||||
if self._additional:
|
||||
opts.update(self._additional)
|
||||
|
||||
if opts:
|
||||
caps[Options.KEY] = opts
|
||||
return caps
|
||||
|
||||
@property
|
||||
def default_capabilities(self) -> dict:
|
||||
return DesiredCapabilities.INTERNETEXPLORER.copy()
|
66
lib/python3.13/site-packages/selenium/webdriver/ie/service.py
Executable file
66
lib/python3.13/site-packages/selenium/webdriver/ie/service.py
Executable file
@ -0,0 +1,66 @@
|
||||
# Licensed to the Software Freedom Conservancy (SFC) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The SFC licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
import typing
|
||||
from typing import List
|
||||
|
||||
from selenium.types import SubprocessStdAlias
|
||||
from selenium.webdriver.common import service
|
||||
|
||||
|
||||
class Service(service.Service):
|
||||
"""Object that manages the starting and stopping of the IEDriver."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
executable_path: str = None,
|
||||
port: int = 0,
|
||||
host: typing.Optional[str] = None,
|
||||
service_args: typing.Optional[typing.List[str]] = None,
|
||||
log_level: typing.Optional[str] = None,
|
||||
log_output: SubprocessStdAlias = None,
|
||||
driver_path_env_key: str = None,
|
||||
**kwargs,
|
||||
) -> None:
|
||||
"""Creates a new instance of the Service.
|
||||
|
||||
:Args:
|
||||
- executable_path : Path to the IEDriver
|
||||
- port : Port the service is running on
|
||||
- host : IP address the service port is bound
|
||||
- log_level : Level of logging of service, may be "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE".
|
||||
Default is "FATAL".
|
||||
- log_output: (Optional) int representation of STDOUT/DEVNULL, any IO instance or String path to file.
|
||||
Default is "stdout".
|
||||
"""
|
||||
self.service_args = service_args or []
|
||||
driver_path_env_key = driver_path_env_key or "SE_IEDRIVER"
|
||||
|
||||
if host:
|
||||
self.service_args.append(f"--host={host}")
|
||||
if log_level:
|
||||
self.service_args.append(f"--log-level={log_level}")
|
||||
|
||||
super().__init__(
|
||||
executable_path=executable_path,
|
||||
port=port,
|
||||
log_output=log_output,
|
||||
driver_path_env_key=driver_path_env_key,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
def command_line_args(self) -> List[str]:
|
||||
return [f"--port={self.port}"] + self.service_args
|
75
lib/python3.13/site-packages/selenium/webdriver/ie/webdriver.py
Executable file
75
lib/python3.13/site-packages/selenium/webdriver/ie/webdriver.py
Executable file
@ -0,0 +1,75 @@
|
||||
# Licensed to the Software Freedom Conservancy (SFC) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The SFC licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from selenium.webdriver.common.driver_finder import DriverFinder
|
||||
from selenium.webdriver.remote.client_config import ClientConfig
|
||||
from selenium.webdriver.remote.remote_connection import RemoteConnection
|
||||
from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver
|
||||
|
||||
from .options import Options
|
||||
from .service import Service
|
||||
|
||||
|
||||
class WebDriver(RemoteWebDriver):
|
||||
"""Controls the IEServerDriver and allows you to drive Internet
|
||||
Explorer."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
options: Options = None,
|
||||
service: Service = None,
|
||||
keep_alive: bool = True,
|
||||
) -> None:
|
||||
"""Creates a new instance of the Ie driver.
|
||||
|
||||
Starts the service and then creates new instance of Ie driver.
|
||||
|
||||
:Args:
|
||||
- options - IE Options instance, providing additional IE options
|
||||
- service - (Optional) service instance for managing the starting and stopping of the driver.
|
||||
- keep_alive - Whether to configure RemoteConnection to use HTTP keep-alive.
|
||||
"""
|
||||
|
||||
self.service = service if service else Service()
|
||||
options = options if options else Options()
|
||||
|
||||
self.service.path = self.service.env_path() or DriverFinder(self.service, options).get_driver_path()
|
||||
self.service.start()
|
||||
|
||||
client_config = ClientConfig(remote_server_addr=self.service.service_url, keep_alive=keep_alive, timeout=120)
|
||||
executor = RemoteConnection(
|
||||
ignore_proxy=options._ignore_local_proxy,
|
||||
client_config=client_config,
|
||||
)
|
||||
|
||||
try:
|
||||
super().__init__(command_executor=executor, options=options)
|
||||
except Exception:
|
||||
self.quit()
|
||||
raise
|
||||
|
||||
self._is_remote = False
|
||||
|
||||
def quit(self) -> None:
|
||||
"""Closes the browser and shuts down the IEServerDriver executable."""
|
||||
try:
|
||||
super().quit()
|
||||
except Exception:
|
||||
# We don't care about the message because something probably has gone wrong
|
||||
pass
|
||||
finally:
|
||||
self.service.stop()
|
Reference in New Issue
Block a user