This part is for developers, who want to work on IntegronFinder scripts.

Developer installation

Dependencies

Python version >=3.10 is required to run Integron_Finder: https://docs.python.org/3.10/index.html

Integron_Finder has one program dependency:

The hmmsearch, cmsearch and prodigal programs should be installed (e.g., in the PATH) in order to use integron_finder. Otherwise, the paths to these executables must be specified via the command-line: see options –hmmsearch –cmsearch –prodigal

Integron_Finder also relies on some Python library dependencies:

  • colorlog

  • pandas

  • matplotlib

  • sphinx

  • sphinx_rtd_theme

  • coverage

  • build

  • ruff

  • pre-commit

These dependencies will be automatically retrieved and installed when using pip for installation (see below).

If you are not part of the project, start by forking IntegronFinder repository. For that, sign in to your account on github, and go to https://github.com/gem-pasteur/Integron_Finder. Then, click on ‘Fork’ (under your account icon). This will create a copy of the repository, but with your username instead of ‘gem-pasteur’.

create a virtual environment:

virtualenv -p python3 Integron_Finder

activate you virtualenv:

source Integron_Finder/bin/activate

then install integron_finder in developer mode:

pip install -e "git+https://github.com/gem-pasteur/Integron_Finder#egg=integron_finder[dev]"

or clone your repository manually, then install it

mkdir src
cd src
git clone https://github.com/gem-pasteur/Integron_Finder
cd Integron_Finder
pip install -e ".[dev]"

install tools to ensure coding style:

pre-commit install

It installs the requirements and create a directory in the virtualenv src/integron_finder and create links in the virtualenv. So integron_finder is runnable and you can modify the sources and run it again without to reinstall the project.

Note

[dev] allow to install extra dependencies to generate documentation, compute test coverage …

Note

from 2.0.6 version, Integron_Finder has adopted ruff as linter and pre-commit to ensure the coding style. please read CONTRIBUTING.md guide lines.

Warning

Debian/Ubuntu distribution –user is the default. So the –prefix option does not work and the –root option has unexpected behavior. Therefore the best solution is to use –user or a virtualenv.

Integron_Finder testing procedures

Integron_Finder project use unittest framework (included in the standard library) to test the code.

All tests stuff is in tests directory.

  • The data directory contains data needed by the tests

  • in the __init__.py file a IntegronTest class is defined and should be the base of all testcase use in the project

  • each test_*.py represent a file containing unit or functional tests

To run all the tests (in the virtualenv)

python -m unittest discover

To increase verbosity of output

python -m unittest discover -vv
test_integron_1elem_int (tests.test_add_feature.TestAddFeature.test_integron_1elem_int) ... ok
test_integron_1elem_prom (tests.test_add_feature.TestAddFeature.test_integron_1elem_prom) ... ok
test_integron_1elem_prot (tests.test_add_feature.TestAddFeature.test_integron_1elem_prot) ... ok
test_integron_2int_nelem (tests.test_add_feature.TestAddFeature.test_integron_2int_nelem) ... ok
test_integron_long_seqname (tests.test_add_feature.TestAddFeature.test_integron_long_seqname) ... ok
test_integron_nelem (tests.test_add_feature.TestAddFeature.test_integron_nelem) ... ok
test_config (tests.test_config.TestConfig.test_config) ... ok
test_default_topology (tests.test_config.TestConfig.test_default_topology) ... ok
test_func_annot_path (tests.test_config.TestConfig.test_func_annot_path) ... ok
test_getattr (tests.test_config.TestConfig.test_getattr) ... ok
test_input_dir (tests.test_config.TestConfig.test_input_dir) ... ok
test_log_level (tests.test_config.TestConfig.test_log_level) ... ok
test_model_attc_name (tests.test_config.TestConfig.test_model_attc_name) ... ok
test_model_attc_path (tests.test_config.TestConfig.test_model_attc_path) ... ok
test_model_dir (tests.test_config.TestConfig.test_model_dir) ... ok
test_model_integrase (tests.test_config.TestConfig.test_model_integrase) ... ok
test_model_len (tests.test_config.TestConfig.test_model_len) ... ok
test_model_phage_int (tests.test_config.TestConfig.test_model_phage_int) ... ok
...

----------------------------------------------------------------------
Ran 246 tests in 400.863s

OK

The tests must be in python file (.py) starting with with test_ It’s possible to specify one or several test files, one module, or one class in a module or a method in a Test class.

Test the test_pprot_db module

python -m unittest -vv tests.test_prot_db
test_ProteinDB (tests.test_prot_db.TestCustomDB.test_ProteinDB) ... ok
test_ProteinDB_bad_parser (tests.test_prot_db.TestCustomDB.test_ProteinDB_bad_parser) ... ok
test_coding_prot_ids (tests.test_prot_db.TestCustomDB.test_coding_prot_ids) ... ok
test_get_description (tests.test_prot_db.TestCustomDB.test_get_description) ... ok
test_get_description_lazy_parser (tests.test_prot_db.TestCustomDB.test_get_description_lazy_parser) ... ok
test_get_description_stupid_parser (tests.test_prot_db.TestCustomDB.test_get_description_stupid_parser) ... ok
test_get_description_stupid_parser2 (tests.test_prot_db.TestCustomDB.test_get_description_stupid_parser2) ... ok
test_getitem (tests.test_prot_db.TestCustomDB.test_getitem) ... ok
test_iter (tests.test_prot_db.TestCustomDB.test_iter) ... ok
test_protfile (tests.test_prot_db.TestCustomDB.test_protfile) ... ok
test_ProteinDB (tests.test_prot_db.TestGemBase.test_ProteinDB) ... ok
test_codig_prot_ids (tests.test_prot_db.TestGemBase.test_codig_prot_ids) ... ok
test_find_gembase_file_basename (tests.test_prot_db.TestGemBase.test_find_gembase_file_basename) ... ok
...
test_ProteinDB_no_prodigal (tests.test_prot_db.TestProdigalDB.test_ProteinDB_no_prodigal) ... ok
test_coding_prot_ids (tests.test_prot_db.TestProdigalDB.test_coding_prot_ids) ... ok
test_get_description (tests.test_prot_db.TestProdigalDB.test_get_description) ... ok
test_getitem (tests.test_prot_db.TestProdigalDB.test_getitem) ... ok
test_iter (tests.test_prot_db.TestProdigalDB.test_iter) ... ok
test_make_protfile (tests.test_prot_db.TestProdigalDB.test_make_protfile) ... ok
test_make_protfile_no_dir (tests.test_prot_db.TestProdigalDB.test_make_protfile_no_dir) ... ok
test_make_protfile_prodigal_failed (tests.test_prot_db.TestProdigalDB.test_make_protfile_prodigal_failed) ... ok
test_protfile (tests.test_prot_db.TestProdigalDB.test_protfile) ... ok
test_str (tests.test_prot_db.TestRepliconType.test_str) ... ok

----------------------------------------------------------------------
Ran 41 tests in 5.249s

OK

Test only the class TestProdigalDB (this module contains 5 classes)

python -m unittest -vv tests.test_prot_db.TestProdigalDB
test_ProteinDB (tests.test_prot_db.TestProdigalDB.test_ProteinDB) ... ok
test_ProteinDB_no_prodigal (tests.test_prot_db.TestProdigalDB.test_ProteinDB_no_prodigal) ... ok
test_coding_prot_ids (tests.test_prot_db.TestProdigalDB.test_coding_prot_ids) ... ok
test_get_description (tests.test_prot_db.TestProdigalDB.test_get_description) ... ok
test_getitem (tests.test_prot_db.TestProdigalDB.test_getitem) ... ok
test_iter (tests.test_prot_db.TestProdigalDB.test_iter) ... ok
test_make_protfile (tests.test_prot_db.TestProdigalDB.test_make_protfile) ... ok
test_make_protfile_no_dir (tests.test_prot_db.TestProdigalDB.test_make_protfile_no_dir) ... ok
test_make_protfile_prodigal_failed (tests.test_prot_db.TestProdigalDB.test_make_protfile_prodigal_failed) ... ok
test_protfile (tests.test_prot_db.TestProdigalDB.test_protfile) ... ok

----------------------------------------------------------------------
Ran 10 tests in 0.857s

OK

Test only the method test_protfile from the test Class TestProdigalDB in module test_prot_db

python -m unittest -vv tests.test_prot_db.TestProdigalDB.test_protfile
test_protfile (tests.test_prot_db.TestProdigalDB.test_protfile) ... ok

----------------------------------------------------------------------
Ran 1 test in 0.112s

OK

Coverage

To compute the tests coverage, we use the coverage package. The package is automatically installed if you have installed integron_finder with the dev target see installation The coverage package is setup in the pyproject.toml configuration file

To compute the coverage

coverage run
...
test_w_chunk (tests.test_split.TestMain.test_w_chunk) ... ok
test_wo_chunk (tests.test_split.TestMain.test_wo_chunk) ... ok
test_mute (tests.test_split.TestParseArgs.test_mute) ... ok
test_parse_chunk (tests.test_split.TestParseArgs.test_parse_chunk) ... ok
test_parse_outdir (tests.test_split.TestParseArgs.test_parse_outdir) ... ok
test_parse_replicon (tests.test_split.TestParseArgs.test_parse_replicon) ... ok
test_quiet (tests.test_split.TestParseArgs.test_quiet) ... ok
test_verbose (tests.test_split.TestParseArgs.test_verbose) ... ok
test_split_avoid_overwriting (tests.test_split.TestSplit.test_split_avoid_overwriting) ... ok
test_split_w_chunk (tests.test_split.TestSplit.test_split_w_chunk) ... ok
test_split_wo_chunk (tests.test_split.TestSplit.test_split_wo_chunk) ... ok
test_getitem (tests.test_topology.TestTopology.test_getitem) ... ok
test_getitem_cmdline_topofile (tests.test_topology.TestTopology.test_getitem_cmdline_topofile) ... ok
test_getitem_gembase (tests.test_topology.TestTopology.test_getitem_gembase) ... ok
test_parse (tests.test_topology.TestTopology.test_parse) ... ok
test_parse_topology (tests.test_topology.TestTopology.test_parse_topology) ... ok
test_FastaIterator (tests.test_utils.TestUtils.test_FastaIterator) ... ok
test_FastaIterator_test_topologies (tests.test_utils.TestUtils.test_FastaIterator_test_topologies) ... ok
test_get_name_from_path (tests.test_utils.TestUtils.test_get_name_from_path) ... ok
test_log_level (tests.test_utils.TestUtils.test_log_level) ... ok
test_model_len (tests.test_utils.TestUtils.test_model_len) ... ok
test_read_multi_prot_fasta (tests.test_utils.TestUtils.test_read_multi_prot_fasta) ... ok

----------------------------------------------------------------------
Ran 246 tests in 400.863s

OK

Then display a report

coverage report
Name                                  Stmts   Miss Branch BrPart  Cover
-----------------------------------------------------------------------
integron_finder/__init__.py              81     12     18      4    84%
integron_finder/annotation.py            84      0     30      0   100%
integron_finder/argparse_utils.py        14      1      2      1    88%
integron_finder/attc.py                 152      0     62      4    98%
integron_finder/config.py               104      2     48      2    97%
integron_finder/hmm.py                   89      0     28      1    99%
integron_finder/infernal.py             147      0     60      2    99%
integron_finder/integrase.py             33      0     12      2    96%
integron_finder/integron.py             403     11    146      8    97%
integron_finder/prot_db.py              374     17    122      7    95%
integron_finder/results.py               45      0     10      0   100%
integron_finder/scripts/__init__.py       0      0      0      0   100%
integron_finder/scripts/finder.py       284     28    116     19    87%
integron_finder/scripts/merge.py         82      3     30      4    94%
integron_finder/scripts/split.py         76      5     28      6    89%
integron_finder/topology.py              39      0     22      1    98%
integron_finder/utils.py                 96      1     26      2    98%
-----------------------------------------------------------------------
TOTAL                                  2103     80    760     63    95%

or generate a html report

coverage html
Wrote HTML report to htmlcov/index.html

The results are in the htmlcov directory. With you favourite web browser, open the index.html file. for more options please refer to the coverage documentation .

Documentation

Documentation is done using sphinx. Source files are located in doc/sources. To generate the documentation you just have to run the makefile located in doc directory.

make html

To generate the documentation in html format or

make latexpdf

to generate the documentation in pdf format (for this option you need to have latex installed on your compute)

You can complete them.

Build a new release

  1. activate the virtualenv:

    ./Integron_Finder/bin/activate
    
  2. Go to the root of the project:

    cd Integron_Finder/src/Integron_Finder
    
  3. Te build the new release:

    python -m build .
    

it will create a source tar.gz distribution and a wheel

Send changes to upstream repository

If you want to integrate your code in the upstream (main) repository, you need to create a pull request.

  1. Read the Contibuting guide

  2. Create a new branch with <your branch name> a descriptive name (e.g. ‘adding-xx-feature’, ‘fixing-typos’, etc.), so that others understand what your are working on.

  3. Work on it

  4. Test that your work does not break the tests. add tests corresponding to your code

  5. Push your local branch on your integron_finder clone on github

    git push --set-upstream origin <your branch name>
    
  6. ask for pull request

    • Go to your forked repository on github https://github.com/<your_login>/Integron_Finder/pulls

    • Click on ‘New pull request’

    • Choose your repository and the branch on which you did your changes in ‘head fork’ (right-hand side), and choose ‘gem-pasteur/Integron_Finder’ with the branch on which you want to merge (probably master) in ‘base fork’ (left-hand side).

    • A green ‘Able to merge’ text should appear if git is able to automatically merge the 2 branches. In that case, click on ‘Create pull request’, write your comments on the changes you made, why etc, and save. We will receive the pull request.