Skip to content

baseinfo

VERSIONED_BASE_URL_PATTERN = '^.+/v[0-1](\\.[0-9]+)*/?$' module-attribute

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 instance-attribute

version 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
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
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[
        bool | None,
        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
    license: Annotated[
        Link | AnyHttpUrl | None,
        StrictField(
            ...,
            description="""A [JSON API links object](http://jsonapi.org/format/1.0/#document-links) giving a URL to a web page containing a human-readable text describing the license (or licensing options if there are multiple) covering all the data and metadata provided by this database.
Clients are advised not to try automated parsing of this link or its content, but rather rely on the field `available_licenses` instead.""",
        ),
    ] = None
    available_licenses: Annotated[
        list[str] | None,
        StrictField(
            ...,
            description="""List of [SPDX license identifiers](https://spdx.org/licenses/) specifying a set of alternative licenses available to the client for licensing the complete database, i.e., all the entries, metadata, and the content and structure of the database itself.

If more than one license is available to the client, the identifier of each one SHOULD be included in the list.
Inclusion of a license identifier in the list is a commitment of the database that the rights are in place to grant clients access to all the individual entries, all metadata, and the content and structure of the database itself according to the terms of any of these licenses (at the choice of the client).
If the licensing information provided via the field license omits licensing options specified in `available_licenses`, or if it otherwise contradicts them, a client MUST still be allowed to interpret the inclusion of a license in `available_licenses` as a full commitment from the database without exceptions, under the respective licenses.
If the database cannot make that commitment, e.g., if only part of the database is available under a license, the corresponding license identifier MUST NOT appear in `available_licenses` (but, rather, the field license is to be used to clarify the licensing situation.)
An empty list indicates that none of the SPDX licenses apply and that the licensing situation is clarified in human readable form in the field `license`.
An unknown value means that the database makes no commitment.""",
        ),
    ] = None

    available_licenses_for_entries: Annotated[
        list[str] | None,
        StrictField(
            ...,
            description="""List of [SPDX license identifiers](https://spdx.org/licenses/) specifying a set of additional alternative licenses available to the client for licensing individual, and non-substantial sets of, database entries, metadata, and extracts from the database that do not constitute substantial parts of the database.

Note that the definition of the field `available_licenses` implies that licenses specified in that field are available also for the licensing specified by this field, even if they are not explicitly included in the field `available_licenses_for_entries` or if it is `null` (however, the opposite relationship does not hold).
If `available_licenses` is unknown, only the licenses in `available_licenses_for_entries` apply.""",
        ),
    ] = None

    @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 instance-attribute

available_api_versions instance-attribute

available_endpoints instance-attribute

available_licenses = None class-attribute instance-attribute

available_licenses_for_entries = None class-attribute instance-attribute

entry_types_by_format instance-attribute

formats = ['json'] class-attribute instance-attribute

is_index = False class-attribute instance-attribute

license = None class-attribute instance-attribute

formats_and_endpoints_must_be_valid()

Source code in optimade/models/baseinfo.py
145
146
147
148
149
150
151
152
153
154
155
@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
158
159
160
161
class BaseInfoResource(Resource):
    id: Literal["/"] = "/"
    type: Literal["info"] = "info"
    attributes: BaseInfoAttributes

attributes instance-attribute

id = '/' class-attribute instance-attribute

meta = None class-attribute instance-attribute

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

relationships = None class-attribute instance-attribute

type = 'info' class-attribute instance-attribute