def testReplacedConflicts(self): self.import_feed('http://localhost:8000/Hello', 'Hello') s = solver.DefaultSolver(self.config) replaced_path = model.canonical_iface_uri( os.path.join(mydir, 'Replaced.xml')) replaced_conflicts_path = model.canonical_iface_uri( os.path.join(mydir, 'ReplacedConflicts.xml')) r = Requirements(replaced_conflicts_path) s.solve_for(r) assert s.ready, s.get_failure_reason() assert s.selections self.assertEqual("b", s.selections.selections[replaced_conflicts_path].id) self.assertEqual( "2", s.selections.selections[replaced_conflicts_path].version) self.assertEqual( "sha1=3ce644dc725f1d21cfcf02562c76f375944b266a", s.selections.selections["http://localhost:8000/Hello"].id) self.assertEqual(2, len(s.selections.selections)) s.extra_restrictions[self.config.iface_cache.get_interface( r.interface_uri)] = [ model.VersionRangeRestriction(model.parse_version('2'), None) ] s.solve_for(r) assert s.ready, s.get_failure_reason() assert s.selections self.assertEqual( "1", s.selections.selections[replaced_conflicts_path].version) self.assertEqual("0", s.selections.selections[replaced_path].version) self.assertEqual(2, len(s.selections.selections))
def __init__(self, config, requirements): """ @param config: The configuration settings to use @type config: L{config.Config} @param requirements: Details about the program we want to run @type requirements: L{requirements.Requirements} @since: 0.53 """ self.watchers = [] assert config self.config = config assert requirements self.requirements = requirements self.target_arch = arch.get_architecture(requirements.os, requirements.cpu) from zeroinstall.injector.solver import DefaultSolver self.solver = DefaultSolver(self.config) debug(_("Supported systems: '%s'"), arch.os_ranks) debug(_("Supported processors: '%s'"), arch.machine_ranks) if requirements.before or requirements.not_before: self.solver.extra_restrictions[config.iface_cache.get_interface(requirements.interface_uri)] = [ model.VersionRangeRestriction(model.parse_version(requirements.before), model.parse_version(requirements.not_before))]
def __init__(self, guid, data): self._importance = data.get('importance', model.Dependency.Essential) self._metadata = {} self.qdom = None self.interface = guid self.restrictions = [] self.bindings = [] for not_before, before in data.get('restrictions') or []: restriction = model.VersionRangeRestriction( not_before=parse_version(not_before), before=parse_version(before)) self.restrictions.append(restriction)
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 run_gui(args): parser = OptionParser(usage=_("usage: %prog [options] interface")) parser.add_option("", "--before", help=_("choose a version before this"), metavar='VERSION') parser.add_option("", "--cpu", help=_("target CPU type"), metavar='CPU') parser.add_option("-c", "--cache", help=_("show the cache"), action='store_true') parser.add_option("-d", "--download-only", help=_("fetch but don't run"), action='store_true') parser.add_option("", "--message", help=_("message to display when interacting with user")) parser.add_option("", "--not-before", help=_("minimum version to choose"), metavar='VERSION') parser.add_option("", "--os", help=_("target operation system type"), metavar='OS') parser.add_option("-r", "--refresh", help=_("check for updates of all interfaces"), action='store_true') parser.add_option("-s", "--source", help=_("select source code"), action='store_true') parser.add_option("", "--systray", help=_("download in the background"), action='store_true') parser.add_option("-v", "--verbose", help=_("more verbose output"), action='count') parser.add_option("-V", "--version", help=_("display version information"), action='store_true') parser.add_option("", "--with-store", help=_("add an implementation cache"), action='append', metavar='DIR') parser.disable_interspersed_args() (options, args) = parser.parse_args(args) if options.verbose: import logging logger = logging.getLogger() if options.verbose == 1: logger.setLevel(logging.INFO) else: logger.setLevel(logging.DEBUG) if options.cache: # Must fork before importing gtk, or ATK dies if os.fork(): # We exit, so our parent can call waitpid and unblock. sys.exit(0) # The grandchild continues... if options.with_store: from zeroinstall import zerostore for x in options.with_store: iface_cache.stores.stores.append(zerostore.Store(os.path.abspath(x))) import gui if options.version: print "0launch-gui (zero-install) " + gui.version print "Copyright (C) 2009 Thomas Leonard" print _("This program comes with ABSOLUTELY NO WARRANTY," "\nto the extent permitted by law." "\nYou may redistribute copies of this program" "\nunder the terms of the GNU Lesser General Public License." "\nFor more information about these matters, see the file named COPYING.") sys.exit(0) import gtk if gtk.gdk.get_display() is None: print >>sys.stderr, "Failed to connect to display. Aborting." sys.exit(1) if not hasattr(gtk, 'combo_box_new_text'): import combo_compat if options.cache: import cache cache_explorer = cache.CacheExplorer() cache_explorer.show() cache_explorer.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH)) gtk.gdk.flush() cache_explorer.populate_model() cache_explorer.window.set_cursor(None) gtk.main() sys.exit(0) handler = gui.GUIHandler() if len(args) < 1: import preferences # Once we separate configuration from Policy, this hack can go away class DummyPolicy(Policy): def recalculate(fetch_stale_interfaces = True): pass def solve_with_downloads(force = False): pass box = preferences.show_preferences(DummyPolicy('http://localhost/dummy', handler)) box.connect('destroy', gtk.main_quit) gtk.main() sys.exit(0) interface_uri = args[0] if len(args) > 1: parser.print_help() sys.exit(1) import mainwindow, dialog restrictions = [] if options.before or options.not_before: restrictions.append(model.VersionRangeRestriction(model.parse_version(options.before), model.parse_version(options.not_before))) widgets = dialog.Template('main') policy = Policy(interface_uri, handler, src = bool(options.source)) policy.target_arch = arch.get_architecture(options.os, options.cpu) root_iface = iface_cache.get_interface(interface_uri) policy.solver.extra_restrictions[root_iface] = restrictions policy.solver.record_details = True window = mainwindow.MainWindow(policy, widgets, download_only = bool(options.download_only)) handler.mainwindow = window if options.message: window.set_message(options.message) root = iface_cache.get_interface(policy.root) window.browser.set_root(root) window.window.connect('destroy', lambda w: handler.abort_all_downloads()) if options.systray: window.use_systray_icon() @tasks.async def main(): force_refresh = bool(options.refresh) while True: window.refresh_button.set_sensitive(False) window.browser.set_update_icons(force_refresh) solved = policy.solve_with_downloads(force = force_refresh) if not window.systray_icon: window.show() yield solved try: window.refresh_button.set_sensitive(True) tasks.check(solved) except Exception, ex: window.report_exception(ex) if window.systray_icon and window.systray_icon.get_visible() and \ window.systray_icon.is_embedded(): if policy.ready: window.systray_icon.set_tooltip(_('Downloading updates for %s') % root_iface.get_name()) window.run_button.set_active(True) else: # Should already be reporting an error, but # blink it again just in case window.systray_icon.set_blinking(True) yield dialog.ButtonClickedBlocker(window.refresh_button) force_refresh = True
def _normal_mode(options, args): from zeroinstall.injector import handler if len(args) < 1: if options.gui: from zeroinstall import helpers return helpers.get_selections_gui(None, []) else: raise UsageError() iface_uri = model.canonical_iface_uri(args[0]) root_iface = iface_cache.get_interface(iface_uri) if os.isatty(1): h = handler.ConsoleHandler() else: h = handler.Handler() h.dry_run = bool(options.dry_run) policy = autopolicy.AutoPolicy(iface_uri, handler = h, download_only = bool(options.download_only), src = options.source) if options.before or options.not_before: policy.solver.extra_restrictions[root_iface] = [model.VersionRangeRestriction(model.parse_version(options.before), model.parse_version(options.not_before))] if options.os or options.cpu: from zeroinstall.injector import arch policy.target_arch = arch.get_architecture(options.os, options.cpu) if options.offline: policy.network_use = model.network_offline if options.get_selections: if len(args) > 1: raise SafeException(_("Can't use arguments with --get-selections")) if options.main: raise SafeException(_("Can't use --main with --get-selections")) # Note that need_download() triggers a solve if options.refresh or options.gui: # We could run immediately, but the user asked us not to can_run_immediately = False else: can_run_immediately = (not policy.need_download()) and policy.ready stale_feeds = [feed for feed in policy.solver.feeds_used if policy.is_stale(iface_cache.get_feed(feed))] if options.download_only and stale_feeds: can_run_immediately = False if can_run_immediately: if stale_feeds: if policy.network_use == model.network_offline: logging.debug(_("No doing background update because we are in off-line mode.")) else: # There are feeds we should update, but we can run without them. # Do the update in the background while the program is running. import background background.spawn_background_update(policy, options.verbose > 0) if options.get_selections: _get_selections(policy) else: if not options.download_only: from zeroinstall.injector import run run.execute(policy, args[1:], dry_run = options.dry_run, main = options.main, wrapper = options.wrapper) else: logging.info(_("Downloads done (download-only mode)")) assert options.dry_run or options.download_only return # If the user didn't say whether to use the GUI, choose for them. if options.gui is None and os.environ.get('DISPLAY', None): options.gui = True # If we need to download anything, we might as well # refresh all the interfaces first. Also, this triggers # the 'checking for updates' box, which is non-interactive # when there are no changes to the selection. options.refresh = True logging.info(_("Switching to GUI mode... (use --console to disable)")) prog_args = args[1:] try: from zeroinstall.injector import run if options.gui: gui_args = [] if options.download_only: # Just changes the button's label gui_args.append('--download-only') if options.refresh: gui_args.append('--refresh') if options.systray: gui_args.append('--systray') if options.not_before: gui_args.insert(0, options.not_before) gui_args.insert(0, '--not-before') if options.before: gui_args.insert(0, options.before) gui_args.insert(0, '--before') if options.source: gui_args.insert(0, '--source') if options.message: gui_args.insert(0, options.message) gui_args.insert(0, '--message') if options.verbose: gui_args.insert(0, '--verbose') if options.verbose > 1: gui_args.insert(0, '--verbose') if options.cpu: gui_args.insert(0, options.cpu) gui_args.insert(0, '--cpu') if options.os: gui_args.insert(0, options.os) gui_args.insert(0, '--os') if options.with_store: for x in options.with_store: gui_args += ['--with-store', x] sels = _fork_gui(iface_uri, gui_args, prog_args, options) if not sels: sys.exit(1) # Aborted else: #program_log('download_and_execute ' + iface_uri) downloaded = policy.solve_and_download_impls(refresh = bool(options.refresh)) if downloaded: policy.handler.wait_for_blocker(downloaded) sels = selections.Selections(policy) if options.get_selections: doc = sels.toDOM() doc.writexml(sys.stdout) sys.stdout.write('\n') elif not options.download_only: run.execute_selections(sels, prog_args, options.dry_run, options.main, options.wrapper) except NeedDownload, ex: # This only happens for dry runs print ex