cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#! /usr/bin/python
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# CDDL HEADER START
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# The contents of this file are subject to the terms of the
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# Common Development and Distribution License (the "License").
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# You may not use this file except in compliance with the License.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# or http://www.opensolaris.org/os/licensing.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# See the License for the specific language governing permissions
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# and limitations under the License.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# When distributing Covered Code, include this CDDL HEADER in each
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# If applicable, add the following below this CDDL HEADER, with the
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# fields enclosed by brackets "[]" replaced with your own identifying
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# information: Portions Copyright [yyyy] [name of copyright owner]
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# CDDL HEADER END
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
84bb51db52515f628cb1781523b3574cbfe72c74Mark J. Nelson# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe# Copyright 2010, Richard Lowe
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# Various database lookup classes/methods, i.e.:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# * monaco
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# * bugs.opensolaris.org (b.o.o.)
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe# * redmine (illumos.org)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Loweimport htmllib
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelsonimport re
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelsonimport urllib
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenscheinimport urllib2
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowetry: # Python >= 2.5
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe from xml.etree import ElementTree
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Loweexcept ImportError:
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe from elementtree import ElementTree
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
41a5f560d7437bb41abade5dce25dc6875da156aMark J. Nelsonclass NonExistentBug(Exception):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson def __str__(self):
41a5f560d7437bb41abade5dce25dc6875da156aMark J. Nelson return "Bug %s does not exist" % (Exception.__str__(self))
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenscheinclass BugDBException(Exception):
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein def __str__(self):
41a5f560d7437bb41abade5dce25dc6875da156aMark J. Nelson return "Unknown bug database: %s" % (Exception.__str__(self))
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenscheinclass BugDB(object):
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein """Lookup change requests.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein Usage:
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein bdb = BugDB()
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein r = bdb.lookup("6455550")
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein print r["6455550"]["synopsis"]
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein r = bdb.lookup(["6455550", "6505625"])
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein print r["6505625"]["synopsis"]
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein """
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
37cc68d40a0ab1290a015e66cad4cade598c921bJoshua M. Clulow VALID_DBS = ["illumos"]
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe
37cc68d40a0ab1290a015e66cad4cade598c921bJoshua M. Clulow def __init__(self, priority = ["illumos"]):
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein """Create a BugDB object.
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein Keyword argument:
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein priority: use bug databases in this order
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson """
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein for database in priority:
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe if database not in self.VALID_DBS:
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein raise BugDBException, database
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein self.__priority = priority
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe def __illbug(self, cr):
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe url = "http://illumos.org/issues/%s.xml" % cr
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe req = urllib2.Request(url)
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe try:
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe data = urllib2.urlopen(req)
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe except urllib2.HTTPError, e:
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe if e.code == 404:
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe raise NonExistentBug(cr)
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe else:
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe raise
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe bug = ElementTree.parse(data)
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe return {'cr_number': bug.find('id').text,
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe 'synopsis': bug.find('subject').text,
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe 'status': bug.find('status').attrib['name']
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe }
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson def lookup(self, crs):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson """Return all info for requested change reports.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson Argument:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson crs: one change request id (may be integer, string, or list),
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe or multiple change request ids (must be a list)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson Returns:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson Dictionary, mapping CR=>dictionary, where the nested dictionary
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson is a mapping of field=>value
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson """
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein results = {}
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if not isinstance(crs, list):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson crs = [str(crs)]
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein for database in self.__priority:
37cc68d40a0ab1290a015e66cad4cade598c921bJoshua M. Clulow if database == "illumos":
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe for cr in crs:
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe try:
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe results[str(cr)] = self.__illbug(cr)
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe except NonExistentBug:
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe continue
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein # the CR has already been found by one bug database
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein # so don't bother looking it up in the others
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein for cr in crs:
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein if cr in results:
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein crs.remove(cr)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe return results