def __init__(self, root=None, handler=None, src=None, command=-1, config=None, requirements=None): """ @param requirements: Details about the program we want to run @type requirements: L{requirements.Requirements} @param config: The configuration settings to use, or None to load from disk. @type config: L{config.Config} Note: all other arguments are deprecated (since 0launch 0.52) """ if requirements is None: from zeroinstall.injector.requirements import Requirements requirements = Requirements(root) requirements.source = bool( src) # Root impl must be a "src" machine type if command == -1: if src: command = 'compile' else: command = 'run' requirements.command = command else: assert root == src == None assert command == -1 if config is None: config = load_config(handler) else: assert handler is None, "can't pass a handler and a config" self.driver = driver.Driver(config=config, requirements=requirements)
def __init__(self, root = None, handler = None, src = None, command = -1, config = None, requirements = None): """ @param requirements: Details about the program we want to run @type requirements: L{requirements.Requirements} @param config: The configuration settings to use, or None to load from disk. @type config: L{config.Config} Note: all other arguments are deprecated (since 0launch 0.52) """ if requirements is None: from zeroinstall.injector.requirements import Requirements requirements = Requirements(root) requirements.source = bool(src) # Root impl must be a "src" machine type if command == -1: if src: command = 'compile' else: command = 'run' requirements.command = command else: assert root == src == None assert command == -1 if config is None: config = load_config(handler) else: assert handler is None, "can't pass a handler and a config" self.driver = driver.Driver(config = config, requirements = requirements)
def testDetails(self): iface_cache = self.config.iface_cache s = solver.DefaultSolver(self.config) foo_binary_uri = 'http://foo/Binary.xml' foo = iface_cache.get_interface(foo_binary_uri) self.import_feed(foo_binary_uri, 'Binary.xml') foo_src = iface_cache.get_interface('http://foo/Source.xml') self.import_feed(foo_src.uri, 'Source.xml') compiler = iface_cache.get_interface('http://foo/Compiler.xml') self.import_feed(compiler.uri, 'Compiler.xml') r = Requirements('http://foo/Binary.xml') r.source = True r.command = 'compile' s.record_details = True s.solve_for(r) assert s.ready, s.get_failure_reason() foo_bin_impls = iface_cache.get_feed(foo_binary_uri).implementations foo_src_impls = iface_cache.get_feed(foo_src.uri).implementations foo_impls = iface_cache.get_feed(foo.uri).implementations compiler_impls = iface_cache.get_feed(compiler.uri).implementations assert len(s.details) == 2 self.assertEqual([ (foo_src_impls['impossible'], None), (foo_src_impls['sha1=234'], None), (foo_impls['sha1=123'], 'Not source code'), (foo_src_impls['old'], None), ], sorted(s.details[foo])) self.assertEqual([ (compiler_impls['sha1=999'], None), (compiler_impls['sha1=345'], None), (compiler_impls['sha1=678'], None), ], s.details[compiler]) def justify(uri, impl, expected): iface = iface_cache.get_interface(uri) e = s.justify_decision(r, iface, impl) self.assertEqual(expected, e) justify(foo_binary_uri, foo_bin_impls["sha1=123"], 'Binary 1.0 cannot be used (regardless of other components): Not source code') justify(foo_binary_uri, foo_src_impls["sha1=234"], 'Binary 1.0 was selected as the preferred version.') justify(foo_binary_uri, foo_src_impls["old"], 'Binary 0.1 is ranked lower than 1.0: newer versions are preferred') justify(foo_binary_uri, foo_src_impls["impossible"], "There is no possible selection using Binary 3.\n" "Can't find all required implementations:\n" "- http://foo/Binary.xml -> 3 (impossible)\n" " User requested implementation 3 (impossible)\n" "- http://foo/Compiler.xml -> (problem)\n" " http://foo/Binary.xml 3 requires version < 1.0, 1.0 <= version\n" " No usable implementations satisfy the restrictions") justify(compiler.uri, compiler_impls["sha1=999"], '''Compiler 5 is selectable, but using it would produce a less optimal solution overall.\n\nThe changes would be:\n\nhttp://foo/Binary.xml: 1.0 to 0.1''')
def __init__(self, root = None, handler = None, src = None, command = -1, config = None, requirements = None): """ @param requirements: Details about the program we want to run @type requirements: L{requirements.Requirements} @param config: The configuration settings to use, or None to load from disk. @type config: L{ConfigParser.ConfigParser} Note: all other arguments are deprecated (since 0launch 0.52) """ self.watchers = [] if requirements is None: from zeroinstall.injector.requirements import Requirements requirements = Requirements(root) requirements.source = bool(src) # Root impl must be a "src" machine type if command == -1: if src: command = 'compile' else: command = 'run' requirements.command = command self.target_arch = arch.get_host_architecture() else: assert root == src == None assert command == -1 self.target_arch = arch.get_architecture(requirements.os, requirements.cpu) self.requirements = requirements self.stale_feeds = set() if config is None: self.config = load_config(handler or Handler()) else: assert handler is None, "can't pass a handler and a config" self.config = config from zeroinstall.injector.solver import DefaultSolver self.solver = DefaultSolver(self.config) # If we need to download something but can't because we are offline, # warn the user. But only the first time. self._warned_offline = False 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 testArchFor(self): s = solver.DefaultSolver(self.config) r = Requirements('http://foo/Binary.xml') r.cpu = 'i386' bin_arch = s.get_arch_for(r) self.assertEqual({'i386': 0, None: 1}, bin_arch.machine_ranks) r.source = True src_arch = s.get_arch_for(r) self.assertEqual({'src': 1}, src_arch.machine_ranks) child = self.config.iface_cache.get_interface('http://foo/Dep.xml') arch = s.get_arch_for(r, child) self.assertEqual(arch.machine_ranks, bin_arch.machine_ranks) child = self.config.iface_cache.get_interface(r.interface_uri) arch = s.get_arch_for(r, child) self.assertEqual(arch.machine_ranks, src_arch.machine_ranks)
def testDetails(self): iface_cache = self.config.iface_cache s = solver.DefaultSolver(self.config) foo_binary_uri = 'http://foo/Binary.xml' foo = iface_cache.get_interface(foo_binary_uri) self.import_feed(foo_binary_uri, 'Binary.xml') foo_src = iface_cache.get_interface('http://foo/Source.xml') self.import_feed(foo_src.uri, 'Source.xml') compiler = iface_cache.get_interface('http://foo/Compiler.xml') self.import_feed(compiler.uri, 'Compiler.xml') r = Requirements('http://foo/Binary.xml') r.source = True r.command = 'compile' s.record_details = True s.solve_for(r) assert s.ready, s.get_failure_reason() foo_bin_impls = iface_cache.get_feed(foo_binary_uri).implementations foo_src_impls = iface_cache.get_feed(foo_src.uri).implementations foo_impls = iface_cache.get_feed(foo.uri).implementations compiler_impls = iface_cache.get_feed(compiler.uri).implementations assert len(s.details) == 2 self.assertEqual([ (foo_src_impls['impossible'], None), (foo_src_impls['sha1=234'], None), (foo_impls['sha1=123'], 'Not source code'), (foo_src_impls['old'], None), ], sorted(s.details[foo])) self.assertEqual([ (compiler_impls['sha1=999'], None), (compiler_impls['sha1=345'], None), (compiler_impls['sha1=678'], None), ], s.details[compiler]) def justify(uri, impl, expected): iface = iface_cache.get_interface(uri) e = s.justify_decision(r, iface, impl) self.assertEqual(expected, e) self.maxDiff = 1000 justify( foo_binary_uri, foo_bin_impls["sha1=123"], 'Binary 1.0 cannot be used (regardless of other components): Not source code' ) justify(foo_binary_uri, foo_src_impls["sha1=234"], 'Binary 1.0 was selected as the preferred version.') justify( foo_binary_uri, foo_src_impls["old"], 'Binary 0.1 is ranked lower than 1.0: newer versions are preferred' ) justify( foo_binary_uri, foo_src_impls["impossible"], "There is no possible selection using Binary 3.\n" "Can't find all required implementations:\n" "- http://foo/Binary.xml -> 3 (impossible)\n" " User requested implementation 3 (impossible)\n" "- http://foo/Compiler.xml -> (problem)\n" " http://foo/Binary.xml 3 requires version < 1.0, 1.0 <= version\n" " No usable implementations satisfy the restrictions:\n" " sha1=999 (5): incompatible with restrictions\n" " sha1=345 (1.0): incompatible with restrictions\n" " sha1=678 (0.1): incompatible with restrictions") justify( compiler.uri, compiler_impls["sha1=999"], '''Compiler 5 is selectable, but using it would produce a less optimal solution overall.\n\nThe changes would be:\n\nhttp://foo/Binary.xml: 1.0 to 0.1''' )
def testSelections(self): requirements = Requirements('http://foo/Source.xml') requirements.source = True requirements.command = 'compile' driver = Driver(requirements = requirements, config = self.config) source = self.config.iface_cache.get_interface('http://foo/Source.xml') compiler = self.config.iface_cache.get_interface('http://foo/Compiler.xml') self.import_feed(source.uri, 'Source.xml') self.import_feed(compiler.uri, 'Compiler.xml') self.config.network_use = model.network_full #import logging #logging.getLogger().setLevel(logging.DEBUG) assert driver.need_download() def assertSel(s): self.assertEqual('http://foo/Source.xml', s.interface) self.assertEqual(2, len(s.selections)) sels = [(sel.interface, sel) for sel in s.selections.values()] sels.sort() sels = [sel for uri,sel in sels] self.assertEqual('http://foo/Compiler.xml', sels[0].interface) self.assertEqual('http://foo/Source.xml', sels[1].interface) self.assertEqual("sha1=345", sels[0].id) self.assertEqual("1.0", sels[0].version) self.assertEqual('sha1=234', sels[1].id) self.assertEqual("1.0", sels[1].version) self.assertEqual("bar", sels[1].attrs['http://namespace foo']) self.assertEqual("1.0", sels[1].attrs['version']) assert 'version-modifier' not in sels[1].attrs self.assertEqual(0, len(sels[0].bindings)) self.assertEqual(0, len(sels[0].dependencies)) self.assertEqual(3, len(sels[1].bindings)) self.assertEqual('.', sels[1].bindings[0].insert) self.assertEqual('/', sels[1].bindings[1].mount_point) self.assertEqual('source', sels[1].bindings[2].qdom.attrs['foo']) self.assertEqual(1, len(sels[1].dependencies)) dep = sels[1].dependencies[0] self.assertEqual('http://foo/Compiler.xml', dep.interface) self.assertEqual(4, len(dep.bindings)) self.assertEqual('bin', dep.bindings[0].insert) self.assertEqual('PATH', dep.bindings[0].name) self.assertEqual('prepend', dep.bindings[0].mode) assert dep.bindings[0].separator in ';:' self.assertEqual('bin', dep.bindings[1].value) self.assertEqual('NO_PATH', dep.bindings[1].name) self.assertEqual(',', dep.bindings[1].separator) self.assertEqual('bin', dep.bindings[2].insert) self.assertEqual('BINDIR', dep.bindings[2].name) self.assertEqual('replace', dep.bindings[2].mode) foo_binding = dep.bindings[3] self.assertEqual('compiler', foo_binding.qdom.attrs['foo']) self.assertEqual('child', foo_binding.qdom.childNodes[0].name) self.assertEqual('run', foo_binding.command) self.assertEqual(["sha1=345", 'sha256new_345'], sorted(sels[0].digests)) assert driver.solver.ready, driver.solver.get_failure_reason() s1 = driver.solver.selections s1.selections['http://foo/Source.xml'].attrs['http://namespace foo'] = 'bar' assertSel(s1) xml = s1.toDOM().toxml("utf-8") root = qdom.parse(BytesIO(xml)) self.assertEqual(namespaces.XMLNS_IFACE, root.uri) s2 = selections.Selections(root) assertSel(s2)
def testBackgroundUnsolvable(self): my_dbus.system_services = {"org.freedesktop.NetworkManager": {"/org/freedesktop/NetworkManager": NetworkManager()}} trust.trust_db.trust_key('DE937DD411906ACF7C263B396FCF121BE2390E0B', 'example.com:8000') global ran_gui # Select a version of Hello run_server('Hello.xml', '6FCF121BE2390E0B.gpg', 'HelloWorld.tgz') r = Requirements('http://example.com:8000/Hello.xml') driver = Driver(requirements = r, config = self.config) tasks.wait_for_blocker(driver.solve_with_downloads()) assert driver.solver.ready kill_server_process() # Save it as an app app = self.config.app_mgr.create_app('test-app', r) # Replace the selection with a bogus and unusable <package-implementation> sels = driver.solver.selections sel, = sels.selections.values() sel.attrs['id'] = "package:dummy:badpackage" sel.attrs['package'] = "badpackage" sel.get_command('run').qdom.attrs['path'] = '/i/dont/exist' app.set_selections(driver.solver.selections) # Not time for a background update yet, but the missing binary should trigger # an update anyway. self.config.freshness = 0 # Check we try to launch the GUI... os.environ['DISPLAY'] = 'dummy' try: app.get_selections(may_update = True) assert 0 except model.SafeException as ex: assert 'Aborted by user' in str(ex) assert ran_gui ran_gui = False # Check we can also work without the GUI... del os.environ['DISPLAY'] run_server('Hello.xml', 'HelloWorld.tgz') sels = app.get_selections(may_update = True) kill_server_process() dl = app.download_selections(sels) assert dl == None assert not ran_gui # Now trigger a background update which discovers that no solution is possible timestamp = os.path.join(app.path, 'last-checked') last_check_attempt = os.path.join(app.path, 'last-check-attempt') selections_path = os.path.join(app.path, 'selections.xml') def reset_timestamps(): global ran_gui ran_gui = False os.utime(timestamp, (1, 1)) # 1970 os.utime(selections_path, (1, 1)) if os.path.exists(last_check_attempt): os.unlink(last_check_attempt) reset_timestamps() r.source = True app.set_requirements(r) run_server('Hello.xml') with trapped_exit(1): sels = app.get_selections(may_update = True) kill_server_process()
def testSelections(self): requirements = Requirements('http://foo/Source.xml') requirements.source = True requirements.command = 'compile' driver = Driver(requirements=requirements, config=self.config) source = self.config.iface_cache.get_interface('http://foo/Source.xml') compiler = self.config.iface_cache.get_interface( 'http://foo/Compiler.xml') self.import_feed(source.uri, 'Source.xml') self.import_feed(compiler.uri, 'Compiler.xml') self.config.network_use = model.network_full #import logging #logging.getLogger().setLevel(logging.DEBUG) assert driver.need_download() def assertSel(s): self.assertEqual('http://foo/Source.xml', s.interface) self.assertEqual(2, len(s.selections)) sels = [(sel.interface, sel) for sel in s.selections.values()] sels.sort() sels = [sel for uri, sel in sels] self.assertEqual('http://foo/Compiler.xml', sels[0].interface) self.assertEqual('http://foo/Source.xml', sels[1].interface) self.assertEqual("sha1=345", sels[0].id) self.assertEqual("1.0", sels[0].version) self.assertEqual('sha1=234', sels[1].id) self.assertEqual("1.0", sels[1].version) self.assertEqual("bar", sels[1].attrs['http://namespace foo']) self.assertEqual("1.0", sels[1].attrs['version']) assert 'version-modifier' not in sels[1].attrs self.assertEqual(0, len(sels[0].bindings)) self.assertEqual(0, len(sels[0].dependencies)) self.assertEqual(3, len(sels[1].bindings)) self.assertEqual('.', sels[1].bindings[0].insert) self.assertEqual('/', sels[1].bindings[1].mount_point) self.assertEqual('source', sels[1].bindings[2].qdom.attrs['foo']) self.assertEqual(1, len(sels[1].dependencies)) dep = sels[1].dependencies[0] self.assertEqual('http://foo/Compiler.xml', dep.interface) self.assertEqual(4, len(dep.bindings)) self.assertEqual('bin', dep.bindings[0].insert) self.assertEqual('PATH', dep.bindings[0].name) self.assertEqual('prepend', dep.bindings[0].mode) assert dep.bindings[0].separator in ';:' self.assertEqual('bin', dep.bindings[1].value) self.assertEqual('NO_PATH', dep.bindings[1].name) self.assertEqual(',', dep.bindings[1].separator) self.assertEqual('bin', dep.bindings[2].insert) self.assertEqual('BINDIR', dep.bindings[2].name) self.assertEqual('replace', dep.bindings[2].mode) foo_binding = dep.bindings[3] self.assertEqual('compiler', foo_binding.qdom.attrs['foo']) self.assertEqual('child', foo_binding.qdom.childNodes[0].name) self.assertEqual('run', foo_binding.command) self.assertEqual(["sha1=345", 'sha256new_345'], sorted(sels[0].digests)) assert driver.solver.ready, driver.solver.get_failure_reason() s1 = driver.solver.selections s1.selections['http://foo/Source.xml'].attrs[ 'http://namespace foo'] = 'bar' assertSel(s1) xml = s1.toDOM().toxml("utf-8") root = qdom.parse(BytesIO(xml)) self.assertEqual(namespaces.XMLNS_IFACE, root.uri) s2 = selections.Selections(root) assertSel(s2)
def testBackgroundUnsolvable(self): my_dbus.system_services = { "org.freedesktop.NetworkManager": { "/org/freedesktop/NetworkManager": NetworkManager() } } trust.trust_db.trust_key('DE937DD411906ACF7C263B396FCF121BE2390E0B', 'example.com:8000') global ran_gui # Select a version of Hello run_server('Hello.xml', '6FCF121BE2390E0B.gpg', 'HelloWorld.tgz') r = Requirements('http://example.com:8000/Hello.xml') driver = Driver(requirements=r, config=self.config) tasks.wait_for_blocker(driver.solve_with_downloads()) assert driver.solver.ready kill_server_process() # Save it as an app app = self.config.app_mgr.create_app('test-app', r) # Replace the selection with a bogus and unusable <package-implementation> sels = driver.solver.selections sel, = sels.selections.values() sel.attrs['id'] = "package:dummy:badpackage" sel.attrs['package'] = "badpackage" sel.get_command('run').qdom.attrs['path'] = '/i/dont/exist' app.set_selections(driver.solver.selections) # Not time for a background update yet, but the missing binary should trigger # an update anyway. self.config.freshness = 0 # Check we try to launch the GUI... os.environ['DISPLAY'] = 'dummy' try: app.get_selections(may_update=True) assert 0 except model.SafeException as ex: assert 'Aborted by user' in str(ex) assert ran_gui ran_gui = False # Check we can also work without the GUI... del os.environ['DISPLAY'] run_server('Hello.xml', 'HelloWorld.tgz') sels = app.get_selections(may_update=True) kill_server_process() dl = app.download_selections(sels) assert dl == None assert not ran_gui # Now trigger a background update which discovers that no solution is possible timestamp = os.path.join(app.path, 'last-checked') last_check_attempt = os.path.join(app.path, 'last-check-attempt') selections_path = os.path.join(app.path, 'selections.xml') def reset_timestamps(): global ran_gui ran_gui = False os.utime(timestamp, (1, 1)) # 1970 os.utime(selections_path, (1, 1)) if os.path.exists(last_check_attempt): os.unlink(last_check_attempt) reset_timestamps() r.source = True app.set_requirements(r) run_server('Hello.xml') with trapped_exit(1): sels = app.get_selections(may_update=True) kill_server_process()