Repository: Gradiant/pyodi (language: python)

Issue:
[apps] Organize groups of apps by package
In the `pyodi.apps` directory, it seems that most apps are composed by two types of files (modules): an "entrypoint" module that defines the commands of the app, and one module for each command/feature, with the logic inside. For example, the "coco" app has a `coco.py` entrypoint and two logic modules (`coco_merge.py` and `coco_split.py`).

I think this could be refactored into having one package within `pyodi.apps` for each app (so, for example, a `pyodi.apps.coco` package).

Possible caveat: this might cause problems if running an entrypoint directly (as `__main__`)?


Discussion / hints:
Branch [issue-138-_apps_Organize_groups_of_apps_by_package](https://github.com/Gradiant/pyodi/tree/issue-138-_apps_Organize_groups_of_apps_by_package) created!

Fix patch:
diff --git a/docs/reference/apps/coco-merge.md b/docs/reference/apps/coco-merge.md
index 89f9675..5382bfa 100644
--- a/docs/reference/apps/coco-merge.md
+++ b/docs/reference/apps/coco-merge.md
@@ -1,1 +1,1 @@
-::: pyodi.apps.coco_merge
+::: pyodi.apps.coco.coco_merge
diff --git a/docs/reference/apps/coco-split.md b/docs/reference/apps/coco-split.md
index b3f1bbd..8028eb3 100644
--- a/docs/reference/apps/coco-split.md
+++ b/docs/reference/apps/coco-split.md
@@ -1,1 +1,1 @@
-::: pyodi.apps.coco_split
+::: pyodi.apps.coco.coco_split
diff --git a/docs/reference/apps/crops-merge.md b/docs/reference/apps/crops-merge.md
index 41e47f4..1b51ab9 100644
--- a/docs/reference/apps/crops-merge.md
+++ b/docs/reference/apps/crops-merge.md
@@ -1,1 +1,1 @@
-::: pyodi.apps.crops_merge
+::: pyodi.apps.crops.crops_merge
diff --git a/docs/reference/apps/crops-split.md b/docs/reference/apps/crops-split.md
index 5102af6..90b2f3f 100644
--- a/docs/reference/apps/crops-split.md
+++ b/docs/reference/apps/crops-split.md
@@ -1,1 +1,1 @@
-::: pyodi.apps.crops_split
+::: pyodi.apps.crops.crops_split
diff --git a/docs/reference/apps/train-config-evaluation.md b/docs/reference/apps/train-config-evaluation.md
index dbeb59e..256ab4a 100644
--- a/docs/reference/apps/train-config-evaluation.md
+++ b/docs/reference/apps/train-config-evaluation.md
@@ -1,1 +1,1 @@
-::: pyodi.apps.train_config_evaluation
+::: pyodi.apps.train_config.train_config_evaluation
diff --git a/docs/reference/apps/train-config-generation.md b/docs/reference/apps/train-config-generation.md
index 9bebe36..b09e75e 100644
--- a/docs/reference/apps/train-config-generation.md
+++ b/docs/reference/apps/train-config-generation.md
@@ -1,1 +1,1 @@
-::: pyodi.apps.train_config_generation
+::: pyodi.apps.train_config.train_config_generation
diff --git a/pyodi/apps/coco.py b/pyodi/apps/coco/__init__.py
similarity index 54%
rename from pyodi/apps/coco.py
rename to pyodi/apps/coco/__init__.py
index f6ec795..c51760f 100644
--- a/pyodi/apps/coco.py
+++ b/pyodi/apps/coco/__init__.py
@@ -1,9 +1,7 @@
 import typer
 
-from pyodi.apps.coco_merge import coco_merge
-from pyodi.apps.coco_split import property_split, random_split
-
-# TODO Split entrypoint and logic/command modules in packages? (issue #138)
+from pyodi.apps.coco.coco_merge import coco_merge
+from pyodi.apps.coco.coco_split import property_split, random_split
 
 coco_app = typer.Typer()
 coco_app.command("merge")(coco_merge)
diff --git a/pyodi/apps/coco_merge.py b/pyodi/apps/coco/coco_merge.py
similarity index 96%
rename from pyodi/apps/coco_merge.py
rename to pyodi/apps/coco/coco_merge.py
index 6681432..7c3ff6d 100644
--- a/pyodi/apps/coco_merge.py
+++ b/pyodi/apps/coco/coco_merge.py
@@ -1,6 +1,6 @@
 """# Coco Merge App.
 
-The [`pyodi coco`][pyodi.apps.coco_merge.coco_merge] app can be used to merge COCO annotation files.
+The [`pyodi coco`][pyodi.apps.coco.coco_merge.coco_merge] app can be used to merge COCO annotation files.
 
 Example usage:
 
diff --git a/pyodi/apps/coco_split.py b/pyodi/apps/coco/coco_split.py
similarity index 98%
rename from pyodi/apps/coco_split.py
rename to pyodi/apps/coco/coco_split.py
index 51c1b47..0729a2c 100644
--- a/pyodi/apps/coco_split.py
+++ b/pyodi/apps/coco/coco_split.py
@@ -1,6 +1,6 @@
 """# Coco Split App.
 
-The [`pyodi coco split`][pyodi.apps.coco_split] app can be used to split COCO
+The [`pyodi coco split`][pyodi.apps.coco.coco_split] app can be used to split COCO
 annotation files in train and val annotations files.
 
 There are two modes: 'random' or 'property'. The 'random' mode splits randomly the COCO file, while
diff --git a/pyodi/apps/crops.py b/pyodi/apps/crops/__init__.py
similarity index 61%
rename from pyodi/apps/crops.py
rename to pyodi/apps/crops/__init__.py
index 8537c9f..e081f05 100644
--- a/pyodi/apps/crops.py
+++ b/pyodi/apps/crops/__init__.py
@@ -1,7 +1,7 @@
 import typer
 
-from pyodi.apps.crops_merge import crops_merge
-from pyodi.apps.crops_split import crops_split
+from pyodi.apps.crops.crops_merge import crops_merge
+from pyodi.apps.crops.crops_split import crops_split
 
 crops_app = typer.Typer()
 crops_app.command("merge")(crops_merge)
diff --git a/pyodi/apps/crops_merge.py b/pyodi/apps/crops/crops_merge.py
similarity index 100%
rename from pyodi/apps/crops_merge.py
rename to pyodi/apps/crops/crops_merge.py
diff --git a/pyodi/apps/crops_split.py b/pyodi/apps/crops/crops_split.py
similarity index 100%
rename from pyodi/apps/crops_split.py
rename to pyodi/apps/crops/crops_split.py
diff --git a/pyodi/apps/train_config.py b/pyodi/apps/train_config/__init__.py
similarity index 57%
rename from pyodi/apps/train_config.py
rename to pyodi/apps/train_config/__init__.py
index 90c870a..5920e72 100644
--- a/pyodi/apps/train_config.py
+++ b/pyodi/apps/train_config/__init__.py
@@ -1,7 +1,7 @@
 import typer
 
-from pyodi.apps.train_config_evaluation import train_config_evaluation
-from pyodi.apps.train_config_generation import train_config_generation
+from pyodi.apps.train_config.train_config_evaluation import train_config_evaluation
+from pyodi.apps.train_config.train_config_generation import train_config_generation
 
 train_config_app = typer.Typer()
 train_config_app.command("evaluation")(train_config_evaluation)
diff --git a/pyodi/apps/train_config_evaluation.py b/pyodi/apps/train_config/train_config_evaluation.py
similarity index 98%
rename from pyodi/apps/train_config_evaluation.py
rename to pyodi/apps/train_config/train_config_evaluation.py
index 421ea66..d0ec8a6 100644
--- a/pyodi/apps/train_config_evaluation.py
+++ b/pyodi/apps/train_config/train_config_evaluation.py
@@ -1,6 +1,6 @@
 r"""# Train Config Evaluation App.
 
-The [`pyodi train-config evaluation`][pyodi.apps.train_config_evaluation.train_config_evaluation]
+The [`pyodi train-config evaluation`][pyodi.apps.train_config.train_config_evaluation.train_config_evaluation]
 app can be used to evaluate a given [mmdetection](https://github.com/open-mmlab/mmdetection)
 Anchor Generator Configuration to train your model using a specific training pipeline.
 
diff --git a/pyodi/apps/train_config_generation.py b/pyodi/apps/train_config/train_config_generation.py
similarity index 96%
rename from pyodi/apps/train_config_generation.py
rename to pyodi/apps/train_config/train_config_generation.py
index ece093d..dd388af 100644
--- a/pyodi/apps/train_config_generation.py
+++ b/pyodi/apps/train_config/train_config_generation.py
@@ -1,6 +1,6 @@
 r"""# Train Config Generation App.
 
-The [`pyodi train-config generation`][pyodi.apps.train_config_generation.train_config_generation]
+The [`pyodi train-config generation`][pyodi.apps.train_config.train_config_generation.train_config_generation]
 app can be used to automatically generate a [mmdetection](https://github.com/open-mmlab/mmdetection)
 anchor configuration to train your model.
 
@@ -87,7 +87,7 @@
 )
 ```
 
-By default, [`pyodi train-config evaluation`][pyodi.apps.train_config_evaluation.train_config_evaluation] is
+By default, [`pyodi train-config evaluation`][pyodi.apps.train_config.train_config_evaluation.train_config_evaluation] is
 used after the generation of anchors in order to compare which generated anchor config suits better your data.
 You can disable this evaluation by setting to False the `evaluate` argument, but it is strongly advised to
 use the anchor evaluation module.
@@ -104,7 +104,7 @@
 import typer
 from loguru import logger
 
-from pyodi.apps.train_config_evaluation import train_config_evaluation
+from pyodi.apps.train_config.train_config_evaluation import train_config_evaluation
 from pyodi.core.anchor_generator import AnchorGenerator
 from pyodi.core.boxes import (
     filter_zero_area_bboxes,
@@ -153,7 +153,7 @@ def train_config_generation(
         output_size: Size of saved images. Defaults to (1600, 900).
         keep_ratio: Whether to keep the aspect ratio or not. Defaults to False.
         evaluate: Whether to evaluate or not the anchors. Check
-            [`pyodi train-config evaluation`][pyodi.apps.train_config_evaluation.train_config_evaluation]
+            [`pyodi train-config evaluation`][pyodi.apps.train_config.train_config_evaluation.train_config_evaluation]
             for more information.
 
     Returns:


Test patch:
diff --git a/tests/apps/test_coco_merge.py b/tests/apps/test_coco_merge.py
index 762bf7b..1fb4b15 100644
--- a/tests/apps/test_coco_merge.py
+++ b/tests/apps/test_coco_merge.py
@@ -1,6 +1,6 @@
 import json
 
-from pyodi.apps.coco_merge import coco_merge
+from pyodi.apps.coco.coco_merge import coco_merge
 
 
 def test_coco_merge(tmp_path):
diff --git a/tests/apps/test_coco_split.py b/tests/apps/test_coco_split.py
index b4dc17b..136a447 100644
--- a/tests/apps/test_coco_split.py
+++ b/tests/apps/test_coco_split.py
@@ -1,7 +1,7 @@
 import json
 from pathlib import Path
 
-from pyodi.apps.coco_split import property_split, random_split
+from pyodi.apps.coco.coco_split import property_split, random_split
 
 
 def get_coco_data():
diff --git a/tests/apps/test_crops_merge.py b/tests/apps/test_crops_merge.py
index e5a7e41..86f9644 100644
--- a/tests/apps/test_crops_merge.py
+++ b/tests/apps/test_crops_merge.py
@@ -3,7 +3,7 @@
 
 import numpy as np
 
-from pyodi.apps.crops_merge import crops_merge
+from pyodi.apps.crops.crops_merge import crops_merge
 
 
 def test_crops_merge(tmpdir):
diff --git a/tests/apps/test_crops_split.py b/tests/apps/test_crops_split.py
index 50e9d96..e33724e 100644
--- a/tests/apps/test_crops_split.py
+++ b/tests/apps/test_crops_split.py
@@ -5,7 +5,7 @@
 import numpy as np
 from PIL import Image
 
-from pyodi.apps.crops_split import crops_split
+from pyodi.apps.crops.crops_split import crops_split
 
 
 def create_image() -> Image: