|
12 | 12 |
|
13 | 13 | logger = logging.getLogger(__name__) |
14 | 14 |
|
15 | | -def handle_cli_exceptions(func): |
| 15 | +def handle_cli_exceptions(resource_type=None, operation_type=None): |
16 | 16 | """ |
17 | | - Smart decorator that automatically detects resource/operation types and applies |
18 | | - enhanced 404 handling. Eliminates repetitive exception handling across CLI commands. |
| 17 | + Decorator that applies enhanced 404 handling with explicit resource/operation types. |
| 18 | + Eliminates repetitive exception handling across CLI commands. |
19 | 19 | |
20 | 20 | This decorator: |
21 | | - 1. Auto-detects resource type from command name (hyp-jumpstart-endpoint, etc.) |
22 | | - 2. Auto-detects operation type from function name (delete, describe, etc.) |
23 | | - 3. Applies enhanced 404 handling with contextual messages |
24 | | - 4. Handles all other exceptions consistently |
| 21 | + 1. Uses explicit resource_type and operation_type parameters |
| 22 | + 2. Applies enhanced 404 handling with contextual messages |
| 23 | + 3. Handles all other exceptions consistently |
25 | 24 | |
26 | 25 | Usage: |
27 | | - @handle_cli_exceptions |
| 26 | + @handle_cli_exceptions( |
| 27 | + resource_type=ResourceType.HYP_JUMPSTART_ENDPOINT, |
| 28 | + operation_type=OperationType.DELETE |
| 29 | + ) |
28 | 30 | @click.command("hyp-jumpstart-endpoint") |
29 | 31 | def js_delete(name, namespace): |
30 | 32 | # Command logic here - no try/catch needed! |
31 | 33 | pass |
32 | 34 | """ |
33 | | - @functools.wraps(func) |
34 | | - def wrapper(*args, **kwargs): |
35 | | - try: |
36 | | - return func(*args, **kwargs) |
37 | | - except Exception as e: |
38 | | - # Check if this is a 404 error that can benefit from enhanced handling |
39 | | - if isinstance(e, ApiException) and e.status == 404: |
40 | | - # Auto-detect resource and operation types |
41 | | - resource_type = _detect_resource_type(func) |
42 | | - operation_type = _detect_operation_type(func) |
| 35 | + def decorator(func): |
| 36 | + @functools.wraps(func) |
| 37 | + def wrapper(*args, **kwargs): |
| 38 | + try: |
| 39 | + return func(*args, **kwargs) |
| 40 | + except Exception as e: |
| 41 | + # Check if this is a 404 error that can benefit from enhanced handling |
| 42 | + if isinstance(e, ApiException) and e.status == 404: |
| 43 | + # Extract name and namespace from kwargs if available |
| 44 | + name = kwargs.get('name', 'unknown') |
| 45 | + namespace = kwargs.get('namespace', 'default') |
| 46 | + |
| 47 | + if resource_type and operation_type: |
| 48 | + try: |
| 49 | + handle_404(name, namespace, resource_type, operation_type) |
| 50 | + except Exception as enhanced_error: |
| 51 | + click.echo(str(enhanced_error)) |
| 52 | + sys.exit(1) |
43 | 53 |
|
44 | | - # Extract name and namespace from kwargs if available |
45 | | - name = kwargs.get('name', 'unknown') |
46 | | - namespace = kwargs.get('namespace', 'default') |
47 | | - |
48 | | - if resource_type and operation_type: |
49 | | - try: |
50 | | - handle_404(name, namespace, resource_type, operation_type) |
51 | | - except Exception as enhanced_error: |
52 | | - click.echo(str(enhanced_error)) |
53 | | - sys.exit(1) |
54 | | - |
55 | | - # For non-404 errors or when auto-detection fails, use standard handling |
56 | | - logger.debug(f"CLI command failed: {func.__name__}", exc_info=True) |
57 | | - click.echo(str(e)) |
58 | | - sys.exit(1) |
59 | | - |
60 | | - return wrapper |
61 | | - |
62 | | - |
63 | | -def _detect_resource_type(func) -> ResourceType: |
64 | | - """ |
65 | | - Auto-detect resource type from function name or click command name. |
66 | | - |
67 | | - Args: |
68 | | - func: The decorated function |
69 | | - |
70 | | - Returns: |
71 | | - ResourceType enum or None if not detected |
72 | | - """ |
73 | | - # First try to get the Click command name from the decorator |
74 | | - try: |
75 | | - if hasattr(func, 'name') and func.name and isinstance(func.name, str): |
76 | | - command_name = func.name.lower() |
77 | | - if 'jumpstart' in command_name: |
78 | | - return ResourceType.HYP_JUMPSTART_ENDPOINT |
79 | | - elif 'custom' in command_name: |
80 | | - return ResourceType.HYP_CUSTOM_ENDPOINT |
81 | | - elif 'pytorch' in command_name: |
82 | | - return ResourceType.HYP_PYTORCH_JOB |
83 | | - except (AttributeError, TypeError): |
84 | | - pass |
85 | | - |
86 | | - # Fallback to function name detection |
87 | | - try: |
88 | | - func_name = func.__name__.lower() |
89 | | - |
90 | | - # Function name patterns |
91 | | - if 'js_' in func_name or 'jumpstart' in func_name: |
92 | | - return ResourceType.HYP_JUMPSTART_ENDPOINT |
93 | | - elif 'custom' in func_name: |
94 | | - return ResourceType.HYP_CUSTOM_ENDPOINT |
95 | | - elif 'pytorch' in func_name or 'training' in func_name: |
96 | | - return ResourceType.HYP_PYTORCH_JOB |
97 | | - |
98 | | - except (AttributeError, TypeError): |
99 | | - pass |
100 | | - |
101 | | - return None |
102 | | - |
103 | | - |
104 | | -def _detect_operation_type(func) -> OperationType: |
105 | | - """ |
106 | | - Auto-detect operation type from function name. |
107 | | - |
108 | | - Args: |
109 | | - func: The decorated function |
110 | | - |
111 | | - Returns: |
112 | | - OperationType enum or None if not detected |
113 | | - """ |
114 | | - try: |
115 | | - func_name = func.__name__.lower() |
116 | | - |
117 | | - if 'delete' in func_name: |
118 | | - return OperationType.DELETE |
119 | | - elif 'describe' in func_name or 'get' in func_name: |
120 | | - return OperationType.DESCRIBE |
121 | | - elif 'list' in func_name: |
122 | | - return OperationType.LIST |
123 | | - |
124 | | - return OperationType.GET # Default fallback |
| 54 | + # For non-404 errors or when parameters not provided, use standard handling |
| 55 | + logger.debug(f"CLI command failed: {func.__name__}", exc_info=True) |
| 56 | + click.echo(str(e)) |
| 57 | + sys.exit(1) |
125 | 58 |
|
126 | | - except (AttributeError, TypeError, Exception): |
127 | | - # Handle any exceptions during detection gracefully |
128 | | - return OperationType.GET # Default fallback |
| 59 | + return wrapper |
| 60 | + return decorator |
0 commit comments