66
77
88ADAPTERS = {}
9+ NOT_THERE = (None , None , None )
910
1011
1112def register_adapter (from_version ):
@@ -49,7 +50,51 @@ def is_type_specifier(json_dict):
4950 return key [0 ] == key [0 ].upper ()
5051
5152
52- def rename_parameter (config , old_path , new_path ):
53+ def find_parameter (config , path_str ):
54+ # Recursively find path elements, skipping into type specifiers.
55+ # Return the value and its container so the value can be deleted.
56+
57+ path = path_str .split ("." )
58+ value = config
59+ container = None
60+ for segment in path :
61+ while is_type_specifier (value ):
62+ container , value = value , next (iter (value .values ()))
63+ if segment not in value :
64+ return NOT_THERE
65+ container , value = value , value [segment ]
66+ return path [- 1 ], container , value
67+
68+
69+ def _create_path (config , path ):
70+ # Recursively find path elements, skipping into type specifiers.
71+ # If any container isn't there, create a new empty object for it.
72+ # This will only be created if the
73+ value = config
74+ for segment in path :
75+ while is_type_specifier (value ):
76+ value = next (iter (value .values ()))
77+ if segment not in value :
78+ value [segment ] = {}
79+ value = value [segment ]
80+ while is_type_specifier (value ):
81+ value = next (iter (value .values ()))
82+ return value
83+
84+
85+ def create_parameter (config , path_str , value ):
86+ * path , param = path_str .split ("." )
87+ new_container = _create_path (config , path )
88+ new_container [param ] = value
89+
90+
91+ def delete_parameter (config , path_str ):
92+ param_name , container , _ = find_parameter (config , path_str )
93+ if container :
94+ container .pop (param_name , None )
95+
96+
97+ def rename_parameter (config , old_path , new_path , transform = lambda x : x ):
5398 """A powerful tool for writing config adapters, this allows you to specify
5499 a JSON-style path for an old and new config parameter. For instance
55100
@@ -60,47 +105,13 @@ def rename_parameter(config, old_path, new_path):
60105 set it in task.trainer.num_batches_per_epoch instead, creating trainer as an empty
61106 dictionary if necessary."""
62107
63- old_path = old_path .split ("." )
64- new_path = new_path .split ("." )
65-
66- NOT_THERE = object ()
67-
68- def find_path (config , path ):
69- # Recursively find path elements, skipping into type specifiers.
70- # Return the value and its container so the value can be deleted.
71- value = config
72- container = None
73- for segment in path :
74- while is_type_specifier (value ):
75- container , value = value , next (iter (value .values ()))
76- if segment not in value :
77- return NOT_THERE
78- container , value = value , value [segment ]
79- return container , value
80-
81- def create_path (config , path ):
82- # Recursively find path elements, skipping into type specifiers.
83- # If any container isn't there, create a new empty object for it.
84- # This will only be created if the
85- value = config
86- for segment in path :
87- while is_type_specifier (value ):
88- value = next (iter (value .values ()))
89- if segment not in value :
90- value [segment ] = {}
91- value = value [segment ]
92- while is_type_specifier (value ):
93- value = next (iter (value .values ()))
94- return value
95-
96- found = find_path (config , old_path )
108+ found = find_parameter (config , old_path )
97109 if found is not NOT_THERE :
98- container , old_value = found
110+ param_name , container , old_value = found
99111 # Delete old value
100- container .pop (old_path [ - 1 ] )
112+ container .pop (param_name )
101113 # Update new value
102- new_container = create_path (config , new_path [:- 1 ])
103- new_container [new_path [- 1 ]] = old_value
114+ create_parameter (config , new_path , transform (old_value ))
104115
105116 return config
106117
0 commit comments