diff --git a/README.md b/README.md index 5a58a3d..ee46f10 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,8 @@ Binette is inspired from the metaWRAP bin-refinement tool but it effectively sol +A comprehensive documentation of Binette is avalaible here: https://binette.readthedocs.io/ + # Installation ## With Bioconda @@ -164,12 +166,12 @@ The `final_bins_quality_reports.tsv` file contains the following columns: | **N50** | Displays the N50 of the bin. | | **contig_count** | The number of contigs contained within the bin. | -# Feature requests and bug reporting +# Help, feature requests and bug reporting -Please submit bug reports and feature requests by opening an [issue](https://github.com/genotoul-bioinfo/Binette/issues). +To report bugs, request new features, or seek help and support, please open an [issue](https://github.com/genotoul-bioinfo/Binette/issues). # Licence -This program is released as an open source software under the terms of [MIT License](https://forgemia.inra.fr/jean.mainguy/binette/-/raw/main/LICENSE). +This program is released as an open source software under the terms of [MIT License](LICENSE). diff --git a/binette/main.py b/binette/main.py index 667d038..d4eb9f8 100755 --- a/binette/main.py +++ b/binette/main.py @@ -8,7 +8,7 @@ Portability : POSIX """ -from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter +from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter, Action, Namespace import sys import logging @@ -39,6 +39,26 @@ def init_logging(verbose, debug): f'command line: {" ".join(sys.argv)}', ) +class UniqueStore(Action): + """ + Custom argparse action to ensure an argument is provided only once. + """ + + def __call__(self, parser: ArgumentParser, namespace: Namespace, values: str, option_string: str = None) -> None: + """ + Ensures the argument is only used once. Raises an error if the argument appears multiple times. + + :param parser: The argparse parser instance. + :param namespace: The namespace object that will contain the parsed arguments. + :param values: The value associated with the argument. + :param option_string: The option string that was used to invoke this action. + """ + # Check if the argument has already been set + if getattr(namespace, self.dest, self.default) is not self.default: + parser.error(f"Error: The argument {option_string} can only be specified once.") + + # Set the argument value + setattr(namespace, self.dest, values) def parse_arguments(args): @@ -57,6 +77,7 @@ def parse_arguments(args): "-d", "--bin_dirs", nargs="+", + action=UniqueStore, help="List of bin folders containing each bin in a fasta file.", ) @@ -64,6 +85,7 @@ def parse_arguments(args): "-b", "--contig2bin_tables", nargs="+", + action=UniqueStore, help="List of contig2bin table with two columns separated\ with a tabulation: contig, bin", ) diff --git a/docs/contributing.md b/docs/contributing.md index 80a8ac9..f400a68 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -1,18 +1,19 @@ # Contributing -Thank you for your interest in contributing to Binette! This is an open-source project and everyone is welcome to contribute to it. +Thank you for your interest in contributing to Binette! This is an open-source project, and we welcome everyone to get involved. -## Reporting a Bug +## Help or Reporting a Bug -If you have any question, if you found a bug. Please open an issue. +If you have a question or found a bug? Please open an issue. -You can check the [Issues](https://github.com/genotoul-bioinfo/Binette/issues) page to see if the bug or question has been already reported. +Before you do, check the [Issues](https://github.com/genotoul-bioinfo/Binette/issues) page to see if it's already been reported. -If it's not reported, create a new [issue](https://github.com/genotoul-bioinfo/Binette/issues). +If you don’t see it there, create a new [issue](https://github.com/genotoul-bioinfo/Binette/issues). We appreciate your input! -## Adding a New Feature to Binette -### Starting with an Issue +## Adding a new feature to Binette + +### Starting with an issue If you have ideas for new features or improvements, initiate a discussion in an issue. This allows us to evaluate and discuss your suggestions together. @@ -28,7 +29,7 @@ For minor changes like fixing typos or making small edits, create a new Pull Req Create an environment with all Binette prerequisites installed by following the installation instructions [here](./installation.md#installing-from-source-code-within-a-conda-environnement). 3. **Install in Editable Mode:** - To enable seamless code editing and testing of new functionality, install PPanGGOLiN in editable mode using the following command: + To enable code editing and testing of new functionality, you can install Binette in editable mode using the following command: ```bash pip install -e . diff --git a/tests/main_binette_test.py b/tests/main_binette_test.py index b6f7873..d4ceba9 100644 --- a/tests/main_binette_test.py +++ b/tests/main_binette_test.py @@ -1,7 +1,7 @@ import pytest import logging -from binette.main import log_selected_bin_info, select_bins_and_write_them, manage_protein_alignement, parse_input_files, parse_arguments, init_logging, main +from binette.main import log_selected_bin_info, select_bins_and_write_them, manage_protein_alignement, parse_input_files, parse_arguments, init_logging, main, UniqueStore from binette.bin_manager import Bin from binette import diamond, contig_manager, cds import os @@ -10,6 +10,8 @@ from collections import Counter from tests.bin_manager_test import create_temp_bin_directories, create_temp_bin_files +from argparse import ArgumentParser + @pytest.fixture def bins(): @@ -237,6 +239,20 @@ def test_parse_input_files_bin_dirs(create_temp_bin_directories, tmp_path): assert len(contig_to_length) == 5 +def test_argument_used_once(): + # Test UniqueStore class + parser = ArgumentParser(description='Test parser') + parser.add_argument('--example', action=UniqueStore, help='Example argument') + args = parser.parse_args(['--example', 'value']) + assert args.example == 'value' + +def test_argument_used_multiple_times(): + # Test UniqueStore class + parser = ArgumentParser(description='Test parser') + parser.add_argument('--example', action=UniqueStore, help='Example argument') + with pytest.raises(SystemExit): + parser.parse_args(['--example', 'value', '--example', 'value2']) + def test_parse_arguments_required_arguments(): # Test when only required arguments are provided