You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tooling.apache.org by sb...@apache.org on 2025/04/14 19:16:12 UTC

(tooling-trusted-release) branch main updated: Add a script to check the order of top level functions in a module

This is an automated email from the ASF dual-hosted git repository.

sbp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-release.git


The following commit(s) were added to refs/heads/main by this push:
     new 0819974  Add a script to check the order of top level functions in a module
0819974 is described below

commit 0819974e1bd04859ecd801c097195e593a9ca2e7
Author: Sean B. Palmer <se...@miscoranda.com>
AuthorDate: Mon Apr 14 20:15:54 2025 +0100

    Add a script to check the order of top level functions in a module
---
 scripts/interface_order.py | 86 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 86 insertions(+)

diff --git a/scripts/interface_order.py b/scripts/interface_order.py
new file mode 100644
index 0000000..332bab4
--- /dev/null
+++ b/scripts/interface_order.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python3
+
+import ast
+import enum
+import pathlib
+import sys
+from collections.abc import Sequence
+
+
+class ExitCode(enum.IntEnum):
+    SUCCESS = 0
+    FAILURE = 1
+    USAGE_ERROR = 2
+
+
+def _extract_top_level_function_names(tree: ast.Module) -> list[str]:
+    function_names: list[str] = []
+    for node in tree.body:
+        if isinstance(node, ast.FunctionDef):
+            function_names.append(node.name)
+    return function_names
+
+
+def _parse_python_code(code: str, filename: str) -> ast.Module | None:
+    try:
+        return ast.parse(code, filename=filename)
+    except SyntaxError as e:
+        print(f"Error: Invalid Python syntax in {filename}: {e}", file=sys.stderr)
+        return None
+
+
+def _read_file_content(file_path: pathlib.Path) -> str | None:
+    try:
+        return file_path.read_text(encoding="utf-8")
+    except FileNotFoundError:
+        print(f"Error: File not found: {file_path}", file=sys.stderr)
+        return None
+    except OSError as e:
+        print(f"Error: Could not read file {file_path}: {e}", file=sys.stderr)
+        return None
+
+
+def _verify_names_are_sorted(names: Sequence[str], filename: str) -> bool:
+    is_sorted = all(names[i] <= names[i + 1] for i in range(len(names) - 1))
+    if is_sorted:
+        return True
+
+    for i in range(len(names) - 1):
+        if names[i] > names[i + 1]:
+            print(
+                f"Error: Function '{names[i + 1]}' in {filename} is not ordered correctly relative to '{names[i]}'",
+                file=sys.stderr,
+            )
+    return False
+
+
+def main() -> None:
+    if len(sys.argv) != 2:
+        print("Usage: python interface_order.py <filename>", file=sys.stderr)
+        sys.exit(ExitCode.USAGE_ERROR)
+
+    file_path = pathlib.Path(sys.argv[1])
+
+    content = _read_file_content(file_path)
+    if content is None:
+        sys.exit(ExitCode.FAILURE)
+
+    tree = _parse_python_code(content, str(file_path))
+    if tree is None:
+        sys.exit(ExitCode.FAILURE)
+
+    function_names = _extract_top_level_function_names(tree)
+
+    if not function_names:
+        print(f"No top-level functions found in {file_path}. Nothing to check")
+        sys.exit(ExitCode.SUCCESS)
+
+    if _verify_names_are_sorted(function_names, str(file_path)):
+        print(f"Top-level functions in {file_path} are alphabetically ordered")
+        sys.exit(ExitCode.SUCCESS)
+    else:
+        sys.exit(ExitCode.FAILURE)
+
+
+if __name__ == "__main__":
+    main()


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tooling.apache.org
For additional commands, e-mail: commits-help@tooling.apache.org