summaryrefslogtreecommitdiff
blob: 16abf7001a8aeed26a000e0c2447cefadc4f0061 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# Copyright 2012 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

import cStringIO
import datetime
import getpass
import re

import portage


CPV_REGEX = re.compile("[A-Za-z0-9+_.-]+/[A-Za-z0-9+_-]+-[0-9]+(?:\.[0-9]+)*[a-z0-9_]*(?:-r[0-9]+)?")


def chunks(iterable, length):
	for i in range(0, len(iterable), length):
		yield iterable[i:i + length]


# Snippet from http://bugs.python.org/issue9584
def expand_braces(orig):
	r = r'.*(\{.+?[^\\]\})'
	p = re.compile(r)

	s = orig[:]
	res = list()

	m = p.search(s)
	if m is not None:
		sub = m.group(1)
		open_brace = s.find(sub)
		close_brace = open_brace + len(sub) - 1
		if ',' in sub:
			for pat in sub.strip('{}').split(','):
				res.extend(expand_braces(s[:open_brace] + pat + s[close_brace+1:]))

		else:
			res.extend(expand_braces(s[:open_brace] + sub.replace('}', '\\}') + s[close_brace+1:]))

	else:
		res.append(s.replace('\\}', '}'))

	return list(set(res))


def get_input(prompt):
	return raw_input(prompt)


def login(bugzilla):
	"""Authenticate a session.
	"""
	# prompt for username
	user = get_input('Bugzilla Username: ')

	# prompt for password
	password = getpass.getpass()

	# perform login
	params = {}
	params['login'] = user
	params['password'] = password
	print 'Logging in'
	bugzilla.User.login(params)


class Bug:
	def __init__(self, xml=None, id_number=None, summary=None, status=None):
		if xml is not None:
			self.__id = int(xml.find("bug_id").text)
			self.__summary = xml.find("short_desc").text
			self.__status = xml.find("bug_status").text
			self.__depends_on = [int(dep.text) for dep in xml.findall("dependson")]
			self.__comments = [c.find("who").text + "\n" + c.find("thetext").text for c in xml.findall("long_desc")]
			self.__cc = [cc.text for cc in xml.findall("cc")]
			self.__creation_timestamp = datetime.datetime.strptime(xml.find('creation_ts').text, '%Y-%m-%d %H:%M:%S +0000')

			self.__keywords = []
			keywords_elem = xml.find("keywords")
			if keywords_elem is not None and keywords_elem.text:
				self.__keywords = [k.strip() for k in keywords_elem.text.split(",")]
		if id_number is not None:
			self.__id = id_number
		if summary is not None:
			self.__summary = summary
		if status is not None:
			self.__status = status
		self.__cpvs_detected = False
		self.__cpvs = []
	
	def detect_cpvs(self):
		if self.__cpvs_detected:
			return
		for cpv_string in list(set([self.summary()] + expand_braces(self.summary()))):
			for cpv_candidate in CPV_REGEX.findall(cpv_string):
				if portage.db["/"]["porttree"].dbapi.cpv_exists(cpv_candidate):
					self.__cpvs.append(cpv_candidate)
		self.__cpvs = list(set(self.__cpvs))
		self.__cpvs_detected = True
	
	def id_number(self):
		return self.__id
	
	def summary(self):
		return self.__summary
	
	def status(self):
		return self.__status
	
	def depends_on(self):
		return self.__depends_on
	
	def comments(self):
		return self.__comments
	
	def cc(self):
		return self.__cc

	def creation_timestamp(self):
		return self.__creation_timestamp

	def keywords(self):
		return self.__keywords
	
	def cpvs(self):
		assert(self.__cpvs_detected)
		return self.__cpvs