def get_failure_reason(self): """Return an exception explaining why the solve failed.""" assert not self.ready if self._failure_reason: return model.SafeException(self._failure_reason) return model.SafeException( _("Can't find all required implementations:") + '\n' + '\n'.join([ "- %s -> %s" % (iface, self.selections[iface]) for iface in self.selections ]))
def testInvalidXMLSig(self): for error, sig in invalid_xmls_sigs: try: self.check_bad(bad_xml_main + b'\n' + sig) except model.SafeException as ex: if error not in str(ex): raise model.SafeException(str(ex) + '\nSig:\n' + sig)
def get_command(self, name): """@type name: str @rtype: L{Command}""" if name not in self.commands: raise model.SafeException( "Command '{name}' not present in selections for {iface}". format(name=name, iface=self.interface)) return self.commands[name]
def get_path(self, stores, missing_ok = False): """Return the root directory of this implementation. For local implementations, this is L{local_path}. For cached implementations, this is the directory in the cache. @param stores: stores to search @type stores: L{zerostore.Stores} @param missing_ok: return None for uncached implementations @type missing_ok: bool @return: the path of the directory @rtype: str | None @since: 1.8""" if self.local_path is not None: return self.local_path if not self.digests: # (for now, we assume this is always an error, even for missing_ok) raise model.SafeException("No digests for {feed} {version}".format(feed = self.feed, version = self.version)) if missing_ok: return stores.lookup_maybe(self.digests) else: return stores.lookup_any(self.digests)
def run_test_combinations(config, spec): r = requirements.Requirements(spec.test_iface) r.command = spec.command d = driver.Driver(config=config, requirements=r) solver = d.solver # Explore all combinations... tested_iface = config.iface_cache.get_interface(spec.test_iface) results = Results(spec) for combo in spec.get_combos(spec.test_ifaces): key = set() restrictions = {} selections = {} for (uri, version) in combo.iteritems(): iface = config.iface_cache.get_interface(uri) selections[iface] = version if version.startswith('%'): if version == '%nonlocal': restrictions[iface] = [NonlocalRestriction()] else: raise model.SafeException( "Unknown special '{special}'".format(special=version)) elif ',' in version: not_before, before = [ model.parse_version(v) if v != "" else None for v in version.split(',') ] if (not_before and before) and not_before >= before: raise model.SafeException( "Low version >= high version in %s!" % version) restrictions[iface] = [ model.VersionRangeRestriction(before, not_before) ] else: restrictions[iface] = [ model.VersionExpressionRestriction(version) ] key.add((uri, version)) solver.extra_restrictions = restrictions solve = d.solve_with_downloads() tasks.wait_for_blocker(solve) if not solver.ready: logging.info("Can't select combination %s: %s", combo, solver.get_failure_reason()) result = 'skipped' for uri, impl in solver.selections.iteritems(): if impl is None: selections[uri] = selections.get(uri, None) or '?' else: selections[uri] = impl.get_version() if not selections: selections = solver.get_failure_reason() else: selections = {} for iface, impl in solver.selections.iteritems(): if impl: version = impl.get_version() else: impl = None selections[iface] = version download = d.download_uncached_implementations() if download: config.handler.wait_for_blocker(download) print format_combo(selections) result = run_tests(config, tested_iface, solver.selections, spec) results.by_status[result].append(selections) results.by_combo[frozenset(key)] = (result, selections) return results
def install(handler): raise model.SafeException( _("This program depends on '%s', which is a package that is available through your distribution. " "Please install it manually using your distribution's tools and try again. Or, install 'packagekit' and I can " "use that to install it.") % package)
def _init_from_qdom(self, root): """Parse and load a selections document. @param root: a saved set of selections. @type root: L{Element}""" self.interface = root.getAttribute('interface') self.command = root.getAttribute('command') if self.interface is None: raise model.SafeException( _("Not a selections document (no 'interface' attribute on root)" )) old_commands = [] for selection in root.childNodes: if selection.uri != XMLNS_IFACE: continue if selection.name != 'selection': if selection.name == 'command': old_commands.append(Command(selection, None)) continue requires = [] bindings = [] digests = [] commands = {} for elem in selection.childNodes: if elem.uri != XMLNS_IFACE: continue if elem.name in binding_names: bindings.append(process_binding(elem)) elif elem.name == 'requires': dep = process_depends(elem, None) requires.append(dep) elif elem.name == 'manifest-digest': for aname, avalue in elem.attrs.items(): digests.append( zerostore.format_algorithm_digest_pair( aname, avalue)) elif elem.name == 'command': name = elem.getAttribute('name') assert name, "Missing name attribute on <command>" commands[name] = Command(elem, None) # For backwards compatibility, allow getting the digest from the ID sel_id = selection.attrs['id'] local_path = selection.attrs.get("local-path", None) if (not local_path) and '=' in sel_id: alg = sel_id.split('=', 1)[0] if alg in ('sha1', 'sha1new', 'sha256'): if sel_id not in digests: digests.append(sel_id) iface_uri = selection.attrs['interface'] s = XMLSelection(requires, bindings, selection.attrs, digests, commands) self.selections[iface_uri] = s if self.command is None: # Old style selections document if old_commands: # 0launch 0.52 to 1.1 self.command = 'run' iface = self.interface for command in old_commands: command.qdom.attrs['name'] = 'run' self.selections[iface].commands['run'] = command runner = command.get_runner() if runner: iface = runner.interface else: iface = None else: # 0launch < 0.51 root_sel = self.selections[self.interface] main = root_sel.attrs.get('main', None) if main is not None: root_sel.commands['run'] = Command( Element(XMLNS_IFACE, 'command', { 'path': main, 'name': 'run' }), None) self.command = 'run' elif self.command == '': # New style, but no command requested self.command = None assert not old_commands, "<command> list in new-style selections document!"
def get_failure_reason(self): """Return an exception explaining why the solve failed.""" assert not self.ready sels = self.selections.selections iface_cache = self.config.iface_cache problem = self._problem impls_for_iface = self._impls_for_iface assert impls_for_iface def show(iface_uri): # Find all restrictions that are in play and affect this interface sel = sels[iface_uri] if sel: msg = '{version} ({impl})'.format(version=sel.version, impl=sel.id) else: msg = "(problem)" iface = iface_cache.get_interface(iface_uri) impls = impls_for_iface[iface_cache.get_interface(iface_uri)] impls = [i for i in impls if not isinstance(i, _DummyImpl)] def apply_restrictions(impls, restrictions): for r in restrictions: impls = [i for i in impls if r.meets_restriction(i)] return impls # orig_impls is all the implementations passed to the SAT solver (these are the # ones with a compatible OS, CPU, etc). They are sorted most desirable first. orig_impls = impls def get_machine_group(impl): machine = impl.machine if machine and machine != 'src': return arch.machine_groups.get(machine, 0) return None example_machine_impl = None # An example chosen impl with a machine type our_feed = iface_cache.get_feed(iface_uri) our_replacement = our_feed.get_replaced_by() if our_feed else None # For each selected implementation... for other_uri, other_sel in sels.items(): # Check for interface-level conflicts other_iface = iface_cache.get_feed(other_uri) if other_iface and other_iface.get_replaced_by() == iface_uri: msg += "\n " + _( "Replaces (and therefore conflicts with) {old}" ).format(old=other_uri) if other_sel: impls = [] if our_replacement == other_uri: msg += "\n " + _( "Replaced by (and therefore conflicts with) {old}" ).format(old=other_uri) if other_sel: impls = [] # Otherwise, if we didn't select an implementation then that can't be causing a problem if not other_sel: continue if example_machine_impl is None: required_machine_group = get_machine_group(other_sel.impl) if required_machine_group is not None: example_machine_impl = other_sel.impl for dep in other_sel.impl.requires: if not isinstance(dep, model.InterfaceRestriction): continue # If it depends on us and has restrictions... if dep.interface == iface_uri and dep.restrictions: # Report the restriction msg += "\n " + _( "{iface} {version} requires {reqs}").format( iface=other_uri, version=other_sel.version, reqs=', '.join( str(r) for r in dep.restrictions)) # Remove implementations incompatible with the other selections impls = apply_restrictions(impls, dep.restrictions) # Check for user-supplied restrictions user = self.extra_restrictions.get(iface, []) if user: msg += "\n " + _("User requested {reqs}").format( reqs=', '.join(str(r) for r in user)) impls = apply_restrictions(impls, user) if sel is None: # Report on available implementations all_impls = self.details.get(iface, {}) if not orig_impls: if not all_impls: msg += "\n " + _("No known implementations at all") else: # No implementations were passed to the solver. msg += "\n " + _("No usable implementations:") for i, reason in all_impls[:5]: msg += "\n {impl}: {reason}".format( impl=i, reason=reason) if len(all_impls) > 5: msg += "\n ..." elif not impls: msg += "\n " + _( "No usable implementations satisfy the restrictions") else: # Might still be unusable e.g. if missing a required command. Show reasons, if any. shown = 0 candidate_impls = set(impls) for i, reason in all_impls: if reason is _ForceImpl.reason: # We're doing a justify_decision, and this wasn't the one the user specified continue if i not in candidate_impls: # Skip, as hopefully obvious from above restrictions why not chosen continue if reason is None and example_machine_impl: # Could be an architecture problem this_machine_group = get_machine_group(i) if this_machine_group is not None and this_machine_group != required_machine_group: reason = _( "Can't use {this_arch} with selection of {other_name} ({other_arch})" ).format( this_arch=i.machine, other_name=example_machine_impl.feed. get_name(), other_arch=example_machine_impl.machine) if reason is None: var = self._iface_to_vars[iface].get(i, None) if var is None: reason = "BUG: no var for impl!" else: varinfo = problem.get_varinfo_for_lit(var) reason = "Hard to explain. Internal reason: {reason} => {assignment}".format( reason=varinfo.reason, assignment=varinfo) if reason is not _ForceImpl.reason: if shown >= 5: msg += "\n ..." break if shown == 0: msg += "\n " + _("Rejected candidates:") msg += "\n {impl}: {reason}".format( impl=i, reason=reason) shown += 1 return msg msg = _("Can't find all required implementations:") + '\n' + \ '\n'.join(["- %s -> %s" % (iface, show(iface)) for iface in sorted(sels)]) if self.config.network_use == model.network_offline: msg += "\nNote: 0install is in off-line mode" return model.SafeException(msg)
def get_download(self, url, force=False, hint=None, factory=None): if self.allow_downloads: return handler.Handler.get_download(self, url, force, hint, factory) raise model.SafeException("DummyHandler: " + url)