# Copyright (C) 2016 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
try:
from urllib2 import ProxyHandler, build_opener, install_opener, urlopen # Python 2
except ImportError:
from urllib.request import ProxyHandler, build_opener, install_opener, urlopen # Python 3
################ workarounds for issues tracked inside jira #################
JIRA_URL='https://bugreports.qt.io/browse'
class JIRA:
__instance__ = None
# Helper class
class Bug:
CREATOR = 'QTCREATORBUG'
SDK = 'QTSDK'
QT = 'QTBUG'
QT_QUICKCOMPONENTS = 'QTCOMPONENTS'
# constructor of JIRA
def __init__(self, number, bugType=Bug.CREATOR):
if JIRA.__instance__ == None:
JIRA.__instance__ = JIRA.__impl(number, bugType)
setattr(JIRA, '__instance__', JIRA.__instance__)
else:
JIRA.__instance__._bugType = bugType
JIRA.__instance__._number = number
JIRA.__instance__.__fetchResolutionFromJira__()
# overridden to make it possible to use JIRA just like the
# underlying implementation (__impl)
def __getattr__(self, attr):
return getattr(self.__instance__, attr)
# overridden to make it possible to use JIRA just like the
# underlying implementation (__impl)
def __setattr__(self, attr, value):
return setattr(self.__instance__, attr, value)
# function to check if the given bug is open or not
@staticmethod
def isBugStillOpen(number, bugType=Bug.CREATOR):
tmpJIRA = JIRA(number, bugType)
return tmpJIRA.isOpen()
# implementation of JIRA singleton
class __impl:
# constructor of __impl
def __init__(self, number, bugType):
self._number = number
self._bugType = bugType
self._fix = None
self._fetchResults_ = {}
self.__fetchResolutionFromJira__()
# this function checks the resolution of the given bug
# and returns True if the bug can still be assumed as 'Open' and False otherwise
def isOpen(self):
# handle special cases
if self._resolution == None:
return True
if self._resolution in ('Duplicate', 'Moved', 'Incomplete', 'Cannot Reproduce', 'Invalid'):
test.warning("Resolution of bug is '%s' - assuming 'Open' for now." % self._resolution,
"Please check the bugreport manually and update this test.")
return True
return self._resolution not in ('Done', 'Fixed')
# this function tries to fetch the resolution from JIRA for the given bug
# if this isn't possible or the lookup is disabled it does only check the internal
# dict whether a function for the given bug is deposited or not
def __fetchResolutionFromJira__(self):
global JIRA_URL
bug = "%s-%d" % (self._bugType, self._number)
if bug in self._fetchResults_:
result = self._fetchResults_[bug]
self._resolution = result[0]
self._fix = result[1]
return
data = None
proxy = os.getenv("SYSTEST_PROXY", None)
try:
if proxy:
proxy = ProxyHandler({'https': proxy})
opener = build_opener(proxy)
install_opener(opener)
bugReport = urlopen('%s/%s' % (JIRA_URL, bug))
data = bugReport.read()
except:
data = self.__tryExternalTools__(proxy)
if data == None:
test.warning("Sorry, ssl module missing - cannot fetch data via HTTPS",
"Try to install the ssl module by yourself, or set the python "
"path inside SQUISHDIR/etc/paths.ini to use a python version with "
"ssl support OR install wget or curl to get rid of this warning!")
if data == None:
test.fatal("No resolution info for %s" % bug)
self._resolution = 'Done'
else:
if isinstance(data, (bytes)):
data = str(data)
data = data.replace("\r", "").replace("\n", "")
resPattern = re.compile('(?P.*?)')
resolution = resPattern.search(data)
fixVersion = 'None'
fixPattern = re.compile('(?P.*?)')
fix = fixPattern.search(data)
titlePattern = re.compile('title="(?P.*?)"')
if fix:
fix = titlePattern.search(fix.group('fix').strip())
if fix:
fixVersion = fix.group('title').strip()
self._fix = fixVersion
if resolution:
self._resolution = resolution.group("resolution").strip()
else:
test.fatal("FATAL: Cannot get resolution of bugreport %s" % bug,
"Looks like JIRA has changed.... Please verify!")
self._resolution = None
if self._resolution == None:
self.__cropAndLog__(data)
self._fetchResults_.update({bug:[self._resolution, self._fix]})
# simple helper function - used as fallback if python has no ssl support
# tries to find curl or wget in PATH and fetches data with it instead of
# using urllib2
def __tryExternalTools__(self, proxy=None):
global JIRA_URL
if proxy:
cmdAndArgs = { 'curl':['-k', '--proxy', proxy],
'wget':['-qO-']}
else:
cmdAndArgs = { 'curl':['-k'], 'wget':['-qO-']}
for call in cmdAndArgs:
prog = which(call)
if prog:
if call == 'wget' and proxy and os.getenv("https_proxy", None) == None:
test.warning("Missing environment variable https_proxy for using wget with proxy!")
cmdline = [prog] + cmdAndArgs[call]
cmdline += ['%s/%s-%d' % (JIRA_URL, self._bugType, self._number)]
return getOutputFromCmdline(cmdline)
return None
# this function crops multiple whitespaces from fetched and searches for expected
# ids without using regex
def __cropAndLog__(self, fetched):
if fetched == None:
test.log("None passed to __cropAndLog__()")
return
fetched = " ".join(fetched.split())
resoInd = fetched.find('resolution-val')
if resoInd == -1:
test.log("Resolution not found inside fetched data.",
"%s[...]" % fetched[:200])
else:
test.log("Fetched and cropped data: [...]%s[...]" % fetched[resoInd-20:resoInd+100])