1#! /usr/bin/python 2# 3# CDDL HEADER START 4# 5# The contents of this file are subject to the terms of the 6# Common Development and Distribution License (the "License"). 7# You may not use this file except in compliance with the License. 8# 9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10# or http://www.opensolaris.org/os/licensing. 11# See the License for the specific language governing permissions 12# and limitations under the License. 13# 14# When distributing Covered Code, include this CDDL HEADER in each 15# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16# If applicable, add the following below this CDDL HEADER, with the 17# fields enclosed by brackets "[]" replaced with your own identifying 18# information: Portions Copyright [yyyy] [name of copyright owner] 19# 20# CDDL HEADER END 21# 22 23# 24# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 25# 26 27# Copyright 2010, Richard Lowe 28# Copyright 2018 OmniOS Community Edition (OmniOSce) Association. 29# Copyright 2024 Oxide Computer Company 30 31# 32# Various database lookup classes/methods, i.e.: 33# * monaco 34# * bugs.opensolaris.org (b.o.o.) 35# * redmine (illumos.org) 36# 37 38import re 39try: 40 from urllib.request import urlopen, Request 41 from urllib.error import HTTPError 42except ImportError: 43 # Python 2 44 from urllib2 import Request, urlopen, HTTPError 45 46try: # Python >= 2.5 47 from xml.etree import ElementTree 48except ImportError: 49 from elementtree import ElementTree 50 51class NonExistentBug(Exception): 52 def __str__(self): 53 return "Bug %s does not exist" % (Exception.__str__(self)) 54 55class BugDBException(Exception): 56 def __str__(self): 57 return "Unknown bug database: %s" % (Exception.__str__(self)) 58 59class BugDB(object): 60 """Lookup change requests. 61 62 Usage: 63 bdb = BugDB() 64 r = bdb.lookup("6455550") 65 print r["6455550"]["synopsis"] 66 r = bdb.lookup(["6455550", "6505625"]) 67 print r["6505625"]["synopsis"] 68 """ 69 70 VALID_DBS = ["illumos"] 71 72 def __init__(self, priority = ["illumos"]): 73 """Create a BugDB object. 74 75 Keyword argument: 76 priority: use bug databases in this order 77 """ 78 for database in priority: 79 if database not in self.VALID_DBS: 80 raise BugDBException(database) 81 self.__priority = priority 82 83 84 def __illbug(self, cr): 85 url = "http://illumos.org/issues/%s.xml" % cr 86 req = Request( 87 url, 88 headers = { 89 "User-Agent": "git-pbchk" 90 } 91 ) 92 93 try: 94 data = urlopen(req) 95 except HTTPError as e: 96 if e.code == 401 or e.code == 404: 97 raise NonExistentBug(cr) 98 else: 99 raise 100 101 bug = ElementTree.parse(data) 102 103 return {'cr_number': bug.find('id').text, 104 'synopsis': bug.find('subject').text, 105 'status': bug.find('status').attrib['name'] 106 } 107 108 109 def lookup(self, crs): 110 """Return all info for requested change reports. 111 112 Argument: 113 crs: one change request id (may be integer, string, or list), 114 or multiple change request ids (must be a list) 115 116 Returns: 117 Dictionary, mapping CR=>dictionary, where the nested dictionary 118 is a mapping of field=>value 119 """ 120 results = {} 121 if not isinstance(crs, list): 122 crs = [str(crs)] 123 for database in self.__priority: 124 if database == "illumos": 125 for cr in crs: 126 try: 127 results[str(cr)] = self.__illbug(cr) 128 except NonExistentBug: 129 continue 130 131 # the CR has already been found by one bug database 132 # so don't bother looking it up in the others 133 for cr in crs: 134 if cr in results: 135 crs.remove(cr) 136 137 return results 138