diff --git a/doc/source/api/output.rst b/doc/source/api/output.rst index c656b5de..ba1ed00d 100644 --- a/doc/source/api/output.rst +++ b/doc/source/api/output.rst @@ -284,6 +284,13 @@ methods :return: A list of `str` labels of workloads that were part of this run. +.. method:: RunOutput.add_classifier(name, value, overwrite=False) + + Add a classifier to the run as a whole. If a classifier with the specified + ``name`` already exists, a``ValueError`` will be raised, unless + `overwrite=True` is specified. + + :class:`RunDatabaseOutput` --------------------------- @@ -402,7 +409,7 @@ artifacts, metadata, and configuration. It has the following attributes: methods ~~~~~~~ -.. method:: RunOutput.get_artifact(name) +.. method:: JobOutput.get_artifact(name) Return the :class:`Artifact` specified by ``name`` associated with this job. @@ -410,7 +417,7 @@ methods :return: The :class:`Artifact` with that name :raises HostError: If the artifact with the specified name does not exist. -.. method:: RunOutput.get_artifact_path(name) +.. method:: JobOutput.get_artifact_path(name) Return the path to the file backing the artifact specified by ``name``, associated with this job. @@ -419,13 +426,20 @@ methods :return: The path to the artifact :raises HostError: If the artifact with the specified name does not exist. -.. method:: RunOutput.get_metric(name) +.. method:: JobOutput.get_metric(name) Return the :class:`Metric` associated with this job with the specified `name`. :return: The :class:`Metric` object for the metric with the specified name. +.. method:: JobOutput.add_classifier(name, value, overwrite=False) + + Add a classifier to the job. The classifier will be propagated to all + existing artifacts and metrics, as well as those added afterwards. If a + classifier with the specified ``name`` already exists, a ``ValueError`` will + be raised, unless `overwrite=True` is specified. + :class:`JobDatabaseOutput` --------------------------- diff --git a/wa/framework/execution.py b/wa/framework/execution.py index ac386ba9..bd4b062a 100644 --- a/wa/framework/execution.py +++ b/wa/framework/execution.py @@ -249,6 +249,11 @@ class ExecutionContext(object): def add_event(self, message): self.output.add_event(message) + def add_classifier(self, name, value, overwrite=False): + self.output.add_classifier(name, value, overwrite) + if self.current_job: + self.current_job.add_classifier(name, value, overwrite) + def add_metadata(self, key, *args, **kwargs): self.output.add_metadata(key, *args, **kwargs) diff --git a/wa/framework/job.py b/wa/framework/job.py index 347b4e54..127da658 100644 --- a/wa/framework/job.py +++ b/wa/framework/job.py @@ -181,6 +181,11 @@ class Job(object): if force or self.status < status: self.status = status + def add_classifier(self, name, value, overwrite=False): + if name in self.classifiers and not overwrite: + raise ValueError('Cannot overwrite "{}" classifier.'.format(name)) + self.classifiers[name] = value + def __str__(self): return '{} ({}) [{}]'.format(self.id, self.label, self.iteration) diff --git a/wa/framework/output.py b/wa/framework/output.py index 66b90a1d..682d08a2 100644 --- a/wa/framework/output.py +++ b/wa/framework/output.py @@ -165,6 +165,9 @@ class Output(object): artifact = self.get_artifact(name) return self.get_path(artifact.path) + def add_classifier(self, name, value, overwrite=False): + self.result.add_classifier(name, value, overwrite) + def add_metadata(self, key, *args, **kwargs): self.result.add_metadata(key, *args, **kwargs) @@ -410,6 +413,21 @@ class Result(Podable): return artifact raise HostError('Artifact "{}" not found'.format(name)) + def add_classifier(self, name, value, overwrite=False): + if name in self.classifiers and not overwrite: + raise ValueError('Cannot overwrite "{}" classifier.'.format(name)) + self.classifiers[name] = value + + for metric in self.metrics: + if name in metric.classifiers and not overwrite: + raise ValueError('Cannot overwrite "{}" classifier; clashes with {}.'.format(name, metric)) + metric.classifiers[name] = value + + for artifact in self.artifacts: + if name in artifact.classifiers and not overwrite: + raise ValueError('Cannot overwrite "{}" classifier; clashes with {}.'.format(name, artifact)) + artifact.classifiers[name] = value + def add_metadata(self, key, *args, **kwargs): force = kwargs.pop('force', False) if kwargs: