Skip to content

confingy.fingy#

fingy #

Functions for transforming fingys, which are any python object that can be serialized/deserialized by confingy. This includes any class wrapped with confingy.track or confingy.lazy, as well as dataclasses and built-in types.

serialize_fingy #

serialize_fingy(fingy: Any) -> dict[str, Any]

Serialize a fingy to a JSON-compatible dictionary.

Parameters:

Name Type Description Default
fingy Any

The object to serialize

required

Returns:

Type Description
dict[str, Any]

A dictionary that can be saved to JSON

Source code in src/confingy/fingy.py
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
def serialize_fingy(fingy: Any) -> dict[str, Any]:
    """
    Serialize a fingy to a JSON-compatible dictionary.

    Args:
        fingy: The object to serialize

    Returns:
        A dictionary that can be saved to JSON
    """
    context = SerializationContext()

    # Register handlers using the central registry
    for handler in HandlerRegistry.get_default_handlers():
        context.register_handler(handler)

    result = context.serialize(fingy)
    return result if result is not None else {}

deserialize_fingy #

deserialize_fingy(
    data: dict[str, Any],
    expected_type: Optional[type] = None,
    strict: bool = True,
) -> Any

Deserialize a dictionary back to a fingy.

Parameters:

Name Type Description Default
data dict[str, Any]

The dictionary to deserialize

required
expected_type Optional[type]

Optional type hint for the expected result

None
strict bool

If True (default), raise an error when serialized configs contain kwargs that no longer exist in the class signature. If False, emit a warning and ignore the extra kwargs. Similar to PyTorch's load_state_dict strict parameter.

True

Returns:

Type Description
Any

The reconstructed object

Source code in src/confingy/fingy.py
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
def deserialize_fingy(
    data: dict[str, Any],
    expected_type: Optional[type] = None,
    strict: bool = True,
) -> Any:
    """
    Deserialize a dictionary back to a fingy.

    Args:
        data: The dictionary to deserialize
        expected_type: Optional type hint for the expected result
        strict: If True (default), raise an error when serialized configs contain
            kwargs that no longer exist in the class signature. If False, emit
            a warning and ignore the extra kwargs. Similar to PyTorch's
            load_state_dict strict parameter.

    Returns:
        The reconstructed object
    """
    context = DeserializationContext(strict=strict)

    # Register all handlers using the central registry
    for handler in HandlerRegistry.get_default_handlers():
        context.register_handler(handler)

    return context.deserialize(data, expected_type)

save_fingy #

save_fingy(fingy: Any, filename: str) -> None

Save a fingy to a JSON file.

Parameters:

Name Type Description Default
fingy Any

The fingy object to save

required
filename str

Path to the output file

required
Source code in src/confingy/fingy.py
72
73
74
75
76
77
78
79
80
81
82
83
84
def save_fingy(fingy: Any, filename: str) -> None:
    """
    Save a fingy to a JSON file.

    Args:
        fingy: The fingy object to save
        filename: Path to the output file
    """
    logger.debug(f"Saving fingy to {filename}")
    serialized = serialize_fingy(fingy)

    with open(filename, "w") as f:
        json.dump(serialized, f, indent=2, sort_keys=True)

load_fingy #

load_fingy(filename: str, strict: bool = True) -> Any

Load and deserialize a fingy from a JSON file.

Parameters:

Name Type Description Default
filename str

Path to the JSON file

required
strict bool

If True (default), raise an error when serialized configs contain kwargs that no longer exist in the class signature. If False, emit a warning and ignore the extra kwargs.

True

Returns:

Type Description
Any

The deserialized fingy object (may contain lazy instances)

Source code in src/confingy/fingy.py
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
def load_fingy(filename: str, strict: bool = True) -> Any:
    """
    Load and deserialize a fingy from a JSON file.

    Args:
        filename: Path to the JSON file
        strict: If True (default), raise an error when serialized configs contain
            kwargs that no longer exist in the class signature. If False, emit
            a warning and ignore the extra kwargs.

    Returns:
        The deserialized fingy object (may contain lazy instances)
    """
    logger.debug(f"Loading fingy from {filename}")

    with open(filename) as f:
        data = json.load(f)

    return deserialize_fingy(data, strict=strict)

prettify_fingy #

prettify_fingy(fingy: Any) -> dict[str, Any]

Prettify a fingy object.

This function serializes a fingy object and then transforms it into a more readable format by collapsing _confingy_* metadata fields into a simple string representation of the form {module}.{class} and preserving the actual field values.

Parameters:

Name Type Description Default
fingy Any

The fingy object to prettify

required

Returns:

Type Description
dict[str, Any]

A dictionary with collapsed metadata that's easier to read

Examples:

Input fingy object that serializes to:

{
    "_confingy_class": "TrainingConfig",
    "_confingy_module": "__main__",
    "_confingy_dataclass": true,
    "_confingy_fields": {
        "dataset": {
            "_confingy_class": "MyDataset",
            "_confingy_module": "__main__",
            "_confingy_init": {
                "size": 100
            }
        }
    }
}

Output:

{
    "__main__.TrainingConfig": {
        "dataset": {
            "__main__.MyDataset": {
                "size": 100
            }
        }
    }
}

Source code in src/confingy/fingy.py
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
def prettify_fingy(fingy: Any) -> dict[str, Any]:
    """
    Prettify a fingy object.

    This function serializes a fingy object and then transforms it into a more
    readable format by collapsing `_confingy_*` metadata fields into a simple string
    representation of the form `{module}.{class}` and preserving the actual field values.

    Args:
        fingy: The fingy object to prettify

    Returns:
        A dictionary with collapsed metadata that's easier to read

    Examples:
        Input fingy object that serializes to:
        ```json
        {
            "_confingy_class": "TrainingConfig",
            "_confingy_module": "__main__",
            "_confingy_dataclass": true,
            "_confingy_fields": {
                "dataset": {
                    "_confingy_class": "MyDataset",
                    "_confingy_module": "__main__",
                    "_confingy_init": {
                        "size": 100
                    }
                }
            }
        }
        ```

        Output:
        ```json
        {
            "__main__.TrainingConfig": {
                "dataset": {
                    "__main__.MyDataset": {
                        "size": 100
                    }
                }
            }
        }
        ```
    """
    serialized = serialize_fingy(fingy)
    return prettify_serialized_fingy(serialized)

prettify_serialized_fingy #

prettify_serialized_fingy(data: Any) -> Any

Transform confingy serialized data into a prettier format.

This function recursively processes serialized confingy data, collapsing metadata fields into readable string representations while preserving the actual content. See prettify_fingy for examples.

Parameters:

Name Type Description Default
data Any

The serialized data to transform

required

Returns:

Type Description
Any

Transformed data with collapsed metadata

Source code in src/confingy/fingy.py
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
def prettify_serialized_fingy(data: Any) -> Any:
    """
    Transform confingy serialized data into a prettier format.

    This function recursively processes serialized confingy data, collapsing metadata
    fields into readable string representations while preserving the actual content.
    See [prettify_fingy][confingy.fingy.prettify_fingy] for examples.

    Args:
        data: The serialized data to transform

    Returns:
        Transformed data with collapsed metadata
    """
    # Base cases
    if data is None or isinstance(data, int | float | str | bool):
        return data

    # Handle lists and tuples
    if isinstance(data, list | tuple):
        result = [prettify_serialized_fingy(item) for item in data]
        return tuple(result) if isinstance(data, tuple) else result

    # Handle dictionaries
    if isinstance(data, dict):
        # Check if this dictionary represents a confingy object
        if SerializationKeys.CLASS in data and SerializationKeys.MODULE in data:
            # This is a confingy object - collapse it
            class_name = data.get(SerializationKeys.CLASS)
            module_name = data.get(SerializationKeys.MODULE)

            # Special handling for type objects
            if class_name == "type" and SerializationKeys.NAME in data:
                return f"{module_name}.{data[SerializationKeys.NAME]}"

            # Special handling for enum members
            if data.get(SerializationKeys.ENUM):
                return f"{module_name}.{class_name}.{data[SerializationKeys.NAME]}"

            key = f"{module_name}.{class_name}"

            # Determine what the nested content should be
            if SerializationKeys.FIELDS in data:
                # Dataclass - use fields
                nested_content = prettify_serialized_fingy(
                    data[SerializationKeys.FIELDS]
                )
            elif SerializationKeys.INIT in data:
                # Tracked class - use init args
                nested_content = prettify_serialized_fingy(data[SerializationKeys.INIT])
            elif SerializationKeys.CONFIG in data:
                # Lazy object - use config
                nested_content = prettify_serialized_fingy(
                    data[SerializationKeys.CONFIG]
                )
            elif SerializationKeys.NAME in data:
                # Type or callable with qualified name
                return f"{module_name}.{data[SerializationKeys.NAME]}"
            elif SerializationKeys.UNSERIALIZABLE in data:
                # Unserializable object
                return data[SerializationKeys.UNSERIALIZABLE]
            elif data.get(SerializationKeys.CALLABLE) == "method":
                # Bound method
                obj = prettify_serialized_fingy(data.get(SerializationKeys.OBJECT, {}))
                method = data.get(SerializationKeys.METHOD, "unknown")
                if isinstance(obj, dict) and len(obj) == 1:
                    # If obj is a collapsed dict with single key, extract it
                    obj_key = next(iter(obj.keys()))
                    return f"{obj_key}.{method}"
                return f"{obj}.{method}"
            elif data.get(SerializationKeys.CALLABLE) == "function":
                # Function
                return f"{module_name}.{data.get(SerializationKeys.NAME, 'unknown')}"
            else:
                # Unknown structure, try to extract any meaningful content
                nested_content = {
                    k: prettify_serialized_fingy(v)
                    for k, v in data.items()
                    if not k.startswith("_confingy_")
                }
                if not nested_content:
                    # No non-metadata content
                    return key

            # Return the collapsed representation
            if isinstance(nested_content, dict) and nested_content or nested_content:
                return {key: nested_content}
            else:
                return key
        else:
            # Regular dictionary - recursively process values
            return {k: prettify_serialized_fingy(v) for k, v in data.items()}

    # For any other type, return as-is
    return data

transpile_fingy #

transpile_fingy(
    fingy_data: dict[str, Any] | str | Path,
) -> str

Transpile a serialized fingy back into Python code.

Parameters:

Name Type Description Default
fingy_data dict[str, Any] | str | Path

Either a dictionary of serialized confingy fingy data, a JSON string, or a path to a JSON file

required

Returns:

Type Description
str

Python code as a string

Examples:

from confingy import serialize_fingy, transpile_fingy
config = MyConfig(...)
serialized = serialize_fingy(config)
python_code = transpile_fingy(serialized)
print(python_code)
Source code in src/confingy/fingy.py
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
def transpile_fingy(fingy_data: dict[str, Any] | str | Path) -> str:
    """
    Transpile a serialized fingy back into Python code.

    Args:
        fingy_data: Either a dictionary of serialized confingy fingy data,
                    a JSON string, or a path to a JSON file

    Returns:
        Python code as a string

    Examples:
        ```python
        from confingy import serialize_fingy, transpile_fingy
        config = MyConfig(...)
        serialized = serialize_fingy(config)
        python_code = transpile_fingy(serialized)
        print(python_code)
        ```
    """
    transpiler = _ConfingyTranspiler()
    return transpiler.transpile(fingy_data)