Added new record type for patches

Implements bp metric-patchset

Change-Id: Ia63c5aa8b3c02d978b223b6193b7bce60a6caafd
This commit is contained in:
Ilya Shakhat 2014-04-16 13:00:51 +04:00
parent a18739e415
commit 1481d548bc
5 changed files with 82 additions and 55 deletions

View File

@ -52,6 +52,13 @@ def _extend_record_common_fields(record):
_extend_author_fields(coauthor)
def _extend_by_parent_info(record, parent):
parent = parent.copy()
_extend_record_common_fields(parent)
for k, v in six.iteritems(parent):
record['parent_' + k] = v
def extend_record(record):
record = record.copy()
_extend_record_common_fields(record)
@ -69,14 +76,11 @@ def extend_record(record):
if not parent:
return None
parent = parent.copy()
_extend_record_common_fields(parent)
for k, v in six.iteritems(parent):
record['parent_%s' % k] = v
record['review_number'] = parent.get('review_number')
record['subject'] = parent['subject']
record['url'] = parent['url']
_extend_by_parent_info(record, parent)
elif record['record_type'] == 'patch':
parent = vault.get_memory_storage().get_record_by_primary_key(
record['review_id'])
_extend_by_parent_info(record, parent)
elif record['record_type'] == 'email':
record['email_link'] = record.get('email_link') or ''
record['blueprint_links'] = []

View File

@ -91,14 +91,17 @@ show_record_type=True, show_user_gravatar=True, gravatar_size=32, show_all=True)
<div><span style="color: green">+<span>${lines_added}</span></span>
<span style="color: blue">- <span>${lines_deleted}</span></span></div>
{%elif record_type == "mark" %}
<div class="header">Review &ldquo;${subject}&rdquo;</div>
<div>Submitted by: {%html parent_author_link %} ({%html parent_company_link %}) (#${review_number})</div>
<div>Change Id: <a href="${url}">${review_id}</a></div>
<div class="header">Review &ldquo;${parent_subject}&rdquo;</div>
<div>Submitted by: {%html parent_author_link %} ({%html parent_company_link %}) (#${parent_review_number})</div>
<div>Change Id: <a href="${parent_url}">${review_id}</a></div>
<div style="color: {%if value > 0 %} green {%else%} blue {%/if%}">${description}: <span class="review_mark">${value}</span></div>
{%elif record_type == "review" %}
<div class="header">Patch &ldquo;${subject}&rdquo;</div>
<div class="header">New change request &ldquo;${subject}&rdquo;</div>
<div>Current Status: ${status}</div>
<div>Change Id: <a href="${url}">${id}</a></div>
{%elif record_type == "patch" %}
<div class="header">Patch #${number} &ldquo;${parent_subject}&rdquo;</div>
<div>Change Id: <a href="${parent_url}">${review_id}</a></div>
{%elif record_type == "email" %}
<div class="header">
{%if email_link != "" %}

View File

@ -256,13 +256,11 @@ class RecordProcessor(object):
yield new_record
def _spawn_review(self, record):
def _make_review_record(self, record):
# copy everything except patchsets and flatten user data
review = dict([(k, v) for k, v in six.iteritems(record)
if k not in ['patchSets', 'owner', 'createdOn']])
owner = record['owner']
if 'email' not in owner or 'username' not in owner:
return # ignore
review['primary_key'] = review['id']
review['launchpad_id'] = owner['username']
@ -286,56 +284,74 @@ class RecordProcessor(object):
review['value'] = 0
self._update_record_and_user(review)
return review
yield review
def _make_patch_record(self, review, patch):
patch_record = dict()
patch_record['record_type'] = 'patch'
patch_record['primary_key'] = utils.get_patch_id(
review['id'], patch['number'])
patch_record['number'] = patch['number']
patch_record['date'] = patch['createdOn']
uploader = patch['uploader']
patch_record['launchpad_id'] = uploader['username']
patch_record['author_name'] = uploader['name']
patch_record['author_email'] = uploader['email'].lower()
patch_record['module'] = review['module']
patch_record['branch'] = review['branch']
patch_record['review_id'] = review['id']
def _spawn_marks(self, record):
review_id = record['id']
module = record['module']
branch = record['branch']
self._update_record_and_user(patch_record)
return patch_record
for patch in record.get('patchSets', []):
if 'approvals' not in patch:
continue # not reviewed by anyone
for approval in patch['approvals']:
if approval['type'] not in ('CRVW', 'APRV'):
continue # keep only Code-Review and Approved
def _make_mark_record(self, review, patch, approval):
# copy everything and flatten user data
mark = dict([(k, v) for k, v in six.iteritems(approval)
if k not in ['by', 'grantedOn', 'value']])
reviewer = approval['by']
# copy everything and flatten user data
mark = dict([(k, v) for k, v in six.iteritems(approval)
if k not in ['by', 'grantedOn', 'value']])
reviewer = approval['by']
mark['record_type'] = 'mark'
mark['value'] = int(approval['value'])
mark['date'] = approval['grantedOn']
mark['primary_key'] = (review['id'] + str(mark['date']) + mark['type'])
mark['launchpad_id'] = reviewer['username']
mark['author_name'] = reviewer['name']
mark['author_email'] = reviewer['email'].lower()
mark['module'] = review['module']
mark['branch'] = review['branch']
mark['review_id'] = review['id']
mark['patch'] = int(patch['number'])
if 'email' not in reviewer or 'username' not in reviewer:
continue # ignore
mark['record_type'] = 'mark'
mark['value'] = int(approval['value'])
mark['date'] = approval['grantedOn']
mark['primary_key'] = (record['id'] +
str(mark['date']) +
mark['type'])
mark['launchpad_id'] = reviewer['username']
mark['author_name'] = reviewer['name']
mark['author_email'] = reviewer['email'].lower()
mark['module'] = module
mark['branch'] = branch
mark['review_id'] = review_id
mark['patch'] = int(patch['number'])
self._update_record_and_user(mark)
yield mark
self._update_record_and_user(mark)
return mark
def _process_review(self, record):
"""
Process a review. Review spawns into records of two types:
Process a review. Review spawns into records of three types:
* review - records that a user created review request
* patch - records that a user submitted another patch set
* mark - records that a user set approval mark to given review
"""
for gen in [self._spawn_review, self._spawn_marks]:
for r in gen(record):
yield r
owner = record['owner']
if 'email' not in owner or 'username' not in owner:
return # ignore
yield self._make_review_record(record)
for patch in record.get('patchSets', []):
yield self._make_patch_record(record, patch)
if 'approvals' not in patch:
continue # not reviewed by anyone
for approval in patch['approvals']:
if approval['type'] not in ('CRVW', 'APRV'):
continue # keep only Code-Review and Approved
if ('email' not in approval['by'] or
'username' not in approval['by']):
continue # ignore
yield self._make_mark_record(record, patch, approval)
def _guess_module(self, record):
subject = record['subject'].lower()

View File

@ -165,6 +165,10 @@ def get_blueprint_id(module, name):
return module + ':' + name
def get_patch_id(review_id, patch_number):
return review_id + ':' + patch_number
def add_index(sequence, start=1, item_filter=lambda x: True):
n = start
for item in sequence:

View File

@ -776,7 +776,7 @@ class TestRecordProcessor(testtools.TestCase):
'emails': ['john_doe@ibm.com'],
'core': [('nova', 'master')],
'companies': [{'company_name': 'IBM', 'end_date': 0}]}
user_2 = {'seq': 2, 'user_id': 'homer',
user_2 = {'seq': 3, 'user_id': 'homer',
'launchpad_id': 'homer', 'user_name': 'Homer Simpson',
'emails': ['hsimpson@gmail.com'],
'core': [],