blob: 079f5ab7162704496f6f3c7f7b5daf980b7e7625 [file] [log] [blame]
# -*- coding: utf-8 -*-
# Copyright 2016 The Chromium OS Authors. All rights reserved.
# 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."""
from __future__ import print_function
import abc
import itertools
import json
import six
class Annotation(object):
"""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
@six.add_metaclass(abc.ABCMeta)
class _NamedAnnotation(Annotation):
"""Abstract subclass for creating named annotations.
Concrete subclasses should define the ANNOTATION_NAME class attribute.
"""
def __init__(self, *args):
super(_NamedAnnotation, self).__init__(self.ANNOTATION_NAME, args)
@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(StepLink, self).__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(SetBuildProperty, self).__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(SetEmailNotifyProperty, self).__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-')