2 changed files with 0 additions and 168 deletions
@ -1,85 +0,0 @@ |
|||||
#!/usr/bin/env python3 |
|
||||
""" |
|
||||
Test the CORRECT fix with separate functions. |
|
||||
""" |
|
||||
|
|
||||
import re |
|
||||
|
|
||||
# Simulated APIRoute for testing |
|
||||
class MockRoute: |
|
||||
def __init__(self, name: str, path_format: str, methods: set[str]): |
|
||||
self.name = name |
|
||||
self.path_format = path_format |
|
||||
self.methods = methods |
|
||||
|
|
||||
# The ORIGINAL public function - unchanged signature |
|
||||
def generate_unique_id(route: "MockRoute") -> str: |
|
||||
"""Public API - unchanged signature for backward compatibility""" |
|
||||
operation_id = f"{route.name}{route.path_format}" |
|
||||
operation_id = re.sub(r"\W", "_", operation_id) |
|
||||
assert route.methods |
|
||||
operation_id = f"{operation_id}_{list(route.methods)[0].lower()}" |
|
||||
return operation_id |
|
||||
|
|
||||
|
|
||||
# NEW internal function for OpenAPI per-method generation |
|
||||
def get_openapi_operation_id(route: "MockRoute", method: str) -> str: |
|
||||
"""Generate unique operation ID for specific HTTP method in OpenAPI""" |
|
||||
operation_id = f"{route.name}{route.path_format}" |
|
||||
operation_id = re.sub(r"\W", "_", operation_id) |
|
||||
operation_id = f"{operation_id}_{method.lower()}" |
|
||||
return operation_id |
|
||||
|
|
||||
|
|
||||
# Test 1: Custom generate_unique_id function (user compat) |
|
||||
print("Test 1: Backward compatibility with custom functions") |
|
||||
def custom_generate_unique_id(route): |
|
||||
return f"custom_{route.name}" |
|
||||
|
|
||||
route1 = MockRoute(name="get_text", path_format="/text", methods={"GET"}) |
|
||||
result = custom_generate_unique_id(route1) |
|
||||
print(f" Custom function still works: {result}") |
|
||||
assert result == "custom_get_text", f"Expected 'custom_get_text', got '{result}'" |
|
||||
print(" ✓ PASS: Custom functions compatible") |
|
||||
|
|
||||
# Test 2: Public API unchanged |
|
||||
print("\nTest 2: Public generate_unique_id unchanged") |
|
||||
route2 = MockRoute(name="get_text", path_format="/text", methods={"GET"}) |
|
||||
result = generate_unique_id(route2) |
|
||||
print(f" Public API result: {result}") |
|
||||
assert result == "get_text_text_get", f"Expected 'get_text_text_get', got '{result}'" |
|
||||
print(" ✓ PASS: Public API works as before") |
|
||||
|
|
||||
# Test 3: New function for multi-method routes |
|
||||
print("\nTest 3: Per-method operation IDs for OpenAPI") |
|
||||
route3 = MockRoute(name="handle_items", path_format="/items/", methods={"GET", "POST", "DELETE"}) |
|
||||
op_id_get = get_openapi_operation_id(route3, "GET") |
|
||||
op_id_post = get_openapi_operation_id(route3, "POST") |
|
||||
op_id_delete = get_openapi_operation_id(route3, "DELETE") |
|
||||
print(f" GET: {op_id_get}") |
|
||||
print(f" POST: {op_id_post}") |
|
||||
print(f" DELETE: {op_id_delete}") |
|
||||
|
|
||||
assert op_id_get == "handle_items_items__get" |
|
||||
assert op_id_post == "handle_items_items__post" |
|
||||
assert op_id_delete == "handle_items_items__delete" |
|
||||
assert len({op_id_get, op_id_post, op_id_delete}) == 3 |
|
||||
print(" ✓ PASS: Unique IDs per method") |
|
||||
|
|
||||
# Test 4: Public API for multi-method route |
|
||||
print("\nTest 4: Public API on multi-method route") |
|
||||
route4 = MockRoute(name="handle_items", path_format="/items/", methods={"GET", "POST", "DELETE"}) |
|
||||
unique_id = generate_unique_id(route4) |
|
||||
print(f" route.unique_id would be: {unique_id}") |
|
||||
print(f" (uses first method from set)") |
|
||||
print(" ✓ PASS: Maintains backward compatibility") |
|
||||
|
|
||||
print("\n" + "="*60) |
|
||||
print("✅ ALL TESTS PASSED - CORRECT FIX!") |
|
||||
print("="*60) |
|
||||
print("\nSummary:") |
|
||||
print("- Public generate_unique_id() signature unchanged") |
|
||||
print("- Custom user functions remain compatible") |
|
||||
print("- New get_openapi_operation_id() for per-method IDs") |
|
||||
print("- Multi-method routes get unique IDs in OpenAPI") |
|
||||
print("- Fixes issue #13175 without breaking changes") |
|
||||
@ -1,83 +0,0 @@ |
|||||
#!/usr/bin/env python3 |
|
||||
""" |
|
||||
Test the generate_unique_id logic without requiring FastAPI to be installed. |
|
||||
This verifies the backward compatibility fix works correctly. |
|
||||
""" |
|
||||
|
|
||||
import re |
|
||||
from typing import TYPE_CHECKING |
|
||||
|
|
||||
if TYPE_CHECKING: |
|
||||
from fastapi.routing import APIRoute |
|
||||
|
|
||||
# Simulated APIRoute for testing |
|
||||
class MockRoute: |
|
||||
def __init__(self, name: str, path_format: str, methods: set[str]): |
|
||||
self.name = name |
|
||||
self.path_format = path_format |
|
||||
self.methods = methods |
|
||||
|
|
||||
def generate_unique_id(route: "MockRoute", method: str | None = None) -> str: |
|
||||
"""The fixed implementation we're testing.""" |
|
||||
operation_id = f"{route.name}{route.path_format}" |
|
||||
operation_id = re.sub(r"\W", "_", operation_id) |
|
||||
assert route.methods |
|
||||
if method: |
|
||||
# Include the specific method being generated |
|
||||
operation_id = f"{operation_id}_{method.lower()}" |
|
||||
else: |
|
||||
# When no specific method is provided, use the first method for backwards compatibility |
|
||||
operation_id = f"{operation_id}_{list(route.methods)[0].lower()}" |
|
||||
return operation_id |
|
||||
|
|
||||
# Test 1: Single method route (backward compatibility) |
|
||||
print("Test 1: Single method route") |
|
||||
route1 = MockRoute(name="get_text", path_format="/text", methods={"GET"}) |
|
||||
op_id = generate_unique_id(route1) # No method param |
|
||||
print(f" Without method param: {op_id}") |
|
||||
assert op_id == "get_text_text_get", f"Expected 'get_text_text_get', got '{op_id}'" |
|
||||
print(" ✓ PASS: Backward compatibility preserved") |
|
||||
|
|
||||
# Test 2: Multi-method route without parameter (route creation) |
|
||||
print("\nTest 2: Multi-method route - route creation (no method param)") |
|
||||
route2 = MockRoute(name="handle_items", path_format="/items/", methods={"GET", "POST", "DELETE"}) |
|
||||
op_id = generate_unique_id(route2) # No method param - should use first method |
|
||||
print(f" Without method param: {op_id}") |
|
||||
# Should use the FIRST method from the set (deterministic for sets with single element in this case) |
|
||||
# But sets are unordered, so let's check it uses ONE method |
|
||||
assert "_get" in op_id or "_post" in op_id or "_delete" in op_id, f"Expected one method suffix, got '{op_id}'" |
|
||||
print(f" ✓ PASS: Uses single method suffix (backward compatible)") |
|
||||
|
|
||||
# Test 3: Multi-method route with specific method (OpenAPI generation) |
|
||||
print("\nTest 3: Multi-method route - OpenAPI generation (with method param)") |
|
||||
route3 = MockRoute(name="handle_items", path_format="/items/", methods={"GET", "POST", "DELETE"}) |
|
||||
op_id_get = generate_unique_id(route3, method="GET") |
|
||||
op_id_post = generate_unique_id(route3, method="POST") |
|
||||
op_id_delete = generate_unique_id(route3, method="DELETE") |
|
||||
print(f" GET: {op_id_get}") |
|
||||
print(f" POST: {op_id_post}") |
|
||||
print(f" DELETE: {op_id_delete}") |
|
||||
|
|
||||
assert op_id_get == "handle_items_items__get", f"Expected 'handle_items_items__get', got '{op_id_get}'" |
|
||||
assert op_id_post == "handle_items_items__post", f"Expected 'handle_items_items__post', got '{op_id_post}'" |
|
||||
assert op_id_delete == "handle_items_items__delete", f"Expected 'handle_items_items__delete', got '{op_id_delete}'" |
|
||||
|
|
||||
# Verify all are unique |
|
||||
assert len({op_id_get, op_id_post, op_id_delete}) == 3, "Operation IDs are not unique!" |
|
||||
print(f" ✓ PASS: All operation IDs are unique per method") |
|
||||
|
|
||||
# Test 4: Verify original behavior for path with special characters |
|
||||
print("\nTest 4: Path with special characters") |
|
||||
route4 = MockRoute(name="get_id_path", path_format="/path/{item_id}", methods={"GET"}) |
|
||||
op_id = generate_unique_id(route4) |
|
||||
print(f" Operation ID: {op_id}") |
|
||||
assert op_id == "get_id_path_path__item_id__get", f"Expected 'get_id_path_path__item_id__get', got '{op_id}'" |
|
||||
print(f" ✓ PASS: Special characters handled correctly") |
|
||||
|
|
||||
print("\n" + "="*60) |
|
||||
print("✅ ALL TESTS PASSED - Fix is correct!") |
|
||||
print("="*60) |
|
||||
print("\nSummary:") |
|
||||
print("- Backward compatibility preserved: Single methods work as before") |
|
||||
print("- Fix implemented: Multi-method routes generate unique IDs per method") |
|
||||
print("- Operation ID formats match expected test patterns") |
|
||||
Loading…
Reference in new issue