MCPcopy
hub / github.com/treeverse/dvc / ForeachDefinition

Class ForeachDefinition

dvc/parsing/__init__.py:362–498  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

360
361
362class ForeachDefinition:
363 def __init__(
364 self,
365 resolver: DataResolver,
366 context: Context,
367 name: str,
368 definition: "DictStrAny",
369 where: str = STAGES_KWD,
370 ):
371 self.resolver = resolver
372 self.relpath = self.resolver.relpath
373 self.context = context
374 self.name = name
375
376 assert DO_KWD in definition
377 assert MATRIX_KWD not in definition
378 self.foreach_data = definition[FOREACH_KWD]
379 self._template = definition[DO_KWD]
380
381 self.pair = IterationPair()
382 self.where = where
383
384 @cached_property
385 def template(self):
386 # optimization: check for syntax errors only once for `foreach` stages
387 check_syntax_errors(self._template, self.name, self.relpath)
388 return self._template
389
390 @cached_property
391 def resolved_iterable(self):
392 return self._resolve_foreach_data()
393
394 def _resolve_foreach_data(self) -> "SeqOrMap":
395 try:
396 iterable = self.context.resolve(self.foreach_data, unwrap=False)
397 except (ContextError, ParseError) as exc:
398 format_and_raise(exc, f"'{self.where}.{self.name}.foreach'", self.relpath)
399
400 # foreach data can be a resolved dictionary/list.
401 self._check_is_map_or_seq(iterable)
402 # foreach stages will have `item` and `key` added to the context
403 # so, we better warn them if they have them already in the context
404 # from the global vars. We could add them in `set_temporarily`, but
405 # that'd make it display for each iteration.
406 self._warn_if_overwriting(self._inserted_keys(iterable))
407 return iterable
408
409 def _check_is_map_or_seq(self, iterable):
410 if not is_map_or_seq(iterable):
411 node = iterable.value if isinstance(iterable, Node) else iterable
412 typ = type(node).__name__
413 raise ResolveError(
414 f"failed to resolve '{self.where}.{self.name}.foreach'"
415 f" in '{self.relpath}': expected list/dictionary, got " + typ
416 )
417
418 def _warn_if_overwriting(self, keys: list[str]):
419 warn_for = [k for k in keys if k in self.context]

Calls

no outgoing calls