def spawn_build(self, iface_name): assert self.child is None self.details.insert_at_end_and_scroll('Building %s\n' % iface_name, 'heading') # Group all the child processes so we can kill them easily def become_group_leader(): os.setpgid(0, 0) devnull = os.open(os.devnull, os.O_RDONLY) try: self.child = subprocess.Popen([sys.executable, '-u', sys.argv[0], 'build'], stdin = devnull, stdout = subprocess.PIPE, stderr = subprocess.STDOUT, preexec_fn = become_group_leader) finally: os.close(devnull) import codecs decoder = codecs.getincrementaldecoder('utf-8')(errors = 'replace') while True: yield tasks.InputBlocker(self.child.stdout, 'output from child') got = os.read(self.child.stdout.fileno(), 100) chars = decoder.decode(got, final = not got) self.details.insert_at_end_and_scroll(chars) if not got: break self.child.wait() code = self.child.returncode self.child = None if code: self.details.insert_at_end_and_scroll('Build process exited with error status %d\n' % code, 'error') raise SafeException('Build process exited with error status %d' % code) self.details.insert_at_end_and_scroll('Build completed successfully\n', 'heading')
def handle_events(): while True: logger.debug("waiting for stdin") yield tasks.InputBlocker(stdin, 'wait for commands from master') logger.debug("reading JSON") message = recv_json() logger.debug("got %s", message) if message is None: break handle_message(config, options, message)
def testInputBlocker(self): r, w = os.pipe() b = tasks.InputBlocker(r, "waiting for input") t = tasks.TimeoutBlocker(0.01, "timeout") @tasks. async def run(): yield b, t assert t.happened assert not b.happened os.write(w, b"!") yield b assert b.happened os.close(r) os.close(w) tasks.wait_for_blocker(run())
def confirm_import_feed(self, pending, valid_sigs): """Sub-classes should override this method to interact with the user about new feeds. If multiple feeds need confirmation, L{trust.TrustMgr.confirm_keys} will only invoke one instance of this method at a time. @param pending: the new feed to be imported @type pending: L{PendingFeed} @param valid_sigs: maps signatures to a list of fetchers collecting information about the key @type valid_sigs: {L{gpg.ValidSig} : L{fetch.KeyInfoFetcher}} @since: 0.42""" from zeroinstall.injector import trust assert valid_sigs domain = trust.domain_from_url(pending.url) # Ask on stderr, because we may be writing XML to stdout print >>sys.stderr, _("Feed: %s") % pending.url print >>sys.stderr, _("The feed is correctly signed with the following keys:") for x in valid_sigs: print >>sys.stderr, "-", x def text(parent): text = "" for node in parent.childNodes: if node.nodeType == node.TEXT_NODE: text = text + node.data return text shown = set() key_info_fetchers = valid_sigs.values() while key_info_fetchers: old_kfs = key_info_fetchers key_info_fetchers = [] for kf in old_kfs: infos = set(kf.info) - shown if infos: if len(valid_sigs) > 1: print "%s: " % kf.fingerprint for key_info in infos: print >>sys.stderr, "-", text(key_info) shown.add(key_info) if kf.blocker: key_info_fetchers.append(kf) if key_info_fetchers: for kf in key_info_fetchers: print >>sys.stderr, kf.status stdin = tasks.InputBlocker(0, 'console') blockers = [kf.blocker for kf in key_info_fetchers] + [stdin] yield blockers for b in blockers: try: tasks.check(b) except Exception as ex: warn(_("Failed to get key info: %s"), ex) if stdin.happened: print >>sys.stderr, _("Skipping remaining key lookups due to input from user") break if not shown: print >>sys.stderr, _("Warning: Nothing known about this key!") if len(valid_sigs) == 1: print >>sys.stderr, _("Do you want to trust this key to sign feeds from '%s'?") % domain else: print >>sys.stderr, _("Do you want to trust all of these keys to sign feeds from '%s'?") % domain while True: print >>sys.stderr, _("Trust [Y/N] "), i = raw_input() if not i: continue if i in 'Nn': raise NoTrustedKeys(_('Not signed with a trusted key')) if i in 'Yy': break for key in valid_sigs: print >>sys.stderr, _("Trusting %(key_fingerprint)s for %(domain)s") % {'key_fingerprint': key.fingerprint, 'domain': domain} trust.trust_db.trust_key(key.fingerprint, domain)
def confirm_import_feed(self, pending, valid_sigs): """ verify the feed """ from zeroinstall.injector import trust assert valid_sigs domain = trust.domain_from_url(pending.url) # Ask on stderr, because we may be writing XML to stdout print "Feed: %s" % pending.url print "The feed is correctly signed with the following keys:" for x in valid_sigs: print "-", x def text(parent): text = "" for node in parent.childNodes: if node.nodeType == node.TEXT_NODE: text = text + node.data return text shown = set() key_info_fetchers = valid_sigs.values() while key_info_fetchers: old_kfs = key_info_fetchers key_info_fetchers = [] for kf in old_kfs: infos = set(kf.info) - shown if infos: if len(valid_sigs) > 1: print("%s: " % kf.fingerprint) for key_info in infos: print("-", text(key_info)) shown.add(key_info) if kf.blocker: key_info_fetchers.append(kf) if key_info_fetchers: for kf in key_info_fetchers: print(kf.status) stdin = tasks.InputBlocker(0, 'console') blockers = [kf.blocker for kf in key_info_fetchers] + [stdin] yield blockers for b in blockers: try: tasks.check(b) except Exception as ex: warn(_("Failed to get key info: %s"), ex) if stdin.happened: print( "Skipping remaining key lookups due to input from user" ) break for key in valid_sigs: print("Trusting %(key_fingerprint)s for %(domain)s") % { 'key_fingerprint': key.fingerprint, 'domain': domain } trust.trust_db.trust_key(key.fingerprint, domain)
def _do_download(self): """Will trigger L{downloaded} when done (on success or failure).""" self.errors = '' # Can't use fork here, because Windows doesn't have it assert self.child is None, self.child child_args = [sys.executable, '-u', __file__, self.url] if self.modification_time: child_args.append(self.modification_time) self.child = subprocess.Popen(child_args, stderr=subprocess.PIPE, stdout=self.tempfile) self.status = download_fetching # Wait for child to exit, collecting error output as we go while True: yield tasks.InputBlocker(self.child.stderr, "read data from " + self.url) data = os.read(self.child.stderr.fileno(), 100) if not data: break self.errors += data # Download is complete... assert self.status is download_fetching assert self.tempfile is not None assert self.child is not None status = self.child.wait() self.child = None errors = self.errors self.errors = None if status == RESULT_NOT_MODIFIED: debug("%s not modified", self.url) self.tempfile = None self.unmodified = True self.status = download_complete self._final_total_size = 0 self.downloaded.trigger() return if status and not self.aborted_by_user and not errors: errors = _('Download process exited with error status ' 'code %s') % hex(status) self._final_total_size = self.get_bytes_downloaded_so_far() stream = self.tempfile self.tempfile = None try: if self.aborted_by_user: raise DownloadAborted(errors) if errors: raise DownloadError(errors.strip()) # Check that the download has the correct size, if we know what it should be. if self.expected_size is not None: size = os.fstat(stream.fileno()).st_size if size != self.expected_size: raise SafeException( _('Downloaded archive has incorrect size.\n' 'URL: %(url)s\n' 'Expected: %(expected_size)d bytes\n' 'Received: %(size)d bytes') % { 'url': self.url, 'expected_size': self.expected_size, 'size': size }) except: self.status = download_failed _unused, ex, tb = sys.exc_info() self.downloaded.trigger(exception=(ex, tb)) else: self.status = download_complete self.downloaded.trigger()
def confirm_import_feed(self, pending, valid_sigs): """Sub-classes should override this method to interact with the user about new feeds. If multiple feeds need confirmation, L{confirm_keys} will only invoke one instance of this method at a time. @param pending: the new feed to be imported @type pending: L{PendingFeed} @param valid_sigs: maps signatures to a list of fetchers collecting information about the key @type valid_sigs: {L{gpg.ValidSig} : L{fetch.KeyInfoFetcher}} @since: 0.42 @see: L{confirm_keys}""" from zeroinstall.injector import trust assert valid_sigs domain = trust.domain_from_url(pending.url) # Ask on stderr, because we may be writing XML to stdout print >> sys.stderr, _("Feed: %s") % pending.url print >> sys.stderr, _( "The feed is correctly signed with the following keys:") for x in valid_sigs: print >> sys.stderr, "-", x def text(parent): text = "" for node in parent.childNodes: if node.nodeType == node.TEXT_NODE: text = text + node.data return text shown = set() key_info_fetchers = valid_sigs.values() while key_info_fetchers: old_kfs = key_info_fetchers key_info_fetchers = [] for kf in old_kfs: infos = set(kf.info) - shown if infos: if len(valid_sigs) > 1: print "%s: " % kf.fingerprint for info in infos: print >> sys.stderr, "-", text(info) shown.add(info) if kf.blocker: key_info_fetchers.append(kf) if key_info_fetchers: for kf in key_info_fetchers: print >> sys.stderr, kf.status stdin = tasks.InputBlocker(0, 'console') blockers = [kf.blocker for kf in key_info_fetchers] + [stdin] yield blockers for b in blockers: try: tasks.check(b) except Exception, ex: warn(_("Failed to get key info: %s"), ex) if stdin.happened: print >> sys.stderr, _( "Skipping remaining key lookups due to input from user" ) break