Skip to content

[py] Addressing mypy type annotation errors #15928

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: trunk
Choose a base branch
from
8 changes: 5 additions & 3 deletions py/selenium/webdriver/chrome/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class Service(service.ChromiumService):
:param env: (Optional) Mapping of environment variables for the new process, defaults to `os.environ`.
"""

_service_args: list[str]

def __init__(
self,
executable_path: Optional[str] = None,
Expand All @@ -43,7 +45,7 @@ def __init__(
env: Optional[Mapping[str, str]] = None,
**kwargs,
) -> None:
self._service_args = service_args or []
self._service_args = list(service_args or [])

super().__init__(
executable_path=executable_path,
Expand All @@ -55,11 +57,11 @@ def __init__(
)

@property
def service_args(self) -> Sequence[str]:
def service_args(self) -> list[str]:
return self._service_args

@service_args.setter
def service_args(self, value: Sequence[str]):
def service_args(self, value: list[str]):
if isinstance(value, str) or not isinstance(value, Sequence):
raise TypeError("service_args must be a sequence")
self._service_args = list(value)
2 changes: 2 additions & 0 deletions py/selenium/webdriver/chrome/webdriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
class WebDriver(ChromiumDriver):
"""Controls the ChromeDriver and allows you to drive the browser."""

service: Service

def __init__(
self,
options: Optional[Options] = None,
Expand Down
9 changes: 6 additions & 3 deletions py/selenium/webdriver/chromium/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

from collections.abc import Mapping, Sequence
from io import IOBase
from typing import Optional
from typing import Optional, Union

from selenium.types import SubprocessStdAlias
from selenium.webdriver.common import service
Expand All @@ -35,6 +35,9 @@ class ChromiumService(service.Service):
:param driver_path_env_key: (Optional) Environment variable to use to get the path to the driver executable.
"""

_service_args: list[str]
log_output: Union[None, IOBase, int, SubprocessStdAlias]
Copy link
Contributor Author

@bandophahita bandophahita Jun 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Annotation to let mypy know what log_output attribute can be. Autodetermination wasn't smart enough to see past the argument annotation which was fine for the argument but incomplete for the attribute.

Copy link
Contributor Author

@bandophahita bandophahita Jun 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a real possibility that the argument annotation is incomplete here too. I didn't address this. Someone more familiar with the log_output argument should confirm it's annotation.


def __init__(
self,
executable_path: Optional[str] = None,
Expand Down Expand Up @@ -69,11 +72,11 @@ def command_line_args(self) -> list[str]:
return [f"--port={self.port}"] + self._service_args

@property
def service_args(self) -> Sequence[str]:
def service_args(self) -> list[str]:
return self._service_args

@service_args.setter
def service_args(self, value: Sequence[str]):
def service_args(self, value: list[str]):
if isinstance(value, str) or not isinstance(value, Sequence):
raise TypeError("service_args must be a sequence")
self._service_args = list(value)
13 changes: 6 additions & 7 deletions py/selenium/webdriver/chromium/webdriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@
# specific language governing permissions and limitations
# under the License.

from typing import Optional

from selenium.webdriver.chromium.options import ChromiumOptions
from selenium.webdriver.chromium.remote_connection import ChromiumRemoteConnection
from selenium.webdriver.chromium.service import ChromiumService
from selenium.webdriver.common.driver_finder import DriverFinder
from selenium.webdriver.common.options import ArgOptions
from selenium.webdriver.common.service import Service
from selenium.webdriver.remote.command import Command
from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver

Expand All @@ -31,10 +30,10 @@ class ChromiumDriver(RemoteWebDriver):

def __init__(
self,
browser_name: Optional[str] = None,
vendor_prefix: Optional[str] = None,
options: ArgOptions = ArgOptions(),
service: Optional[Service] = None,
browser_name: str,
vendor_prefix: str,
options: ChromiumOptions = ChromiumOptions(),
service: ChromiumService = ChromiumService(),
keep_alive: bool = True,
) -> None:
"""Creates a new WebDriver instance of the ChromiumDriver. Starts the
Expand Down
2 changes: 2 additions & 0 deletions py/selenium/webdriver/common/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ class Service(ABC):
:param driver_path_env_key: (Optional) Environment variable to use to get the path to the driver executable.
"""

log_output: Union[None, IOBase, int, SubprocessStdAlias]

def __init__(
self,
executable_path: Optional[str] = None,
Expand Down
4 changes: 2 additions & 2 deletions py/selenium/webdriver/edge/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ def __init__(
)

@property
def service_args(self) -> Sequence[str]:
def service_args(self) -> list[str]:
return self._service_args

@service_args.setter
def service_args(self, value: Sequence[str]):
def service_args(self, value: list[str]):
if isinstance(value, str) or not isinstance(value, Sequence):
raise TypeError("service_args must be a sequence")
self._service_args = list(value)
2 changes: 2 additions & 0 deletions py/selenium/webdriver/edge/webdriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
class WebDriver(ChromiumDriver):
"""Controls the MSEdgeDriver and allows you to drive the browser."""

service: Service
Copy link
Contributor Author

@bandophahita bandophahita Jun 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class annotation lets mypy understand that the webdriver has an attribute service that is an instance of Service. The Optional[Service] argument annotation caused mypy to believe the attribute webdriver.servce could be None, when in fact it never is. Mypy isn't smart enough to read the code that way.


def __init__(
self,
options: Optional[Options] = None,
Expand Down
2 changes: 2 additions & 0 deletions py/selenium/webdriver/wpewebkit/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class Service(service.Service):
:param env: (Optional) Mapping of environment variables for the new process, defaults to `os.environ`.
"""

_service_args: list[str]

def __init__(
self,
executable_path: str = DEFAULT_EXECUTABLE_PATH,
Expand Down
4 changes: 3 additions & 1 deletion py/selenium/webdriver/wpewebkit/webdriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@
class WebDriver(RemoteWebDriver):
"""Controls the WPEWebKitDriver and allows you to drive the browser."""

service: Service

def __init__(
self,
options=None,
options: Optional[Options] = None,
service: Optional[Service] = None,
):
"""Creates a new instance of the WPEWebKit driver.
Expand Down