diff --git a/pyproject.toml b/pyproject.toml
index 8e52531e530ce394f08c59a2e551d8907b3c3915..61f7768f48ea66d41bffd1193571667dee581593 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -22,6 +22,8 @@ dependencies = [
 
 [project.optional-dependencies]
 QUALITY = [
+    "black",
+    "mypy",
     "pre-commit",
 ]
 
@@ -29,3 +31,10 @@ QUALITY = [
 strict-config = true
 plugins.line-length.enabled = false
 
+[[tool.mypy.overrides]]
+module = [
+    "packaging.requirements",
+    "packaging.specifiers",
+    "packaging",
+]
+ignore_missing_imports = true
\ No newline at end of file
diff --git a/templates/python/dependancy_management/depandabot/compare.py b/templates/python/dependancy_management/depandabot/compare.py
index 4899f21d2b5bc18236de9f3a09aa185beb183787..22462d28eaa75c1cd0fc0190859707551d1e64da 100644
--- a/templates/python/dependancy_management/depandabot/compare.py
+++ b/templates/python/dependancy_management/depandabot/compare.py
@@ -7,6 +7,11 @@ import argparse
 import typing
 
 
+class OldNewRequirements(typing.NamedTuple):
+    old: packaging.requirements.Requirement
+    new: packaging.requirements.Requirement
+
+
 def clean_lines(f: io.TextIOWrapper) -> typing.Generator[str, None, None]:
     for line in f:
         # remove comments and hashes
@@ -16,71 +21,16 @@ def clean_lines(f: io.TextIOWrapper) -> typing.Generator[str, None, None]:
             yield line.rstrip("\n").rstrip("\\")
 
 
-def compare_requirements(
-    file: pathlib.Path,
-) -> tuple[
-    packaging.requirements.Requirement,
-    packaging.requirements.Requirement,
-    packaging.requirements.Requirement,
-]:
-    set_before = set()
-    set_after = set()
-    with file.open() as f:
-        set_after = {
-            packaging.requirements.Requirement(line) for line in clean_lines(f)
-        }
-
-    set_before = {
-        packaging.requirements.Requirement(line)
-        for line in clean_lines(retrieve_requirements(file))
-    }
-
-    d_new = {s.name: s for s in set_after.difference(set_before)}
-    d_old = {s.name: s for s in set_before.difference(set_after)}
-
-    set_added = {v for k, v in d_new.items() if k not in d_old}
-    set_updated = {(d_old[k], v) for k, v in d_new.items() if k in d_old}
-    set_removed = {v for k, v in d_old.items() if k not in d_new}
-
-    return (set_added, set_updated, set_removed)
-
-
-def generate_changes(
-    added: set[packaging.requirements.Requirement],
-    updated: set[
-        tuple[
-            packaging.requirements.Requirement,
-            packaging.requirements.Requirement,
-        ]
-    ],
-    removed: set[packaging.requirements.Requirement],
-) -> str:
-    description = []
-    for a in added:
-        description.append(
-            f"- Added `{a.name}` version "
-            f"`{retrieve_equal_version(a.specifier).version}`"
-        )
-    for u in updated:
-        description.append(
-            f"- Bump `{u[0].name}` from "
-            f"`{retrieve_equal_version(u[0].specifier).version}` to "
-            f"`{retrieve_equal_version(u[1].specifier).version}`"
-        )
-    for r in removed:
-        description.append(
-            f"- Removed `{r.name}` version "
-            f"`{retrieve_equal_version(r.specifier).version}`"
-        )
-    return "\r\n".join(description)
-
-
 def retrieve_equal_version(
     specifier: packaging.specifiers.SpecifierSet,
 ) -> packaging.specifiers.Specifier:
+    """
+    :raises ValueError: if no equal version is found
+    """
     for s in specifier:
         if s.operator == "==":
             return s
+    raise ValueError("No equal version found")
 
 
 def retrieve_requirements(file: pathlib.Path) -> io.StringIO:
@@ -92,27 +42,107 @@ def retrieve_requirements(file: pathlib.Path) -> io.StringIO:
     return content
 
 
+def compare_requirements(
+    requirements: pathlib.Path,
+) -> tuple[
+    set[packaging.requirements.Requirement],
+    set[
+        OldNewRequirements[
+            packaging.requirements.Requirement, packaging.requirements.Requirement
+        ]
+    ],
+    set[packaging.requirements.Requirement],
+]:
+    with requirements.open() as file:
+        set_after = {
+            packaging.requirements.Requirement(line) for line in clean_lines(file)
+        }
+
+    set_before = {
+        packaging.requirements.Requirement(line)
+        for line in clean_lines(retrieve_requirements(requirements))
+    }
+
+    new_requirements = {
+        requirement.name: requirement
+        for requirement in set_after.difference(set_before)
+    }
+    old_requirements = {
+        requirement.name: requirement
+        for requirement in set_before.difference(set_after)
+    }
+
+    added_requirements = {
+        requirement
+        for package_name, requirement in new_requirements.items()
+        if package_name not in old_requirements
+    }
+    updated_requirements = {
+        OldNewRequirements(old_requirements[package_name], requirement)
+        for package_name, requirement in new_requirements.items()
+        if package_name in old_requirements
+    }
+    removed_requirements = {
+        requirement
+        for package_name, requirement in old_requirements.items()
+        if package_name not in new_requirements
+    }
+
+    return added_requirements, updated_requirements, removed_requirements
+
+
 def parser() -> argparse.ArgumentParser:
-    p = argparse.ArgumentParser()
-    p.add_argument(
+    parser = argparse.ArgumentParser()
+    parser.add_argument(
         "requirements_file",
         nargs="?",
         default=pathlib.Path("requirements.txt"),
         type=pathlib.Path,
     )
-    p.add_argument(
+    parser.add_argument(
         "-o",
-        nargs=1,
+        nargs="?",
         default=pathlib.Path("description.md"),
         type=pathlib.Path,
         required=False,
     )
-    return p
+    return parser
+
+
+def generate_changes(
+    added_requirements: set[packaging.requirements.Requirement],
+    updated: set[
+        OldNewRequirements[
+            packaging.requirements.Requirement,
+            packaging.requirements.Requirement,
+        ]
+    ],
+    removed: set[packaging.requirements.Requirement],
+) -> str:
+    description = (
+        [
+            f"- Added `{requirement.name}` version "
+            f"`{retrieve_equal_version(requirement.specifier).version}`"
+            for requirement in added_requirements
+        ]
+        + [
+            f"- Bump `{requirements.old.name}` from "
+            f"`{retrieve_equal_version(requirements.old.specifier).version}` to "
+            f"`{retrieve_equal_version(requirements.new.specifier).version}`"
+            for requirements in updated
+        ]
+        + [
+            f"- Removed `{requirement.name}` version "
+            f"`{retrieve_equal_version(requirement.specifier).version}`"
+            for requirement in removed
+        ]
+    )
+    return "\r\n".join(description)
 
 
 def main():
     args = parser().parse_args()
-    (added, updated, removed) = compare_requirements(args.requirements_file)
+    added, updated, removed = compare_requirements(args.requirements_file)
     args.o.write_text(generate_changes(added, updated, removed))
 
 
diff --git a/templates/python/dependancy_management/depandabot/depandabot.yml b/templates/python/dependancy_management/depandabot/depandabot.yml
index 8ef6397b2687c710ca5191326bac186538d1c8a9..0e8361b54e01f9323057046e3751dcebf1200df2 100644
--- a/templates/python/dependancy_management/depandabot/depandabot.yml
+++ b/templates/python/dependancy_management/depandabot/depandabot.yml
@@ -8,17 +8,19 @@ depandabot:
     image: python:${IMAGE_TAG}
 
     variables:
-        PYTHON_SETUP: pip install pip-tools packaging
+        PYTHON_SETUP: pip install pip-tools
         GITLAB_API_URL: "${CI_SERVER_HOST}"
+        REQUIREMENTS_FILE_PATH: "requirements.in"
+        OUTPUT_FILE_PATH: "requirements${IMAGE_TAG}.txt"
     
     script:
         - !reference [.python_install, script]
         - DEPS_BRANCH="depandabot/requirements-txt/$(date +%s)"
         - |
             COMMIT_MESSAGE="build(deps): bump new versions"
-        - $([ -f ${REQUIREMENTS_FILE_PATH} ]) && ACTION="update" || ACTION="create"
-        - pip-compile --quiet -o ${REQUIREMENTS_FILE_PATH}
-        - if [ -n "$(git status --porcelain ${REQUIREMENTS_FILE_PATH})" ]; then
+        - $([ -f ${OUTPUT_FILE_PATH} ]) && ACTION="update" || ACTION="create"
+        - pip-compile --quiet -o ${OUTPUT_FILE_PATH} ${REQUIREMENTS_FILE_PATH}
+        - if [ -n "$(git status --porcelain ${OUTPUT_FILE_PATH})" ]; then
         - |
             curl --header "Authorization: Bearer ${DEPANDABOT_TOKEN}" \
             --form "branch=$DEPS_BRANCH" \
@@ -29,10 +31,10 @@ depandabot:
             --form "branch=$DEPS_BRANCH" \
             --form "commit_message=$COMMIT_MESSAGE" \
             --form "actions[][action]=$ACTION" \
-            --form "actions[][file_path]=${REQUIREMENTS_FILE_PATH}" \
-            --form "actions[][content]=<${REQUIREMENTS_FILE_PATH}" \
+            --form "actions[][file_path]=${OUTPUT_FILE_PATH}" \
+            --form "actions[][content]=<${OUTPUT_FILE_PATH}" \
             "https://${GITLAB_API_URL}/api/v4/projects/${CI_PROJECT_ID}/repository/commits"
-        - python compare.py -o description.md ${REQUIREMENTS_FILE_PATH} 
+        - python compare.py -o description.md ${OUTPUT_FILE_PATH}
         - |
             curl --header "Authorization: Bearer ${DEPANDABOT_TOKEN}" \
             --form "source_branch=$DEPS_BRANCH" \