Package zeroinstall :: Module helpers
[frames] | no frames]

Source Code for Module zeroinstall.helpers

  1  """ 
  2  Convenience routines for performing common operations. 
  3  @since: 0.28 
  4  """ 
  5   
  6  # Copyright (C) 2009, Thomas Leonard 
  7  # See the README file for details, or visit http://0install.net. 
  8   
  9  import os, sys, logging 
 10  from zeroinstall import support 
 11  from zeroinstall.support import tasks 
 12   
13 -def get_selections_gui(iface_uri, gui_args, test_callback = None):
14 """Run the GUI to choose and download a set of implementations. 15 The user may ask the GUI to submit a bug report about the program. In that case, 16 the GUI may ask us to test it. test_callback is called in that case with the implementations 17 to be tested; the callback will typically call L{zeroinstall.injector.run.test_selections} and return the result of that. 18 @param iface_uri: the required program, or None to show just the preferences dialog 19 @type iface_uri: str 20 @param gui_args: any additional arguments for the GUI itself 21 @type gui_args: [str] 22 @param test_callback: function to use to try running the program 23 @type test_callback: L{zeroinstall.injector.selections.Selections} -> str 24 @return: the selected implementations 25 @rtype: L{zeroinstall.injector.selections.Selections} 26 @since: 0.28 27 """ 28 from zeroinstall.injector import selections, qdom 29 from StringIO import StringIO 30 31 from os.path import join, dirname 32 gui_exe = join(dirname(__file__), '0launch-gui', '0launch-gui') 33 34 import socket 35 cli, gui = socket.socketpair() 36 37 try: 38 child = os.fork() 39 if child == 0: 40 # We are the child (GUI) 41 try: 42 try: 43 cli.close() 44 # We used to use pipes to support Python2.3... 45 os.dup2(gui.fileno(), 1) 46 os.dup2(gui.fileno(), 0) 47 if iface_uri is not None: 48 gui_args = gui_args + ['--', iface_uri] 49 os.execvp(sys.executable, [sys.executable, gui_exe] + gui_args) 50 except: 51 import traceback 52 traceback.print_exc(file = sys.stderr) 53 finally: 54 sys.stderr.flush() 55 os._exit(1) 56 # We are the parent (CLI) 57 gui.close() 58 gui = None 59 60 while True: 61 logging.info("Waiting for selections from GUI...") 62 63 reply = support.read_bytes(cli.fileno(), len('Length:') + 9, null_ok = True) 64 if reply: 65 if not reply.startswith('Length:'): 66 raise Exception("Expected Length:, but got %s" % repr(reply)) 67 xml = support.read_bytes(cli.fileno(), int(reply.split(':', 1)[1], 16)) 68 69 dom = qdom.parse(StringIO(xml)) 70 sels = selections.Selections(dom) 71 72 if dom.getAttribute('run-test'): 73 logging.info("Testing program, as requested by GUI...") 74 if test_callback is None: 75 output = "Can't test: no test_callback was passed to get_selections_gui()\n" 76 else: 77 output = test_callback(sels) 78 logging.info("Sending results to GUI...") 79 output = ('Length:%8x\n' % len(output)) + output 80 logging.debug("Sending: %s", repr(output)) 81 while output: 82 sent = cli.send(output) 83 output = output[sent:] 84 continue 85 else: 86 sels = None 87 88 pid, status = os.waitpid(child, 0) 89 assert pid == child 90 if status == 1 << 8: 91 logging.info("User cancelled the GUI; aborting") 92 return None # Aborted 93 if status != 0: 94 raise Exception("Error from GUI: code = %d" % status) 95 break 96 finally: 97 for sock in [cli, gui]: 98 if sock is not None: sock.close() 99 100 return sels
101
102 -def ensure_cached(uri, command = 'run', config = None):
103 """Ensure that an implementation of uri is cached. 104 If not, it downloads one. It uses the GUI if a display is 105 available, or the console otherwise. 106 @param uri: the required interface 107 @type uri: str 108 @return: the selected implementations, or None if the user cancelled 109 @rtype: L{zeroinstall.injector.selections.Selections} 110 """ 111 from zeroinstall.injector.driver import Driver 112 113 if config is None: 114 from zeroinstall.injector.config import load_config 115 config = load_config() 116 117 from zeroinstall.injector.requirements import Requirements 118 requirements = Requirements(uri) 119 requirements.command = command 120 121 d = Driver(config, requirements) 122 123 if d.need_download() or not d.solver.ready: 124 if os.environ.get('DISPLAY', None): 125 return get_selections_gui(uri, ['--command', command]) 126 else: 127 done = d.solve_and_download_impls() 128 tasks.wait_for_blocker(done) 129 130 return d.solver.selections
131