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
示例#3
0
    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)
示例#4
0
    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
示例#8
0
    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')