我遇到了这个错误。有人可以建议这里有什么问题吗?
Traceback (most recent call last):
File ".\move2ready.py", line 318, in <module>
main()
File ".\move2ready.py", line 268, in main
success = moveToReady(prism, cr, pl_name)
File ".\move2ready.py", line 153, in moveToReady
retval = prism.saveChangeRequest(CR)
File ".\move2ready.py", line 75, in saveChangeRequest
request = self.soapclient.factory.create('ns4:SaveCRRequest')
File "build\bdist.win32\egg\suds\client.py", line 234, in create
suds.TypeNotFound: Type not found: 'ns4:SaveCRRequest'
完整代码:
#!/usr/bin/env python2.6
'''
When moving Prism CRs to the Ready state, it becomes quite tedious when users have to modify the state from from Open to Analysis to Fix to Ready for each CR. It will be time-saving if we have just ONE command line utility program that is able to pull a list of CRs from any intermediate
state, either Open or Analysis or Fix, and to Ready automatically.
Command line options:
-h / --help show this help message and exit
-c / --cr (required) provide the list of CR numbers separated by space.
-o / --fo provide an output file whose content is a summary of the results..
-p / --pl (required) provide the PL name.
-i / --fi (required if --cr is not specified) provide an input file which contains the list of CRs.
How to use:
Example 1:
python .\move2ready.py --cr 320538 320899 --pl MSM0000.NA.0.0
Example 2:
python .\move2ready.py --fi ./cr.txt --fo ./out.txt --pl MSM0000.NA.0.0
Note: A typical cr.txt can be:
CR320538
CR320899
CR321167
CR322928
'''
import datetime
import sys
import logging
import re
import getpass
from time import strftime as date
from optparse import OptionParser
try:
import suds
from suds.client import Client
from suds.transport import http
from suds.transport.https import WindowsHttpAuthenticated
except ImportError:
print '''###### ERROR ######
One or more prerequisite packages are missing.
Please install SUDS and NTLM Python packages before running this script.
To install SUDS and NTLM:
1. Find and install the correct version of Python SetupTools. (http://pypi.python.org/pypi/setuptools)
2. Copy the source files for SUDS and NTLM to a local directory (http://http://pypi.python.org)
3. For both SUDS and NTLM, cd into THE local directory, and run " Python setup.py install "
4. Close all command prompts and open a new one. That's it. :)
move2ready.py terminated!
'''
class Prism:
def __init__(self, url, q_user, q_passwd):
self.url = url
user = q_user
user = user.rstrip()
passwd = q_passwd
passwd = passwd.rstrip()
try:
self.soapclient = Client(url, transport=WindowsHttpAuthenticated(username=user, password=passwd))
request = self.soapclient.factory.create('ns2:CRRequest')
except:
print 'Prism authentication failed!'
sys.exit()
def getChangeRequestById(self, key):
request = self.soapclient.factory.create('ns2:CRRequest')
request['ChangeRequestId'] = key
response = self.soapclient.service.GetChangeRequestById([request])
return response['ChangeRequest']
def saveChangeRequest(self, CR):
request = self.soapclient.factory.create('ns4:SaveCRRequest')
request['ChangeRequest'] = CR
request['UserName'] = 'admin'
response = self.soapclient.service.SaveChangeRequest([request])
return response['ChangeRequestId']
def editObject(self, obj, **kwargs):
for key, value in kwargs.iteritems():
if key in obj:
obj[key] = value
return obj
def updateChangeRequest(self, CR, **kwargs):
newCR=editObject(CR, kwargs)
saveChangeRequest(newCR)
def updateChangeRequestById(self, CRkey, **kwargs):
CR = getChangeRequestById(CRkey)
return updateChangeRequest(CR, kwargs)
# end of Prism class
# Find the index of specified PL name among all PL names associated with this CR
def findTargetPlIndex(PL_all, pl_name, attr_name):
target_index = 0
for pl in PL_all:
if (pl[attr_name].lower() == pl_name.lower()):
return target_index
target_index += 1
print "[ERROR] The specified PL name is not found in this CR."
exit(-1)
# end of findTargetPlIndex
# When one move is performed, add some auto-generated text as Analysis Text
def addAnalysisText(CR, text):
if CR['Analysis'] == None:
CR['Analysis'] = []
CR['Analysis'].append({'Text':"Analyzed by move2ready tool"})
#else:
#CR['Analysis']['Text'] += "\n\n" + text
#CR['Analysis']['Text'] += "\n\n" +
# end of addAnalysisText
def moveToReady(prism, cr_id, pl_name):
print "======================================"
print "Start processing CR:" + cr_id + "..."
CR = prism.getChangeRequestById(cr_id)
PL_all = CR['ProductLines']['ProductLineEntity']
PL_index = findTargetPlIndex(PL_all, pl_name, 'ProductLineName')
PL = PL_all[PL_index]
# Move from open to analysis
if PL['Status'] == "Open":
print "Moving from Open to Analysis..."
PL['Status'] = "Analysis"
PL['AnalysisDueDate'] = datetime.datetime.today()
PL['Priority'] = "2"
retval = prism.saveChangeRequest(CR)
CR = prism.getChangeRequestById(cr_id)
PL = CR['ProductLines']['ProductLineEntity'][PL_index]
# Move from analysis to fix
if PL['Status'] == "Analysis":
print "Moving from Analysis to fix..."
PL['Status'] = "Fix"
addAnalysisText(CR, "move2ready utility moved this CR to Fix")
PL['ReadyDate'] = datetime.datetime.today() # required field
retval = prism.saveChangeRequest(CR)
CR = prism.getChangeRequestById(cr_id)
PL = CR['ProductLines']['ProductLineEntity'][PL_index]
# Move from Fix to Ready
if PL['Status'] == "Fix":
print "Moving from Fix to Ready..."
PL['Status'] = "Ready"
addAnalysisText(CR, "move2ready utility moved this CR to Ready")
retval = prism.saveChangeRequest(CR)
CR = prism.getChangeRequestById(cr_id)
PL = CR['ProductLines']['ProductLineEntity'][PL_index]
CR = prism.getChangeRequestById(cr_id)
PL = CR['ProductLines']['ProductLineEntity'][PL_index]
if PL['Status'] == "Ready":
return True
else:
return False
# end of moveToReady
# Handle variable number of arguments for an option
def vararg_callback(option, opt_str, value, parser):
assert value is None
value = []
def floatable(str):
try:
float(str)
return True
except ValueError:
return False
for arg in parser.rargs:
if arg[:2] == "--" and len(arg) > 2:
break
if arg[:1] == "-" and len(arg) > 1 and not floatable(arg):
break
value.append(arg)
del parser.rargs[:len(value)]
setattr(parser.values, option.dest, value)
# end of vararg_callback method
def handleCommandArgs():
desc = 'move2ready tool helps Prism users to move one or multiple CRs to Ready state automatically.'
usage = 'Python move2ready.py [options], version=1.0.0'
parser = OptionParser(description=desc, usage=usage)
parser.add_option('-c', '--cr', \
dest='cr', \
help='provide the list of CR numbers separated by space. E.g. --cr 320899 330022', \
action='callback', \
callback=vararg_callback)
parser.add_option('-i', '--fi', \
dest='fi', \
help='provide an input file which contains the list of CRs you want to move. ', \
action='store')
parser.add_option('-o', '--fo', \
dest='fo', \
help='provide an output file whose content is a summary of the results.', \
action='store')
parser.add_option('-p', '--pl', \
dest='pl', \
help='provide the PL name. E.g. --pl MPSS.NI.2.0',\
action='store')
(options, args) = parser.parse_args()
if not (options.fi or options.cr):
parser.error('No action requested, you must add "--cr" or "--fi" as argument.\n')
exit(1)
if not options.pl:
parser.error('No action requested, you must add "--pl" as argument.\n')
exit(1)
return options
# end of handleCommandArgs
#extract pure numeric CR values
def getCRFromFile(cr_list):
clean_cr_list = []
for cr in cr_list:
clean_cr_list.append(re.findall(r'\d+', cr)[-1])
return clean_cr_list
# end of getCRFromFile
def main():
options = handleCommandArgs()
file_in = options.fi
file_out = options.fo
cr_list = options.cr
pl_name = options.pl
# Use fi option to parse file-in which has cr lists
if cr_list == None:
f = open(file_in)
cr_list = f.readlines()
cr_list = getCRFromFile(cr_list)
f.close()
# Use fo option to parse file-out which saves the echo info
echo_to_file = False if file_out == None else True
if echo_to_file:
f = open(file_out, 'a+')
f.write('\n=====================================\n')
f.write(str(date('%Y-%m-%d %H:%M:%S')))
f.write('\n')
f.close()
username = raw_input('Enter your QualPass username (e.g. NA\jsmith): ')
password = getpass.getpass()
url = 'http://prism:8000/ChangeRequestWebService.svc?wsdl';
prism = Prism(url, username, password)
for cr in cr_list:
try:
result_log = ''
success = moveToReady(prism, cr, pl_name)
if success:
result_log = '[CR: ' + cr + '] ' + 'Successfully moved to Ready.\n';
print '''
.______ ___ _______. _______.
| _ \ / \ / | / |
| |_) | / ^ \ | (----` | (----`
| ___/ / /_\ \ \ \ \ \
| | / _____ \ .----) | .----) |
| _| /__/ \__\ |_______/ |_______/
'''
else:
result_log = '[CR: ' + cr + '] ' + 'Failed to move to Ready\n';
print '''
_______ ___ __ __
| ____| / \ | | | |
| |__ / ^ \ | | | |
| __| / /_\ \ | | | |
| | / _____ \ | | | `----.
|__| /__/ \__\ |__| |_______|
'''
if echo_to_file:
f = open(file_out, 'a+')
f.write(result_log)
f.close()
else:
print result_log
except suds.WebFault as detail:
print '[CR: ' + cr + '] ',
print detail
print '''
_______ ___ __ __
| ____| / \ | | | |
| |__ / ^ \ | | | |
| __| / /_\ \ | | | |
| | / _____ \ | | | `----.
|__| /__/ \__\ |__| |_______|
'''
if echo_to_file:
f = open(file_out, 'a+')
f.write(result_log)
f.close()
if __name__ == '__main__':
main()