# Examples of contributions

## How to add a new sub-command

**You need first to clone and install the tool in [develop mode](installation.html)**

Let's say that you want to add a new operation to `mirtop`, for instance, similar to the `stats` command to work with sGFF3 files. Assume a `test` function for this exmaple to just read the file and print `Hello GFF3.`

* Create the folder inside `mirtop/test`. The create to empty files named:
 * `test.py`
 * `__init__.py`

* Modify the `test.py` file with this content:

```
from mirtop.gff.body import read_gff_line

import mirtop.libs.logger as mylog
logger = mylog.getLogger(__name__)

def test(args):
	for fn in args.files:
		_test(fn)
		logger.info("Hello GFF3: %s" % fn)


def _test(fn):
	logger.debug("I am going to read this file: %s" % fn)
	for line in fn:
		read_gff_line(line)
```

* Choose a sub_command name, in this case: `test`.
* Add the arguments function at the end of this file: https://github.com/miRTop/mirtop/blob/dev/mirtop/libs/parse.py, using a naming following `add_subparser_test`. 

```
def add_subparser_test(subparsers):
    parser = subparsers.add_parser("test", help="test function")
    parser.add_argument("files", nargs="*", help="GFF/GTF files.")
    parser = _add_debug_option(parser)
    return parser
```

* Add the function name to `parse_cl` function, at the end of the `sub_cmds` array.

```
    sub_cmds = {"gff": add_subparser_gff,
                "stats": add_subparser_stats,
                "compare": add_subparser_compare,
                "target": add_subparser_target,
                "simulator": add_subparser_simulator,
                "counts": add_subparser_counts,
                "export": add_subparser_export,
                "test": add_subparser_test
                }
```

* To get the function re-directed from the command line when you use the sub_cmd name, add a line to the `command_line.py` file, adding another `else` statement:

```
	elif "test" in kwargs:
        logger.info("Run test.")
        test(kwargs["args"])
```

* The function you use to link to the operation added need to be imported at the beginning. Let's say that the `test` function is at `mirtop/test/test.py`:

```
from mirtop.test import test
```

Try the new operation:

```
mirtop test data/examples/correct_file.gff
```

## Add a unit test

## for the internal function


Add to the end of `test/test_functions.py`, but inside `class FunctionsTest(unittest.TestCase):` this code:


```
    @attr(fn_test=True)
    def test_function_test(self):
        from mirtop import test
        test._test("data/examples/gff/correct_file.gff")

```

## for the sub-command

Add to the end of `test/test_function.py`, but inside `class AutomatedAnalysisTest(unittest.TestCase):` this code:

```
    @attr(cmd_test=True)
    def test_srnaseq_annotation_bam(self):
        """Run test analysis
        """
        with make_workdir():
            clcode = ["mirtop",
                      "test",
                      "../../data/examples/gff/correct_file.gff"]
            print("")
            print(" ".join(clcode))
            subprocess.check_call(clcode)

```

## test the unit

**nose is needed: pip install nose**

Run the function test from the top parent folder:

```
./run_test.sh fn_test
```

Run the command test from the top parent folder:

```
./run_test.sh cmd_test
```
