Claude Code Claude Opus 4.6 commited on
Commit
3923b92
·
1 Parent(s): 1485017

Claude Code: Fix import structure - decouple error_handlers from app

Browse files

- Remove module-level sys.path manipulation from error_handlers.py
- Add register_error_handlers(app) function for explicit handler registration
- Move sys.path setup to app.py where it belongs
- This eliminates potential circular import issues

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

Files changed (2) hide show
  1. app.py +31 -13
  2. error_handlers.py +19 -20
app.py CHANGED
@@ -15,20 +15,39 @@ import uuid
15
  import logging
16
  from datetime import datetime
17
  from enum import Enum
 
 
 
 
 
18
  from fastapi import FastAPI, HTTPException, BackgroundTasks, WebSocket, WebSocketDisconnect, Request
19
  from fastapi.responses import JSONResponse, FileResponse
20
  from fastapi.staticfiles import StaticFiles
21
  from fastapi.middleware import Middleware
22
  from starlette.middleware.base import BaseHTTPMiddleware
23
- from pathlib import Path
24
- from typing import Any, Optional
25
- from contextlib import asynccontextmanager
26
- import uvicorn
27
- from error_handlers import (
28
- http_exception_handler,
29
- value_error_handler,
30
- generic_exception_handler,
31
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
  # ============================================================================
34
  # CONFIGURATION & LOGGING
@@ -744,10 +763,9 @@ app = FastAPI(
744
  lifespan=lifespan
745
  )
746
 
747
- # Register exception handlers
748
- app.add_exception_handler(HTTPException, http_exception_handler)
749
- app.add_exception_handler(ValueError, value_error_handler)
750
- app.add_exception_handler(Exception, generic_exception_handler)
751
 
752
  # Add request logging middleware
753
  app.add_middleware(RequestLoggingMiddleware)
 
15
  import logging
16
  from datetime import datetime
17
  from enum import Enum
18
+ from pathlib import Path
19
+ from typing import Any, Optional
20
+ from contextlib import asynccontextmanager
21
+
22
+ import uvicorn
23
  from fastapi import FastAPI, HTTPException, BackgroundTasks, WebSocket, WebSocketDisconnect, Request
24
  from fastapi.responses import JSONResponse, FileResponse
25
  from fastapi.staticfiles import StaticFiles
26
  from fastapi.middleware import Middleware
27
  from starlette.middleware.base import BaseHTTPMiddleware
28
+
29
+ # ============================================================================
30
+ # SYS.PATH SETUP (must happen before other imports)
31
+ # ============================================================================
32
+
33
+ # Set up sys.path for agents imports at module load time
34
+ # This ensures `from agents import brain_minimal` works regardless of import order
35
+ # Dynamic path resolution with fallbacks for different Docker contexts
36
+ _script_dir = Path(os.path.abspath(os.path.dirname(__file__))) # Absolute path of this script
37
+
38
+ # Try multiple possible locations for .openclaw directory
39
+ _possible_openclaw_paths = [
40
+ _script_dir / ".openclaw", # /app/.openclaw (legacy/flat structure)
41
+ _script_dir / "openclaw" / ".openclaw", # /app/openclaw/.openclaw (nested structure)
42
+ Path("/app/openclaw/.openclaw"), # Absolute Docker path (nested)
43
+ Path("/app/.openclaw"), # Absolute Docker path (flat)
44
+ ]
45
+
46
+ # Add all valid paths to sys.path
47
+ for path_dir in _possible_openclaw_paths:
48
+ path_str = str(path_dir)
49
+ if path_str not in sys.path and path_dir.exists():
50
+ sys.path.insert(0, path_str)
51
 
52
  # ============================================================================
53
  # CONFIGURATION & LOGGING
 
763
  lifespan=lifespan
764
  )
765
 
766
+ # Register exception handlers (import here to avoid circular dependency)
767
+ from error_handlers import register_error_handlers
768
+ register_error_handlers(app)
 
769
 
770
  # Add request logging middleware
771
  app.add_middleware(RequestLoggingMiddleware)
error_handlers.py CHANGED
@@ -2,6 +2,9 @@
2
  """
3
  Error handling utilities for HuggingClaw - Cain.
4
  Provides specific exception handlers for common operations.
 
 
 
5
  """
6
  import json
7
  import os
@@ -11,7 +14,7 @@ import traceback
11
  from datetime import datetime
12
  from pathlib import Path
13
  from typing import Dict, Any, Optional
14
- from fastapi import HTTPException, Request
15
  from fastapi.responses import JSONResponse
16
 
17
  # Dedicated error logger for exception tracking
@@ -31,25 +34,6 @@ error_logger = logging.getLogger("cain.errors")
31
  error_logger.setLevel(logging.ERROR)
32
  error_logger.addHandler(error_handler)
33
 
34
- # CRITICAL: Set up sys.path for agents imports at module load time
35
- # This ensures `from agents import brain_minimal` works regardless of import order
36
- # Dynamic path resolution with fallbacks for different Docker contexts
37
- _script_dir = Path(os.path.abspath(os.path.dirname(__file__))) # Absolute path of this script
38
-
39
- # Try multiple possible locations for .openclaw directory
40
- _possible_openclaw_paths = [
41
- _script_dir / ".openclaw", # /app/.openclaw (legacy/flat structure)
42
- _script_dir / "openclaw" / ".openclaw", # /app/openclaw/.openclaw (nested structure)
43
- Path("/app/openclaw/.openclaw"), # Absolute Docker path (nested)
44
- Path("/app/.openclaw"), # Absolute Docker path (flat)
45
- ]
46
-
47
- # Add all valid paths to sys.path
48
- for path_dir in _possible_openclaw_paths:
49
- path_str = str(path_dir)
50
- if path_str not in sys.path and path_dir.exists():
51
- sys.path.insert(0, path_str)
52
-
53
 
54
  def log_exception(exc: Exception, request: Request = None) -> None:
55
  """
@@ -378,3 +362,18 @@ def write_cain_status(status_data: Dict[str, Any]) -> bool:
378
  except (PermissionError, OSError, json.JSONDecodeError) as e:
379
  print(f"Error writing status file: {e}")
380
  return False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  """
3
  Error handling utilities for HuggingClaw - Cain.
4
  Provides specific exception handlers for common operations.
5
+
6
+ NOTE: This module is intentionally decoupled from app.py to avoid circular imports.
7
+ Exception handlers are registered via register_error_handlers(app) function.
8
  """
9
  import json
10
  import os
 
14
  from datetime import datetime
15
  from pathlib import Path
16
  from typing import Dict, Any, Optional
17
+ from fastapi import FastAPI, HTTPException, Request
18
  from fastapi.responses import JSONResponse
19
 
20
  # Dedicated error logger for exception tracking
 
34
  error_logger.setLevel(logging.ERROR)
35
  error_logger.addHandler(error_handler)
36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
 
38
  def log_exception(exc: Exception, request: Request = None) -> None:
39
  """
 
362
  except (PermissionError, OSError, json.JSONDecodeError) as e:
363
  print(f"Error writing status file: {e}")
364
  return False
365
+
366
+
367
+ def register_error_handlers(app: FastAPI) -> None:
368
+ """
369
+ Register exception handlers with the FastAPI app.
370
+
371
+ This function-based registration avoids circular imports by not importing
372
+ app at module level. Call this after creating the FastAPI app instance.
373
+
374
+ Args:
375
+ app: The FastAPI application instance.
376
+ """
377
+ app.add_exception_handler(HTTPException, http_exception_handler)
378
+ app.add_exception_handler(ValueError, value_error_handler)
379
+ app.add_exception_handler(Exception, generic_exception_handler)