66import logging
77from collections import abc , defaultdict
88from itertools import count
9- from typing import Any , Callable , Collection , List , Mapping , Optional , Tuple , Union
9+ from typing import (
10+ Any ,
11+ Callable ,
12+ Collection ,
13+ List ,
14+ Mapping ,
15+ NamedTuple ,
16+ Optional ,
17+ Tuple ,
18+ Union ,
19+ )
1020
1121import networkx as nx
1222from boltons .setutils import IndexedSet as iset
@@ -599,6 +609,20 @@ def compile(
599609 return plan
600610
601611
612+ class NestArgs (NamedTuple ):
613+ """:term:`operation nesting` callables receive instances of this class."""
614+
615+ #: the parent :class:`.NetworkOperation` of the operation currently being processed
616+ parent : "NetworkOperation"
617+ #: what is currently being renamed,
618+ #: one of the string: ``(op | needs | provides)``
619+ typ : str
620+ #: the operation currently being processed
621+ op : Operation
622+ # the name of the item to be renamed/nested
623+ name : str
624+
625+
602626def build_network (
603627 operations ,
604628 rescheduled = None ,
@@ -608,7 +632,12 @@ def build_network(
608632 nest = None ,
609633 node_props = None ,
610634):
611- """The :term:`network` factory that does :term:`operation merging` before constructing it. """
635+ """
636+ The :term:`network` factory that does :term:`operation merging` before constructing it.
637+
638+ :param nest:
639+ see same-named param in :func:`.compose`
640+ """
612641 from boltons .setutils import IndexedSet as iset
613642 from .op import NULL_OP
614643 from .pipeline import NetworkOperation
@@ -622,7 +651,7 @@ def proc_op(op, parent=None):
622651 #
623652 if (
624653 node_props
625- or ( nest and parent )
654+ or nest
626655 or rescheduled is not None
627656 or endured is not None
628657 or parallel is not None
@@ -646,43 +675,51 @@ def proc_op(op, parent=None):
646675 ## If `nest`, rename the op & data (predicated by `nest`)
647676 # by prefixing them with their parent netop.
648677 #
678+ nest_args = NestArgs (parent , op , None , None )
649679 if nest :
650- kw ["name" ] = node_renamed ("operation" , op , parent )
651- kw ["needs" ] = [node_renamed ("needs" , n , parent ) for n in op .needs ]
680+ kw ["name" ] = rename (nest_args ._replace (typ = "op" , name = op .name ))
681+ kw ["needs" ] = [
682+ rename (nest_args ._replace (typ = "needs" , name = n )) for n in op .needs
683+ ]
652684 kw ["provides" ] = [
653- node_renamed ("provides" , n , parent ) for n in op .provides
685+ rename (nest_args ._replace (typ = "provides" , name = n ))
686+ for n in op .provides
654687 ]
655688
656689 op = op .withset (** kw )
657690
658691 return op
659692
660- def node_renamed ( typ , node , parent ) -> str :
693+ def rename ( nest_args : NestArgs ) -> str :
661694 """Handle user's or default `nest` callable's results."""
662- assert callable (nest ), (nest , operations )
663-
664- ret = nest (typ , node , parent )
695+ assert callable (nest ), (nest , nest_args )
696+
697+ ok = False
698+ try :
699+ ret = nest (nest_args )
700+ if not ret :
701+ # A falsy means don't touch the node.
702+ ret = nest_args .name
703+ elif not isinstance (ret , str ):
704+ # Truthy but not str values mean apply default nesting.
705+ ret = nest_any_node (nest_args )
706+
707+ ok = True
708+ return ret
709+ finally :
710+ if not ok :
711+ log .warning ("Failed to nest-rename %s" , nest_args )
665712
666- if not ret :
667- # A falsy means don't touch the node.
668- return node .name if isinstance (node , Operation ) else node
669-
670- if not isinstance (ret , str ):
671- # Truthy but not str values mean nest!
672- ret = nest_any_node (typ , node , parent )
673-
674- return ret
675-
676- ## Set default nesting if requested by user.
677- #
678713 if nest :
714+ ## Set default nesting if not one provided by user.
715+ #
679716 if not callable (nest ):
680717 nest = nest_any_node
681718
682719 merge_set = iset () # Preseve given node order.
683720 for op in operations :
684721 if isinstance (op , NetworkOperation ):
685- merge_set .update (proc_op (s , op . name ) for s in yield_ops (op .net .graph ))
722+ merge_set .update (proc_op (s , op ) for s in yield_ops (op .net .graph ))
686723 else :
687724 merge_set .add (proc_op (op ))
688725 merge_set = iset (i for i in merge_set if not isinstance (i , NULL_OP ))
@@ -693,22 +730,18 @@ def node_renamed(typ, node, parent) -> str:
693730 return net
694731
695732
696- def nest_any_node (
697- node_type : str , node : Union [Operation , str ], parent : "NetworkOperation"
698- ) -> str :
699- """Nest both operation & data `node` under `parent` (if given).
733+ def nest_any_node (nest_args : NestArgs ) -> str :
734+ """Nest both operation & data under `parent`'s name (if given).
700735
701736 :return:
702737 the nested name of the operation or data
703738 """
704739
705740 def prefixed (name ):
706- return f"{ parent } .{ name } " if parent else name
741+ return f"{ nest_args . parent . name } .{ name } " if nest_args . parent else name
707742
708- if isinstance (node , Operation ):
709- new_name = prefixed (node .name )
710- else :
711- assert isinstance (node , str ), locals ()
712- new_name = dep_renamed (node , prefixed )
713-
714- return new_name
743+ return (
744+ prefixed (nest_args .name )
745+ if nest_args .typ == "op"
746+ else dep_renamed (nest_args .name , prefixed )
747+ )
0 commit comments