from __future__ import annotations import builtins import json import keyword from pathlib import Path import pytest # --------------------------------------------------------------------------- # Dynamic Discovery: Find the pack file in this specific repository # --------------------------------------------------------------------------- def find_pack_file() -> Path: """Scans the repository root for a Foreignthon language pack JSON.""" repo_root = Path(__file__).parent.parent for path in repo_root.rglob("*.json"): # Ignore virtual environments, cache files, and CI directories ignored_dirs = {".venv", "venv", ".git", ".pytest_cache", ".gitea", ".github"} if any(part in path.parts for part in ignored_dirs): continue # Peek inside the JSON to see if it's a Foreignthon pack try: with open(path, encoding="utf-8") as f: content = json.load(f) if "meta" in content and "keywords" in content: return path except (json.JSONDecodeError, KeyError, TypeError): continue raise FileNotFoundError( "Could not find a valid Foreignthon language pack JSON file in this repository." ) # --------------------------------------------------------------------------- # Global Validation Sets # --------------------------------------------------------------------------- VALID_KEYWORDS = set(keyword.kwlist) | {"True", "False", "None"} VALID_BUILTINS = set(dir(builtins)) # --------------------------------------------------------------------------- # The Universal Test Suite # --------------------------------------------------------------------------- @pytest.fixture(scope="module") def pack_data() -> tuple[Path, dict]: """Loads the dynamically discovered pack file once for the test module.""" path = find_pack_file() with open(path, encoding="utf-8") as f: return path, json.load(f) def test_meta_section_integrity(pack_data): path, data = pack_data assert "meta" in data, f"Missing 'meta' section in {path.name}" meta = data["meta"] assert meta.get("name"), "meta.name cannot be empty" assert meta.get("native_name"), "meta.native_name cannot be empty" assert meta.get("code"), "meta.code cannot be empty" # Enforce that the file name matches the language code (e.g., es.json matches code 'es') assert ( path.stem == meta["code"] ), f"Filename '{path.name}' must exactly match meta.code '{meta['code']}'" def test_keywords_integrity(pack_data): path, data = pack_data assert "keywords" in data, f"Missing 'keywords' section in {path.name}" for foreign_word, python_keyword in data["keywords"].items(): assert python_keyword in VALID_KEYWORDS, ( f"Invalid target '{python_keyword}' for foreign keyword '{foreign_word}' in {path.name}. " "It is not a recognized Python keyword." ) def test_builtins_and_exceptions_integrity(pack_data): path, data = pack_data # Validate Builtins assert "builtins" in data, f"Missing 'builtins' section in {path.name}" for foreign_word, python_builtin in data["builtins"].items(): assert ( python_builtin in VALID_BUILTINS ), f"Invalid target '{python_builtin}' for builtin function '{foreign_word}' in {path.name}." # Validate Exceptions assert "exceptions" in data, f"Missing 'exceptions' section in {path.name}" for foreign_word, python_exception in data["exceptions"].items(): assert ( python_exception in VALID_BUILTINS ), f"Invalid target '{python_exception}' for exception '{foreign_word}' in {path.name}." def test_postfix_keywords_integrity(pack_data): path, data = pack_data assert "postfix_keywords" in data, f"Missing 'postfix_keywords' section in {path.name}" assert isinstance(data["postfix_keywords"], list), "'postfix_keywords' must be an array/list" # Extract all the English Python keywords that have been mapped in this pack mapped_python_targets = set(data["keywords"].values()) # Ensure any declared English postfix keyword actually has a mapped translation for post_kw in data["postfix_keywords"]: assert post_kw in mapped_python_targets, ( f"English postfix keyword '{post_kw}' is missing from the mapped values " f"in the main 'keywords' dictionary in {path.name}." )