@@ -66,28 +66,6 @@ def _track_stage(stage):
66
66
stage .repo .scm .track_changed_files ()
67
67
68
68
69
- def _get_active_graph (G ):
70
- import networkx as nx
71
-
72
- active = G .copy ()
73
- for stage in G :
74
- if not stage .frozen :
75
- continue
76
- active .remove_edges_from (G .out_edges (stage ))
77
- for edge in G .out_edges (stage ):
78
- _ , to_stage = edge
79
- for node in nx .dfs_preorder_nodes (G , to_stage ):
80
- # NOTE: `in_degree` will return InDegreeView({}) if stage
81
- # no longer exists in the `active` DAG.
82
- if not active .in_degree (node ):
83
- # NOTE: if some edge no longer exists `remove_edges_from`
84
- # will ignore it without error.
85
- active .remove_edges_from (G .out_edges (node ))
86
- active .remove_node (node )
87
-
88
- return active
89
-
90
-
91
69
@locked
92
70
@scm_context
93
71
def reproduce (
@@ -104,7 +82,7 @@ def reproduce(
104
82
if isinstance (targets , str ):
105
83
targets = [targets ]
106
84
107
- if not all_pipelines and targets is None :
85
+ if not all_pipelines and not targets :
108
86
from dvc .dvcfile import PIPELINE_FILE
109
87
110
88
targets = [PIPELINE_FILE ]
@@ -113,36 +91,33 @@ def reproduce(
113
91
if not interactive :
114
92
kwargs ["interactive" ] = self .config ["core" ].get ("interactive" , False )
115
93
116
- active_graph = _get_active_graph (self .graph )
117
- active_pipelines = get_pipelines (active_graph )
118
-
119
94
stages = set ()
120
95
if pipeline or all_pipelines :
96
+ pipelines = get_pipelines (self .graph )
121
97
if all_pipelines :
122
- pipelines = active_pipelines
98
+ used_pipelines = pipelines
123
99
else :
124
- pipelines = []
100
+ used_pipelines = []
125
101
for target in targets :
126
102
stage = self .stage .get_target (target )
127
- pipelines .append (get_pipeline (active_pipelines , stage ))
103
+ used_pipelines .append (get_pipeline (pipelines , stage ))
128
104
129
- for pipeline in pipelines :
130
- for stage in pipeline :
131
- if pipeline .in_degree (stage ) == 0 :
105
+ for pline in used_pipelines :
106
+ for stage in pline :
107
+ if pline .in_degree (stage ) == 0 :
132
108
stages .add (stage )
133
109
else :
134
110
for target in targets :
135
111
stages .update (
136
112
self .stage .collect (
137
113
target ,
138
114
recursive = recursive ,
139
- graph = active_graph ,
140
115
accept_group = accept_group ,
141
116
glob = glob ,
142
117
)
143
118
)
144
119
145
- return _reproduce_stages (active_graph , list (stages ), ** kwargs )
120
+ return _reproduce_stages (self . graph , list (stages ), ** kwargs )
146
121
147
122
148
123
def _reproduce_stages (
@@ -183,15 +158,15 @@ def _reproduce_stages(
183
158
184
159
The derived evaluation of _downstream_ B would be: [B, D, E]
185
160
"""
186
- pipeline = _get_pipeline (G , stages , downstream , single_item )
161
+ steps = _get_steps (G , stages , downstream , single_item )
187
162
188
163
force_downstream = kwargs .pop ("force_downstream" , False )
189
164
result = []
190
165
unchanged = []
191
166
# `ret` is used to add a cosmetic newline.
192
167
ret = []
193
168
checkpoint_func = kwargs .pop ("checkpoint_func" , None )
194
- for stage in pipeline :
169
+ for stage in steps :
195
170
if ret :
196
171
logger .info ("" )
197
172
@@ -225,9 +200,17 @@ def _reproduce_stages(
225
200
return result
226
201
227
202
228
- def _get_pipeline (G , stages , downstream , single_item ):
203
+ def _get_steps (G , stages , downstream , single_item ):
229
204
import networkx as nx
230
205
206
+ active = G .copy ()
207
+ if not single_item :
208
+ # NOTE: frozen stages don't matter for single_item
209
+ for stage in G :
210
+ if stage .frozen :
211
+ # NOTE: disconnect frozen stage from its dependencies
212
+ active .remove_edges_from (G .out_edges (stage ))
213
+
231
214
all_pipelines = []
232
215
for stage in stages :
233
216
if downstream :
@@ -239,20 +222,21 @@ def _get_pipeline(G, stages, downstream, single_item):
239
222
# itself, and then reverse it, instead of using
240
223
# graph.reverse() directly because it calls `deepcopy`
241
224
# underneath -- unless copy=False is specified.
242
- nodes = nx .dfs_postorder_nodes (G . copy () .reverse (copy = False ), stage )
225
+ nodes = nx .dfs_postorder_nodes (active .reverse (copy = False ), stage )
243
226
all_pipelines += reversed (list (nodes ))
244
227
else :
245
- all_pipelines += nx .dfs_postorder_nodes (G , stage )
228
+ all_pipelines += nx .dfs_postorder_nodes (active , stage )
246
229
247
- pipeline = []
230
+ steps = []
248
231
for stage in all_pipelines :
249
- if stage not in pipeline :
232
+ if stage not in steps :
233
+ # NOTE: order of steps still matters for single_item
250
234
if single_item and stage not in stages :
251
235
continue
252
236
253
- pipeline .append (stage )
237
+ steps .append (stage )
254
238
255
- return pipeline
239
+ return steps
256
240
257
241
258
242
def _repro_callback (experiments_callback , unchanged , stages ):
0 commit comments