Skip to content

OPTIMADE Data Models

This page provides documentation for the optimade.models submodule, where all the OPTIMADE (and JSON:API)-defined data models are located.

For example, the three OPTIMADE entry types, structures, references and links, are defined primarily through the corresponding attribute models:

As well as validating data types when creating instances of these models, this package defines several OPTIMADE-specific validators that ensure consistency between fields (e.g., the value of nsites matches the number of positions provided in cartesian_site_positions).

ATOMIC_NUMBERS = {} module-attribute

CHEMICAL_SYMBOLS = ['H', 'He', 'Li', 'Be', 'B', 'C', 'N', 'O', 'F', 'Ne', 'Na', 'Mg', 'Al', 'Si', 'P', 'S', 'Cl', 'Ar', 'K', 'Ca', 'Sc', 'Ti', 'V', 'Cr', 'Mn', 'Fe', 'Co', 'Ni', 'Cu', 'Zn', 'Ga', 'Ge', 'As', 'Se', 'Br', 'Kr', 'Rb', 'Sr', 'Y', 'Zr', 'Nb', 'Mo', 'Tc', 'Ru', 'Rh', 'Pd', 'Ag', 'Cd', 'In', 'Sn', 'Sb', 'Te', 'I', 'Xe', 'Cs', 'Ba', 'La', 'Ce', 'Pr', 'Nd', 'Pm', 'Sm', 'Eu', 'Gd', 'Tb', 'Dy', 'Ho', 'Er', 'Tm', 'Yb', 'Lu', 'Hf', 'Ta', 'W', 'Re', 'Os', 'Ir', 'Pt', 'Au', 'Hg', 'Tl', 'Pb', 'Bi', 'Po', 'At', 'Rn', 'Fr', 'Ra', 'Ac', 'Th', 'Pa', 'U', 'Np', 'Pu', 'Am', 'Cm', 'Bk', 'Cf', 'Es', 'Fm', 'Md', 'No', 'Lr', 'Rf', 'Db', 'Sg', 'Bh', 'Hs', 'Mt', 'Ds', 'Rg', 'Cn', 'Nh', 'Fl', 'Mc', 'Lv', 'Ts', 'Og'] module-attribute

EXTRA_SYMBOLS = ['X', 'vacancy'] module-attribute

Vector3D = Annotated[list[Annotated[float, BeforeValidator(float)]], Field(min_length=3, max_length=3)] module-attribute

Assembly

Bases: BaseModel

A description of groups of sites that are statistically correlated.

  • Examples (for each entry of the assemblies list):
    • {"sites_in_groups": [[0], [1]], "group_probabilities: [0.3, 0.7]}: the first site and the second site never occur at the same time in the unit cell. Statistically, 30 % of the times the first site is present, while 70 % of the times the second site is present.
    • {"sites_in_groups": [[1,2], [3]], "group_probabilities: [0.3, 0.7]}: the second and third site are either present together or not present; they form the first group of atoms for this assembly. The second group is formed by the fourth site. Sites of the first group (the second and the third) are never present at the same time as the fourth site. 30 % of times sites 1 and 2 are present (and site 3 is absent); 70 % of times site 3 is present (and sites 1 and 2 are absent).
Source code in optimade/models/structures.py
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
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
class Assembly(BaseModel):
    """A description of groups of sites that are statistically correlated.

    - **Examples** (for each entry of the assemblies list):
        - `{"sites_in_groups": [[0], [1]], "group_probabilities: [0.3, 0.7]}`: the first site and the second site never occur at the same time in the unit cell.
          Statistically, 30 % of the times the first site is present, while 70 % of the times the second site is present.
        - `{"sites_in_groups": [[1,2], [3]], "group_probabilities: [0.3, 0.7]}`: the second and third site are either present together or not present; they form the first group of atoms for this assembly.
          The second group is formed by the fourth site. Sites of the first group (the second and the third) are never present at the same time as the fourth site.
          30 % of times sites 1 and 2 are present (and site 3 is absent); 70 % of times site 3 is present (and sites 1 and 2 are absent).

    """

    sites_in_groups: Annotated[
        list[list[int]],
        OptimadeField(
            description="""Index of the sites (0-based) that belong to each group for each assembly.

- **Examples**:
    - `[[1], [2]]`: two groups, one with the second site, one with the third.
    - `[[1,2], [3]]`: one group with the second and third site, one with the fourth.""",
            support=SupportLevel.MUST,
            queryable=SupportLevel.OPTIONAL,
        ),
    ]

    group_probabilities: Annotated[
        list[float],
        OptimadeField(
            description="""Statistical probability of each group. It MUST have the same length as `sites_in_groups`.
It SHOULD sum to one.
See below for examples of how to specify the probability of the occurrence of a vacancy.
The possible reasons for the values not to sum to one are the same as already specified above for the `concentration` of each `species`.""",
            support=SupportLevel.MUST,
            queryable=SupportLevel.OPTIONAL,
        ),
    ]

    @field_validator("sites_in_groups", mode="after")
    @classmethod
    def validate_sites_in_groups(cls, value: list[list[int]]) -> list[list[int]]:
        sites = []
        for group in value:
            sites.extend(group)
        if len(set(sites)) != len(sites):
            raise ValueError(
                f"A site MUST NOT appear in more than one group. Given value: {value}"
            )
        return value

    @model_validator(mode="after")
    def check_self_consistency(self) -> "Assembly":
        if len(self.group_probabilities) != len(self.sites_in_groups):
            raise ValueError(
                f"sites_in_groups and group_probabilities MUST be of same length, "
                f"but are {len(self.sites_in_groups)} and {len(self.group_probabilities)}, "
                "respectively"
            )
        return self

group_probabilities: Annotated[list[float], OptimadeField(description='Statistical probability of each group. It MUST have the same length as `sites_in_groups`.\nIt SHOULD sum to one.\nSee below for examples of how to specify the probability of the occurrence of a vacancy.\nThe possible reasons for the values not to sum to one are the same as already specified above for the `concentration` of each `species`.', support=SupportLevel.MUST, queryable=SupportLevel.OPTIONAL)] instance-attribute

sites_in_groups: Annotated[list[list[int]], OptimadeField(description='Index of the sites (0-based) that belong to each group for each assembly.\n\n- **Examples**:\n - `[[1], [2]]`: two groups, one with the second site, one with the third.\n - `[[1,2], [3]]`: one group with the second and third site, one with the fourth.', support=SupportLevel.MUST, queryable=SupportLevel.OPTIONAL)] instance-attribute

check_self_consistency()

Source code in optimade/models/structures.py
265
266
267
268
269
270
271
272
273
@model_validator(mode="after")
def check_self_consistency(self) -> "Assembly":
    if len(self.group_probabilities) != len(self.sites_in_groups):
        raise ValueError(
            f"sites_in_groups and group_probabilities MUST be of same length, "
            f"but are {len(self.sites_in_groups)} and {len(self.group_probabilities)}, "
            "respectively"
        )
    return self

validate_sites_in_groups(value) classmethod

Source code in optimade/models/structures.py
253
254
255
256
257
258
259
260
261
262
263
@field_validator("sites_in_groups", mode="after")
@classmethod
def validate_sites_in_groups(cls, value: list[list[int]]) -> list[list[int]]:
    sites = []
    for group in value:
        sites.extend(group)
    if len(set(sites)) != len(sites):
        raise ValueError(
            f"A site MUST NOT appear in more than one group. Given value: {value}"
        )
    return value

Attributes

Bases: BaseModel

Members of the attributes object ("attributes") represent information about the resource object in which it's defined. The keys for Attributes MUST NOT be: relationships links id type

Source code in optimade/models/jsonapi.py
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
class Attributes(BaseModel):
    """
    Members of the attributes object ("attributes\") represent information about the resource object in which it's defined.
    The keys for Attributes MUST NOT be:
        relationships
        links
        id
        type
    """

    model_config = ConfigDict(extra="allow")

    @model_validator(mode="after")
    def check_illegal_attributes_fields(self) -> "Attributes":
        illegal_fields = ("relationships", "links", "id", "type")
        for field in illegal_fields:
            if hasattr(self, field):
                raise ValueError(
                    f"{illegal_fields} MUST NOT be fields under Attributes"
                )
        return self

model_config = ConfigDict(extra='allow') class-attribute instance-attribute

check_illegal_attributes_fields()

Source code in optimade/models/jsonapi.py
330
331
332
333
334
335
336
337
338
@model_validator(mode="after")
def check_illegal_attributes_fields(self) -> "Attributes":
    illegal_fields = ("relationships", "links", "id", "type")
    for field in illegal_fields:
        if hasattr(self, field):
            raise ValueError(
                f"{illegal_fields} MUST NOT be fields under Attributes"
            )
    return self

AvailableApiVersion

Bases: BaseModel

A JSON object containing information about an available API version

Source code in optimade/models/baseinfo.py
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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
class AvailableApiVersion(BaseModel):
    """A JSON object containing information about an available API version"""

    url: Annotated[
        AnyHttpUrl,
        StrictField(
            description="A string specifying a versioned base URL that MUST adhere to the rules in section Base URL",
            json_schema_extra={
                "pattern": VERSIONED_BASE_URL_PATTERN,
            },
        ),
    ]

    version: Annotated[
        SemanticVersion,
        StrictField(
            description="""A string containing the full version number of the API served at that versioned base URL.
The version number string MUST NOT be prefixed by, e.g., 'v'.
Examples: `1.0.0`, `1.0.0-rc.2`.""",
        ),
    ]

    @field_validator("url", mode="after")
    @classmethod
    def url_must_be_versioned_base_Url(cls, value: AnyHttpUrl) -> AnyHttpUrl:
        """The URL must be a versioned base URL"""
        if not re.match(VERSIONED_BASE_URL_PATTERN, str(value)):
            raise ValueError(
                f"URL {value} must be a versioned base URL (i.e., must match the "
                f"pattern '{VERSIONED_BASE_URL_PATTERN}')"
            )
        return value

    @model_validator(mode="after")
    def crosscheck_url_and_version(self) -> "AvailableApiVersion":
        """Check that URL version and API version are compatible."""
        url = (
            str(self.url)
            .split("/")[-2 if str(self.url).endswith("/") else -1]
            .replace("v", "")
        )
        # as with version urls, we need to split any release tags or build metadata out of these URLs
        url_version = tuple(
            int(val) for val in url.split("-")[0].split("+")[0].split(".")
        )
        api_version = tuple(
            int(val) for val in str(self.version).split("-")[0].split("+")[0].split(".")
        )
        if any(a != b for a, b in zip(url_version, api_version)):
            raise ValueError(
                f"API version {api_version} is not compatible with url version {url_version}."
            )
        return self

url: Annotated[AnyHttpUrl, StrictField(description='A string specifying a versioned base URL that MUST adhere to the rules in section Base URL', json_schema_extra={pattern: VERSIONED_BASE_URL_PATTERN})] instance-attribute

version: Annotated[SemanticVersion, StrictField(description="A string containing the full version number of the API served at that versioned base URL.\nThe version number string MUST NOT be prefixed by, e.g., 'v'.\nExamples: `1.0.0`, `1.0.0-rc.2`.")] instance-attribute

crosscheck_url_and_version()

Check that URL version and API version are compatible.

Source code in optimade/models/baseinfo.py
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
@model_validator(mode="after")
def crosscheck_url_and_version(self) -> "AvailableApiVersion":
    """Check that URL version and API version are compatible."""
    url = (
        str(self.url)
        .split("/")[-2 if str(self.url).endswith("/") else -1]
        .replace("v", "")
    )
    # as with version urls, we need to split any release tags or build metadata out of these URLs
    url_version = tuple(
        int(val) for val in url.split("-")[0].split("+")[0].split(".")
    )
    api_version = tuple(
        int(val) for val in str(self.version).split("-")[0].split("+")[0].split(".")
    )
    if any(a != b for a, b in zip(url_version, api_version)):
        raise ValueError(
            f"API version {api_version} is not compatible with url version {url_version}."
        )
    return self

url_must_be_versioned_base_Url(value) classmethod

The URL must be a versioned base URL

Source code in optimade/models/baseinfo.py
38
39
40
41
42
43
44
45
46
47
@field_validator("url", mode="after")
@classmethod
def url_must_be_versioned_base_Url(cls, value: AnyHttpUrl) -> AnyHttpUrl:
    """The URL must be a versioned base URL"""
    if not re.match(VERSIONED_BASE_URL_PATTERN, str(value)):
        raise ValueError(
            f"URL {value} must be a versioned base URL (i.e., must match the "
            f"pattern '{VERSIONED_BASE_URL_PATTERN}')"
        )
    return value

BaseInfoAttributes

Bases: BaseModel

Attributes for Base URL Info endpoint

Source code in optimade/models/baseinfo.py
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 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
114
115
116
117
118
119
120
121
122
class BaseInfoAttributes(BaseModel):
    """Attributes for Base URL Info endpoint"""

    api_version: Annotated[
        SemanticVersion,
        StrictField(
            description="""Presently used full version of the OPTIMADE API.
The version number string MUST NOT be prefixed by, e.g., "v".
Examples: `1.0.0`, `1.0.0-rc.2`.""",
        ),
    ]
    available_api_versions: Annotated[
        list[AvailableApiVersion],
        StrictField(
            description="A list of dictionaries of available API versions at other base URLs",
        ),
    ]
    formats: Annotated[
        list[str], StrictField(description="List of available output formats.")
    ] = ["json"]
    available_endpoints: Annotated[
        list[str],
        StrictField(
            description="List of available endpoints (i.e., the string to be appended to the versioned base URL).",
        ),
    ]
    entry_types_by_format: Annotated[
        dict[str, list[str]],
        StrictField(
            description="Available entry endpoints as a function of output formats."
        ),
    ]
    is_index: Annotated[
        Optional[bool],
        StrictField(
            description="If true, this is an index meta-database base URL (see section Index Meta-Database). "
            "If this member is not provided, the client MUST assume this is not an index meta-database base URL "
            "(i.e., the default is for `is_index` to be `false`).",
        ),
    ] = False

    @model_validator(mode="after")
    def formats_and_endpoints_must_be_valid(self) -> "BaseInfoAttributes":
        for format_, endpoints in self.entry_types_by_format.items():
            if format_ not in self.formats:
                raise ValueError(f"'{format_}' must be listed in formats to be valid")
            for endpoint in endpoints:
                if endpoint not in self.available_endpoints:
                    raise ValueError(
                        f"'{endpoint}' must be listed in available_endpoints to be valid"
                    )
        return self

api_version: Annotated[SemanticVersion, StrictField(description='Presently used full version of the OPTIMADE API.\nThe version number string MUST NOT be prefixed by, e.g., "v".\nExamples: `1.0.0`, `1.0.0-rc.2`.')] instance-attribute

available_api_versions: Annotated[list[AvailableApiVersion], StrictField(description='A list of dictionaries of available API versions at other base URLs')] instance-attribute

available_endpoints: Annotated[list[str], StrictField(description='List of available endpoints (i.e., the string to be appended to the versioned base URL).')] instance-attribute

entry_types_by_format: Annotated[dict[str, list[str]], StrictField(description='Available entry endpoints as a function of output formats.')] instance-attribute

formats: Annotated[list[str], StrictField(description='List of available output formats.')] = ['json'] class-attribute instance-attribute

is_index: Annotated[Optional[bool], StrictField(description='If true, this is an index meta-database base URL (see section Index Meta-Database). If this member is not provided, the client MUST assume this is not an index meta-database base URL (i.e., the default is for `is_index` to be `false`).')] = False class-attribute instance-attribute

formats_and_endpoints_must_be_valid()

Source code in optimade/models/baseinfo.py
112
113
114
115
116
117
118
119
120
121
122
@model_validator(mode="after")
def formats_and_endpoints_must_be_valid(self) -> "BaseInfoAttributes":
    for format_, endpoints in self.entry_types_by_format.items():
        if format_ not in self.formats:
            raise ValueError(f"'{format_}' must be listed in formats to be valid")
        for endpoint in endpoints:
            if endpoint not in self.available_endpoints:
                raise ValueError(
                    f"'{endpoint}' must be listed in available_endpoints to be valid"
                )
    return self

BaseInfoResource

Bases: Resource

Source code in optimade/models/baseinfo.py
125
126
127
128
class BaseInfoResource(Resource):
    id: Literal["/"] = "/"
    type: Literal["info"] = "info"
    attributes: BaseInfoAttributes

attributes: BaseInfoAttributes instance-attribute

id: Literal['/'] = '/' class-attribute instance-attribute

meta: Annotated[Optional[Meta], StrictField(description='a meta object containing non-standard meta-information about a resource that can not be represented as an attribute or relationship.')] = None class-attribute instance-attribute

model_config = ConfigDict(json_schema_extra=resource_json_schema_extra) class-attribute instance-attribute

relationships: Annotated[Optional[Relationships], StrictField(description='[Relationships object](https://jsonapi.org/format/1.0/#document-resource-object-relationships)\ndescribing relationships between the resource and other JSON API resources.')] = None class-attribute instance-attribute

type: Literal['info'] = 'info' class-attribute instance-attribute

BaseRelationshipMeta

Bases: Meta

Specific meta field for base relationship resource

Source code in optimade/models/optimade_json.py
407
408
409
410
411
412
413
414
415
class BaseRelationshipMeta(jsonapi.Meta):
    """Specific meta field for base relationship resource"""

    description: Annotated[
        str,
        StrictField(
            description="OPTIONAL human-readable description of the relationship."
        ),
    ]

description: Annotated[str, StrictField(description='OPTIONAL human-readable description of the relationship.')] instance-attribute

model_config = ConfigDict(extra='allow') class-attribute instance-attribute

BaseRelationshipResource

Bases: BaseResource

Minimum requirements to represent a relationship resource

Source code in optimade/models/optimade_json.py
418
419
420
421
422
423
424
425
426
class BaseRelationshipResource(jsonapi.BaseResource):
    """Minimum requirements to represent a relationship resource"""

    meta: Annotated[
        Optional[BaseRelationshipMeta],
        StrictField(
            description="Relationship meta field. MUST contain 'description' if supplied.",
        ),
    ] = None

id: Annotated[str, StrictField(description='Resource ID')] instance-attribute

meta: Annotated[Optional[BaseRelationshipMeta], StrictField(description="Relationship meta field. MUST contain 'description' if supplied.")] = None class-attribute instance-attribute

model_config = ConfigDict(json_schema_extra=resource_json_schema_extra) class-attribute instance-attribute

type: Annotated[str, StrictField(description='Resource type')] instance-attribute

BaseResource

Bases: BaseModel

Minimum requirements to represent a Resource

Source code in optimade/models/jsonapi.py
218
219
220
221
222
223
224
class BaseResource(BaseModel):
    """Minimum requirements to represent a Resource"""

    model_config = ConfigDict(json_schema_extra=resource_json_schema_extra)

    id: Annotated[str, StrictField(description="Resource ID")]
    type: Annotated[str, StrictField(description="Resource type")]

id: Annotated[str, StrictField(description='Resource ID')] instance-attribute

model_config = ConfigDict(json_schema_extra=resource_json_schema_extra) class-attribute instance-attribute

type: Annotated[str, StrictField(description='Resource type')] instance-attribute

DataType

Bases: Enum

Optimade Data types

See the section "Data types" in the OPTIMADE API specification for more information.

Source code in optimade/models/optimade_json.py
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 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
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
class DataType(Enum):
    """Optimade Data types

    See the section "Data types" in the OPTIMADE API specification for more information.
    """

    STRING = "string"
    INTEGER = "integer"
    FLOAT = "float"
    BOOLEAN = "boolean"
    TIMESTAMP = "timestamp"
    LIST = "list"
    DICTIONARY = "dictionary"
    UNKNOWN = "unknown"

    @classmethod
    def get_values(cls) -> list[str]:
        """Get OPTIMADE data types (enum values) as a (sorted) list"""
        return sorted(_.value for _ in cls)

    @classmethod
    def from_python_type(
        cls, python_type: Union[type, str, object]
    ) -> Optional["DataType"]:
        """Get OPTIMADE data type from a Python type"""
        mapping = {
            "bool": cls.BOOLEAN,
            "int": cls.INTEGER,
            "float": cls.FLOAT,
            "complex": None,
            "generator": cls.LIST,
            "list": cls.LIST,
            "tuple": cls.LIST,
            "range": cls.LIST,
            "hash": cls.INTEGER,
            "str": cls.STRING,
            "bytes": cls.STRING,
            "bytearray": None,
            "memoryview": None,
            "set": cls.LIST,
            "frozenset": cls.LIST,
            "dict": cls.DICTIONARY,
            "dict_keys": cls.LIST,
            "dict_values": cls.LIST,
            "dict_items": cls.LIST,
            "Nonetype": cls.UNKNOWN,
            "None": cls.UNKNOWN,
            "datetime": cls.TIMESTAMP,
            "date": cls.TIMESTAMP,
            "time": cls.TIMESTAMP,
            "datetime.datetime": cls.TIMESTAMP,
            "datetime.date": cls.TIMESTAMP,
            "datetime.time": cls.TIMESTAMP,
        }

        if isinstance(python_type, type):
            python_type = python_type.__name__
        elif isinstance(python_type, object):
            if str(python_type) in mapping:
                python_type = str(python_type)
            else:
                python_type = type(python_type).__name__

        return mapping.get(python_type, None)

    @classmethod
    def from_json_type(cls, json_type: str) -> Optional["DataType"]:
        """Get OPTIMADE data type from a named JSON type"""
        mapping = {
            "string": cls.STRING,
            "integer": cls.INTEGER,
            "number": cls.FLOAT,  # actually includes both integer and float
            "object": cls.DICTIONARY,
            "array": cls.LIST,
            "boolean": cls.BOOLEAN,
            "null": cls.UNKNOWN,
            # OpenAPI "format"s:
            "double": cls.FLOAT,
            "float": cls.FLOAT,
            "int32": cls.INTEGER,
            "int64": cls.INTEGER,
            "date": cls.TIMESTAMP,
            "date-time": cls.TIMESTAMP,
            "password": cls.STRING,
            "byte": cls.STRING,
            "binary": cls.STRING,
            # Non-OpenAPI "format"s, but may still be used by pydantic/FastAPI
            "email": cls.STRING,
            "uuid": cls.STRING,
            "uri": cls.STRING,
            "hostname": cls.STRING,
            "ipv4": cls.STRING,
            "ipv6": cls.STRING,
        }

        return mapping.get(json_type, None)

BOOLEAN = 'boolean' class-attribute instance-attribute

DICTIONARY = 'dictionary' class-attribute instance-attribute

FLOAT = 'float' class-attribute instance-attribute

INTEGER = 'integer' class-attribute instance-attribute

LIST = 'list' class-attribute instance-attribute

STRING = 'string' class-attribute instance-attribute

TIMESTAMP = 'timestamp' class-attribute instance-attribute

UNKNOWN = 'unknown' class-attribute instance-attribute

from_json_type(json_type) classmethod

Get OPTIMADE data type from a named JSON type

Source code in optimade/models/optimade_json.py
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
@classmethod
def from_json_type(cls, json_type: str) -> Optional["DataType"]:
    """Get OPTIMADE data type from a named JSON type"""
    mapping = {
        "string": cls.STRING,
        "integer": cls.INTEGER,
        "number": cls.FLOAT,  # actually includes both integer and float
        "object": cls.DICTIONARY,
        "array": cls.LIST,
        "boolean": cls.BOOLEAN,
        "null": cls.UNKNOWN,
        # OpenAPI "format"s:
        "double": cls.FLOAT,
        "float": cls.FLOAT,
        "int32": cls.INTEGER,
        "int64": cls.INTEGER,
        "date": cls.TIMESTAMP,
        "date-time": cls.TIMESTAMP,
        "password": cls.STRING,
        "byte": cls.STRING,
        "binary": cls.STRING,
        # Non-OpenAPI "format"s, but may still be used by pydantic/FastAPI
        "email": cls.STRING,
        "uuid": cls.STRING,
        "uri": cls.STRING,
        "hostname": cls.STRING,
        "ipv4": cls.STRING,
        "ipv6": cls.STRING,
    }

    return mapping.get(json_type, None)

from_python_type(python_type) classmethod

Get OPTIMADE data type from a Python type

Source code in optimade/models/optimade_json.py
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
@classmethod
def from_python_type(
    cls, python_type: Union[type, str, object]
) -> Optional["DataType"]:
    """Get OPTIMADE data type from a Python type"""
    mapping = {
        "bool": cls.BOOLEAN,
        "int": cls.INTEGER,
        "float": cls.FLOAT,
        "complex": None,
        "generator": cls.LIST,
        "list": cls.LIST,
        "tuple": cls.LIST,
        "range": cls.LIST,
        "hash": cls.INTEGER,
        "str": cls.STRING,
        "bytes": cls.STRING,
        "bytearray": None,
        "memoryview": None,
        "set": cls.LIST,
        "frozenset": cls.LIST,
        "dict": cls.DICTIONARY,
        "dict_keys": cls.LIST,
        "dict_values": cls.LIST,
        "dict_items": cls.LIST,
        "Nonetype": cls.UNKNOWN,
        "None": cls.UNKNOWN,
        "datetime": cls.TIMESTAMP,
        "date": cls.TIMESTAMP,
        "time": cls.TIMESTAMP,
        "datetime.datetime": cls.TIMESTAMP,
        "datetime.date": cls.TIMESTAMP,
        "datetime.time": cls.TIMESTAMP,
    }

    if isinstance(python_type, type):
        python_type = python_type.__name__
    elif isinstance(python_type, object):
        if str(python_type) in mapping:
            python_type = str(python_type)
        else:
            python_type = type(python_type).__name__

    return mapping.get(python_type, None)

get_values() classmethod

Get OPTIMADE data types (enum values) as a (sorted) list

Source code in optimade/models/optimade_json.py
47
48
49
50
@classmethod
def get_values(cls) -> list[str]:
    """Get OPTIMADE data types (enum values) as a (sorted) list"""
    return sorted(_.value for _ in cls)

EntryInfoProperty

Bases: BaseModel

Source code in optimade/models/entries.py
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
class EntryInfoProperty(BaseModel):
    description: Annotated[
        str,
        StrictField(description="A human-readable description of the entry property"),
    ]

    unit: Annotated[
        Optional[str],
        StrictField(
            description="""The physical unit of the entry property.
This MUST be a valid representation of units according to version 2.1 of [The Unified Code for Units of Measure](https://unitsofmeasure.org/ucum.html).
It is RECOMMENDED that non-standard (non-SI) units are described in the description for the property.""",
        ),
    ] = None

    sortable: Annotated[
        Optional[bool],
        StrictField(
            description="""Defines whether the entry property can be used for sorting with the "sort" parameter.
If the entry listing endpoint supports sorting, this key MUST be present for sortable properties with value `true`.""",
        ),
    ] = None

    type: Annotated[
        Optional[DataType],
        StrictField(
            title="Type",
            description="""The type of the property's value.
This MUST be any of the types defined in the Data types section.
For the purpose of compatibility with future versions of this specification, a client MUST accept values that are not `string` values specifying any of the OPTIMADE Data types, but MUST then also disregard the `type` field.
Note, if the value is a nested type, only the outermost type should be reported.
E.g., for the entry resource `structures`, the `species` property is defined as a list of dictionaries, hence its `type` value would be `list`.""",
        ),
    ] = None

description: Annotated[str, StrictField(description='A human-readable description of the entry property')] instance-attribute

sortable: Annotated[Optional[bool], StrictField(description='Defines whether the entry property can be used for sorting with the "sort" parameter.\nIf the entry listing endpoint supports sorting, this key MUST be present for sortable properties with value `true`.')] = None class-attribute instance-attribute

type: Annotated[Optional[DataType], StrictField(title=Type, description="The type of the property's value.\nThis MUST be any of the types defined in the Data types section.\nFor the purpose of compatibility with future versions of this specification, a client MUST accept values that are not `string` values specifying any of the OPTIMADE Data types, but MUST then also disregard the `type` field.\nNote, if the value is a nested type, only the outermost type should be reported.\nE.g., for the entry resource `structures`, the `species` property is defined as a list of dictionaries, hence its `type` value would be `list`.")] = None class-attribute instance-attribute

unit: Annotated[Optional[str], StrictField(description='The physical unit of the entry property.\nThis MUST be a valid representation of units according to version 2.1 of [The Unified Code for Units of Measure](https://unitsofmeasure.org/ucum.html).\nIt is RECOMMENDED that non-standard (non-SI) units are described in the description for the property.')] = None class-attribute instance-attribute

EntryInfoResource

Bases: BaseModel

Source code in optimade/models/entries.py
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
class EntryInfoResource(BaseModel):
    formats: Annotated[
        list[str],
        StrictField(
            description="List of output formats available for this type of entry."
        ),
    ]

    description: Annotated[str, StrictField(description="Description of the entry.")]

    properties: Annotated[
        dict[ValidIdentifier, EntryInfoProperty],
        StrictField(
            description="A dictionary describing queryable properties for this entry type, where each key is a property name.",
        ),
    ]

    output_fields_by_format: Annotated[
        dict[str, list[ValidIdentifier]],
        StrictField(
            description="Dictionary of available output fields for this entry type, where the keys are the values of the `formats` list and the values are the keys of the `properties` dictionary.",
        ),
    ]

description: Annotated[str, StrictField(description='Description of the entry.')] instance-attribute

formats: Annotated[list[str], StrictField(description='List of output formats available for this type of entry.')] instance-attribute

output_fields_by_format: Annotated[dict[str, list[ValidIdentifier]], StrictField(description='Dictionary of available output fields for this entry type, where the keys are the values of the `formats` list and the values are the keys of the `properties` dictionary.')] instance-attribute

properties: Annotated[dict[ValidIdentifier, EntryInfoProperty], StrictField(description='A dictionary describing queryable properties for this entry type, where each key is a property name.')] instance-attribute

EntryInfoResponse

Bases: Success

Source code in optimade/models/responses.py
58
59
60
61
62
class EntryInfoResponse(Success):
    data: Annotated[
        EntryInfoResource,
        StrictField(description="OPTIMADE information for an entry endpoint."),
    ]

data: Annotated[EntryInfoResource, StrictField(description='OPTIMADE information for an entry endpoint.')] instance-attribute

errors: Annotated[Optional[list[Error]], StrictField(description='A list of unique errors', uniqueItems=True)] = None class-attribute instance-attribute

included: Annotated[Optional[list[Resource]], StrictField(description='A list of unique included resources', uniqueItems=True)] = None class-attribute instance-attribute

jsonapi: Annotated[Optional[JsonApi], StrictField(description='Information about the JSON API used')] = None class-attribute instance-attribute

meta: Annotated[ResponseMeta, StrictField(description='A meta object containing non-standard information')] instance-attribute

model_config = ConfigDict(json_encoders={datetime: lambda v: v.astimezone(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ')}) class-attribute instance-attribute

The specification mandates that datetimes must be encoded following RFC3339, which does not support fractional seconds, thus they must be stripped in the response. This can cause issues when the underlying database contains fields that do include microseconds, as filters may return unexpected results.

either_data_meta_or_errors_must_be_set()

Overwriting the existing validation function, since 'errors' MUST NOT be set.

Source code in optimade/models/optimade_json.py
391
392
393
394
395
396
397
398
399
400
401
402
403
404
@model_validator(mode="after")
def either_data_meta_or_errors_must_be_set(self) -> "Success":
    """Overwriting the existing validation function, since 'errors' MUST NOT be set."""
    required_fields = ("data", "meta")
    if not any(field in self.model_fields_set for field in required_fields):
        raise ValueError(
            f"At least one of {required_fields} MUST be specified in the top-level response."
        )

    # errors MUST be skipped
    if self.errors or "errors" in self.model_fields_set:
        raise ValueError("'errors' MUST be skipped for a successful response.")

    return self

EntryRelationships

Bases: Relationships

This model wraps the JSON API Relationships to include type-specific top level keys.

Source code in optimade/models/entries.py
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
class EntryRelationships(Relationships):
    """This model wraps the JSON API Relationships to include type-specific top level keys."""

    references: Annotated[
        Optional[ReferenceRelationship],
        StrictField(
            description="Object containing links to relationships with entries of the `references` type.",
        ),
    ] = None

    structures: Annotated[
        Optional[StructureRelationship],
        StrictField(
            description="Object containing links to relationships with entries of the `structures` type.",
        ),
    ] = None

references: Annotated[Optional[ReferenceRelationship], StrictField(description='Object containing links to relationships with entries of the `references` type.')] = None class-attribute instance-attribute

structures: Annotated[Optional[StructureRelationship], StrictField(description='Object containing links to relationships with entries of the `structures` type.')] = None class-attribute instance-attribute

check_illegal_relationships_fields()

Source code in optimade/models/jsonapi.py
296
297
298
299
300
301
302
303
304
@model_validator(mode="after")
def check_illegal_relationships_fields(self) -> "Relationships":
    illegal_fields = ("id", "type")
    for field in illegal_fields:
        if hasattr(self, field):
            raise ValueError(
                f"{illegal_fields} MUST NOT be fields under Relationships"
            )
    return self

EntryResource

Bases: Resource

The base model for an entry resource.

Source code in optimade/models/entries.py
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
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
class EntryResource(Resource):
    """The base model for an entry resource."""

    id: Annotated[
        str,
        OptimadeField(
            description="""An entry's ID as defined in section Definition of Terms.

- **Type**: string.

- **Requirements/Conventions**:
    - **Support**: MUST be supported by all implementations, MUST NOT be `null`.
    - **Query**: MUST be a queryable property with support for all mandatory filter features.
    - **Response**: REQUIRED in the response.

- **Examples**:
    - `"db/1234567"`
    - `"cod/2000000"`
    - `"cod/2000000@1234567"`
    - `"nomad/L1234567890"`
    - `"42"`""",
            support=SupportLevel.MUST,
            queryable=SupportLevel.MUST,
        ),
    ]

    type: Annotated[
        str,
        OptimadeField(
            description="""The name of the type of an entry.

- **Type**: string.

- **Requirements/Conventions**:
    - **Support**: MUST be supported by all implementations, MUST NOT be `null`.
    - **Query**: MUST be a queryable property with support for all mandatory filter features.
    - **Response**: REQUIRED in the response.
    - MUST be an existing entry type.
    - The entry of type `<type>` and ID `<id>` MUST be returned in response to a request for `/<type>/<id>` under the versioned base URL.

- **Example**: `"structures"`""",
            support=SupportLevel.MUST,
            queryable=SupportLevel.MUST,
        ),
    ]

    attributes: Annotated[
        EntryResourceAttributes,
        StrictField(
            description="""A dictionary, containing key-value pairs representing the entry's properties, except for `type` and `id`.
Database-provider-specific properties need to include the database-provider-specific prefix (see section on Database-Provider-Specific Namespace Prefixes).""",
        ),
    ]

    relationships: Annotated[
        Optional[EntryRelationships],
        StrictField(
            description="""A dictionary containing references to other entries according to the description in section Relationships encoded as [JSON API Relationships](https://jsonapi.org/format/1.0/#document-resource-object-relationships).
The OPTIONAL human-readable description of the relationship MAY be provided in the `description` field inside the `meta` dictionary of the JSON API resource identifier object.""",
        ),
    ] = None

attributes: Annotated[EntryResourceAttributes, StrictField(description="A dictionary, containing key-value pairs representing the entry's properties, except for `type` and `id`.\nDatabase-provider-specific properties need to include the database-provider-specific prefix (see section on Database-Provider-Specific Namespace Prefixes).")] instance-attribute

id: Annotated[str, OptimadeField(description='An entry\'s ID as defined in section Definition of Terms.\n\n- **Type**: string.\n\n- **Requirements/Conventions**:\n - **Support**: MUST be supported by all implementations, MUST NOT be `null`.\n - **Query**: MUST be a queryable property with support for all mandatory filter features.\n - **Response**: REQUIRED in the response.\n\n- **Examples**:\n - `"db/1234567"`\n - `"cod/2000000"`\n - `"cod/2000000@1234567"`\n - `"nomad/L1234567890"`\n - `"42"`', support=SupportLevel.MUST, queryable=SupportLevel.MUST)] instance-attribute

meta: Annotated[Optional[Meta], StrictField(description='a meta object containing non-standard meta-information about a resource that can not be represented as an attribute or relationship.')] = None class-attribute instance-attribute

model_config = ConfigDict(json_schema_extra=resource_json_schema_extra) class-attribute instance-attribute

relationships: Annotated[Optional[EntryRelationships], StrictField(description='A dictionary containing references to other entries according to the description in section Relationships encoded as [JSON API Relationships](https://jsonapi.org/format/1.0/#document-resource-object-relationships).\nThe OPTIONAL human-readable description of the relationship MAY be provided in the `description` field inside the `meta` dictionary of the JSON API resource identifier object.')] = None class-attribute instance-attribute

type: Annotated[str, OptimadeField(description='The name of the type of an entry.\n\n- **Type**: string.\n\n- **Requirements/Conventions**:\n - **Support**: MUST be supported by all implementations, MUST NOT be `null`.\n - **Query**: MUST be a queryable property with support for all mandatory filter features.\n - **Response**: REQUIRED in the response.\n - MUST be an existing entry type.\n - The entry of type `<type>` and ID `<id>` MUST be returned in response to a request for `/<type>/<id>` under the versioned base URL.\n\n- **Example**: `"structures"`', support=SupportLevel.MUST, queryable=SupportLevel.MUST)] instance-attribute

EntryResourceAttributes

Bases: Attributes

Contains key-value pairs representing the entry's properties.

Source code in optimade/models/entries.py
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 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
114
115
116
117
class EntryResourceAttributes(Attributes):
    """Contains key-value pairs representing the entry's properties."""

    immutable_id: Annotated[
        Optional[str],
        OptimadeField(
            description="""The entry's immutable ID (e.g., an UUID). This is important for databases having preferred IDs that point to "the latest version" of a record, but still offer access to older variants. This ID maps to the version-specific record, in case it changes in the future.

- **Type**: string.

- **Requirements/Conventions**:
    - **Support**: OPTIONAL support in implementations, i.e., MAY be `null`.
    - **Query**: MUST be a queryable property with support for all mandatory filter features.

- **Examples**:
    - `"8bd3e750-b477-41a0-9b11-3a799f21b44f"`
    - `"fjeiwoj,54;@=%<>#32"` (Strings that are not URL-safe are allowed.)""",
            support=SupportLevel.OPTIONAL,
            queryable=SupportLevel.MUST,
        ),
    ] = None

    last_modified: Annotated[
        Optional[datetime],
        OptimadeField(
            description="""Date and time representing when the entry was last modified.

- **Type**: timestamp.

- **Requirements/Conventions**:
    - **Support**: SHOULD be supported by all implementations, i.e., SHOULD NOT be `null`.
    - **Query**: MUST be a queryable property with support for all mandatory filter features.
    - **Response**: REQUIRED in the response unless the query parameter `response_fields` is present and does not include this property.

- **Example**:
    - As part of JSON response format: `"2007-04-05T14:30:20Z"` (i.e., encoded as an [RFC 3339 Internet Date/Time Format](https://tools.ietf.org/html/rfc3339#section-5.6) string.)""",
            support=SupportLevel.SHOULD,
            queryable=SupportLevel.MUST,
        ),
    ]

    @field_validator("immutable_id", mode="before")
    @classmethod
    def cast_immutable_id_to_str(cls, value: Any) -> str:
        """Convenience validator for casting `immutable_id` to a string."""
        if value is not None and not isinstance(value, str):
            value = str(value)

        return value

immutable_id: Annotated[Optional[str], OptimadeField(description='The entry\'s immutable ID (e.g., an UUID). This is important for databases having preferred IDs that point to "the latest version" of a record, but still offer access to older variants. This ID maps to the version-specific record, in case it changes in the future.\n\n- **Type**: string.\n\n- **Requirements/Conventions**:\n - **Support**: OPTIONAL support in implementations, i.e., MAY be `null`.\n - **Query**: MUST be a queryable property with support for all mandatory filter features.\n\n- **Examples**:\n - `"8bd3e750-b477-41a0-9b11-3a799f21b44f"`\n - `"fjeiwoj,54;@=%<>#32"` (Strings that are not URL-safe are allowed.)', support=SupportLevel.OPTIONAL, queryable=SupportLevel.MUST)] = None class-attribute instance-attribute

last_modified: Annotated[Optional[datetime], OptimadeField(description='Date and time representing when the entry was last modified.\n\n- **Type**: timestamp.\n\n- **Requirements/Conventions**:\n - **Support**: SHOULD be supported by all implementations, i.e., SHOULD NOT be `null`.\n - **Query**: MUST be a queryable property with support for all mandatory filter features.\n - **Response**: REQUIRED in the response unless the query parameter `response_fields` is present and does not include this property.\n\n- **Example**:\n - As part of JSON response format: `"2007-04-05T14:30:20Z"` (i.e., encoded as an [RFC 3339 Internet Date/Time Format](https://tools.ietf.org/html/rfc3339#section-5.6) string.)', support=SupportLevel.SHOULD, queryable=SupportLevel.MUST)] instance-attribute

model_config = ConfigDict(extra='allow') class-attribute instance-attribute

cast_immutable_id_to_str(value) classmethod

Convenience validator for casting immutable_id to a string.

Source code in optimade/models/entries.py
110
111
112
113
114
115
116
117
@field_validator("immutable_id", mode="before")
@classmethod
def cast_immutable_id_to_str(cls, value: Any) -> str:
    """Convenience validator for casting `immutable_id` to a string."""
    if value is not None and not isinstance(value, str):
        value = str(value)

    return value

check_illegal_attributes_fields()

Source code in optimade/models/jsonapi.py
330
331
332
333
334
335
336
337
338
@model_validator(mode="after")
def check_illegal_attributes_fields(self) -> "Attributes":
    illegal_fields = ("relationships", "links", "id", "type")
    for field in illegal_fields:
        if hasattr(self, field):
            raise ValueError(
                f"{illegal_fields} MUST NOT be fields under Attributes"
            )
    return self

EntryResponseMany

Bases: Success

Source code in optimade/models/responses.py
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
class EntryResponseMany(Success):
    data: Annotated[  # type: ignore[assignment]
        Union[list[EntryResource], list[dict[str, Any]]],
        StrictField(
            description="List of unique OPTIMADE entry resource objects.",
            uniqueItems=True,
            union_mode="left_to_right",
        ),
    ]
    included: Annotated[
        Optional[Union[list[EntryResource], list[dict[str, Any]]]],
        StrictField(
            description="A list of unique included OPTIMADE entry resources.",
            uniqueItems=True,
            union_mode="left_to_right",
        ),
    ] = None  # type: ignore[assignment]

data: Annotated[Union[list[EntryResource], list[dict[str, Any]]], StrictField(description='List of unique OPTIMADE entry resource objects.', uniqueItems=True, union_mode=left_to_right)] instance-attribute

errors: Annotated[Optional[list[Error]], StrictField(description='A list of unique errors', uniqueItems=True)] = None class-attribute instance-attribute

included: Annotated[Optional[Union[list[EntryResource], list[dict[str, Any]]]], StrictField(description='A list of unique included OPTIMADE entry resources.', uniqueItems=True, union_mode=left_to_right)] = None class-attribute instance-attribute

jsonapi: Annotated[Optional[JsonApi], StrictField(description='Information about the JSON API used')] = None class-attribute instance-attribute

meta: Annotated[ResponseMeta, StrictField(description='A meta object containing non-standard information')] instance-attribute

model_config = ConfigDict(json_encoders={datetime: lambda v: v.astimezone(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ')}) class-attribute instance-attribute

The specification mandates that datetimes must be encoded following RFC3339, which does not support fractional seconds, thus they must be stripped in the response. This can cause issues when the underlying database contains fields that do include microseconds, as filters may return unexpected results.

either_data_meta_or_errors_must_be_set()

Overwriting the existing validation function, since 'errors' MUST NOT be set.

Source code in optimade/models/optimade_json.py
391
392
393
394
395
396
397
398
399
400
401
402
403
404
@model_validator(mode="after")
def either_data_meta_or_errors_must_be_set(self) -> "Success":
    """Overwriting the existing validation function, since 'errors' MUST NOT be set."""
    required_fields = ("data", "meta")
    if not any(field in self.model_fields_set for field in required_fields):
        raise ValueError(
            f"At least one of {required_fields} MUST be specified in the top-level response."
        )

    # errors MUST be skipped
    if self.errors or "errors" in self.model_fields_set:
        raise ValueError("'errors' MUST be skipped for a successful response.")

    return self

EntryResponseOne

Bases: Success

Source code in optimade/models/responses.py
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
class EntryResponseOne(Success):
    data: Annotated[
        Optional[Union[EntryResource, dict[str, Any]]],
        StrictField(
            description="The single entry resource returned by this query.",
            union_mode="left_to_right",
        ),
    ] = None  # type: ignore[assignment]
    included: Annotated[
        Optional[Union[list[EntryResource], list[dict[str, Any]]]],
        StrictField(
            description="A list of unique included OPTIMADE entry resources.",
            uniqueItems=True,
            union_mode="left_to_right",
        ),
    ] = None  # type: ignore[assignment]

data: Annotated[Optional[Union[EntryResource, dict[str, Any]]], StrictField(description='The single entry resource returned by this query.', union_mode=left_to_right)] = None class-attribute instance-attribute

errors: Annotated[Optional[list[Error]], StrictField(description='A list of unique errors', uniqueItems=True)] = None class-attribute instance-attribute

included: Annotated[Optional[Union[list[EntryResource], list[dict[str, Any]]]], StrictField(description='A list of unique included OPTIMADE entry resources.', uniqueItems=True, union_mode=left_to_right)] = None class-attribute instance-attribute

jsonapi: Annotated[Optional[JsonApi], StrictField(description='Information about the JSON API used')] = None class-attribute instance-attribute

meta: Annotated[ResponseMeta, StrictField(description='A meta object containing non-standard information')] instance-attribute

model_config = ConfigDict(json_encoders={datetime: lambda v: v.astimezone(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ')}) class-attribute instance-attribute

The specification mandates that datetimes must be encoded following RFC3339, which does not support fractional seconds, thus they must be stripped in the response. This can cause issues when the underlying database contains fields that do include microseconds, as filters may return unexpected results.

either_data_meta_or_errors_must_be_set()

Overwriting the existing validation function, since 'errors' MUST NOT be set.

Source code in optimade/models/optimade_json.py
391
392
393
394
395
396
397
398
399
400
401
402
403
404
@model_validator(mode="after")
def either_data_meta_or_errors_must_be_set(self) -> "Success":
    """Overwriting the existing validation function, since 'errors' MUST NOT be set."""
    required_fields = ("data", "meta")
    if not any(field in self.model_fields_set for field in required_fields):
        raise ValueError(
            f"At least one of {required_fields} MUST be specified in the top-level response."
        )

    # errors MUST be skipped
    if self.errors or "errors" in self.model_fields_set:
        raise ValueError("'errors' MUST be skipped for a successful response.")

    return self

Bases: BaseModel

A Links object specific to Error objects

Source code in optimade/models/jsonapi.py
112
113
114
115
116
117
118
119
120
class ErrorLinks(BaseModel):
    """A Links object specific to Error objects"""

    about: Annotated[
        Optional[JsonLinkType],
        StrictField(
            description="A link that leads to further details about this particular occurrence of the problem.",
        ),
    ] = None

about: Annotated[Optional[JsonLinkType], StrictField(description='A link that leads to further details about this particular occurrence of the problem.')] = None class-attribute instance-attribute

ErrorResponse

Bases: Response

errors MUST be present and data MUST be skipped

Source code in optimade/models/responses.py
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class ErrorResponse(Response):
    """errors MUST be present and data MUST be skipped"""

    meta: Annotated[
        ResponseMeta,
        StrictField(description="A meta object containing non-standard information."),
    ]
    errors: Annotated[
        list[OptimadeError],
        StrictField(
            description="A list of OPTIMADE-specific JSON API error objects, where the field detail MUST be present.",
            uniqueItems=True,
        ),
    ]

    @model_validator(mode="after")
    def data_must_be_skipped(self) -> "ErrorResponse":
        if self.data or "data" in self.model_fields_set:
            raise ValueError("data MUST be skipped for failures reporting errors.")
        return self

data: Annotated[Optional[Union[None, Resource, list[Resource]]], StrictField(description='Outputted Data', uniqueItems=True)] = None class-attribute instance-attribute

errors: Annotated[list[OptimadeError], StrictField(description='A list of OPTIMADE-specific JSON API error objects, where the field detail MUST be present.', uniqueItems=True)] instance-attribute

included: Annotated[Optional[list[Resource]], StrictField(description='A list of unique included resources', uniqueItems=True)] = None class-attribute instance-attribute

jsonapi: Annotated[Optional[JsonApi], StrictField(description='Information about the JSON API used')] = None class-attribute instance-attribute

meta: Annotated[ResponseMeta, StrictField(description='A meta object containing non-standard information.')] instance-attribute

model_config = ConfigDict(json_encoders={datetime: lambda v: v.astimezone(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ')}) class-attribute instance-attribute

The specification mandates that datetimes must be encoded following RFC3339, which does not support fractional seconds, thus they must be stripped in the response. This can cause issues when the underlying database contains fields that do include microseconds, as filters may return unexpected results.

data_must_be_skipped()

Source code in optimade/models/responses.py
45
46
47
48
49
@model_validator(mode="after")
def data_must_be_skipped(self) -> "ErrorResponse":
    if self.data or "data" in self.model_fields_set:
        raise ValueError("data MUST be skipped for failures reporting errors.")
    return self

either_data_meta_or_errors_must_be_set()

Source code in optimade/models/jsonapi.py
403
404
405
406
407
408
409
410
411
412
@model_validator(mode="after")
def either_data_meta_or_errors_must_be_set(self) -> "Response":
    required_fields = ("data", "meta", "errors")
    if not any(field in self.model_fields_set for field in required_fields):
        raise ValueError(
            f"At least one of {required_fields} MUST be specified in the top-level response"
        )
    if "errors" in self.model_fields_set and not self.errors:
        raise ValueError("Errors MUST NOT be an empty or 'null' value.")
    return self

ErrorSource

Bases: BaseModel

an object containing references to the source of the error

Source code in optimade/models/jsonapi.py
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
class ErrorSource(BaseModel):
    """an object containing references to the source of the error"""

    pointer: Annotated[
        Optional[str],
        StrictField(
            description="a JSON Pointer [RFC6901] to the associated entity in the request document "
            '[e.g. "/data" for a primary data object, or "/data/attributes/title" for a specific attribute].',
        ),
    ] = None
    parameter: Annotated[
        Optional[str],
        StrictField(
            description="a string indicating which URI query parameter caused the error.",
        ),
    ] = None

parameter: Annotated[Optional[str], StrictField(description='a string indicating which URI query parameter caused the error.')] = None class-attribute instance-attribute

pointer: Annotated[Optional[str], StrictField(description='a JSON Pointer [RFC6901] to the associated entity in the request document [e.g. "/data" for a primary data object, or "/data/attributes/title" for a specific attribute].')] = None class-attribute instance-attribute

Implementation

Bases: BaseModel

Information on the server implementation

Source code in optimade/models/optimade_json.py
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
class Implementation(BaseModel):
    """Information on the server implementation"""

    name: Annotated[
        Optional[str], StrictField(description="name of the implementation")
    ] = None

    version: Annotated[
        Optional[str],
        StrictField(description="version string of the current implementation"),
    ] = None

    homepage: Annotated[
        Optional[jsonapi.JsonLinkType],
        StrictField(
            description="A [JSON API links object](http://jsonapi.org/format/1.0/#document-links) pointing to the homepage of the implementation.",
        ),
    ] = None

    source_url: Annotated[
        Optional[jsonapi.JsonLinkType],
        StrictField(
            description="A [JSON API links object](http://jsonapi.org/format/1.0/#document-links) pointing to the implementation source, either downloadable archive or version control system.",
        ),
    ] = None

    maintainer: Annotated[
        Optional[ImplementationMaintainer],
        StrictField(
            description="A dictionary providing details about the maintainer of the implementation.",
        ),
    ] = None

    issue_tracker: Annotated[
        Optional[jsonapi.JsonLinkType],
        StrictField(
            description="A [JSON API links object](http://jsonapi.org/format/1.0/#document-links) pointing to the implementation's issue tracker.",
        ),
    ] = None

homepage: Annotated[Optional[jsonapi.JsonLinkType], StrictField(description='A [JSON API links object](http://jsonapi.org/format/1.0/#document-links) pointing to the homepage of the implementation.')] = None class-attribute instance-attribute

issue_tracker: Annotated[Optional[jsonapi.JsonLinkType], StrictField(description="A [JSON API links object](http://jsonapi.org/format/1.0/#document-links) pointing to the implementation's issue tracker.")] = None class-attribute instance-attribute

maintainer: Annotated[Optional[ImplementationMaintainer], StrictField(description='A dictionary providing details about the maintainer of the implementation.')] = None class-attribute instance-attribute

name: Annotated[Optional[str], StrictField(description='name of the implementation')] = None class-attribute instance-attribute

source_url: Annotated[Optional[jsonapi.JsonLinkType], StrictField(description='A [JSON API links object](http://jsonapi.org/format/1.0/#document-links) pointing to the implementation source, either downloadable archive or version control system.')] = None class-attribute instance-attribute

version: Annotated[Optional[str], StrictField(description='version string of the current implementation')] = None class-attribute instance-attribute

ImplementationMaintainer

Bases: BaseModel

Details about the maintainer of the implementation

Source code in optimade/models/optimade_json.py
233
234
235
236
237
238
class ImplementationMaintainer(BaseModel):
    """Details about the maintainer of the implementation"""

    email: Annotated[
        EmailStr, StrictField(description="the maintainer's email address")
    ]

email: Annotated[EmailStr, StrictField(description="the maintainer's email address")] instance-attribute

IndexInfoAttributes

Bases: BaseInfoAttributes

Attributes for Base URL Info endpoint for an Index Meta-Database

Source code in optimade/models/index_metadb.py
17
18
19
20
21
22
23
24
25
class IndexInfoAttributes(BaseInfoAttributes):
    """Attributes for Base URL Info endpoint for an Index Meta-Database"""

    is_index: Annotated[
        bool,
        StrictField(
            description="This must be `true` since this is an index meta-database (see section Index Meta-Database).",
        ),
    ] = True

api_version: Annotated[SemanticVersion, StrictField(description='Presently used full version of the OPTIMADE API.\nThe version number string MUST NOT be prefixed by, e.g., "v".\nExamples: `1.0.0`, `1.0.0-rc.2`.')] instance-attribute

available_api_versions: Annotated[list[AvailableApiVersion], StrictField(description='A list of dictionaries of available API versions at other base URLs')] instance-attribute

available_endpoints: Annotated[list[str], StrictField(description='List of available endpoints (i.e., the string to be appended to the versioned base URL).')] instance-attribute

entry_types_by_format: Annotated[dict[str, list[str]], StrictField(description='Available entry endpoints as a function of output formats.')] instance-attribute

formats: Annotated[list[str], StrictField(description='List of available output formats.')] = ['json'] class-attribute instance-attribute

is_index: Annotated[bool, StrictField(description='This must be `true` since this is an index meta-database (see section Index Meta-Database).')] = True class-attribute instance-attribute

formats_and_endpoints_must_be_valid()

Source code in optimade/models/baseinfo.py
112
113
114
115
116
117
118
119
120
121
122
@model_validator(mode="after")
def formats_and_endpoints_must_be_valid(self) -> "BaseInfoAttributes":
    for format_, endpoints in self.entry_types_by_format.items():
        if format_ not in self.formats:
            raise ValueError(f"'{format_}' must be listed in formats to be valid")
        for endpoint in endpoints:
            if endpoint not in self.available_endpoints:
                raise ValueError(
                    f"'{endpoint}' must be listed in available_endpoints to be valid"
                )
    return self

IndexInfoResource

Bases: BaseInfoResource

Index Meta-Database Base URL Info endpoint resource

Source code in optimade/models/index_metadb.py
46
47
48
49
50
51
52
53
54
55
56
57
class IndexInfoResource(BaseInfoResource):
    """Index Meta-Database Base URL Info endpoint resource"""

    attributes: IndexInfoAttributes
    relationships: Annotated[  # type: ignore[assignment]
        Optional[dict[Literal["default"], IndexRelationship]],
        StrictField(
            title="Relationships",
            description="""Reference to the Links identifier object under the `links` endpoint that the provider has chosen as their 'default' OPTIMADE API database.
A client SHOULD present this database as the first choice when an end-user chooses this provider.""",
        ),
    ]

attributes: IndexInfoAttributes instance-attribute

id: Literal['/'] = '/' class-attribute instance-attribute

meta: Annotated[Optional[Meta], StrictField(description='a meta object containing non-standard meta-information about a resource that can not be represented as an attribute or relationship.')] = None class-attribute instance-attribute

model_config = ConfigDict(json_schema_extra=resource_json_schema_extra) class-attribute instance-attribute

relationships: Annotated[Optional[dict[Literal['default'], IndexRelationship]], StrictField(title=Relationships, description="Reference to the Links identifier object under the `links` endpoint that the provider has chosen as their 'default' OPTIMADE API database.\nA client SHOULD present this database as the first choice when an end-user chooses this provider.")] instance-attribute

type: Literal['info'] = 'info' class-attribute instance-attribute

IndexInfoResponse

Bases: Success

Source code in optimade/models/responses.py
52
53
54
55
class IndexInfoResponse(Success):
    data: Annotated[
        IndexInfoResource, StrictField(description="Index meta-database /info data.")
    ]

data: Annotated[IndexInfoResource, StrictField(description='Index meta-database /info data.')] instance-attribute

errors: Annotated[Optional[list[Error]], StrictField(description='A list of unique errors', uniqueItems=True)] = None class-attribute instance-attribute

included: Annotated[Optional[list[Resource]], StrictField(description='A list of unique included resources', uniqueItems=True)] = None class-attribute instance-attribute

jsonapi: Annotated[Optional[JsonApi], StrictField(description='Information about the JSON API used')] = None class-attribute instance-attribute

meta: Annotated[ResponseMeta, StrictField(description='A meta object containing non-standard information')] instance-attribute

model_config = ConfigDict(json_encoders={datetime: lambda v: v.astimezone(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ')}) class-attribute instance-attribute

The specification mandates that datetimes must be encoded following RFC3339, which does not support fractional seconds, thus they must be stripped in the response. This can cause issues when the underlying database contains fields that do include microseconds, as filters may return unexpected results.

either_data_meta_or_errors_must_be_set()

Overwriting the existing validation function, since 'errors' MUST NOT be set.

Source code in optimade/models/optimade_json.py
391
392
393
394
395
396
397
398
399
400
401
402
403
404
@model_validator(mode="after")
def either_data_meta_or_errors_must_be_set(self) -> "Success":
    """Overwriting the existing validation function, since 'errors' MUST NOT be set."""
    required_fields = ("data", "meta")
    if not any(field in self.model_fields_set for field in required_fields):
        raise ValueError(
            f"At least one of {required_fields} MUST be specified in the top-level response."
        )

    # errors MUST be skipped
    if self.errors or "errors" in self.model_fields_set:
        raise ValueError("'errors' MUST be skipped for a successful response.")

    return self

IndexRelationship

Bases: BaseModel

Index Meta-Database relationship

Source code in optimade/models/index_metadb.py
34
35
36
37
38
39
40
41
42
43
class IndexRelationship(BaseModel):
    """Index Meta-Database relationship"""

    data: Annotated[
        Optional[RelatedLinksResource],
        StrictField(
            description="""[JSON API resource linkage](http://jsonapi.org/format/1.0/#document-links).
It MUST be either `null` or contain a single Links identifier object with the fields `id` and `type`""",
        ),
    ]

data: Annotated[Optional[RelatedLinksResource], StrictField(description='[JSON API resource linkage](http://jsonapi.org/format/1.0/#document-links).\nIt MUST be either `null` or contain a single Links identifier object with the fields `id` and `type`')] instance-attribute

InfoResponse

Bases: Success

Source code in optimade/models/responses.py
65
66
67
68
class InfoResponse(Success):
    data: Annotated[
        BaseInfoResource, StrictField(description="The implementations /info data.")
    ]

data: Annotated[BaseInfoResource, StrictField(description='The implementations /info data.')] instance-attribute

errors: Annotated[Optional[list[Error]], StrictField(description='A list of unique errors', uniqueItems=True)] = None class-attribute instance-attribute

included: Annotated[Optional[list[Resource]], StrictField(description='A list of unique included resources', uniqueItems=True)] = None class-attribute instance-attribute

jsonapi: Annotated[Optional[JsonApi], StrictField(description='Information about the JSON API used')] = None class-attribute instance-attribute

meta: Annotated[ResponseMeta, StrictField(description='A meta object containing non-standard information')] instance-attribute

model_config = ConfigDict(json_encoders={datetime: lambda v: v.astimezone(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ')}) class-attribute instance-attribute

The specification mandates that datetimes must be encoded following RFC3339, which does not support fractional seconds, thus they must be stripped in the response. This can cause issues when the underlying database contains fields that do include microseconds, as filters may return unexpected results.

either_data_meta_or_errors_must_be_set()

Overwriting the existing validation function, since 'errors' MUST NOT be set.

Source code in optimade/models/optimade_json.py
391
392
393
394
395
396
397
398
399
400
401
402
403
404
@model_validator(mode="after")
def either_data_meta_or_errors_must_be_set(self) -> "Success":
    """Overwriting the existing validation function, since 'errors' MUST NOT be set."""
    required_fields = ("data", "meta")
    if not any(field in self.model_fields_set for field in required_fields):
        raise ValueError(
            f"At least one of {required_fields} MUST be specified in the top-level response."
        )

    # errors MUST be skipped
    if self.errors or "errors" in self.model_fields_set:
        raise ValueError("'errors' MUST be skipped for a successful response.")

    return self

JsonApi

Bases: BaseModel

An object describing the server's implementation

Source code in optimade/models/jsonapi.py
58
59
60
61
62
63
64
65
66
class JsonApi(BaseModel):
    """An object describing the server's implementation"""

    version: Annotated[str, StrictField(description="Version of the json API used")] = (
        "1.0"
    )
    meta: Annotated[
        Optional[Meta], StrictField(description="Non-standard meta information")
    ] = None

meta: Annotated[Optional[Meta], StrictField(description='Non-standard meta information')] = None class-attribute instance-attribute

version: Annotated[str, StrictField(description='Version of the json API used')] = '1.0' class-attribute instance-attribute

Bases: BaseModel

A link MUST be represented as either: a string containing the link's URL or a link object.

Source code in optimade/models/jsonapi.py
41
42
43
44
45
46
47
48
49
50
51
52
class Link(BaseModel):
    """A link **MUST** be represented as either: a string containing the link's URL or a link object."""

    href: Annotated[
        AnyUrl, StrictField(description="a string containing the link's URL.")
    ]
    meta: Annotated[
        Optional[Meta],
        StrictField(
            description="a meta object containing non-standard meta-information about the link.",
        ),
    ] = None

href: Annotated[AnyUrl, StrictField(description="a string containing the link's URL.")] instance-attribute

meta: Annotated[Optional[Meta], StrictField(description='a meta object containing non-standard meta-information about the link.')] = None class-attribute instance-attribute

LinksResource

Bases: EntryResource

A Links endpoint resource object

Source code in optimade/models/links.py
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
class LinksResource(EntryResource):
    """A Links endpoint resource object"""

    type: Annotated[
        Literal["links"],
        StrictField(
            description="These objects are described in detail in the section Links Endpoint",
            pattern="^links$",
        ),
    ] = "links"

    attributes: Annotated[
        LinksResourceAttributes,
        StrictField(
            description="A dictionary containing key-value pairs representing the Links resource's properties.",
        ),
    ]

    @model_validator(mode="after")
    def relationships_must_not_be_present(self) -> "LinksResource":
        if self.relationships or "relationships" in self.model_fields_set:
            raise ValueError('"relationships" is not allowed for links resources')
        return self

attributes: Annotated[LinksResourceAttributes, StrictField(description="A dictionary containing key-value pairs representing the Links resource's properties.")] instance-attribute

id: Annotated[str, OptimadeField(description='An entry\'s ID as defined in section Definition of Terms.\n\n- **Type**: string.\n\n- **Requirements/Conventions**:\n - **Support**: MUST be supported by all implementations, MUST NOT be `null`.\n - **Query**: MUST be a queryable property with support for all mandatory filter features.\n - **Response**: REQUIRED in the response.\n\n- **Examples**:\n - `"db/1234567"`\n - `"cod/2000000"`\n - `"cod/2000000@1234567"`\n - `"nomad/L1234567890"`\n - `"42"`', support=SupportLevel.MUST, queryable=SupportLevel.MUST)] instance-attribute

meta: Annotated[Optional[Meta], StrictField(description='a meta object containing non-standard meta-information about a resource that can not be represented as an attribute or relationship.')] = None class-attribute instance-attribute

model_config = ConfigDict(json_schema_extra=resource_json_schema_extra) class-attribute instance-attribute

relationships: Annotated[Optional[EntryRelationships], StrictField(description='A dictionary containing references to other entries according to the description in section Relationships encoded as [JSON API Relationships](https://jsonapi.org/format/1.0/#document-resource-object-relationships).\nThe OPTIONAL human-readable description of the relationship MAY be provided in the `description` field inside the `meta` dictionary of the JSON API resource identifier object.')] = None class-attribute instance-attribute

type: Annotated[Literal['links'], StrictField(description='These objects are described in detail in the section Links Endpoint', pattern='^links$')] = 'links' class-attribute instance-attribute

relationships_must_not_be_present()

Source code in optimade/models/links.py
116
117
118
119
120
@model_validator(mode="after")
def relationships_must_not_be_present(self) -> "LinksResource":
    if self.relationships or "relationships" in self.model_fields_set:
        raise ValueError('"relationships" is not allowed for links resources')
    return self

LinksResourceAttributes

Bases: Attributes

Links endpoint resource object attributes

Source code in optimade/models/links.py
34
35
36
37
38
39
40
41
42
43
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
class LinksResourceAttributes(Attributes):
    """Links endpoint resource object attributes"""

    name: Annotated[
        str,
        StrictField(
            description="Human-readable name for the OPTIMADE API implementation, e.g., for use in clients to show the name to the end-user.",
        ),
    ]
    description: Annotated[
        str,
        StrictField(
            description="Human-readable description for the OPTIMADE API implementation, e.g., for use in clients to show a description to the end-user.",
        ),
    ]
    base_url: Annotated[
        Optional[JsonLinkType],
        StrictField(
            description="JSON API links object, pointing to the base URL for this implementation",
        ),
    ]

    homepage: Annotated[
        Optional[JsonLinkType],
        StrictField(
            description="JSON API links object, pointing to a homepage URL for this implementation",
        ),
    ]

    link_type: Annotated[
        LinkType,
        StrictField(
            title="Link Type",
            description="""The type of the linked relation.
MUST be one of these values: 'child', 'root', 'external', 'providers'.""",
        ),
    ]

    aggregate: Annotated[
        Optional[Aggregate],
        StrictField(
            title="Aggregate",
            description="""A string indicating whether a client that is following links to aggregate results from different OPTIMADE implementations should follow this link or not.
This flag SHOULD NOT be indicated for links where `link_type` is not `child`.

If not specified, clients MAY assume that the value is `ok`.
If specified, and the value is anything different than `ok`, the client MUST assume that the server is suggesting not to follow the link during aggregation by default (also if the value is not among the known ones, in case a future specification adds new accepted values).

Specific values indicate the reason why the server is providing the suggestion.
A client MAY follow the link anyway if it has reason to do so (e.g., if the client is looking for all test databases, it MAY follow the links marked with `aggregate`=`test`).

If specified, it MUST be one of the values listed in section Link Aggregate Options.""",
        ),
    ] = Aggregate.OK

    no_aggregate_reason: Annotated[
        Optional[str],
        StrictField(
            description="""An OPTIONAL human-readable string indicating the reason for suggesting not to aggregate results following the link.
It SHOULD NOT be present if `aggregate`=`ok`.""",
        ),
    ] = None

aggregate: Annotated[Optional[Aggregate], StrictField(title=Aggregate, description='A string indicating whether a client that is following links to aggregate results from different OPTIMADE implementations should follow this link or not.\nThis flag SHOULD NOT be indicated for links where `link_type` is not `child`.\n\nIf not specified, clients MAY assume that the value is `ok`.\nIf specified, and the value is anything different than `ok`, the client MUST assume that the server is suggesting not to follow the link during aggregation by default (also if the value is not among the known ones, in case a future specification adds new accepted values).\n\nSpecific values indicate the reason why the server is providing the suggestion.\nA client MAY follow the link anyway if it has reason to do so (e.g., if the client is looking for all test databases, it MAY follow the links marked with `aggregate`=`test`).\n\nIf specified, it MUST be one of the values listed in section Link Aggregate Options.')] = Aggregate.OK class-attribute instance-attribute

base_url: Annotated[Optional[JsonLinkType], StrictField(description='JSON API links object, pointing to the base URL for this implementation')] instance-attribute

description: Annotated[str, StrictField(description='Human-readable description for the OPTIMADE API implementation, e.g., for use in clients to show a description to the end-user.')] instance-attribute

homepage: Annotated[Optional[JsonLinkType], StrictField(description='JSON API links object, pointing to a homepage URL for this implementation')] instance-attribute

model_config = ConfigDict(extra='allow') class-attribute instance-attribute

name: Annotated[str, StrictField(description='Human-readable name for the OPTIMADE API implementation, e.g., for use in clients to show the name to the end-user.')] instance-attribute

no_aggregate_reason: Annotated[Optional[str], StrictField(description='An OPTIONAL human-readable string indicating the reason for suggesting not to aggregate results following the link.\nIt SHOULD NOT be present if `aggregate`=`ok`.')] = None class-attribute instance-attribute

check_illegal_attributes_fields()

Source code in optimade/models/jsonapi.py
330
331
332
333
334
335
336
337
338
@model_validator(mode="after")
def check_illegal_attributes_fields(self) -> "Attributes":
    illegal_fields = ("relationships", "links", "id", "type")
    for field in illegal_fields:
        if hasattr(self, field):
            raise ValueError(
                f"{illegal_fields} MUST NOT be fields under Attributes"
            )
    return self

LinksResponse

Bases: EntryResponseMany

Source code in optimade/models/responses.py
108
109
110
111
112
113
114
115
116
class LinksResponse(EntryResponseMany):
    data: Annotated[
        Union[list[LinksResource], list[dict[str, Any]]],
        StrictField(
            description="List of unique OPTIMADE links resource objects.",
            uniqueItems=True,
            union_mode="left_to_right",
        ),
    ]

data: Annotated[Union[list[LinksResource], list[dict[str, Any]]], StrictField(description='List of unique OPTIMADE links resource objects.', uniqueItems=True, union_mode=left_to_right)] instance-attribute

errors: Annotated[Optional[list[Error]], StrictField(description='A list of unique errors', uniqueItems=True)] = None class-attribute instance-attribute

included: Annotated[Optional[Union[list[EntryResource], list[dict[str, Any]]]], StrictField(description='A list of unique included OPTIMADE entry resources.', uniqueItems=True, union_mode=left_to_right)] = None class-attribute instance-attribute

jsonapi: Annotated[Optional[JsonApi], StrictField(description='Information about the JSON API used')] = None class-attribute instance-attribute

meta: Annotated[ResponseMeta, StrictField(description='A meta object containing non-standard information')] instance-attribute

model_config = ConfigDict(json_encoders={datetime: lambda v: v.astimezone(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ')}) class-attribute instance-attribute

The specification mandates that datetimes must be encoded following RFC3339, which does not support fractional seconds, thus they must be stripped in the response. This can cause issues when the underlying database contains fields that do include microseconds, as filters may return unexpected results.

either_data_meta_or_errors_must_be_set()

Overwriting the existing validation function, since 'errors' MUST NOT be set.

Source code in optimade/models/optimade_json.py
391
392
393
394
395
396
397
398
399
400
401
402
403
404
@model_validator(mode="after")
def either_data_meta_or_errors_must_be_set(self) -> "Success":
    """Overwriting the existing validation function, since 'errors' MUST NOT be set."""
    required_fields = ("data", "meta")
    if not any(field in self.model_fields_set for field in required_fields):
        raise ValueError(
            f"At least one of {required_fields} MUST be specified in the top-level response."
        )

    # errors MUST be skipped
    if self.errors or "errors" in self.model_fields_set:
        raise ValueError("'errors' MUST be skipped for a successful response.")

    return self

Meta

Bases: BaseModel

Non-standard meta-information that can not be represented as an attribute or relationship.

Source code in optimade/models/jsonapi.py
35
36
37
38
class Meta(BaseModel):
    """Non-standard meta-information that can not be represented as an attribute or relationship."""

    model_config = ConfigDict(extra="allow")

model_config = ConfigDict(extra='allow') class-attribute instance-attribute

OptimadeError

Bases: Error

detail MUST be present

Source code in optimade/models/optimade_json.py
130
131
132
133
134
135
136
137
138
class OptimadeError(jsonapi.Error):
    """detail MUST be present"""

    detail: Annotated[
        str,
        StrictField(
            description="A human-readable explanation specific to this occurrence of the problem.",
        ),
    ]

code: Annotated[Optional[str], StrictField(description='an application-specific error code, expressed as a string value.')] = None class-attribute instance-attribute

detail: Annotated[str, StrictField(description='A human-readable explanation specific to this occurrence of the problem.')] instance-attribute

id: Annotated[Optional[str], StrictField(description='A unique identifier for this particular occurrence of the problem.')] = None class-attribute instance-attribute

meta: Annotated[Optional[Meta], StrictField(description='a meta object containing non-standard meta-information about the error.')] = None class-attribute instance-attribute

source: Annotated[Optional[ErrorSource], StrictField(description='An object containing references to the source of the error')] = None class-attribute instance-attribute

status: Annotated[Optional[Annotated[str, BeforeValidator(str)]], StrictField(description='the HTTP status code applicable to this problem, expressed as a string value.')] = None class-attribute instance-attribute

title: Annotated[Optional[str], StrictField(description='A short, human-readable summary of the problem. It **SHOULD NOT** change from occurrence to occurrence of the problem, except for purposes of localization.')] = None class-attribute instance-attribute

__hash__()

Source code in optimade/models/jsonapi.py
191
192
def __hash__(self):
    return hash(self.model_dump_json())

Periodicity

Bases: IntEnum

Integer enumeration of dimension_types values

Source code in optimade/models/structures.py
48
49
50
51
52
class Periodicity(IntEnum):
    """Integer enumeration of dimension_types values"""

    APERIODIC = 0
    PERIODIC = 1

APERIODIC = 0 class-attribute instance-attribute

PERIODIC = 1 class-attribute instance-attribute

Person

Bases: BaseModel

A person, i.e., an author, editor or other.

Source code in optimade/models/references.py
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Person(BaseModel):
    """A person, i.e., an author, editor or other."""

    name: Annotated[
        str,
        OptimadeField(
            description="""Full name of the person, REQUIRED.""",
            support=SupportLevel.MUST,
            queryable=SupportLevel.OPTIONAL,
        ),
    ]

    firstname: Annotated[
        Optional[str],
        OptimadeField(
            description="""First name of the person.""",
            support=SupportLevel.OPTIONAL,
            queryable=SupportLevel.OPTIONAL,
        ),
    ] = None

    lastname: Annotated[
        Optional[str],
        OptimadeField(
            description="""Last name of the person.""",
            support=SupportLevel.OPTIONAL,
            queryable=SupportLevel.OPTIONAL,
        ),
    ] = None

firstname: Annotated[Optional[str], OptimadeField(description='First name of the person.', support=SupportLevel.OPTIONAL, queryable=SupportLevel.OPTIONAL)] = None class-attribute instance-attribute

lastname: Annotated[Optional[str], OptimadeField(description='Last name of the person.', support=SupportLevel.OPTIONAL, queryable=SupportLevel.OPTIONAL)] = None class-attribute instance-attribute

name: Annotated[str, OptimadeField(description='Full name of the person, REQUIRED.', support=SupportLevel.MUST, queryable=SupportLevel.OPTIONAL)] instance-attribute

Provider

Bases: BaseModel

Information on the database provider of the implementation.

Source code in optimade/models/optimade_json.py
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
class Provider(BaseModel):
    """Information on the database provider of the implementation."""

    name: Annotated[
        str, StrictField(description="a short name for the database provider")
    ]

    description: Annotated[
        str, StrictField(description="a longer description of the database provider")
    ]

    prefix: Annotated[
        str,
        StrictField(
            pattern=r"^[a-z]([a-z]|[0-9]|_)*$",
            description="database-provider-specific prefix as found in section Database-Provider-Specific Namespace Prefixes.",
        ),
    ]

    homepage: Annotated[
        Optional[jsonapi.JsonLinkType],
        StrictField(
            description="a [JSON API links object](http://jsonapi.org/format/1.0#document-links) "
            "pointing to homepage of the database provider, either "
            "directly as a string, or as a link object.",
        ),
    ] = None

description: Annotated[str, StrictField(description='a longer description of the database provider')] instance-attribute

homepage: Annotated[Optional[jsonapi.JsonLinkType], StrictField(description='a [JSON API links object](http://jsonapi.org/format/1.0#document-links) pointing to homepage of the database provider, either directly as a string, or as a link object.')] = None class-attribute instance-attribute

name: Annotated[str, StrictField(description='a short name for the database provider')] instance-attribute

prefix: Annotated[str, StrictField(pattern='^[a-z]([a-z]|[0-9]|_)*$', description='database-provider-specific prefix as found in section Database-Provider-Specific Namespace Prefixes.')] instance-attribute

ReferenceResource

Bases: EntryResource

The references entries describe bibliographic references.

The following properties are used to provide the bibliographic details:

  • address, annote, booktitle, chapter, crossref, edition, howpublished, institution, journal, key, month, note, number, organization, pages, publisher, school, series, title, volume, year: meanings of these properties match the BibTeX specification, values are strings;
  • bib_type: type of the reference, corresponding to type property in the BibTeX specification, value is string;
  • authors and editors: lists of person objects which are dictionaries with the following keys:
    • name: Full name of the person, REQUIRED.
    • firstname, lastname: Parts of the person's name, OPTIONAL.
  • doi and url: values are strings.
  • Requirements/Conventions:
    • Support: OPTIONAL support in implementations, i.e., any of the properties MAY be null.
    • Query: Support for queries on any of these properties is OPTIONAL. If supported, filters MAY support only a subset of comparison operators.
    • Every references entry MUST contain at least one of the properties.
Source code in optimade/models/references.py
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
class ReferenceResource(EntryResource):
    """The `references` entries describe bibliographic references.

    The following properties are used to provide the bibliographic details:

    - **address**, **annote**, **booktitle**, **chapter**, **crossref**, **edition**, **howpublished**, **institution**, **journal**, **key**, **month**, **note**, **number**, **organization**, **pages**, **publisher**, **school**, **series**, **title**, **volume**, **year**: meanings of these properties match the [BibTeX specification](http://bibtexml.sourceforge.net/btxdoc.pdf), values are strings;
    - **bib_type**: type of the reference, corresponding to **type** property in the BibTeX specification, value is string;
    - **authors** and **editors**: lists of *person objects* which are dictionaries with the following keys:
        - **name**: Full name of the person, REQUIRED.
        - **firstname**, **lastname**: Parts of the person's name, OPTIONAL.
    - **doi** and **url**: values are strings.
    - **Requirements/Conventions**:
        - **Support**: OPTIONAL support in implementations, i.e., any of the properties MAY be `null`.
        - **Query**: Support for queries on any of these properties is OPTIONAL.
            If supported, filters MAY support only a subset of comparison operators.
        - Every references entry MUST contain at least one of the properties.

    """

    type: Annotated[
        Literal["references"],
        OptimadeField(
            description="""The name of the type of an entry.
- **Type**: string.
- **Requirements/Conventions**:
    - **Support**: MUST be supported by all implementations, MUST NOT be `null`.
    - **Query**: MUST be a queryable property with support for all mandatory filter features.
    - **Response**: REQUIRED in the response.
    - MUST be an existing entry type.
    - The entry of type <type> and ID <id> MUST be returned in response to a request for `/<type>/<id>` under the versioned base URL.
- **Example**: `"structures"`""",
            pattern="^references$",
            support=SupportLevel.MUST,
            queryable=SupportLevel.MUST,
        ),
    ] = "references"
    attributes: ReferenceResourceAttributes

    @field_validator("attributes", mode="before")
    @classmethod
    def validate_attributes(cls, value: Any) -> dict[str, Any]:
        if not isinstance(value, dict):
            if isinstance(value, BaseModel):
                value = value.model_dump()
            else:
                raise TypeError("attributes field must be a mapping")
        if not any(prop[1] is not None for prop in value):
            raise ValueError("reference object must have at least one field defined")
        return value

attributes: ReferenceResourceAttributes instance-attribute

id: Annotated[str, OptimadeField(description='An entry\'s ID as defined in section Definition of Terms.\n\n- **Type**: string.\n\n- **Requirements/Conventions**:\n - **Support**: MUST be supported by all implementations, MUST NOT be `null`.\n - **Query**: MUST be a queryable property with support for all mandatory filter features.\n - **Response**: REQUIRED in the response.\n\n- **Examples**:\n - `"db/1234567"`\n - `"cod/2000000"`\n - `"cod/2000000@1234567"`\n - `"nomad/L1234567890"`\n - `"42"`', support=SupportLevel.MUST, queryable=SupportLevel.MUST)] instance-attribute

meta: Annotated[Optional[Meta], StrictField(description='a meta object containing non-standard meta-information about a resource that can not be represented as an attribute or relationship.')] = None class-attribute instance-attribute

model_config = ConfigDict(json_schema_extra=resource_json_schema_extra) class-attribute instance-attribute

relationships: Annotated[Optional[EntryRelationships], StrictField(description='A dictionary containing references to other entries according to the description in section Relationships encoded as [JSON API Relationships](https://jsonapi.org/format/1.0/#document-resource-object-relationships).\nThe OPTIONAL human-readable description of the relationship MAY be provided in the `description` field inside the `meta` dictionary of the JSON API resource identifier object.')] = None class-attribute instance-attribute

type: Annotated[Literal['references'], OptimadeField(description='The name of the type of an entry.\n- **Type**: string.\n- **Requirements/Conventions**:\n - **Support**: MUST be supported by all implementations, MUST NOT be `null`.\n - **Query**: MUST be a queryable property with support for all mandatory filter features.\n - **Response**: REQUIRED in the response.\n - MUST be an existing entry type.\n - The entry of type <type> and ID <id> MUST be returned in response to a request for `/<type>/<id>` under the versioned base URL.\n- **Example**: `"structures"`', pattern='^references$', support=SupportLevel.MUST, queryable=SupportLevel.MUST)] = 'references' class-attribute instance-attribute

validate_attributes(value) classmethod

Source code in optimade/models/references.py
323
324
325
326
327
328
329
330
331
332
333
@field_validator("attributes", mode="before")
@classmethod
def validate_attributes(cls, value: Any) -> dict[str, Any]:
    if not isinstance(value, dict):
        if isinstance(value, BaseModel):
            value = value.model_dump()
        else:
            raise TypeError("attributes field must be a mapping")
    if not any(prop[1] is not None for prop in value):
        raise ValueError("reference object must have at least one field defined")
    return value

ReferenceResourceAttributes

Bases: EntryResourceAttributes

Model that stores the attributes of a reference.

Many properties match the meaning described in the BibTeX specification.

Source code in optimade/models/references.py
 42
 43
 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
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 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
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
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
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
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
class ReferenceResourceAttributes(EntryResourceAttributes):
    """Model that stores the attributes of a reference.

    Many properties match the meaning described in the
    [BibTeX specification](http://bibtexml.sourceforge.net/btxdoc.pdf).

    """

    authors: Annotated[
        Optional[list[Person]],
        OptimadeField(
            description="List of person objects containing the authors of the reference.",
            support=SupportLevel.OPTIONAL,
            queryable=SupportLevel.OPTIONAL,
        ),
    ] = None

    editors: Annotated[
        Optional[list[Person]],
        OptimadeField(
            description="List of person objects containing the editors of the reference.",
            support=SupportLevel.OPTIONAL,
            queryable=SupportLevel.OPTIONAL,
        ),
    ] = None

    doi: Annotated[
        Optional[str],
        OptimadeField(
            description="The digital object identifier of the reference.",
            support=SupportLevel.OPTIONAL,
            queryable=SupportLevel.OPTIONAL,
        ),
    ] = None

    url: Annotated[
        Optional[AnyUrl],
        OptimadeField(
            description="The URL of the reference.",
            support=SupportLevel.OPTIONAL,
            queryable=SupportLevel.OPTIONAL,
        ),
    ] = None

    address: Annotated[
        Optional[str],
        OptimadeField(
            description="Meaning of property matches the BiBTeX specification.",
            support=SupportLevel.OPTIONAL,
            queryable=SupportLevel.OPTIONAL,
        ),
    ] = None

    annote: Annotated[
        Optional[str],
        OptimadeField(
            description="Meaning of property matches the BiBTeX specification.",
            support=SupportLevel.OPTIONAL,
            queryable=SupportLevel.OPTIONAL,
        ),
    ] = None

    booktitle: Annotated[
        Optional[str],
        OptimadeField(
            description="Meaning of property matches the BiBTeX specification.",
            support=SupportLevel.OPTIONAL,
            queryable=SupportLevel.OPTIONAL,
        ),
    ] = None

    chapter: Annotated[
        Optional[str],
        OptimadeField(
            description="Meaning of property matches the BiBTeX specification.",
            support=SupportLevel.OPTIONAL,
            queryable=SupportLevel.OPTIONAL,
        ),
    ] = None

    crossref: Annotated[
        Optional[str],
        OptimadeField(
            description="Meaning of property matches the BiBTeX specification.",
            support=SupportLevel.OPTIONAL,
            queryable=SupportLevel.OPTIONAL,
        ),
    ] = None

    edition: Annotated[
        Optional[str],
        OptimadeField(
            description="Meaning of property matches the BiBTeX specification.",
            support=SupportLevel.OPTIONAL,
            queryable=SupportLevel.OPTIONAL,
        ),
    ] = None

    howpublished: Annotated[
        Optional[str],
        OptimadeField(
            description="Meaning of property matches the BiBTeX specification.",
            support=SupportLevel.OPTIONAL,
            queryable=SupportLevel.OPTIONAL,
        ),
    ] = None

    institution: Annotated[
        Optional[str],
        OptimadeField(
            description="Meaning of property matches the BiBTeX specification.",
            support=SupportLevel.OPTIONAL,
            queryable=SupportLevel.OPTIONAL,
        ),
    ] = None

    journal: Annotated[
        Optional[str],
        OptimadeField(
            description="Meaning of property matches the BiBTeX specification.",
            support=SupportLevel.OPTIONAL,
            queryable=SupportLevel.OPTIONAL,
        ),
    ] = None

    key: Annotated[
        Optional[str],
        OptimadeField(
            description="Meaning of property matches the BiBTeX specification.",
            support=SupportLevel.OPTIONAL,
            queryable=SupportLevel.OPTIONAL,
        ),
    ] = None

    month: Annotated[
        Optional[str],
        OptimadeField(
            description="Meaning of property matches the BiBTeX specification.",
            support=SupportLevel.OPTIONAL,
            queryable=SupportLevel.OPTIONAL,
        ),
    ] = None

    note: Annotated[
        Optional[str],
        OptimadeField(
            description="Meaning of property matches the BiBTeX specification.",
            support=SupportLevel.OPTIONAL,
            queryable=SupportLevel.OPTIONAL,
        ),
    ] = None

    number: Annotated[
        Optional[str],
        OptimadeField(
            description="Meaning of property matches the BiBTeX specification.",
            support=SupportLevel.OPTIONAL,
            queryable=SupportLevel.OPTIONAL,
        ),
    ] = None

    organization: Annotated[
        Optional[str],
        OptimadeField(
            description="Meaning of property matches the BiBTeX specification.",
            support=SupportLevel.OPTIONAL,
            queryable=SupportLevel.OPTIONAL,
        ),
    ] = None

    pages: Annotated[
        Optional[str],
        OptimadeField(
            description="Meaning of property matches the BiBTeX specification.",
            support=SupportLevel.OPTIONAL,
            queryable=SupportLevel.OPTIONAL,
        ),
    ] = None

    publisher: Annotated[
        Optional[str],
        OptimadeField(
            description="Meaning of property matches the BiBTeX specification.",
            support=SupportLevel.OPTIONAL,
            queryable=SupportLevel.OPTIONAL,
        ),
    ] = None

    school: Annotated[
        Optional[str],
        OptimadeField(
            description="Meaning of property matches the BiBTeX specification.",
            support=SupportLevel.OPTIONAL,
            queryable=SupportLevel.OPTIONAL,
        ),
    ] = None

    series: Annotated[
        Optional[str],
        OptimadeField(
            description="Meaning of property matches the BiBTeX specification.",
            support=SupportLevel.OPTIONAL,
            queryable=SupportLevel.OPTIONAL,
        ),
    ] = None

    title: Annotated[
        Optional[str],
        OptimadeField(
            description="Meaning of property matches the BiBTeX specification.",
            support=SupportLevel.OPTIONAL,
            queryable=SupportLevel.OPTIONAL,
        ),
    ] = None

    bib_type: Annotated[
        Optional[str],
        OptimadeField(
            description="Type of the reference, corresponding to the **type** property in the BiBTeX specification.",
            support=SupportLevel.OPTIONAL,
            queryable=SupportLevel.OPTIONAL,
        ),
    ] = None

    volume: Annotated[
        Optional[str],
        OptimadeField(
            description="Meaning of property matches the BiBTeX specification.",
            support=SupportLevel.OPTIONAL,
            queryable=SupportLevel.OPTIONAL,
        ),
    ] = None

    year: Annotated[
        Optional[str],
        OptimadeField(
            description="Meaning of property matches the BiBTeX specification.",
            support=SupportLevel.OPTIONAL,
            queryable=SupportLevel.OPTIONAL,
        ),
    ] = None

address: Annotated[Optional[str], OptimadeField(description='Meaning of property matches the BiBTeX specification.', support=SupportLevel.OPTIONAL, queryable=SupportLevel.OPTIONAL)] = None class-attribute instance-attribute

annote: Annotated[Optional[str], OptimadeField(description='Meaning of property matches the BiBTeX specification.', support=SupportLevel.OPTIONAL, queryable=SupportLevel.OPTIONAL)] = None class-attribute instance-attribute

authors: Annotated[Optional[list[Person]], OptimadeField(description='List of person objects containing the authors of the reference.', support=SupportLevel.OPTIONAL, queryable=SupportLevel.OPTIONAL)] = None class-attribute instance-attribute

bib_type: Annotated[Optional[str], OptimadeField(description='Type of the reference, corresponding to the **type** property in the BiBTeX specification.', support=SupportLevel.OPTIONAL, queryable=SupportLevel.OPTIONAL)] = None class-attribute instance-attribute

booktitle: Annotated[Optional[str], OptimadeField(description='Meaning of property matches the BiBTeX specification.', support=SupportLevel.OPTIONAL, queryable=SupportLevel.OPTIONAL)] = None class-attribute instance-attribute

chapter: Annotated[Optional[str], OptimadeField(description='Meaning of property matches the BiBTeX specification.', support=SupportLevel.OPTIONAL, queryable=SupportLevel.OPTIONAL)] = None class-attribute instance-attribute

crossref: Annotated[Optional[str], OptimadeField(description='Meaning of property matches the BiBTeX specification.', support=SupportLevel.OPTIONAL, queryable=SupportLevel.OPTIONAL)] = None class-attribute instance-attribute

doi: Annotated[Optional[str], OptimadeField(description='The digital object identifier of the reference.', support=SupportLevel.OPTIONAL, queryable=SupportLevel.OPTIONAL)] = None class-attribute instance-attribute

edition: Annotated[Optional[str], OptimadeField(description='Meaning of property matches the BiBTeX specification.', support=SupportLevel.OPTIONAL, queryable=SupportLevel.OPTIONAL)] = None class-attribute instance-attribute

editors: Annotated[Optional[list[Person]], OptimadeField(description='List of person objects containing the editors of the reference.', support=SupportLevel.OPTIONAL, queryable=SupportLevel.OPTIONAL)] = None class-attribute instance-attribute

howpublished: Annotated[Optional[str], OptimadeField(description='Meaning of property matches the BiBTeX specification.', support=SupportLevel.OPTIONAL, queryable=SupportLevel.OPTIONAL)] = None class-attribute instance-attribute

immutable_id: Annotated[Optional[str], OptimadeField(description='The entry\'s immutable ID (e.g., an UUID). This is important for databases having preferred IDs that point to "the latest version" of a record, but still offer access to older variants. This ID maps to the version-specific record, in case it changes in the future.\n\n- **Type**: string.\n\n- **Requirements/Conventions**:\n - **Support**: OPTIONAL support in implementations, i.e., MAY be `null`.\n - **Query**: MUST be a queryable property with support for all mandatory filter features.\n\n- **Examples**:\n - `"8bd3e750-b477-41a0-9b11-3a799f21b44f"`\n - `"fjeiwoj,54;@=%<>#32"` (Strings that are not URL-safe are allowed.)', support=SupportLevel.OPTIONAL, queryable=SupportLevel.MUST)] = None class-attribute instance-attribute

institution: Annotated[Optional[str], OptimadeField(description='Meaning of property matches the BiBTeX specification.', support=SupportLevel.OPTIONAL, queryable=SupportLevel.OPTIONAL)] = None class-attribute instance-attribute

journal: Annotated[Optional[str], OptimadeField(description='Meaning of property matches the BiBTeX specification.', support=SupportLevel.OPTIONAL, queryable=SupportLevel.OPTIONAL)] = None class-attribute instance-attribute

key: Annotated[Optional[str], OptimadeField(description='Meaning of property matches the BiBTeX specification.', support=SupportLevel.OPTIONAL, queryable=SupportLevel.OPTIONAL)] = None class-attribute instance-attribute

last_modified: Annotated[Optional[datetime], OptimadeField(description='Date and time representing when the entry was last modified.\n\n- **Type**: timestamp.\n\n- **Requirements/Conventions**:\n - **Support**: SHOULD be supported by all implementations, i.e., SHOULD NOT be `null`.\n - **Query**: MUST be a queryable property with support for all mandatory filter features.\n - **Response**: REQUIRED in the response unless the query parameter `response_fields` is present and does not include this property.\n\n- **Example**:\n - As part of JSON response format: `"2007-04-05T14:30:20Z"` (i.e., encoded as an [RFC 3339 Internet Date/Time Format](https://tools.ietf.org/html/rfc3339#section-5.6) string.)', support=SupportLevel.SHOULD, queryable=SupportLevel.MUST)] instance-attribute

model_config = ConfigDict(extra='allow') class-attribute instance-attribute

month: Annotated[Optional[str], OptimadeField(description='Meaning of property matches the BiBTeX specification.', support=SupportLevel.OPTIONAL, queryable=SupportLevel.OPTIONAL)] = None class-attribute instance-attribute

note: Annotated[Optional[str], OptimadeField(description='Meaning of property matches the BiBTeX specification.', support=SupportLevel.OPTIONAL, queryable=SupportLevel.OPTIONAL)] = None class-attribute instance-attribute

number: Annotated[Optional[str], OptimadeField(description='Meaning of property matches the BiBTeX specification.', support=SupportLevel.OPTIONAL, queryable=SupportLevel.OPTIONAL)] = None class-attribute instance-attribute

organization: Annotated[Optional[str], OptimadeField(description='Meaning of property matches the BiBTeX specification.', support=SupportLevel.OPTIONAL, queryable=SupportLevel.OPTIONAL)] = None class-attribute instance-attribute

pages: Annotated[Optional[str], OptimadeField(description='Meaning of property matches the BiBTeX specification.', support=SupportLevel.OPTIONAL, queryable=SupportLevel.OPTIONAL)] = None class-attribute instance-attribute

publisher: Annotated[Optional[str], OptimadeField(description='Meaning of property matches the BiBTeX specification.', support=SupportLevel.OPTIONAL, queryable=SupportLevel.OPTIONAL)] = None class-attribute instance-attribute

school: Annotated[Optional[str], OptimadeField(description='Meaning of property matches the BiBTeX specification.', support=SupportLevel.OPTIONAL, queryable=SupportLevel.OPTIONAL)] = None class-attribute instance-attribute

series: Annotated[Optional[str], OptimadeField(description='Meaning of property matches the BiBTeX specification.', support=SupportLevel.OPTIONAL, queryable=SupportLevel.OPTIONAL)] = None class-attribute instance-attribute

title: Annotated[Optional[str], OptimadeField(description='Meaning of property matches the BiBTeX specification.', support=SupportLevel.OPTIONAL, queryable=SupportLevel.OPTIONAL)] = None class-attribute instance-attribute

url: Annotated[Optional[AnyUrl], OptimadeField(description='The URL of the reference.', support=SupportLevel.OPTIONAL, queryable=SupportLevel.OPTIONAL)] = None class-attribute instance-attribute

volume: Annotated[Optional[str], OptimadeField(description='Meaning of property matches the BiBTeX specification.', support=SupportLevel.OPTIONAL, queryable=SupportLevel.OPTIONAL)] = None class-attribute instance-attribute

year: Annotated[Optional[str], OptimadeField(description='Meaning of property matches the BiBTeX specification.', support=SupportLevel.OPTIONAL, queryable=SupportLevel.OPTIONAL)] = None class-attribute instance-attribute

cast_immutable_id_to_str(value) classmethod

Convenience validator for casting immutable_id to a string.

Source code in optimade/models/entries.py
110
111
112
113
114
115
116
117
@field_validator("immutable_id", mode="before")
@classmethod
def cast_immutable_id_to_str(cls, value: Any) -> str:
    """Convenience validator for casting `immutable_id` to a string."""
    if value is not None and not isinstance(value, str):
        value = str(value)

    return value

check_illegal_attributes_fields()

Source code in optimade/models/jsonapi.py
330
331
332
333
334
335
336
337
338
@model_validator(mode="after")
def check_illegal_attributes_fields(self) -> "Attributes":
    illegal_fields = ("relationships", "links", "id", "type")
    for field in illegal_fields:
        if hasattr(self, field):
            raise ValueError(
                f"{illegal_fields} MUST NOT be fields under Attributes"
            )
    return self

ReferenceResponseMany

Bases: EntryResponseMany

Source code in optimade/models/responses.py
150
151
152
153
154
155
156
157
158
class ReferenceResponseMany(EntryResponseMany):
    data: Annotated[
        Union[list[ReferenceResource], list[dict[str, Any]]],
        StrictField(
            description="List of unique OPTIMADE references entry resource objects.&qu