diff --git a/CHANGELOG.md b/CHANGELOG.md index bd8f4c3..5be361a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## [7.0.0] - xx/08/2024 +## [7.0.0] - 14/08/2024 This version was written and tested on Python 3.11.1 #### Added @@ -6,6 +6,11 @@ This version was written and tested on Python 3.11.1 - Added new command assosiation "selupd" for easier use - Added automatic pypi release - Added deleting of .tmp files when downloading is manually stopped (KeyboardInterrupt) +- Added driver-version argument to command line + +#### Reworked + +- Reworked the version parameter: It now accepts the channel version (beta, dev, canary) for chromedriver and edgedriver instead of a specific driver version. #### Improvements @@ -20,6 +25,7 @@ This version was written and tested on Python 3.11.1 - Fixed an issue with incorrect extracting of tar.gz archives when specific filename is present - Fixed an issue with incorrect extracting of chromedriver with third_party_notice file - Fixed an issues with browsers versions checking +- Fixed issues with system_name not working #### Removed diff --git a/README.md b/README.md index c366d28..27876ea 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,19 @@ pip install selenium-driver-updater ``` ## Usage in code -This example shows how you can use this library to download chromedriver binary and use it immediately. +This example shows how you can use this library to download chromedriver binary and use it immediately. The chromedriver will be downloaded to base directory. +```python +from selenium_driver_updater import DriverUpdater +from selenium import webdriver + +filename = DriverUpdater.install(DriverUpdater.chromedriver) + +driver = webdriver.Chrome(filename) +driver.get('https://google.com') + +``` + +Or you can specify a path where you want to download a chromedriver to ```python from selenium_driver_updater import DriverUpdater from selenium import webdriver @@ -27,14 +39,26 @@ import os base_dir = os.path.dirname(os.path.abspath(__file__)) -filename = DriverUpdater.install(path=base_dir, driver_name=DriverUpdater.chromedriver, upgrade=True, check_driver_is_up_to_date=True) +filename = DriverUpdater.install(path=base_dir, driver_name=DriverUpdater.chromedriver) driver = webdriver.Chrome(filename) driver.get('https://google.com') ``` -Or you can use library to download and update chromedriver and geckodriver binaries at the same time. +You can also specify the version type (beta, dev, canary) you want to download. +```python +from selenium_driver_updater import DriverUpdater +from selenium import webdriver + +filename = DriverUpdater.install(driver_name=DriverUpdater.chromedriver, version=DriverUpdater.chromedriver_beta) + +driver = webdriver.Chrome(filename) +driver.get('https://google.com') + +``` + +You can also use library to download and update chromedriver and geckodriver binaries at the same time. ```python from selenium_driver_updater import DriverUpdater from selenium import webdriver @@ -43,7 +67,7 @@ import os base_dir = os.path.dirname(os.path.abspath(__file__)) list_drivers = [DriverUpdater.chromedriver, DriverUpdater.geckodriver] -filenames = DriverUpdater.install(path=base_dir, driver_name=list_drivers, upgrade=True, check_driver_is_up_to_date=True) +filenames = DriverUpdater.install(path=base_dir, driver_name=list_drivers) print(filenames) driver_chrome = webdriver.Chrome(filename[0]) @@ -61,6 +85,12 @@ selenium-driver-updater --help ``` To see all available arguments and commands +Or you can use alias +```bash +selupd --help +``` +for easier use + This example shows how you can use this console updater to download chromedriver to current dir ```bash selenium-driver-updater -d chromedriver @@ -76,7 +106,7 @@ selenium-driver-updater -d chromedriver,geckodriver ### ``Chromedriver`` #### ``DriverUpdater.chromedriver`` -For installing or updating [chromedriver binary](https://chromedriver.chromium.org) +For installing or updating [chromedriver binary](https://developer.chrome.com/docs/chromedriver/) All supported OS for this driver are: diff --git a/selenium_driver_updater/_chromeDriver.py b/selenium_driver_updater/_chromeDriver.py index 9fd0f2d..730498b 100644 --- a/selenium_driver_updater/_chromeDriver.py +++ b/selenium_driver_updater/_chromeDriver.py @@ -29,7 +29,8 @@ def __init__(self, **kwargs): specific_system = specific_system.replace('mac64_m1', 'mac-arm64') specific_system = specific_system.replace('mac64', 'mac-x64') if specific_system: - self.system_name = f"chromedriver_{specific_system}.zip" + self.system_name = f"chromedriver-{specific_system}.zip" + self.specific_system = specific_system self.chromedriver_path = self.driver_path @@ -70,39 +71,32 @@ def main(self) -> str: driver_path = self._download_driver(previous_version=True) else: - - try: - if version.parse(self.version) < version.parse('115'): - message = 'Versions below 115 are not supported - aborting operation' - logger.error(message) - raise DriverVersionInvalidException(message) - except Exception: - raise DriverVersionInvalidException('Invalid version was provided, please check it') driver_path = self._download_driver(version=self.version) return driver_path - def _get_latest_version_driver(self, no_messages : bool = False) -> str: - """Gets latest driver version + def _get_latest_version_driver(self, no_messages: bool = False) -> str: + """Gets the latest driver version based on the specified channel. Returns: - str + str: Latest version of the specific driver. + """ - latest_version (str) : Latest version of specific driver. + latest_version: str = '' - """ + channel_suffix = self.version.split('_')[1] if '_' in self.version else 'stable' - latest_version : str = '' + channel = channel_suffix.capitalize() # 'Beta', 'Dev', 'Canary' + + url = self.setting["ChromeDriver"]["LinkLastRelease"] - url = self.setting[self.driver_name_setting]["LinkLastRelease"] json_data = self.requests_getter.get_result_by_request(url=url, is_json=True) - latest_version = json_data.get('channels').get('Stable').get('version') + latest_version = json_data.get('channels', {}).get(channel, {}).get('version', '') if not no_messages: - - logger.info(f'Latest version of {self.driver_name}: {latest_version}') + logger.info(f'Latest version of chromedriver {self.version}: {latest_version}') return latest_version @@ -203,12 +197,7 @@ def _download_driver(self, version : str = '', previous_version : bool = False) super()._delete_current_driver_for_current_os() - if version: - - url = self.setting["ChromeDriver"]["LinkLastReleaseFile"].format(version) - logger.info(f'Started download chromedriver specific_version: {version}') - - elif previous_version: + if previous_version: latest_previous_version = self._get_latest_previous_version_chromedriver_via_requests() @@ -220,24 +209,17 @@ def _download_driver(self, version : str = '', previous_version : bool = False) latest_version = self._get_latest_version_driver() url = self.setting["ChromeDriver"]["LinkLastReleaseFile"].format(latest_version) - logger.info(f'Started download chromedriver latest_version: {latest_version}') + channel = 'stable' if '_' not in self.version else self.version.split('_')[1] + logger.info(f'Started download chromedriver {channel} latest_version: {latest_version}') if self.system_name: - url = url.replace(url.split("/")[-1], '') - url = url + self.system_name - + url = url.replace(url.split("/")[-1], self.system_name) + url = url.replace(url.split("/")[-2], self.specific_system) + logger.info(f'Started downloading chromedriver for specific system: {self.system_name}') if any([version, self.system_name ,latest_previous_version]): - if 'mac_arm64' in url: - try: - super()._check_if_version_is_valid(url=url) - except Exception: - logger.warning('Could not find binary with mac_arm64 name, trying to check version using different name') - url = url.replace('mac_arm64', 'mac64_m1') - super()._check_if_version_is_valid(url=url) - else: - super()._check_if_version_is_valid(url=url) + super()._check_if_version_is_valid(url=url) archive_name = url.split("/")[-1] out_path = self.path + archive_name diff --git a/selenium_driver_updater/_edgeDriver.py b/selenium_driver_updater/_edgeDriver.py index 4e5428f..036fcfb 100644 --- a/selenium_driver_updater/_edgeDriver.py +++ b/selenium_driver_updater/_edgeDriver.py @@ -145,12 +145,7 @@ def _download_driver(self, version : str = '', previous_version : bool = False) super()._delete_current_driver_for_current_os() - if version: - - url = str(self.setting["EdgeDriver"]["LinkLastReleaseFile"]).format(version) - logger.info(f'Started download edgedriver specific_version: {version}') - - elif previous_version: + if previous_version: latest_previous_version = self._get_latest_previous_version_edgedriver_via_requests() @@ -158,11 +153,15 @@ def _download_driver(self, version : str = '', previous_version : bool = False) logger.info(f'Started download edgedriver latest_previous_version: {latest_previous_version}') else: + + if self.version: + self.setting["EdgeDriver"]["LinkLastRelease"] = self.setting["EdgeDriver"]["LinkLastRelease"].replace('STABLE', self.version.split('_')[1].upper()) latest_version = super()._get_latest_version_driver() url = str(self.setting["EdgeDriver"]["LinkLastReleaseFile"]).format(latest_version) - logger.info(f'Started download edgedriver latest_version: {latest_version}') + channel = '' if '_' not in self.version else self.version.split('_')[1] + logger.info(f'Started download edgedriver {channel} latest_version: {latest_version}') if self.system_name: url = url.replace(url.split("/")[-1], '') diff --git a/selenium_driver_updater/consoleUpdater.py b/selenium_driver_updater/consoleUpdater.py index 67dda60..9c1f3e3 100644 --- a/selenium_driver_updater/consoleUpdater.py +++ b/selenium_driver_updater/consoleUpdater.py @@ -23,59 +23,68 @@ def parse_command_line(): description=description_text, formatter_class=argparse.RawTextHelpFormatter ) parser.add_argument( - "--driver_name", - "-d", - type=ConsoleUpdater.comma_separated_string, - action="store", - dest="driver_name", - metavar="DRIVER_NAME", - help="Specified driver name/names which will be downloaded or updated, if you want to specify multiple drivers, use commas", - default='', - required=True, + "--driver_name", + "-d", + type=ConsoleUpdater.comma_separated_string, + action="store", + dest="driver_name", + metavar="DRIVER_NAME", + help="Specified driver name/names which will be downloaded or updated, if you want to specify multiple drivers, use commas", + default='', + required=True, ) parser.add_argument( - "--path", - "-p", - action="store", - dest="path", - metavar="DIR", - help="Specified path which will used for downloading or updating Selenium driver binary. Must be folder path", - default='', + "--path", + "-p", + action="store", + dest="path", + metavar="DIR", + help="Specified path which will used for downloading or updating Selenium driver binary. Must be folder path", + default='', ) parser.add_argument( - "--info_messages", - "-im", - action="store", - dest="info_messages", - metavar="BOOLEAN", - help="If false, it will disable all info messages", - default=True, + "--info_messages", + "-im", + action="store", + dest="info_messages", + metavar="BOOLEAN", + help="If false, it will disable all info messages", + default=True, ) parser.add_argument( - "--filename", - type=ConsoleUpdater.comma_separated_string, - action="store", - dest="filename", - metavar="FILENAME", - help="Specific name for driver. If given, it will replace name for driver", - default='', + "--filename", + type=ConsoleUpdater.comma_separated_string, + action="store", + dest="filename", + metavar="FILENAME", + help="Specific name for driver. If given, it will replace name for driver", + default='', ) parser.add_argument( - "--check_browser", - "-cb", - action="store", - dest="check_browser", - metavar="BOOLEAN", - help="If true, it will check browser version before specific driver update or upgrade", - default=False, + "--check_browser", + "-cb", + action="store", + dest="check_browser", + metavar="BOOLEAN", + help="If true, it will check browser version before specific driver update or upgrade", + default=False, ) parser.add_argument( - "--system_name", - action="store", - dest="system_name", - metavar="SYSTEM_NAME", - help="Specific OS for driver", - default='', + "--system_name", + action="store", + dest="system_name", + metavar="SYSTEM_NAME", + help="Specific OS for driver", + default='', + ) + parser.add_argument( + "--driver-version", + "-dv", + action="store", + dest="version", + metavar="DRIVER_VERSION", + help="Specific version for driver", + default='', ) parser.add_argument("--version", action="version", version=str(setting["Program"]["version"])) return parser.parse_args() diff --git a/selenium_driver_updater/driverUpdater.py b/selenium_driver_updater/driverUpdater.py index 20c1b61..767393e 100644 --- a/selenium_driver_updater/driverUpdater.py +++ b/selenium_driver_updater/driverUpdater.py @@ -40,9 +40,18 @@ class DriverUpdater(): #DRIVERS chromedriver = 'chromedriver' + chromedriver_beta = 'chromedriver_beta' + chromedriver_dev = 'chromedriver_dev' + chromedriver_canary = 'chromedriver_canary' + geckodriver = 'geckodriver' operadriver = 'operadriver' + edgedriver = 'edgedriver' + edgedriver_beta = 'edgedriver_beta' + edgedriver_dev = 'edgedriver_dev' + edgedriver_canary = 'edgedriver_canary' + safaridriver = 'safaridriver' #OS'S @@ -68,7 +77,7 @@ def install(driver_name, **kwargs): path (str) : Specified path which will used for downloading or updating Selenium driver binary. Must be folder path. info_messages (bool) : If false, it will disable all info messages. Defaults to True. filename (str) : Specific name for driver. If given, it will replace current name for driver. Defaults to empty string. - version (str) : Specific version for driver. If given, it will downloads given version. Defaults to empty string. + version (str) : Specific channel version for driver (beta, dev, canary). If given, it will download given channel latest version. Defaults to empty string. check_browser (bool) : If true, it will check browser version before specific driver update or upgrade. Defaults to False. enable_library_update_check (bool) : If true, it will enable checking for library update while starting. Defaults to True. system_name (Union[str, list[str]]) : Specific OS for driver. Defaults to empty string. @@ -219,8 +228,18 @@ def __check_system_name_type() -> None: @staticmethod def __check_version_type() -> None: - if _info.version: - DriverUpdater.__check_parameter_type_is_valid(_info.version, type(_info.driver_name), 'version') + valid_versions = { + 'chromedriver_beta', + 'chromedriver_dev', + 'chromedriver_canary', + 'edgedriver_beta', + 'edgedriver_dev', + 'edgedriver_canary' + } + + if _info.version and _info.version not in valid_versions: + message = f"Invalid version specified: {_info.version}. Must be one of {', '.join(valid_versions)}." + raise ValueError(message) @staticmethod def __validate_system_names() -> None: diff --git a/selenium_driver_updater/test/chrome_driver_test.py b/selenium_driver_updater/test/chrome_driver_test.py index 8c5c775..33892d1 100644 --- a/selenium_driver_updater/test/chrome_driver_test.py +++ b/selenium_driver_updater/test/chrome_driver_test.py @@ -55,12 +55,6 @@ def test_get_current_version_chrome_selenium_failure(chrome_driver_setup): current_version = chrome_driver_failure._get_current_version_driver() assert len(current_version) == 0 -def test_download_driver_failure(chrome_driver_setup): - """Test downloading driver with failure.""" - _, chrome_driver_failure = chrome_driver_setup - with pytest.raises(DriverVersionInvalidException): - chrome_driver_failure._download_driver(version='blablablanotversion') - def test_compare_current_version_and_latest_version_failure(chrome_driver_setup): """Test comparing current and latest versions with failure.""" _, chrome_driver_failure = chrome_driver_setup @@ -69,12 +63,6 @@ def test_compare_current_version_and_latest_version_failure(chrome_driver_setup) assert len(current_version) == 0 assert len(latest_version) == 0 -def test_chromedriver_is_up_to_date_failure(chrome_driver_setup): - """Test if ChromeDriver is up to date with failure.""" - _, chrome_driver_failure = chrome_driver_setup - with pytest.raises(DriverVersionInvalidException): - chrome_driver_failure.main() - def test_if_version_is_valid_failure(chrome_driver_setup): """Test if a specific version is valid with failure.""" _, chrome_driver_failure = chrome_driver_setup @@ -107,7 +95,7 @@ def test_download_driver_specific_version(setup_paths): chrome_driver._delete_current_driver_for_current_os() assert not Path(chromedriver_path).exists() - file_name = chrome_driver._download_driver(version='115.0.5763.0') + file_name = chrome_driver._download_driver(version='chromedriver_beta') assert file_name is not None assert len(file_name) > 0 assert Path(chromedriver_path).exists() @@ -117,7 +105,6 @@ def test_download_driver_specific_version(setup_paths): current_version = chrome_driver._get_current_version_driver() assert current_version is not None assert len(current_version) > 0 - assert current_version == '115.0.5763.0' def test_download_driver_latest_previous_version(setup_paths): """Test downloading the latest previous version of ChromeDriver.""" diff --git a/selenium_driver_updater/test/edge_driver_test.py b/selenium_driver_updater/test/edge_driver_test.py index fd5804e..e281696 100644 --- a/selenium_driver_updater/test/edge_driver_test.py +++ b/selenium_driver_updater/test/edge_driver_test.py @@ -47,12 +47,6 @@ def test_check_get_current_version_edge_selenium_failure(setup_edgedriver): assert len(current_version) == 0, f"Unexpected current version: {current_version}" -def test_check_download_driver_failure(setup_edgedriver): - _, edgedriver_failure, _ = setup_edgedriver - with pytest.raises(DriverVersionInvalidException): - edgedriver_failure._download_driver(version="blablablanotversion") - - def test_compare_current_version_and_latest_version_failure(setup_edgedriver): _, edgedriver_failure, _ = setup_edgedriver is_driver_up_to_date, current_version, latest_version = edgedriver_failure._compare_current_version_and_latest_version() @@ -60,11 +54,6 @@ def test_compare_current_version_and_latest_version_failure(setup_edgedriver): assert len(current_version) == 0 assert len(latest_version) == 0 -def test_check_if_edgedriver_is_up_to_date_failure(setup_edgedriver): - _, edgedriver_failure, _ = setup_edgedriver - with pytest.raises(DriverVersionInvalidException): - edgedriver_failure.main() - def test_check_if_version_is_valid_failure(setup_edgedriver): _, edgedriver_failure, _ = setup_edgedriver @@ -85,7 +74,7 @@ def test_check_download_driver_specific_version(setup_edgedriver): edgedriver_path = edgedriver.driver_path assert not Path(edgedriver_path).exists() - specific_version = '128.0.2739.22' + specific_version = 'edgedriver_beta' file_name = edgedriver._download_driver(version=specific_version) assert file_name is not None assert len(file_name) > 0 @@ -96,7 +85,6 @@ def test_check_download_driver_specific_version(setup_edgedriver): current_version = edgedriver._get_current_version_driver() assert current_version is not None assert len(current_version) > 0 - assert current_version == specific_version def test_download_driver_latest_previous_version(setup_edgedriver): @@ -164,7 +152,7 @@ def test_check_if_edgedriver_is_up_to_date(setup_edgedriver): def test_check_if_version_is_valid(setup_edgedriver): edgedriver, _, setting_local = setup_edgedriver - specific_version = '128.0.2739.22' + specific_version = '129.0.2766.0' url = str(setting_local["EdgeDriver"]["LinkLastReleaseFile"]).format(specific_version) if 'mac64_m1' in url: