Skip to content

Commit d3a9bbe

Browse files
author
nevil06
committed
error fix
1 parent d194233 commit d3a9bbe

File tree

1 file changed

+191
-0
lines changed

1 file changed

+191
-0
lines changed
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Function Name Validator for Gemini API
4+
Validates and corrects function names to meet Gemini API requirements.
5+
6+
Requirements:
7+
- Must start with a letter (a-z, A-Z) or underscore (_)
8+
- Can only contain: letters, digits, underscores, dots (.), or dashes (-)
9+
- Maximum length: 64 characters
10+
"""
11+
12+
import re
13+
from typing import Tuple
14+
15+
16+
class FunctionNameValidator:
17+
"""Validator for Gemini API function names."""
18+
19+
# Gemini API function name constraints
20+
MAX_LENGTH = 64
21+
VALID_CHARS_PATTERN = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_.\-]*$')
22+
VALID_START_PATTERN = re.compile(r'^[a-zA-Z_]')
23+
VALID_BODY_PATTERN = re.compile(r'^[a-zA-Z0-9_.\-]+$')
24+
25+
@classmethod
26+
def validate(cls, name: str) -> Tuple[bool, str]:
27+
"""
28+
Validate if a function name meets Gemini API requirements.
29+
30+
Args:
31+
name: The function name to validate
32+
33+
Returns:
34+
Tuple of (is_valid, error_message)
35+
- is_valid: True if the name is valid, False otherwise
36+
- error_message: Empty string if valid, otherwise describes the issue
37+
"""
38+
if not name:
39+
return False, "Function name cannot be empty"
40+
41+
if len(name) > cls.MAX_LENGTH:
42+
return False, f"Function name exceeds maximum length of {cls.MAX_LENGTH} characters (current: {len(name)})"
43+
44+
if not cls.VALID_START_PATTERN.match(name[0]):
45+
return False, f"Function name must start with a letter or underscore, found: '{name[0]}'"
46+
47+
if not cls.VALID_CHARS_PATTERN.match(name):
48+
invalid_chars = set()
49+
for char in name:
50+
if not re.match(r'[a-zA-Z0-9_.\-]', char):
51+
invalid_chars.add(char)
52+
return False, f"Function name contains invalid characters: {', '.join(repr(c) for c in sorted(invalid_chars))}"
53+
54+
return True, ""
55+
56+
@classmethod
57+
def correct(cls, name: str, fallback_prefix: str = "func") -> str:
58+
"""
59+
Correct a function name to meet Gemini API requirements.
60+
61+
Args:
62+
name: The function name to correct
63+
fallback_prefix: Prefix to use if the name is empty or starts with invalid character
64+
65+
Returns:
66+
A corrected function name that meets all requirements
67+
"""
68+
if not name:
69+
return fallback_prefix
70+
71+
# Replace invalid characters with underscores
72+
corrected = re.sub(r'[^a-zA-Z0-9_.\-]', '_', name)
73+
74+
# Ensure it starts with a letter or underscore
75+
if not cls.VALID_START_PATTERN.match(corrected[0]):
76+
# If starts with a digit, dot, or dash, prepend the fallback prefix
77+
corrected = f"{fallback_prefix}_{corrected}"
78+
79+
# Truncate to maximum length
80+
if len(corrected) > cls.MAX_LENGTH:
81+
corrected = corrected[:cls.MAX_LENGTH]
82+
# Ensure we didn't cut off in the middle leaving a trailing invalid char
83+
# (though underscores, dots, and dashes are valid at the end)
84+
85+
# Final validation - this should always pass now
86+
is_valid, _ = cls.validate(corrected)
87+
if not is_valid:
88+
# Fallback to a safe default if somehow still invalid
89+
return fallback_prefix
90+
91+
return corrected
92+
93+
@classmethod
94+
def validate_and_correct(cls, name: str, fallback_prefix: str = "func") -> Tuple[bool, str, str]:
95+
"""
96+
Validate a function name and provide a corrected version if invalid.
97+
98+
Args:
99+
name: The function name to validate
100+
fallback_prefix: Prefix to use for correction if needed
101+
102+
Returns:
103+
Tuple of (is_valid, corrected_name, message)
104+
- is_valid: True if the original name was valid
105+
- corrected_name: The original name if valid, otherwise a corrected version
106+
- message: Empty if valid, otherwise describes what was corrected
107+
"""
108+
is_valid, error_msg = cls.validate(name)
109+
110+
if is_valid:
111+
return True, name, ""
112+
113+
corrected = cls.correct(name, fallback_prefix)
114+
message = f"Original name '{name}' was invalid: {error_msg}. Corrected to: '{corrected}'"
115+
116+
return False, corrected, message
117+
118+
119+
# Convenience functions for direct use
120+
def validate_function_name(name: str) -> Tuple[bool, str]:
121+
"""
122+
Validate if a function name meets Gemini API requirements.
123+
124+
Args:
125+
name: The function name to validate
126+
127+
Returns:
128+
Tuple of (is_valid, error_message)
129+
"""
130+
return FunctionNameValidator.validate(name)
131+
132+
133+
def correct_function_name(name: str, fallback_prefix: str = "func") -> str:
134+
"""
135+
Correct a function name to meet Gemini API requirements.
136+
137+
Args:
138+
name: The function name to correct
139+
fallback_prefix: Prefix to use if the name is empty or starts with invalid character
140+
141+
Returns:
142+
A corrected function name that meets all requirements
143+
"""
144+
return FunctionNameValidator.correct(name, fallback_prefix)
145+
146+
147+
def validate_and_correct_function_name(name: str, fallback_prefix: str = "func") -> Tuple[bool, str, str]:
148+
"""
149+
Validate a function name and provide a corrected version if invalid.
150+
151+
Args:
152+
name: The function name to validate
153+
fallback_prefix: Prefix to use for correction if needed
154+
155+
Returns:
156+
Tuple of (is_valid, corrected_name, message)
157+
"""
158+
return FunctionNameValidator.validate_and_correct(name, fallback_prefix)
159+
160+
161+
if __name__ == "__main__":
162+
# Example usage and testing
163+
test_cases = [
164+
"valid_function_name",
165+
"ValidFunctionName",
166+
"_private_function",
167+
"function.with.dots",
168+
"function-with-dashes",
169+
"123_starts_with_number",
170+
"has spaces in it",
171+
"has@special#chars",
172+
"a" * 70, # Too long
173+
"", # Empty
174+
"café", # Unicode
175+
".starts.with.dot",
176+
"-starts-with-dash",
177+
]
178+
179+
print("Function Name Validation Tests")
180+
print("=" * 80)
181+
182+
for test_name in test_cases:
183+
is_valid, corrected, message = validate_and_correct_function_name(test_name)
184+
185+
print(f"\nOriginal: {repr(test_name)}")
186+
print(f"Valid: {is_valid}")
187+
if not is_valid:
188+
print(f"Corrected: {repr(corrected)}")
189+
print(f"Message: {message}")
190+
else:
191+
print(f"✓ Name is valid")

0 commit comments

Comments
 (0)