def _check_if_chrome_browser_is_up_to_date(self) -> None: """Сhecks for the latest version of chrome browser""" try: if platform.system() not in ['Darwin']: message = 'Chrome browser checking/updating is currently disabled for your OS. Please wait for the new releases.' logger.error(message) return is_browser_up_to_date, current_version, latest_version = self._compare_current_version_and_latest_version_chrome_browser( ) if not is_browser_up_to_date: self._get_latest_chrome_browser_for_current_os() is_browser_up_to_date, current_version, latest_version = self._compare_current_version_and_latest_version_chrome_browser( ) if not is_browser_up_to_date: message = f'Problem with updating chrome browser current_version: {current_version} latest_version: {latest_version}' logger.info(message) except (ValueError, FileNotFoundError): pass
def _get_latest_version_chrome_browser(self, no_messages: bool = False) -> str: """Gets latest chrome browser version Returns: str latest_version (str) : Latest version of chrome browser. """ latest_version: str = '' latest_stable_version_element: Any = '' url = self.setting["ChromeBrowser"]["LinkAllLatestRelease"] json_data = self.requests_getter.get_result_by_request(url=url) soup = BeautifulSoup(json_data, 'html.parser') elements_news = soup.findAll('div', attrs={'class': 'post'}) stable_channel_header_text = 'Stable Channel Update for Desktop' for news in elements_news: if stable_channel_header_text in news.text: current_os = platform.system().replace('Darwin', 'Mac') if not current_os.lower() in news.text.lower(): continue latest_stable_version_element = news.text break if not latest_stable_version_element: message = f'Could not determine latest stable channel post of Chrome Browser. Maybe the text "{stable_channel_header_text}" is changed' logger.error(message) message = 'Trying to determine latest stable channel post of Chrome Browser without OS detection' logger.info(message) latest_stable_version_element = [ news.text for news in elements_news if stable_channel_header_text in news.text ][0] if not latest_stable_version_element: return latest_version latest_version = re.findall( self.setting["Program"]["wedriverVersionPattern"], latest_stable_version_element)[0] if not no_messages: logger.info(f'Latest version of chrome browser: {latest_version}') return latest_version
def __check_all_input_parameteres() -> None: """Private function for checking all input parameters""" if not Path(_info.path).exists() and _info.path.endswith(os.path.sep): message = f"The specified path does not exist current path is: {_info.path}, trying to create this directory" logger.error(message) Path(_info.path).mkdir() logger.info( f'Successfully created new directory at path: {_info.path}') if not Path(_info.path).is_dir(): message = f"The specified path is not a directory current path is: {_info.path}" raise NotADirectoryError(message) if isinstance(_info.driver_name, (list, str)): if _info.filename: DriverUpdater.__check_parameter_type_is_valid( _info.filename, type(_info.driver_name), 'filename') if _info.system_name: DriverUpdater.__check_parameter_type_is_valid( _info.system_name, type(_info.driver_name), 'system_name') if _info.version: DriverUpdater.__check_parameter_type_is_valid( _info.version, type(_info.driver_name), 'version') if isinstance(_info.driver_name, str): if _info.system_name: DriverUpdater.__check_system_name_is_valid( system_name=_info.system_name) elif isinstance(_info.driver_name, list): if _info.system_name: for os_system in _info.system_name: DriverUpdater.__check_system_name_is_valid( system_name=os_system) else: message = f'The type of "driver_name" must be a list or str current type is: {type(_info.driver_name)}' raise ValueError(message)
def __check_library_is_up_to_date() -> None: """Private function for comparing latest version and current version of program""" url: str = str(setting["PyPi"]["urlProjectJson"]) if 'b' not in str(setting["Program"]["version"]).lower(): json_data = RequestsGetter.get_result_by_request(url=url, is_json=True) current_version = str(setting["Program"]["version"]) latest_version = json_data.get('info').get('version') current_version_tuple = tuple( map(int, (current_version.split(".")))) latest_version_tuple = tuple(map(int, (latest_version.split(".")))) if latest_version_tuple > current_version_tuple: message = ( 'Your selenium-driver-updater library is out of date,' 'please update it via "pip install selenium-driver-updater --upgrade" ' f'current_version: {current_version} latest_version: {latest_version} ' ) logger.warning(message) elif latest_version_tuple == current_version_tuple: message = 'Your selenium-driver-updater library is up to date.' logger.info(message) else: message = 'Unable to compare the latest version and the current version of the library.' logger.error(message) else: message = ( 'Thanks for participating in beta releases for selenium-driver-updater library,' f'you are using the beta version {str(setting["Program"]["version"])}' ) logger.info(message) message = 'Note that beta version does not guarantee errors avoiding. If something goes wrong - please create an issue on github repository' logger.info(message) message = 'Github repository link: https://github.com/Svinokur/selenium_driver_updater' logger.info(message)
def main(self) -> str: """Main function, checks for the latest version, downloads or updates chromedriver binary or downloads specific version of chromedriver. Returns: str driver_path (str) : Path where chromedriver was downloaded or updated. """ driver_path: str = '' self.chromebrowser.main() if not self.version: #additional checking for main versions to equal - for example, chromedriver version main is 90 and chrome browser is still 89 is_equal, latest_version_driver, latest_version_browser = self._compare_latest_version_main_chromedriver_and_latest_version_main_chrome_browser( ) if is_equal: driver_path = self._check_if_chromedriver_is_up_to_date() if not is_equal: message = ( f' Problem with chromedriver latest_version_driver:' f'{latest_version_driver} latest_version_browser: {latest_version_browser}\n' ' It often happen when new version of chromedriver released, but new version of chrome browser is not\n' ' Trying to download the latest previous version of chromedriver' ) logger.error(message) driver_path = self._download_driver(previous_version=True) else: driver_path = self._download_driver(version=self.version) return driver_path
def get_release_version_by_repo_name_via_site(repo_name: str, index: int = 0) -> Any: """Gets latest release asset by github repository name Args: repo_name (str): Repository path on github. Returns: Any json_data : All latest release data. """ url: str = str(setting["Github"]["linkAllReleases"]).format(repo_name) version: str = '' json_data = RequestsGetter.get_result_by_request(url=url) soup = BeautifulSoup(json_data, 'html.parser') try: version = soup.findAll('a', href=lambda href: href and 'releases/tag' in href)[index].text.strip() except IndexError: logger.error( 'Could not retrieve version via releases, trying to retrieve version via tags' ) url: str = 'https://github.com/{}/tags'.format(repo_name) json_data = RequestsGetter.get_result_by_request(url=url) soup = BeautifulSoup(json_data, 'html.parser') version_tag = soup.findAll( 'a', href=lambda href: href and 'releases/tag' in href )[index].text.strip() version = re.findall(setting["Program"]["wedriverVersionPattern"], str(version_tag))[0] return version
def _check_if_chromedriver_is_up_to_date(self) -> str: """Сhecks for the latest version, downloads or updates chromedriver binary Returns: str driver_path (str) : Path where chromedriver was downloaded or updated. """ driver_path: str = '' if self.check_driver_is_up_to_date and not self.system_name: is_driver_up_to_date, current_version, latest_version = super( )._compare_current_version_and_latest_version() if is_driver_up_to_date: return self.chromedriver_path driver_path = self._download_driver() if self.check_driver_is_up_to_date and not self.system_name: is_driver_up_to_date, current_version, latest_version = super( )._compare_current_version_and_latest_version() if not is_driver_up_to_date: message = ( f'Problem with updating chromedriver' f'current_version: {current_version} latest_version: {latest_version}' ) logger.error(message) message = 'Trying to download previous latest version of chromedriver' logger.info(message) driver_path = self._download_driver(previous_version=True) return driver_path
def install(driver_name, **kwargs): """Function for install or update Selenium driver binary Args: driver_name (Union[str, list[str]]) : Specified driver name/names which will be downloaded or updated. Like "DriverUpdater.chromedriver" or etc. path (str) : Specified path which will used for downloading or updating Selenium driver binary. Must be folder path. upgrade (bool) : If true, it will overwrite existing driver in the folder. Defaults to False. chmod (bool) : If true, it will make driver binary executable. Defaults to True. check_driver_is_up_to_date (bool) : If true, it will check driver version before and after upgrade. Defaults to True. 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. check_browser_is_up_to_date (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. old_return (bool) : If true, it will return additional variables "result" and "message" in returning Tuple. Returns: str driver_path (str) : Path where Selenium driver binary was downloaded or updated. """ #Initialize all variables result_run: bool = True message_run: str = '' old_return = bool(kwargs.get('old_return', False)) driver_path = '' _info.driver_name = driver_name _info.info_messages = bool(kwargs.get('info_messages', True)) if _info.info_messages: logger.setLevel(levels['info']) else: logger.setLevel(levels['error']) path = kwargs.get('path') if not path: path = os.getcwd() logger.info( 'You have not specified the path - so used default folder path instead' ) _info.path = str(os.path.abspath(path) + os.path.sep) _info.filename = str(kwargs.get('filename', '')).replace( '.', '') if type(kwargs.get('filename', '')) not in [ list, dict, tuple ] else kwargs.get('filename', '') _info.enable_library_update_check = bool( kwargs.get('enable_library_update_check', True)) _info.upgrade = bool(kwargs.get('upgrade', False)) _info.chmod = bool(kwargs.get('chmod', True)) _info.check_driver_is_up_to_date = bool( kwargs.get('check_driver_is_up_to_date', True)) _info.version = str(kwargs.get('version', '')) if type( kwargs.get('version', '')) not in [list, dict, tuple ] else kwargs.get( 'version', '') _info.check_browser_is_up_to_date = bool( kwargs.get('check_browser_is_up_to_date', False)) _info.system_name = kwargs.get('system_name', '') try: DriverUpdater.__check_enviroment_and_variables() if isinstance(_info.driver_name, str): driver_path = DriverUpdater.__run_specific_driver() elif isinstance(_info.driver_name, list): list_of_paths: list[str] = [] for i, driver in enumerate(_info.driver_name): time.sleep(1) #small sleep try: filename_driver = str(_info.filename[i]) filename_driver = filename_driver.replace('.', '') except IndexError: filename_driver = '' try: system_name_driver = str(_info.system_name[i]) except IndexError: system_name_driver = '' try: version_driver = str(_info.version[i]) except IndexError: version_driver = '' driver_path = DriverUpdater.__run_specific_driver( driver_name=driver, filename=filename_driver, system_name=system_name_driver, version=version_driver, index=i) list_of_paths.append(driver_path) driver_path = list_of_paths except Exception: result_run: bool = False message_run = f'error: {str(traceback.format_exc())}' logger.error(message_run) if old_return: return result_run, message_run, driver_path return driver_path
def _get_latest_chrome_browser_for_current_os(self) -> None: """Trying to update chrome browser to its latest version""" if platform.system() not in ['Darwin']: message = 'Chrome browser checking/updating is currently disabled for your OS. Please wait for the new releases.' logger.error(message) return url_release = self.setting["ChromeBrowser"]["LinkAllLatestReleaseFile"] path = self.chromedriver_path.replace( self.chromedriver_path.split(os.path.sep)[-1], '') + 'selenium-driver-updater' + os.path.sep archive_name = url_release.split('/')[-1] if not Path(path).exists(): Path(path).mkdir() if Path(path + archive_name).exists(): Path(path + archive_name).unlink() logger.info( f'Started to download chrome browser by url: {url_release}') archive_path = wget.download(url=url_release, out=path + archive_name) logger.info(f'Chrome browser was downloaded to path: {archive_path}') if platform.system() == 'Darwin': volume_path: str = '' try: logger.info('Trying to kill all chrome processes') subprocess.Popen(r'killall Google\ Chrome', shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) logger.info('Successfully killed all chrome processes') logger.info(f'Trying to attach image: {archive_path}') with subprocess.Popen(['hdiutil', 'attach', archive_path], stdout=subprocess.PIPE) as process: info = process.communicate()[0].decode('UTF-8') volume_path = re.findall('Volumes.*', info)[0] volume_path = f"/{volume_path}/" chrome_browser_path = volume_path + 'Google Chrome.app' logger.info( f'Successfully attached {archive_name} at path: {volume_path}' ) chrome_browser_path_application = '/Applications/Google Chrome.app' try: if Path(chrome_browser_path_application).exists(): shutil.rmtree(chrome_browser_path_application) except PermissionError: logger.error( f'Cannot delete chromebrowser at path: {chrome_browser_path_application} abort operation' ) return logger.info( f'Trying to move chrome browser from: {chrome_browser_path} to: {chrome_browser_path_application}' ) os.system( f'rsync -a "{volume_path}Google Chrome.app" /Applications/' ) logger.info( f'Successfully moved chrome browser from: {chrome_browser_path} to: {chrome_browser_path_application}' ) finally: with subprocess.Popen(['hdiutil', 'eject', volume_path], stdout=subprocess.PIPE) as process: info = process.communicate()[0].decode('UTF-8') logger.info( f'Successfully ejected {archive_name} at path: {volume_path}' ) if Path(archive_path).exists(): Path(archive_path).unlink()
def _get_latest_firefox_browser_for_current_os(self) -> None: """Trying to update firefox browser to its latest version""" if platform.system() not in ['Darwin']: message = 'Firefox browser checking/updating is currently disabled for your OS. Please wait for the new releases.' logger.error(message) return latest_version = self._get_latest_version_firefox_browser() system_name = platform.system() system_name = system_name.replace('Darwin', 'mac') system_name = system_name.replace('Windows', 'win') file_format = 'dmg' if system_name == 'mac' else 'exe' locale_name = locale.getlocale()[0].replace('_', '-') url_release = self.setting["FirefoxBrowser"]["LinkAllLatestRelease"].format(latest_version, system_name, locale_name, latest_version, file_format) try: url = url_release.replace(url_release.split('/')[-1], '') self.requests_getter.get_result_by_request(url) except Exception: message = f'Unknown locale name was specified locale_name: {locale_name}' raise OSError(message) path = self.geckodriver_path.replace(self.geckodriver_path.split(os.path.sep)[-1], '') + 'selenium-driver-updater' + os.path.sep archive_name = url_release.split('/')[-1] if not Path(path).exists(): Path(path).mkdir() if Path(path + archive_name).exists(): Path(path + archive_name).unlink() logger.info(f'Started to download firefox browser by url: {url_release}') archive_path = wget.download(url=url_release, out=path + archive_name) logger.info(f'Firefox browser was downloaded to path: {archive_path}') if platform.system() == 'Darwin': volume_path:str = '' try: logger.info('Trying to kill all firefox processes') subprocess.Popen('killall firefox', shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) logger.info('Successfully killed all firefox processes') logger.info(f'Trying to attach image: {archive_path}') with subprocess.Popen(['hdiutil', 'attach', archive_path], stdout=subprocess.PIPE) as process: info = process.communicate()[0].decode('UTF-8') volume_path = re.findall('Volumes.*', info)[0] volume_path = f"/{volume_path}/" firefox_browser_path = volume_path + 'Firefox.app' logger.info(f'Successfully attached {archive_name} at path: {volume_path}') firefox_browser_path_application = '/Applications/Firefox.app' if Path(firefox_browser_path_application).exists(): shutil.rmtree(firefox_browser_path_application) logger.info(f'Trying to move firefox browser from: {firefox_browser_path} to: {firefox_browser_path_application} ') os.system(f'rsync -a {volume_path}Firefox.app /Applications/') logger.info(f'Successfully moved firefox browser from: {firefox_browser_path} to: {firefox_browser_path_application}') finally: with subprocess.Popen(['hdiutil', 'eject', volume_path], stdout=subprocess.PIPE) as process: info = process.communicate()[0].decode('UTF-8') logger.info(f'Successfully ejected {archive_name} at path: {volume_path}') if Path(archive_path).exists(): Path(archive_path).unlink()
def _get_latest_opera_browser_for_current_os(self) -> None: """Trying to update opera browser to its latest version""" if platform.system() not in ['Darwin', 'Windows']: message = 'Opera browser checking/updating is currently disabled for your OS. Please wait for the new releases.' logger.error(message) return latest_version = self._get_latest_version_opera_browser() url_full_release = self.url_release + self.system_name if platform.system() == 'Darwin': if 'arm' in str( os.uname().machine) and platform.system() == 'Darwin': url_full_release = url_full_release + f'Opera_{latest_version}_Autoupdate_arm64.tar.xz' else: url_full_release = url_full_release + f'Opera_{latest_version}_Autoupdate.tar.xz' elif platform.system() == 'Windows': if self.setting['Program']['OSBitness'] == '64': url_full_release = url_full_release + f'Opera_{latest_version}_Setup_x64.exe' else: url_full_release = url_full_release + f'Opera_{latest_version}_Setup.exe' logger.info( f'Started download operabrowser by url: {url_full_release}') path = self.operadriver_path.replace( self.operadriver_path.split(os.path.sep)[-1], '') + 'selenium-driver-updater' + os.path.sep archive_name = url_full_release.split('/')[-1] if not Path(path).exists(): Path(path).mkdir() if Path(path + archive_name).exists(): Path(path + archive_name).unlink() logger.info( f'Started to download opera browser by url: {url_full_release}') archive_path = wget.download(url=url_full_release, out=path + archive_name) logger.info(f'Opera browser was downloaded to path: {archive_path}') if platform.system() == 'Darwin': logger.info('Trying to kill all opera processes') subprocess.Popen('killall Opera', shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) subprocess.Popen('killall Opera', shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) logger.info('Successfully killed all opera processes') self.extractor.extract_all_tar_xz_archive( archive_path=archive_path, delete_archive=True, out_path=path) opera_browser_path = path + 'Opera.app' opera_browser_path_application = '/Applications/Opera.app' if Path(opera_browser_path_application).exists(): shutil.rmtree(opera_browser_path_application) shutil.move(opera_browser_path, opera_browser_path_application) logger.info( f'Successfully moved opera browser from: {opera_browser_path} to: {opera_browser_path_application}' ) if Path(archive_path).exists(): Path(archive_path).unlink() elif platform.system() == 'Windows': logger.info('Trying to kill all opera.exe processes') subprocess.Popen('taskkill /F /IM "opera.exe" /T', shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) logger.info('Successfully killed all opera.exe processes') logger.info('Trying to install new opera browser') os.system( f'{archive_path} /install /silent /launchopera=no /desktopshortcut=no /pintotaskbar=no /setdefaultbrowser=0' ) logger.info('Successfully updated current opera browser')