1+ import json
12from typing import List , Optional
23
34import tiled .client
45import tiled .server .app
56import typer
6-
7- from tiled .utils import import_object
87from rich .progress import Progress
9-
8+ from tiled .utils import import_object
9+ from typing_extensions import Annotated
1010
1111cli_app = typer .Typer ()
1212admin_app = typer .Typer ()
1717)
1818
1919
20+ def parse_dict_arg (arg ):
21+ """
22+ Parse a string like '{"key1": "value1", "key2": 2}' into a dictionary.
23+
24+ Returns:
25+ dict: The parsed dictionary or an empty dict if arg is None or empty.
26+ """
27+ if arg is None or arg .strip () == '' :
28+ return {}
29+
30+ try :
31+ result = json .loads (arg )
32+ if isinstance (result , dict ):
33+ return result
34+ else :
35+ raise ValueError ("Parsed value is not a dictionary." )
36+ except json .JSONDecodeError as e :
37+ raise ValueError (f"Invalid JSON string: { arg } " ) from e
38+
39+
2040@admin_app .command ("shape-fixer" )
2141def shape_fix (
2242 uri : str ,
@@ -29,6 +49,7 @@ def shape_fix(
2949 handler : Optional [List [str ]] = typer .Option (
3050 None , help = "Handler given as 'SPEC = import_path'"
3151 ),
52+ root_map : Annotated [Optional [dict ], typer .Option (parser = parse_dict_arg )] = None ,
3253):
3354 """
3455 Fix shape metadata in Event Descriptors.
@@ -67,6 +88,10 @@ def shape_fix(
6788 typer .echo (f"Limited to first { limit } BlueskyRuns only" )
6889 items = items [:limit ]
6990
91+ root_map = root_map if root_map is not None else {}
92+ root_map = getattr (adapter , "root_map" , {}) | root_map
93+ typer .echo (f"Using root map: { root_map } " )
94+
7095 app = tiled .server .app .build_app (adapter )
7196 with tiled .client .Context .from_app (app ) as context :
7297 tiled_client = tiled .client .from_context (context )
@@ -81,7 +106,7 @@ def shape_fix(
81106 mds_database ,
82107 asset_database ,
83108 descriptor ,
84- adapter . root_map ,
109+ root_map ,
85110 handler_registry ,
86111 patch_resource = patch_resource ,
87112 )
0 commit comments