Skip to content

Instantly share code, notes, and snippets.

@mcepl
Created April 28, 2015 07:27
Show Gist options
  • Save mcepl/760e9640dfd2a44499f8 to your computer and use it in GitHub Desktop.
Save mcepl/760e9640dfd2a44499f8 to your computer and use it in GitHub Desktop.
#!/usr/bin/python
import re
import logging
import sys
import email
import time
from collections import OrderedDict as odict
logging.basicConfig(format='%(levelname)s:%(funcName)s:%(message)s',
level=logging.INFO)
BUG_PATTERN = re.compile(r"\s*Bug\s+\d{3,7}:\s*$", re.UNICODE)
HEADING_PATTERN = re.compile(r"\s*(.*?\S)\s*(\(\d* bugs\))?\s*$",
re.UNICODE)
DATE_FORMAT_STRING = "%Y-%m-%d"
CSVPrint = True
SEPARATOR = ","
SKIP_OVER_HEADER = 5
TranslateNamesPairs = odict([
("all Gecko bugs", "Gecko"),
("NEW Gecko bugs", "Gecko NEW"),
("ASSIGNED Gecko bugs", "Gecko AS"),
("all gecko-maint bugs", "gecko-maint"),
("NEW gecko-maint bugs", "gecko-maint NEW"),
("ASSIGNED gecko-maint bugs", "gecko-maint AS"),
("all Xorg bugs", "X"),
("NEW Xorg bugs", "X NEW"),
("ASIGNED Xorg bugs", "X AS"),
("all xgl-maint bugs", "xgl-maint"),
("NEW xgl-maint bugs", "xgl-maint NEW"),
("ASSIGNED xgl-maint bugs", "xgl-maint AS"),
("all OpenOffice.org bugs", "OOo"),
("NEW OpenOffice.org bugs", "OOo NEW"),
("ASSIGNED OpenOffice.org bugs", "OOo AS"),
("all Evolution bugs", "Evo"),
("NEW Evolution bugs", "Evo NEW"),
("ASSIGNED Evolution bugs", "Evo AS"),
("all airlied's bugs", "Airlied"),
("NEW airlied's bugs", "Airlied NEW"),
("ASSIGNED airlied's bugs", "Airlied AS"),
("all ajax's bugs", "Ajax"),
("NEW ajax's bugs", "Ajax NEW"),
("ASSIGNED ajax's bugs", "Ajax AS"),
("all bugs of Jerome Glisse", "jerome"),
("NEW bugs of Jerome Glisse", "jerome NEW"),
("ASSIGNED bugs of Jerome Glisse", "jerome AS"),
("all bugs of Ben Skeggs", "darktama"),
("NEW bugs of Ben Skeggs", "darktama NEW"),
("ASSIGNED bugs of Ben Skeggs", "darktama AS"),
("all caillon's bugs", "caillon"),
("NEW caillon's bugs", "caillon NEW"),
("ASSIGNED caillon's bugs", "caillon AS"),
("all bugs of Matthew Barnes", "mbarnes"),
("NEW bugs of Matthew Barnes", "mbarnes NEW"),
("ASSIGNED bugs of Matthew Barnes", "mbarnes AS"),
("all bugs of Soren Sandmann Pedersen", "ssp"),
("NEW bugs of Soren Sandmann Pedersen", "ssp NEW"),
("ASSIGNED bugs of Soren Sandmann Pedersen", "ssp AS"),
("all halfline's bugs", "Halfline"),
("NEW halfline's bugs", "Halfline NEW"),
("ASSIGNED halfline's bugs", "Halfline AS"),
("all bugs of Peter Hutterer", "whot"),
("NEW bugs of Peter Hutterer", "whot NEW"),
("ASSIGNED bugs of Peter Hutterer", "whot AS"),
("old NEEDINFO bugs", "old NEEDINFOs")
])
class Report(object):
def __init__(self, filename, header=False):
self.results = odict()
self.header = header
self.current_key = None
self.msg = email.message_from_file(open(filename))
self.msgDate = email.utils.parsedate(self.msg['Date']) or \
time.localtime(0)
logging.debug("self.msgDate = %s (type %s)", self.msgDate,
type(self.msgDate))
self.__generate()
def _getText(self):
"""Return the primary text content of the message."""
if self.msg.is_multipart():
for part in self.msg.walk():
if part.get_content_type() == "text/plain":
return part.get_payload(decode=True).decode(
part.get_content_charset())
elif self.msg.get_content_type() == "text/plain":
return self.msg.get_payload(decode=True).decode(
self.msg.get_content_charset())
else:
raise ValueError("Cannot find text/plain part of the message")
def __start_new_section(self, match):
key_string = match.group(1).strip()
if key_string in TranslateNamesPairs:
logging.debug("heading match = group(1) %s", match.groups())
self.current_key = TranslateNamesPairs[key_string]
logging.debug("setting current_key = %s",
self.current_key)
self.results[self.current_key] = 0
def __bump_the_key(self):
if self.current_key:
logging.debug("Upping record for key = %s [was %d]",
self.current_key,
self.results[self.current_key])
self.results[self.current_key] += 1
def __generate(self):
bodyText = self._getText()
# Now the real parsing begins
# Skip SKIP_OVER_HEADER lines of explanation
for line in bodyText.split("\n")[SKIP_OVER_HEADER:]:
line = line.strip()
logging.debug('current line = "%s"', line)
# Skip over empty lines
if len(line) == 0:
continue
# When we have found key, we need to store the old one
if BUG_PATTERN.search(line):
self.__bump_the_key()
else:
match = HEADING_PATTERN.search(line)
if match:
self.__start_new_section(match)
logging.debug("self.results = %s", self.results)
def __str__(self):
"""
Format self.results to CSV line
@return String with CSV (with or without header depending on
self.header)
"""
firstLine = ""
secondLine = ""
keyResults = 0
dateStr = ""
# Generate first column with header if required
if not self.header:
#rowDate = time.strftime(DATE_FORMAT_STRING, msgDate)+SEPARATOR
dateStr = time.strftime(DATE_FORMAT_STRING, self.msgDate)
firstLine = SEPARATOR
secondLine = dateStr + SEPARATOR
else:
firstLine = ""
secondLine = ""
secLineTmp = ""
for key, label in TranslateNamesPairs.items():
logging.debug("pair = %s , %s", key, label)
firstLine += label + SEPARATOR
logging.debug("results = %s\ntransKey = %s", self.results, label)
if (label in self.results):
keyResults = self.results[label]
else:
keyResults = 0
logging.debug("keyResults = %s", keyResults)
if (keyResults > 0):
secLineTmp = str(int(keyResults))
else:
logging.debug("%s has zero bugs.", key)
secLineTmp = "0"
secondLine += secLineTmp + SEPARATOR
if self.header:
return ("%s\n%s" % (firstLine, secondLine))
else:
return secondLine
# @param args
# @throws IOException
if __name__ == "__main__":
out = ""
repObj = Report(sys.argv[1], not CSVPrint)
print((str(repObj)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment