Files
Kalulu/.github/scripts/check_file_naming.py
T

84 lines
3.0 KiB
Python

import os
import re
import sys
# File extensions to validate
TARGET_EXTS = {
".gd", # Godot scripts
".tscn", # Godot scenes
".tres", ".res", # resources
".png", ".jpg", # images
".glb", ".gltf", ".dae", ".obj", # 3D models
".wav", ".ogg", ".mp3", # sounds
}
# Directories to ignore entirely (e.g., external or tooling folders)
EXCLUDED_DIRS = {"addons", "script_templates", ".git", ".github", ".godot", "android"}
invalid_files = []
invalid_dirs = []
_BASE_PATTERN = re.compile(r"^[a-z0-9_]+$")
def to_snake_case(filename: str) -> str:
base, ext = os.path.splitext(filename)
s1 = re.sub(r"([A-Z]+)([A-Z][a-z])", r"\1_\2", base)
s2 = re.sub(r"([a-z0-9])([A-Z])", r"\1_\2", s1)
s3 = re.sub(r"[-\s]+", "_", s2)
return s3.lower() + ext
for root, dirs, files in os.walk('.', topdown=True):
rel_root = os.path.relpath(root, '.')
if any(
rel_root == excluded or rel_root.startswith(f"{excluded}{os.sep}")
for excluded in EXCLUDED_DIRS
):
dirs[:] = []
continue
if rel_root != '.':
dirname = os.path.basename(root)
if not _BASE_PATTERN.match(dirname):
suggestion = to_snake_case(dirname)
if os.path.dirname(rel_root):
suggested_rel = os.path.join(os.path.dirname(rel_root), suggestion)
else:
suggested_rel = suggestion
invalid_dirs.append((rel_root, suggested_rel))
# Validate subdirectories
for dir in list(dirs):
rel_path = os.path.join(rel_root, dir) if rel_root != '.' else dir
if any(
rel_path == excluded or rel_path.startswith(f"{excluded}{os.sep}")
for excluded in EXCLUDED_DIRS
):
dirs.remove(dir)
continue
if not _BASE_PATTERN.match(dir):
suggestion = to_snake_case(dir)
suggested_rel = os.path.join(rel_root, suggestion) if rel_root != '.' else suggestion
invalid_dirs.append((rel_path, suggested_rel))
for name in files:
base, ext = os.path.splitext(name)
if ext in TARGET_EXTS:
if not _BASE_PATTERN.match(base):
suggestion = to_snake_case(name)
rel_path = os.path.join(rel_root, name) if rel_root != '.' else name
suggested_rel = os.path.join(rel_root, suggestion) if rel_root != '.' else suggestion
invalid_files.append((rel_path, suggested_rel))
if invalid_dirs or invalid_files:
count = len(invalid_dirs) + len(invalid_files)
print("### \u274c Godot File Naming Convention Check Failed\n")
print(f"Script names must be in snake_case.\n{count} invalid name{'s' if count > 1 else ''} detected:\n")
for path, suggestion in invalid_dirs:
print(f"- **Directory** `{path}` \u2192 `{suggestion}`")
for path, suggestion in invalid_files:
print(f"- **File** `{path}` \u2192 `{suggestion}`")
sys.exit(1)
else:
print("\u2705 All filenames and directories follow Godot naming convention.")