internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: gwastro/pycbc

Issue:
Minifollowups should use f-lower from template bank
Looks like single_template is not equivalent to the search as it is not using the variable f-lower, this should be easy enough to get from the templates as we do for other mass/spin parameters.
Minifollowups should use f-lower from template bank
Looks like single_template is not equivalent to the search as it is not using the variable f-lower, this should be easy enough to get from the templates as we do for other mass/spin parameters.
Minifollowups should use f-lower from template bank
Looks like single_template is not equivalent to the search as it is not using the variable f-lower, this should be easy enough to get from the templates as we do for other mass/spin parameters.


Discussion:

Resolving patch:
diff --git a/pycbc/io/hdf.py b/pycbc/io/hdf.py
--- a/pycbc/io/hdf.py
+++ b/pycbc/io/hdf.py
@@ -493,6 +493,11 @@ def inclination(self):
         self.checkbank('inclination')
         return np.array(self.bank['inclination'])[self.template_id]
 
+    @property
+    def f_lower(self):
+        self.checkbank('f_lower')
+        return np.array(self.bank['f_lower'])[self.template_id]
+
     @property
     def mtotal(self):
         return self.mass1 + self.mass2
diff --git a/pycbc/workflow/minifollowups.py b/pycbc/workflow/minifollowups.py
--- a/pycbc/workflow/minifollowups.py
+++ b/pycbc/workflow/minifollowups.py
@@ -373,6 +373,8 @@ def make_single_template_plots(workflow, segs, data_read_name, analyzed_name,
                 node.add_opt('--mass2', "%.6f" % params['mass2'])
                 node.add_opt('--spin1z',"%.6f" % params['spin1z'])
                 node.add_opt('--spin2z',"%.6f" % params['spin2z'])
+                node.add_opt('--template-start-frequency',
+                             "%.6f" % params['f_lower'])
                 # Is this precessing?
                 if params.has_key('u_vals') or \
                                              params.has_key('u_vals_%s' % ifo):


Test patch:
Repository: gwastro/pycbc

Issue:
PyCBC can't import its own version
It seems that a broken relative import means pycbc can't actually import its own version, from `ldas-pcdev1.ligo.caltech.edu`:

```bash
$ . /cvmfs/oasis.opensciencegrid.org/ligo/sw/pycbc/x86_64_rhel_7/virtualenv/pycbc-v1.9.2/bin/activate
(pycbc-v1.9.2) $ python -c "import pycbc; print(pycbc.pycbc_version)"
none
```

The fix is pretty trivial, I will post a PR shortly.


Discussion:

Resolving patch:
diff --git a/pycbc/__init__.py b/pycbc/__init__.py
--- a/pycbc/__init__.py
+++ b/pycbc/__init__.py
@@ -32,12 +32,15 @@
 try:
     # This will fail when pycbc is imported during the build process,
     # before version.py has been generated.
-    from version import git_hash
-    from version import version as pycbc_version
+    from .version import git_hash
+    from .version import version as pycbc_version
 except:
     git_hash = 'none'
     pycbc_version = 'none'
 
+__version__ = pycbc_version
+
+
 def init_logging(verbose=False, format='%(asctime)s %(message)s'):
     """ Common utility for setting up logging in PyCBC.
 


Test patch:
Repository: gwastro/pycbc

Issue:
_check_lal_pars does not correctly assign quadfmode2
The function does 

`if p['lambda_octu1'] is not None:
        lalsimulation.SimInspiralWaveformParamsInsertTidalOctupolarLambda1(lal_pars, p['lambda_octu1'])
    if p['lambda_octu2'] is not None:
        lalsimulation.SimInspiralWaveformParamsInsertTidalOctupolarLambda2(lal_pars, p['lambda_octu2'])
    if p['quadfmode1'] is not None:
        lalsimulation.SimInspiralWaveformParamsInsertTidalQuadrupolarFMode1(lal_pars, p['quadfmode1'])
    if p['quadfmode2'] is not None:
        lalsimulation.SimInspiralWaveformParamsInsertTidalQuadrupolarFMode2(lal_pars, p['lambda_octu2'])`

hence assigning the content of lambda_octu2 to quadfmode2


Discussion:

Resolving patch:
diff --git a/pycbc/waveform/waveform.py b/pycbc/waveform/waveform.py
--- a/pycbc/waveform/waveform.py
+++ b/pycbc/waveform/waveform.py
@@ -106,7 +106,7 @@ def _check_lal_pars(p):
     if p['quadfmode1'] is not None:
         lalsimulation.SimInspiralWaveformParamsInsertTidalQuadrupolarFMode1(lal_pars, p['quadfmode1'])
     if p['quadfmode2'] is not None:
-        lalsimulation.SimInspiralWaveformParamsInsertTidalQuadrupolarFMode2(lal_pars, p['lambda_octu2'])
+        lalsimulation.SimInspiralWaveformParamsInsertTidalQuadrupolarFMode2(lal_pars, p['quadfmode2'])
     if p['octufmode1'] is not None:
         lalsimulation.SimInspiralWaveformParamsInsertTidalOctupolarFMode1(lal_pars, p['octufmode1'])
     if p['octufmode2'] is not None:


Test patch:
Repository: gwastro/pycbc

Issue:
Remove upper requirement on the astropy version
Is there any reason for having the upper version bound on astropy (`astropy>=2.0.3,<3.0.0`) in the requirements file? Is this just that PyCBC is not yet completely Python 3 compatible yet? From looking at the locations where astropy is used in the code, and testing them with astropy v3.1.2 installed, I don't seem to see any problems.

If the issue is that not having the upper bound makes the test suite try and download a non-Python 2 compatible astropy version, you could edit the requirements file to, e.g.,

```
astropy>=2.0.3,<3.0.0; python_version <= '2.7'
astropy>=2.0.3; python_version > '3.4'
```


Discussion:
@mattpitkin You've exactly understood the reason. If you have a chance to patch requirement.txt (and setup.py) to add this, then that would be great. Otherwise, I should have a chance when I get back from travelling next week. 
Cool, I'll submit a patch now.

Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -43,7 +43,8 @@
                       'pillow',
                       'h5py>=2.5',
                       'jinja2',
-                      'astropy>=2.0.3,<3.0.0',
+                      'astropy>=2.0.3,<3.0.0; python_version <= "2.7"',
+                      'astropy>=2.0.3; python_version > "3.4"',
                       'mpld3>=0.3',
                       'lscsoft-glue>=1.59.3',
                       'emcee==2.2.1',


Test patch:
Repository: gwastro/pycbc

Issue:
Minifollowup single info should not allow incompatible trigger choices
At present if `--n-loudest` and `--trigger-id` are both passed to pycbc_page_snglinfo, `--n-loudest` is silently ignored.  Thus the value of n-loudest could be complete nonsense and in general contradictory to trigger id.  We should not allow 'nonsense' arguments that are ignored due to being redundant with another argument, so make these mutually exclusive.  (This may have other implications for minifollowup code.)


Discussion:

Resolving patch:
diff --git a/pycbc/workflow/minifollowups.py b/pycbc/workflow/minifollowups.py
--- a/pycbc/workflow/minifollowups.py
+++ b/pycbc/workflow/minifollowups.py
@@ -548,7 +548,7 @@ def make_coinc_info(workflow, singles, bank, coinc, out_dir,
     return files
 
 def make_sngl_ifo(workflow, sngl_file, bank_file, trigger_id, out_dir, ifo,
-                  tags=None, rank=None):
+                  tags=None):
     """Setup a job to create sngl detector sngl ifo html summary snippet.
     """
     tags = [] if tags is None else tags
@@ -560,8 +560,6 @@ def make_sngl_ifo(workflow, sngl_file, bank_file, trigger_id, out_dir, ifo,
     node.add_input_opt('--single-trigger-file', sngl_file)
     node.add_input_opt('--bank-file', bank_file)
     node.add_opt('--trigger-id', str(trigger_id))
-    if rank is not None:
-        node.add_opt('--n-loudest', str(rank))
     node.add_opt('--instrument', ifo)
     node.new_output_file_opt(workflow.analysis_time, '.html', '--output-file')
     workflow += node


Test patch:
Repository: gwastro/pycbc

Issue:
don't require cpnest
Also don't install eah script


Discussion:

Resolving patch:
diff --git a/docs/removeGPUmods.py b/docs/remove_non_standard_imports.py
similarity index 96%
rename from docs/removeGPUmods.py
rename to docs/remove_non_standard_imports.py
--- a/docs/removeGPUmods.py
+++ b/docs/remove_non_standard_imports.py
@@ -38,7 +38,7 @@ def check_module_name_line(currLine):
 
 # Can these be named somewhat more obviously!
 excludes=['cuda', 'cufft', 'cuda_pyfft', 'cl_pyfft',\
-          'pycbc_phenomC_tmplt', 'TaylorF2','fotonfilter']
+          'pycbc_phenomC_tmplt', 'TaylorF2','fotonfilter', 'cpnest']
 
 fileList = glob.glob('pycbc.*.rst')
 
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -245,7 +245,7 @@ def run(self):
     setup_requires = setup_requires,
     extras_require = extras_require,
     install_requires = install_requires,
-    scripts  = find_files('bin', relpath='./') + ['tools/einsteinathome/pycbc_build_eah.sh'],
+    scripts  = find_files('bin', relpath='./'),
     packages = find_packages(),
     package_data = {'pycbc.workflow': find_files('pycbc/workflow'),
                     'pycbc.results': find_files('pycbc/results'),


Test patch:
Repository: gwastro/pycbc

Issue:
PyCBC Live: phase-time-amp files broken on Python 3
PyCBC Live is currently broken on Python 3, due to this:
```
RuntimeError: We already have one file with stat attr = phasetd_newsnr. Can't provide more than one!
```
Modify/remove [this loop](https://github.com/gwastro/pycbc/blob/master/pycbc/events/coinc.py#L766) and pass all the files to line 775, along with the ifos that are requested. Also modify the 'stat' attribute name in each file.


Discussion:

Resolving patch:
diff --git a/pycbc/events/coinc.py b/pycbc/events/coinc.py
--- a/pycbc/events/coinc.py
+++ b/pycbc/events/coinc.py
@@ -25,7 +25,7 @@
 coincident triggers.
 """
 
-import h5py, numpy, logging, pycbc.pnutils, copy, lal
+import numpy, logging, pycbc.pnutils, copy, lal
 from pycbc.detector import Detector
 
 
@@ -762,17 +762,8 @@ def __init__(self, num_templates, analysis_block, background_statistic,
         self.num_templates = num_templates
         self.analysis_block = analysis_block
 
-        # Only pass a valid stat file for this ifo pair
-        for fname in stat_files:
-            f = h5py.File(fname, 'r')
-            ifos_set = set([f.attrs['ifo0'], f.attrs['ifo1']])
-            f.close()
-            if ifos_set == set(ifos):
-                stat_files = [fname]
-                logging.info('Setup ifos %s-%s with file %s and stat %s',
-                             ifos[0], ifos[1], fname, background_statistic)
-
-        self.stat_calculator = stat.get_statistic(background_statistic)(stat_files)
+        stat_class = stat.get_statistic(background_statistic)
+        self.stat_calculator = stat_class(stat_files, ifos)
 
         self.timeslide_interval = timeslide_interval
         self.return_background = return_background
diff --git a/pycbc/events/stat.py b/pycbc/events/stat.py
--- a/pycbc/events/stat.py
+++ b/pycbc/events/stat.py
@@ -380,8 +380,6 @@ def logsignalrate_multiifo(self, stats, shift, to_shift):
         # does not require ifos to be specified, only 1 p/t/a file
         if self.hist is None:
             self.get_hist()
-        else:
-            logging.info("Using pre-set signal histogram")
 
         # figure out which ifo has the smallest SNR of the contributing ifos
         # Store a list 'rtypes' by ifo of which triggers that reference ifo
@@ -577,8 +575,6 @@ def logsignalrate(self, s0, s1, shift):
         # does not require ifos to be specified, only 1 p/t/a file
         if self.hist is None:
             self.get_hist()
-        else:
-            logging.info("Using pre-set signal histogram")
 
         # for 2-ifo pipeline, add time shift to 2nd ifo ('s1')
         slidevec = [0, 1]


Test patch:
Repository: gwastro/pycbc

Issue:
pycbc live depends on bank template start frequency > low_frequency_cutoff
Low frequency cutoff is not enforced in pycbc live. It relies on the template starting frequency being greater than the low frequency cutoff (which is used for the psd estimation).


Discussion:

Resolving patch:
diff --git a/pycbc/frame/frame.py b/pycbc/frame/frame.py
--- a/pycbc/frame/frame.py
+++ b/pycbc/frame/frame.py
@@ -617,7 +617,7 @@ def update_cache_by_increment(self, blocksize):
             name = '%s/%s-%s-%s.gwf' % (pattern, self.beg, s, self.dur)
             # check that file actually exists, else abort now
             if not os.path.exists(name):
-                logging.info("%s does not seem to exist yet" % name)
+                logging.info("%s not found yet", os.path.basename(name))
                 raise RuntimeError
 
             keys.append(name)
diff --git a/pycbc/io/live.py b/pycbc/io/live.py
--- a/pycbc/io/live.py
+++ b/pycbc/io/live.py
@@ -299,7 +299,7 @@ def upload(self, fname, gracedb_server=None, testing=True,
             psd_series_plot_fname = snr_series_fname.replace('.hdf',
                                                              '_psd.png')
             pylab.figure()
-            for ifo in self.snr_series:
+            for ifo in sorted(self.snr_series):
                 curr_snrs = self.snr_series[ifo]
                 curr_snrs.save(snr_series_fname, group='%s/snr' % ifo)
                 pylab.plot(curr_snrs.sample_times, abs(curr_snrs),
@@ -318,7 +318,7 @@ def upload(self, fname, gracedb_server=None, testing=True,
             pylab.close()
 
             pylab.figure()
-            for ifo in self.snr_series:
+            for ifo in sorted(self.snr_series):
                 # Undo dynamic range factor
                 curr_psd = self.psds[ifo].astype(numpy.float64)
                 curr_psd /= pycbc.DYN_RANGE_FAC ** 2.0
@@ -327,8 +327,8 @@ def upload(self, fname, gracedb_server=None, testing=True,
                 pylab.loglog(curr_psd.sample_frequencies[1:],
                              curr_psd[1:]**0.5, c=ifo_color(ifo), label=ifo)
             pylab.legend()
-            pylab.xlim([20, 2000])
-            pylab.ylim([1E-24, 1E-21])
+            pylab.xlim([10, 1300])
+            pylab.ylim([3E-24, 1E-20])
             pylab.xlabel('Frequency (Hz)')
             pylab.ylabel('ASD')
             pylab.savefig(psd_series_plot_fname)


Test patch:
Repository: gwastro/pycbc

Issue:
epsie should not be hard-required
Espsie imports still leak in when running inference code. @cdcapano Can you sanitize these so epsie is not a hard requirement. 


Discussion:
I just ran into missing `epsie` as well when just doing
`from pycbc.inference.option_utils import prior_from_config`, so this is a problem even when not running an actual sampler.
@cdcapano Can you please fix this as high priority.

Resolving patch:
diff --git a/pycbc/inference/io/__init__.py b/pycbc/inference/io/__init__.py
--- a/pycbc/inference/io/__init__.py
+++ b/pycbc/inference/io/__init__.py
@@ -33,7 +33,6 @@
 from pycbc.inference.option_utils import (ParseLabelArg, ParseParametersArg)
 from .emcee import EmceeFile
 from .emcee_pt import EmceePTFile
-from .epsie import EpsieFile
 from .cpnest import CPNestFile
 from .multinest import MultinestFile
 from .dynesty import DynestyFile
@@ -44,7 +43,6 @@
 filetypes = {
     EmceeFile.name: EmceeFile,
     EmceePTFile.name: EmceePTFile,
-    EpsieFile.name: EpsieFile,
     CPNestFile.name: CPNestFile,
     MultinestFile.name: MultinestFile,
     DynestyFile.name: DynestyFile,
@@ -52,6 +50,12 @@
     UltranestFile.name: UltranestFile,
 }
 
+try:
+    from .epsie import EpsieFile
+    filetypes[EpsieFile.name] = EpsieFile
+except ImportError:
+    pass
+
 
 def get_file_type(filename):
     """ Returns I/O object to use for file.


Test patch:
Repository: gwastro/pycbc

Issue:
Direct float comparison 
https://github.com/gwastro/pycbc/blob/812b518c61e2cf26dfe79eb91ceec19c666b08c4/pycbc/filter/matchedfilter.py#L1237

Here two floating-point numbers are compared with an `==` operator. This test can fail due to the finite precision of the floats. Is there any reason why `==` is used instead of the following ?
```python
try:
    numpy.testing.assert_almost_equal(stilde.delta_f, psd.delta_f)
except:
    raise TypeError("PSD delta_f does not match data")
qtilde[kmin:kmax] /= psd[kmin:kmax]
```


Discussion:
I don't think so anymore. I think we'd be happy to accept a PR to change this if you would find it useful. 

Resolving patch:
diff --git a/pycbc/filter/matchedfilter.py b/pycbc/filter/matchedfilter.py
--- a/pycbc/filter/matchedfilter.py
+++ b/pycbc/filter/matchedfilter.py
@@ -1088,7 +1088,7 @@ def sigmasq(htilde, psd = None, low_frequency_cutoff=None,
     if psd:
         try:
             numpy.testing.assert_almost_equal(ht.delta_f, psd.delta_f)
-        except:
+        except AssertionError:
             raise ValueError('Waveform does not have same delta_f as psd')
 
     if psd is None:
@@ -1234,10 +1234,11 @@ def matched_filter_core(template, data, psd=None, low_frequency_cutoff=None,
 
     if psd is not None:
         if isinstance(psd, FrequencySeries):
-            if psd.delta_f == stilde.delta_f :
-                qtilde[kmin:kmax] /= psd[kmin:kmax]
-            else:
-                raise TypeError("PSD delta_f does not match data")
+            try:
+                numpy.testing.assert_almost_equal(stilde.delta_f, psd.delta_f)
+            except AssertionError:
+                raise ValueError("PSD delta_f does not match data")
+            qtilde[kmin:kmax] /= psd[kmin:kmax]
         else:
             raise TypeError("PSD must be a FrequencySeries")
 
@@ -1902,4 +1903,3 @@ def compute_followup_snr_series(data_reader, htilde, trig_time,
            'compute_u_val_for_sky_loc_stat_no_phase',
            'compute_u_val_for_sky_loc_stat',
            'followup_event_significance']
-


Test patch:
diff --git a/test/test_matchedfilter.py b/test/test_matchedfilter.py
--- a/test/test_matchedfilter.py
+++ b/test/test_matchedfilter.py
@@ -134,7 +134,7 @@ def test_errors(self):
             #Check that an incompatible psd produces an error
             self.assertRaises(TypeError,match,self.filt,self.filt,psd=self.filt)
             psd = FrequencySeries(zeros(len(self.filt)/2+1),delta_f=100000)
-            self.assertRaises(TypeError,match,self.filt,self.filt,psd=psd)
+            self.assertRaises(ValueError,match,self.filt,self.filt,psd=psd)
 
             #Check that only TimeSeries or FrequencySeries are accepted
             self.assertRaises(TypeError,match,zeros(10),zeros(10))
Repository: gwastro/pycbc

Issue:
PyCBC inference fails if psd-inverse-length not given.
Pycbc_inference relies on a pad variable that is only initialized if the PSD inverse length is given:

https://github.com/gwastro/pycbc/compare/master...spxiwh:basic_lisa_detector_hack?expand=1#diff-8f038663d003b687dc646a7f8d409e3cR334


Discussion:

Resolving patch:
diff --git a/pycbc/inference/models/data_utils.py b/pycbc/inference/models/data_utils.py
--- a/pycbc/inference/models/data_utils.py
+++ b/pycbc/inference/models/data_utils.py
@@ -339,6 +339,8 @@ def data_opts_from_config(cp, section, filter_flow):
                          "(= psd-inverse-length/2) seconds to "
                          "account for PSD wrap around effects.",
                          det, pad)
+        else:
+            pad = 0
         gps_start[det] -= pad
         gps_end[det] += pad
         if opts.psd_start_time[det] is not None:


Test patch:
Repository: gwastro/pycbc

Issue:
Bug in command line option of pycbc_multi_inspiral code
Hi, So I was trying running pycbc_multi_inspiral code with command line option of `injection-f-ref 10 `  and  I get this error. 
```
ValueError: Issue with option: injection_f_ref 
Received value: 1 0 
If you are supplying a value for all ifos, you must only supply one value.
```
Probing further it turns out this command line option if removed the code did get run. I also pasted the full error below.   Just to mention what I was trying is to use pycbc_multi_inspiral code given an injection parameter file.  So, I created an injection.hdf file using pycbc_create_injections and I am using templatebank files from previous pygrb successful runs. If further information is needed please tell me.  This was full error  I received 
```
File "pycbc_multi_inspiral", line 118, in <module>
    opt = parser.parse_args()
  File "/usr/lib64/python3.6/argparse.py", line 1734, in parse_args
    args, argv = self.parse_known_args(args, namespace)
  File "/usr/lib64/python3.6/argparse.py", line 1766, in parse_known_args
    namespace, args = self._parse_known_args(args, namespace)
  File "/usr/lib64/python3.6/argparse.py", line 1972, in _parse_known_args
    start_index = consume_optional(start_index)
  File "/usr/lib64/python3.6/argparse.py", line 1912, in consume_optional
    take_action(action, args, option_string)
  File "/usr/lib64/python3.6/argparse.py", line 1840, in take_action
    action(self, namespace, argument_values, option_string)
  File "/home/jam.sadiq/SearchPipeline/env/lib/python3.6/site-packages/PyCBC-0.0a8053-py3.6-linux-x86_64.egg/pycbc/types/optparse.py", line 102, in __call__
    raise ValueError(err_msg)
ValueError: Issue with option: injection_f_ref 
Received value: 1 0 
If you are supplying a value for all ifos, you must only supply one value.
```


Discussion:

Resolving patch:
diff --git a/pycbc/types/optparse.py b/pycbc/types/optparse.py
--- a/pycbc/types/optparse.py
+++ b/pycbc/types/optparse.py
@@ -43,7 +43,7 @@ class MultiDetOptionAction(argparse.Action):
     def __init__(self,
                  option_strings,
                  dest,
-                 nargs=None,
+                 nargs='+',
                  const=None,
                  default=None,
                  type=None,


Test patch:
Repository: gwastro/pycbc

Issue:
`examples/filter/fir.py` does not work
Building the documentation currently produces this error:
```
Warning, treated as error:
/home/runner/work/pycbc/pycbc/docs/filter.rst:16:Exception occurred in plotting fir
 from /home/runner/work/pycbc/pycbc/docs/../examples/filter/fir.py:
Traceback (most recent call last):
  File "/home/runner/work/pycbc/pycbc/.tox/py-docs/lib/python3.7/site-packages/matplotlib/sphinxext/plot_directive.py", line 517, in _run_code
    exec(code, ns)
  File "<string>", line 18, in <module>
  File "/home/runner/work/pycbc/pycbc/.tox/py-docs/lib/python3.7/site-packages/pycbc/filter/resample.py", line 113, in fir_zero_filter
    series.roll(-len(coeff)//2)
AttributeError: 'numpy.ndarray' object has no attribute 'roll'
```
It seems this is caused by some confusion between a PyCBC TimeSeries and a numpy array.


Discussion:

Resolving patch:
diff --git a/pycbc/filter/resample.py b/pycbc/filter/resample.py
--- a/pycbc/filter/resample.py
+++ b/pycbc/filter/resample.py
@@ -52,7 +52,9 @@ def lfilter(coefficients, timeseries):
     # If there aren't many points just use the default scipy method
     if len(timeseries) < 2**7:
         series = scipy.signal.lfilter(coefficients, 1.0, timeseries)
-        return series
+        return TimeSeries(series,
+                          epoch=timeseries.start_time,
+                          delta_t=timeseries.delta_t)
     elif (len(timeseries) < fillen * 10) or (len(timeseries) < 2**18):
         cseries = (Array(coefficients[::-1] * 1)).astype(timeseries.dtype)
         cseries.resize(len(timeseries))


Test patch:
diff --git a/test/test_resample.py b/test/test_resample.py
--- a/test/test_resample.py
+++ b/test/test_resample.py
@@ -82,7 +82,7 @@ def test_lfilter(self):
             test = test[len(c):]
 
             maxreldiff =  ((ref - test) / ref).max()
-
+            self.assertTrue(isinstance(test, TimeSeries))
             self.assertTrue(maxreldiff < 1e-7)
 
 suite = unittest.TestSuite()