From 4fac8ae16523a56d00b2842c7bd31e694b8d87ee Mon Sep 17 00:00:00 2001
From: Serge Bazanski <q3k@q3k.org>
Date: Thu, 20 Jul 2023 21:10:55 +0200
Subject: [PATCH] ci: run mypy

---
 .gitlab-ci.yml                                | 19 +++++-
 ...lang-tidy-report.py => codequal-report.py} | 66 ++++++++++++++-----
 2 files changed, 68 insertions(+), 17 deletions(-)
 rename tools/{clang-tidy-report.py => codequal-report.py} (66%)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 86face4518..bfab284bfa 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -17,11 +17,26 @@ clang-tidy:
   script:
     - "idf.py build"
     - "idf.py clang-check"
-    - "python3 tools/clang-tidy-report.py warnings.txt > clang-tidy-cqual.json"
+    - "python3 tools/codequal-report.py clang-tidy warnings.txt > cqual.json"
   artifacts:
     when: always
     reports:
-      codequality: clang-tidy-cqual.json
+      codequality: cqual.json
+
+mypy:
+  stage: check
+  variables:
+    MYPYPATH: python_payload/mypystubs
+  script:
+    - "set +e +o pipefail"
+    - "mypy python_payload/main_st4m.py --strict --no-color-output > warnings.txt; result=$?"
+    - "python3 tools/codequal-report.py mypy warnings.txt > cqual.json"
+    - "set -e -o pipefail"
+    - "[ $result == 0 ]"
+  artifacts:
+    when: always
+    reports:
+      codequality: cqual.json
 
 build-p3:
   stage: build
diff --git a/tools/clang-tidy-report.py b/tools/codequal-report.py
similarity index 66%
rename from tools/clang-tidy-report.py
rename to tools/codequal-report.py
index 6bd7ae224a..ecab2c5342 100644
--- a/tools/clang-tidy-report.py
+++ b/tools/codequal-report.py
@@ -19,7 +19,7 @@ class MagicJSONEncoder(json.JSONEncoder):
 @dataclass
 class Position:
     line: int
-    column: int
+    column: Union[int, None]
 
 
 @dataclass
@@ -50,18 +50,26 @@ class Issue:
     fingerprint: str
 
 
-def parse_line(s: str) -> Union[Issue, None]:
-    parts = s.split(':', 4)
+def parse_line(s: str, nocol: bool=False) -> Union[Issue, None]:
+    nparts = 4
+    if nocol:
+        nparts = 3
+    parts = s.split(':', nparts)
     path = parts[0]
     path = path.removeprefix(os.getcwd() + '/')
     line = int(parts[1])
-    col = int(parts[2])
-    level = parts[3].strip()
+    if nocol:
+        col = None
+        level = parts[2].strip()
+        rest = parts[3].strip()
+    else:
+        level = parts[3].strip()
+        col = int(parts[2])
+        rest = parts[4].strip()
     severity: Severity = {
         'warning': Severity.major,
         'error': Severity.blocker,
     }.get(level, Severity.info)
-    rest = parts[4].strip()
     check = ''
     if rest.endswith(']'):
         rest, check = rest.split('[')
@@ -72,14 +80,24 @@ def parse_line(s: str) -> Union[Issue, None]:
     return Issue(description=rest, check_name=check, severity=severity, location=location, fingerprint=fp)
 
 
-def main() -> None:
-    if len(sys.argv) < 2:
-        sys.stderr.write(f"Usage: {sys.argv[0]} warnings.txt\n")
-        sys.stderr.flush()
-        sys.exit(1)
+def mypy(p: str) -> List[Issue]:
+    res: List[Issue] = []
+    with open(p) as f:
+        for line in f:
+            line = line.strip()
+            if line.startswith('Found '):
+                continue
+            if line.startswith('Success: '):
+                continue
+            v = parse_line(line, nocol=True)
+            if v is not None:
+                res.append(v)
+    return res
 
+
+def clang_tidy(p: str) -> List[Issue]:
     res: List[Issue] = []
-    with open(sys.argv[1]) as f:
+    with open(p) as f:
         in_checks = False
         in_list = False
         in_context = False
@@ -103,11 +121,29 @@ def main() -> None:
                     if v is not None:
                         res.append(v)
                     in_context = True
+    return res
+
+
+def main() -> None:
+    if len(sys.argv) < 3:
+        sys.stderr.write(f"Usage: {sys.argv[0]} (clang-tidy|mypy) warnings.txt\n")
+        sys.stderr.flush()
+        sys.exit(1)
+
+    kind = sys.argv[1]
+    path = sys.argv[2]
+    if kind == 'clang-tidy':
+        res = clang_tidy(path)
+    elif kind == 'mypy':
+        res = mypy(path)
+    else:
+        sys.stderr.write(f"Unknown kind {kind}\n")
+        sys.stderr.flush()
+        sys.exit(1)
+
     json.dump(res, sys.stdout, cls=MagicJSONEncoder)
     if res != []:
-        sys.stderr.write("Clang-tidy report not empty")
-        sys.stderr.flush()
-        os.exit(1)
+        sys.exit(1)
 
 if __name__ == '__main__':
     main()
-- 
GitLab