| Index: commit-queue/verification/base.py
|
| ===================================================================
|
| --- commit-queue/verification/base.py (revision 249146)
|
| +++ commit-queue/verification/base.py (working copy)
|
| @@ -1,170 +0,0 @@
|
| -# coding=utf8
|
| -# Copyright (c) 2012 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.
|
| -"""Defines base classes for pending change verification classes."""
|
| -
|
| -import model
|
| -
|
| -
|
| -# Verifier state in priority level.
|
| -# SUCCEEDED : This verifier is fine to commit this patch.
|
| -# PROCESSING: No decision was made yet. The verifier runs asynchronously.
|
| -# FAILED : Verification failed, this patch must not be committed.
|
| -# IGNORED : This patch must be ignored and no comment added to the code
|
| -# review.
|
| -SUCCEEDED, PROCESSING, FAILED, IGNORED = range(4)
|
| -VALID_STATES = set((SUCCEEDED, PROCESSING, FAILED, IGNORED))
|
| -
|
| -
|
| -class DiscardPending(Exception):
|
| - """Exception to be raised when a pending item should be discarded."""
|
| -
|
| - def __init__(self, pending, status):
|
| - super(DiscardPending, self).__init__(status)
|
| - self.pending = pending
|
| - self.status = status
|
| -
|
| -
|
| -class Verified(model.PersistentMixIn):
|
| - """A set of verifications that are for a specific patch."""
|
| - verifications = dict
|
| -
|
| - def pending_name(self):
|
| - raise NotImplementedError()
|
| -
|
| - @model.immutable
|
| - def get_state(self):
|
| - """Returns the combined state of all the verifiers for this item.
|
| -
|
| - Use priority with the states: IGNORED > FAILED > PROCESSING > SUCCEEDED.
|
| - """
|
| - # If there's an error message, it failed.
|
| - if self.error_message():
|
| - return FAILED
|
| - if not self.verifications:
|
| - return PROCESSING
|
| - states = set(v.get_state() for v in self.verifications.itervalues())
|
| - assert states.issubset(VALID_STATES)
|
| - return max(states)
|
| -
|
| - @model.immutable
|
| - def postpone(self):
|
| - """This item shouldn't be committed right now.
|
| -
|
| - Call repeatedly until it returns False. This is a potentially slow call so
|
| - only call it when get_state() returns SUCEEDED.
|
| - """
|
| - return any(v.postpone() for v in self.verifications.itervalues())
|
| -
|
| - @model.immutable
|
| - def error_message(self):
|
| - """Returns all the error messages concatenated if any."""
|
| - out = (i.error_message for i in self.verifications.itervalues())
|
| - return '\n\n'.join(filter(None, out))
|
| -
|
| - def apply_patch(self, context, prepare):
|
| - """Applies a patch from the codereview tool to the checkout."""
|
| - raise NotImplementedError()
|
| -
|
| - @model.immutable
|
| - def why_not(self):
|
| - """Returns a string of all the reasons the current patch can't be
|
| - commited"""
|
| - why_nots = dict((k, v.why_not())
|
| - for k, v in self.verifications.iteritems())
|
| - return '\n'.join('%s: %s' % (k, v) for k, v in why_nots.iteritems() if v)
|
| -
|
| -
|
| -class IVerifierStatus(model.PersistentMixIn):
|
| - """Interface for objects in Verified.verifications dictionary."""
|
| - error_message = (None, unicode)
|
| -
|
| - def get_state(self):
|
| - """See Verified.get_state()."""
|
| - raise NotImplementedError()
|
| -
|
| - @model.immutable
|
| - def postpone(self): # pylint: disable=R0201
|
| - """See Verified.postpone()."""
|
| - return False
|
| -
|
| - def why_not(self):
|
| - """Returns a message why the commit cannot be committed yet.
|
| -
|
| - E.g. why get_state() == PROCESSING.
|
| - """
|
| - raise NotImplementedError()
|
| -
|
| -
|
| -class SimpleStatus(IVerifierStatus):
|
| - """Base class to be used for simple true/false and why not verifiers."""
|
| - state = int
|
| -
|
| - def __init__(self, state=PROCESSING, **kwargs):
|
| - super(SimpleStatus, self).__init__(state=state, **kwargs)
|
| -
|
| - @model.immutable
|
| - def get_state(self):
|
| - return self.state
|
| -
|
| - @model.immutable
|
| - def why_not(self):
|
| - if self.state == PROCESSING:
|
| - return 'Processing'
|
| - return
|
| -
|
| -
|
| -class Verifier(object):
|
| - """This class and its subclasses are *not* serialized."""
|
| - name = None
|
| -
|
| - def __init__(self):
|
| - assert self.name is not None
|
| -
|
| - def verify(self, pending):
|
| - """Verifies a pending change.
|
| -
|
| - Called with os.getcwd() == checkout.project_path.
|
| - """
|
| - raise NotImplementedError()
|
| -
|
| - def update_status(self, queue):
|
| - """Updates the status of all pending changes, for asynchronous checks.
|
| -
|
| - It is not necessarily called from inside checkout.project_path.
|
| - """
|
| - raise NotImplementedError()
|
| -
|
| - @model.immutable
|
| - def loop(self, queue, gen_obj, pending_only):
|
| - """Loops in a pending queue and returns the verified item corresponding to
|
| - the Verifier.
|
| - """
|
| - for pending in queue:
|
| - if self.name not in pending.verifications:
|
| - pending.verifications[self.name] = gen_obj()
|
| - if (not pending_only or
|
| - pending.verifications[self.name].get_state() == PROCESSING):
|
| - yield pending, pending.verifications[self.name]
|
| -
|
| -
|
| -class VerifierCheckout(Verifier): # pylint: disable=W0223
|
| - """A verifier that needs a rietveld and checkout objects.
|
| -
|
| - When verify() is called, it is guaranteed that the patch is applied on the
|
| - checkout.
|
| - """
|
| - def __init__(self, context_obj):
|
| - super(VerifierCheckout, self).__init__()
|
| - self.context = context_obj
|
| -
|
| - @model.immutable
|
| - def send_status(self, pending, data):
|
| - """Sends an update to the CQ dashboard.
|
| -
|
| - self.context.status is usually an instance of AsyncPush so the HTTP POST is
|
| - done in a background thread.
|
| - """
|
| - self.context.status.send(
|
| - pending, {'verification': self.name, 'payload': data})
|
|
|