prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  `RPA.core.webdriver` used by Selenium can't download latest Mac arm64 webdriver
  💻 System affected: M1/M2 Macs with no working `chromedriver` available in PATH under Chrome browser version **106.0.5249.61** and onwards.
  
  [Fix](https://github.com/SergeyPirogov/webdriver_manager/issues/446#issuecomment-1274558712) is already merged upstream but has not yet been released in PyPI.
  
  ### Reproduce
  
  ```python
  inv code.test-robot -r browser -t "Open Browser With Dict Options"
  ```
  
  ### Solution
  The desired fix would be to bump the `webdriver-manager` package `>3.8.3` once such version gets released.
  
  ### Workaround
  Meanwhile, we can implement the [workaround](https://github.com/SergeyPirogov/webdriver_manager/pull/445/files#diff-38d3c158b7a31027012330b5537df014f3ec50ffa657a2787d449bd3e3c9367bL32-R33) ourselves too as described above (`mac64_m1` -> `mac_arm64`) so we can hit the right web driver download URL.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `packages/core/src/RPA/core/webdriver.py`
  Content:
  ```
  1 import contextlib
  2 import logging
  3 import os
  4 import platform
  5 import stat
  6 from pathlib import Path
  7 from typing import Optional
  8 
  9 import requests
  10 from requests import Response
  11 from selenium import webdriver
  12 from selenium.webdriver.common.service import Service
  13 from selenium.webdriver.remote.webdriver import WebDriver
  14 from webdriver_manager.chrome import ChromeDriverManager
  15 from webdriver_manager.core.download_manager import WDMDownloadManager
  16 from webdriver_manager.core.http import WDMHttpClient
  17 from webdriver_manager.core.manager import DriverManager
  18 from webdriver_manager.core.utils import os_name as get_os_name
  19 from webdriver_manager.firefox import GeckoDriverManager
  20 from webdriver_manager.microsoft import EdgeChromiumDriverManager, IEDriverManager
  21 from webdriver_manager.opera import OperaDriverManager
  22 
  23 from RPA.core.robocorp import robocorp_home
  24 
  25 
  26 LOGGER = logging.getLogger(__name__)
  27 
  28 DRIVER_ROOT = robocorp_home() / "webdrivers"
  29 DRIVER_PREFERENCE = {
  30     "Windows": ["Chrome", "Firefox", "ChromiumEdge"],
  31     "Linux": ["Chrome", "Firefox", "ChromiumEdge"],
  32     "Darwin": ["Chrome", "Firefox", "ChromiumEdge", "Safari"],
  33     "default": ["Chrome", "Firefox"],
  34 }
  35 AVAILABLE_DRIVERS = {
  36     # Driver names taken from `webdrivermanager` and adapted to `webdriver_manager`.
  37     "chrome": ChromeDriverManager,
  38     "firefox": GeckoDriverManager,
  39     "gecko": GeckoDriverManager,
  40     "mozilla": GeckoDriverManager,
  41     # NOTE: Selenium 4 dropped support for Opera.
  42     #  (https://github.com/SeleniumHQ/selenium/issues/10835)
  43     "opera": OperaDriverManager,
  44     # NOTE: In Selenium 4 `Edge` is the same with `ChromiumEdge`.
  45     "edge": EdgeChromiumDriverManager,
  46     "chromiumedge": EdgeChromiumDriverManager,
  47     # NOTE: IE is discontinued and not supported/encouraged anymore.
  48     "ie": IEDriverManager,
  49 }
  50 
  51 
  52 class Downloader(WDMHttpClient):
  53 
  54     """Custom downloader which disables download progress reporting."""
  55 
  56     def get(self, url, **kwargs) -> Response:
  57         resp = requests.get(url=url, verify=self._ssl_verify, stream=True, **kwargs)
  58         self.validate_response(resp)
  59         return resp
  60 
  61 
  62 @contextlib.contextmanager
  63 def suppress_logging():
  64     """Suppress webdriver-manager logging."""
  65     wdm_log = "WDM_LOG"
  66     original_value = os.getenv(wdm_log, "")
  67     try:
  68         os.environ[wdm_log] = str(logging.NOTSET)
  69         yield
  70     finally:
  71         os.environ[wdm_log] = original_value
  72 
  73 
  74 def start(browser: str, service: Optional[Service] = None, **options) -> WebDriver:
  75     """Start a webdriver with the given options."""
  76     browser = browser.strip()
  77     webdriver_factory = getattr(webdriver, browser, None)
  78     if not webdriver_factory:
  79         raise ValueError(f"Unsupported browser: {browser}")
  80 
  81     # NOTE: It is recommended to pass a `service` rather than deprecated `options`.
  82     driver = webdriver_factory(service=service, **options)
  83     return driver
  84 
  85 
  86 def _to_manager(browser: str, root: Path = DRIVER_ROOT) -> DriverManager:
  87     browser = browser.strip()
  88     manager_factory = AVAILABLE_DRIVERS.get(browser.lower())
  89     if not manager_factory:
  90         raise ValueError(
  91             f"Unsupported browser {browser!r}! (choose from: {list(AVAILABLE_DRIVERS)})"
  92         )
  93 
  94     download_manager = WDMDownloadManager(Downloader())
  95     manager = manager_factory(path=str(root), download_manager=download_manager)
  96     return manager
  97 
  98 
  99 def _set_executable(path: str) -> None:
  100     st = os.stat(path)
  101     os.chmod(
  102         path,
  103         st.st_mode | stat.S_IXOTH | stat.S_IXGRP | stat.S_IEXEC,
  104     )
  105 
  106 
  107 def download(browser: str, root: Path = DRIVER_ROOT) -> Optional[str]:
  108     """Download a webdriver binary for the given browser and return the path to it."""
  109     manager = _to_manager(browser, root)
  110     driver = manager.driver
  111     resolved_os = getattr(driver, "os_type", driver.get_os_type())
  112     os_name = get_os_name()
  113     if os_name not in resolved_os:
  114         LOGGER.warning(
  115             "Attempting to download incompatible driver for OS %r on OS %r! Skip",
  116             resolved_os,
  117             os_name,
  118         )
  119         return None  # incompatible driver download attempt
  120 
  121     with suppress_logging():
  122         path: str = manager.install()
  123     if platform.system() != "Windows":
  124         _set_executable(path)
  125     LOGGER.debug("Downloaded webdriver to: %s", path)
  126     return path
  127
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/packages/core/src/RPA/core/webdriver.py b/packages/core/src/RPA/core/webdriver.py
  --- a/packages/core/src/RPA/core/webdriver.py
  +++ b/packages/core/src/RPA/core/webdriver.py
  @@ -7,6 +7,7 @@
   from typing import Optional
   
   import requests
  +from packaging import version
   from requests import Response
   from selenium import webdriver
   from selenium.webdriver.common.service import Service
  @@ -53,7 +54,23 @@
   
       """Custom downloader which disables download progress reporting."""
   
  +    def __init__(self, *args, **kwargs):
  +        super().__init__(*args, **kwargs)
  +        self.driver = None
  +
  +    def _fix_mac_arm_url(self, url) -> str:
  +        if "m1" not in self.driver.get_os_type():
  +            return url
  +
  +        # FIXME(cmin764): Remove this when the issue below gets closed
  +        #  https://github.com/SergeyPirogov/webdriver_manager/issues/446
  +        browser_version = self.driver.get_version()
  +        if version.parse(browser_version) >= version.parse("106.0.5249.61"):
  +            url = url.replace("mac64_m1", "mac_arm64")
  +        return url
  +
       def get(self, url, **kwargs) -> Response:
  +        url = self._fix_mac_arm_url(url)
           resp = requests.get(url=url, verify=self._ssl_verify, stream=True, **kwargs)
           self.validate_response(resp)
           return resp
  @@ -91,8 +108,10 @@
               f"Unsupported browser {browser!r}! (choose from: {list(AVAILABLE_DRIVERS)})"
           )
   
  -    download_manager = WDMDownloadManager(Downloader())
  +    downloader = Downloader()
  +    download_manager = WDMDownloadManager(downloader)
       manager = manager_factory(path=str(root), download_manager=download_manager)
  +    downloader.driver = manager.driver
       return manager
  
verification_info: {"golden_diff": "diff --git a/packages/core/src/RPA/core/webdriver.py b/packages/core/src/RPA/core/webdriver.py\n--- a/packages/core/src/RPA/core/webdriver.py\n+++ b/packages/core/src/RPA/core/webdriver.py\n@@ -7,6 +7,7 @@\n from typing import Optional\n \n import requests\n+from packaging import version\n from requests import Response\n from selenium import webdriver\n from selenium.webdriver.common.service import Service\n@@ -53,7 +54,23 @@\n \n     \"\"\"Custom downloader which disables download progress reporting.\"\"\"\n \n+    def __init__(self, *args, **kwargs):\n+        super().__init__(*args, **kwargs)\n+        self.driver = None\n+\n+    def _fix_mac_arm_url(self, url) -> str:\n+        if \"m1\" not in self.driver.get_os_type():\n+            return url\n+\n+        # FIXME(cmin764): Remove this when the issue below gets closed\n+        #  https://github.com/SergeyPirogov/webdriver_manager/issues/446\n+        browser_version = self.driver.get_version()\n+        if version.parse(browser_version) >= version.parse(\"106.0.5249.61\"):\n+            url = url.replace(\"mac64_m1\", \"mac_arm64\")\n+        return url\n+\n     def get(self, url, **kwargs) -> Response:\n+        url = self._fix_mac_arm_url(url)\n         resp = requests.get(url=url, verify=self._ssl_verify, stream=True, **kwargs)\n         self.validate_response(resp)\n         return resp\n@@ -91,8 +108,10 @@\n             f\"Unsupported browser {browser!r}! (choose from: {list(AVAILABLE_DRIVERS)})\"\n         )\n \n-    download_manager = WDMDownloadManager(Downloader())\n+    downloader = Downloader()\n+    download_manager = WDMDownloadManager(downloader)\n     manager = manager_factory(path=str(root), download_manager=download_manager)\n+    downloader.driver = manager.driver\n     return manager\n", "issue": "`RPA.core.webdriver` used by Selenium can't download latest Mac arm64 webdriver\n\ud83d\udcbb System affected: M1/M2 Macs with no working `chromedriver` available in PATH under Chrome browser version **106.0.5249.61** and onwards.\r\n\r\n[Fix](https://github.com/SergeyPirogov/webdriver_manager/issues/446#issuecomment-1274558712) is already merged upstream but has not yet been released in PyPI.\r\n\r\n### Reproduce\r\n\r\n```python\r\ninv code.test-robot -r browser -t \"Open Browser With Dict Options\"\r\n```\r\n\r\n### Solution\r\nThe desired fix would be to bump the `webdriver-manager` package `>3.8.3` once such version gets released.\r\n\r\n### Workaround\r\nMeanwhile, we can implement the [workaround](https://github.com/SergeyPirogov/webdriver_manager/pull/445/files#diff-38d3c158b7a31027012330b5537df014f3ec50ffa657a2787d449bd3e3c9367bL32-R33) ourselves too as described above (`mac64_m1` -> `mac_arm64`) so we can hit the right web driver download URL.\n", "before_files": [{"content": "import contextlib\nimport logging\nimport os\nimport platform\nimport stat\nfrom pathlib import Path\nfrom typing import Optional\n\nimport requests\nfrom requests import Response\nfrom selenium import webdriver\nfrom selenium.webdriver.common.service import Service\nfrom selenium.webdriver.remote.webdriver import WebDriver\nfrom webdriver_manager.chrome import ChromeDriverManager\nfrom webdriver_manager.core.download_manager import WDMDownloadManager\nfrom webdriver_manager.core.http import WDMHttpClient\nfrom webdriver_manager.core.manager import DriverManager\nfrom webdriver_manager.core.utils import os_name as get_os_name\nfrom webdriver_manager.firefox import GeckoDriverManager\nfrom webdriver_manager.microsoft import EdgeChromiumDriverManager, IEDriverManager\nfrom webdriver_manager.opera import OperaDriverManager\n\nfrom RPA.core.robocorp import robocorp_home\n\n\nLOGGER = logging.getLogger(__name__)\n\nDRIVER_ROOT = robocorp_home() / \"webdrivers\"\nDRIVER_PREFERENCE = {\n    \"Windows\": [\"Chrome\", \"Firefox\", \"ChromiumEdge\"],\n    \"Linux\": [\"Chrome\", \"Firefox\", \"ChromiumEdge\"],\n    \"Darwin\": [\"Chrome\", \"Firefox\", \"ChromiumEdge\", \"Safari\"],\n    \"default\": [\"Chrome\", \"Firefox\"],\n}\nAVAILABLE_DRIVERS = {\n    # Driver names taken from `webdrivermanager` and adapted to `webdriver_manager`.\n    \"chrome\": ChromeDriverManager,\n    \"firefox\": GeckoDriverManager,\n    \"gecko\": GeckoDriverManager,\n    \"mozilla\": GeckoDriverManager,\n    # NOTE: Selenium 4 dropped support for Opera.\n    #  (https://github.com/SeleniumHQ/selenium/issues/10835)\n    \"opera\": OperaDriverManager,\n    # NOTE: In Selenium 4 `Edge` is the same with `ChromiumEdge`.\n    \"edge\": EdgeChromiumDriverManager,\n    \"chromiumedge\": EdgeChromiumDriverManager,\n    # NOTE: IE is discontinued and not supported/encouraged anymore.\n    \"ie\": IEDriverManager,\n}\n\n\nclass Downloader(WDMHttpClient):\n\n    \"\"\"Custom downloader which disables download progress reporting.\"\"\"\n\n    def get(self, url, **kwargs) -> Response:\n        resp = requests.get(url=url, verify=self._ssl_verify, stream=True, **kwargs)\n        self.validate_response(resp)\n        return resp\n\n\n@contextlib.contextmanager\ndef suppress_logging():\n    \"\"\"Suppress webdriver-manager logging.\"\"\"\n    wdm_log = \"WDM_LOG\"\n    original_value = os.getenv(wdm_log, \"\")\n    try:\n        os.environ[wdm_log] = str(logging.NOTSET)\n        yield\n    finally:\n        os.environ[wdm_log] = original_value\n\n\ndef start(browser: str, service: Optional[Service] = None, **options) -> WebDriver:\n    \"\"\"Start a webdriver with the given options.\"\"\"\n    browser = browser.strip()\n    webdriver_factory = getattr(webdriver, browser, None)\n    if not webdriver_factory:\n        raise ValueError(f\"Unsupported browser: {browser}\")\n\n    # NOTE: It is recommended to pass a `service` rather than deprecated `options`.\n    driver = webdriver_factory(service=service, **options)\n    return driver\n\n\ndef _to_manager(browser: str, root: Path = DRIVER_ROOT) -> DriverManager:\n    browser = browser.strip()\n    manager_factory = AVAILABLE_DRIVERS.get(browser.lower())\n    if not manager_factory:\n        raise ValueError(\n            f\"Unsupported browser {browser!r}! (choose from: {list(AVAILABLE_DRIVERS)})\"\n        )\n\n    download_manager = WDMDownloadManager(Downloader())\n    manager = manager_factory(path=str(root), download_manager=download_manager)\n    return manager\n\n\ndef _set_executable(path: str) -> None:\n    st = os.stat(path)\n    os.chmod(\n        path,\n        st.st_mode | stat.S_IXOTH | stat.S_IXGRP | stat.S_IEXEC,\n    )\n\n\ndef download(browser: str, root: Path = DRIVER_ROOT) -> Optional[str]:\n    \"\"\"Download a webdriver binary for the given browser and return the path to it.\"\"\"\n    manager = _to_manager(browser, root)\n    driver = manager.driver\n    resolved_os = getattr(driver, \"os_type\", driver.get_os_type())\n    os_name = get_os_name()\n    if os_name not in resolved_os:\n        LOGGER.warning(\n            \"Attempting to download incompatible driver for OS %r on OS %r! Skip\",\n            resolved_os,\n            os_name,\n        )\n        return None  # incompatible driver download attempt\n\n    with suppress_logging():\n        path: str = manager.install()\n    if platform.system() != \"Windows\":\n        _set_executable(path)\n    LOGGER.debug(\"Downloaded webdriver to: %s\", path)\n    return path\n", "path": "packages/core/src/RPA/core/webdriver.py"}], "after_files": [{"content": "import contextlib\nimport logging\nimport os\nimport platform\nimport stat\nfrom pathlib import Path\nfrom typing import Optional\n\nimport requests\nfrom packaging import version\nfrom requests import Response\nfrom selenium import webdriver\nfrom selenium.webdriver.common.service import Service\nfrom selenium.webdriver.remote.webdriver import WebDriver\nfrom webdriver_manager.chrome import ChromeDriverManager\nfrom webdriver_manager.core.download_manager import WDMDownloadManager\nfrom webdriver_manager.core.http import WDMHttpClient\nfrom webdriver_manager.core.manager import DriverManager\nfrom webdriver_manager.core.utils import os_name as get_os_name\nfrom webdriver_manager.firefox import GeckoDriverManager\nfrom webdriver_manager.microsoft import EdgeChromiumDriverManager, IEDriverManager\nfrom webdriver_manager.opera import OperaDriverManager\n\nfrom RPA.core.robocorp import robocorp_home\n\n\nLOGGER = logging.getLogger(__name__)\n\nDRIVER_ROOT = robocorp_home() / \"webdrivers\"\nDRIVER_PREFERENCE = {\n    \"Windows\": [\"Chrome\", \"Firefox\", \"ChromiumEdge\"],\n    \"Linux\": [\"Chrome\", \"Firefox\", \"ChromiumEdge\"],\n    \"Darwin\": [\"Chrome\", \"Firefox\", \"ChromiumEdge\", \"Safari\"],\n    \"default\": [\"Chrome\", \"Firefox\"],\n}\nAVAILABLE_DRIVERS = {\n    # Driver names taken from `webdrivermanager` and adapted to `webdriver_manager`.\n    \"chrome\": ChromeDriverManager,\n    \"firefox\": GeckoDriverManager,\n    \"gecko\": GeckoDriverManager,\n    \"mozilla\": GeckoDriverManager,\n    # NOTE: Selenium 4 dropped support for Opera.\n    #  (https://github.com/SeleniumHQ/selenium/issues/10835)\n    \"opera\": OperaDriverManager,\n    # NOTE: In Selenium 4 `Edge` is the same with `ChromiumEdge`.\n    \"edge\": EdgeChromiumDriverManager,\n    \"chromiumedge\": EdgeChromiumDriverManager,\n    # NOTE: IE is discontinued and not supported/encouraged anymore.\n    \"ie\": IEDriverManager,\n}\n\n\nclass Downloader(WDMHttpClient):\n\n    \"\"\"Custom downloader which disables download progress reporting.\"\"\"\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.driver = None\n\n    def _fix_mac_arm_url(self, url) -> str:\n        if \"m1\" not in self.driver.get_os_type():\n            return url\n\n        # FIXME(cmin764): Remove this when the issue below gets closed\n        #  https://github.com/SergeyPirogov/webdriver_manager/issues/446\n        browser_version = self.driver.get_version()\n        if version.parse(browser_version) >= version.parse(\"106.0.5249.61\"):\n            url = url.replace(\"mac64_m1\", \"mac_arm64\")\n        return url\n\n    def get(self, url, **kwargs) -> Response:\n        url = self._fix_mac_arm_url(url)\n        resp = requests.get(url=url, verify=self._ssl_verify, stream=True, **kwargs)\n        self.validate_response(resp)\n        return resp\n\n\n@contextlib.contextmanager\ndef suppress_logging():\n    \"\"\"Suppress webdriver-manager logging.\"\"\"\n    wdm_log = \"WDM_LOG\"\n    original_value = os.getenv(wdm_log, \"\")\n    try:\n        os.environ[wdm_log] = str(logging.NOTSET)\n        yield\n    finally:\n        os.environ[wdm_log] = original_value\n\n\ndef start(browser: str, service: Optional[Service] = None, **options) -> WebDriver:\n    \"\"\"Start a webdriver with the given options.\"\"\"\n    browser = browser.strip()\n    webdriver_factory = getattr(webdriver, browser, None)\n    if not webdriver_factory:\n        raise ValueError(f\"Unsupported browser: {browser}\")\n\n    # NOTE: It is recommended to pass a `service` rather than deprecated `options`.\n    driver = webdriver_factory(service=service, **options)\n    return driver\n\n\ndef _to_manager(browser: str, root: Path = DRIVER_ROOT) -> DriverManager:\n    browser = browser.strip()\n    manager_factory = AVAILABLE_DRIVERS.get(browser.lower())\n    if not manager_factory:\n        raise ValueError(\n            f\"Unsupported browser {browser!r}! (choose from: {list(AVAILABLE_DRIVERS)})\"\n        )\n\n    downloader = Downloader()\n    download_manager = WDMDownloadManager(downloader)\n    manager = manager_factory(path=str(root), download_manager=download_manager)\n    downloader.driver = manager.driver\n    return manager\n\n\ndef _set_executable(path: str) -> None:\n    st = os.stat(path)\n    os.chmod(\n        path,\n        st.st_mode | stat.S_IXOTH | stat.S_IXGRP | stat.S_IEXEC,\n    )\n\n\ndef download(browser: str, root: Path = DRIVER_ROOT) -> Optional[str]:\n    \"\"\"Download a webdriver binary for the given browser and return the path to it.\"\"\"\n    manager = _to_manager(browser, root)\n    driver = manager.driver\n    resolved_os = getattr(driver, \"os_type\", driver.get_os_type())\n    os_name = get_os_name()\n    if os_name not in resolved_os:\n        LOGGER.warning(\n            \"Attempting to download incompatible driver for OS %r on OS %r! Skip\",\n            resolved_os,\n            os_name,\n        )\n        return None  # incompatible driver download attempt\n\n    with suppress_logging():\n        path: str = manager.install()\n    if platform.system() != \"Windows\":\n        _set_executable(path)\n    LOGGER.debug(\"Downloaded webdriver to: %s\", path)\n    return path\n", "path": "packages/core/src/RPA/core/webdriver.py"}]}