[cubicweb-ctl] respect sys.exit status code when aborting a command
When exploring the stack of all calls to a cubicweb-ctl command, it has been
discovered than on a KeyboardInterrupt and on a SystemExit exception the base
class InstanceCommand (for commands that works on one instance) will always set
the return code of cubicweb-ctl to 8: this mean that if another command do a
`sys.exit(some_code)` the exit code will be ignored and overwritten by '8'.
This behavior is not intuitive, apparently not documented and doesn't seems to
have any justification. It also prevent commands from exciting with different
return codes which could be a desired behavior in the situation of scripting.
#!/usr/bin/env python"""Parser for Javascript comments."""importos.pathasospimportsys,os,getopt,redefclean_comment(match):comment=match.group()comment=strip_stars(comment)returncomment# Rest utilitiesdefrest_title(title,level,level_markups=['=','=','-','~','+','`']):size=len(title)iflevel==0:return'\n'.join((level_markups[level]*size,title,level_markups[0]*size))+'\n'return'\n'.join(('\n'+title,level_markups[level]*size))+'\n'defget_doc_comments(text):""" Return a list of all documentation comments in the file text. Each comment is a pair, with the first element being the comment text and the second element being the line after it, which may be needed to guess function & arguments. >>> get_doc_comments(read_file('examples/module.js'))[0][0][:40] '/**\n * This is the module documentation.' >>> get_doc_comments(read_file('examples/module.js'))[1][0][7:50] 'This is documentation for the first method.' >>> get_doc_comments(read_file('examples/module.js'))[1][1] 'function the_first_function(arg1, arg2) ' >>> get_doc_comments(read_file('examples/module.js'))[2][0] '/** This is the documentation for the second function. */' """return[clean_comment(match)formatchinre.finditer('/\*\*.*?\*/',text,re.DOTALL|re.MULTILINE)]RE_STARS=re.compile('^\s*?\* ?',re.MULTILINE)defstrip_stars(doc_comment):""" Strip leading stars from a doc comment. >>> strip_stars('/** This is a comment. */') 'This is a comment.' >>> strip_stars('/**\n * This is a\n * multiline comment. */') 'This is a\n multiline comment.' >>> strip_stars('/** \n\t * This is a\n\t * multiline comment. \n*/') 'This is a\n multiline comment.' """returnRE_STARS.sub('',doc_comment[3:-2]).strip()defparse_js_files(args=sys.argv):""" Main command-line invocation. """try:opts,args=getopt.gnu_getopt(args[1:],'p:o:h',['jspath=','output=','help'])opts=dict(opts)exceptgetopt.GetoptError:usage()sys.exit(2)rst_dir=opts.get('--output')oropts.get('-o')ifrst_dirisNoneandlen(args)!=1:rst_dir='apidocs'js_dir=opts.get('--jspath')oropts.get('-p')ifnotosp.exists(osp.join(rst_dir)):os.makedirs(osp.join(rst_dir))index=set()forjs_path,js_dirs,js_filesinos.walk(js_dir):rst_path=re.sub('%s%s*'%(js_dir,osp.sep),'',js_path)forjs_fileinjs_files:ifnotjs_file.endswith('.js'):continueifjs_fileinFILES_TO_IGNORE:continueifnotosp.exists(osp.join(rst_dir,rst_path)):os.makedirs(osp.join(rst_dir,rst_path))rst_content=extract_rest(js_path,js_file)filename=osp.join(rst_path,js_file[:-3])# add to indexindex.add(filename)# save rst filewithopen(osp.join(rst_dir,filename)+'.rst','wb')asf_rst:f_rst.write(rst_content)stream=open(osp.join(rst_dir,'index.rst'),'w')stream.write('''Javascript API==============.. toctree:: :maxdepth: 1''')# first write expected files in orderforfileidinINDEX_IN_ORDER:try:index.remove(fileid)exceptException:raiseException('Bad file id %s referenced in INDEX_IN_ORDER in %s, ''fix this please'%(fileid,__file__))stream.write(' %s\n'%fileid)# append remaining, by alphabetical orderforfileidinsorted(index):stream.write(' %s\n'%fileid)stream.close()defextract_rest(js_dir,js_file):js_filepath=osp.join(js_dir,js_file)filecontent=open(js_filepath,'U').read()comments=get_doc_comments(filecontent)rst=rest_title(js_file,0)rst+='.. module:: %s\n\n'%js_filerst+='\n\n'.join(comments)returnrstINDEX_IN_ORDER=['cubicweb','cubicweb.python','cubicweb.htmlhelpers','cubicweb.ajax','cubicweb.ajax.box','cubicweb.facets','cubicweb.widgets','cubicweb.image','cubicweb.flot','cubicweb.calendar','cubicweb.preferences','cubicweb.edition','cubicweb.reledit',]FILES_TO_IGNORE=set(['jquery.js','jquery.treeview.js','jquery.tablesorter.js','jquery.timePicker.js','jquery.flot.js','jquery.corner.js','jquery.ui.js','excanvas.js','gmap.utility.labeledmarker.js','cubicweb.fckcwconfig.js','cubicweb.fckcwconfig-full.js','cubicweb.compat.js',])if__name__=='__main__':parse_js_files()