Spaces:
Configuration error
Configuration error
import os | |
import ast | |
import sys | |
from typing import List, Tuple, Optional | |
def find_litellm_type_hints(directory: str) -> List[Tuple[str, int, str]]: | |
""" | |
Recursively search for Python files in the given directory | |
and find type hints containing 'litellm.'. | |
Args: | |
directory (str): The root directory to search for Python files | |
Returns: | |
List of tuples containing (file_path, line_number, type_hint) | |
""" | |
litellm_type_hints = [] | |
def is_litellm_type_hint(node): | |
""" | |
Recursively check if a type annotation contains 'litellm.' | |
Handles more complex type hints like: | |
- Optional[litellm.Type] | |
- Union[litellm.Type1, litellm.Type2] | |
- Nested type hints | |
""" | |
try: | |
# Convert node to string representation | |
type_str = ast.unparse(node) | |
# Direct check for litellm in type string | |
if "litellm." in type_str: | |
return True | |
# Handle more complex type hints | |
if isinstance(node, ast.Subscript): | |
# Check Union or Optional types | |
if isinstance(node.value, ast.Name) and node.value.id in [ | |
"Union", | |
"Optional", | |
]: | |
# Check each element in the Union/Optional type | |
if isinstance(node.slice, ast.Tuple): | |
return any(is_litellm_type_hint(elt) for elt in node.slice.elts) | |
else: | |
return is_litellm_type_hint(node.slice) | |
# Recursive check for subscripted types | |
return is_litellm_type_hint(node.value) or is_litellm_type_hint( | |
node.slice | |
) | |
# Recursive check for attribute types | |
if isinstance(node, ast.Attribute): | |
return "litellm." in ast.unparse(node) | |
# Recursive check for name types | |
if isinstance(node, ast.Name): | |
return "litellm" in node.id | |
return False | |
except Exception: | |
# Fallback to string checking if parsing fails | |
try: | |
return "litellm." in ast.unparse(node) | |
except: | |
return False | |
def scan_file(file_path: str): | |
""" | |
Scan a single Python file for LiteLLM type hints | |
""" | |
try: | |
# Use utf-8-sig to handle files with BOM, ignore errors | |
with open(file_path, "r", encoding="utf-8-sig", errors="ignore") as file: | |
tree = ast.parse(file.read()) | |
for node in ast.walk(tree): | |
# Check type annotations in variable annotations | |
if isinstance(node, ast.AnnAssign) and node.annotation: | |
if is_litellm_type_hint(node.annotation): | |
litellm_type_hints.append( | |
(file_path, node.lineno, ast.unparse(node.annotation)) | |
) | |
# Check type hints in function arguments | |
elif isinstance(node, ast.FunctionDef): | |
for arg in node.args.args: | |
if arg.annotation and is_litellm_type_hint(arg.annotation): | |
litellm_type_hints.append( | |
(file_path, arg.lineno, ast.unparse(arg.annotation)) | |
) | |
# Check return type annotation | |
if node.returns and is_litellm_type_hint(node.returns): | |
litellm_type_hints.append( | |
(file_path, node.lineno, ast.unparse(node.returns)) | |
) | |
except SyntaxError as e: | |
print(f"Syntax error in {file_path}: {e}", file=sys.stderr) | |
except Exception as e: | |
print(f"Error processing {file_path}: {e}", file=sys.stderr) | |
# Recursively walk through directory | |
for root, dirs, files in os.walk(directory): | |
# Remove virtual environment and cache directories from search | |
dirs[:] = [ | |
d | |
for d in dirs | |
if not any( | |
venv in d | |
for venv in [ | |
"venv", | |
"env", | |
"myenv", | |
".venv", | |
"__pycache__", | |
".pytest_cache", | |
] | |
) | |
] | |
for file in files: | |
if file.endswith(".py"): | |
full_path = os.path.join(root, file) | |
# Skip files in virtual environment or cache directories | |
if not any( | |
venv in full_path | |
for venv in [ | |
"venv", | |
"env", | |
"myenv", | |
".venv", | |
"__pycache__", | |
".pytest_cache", | |
] | |
): | |
scan_file(full_path) | |
return litellm_type_hints | |
def main(): | |
# Get directory from command line argument or use current directory | |
directory = "./litellm/" | |
# Find LiteLLM type hints | |
results = find_litellm_type_hints(directory) | |
# Print results | |
if results: | |
print("LiteLLM Type Hints Found:") | |
for file_path, line_num, type_hint in results: | |
print(f"{file_path}:{line_num} - {type_hint}") | |
else: | |
print("No LiteLLM type hints found.") | |
if __name__ == "__main__": | |
main() | |