"""
import datetime
import json
+import logging
import os
import re
import shlex
import sys
# TODO: Haven't tested python 3
-if sys.version < '3':
+if sys.version < "3":
import urllib
import urlparse
do_input = input
+logger = logging.getLogger("changes.gerritquery")
+
+
class GitReviewException(Exception):
EXIT_CODE = 127
def __init__(self, *args):
Exception.__init__(self, *args)
(self.rc, self.output, self.argv, self.envp) = args
- self.quickmsg = dict([
- ("argv", " ".join(self.argv)),
- ("rc", self.rc),
- ("output", self.output)])
+ self.quickmsg = dict(
+ [("argv", " ".join(self.argv)), ("rc", self.rc), ("output", self.output)]
+ )
def __str__(self):
- return self.__doc__ + """
+ return (
+ self.__doc__
+ + """
The following command failed with exit code %(rc)d
"%(argv)s"
-----------------------
%(output)s
------------------------""" % self.quickmsg
+-----------------------"""
+ % self.quickmsg
+ )
class GerritQuery:
- REMOTE_URL = 'ssh://git.opendaylight.org:29418'
- BRANCH = 'master'
+ REMOTE_URL = "ssh://git.opendaylight.org:29418"
+ BRANCH = "master"
QUERY_LIMIT = 50
remote_url = REMOTE_URL
branch = BRANCH
query_limit = QUERY_LIMIT
- verbose = 0
def __init__(self, remote_url, branch, query_limit, verbose):
self.remote_url = remote_url
self.query_limit = query_limit
self.verbose = verbose
- def set_verbose(self, verbose):
- self.verbose = verbose
-
@staticmethod
def print_safe_encoding(string):
- if sys.stdout.encoding is None:
- # just print(string) could still throw a UnicodeEncodeError sometimes so casting string to unicode
- print(unicode(string))
- else:
- print(string.encode(sys.stdout.encoding, 'replace'))
+ try:
+ # FIXME: Python3 does not have 'unicode'
+ if isinstance(string, unicode):
+ encoding = "utf-8"
+ if hasattr(sys.stdout, "encoding") and sys.stdout.encoding:
+ encoding = sys.stdout.encoding
+ return string.encode(encoding or "utf-8", "replace")
+ else:
+ return str(string)
+ except Exception:
+ return str(string)
def run_command_status(self, *argv, **kwargs):
-
- if self.verbose >= 2:
- print(datetime.datetime.now(), "Running:", " ".join(argv))
+ logger.debug("%s Running: %s", datetime.datetime.now(), " ".join(argv))
if len(argv) == 1:
# for python2 compatibility with shlex
if sys.version_info < (3,) and isinstance(argv[0], unicode):
- argv = shlex.split(argv[0].encode('utf-8'))
+ argv = shlex.split(argv[0].encode("utf-8"))
else:
argv = shlex.split(str(argv[0]))
- stdin = kwargs.pop('stdin', None)
+ stdin = kwargs.pop("stdin", None)
newenv = os.environ.copy()
- newenv['LANG'] = 'C'
- newenv['LANGUAGE'] = 'C'
+ newenv["LANG"] = "C"
+ newenv["LANGUAGE"] = "C"
newenv.update(kwargs)
- p = subprocess.Popen(argv,
- stdin=subprocess.PIPE if stdin else None,
- stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT,
- env=newenv)
+ p = subprocess.Popen(
+ argv,
+ stdin=subprocess.PIPE if stdin else None,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ env=newenv,
+ )
(out, nothing) = p.communicate(stdin)
- out = out.decode('utf-8', 'replace')
+ out = out.decode("utf-8", "replace")
return p.returncode, out.strip()
def run_command(self, *argv, **kwargs):
:param str request: A gerrit query
:return unicode: The JSON response
"""
- (hostname, username, port, project_name) = \
- self.parse_gerrit_ssh_params_from_git_url()
+ (
+ hostname,
+ username,
+ port,
+ project_name,
+ ) = self.parse_gerrit_ssh_params_from_git_url()
port_data = "p%s" % port if port is not None else ""
if username is None:
else:
userhost = "%s@%s" % (username, hostname)
- if self.verbose >= 2:
- print("gerrit request %s %s" % (self.remote_url, request))
+ logger.debug("gerrit request %s %s" % (self.remote_url, request))
output = self.run_command_exc(
- CommandFailed,
- "ssh", "-x" + port_data, userhost,
- request)
- if self.verbose >= 3:
- self.print_safe_encoding(output)
+ CommandFailed, "ssh", "-x" + port_data, userhost, request
+ )
+ if logger.isEnabledFor(logging.DEBUG):
+ logger.debug("%s", self.print_safe_encoding(output))
return output
- def make_gerrit_query(self, project, changeid=None, limit=1, msg=None, status=None, comments=False):
+ def make_gerrit_query(
+ self,
+ project,
+ changeid=None,
+ limit=1,
+ msg=None,
+ status=None,
+ comments=False,
+ commitid=None,
+ ):
"""
Make a gerrit query by combining the given options.
:param str msg or None: A commit-msg to search
:param str status or None: The gerrit status, i.e. merged
:param bool comments: If true include comments
+ :param commitid: A commit hash to search
:return str: A gerrit query
"""
- query = "gerrit query --format=json limit:%d " \
- "project:%s branch:%s" \
- % (limit, project, self.branch)
+
+ if project == "odlparent" or project == "yangtools":
+ query = "gerrit query --format=json limit:%d " "project:%s" % (
+ limit,
+ project,
+ )
+ else:
+ query = "gerrit query --format=json limit:%d " "project:%s branch:%s" % (
+ limit,
+ project,
+ self.branch,
+ )
if changeid:
query += " change:%s" % changeid
if msg:
- query += " message:%s" % msg
+ query += " message:{%s}" % msg
+ if commitid:
+ query += " commit:%s" % commitid
if status:
query += " status:%s --all-approvals" % status
if comments:
if line and line[0] == "{":
try:
data = json.loads(line)
- parsed['id'] = data['id']
- parsed['number'] = data['number']
- parsed['subject'] = data['subject']
- parsed['url'] = data['url']
- parsed['lastUpdated'] = data['lastUpdated']
- parsed['grantedOn'] = 0
+ parsed["id"] = data["id"]
+ parsed["number"] = data["number"]
+ parsed["subject"] = data["subject"]
+ parsed["url"] = data["url"]
+ parsed["lastUpdated"] = data["lastUpdated"]
+ parsed["grantedOn"] = 0
if "patchSets" in data:
- patch_sets = data['patchSets']
+ patch_sets = data["patchSets"]
for patch_set in reversed(patch_sets):
if "approvals" in patch_set:
- approvals = patch_set['approvals']
+ approvals = patch_set["approvals"]
for approval in approvals:
- if 'type' in approval and approval['type'] == 'SUBM':
- parsed['grantedOn'] = approval['grantedOn']
+ if (
+ "type" in approval
+ and approval["type"] == "SUBM"
+ ):
+ parsed["grantedOn"] = approval["grantedOn"]
break
- if parsed['grantedOn'] != 0:
+ if parsed["grantedOn"] != 0:
break
if "comments" in data:
- comments = data['comments']
+ comments = data["comments"]
for comment in reversed(comments):
if "message" in comment and "timestamp" in comment:
- message = comment['message']
- timestamp = comment['timestamp']
- if "Build Started" in message and "patch-test" in message:
- parsed['grantedOn'] = timestamp
+ message = comment["message"]
+ timestamp = comment["timestamp"]
+ if (
+ "Build Started" in message
+ and "patch-test" in message
+ ):
+ parsed["grantedOn"] = timestamp
break
except Exception:
- if self.verbose:
- print("Failed to decode JSON: %s" % traceback.format_exc())
- self.print_safe_encoding(line)
+ logger.warn("Failed to decode JSON: %s", traceback.format_exc())
+ if logger.isEnabledFor(logging.DEBUG):
+ logger.warn(self.print_safe_encoding(line))
except Exception as err:
- print("Exception: %s" % traceback.format_exc())
+ logger.warn("Exception: %s", traceback.format_exc())
raise parse_exc(err)
return parsed
:return list: Lines of the JSON
"""
lines = []
- for line in changes.split("\n"):
- if line.find('"type":"error","message"') != -1:
- print("there was a query error")
- continue
- if line.find('stats') == -1:
+ skipped = 0
+ for i, line in enumerate(changes.split("\n")):
+ if line.find('"grantedOn":') != -1:
lines.append(line)
- if self.verbose >= 2:
- print("get_gerrit_lines: found %d lines" % len(lines))
+ else:
+ logger.debug("skipping: {}".format(line))
+ skipped += 1
+ logger.debug(
+ "get_gerrit_lines: found {} lines, skipped: {}".format(len(lines), skipped)
+ )
return lines
- def get_gerrits(self, project, changeid=None, limit=1, msg=None, status=None, comments=False):
+ def get_gerrits(
+ self,
+ project,
+ changeid=None,
+ limit=1,
+ msg=None,
+ status=None,
+ comments=False,
+ commitid=None,
+ ):
"""
Get a list of gerrits from gerrit query request.
:param str or None msg: A commit-msg to search
:param str or None status: The gerrit status, i.e. merged
:param bool comments: If true include comments
+ :param commitid: A commit hash to search
:return str: List of gerrits sorted by merge time
"""
- query = self.make_gerrit_query(project, changeid, limit, msg, status, comments)
+ logger.debug(
+ "get_gerrits: project: %s, changeid: %s, limit: %d, msg: %s, status: %s, comments: %s, "
+ + "commitid: %s",
+ project,
+ changeid,
+ limit,
+ msg,
+ status,
+ comments,
+ commitid,
+ )
+ query = self.make_gerrit_query(
+ project, changeid, limit, msg, status, comments, commitid
+ )
changes = self.gerrit_request(query)
lines = self.extract_lines_from_json(changes)
gerrits = []
+ sorted_gerrits = []
for line in lines:
gerrits.append(self.parse_gerrit(line))
from operator import itemgetter
- sorted_gerrits = sorted(gerrits, key=itemgetter('grantedOn'), reverse=True)
+
+ if gerrits is None:
+ logger.warn("No gerrits were found for %s", project)
+ return gerrits
+ try:
+ sorted_gerrits = sorted(gerrits, key=itemgetter("grantedOn"), reverse=True)
+ except KeyError as e:
+ logger.warn("KeyError exception in %s, %s", project, str(e))
return sorted_gerrits