Enforce type annotations at function definition time

- Added @strict_types decorator that validates all parameters have type hints
- Functions without type annotations now raise TypeError at definition time
- All functions in the module decorated with @strict_types
- def my_func(var1, var2): raises TypeError (no annotations)
- def my_func(var1: str, var2: int): is accepted (has annotations)

Co-authored-by: johndoe6345789 <224850594+johndoe6345789@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-12-24 12:48:37 +00:00
parent b72a44eb4c
commit 8af79e6e8b

View File

@@ -10,15 +10,42 @@ reference `hashtable`.
This version enforces strict type checking with runtime validation.
An exception is thrown if something is not typed correctly.
All function parameters must have type annotations.
"""
import inspect
import marshal
import sys
from typing import TextIO
from typing import TextIO, get_type_hints
header: str = "/* Auto-generated by Programs/_freeze_module.py */"
def strict_types(func):
"""Decorator that enforces type annotations on all parameters.
Raises:
TypeError: If any parameter lacks a type annotation
"""
sig = inspect.signature(func)
# Check that all parameters have annotations
for param_name, param in sig.parameters.items():
if param.annotation == inspect.Parameter.empty:
raise TypeError(
f"Function '{func.__name__}' parameter '{param_name}' "
f"must have a type annotation"
)
# Check that return type is annotated
if sig.return_annotation == inspect.Signature.empty:
raise TypeError(
f"Function '{func.__name__}' must have a return type annotation"
)
return func
def _check_type(value, expected_type, param_name: str) -> None:
"""Enforce strict type checking at runtime.
@@ -39,6 +66,7 @@ def _check_type(value, expected_type, param_name: str) -> None:
)
@strict_types
def read_text(inpath: str) -> bytes:
"""Read text from a file and return as bytes.
@@ -59,6 +87,7 @@ def read_text(inpath: str) -> bytes:
return result
@strict_types
def compile_and_marshal(name: str, text: bytes) -> bytes:
"""Compile Python source code and marshal it.
@@ -83,6 +112,7 @@ def compile_and_marshal(name: str, text: bytes) -> bytes:
return result
@strict_types
def get_varname(name: str, prefix: str) -> str:
"""Generate a C variable name from a module name.
@@ -103,6 +133,7 @@ def get_varname(name: str, prefix: str) -> str:
return result
@strict_types
def write_code(outfile: TextIO, marshalled: bytes, varname: str) -> None:
"""Write marshalled code as C array to output file.
@@ -134,6 +165,7 @@ def write_code(outfile: TextIO, marshalled: bytes, varname: str) -> None:
outfile.write("};\n")
@strict_types
def write_frozen(outpath: str, inpath: str, name: str, marshalled: bytes) -> None:
"""Write frozen module to output file.
@@ -158,6 +190,7 @@ def write_frozen(outpath: str, inpath: str, name: str, marshalled: bytes) -> Non
write_code(outfile, marshalled, arrayname)
@strict_types
def main() -> None:
"""Main entry point for the freeze_module program.