Merge lp:~james-w/launchpad-work-items-tracker/blueprints-api into lp:launchpad-work-items-tracker

Proposed by James Westby
Status: Superseded
Proposed branch: lp:~james-w/launchpad-work-items-tracker/blueprints-api
Merge into: lp:launchpad-work-items-tracker
Diff against target: 476 lines (+120/-199)
1 file modified
collect (+120/-199)
To merge this branch: bzr merge lp:~james-w/launchpad-work-items-tracker/blueprints-api
Reviewer Review Type Date Requested Status
Jamie Bennett (community) Needs Information
Clint Byrum (community) Needs Resubmitting
Review via email: mp+43136@code.launchpad.net

This proposal has been superseded by a proposal from 2010-12-09.

Description of the change

Hi,

This makes use of the newly exposed blueprints API on Launchpad, reducing
the amount of screen scraping, round trips, and data transferred enormously.

The only regression that I think this will cause is that when someone writes
"bug 12345" in the whiteboard, it will no longer be a link to that bug
when viewed on the workitems page, but I think we can live with that for
now. If you disagree let me know and I will code it.

Apologies that the diff is a little large and not particularly clear, but
I couldn't think of a good way to migrate a bit at a time.

Thanks,

James

To post a comment you must log in.
Revision history for this message
Clint Byrum (clint-fewbar) wrote :
Download full text (4.8 KiB)

Upon running the code as-is, I received a failure rather quickly:

clint@clint-MacBookPro:~/src/wi/bzr/trunk$ ./collect -d ../natty.db -c ../natty.cfg --debug
lp_import_milestones(): milestone table already filled
lp_import_teams(): teams table already filled
lp_import(): downloading cloud-server-n-automated-testing from https://api.launchpad.net/devel/ubuntu/+spec/cloud-server-n-automated-testing
lp_import_blueprint(cloud-server-n-automated-testing): finished parsing; data: {'status': 'Session for discussion about automated testing of Ubuntu Server; automated ISO testing was implemented for Maverick using libvirt/kvm + Hudson (see http://launchpad.net/ubuntu-server-iso-testing). This approach could be applied in other variants and for other aspects of server testing', 'definition': 'Approved', 'implementation': 'Started', 'milestone': 'natty-alpha-3', 'approver': 'robbie.w', 'details_url': None, 'priority': 'Essential', 'assignee': 'james-page', 'roadmap_notes': None, 'drafter': 'james-page'}
lp_import_blueprint_workitems(): processing cloud-server-n-automated-testing (spec milestone: natty-alpha-3, spec assignee: james-page, spec implementation: Started)
lp_import_blueprint_workitems(): starting work items block at Work items for natty-alpha-2:
  ... setting milestone to natty-alpha-2
 workitem (raw): '[hggdh2] Way forward on production deployment of ISO testing: TODO'
 workitem (clean): '[hggdh2] Way forward on production deployment of ISO testing: TODO'
 workitem (raw): '[james-page] Move Server ISO tests to normal PXE + TFTP instead for broader fit with potential test architectures: DONE'
 workitem (clean): '[james-page] Move Server ISO tests to normal PXE + TFTP instead for broader fit with potential test architectures: DONE'
 workitem (raw): '[james-page] Server ISO test - review what the iso overlay looks like and refactor as required: DONE'
 workitem (clean): '[james-page] Server ISO test - review what the iso overlay looks like and refactor as required: DONE'
 workitem (raw): '[james-page] Package ubuntu-server-iso-testing and locate in PPA: INPROGRESS'
 workitem (clean): '[james-page] Package ubuntu-server-iso-testing and locate in PPA: INPROGRESS'
 workitem (raw): ''
lp_import_blueprint_workitems(): closing work items block with line:
lp_import_blueprint_workitems(): starting work items block at Work items for natty-alpha-3:
  ... setting milestone to natty-alpha-3
 workitem (raw): '[james-page] Automate EC2 testing and increase depth of image testing using unittest/subunit: TODO'
 workitem (clean): '[james-page] Automate EC2 testing and increase depth of image testing using unittest/subunit: TODO'
 workitem (raw): '[james-page] Server ISO test - fix concurrency in ISO download: TODO'
 workitem (clean): '[james-page] Server ISO test - fix concurrency in ISO download: TODO'
 workitem (raw): '[cr2] Output plugin for checkbox to write to couchdb: TODO'
 workitem (clean): '[cr2] Output plugin for checkbox to write to couchdb: TODO'
https://launchpad.net/ubuntu/+spec/cloud-server-n-automated-testing
  [WARNING] assignee "cr2" is not a valid Launchpad account
 workitem (raw): '[cr2] Checkbox plugin to download tests from couchdb to ex...

Read more...

review: Needs Resubmitting
250. By Clint Byrum

merging extra project support from James Westby

251. By Martin Pitt

fix previous commit to not crash

Revision history for this message
Jamie Bennett (jamiebennett) wrote :

On testing the code I was prompted to log in using open id (from the command-line). As this was tested via ssh to a development box 'Links' was launched as the web browser to gather my open id information. From there you cannot log in (Launchpad/Links issue). This did not happen on previous versions.

review: Needs Information
252. By Martin Pitt

fix previous commit properly, thanks James

253. By Martin Pitt

revert extra-projects merge for now; this is creating a conceptual conflict on milestones, and should rather be handled in separate configurations for linaro

254. By Martin Pitt

consider fixed bugs in bug list based reports as well

255. By Martin Pitt

add "Unknown" bug state

256. By Martin Pitt

drop Unknown bug state, does not exist any more

257. By Martin Pitt

better fix for "Unknown" task status

258. By Martin Pitt

finally fix unknown bug states

259. By Martin Pitt

html-report: Add textual stats over time

260. By Martin Pitt

html-report: sort dates

261. By Martin Pitt

fix time-stats todo column

262. By Martin Pitt

time-stats: not all states exist always

263. By Martin Pitt

collect: add "Expired" bug state

264. By James Westby

Merge blueprints API branch.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'collect'
--- collect 2010-12-09 13:58:55 +0000
+++ collect 2010-12-09 15:54:09 +0000
@@ -3,7 +3,7 @@
3# Pull work items from various sources (blueprint whiteboards, linked blueprint3# Pull work items from various sources (blueprint whiteboards, linked blueprint
4# bugs, wiki pages) and put them into a database.4# bugs, wiki pages) and put them into a database.
55
6import urllib, re, sys, optparse, smtplib, pwd, os6import urllib, re, sys, optparse, smtplib, pwd, os, urlparse
7from email.mime.text import MIMEText7from email.mime.text import MIMEText
8import sqlite3 as dbapi28import sqlite3 as dbapi2
99
@@ -54,51 +54,20 @@
54 dbg('Queueing data error: ' + s)54 dbg('Queueing data error: ' + s)
5555
5656
57def web_link(item):
58 """Get a link to the Launchpad API object on the website."""
59 api_link = item.self_link
60 parts = urlparse.urlparse(api_link)
61 return parts.scheme + "://" + parts.netloc.replace("api.", "") + "/" + parts.path.split("/", 2)[2]
62
63
57########################################################################64########################################################################
58#65#
59# Functions for parsing Launchpad data66# Functions for parsing Launchpad data
60#67#
61########################################################################68########################################################################
6269
63def lp_blueprints_from_list(url, name_pattern = None):70def lp_import_blueprint(db, bp):
64 '''Return blueprints from a LP list view.
65
66 This can optionally specify a name pattern (which is mostly useful for
67 testing and debugging, to only parse a small subset of blueprints)
68
69 Return a dictionary name -> (url, milestone).
70 '''
71 blueprint_name_filter = re.compile('href="(/[a-zA-Z0-9-]+/\+spec/%s[^"]+)"(?!.*class.*sprite)' %
72 (name_pattern or '.'))
73 milestone_re = re.compile('href=".*/[a-zA-Z0-9-]+/\+milestone/([^"]+)"')
74
75 result = {}
76 scan_tr_end = False
77 milestone = None
78 bp = None
79 dbg("lp_blueprints_from_list(): Loading '%s'" % url)
80 for l in urllib.urlopen(url):
81 if scan_tr_end:
82 m = milestone_re.search(l)
83 if m:
84 milestone = m.group(1)
85 dbg('lp_blueprints_from_list(): current spec milestone: ' + milestone)
86 if '</tr>' in l:
87 scan_tr_end = False
88 if bp:
89 result[bp.split('/')[-1]] = (bp, milestone)
90 bp = None
91 milestone = None
92 else:
93 m = blueprint_name_filter.search(l)
94 if m:
95 bp = report_tools.blueprints_base_url + m.group(1)
96 dbg('lp_blueprints_from_list(): found BP: ' + bp)
97 scan_tr_end = True
98
99 return result
100
101def lp_import_blueprint(db, name, url, contents):
102 '''Import details of a blueprint into the specs table.71 '''Import details of a blueprint into the specs table.
10372
104 If a blueprint does not have a status, use the description.73 If a blueprint does not have a status, use the description.
@@ -112,56 +81,50 @@
112 cur.execute('SELECT name FROM milestones')81 cur.execute('SELECT name FROM milestones')
113 valid_milestones = [m[0] for m in cur] + [None]82 valid_milestones = [m[0] for m in cur] + [None]
11483
115 queries = {84 def get_whiteboard_section(heading):
116 'priority': '<dt>Priority:</dt>\s*<dd>\s*([^\n]*)',85 if bp.whiteboard is None:
117 'definition': '<dt>Definition:</dt>\s*<dd>\s*([^\n]*)',86 return None
118 'implementation': '<dt>Implementation:</dt>\s*<dd>\s*([^\n]*)',87 regex = '^' + heading + ':\s*\n(.*?)\n\n'
119 'approver': '<dt>Approver:</dt>\s*<dd>\s*<a href="https://.*?launchpad.net/~([a-zA-Z0-9_-]+)" ',88 m = re.search(regex, bp.whiteboard, re.S | re.I | re.M)
120 'drafter': '<dt>Drafter:</dt>\s*<dd>\s*<a href="https://.*?launchpad.net/~([a-zA-Z0-9_-]+)" ',89 if m is not None:
121 'assignee': '<dt>Assignee:</dt>\s*<dd>\s*<a href="https://.*?launchpad.net/~([a-zA-Z0-9_-]+)" ',90 section = m.group(1).strip()
122 'milestone': '<dt>Milestone target:</dt>\s*<dd>\s*<a href="https://.*?launchpad.net/\w+/\+milestone/([a-zA-Z0-9_\.-]+)"',91 else:
123 'description': '<div class="top-portlet">\s*<p>(.*?)</p>',92 section = None
124 'status': '(?:<p>|^)[Ss]tatus:\s*<br />(.*?)</p>',93 return section
125 'details_url': 'href="([^"]*)">Read the full specification</a>',
126 'roadmap_notes': '(?:<p>|^)[Rr]oadmap\s+[Nn]otes:\s*<br />(.*?)</p>',
127 }
12894
129 data = {}95 data = {}
130 for key, r in queries.iteritems():96 data['priority'] = bp.priority
131 m = re.search(r, contents, re.S)97 data['definition'] = bp.definition_status
132 if not m:98 data['implementation'] = bp.implementation_status
133 dbg('lp_import_blueprint(%s): did not find a match for key %s' % (name, key))99 data['approver'] = bp.approver and bp.approver.name or None
134 if key == 'description':100 data['drafter'] = bp.drafter and bp.drafter.name or None
135 data[key] = '(no description)'101 data['assignee'] = bp.assignee and bp.assignee.name or None
136 else:102 data['milestone'] = bp.milestone and bp.milestone.name or None
137 data[key] = None103 data['description'] = bp.summary or "(no description)"
138 else:104 data['status'] = get_whiteboard_section('Status')
139 data[key] = m.group(1).strip()105 data['details_url'] = bp.specification_url
106 data['roadmap_notes'] = get_whiteboard_section('Roadmap\s+Notes')
140107
141 # ignore "later" milestone"108 # ignore "later" milestone"
142 if data['milestone'] == 'later':109 if data['milestone'] == 'later':
143 dbg('lp_import_blueprint(%s): spec has "later" milestone, ignoring it' % name)110 dbg('lp_import_blueprint(%s): spec has "later" milestone, ignoring it' % bp.name)
144 return False111 return False
145112
146 if data['milestone'] not in valid_milestones:113 if data['milestone'] not in valid_milestones:
147 data_error(url, 'milestone "%s" is unknown/invalid' % data['milestone'], True)114 data_error(web_link(bp), 'milestone "%s" is unknown/invalid' % data['milestone'], True)
148115
149 # if we have an explicit status: in the whiteboard, use that; otherwise use116 # if we have an explicit status: in the whiteboard, use that; otherwise use
150 # description as status text117 # description as status text
151 if data['status']:118 if data['status']:
152 data['status'] = data['status'].replace('<br />',119 data['status'] = data['status'].strip()
153 '\n').replace('</div>', '').replace('&nbsp;', ' ').replace(
154 '<wbr></wbr>', '').strip()
155 else:120 else:
156 data['status'] = data['description'].replace('<br />',121 data['status'] = data['description'].strip()
157 '\n').replace('</div>', '').replace('&nbsp;', ' ').replace(
158 '<wbr></wbr>', '').strip()
159 del data['description']122 del data['description']
160123
161 dbg('lp_import_blueprint(%s): finished parsing; data: %s' % (name, str(data)))124 dbg('lp_import_blueprint(%s): finished parsing; data: %s' % (bp.name, str(data)))
162125
163 db.cursor().execute('INSERT INTO specs VALUES (?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?,?)',126 db.cursor().execute('INSERT INTO specs VALUES (?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?,?)',
164 (name, url, data['priority'], data['implementation'],127 (bp.name, web_link(bp), data['priority'], data['implementation'],
165 data['assignee'], data['status'], data['milestone'],128 data['assignee'], data['status'], data['milestone'],
166 data['definition'], data['drafter'], data['approver'],129 data['definition'], data['drafter'], data['approver'],
167 data['details_url'], data['roadmap_notes']))130 data['details_url'], data['roadmap_notes']))
@@ -173,10 +136,7 @@
173136
174 '''137 '''
175138
176 ### cargo culted from parse_blueprint_workitem139 line = line.strip()
177 line = line.replace('<br />', '').replace('</div>', '').replace('</p>',
178 '').replace('<wbr></wbr>', '').replace('&nbsp;', ' ').replace(
179 '<a href="/', '<a href="https://launchpad.net/').strip()
180 if not line:140 if not line:
181 return141 return
182142
@@ -196,14 +156,9 @@
196 db.commit()156 db.commit()
197157
198def parse_complexity_item(lp, db, line, bp_name, bp_url, def_milestone, def_assignee):158def parse_complexity_item(lp, db, line, bp_name, bp_url, def_milestone, def_assignee):
199 159 line = line.strip()
200 line = line.replace('<br />', '').replace('</div>', '').replace('</p>',160 # remove special characters people tend to type
201 '').replace('<wbr></wbr>', '').replace('&nbsp;', ' ').replace(
202 '<a href="/', '<a href="https://launchpad.net/').strip()
203
204 # remove special characters people tend to type
205 line = re.sub('[^\w -.]', '', line)161 line = re.sub('[^\w -.]', '', line)
206
207 if not line:162 if not line:
208 return163 return
209164
@@ -214,17 +169,15 @@
214 assignee = None169 assignee = None
215170
216 try:171 try:
217 list = line.split()172 complexity_list = line.split()
218 list.reverse()173 complexity_list.reverse()
219174
220 # we may not have any values in the list, so append our175 # we may not have any values in the list, so append our
221 # default values in the right order so they can be mapped176 # default values in the right order so they can be mapped
222 defs = [None, def_milestone, def_assignee]177 defs = [None, def_milestone, def_assignee]
223 for i in range(len(list), len(defs)):178 for i in range(len(complexity_list), len(defs)):
224 list.append(defs[i])179 complexity_list.append(defs[i])
225 180 (num, milestone, assignee) = complexity_list
226 (num, milestone, assignee) = list
227
228 if not num:181 if not num:
229 data_error(bp_url, 'No complexity points defined for %s' % line)182 data_error(bp_url, 'No complexity points defined for %s' % line)
230183
@@ -233,17 +186,17 @@
233 cur = db.cursor()186 cur = db.cursor()
234 cur.execute('INSERT INTO complexity VALUES(?,?,?,?,date(CURRENT_TIMESTAMP))',187 cur.execute('INSERT INTO complexity VALUES(?,?,?,?,date(CURRENT_TIMESTAMP))',
235 (assignee, num, milestone, bp_name))188 (assignee, num, milestone, bp_name))
236
237 except ValueError:189 except ValueError:
238 data_error(bp_url, "\tComplexity line '%s' could not be parsed %s" % (line, ValueError))190 data_error(bp_url, "\tComplexity line '%s' could not be parsed %s" % (line, ValueError))
239191
192
240def parse_blueprint_workitem(line, default_assignee, milestone,193def parse_blueprint_workitem(line, default_assignee, milestone,
241 blueprint_url, launchpad, result_list):194 blueprint_url, launchpad, result_list):
242 '''Parse a work item line of a blueprint whiteboard.'''195 '''Parse a work item line of a blueprint whiteboard.'''
243196
244 line = line.replace('<br />', '').replace('</div>', '').replace('</p>',197 # FIXME: we lose bug linking etc. that is done by the tales
245 '').replace('<wbr></wbr>', '').replace('&nbsp;', ' ').replace(198 # formatters in LP here.
246 '<a href="/', '<a href="https://launchpad.net/').strip()199 line = line.strip()
247 if not line:200 if not line:
248 return201 return
249 dbg("\tworkitem (clean): '%s'" % (line))202 dbg("\tworkitem (clean): '%s'" % (line))
@@ -286,13 +239,10 @@
286239
287 result_list.append((desc, state, assignee, milestone))240 result_list.append((desc, state, assignee, milestone))
288241
289def follow_blueprint_buglink(bugnum, default_assignee, blueprint_name,242def follow_blueprint_buglink(bug, default_assignee, blueprint_name,
290 launchpad, release, default_milestone, result_list):243 launchpad, release, default_milestone, result_list):
291 '''Query launchpad for the information on a linked bug'''244 '''Query launchpad for the information on a linked bug'''
292245
293 bugnum = int(bugnum)
294 dbg('follow_blueprint_buglink(): processing bug %i (default milestone: %s)' % (bugnum, default_milestone))
295 bug = launchpad.bugs[bugnum]
296 for task in bug.bug_tasks:246 for task in bug.bug_tasks:
297 state = bug_wi_states.get(task.status, 'todo')247 state = bug_wi_states.get(task.status, 'todo')
298 if state is None:248 if state is None:
@@ -329,7 +279,7 @@
329 if better_task:279 if better_task:
330 continue280 continue
331281
332 desc = '<a href="https://launchpad.net/bugs/%d">LP: #%d</a>: ' % (bugnum, bugnum) + bug.title282 desc = '<a href="https://launchpad.net/bugs/%d">LP: #%d</a>: ' % (bug.id, bug.id) + bug.title
333 if rtype != 'distribution':283 if rtype != 'distribution':
334 desc += ' (%s)' % target.name284 desc += ' (%s)' % target.name
335285
@@ -354,32 +304,27 @@
354 return word304 return word
355 return None305 return None
356306
357def lp_import_blueprint_workitems(lp, db, bp_name, bp_url, contents, release):307def lp_import_blueprint_workitems(lp, db, bp, release):
358 '''Collect work items from a Launchpad blueprint.308 '''Collect work items from a Launchpad blueprint.
359309
360 This includes work items from the whiteboard as well as linked bugs.310 This includes work items from the whiteboard as well as linked bugs.
361 '''311 '''
362 linked_bugs_re = re.compile('<div id="bug_links".*>', re.I)312 work_items_re = re.compile('^work items(.*)\s*:\s*$', re.I)
363 bugnum_re = re.compile('<a href="https://bugs\..*launchpad\.net/bugs/([0-9]+)" class="sprite bug">')313 meta_re = re.compile('^Meta.*?:$', re.I)
364 work_items_re = re.compile('(<p>|^)work items(.*)\s*:\s*<br />', re.I)314 complexity_re = re.compile('^Complexity.*?:$', re.I)
365 meta_re = re.compile( '(<p>|^)Meta.*?:<br />', re.I )
366 complexity_re = re.compile( '(<p>|^)Complexity.*?:<br />', re.I )
367315
368 in_workitems_block = False316 in_workitems_block = False
369 in_linked_bugs_block = False
370 in_meta_block = False317 in_meta_block = False
371 in_complexity_block = False318 in_complexity_block = False
372 found_linked_bugs = False
373 work_items = []319 work_items = []
374 found_wb_workitems = False
375 milestone = None320 milestone = None
376321
377 cur = db.cursor()322 cur = db.cursor()
378 cur.execute('SELECT assignee, milestone, implementation FROM specs WHERE name = ?', (bp_name,))323 cur.execute('SELECT assignee, milestone, implementation FROM specs WHERE name = ?', (bp.name,))
379 (spec_assignee, spec_milestone, spec_implementation) = cur.fetchone()324 (spec_assignee, spec_milestone, spec_implementation) = cur.fetchone()
380325
381 dbg('lp_import_blueprint_workitems(): processing %s (spec milestone: %s, spec assignee: %s, spec implementation: %s)' % (326 dbg('lp_import_blueprint_workitems(): processing %s (spec milestone: %s, spec assignee: %s, spec implementation: %s)' % (
382 bp_name, spec_milestone, spec_assignee, spec_implementation))327 bp.name, spec_milestone, spec_assignee, spec_implementation))
383328
384 cur.execute('SELECT team FROM teams WHERE name = ?', (spec_assignee,))329 cur.execute('SELECT team FROM teams WHERE name = ?', (spec_assignee,))
385 assignee_teams = [t[0] for t in cur]330 assignee_teams = [t[0] for t in cur]
@@ -387,69 +332,51 @@
387 cur.execute('SELECT name FROM milestones')332 cur.execute('SELECT name FROM milestones')
388 valid_milestones = [m[0] for m in cur]333 valid_milestones = [m[0] for m in cur]
389334
390 for l in contents.splitlines():335 if bp.whiteboard:
391336 for l in bp.whiteboard.splitlines():
392 if not in_workitems_block and not in_linked_bugs_block \337
393 and not in_meta_block and not in_complexity_block:338 if (not in_workitems_block
394 m = work_items_re.search(l)339 and not in_meta_block and not in_complexity_block):
395 if m:340 m = work_items_re.search(l)
396 in_workitems_block = True341 if m:
397 found_wb_workitems = True342 in_workitems_block = True
398 dbg('lp_import_blueprint_workitems(): starting work items block at ' + l)343 dbg('lp_import_blueprint_workitems(): starting work items block at ' + l)
399 if not milestone:344 if not milestone:
400 milestone = milestone_extract(m.group(2), valid_milestones)345 milestone = milestone_extract(m.group(1), valid_milestones)
401 dbg(' ... setting milestone to ' + str(milestone))346 dbg(' ... setting milestone to ' + str(milestone))
402 if linked_bugs_re.search(l):347 if meta_re.search(l):
403 in_linked_bugs_block = True348 in_meta_block = True
404 found_linked_bugs = True349 if complexity_re.search(l):
405 if meta_re.search(l):350 in_complexity_block = True
406 in_meta_block = True351 continue
407 if complexity_re.search(l):352
408 in_complexity_block = True 353 if in_workitems_block:
409 continue354 dbg("\tworkitem (raw): '%s'" % (l.strip()))
410355 if not l.strip():
411 if in_workitems_block:356 dbg('lp_import_blueprint_workitems(): closing work items block with line: ' + l)
412 dbg("\tworkitem (raw): '%s'" % (l.strip()))357 in_workitems_block = False
413 parse_blueprint_workitem(l, spec_assignee, milestone or358 milestone = None
414 spec_milestone, bp_url, lp, work_items)359 parse_blueprint_workitem(l, spec_assignee, milestone or
415360 spec_milestone, web_link(bp), lp, work_items)
416 if '</p>' in l:361
417 dbg('lp_import_blueprint_workitems(): closing work items block with line: ' + l)362 if in_meta_block:
418 in_workitems_block = False363 dbg("\tmeta line (raw): '%s'" % (l.strip()))
419 milestone = None364 if not l.strip():
420365 in_meta_block = False
421 if in_linked_bugs_block:366 continue
422 dbg("\tbug block line (raw): '%s'" % (l.strip()))367 parse_meta_item(lp, db, l, bp.name)
423 m = bugnum_re.search(l)368
424 if m and lp:369 if in_complexity_block:
425 follow_blueprint_buglink(m.group(1), spec_assignee,370 dbg("\tcomplexity block line (raw): '%s'" % (l.strip()))
426 bp_name, lp, release,371 if not l.strip():
427 milestone or spec_milestone, work_items)372 in_complexity_block = False
428373 continue
429 if '</div>' in l:374 parse_complexity_item(lp, db, l, bp.name, web_link(bp), spec_milestone, spec_assignee)
430 in_linked_bugs_block = False375
431 continue376 if lp:
432377 for bug in bp.bugs:
433 if in_meta_block:378 follow_blueprint_buglink(bug, spec_assignee, bp.name, lp, release,
434 dbg("\tmeta line (raw): '%s'" % (l.strip()))379 spec_milestone, work_items)
435 parse_meta_item( lp, db, l, bp_name )
436
437 # done with the meta information?
438 if '</p>' in l:
439 in_meta_block = False
440 continue
441
442 if in_complexity_block:
443 dbg("\tcomplexity block line (raw): '%s'" % (l.strip()))
444 parse_complexity_item(lp, db, l, bp_name, bp_url, spec_milestone, spec_assignee)
445
446 # done with the meta information?
447 if '</p>' in l:
448 in_complexity_block = False
449 continue
450
451 if found_wb_workitems and '</div>' in l:
452 break
453380
454 if not work_items:381 if not work_items:
455 #data_error(bp_url, 'no work items defined', True)382 #data_error(bp_url, 'no work items defined', True)
@@ -465,7 +392,8 @@
465392
466 for (desc, status, assignee, milestone) in work_items:393 for (desc, status, assignee, milestone) in work_items:
467 db.cursor().execute('INSERT INTO work_items VALUES (?, ?, ?, ?, ?, date(CURRENT_TIMESTAMP))',394 db.cursor().execute('INSERT INTO work_items VALUES (?, ?, ?, ?, ?, date(CURRENT_TIMESTAMP))',
468 (desc, bp_name, status, assignee, milestone))395 (desc, bp.name, status, assignee, milestone))
396
469397
470def lp_import_milestones(lp_project, db):398def lp_import_milestones(lp_project, db):
471 '''Import milestones from Launchpad into DB.399 '''Import milestones from Launchpad into DB.
@@ -544,40 +472,33 @@
544def lp_import(db, cfg, name_pattern = None):472def lp_import(db, cfg, name_pattern = None):
545 '''Collect blueprint work items and status from Launchpad into DB.'''473 '''Collect blueprint work items and status from Launchpad into DB.'''
546474
547 lp = Launchpad.login_with('ubuntu-work-items', service_root=EDGE_SERVICE_ROOT)475 lp = Launchpad.login_with('ubuntu-work-items', service_root="production", version="devel")
548476
549 urls = []477 projects = []
550
551 def import_project(project):
552 lp_import_milestones(project, db)
553 url = '%s/%s/+specs?batch=300' % (
554 report_tools.blueprints_base_url, project.name)
555 urls.append(url)
556478
557 if 'release' in cfg:479 if 'release' in cfg:
558 lp_project = lp.distributions['ubuntu'].getSeries(name_or_version=cfg['release'])480 lp_project = lp.distributions['ubuntu'].getSeries(name_or_version=cfg['release'])
559 url = '%s/ubuntu/%s/+specs?batch=300' % (481 projects.append(lp_project)
560 report_tools.blueprints_base_url, cfg['release'])
561 urls.append(url)
562 else:482 else:
563 assert 'project' in cfg, 'Configuration needs to specify project or release'483 assert 'project' in cfg, 'Configuration needs to specify project or release'
564 lp_project = lp.projects[cfg['project']]484 lp_project = lp.projects[cfg['project']]
565 import_project(lp_project)485 projects.append(lp_project)
486
487 lp_import_milestones(lp_project, db)
488 lp_import_teams(lp, db, cfg)
566489
567 extra_projects = cfg.get('extra_projects', [])490 extra_projects = cfg.get('extra_projects', [])
568 for extra_project_name in extra_projects:491 for extra_project_name in extra_projects:
569 extra_project = lp.projects[extra_project_name]492 extra_project = lp.projects[extra_project_name]
570 import_project(extra_project)493 lp_import_milestones(extra_project, db)
571494 projects.append(extra_project)
572 lp_import_milestones(lp_project, db)495
573 lp_import_teams(lp, db, cfg)496 for project in projects:
574497 # XXX: should this be valid_ or all_specifications?
575 for url in urls:498 for bp in lp_project.valid_specifications:
576 for (bp, (url, milestone)) in lp_blueprints_from_list(url, name_pattern).iteritems():499 dbg('lp_import(): downloading %s from %s' % (bp.name, bp.self_link))
577 dbg('lp_import(): downloading %s from %s' % (bp, url))500 if lp_import_blueprint(db, bp):
578 contents = urllib.urlopen(url).read().decode('UTF-8')501 lp_import_blueprint_workitems(lp, db, bp, cfg.get('release'))
579 if lp_import_blueprint(db, bp, url, contents):
580 lp_import_blueprint_workitems(lp, db, bp, url, contents, cfg.get('release'))
581 lp_import_bug_workitems(lp_project, db, cfg)502 lp_import_bug_workitems(lp_project, db, cfg)
582503
583########################################################################504########################################################################

Subscribers

People subscribed via source and target branches

to all changes: