def assert_artifact(self, step, name, value, fields=None): for task, artifacts in self.artifact_dict(step, name).items(): if name in artifacts: artifact = artifacts[name] if fields: for field, v in fields.items(): if is_stringish(artifact): data = json.loads(artifact) else: data = artifact if not isinstance(data, dict): raise AssertArtifactFailed( "Task '%s' expected %s to be a dictionary (got %s)" % (task, name, type(data))) if data.get(field, None) != v: raise AssertArtifactFailed( "Task '%s' expected %s[%s]=%r but got %s[%s]=%s" % (task, name, field, truncate(value), name, field, truncate(data[field]))) elif artifact != value: raise AssertArtifactFailed( "Task '%s' expected %s=%r but got %s=%s" % (task, name, truncate(value), name, truncate(artifact))) else: raise AssertArtifactFailed("Task '%s' expected %s=%s but " "the key was not found" %\ (task, name, truncate(value))) return True
def assert_artifact(self, step, name, value, fields=None): for task in self.run[step]: for artifact in task: if artifact.id == name: if fields: for field, v in fields.items(): if is_stringish(artifact.data): data = json.loads(artifact.data) else: data = artifact.data if not isinstance(data, dict): raise AssertArtifactFailed( "Task '%s' expected %s to be a dictionary; got %s" % (task.id, name, type(data))) if data.get(field, None) != v: raise AssertArtifactFailed( "Task '%s' expected %s[%s]=%r but got %s[%s]=%s" % (task.id, name, field, truncate(value), name, field, truncate(data[field]))) elif artifact.data == value: break else: raise AssertArtifactFailed("Task '%s' expected %s=%r " "but got %s=%s" %\ (task.id, name, truncate(value), name, truncate(artifact.data))) else: raise AssertArtifactFailed("Task '%s' expected %s=%s but " "the key was not found" %\ (task.id, name, truncate(value))) return True
def mutate_user_tags_for_run(cls, flow_id, run_id, tags_to_remove=None, tags_to_add=None): """ Mutate the set of user tags for a run. Removals logically get applied after additions. Operations occur as a batch atomically. Parameters ---------- flow_id : str Flow id, that the run belongs to. run_id: str Run id, together with flow_id, that identifies the specific Run whose tags to mutate tags_to_remove: iterable over str Iterable over tags to remove tags_to_add: iterable over str Iterable over tags to add Return ------ Run tags after mutation operations """ # perform common validation, across all provider implementations if tags_to_remove is None: tags_to_remove = [] if tags_to_add is None: tags_to_add = [] if not tags_to_add and not tags_to_remove: raise MetaflowTaggingError("Must add or remove at least one tag") if is_stringish(tags_to_add): raise MetaflowTaggingError("tags_to_add may not be a string") if is_stringish(tags_to_remove): raise MetaflowTaggingError("tags_to_remove may not be a string") def _is_iterable(something): try: iter(something) return True except TypeError: return False if not _is_iterable(tags_to_add): raise MetaflowTaggingError("tags_to_add must be iterable") if not _is_iterable(tags_to_remove): raise MetaflowTaggingError("tags_to_remove must be iterable") # check each tag is valid for tag in chain(tags_to_add, tags_to_remove): validate_tag(tag) # onto subclass implementation final_user_tags = cls._mutate_user_tags_for_run( flow_id, run_id, tags_to_add=tags_to_add, tags_to_remove=tags_to_remove) return final_user_tags