Skip to content

Base model behavior

All qcdata models inherit a computed, read-only qcdata_version containing the installed package version. It is included in default dumps and saves, even with exclude_unset=True, and appears on each serialized nested model. It is omitted from the usual representation to keep scientific values readable.

On loading, a saved stamp is accepted and discarded; serialization supplies the current version. This identifies the last writer of the representation, not the original creator, a minimum reader version, or a formal schema version. Reading a stamped file does not guarantee that an older or newer package can interpret it. Files without a stamp are accepted normally.

JSON, YAML, and TOML preserve this metadata. Structure XYZ exports include it as a comment token. External QCSchema conversions exclude it from model and identifier fields.

Mutation and persistence

Attribute assignment is frozen, but nested dictionaries, lists, and arrays are not deeply immutable. Direct container mutation is unsupported. Use model_dump(), edit the returned built-in values, and reconstruct with model_validate() so validation runs again. Scientific array fields dump as independent lists. Arbitrary custom objects in extras are not covered by this independence guarantee. File-collection helpers and Structure.add_identifiers() remain explicit mutation exceptions.

save() defaults to exclude_unset=True for compact files. Fields omitted during construction are excluded; explicitly supplied values are retained even when equal to their defaults. Computed version stamps remain included. Pass exclude_unset=False to include unset/default-valued fields. exclude_none=True remains the default.

Supported file and identifier helpers mark changed fields as set so those changes are saved. Direct mutation of initially unset containers is unsupported and may be omitted. The dump/edit/validate workflow preserves edits, but reconstructing from a full dump makes its fields explicitly set and can produce larger files.

qcdata.models.base_models.QCDataBaseModel

Base model for all QCData objects.

Attributes:

Name Type Description
qcdata_version str

Installed qcdata version writing this representation. Automatically refreshed on serialization; not a schema version.

extras dict[str, Any]

Additional information to bundle with the object. Use for schema development and scratch space.

qcdata_version property

qcdata_version: str

The package version serializing the object, not its original creator.

open classmethod

open(filepath: Path | str) -> Self

Instantiate an object from data saved to disk.

Parameters:

Name Type Description Default
filepath Path | str

The path to the object on disk.

required

Returns:

Type Description
Self

The instantiated object.

Example
my_obj = MyModel.open("path/to/file.json")
Source code in src/qcdata/models/base_models.py
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
@classmethod
def open(cls, filepath: Path | str) -> Self:
    """Instantiate an object from data saved to disk.

    Args:
        filepath: The path to the object on disk.

    Returns:
        The instantiated object.

    Example:
        ```python
        my_obj = MyModel.open("path/to/file.json")
        ```
    """
    filepath = Path(filepath)
    data = filepath.read_text()

    if filepath.suffix in [".yaml", ".yml"]:
        return cls.model_validate(yaml.safe_load(data))
    elif filepath.suffix == ".toml":
        return cls.model_validate(toml.loads(data))

    # Assume json for all other file extensions
    return cls.model_validate_json(data)

open_multi classmethod

open_multi(filepath: Path | str) -> list[Self]

Instantiate a list of objects from data saved to disk.

Parameters:

Name Type Description Default
filepath Path | str

The path to the object on disk. Must be a list of objects.

required

Returns:

Type Description
list[Self]

A list of instantiated objects.

Example
my_objs = MyModel().open_multi("path/to/file.json")
Source code in src/qcdata/models/base_models.py
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
@classmethod
def open_multi(cls, filepath: Path | str) -> list[Self]:
    """Instantiate a list of objects from data saved to disk.

    Args:
        filepath: The path to the object on disk. Must be a list of objects.

    Returns:
        A list of instantiated objects.

    Example:
        ```python
        my_objs = MyModel().open_multi("path/to/file.json")
        ```
    """
    filepath = Path(filepath)
    data = filepath.read_text()

    if filepath.suffix in [".yaml", ".yml"]:
        return [cls.model_validate(d) for d in yaml.safe_load(data)]
    elif filepath.suffix == ".toml":
        return [cls.model_validate(d) for d in toml.loads(data)]

    # Assume json for all other file extensions
    return [cls.model_validate(d) for d in json.loads(data)]

save

save(
    filepath: Path | str,
    exclude_none: bool = True,
    exclude_unset: bool = True,
    indent: int = 4,
    **kwargs,
) -> None

Save an object to disk as json, yaml, or toml. Objects such as Structure and OptimizationData can additionally be saved as xyz files.

Note

By default the object will be saved as a json file. If the file extension is .yaml or .yml, the object will be saved as a yaml file. If the file extension is .toml, the object will be saved as a toml file. If the file extension is .xyz, the object will be saved as an xyz file (for objects that support this format such as a Structure or an OptimizationData which contains .trajectory: list[Structure]).

Additionally, padding will be added to the file by default to make it more human-readable. You can adjust the amount of padding added by changing the indent parameter. Pass indent=None to create a more compact file.

Parameters:

Name Type Description Default
filepath Path | str

The path to write the object to.

required
exclude_none bool

If True, attributes with a value of None will not be written. Changing default behavior from pydantic.model_dump() to True.

True
exclude_unset bool

If True, fields omitted during construction are excluded, even if their containers were later modified. Defaults to True for compact files; pass False to include unset/default-valued fields.

True
indent int

The number of spaces to use for indentation in the JSON file. 0 creates a more compact JSON file, 4 is more human-readable.

4
**kwargs

Additional keyword arguments to pass to the serialization method.

{}
Example
my_obj.save("path/to/file.json")
my_obj.save("path/to/file.yaml")
my_obj.save("path/to/file.toml")
my_obj.save("path/to/file.xyz")
Source code in src/qcdata/models/base_models.py
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
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
def save(
    self,
    filepath: Path | str,
    exclude_none: bool = True,
    exclude_unset: bool = True,
    indent: int = 4,
    **kwargs,
) -> None:
    """
    Save an object to disk as `json`, `yaml`, or `toml`. Objects such as `Structure`
    and `OptimizationData` can additionally be saved as `xyz` files.

    Note:
        By default the object will be saved as a `json` file. If the file extension
        is `.yaml` or `.yml`, the object will be saved as a `yaml` file. If the file
        extension is `.toml`, the object will be saved as a `toml` file. If the file
        extension is `.xyz`, the object will be saved as an `xyz` file (for objects
        that support this format such as a `Structure` or an `OptimizationData`
        which contains `.trajectory: list[Structure]`).

        Additionally, padding will be added to the file by default to make it more
        human-readable. You can adjust the amount of padding added by changing the
        `indent` parameter. Pass `indent=None` to create a more compact file.

    Args:
        filepath: The path to write the object to.
        exclude_none: If True, attributes with a value of None will not be written.
            Changing default behavior from pydantic.model_dump() to True.
        exclude_unset: If True, fields omitted during construction are excluded,
            even if their containers were later modified. Defaults to True for
            compact files; pass False to include unset/default-valued fields.
        indent: The number of spaces to use for indentation in the JSON file. 0
            creates a more compact JSON file, 4 is more human-readable.
        **kwargs: Additional keyword arguments to pass to the serialization method.

    Example:
        ```python
        my_obj.save("path/to/file.json")
        ```

        ```python
        my_obj.save("path/to/file.yaml")
        ```

        ```python
        my_obj.save("path/to/file.toml")
        ```

        ```python
        my_obj.save("path/to/file.xyz")
        ```
    """
    filepath = Path(filepath)
    filepath.parent.mkdir(exist_ok=True, parents=True)

    model_dict = self.model_dump(
        mode="json",
        exclude_none=exclude_none,
        exclude_unset=exclude_unset,
        **kwargs,
    )

    if filepath.suffix in [".yaml", ".yml"]:
        data = yaml.dump(model_dict, indent=indent)

    elif filepath.suffix == ".toml":
        data = toml.dumps(model_dict)

    else:
        # Write data to json regardless of file extension
        data = json.dumps(model_dict, indent=indent)

    filepath.write_text(data)