From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) by finch.gentoo.org (Postfix) with ESMTP id D6C1A1381F3 for ; Tue, 20 Aug 2013 21:46:30 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id BB3C7E0C27; Tue, 20 Aug 2013 21:46:26 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) (using TLSv1 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id EDB17E0C80 for ; Tue, 20 Aug 2013 21:46:25 +0000 (UTC) Received: from hornbill.gentoo.org (hornbill.gentoo.org [94.100.119.163]) (using TLSv1 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id BB23633EBDF for ; Tue, 20 Aug 2013 21:46:24 +0000 (UTC) Received: from localhost.localdomain (localhost [127.0.0.1]) by hornbill.gentoo.org (Postfix) with ESMTP id 478EDE5461 for ; Tue, 20 Aug 2013 21:46:23 +0000 (UTC) From: "André Erdmann" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "André Erdmann" Message-ID: <1377016249.0b0d88215de41754ba1525d656af10868cd5a460.dywi@gentoo> Subject: [gentoo-commits] proj/R_overlay:master commit in: roverlay/depres/ X-VCS-Repository: proj/R_overlay X-VCS-Files: roverlay/depres/channels.py X-VCS-Directories: roverlay/depres/ X-VCS-Committer: dywi X-VCS-Committer-Name: André Erdmann X-VCS-Revision: 0b0d88215de41754ba1525d656af10868cd5a460 X-VCS-Branch: master Date: Tue, 20 Aug 2013 21:46:23 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Archives-Salt: 165e0cd2-f64a-4186-9be1-46ae048fce5c X-Archives-Hash: f76bd7ddffc83a057f64d16ae00faedd commit: 0b0d88215de41754ba1525d656af10868cd5a460 Author: André Erdmann mailerd de> AuthorDate: Tue Aug 20 16:26:05 2013 +0000 Commit: André Erdmann mailerd de> CommitDate: Tue Aug 20 16:30:49 2013 +0000 URL: http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=0b0d8821 roverlay/depres: non-greedy depres channel The non-greedy channel processes all deps, whether successful or not. The default behavior (EbuildJobChannel) is to stop if any mandatory dep cannot be resolved. This is desirable when running overlay creation (it's faster), but can hide unresolvable dep strings, which is not useful when writing dep rules. Single-threaded depres shouldn't be affected, though, since the ebuild channel has to wait until the resolver is done. So, the typical use case for non-greedy depres channels is when dealing with partial results (which overlay creation doesn't). --- roverlay/depres/channels.py | 181 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 168 insertions(+), 13 deletions(-) diff --git a/roverlay/depres/channels.py b/roverlay/depres/channels.py index 73459e5..d3ba725 100644 --- a/roverlay/depres/channels.py +++ b/roverlay/depres/channels.py @@ -160,19 +160,20 @@ class EbuildJobChannel ( _EbuildJobChannelBase ): def satisfy_request ( self, - close_if_unresolvable=True, preserve_order=False + close_if_unresolvable=True, preserve_order=False, want_tuple=True ): """Tells to the dependency resolver to run. - It blocks until this channel is done, which means that either all + Blocks until this channel is done, which means that either all deps are resolved or a mandatory one is unresolvable. arguments: * close_if_unresolvable -- close the channel if one dep is unresolvable this seems reasonable and defaults to True * preserve_order -- if set and True: - return resolved deps as tuple, not as - frozenset + return resolved deps as list or tuple, + not as frozenset Note that this doesn't filter out duplicates! + * want_tuple -- sets the return type for preserve_order Returns a 2-tuple ( , ) if all mandatory dependencies could be resolved, else None. @@ -180,9 +181,9 @@ class EbuildJobChannel ( _EbuildJobChannelBase ): could not be resolved. """ dep_collected = list() - dep_unresolveable = list() + dep_unresolvable = list() resolved = dep_collected.append - unresolvable = dep_unresolveable.append + unresolvable = dep_unresolvable.append def handle_queue_item ( dep_env ): self._depdone += 1 @@ -233,18 +234,172 @@ class EbuildJobChannel ( _EbuildJobChannelBase ): # DEPEND/RDEPEND/.. later, seewave requires sci-libs/fftw # in both DEPEND and RDEPEND for example self._collected_deps = frozenset ( dep_collected ) - self._unresolvable_deps = frozenset ( dep_unresolveable ) \ - if len ( dep_unresolveable ) > 0 else None + self._unresolvable_deps = frozenset ( dep_unresolvable ) \ + if len ( dep_unresolvable ) > 0 else None if preserve_order: - return ( - tuple ( dep_collected ), - tuple ( dep_unresolveable ) \ - if len ( dep_unresolveable ) > 0 else None - ) + if want_tuple: + return ( + tuple ( dep_collected ), + tuple ( dep_unresolvable ) if dep_unresolvable else None + ) + else: + return ( dep_collected, dep_unresolvable or None ) else: return ( self._collected_deps, self._unresolvable_deps ) else: if close_if_unresolvable: self.close() return None # --- end of satisfy_request (...) --- + +# --- end of EbuildJobChannel --- + +class NonGreedyDepresChannel ( _EbuildJobChannelBase ): + + def handle_request ( self, + preserve_order, allow_close=True, want_tuple=True + ): + """Tells to the dependency resolver to run. + Blocks until this channel is done, which means that all deps have been + processed, whether successful or not. + + arguments: + + * preserve_order -- if True: return resolved deps as list or tuple, + not as frozenset + Note that this doesn't filter out duplicates! + * allow_close -- whether to allow automatic close() on error + Defaults to True. + * want_tuple -- sets the return type for preserve_order + + Returns a 3-tuple + ( , , ) + + Also stores resolved/unresolvable deps in self._collected_deps, + self._unresolvable_deps. + + Automatically closes this channel if on-error mode and returns a + 3-tuple (None,None,None) unless allow_close is set to False. + """ + dep_collected = list() + dep_unresolvable = list() + resolved = dep_collected.append + unresolvable = dep_unresolvable.append + + def handle_queue_item ( dep_env ): + self._depdone += 1 + + if dep_env is None: + # queue unblocked -> on_error mode, return False + #ret = False + ret = None + elif dep_env.is_resolved(): + # successfully resolved + resolved ( dep_env.get_resolved() ) + ret = True + else: + # dep_env not resolved, + # resolve it as "not resolved" (placeholder if preserve_order) + # and add it to the list of unresolvable deps + # return false if mandatory bit is set + if preserve_order: + resolved ( roverlay.depres.depresult.DEP_NOT_RESOLVED ) + unresolvable ( dep_env.dep_str ) + ret = bool ( deptype.mandatory & ~dep_env.deptype_mask ) + + self._depres_queue.task_done() + return ret + # --- end of handle_queue_item (...) --- + + satisfiable = True + process_dep_result = True + + # loop until + # (a) satisfiable is None (= on_error mode) or + # (b) all deps processed or + # (c) error queue not empty + while ( + ( satisfiable is not None ) and + self._depdone < self._depcount and self.err_queue.empty + ): + # tell the resolver to start + self._depres_master.start() + + # wait for one result at least + process_dep_result = handle_queue_item ( self._depres_queue.get() ) + if process_dep_result is None: + satisfiable = None + elif process_dep_result is False: + satisfiable = False + + # and process all available results + while ( satisfiable is not None ) and not self._depres_queue.empty(): + process_dep_result = handle_queue_item ( + self._depres_queue.get_nowait() + ) + if process_dep_result is None: + satisfiable = None + elif process_dep_result is False: + satisfiable = False + # --- end while + + if allow_close and ( + not self.err_queue.empty or satisfiable is None + ): + self.close() + return ( None, None, None ) + elif preserve_order: + if want_tuple: + # COULDFIX: tests/depres expects tuples for comparision + self._collected_deps = tuple ( dep_collected ) + self._unresolvable_deps = tuple ( dep_unresolvable ) + else: + self._collected_deps = dep_collected + self._unresolvable_deps = dep_unresolvable + else: + self._collected_deps = frozenset ( dep_collected ) + self._unresolvable_deps = frozenset ( dep_unresolvable ) + + return ( satisfiable, self._collected_deps, self._unresolvable_deps ) + # --- end of handle_request (...) --- + + def satisfy_request ( self, + close_if_unresolvable=True, preserve_order=False, want_tuple=True + ): + """Tells to the dependency resolver to run. + Blocks until this channel is done, which means that all deps have been + processed, whether successful or not. + + arguments: + * close_if_unresolvable -- close the channel if one dep is unresolvable + this seems reasonable and defaults to True + * preserve_order -- if set and True: + return resolved deps as tuple, + not as frozenset + Note that this doesn't filter out duplicates! + * want_tuple -- sets the return type for preserve_order + + Returns a 2-tuple + ( , |None ) + if all mandatory deps could be resolved, else None. + + Calls handle_request() for doing the actual work. This is a compat + function that provides a common interface for ebuild creation jobs, + consider using handle_request() directly. + """ + satisfiable, dep_resolved, dep_unresolable = self.handle_request ( + preserve_order=preserve_order, allow_close=close_if_unresolvable, + want_tuple=want_tuple + ) + + if satisfiable and self.err_queue.empty: + return ( self._collected_deps, self._unresolvable_deps or None ) + elif satisfiable is None or not close_if_unresolvable: + # already closed or don't close + return None + else: + self.close() + return None + # --- end of satisfy_request (...) --- + +# --- end of NonGreedyDepresChannel ---