[med-svn] [Git][med-team/busco][master] 9 commits: New upstream version 5.2.0

Nilesh Patra (@nilesh) gitlab at salsa.debian.org
Thu Jul 1 22:04:14 BST 2021



Nilesh Patra pushed to branch master at Debian Med / busco


Commits:
de037af5 by Nilesh Patra at 2021-07-02T00:32:49+05:30
New upstream version 5.2.0
- - - - -
c2532cd6 by Nilesh Patra at 2021-07-02T00:32:56+05:30
Update upstream source from tag 'upstream/5.2.0'

Update to upstream version '5.2.0'
with Debian dir a05af566759f84f85a310661d80e8c2dc0c47867
- - - - -
ab15fc36 by Nilesh Patra at 2021-07-01T19:07:56+00:00
Update manpage

- - - - -
1fffac37 by Nilesh Patra at 2021-07-02T01:00:48+05:30
Install config.ini file as an example

- - - - -
def6700d by Nilesh Patra at 2021-07-02T01:01:22+05:30
Add Depends on python3-biopython and python3-pandas

- - - - -
c0803fee by Nilesh Patra at 2021-07-02T01:01:45+05:30
Extend B-D from python3 to python3-all

- - - - -
7eae95cb by Nilesh Patra at 2021-07-02T02:28:44+05:30
d/p/fix-and-disable-tests.patch: Add patch to fix test execution

- - - - -
e0dd9be2 by Nilesh Patra at 2021-07-02T02:32:27+05:30
Add autopkgtests

- - - - -
addf6954 by Nilesh Patra at 2021-07-02T02:32:59+05:30
Interim changelog entry

- - - - -


19 changed files:

- CHANGELOG
- README.md
- debian/busco.1
- debian/changelog
- debian/control
- + debian/examples
- + debian/patches/fix-and-disable-tests.patch
- + debian/patches/series
- + debian/tests/control
- + debian/tests/run-unit-test
- src/busco/Actions.py
- src/busco/BuscoConfig.py
- src/busco/BuscoDownloadManager.py
- src/busco/BuscoLogger.py
- src/busco/BuscoRunner.py
- src/busco/_version.py
- src/busco/busco_tools/Toolset.py
- src/busco/run_BUSCO.py
- tests/unittests/run_BUSCO_unittests.py


Changes:

=====================================
CHANGELOG
=====================================
@@ -1,3 +1,13 @@
+5.2.0
+- Issue #224 fixed
+- Issue #232 fixed
+- Issue #266 fixed
+- Issue #270 fixed
+- Issue #352 fixed
+- Issue #368 fixed
+- Issue #386 fixed
+- Introduce direct download option (Issues #252, #288)
+
 5.1.3
 - Issue #408 fixed
 - Bug fixes


=====================================
README.md
=====================================
@@ -32,20 +32,16 @@ Report problems on the BUSCO issue board at https://gitlab.com/ezlab/busco/issue
 ***
 ### How to cite BUSCO
 
-*BUSCO: Assessing Genome Assembly and Annotation Completeness.*
-Mathieu Seppey, Mosè Manni, Evgeny M. Zdobnov
-In: Kollmar M. (eds) Gene Prediction. Methods in Molecular Biology, vol 1962. Humana, New York, NY. 2019
-doi.org/10.1007/978-1-4939-9173-0_14
-
-*BUSCO applications from quality assessments to gene prediction and phylogenomics.*
-Robert M. Waterhouse, Mathieu Seppey, Felipe A. Simão, Mosè Manni, Panagiotis Ioannidis, Guennadi Klioutchnikov, Evgenia V. Kriventseva, and Evgeny M. Zdobnov
-*Mol Biol Evol*, published online Dec 6, 2017 
-doi: 10.1093/molbev/msx319 
-
-*BUSCO: assessing genome assembly and annotation completeness with single-copy orthologs.*
-Felipe A. Simão, Robert M. Waterhouse, Panagiotis Ioannidis, Evgenia V. Kriventseva, and Evgeny M. Zdobnov
-*Bioinformatics*, published online June 9, 2015 
-doi: 10.1093/bioinformatics/btv351
+If you have used BUSCO v4 or V5 in your analyses, please cite:
+
+Manni M., Berkeley M.R., Seppey M., Simao F.A., Zdobnov E.M. 2021. BUSCO update: novel and streamlined workflows along with broader and deeper phylogenetic coverage for scoring of eukaryotic, prokaryotic, and viral genomes. arXiv:2106.11799 [q-bio] [Internet]. Available from: http://arxiv.org/abs/2106.11799
+
+Previous publications:
+BUSCO: Assessing Genome Assembly and Annotation Completeness. Mathieu Seppey, Mosè Manni, Evgeny M. Zdobnov In: Kollmar M. (eds) Gene Prediction. Methods in Molecular Biology, vol 1962. Humana, New York, NY. 2019 doi.org/10.1007/978-1-4939-9173-0_14
+
+BUSCO applications from quality assessments to gene prediction and phylogenomics. Robert M. Waterhouse, Mathieu Seppey, Felipe A. Simão, Mosè Manni, Panagiotis Ioannidis, Guennadi Klioutchnikov, Evgenia V. Kriventseva, and Evgeny M. Zdobnov Mol Biol Evol, published online Dec 6, 2017 doi: 10.1093/molbev/msx319
+
+BUSCO: assessing genome assembly and annotation completeness with single-copy orthologs. Felipe A. Simão, Robert M. Waterhouse, Panagiotis Ioannidis, Evgenia V. Kriventseva, and Evgeny M. Zdobnov Bioinformatics, published online June 9, 2015 doi: 10.1093/bioinformatics/btv351
 
 Copyright (c) 2016-2021, Evgeny Zdobnov (ez at ezlab.org)
 Licensed under the MIT license. See LICENSE.md file.


=====================================
debian/busco.1
=====================================
@@ -1,30 +1,20 @@
-.\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.47.15.
-.TH BUSCO "1" "May 2020" "busco 4.0.6" "User Commands"
+.\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.47.16.
+.TH BUSCO "1" "July 2021" "busco 5.2.0" "User Commands"
 .SH NAME
 busco \- benchmarking sets of universal single-copy orthologs
-.SH SYNOPSIS
-.B busco
-\fB\-i\fR [SEQUENCE_FILE] \fB\-l\fR [LINEAGE] \fB\-o\fR [OUTPUT_NAME] \fB\-m\fR [MODE] [OTHER OPTIONS]
 .SH DESCRIPTION
-Assessing genome assembly and annotation completeness with Benchmarking
-Universal Single-Copy Orthologs (BUSCO).
-.SH OPTIONS
+usage: busco \fB\-i\fR [SEQUENCE_FILE] \fB\-l\fR [LINEAGE] \fB\-o\fR [OUTPUT_NAME] \fB\-m\fR [MODE] [OTHER OPTIONS]
+.PP
+Welcome to BUSCO 5.2.0: the Benchmarking Universal Single\-Copy Ortholog assessment tool.
+For more detailed usage information, please review the README file provided with this distribution and the BUSCO user guide. Visit this page https://gitlab.com/ezlab/busco#how\-to\-cite\-busco to see how to cite BUSCO
+.SS "optional arguments:"
 .TP
-\fB\-i\fR FASTA FILE, \fB\-\-in\fR FASTA FILE
+\fB\-i\fR SEQUENCE_FILE, \fB\-\-in\fR SEQUENCE_FILE
 Input sequence file in FASTA format. Can be an assembled genome or transcriptome (DNA), or protein sequences from an annotated gene set.
 .TP
-\fB\-c\fR N, \fB\-\-cpu\fR N
-Specify the number (N=integer) of threads/cores to use.
-.TP
 \fB\-o\fR OUTPUT, \fB\-\-out\fR OUTPUT
 Give your analysis run a recognisable short name. Output folders and files will be labelled with this name. WARNING: do not provide a path
 .TP
-\fB\-\-out_path\fR OUTPUT_PATH
-Optional location for results folder, excluding results folder name. Default is current working directory.
-.TP
-\fB\-e\fR N, \fB\-\-evalue\fR N
-E\-value cutoff for BLAST searches. Allowed formats, 0.001 or 1e\-03 (Default: 1e\-03)
-.TP
 \fB\-m\fR MODE, \fB\-\-mode\fR MODE
 Specify which BUSCO analysis mode to run.
 There are three valid modes:
@@ -35,20 +25,11 @@ There are three valid modes:
 \fB\-l\fR LINEAGE, \fB\-\-lineage_dataset\fR LINEAGE
 Specify the name of the BUSCO lineage to be used.
 .TP
-\fB\-f\fR, \fB\-\-force\fR
-Force rewriting of existing files. Must be used when output files with the provided name already exist.
-.TP
-\fB\-\-limit\fR REGION_LIMIT
-How many candidate regions (contig or transcript) to consider per BUSCO (default: 3)
+\fB\-\-augustus\fR
+Use augustus gene predictor for eukaryote runs
 .TP
-\fB\-\-long\fR
-Optimization mode Augustus self\-training (Default: Off) adds considerably to the run time, but can improve results for some non\-model organisms
-.TP
-\fB\-q\fR, \fB\-\-quiet\fR
-Disable the info logs, displays only errors
-.TP
-\fB\-\-augustus_parameters\fR AUGUSTUS_PARAMETERS
-Pass additional arguments to Augustus. All arguments should be contained within a single pair of quotation marks, separated by commas. E.g. '\-\-param1=1,\-\-param2=2'
+\fB\-\-augustus_parameters\fR "\-\-PARAM1=VALUE1,\-\-PARAM2=VALUE2"
+Pass additional arguments to Augustus. All arguments should be contained within a single pair of quotation marks, separated by commas.
 .TP
 \fB\-\-augustus_species\fR AUGUSTUS_SPECIES
 Specify a species for Augustus training.
@@ -56,29 +37,71 @@ Specify a species for Augustus training.
 \fB\-\-auto\-lineage\fR
 Run auto\-lineage to find optimum lineage path
 .TP
-\fB\-\-auto\-lineage\-prok\fR
-Run auto\-lineage just on non\-eukaryote trees to find optimum lineage path
-.TP
 \fB\-\-auto\-lineage\-euk\fR
 Run auto\-placement just on eukaryote tree to find optimum lineage path
 .TP
-\fB\-\-update\-data\fR
-Download and replace with last versions all lineages datasets and files necessary to their automated selection
+\fB\-\-auto\-lineage\-prok\fR
+Run auto\-lineage just on non\-eukaryote trees to find optimum lineage path
 .TP
-\fB\-\-offline\fR
-To indicate that BUSCO cannot attempt to download files
+\fB\-c\fR N, \fB\-\-cpu\fR N
+Specify the number (N=integer) of threads/cores to use.
 .TP
 \fB\-\-config\fR CONFIG_FILE
 Provide a config file
 .TP
-\fB\-v\fR, \fB\-\-version\fR
-Show this version and exit
+\fB\-\-datasets_version\fR DATASETS_VERSION
+Specify the version of BUSCO datasets, e.g. odb10
+.TP
+\fB\-\-download\fR [dataset ...]
+Download dataset. Possible values are a specific dataset name, "all", "prokaryota", "eukaryota", or "virus". If used together with other command line arguments, make sure to place this last.
+.TP
+\fB\-\-download_base_url\fR DOWNLOAD_BASE_URL
+Set the url to the remote BUSCO dataset location
+.TP
+\fB\-\-download_path\fR DOWNLOAD_PATH
+Specify local filepath for storing BUSCO dataset downloads
+.TP
+\fB\-e\fR N, \fB\-\-evalue\fR N
+E\-value cutoff for BLAST searches. Allowed formats, 0.001 or 1e\-03 (Default: 1e\-03)
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+Force rewriting of existing files. Must be used when output files with the provided name already exist.
 .TP
 \fB\-h\fR, \fB\-\-help\fR
 Show this help message and exit
 .TP
+\fB\-\-limit\fR N
+How many candidate regions (contig or transcript) to consider per BUSCO (default: 3)
+.TP
 \fB\-\-list\-datasets\fR
 Print the list of available BUSCO datasets
+.TP
+\fB\-\-long\fR
+Optimization Augustus self\-training mode (Default: Off); adds considerably to the run time, but can improve results for some non\-model organisms
+.TP
+\fB\-\-metaeuk_parameters\fR "\-\-PARAM1=VALUE1,\-\-PARAM2=VALUE2"
+Pass additional arguments to Metaeuk for the first run. All arguments should be contained within a single pair of quotation marks, separated by commas.
+.TP
+\fB\-\-metaeuk_rerun_parameters\fR "\-\-PARAM1=VALUE1,\-\-PARAM2=VALUE2"
+Pass additional arguments to Metaeuk for the second run. All arguments should be contained within a single pair of quotation marks, separated by commas.
+.TP
+\fB\-\-offline\fR
+To indicate that BUSCO cannot attempt to download files
+.TP
+\fB\-\-out_path\fR OUTPUT_PATH
+Optional location for results folder, excluding results folder name. Default is current working directory.
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Disable the info logs, displays only errors
+.TP
+\fB\-r\fR, \fB\-\-restart\fR
+Continue a run that had already partially completed.
+.TP
+\fB\-\-update\-data\fR
+Download and replace with last versions all lineages datasets and files necessary to their automated selection
+.TP
+\fB\-v\fR, \fB\-\-version\fR
+Show this version and exit
 .SH AUTHOR
- This manpage was written by Andreas Tille for the Debian distribution and
+ This manpage was written by Nilesh Patra for the Debian distribution and
  can be used for any other usage of the program.


=====================================
debian/changelog
=====================================
@@ -1,8 +1,14 @@
-busco (5.1.3-1) UNRELEASED; urgency=medium
+busco (5.2.0-1) UNRELEASED; urgency=medium
 
-  * New upstream version 5.1.3
+  * New upstream version 5.2.0
+  * Update manpage
+  * Install config.ini file as an example
+  * Add Depends on python3-biopython and python3-pandas
+  * Extend B-D from python3 to python3-all
+  * d/p/fix-and-disable-tests.patch: Add patch to fix test execution
+  * Add autopkgtests
 
- -- Nilesh Patra <nilesh at debian.org>  Tue, 20 Apr 2021 16:59:57 +0530
+ -- Nilesh Patra <nilesh at debian.org>  Fri, 02 Jul 2021 02:32:36 +0530
 
 busco (5.0.0-1) unstable; urgency=medium
 


=====================================
debian/control
=====================================
@@ -5,7 +5,7 @@ Maintainer: Debian Med Packaging Team <debian-med-packaging at lists.alioth.debian.
 Uploaders: Andreas Tille <tille at debian.org>, Nilesh Patra <nilesh at debian.org>
 Build-Depends: debhelper-compat (= 13),
                dh-python,
-               python3,
+               python3-all,
                python3-setuptools
 Standards-Version: 4.5.1
 Vcs-Browser: https://salsa.debian.org/med-team/busco
@@ -16,7 +16,9 @@ Rules-Requires-Root: no
 Package: busco
 Architecture: all
 Depends: ${python3:Depends},
-         ${misc:Depends}
+         ${misc:Depends},
+         python3-pandas,
+         python3-biopython
 Description: benchmarking sets of universal single-copy orthologs
  Assessing genome assembly and annotation completeness with Benchmarking
  Universal Single-Copy Orthologs (BUSCO).


=====================================
debian/examples
=====================================
@@ -0,0 +1 @@
+config/*


=====================================
debian/patches/fix-and-disable-tests.patch
=====================================
@@ -0,0 +1,161 @@
+Description: Replace __main__ calls with proper busco imports, skipping test_run_lineages_initializes_BuscoRunner
+ for now as this fails with a Mock iterable problem
+Author: Nilesh Patra <nilesh at debian.org>
+Last-Update: 2021-07-02
+--- a/tests/unittests/AutoLineage_unittests.py
++++ b/tests/unittests/AutoLineage_unittests.py
+@@ -45,7 +45,7 @@
+         mock_run_lineages_list.assert_has_calls(calls, any_order=True)
+ 
+     @patch("busco.AutoLineage.logger.info")
+-    @patch("__main__.AutoLineage_unittests.AutoLineage.AnalysisRunner")
++    @patch("busco.AutoLineage.AnalysisRunner")
+     @patch("busco.ConfigManager.BuscoConfigAuto", autospec=True)
+     def test_run_lineages_initializes_BuscoConfigAuto(self, mock_config_auto, *args):
+         config_manager = BuscoConfigManager({})
+@@ -71,9 +71,10 @@
+         ]
+         mock_config_auto.assert_has_calls(calls, any_order=True)
+ 
++    @unittest.skip("Skipping for now, ends with Mock iterable error")
+     @patch("busco.AutoLineage.logger.info")
+-    @patch("__main__.AutoLineage_unittests.BuscoConfigManager.load_busco_config_auto")
+-    @patch("__main__.AutoLineage_unittests.AutoLineage.AnalysisRunner")
++    @patch("busco.ConfigManager.BuscoConfigManager.load_busco_config_auto")
++    @patch("busco.AutoLineage.AnalysisRunner")
+     def test_run_lineages_initializes_BuscoRunner(
+         self, mock_runner, mock_config_auto, *args
+     ):
+@@ -89,7 +90,7 @@
+     @patch("busco.AutoLineage.logger.info")
+     @patch("busco.BuscoConfig.BuscoConfigAuto", autospec=True)
+     @patch("busco.ConfigManager.BuscoConfigManager")
+-    @patch("__main__.AutoLineage_unittests.AutoLineage.AnalysisRunner")
++    @patch("busco.AutoLineage.AnalysisRunner")
+     def test_run_lineages_runs_analysis(self, mock_runner, mock_config_manager, *args):
+         asl = AutoLineage.AutoSelectLineage(mock_config_manager.config_main)
+         test_lineages = ["a", "b", "c"]
+@@ -103,7 +104,7 @@
+     @patch("busco.AutoLineage.logger.info")
+     @patch("busco.BuscoConfig.BuscoConfigAuto", autospec=True)
+     @patch("busco.ConfigManager.BuscoConfigManager")
+-    @patch("__main__.AutoLineage_unittests.AutoLineage.AnalysisRunner")
++    @patch("busco.AutoLineage.AnalysisRunner")
+     def test_run_lineages_returns_runners(
+         self, mock_runner, mock_config_manager, *args
+     ):
+@@ -123,7 +124,7 @@
+ 
+     @patch("busco.AutoLineage.logger.info")
+     @patch("busco.BuscoConfig.BuscoConfigAuto", autospec=True)
+-    @patch("__main__.AutoLineage_unittests.AutoLineage.AnalysisRunner")
++    @patch("busco.AutoLineage.AnalysisRunner")
+     @patch("busco.ConfigManager.BuscoConfigManager")
+     def test_record_results_first_run(self, mock_config_manager, *args):
+         asl = AutoLineage.AutoSelectLineage(mock_config_manager.config_main)
+@@ -137,7 +138,7 @@
+ 
+     @patch("busco.AutoLineage.logger.info")
+     @patch("busco.BuscoConfig.BuscoConfigAuto", autospec=True)
+-    @patch("__main__.AutoLineage_unittests.AutoLineage.AnalysisRunner")
++    @patch("busco.AutoLineage.AnalysisRunner")
+     @patch("busco.ConfigManager.BuscoConfigManager")
+     def test_record_results_multiple_runs(self, mock_config_manager, *args):
+         asl = AutoLineage.AutoSelectLineage(mock_config_manager.config_main)
+@@ -260,7 +261,7 @@
+ 
+     @patch("busco.AutoLineage.logger.info")
+     @patch("busco.AutoLineage.AutoSelectLineage.cleanup_disused_runs")
+-    @patch("__main__.AutoLineage_unittests.BuscoRunner.AnalysisRunner.mode_dict")
++    @patch("busco.BuscoRunner.AnalysisRunner.mode_dict")
+     @patch("busco.ConfigManager.BuscoConfigManager")
+     def test_get_best_match_lineage(
+         self, mock_config_manager, fake_modedict, mock_cleanup, *args
+--- a/tests/unittests/BuscoConfig_unittests.py
++++ b/tests/unittests/BuscoConfig_unittests.py
+@@ -353,7 +353,7 @@
+             config.configure()
+             config._check_evalue()
+ 
+-    @patch("__main__.BuscoConfig_unittests.BuscoConfig.logger.warning")
++    @patch("busco.BuscoConfig.logger.warning")
+     def test_evalue_default(self, mock_logger):
+         self.test_params["evalue"] = 0.001
+         config = BuscoConfig.BuscoConfigMain(self.base_config, self.test_params)
+@@ -399,7 +399,7 @@
+         )
+ 
+     @patch(
+-        "__main__.BuscoConfig_unittests.BuscoConfig.os.path.isdir", return_value=True
++        "busco.BuscoConfig.os.path.isdir", return_value=True
+     )
+     def test_batch_mode_true(self, *args):
+         config = BuscoConfig.BuscoConfigMain(self.base_config, self.test_params)
+@@ -409,10 +409,10 @@
+         config.set.assert_has_calls(calls)
+ 
+     @patch(
+-        "__main__.BuscoConfig_unittests.BuscoConfig.os.path.isdir", return_value=False
++        "busco.BuscoConfig.os.path.isdir", return_value=False
+     )
+     @patch(
+-        "__main__.BuscoConfig_unittests.BuscoConfig.os.path.isfile", return_value=True
++        "busco.BuscoConfig.os.path.isfile", return_value=True
+     )
+     def test_batch_mode_false_with_file(self, *args):
+         config = BuscoConfig.BuscoConfigMain(self.base_config, self.test_params)
+@@ -420,10 +420,10 @@
+         config._check_batch_mode()
+ 
+     @patch(
+-        "__main__.BuscoConfig_unittests.BuscoConfig.os.path.isdir", return_value=False
++        "busco.BuscoConfig.os.path.isdir", return_value=False
+     )
+     @patch(
+-        "__main__.BuscoConfig_unittests.BuscoConfig.os.path.isfile", return_value=False
++        "busco.BuscoConfig.os.path.isfile", return_value=False
+     )
+     def test_batch_mode_false_with_error(self, *args):
+         config = BuscoConfig.BuscoConfigMain(self.base_config, self.test_params)
+@@ -441,14 +441,14 @@
+         with self.assertRaises(BuscoConfig.BatchFatalError):
+             config._check_required_input_exists()
+ 
+-    @patch("__main__.BuscoConfig_unittests.BuscoConfig.BuscoDownloadManager")
++    @patch("busco.BuscoConfig.BuscoDownloadManager")
+     def test_downloader_initialized(self, mock_downloader):
+         config = BuscoConfig.BuscoConfigMain(self.base_config, self.test_params)
+         config.configure()
+         config._init_downloader()
+         mock_downloader.assert_called()
+ 
+-    @patch("__main__.BuscoConfig_unittests.BuscoConfig.PrettyLog")
++    @patch("busco.BuscoConfig.PrettyLog")
+     def test_log_config(self, mock_pretty_log):
+         config = BuscoConfig.BuscoConfigMain(self.base_config, self.test_params)
+         config.configure()
+--- a/tests/unittests/ConfigManager_unittests.py
++++ b/tests/unittests/ConfigManager_unittests.py
+@@ -49,18 +49,18 @@
+                 config_manager.config_file, os.environ.get("BUSCO_CONFIG_FILE")
+             )
+ 
+-    @patch("__main__.ConfigManager_unittests.ConfigManager.logger", autospec=True)
++    @patch("busco.ConfigManager.logger", autospec=True)
+     @patch(
+-        "__main__.ConfigManager_unittests.ConfigManager.BuscoConfigMain", autospec=True
++        "busco.ConfigManager.BuscoConfigMain", autospec=True
+     )
+     def test_config_main_configured(self, mock_config, *args):
+         config_manager = ConfigManager.BuscoConfigManager(self.params)
+         config_manager.load_busco_config_main()
+         mock_config.return_value.configure.assert_called()
+ 
+-    @patch("__main__.ConfigManager_unittests.ConfigManager.logger", autospec=True)
++    @patch("busco.ConfigManager.logger", autospec=True)
+     @patch(
+-        "__main__.ConfigManager_unittests.ConfigManager.BuscoConfigMain", autospec=True
++        "busco.ConfigManager.BuscoConfigMain", autospec=True
+     )
+     def test_config_main_validated(self, mock_config, *args):
+         config_manager = ConfigManager.BuscoConfigManager(self.params)


=====================================
debian/patches/series
=====================================
@@ -0,0 +1 @@
+fix-and-disable-tests.patch


=====================================
debian/tests/control
=====================================
@@ -0,0 +1,3 @@
+Tests: run-unit-test
+Depends: @, python3-all, quilt
+Restrictions: allow-stderr


=====================================
debian/tests/run-unit-test
=====================================
@@ -0,0 +1,32 @@
+#!/bin/bash
+set -e
+
+pkg='busco'
+CUR_DIR=`pwd`
+
+QUILT_PATCHES=debian/patches quilt push -a || true
+
+if [ "$AUTOPKGTEST_TMP" = "" ] ; then
+  AUTOPKGTEST_TMP=`mktemp -d /tmp/${pkg}-test.XXXXXX`
+  trap "rm -rf $AUTOPKGTEST_TMP" 0 INT QUIT ABRT PIPE TERM
+fi
+
+cd $AUTOPKGTEST_TMP
+
+cp -a ${CUR_DIR}/test*/ .
+mkdir -p config
+cp -a /usr/share/doc/${pkg}/examples/config.ini config/
+
+ls
+ls tests
+for py in $(py3versions -s 2> /dev/null)
+do
+    echo "Testing with $py in $(pwd):"
+    $py -m unittest tests/unittest_runner.py -v 
+    
+done
+
+cd ${CUR_DIR}
+QUILT_PATCHES=debian/patches quilt pop -a || true
+
+echo "PASS"


=====================================
src/busco/Actions.py
=====================================
@@ -2,6 +2,7 @@ import argparse
 from busco.BuscoConfig import PseudoConfig
 from busco.ConfigManager import BuscoConfigManager
 from busco.BuscoLogger import BuscoLogger
+from busco.BuscoDownloadManager import BuscoDownloadManager
 import os
 import sys
 
@@ -15,19 +16,22 @@ class ListLineagesAction(argparse.Action):
 
     def __call__(self, parser, namespace, values, option_string=None):
         try:
-            self.config_manager = BuscoConfigManager({})
+            self.config_manager = BuscoConfigManager(namespace.__dict__)
         except SystemExit as se:
             type(self).logger.error(se)
             raise SystemExit(1)
 
-        self.config = PseudoConfig(self.config_manager.config_file)
+        self.config = PseudoConfig(
+            self.config_manager.config_file, self.config_manager.params
+        )
         try:
             self.config.load()
             self.print_lineages()
         except SystemExit as se:
             type(self).logger.error(se)
+            raise SystemExit(1)
         finally:
-            os.remove("busco_{}.log".format(BuscoLogger.random_id))
+            os.remove("busco_{}.log".format(BuscoLogger.pid))
             parser.exit()
 
     def print_lineages(self):
@@ -45,6 +49,76 @@ class ListLineagesAction(argparse.Action):
         return lineages_list_file
 
 
+class DirectDownload(argparse.Action):
+    logger = BuscoLogger.get_logger(__name__)
+
+    def __init__(
+        self, option_strings, dest, nargs="*", default="==SUPPRESS==", **kwargs
+    ):
+        super().__init__(option_strings, dest, nargs=nargs, default=default, **kwargs)
+
+    def __call__(self, parser, namespace, values, option_string=None):
+        try:
+            self.config_manager = BuscoConfigManager(namespace.__dict__)
+        except SystemExit as se:
+            type(self).logger.error(se)
+            raise SystemExit(1)
+
+        self.config = PseudoConfig(
+            self.config_manager.config_file, self.config_manager.params
+        )
+        try:
+            self.config.load()
+            bdm = BuscoDownloadManager(self.config)
+            bdm.update_data = True
+            self.download_datasets(bdm, values)
+
+        except SystemExit as se:
+            type(self).logger.error(se)
+            raise SystemExit(1)
+        finally:
+            os.remove("busco_{}.log".format(BuscoLogger.random_id))
+            parser.exit()
+
+    def download_datasets(self, bdm, values):
+        for item in values:
+            self.get(bdm, item)
+
+    def get(self, bdm, item):
+        if item == "all":
+            files_to_get = bdm.version_files.index
+        elif item == "prokaryota":
+            files_to_get = [
+                item
+                for item in bdm.version_files.index
+                if bdm.version_files.loc[item]["domain"] == "Prokaryota"
+            ]
+        elif item == "eukaryota":
+            files_to_get = [
+                item
+                for item in bdm.version_files.index
+                if bdm.version_files.loc[item]["domain"] == "Eukaryota"
+            ]
+        elif item == "virus":
+            files_to_get = [
+                item
+                for item in bdm.version_files.index
+                if bdm.version_files.loc[item]["domain"] == "Virus"
+            ]
+        else:
+            try:
+                if isinstance(item, str) and item in bdm.version_files.index:
+                    files_to_get = [item]
+                else:
+                    raise KeyError
+            except KeyError:
+                "{} is not a recognized option".format(item)
+
+        filetypes = [bdm.version_files.loc[f]["type"] for f in files_to_get]
+        for f, filename in enumerate(files_to_get):
+            bdm.get(filename, filetypes[f])
+
+
 class CleanHelpAction(argparse.Action):
     def __init__(self, option_strings, dest, nargs=0, default="==SUPPRESS==", **kwargs):
         super().__init__(option_strings, dest, nargs=nargs, default=default, **kwargs)
@@ -52,7 +126,7 @@ class CleanHelpAction(argparse.Action):
     def __call__(self, parser, namespace, values, option_string=None):
         parser.print_help()
         try:
-            os.remove("busco_{}.log".format(BuscoLogger.random_id))
+            os.remove("busco_{}.log".format(BuscoLogger.pid))
         except OSError:
             pass
         parser.exit()
@@ -79,7 +153,7 @@ class CleanVersionAction(argparse.Action):
         formatter.add_text(version)
         parser._print_message(formatter.format_help(), sys.stdout)
         try:
-            os.remove("busco_{}.log".format(BuscoLogger.random_id))
+            os.remove("busco_{}.log".format(BuscoLogger.pid))
         except OSError:
             pass
         parser.exit()


=====================================
src/busco/BuscoConfig.py
=====================================
@@ -52,6 +52,35 @@ class BaseConfig(ConfigParser):
         "hmmsearch",
     }
 
+    PERMITTED_OPTIONS = [
+        "in",
+        "out",
+        "out_path",
+        "mode",
+        "auto-lineage",
+        "auto-lineage-prok",
+        "auto-lineage-euk",
+        "cpu",
+        "force",
+        "restart",
+        "download_path",
+        "datasets_version",
+        "quiet",
+        "offline",
+        "long",
+        "augustus_parameters",
+        "augustus_species",
+        "download_base_url",
+        "lineage_dataset",
+        "update-data",
+        "metaeuk_parameters",
+        "metaeuk_rerun_parameters",
+        "evalue",
+        "limit",
+        "use_augustus",
+        "batch_mode",
+    ]
+
     def __init__(self):
         super().__init__()
         config_dict = {"busco_run": type(self).DEFAULT_ARGS_VALUES}
@@ -95,21 +124,36 @@ class BaseConfig(ConfigParser):
         self.downloader = BuscoDownloadManager(self)
         return
 
-    # @log("Setting value in config")
-    # def set(self, *args, **kwargs):
-    #     super().set(*args, **kwargs)
+    def _update_config_with_args(self, args):
+        """
+        Include command line arguments in config. Overwrite any values given in the config file.
+        :param args: Dictionary of parsed command line arguments. To see full list, inspect run_BUSCO_unittests.py or
+        type busco -h
+        :type args: dict
+        :return:
+        """
+        for key, val in args.items():
+            if key in type(self).PERMITTED_OPTIONS:
+                if val is not None and type(val) is not bool:
+                    self.set("busco_run", key, str(val))
+                elif val:  # if True
+                    self.set("busco_run", key, "True")
+        return
 
 
 class PseudoConfig(BaseConfig):
-    def __init__(self, conf_file):
+    def __init__(self, conf_file, params):
         super().__init__()
         self.conf_file = conf_file
+        self.params = params
+        self.params = params
 
     def load(self):
         if self.conf_file != "local environment":
             self._load_config_file()
         else:
             self.set("busco_run", "update-data", "True")
+        self._update_config_with_args(self.params)
         self._fill_default_values()
         self._init_downloader()
 
@@ -329,35 +373,6 @@ class BuscoConfigMain(BuscoConfig, BaseConfig):
 
     MANDATORY_USER_PROVIDED_PARAMS = ["in", "out", "mode"]
 
-    PERMITTED_OPTIONS = [
-        "in",
-        "out",
-        "out_path",
-        "mode",
-        "auto-lineage",
-        "auto-lineage-prok",
-        "auto-lineage-euk",
-        "cpu",
-        "force",
-        "restart",
-        "download_path",
-        "datasets_version",
-        "quiet",
-        "offline",
-        "long",
-        "augustus_parameters",
-        "augustus_species",
-        "download_base_url",
-        "lineage_dataset",
-        "update-data",
-        "metaeuk_parameters",
-        "metaeuk_rerun_parameters",
-        "evalue",
-        "limit",
-        "use_augustus",
-        "batch_mode",
-    ]
-
     def __init__(self, conf_file, params, **kwargs):
         """
         :param conf_file: a path to a config.ini file
@@ -693,22 +708,6 @@ class BuscoConfigMain(BuscoConfig, BaseConfig):
 
         return
 
-    def _update_config_with_args(self, args):
-        """
-        Include command line arguments in config. Overwrite any values given in the config file.
-        :param args: Dictionary of parsed command line arguments. To see full list, inspect run_BUSCO_unittests.py or
-        type busco -h
-        :type args: dict
-        :return:
-        """
-        for key, val in args.items():
-            if key in type(self).PERMITTED_OPTIONS:
-                if val is not None and type(val) is not bool:
-                    self.set("busco_run", key, str(val))
-                elif val:  # if True
-                    self.set("busco_run", key, "True")
-        return
-
 
 # Code taken from https://dave.dkjones.org/posts/2013/pretty-print-log-python/
 class PrettyLog:


=====================================
src/busco/BuscoDownloadManager.py
=====================================
@@ -19,6 +19,7 @@ import hashlib
 import urllib.request
 from urllib.error import URLError
 import gzip
+import pandas as pd
 
 from busco.BuscoLogger import BuscoLogger
 from busco.BuscoLogger import LogDecorator as log
@@ -35,7 +36,7 @@ class BuscoDownloadManager:
     Else, a warning is produced.
     """
 
-    version_files = {}
+    version_files = None
 
     def __init__(self, config):
         """
@@ -47,7 +48,7 @@ class BuscoDownloadManager:
         self.download_base_url = config.get("busco_run", "download_base_url")
         self.local_download_path = config.get("busco_run", "download_path")
         self._create_main_download_dir()
-        if not type(self).version_files and not self.offline:
+        if not type(self).version_files is not None and not self.offline:
             self._load_versions()
 
     def _create_main_download_dir(self):
@@ -58,15 +59,12 @@ class BuscoDownloadManager:
     def _load_versions(self):
         try:
             versions_file = self._obtain_versions_file()
-            with open(versions_file, "r") as v_file:
-                for line in v_file:
-                    line = line.strip().split("\t")
-                    dataset_name = line[0]
-                    dataset_date = line[1]
-                    dataset_hash = line[2]
-                    type(self).version_files.update(
-                        {dataset_name: (dataset_date, dataset_hash)}
-                    )
+            type(self).version_files = pd.read_csv(
+                versions_file,
+                sep="\t",
+                names=["dataset", "date", "hash", "domain", "type"],
+                index_col="dataset",
+            )
         except URLError as e:
             if self.offline:
                 logger.warning(
@@ -118,7 +116,7 @@ class BuscoDownloadManager:
 
     def _check_existing_version(self, local_filepath, category, data_basename):
         try:
-            latest_update = type(self).version_files[data_basename][0]
+            latest_update = type(self).version_files.loc[data_basename]["date"]
         except KeyError:
             raise BuscoError(
                 "{} is not a valid option for '{}'".format(data_basename, category)
@@ -153,7 +151,7 @@ class BuscoDownloadManager:
                 > 0
             )
 
-        hash = type(self).version_files[data_basename][1]
+        hash = type(self).version_files.loc[data_basename]["hash"]
 
         return present, up_to_date, latest_version, local_filepath, hash
 


=====================================
src/busco/BuscoLogger.py
=====================================
@@ -18,10 +18,6 @@ import logging.handlers
 import sys
 import io
 import os
-import select
-import time
-import threading
-import random
 from busco.Exceptions import BatchFatalError, BuscoError
 
 from configparser import NoOptionError
@@ -138,103 +134,6 @@ class LogDecorator:
         return
 
 
-class ToolLogger(logging.getLoggerClass()):
-
-    _level = logging.DEBUG
-
-    def __init__(self, filename):
-        super().__init__(filename)
-        self.setLevel(type(self)._level)
-        self._external_formatter = logging.Formatter("%(message)s")
-        self._file_hdlr = logging.FileHandler(filename, mode="a", encoding="UTF-8")
-        self._file_hdlr.setFormatter(self._external_formatter)
-        self.addHandler(self._file_hdlr)
-
-
-# The following code was created by combining code based on a SO answer here:
-# https://stackoverflow.com/questions/4713932/decorate-delegate-a-file-object-to-add-functionality/4838875#4838875
-# with code from the Python docs here:
-# https://docs.python.org/3.7/howto/logging-cookbook.html#network-logging
-# and is used to log multiple processes to the same file by way of a SocketHandler and separate the streams of
-# external tools into stdout and stderr.
-
-
-class StreamLogger(io.IOBase):
-    def __init__(self, level, logger, augustus_out=False):
-        self.logger = logger
-        self.level = level
-        self.augustus_out = augustus_out
-        self._run = None
-        self.pipe = os.pipe()
-        if self.augustus_out:
-            self.gene_found = False
-            self.output_complete = False
-            self.thread = threading.Thread(target=self._flusher_augustus_out)
-        else:
-            self.thread = threading.Thread(target=self._flusher)
-        self.thread.start()
-
-    def _flusher_augustus_out(self):
-        self._run = True
-        buf = b""
-        timeout = 10
-        read_only = select.POLLIN | select.POLLPRI | select.POLLHUP | select.POLLERR
-        # Switched from select.select() to select.poll() using examples at https://pymotw.com/2/select/
-        # This is necessary to handle greater than 1024 file descriptors, but makes BUSCO incompatible with Windows.
-        poller = select.poll()
-        server = self.pipe[0]
-        poller.register(server, read_only)
-        while self._run or (self.gene_found and not self.output_complete):
-            events = poller.poll(timeout)
-            for fd, flag in events:
-                if flag & (select.POLLIN | select.POLLPRI):
-                    buf += os.read(fd, 4096)
-                    while b"\n" in buf:
-                        if b"start gene" in buf:
-                            self.gene_found = True
-                        if b"command line" in buf:
-                            self.output_complete = True
-                        data, buf = buf.split(b"\n", 1)
-                        self.write(data.decode())
-
-        self._run = None
-
-    def _flusher(self):
-        self._run = True
-        buf = b""
-        timeout = 10
-        read_only = select.POLLIN | select.POLLPRI | select.POLLHUP | select.POLLERR
-        # Switched from select.select() to select.poll() using examples at https://pymotw.com/2/select/
-        # This is necessary to handle greater than 1024 file descriptors, but makes BUSCO incompatible with Windows.
-        poller = select.poll()
-        server = self.pipe[0]
-        poller.register(server, read_only)
-        while self._run:
-            events = poller.poll(timeout)
-            for fd, flag in events:
-                if flag & (select.POLLIN | select.POLLPRI):
-                    buf += os.read(fd, 4096)
-                    while b"\n" in buf:
-                        data, buf = buf.split(b"\n", 1)
-                        self.write(data.decode())
-
-        self._run = None
-
-    def write(self, data):
-        return self.logger.log(self.level, data)
-
-    def fileno(self):
-        return self.pipe[1]
-
-    def close(self):
-        if self._run:
-            self._run = False
-            while self._run is not None:
-                time.sleep(0.01)
-            os.close(self.pipe[0])
-            os.close(self.pipe[1])
-
-
 class BuscoLogger(logging.getLoggerClass()):
     """
     This class customizes the _logger class
@@ -243,7 +142,8 @@ class BuscoLogger(logging.getLoggerClass()):
     _level = logging.DEBUG
     _has_warning = False
     warn_output = io.StringIO()
-    random_id = str(random.getrandbits(32))
+    ppid = str(os.getppid())
+    pid = str(os.getpid())
 
     def __init__(self, name):
         """
@@ -252,9 +152,12 @@ class BuscoLogger(logging.getLoggerClass()):
         """
         super(BuscoLogger, self).__init__(name)
         self.setLevel(BuscoLogger._level)
-        self._normal_formatter = logging.Formatter("%(levelname)s:\t%(message)s")
+        self._normal_formatter = logging.Formatter(
+            "%(asctime)s %(levelname)s:\t%(message)s", datefmt="%Y-%m-%d %H:%M:%S"
+        )
         self._verbose_formatter = logging.Formatter(
-            "%(levelname)s:%(name)s\t%(message)s"
+            "%(asctime)s %(levelname)s:%(name)s\t%(message)s",
+            datefmt="%Y-%m-%d %H:%M:%S",
         )
         self._external_formatter = logging.Formatter("%(message)s")
 
@@ -270,10 +173,13 @@ class BuscoLogger(logging.getLoggerClass()):
         self.addHandler(self._err_hdlr)
 
         try:
-            # Random id used in filename to avoid complications for parallel BUSCO runs.
-            self._file_hdlr = logging.FileHandler(
-                "busco_{}.log".format(type(self).random_id), mode="a"
-            )
+            # Identify main log file with process ID and have all spawned processes log to the correct file
+            log_filename = "busco_{}.log".format(type(self).ppid)
+            if not os.path.exists(log_filename):
+                log_filename = "busco_{}.log".format(type(self).pid)
+
+            # Process id used in filename to avoid complications for parallel BUSCO runs.
+            self._file_hdlr = logging.FileHandler(log_filename, mode="a")
         except IOError as e:
             errStr = (
                 "No permission to write in the current directory: {}".format(
@@ -296,6 +202,13 @@ class BuscoLogger(logging.getLoggerClass()):
     def __call__(self):
         pass
 
+    @classmethod
+    def reset(cls):
+        cls._level = logging.DEBUG
+        cls._has_warning = False
+        cls.warn_output = io.StringIO()
+        return
+
     @staticmethod
     def get_logger(name, config=None):
         """


=====================================
src/busco/BuscoRunner.py
=====================================
@@ -188,6 +188,7 @@ class BatchRunner:
                 type(self).batch_results.append(run_summary)
 
                 AnalysisRunner.reset()
+                BuscoLogger.reset()
 
             except NoOptionError as noe:
                 raise BatchFatalError(noe)
@@ -195,7 +196,17 @@ class BatchRunner:
             except BatchFatalError:
                 raise
 
-            except BuscoError:
+            except BuscoError as be:
+                if "did not recognize any genes" in be.value:
+                    type(self).batch_results.append(
+                        "{}\tNo genes found\n".format(os.path.basename(input_file))
+                    )
+                else:
+                    type(self).batch_results.append(
+                        "{}\tRun failed; check logs\n".format(
+                            os.path.basename(input_file)
+                        )
+                    )
                 continue
 
         try:
@@ -579,13 +590,13 @@ class AnalysisRunner:
             if not os.path.exists(log_folder):
                 os.makedirs(log_folder)
             shutil.move(
-                "busco_{}.log".format(BuscoLogger.random_id),
+                "busco_{}.log".format(BuscoLogger.pid),
                 os.path.join(log_folder, "busco.log"),
             )
         except OSError:
             logger.warning(
                 "Unable to move 'busco_{}.log' to the 'logs' folder.".format(
-                    BuscoLogger.random_id
+                    BuscoLogger.pid
                 )
             )
         return
@@ -616,6 +627,9 @@ class AnalysisRunner:
             "For assistance with interpreting the results, please consult the userguide: "
             "https://busco.ezlab.org/busco_userguide.html\n"
         )
+        logger.info(
+            "Visit this page https://gitlab.com/ezlab/busco#how-to-cite-busco to see how to cite BUSCO"
+        )
 
 
 class SmartBox:


=====================================
src/busco/_version.py
=====================================
@@ -6,4 +6,4 @@ Copyright (c) 2016-2021, Evgeny Zdobnov (ez at ezlab.org)
 Licensed under the MIT license. See LICENSE.md file.
 
 """
-__version__ = "5.1.3"
+__version__ = "5.2.0"


=====================================
src/busco/busco_tools/Toolset.py
=====================================
@@ -14,14 +14,12 @@ Licensed under the MIT license. See LICENSE.md file.
 import os
 import subprocess
 from subprocess import TimeoutExpired
-from multiprocessing import Process, Pool, Value, Lock
+from multiprocessing import Process, Pool, Value, set_start_method
 import time
 from abc import ABCMeta, abstractmethod
-from busco.BuscoLogger import BuscoLogger, ToolLogger
+from busco.BuscoLogger import BuscoLogger
 from busco.BuscoLogger import LogDecorator as log
-from busco.BuscoLogger import StreamLogger
 from busco.Exceptions import BatchFatalError
-import logging
 
 logger = BuscoLogger.get_logger(__name__)
 
@@ -65,26 +63,25 @@ class Job(Process):
         Start external process and block the current thread's execution
         till the process' run is over
         """
-        with StreamLogger(logging.DEBUG, self.job_outlogger, **self.kwargs) as out:
-            with StreamLogger(logging.ERROR, self.job_errlogger) as err:
+
+        with open(self.job_outlogger, "wb") as f_out:
+            with open(self.job_errlogger, "wb") as f_err:
                 try:
-                    # Stick with Popen(), communicate() and wait() instead of just run() to ensure compatibility with
-                    # Python versions < 3.5.
-                    p = subprocess.Popen(
-                        self.cmd_line, shell=False, stdout=out, stderr=err, cwd=self.cwd
+                    process = subprocess.run(
+                        self.cmd_line,
+                        capture_output=True,  # stdout and stderr streams are stored and written to file after job completion
+                        cwd=self.cwd,
+                        shell=False,
+                        timeout=self.timeout,
                     )
-                    p.wait(self.timeout)
                 except TimeoutExpired:
-                    p.kill()
                     logger.warning(
                         "The following job was killed as it was taking too long (>1hr) to "
                         "complete.\n{}".format(" ".join(self.cmd_line))
                     )
+                f_out.write(process.stdout)
+                f_err.write(process.stderr)
 
-        self.job_outlogger._file_hdlr.close()
-        self.job_outlogger.removeHandler(self.job_outlogger._file_hdlr)
-        self.job_errlogger._file_hdlr.close()
-        self.job_errlogger.removeHandler(self.job_errlogger._file_hdlr)
         with cnt.get_lock():
             cnt.value += 1
 
@@ -106,6 +103,8 @@ class Tool(metaclass=ABCMeta):
     Collection of utility methods used by all tools
     """
 
+    set_start_method("spawn", force=True)
+
     def __init__(self):
         """
         Initialize job list for a tool
@@ -116,7 +115,7 @@ class Tool(metaclass=ABCMeta):
         """
         if self.name == "augustus":
             self.kwargs = {"augustus_out": True}
-            self.timeout = 3600
+            self.timeout = 3600  # Possibly no longer necessary from 5.2.0 with the new logging system in place, but no harm to leave it here
         else:
             self.kwargs = {}
             self.timeout = None
@@ -149,20 +148,16 @@ class Tool(metaclass=ABCMeta):
         """
         Create one work item
         """
-        self.tool_outlogger = ToolLogger(self.logfile_path_out)
-        self.tool_errlogger = ToolLogger(self.logfile_path_err)
         job = Job(
             self.name,
             self.cmd[:],
-            self.tool_outlogger,
-            self.tool_errlogger,
+            self.logfile_path_out,
+            self.logfile_path_err,
             self.timeout,
             self.cwd,
             **self.kwargs
         )
         self.jobs_to_run.append(job)
-        # if self.count_jobs_created:
-        #     self.total += 1
         return job
 
     def remove_job(self, job):


=====================================
src/busco/run_BUSCO.py
=====================================
@@ -27,7 +27,12 @@ from busco.Exceptions import BatchFatalError, BuscoError
 from busco.BuscoLogger import BuscoLogger
 from busco.BuscoLogger import LogDecorator as log
 from busco.ConfigManager import BuscoConfigManager
-from busco.Actions import ListLineagesAction, CleanHelpAction, CleanVersionAction
+from busco.Actions import (
+    ListLineagesAction,
+    CleanHelpAction,
+    CleanVersionAction,
+    DirectDownload,
+)
 from busco.ConfigManager import BuscoConfigMain
 
 # from busco.busco_tools.Toolset import ToolException
@@ -130,7 +135,9 @@ def _parse_args():
     parser = argparse.ArgumentParser(
         description="Welcome to BUSCO {}: the Benchmarking Universal Single-Copy Ortholog assessment tool.\n"
         "For more detailed usage information, please review the README file provided with "
-        "this distribution and the BUSCO user guide.".format(busco.__version__),
+        "this distribution and the BUSCO user guide. Visit this page https://gitlab.com/ezlab/busco#how-to-cite-busco to see how to cite BUSCO".format(
+            busco.__version__
+        ),
         usage="busco -i [SEQUENCE_FILE] -l [LINEAGE] -o [OUTPUT_NAME] -m [MODE] [OTHER OPTIONS]",
         formatter_class=RawTextHelpFormatter,
         add_help=False,
@@ -248,6 +255,16 @@ def _parse_args():
         help="Specify the version of BUSCO datasets, e.g. odb10",
     )
 
+    optional.add_argument(
+        "--download",
+        dest="download",
+        required=False,
+        type=str,
+        metavar="dataset",
+        action=DirectDownload,
+        help='Download dataset. Possible values are a specific dataset name, "all", "prokaryota", "eukaryota", or "virus". If used together with other command line arguments, make sure to place this last.',
+    )
+
     optional.add_argument(
         "--download_base_url",
         dest="download_base_url",


=====================================
tests/unittests/run_BUSCO_unittests.py
=====================================
@@ -86,6 +86,7 @@ class TestParams(unittest.TestCase):
             "augustus_species": None,
             "long": False,
             "datasets_version": None,
+            "download": "==SUPPRESS==",
             "download_base_url": None,
             "download_path": None,
             "update-data": False,
@@ -142,6 +143,7 @@ class TestParams(unittest.TestCase):
             "augustus_species": None,
             "long": False,
             "datasets_version": None,
+            "download": "==SUPPRESS==",
             "download_base_url": None,
             "download_path": None,
             "update-data": False,
@@ -209,6 +211,7 @@ class TestParams(unittest.TestCase):
             "metaeuk_parameters": metaeuk_parameters,
             "metaeuk_rerun_parameters": metaeuk_rerun_parameters,
             "datasets_version": datasets_version,
+            "download": "==SUPPRESS==",
             "download_base_url": download_base_url,
             "download_path": download_path,
             "auto-lineage": True,



View it on GitLab: https://salsa.debian.org/med-team/busco/-/compare/a20a2173d807db21e2e90d6c743260925bc3fb4f...addf6954930df192687aa921642ee094c08240e8

-- 
View it on GitLab: https://salsa.debian.org/med-team/busco/-/compare/a20a2173d807db21e2e90d6c743260925bc3fb4f...addf6954930df192687aa921642ee094c08240e8
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20210701/3fe14b37/attachment-0001.htm>


More information about the debian-med-commit mailing list