def _req_as_option(self, req: UpgradeRequirement, tooltip: bool = True, custom_tooltip: str = None) -> InputOption: if req.pkg.installed: icon_path = req.pkg.get_disk_icon_path() if not icon_path or not os.path.isfile(icon_path): icon_path = req.pkg.get_type_icon_path() else: icon_path = req.pkg.get_type_icon_path() size_str = '{}: {}'.format( self.i18n['size'].capitalize(), '?' if req.extra_size is None else get_human_size_str(req.extra_size)) if req.extra_size != req.required_size: size_str += ' ( {}: {} )'.format( self.i18n['action.update.pkg.required_size'].capitalize(), '?' if req.required_size is None else get_human_size_str( req.required_size)) label = '{}{} - {}'.format( req.pkg.name, ' ( {} )'.format(req.pkg.latest_version) if req.pkg.latest_version else '', size_str) return InputOption(label=label, value=None, tooltip=custom_tooltip if custom_tooltip else (req.pkg.get_name_tooltip() if tooltip else None), read_only=True, icon_path=icon_path)
def get_info(self, pkg: SnapApplication) -> dict: info = { 'description': pkg.description, 'developer': pkg.developer, 'license': pkg.license, 'contact': pkg.contact, 'snap-id': pkg.id, 'name': pkg.name, 'publisher': pkg.publisher, 'revision': pkg.rev, 'tracking': pkg.tracking, 'channel': pkg.channel, 'type': pkg.type } if pkg.installed: commands = [ *{ c['name'] for c in SnapdClient(self.logger).list_commands(pkg.name) } ] commands.sort() info['commands'] = commands if pkg.installed_size: info['installed_size']: get_human_size_str(pkg.installed_size) elif pkg.download_size: info['download_size'] = get_human_size_str(pkg.download_size) return info
def get_info(self, pkg: WebApplication) -> dict: if pkg.installed: info = { '0{}_{}'.format(idx + 1, att): getattr(pkg, att) for idx, att in enumerate(('url', 'description', 'version', 'categories', 'installation_dir', 'desktop_entry')) } info['07_exec_file'] = pkg.get_exec_path() info['08_icon_path'] = pkg.get_disk_icon_path() if os.path.exists(pkg.installation_dir): info['09_size'] = get_human_size_str( get_dir_size(pkg.installation_dir)) config_dir = pkg.get_config_dir() if config_dir: info['10_config_dir'] = config_dir if info.get('04_categories'): info['04_categories'] = [ self.i18n[c.lower()].capitalize() for c in info['04_categories'] ] return info else: return { '0{}_{}'.format(idx + 1, att): getattr(pkg, att) for idx, att in enumerate(('url', 'description', 'version', 'categories')) }
def request_install_missing_deps(pkgname: str, deps: List[Tuple[str, str]], watcher: ProcessWatcher, i18n: I18n) -> bool: msg = '<p>{}</p>'.format(i18n['arch.missing_deps.body'].format( name=bold(pkgname) if pkgname else '', deps=bold(str(len(deps))))) opts = [] repo_deps = [d[0] for d in deps if d[1] != 'aur'] sizes = pacman.get_update_size(repo_deps) if repo_deps else {} for dep in deps: size = sizes.get(dep[0]) op = InputOption( '{} ({}: {}) - {}: {}'.format( dep[0], i18n['repository'], dep[1].lower(), i18n['size'].capitalize(), get_human_size_str(size) if size else '?'), dep[0]) op.read_only = True op.icon_path = _get_repo_icon(dep[1]) opts.append(op) comp = MultipleSelectComponent(label='', options=opts, default_options=set(opts)) return watcher.request_confirmation( i18n['arch.missing_deps.title'], msg, [comp], confirmation_label=i18n['continue'].capitalize(), deny_label=i18n['cancel'].capitalize())
def request_optional_deps(pkgname: str, pkg_repos: dict, watcher: ProcessWatcher, i18n: I18n) -> Set[str]: opts = [] repo_deps = [ p for p, data in pkg_repos.items() if data['repository'] != 'aur' ] sizes = pacman.get_update_size(repo_deps) if repo_deps else {} for p, d in pkg_repos.items(): size = sizes.get(p) op = InputOption( '{}{} ({}: {}) - {}: {}'.format( p, ': ' + d['desc'] if d['desc'] else '', i18n['repository'], d['repository'].lower(), i18n['size'].capitalize(), get_human_size_str(size) if size else '?'), p) op.icon_path = _get_repo_icon(d['repository']) opts.append(op) view_opts = MultipleSelectComponent(label='', options=opts, default_options=set(opts)) install = watcher.request_confirmation( title=i18n['arch.install.optdeps.request.title'], body='<p>{}.</p><p>{}:</p>'.format( i18n['arch.install.optdeps.request.body'].format(bold(pkgname)), i18n['arch.install.optdeps.request.help']), components=[view_opts], confirmation_label=i18n['install'].capitalize(), deny_label=i18n['do_not.install'].capitalize()) if install: return {o.value for o in view_opts.values}
def _gen_to_install_form( self, reqs: List[UpgradeRequirement] ) -> Tuple[FormComponent, Tuple[int, int]]: opts = [self._req_as_option(r, custom_tooltip=r.reason) for r in reqs] comps = [ MultipleSelectComponent(label='', options=opts, default_options=set(opts)) ] required_size, extra_size = self._sum_pkgs_size(reqs) lb = '{} ( {}: {}. {}: {}. {}: {} )'.format( self.i18n['action.update.required_label'].capitalize(), self.i18n['amount'].capitalize(), len(opts), self.i18n['size'].capitalize(), '?' if extra_size is None else get_human_size_str(extra_size), self.i18n['action.update.pkg.required_size'].capitalize(), '?' if required_size is None else get_human_size_str(required_size)) return FormComponent(label=lb, components=comps), (required_size, extra_size)
def _gen_to_remove_form(self, reqs: List[UpgradeRequirement]) -> FormComponent: opts = [self._req_as_option(r, False, r.reason, required_size=False) for r in reqs] comps = [MultipleSelectComponent(label='', options=opts, default_options=set(opts))] required_size, extra_size = self._sum_pkgs_size(reqs) lb = '{} ( {}: {}. {}: {} )'.format(self.i18n['action.update.label_to_remove'].capitalize(), self.i18n['amount'].capitalize(), len(opts), self.i18n['size'].capitalize(), '?' if extra_size is None else get_human_size_str(-extra_size)) return FormComponent(label=lb, components=comps)
def get_content_length(self, url: str, session: bool = True) -> str: params = {'url': url, 'allow_redirects': True, 'stream': True} if session: res = self.session.get(**params) else: res = requests.get(**params) if res.status_code == 200: size = res.headers.get('Content-Length') if size is not None: return system.get_human_size_str(size)
def get_content_length(self, url: str) -> str: """ :param url: :return: """ res = self.session.get(url, allow_redirects=True, stream=True) if res.status_code == 200: size = res.headers.get('Content-Length') if size is not None: return system.get_human_size_str(size)
def get_content_length(self, url: str, session: bool = True) -> str: size = self.get_content_length_in_bytes(url, session) if size: return system.get_human_size_str(size)
def run(self): root_user = user.is_root() to_update, upgrade_requires_root, bkp_supported = [], False, False for pkg in self.pkgs: if pkg.model.update and not pkg.model.is_update_ignored( ) and pkg.update_checked: to_update.append(pkg) if not bkp_supported and pkg.model.supports_backup(): bkp_supported = True if not root_user and not upgrade_requires_root and self.manager.requires_root( SoftwareAction.UPGRADE, pkg.model): upgrade_requires_root = True if upgrade_requires_root: valid_password, root_password = self._request_password() else: valid_password, root_password = True, None if not valid_password: self.notify_finished({ 'success': False, 'updated': 0, 'types': set(), 'id': None }) self.pkgs = None return if len(to_update) > 1: self.disable_progress_controll() else: self.enable_progress_controll() success = False updated, updated_types = 0, set() models = [view.model for view in to_update] self.change_substatus(self.i18n['action.update.requirements.status']) requirements = self.manager.get_upgrade_requirements( models, root_password, self) if not requirements: self.pkgs = None self.notify_finished({ 'success': success, 'updated': updated, 'types': updated_types, 'id': None }) return comps, required_size, extra_size = [], 0, 0 if requirements.cannot_upgrade: comps.append( self._gen_cannot_upgrade_form(requirements.cannot_upgrade)) if requirements.to_install: req_form, reqs_size = self._gen_to_install_form( requirements.to_install) required_size += reqs_size[0] extra_size += reqs_size[1] comps.append(req_form) if requirements.to_remove: comps.append(self._gen_to_remove_form(requirements.to_remove)) can_upgrade = False if requirements.to_upgrade: can_upgrade = True updates_form, updates_size = self._gen_to_update_form( requirements.to_upgrade) required_size += updates_size[0] extra_size += updates_size[1] comps.append(updates_form) extra_size_text = '{}: {}'.format( self.i18n['action.update.total_size'].capitalize(), get_human_size_str(extra_size)) req_size_text = '{}: {}'.format( self.i18n['action.update.required_size'].capitalize(), get_human_size_str(required_size)) comps.insert( 0, TextComponent('{} | {}'.format(extra_size_text, req_size_text), size=14)) comps.insert(1, TextComponent('')) if not self.request_confirmation( title=self.i18n['action.update.summary'].capitalize(), body='', components=comps, confirmation_label=self.i18n['proceed'].capitalize(), deny_label=self.i18n['cancel'].capitalize(), confirmation_button=can_upgrade): self.notify_finished({ 'success': success, 'updated': updated, 'types': updated_types, 'id': None }) self.pkgs = None return self.change_substatus('') app_config = CoreConfigManager().get_config() # backup dialog ( if enabled, supported and accepted ) should_backup = bkp_supported should_backup = should_backup and self._check_backup_requirements( app_config=app_config, pkg=None, action_key='upgrade') should_backup = should_backup and self._should_backup( action_key='upgrade', app_config=app_config, i18n=self.i18n) # trim dialog ( if enabled and accepted ) if app_config['disk']['trim']['after_upgrade'] is not False: should_trim = app_config['disk']['trim'][ 'after_upgrade'] or self._ask_for_trim() else: should_trim = False if should_trim and not root_user and root_password is None: # trim requires root and the password might have not being asked yet valid_password, root_password = self._request_password() if not valid_password: self.notify_finished({ 'success': False, 'updated': 0, 'types': set(), 'id': None }) self.pkgs = None return # performing backup if should_backup: proceed, root_password = self.request_backup( action_key='upgrade', app_config=app_config, i18n=self.i18n, root_password=root_password, pkg=None, backup_only=True) if not proceed: self.notify_finished({ 'success': False, 'updated': 0, 'types': set(), 'id': None }) self.pkgs = None return self.change_substatus('') timestamp = datetime.now() upgrade_id = 'upgrade_{}{}{}_{}'.format(timestamp.year, timestamp.month, timestamp.day, int(time.time())) self._write_summary_log(upgrade_id, requirements) success = bool(self.manager.upgrade(requirements, root_password, self)) self.change_substatus('') if success: updated = len(requirements.to_upgrade) updated_types.update( (req.pkg.__class__ for req in requirements.to_upgrade)) if should_trim: self._trim_disk(root_password) if bool(app_config['updates']['ask_for_reboot']): msg = '<p>{}</p>{}</p><br/><p>{}</p>'.format( self.i18n['action.update.success.reboot.line1'], self.i18n['action.update.success.reboot.line2'], self.i18n['action.update.success.reboot.line3']) self.request_reboot(msg) self.notify_finished({ 'success': success, 'updated': updated, 'types': updated_types, 'id': upgrade_id }) self.pkgs = None
def download(self, file_url: str, watcher: ProcessWatcher, output_path: str = None, cwd: str = None, root_password: str = None, substatus_prefix: str = None, display_file_size: bool = True, max_threads: int = None, known_size: int = None) -> bool: self.logger.info('Downloading {}'.format(file_url)) handler = ProcessHandler(watcher) file_name = file_url.split('/')[-1] final_cwd = cwd if cwd else '.' success = False ti = time.time() try: if output_path and os.path.exists(output_path): self.logger.info( 'Removing old file found before downloading: {}'.format( output_path)) os.remove(output_path) self.logger.info("Old file {} removed".format(output_path)) client = self.get_available_multithreaded_tool() if client: threads = self._get_appropriate_threads_number( max_threads, known_size) if client == 'aria2': ti = time.time() process = self._get_aria2c_process(file_url, output_path, final_cwd, root_password, threads) downloader = 'aria2' else: ti = time.time() process = self._get_axel_process(file_url, output_path, final_cwd, root_password, threads) downloader = 'axel' else: ti = time.time() process = self._get_wget_process(file_url, output_path, final_cwd, root_password) downloader = 'wget' name = file_url.split('/')[-1] if output_path and not RE_HAS_EXTENSION.match( name) and RE_HAS_EXTENSION.match(output_path): name = output_path.split('/')[-1] if substatus_prefix: msg = substatus_prefix + ' ' else: msg = '' msg += bold('[{}] ').format( downloader) + self.i18n['downloading'] + ' ' + bold(name) if watcher: watcher.change_substatus(msg) if display_file_size: if known_size: watcher.change_substatus( msg + ' ( {} )'.format(get_human_size_str(known_size))) else: Thread(target=self._display_file_size, args=(file_url, msg, watcher)).start() success, _ = handler.handle_simple(process) except: traceback.print_exc() self._rm_bad_file(file_name, output_path, final_cwd, handler, root_password) tf = time.time() self.logger.info(file_name + ' download took {0:.2f} minutes'.format((tf - ti) / 60)) if not success: self.logger.error("Could not download '{}'".format(file_name)) self._rm_bad_file(file_name, output_path, final_cwd, handler, root_password) return success
def run(self): valid_password, root_password = self._request_password() if not valid_password: self.notify_finished({ 'success': False, 'updated': 0, 'types': set(), 'id': None }) self.pkgs = None return to_update = [ pkg for pkg in self.pkgs if pkg.model.update and not pkg.model.is_update_ignored() and pkg.update_checked ] if len(to_update) > 1: self.disable_progress_controll() else: self.enable_progress_controll() success = False updated, updated_types = 0, set() models = [view.model for view in to_update] self.change_substatus(self.i18n['action.update.requirements.status']) requirements = self.manager.get_upgrade_requirements( models, root_password, self) if not requirements: self.pkgs = None self.notify_finished({ 'success': success, 'updated': updated, 'types': updated_types, 'id': None }) return comps, required_size, extra_size = [], 0, 0 if requirements.cannot_upgrade: comps.append( self._gen_cannot_update_form(requirements.cannot_upgrade)) if requirements.to_install: req_form, reqs_size = self._gen_to_install_form( requirements.to_install) required_size += reqs_size[0] extra_size += reqs_size[1] comps.append(req_form) if requirements.to_remove: comps.append(self._gen_to_remove_form(requirements.to_remove)) updates_form, updates_size = self._gen_to_update_form( requirements.to_upgrade) required_size += updates_size[0] extra_size += updates_size[1] comps.append(updates_form) extra_size_text = '{}: {}'.format( self.i18n['action.update.total_size'].capitalize(), get_human_size_str(extra_size)) req_size_text = '{}: {}'.format( self.i18n['action.update.required_size'].capitalize(), get_human_size_str(required_size)) comps.insert( 0, TextComponent('{} | {}'.format(extra_size_text, req_size_text), size=14)) comps.insert(1, TextComponent('')) if not self.request_confirmation( title=self.i18n['action.update.summary'].capitalize(), body='', components=comps, confirmation_label=self.i18n['proceed'].capitalize(), deny_label=self.i18n['cancel'].capitalize()): self.notify_finished({ 'success': success, 'updated': updated, 'types': updated_types, 'id': None }) self.pkgs = None return self.change_substatus('') app_config = read_config() # trim dialog if app_config['disk']['trim']['after_upgrade'] is not False: should_trim = app_config['disk']['trim'][ 'after_upgrade'] or self._ask_for_trim() else: should_trim = False # backup process ( if enabled, supported and accepted ) if bool(app_config['backup'] ['enabled']) and app_config['backup']['upgrade'] in ( True, None) and timeshift.is_available(): any_requires_bkp = False for dep in requirements.to_upgrade: if dep.pkg.supports_backup(): any_requires_bkp = True break if any_requires_bkp: if not self.request_backup(app_config, 'upgrade', self.i18n, root_password): self.notify_finished({ 'success': success, 'updated': updated, 'types': updated_types, 'id': None }) self.pkgs = None return self.change_substatus('') timestamp = datetime.now() upgrade_id = 'upgrade_{}{}{}_{}'.format(timestamp.year, timestamp.month, timestamp.day, int(time.time())) self._write_summary_log(upgrade_id, requirements) success = bool(self.manager.upgrade(requirements, root_password, self)) self.change_substatus('') if success: updated = len(requirements.to_upgrade) updated_types.update( (req.pkg.__class__ for req in requirements.to_upgrade)) if should_trim: self._trim_disk(root_password) if bool(app_config['updates']['ask_for_reboot']): msg = '<p>{}</p>{}</p><br/><p>{}</p>'.format( self.i18n['action.update.success.reboot.line1'], self.i18n['action.update.success.reboot.line2'], self.i18n['action.update.success.reboot.line3']) self.request_reboot(msg) self.notify_finished({ 'success': success, 'updated': updated, 'types': updated_types, 'id': upgrade_id }) self.pkgs = None