changeset 11514:dc3c8df55905

added support for pylint and fixed errors/warnings it found
author Doug Simon <doug.simon@oracle.com>
date Tue, 03 Sep 2013 16:33:41 +0200
parents 8d4e5e08d83f
children 65d2f38c0aa5 1f03076a121b
files mx/.pylintrc mx/commands.py mx/outputparser.py mx/sanitycheck.py mxtool/.pylintrc mxtool/mx.py
diffstat 6 files changed, 978 insertions(+), 419 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mx/.pylintrc	Tue Sep 03 16:33:41 2013 +0200
@@ -0,0 +1,275 @@
+[MASTER]
+
+# Specify a configuration file.
+#rcfile=
+
+# Python code to execute, usually for sys.path manipulation such as
+# pygtk.require().
+#init-hook=
+
+# Profiled execution.
+profile=no
+
+# Add files or directories to the blacklist. They should be base names, not
+# paths.
+ignore=CVS
+
+# Pickle collected data for later comparisons.
+persistent=yes
+
+# List of plugins (as comma separated values of python modules names) to load,
+# usually to register additional checkers.
+load-plugins=
+
+
+[MESSAGES CONTROL]
+
+# Enable the message, report, category or checker with the given id(s). You can
+# either give multiple identifier separated by comma (,) or put this option
+# multiple time. See also the "--disable" option for examples.
+#enable=
+
+# Disable the message, report, category or checker with the given id(s). You
+# can either give multiple identifiers separated by comma (,) or put this
+# option multiple times (only on the command line, not in the configuration
+# file where it should appear only once).You can also use "--disable=all" to
+# disable everything first and then reenable specific checks. For example, if
+# you want to run only the similarities checker, you can use "--disable=all
+# --enable=similarities". If you want to run only the classes checker, but have
+# no Warning level messages displayed, use"--disable=all --enable=classes
+# --disable=W"
+disable=attribute-defined-outside-init,arguments-differ,
+        bare-except,global-statement,protected-access,redefined-outer-name,
+        unused-argument,star-args,pointless-string-statement,old-style-class,
+        too-many-lines,missing-docstring,no-init
+
+[REPORTS]
+
+# Set the output format. Available formats are text, parseable, colorized, msvs
+# (visual studio) and html. You can also give a reporter class, eg
+# mypackage.mymodule.MyReporterClass.
+output-format=text
+
+# Put messages in a separate file for each module / package specified on the
+# command line instead of printing them on stdout. Reports (if any) will be
+# written in a file name "pylint_global.[txt|html]".
+files-output=no
+
+# Tells whether to display a full report or only the messages
+reports=no
+
+# Python expression which should return a note less than 10 (10 is the highest
+# note). You have access to the variables errors warning, statement which
+# respectively contain the number of errors / warnings messages and the total
+# number of statements analyzed. This is used by the global evaluation report
+# (RP0004).
+evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
+
+# Add a comment according to your evaluation note. This is used by the global
+# evaluation report (RP0004).
+comment=no
+
+# Template used to display messages. This is a python new-style format string
+# used to format the massage information. See doc for all details
+#msg-template=
+
+
+[BASIC]
+
+# Required attributes for module, separated by a comma
+required-attributes=
+
+# List of builtins function names that should not be used, separated by a comma
+bad-functions=filter,apply,input
+
+# Regular expression which should only match correct module names
+module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
+
+# Regular expression which should only match correct module level names
+const-rgx=[a-zA-Z0-9_]{2,30}$
+
+# Regular expression which should only match correct class names
+class-rgx=[A-Z_][a-zA-Z0-9]+$
+
+# Regular expression which should only match correct function names
+function-rgx=[a-z_][a-zA-Z0-9_]{1,30}$
+
+# Regular expression which should only match correct method names
+method-rgx=[a-z_][a-zA-Z0-9_]{2,30}$
+
+# Regular expression which should only match correct instance attribute names
+attr-rgx=[a-z_][a-zA-Z0-9_]{1,30}$
+
+# Regular expression which should only match correct argument names
+argument-rgx=[a-z_][a-zA-Z0-9_]{0,30}$
+
+# Regular expression which should only match correct variable names
+variable-rgx=[a-z_][a-zA-Z0-9_]{0,30}$
+
+# Regular expression which should only match correct attribute names in class
+# bodies
+class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
+
+# Regular expression which should only match correct list comprehension /
+# generator expression variable names
+inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
+
+# Good variable names which should always be accepted, separated by a comma
+good-names=i,j,k,ex,Run,_
+
+# Bad variable names which should always be refused, separated by a comma
+bad-names=foo,bar,baz,toto,tutu,tata
+
+# Regular expression which should only match function or class names that do
+# not require a docstring.
+no-docstring-rgx=.*
+
+# Minimum line length for functions/classes that require docstrings, shorter
+# ones are exempt.
+docstring-min-length=-1
+
+
+[FORMAT]
+
+# Maximum number of characters on a single line.
+max-line-length=300
+
+# Regexp for a line that is allowed to be longer than the limit.
+ignore-long-lines=^\s*(# )?<?https?://\S+>?$
+
+# Maximum number of lines in a module
+max-module-lines=1000
+
+# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
+# tab).
+indent-string='    '
+
+
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+notes=FIXME
+
+
+[SIMILARITIES]
+
+# Minimum lines number of a similarity.
+min-similarity-lines=4
+
+# Ignore comments when computing similarities.
+ignore-comments=yes
+
+# Ignore docstrings when computing similarities.
+ignore-docstrings=yes
+
+# Ignore imports when computing similarities.
+ignore-imports=no
+
+
+[TYPECHECK]
+
+# Tells whether missing members accessed in mixin class should be ignored. A
+# mixin class is detected if its name ends with "mixin" (case insensitive).
+ignore-mixin-members=yes
+
+# List of classes names for which member attributes should not be checked
+# (useful for classes with attributes dynamically set).
+ignored-classes=SQLObject
+
+# When zope mode is activated, add a predefined set of Zope acquired attributes
+# to generated-members.
+zope=no
+
+# List of members which are set dynamically and missed by pylint inference
+# system, and so shouldn't trigger E0201 when accessed. Python regular
+# expressions are accepted.
+generated-members=REQUEST,acl_users,aq_parent
+
+
+[VARIABLES]
+
+# Tells whether we should check for unused import in __init__ files.
+init-import=no
+
+# A regular expression matching the beginning of the name of dummy variables
+# (i.e. not used).
+dummy-variables-rgx=_$|dummy
+
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid to define new builtins when possible.
+additional-builtins=
+
+
+[CLASSES]
+
+# List of interface methods to ignore, separated by a comma. This is used for
+# instance to not check methods defines in Zope's Interface base class.
+ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
+
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,__new__,setUp
+
+# List of valid names for the first argument in a class method.
+valid-classmethod-first-arg=cls
+
+# List of valid names for the first argument in a metaclass class method.
+valid-metaclass-classmethod-first-arg=mcs
+
+
+[DESIGN]
+
+# Maximum number of arguments for function / method
+max-args=5
+
+# Argument names that match this expression will be ignored. Default to name
+# with leading underscore
+ignored-argument-names=_.*
+
+# Maximum number of locals for function / method body
+max-locals=15
+
+# Maximum number of return / yield for function / method body
+max-returns=6
+
+# Maximum number of branch for function / method body
+max-branches=12
+
+# Maximum number of statements in function / method body
+max-statements=50
+
+# Maximum number of parents for a class (see R0901).
+max-parents=7
+
+# Maximum number of attributes for a class (see R0902).
+max-attributes=7
+
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=2
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
+
+
+[IMPORTS]
+
+# Deprecated modules which should not be used, separated by a comma
+deprecated-modules=regsub,TERMIOS,Bastion,rexec
+
+# Create a graph of every (i.e. internal and external) dependencies in the
+# given file (report RP0402 must not be disabled)
+import-graph=
+
+# Create a graph of external dependencies in the given file (report RP0402 must
+# not be disabled)
+ext-import-graph=
+
+# Create a graph of internal dependencies in the given file (report RP0402 must
+# not be disabled)
+int-import-graph=
+
+
+[EXCEPTIONS]
+
+# Exceptions that will emit a warning when being caught. Defaults to
+# "Exception"
+overgeneral-exceptions=Exception
--- a/mx/commands.py	Tue Sep 03 14:14:09 2013 +0200
+++ b/mx/commands.py	Tue Sep 03 16:33:41 2013 +0200
@@ -45,10 +45,10 @@
 _vmChoices = {
     'graal' : 'All compilation is performed with Graal. This includes bootstrapping Graal itself unless -XX:-BootstrapGraal is used.',
     'server' : 'Normal compilation is performed with the tiered system (i.e., client + server), Truffle compilation is performed with Graal. Use this for optimal Truffle performance.',
-    'client' : None, # normal compilation with client compiler, explicit compilation (e.g., by Truffle) with Graal
-    'server-nograal' : None, # all compilation with tiered system (i.e., client + server), Graal omitted
-    'client-nograal' : None, # all compilation with client compiler, Graal omitted
-    'original' : None, # default VM copied from bootstrap JDK
+    'client' : None,  # normal compilation with client compiler, explicit compilation (e.g., by Truffle) with Graal
+    'server-nograal' : None,  # all compilation with tiered system (i.e., client + server), Graal omitted
+    'client-nograal' : None,  # all compilation with client compiler, Graal omitted
+    'original' : None,  # default VM copied from bootstrap JDK
 }
 
 """ The VM that will be run by the 'vm' command and built by default by the 'build' command.
@@ -101,7 +101,7 @@
     _vm = vm
     return vm
 
-""" 
+"""
 A context manager that can be used with the 'with' statement to set the VM
 used by all VM executions within the scope of the 'with' statement. For example:
 
@@ -116,17 +116,17 @@
         self.build = build if build else _vmbuild
         self.previousVm = _vm
         self.previousBuild = _vmbuild
-        
+
     def __enter__(self):
         global _vm, _vmbuild
         _vm = self.vm
         _vmbuild = self.build
-        
+
     def __exit__(self, exc_type, exc_value, traceback):
         global _vm, _vmbuild
         _vm = self.previousVm
         _vmbuild = self.previousBuild
-    
+
 def _chmodDir(chmodFlags, dirname, fnames):
     os.chmod(dirname, chmodFlags)
     for name in fnames:
@@ -144,7 +144,7 @@
                 shutil.rmtree(name)
             elif os.path.isfile(name):
                 os.unlink(name)
-                
+
         rmIfExists(join(_graal_home, 'build'))
         rmIfExists(join(_graal_home, 'build-nograal'))
         rmIfExists(_jdksDir())
@@ -153,7 +153,7 @@
 def export(args):
     """create a GraalVM zip file for distribution"""
 
-    parser = ArgumentParser(prog='mx export');
+    parser = ArgumentParser(prog='mx export')
     parser.add_argument('--omit-vm-build', action='store_false', dest='vmbuild', help='omit VM build step')
     parser.add_argument('--omit-dist-init', action='store_false', dest='distInit', help='omit class files and IDE configurations from distribution')
     parser.add_argument('zipfile', nargs=REMAINDER, metavar='zipfile')
@@ -200,13 +200,13 @@
     vmOpts, benchmarksAndOptions = _extract_VM_args(args, useDoubleDash=availableBenchmarks is None)
 
     if availableBenchmarks is None:
-        harnessArgs = benchmarksAndOptions 
+        harnessArgs = benchmarksAndOptions
         return runBenchmark(None, harnessArgs, vmOpts)
 
     if len(benchmarksAndOptions) == 0:
         mx.abort('at least one benchmark name or "all" must be specified')
     benchmarks = list(itertools.takewhile(lambda x: not x.startswith('-'), benchmarksAndOptions))
-    harnessArgs = benchmarksAndOptions[len(benchmarks):] 
+    harnessArgs = benchmarksAndOptions[len(benchmarks):]
 
     if 'all' in benchmarks:
         benchmarks = availableBenchmarks
@@ -228,7 +228,7 @@
 
     def launcher(bm, harnessArgs, extraVmOpts):
         return sanitycheck.getDacapo(bm, harnessArgs).test(_get_vm(), extraVmOpts=extraVmOpts)
-        
+
     _run_benchmark(args, sanitycheck.dacapoSanityWarmup.keys(), launcher)
 
 def scaladacapo(args):
@@ -332,7 +332,7 @@
             if mx.get_os() != 'windows':
                 chmodRecursive(jdk, 0755)
             shutil.move(join(_vmLibDirInJdk(jdk), defaultVM), join(_vmLibDirInJdk(jdk), 'original'))
-            
+
 
             with open(jvmCfg, 'w') as fp:
                 for line in jvmCfgLines:
@@ -348,10 +348,10 @@
             if _installed_jdks and mx._opts.verbose:
                 mx.log("Could not find JDK directory at " + jdk)
             _handle_missing_VM(build, vmToCheck if vmToCheck else 'graal')
-            
+
     if installGraalJar:
         _installGraalJarInJdks(mx.distribution('GRAAL'))
-    
+
     if vmToCheck is not None:
         jvmCfg = _vmCfgInJdk(jdk)
         found = False
@@ -362,7 +362,7 @@
                     break
         if not found:
             _handle_missing_VM(build, vmToCheck)
-        
+
     return jdk
 
 def _installGraalJarInJdks(graalDist):
@@ -378,25 +378,27 @@
                 shutil.copyfile(graalJar, tmp)
                 os.close(fd)
                 shutil.move(tmp, join(jreLibDir, 'graal.jar'))
-                
+
                 if exists(graalOptions):
                     shutil.copy(graalOptions, join(jreLibDir, 'graal.options'))
 
 # run a command in the windows SDK Debug Shell
-def _runInDebugShell(cmd, workingDir, logFile=None, findInOutput=None, respondTo={}):
+def _runInDebugShell(cmd, workingDir, logFile=None, findInOutput=None, respondTo=None):
+    if respondTo is None:
+        respondTo = {}
     newLine = os.linesep
-    STARTTOKEN = 'RUNINDEBUGSHELL_STARTSEQUENCE'
-    ENDTOKEN = 'RUNINDEBUGSHELL_ENDSEQUENCE'
+    startToken = 'RUNINDEBUGSHELL_STARTSEQUENCE'
+    endToken = 'RUNINDEBUGSHELL_ENDSEQUENCE'
 
     winSDK = mx.get_env('WIN_SDK', 'C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\')
-    
+
     if not exists(winSDK):
         mx.abort("Could not find Windows SDK : '" + winSDK + "' does not exist")
-        
+
     if not exists(join(winSDK, 'Bin', 'SetEnv.cmd')):
         mx.abort("Invalid Windows SDK path (" + winSDK + ") : could not find Bin/SetEnv.cmd (you can use the WIN_SDK environment variable to specify an other path)")
 
-    p = subprocess.Popen('cmd.exe /E:ON /V:ON /K ""' + winSDK + '/Bin/SetEnv.cmd" & echo ' + STARTTOKEN + '"', \
+    p = subprocess.Popen('cmd.exe /E:ON /V:ON /K ""' + winSDK + '/Bin/SetEnv.cmd" & echo ' + startToken + '"', \
             shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
     stdout = p.stdout
     stdin = p.stdin
@@ -404,20 +406,20 @@
         log = open(logFile, 'w')
     ret = False
     while True:
-        
+
         # encoding may be None on windows plattforms
         if sys.stdout.encoding is None:
             encoding = 'utf-8'
         else:
             encoding = sys.stdout.encoding
-        
+
         line = stdout.readline().decode(encoding)
         if logFile:
             log.write(line.encode('utf-8'))
         line = line.strip()
         mx.log(line)
-        if line == STARTTOKEN:
-            stdin.write('cd /D ' + workingDir + ' & ' + cmd + ' & echo ' + ENDTOKEN + newLine)
+        if line == startToken:
+            stdin.write('cd /D ' + workingDir + ' & ' + cmd + ' & echo ' + endToken + newLine)
         for regex in respondTo.keys():
             match = regex.search(line)
             if match:
@@ -426,7 +428,7 @@
             match = findInOutput.search(line)
             if match:
                 ret = True
-        if line == ENDTOKEN:
+        if line == endToken:
             if not findInOutput:
                 stdin.write('echo ERRXXX%errorlevel%' + newLine)
             else:
@@ -434,7 +436,7 @@
         if line.startswith('ERRXXX'):
             if line == 'ERRXXX0':
                 ret = True
-            break;
+            break
     stdin.write('exit' + newLine)
     if logFile:
         log.close()
@@ -456,16 +458,16 @@
         'INSTALL' : 'Install the built VM into the JDK? (default: y)',
         'ZIP_DEBUGINFO_FILES' : 'Install zipped debug symbols file? (default: 0)',
     }
-    
+
     mx.log('HotSpot build variables that can be set by the -D option to "mx build":')
     mx.log('')
     for n in sorted(buildVars.iterkeys()):
         mx.log(n)
         mx.log(textwrap.fill(buildVars[n], initial_indent='    ', subsequent_indent='    ', width=200))
-        
+
     mx.log('')
     mx.log('Note that these variables can be given persistent values in the file ' + join(_graal_home, 'mx', 'env') + ' (see \'mx about\').')
-    
+
 def build(args, vm=None):
     """build the VM binary
 
@@ -486,7 +488,7 @@
             return result
 
     # Call mx.build to compile the Java sources
-    parser=AP()
+    parser = AP()
     parser.add_argument('--export-dir', help='directory to which graal.jar and graal.options will be copied', metavar='<path>')
     parser.add_argument('-D', action='append', help='set a HotSpot build variable (run \'mx buildvars\' to list variables)', metavar='name=value')
     opts2 = mx.build(['--source', '1.7'] + args, parser=parser)
@@ -520,11 +522,11 @@
     else:
         assert vm == 'graal', vm
         buildSuffix = 'graal'
-        
+
     if _installed_jdks:
-        if not mx.ask_yes_no("You are going to build while --installed-jdks is set (" + _installed_jdks + ") are you sure you want to continue", 'n'):
+        if not mx.ask_yes_no("You are going to build because --installed-jdks is set (" + _installed_jdks + ") - are you sure you want to continue", 'n'):
             mx.abort(1)
-        
+
     for build in builds:
         if build == 'ide-build-target':
             build = os.environ.get('IDE_BUILD_TARGET', None)
@@ -579,7 +581,7 @@
             variant = {'client': 'compiler1', 'server': 'compiler2'}.get(vm, vm)
             project_config = variant + '_' + build
             _runInDebugShell('msbuild ' + _graal_home + r'\build\vs-amd64\jvm.vcproj /p:Configuration=' + project_config + ' /target:clean', _graal_home)
-            winCompileCmd = r'set HotSpotMksHome=' + mksHome + r'& set OUT_DIR=' + jdk + r'& set JAVA_HOME=' + jdk + r'& set path=%JAVA_HOME%\bin;%path%;%HotSpotMksHome%& cd /D "' +_graal_home + r'\make\windows"& call create.bat ' + _graal_home
+            winCompileCmd = r'set HotSpotMksHome=' + mksHome + r'& set OUT_DIR=' + jdk + r'& set JAVA_HOME=' + jdk + r'& set path=%JAVA_HOME%\bin;%path%;%HotSpotMksHome%& cd /D "' + _graal_home + r'\make\windows"& call create.bat ' + _graal_home
             print(winCompileCmd)
             winCompileSuccess = re.compile(r"^Writing \.vcxproj file:")
             if not _runInDebugShell(winCompileCmd, _graal_home, compilelogfile, winCompileSuccess):
@@ -592,14 +594,14 @@
         else:
             cpus = multiprocessing.cpu_count()
             runCmd = [mx.gmake_cmd()]
-            runCmd.append(build + buildSuffix) 
+            runCmd.append(build + buildSuffix)
             env = os.environ.copy()
-            
+
             if opts2.D:
                 for nv in opts2.D:
                     name, value = nv.split('=', 1)
                     env[name.strip()] = value
-            
+
             env.setdefault('ARCH_DATA_MODEL', '64')
             env.setdefault('LANG', 'C')
             env.setdefault('HOTSPOT_BUILD_JOBS', str(cpus))
@@ -647,7 +649,7 @@
                 if line.strip() == vmKnown.strip():
                     found = True
                 lines.append(line)
-                
+
         if not found:
             mx.log('Appending "' + prefix + 'KNOWN" to ' + jvmCfg)
             if mx.get_os() != 'windows':
@@ -701,7 +703,7 @@
         for p in mx.projects():
             excludes += _find_classes_with_annotations(p, None, ['@Snippet', '@ClassSubstitution', '@Test'], includeInnerClasses=True).keys()
             excludes += p.find_classes_with_matching_source_line(None, lambda line: 'JaCoCo Exclude' in line, includeInnerClasses=True).keys()
-            
+
         includes = ['com.oracle.graal.*']
         agentOptions = {
                         'append' : 'true' if _jacoco == 'append' else 'false',
@@ -716,12 +718,12 @@
 
     exe = join(jdk, 'bin', mx.exe_suffix('java'))
     pfx = _vm_prefix.split() if _vm_prefix is not None else []
-    
+
     if '-version' in args:
-        ignoredArgs = args[args.index('-version')+1:]
+        ignoredArgs = args[args.index('-version') + 1:]
         if  len(ignoredArgs) > 0:
             mx.log("Warning: The following options will be ignored by the vm because they come after the '-version' argument: " + ' '.join(ignoredArgs))
-    
+
     return mx.run(pfx + [exe, '-' + vm] + args, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd, timeout=timeout)
 
 def _find_classes_with_annotations(p, pkgRoot, annotations, includeInnerClasses=False):
@@ -730,7 +732,7 @@
     (ignoring preceding whitespace) and return the fully qualified class name for each Java
     source file matched in a list.
     """
-    
+
     matches = lambda line : len([a for a in annotations if line == a or line.startswith(a + '(')]) != 0
     return p.find_classes_with_matching_source_line(pkgRoot, matches, includeInnerClasses)
 
@@ -742,7 +744,7 @@
         if useDoubleDash:
             if args[i] == '--':
                 vmArgs = args[:i]
-                remainder = args[i + 1:] 
+                remainder = args[i + 1:]
                 return vmArgs, remainder
         else:
             if not args[i].startswith('-'):
@@ -752,25 +754,19 @@
                     else:
                         continue
                 vmArgs = args[:i]
-                remainder = args[i:] 
+                remainder = args[i:]
                 return vmArgs, remainder
-            
+
     return args, []
-    
+
 def _run_tests(args, harness, annotations, testfile):
-    
-    
+
+
     vmArgs, tests = _extract_VM_args(args)
     for t in tests:
         if t.startswith('-'):
             mx.abort('VM option ' + t + ' must precede ' + tests[0])
 
-    def containsAny(c, substrings):
-        for s in substrings:
-            if s in c:
-                return True
-        return False
-    
     candidates = []
     for p in mx.projects():
         if mx.java().javaCompliance < p.javaCompliance:
@@ -835,14 +831,14 @@
 
     If filters are supplied, only tests whose fully qualified name
     includes a filter as a substring are run.
-    
+
     For example, this command line:
-    
+
        mx unittest -G:Dump= -G:MethodFilter=BC_aload.* -G:+PrintCFG BC_aload
-    
+
     will run all JUnit test classes that contain 'BC_aload' in their
-    fully qualified name and will pass these options to the VM: 
-    
+    fully qualified name and will pass these options to the VM:
+
         -G:Dump= -G:MethodFilter=BC_aload.* -G:+PrintCFG
 
     To get around command line length limitations on some OSes, the
@@ -855,7 +851,7 @@
     As with all other commands, using the global '-v' before 'unittest'
     command will cause mx to show the complete command line
     it uses to run the VM.
-""" 
+"""
 
 def unittest(args):
     """run the JUnit tests (all testcases){0}"""
@@ -877,8 +873,8 @@
 
     vmsDefault = ','.join(_vmChoices.keys())
     vmbuildsDefault = ','.join(_vmbuildChoices)
-    
-    parser = ArgumentParser(prog='mx buildvms');
+
+    parser = ArgumentParser(prog='mx buildvms')
     parser.add_argument('--vms', help='a comma separated list of VMs to build (default: ' + vmsDefault + ')', metavar='<args>', default=vmsDefault)
     parser.add_argument('--builds', help='a comma separated list of build types (default: ' + vmbuildsDefault + ')', metavar='<args>', default=vmbuildsDefault)
     parser.add_argument('-n', '--no-check', action='store_true', help='omit running "java -version" after each build')
@@ -899,7 +895,8 @@
                 start = time.time()
                 mx.log('BEGIN: ' + v + '-' + vmbuild + '\t(see: ' + logFile + ')')
                 # Run as subprocess so that output can be directed to a file
-                subprocess.check_call([sys.executable, '-u', join('mxtool', 'mx.py'), '--vm', v, '--vmbuild', vmbuild, 'build'], cwd=_graal_home, stdout=log, stderr=subprocess.STDOUT)
+                subprocess.check_call([sys.executable, '-u', join('mxtool', 'mx.py'), '--vm', v, '--vmbuild',
+                                       vmbuild, 'build'], cwd=_graal_home, stdout=log, stderr=subprocess.STDOUT)
                 duration = datetime.timedelta(seconds=time.time() - start)
                 mx.log('END:   ' + v + '-' + vmbuild + '\t[' + str(duration) + ']')
             else:
@@ -938,7 +935,7 @@
             mx.abort(codeOrMessage)
             return self
 
-    parser = ArgumentParser(prog='mx gate');
+    parser = ArgumentParser(prog='mx gate')
     parser.add_argument('-j', '--omit-java-clean', action='store_false', dest='cleanJava', help='omit cleaning Java native code')
     parser.add_argument('-n', '--omit-native-clean', action='store_false', dest='cleanNative', help='omit cleaning and building native code')
     parser.add_argument('-g', '--only-build-graalvm', action='store_false', dest='buildNonGraal', help='only build the Graal VM')
@@ -947,7 +944,7 @@
     args = parser.parse_args(args)
 
     global _jacoco
-    
+
     tasks = []
     total = Task('Gate')
     try:
@@ -978,7 +975,7 @@
         if mx.canonicalizeprojects([]) != 0:
             t.abort('Rerun "mx canonicalizeprojects" and check-in the modified mx/projects files.')
         tasks.append(t.stop())
-        
+
         t = Task('BuildJava')
         build(['--no-native', '--jdt-warning-as-error'])
         tasks.append(t.stop())
@@ -987,10 +984,10 @@
         if mx.checkstyle([]) != 0:
             t.abort('Checkstyle warnings were found')
         tasks.append(t.stop())
-        
+
         if exists('jacoco.exec'):
             os.unlink('jacoco.exec')
-        
+
         if args.jacocout is not None:
             _jacoco = 'append'
         else:
@@ -1009,10 +1006,10 @@
             t = Task('BootstrapWithGCVerification:product')
             vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'])
             tasks.append(t.stop())
-    
+
         with VM('graal', 'product'):
             t = Task('BootstrapWithG1GCVerification:product')
-            vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:-UseSerialGC','-XX:+UseG1GC','-XX:+UseNewCode','-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'])
+            vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:-UseSerialGC', '-XX:+UseG1GC', '-XX:+UseNewCode', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'])
             tasks.append(t.stop())
 
         with VM('graal', 'product'):
@@ -1025,7 +1022,7 @@
             vm(['-G:+AOTCompilation', '-G:+VerifyPhases', '-esa', '-version'])
             tasks.append(t.stop())
 
-        with VM('server', 'product'): # hosted mode
+        with VM('server', 'product'):  # hosted mode
             t = Task('UnitTests:hosted-product')
             unittest([])
             tasks.append(t.stop())
@@ -1039,7 +1036,7 @@
 
         if args.jacocout is not None:
             jacocoreport([args.jacocout])
-            
+
         _jacoco = 'off'
 
         t = Task('CleanAndBuildGraalVisualizer')
@@ -1060,7 +1057,7 @@
                         t = Task('DaCapo_pmd:' + theVm + ':' + vmbuild)
                         dacapo(['pmd'])
                         tasks.append(t.stop())
-    
+
                         t = Task('UnitTests:' + theVm + ':' + vmbuild)
                         unittest(['-XX:CompileCommand=exclude,*::run*', 'graal.api'])
                         tasks.append(t.stop())
@@ -1080,7 +1077,7 @@
         mx.log('  ' + str(t.duration) + '\t' + t.title)
     mx.log('  =======')
     mx.log('  ' + str(total.duration))
-    
+
 def deoptalot(args):
     """bootstrap a fastdebug Graal VM with DeoptimizeALot and VerifyOops on
 
@@ -1090,15 +1087,15 @@
     if len(args) > 0 and args[0].isdigit():
         count = int(args[0])
         del args[0]
-    
+
     for _ in range(count):
         if not vm(['-XX:+DeoptimizeALot', '-XX:+VerifyOops'] + args + ['-version'], vmbuild='fastdebug') == 0:
             mx.abort("Failed")
-            
+
 def longtests(args):
-    
+
     deoptalot(['15', '-Xmx48m'])
-    
+
     dacapo(['100', 'eclipse', '-esa'])
 
 def gv(args):
@@ -1133,7 +1130,7 @@
     vm = _get_vm()
     if len(args) is 0:
         args = ['all']
-    
+
     vmArgs = [arg for arg in args if arg.startswith('-')]
 
     def benchmarks_in_group(group):
@@ -1142,7 +1139,7 @@
 
     results = {}
     benchmarks = []
-    #DaCapo
+    # DaCapo
     if ('dacapo' in args or 'all' in args):
         benchmarks += sanitycheck.getDacapos(level=sanitycheck.SanityCheckLevel.Benchmark)
     else:
@@ -1165,23 +1162,23 @@
             if (iterations > 0):
                 benchmarks += [sanitycheck.getScalaDacapo(scaladacapo, ['-n', str(iterations)])]
 
-    #Bootstrap
+    # Bootstrap
     if ('bootstrap' in args or 'all' in args):
         benchmarks += sanitycheck.getBootstraps()
-    #SPECjvm2008
+    # SPECjvm2008
     if ('specjvm2008' in args or 'all' in args):
         benchmarks += [sanitycheck.getSPECjvm2008(['-ikv', '-wt', '120', '-it', '120'])]
     else:
         specjvms = benchmarks_in_group('specjvm2008')
         for specjvm in specjvms:
             benchmarks += [sanitycheck.getSPECjvm2008(['-ikv', '-wt', '120', '-it', '120', specjvm])]
-            
+
     if ('specjbb2005' in args or 'all' in args):
         benchmarks += [sanitycheck.getSPECjbb2005()]
-        
-    if ('specjbb2013' in args): # or 'all' in args //currently not in default set
+
+    if ('specjbb2013' in args):  # or 'all' in args //currently not in default set
         benchmarks += [sanitycheck.getSPECjbb2013()]
-        
+
     if ('ctw-full' in args):
         benchmarks.append(sanitycheck.getCTW(vm, sanitycheck.CTWMode.Full))
     if ('ctw-noinline' in args):
@@ -1200,10 +1197,10 @@
 
 def specjvm2008(args):
     """run one or more SPECjvm2008 benchmarks"""
-    
+
     def launcher(bm, harnessArgs, extraVmOpts):
         return sanitycheck.getSPECjvm2008(harnessArgs + [bm]).bench(_get_vm(), extraVmOpts=extraVmOpts)
-    
+
     availableBenchmarks = set(sanitycheck.specjvm2008Names)
     for name in sanitycheck.specjvm2008Names:
         parts = name.rsplit('.', 1)
@@ -1214,23 +1211,23 @@
             availableBenchmarks.add(group)
 
     _run_benchmark(args, sorted(availableBenchmarks), launcher)
-    
+
 def specjbb2013(args):
     """runs the composite SPECjbb2013 benchmark"""
-    
+
     def launcher(bm, harnessArgs, extraVmOpts):
         assert bm is None
         return sanitycheck.getSPECjbb2013(harnessArgs).bench(_get_vm(), extraVmOpts=extraVmOpts)
-    
+
     _run_benchmark(args, None, launcher)
 
 def specjbb2005(args):
     """runs the composite SPECjbb2005 benchmark"""
-    
+
     def launcher(bm, harnessArgs, extraVmOpts):
         assert bm is None
         return sanitycheck.getSPECjbb2005(harnessArgs).bench(_get_vm(), extraVmOpts=extraVmOpts)
-    
+
     _run_benchmark(args, None, launcher)
 
 def hsdis(args, copyToDir=None):
@@ -1254,17 +1251,17 @@
     Run a tool over the input files to convert all embedded HexCodeFiles
     to a disassembled format."""
 
-    parser = ArgumentParser(prog='mx hcfdis');
+    parser = ArgumentParser(prog='mx hcfdis')
     parser.add_argument('-m', '--map', help='address to symbol map applied to disassembler output')
     parser.add_argument('files', nargs=REMAINDER, metavar='files...')
 
     args = parser.parse_args(args)
-    
+
     path = join(_graal_home, 'lib', 'hcfdis-1.jar')
     if not exists(path):
         mx.download(path, ['http://lafo.ssw.uni-linz.ac.at/hcfdis-1.jar'])
     mx.run_java(['-jar', path] + args.files)
-    
+
     if args.map is not None:
         addressRE = re.compile(r'0[xX]([A-Fa-f0-9]+)')
         with open(args.map) as fp:
@@ -1273,8 +1270,8 @@
         for l in lines:
             addressAndSymbol = l.split(' ', 1)
             if len(addressAndSymbol) == 2:
-                address, symbol = addressAndSymbol;
-                if address.startswith('0x'): 
+                address, symbol = addressAndSymbol
+                if address.startswith('0x'):
                     address = long(address, 16)
                     symbols[address] = symbol
         for f in args.files:
@@ -1364,7 +1361,7 @@
 
     if (_vmSourcesAvailable):
         mx.add_argument('--vm', action='store', dest='vm', choices=_vmChoices.keys(), help='the VM type to build/run')
-        mx.add_argument('--vmbuild', action='store', dest='vmbuild', choices=_vmbuildChoices, help='the VM build to build/run (default: ' + _vmbuildChoices[0] +')')
+        mx.add_argument('--vmbuild', action='store', dest='vmbuild', choices=_vmbuildChoices, help='the VM build to build/run (default: ' + _vmbuildChoices[0] + ')')
         mx.add_argument('--ecl', action='store_true', dest='make_eclipse_launch', help='create launch configuration for running VM execution(s) in Eclipse')
         mx.add_argument('--vmprefix', action='store', dest='vm_prefix', help='prefix for running the VM (e.g. "/usr/bin/gdb --args")', metavar='<prefix>')
         mx.add_argument('--gdb', action='store_const', const='/usr/bin/gdb --args', dest='vm_prefix', help='alias for --vmprefix "/usr/bin/gdb --args"')
@@ -1373,9 +1370,9 @@
             'export': [export, '[-options] [zipfile]'],
         })
 
-    mx.commands.update(commands)
+    mx._commands.update(commands)
 
-def mx_post_parse_cmd_line(opts):#
+def mx_post_parse_cmd_line(opts):  #
     # TODO _minVersion check could probably be part of a Suite in mx?
     if (mx.java().version < _minVersion) :
         mx.abort('Requires Java version ' + str(_minVersion) + ' or greater, got version ' + str(mx.java().version))
--- a/mx/outputparser.py	Tue Sep 03 14:14:09 2013 +0200
+++ b/mx/outputparser.py	Tue Sep 03 16:33:41 2013 +0200
@@ -26,13 +26,13 @@
 import re
 
 class OutputParser:
-    
+
     def __init__(self):
         self.matchers = []
-        
+
     def addMatcher(self, matcher):
         self.matchers.append(matcher)
-    
+
     def parse(self, output):
         valueMaps = []
         for matcher in self.matchers:
@@ -47,12 +47,12 @@
 given as the group name enclosed in '<' and '>'.
 """
 class ValuesMatcher:
-    
+
     def __init__(self, regex, valuesTemplate):
         assert isinstance(valuesTemplate, dict)
         self.regex = regex
         self.valuesTemplate = valuesTemplate
-        
+
     def parse(self, text, valueMaps):
         for match in self.regex.finditer(text):
             valueMap = {}
@@ -62,10 +62,10 @@
                 assert not valueMap.has_key(key), key
                 valueMap[key] = value
             valueMaps.append(valueMap)
-        
+
     def get_template_value(self, match, template):
         def replace_var(m):
             groupName = m.group(1)
             return match.group(groupName)
-        
+
         return re.sub(r'<([\w]+)>', replace_var, template)
--- a/mx/sanitycheck.py	Tue Sep 03 14:14:09 2013 +0200
+++ b/mx/sanitycheck.py	Tue Sep 03 16:33:41 2013 +0200
@@ -27,31 +27,31 @@
 import re, mx, commands, os, sys, StringIO, subprocess
 from os.path import isfile, join, exists
 
-gc='UseSerialGC'
+gc = 'UseSerialGC'
 
 dacapoSanityWarmup = {
-    'avrora':     [0, 0,  3,  6, 13],
-    'batik':      [0, 0,  5,  5, 20],
-    'eclipse':    [2, 4,  5, 10, 16],
+    'avrora':     [0, 0, 3, 6, 13],
+    'batik':      [0, 0, 5, 5, 20],
+    'eclipse':    [2, 4, 5, 10, 16],
     'fop':        [4, 8, 10, 20, 30],
-    'h2':         [0, 0,  5,  5,  8],
-    'jython':     [0, 0,  5, 10, 13],
-    'luindex':    [0, 0,  5, 10, 10],
-    'lusearch':   [0, 4,  5,  5,  8],
-    'pmd':        [0, 0,  5, 10, 13],
-    'sunflow':    [0, 2,  5, 10, 15],
-    'tomcat':     [0, 0,  5, 10, 15],
-    'tradebeans': [0, 0,  5, 10, 13],
-    'tradesoap':  [2, 4,  5, 10, 15],
-    'xalan':      [0, 0,  5, 10, 18],
+    'h2':         [0, 0, 5, 5, 8],
+    'jython':     [0, 0, 5, 10, 13],
+    'luindex':    [0, 0, 5, 10, 10],
+    'lusearch':   [0, 4, 5, 5, 8],
+    'pmd':        [0, 0, 5, 10, 13],
+    'sunflow':    [0, 2, 5, 10, 15],
+    'tomcat':     [0, 0, 5, 10, 15],
+    'tradebeans': [0, 0, 5, 10, 13],
+    'tradesoap':  [2, 4, 5, 10, 15],
+    'xalan':      [0, 0, 5, 10, 18],
 }
 
 dacapoScalaSanityWarmup = {
 # (tw) actors sometimes fails verification; hardly reproducible
-    'actors':     [0, 0, 0,  0,  0],
+    'actors':     [0, 0, 0, 0, 0],
 # (lstadler) apparat was disabled due to a deadlock which I think is the benchmarks fault.
-    'apparat':    [0, 0, 0,  0,  0],
-    'factorie':   [0, 0, 2,  5,  5],
+    'apparat':    [0, 0, 0, 0, 0],
+    'factorie':   [0, 0, 2, 5, 5],
     'kiama':      [0, 0, 3, 13, 15],
     'scalac':     [0, 0, 5, 15, 20],
     'scaladoc':   [0, 0, 5, 15, 15],
@@ -59,8 +59,8 @@
     'scalariform':[0, 0, 6, 15, 20],
     'scalatest':  [0, 0, 2, 10, 12],
     'scalaxb':    [0, 0, 5, 15, 25],
-#(gdub) specs sometimes returns a non-zero value event though there is no apparent failure
-    'specs':      [0, 0, 0,  0,  0],
+# (gdub) specs sometimes returns a non-zero value event though there is no apparent failure
+    'specs':      [0, 0, 0, 0, 0],
     'tmt':        [0, 0, 3, 10, 12]
 }
 
@@ -137,60 +137,68 @@
     'xml.validation'
 ]
 
+def _noneAsEmptyList(a):
+    if a is None:
+        return []
+    return a
+
 class SanityCheckLevel:
     Fast, Gate, Normal, Extensive, Benchmark = range(5)
-    
-def getSPECjbb2005(benchArgs = []):
-    
+
+def getSPECjbb2005(benchArgs=None):
+    benchArgs = [] if benchArgs is None else benchArgs
+
     specjbb2005 = mx.get_env('SPECJBB2005')
     if specjbb2005 is None or not exists(join(specjbb2005, 'jbb.jar')):
         mx.abort('Please set the SPECJBB2005 environment variable to a SPECjbb2005 directory')
-    
+
     score = re.compile(r"^Valid run, Score is  (?P<score>[0-9]+)$", re.MULTILINE)
     error = re.compile(r"VALIDATION ERROR")
     success = re.compile(r"^Valid run, Score is  [0-9]+$", re.MULTILINE)
     matcher = ValuesMatcher(score, {'group' : 'SPECjbb2005', 'name' : 'score', 'score' : '<score>'})
     classpath = ['jbb.jar', 'check.jar']
-    return Test("SPECjbb2005", ['spec.jbb.JBBmain', '-propfile', 'SPECjbb.props'] + benchArgs, [success], [error], [matcher], vmOpts=['-Xms3g', '-XX:+'+gc, '-XX:-UseCompressedOops', '-cp', os.pathsep.join(classpath)], defaultCwd=specjbb2005)
+    return Test("SPECjbb2005", ['spec.jbb.JBBmain', '-propfile', 'SPECjbb.props'] + benchArgs, [success], [error], [matcher], vmOpts=['-Xms3g', '-XX:+' + gc, '-XX:-UseCompressedOops', '-cp', os.pathsep.join(classpath)], defaultCwd=specjbb2005)
 
-def getSPECjbb2013(benchArgs = []):
-    
+def getSPECjbb2013(benchArgs=None):
+
     specjbb2013 = mx.get_env('SPECJBB2013')
     if specjbb2013 is None or not exists(join(specjbb2013, 'specjbb2013.jar')):
         mx.abort('Please set the SPECJBB2013 environment variable to a SPECjbb2013 directory')
-    
+
     jops = re.compile(r"^RUN RESULT: hbIR \(max attempted\) = [0-9]+, hbIR \(settled\) = [0-9]+, max-jOPS = (?P<max>[0-9]+), critical-jOPS = (?P<critical>[0-9]+)$", re.MULTILINE)
-    #error?
+    # error?
     success = re.compile(r"org.spec.jbb.controller: Run finished", re.MULTILINE)
     matcherMax = ValuesMatcher(jops, {'group' : 'SPECjbb2013', 'name' : 'max', 'score' : '<max>'})
     matcherCritical = ValuesMatcher(jops, {'group' : 'SPECjbb2013', 'name' : 'critical', 'score' : '<critical>'})
-    return Test("SPECjbb2013", ['-jar', 'specjbb2013.jar', '-m', 'composite'] + benchArgs, [success], [], [matcherCritical, matcherMax], vmOpts=['-Xmx6g', '-Xms6g', '-Xmn3g', '-XX:+UseParallelOldGC', '-XX:-UseAdaptiveSizePolicy', '-XX:-UseBiasedLocking', '-XX:-UseCompressedOops'], defaultCwd=specjbb2013)
-    
-def getSPECjvm2008(benchArgs=[]):
-    
+    return Test("SPECjbb2013", ['-jar', 'specjbb2013.jar', '-m', 'composite'] +
+                _noneAsEmptyList(benchArgs), [success], [], [matcherCritical, matcherMax],
+                vmOpts=['-Xmx6g', '-Xms6g', '-Xmn3g', '-XX:+UseParallelOldGC', '-XX:-UseAdaptiveSizePolicy', '-XX:-UseBiasedLocking', '-XX:-UseCompressedOops'], defaultCwd=specjbb2013)
+
+def getSPECjvm2008(benchArgs=None):
+
     specjvm2008 = mx.get_env('SPECJVM2008')
     if specjvm2008 is None or not exists(join(specjvm2008, 'SPECjvm2008.jar')):
         mx.abort('Please set the SPECJVM2008 environment variable to a SPECjvm2008 directory')
-    
+
     score = re.compile(r"^(Score on|Noncompliant) (?P<benchmark>[a-zA-Z0-9\._]+)( result)?: (?P<score>[0-9]+((,|\.)[0-9]+)?)( SPECjvm2008 Base)? ops/m$", re.MULTILINE)
     error = re.compile(r"^Errors in benchmark: ", re.MULTILINE)
     # The ' ops/m' at the end of the success string is important : it's how you can tell valid and invalid runs apart
     success = re.compile(r"^(Noncompliant c|C)omposite result: [0-9]+((,|\.)[0-9]+)?( SPECjvm2008 (Base|Peak))? ops/m$", re.MULTILINE)
     matcher = ValuesMatcher(score, {'group' : 'SPECjvm2008', 'name' : '<benchmark>', 'score' : '<score>'})
-    
-    return Test("SPECjvm2008", ['-jar', 'SPECjvm2008.jar'] + benchArgs, [success], [error], [matcher], vmOpts=['-Xms3g', '-XX:+'+gc, '-XX:-UseCompressedOops'], defaultCwd=specjvm2008)
 
-def getDacapos(level=SanityCheckLevel.Normal, gateBuildLevel=None, dacapoArgs=[]):
+    return Test("SPECjvm2008", ['-jar', 'SPECjvm2008.jar'] + _noneAsEmptyList(benchArgs), [success], [error], [matcher], vmOpts=['-Xms3g', '-XX:+' + gc, '-XX:-UseCompressedOops'], defaultCwd=specjvm2008)
+
+def getDacapos(level=SanityCheckLevel.Normal, gateBuildLevel=None, dacapoArgs=None):
     checks = []
-    
+
     for (bench, ns) in dacapoSanityWarmup.items():
         if ns[level] > 0:
             if gateBuildLevel is None or gateBuildLevel in dacapoGateBuildLevels[bench]:
-                checks.append(getDacapo(bench, ['-n', str(ns[level])] + dacapoArgs))
-    
+                checks.append(getDacapo(bench, ['-n', str(ns[level])] + _noneAsEmptyList(dacapoArgs)))
+
     return checks
 
-def getDacapo(name, dacapoArgs=[]):
+def getDacapo(name, dacapoArgs=None):
     dacapo = mx.get_env('DACAPO_CP')
     if dacapo is None:
         l = mx.library('DACAPO', False)
@@ -198,31 +206,31 @@
             dacapo = l.get_path(True)
         else:
             mx.abort('DaCapo 9.12 jar file must be specified with DACAPO_CP environment variable or as DACAPO library')
-    
+
     if not isfile(dacapo) or not dacapo.endswith('.jar'):
         mx.abort('Specified DaCapo jar file does not exist or is not a jar file: ' + dacapo)
-    
+
     dacapoSuccess = re.compile(r"^===== DaCapo 9\.12 ([a-zA-Z0-9_]+) PASSED in ([0-9]+) msec =====$", re.MULTILINE)
     dacapoFail = re.compile(r"^===== DaCapo 9\.12 ([a-zA-Z0-9_]+) FAILED (warmup|) =====$", re.MULTILINE)
     dacapoTime = re.compile(r"===== DaCapo 9\.12 (?P<benchmark>[a-zA-Z0-9_]+) PASSED in (?P<time>[0-9]+) msec =====")
     dacapoTime1 = re.compile(r"===== DaCapo 9\.12 (?P<benchmark>[a-zA-Z0-9_]+) completed warmup 1 in (?P<time>[0-9]+) msec =====")
-    
+
     dacapoMatcher = ValuesMatcher(dacapoTime, {'group' : 'DaCapo', 'name' : '<benchmark>', 'score' : '<time>'})
     dacapoMatcher1 = ValuesMatcher(dacapoTime1, {'group' : 'DaCapo-1stRun', 'name' : '<benchmark>', 'score' : '<time>'})
-    
-    return Test("DaCapo-" + name, ['-jar', dacapo, name] + dacapoArgs, [dacapoSuccess], [dacapoFail], [dacapoMatcher, dacapoMatcher1], ['-Xms2g', '-XX:+'+gc, '-XX:-UseCompressedOops'])
 
-def getScalaDacapos(level=SanityCheckLevel.Normal, gateBuildLevel=None, dacapoArgs=[]):
+    return Test("DaCapo-" + name, ['-jar', dacapo, name] + _noneAsEmptyList(dacapoArgs), [dacapoSuccess], [dacapoFail], [dacapoMatcher, dacapoMatcher1], ['-Xms2g', '-XX:+' + gc, '-XX:-UseCompressedOops'])
+
+def getScalaDacapos(level=SanityCheckLevel.Normal, gateBuildLevel=None, dacapoArgs=None):
     checks = []
-    
+
     for (bench, ns) in dacapoScalaSanityWarmup.items():
         if ns[level] > 0:
             if gateBuildLevel is None or gateBuildLevel in dacapoScalaGateBuildLevels[bench]:
-                checks.append(getScalaDacapo(bench, ['-n', str(ns[level])] + dacapoArgs))
-    
+                checks.append(getScalaDacapo(bench, ['-n', str(ns[level])] + _noneAsEmptyList(dacapoArgs)))
+
     return checks
 
-def getScalaDacapo(name, dacapoArgs=[]):
+def getScalaDacapo(name, dacapoArgs=None):
     dacapo = mx.get_env('DACAPO_SCALA_CP')
     if dacapo is None:
         l = mx.library('DACAPO_SCALA', False)
@@ -230,23 +238,23 @@
             dacapo = l.get_path(True)
         else:
             mx.abort('Scala DaCapo 0.1.0 jar file must be specified with DACAPO_SCALA_CP environment variable or as DACAPO_SCALA library')
-    
+
     if not isfile(dacapo) or not dacapo.endswith('.jar'):
         mx.abort('Specified Scala DaCapo jar file does not exist or is not a jar file: ' + dacapo)
-    
+
     dacapoSuccess = re.compile(r"^===== DaCapo 0\.1\.0(-SNAPSHOT)? ([a-zA-Z0-9_]+) PASSED in ([0-9]+) msec =====$", re.MULTILINE)
     dacapoFail = re.compile(r"^===== DaCapo 0\.1\.0(-SNAPSHOT)? ([a-zA-Z0-9_]+) FAILED (warmup|) =====$", re.MULTILINE)
     dacapoTime = re.compile(r"===== DaCapo 0\.1\.0(-SNAPSHOT)? (?P<benchmark>[a-zA-Z0-9_]+) PASSED in (?P<time>[0-9]+) msec =====")
-    
+
     dacapoMatcher = ValuesMatcher(dacapoTime, {'group' : "Scala-DaCapo", 'name' : '<benchmark>', 'score' : '<time>'})
-    
-    return Test("Scala-DaCapo-" + name, ['-jar', dacapo, name] + dacapoArgs, [dacapoSuccess], [dacapoFail], [dacapoMatcher], ['-Xms2g', '-XX:+'+gc, '-XX:-UseCompressedOops'])
+
+    return Test("Scala-DaCapo-" + name, ['-jar', dacapo, name] + _noneAsEmptyList(dacapoArgs), [dacapoSuccess], [dacapoFail], [dacapoMatcher], ['-Xms2g', '-XX:+' + gc, '-XX:-UseCompressedOops'])
 
 def getBootstraps():
     time = re.compile(r"Bootstrapping Graal\.+ in (?P<time>[0-9]+) ms")
     scoreMatcher = ValuesMatcher(time, {'group' : 'Bootstrap', 'name' : 'BootstrapTime', 'score' : '<time>'})
     scoreMatcherBig = ValuesMatcher(time, {'group' : 'Bootstrap-bigHeap', 'name' : 'BootstrapTime', 'score' : '<time>'})
-    
+
     tests = []
     tests.append(Test("Bootstrap", ['-version'], successREs=[time], scoreMatchers=[scoreMatcher], ignoredVMs=['client', 'server'], benchmarkCompilationRate=False))
     tests.append(Test("Bootstrap-bigHeap", ['-version'], successREs=[time], scoreMatchers=[scoreMatcherBig], vmOpts=['-Xms2g'], ignoredVMs=['client', 'server'], benchmarkCompilationRate=False))
@@ -255,16 +263,16 @@
 class CTWMode:
     Full, NoInline, NoComplex = range(3)
 
-def getCTW(vm,mode):
+def getCTW(vm, mode):
     time = re.compile(r"CompileTheWorld : Done \([0-9]+ classes, [0-9]+ methods, (?P<time>[0-9]+) ms\)")
     scoreMatcher = ValuesMatcher(time, {'group' : 'CompileTheWorld', 'name' : 'CompileTime', 'score' : '<time>'})
-    
+
     jre = os.environ.get('JAVA_HOME')
     if exists(join(jre, 'jre')):
         jre = join(jre, 'jre')
     rtjar = join(jre, 'lib', 'rt.jar')
 
-    
+
     args = ['-XX:+CompileTheWorld', '-Xbootclasspath/p:' + rtjar]
     if commands.isGraalEnabled(vm):
         args += ['-XX:+BootstrapGraal', '-G:-Debug']
@@ -276,9 +284,9 @@
     if mode >= CTWMode.NoComplex:
         if commands.isGraalEnabled(vm):
             args += ['-G:-OptLoopTransform', '-G:-OptTailDuplication', '-G:-FullUnroll', '-G:-MemoryAwareScheduling', '-G:-NewMemoryAwareScheduling', '-G:-PartialEscapeAnalysis']
-        
+
     return Test("CompileTheWorld", args, successREs=[time], scoreMatchers=[scoreMatcher], benchmarkCompilationRate=False)
-    
+
 
 class Tee:
     def __init__(self):
@@ -291,24 +299,24 @@
 Encapsulates a single program that is a sanity test and/or a benchmark.
 """
 class Test:
-    def __init__(self, name, cmd, successREs=[], failureREs=[], scoreMatchers=[], vmOpts=[], defaultCwd=None, ignoredVMs=[], benchmarkCompilationRate=False):
+    def __init__(self, name, cmd, successREs=None, failureREs=None, scoreMatchers=None, vmOpts=None, defaultCwd=None, ignoredVMs=None, benchmarkCompilationRate=False):
 
         self.name = name
-        self.successREs = successREs
-        self.failureREs = failureREs + [re.compile(r"Exception occurred in scope: ")]
-        self.scoreMatchers = scoreMatchers
-        self.vmOpts = vmOpts
+        self.successREs = _noneAsEmptyList(successREs)
+        self.failureREs = _noneAsEmptyList(failureREs) + [re.compile(r"Exception occurred in scope: ")]
+        self.scoreMatchers = _noneAsEmptyList(scoreMatchers)
+        self.vmOpts = _noneAsEmptyList(vmOpts)
         self.cmd = cmd
         self.defaultCwd = defaultCwd
-        self.ignoredVMs = ignoredVMs
+        self.ignoredVMs = _noneAsEmptyList(ignoredVMs)
         self.benchmarkCompilationRate = benchmarkCompilationRate
         if benchmarkCompilationRate:
             self.vmOpts = self.vmOpts + ['-XX:+CITime']
-        
+
     def __str__(self):
         return self.name
-    
-    def test(self, vm, cwd=None, extraVmOpts=[], vmbuild=None):
+
+    def test(self, vm, cwd=None, extraVmOpts=None, vmbuild=None):
         """
         Run this program as a sanity test.
         """
@@ -319,27 +327,27 @@
         parser = OutputParser()
         jvmError = re.compile(r"(?P<jvmerror>([A-Z]:|/).*[/\\]hs_err_pid[0-9]+\.log)")
         parser.addMatcher(ValuesMatcher(jvmError, {'jvmError' : '<jvmerror>'}))
-        
+
         for successRE in self.successREs:
             parser.addMatcher(ValuesMatcher(successRE, {'passed' : '1'}))
         for failureRE in self.failureREs:
             parser.addMatcher(ValuesMatcher(failureRE, {'failed' : '1'}))
 
         tee = Tee()
-        retcode = commands.vm(self.vmOpts + extraVmOpts + self.cmd, vm, nonZeroIsFatal=False, out=tee.eat, err=subprocess.STDOUT, cwd=cwd, vmbuild=vmbuild)
+        retcode = commands.vm(self.vmOpts + _noneAsEmptyList(extraVmOpts) + self.cmd, vm, nonZeroIsFatal=False, out=tee.eat, err=subprocess.STDOUT, cwd=cwd, vmbuild=vmbuild)
         output = tee.output.getvalue()
         valueMaps = parser.parse(output)
 
         if len(valueMaps) == 0:
             return False
-        
+
         record = {}
         for valueMap in valueMaps:
             for key, value in valueMap.items():
                 if record.has_key(key) and record[key] != value:
                     mx.abort('Inconsistant values returned by test machers : ' + str(valueMaps))
                 record[key] = value
-        
+
         jvmErrorFile = record.get('jvmError')
         if jvmErrorFile:
             mx.log('/!\\JVM Error : dumping error log...')
@@ -347,13 +355,13 @@
                 mx.log(fp.read())
             os.unlink(jvmErrorFile)
             return False
-        
+
         if record.get('failed') == '1':
             return False
-        
+
         return retcode == 0 and record.get('passed') == '1'
-    
-    def bench(self, vm, cwd=None, extraVmOpts=[], vmbuild=None):
+
+    def bench(self, vm, cwd=None, extraVmOpts=None, vmbuild=None):
         """
         Run this program as a benchmark.
         """
@@ -362,7 +370,7 @@
         if cwd is None:
             cwd = self.defaultCwd
         parser = OutputParser()
-        
+
         for successRE in self.successREs:
             parser.addMatcher(ValuesMatcher(successRE, {'passed' : '1'}))
         for failureRE in self.failureREs:
@@ -379,10 +387,10 @@
             else:
                 ibps = re.compile(r"(?P<compiler>[\w]+) compilation speed: +(?P<rate>[0-9]+) bytes/s {standard")
                 parser.addMatcher(ValuesMatcher(ibps, {'group' : 'InlinedBytecodesPerSecond', 'name' : '<compiler>:' + self.name, 'score' : '<rate>'}))
-            
+
         startDelim = 'START: ' + self.name
         endDelim = 'END: ' + self.name
-        
+
         outputfile = os.environ.get('BENCH_OUTPUT', None)
         if outputfile:
             # Used only to debug output parsing
@@ -399,7 +407,7 @@
         else:
             tee = Tee()
             mx.log(startDelim)
-            if commands.vm(self.vmOpts + extraVmOpts + self.cmd, vm, nonZeroIsFatal=False, out=tee.eat, err=subprocess.STDOUT, cwd=cwd, vmbuild=vmbuild) != 0:
+            if commands.vm(self.vmOpts + _noneAsEmptyList(extraVmOpts) + self.cmd, vm, nonZeroIsFatal=False, out=tee.eat, err=subprocess.STDOUT, cwd=cwd, vmbuild=vmbuild) != 0:
                 mx.abort("Benchmark failed (non-zero retcode)")
             mx.log(endDelim)
             output = tee.output.getvalue()
@@ -419,8 +427,8 @@
                 score = valueMap.get('score')
                 if name and score:
                     group[name] = score
-        
+
         if not passed:
             mx.abort("Benchmark failed (not passed)")
-        
+
         return groups
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mxtool/.pylintrc	Tue Sep 03 16:33:41 2013 +0200
@@ -0,0 +1,275 @@
+[MASTER]
+
+# Specify a configuration file.
+#rcfile=
+
+# Python code to execute, usually for sys.path manipulation such as
+# pygtk.require().
+#init-hook=
+
+# Profiled execution.
+profile=no
+
+# Add files or directories to the blacklist. They should be base names, not
+# paths.
+ignore=CVS
+
+# Pickle collected data for later comparisons.
+persistent=yes
+
+# List of plugins (as comma separated values of python modules names) to load,
+# usually to register additional checkers.
+load-plugins=
+
+
+[MESSAGES CONTROL]
+
+# Enable the message, report, category or checker with the given id(s). You can
+# either give multiple identifier separated by comma (,) or put this option
+# multiple time. See also the "--disable" option for examples.
+#enable=
+
+# Disable the message, report, category or checker with the given id(s). You
+# can either give multiple identifiers separated by comma (,) or put this
+# option multiple times (only on the command line, not in the configuration
+# file where it should appear only once).You can also use "--disable=all" to
+# disable everything first and then reenable specific checks. For example, if
+# you want to run only the similarities checker, you can use "--disable=all
+# --enable=similarities". If you want to run only the classes checker, but have
+# no Warning level messages displayed, use"--disable=all --enable=classes
+# --disable=W"
+disable=attribute-defined-outside-init,
+        bare-except,global-statement,protected-access,
+        redefined-outer-name,unused-argument,star-args,
+        old-style-class,too-many-lines,pointless-string-statement,
+
+[REPORTS]
+
+# Set the output format. Available formats are text, parseable, colorized, msvs
+# (visual studio) and html. You can also give a reporter class, eg
+# mypackage.mymodule.MyReporterClass.
+output-format=text
+
+# Put messages in a separate file for each module / package specified on the
+# command line instead of printing them on stdout. Reports (if any) will be
+# written in a file name "pylint_global.[txt|html]".
+files-output=no
+
+# Tells whether to display a full report or only the messages
+reports=no
+
+# Python expression which should return a note less than 10 (10 is the highest
+# note). You have access to the variables errors warning, statement which
+# respectively contain the number of errors / warnings messages and the total
+# number of statements analyzed. This is used by the global evaluation report
+# (RP0004).
+evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
+
+# Add a comment according to your evaluation note. This is used by the global
+# evaluation report (RP0004).
+comment=no
+
+# Template used to display messages. This is a python new-style format string
+# used to format the massage information. See doc for all details
+#msg-template=
+
+
+[BASIC]
+
+# Required attributes for module, separated by a comma
+required-attributes=
+
+# List of builtins function names that should not be used, separated by a comma
+bad-functions=filter,apply,input
+
+# Regular expression which should only match correct module names
+module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
+
+# Regular expression which should only match correct module level names
+const-rgx=_[a-zA-Z0-9_]{2,30}$
+
+# Regular expression which should only match correct class names
+class-rgx=[A-Z_][a-zA-Z0-9]+$
+
+# Regular expression which should only match correct function names
+function-rgx=[a-z_][a-zA-Z0-9_]{1,50}$
+
+# Regular expression which should only match correct method names
+method-rgx=[a-z_][a-zA-Z0-9_]{1,50}$
+
+# Regular expression which should only match correct instance attribute names
+attr-rgx=[a-z_][a-zA-Z0-9_]{2,30}$
+
+# Regular expression which should only match correct argument names
+argument-rgx=[a-z_][a-zA-Z0-9_]{0,30}$
+
+# Regular expression which should only match correct variable names
+variable-rgx=[a-z_][a-zA-Z0-9_]{0,30}$
+
+# Regular expression which should only match correct attribute names in class
+# bodies
+class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
+
+# Regular expression which should only match correct list comprehension /
+# generator expression variable names
+inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
+
+# Good variable names which should always be accepted, separated by a comma
+good-names=i,j,k,ex,Run,_
+
+# Bad variable names which should always be refused, separated by a comma
+bad-names=foo,bar,baz,toto,tutu,tata
+
+# Regular expression which should only match function or class names that do
+# not require a docstring.
+no-docstring-rgx=.*
+
+# Minimum line length for functions/classes that require docstrings, shorter
+# ones are exempt.
+docstring-min-length=-1
+
+
+[FORMAT]
+
+# Maximum number of characters on a single line.
+max-line-length=300
+
+# Regexp for a line that is allowed to be longer than the limit.
+ignore-long-lines=^\s*(# )?<?https?://\S+>?$
+
+# Maximum number of lines in a module
+max-module-lines=1000
+
+# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
+# tab).
+indent-string='    '
+
+
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+notes=FIXME,XXX,TODO
+
+
+[SIMILARITIES]
+
+# Minimum lines number of a similarity.
+min-similarity-lines=4
+
+# Ignore comments when computing similarities.
+ignore-comments=yes
+
+# Ignore docstrings when computing similarities.
+ignore-docstrings=yes
+
+# Ignore imports when computing similarities.
+ignore-imports=no
+
+
+[TYPECHECK]
+
+# Tells whether missing members accessed in mixin class should be ignored. A
+# mixin class is detected if its name ends with "mixin" (case insensitive).
+ignore-mixin-members=yes
+
+# List of classes names for which member attributes should not be checked
+# (useful for classes with attributes dynamically set).
+ignored-classes=SQLObject
+
+# When zope mode is activated, add a predefined set of Zope acquired attributes
+# to generated-members.
+zope=no
+
+# List of members which are set dynamically and missed by pylint inference
+# system, and so shouldn't trigger E0201 when accessed. Python regular
+# expressions are accepted.
+generated-members=REQUEST,acl_users,aq_parent
+
+
+[VARIABLES]
+
+# Tells whether we should check for unused import in __init__ files.
+init-import=no
+
+# A regular expression matching the beginning of the name of dummy variables
+# (i.e. not used).
+dummy-variables-rgx=_$|dummy
+
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid to define new builtins when possible.
+additional-builtins=
+
+
+[CLASSES]
+
+# List of interface methods to ignore, separated by a comma. This is used for
+# instance to not check methods defines in Zope's Interface base class.
+ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
+
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,__new__,setUp
+
+# List of valid names for the first argument in a class method.
+valid-classmethod-first-arg=cls
+
+# List of valid names for the first argument in a metaclass class method.
+valid-metaclass-classmethod-first-arg=mcs
+
+
+[DESIGN]
+
+# Maximum number of arguments for function / method
+max-args=5
+
+# Argument names that match this expression will be ignored. Default to name
+# with leading underscore
+ignored-argument-names=_.*
+
+# Maximum number of locals for function / method body
+max-locals=15
+
+# Maximum number of return / yield for function / method body
+max-returns=6
+
+# Maximum number of branch for function / method body
+max-branches=12
+
+# Maximum number of statements in function / method body
+max-statements=50
+
+# Maximum number of parents for a class (see R0901).
+max-parents=7
+
+# Maximum number of attributes for a class (see R0902).
+max-attributes=7
+
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=2
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
+
+
+[IMPORTS]
+
+# Deprecated modules which should not be used, separated by a comma
+deprecated-modules=regsub,TERMIOS,Bastion,rexec
+
+# Create a graph of every (i.e. internal and external) dependencies in the
+# given file (report RP0402 must not be disabled)
+import-graph=
+
+# Create a graph of external dependencies in the given file (report RP0402 must
+# not be disabled)
+ext-import-graph=
+
+# Create a graph of internal dependencies in the given file (report RP0402 must
+# not be disabled)
+int-import-graph=
+
+
+[EXCEPTIONS]
+
+# Exceptions that will emit a warning when being caught. Defaults to
+# "Exception"
+overgeneral-exceptions=Exception
--- a/mxtool/mx.py	Tue Sep 03 14:14:09 2013 +0200
+++ b/mxtool/mx.py	Tue Sep 03 16:33:41 2013 +0200
@@ -125,7 +125,7 @@
     javaCompliance
         The minimum JDK version (format: x.y) to which the project's
         sources comply (required for non-native projects).
-    
+
     workingSets
         A comma separated list of working set names. The project belongs
         to the given working sets, for which the eclipseinit command
@@ -146,8 +146,6 @@
 from argparse import ArgumentParser, REMAINDER
 from os.path import join, basename, dirname, exists, getmtime, isabs, expandvars, isdir, isfile
 
-DEFAULT_JAVA_ARGS = '-ea -Xss2m -Xmx1g'
-
 _projects = dict()
 _libs = dict()
 _dists = dict()
@@ -169,17 +167,17 @@
             self.path = join(suite.dir, self.path)
         self.deps = deps
         self.update_listeners = set()
-        
+
     def __str__(self):
         return self.name
-    
+
     def add_update_listener(self, listener):
         self.update_listeners.add(listener)
-        
+
     def notify_updated(self):
         for l in self.update_listeners:
             l(self)
-    
+
 """
 A dependency is a library or project specified in a suite.
 """
@@ -202,7 +200,7 @@
 
     def isLibrary(self):
         return isinstance(self, Library)
-    
+
     def isProject(self):
         return isinstance(self, Project)
 
@@ -216,7 +214,7 @@
         self.native = False
         self.workingSets = workingSets
         self.dir = d
-        
+
         # Create directories for projects that don't yet exist
         if not exists(d):
             os.mkdir(d)
@@ -244,7 +242,7 @@
         return deps
 
     def _compute_max_dep_distances(self, name, distances, dist):
-        currentDist = distances.get(name);
+        currentDist = distances.get(name)
         if currentDist is None or currentDist < dist:
             distances[name] = dist
             p = project(name, False)
@@ -260,14 +258,14 @@
         distances = dict()
         result = set()
         self._compute_max_dep_distances(self.name, distances, 0)
-        for n,d in distances.iteritems():
+        for n, d in distances.iteritems():
             assert d > 0 or n == self.name
             if d == 1:
                 result.add(n)
 
         if len(result) == len(self.deps) and frozenset(self.deps) == result:
             return self.deps
-        return result;
+        return result
 
     def max_depth(self):
         """
@@ -275,7 +273,7 @@
         """
         distances = dict()
         self._compute_max_dep_distances(self.name, distances, 0)
-        return max(distances.values())        
+        return max(distances.values())
 
     def source_dirs(self):
         """
@@ -337,23 +335,23 @@
                                     matchFound = True
                                 if pkg and matchFound:
                                     break
-                                        
+
                         if matchFound:
-                            basename = name[:-len('.java')]
+                            simpleClassName = name[:-len('.java')]
                             assert pkg is not None
                             if pkgRoot is None or pkg.startswith(pkgRoot):
                                 pkgOutputDir = join(outputDir, pkg.replace('.', os.path.sep))
                                 if exists(pkgOutputDir):
                                     for e in os.listdir(pkgOutputDir):
                                         if includeInnerClasses:
-                                            if e.endswith('.class') and (e.startswith(basename) or e.startswith(basename + '$')):
+                                            if e.endswith('.class') and (e.startswith(simpleClassName) or e.startswith(simpleClassName + '$')):
                                                 className = pkg + '.' + e[:-len('.class')]
                                                 result[className] = source
-                                        elif e == basename + '.class':
-                                            className = pkg + '.' + basename
+                                        elif e == simpleClassName + '.class':
+                                            className = pkg + '.' + simpleClassName
                                             result[className] = source
         return result
-    
+
     def _init_packages_and_imports(self):
         if not hasattr(self, '_defined_java_packages'):
             packages = set()
@@ -367,21 +365,21 @@
                 for root, _, files in os.walk(sourceDir):
                     javaSources = [name for name in files if name.endswith('.java')]
                     if len(javaSources) != 0:
-                        pkg = root[len(sourceDir) + 1:].replace(os.sep,'.')
+                        pkg = root[len(sourceDir) + 1:].replace(os.sep, '.')
                         if not pkg in depPackages:
                             packages.add(pkg)
                         else:
                             # A project extends a package already defined by one of it dependencies
                             extendedPackages.add(pkg)
                             imports.add(pkg)
-                        
+
                         for n in javaSources:
                             with open(join(root, n)) as fp:
                                 content = fp.read()
                                 imports.update(importRe.findall(content))
             self._defined_java_packages = frozenset(packages)
             self._extended_java_packages = frozenset(extendedPackages)
-            
+
             importedPackages = set()
             for imp in imports:
                 name = imp
@@ -394,12 +392,12 @@
                 if name is not None:
                     importedPackages.add(name)
             self._imported_java_packages = frozenset(importedPackages)
-    
+
     def defined_java_packages(self):
         """Get the immutable set of Java packages defined by the Java sources of this project"""
         self._init_packages_and_imports()
         return self._defined_java_packages
-    
+
     def extended_java_packages(self):
         """Get the immutable set of Java packages extended by the Java sources of this project"""
         self._init_packages_and_imports()
@@ -417,7 +415,7 @@
             if hasattr(self, '_declaredAnnotationProcessors'):
                 ap = set(self._declaredAnnotationProcessors)
 
-            # find dependencies that auto-inject themselves as annotation processors to all dependents                
+            # find dependencies that auto-inject themselves as annotation processors to all dependents
             allDeps = self.all_deps([], includeLibs=False, includeSelf=False, includeAnnotationProcessors=False)
             for p in allDeps:
                 if hasattr(p, 'annotationProcessorForDependents') and p.annotationProcessorForDependents.lower() == 'true':
@@ -442,7 +440,7 @@
         if not isabs(path):
             path = join(self.suite.dir, path)
         if resolve and self.mustExist and not exists(path):
-            assert not len(self.urls) == 0, 'cannot find required library ' + self.name + ' ' + path;
+            assert not len(self.urls) == 0, 'cannot find required library ' + self.name + ' ' + path
             print('Downloading ' + self.name + ' from ' + str(self.urls))
             download(path, self.urls)
         return path
@@ -462,7 +460,7 @@
         path = self.get_path(resolve)
         if exists(path) or not resolve:
             cp.append(path)
-            
+
     def all_deps(self, deps, includeLibs, includeSelf=True, includeAnnotationProcessors=False):
         if not includeLibs or not includeSelf:
             return deps
@@ -482,11 +480,11 @@
         self._load_env(mxDir)
         self._load_commands(mxDir)
         self._load_includes(mxDir)
-        self.name = d # re-initialized in _load_projects
+        self.name = d  # re-initialized in _load_projects
 
     def __str__(self):
         return self.name
-    
+
     def _load_projects(self, mxDir):
         libsMap = dict()
         projsMap = dict()
@@ -536,7 +534,7 @@
             srcDirs = pop_list(attrs, 'sourceDirs')
             deps = pop_list(attrs, 'dependencies')
             ap = pop_list(attrs, 'annotationProcessors')
-            #deps += ap
+            # deps += ap
             javaCompliance = attrs.pop('javaCompliance', None)
             subDir = attrs.pop('subDir', None)
             if subDir is None:
@@ -570,17 +568,17 @@
             d = Distribution(self, name, path, deps)
             d.__dict__.update(attrs)
             self.dists.append(d)
-            
+
         if self.name is None:
             abort('Missing "suite=<name>" in ' + projectsFile)
 
     def _load_commands(self, mxDir):
-        commands = join(mxDir, 'commands.py')
-        if exists(commands):
+        commandsPath = join(mxDir, 'commands.py')
+        if exists(commandsPath):
             # temporarily extend the Python path
             sys.path.insert(0, mxDir)
             mod = __import__('commands')
-            
+
             self.commands = sys.modules.pop('commands')
             sys.modules[join(mxDir, 'commands')] = self.commands
 
@@ -588,7 +586,7 @@
             del sys.path[0]
 
             if not hasattr(mod, 'mx_init'):
-                abort(commands + ' must define an mx_init(env) function')
+                abort(commandsPath + ' must define an mx_init(env) function')
             if hasattr(mod, 'mx_post_parse_cmd_line'):
                 self.mx_post_parse_cmd_line = mod.mx_post_parse_cmd_line
 
@@ -632,7 +630,7 @@
                 abort('cannot redefine library  ' + l.name)
             _libs[l.name] = l
         for d in self.dists:
-            existing = _dists.get(l.name)
+            existing = _dists.get(d.name)
             if existing is not None:
                 abort('cannot redefine distribution  ' + d.name)
             _dists[d.name] = d
@@ -641,7 +639,7 @@
 
 class XMLElement(xml.dom.minidom.Element):
     def writexml(self, writer, indent="", addindent="", newl=""):
-        writer.write(indent+"<" + self.tagName)
+        writer.write(indent + "<" + self.tagName)
 
         attrs = self._get_attributes()
         a_names = attrs.keys()
@@ -657,14 +655,14 @@
                 # text is printed without any indentation or new line padding
                 writer.write(">")
                 self.childNodes[0].writexml(writer)
-                writer.write("</%s>%s" % (self.tagName,newl))
+                writer.write("</%s>%s" % (self.tagName, newl))
             else:
-                writer.write(">%s"%(newl))
+                writer.write(">%s" % (newl))
                 for node in self.childNodes:
-                    node.writexml(writer,indent+addindent,addindent,newl)
-                writer.write("%s</%s>%s" % (indent,self.tagName,newl))
+                    node.writexml(writer, indent + addindent, addindent, newl)
+                writer.write("%s</%s>%s" % (indent, self.tagName, newl))
         else:
-            writer.write("/>%s"%(newl))
+            writer.write("/>%s" % (newl))
 
 class XMLDoc(xml.dom.minidom.Document):
 
@@ -682,7 +680,9 @@
     def comment(self, txt):
         self.current.appendChild(self.createComment(txt))
 
-    def open(self, tag, attributes={}, data=None):
+    def open(self, tag, attributes=None, data=None):
+        if attributes is None:
+            attributes = {}
         element = self.createElement(tag)
         for key, value in attributes.items():
             element.setAttribute(key, value)
@@ -698,7 +698,9 @@
         self.current = self.current.parentNode
         return self
 
-    def element(self, tag, attributes={}, data=None):
+    def element(self, tag, attributes=None, data=None):
+        if attributes is None:
+            attributes = {}
         return self.open(tag, attributes, data).close(tag)
 
     def xml(self, indent='', newl='', escape=False, standalone=None):
@@ -888,7 +890,7 @@
 def _handle_missing_java_home():
     if not sys.stdout.isatty():
         abort('Could not find bootstrap JDK. Use --java-home option or ensure JAVA_HOME environment variable is set.')
- 
+
     candidateJdks = []
     if get_os() == 'darwin':
         base = '/Library/Java/JavaVirtualMachines'
@@ -908,7 +910,7 @@
         javaHome = select_items(candidateJdks + ['<other>'], allowMultiple=False)
         if javaHome == '<other>':
             javaHome = None
-            
+
     while javaHome is None:
         javaHome = raw_input('Enter path of bootstrap JDK: ')
         rtJarPath = join(javaHome, 'jre', 'lib', 'rt.jar')
@@ -917,12 +919,12 @@
             javaHome = None
         else:
             break
-    
+
     envPath = join(_mainSuite.dir, 'mx', 'env')
     if ask_yes_no('Persist this setting by adding "JAVA_HOME=' + javaHome + '" to ' + envPath, 'y'):
         with open(envPath, 'a') as fp:
             print >> fp, 'JAVA_HOME=' + javaHome
-            
+
     return javaHome
 
 class ArgParser(ArgumentParser):
@@ -942,7 +944,7 @@
         self.add_argument('-d', action='store_const', const=8000, dest='java_dbg_port', help='alias for "-dbg 8000"')
         self.add_argument('--cp-pfx', dest='cp_prefix', help='class path prefix', metavar='<arg>')
         self.add_argument('--cp-sfx', dest='cp_suffix', help='class path suffix', metavar='<arg>')
-        self.add_argument('--J', dest='java_args', help='Java VM arguments (e.g. --J @-dsa)', metavar='@<args>', default=DEFAULT_JAVA_ARGS)
+        self.add_argument('--J', dest='java_args', help='Java VM arguments (e.g. --J @-dsa)', metavar='@<args>', default='-ea -Xss2m -Xmx1g')
         self.add_argument('--Jp', action='append', dest='java_args_pfx', help='prefix Java VM arguments (e.g. --Jp @-dsa)', metavar='@<args>', default=[])
         self.add_argument('--Ja', action='append', dest='java_args_sfx', help='suffix Java VM arguments (e.g. --Ja @-dsa)', metavar='@<args>', default=[])
         self.add_argument('--user-home', help='users home directory', metavar='<path>', default=os.path.expanduser('~'))
@@ -987,8 +989,8 @@
 
 def _format_commands():
     msg = '\navailable commands:\n\n'
-    for cmd in sorted(commands.iterkeys()):
-        c, _ = commands[cmd][:2]
+    for cmd in sorted(_commands.iterkeys()):
+        c, _ = _commands[cmd][:2]
         doc = c.__doc__
         if doc is None:
             doc = ''
@@ -1075,7 +1077,7 @@
 
     if env is None:
         env = os.environ
-        
+
     if _opts.verbose:
         if _opts.very_verbose:
             log('Environment variables:')
@@ -1108,17 +1110,17 @@
                 for line in iter(stream.readline, ''):
                     f(line)
                 stream.close()
-            stdout=out if not callable(out) else subprocess.PIPE
-            stderr=err if not callable(err) else subprocess.PIPE
+            stdout = out if not callable(out) else subprocess.PIPE
+            stderr = err if not callable(err) else subprocess.PIPE
             p = subprocess.Popen(args, cwd=cwd, stdout=stdout, stderr=stderr, preexec_fn=preexec_fn, creationflags=creationflags, env=env)
             _currentSubprocess = (p, args)
             if callable(out):
                 t = Thread(target=redirect, args=(p.stdout, out))
-                t.daemon = True # thread dies with the program
+                t.daemon = True  # thread dies with the program
                 t.start()
             if callable(err):
                 t = Thread(target=redirect, args=(p.stderr, err))
-                t.daemon = True # thread dies with the program
+                t.daemon = True  # thread dies with the program
                 t.start()
             if timeout is None or timeout == 0:
                 retcode = waitOn(p)
@@ -1141,7 +1143,7 @@
             if _opts.very_verbose:
                 raise subprocess.CalledProcessError(retcode, ' '.join(args))
             else:
-                log('[exit code: ' + str(retcode)+ ']')
+                log('[exit code: ' + str(retcode) + ']')
         abort(retcode)
 
     return retcode
@@ -1158,7 +1160,7 @@
     """
     Adds the platform specific library prefix to a name
     """
-    os = get_os();
+    os = get_os()
     if os == 'linux' or os == 'solaris' or os == 'darwin':
         return 'lib' + name
     return name
@@ -1167,7 +1169,7 @@
     """
     Adds the platform specific library suffix to a name
     """
-    os = get_os();
+    os = get_os()
     if os == 'windows':
         return name + '.dll'
     if os == 'linux' or os == 'solaris':
@@ -1181,7 +1183,7 @@
 """
 class JavaCompliance:
     def __init__(self, ver):
-        m = re.match('1\.(\d+).*', ver)
+        m = re.match(r'1\.(\d+).*', ver)
         assert m is not None, 'not a recognized version string: ' + ver
         self.value = int(m.group(1))
 
@@ -1193,22 +1195,22 @@
             other = JavaCompliance(other)
 
         return cmp(self.value, other.value)
-    
+
 """
 A Java version as defined in JSR-56
 """
 class JavaVersion:
     def __init__(self, versionString):
-        validChar = '[\x21-\x25\x27-\x29\x2c\x2f-\x5e\x60-\x7f]'
-        separator = '[.\-_]'
+        validChar = r'[\x21-\x25\x27-\x29\x2c\x2f-\x5e\x60-\x7f]'
+        separator = r'[.\-_]'
         m = re.match(validChar + '+(' + separator + validChar + '+)*', versionString)
         assert m is not None, 'not a recognized version string: ' + versionString
-        self.versionString = versionString;
+        self.versionString = versionString
         self.parts = [int(f) if f.isdigit() else f for f in re.split(separator, versionString)]
-        
+
     def __str__(self):
         return self.versionString
-    
+
     def __cmp__(self, other):
         return cmp(self.parts, other.parts)
 
@@ -1219,8 +1221,8 @@
     def __init__(self, opts):
         self.jdk = opts.java_home
         self.debug_port = opts.java_dbg_port
-        self.jar   = exe_suffix(join(self.jdk, 'bin', 'jar'))
-        self.java  = exe_suffix(join(self.jdk, 'bin', 'java'))
+        self.jar = exe_suffix(join(self.jdk, 'bin', 'jar'))
+        self.java = exe_suffix(join(self.jdk, 'bin', 'java'))
         self.javac = exe_suffix(join(self.jdk, 'bin', 'javac'))
         self.javap = exe_suffix(join(self.jdk, 'bin', 'javap'))
         self.javadoc = exe_suffix(join(self.jdk, 'bin', 'javadoc'))
@@ -1298,7 +1300,7 @@
 def logv(msg=None):
     if _opts.verbose:
         log(msg)
-    
+
 def log(msg=None):
     """
     Write a message to the console.
@@ -1332,16 +1334,16 @@
         try:
             output = subprocess.check_output([a, '--version'])
             if 'GNU' in output:
-                return a;
+                return a
         except:
             pass
     abort('Could not find a GNU make executable on the current path.')
 
 def expandvars_in_property(value):
-        result = expandvars(value)
-        if '$' in result or '%' in result:
-            abort('Property contains an undefined environment variable: ' + value)
-        return result
+    result = expandvars(value)
+    if '$' in result or '%' in result:
+        abort('Property contains an undefined environment variable: ' + value)
+    return result
 
 
 def abort(codeOrMessage):
@@ -1352,8 +1354,8 @@
     the object's value is printed and the exit status is one.
     """
 
-    #import traceback
-    #traceback.print_stack()
+    # import traceback
+    # traceback.print_stack()
     currentSubprocess = _currentSubprocess
     if currentSubprocess is not None:
         p, _ = currentSubprocess
@@ -1361,7 +1363,7 @@
             p.kill()
         else:
             _kill_process_group(p.pid)
-    
+
     raise SystemExit(codeOrMessage)
 
 def download(path, urls, verbose=False):
@@ -1451,9 +1453,9 @@
             f.write(content)
 
         log(('modified ' if existed else 'created ') + path)
-        return True;
+        return True
     except IOError as e:
-        abort('Error while writing to ' + path + ': ' + str(e));
+        abort('Error while writing to ' + path + ': ' + str(e))
 
 # Builtin commands
 
@@ -1487,11 +1489,11 @@
         parser.add_argument('remainder', nargs=REMAINDER, metavar='...')
 
     args = parser.parse_args(args)
-    
+
     jdtJar = None
     if args.jdt is not None:
         if args.jdt.endswith('.jar'):
-            jdtJar=args.jdt
+            jdtJar = args.jdt
             if not exists(jdtJar) and os.path.abspath(jdtJar) == os.path.abspath(defaultEcjPath):
                 # Silently ignore JDT if default location is used but not ecj.jar exists there
                 jdtJar = None
@@ -1506,7 +1508,7 @@
         sortedProjects = [project(name) for name in args.only.split(',')]
     else:
         sortedProjects = sorted_deps(projects, includeAnnotationProcessors=True)
-    
+
     for p in sortedProjects:
         if p.native:
             if args.native:
@@ -1521,7 +1523,7 @@
         else:
             if not args.java:
                 continue
-            if exists(join(p.dir, 'plugin.xml')): # eclipse plugin project
+            if exists(join(p.dir, 'plugin.xml')):  # eclipse plugin project
                 continue
 
         # skip building this Java project if its Java compliance level is "higher" than the configured JDK
@@ -1620,11 +1622,11 @@
         ap = p.annotation_processors()
         if len(ap) > 0:
             processorPath = classpath(ap, resolve=True)
-            genDir = p.source_gen_dir();
+            genDir = p.source_gen_dir()
             if exists(genDir):
                 shutil.rmtree(genDir)
             os.mkdir(genDir)
-            processorArgs += ['-processorpath', join(processorPath), '-s', genDir] 
+            processorArgs += ['-processorpath', join(processorPath), '-s', genDir]
         else:
             processorArgs += ['-proc:none']
 
@@ -1633,20 +1635,20 @@
             compliance = str(p.javaCompliance) if p.javaCompliance is not None else args.compliance
             if jdtJar is None:
                 log('Compiling Java sources for {0} with javac...'.format(p.name))
-                
-                
+
+
                 javacCmd = [java().javac, '-g', '-J-Xmx1g', '-source', compliance, '-classpath', cp, '-d', outputDir]
                 if java().debug_port is not None:
                     javacCmd += ['-J-Xdebug', '-J-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(java().debug_port)]
                 javacCmd += processorArgs
                 javacCmd += ['@' + argfile.name]
-                
+
                 if not args.warnAPI:
                     javacCmd.append('-XDignore.symbol.file')
                 run(javacCmd)
             else:
                 log('Compiling Java sources for {0} with JDT...'.format(p.name))
-                                
+
                 jdtArgs = [java().java, '-Xmx1g']
                 if java().debug_port is not None:
                     jdtArgs += ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(java().debug_port)]
@@ -1656,8 +1658,8 @@
                          '-cp', cp, '-g', '-enableJavadoc',
                          '-d', outputDir]
                 jdtArgs += processorArgs
-                         
-                         
+
+
                 jdtProperties = join(p.dir, '.settings', 'org.eclipse.jdt.core.prefs')
                 rootJdtProperties = join(p.suite.dir, 'mx', 'eclipse-settings', 'org.eclipse.jdt.core.prefs')
                 if not exists(jdtProperties) or os.path.getmtime(jdtProperties) < os.path.getmtime(rootJdtProperties):
@@ -1678,12 +1680,12 @@
                     else:
                         jdtArgs += ['-properties', jdtProperties]
                 jdtArgs.append('@' + argfile.name)
-                
+
                 run(jdtArgs)
         finally:
             for n in toBeDeleted:
                 os.remove(n)
-                
+
     for dist in _dists.values():
         archive(['@' + dist.name])
 
@@ -1700,17 +1702,17 @@
     parser.add_argument('-e', '--eclipse-exe', help='location of the Eclipse executable')
     parser.add_argument('-C', '--no-backup', action='store_false', dest='backup', help='do not save backup of modified files')
     parser.add_argument('--projects', action='store', help='comma separated projects to process (omit to process all projects)')
-    
+
     args = parser.parse_args(args)
     if args.eclipse_exe is None:
         args.eclipse_exe = os.environ.get('ECLIPSE_EXE')
     if args.eclipse_exe is None:
         abort('Could not find Eclipse executable. Use -e option or ensure ECLIPSE_EXE environment variable is set.')
-        
+
     # Maybe an Eclipse installation dir was specified - look for the executable in it
     if join(args.eclipse_exe, exe_suffix('eclipse')):
         args.eclipse_exe = join(args.eclipse_exe, exe_suffix('eclipse'))
-        
+
     if not os.path.isfile(args.eclipse_exe) or not os.access(args.eclipse_exe, os.X_OK):
         abort('Not an executable file: ' + args.eclipse_exe)
 
@@ -1725,7 +1727,7 @@
         def __init__(self, settingsFile):
             self.path = settingsFile
             self.javafiles = list()
-            
+
         def settings(self):
             with open(self.path) as fp:
                 return fp.read()
@@ -1744,14 +1746,14 @@
                     self.content = content
                     return True
             os.utime(self.path, self.times)
-            
+
     modified = list()
-    batches = dict() # all sources with the same formatting settings are formatted together
+    batches = dict()  # all sources with the same formatting settings are formatted together
     for p in projects:
         if p.native:
             continue
         sourceDirs = p.source_dirs()
-        
+
         batch = Batch(join(p.dir, '.settings', 'org.eclipse.jdt.core.prefs'))
 
         if not exists(batch.path):
@@ -1776,7 +1778,7 @@
         for fi in batch.javafiles:
             if fi.update():
                 modified.append(fi)
-                
+
     log('{0} files were modified'.format(len(modified)))
     if len(modified) != 0:
         if args.backup:
@@ -1792,25 +1794,25 @@
     return 0
 
 def processorjars():
-    
+
     projs = set()
     for p in sorted_deps():
         if _isAnnotationProcessorDependency(p):
             projs.add(p)
-            
+
     if len(projs) < 0:
         return
-    
+
     pnames = [p.name for p in projs]
     build(['--projects', ",".join(pnames)])
     archive(pnames)
 
 def archive(args):
     """create jar files for projects and distributions"""
-    parser = ArgumentParser(prog='mx archive');
+    parser = ArgumentParser(prog='mx archive')
     parser.add_argument('names', nargs=REMAINDER, metavar='[<project>|@<distribution>]...')
     args = parser.parse_args(args)
-    
+
     for name in args.names:
         if name.startswith('@'):
             dname = name[1:]
@@ -1821,7 +1823,7 @@
             def overwriteCheck(zf, arcname, source):
                 if arcname in zf.namelist():
                     log('warning: ' + d.path + ': overwriting ' + arcname + ' [source: ' + source + ']')
-                
+
             try:
                 zf = zipfile.ZipFile(tmp, 'w')
                 for dep in sorted_deps(d.deps, includeLibs=True):
@@ -1846,7 +1848,7 @@
                         if java().javaCompliance < p.javaCompliance:
                             log('Excluding {0} from {2} (Java compliance level {1} required)'.format(p.name, p.javaCompliance, d.path))
                             continue
-    
+
                         logv('[' + d.path + ': adding project ' + p.name + ']')
                         outputDir = p.output_dir()
                         for root, _, files in os.walk(outputDir):
@@ -1876,7 +1878,7 @@
                 shutil.rmtree(services)
                 # Atomic on Unix
                 shutil.move(tmp, d.path)
-                #print time.time(), 'move:', tmp, '->', d.path
+                # print time.time(), 'move:', tmp, '->', d.path
                 d.notify_updated()
             finally:
                 if exists(tmp):
@@ -1924,11 +1926,11 @@
                     out.write(line + '\n')
                 else:
                     p = project(m.group(1))
-                    
+
                     for pkg in p.defined_java_packages():
                         if not pkg.startswith(p.name):
                             abort('package in {0} does not have prefix matching project name: {1}'.format(p, pkg))
-                    
+
                     ignoredDeps = set([name for name in p.deps if project(name, False) is not None])
                     for pkg in p.imported_java_packages():
                         for name in p.deps:
@@ -1941,7 +1943,7 @@
                                 if pkg in dep.extended_java_packages():
                                     ignoredDeps.discard(name)
                     if len(ignoredDeps) != 0:
-                        candidates = set();
+                        candidates = set()
                         # Compute dependencies based on projects required by p
                         for d in sorted_deps():
                             if not d.defined_java_packages().isdisjoint(p.imported_java_packages()):
@@ -1950,16 +1952,16 @@
                         for c in list(candidates):
                             candidates.difference_update(c.all_deps([], False, False))
                         candidates = [d.name for d in candidates]
-                        
+
                         abort('{0}:{1}: {2} does not use any packages defined in these projects: {3}\nComputed project dependencies: {4}'.format(
                             projectsFile, lineNo, p, ', '.join(ignoredDeps), ','.join(candidates)))
-                    
+
                     out.write('project@' + m.group(1) + '@dependencies=' + ','.join(p.canonical_deps()) + '\n')
                 lineNo = lineNo + 1
             content = out.getvalue()
         if update_file(projectsFile, content):
             changedFiles += 1
-    return changedFiles;
+    return changedFiles
 
 def checkstyle(args):
     """run Checkstyle on the Java sources
@@ -1971,7 +1973,7 @@
 
     parser.add_argument('-f', action='store_true', dest='force', help='force checking (disables timestamp checking)')
     args = parser.parse_args(args)
-    
+
     totalErrors = 0
     for p in sorted_deps():
         if p.native:
@@ -1981,7 +1983,7 @@
 
         if not exists(dotCheckstyle):
             continue
-        
+
         # skip checking this Java project if its Java compliance level is "higher" than the configured JDK
         if java().javaCompliance < p.javaCompliance:
             log('Excluding {0} from checking (Java compliance level {1} required)'.format(p.name, p.javaCompliance))
@@ -2074,13 +2076,12 @@
                     finally:
                         if exists(auditfileName):
                             errors = []
-                            source = None
+                            source = [None]
                             def start_element(name, attrs):
                                 if name == 'file':
-                                    global source
-                                    source = attrs['name']
+                                    source[0] = attrs['name']
                                 elif name == 'error':
-                                    errors.append('{}:{}: {}'.format(source, attrs['line'], attrs['message']))
+                                    errors.append('{}:{}: {}'.format(source[0], attrs['line'], attrs['message']))
 
                             p = xml.parsers.expat.ParserCreate()
                             p.StartElementHandler = start_element
@@ -2108,7 +2109,7 @@
 
     suppliedParser = parser is not None
 
-    parser = parser if suppliedParser else ArgumentParser(prog='mx build');
+    parser = parser if suppliedParser else ArgumentParser(prog='mx build')
     parser.add_argument('--no-native', action='store_false', dest='native', help='do not clean native projects')
     parser.add_argument('--no-java', action='store_false', dest='java', help='do not clean Java projects')
 
@@ -2120,13 +2121,13 @@
                 run([gmake_cmd(), '-C', p.dir, 'clean'])
         else:
             if args.java:
-                genDir = p.source_gen_dir();
+                genDir = p.source_gen_dir()
                 if genDir != '' and exists(genDir):
                     log('Clearing {0}...'.format(genDir))
                     for f in os.listdir(genDir):
                         shutil.rmtree(join(genDir, f))
-                    
-                    
+
+
                 outputDir = p.output_dir()
                 if outputDir != '' and exists(outputDir):
                     log('Removing {0}...'.format(outputDir))
@@ -2150,8 +2151,8 @@
         return
 
     name = args[0]
-    if not commands.has_key(name):
-        hits = [c for c in commands.iterkeys() if c.startswith(name)]
+    if not _commands.has_key(name):
+        hits = [c for c in _commands.iterkeys() if c.startswith(name)]
         if len(hits) == 1:
             name = hits[0]
         elif len(hits) == 0:
@@ -2159,7 +2160,7 @@
         else:
             abort('mx: command \'{0}\' is ambiguous\n    {1}'.format(name, ' '.join(hits)))
 
-    value = commands[name]
+    value = _commands[name]
     (func, usage) = value[:2]
     doc = func.__doc__
     if len(value) > 2:
@@ -2206,10 +2207,12 @@
     slm.close('sourceLookupDirector')
     return slm
 
-def make_eclipse_attach(hostname, port, name=None, deps=[]):
+def make_eclipse_attach(hostname, port, name=None, deps=None):
     """
     Creates an Eclipse launch configuration file for attaching to a Java process.
     """
+    if deps is None:
+        deps = []
     slm = _source_locator_memento(deps)
     launch = XMLDoc()
     launch.open('launchConfiguration', {'type' : 'org.eclipse.jdt.launching.remoteJavaApplication'})
@@ -2232,10 +2235,12 @@
         os.makedirs(eclipseLaunches)
     return update_file(join(eclipseLaunches, name + '.launch'), launch)
 
-def make_eclipse_launch(javaArgs, jre, name=None, deps=[]):
+def make_eclipse_launch(javaArgs, jre, name=None, deps=None):
     """
     Creates an Eclipse launch configuration file for running/debugging a Java command.
     """
+    if deps is None:
+        deps = []
     mainClass = None
     vmArgs = []
     appArgs = []
@@ -2302,7 +2307,7 @@
 
     if suite is None:
         suite = _mainSuite
-        
+
     if buildProcessorJars:
         processorjars()
 
@@ -2329,7 +2334,7 @@
             out.element('classpathentry', {'kind' : 'src', 'path' : src})
 
         if len(p.annotation_processors()) > 0:
-            genDir = p.source_gen_dir();
+            genDir = p.source_gen_dir()
             if not exists(genDir):
                 os.mkdir(genDir)
             out.element('classpathentry', {'kind' : 'src', 'path' : 'src_gen'})
@@ -2337,12 +2342,12 @@
         # Every Java program depends on the JRE
         out.element('classpathentry', {'kind' : 'con', 'path' : 'org.eclipse.jdt.launching.JRE_CONTAINER'})
 
-        if exists(join(p.dir, 'plugin.xml')): # eclipse plugin project
+        if exists(join(p.dir, 'plugin.xml')):  # eclipse plugin project
             out.element('classpathentry', {'kind' : 'con', 'path' : 'org.eclipse.pde.core.requiredPlugins'})
 
         for dep in p.all_deps([], True):
             if dep == p:
-                continue;
+                continue
 
             if dep.isLibrary():
                 if hasattr(dep, 'eclipse.container'):
@@ -2419,7 +2424,7 @@
             out.element('name', data='net.sf.eclipsecs.core.CheckstyleBuilder')
             out.element('arguments', data='')
             out.close('buildCommand')
-        if exists(join(p.dir, 'plugin.xml')): # eclipse plugin project
+        if exists(join(p.dir, 'plugin.xml')):  # eclipse plugin project
             for buildCommand in ['org.eclipse.pde.ManifestBuilder', 'org.eclipse.pde.SchemaBuilder']:
                 out.open('buildCommand')
                 out.element('name', data=buildCommand)
@@ -2427,19 +2432,19 @@
                 out.close('buildCommand')
 
         if _isAnnotationProcessorDependency(p):
-            _genEclipseBuilder(out, p, 'Jar.launch', 'archive ' + p.name, refresh = False, async = False, xmlIndent='', xmlStandalone='no')
-            _genEclipseBuilder(out, p, 'Refresh.launch', '', refresh = True, async = True)
-                       
+            _genEclipseBuilder(out, p, 'Jar.launch', 'archive ' + p.name, refresh=False, async=False, xmlIndent='', xmlStandalone='no')
+            _genEclipseBuilder(out, p, 'Refresh.launch', '', refresh=True, async=True)
+
         if projToDist.has_key(p.name):
             dist, distDeps = projToDist[p.name]
             _genEclipseBuilder(out, p, 'Create' + dist.name + 'Dist.launch', 'archive @' + dist.name, refresh=False, async=True)
-        
+
         out.close('buildSpec')
         out.open('natures')
         out.element('nature', data='org.eclipse.jdt.core.javanature')
         if exists(csConfig):
             out.element('nature', data='net.sf.eclipsecs.core.CheckstyleNature')
-        if exists(join(p.dir, 'plugin.xml')): # eclipse plugin project
+        if exists(join(p.dir, 'plugin.xml')):  # eclipse plugin project
             out.element('nature', data='org.eclipse.pde.PluginNature')
         out.close('natures')
         out.close('projectDescription')
@@ -2462,7 +2467,7 @@
                     if len(p.annotation_processors()) > 0:
                         content = content.replace('org.eclipse.jdt.core.compiler.processAnnotations=disabled', 'org.eclipse.jdt.core.compiler.processAnnotations=enabled')
                     update_file(join(settingsDir, name), content)
-        
+
         if len(p.annotation_processors()) > 0:
             out = XMLDoc()
             out.open('factorypath')
@@ -2495,50 +2500,50 @@
     return p in sorted_deps(annotation_processors())
 
 def _genEclipseBuilder(dotProjectDoc, p, name, mxCommand, refresh=True, async=False, logToConsole=False, xmlIndent='\t', xmlStandalone=None):
-    launchOut = XMLDoc();
+    launchOut = XMLDoc()
     consoleOn = 'true' if logToConsole else 'false'
     launchOut.open('launchConfiguration', {'type' : 'org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType'})
-    launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.core.capture_output',                'value': consoleOn})
+    launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.core.capture_output', 'value': consoleOn})
     launchOut.open('mapAttribute', {'key' : 'org.eclipse.debug.core.environmentVariables'})
-    launchOut.element('mapEntry', {'key' : 'JAVA_HOME',	'value' : java().jdk})
+    launchOut.element('mapEntry', {'key' : 'JAVA_HOME', 	'value' : java().jdk})
     launchOut.close('mapAttribute')
-    
+
     if refresh:
-        launchOut.element('stringAttribute',  {'key' : 'org.eclipse.debug.core.ATTR_REFRESH_SCOPE',            'value': '${project}'})
-    launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_CONSOLE_OUTPUT_ON',          'value': consoleOn})
-    launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND',       'value': 'true' if async else 'false'})
-    
+        launchOut.element('stringAttribute', {'key' : 'org.eclipse.debug.core.ATTR_REFRESH_SCOPE', 'value': '${project}'})
+    launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_CONSOLE_OUTPUT_ON', 'value': consoleOn})
+    launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND', 'value': 'true' if async else 'false'})
+
     baseDir = dirname(dirname(os.path.abspath(__file__)))
-    
+
     cmd = 'mx.sh'
     if get_os() == 'windows':
         cmd = 'mx.cmd'
-    launchOut.element('stringAttribute',  {'key' : 'org.eclipse.ui.externaltools.ATTR_LOCATION',           'value': join(baseDir, cmd) })
-    launchOut.element('stringAttribute',  {'key' : 'org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS',    'value': 'auto,full,incremental'})
-    launchOut.element('stringAttribute',  {'key' : 'org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS',     'value': mxCommand})
-    launchOut.element('booleanAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED','value': 'true'})
-    launchOut.element('stringAttribute',  {'key' : 'org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY',  'value': p.suite.dir})
-    
-    
+    launchOut.element('stringAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_LOCATION', 'value': join(baseDir, cmd) })
+    launchOut.element('stringAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS', 'value': 'auto,full,incremental'})
+    launchOut.element('stringAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS', 'value': mxCommand})
+    launchOut.element('booleanAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED', 'value': 'true'})
+    launchOut.element('stringAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY', 'value': p.suite.dir})
+
+
     launchOut.close('launchConfiguration')
-    
+
     externalToolDir = join(p.dir, '.externalToolBuilders')
-    
+
     if not exists(externalToolDir):
         os.makedirs(externalToolDir)
     update_file(join(externalToolDir, name), launchOut.xml(indent=xmlIndent, standalone=xmlStandalone, newl='\n'))
-    
+
     dotProjectDoc.open('buildCommand')
     dotProjectDoc.element('name', data='org.eclipse.ui.externaltools.ExternalToolBuilder')
     dotProjectDoc.element('triggers', data='auto,full,incremental,')
     dotProjectDoc.open('arguments')
     dotProjectDoc.open('dictionary')
-    dotProjectDoc.element('key', data = 'LaunchConfigHandle')
-    dotProjectDoc.element('value', data = '<project>/.externalToolBuilders/' + name)
+    dotProjectDoc.element('key', data='LaunchConfigHandle')
+    dotProjectDoc.element('value', data='<project>/.externalToolBuilders/' + name)
     dotProjectDoc.close('dictionary')
     dotProjectDoc.open('dictionary')
-    dotProjectDoc.element('key', data = 'incclean')
-    dotProjectDoc.element('value', data = 'true')
+    dotProjectDoc.element('key', data='incclean')
+    dotProjectDoc.element('value', data='true')
     dotProjectDoc.close('dictionary')
     dotProjectDoc.close('arguments')
     dotProjectDoc.close('buildCommand')
@@ -2548,9 +2553,9 @@
     Populate the workspace's working set configuration with working sets generated from project data.
     If the workspace already contains working set definitions, the existing ones will be retained and extended.
     In case mx/env does not contain a WORKSPACE definition pointing to the workspace root directory, the Graal project root directory will be assumed.
-    If no workspace root directory can be identified, the Graal project root directory is used and the user has to place the workingsets.xml file by hand. 
+    If no workspace root directory can be identified, the Graal project root directory is used and the user has to place the workingsets.xml file by hand.
     """
-    
+
     # identify the location where to look for workingsets.xml
     wsfilename = 'workingsets.xml'
     wsroot = suite.dir
@@ -2560,7 +2565,7 @@
     if not exists(wsdir):
         wsdir = wsroot
     wspath = join(wsdir, wsfilename)
-    
+
     # gather working set info from project data
     workingSets = dict()
     for p in projects():
@@ -2571,24 +2576,24 @@
                 workingSets[w] = [p.name]
             else:
                 workingSets[w].append(p.name)
-    
+
     if exists(wspath):
         wsdoc = _copy_workingset_xml(wspath, workingSets)
     else:
         wsdoc = _make_workingset_xml(workingSets)
-    
+
     update_file(wspath, wsdoc.xml(newl='\n'))
 
 def _make_workingset_xml(workingSets):
     wsdoc = XMLDoc()
     wsdoc.open('workingSetManager')
-    
+
     for w in sorted(workingSets.keys()):
         _workingset_open(wsdoc, w)
         for p in workingSets[w]:
             _workingset_element(wsdoc, p)
         wsdoc.close('workingSet')
-    
+
     wsdoc.close('workingSetManager')
     return wsdoc
 
@@ -2597,16 +2602,16 @@
     target.open('workingSetManager')
 
     parser = xml.parsers.expat.ParserCreate()
-    
+
     class ParserState(object):
         def __init__(self):
             self.current_ws_name = 'none yet'
             self.current_ws = None
             self.seen_ws = list()
             self.seen_projects = list()
-    
+
     ps = ParserState()
-    
+
     # parsing logic
     def _ws_start(name, attributes):
         if name == 'workingSet':
@@ -2619,7 +2624,7 @@
                 ps.current_ws = None
             target.open(name, attributes)
             parser.StartElementHandler = _ws_item
-    
+
     def _ws_end(name):
         if name == 'workingSet':
             if not ps.current_ws is None:
@@ -2636,22 +2641,22 @@
                     for p in workingSets[w]:
                         _workingset_element(target, p)
                     target.close('workingSet')
-    
+
     def _ws_item(name, attributes):
         if name == 'item':
             if ps.current_ws is None:
                 target.element(name, attributes)
             else:
-                p_name = attributes['elementID'][1:] # strip off the leading '='
+                p_name = attributes['elementID'][1:]  # strip off the leading '='
                 _workingset_element(target, p_name)
                 ps.seen_projects.append(p_name)
-    
+
     # process document
     parser.StartElementHandler = _ws_start
     parser.EndElementHandler = _ws_end
     with open(wspath, 'r') as wsfile:
         parser.ParseFile(wsfile)
-    
+
     target.close('workingSetManager')
     return target
 
@@ -2660,22 +2665,19 @@
 
 def _workingset_element(wsdoc, p):
     wsdoc.element('item', {'elementID': '=' + p, 'factoryID': 'org.eclipse.jdt.ui.PersistableJavaElementFactory'})
-    
+
 def netbeansinit(args, suite=None):
     """(re)generate NetBeans project configurations"""
 
     if suite is None:
         suite = _mainSuite
 
-    def println(out, obj):
-        out.write(str(obj) + '\n')
-
     updated = False
     for p in projects():
         if p.native:
             continue
 
-        if exists(join(p.dir, 'plugin.xml')): # eclipse plugin project
+        if exists(join(p.dir, 'plugin.xml')):  # eclipse plugin project
             continue
 
         if not exists(join(p.dir, 'nbproject')):
@@ -2715,7 +2717,7 @@
         firstDep = True
         for dep in p.all_deps([], True):
             if dep == p:
-                continue;
+                continue
 
             if not dep.isLibrary():
                 n = dep.name.replace('.', '_')
@@ -2834,7 +2836,7 @@
                 print >> out, 'src.' + src + '.dir=${' + ref + '}'
 
         javacClasspath = []
-        
+
         deps = p.all_deps([], True)
         annotationProcessorOnlyDeps = []
         if len(p.annotation_processors()) > 0:
@@ -2843,12 +2845,12 @@
                 if not apDep in deps:
                     deps.append(apDep)
                     annotationProcessorOnlyDeps.append(apDep)
-        
-        annotationProcessorReferences = [];
-        
+
+        annotationProcessorReferences = []
+
         for dep in deps:
             if dep == p:
-                continue;
+                continue
 
             if dep.isLibrary():
                 if not dep.mustExist:
@@ -2870,12 +2872,12 @@
                 javacClasspath.append('${' + ref + '}')
             else:
                 annotationProcessorReferences.append('${' + ref + '}')
-                annotationProcessorReferences +=  ":\\\n    ${" + ref + "}"
+                annotationProcessorReferences += ":\\\n    ${" + ref + "}"
 
         print >> out, 'javac.classpath=\\\n    ' + (os.pathsep + '\\\n    ').join(javacClasspath)
         print >> out, 'javac.test.processorpath=${javac.test.classpath}\\\n    ' + (os.pathsep + '\\\n    ').join(annotationProcessorReferences)
         print >> out, 'javac.processorpath=${javac.classpath}\\\n    ' + (os.pathsep + '\\\n    ').join(annotationProcessorReferences)
-    
+
         updated = update_file(join(p.dir, 'nbproject', 'project.properties'), out.getvalue()) or updated
         out.close()
 
@@ -2906,7 +2908,7 @@
             rm(join(p.dir, p.name + '.jar'))
         except:
             log("Error removing {0}".format(p.name + '.jar'))
-            
+
 
 def ideinit(args, suite=None):
     """(re)generate Eclipse and NetBeans project configurations"""
@@ -2989,11 +2991,13 @@
                 logv('[package-list file exists - skipping {0}]'.format(p.name))
 
 
-    def find_packages(sourceDirs, pkgs=set()):
+    def find_packages(sourceDirs, pkgs=None):
+        if pkgs is None:
+            pkgs = set()
         for sourceDir in sourceDirs:
             for root, _, files in os.walk(sourceDir):
                 if len([name for name in files if name.endswith('.java')]) != 0:
-                    pkg = root[len(sourceDir) + 1:].replace(os.sep,'.')
+                    pkg = root[len(sourceDir) + 1:].replace(os.sep, '.')
                     if len(packages) == 0 or pkg in packages:
                         if len(exclude_packages) == 0 or not pkg in exclude_packages:
                             pkgs.add(pkg)
@@ -3011,7 +3015,7 @@
         for p in projects:
             # The project must be built to ensure javadoc can find class files for all referenced classes
             build(['--no-native', '--projects', p.name])
-            
+
             pkgs = find_packages(p.source_dirs(), set())
             deps = p.all_deps([], includeLibs=False, includeSelf=False)
             links = ['-link', 'http://docs.oracle.com/javase/' + str(p.javaCompliance.value) + '/docs/api/']
@@ -3049,11 +3053,11 @@
             finally:
                 if delOverviewFile:
                     os.remove(overviewFile)
-                
+
     else:
         # The projects must be built to ensure javadoc can find class files for all referenced classes
         build(['--no-native'])
-        
+
         pkgs = set()
         sp = []
         names = []
@@ -3107,7 +3111,7 @@
             rdelimLen = 0
         old = content[lindex:rindex + rdelimLen]
         return content.replace(old, repl)
-        
+
 # Post-process an overview-summary.html file to move the
 # complete overview to the top of the page
 def _fix_overview_summary(path, topLink):
@@ -3139,7 +3143,7 @@
     assert chunk1.text, 'Could not find header section in ' + path
     assert chunk2.text, 'Could not find footer section in ' + path
 
-    content = chunk1.replace(content, '<div class="header"><div class="subTitle"><div class="block">' + topLink + chunk2.text +'</div></div></div>')
+    content = chunk1.replace(content, '<div class="header"><div class="subTitle"><div class="block">' + topLink + chunk2.text + '</div></div></div>')
     content = chunk2.replace(content, '')
 
     with open(path, 'w') as fp:
@@ -3171,9 +3175,9 @@
     if chunk1.text:
         if chunk2.text:
             repl = re.sub(r'<h2 title=(.*) Description</h2>', r'<h1 title=\1</h1>', chunk2.text, 1)
-            content = chunk1.replace(content, '<div class="header">' + repl +'</div></div>')
+            content = chunk1.replace(content, '<div class="header">' + repl + '</div></div>')
             content = chunk2.replace(content, '')
-        
+
             with open(path, 'w') as fp:
                 fp.write(content)
         else:
@@ -3235,12 +3239,12 @@
 <tbody>"""
                     color = 'row'
                     for p in projects:
-                        print >> fp2, '<tr class="{1}Color"><td class="colFirst"><a href="../{0}/javadoc/index.html", target = "_top">{0}</a></td><td class="colLast">&nbsp;</td></tr>'.format(p.name, color)
+                        print >> fp2, '<tr class="{1}Color"><td class="colFirst"><a href="../{0}/javadoc/index.html",target = "_top">{0}</a></td><td class="colLast">&nbsp;</td></tr>'.format(p.name, color)
                         color = 'row' if color == 'alt' else 'alt'
-                        
+
                     print >> fp2, '</tbody></table></div>'
                     print >> fp2, content[idx:]
-        
+
         title = args.title if args.title is not None else args.name
         javadoc(['--base', tmpbase,
                  '--unified',
@@ -3256,10 +3260,10 @@
                 if not 'version' in subprocess.check_output(['dot', '-V'], stderr=subprocess.STDOUT):
                     dotErr = 'dot -V does not print a string containing "version"'
             except subprocess.CalledProcessError as e:
-                dotErr = 'error calling "dot -V": {}'.format(e) 
+                dotErr = 'error calling "dot -V": {}'.format(e)
             except OSError as e:
                 dotErr = 'error calling "dot -V": {}'.format(e)
-                 
+
             if dotErr != None:
                 abort('cannot generate dependency graph: ' + dotErr)
 
@@ -3273,7 +3277,7 @@
                 print >> fp, 'rankdir=BT;'
                 print >> fp, 'size = "' + str(dim) + ',' + str(dim) + '";'
                 print >> fp, 'node [shape=rect, fontcolor="blue"];'
-                #print >> fp, 'edge [color="green"];'
+                # print >> fp, 'edge [color="green"];'
                 for p in projects:
                     print >> fp, '"' + p.name + '" [URL = "../' + p.name + '/javadoc/index.html", target = "_top"]'
                     for dep in p.canonical_deps():
@@ -3284,7 +3288,7 @@
                     d = p.max_depth()
                     depths.setdefault(d, list()).append(p.name)
                 print >> fp, '}'
-    
+
             run(['dot', '-Tsvg', '-o' + svg, '-Tjpg', '-o' + jpg, dot])
 
             # Post-process generated SVG to remove title elements which most browsers
@@ -3295,7 +3299,7 @@
             content = re.sub('xlink:title="[^"]*"', '', content)
             with open(svg, 'w') as fp:
                 fp.write(content)
-        
+
             # Create HTML that embeds the svg file in an <object> frame
             with open(html, 'w') as fp:
                 print >> fp, '<html><body><object data="{}.svg" type="image/svg+xml"></object></body></html>'.format(args.dot_output_base)
@@ -3346,7 +3350,7 @@
 def select_items(items, descriptions=None, allowMultiple=True):
     """
     Presents a command line interface for selecting one or more (if allowMultiple is true) items.
-    
+
     """
     if len(items) <= 1:
         return items
@@ -3370,10 +3374,10 @@
             except:
                 log('Selection contains non-numeric characters: "' + ' '.join(s) + '"')
                 continue
-            
+
             if allowMultiple and 0 in s:
                 return items
-            
+
             indexes = []
             for n in s:
                 if n not in range(1, len(items) + 1):
@@ -3390,15 +3394,15 @@
 def javap(args):
     """disassemble classes matching given pattern with javap"""
 
-    javap = java().javap
-    if not exists(javap):
-        abort('The javap executable does not exists: ' + javap)
+    javapExe = java().javap
+    if not exists(javapExe):
+        abort('The javap executable does not exists: ' + javapExe)
     else:
         candidates = findclass(args, logToConsole=False)
         if len(candidates) == 0:
             log('no matches')
         selection = select_items(candidates)
-        run([javap, '-private', '-verbose', '-classpath', classpath()] + selection)
+        run([javapExe, '-private', '-verbose', '-classpath', classpath()] + selection)
 
 def show_projects(args):
     """show all loaded projects"""
@@ -3408,7 +3412,7 @@
             log(projectsFile)
             for p in s.projects:
                 log('\t' + p.name)
-                
+
 def ask_yes_no(question, default=None):
     """"""
     assert not default or default == 'y' or default == 'n'
@@ -3437,7 +3441,7 @@
 # If any of the format args are instances of Callable, then they are called with an 'env' are before being
 # used in the call to str.format().
 # Extensions should update this table directly
-commands = {
+_commands = {
     'about': [about, ''],
     'build': [build, '[options]'],
     'checkstyle': [checkstyle, ''],
@@ -3502,8 +3506,8 @@
     command = commandAndArgs[0]
     command_args = commandAndArgs[1:]
 
-    if not commands.has_key(command):
-        hits = [c for c in commands.iterkeys() if c.startswith(command)]
+    if not _commands.has_key(command):
+        hits = [c for c in _commands.iterkeys() if c.startswith(command)]
         if len(hits) == 1:
             command = hits[0]
         elif len(hits) == 0:
@@ -3511,7 +3515,7 @@
         else:
             abort('mx: command \'{0}\' is ambiguous\n    {1}'.format(command, ' '.join(hits)))
 
-    c, _ = commands[command][:2]
+    c, _ = _commands[command][:2]
     def term_handler(signum, frame):
         abort(1)
     signal.signal(signal.SIGTERM, term_handler)