Documented module functions.

Change-Id: I1d05337ca1296b3ea21533ba6ea9ea7c2c4e83b3
This commit is contained in:
Romain Chantereau 2014-03-25 16:37:41 +01:00
parent ceb72af13a
commit 5713bd9df5
1 changed files with 84 additions and 13 deletions

View File

@ -1,4 +1,4 @@
#
## -*- coding: utf-8 -*-
# Copyright (C) 2011 - Soren Hansen
# Copyright (C) 2013 - Red Hat, Inc.
#
@ -14,6 +14,8 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""Utility functions module
"""
import glob
import json
@ -30,6 +32,28 @@ LOG = logging.getLogger(__name__)
def get_projects_info(project=None, all_projects=False, base_dir='./projects'):
"""Return the list of project dict objects.
:param project: pathname of the JSON project info file.
:type project: str or None
:param bool all_projects:
If True deserialize all the .json files of officials projects in
base_dir.
:param str base_dir:
dirname of the path containing the json projects files.
:return: unserialized json of project info.
:rtype: dict
project or all_projects=True must be given.
.. note::
Unofficial projects are filtered out if all_projects is True.
Official qualification is a key of the json file name unofficial, if
present and true, its an unofficial project.
.. note::
all_projects parameters overrides project parameter value if True
"""
if all_projects:
files = glob.glob('%s/*.json' % base_dir)
else:
@ -52,6 +76,18 @@ def get_projects_info(project=None, all_projects=False, base_dir='./projects'):
def projects_q(project):
"""Return the gerrit query selecting all the project in the given list
:param project: List of gerrit project name.
:type project: list of str
:return:
gerrit query according to `Searching Changes`_ section of gerrit
documentation.
:rtype: str
.. _Searching Changes:
https://review.openstack.org/Documentation/user-search.html
"""
return ('(' +
' OR '.join(['project:' + p for p in project['subprojects']]) +
')')
@ -59,6 +95,30 @@ def projects_q(project):
def get_changes(projects, ssh_user, ssh_key, only_open=False, stable='',
server='review.openstack.org'):
"""Get the changesets data list.
:param projects: List of gerrit project names.
:type projects: list of str
:param str ssh_user: Gerrit username.
:param str ssh_key: Filename of one SSH key registered at gerrit.
:param bool only_open: If True, get only the not closed reviews.
:param str stable:
Name of the stable branch. If empty string, the changesets are not
filtered by any branch.
:return: List of de-serialized JSON changeset data as returned by gerrit.
:rtype: list
.. note::
If all the issue are requested whatever the branch is, a cache system
override the gerrit request.
Requesting only the open changes isn't nearly as big of a deal,
so just get the current data.
Also do not use cache for stable stats as they cover different
results.
Cached results are pickled per project in the following filenames:
.{projectname}-changes.pickle.
"""
all_changes = []
client = paramiko.SSHClient()
@ -71,10 +131,6 @@ def get_changes(projects, ssh_user, ssh_key, only_open=False, stable='',
if not only_open and not stable:
# Only use the cache for *all* changes (the entire history).
# Requesting only the open changes isn't nearly as big of a deal,
# so just get the current data.
# Also do not use cache for stable stats as they cover different
# results.
pickle_fn = '.%s-changes.pickle' % project['name']
if os.path.isfile(pickle_fn):
@ -132,6 +188,13 @@ def get_changes(projects, ssh_user, ssh_key, only_open=False, stable='',
def patch_set_approved(patch_set):
"""Return True if the patchset has been approved.
:param dict patch_set: De-serialized dict of a gerrit change
:return: True if one of the patchset reviews approved it.
:rtype: bool
"""
approvals = patch_set.get('approvals', [])
for review in approvals:
if review['type'] == 'APRV':
@ -140,16 +203,24 @@ def patch_set_approved(patch_set):
def get_age_of_patch(patch, now_ts):
"""Compute the number of seconds since the patch submission and now.
:param dict patch: Deserialized JSON of a Gerrit patchset
:param int now_ts: Unix-like timestamp in seconds since EPOCH.
:return int: number of seconds between patch submission and now_ts
.. note::
The createdOn timestamp on the patch isn't what we want.
It's when the patch was written, not submitted for review.
The next best thing in the data we have is the time of the
first review. When all is working well, jenkins or smokestack
will comment within the first hour or two, so that's better
than the other timestamp, which may reflect that the code
was written many weeks ago, even though it was just recently
submitted for review.
"""
approvals = patch.get('approvals', [])
approvals.sort(key=lambda a: a['grantedOn'])
# The createdOn timestamp on the patch isn't what we want.
# It's when the patch was written, not submitted for review.
# The next best thing in the data we have is the time of the
# first review. When all is working well, jenkins or smokestack
# will comment within the first hour or two, so that's better
# than the other timestamp, which may reflect that the code
# was written many weeks ago, even though it was just recently
# submitted for review.
if approvals:
return now_ts - approvals[0]['grantedOn']
else: