blob: 647d0a7aceaab3b517b650f55dcb5347b3b5e9cb [file] [log] [blame]
# Copyright 2016 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Functions and classes for formatting buildbot stage annotations."""
import abc
import itertools
import json
class Annotation:
"""Formatted annotation for buildbot."""
def __init__(self, name, args):
"""Initialize instance.
Args:
name: Annotation name.
args: A sequence of string arguments.
"""
self.name = name
self.args = args
def __str__(self):
inner_text = "@".join(
_EscapeArgText(text)
for text in itertools.chain([self.name], self.args)
)
return "@@@%s@@@" % (inner_text,)
@property
def human_friendly(self):
"""Human-friendly format."""
if self.args:
return "%s: %s" % (self.name, "; ".join(self.args))
else:
return self.name
class _NamedAnnotation(Annotation, metaclass=abc.ABCMeta):
"""Abstract subclass for creating named annotations.
Concrete subclasses should define the ANNOTATION_NAME class attribute.
"""
def __init__(self, *args):
super().__init__(self.ANNOTATION_NAME, args)
# TODO(b/236161656): Fix.
# pylint: disable-next=deprecated-decorator
@abc.abstractproperty
def ANNOTATION_NAME(self):
raise NotImplementedError()
class StepLink(_NamedAnnotation):
"""STEP_LINK annotation."""
ANNOTATION_NAME = "STEP_LINK"
# Some callers pass in text/url by kwarg. We leave the full signature here
# so the API is a bit cleaner/more obvious.
# pylint: disable=useless-super-delegation
def __init__(self, text, url):
super().__init__(text, url)
class StepText(_NamedAnnotation):
"""STEP_TEXT annotation."""
ANNOTATION_NAME = "STEP_TEXT"
class StepWarnings(_NamedAnnotation):
"""STEP_WARNINGS annotation."""
ANNOTATION_NAME = "STEP_WARNINGS"
class StepFailure(_NamedAnnotation):
"""STEP_FAILURE annotation."""
ANNOTATION_NAME = "STEP_FAILURE"
class BuildStep(_NamedAnnotation):
"""BUILD_STEP annotation."""
ANNOTATION_NAME = "BUILD_STEP"
class SetBuildProperty(_NamedAnnotation):
"""SET_BUILD_PROPERTY annotation."""
ANNOTATION_NAME = "SET_BUILD_PROPERTY"
def __init__(self, name, value):
super().__init__(name, json.dumps(value))
class SetEmailNotifyProperty(_NamedAnnotation):
"""SET_BUILD_PROPERTY annotation for email_notify."""
ANNOTATION_NAME = "SET_BUILD_PROPERTY"
def __init__(self, name, value):
super().__init__(name, json.dumps(value))
def __str__(self):
inner_text = "@".join(
text for text in itertools.chain([self.name], self.args)
)
return "@@@%s@@@" % (inner_text)
def _EscapeArgText(text):
"""Escape annotation argument text.
Args:
text: String to escape.
"""
return text.replace("@", "-AT-")