11import json
22import logging
33import sys
4- from datetime import datetime
4+ from datetime import date , datetime
5+ from decimal import Decimal
56from enum import Enum
67from functools import wraps
78from importlib .metadata import version as importlib_version
89from typing import Any , Union
10+ from uuid import UUID
911
1012import typer
1113from groundlight_openapi_client .model_utils import OpenApiModel
1517from groundlight import ExperimentalApi , Groundlight
1618from groundlight .client import ApiTokenError
1719
18- logger = logging .getLogger ("groundlight.sdk" )
20+ logger = logging .getLogger (__name__ )
1921
2022cli_app = typer .Typer (
2123 context_settings = {"help_option_names" : ["-h" , "--help" ], "max_content_width" : 800 },
@@ -40,7 +42,6 @@ def _main(
4042 context_settings = {"help_option_names" : ["-h" , "--help" ], "max_content_width" : 800 },
4143)
4244cli_app .add_typer (experimental_app , name = "exp" , rich_help_panel = "Subcommands" )
43- cli_app .add_typer (experimental_app , name = "experimental" , hidden = True )
4445
4546
4647def is_cli_supported_type (annotation ):
@@ -67,10 +68,20 @@ def is_cli_representable(annotation) -> bool:
6768
6869
6970def _json_default (obj : Any ) -> Any :
70- """Fallback serializer for json.dumps — handles datetime values."""
71- if isinstance (obj , datetime ):
71+ """Fallback serializer for json.dumps for types the stdlib encoder doesn't handle.
72+
73+ Covers common types that appear in OpenAPI client to_dict() output. Unknown types
74+ fall back to str() rather than raising, so CLI output is always usable.
75+ """
76+ if isinstance (obj , (datetime , date )):
7277 return obj .isoformat ()
73- raise TypeError (f"Object of type { type (obj ).__name__ } is not JSON serializable" )
78+ if isinstance (obj , Decimal ):
79+ return float (obj )
80+ if isinstance (obj , UUID ):
81+ return str (obj )
82+ if isinstance (obj , Enum ):
83+ return obj .value
84+ return str (obj )
7485
7586
7687def _format_result (result : Any ) -> str :
@@ -178,6 +189,7 @@ def wrapper(*args, **kwargs):
178189 "ML Pipelines & Priming" ,
179190 "Notes" ,
180191 "Utilities" ,
192+ "Other" ,
181193]
182194
183195# Maps method names to their rich_help_panel group label for the CLI help output.
@@ -256,14 +268,14 @@ def groundlight():
256268 for name , method in sorted (vars (Groundlight ).items (), key = _cli_sort_key ):
257269 if callable (method ) and not name .startswith ("_" ) and name not in _CLI_EXCLUDED_METHODS :
258270 cli_func = class_func_to_cli (method )
259- cli_app .command (rich_help_panel = _COMMAND_GROUPS .get (name ))(cli_func )
271+ cli_app .command (rich_help_panel = _COMMAND_GROUPS .get (name , "Other" ))(cli_func )
260272
261273 for name , method in sorted (vars (ExperimentalApi ).items (), key = _cli_sort_key ):
262274 if not callable (method ) or name .startswith ("_" ) or name in stable_names or name in _CLI_EXCLUDED_METHODS :
263275 continue
264276 try :
265277 cli_func = class_func_to_cli (method , is_experimental = True )
266- experimental_app .command (rich_help_panel = _COMMAND_GROUPS .get (name ))(cli_func )
278+ experimental_app .command (rich_help_panel = _COMMAND_GROUPS .get (name , "Other" ))(cli_func )
267279 except Exception as e : # pylint: disable=broad-except
268280 logger .debug ("Skipping experimental CLI command '%s': %s" , name , e )
269281
0 commit comments