WebKitTools/QueueStatusServer/model/attachment.py
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 # Copyright (C) 2009 Google Inc. All rights reserved.
       
     2 #
       
     3 # Redistribution and use in source and binary forms, with or without
       
     4 # modification, are permitted provided that the following conditions are
       
     5 # met:
       
     6 # 
       
     7 #     * Redistributions of source code must retain the above copyright
       
     8 # notice, this list of conditions and the following disclaimer.
       
     9 #     * Redistributions in binary form must reproduce the above
       
    10 # copyright notice, this list of conditions and the following disclaimer
       
    11 # in the documentation and/or other materials provided with the
       
    12 # distribution.
       
    13 #     * Neither the name of Google Inc. nor the names of its
       
    14 # contributors may be used to endorse or promote products derived from
       
    15 # this software without specific prior written permission.
       
    16 # 
       
    17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
       
    18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
       
    19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
       
    20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
       
    21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
       
    22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
       
    23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
       
    24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
       
    25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
       
    27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    28 
       
    29 import re
       
    30 
       
    31 from google.appengine.api import memcache
       
    32 
       
    33 from model.queues import queues, name_with_underscores
       
    34 from model.queuestatus import QueueStatus
       
    35 from model.workitems import WorkItems
       
    36 
       
    37 
       
    38 class Attachment(object):
       
    39     @classmethod
       
    40     def dirty(cls, attachment_id):
       
    41         memcache.delete(str(attachment_id), namespace="attachment-summary")
       
    42 
       
    43     @classmethod
       
    44     def recent(cls, limit=1):
       
    45         statuses = QueueStatus.all().order("-date")
       
    46         # Notice that we use both a set and a list here to keep the -date ordering.
       
    47         ids = []
       
    48         visited_ids = set()
       
    49         for status in statuses:
       
    50             attachment_id = status.active_patch_id
       
    51             if not attachment_id:
       
    52                 continue
       
    53             if attachment_id in visited_ids:
       
    54                 continue
       
    55             visited_ids.add(attachment_id)
       
    56             ids.append(attachment_id)
       
    57             if len(visited_ids) >= limit:
       
    58                 break
       
    59         return map(cls, ids)
       
    60 
       
    61     def __init__(self, attachment_id):
       
    62         self.id = attachment_id
       
    63         self._summary = None
       
    64         self._cached_queue_positions = None
       
    65 
       
    66     def summary(self):
       
    67         if self._summary:
       
    68             return self._summary
       
    69         self._summary = memcache.get(str(self.id), namespace="attachment-summary")
       
    70         if self._summary:
       
    71             return self._summary
       
    72         self._summary = self._fetch_summary()
       
    73         memcache.set(str(self.id), self._summary, namespace="attachment-summary")
       
    74         return self._summary
       
    75 
       
    76     def state_from_queue_status(self, status):
       
    77         table = {
       
    78             "Pass" : "pass",
       
    79             "Fail" : "fail",
       
    80         }
       
    81         state = table.get(status.message)
       
    82         if state:
       
    83             return state
       
    84         if status.message.startswith("Error:"):
       
    85             return "error"
       
    86         if status:
       
    87             return "pending"
       
    88         return None
       
    89 
       
    90     def position_in_queue(self, queue_name):
       
    91         return self._queue_positions().get(queue_name)
       
    92 
       
    93     def status_for_queue(self, queue_name):
       
    94         underscore_queue_name = name_with_underscores(queue_name)
       
    95         # summary() is a horrible API and should be killed.
       
    96         queue_summary = self.summary().get(underscore_queue_name)
       
    97         if not queue_summary:
       
    98             return None
       
    99         return queue_summary.get("status")
       
   100 
       
   101     def bug_id(self):
       
   102         return self.summary().get("bug_id")
       
   103 
       
   104     def _queue_positions(self):
       
   105         if self._cached_queue_positions:
       
   106             return self._cached_queue_positions
       
   107         # FIXME: Should we be mem-caching this?
       
   108         self._cached_queue_positions = self._calculate_queue_positions()
       
   109         return self._cached_queue_positions
       
   110 
       
   111     def _calculate_queue_positions(self):
       
   112         queue_positions = {}
       
   113         for work_items in WorkItems.all().fetch(limit=len(queues)):
       
   114             queue_name = str(work_items.queue_name)
       
   115             try:
       
   116                 position = work_items.item_ids.index(self.id)
       
   117                 # Display 1-based indecies to the user.
       
   118                 queue_positions[queue_name] = position + 1
       
   119             except ValueError, e:
       
   120                 queue_positions[queue_name] = None
       
   121         return queue_positions
       
   122 
       
   123     # FIXME: This is controller/view code and does not belong in a model.
       
   124     def _fetch_summary(self):
       
   125         summary = { "attachment_id" : self.id }
       
   126 
       
   127         first_status = QueueStatus.all().filter('active_patch_id =', self.id).get()
       
   128         if not first_status:
       
   129             # We don't have any record of this attachment.
       
   130             return summary
       
   131         summary["bug_id"] = first_status.active_bug_id
       
   132 
       
   133         for queue in queues:
       
   134             summary[queue] = None
       
   135             status = QueueStatus.all().filter('queue_name =', queue).filter('active_patch_id =', self.id).order('-date').get()
       
   136             if status:
       
   137                 summary[name_with_underscores(queue)] = {
       
   138                     "state": self.state_from_queue_status(status),
       
   139                     "status": status,
       
   140                 }
       
   141         return summary