diff --git a/tests/test_ie_driver.py b/tests/test_ie_driver.py index c63f5a27..38c947b4 100644 --- a/tests/test_ie_driver.py +++ b/tests/test_ie_driver.py @@ -1,12 +1,20 @@ import os + import pytest -from selenium import webdriver + from webdriver_manager.microsoft import IEDriverManager -@pytest.mark.parametrize("version", ["2.53.1", - "3.0", - "latest"]) +@pytest.mark.parametrize("version", [ + "2.53.1", + "3.0", + "3.13.0", + "3.141.59", + "3.150.0", + # "3.150.1", + # "3.150.2", + "latest", +]) def test_ie_manager_with_different_versions(version): path = IEDriverManager(version).install() assert os.path.exists(path) diff --git a/webdriver_manager/driver.py b/webdriver_manager/driver.py index 04d045c9..2cf5bb61 100644 --- a/webdriver_manager/driver.py +++ b/webdriver_manager/driver.py @@ -1,9 +1,7 @@ import os -import re -from xml.etree import ElementTree +import platform import requests -import platform from webdriver_manager.logger import log from webdriver_manager.utils import ( @@ -69,47 +67,64 @@ def get_latest_release_version(self): class GeckoDriver(Driver): - def __init__(self, name, - version, - os_type, - url, - latest_release_url, - mozila_release_tag): - super(GeckoDriver, self).__init__(name, version, os_type, url, - latest_release_url) + def __init__( + self, + name, + version, + os_type, + url, + latest_release_url, + mozila_release_tag, + ): + super(GeckoDriver, self).__init__( + name, + version, + os_type, + url, + latest_release_url, + ) self._mozila_release_tag = mozila_release_tag - self._os_token = os.getenv("GH_TOKEN", None) - self.auth_header = None self.browser_version = firefox_version() + self._os_token = os.getenv("GH_TOKEN", None) + self.auth_header = ( + {'Authorization': f'token {self._os_token}'} + if self._os_token + else None + ) if self._os_token: log("GH_TOKEN will be used to perform requests", first_line=True) - self.auth_header = {'Authorization': f'token {self._os_token}'} - def get_latest_release_version(self): - # type: () -> str + def get_latest_release_version(self) -> str: log(f"Get LATEST driver version for {self.browser_version}") - resp = requests.get(url=self.latest_release_url, - headers=self.auth_header) + resp = requests.get( + url=self.latest_release_url, + headers=self.auth_header, + ) validate_response(resp) return resp.json()["tag_name"] def get_url(self): - # https://github.com/mozilla/geckodriver/releases/download/v0.11.1/geckodriver-v0.11.1-linux64.tar.gz + """Like https://github.com/mozilla/geckodriver/releases/download/v0.11.1/geckodriver-v0.11.1-linux64.tar.gz""" log(f"Getting latest mozilla release info for {self.get_version()}") - resp = requests.get(url=self.tagged_release_url(self.get_version()), - headers=self.auth_header) + resp = requests.get( + url=self.tagged_release_url(self.get_version()), + headers=self.auth_header, + ) validate_response(resp) assets = resp.json()["assets"] name = f"{self.get_name()}-{self.get_version()}-{self.get_os_type()}{'-aarch64' if (self.get_os_type() == 'macos' and not platform.processor() == 'i386') else ''}" + "." - output_dict = [asset for asset in assets if - asset['name'].startswith(name)] + output_dict = [ + asset for asset in assets if asset['name'].startswith(name) + ] return output_dict[0]['browser_download_url'] def get_os_type(self): - if super().get_os_type().startswith("mac"): - return "macos" - return super().get_os_type() + return ( + "macos" + if super().get_os_type().startswith("mac") + else super().get_os_type() + ) @property def latest_release_url(self): @@ -120,71 +135,80 @@ def tagged_release_url(self, version): class IEDriver(Driver): - def __init__(self, name, version, - os_type, - url, - latest_release_url): - - if os_type == "win64": - os_type = "x64" - else: - os_type = "Win32" - super(IEDriver, self).__init__(version=version, - os_type=os_type, - url=url, - latest_release_url=latest_release_url, - name=name) + def __init__( + self, + name, + version, + os_type, + url, + latest_release_url, + ie_release_tag, + ): + super(IEDriver, self).__init__( + name, + version, + url, + os_type, + latest_release_url, + ) + self.os_type = "x64" if os_type == "win64" else "Win32" + self._ie_release_tag = ie_release_tag + # todo: for 'browser_version' implement installed IE version detection + # like chrome or firefox self.browser_version = "" + self._os_token = os.getenv("GH_TOKEN", None) + self.auth_header = ( + {'Authorization': f'token {self._os_token}'} + if self._os_token + else None + ) + if self._os_token: + log("GH_TOKEN will be used to perform requests", first_line=True) - def sortchildrenby(self, container): - data = [] - for elem in container.iter("Contents"): - key = elem - data.append((key, elem)) - - data.sort() - - def get_latest_release_version(self): - resp = requests.get(self._url) - root = ElementTree.fromstring(resp.text) - - values = {} + def get_latest_release_version(self) -> str: + log(f"Get LATEST driver version for {self.browser_version}") + resp = requests.get( + url=self.latest_release_url, + headers=self.auth_header, + ) + validate_response(resp) + return resp.json()["tag_name"].replace('selenium-', '') - xmlns = '{http://doc.s3.amazonaws.com/2006-03-01}' + def get_url(self): + """Like https://github.com/seleniumhq/selenium/releases/download/3.141.59/IEDriverServer_Win32_3.141.59.zip""" + log(f"Getting latest ie release info for {self.get_version()}") + resp = requests.get( + url=self.tagged_release_url(self.get_version()), + headers=self.auth_header, + ) + validate_response(resp) + assets = resp.json()["assets"] - for child in root.findall(xmlns + 'Contents'): - key = child.find(xmlns + 'Key').text - if self.get_name() in key and self._os_type in key: - last_modified = child.find(xmlns + 'LastModified').text - values[last_modified] = key + name = f"{self.get_name()}_{self.os_type}_{self.get_version()}" + "." + output_dict = [ + asset for asset in assets if asset['name'].startswith(name) + ] + return output_dict[0]['browser_download_url'] - latest_key = values[max(values)] - # 2.39/IEDriverServer_Win32_2.39.0.zip - m = re.match(r".*_{os}_(.*)\.zip".format(os=self.get_os_type()), - latest_key) - if m: - return m.group(1) - else: - raise ValueError("Can't parse latest version {key} | {os}".format( - key=latest_key, os=self.get_os_type())) + @property + def latest_release_url(self): + return self._latest_release_url - def get_url(self): - major, minor, patch = self.__get_divided_version(self.get_version()) - return ("{url}/{major}.{minor}/" - "{name}_{os}_{major}.{minor}.{patch}.zip").format( - url=self._url, name=self.get_name(), os=self.get_os_type(), - major=major, minor=minor, patch=patch) + def tagged_release_url(self, version): + version = self.__get_divided_version(version) + return self._ie_release_tag.format(version) def __get_divided_version(self, version): divided_version = version.split('.') if len(divided_version) == 2: - return divided_version[0], divided_version[1], '0' + return f'{version}.0' elif len(divided_version) == 3: - return divided_version + return version else: raise ValueError( "Version must consist of major, minor and/or patch, " - "but given was: {version}".format(version=self.get_version())) + "but given was: {version}".format(version=self.get_version()) + ) class OperaDriver(Driver): diff --git a/webdriver_manager/microsoft.py b/webdriver_manager/microsoft.py index 1a16b1a4..20ed9372 100644 --- a/webdriver_manager/microsoft.py +++ b/webdriver_manager/microsoft.py @@ -5,43 +5,54 @@ class IEDriverManager(DriverManager): - def __init__(self, version="latest", - os_type=utils.os_type(), - path=None, - name="IEDriverServer", - url="http://selenium-release.storage.googleapis.com", - latest_release_url=None, - log_level=None, - print_first_line=True, - cache_valid_range=1): + def __init__( + self, + version="latest", + os_type=utils.os_type(), + path=None, + name="IEDriverServer", + url="https://github.com/seleniumhq/selenium/releases/download", + latest_release_url="https://api.github.com/repos/seleniumhq/selenium/releases/latest", + ie_release_tag="https://api.github.com/repos/seleniumhq/selenium/releases/tags/selenium-{0}", + log_level=None, + print_first_line=True, + cache_valid_range=1, + ): super().__init__(path, log_level, print_first_line, cache_valid_range) - self.driver = IEDriver(version=version, - os_type=os_type, - name=name, - url=url, - latest_release_url=latest_release_url) + self.driver = IEDriver( + version=version, + os_type=os_type, + name=name, + url=url, + latest_release_url=latest_release_url, + ie_release_tag=ie_release_tag, + ) def install(self): return self._get_driver_path(self.driver) class EdgeChromiumDriverManager(DriverManager): - def __init__(self, version="latest", - os_type=utils.os_type(), - path=None, - name="edgedriver", - url="https://msedgedriver.azureedge.net", - latest_release_url="https://msedgedriver.azureedge.net/" - "LATEST_RELEASE", - log_level=None, - print_first_line=None, - cache_valid_range=1): + def __init__( + self, + version="latest", + os_type=utils.os_type(), + path=None, + name="edgedriver", + url="https://msedgedriver.azureedge.net", + latest_release_url="https://msedgedriver.azureedge.net/LATEST_RELEASE", + log_level=None, + print_first_line=None, + cache_valid_range=1, + ): super().__init__(path, log_level, print_first_line, cache_valid_range) - self.driver = EdgeChromiumDriver(version=version, - os_type=os_type, - name=name, - url=url, - latest_release_url=latest_release_url) + self.driver = EdgeChromiumDriver( + version=version, + os_type=os_type, + name=name, + url=url, + latest_release_url=latest_release_url, + ) def install(self): return self._get_driver_path(self.driver)