internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: DataBiosphere/toil

Issue:
Progress bar is cool but...
It requires the terminal to be `reset` when run in a screen session.  Also, for cactus anyway, it spends the vast majority of the runtime at 99%/100%.

┆Issue is synchronized with this [Jira Task](https://ucsc-cgl.atlassian.net/browse/TOIL-558)
┆Issue Number: TOIL-558



Discussion:
The reset issue might be the same as https://github.com/Rockhopper-Technologies/enlighten/issues/16 which was closed for insufficient information. Maybe we can pick that back up.

The bar is going to spend most of its time almost done because it can only see the issued jobs. If we want it to use not-yet-ready-to-run jobs in the denominator we need an efficient way to get those from the job store, without walking the whole stored tree and with some notion of completed, deleted jobs, which I think we don't have.
@glennhickey, do you still see the issue with enlighten 1.5.2?
Upgrading to 1.5.2 does seem to fix it.  Thanks @avylove -- this seems like a simple patch for toil then..

Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -44,7 +44,7 @@ def runSetup():
     dateutil = 'python-dateutil'
     addict = 'addict<=2.2.0'
     pathlib2 = 'pathlib2==2.3.2'
-    enlighten = 'enlighten>=1.5.1, <2'
+    enlighten = 'enlighten>=1.5.2, <2'
 
     core_reqs = [
         dill,


Test patch:
Repository: DataBiosphere/toil

Issue:
Failing to run workflows on Slurm batchsystem
When running CWL workflows with batchsystem slurm the execution fails due to an error:
```
(...)/toil/lib/python3.7/site-packages/toil/batchSystems/slurm.py", line 106, in _getJobDetailsFromSacct
    values = line.decode('utf-8').strip().split('|')
AttributeError: 'str' object has no attribute 'decode'
```

I have tested running the same CWL worklfow on versions 3.20 and 3.24 without issues but I cannot tell when exactly this behaviour has been introduced.

┆Issue is synchronized with this [Jira Task](https://ucsc-cgl.atlassian.net/browse/TOIL-595)
┆Issue Number: TOIL-595



Discussion:

Resolving patch:
diff --git a/src/toil/batchSystems/slurm.py b/src/toil/batchSystems/slurm.py
--- a/src/toil/batchSystems/slurm.py
+++ b/src/toil/batchSystems/slurm.py
@@ -101,9 +101,9 @@ def _getJobDetailsFromSacct(self, slurmJobID):
                     '-S', '1970-01-01'] # override start time limit
 
             stdout = call_command(args)
-            for line in stdout:
+            for line in stdout.split('\n'):
                 logger.debug("%s output %s", args[0], line)
-                values = line.decode('utf-8').strip().split('|')
+                values = line.strip().split('|')
                 if len(values) < 2:
                     continue
                 state, exitcode = values


Test patch:
Repository: DataBiosphere/toil

Issue:
Update minor dependencies
A few of the minor Toil dependencies are outdated, leading to clutter in commands such as `pip list --outdated`:

* `addict<=2.2.0`
  * Latest version is 2.2.1, with the only change being licenses and tests being added to the release versions
* `dill==0.3.1.1`
  * Latest version is 0.3.2, which drops support for Python 3.4 (not supported by toil anyway) and fixes some minor issues
* `docker==2.5.1`
  * This is a few major versions behind, so updating might be a bit more complex. However, there are some newer releases on the 2.x branch.
* `pathlib2==2.3.2`
  * The latest is 2.3.5, which (vs 2.3.2) drops Py3.3 support and fixes some minor issues

If any of these make sense, I'm happy to make a PR updating `setup.py`

┆Issue is synchronized with this [Jira Task](https://ucsc-cgl.atlassian.net/browse/TOIL-597)
┆Issue Number: TOIL-597



Discussion:
We'd definitely welcome a PR updating any of these.

Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -36,14 +36,14 @@ def runSetup():
     kubernetes = 'kubernetes>=10, <11'
     idna = 'idna>=2'
     pytz = 'pytz>=2012'
-    dill = 'dill==0.3.1.1'
+    dill = 'dill>=0.3.2, <0.4'
     six = 'six>=1.10.0'
     future = 'future'
     requests = 'requests>=2, <3'
-    docker = 'docker==2.5.1'
+    docker = 'docker>=2.7.0, <3'
     dateutil = 'python-dateutil'
-    addict = 'addict<=2.2.0'
-    pathlib2 = 'pathlib2==2.3.2'
+    addict = 'addict>=2.2.1, <2.3'
+    pathlib2 = 'pathlib2>=2.3.5, <3'
     enlighten = 'enlighten>=1.5.2, <2'
 
     core_reqs = [


Test patch:
Repository: DataBiosphere/toil

Issue:
The CachingFileStore's destructor can run in its commit thread
The CachingFileStore's destructor can run in its commit thread. This results in it attempting to join the current thread, which fails. This can I think cause the `JobFileStoreTest.testJobFileStore` test to fail.

https://travis-ci.org/github/DataBiosphere/toil/builds/723196253#L1105-L1113

┆Issue is synchronized with this [Jira Task](https://ucsc-cgl.atlassian.net/browse/TOIL-625)
┆Issue Number: TOIL-625



Discussion:
`waitForCommit` just doesn't account for the fact that it can be running inside of `self.commitThread`, presumably after that thread has finished its real work but before it completely goes away. We need to handle that by just not doing anything; the commit is sure to be done, and we can't join ourselves..

Resolving patch:
diff --git a/src/toil/fileStores/cachingFileStore.py b/src/toil/fileStores/cachingFileStore.py
--- a/src/toil/fileStores/cachingFileStore.py
+++ b/src/toil/fileStores/cachingFileStore.py
@@ -1712,12 +1712,17 @@ def exportFile(self, jobStoreFileID, dstUrl):
 
     def waitForCommit(self):
         # We need to block on the upload thread.
+
         # We may be called even if startCommit is not called. In that
         # case, a new instance of this class should have been created by the
         # worker and ought to pick up all our work by PID via the database, and
         # this instance doesn't actually have to commit.
 
-        if self.commitThread is not None:
+        # If running in the destructor, we may already *be* in the commit
+        # thread. It can do some destructor work after it finishes its real
+        # work.
+
+        if self.commitThread is not None and self.commitThread is not threading.current_thread():
             self.commitThread.join()
 
         return True


Test patch:
Repository: DataBiosphere/toil

Issue:
Kubernetes import in retry module needs to be able to fail
https://github.com/DataBiosphere/toil/blob/79c4c43c1f76484c99ec550aee609c6579a6a77c/src/toil/lib/retry.py#L133

This will break the retry module when the `[kubernetes]` extra isn't installed.

┆Issue is synchronized with this [Jira Task](https://ucsc-cgl.atlassian.net/browse/TOIL-678)
┆Issue Number: TOIL-678



Discussion:
also likewise for `botocore`, as shown with `pip install .[cwl] && toil-cwl-runner --help`.

Resolving patch:
diff --git a/src/toil/lib/retry.py b/src/toil/lib/retry.py
--- a/src/toil/lib/retry.py
+++ b/src/toil/lib/retry.py
@@ -130,19 +130,25 @@ def boto_bucket(bucket_name):
 import urllib.error
 import urllib3.exceptions
 import sqlite3
-import kubernetes.client.rest
-import botocore.exceptions
+try:
+    import kubernetes.client.rest
+    import botocore.exceptions
+except ModuleNotFoundError:
+    kubernetes = None
+    botocore = None
 from contextlib import contextmanager
 from typing import List, Optional, Tuple, Callable, Any, Union
 
 log = logging.getLogger(__name__)
 
-SUPPORTED_HTTP_ERRORS = {http.client.HTTPException,
+SUPPORTED_HTTP_ERRORS = [http.client.HTTPException,
                          urllib.error.HTTPError,
                          urllib3.exceptions.HTTPError,
-                         requests.exceptions.HTTPError,
-                         kubernetes.client.rest.ApiException,
-                         botocore.exceptions.ClientError}
+                         requests.exceptions.HTTPError]
+if kubernetes:
+    SUPPORTED_HTTP_ERRORS.append(kubernetes.client.rest.ApiException)
+if botocore:
+    SUPPORTED_HTTP_ERRORS.append(botocore.exceptions.ClientError)
 
 
 class ErrorCondition:


Test patch:
Repository: DataBiosphere/toil

Issue:
Remove mesos offer log messages
@arkal found that in a recent autoscaling test 90+% of the log messages were debug messages about declining mesos offers.

┆Issue is synchronized with this [Jira Story](https://ucsc-cgl.atlassian.net/browse/TOIL-127)
┆Issue Number: TOIL-127



Discussion:
I've found those useful for debugging during development if I've broken things in the Mesos batch system. Is the concern here around spamming the debug logs? If so, perhaps we move them to a yet lower log level?
@fnothaft yeah, we're debugging large runs and removing this message turns 1gb logs into 70mb. I'm also ok with setting it lower and letting the user set a numerical value for `logLevel`.

Resolving patch:
diff --git a/src/toil/batchSystems/mesos/batchSystem.py b/src/toil/batchSystems/mesos/batchSystem.py
--- a/src/toil/batchSystems/mesos/batchSystem.py
+++ b/src/toil/batchSystems/mesos/batchSystem.py
@@ -359,7 +359,6 @@ def registered(self, driver, frameworkId, masterInfo):
 
     def _declineAllOffers(self, driver, offers):
         for offer in offers:
-            log.debug("Declining offer %s.", offer.id.value)
             driver.declineOffer(offer.id)
 
     def _parseOffer(self, offer):
@@ -417,7 +416,6 @@ def resourceOffers(self, driver, offers):
         jobTypes = self.jobQueues.sortedTypes
 
         if not jobTypes:
-            log.debug('There are no queued tasks. Declining Mesos offers.')
             # Without jobs, we can get stuck with no jobs and no new offers until we decline it.
             self._declineAllOffers(driver, offers)
             return
@@ -426,8 +424,6 @@ def resourceOffers(self, driver, offers):
         # Right now, gives priority to largest jobs
         for offer in offers:
             if offer.hostname in self.ignoredNodes:
-                log.debug("Declining offer %s because node %s is designated for termination" %
-                        (offer.id.value, offer.hostname))
                 driver.declineOffer(offer.id)
                 continue
             runnableTasks = []


Test patch:
Repository: DataBiosphere/toil

Issue:
Add 500 status to retriable SDB BotoServerError
We got the following error that resulted in the leader crashing. Looks like it's a transient SDB error and we already have a retry logic for it, but it [only works for 503 error status](https://github.com/DataBiosphere/toil/blob/558f13eb2c1ab17ce90f470a127e9ba6c058a3dd/src/toil/jobStores/aws/utils.py#L349). We should add 500 to it as well.

```
Traceback (most recent call last):
   File "/usr/lib/python3.6/threading.py", line 916, in _bootstrap_inner
     self.run()
   File "/usr/lib/python3.6/threading.py", line 864, in run
     self._target(*self._args, **self._kwargs)
   File "/usr/local/lib/python3.6/dist-packages/toil/statsAndLogging.py", line 190, in statsAndLoggingAggregator
     if jobStore.readStatsAndLogging(callback) == 0:
   File "/usr/local/lib/python3.6/dist-packages/toil/jobStores/aws/jobStore.py", line 627, in readStatsAndLogging
     for info in self._readStatsAndLogging(callback, self.statsFileOwnerID):
   File "/usr/local/lib/python3.6/dist-packages/toil/jobStores/aws/jobStore.py", line 645, in _readStatsAndLogging
     self.filesDomain.name, str(ownerId))))
   File "/usr/local/lib/python3.6/dist-packages/boto/sdb/queryresultset.py", line 81, in __iter__
     consistent_read=self.consistent_read)
   File "/usr/local/lib/python3.6/dist-packages/boto/sdb/connection.py", line 615, in select
     parent=domain)
   File "/usr/local/lib/python3.6/dist-packages/boto/connection.py", line 1170, in get_list
     response = self.make_request(action, params, path, verb)
   File "/usr/local/lib/python3.6/dist-packages/boto/connection.py", line 1116, in make_request
     return self._mexe(http_request)
   File "/usr/local/lib/python3.6/dist-packages/boto/connection.py", line 1028, in _mexe
     raise BotoServerError(response.status, response.reason, body)
 boto.exception.BotoServerError: BotoServerError: 500 Internal Server Error
 <?xml version="1.0"?>
 <Response><Errors><Error><Code>InternalError</Code><Message>Request could not be executed due to an internal service error</Message></Error></Errors><RequestID>ea63c982-4d9a-a07a-22f1-50f79f3cdc34</RequestID></Response>
 
```

┆Issue is synchronized with this [Jira Task](https://ucsc-cgl.atlassian.net/browse/TOIL-727)
┆Issue Number: TOIL-727



Discussion:

Resolving patch:
diff --git a/src/toil/jobStores/aws/utils.py b/src/toil/jobStores/aws/utils.py
--- a/src/toil/jobStores/aws/utils.py
+++ b/src/toil/jobStores/aws/utils.py
@@ -346,7 +346,7 @@ def connection_reset(e):
 
 
 def sdb_unavailable(e):
-    return isinstance(e, BotoServerError) and e.status == 503
+    return isinstance(e, BotoServerError) and e.status in (500, 503)
 
 
 def no_such_sdb_domain(e):


Test patch:
Repository: DataBiosphere/toil

Issue:
Rare `BucketNotEmpty` exception when cleaning S3 jobstore
I've noticed that we rarely get `BucketNotEmpty` exception (shown below) when trying to clean the s3 jobstore (likely due to some rare s3 API issues/inconsistencies). Would be good to include this as a retriable error in [`_delete_bucket`](https://github.com/DataBiosphere/toil/blob/6ad3e5eb0e0aa7067fe71a028ebb0f76de34f51e/src/toil/jobStores/aws/jobStore.py#L1562).

```
botocore.exceptions.ClientError: An error occurred (BucketNotEmpty) when calling the DeleteBucket operation: The bucket you tried to delete is not empty. You must delete all versions in the bucket.
```

┆Issue is synchronized with this [Jira Task](https://ucsc-cgl.atlassian.net/browse/TOIL-685)
┆Issue Number: TOIL-685



Discussion:

Resolving patch:
diff --git a/src/toil/jobStores/aws/utils.py b/src/toil/jobStores/aws/utils.py
--- a/src/toil/jobStores/aws/utils.py
+++ b/src/toil/jobStores/aws/utils.py
@@ -33,6 +33,7 @@
                             S3CreateError,
                             S3CopyError)
 import boto3
+from botocore.exceptions import ClientError
 
 log = logging.getLogger(__name__)
 
@@ -379,7 +380,8 @@ def retryable_s3_errors(e):
             or (isinstance(e, BotoServerError) and e.status == 500)
             # Throttling response sometimes received on bucket creation
             or (isinstance(e, BotoServerError) and e.status == 503 and e.code == 'SlowDown')
-            or (isinstance(e, S3CopyError) and 'try again' in e.message))
+            or (isinstance(e, S3CopyError) and 'try again' in e.message)
+            or (isinstance(e, ClientError) and 'BucketNotEmpty' in str(e)))
 
 
 def retry_s3(delays=default_delays, timeout=default_timeout, predicate=retryable_s3_errors):


Test patch:
Repository: DataBiosphere/toil

Issue:
Error reading lsf.conf (utf-8)
I am running some CWL workfows using LSF submitter but I found the lsf.conf is in utf-8 format and toil failed to decode it:

```
[2020-11-30T20:49:57+0000] [MainThread] [I] [toil] Running Toil version 4.2.0-3aa1da130141039cb357efe36d7df9b9f6ae9b5b on host noah.
Cannot get parameter information from lsf.conf or ego.conf for LIM from host<noah>
[2020-11-30T20:49:58+0000] [Thread-2  ] [E] [toil.batchSystems.abstractGridEngineBatchSystem] GridEngine like batch system failure
Traceback (most recent call last):
  File "~/lib/python3.6/site-packages/toil/batchSystems/abstractGridEngineBatchSystem.py", line 226, in run
    while self._runStep():
  File "~/python3.6/site-packages/toil/batchSystems/abstractGridEngineBatchSystem.py", line 215, in _runStep
    activity |= self.createJobs(newJob)
  File "~/python3.6/site-packages/toil/batchSystems/abstractGridEngineBatchSystem.py", line 121, in createJobs
    subLine = self.prepareSubmission(cpu, memory, jobID, command, jobName)
  File "~/python3.6/site-packages/toil/batchSystems/lsf.py", line 88, in prepareSubmission
    return self.prepareBsub(cpu, memory, jobID) + [command]
  File "~/python3.6/site-packages/toil/batchSystems/lsf.py", line 253, in prepareBsub
    mem_resource = parse_memory_resource(mem)
  File "~/python3.6/site-packages/toil/batchSystems/lsfHelper.py", line 183, in parse_memory_resource
    return parse_memory(mem, True)
  File "~/python3.6/site-packages/toil/batchSystems/lsfHelper.py", line 195, in parse_memory
    lsf_unit = get_lsf_units(resource=resource)
  File "~/python3.6/site-packages/toil/batchSystems/lsfHelper.py", line 136, in get_lsf_units
    lsf_units = apply_conf_file(get_lsf_units_from_stream, LSF_CONF_FILENAME)
  File "~/python3.6/site-packages/toil/batchSystems/lsfHelper.py", line 71, in apply_conf_file
    value = fn(conf_handle)
  File "~/python3.6/site-packages/toil/batchSystems/lsfHelper.py", line 83, in get_lsf_units_from_stream
    for k, v in tokenize_conf_stream(stream):
  File "~/python3.6/site-packages/toil/batchSystems/lsfHelper.py", line 92, in tokenize_conf_stream
    for line in conf_handle:
  File "~/python3.6/encodings/ascii.py", line 26, in decode
    return codecs.ascii_decode(input, self.errors)[0]
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 1765: ordinal not in range(128)
```

┆Issue is synchronized with this [Jira Task](https://ucsc-cgl.atlassian.net/browse/TOIL-737)
┆Issue Number: TOIL-737



Discussion:

Resolving patch:
diff --git a/src/toil/batchSystems/lsfHelper.py b/src/toil/batchSystems/lsfHelper.py
--- a/src/toil/batchSystems/lsfHelper.py
+++ b/src/toil/batchSystems/lsfHelper.py
@@ -65,7 +65,7 @@ def apply_conf_file(fn, conf_filename):
     for env in LSF_CONF_ENV:
         conf_file = get_conf_file(conf_filename, env)
         if conf_file:
-            with open(conf_file) as conf_handle:
+            with open(conf_file, encoding='utf-8') as conf_handle:
                 value = fn(conf_handle)
             if value:
                 return value


Test patch:
Repository: DataBiosphere/toil

Issue:
Fix failing Google job store tests 
There are a couple tests failing for Google job store, due to String/Byte type inconsistencies between Python2/3 related to #3388. 

**Error:** 
```
Traceback (most recent call last):
   File "/builds/databiosphere/toil/src/toil/test/__init__.py", line 663, in fx
     return generalMethod(self, **prms)
   File "/builds/databiosphere/toil/src/toil/test/jobStores/jobStoreTest.py", line 649, in testImportExportFile
     srcUrl, srcMd5 = other._prepareTestFile(store, size)
   File "/builds/databiosphere/toil/src/toil/test/jobStores/jobStoreTest.py", line 1171, in _prepareTestFile
     GoogleJobStore._writeToUrl(StringIO(contents), urlparse.urlparse(url))
   File "/builds/databiosphere/toil/src/toil/jobStores/googleJobStore.py", line 361, in _writeToUrl
     blob.upload_from_file(readable)
   File "/builds/databiosphere/toil/venv/lib/python3.7/site-packages/google/cloud/storage/blob.py", line 946, in upload_from_file
     client, file_obj, content_type, size, num_retries)
   File "/builds/databiosphere/toil/venv/lib/python3.7/site-packages/google/cloud/storage/blob.py", line 867, in _do_upload
     client, stream, content_type, size, num_retries)
   File "/builds/databiosphere/toil/venv/lib/python3.7/site-packages/google/cloud/storage/blob.py", line 700, in _do_multipart_upload
     transport, data, object_metadata, content_type)
   File "/builds/databiosphere/toil/venv/lib/python3.7/site-packages/google/resumable_media/requests/upload.py", line 137, in transmit
     data, metadata, content_type
   File "/builds/databiosphere/toil/venv/lib/python3.7/site-packages/google/resumable_media/_upload.py", line 292, in _prepare_request
     raise TypeError(u"`data` must be bytes, received", type(data))
 TypeError: ('`data` must be bytes, received', <class 'str'>)
```

┆Issue is synchronized with this [Jira Task](https://ucsc-cgl.atlassian.net/browse/TOIL-779)
┆Issue Number: TOIL-779



Discussion:

Resolving patch:
diff --git a/src/toil/jobStores/googleJobStore.py b/src/toil/jobStores/googleJobStore.py
--- a/src/toil/jobStores/googleJobStore.py
+++ b/src/toil/jobStores/googleJobStore.py
@@ -356,7 +356,7 @@ def _supportsUrl(cls, url, export=False):
         return url.scheme.lower() == 'gs'
 
     @classmethod
-    def _writeToUrl(cls, readable: bytes, url, executable=False) -> None:
+    def _writeToUrl(cls, readable: bytes, url: str, executable: bool = False) -> None:
         blob = cls._getBlobFromURL(url)
         blob.upload_from_file(readable)
 


Test patch:
Repository: DataBiosphere/toil

Issue:
Toil command line options can't be placed in a group
I want to group the Toil command line options into their own group in my script's options, because they're so numerous. (Ideally, eventually, I'd like to suppress most of them in the ordinary help output, because the help really should fit on one screen in order to not be overwhelming.)

Toil isn't happy being passed an ArgumentGroup instead of the base parser. It looks like it's trying to do un-Pythonic dispatch on the actual type of its argument:

```
Traceback (most recent call last):
  File "/cluster/home/anovak/python/bin/build-hgvm", line 11, in <module>
    load_entry_point('hgvm-builder', 'console_scripts', 'build-hgvm')()
  File "/hive/users/anovak/ga4gh/hgvm/hgvm-builder/src/hgvmbuilder/build.py", line 1618, in entrypoint
    sys.exit(main(sys.argv))
  File "/hive/users/anovak/ga4gh/hgvm/hgvm-builder/src/hgvmbuilder/build.py", line 1539, in main
    options = parse_args(args) # This holds the nicely-parsed options object
  File "/hive/users/anovak/ga4gh/hgvm/hgvm-builder/src/hgvmbuilder/build.py", line 69, in parse_args
    Job.Runner.addToilOptions(parser.add_argument_group("Toil configuration"))
  File "/cluster/home/anovak/python/lib/python2.7/site-packages/toil/job.py", line 723, in addToilOptions
    addOptions(parser)
  File "/cluster/home/anovak/python/lib/python2.7/site-packages/toil/common.py", line 552, in addOptions
    addLoggingOptions(parser) # This adds the logging stuff.
  File "/cluster/home/anovak/python/lib/python2.7/site-packages/toil/lib/bioio.py", line 116, in addLoggingOptions
    "argparse.ArgumentParser" % parser.__class__)
RuntimeError: Unanticipated class passed to addLoggingOptions(), <class 'argparse._ArgumentGroup'>. Expecting argparse.ArgumentParse
```

Toil should be changed to accept any parser that lets it call the methods it needs without throwing something.

┆Issue is synchronized with this [Jira Story](https://ucsc-cgl.atlassian.net/browse/TOIL-154)
┆Issue Number: TOIL-154



Discussion:

Resolving patch:
diff --git a/src/toil/common.py b/src/toil/common.py
--- a/src/toil/common.py
+++ b/src/toil/common.py
@@ -22,7 +22,7 @@
 import time
 import uuid
 
-from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
+from argparse import _ArgumentGroup, ArgumentParser, ArgumentDefaultsHelpFormatter
 from typing import Optional, Callable, Any, List
 
 from toil import logProcessContext, lookupEnvVar
@@ -336,8 +336,8 @@ def parser_with_common_options(provisioner_options=False, jobstore_option=True):
 
 
 def addOptions(parser: ArgumentParser, config: Config = Config()):
-    if not isinstance(parser, ArgumentParser):
-        raise ValueError(f"Unanticipated class: {parser.__class__}.  Must be: argparse.ArgumentParser.")
+    if not (isinstance(parser, ArgumentParser) or isinstance(parser, _ArgumentGroup)):
+        raise ValueError(f"Unanticipated class: {parser.__class__}.  Must be: argparse.ArgumentParser or ArgumentGroup.")
 
     add_logging_options(parser)
     parser.register("type", "bool", parseBool)  # Custom type for arg=True/False.


Test patch: