Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Unified Diff: third_party/recipe_engine/third_party/annotator.py

Issue 1241323004: Cross-repo recipe package system. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Roll to latest recipes-py Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/recipe_engine/third_party/annotator.py
diff --git a/third_party/recipe_engine/third_party/annotator.py b/third_party/recipe_engine/third_party/annotator.py
deleted file mode 100644
index 8fcb5ebc02ba7e2aa3554c2c54cafb7ae9155f85..0000000000000000000000000000000000000000
--- a/third_party/recipe_engine/third_party/annotator.py
+++ /dev/null
@@ -1,348 +0,0 @@
-# Copyright (c) 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Contains the parsing system of the Chromium Buildbot Annotator."""
-
-import os
-import sys
-import traceback
-
-# These are maps of annotation key -> number of expected arguments.
-STEP_ANNOTATIONS = {
- 'SET_BUILD_PROPERTY': 2,
- 'STEP_CLEAR': 0,
- 'STEP_EXCEPTION': 0,
- 'STEP_FAILURE': 0,
- 'STEP_LINK': 2,
- 'STEP_LOG_END': 1,
- 'STEP_LOG_END_PERF': 2,
- 'STEP_LOG_LINE': 2,
- 'STEP_SUMMARY_CLEAR': 0,
- 'STEP_SUMMARY_TEXT': 1,
- 'STEP_TEXT': 1,
- 'STEP_TRIGGER': 1,
- 'STEP_WARNINGS': 0,
- 'STEP_NEST_LEVEL': 1,
-}
-
-CONTROL_ANNOTATIONS = {
- 'STEP_CLOSED': 0,
- 'STEP_STARTED': 0,
-}
-
-STREAM_ANNOTATIONS = {
- 'HALT_ON_FAILURE': 0,
- 'HONOR_ZERO_RETURN_CODE': 0,
- 'SEED_STEP': 1,
- 'SEED_STEP_TEXT': 2,
- 'STEP_CURSOR': 1,
-}
-
-DEPRECATED_ANNOTATIONS = {
- 'BUILD_STEP': 1,
-}
-
-ALL_ANNOTATIONS = {}
-ALL_ANNOTATIONS.update(STEP_ANNOTATIONS)
-ALL_ANNOTATIONS.update(CONTROL_ANNOTATIONS)
-ALL_ANNOTATIONS.update(STREAM_ANNOTATIONS)
-ALL_ANNOTATIONS.update(DEPRECATED_ANNOTATIONS)
-
-# This is a mapping of old_annotation_name -> new_annotation_name.
-# Theoretically all annotator scripts should use the new names, but it's hard
-# to tell due to the decentralized nature of the annotator.
-DEPRECATED_ALIASES = {
- 'BUILD_FAILED': 'STEP_FAILURE',
- 'BUILD_WARNINGS': 'STEP_WARNINGS',
- 'BUILD_EXCEPTION': 'STEP_EXCEPTION',
- 'link': 'STEP_LINK',
-}
-
-# A couple of the annotations have the format:
-# @@@THING arg@@@
-# for reasons no one knows. We only need this case until all masters have been
-# restarted to pick up the new master-side parsing code.
-OLD_STYLE_ANNOTATIONS = set((
- 'SEED_STEP',
- 'STEP_CURSOR',
-))
-
-
-def emit(line, stream, flush_before=None):
- if flush_before:
- flush_before.flush()
- print >> stream
- # WinDOS can only handle 64kb of output to the console at a time, per process.
- if sys.platform.startswith('win'):
- lim = 2**15
- while line:
- to_print, line = line[:lim], line[lim:]
- stream.write(to_print)
- stream.write('\n')
- else:
- print >> stream, line
- stream.flush()
-
-
-class MetaAnnotationPrinter(type):
- def __new__(mcs, name, bases, dct):
- annotation_map = dct.get('ANNOTATIONS')
- if annotation_map:
- for key, v in annotation_map.iteritems():
- key = key.lower()
- dct[key] = mcs.make_printer_fn(key, v)
- return type.__new__(mcs, name, bases, dct)
-
- @staticmethod
- def make_printer_fn(name, n_args):
- """Generates a method which emits an annotation to the log stream."""
- upname = name.upper()
- if upname in OLD_STYLE_ANNOTATIONS:
- assert n_args >= 1
- fmt = '@@@%s %%s%s@@@' % (upname, '@%s' * (n_args - 1))
- else:
- fmt = '@@@%s%s@@@' % (upname, '@%s' * n_args)
-
- inner_args = n_args + 1 # self counts
- infix = '1 argument' if inner_args == 1 else ('%d arguments' % inner_args)
- err = '%s() takes %s (%%d given)' % (name, infix)
-
- def printer(self, *args):
- if len(args) != n_args:
- raise TypeError(err % (len(args) + 1))
- self.emit(fmt % args)
- printer.__name__ = name
- printer.__doc__ = """Emits an annotation for %s.""" % name.upper()
-
- return printer
-
-
-class AnnotationPrinter(object):
- """A derivable class which will inject annotation-printing methods into the
- subclass.
-
- A subclass should define a class variable ANNOTATIONS equal to a
- dictionary of the form { '<ANNOTATION_NAME>': <# args> }. This class will
- then inject methods whose names are the undercased version of your
- annotation names, and which take the number of arguments specified in the
- dictionary.
-
- Example:
- >>> my_annotations = { 'STEP_LOG_LINE': 2 }
- >>> class MyObj(AnnotationPrinter):
- ... ANNOTATIONS = my_annotations
- ...
- >>> o = MyObj()
- >>> o.step_log_line('logname', 'here is a line to put in the log')
- @@@STEP_LOG_LINE@logname@here is a line to put in the log@@@
- >>> o.step_log_line()
- Traceback (most recent call last):
- File "<stdin>", line 1, in <module>
- TypeError: step_log_line() takes exactly 3 arguments (1 given)
- >>> o.setp_log_line.__doc__
- "Emits an annotation for STEP_LOG_LINE."
- >>>
- """
- __metaclass__ = MetaAnnotationPrinter
-
- def __init__(self, stream, flush_before):
- self.stream = stream
- self.flush_before = flush_before
-
- def emit(self, line):
- emit(line, self.stream, self.flush_before)
-
-
-class StepCommands(AnnotationPrinter):
- """Class holding step commands. Intended to be subclassed."""
- ANNOTATIONS = STEP_ANNOTATIONS
-
- def __init__(self, stream, flush_before):
- super(StepCommands, self).__init__(stream, flush_before)
- self.emitted_logs = set()
-
- def write_log_lines(self, logname, lines, perf=None):
- if logname in self.emitted_logs:
- raise ValueError('Log %s has been emitted multiple times.' % logname)
- self.emitted_logs.add(logname)
-
- logname = logname.replace('/', '&#x2f;')
-
- for line in lines:
- for actual_line in line.split('\n'):
- self.step_log_line(logname, actual_line)
-
- if perf:
- self.step_log_end_perf(logname, perf)
- else:
- self.step_log_end(logname)
-
-
-class StepControlCommands(AnnotationPrinter):
- """Subclass holding step control commands. Intended to be subclassed.
-
- This is subclassed out so callers in StructuredAnnotationStep can't call
- step_started() or step_closed().
- """
- ANNOTATIONS = CONTROL_ANNOTATIONS
-
-
-class StructuredAnnotationStep(StepCommands, StepControlCommands):
- """Helper class to provide context for a step."""
-
- def __init__(self, annotation_stream, *args, **kwargs):
- self.annotation_stream = annotation_stream
- super(StructuredAnnotationStep, self).__init__(*args, **kwargs)
- self.control = StepControlCommands(self.stream, self.flush_before)
- self.emitted_logs = set()
-
-
- def __enter__(self):
- return self.step_started()
-
- def step_started(self):
- self.control.step_started()
- return self
-
- def __exit__(self, exc_type, exc_value, tb):
- self.annotation_stream.step_cursor(self.annotation_stream.current_step)
- #TODO(martinis) combine this and step_ended
- if exc_type:
- self.step_exception_occured(exc_type, exc_value, tb)
-
- self.control.step_closed()
- self.annotation_stream.current_step = ''
- return not exc_type
-
- def step_exception_occured(self, exc_type, exc_value, tb):
- trace = traceback.format_exception(exc_type, exc_value, tb)
- trace_lines = ''.join(trace).split('\n')
- self.write_log_lines('exception', filter(None, trace_lines))
- self.step_exception()
-
- def step_ended(self):
- self.annotation_stream.step_cursor(self.annotation_stream.current_step)
- self.control.step_closed()
- self.annotation_stream.current_step = ''
-
- return True
-
-
-class StructuredAnnotationStream(AnnotationPrinter):
- """Provides an interface to handle an annotated build.
-
- StructuredAnnotationStream handles most of the step setup and closure calls
- for you. All you have to do is execute your code within the steps and set any
- failures or warnings that come up. You may optionally provide a list of steps
- to seed before execution.
-
- Usage:
-
- stream = StructuredAnnotationStream()
- with stream.step('compile') as s:
- # do something
- if error:
- s.step_failure()
- with stream.step('test') as s:
- # do something
- if warnings:
- s.step_warnings()
- """
- ANNOTATIONS = STREAM_ANNOTATIONS
-
- def __init__(self, stream=sys.stdout,
- flush_before=sys.stderr,
- seed_steps=None): # pylint: disable=W0613
- super(StructuredAnnotationStream, self).__init__(stream=stream,
- flush_before=flush_before)
- self.current_step = ''
-
- def step(self, name):
- """Provide a context with which to execute a step."""
- if self.current_step:
- raise Exception('Can\'t start step %s while in step %s.' % (
- name, self.current_step))
-
- self.seed_step(name)
- self.step_cursor(name)
- self.current_step = name
- return StructuredAnnotationStep(self, stream=self.stream,
- flush_before=self.flush_before)
-
-
-def MatchAnnotation(line, callback_implementor):
- """Call back into |callback_implementor| if line contains an annotation.
-
- Args:
- line (str) - The line to analyze
- callback_implementor (object) - An object which contains methods
- corresponding to all of the annotations in the |ALL_ANNOTATIONS|
- dictionary. For example, it should contain a method STEP_SUMMARY_TEXT
- taking a single argument.
-
- Parsing method:
- * if line doesn't match /^@@@.*@@@$/, return without calling back
- * Look for the first '@' or ' '
- """
- if not (line.startswith('@@@') and line.endswith('@@@') and len(line) > 6):
- return
- line = line[3:-3]
-
- # look until the first @ or ' '
- idx = min((x for x in (line.find('@'), line.find(' '), len(line)) if x > 0))
- cmd_text = line[:idx]
- cmd = DEPRECATED_ALIASES.get(cmd_text, cmd_text)
-
- field_count = ALL_ANNOTATIONS.get(cmd)
- if field_count is None:
- raise Exception('Unrecognized annotator command "%s"' % cmd_text)
-
- if field_count:
- if idx == len(line):
- raise Exception('Annotator command "%s" expects %d args, got 0.'
- % (cmd_text, field_count))
-
- line = line[idx+1:]
-
- args = line.split('@', field_count-1)
- if len(args) != field_count:
- raise Exception('Annotator command "%s" expects %d args, got %d.'
- % (cmd_text, field_count, len(args)))
- else:
- line = line[len(cmd_text):]
- if line:
- raise Exception('Annotator command "%s" expects no args, got cruft "%s".'
- % (cmd_text, line))
- args = []
-
- fn = getattr(callback_implementor, cmd, None)
- if fn is None:
- raise Exception('"%s" does not implement "%s"'
- % (callback_implementor, cmd))
-
- fn(*args)
-
-
-def print_step(step, env, stream):
- """Prints the step command and relevant metadata.
-
- Intended to be similar to the information that Buildbot prints at the
- beginning of each non-annotator step.
- """
- step_info_lines = []
- step_info_lines.append(' '.join(step['cmd']))
- step_info_lines.append('in dir %s:' % (step['cwd'] or os.getcwd()))
- for key, value in sorted(step.items()):
- if value is not None:
- if callable(value):
- # This prevents functions from showing up as:
- # '<function foo at 0x7f523ec7a410>'
- # which is tricky to test.
- value = value.__name__+'(...)'
- step_info_lines.append(' %s: %s' % (key, value))
- step_info_lines.append('full environment:')
- for key, value in sorted(env.items()):
- step_info_lines.append(' %s: %s' % (key, value))
- step_info_lines.append('')
- stream.emit('\n'.join(step_info_lines))
« no previous file with comments | « third_party/recipe_engine/third_party/__init__.py ('k') | third_party/recipe_engine/unittests/field_composer_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698