diff --git a/openapi/index_openapi.json b/openapi/index_openapi.json index 695068f64..b96ce4177 100644 --- a/openapi/index_openapi.json +++ b/openapi/index_openapi.json @@ -44,32 +44,36 @@ "operationId": "get_links_index_optimade_v0_links_get", "parameters": [ { - "description": "See [the full and latest OPTiMaDe spec](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst) for filter query syntax.", + "description": "A filter string, in the format described in section [API Filtering Format Specification](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#api-filtering-format-specification) of the [OPTiMaDe spec](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst).", "required": false, "schema": { "title": "Filter", "type": "string", - "description": "See [the full and latest OPTiMaDe spec](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst) for filter query syntax.", + "description": "A filter string, in the format described in section [API Filtering Format Specification](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#api-filtering-format-specification) of the [OPTiMaDe spec](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst).", "default": "" }, "name": "filter", "in": "query" }, { + "description": "The output format requested (see section [Response Format](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#response-format) in the spec). Defaults to the format string 'json', which specifies the standard output format described in this specification.\n**Example**: http://example.com/optimade/v0.9/structures?response_format=xml", "required": false, "schema": { "title": "Response Format", "type": "string", + "description": "The output format requested (see section [Response Format](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#response-format) in the spec). Defaults to the format string 'json', which specifies the standard output format described in this specification.\n**Example**: http://example.com/optimade/v0.9/structures?response_format=xml", "default": "json" }, "name": "response_format", "in": "query" }, { + "description": "An email address of the user making the request. The email SHOULD be that of a person and not an automatic system.\n**Example**: http://example.com/optimade/v0.9/structures?email_address=user@example.com", "required": false, "schema": { "title": "Email Address", "type": "string", + "description": "An email address of the user making the request. The email SHOULD be that of a person and not an automatic system.\n**Example**: http://example.com/optimade/v0.9/structures?email_address=user@example.com", "format": "email", "default": "" }, @@ -77,86 +81,104 @@ "in": "query" }, { + "description": "A comma-delimited set of fields to be provided in the output. If provided, these fields MUST be returned along with the REQUIRED fields. Other OPTIONAL fields MUST NOT be returned when this parameter is present.\n**Example**: http://example.com/optimade/v0.9/structures?response_fields=last_modified,nsites", "required": false, "schema": { "title": "Response Fields", + "pattern": "([a-z_][a-z_0-9]*(,[a-z_][a-z_0-9]*)*)?", "type": "string", + "description": "A comma-delimited set of fields to be provided in the output. If provided, these fields MUST be returned along with the REQUIRED fields. Other OPTIONAL fields MUST NOT be returned when this parameter is present.\n**Example**: http://example.com/optimade/v0.9/structures?response_fields=last_modified,nsites", "default": "" }, "name": "response_fields", "in": "query" }, { + "description": "If supporting sortable queries, an implementation MUST use the `sort` query parameter with format as specified by [JSON API 1.0](https://jsonapi.org/format/1.0/#fetching-sorting).\n\nAn implementation MAY support multiple sort fields for a single query. If it does, it again MUST conform to the JSON API 1.0 specification.\n\nIf an implementation supports sorting for an [entry listing endpoint](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#entry-listing-endpoints), then the `/info/` endpoint MUST include, for each field name `` in its `data.properties.` response value that can be used for sorting, the key `sortable` with value `true`. If a field name under an entry listing endpoint supporting sorting cannot be used for sorting, the server MUST either leave out the `sortable` key or set it equal to `false` for the specific field name. The set of field names, with `sortable` equal to `true` are allowed to be used in the \"sort fields\" list according to its definition in the JSON API 1.0 specification. The field `sortable` is in addition to each property description (and the OPTIONAL field `unit`). An example is shown in section [Entry Listing Info Endpoints](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#entry-listing-info-endpoints).", "required": false, "schema": { "title": "Sort", + "pattern": "([a-z_][a-z_0-9]*(,[a-z_][a-z_0-9]*)*)?", "type": "string", + "description": "If supporting sortable queries, an implementation MUST use the `sort` query parameter with format as specified by [JSON API 1.0](https://jsonapi.org/format/1.0/#fetching-sorting).\n\nAn implementation MAY support multiple sort fields for a single query. If it does, it again MUST conform to the JSON API 1.0 specification.\n\nIf an implementation supports sorting for an [entry listing endpoint](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#entry-listing-endpoints), then the `/info/` endpoint MUST include, for each field name `` in its `data.properties.` response value that can be used for sorting, the key `sortable` with value `true`. If a field name under an entry listing endpoint supporting sorting cannot be used for sorting, the server MUST either leave out the `sortable` key or set it equal to `false` for the specific field name. The set of field names, with `sortable` equal to `true` are allowed to be used in the \"sort fields\" list according to its definition in the JSON API 1.0 specification. The field `sortable` is in addition to each property description (and the OPTIONAL field `unit`). An example is shown in section [Entry Listing Info Endpoints](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#entry-listing-info-endpoints).", "default": "" }, "name": "sort", "in": "query" }, { + "description": "Sets a numerical limit on the number of entries returned. See [JSON API 1.0](https://jsonapi.org/format/1.0/#fetching-pagination). The API implementation MUST return no more than the number specified. It MAY return fewer. The database MAY have a maximum limit and not accept larger numbers (in which case an error code -- 403 Forbidden -- MUST be returned). The default limit value is up to the API implementation to decide.\n\nA server MUST implement pagination in the case of no user-specified `sort` parameter (via the `links` response field, see section [JSON Response Schema: Common Fields](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#json-response-schema-common-fields)). A server MAY implement pagination in concert with `sort`.", "required": false, "schema": { "title": "Page Limit", "minimum": 0.0, "type": "integer", + "description": "Sets a numerical limit on the number of entries returned. See [JSON API 1.0](https://jsonapi.org/format/1.0/#fetching-pagination). The API implementation MUST return no more than the number specified. It MAY return fewer. The database MAY have a maximum limit and not accept larger numbers (in which case an error code -- 403 Forbidden -- MUST be returned). The default limit value is up to the API implementation to decide.\n\nA server MUST implement pagination in the case of no user-specified `sort` parameter (via the `links` response field, see section [JSON Response Schema: Common Fields](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#json-response-schema-common-fields)). A server MAY implement pagination in concert with `sort`.", "default": 20 }, "name": "page_limit", "in": "query" }, { + "description": "RECOMMENDED for use with _offset-based_ pagination: using `page_offset` and `page_limit` is RECOMMENDED.\n**Example**: Skip 50 structures and fetch up to 100: `/structures?page_offset=50&page_limit=100`.", "required": false, "schema": { "title": "Page Offset", "minimum": 0.0, "type": "integer", + "description": "RECOMMENDED for use with _offset-based_ pagination: using `page_offset` and `page_limit` is RECOMMENDED.\n**Example**: Skip 50 structures and fetch up to 100: `/structures?page_offset=50&page_limit=100`.", "default": 0 }, "name": "page_offset", "in": "query" }, { + "description": "RECOMMENDED for use with _page-based_ pagination: using `page_number` and `page_limit` is RECOMMENDED. It is RECOMMENDED that the first page has number 1, i.e., that `page_number` is 1-based.\n**Example**: Fetch page 2 of up to 50 structures per page: `/structures?page_number=2&page_limit=50`.", "required": false, "schema": { - "title": "Page Page", + "title": "Page Number", "minimum": 0.0, "type": "integer", + "description": "RECOMMENDED for use with _page-based_ pagination: using `page_number` and `page_limit` is RECOMMENDED. It is RECOMMENDED that the first page has number 1, i.e., that `page_number` is 1-based.\n**Example**: Fetch page 2 of up to 50 structures per page: `/structures?page_number=2&page_limit=50`.", "default": 0 }, - "name": "page_page", + "name": "page_number", "in": "query" }, { + "description": "RECOMMENDED for use with _cursor-based_ pagination: using `page_cursor` and `page_limit` is RECOMMENDED.", "required": false, "schema": { "title": "Page Cursor", "minimum": 0.0, "type": "integer", + "description": "RECOMMENDED for use with _cursor-based_ pagination: using `page_cursor` and `page_limit` is RECOMMENDED.", "default": 0 }, "name": "page_cursor", "in": "query" }, { + "description": "RECOMMENDED for use with _value-based_ pagination: using `page_above`/`page_below` and `page_limit` is RECOMMENDED.\n**Example**: Fetch up to 100 structures above sort-field value 4000 (in this example, server chooses to fetch results sorted by increasing id, so `page_above` value refers to an `id` value): `/structures?page_above=4000&page_limit=100`.", "required": false, "schema": { "title": "Page Above", "minimum": 0.0, "type": "integer", + "description": "RECOMMENDED for use with _value-based_ pagination: using `page_above`/`page_below` and `page_limit` is RECOMMENDED.\n**Example**: Fetch up to 100 structures above sort-field value 4000 (in this example, server chooses to fetch results sorted by increasing id, so `page_above` value refers to an `id` value): `/structures?page_above=4000&page_limit=100`.", "default": 0 }, "name": "page_above", "in": "query" }, { + "description": "RECOMMENDED for use with _value-based_ pagination: using `page_above`/`page_below` and `page_limit` is RECOMMENDED.", "required": false, "schema": { "title": "Page Below", "minimum": 0.0, "type": "integer", + "description": "RECOMMENDED for use with _value-based_ pagination: using `page_above`/`page_below` and `page_limit` is RECOMMENDED.", "default": 0 }, "name": "page_below", diff --git a/openapi/openapi.json b/openapi/openapi.json index a2182c1ec..d669ba976 100644 --- a/openapi/openapi.json +++ b/openapi/openapi.json @@ -94,32 +94,36 @@ "operationId": "get_links_optimade_v0_links_get", "parameters": [ { - "description": "See [the full and latest OPTiMaDe spec](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst) for filter query syntax.", + "description": "A filter string, in the format described in section [API Filtering Format Specification](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#api-filtering-format-specification) of the [OPTiMaDe spec](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst).", "required": false, "schema": { "title": "Filter", "type": "string", - "description": "See [the full and latest OPTiMaDe spec](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst) for filter query syntax.", + "description": "A filter string, in the format described in section [API Filtering Format Specification](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#api-filtering-format-specification) of the [OPTiMaDe spec](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst).", "default": "" }, "name": "filter", "in": "query" }, { + "description": "The output format requested (see section [Response Format](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#response-format) in the spec). Defaults to the format string 'json', which specifies the standard output format described in this specification.\n**Example**: http://example.com/optimade/v0.9/structures?response_format=xml", "required": false, "schema": { "title": "Response Format", "type": "string", + "description": "The output format requested (see section [Response Format](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#response-format) in the spec). Defaults to the format string 'json', which specifies the standard output format described in this specification.\n**Example**: http://example.com/optimade/v0.9/structures?response_format=xml", "default": "json" }, "name": "response_format", "in": "query" }, { + "description": "An email address of the user making the request. The email SHOULD be that of a person and not an automatic system.\n**Example**: http://example.com/optimade/v0.9/structures?email_address=user@example.com", "required": false, "schema": { "title": "Email Address", "type": "string", + "description": "An email address of the user making the request. The email SHOULD be that of a person and not an automatic system.\n**Example**: http://example.com/optimade/v0.9/structures?email_address=user@example.com", "format": "email", "default": "" }, @@ -127,86 +131,104 @@ "in": "query" }, { + "description": "A comma-delimited set of fields to be provided in the output. If provided, these fields MUST be returned along with the REQUIRED fields. Other OPTIONAL fields MUST NOT be returned when this parameter is present.\n**Example**: http://example.com/optimade/v0.9/structures?response_fields=last_modified,nsites", "required": false, "schema": { "title": "Response Fields", + "pattern": "([a-z_][a-z_0-9]*(,[a-z_][a-z_0-9]*)*)?", "type": "string", + "description": "A comma-delimited set of fields to be provided in the output. If provided, these fields MUST be returned along with the REQUIRED fields. Other OPTIONAL fields MUST NOT be returned when this parameter is present.\n**Example**: http://example.com/optimade/v0.9/structures?response_fields=last_modified,nsites", "default": "" }, "name": "response_fields", "in": "query" }, { + "description": "If supporting sortable queries, an implementation MUST use the `sort` query parameter with format as specified by [JSON API 1.0](https://jsonapi.org/format/1.0/#fetching-sorting).\n\nAn implementation MAY support multiple sort fields for a single query. If it does, it again MUST conform to the JSON API 1.0 specification.\n\nIf an implementation supports sorting for an [entry listing endpoint](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#entry-listing-endpoints), then the `/info/` endpoint MUST include, for each field name `` in its `data.properties.` response value that can be used for sorting, the key `sortable` with value `true`. If a field name under an entry listing endpoint supporting sorting cannot be used for sorting, the server MUST either leave out the `sortable` key or set it equal to `false` for the specific field name. The set of field names, with `sortable` equal to `true` are allowed to be used in the \"sort fields\" list according to its definition in the JSON API 1.0 specification. The field `sortable` is in addition to each property description (and the OPTIONAL field `unit`). An example is shown in section [Entry Listing Info Endpoints](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#entry-listing-info-endpoints).", "required": false, "schema": { "title": "Sort", + "pattern": "([a-z_][a-z_0-9]*(,[a-z_][a-z_0-9]*)*)?", "type": "string", + "description": "If supporting sortable queries, an implementation MUST use the `sort` query parameter with format as specified by [JSON API 1.0](https://jsonapi.org/format/1.0/#fetching-sorting).\n\nAn implementation MAY support multiple sort fields for a single query. If it does, it again MUST conform to the JSON API 1.0 specification.\n\nIf an implementation supports sorting for an [entry listing endpoint](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#entry-listing-endpoints), then the `/info/` endpoint MUST include, for each field name `` in its `data.properties.` response value that can be used for sorting, the key `sortable` with value `true`. If a field name under an entry listing endpoint supporting sorting cannot be used for sorting, the server MUST either leave out the `sortable` key or set it equal to `false` for the specific field name. The set of field names, with `sortable` equal to `true` are allowed to be used in the \"sort fields\" list according to its definition in the JSON API 1.0 specification. The field `sortable` is in addition to each property description (and the OPTIONAL field `unit`). An example is shown in section [Entry Listing Info Endpoints](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#entry-listing-info-endpoints).", "default": "" }, "name": "sort", "in": "query" }, { + "description": "Sets a numerical limit on the number of entries returned. See [JSON API 1.0](https://jsonapi.org/format/1.0/#fetching-pagination). The API implementation MUST return no more than the number specified. It MAY return fewer. The database MAY have a maximum limit and not accept larger numbers (in which case an error code -- 403 Forbidden -- MUST be returned). The default limit value is up to the API implementation to decide.\n\nA server MUST implement pagination in the case of no user-specified `sort` parameter (via the `links` response field, see section [JSON Response Schema: Common Fields](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#json-response-schema-common-fields)). A server MAY implement pagination in concert with `sort`.", "required": false, "schema": { "title": "Page Limit", "minimum": 0.0, "type": "integer", + "description": "Sets a numerical limit on the number of entries returned. See [JSON API 1.0](https://jsonapi.org/format/1.0/#fetching-pagination). The API implementation MUST return no more than the number specified. It MAY return fewer. The database MAY have a maximum limit and not accept larger numbers (in which case an error code -- 403 Forbidden -- MUST be returned). The default limit value is up to the API implementation to decide.\n\nA server MUST implement pagination in the case of no user-specified `sort` parameter (via the `links` response field, see section [JSON Response Schema: Common Fields](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#json-response-schema-common-fields)). A server MAY implement pagination in concert with `sort`.", "default": 20 }, "name": "page_limit", "in": "query" }, { + "description": "RECOMMENDED for use with _offset-based_ pagination: using `page_offset` and `page_limit` is RECOMMENDED.\n**Example**: Skip 50 structures and fetch up to 100: `/structures?page_offset=50&page_limit=100`.", "required": false, "schema": { "title": "Page Offset", "minimum": 0.0, "type": "integer", + "description": "RECOMMENDED for use with _offset-based_ pagination: using `page_offset` and `page_limit` is RECOMMENDED.\n**Example**: Skip 50 structures and fetch up to 100: `/structures?page_offset=50&page_limit=100`.", "default": 0 }, "name": "page_offset", "in": "query" }, { + "description": "RECOMMENDED for use with _page-based_ pagination: using `page_number` and `page_limit` is RECOMMENDED. It is RECOMMENDED that the first page has number 1, i.e., that `page_number` is 1-based.\n**Example**: Fetch page 2 of up to 50 structures per page: `/structures?page_number=2&page_limit=50`.", "required": false, "schema": { - "title": "Page Page", + "title": "Page Number", "minimum": 0.0, "type": "integer", + "description": "RECOMMENDED for use with _page-based_ pagination: using `page_number` and `page_limit` is RECOMMENDED. It is RECOMMENDED that the first page has number 1, i.e., that `page_number` is 1-based.\n**Example**: Fetch page 2 of up to 50 structures per page: `/structures?page_number=2&page_limit=50`.", "default": 0 }, - "name": "page_page", + "name": "page_number", "in": "query" }, { + "description": "RECOMMENDED for use with _cursor-based_ pagination: using `page_cursor` and `page_limit` is RECOMMENDED.", "required": false, "schema": { "title": "Page Cursor", "minimum": 0.0, "type": "integer", + "description": "RECOMMENDED for use with _cursor-based_ pagination: using `page_cursor` and `page_limit` is RECOMMENDED.", "default": 0 }, "name": "page_cursor", "in": "query" }, { + "description": "RECOMMENDED for use with _value-based_ pagination: using `page_above`/`page_below` and `page_limit` is RECOMMENDED.\n**Example**: Fetch up to 100 structures above sort-field value 4000 (in this example, server chooses to fetch results sorted by increasing id, so `page_above` value refers to an `id` value): `/structures?page_above=4000&page_limit=100`.", "required": false, "schema": { "title": "Page Above", "minimum": 0.0, "type": "integer", + "description": "RECOMMENDED for use with _value-based_ pagination: using `page_above`/`page_below` and `page_limit` is RECOMMENDED.\n**Example**: Fetch up to 100 structures above sort-field value 4000 (in this example, server chooses to fetch results sorted by increasing id, so `page_above` value refers to an `id` value): `/structures?page_above=4000&page_limit=100`.", "default": 0 }, "name": "page_above", "in": "query" }, { + "description": "RECOMMENDED for use with _value-based_ pagination: using `page_above`/`page_below` and `page_limit` is RECOMMENDED.", "required": false, "schema": { "title": "Page Below", "minimum": 0.0, "type": "integer", + "description": "RECOMMENDED for use with _value-based_ pagination: using `page_above`/`page_below` and `page_limit` is RECOMMENDED.", "default": 0 }, "name": "page_below", @@ -254,32 +276,36 @@ "operationId": "get_references_optimade_v0_references_get", "parameters": [ { - "description": "See [the full and latest OPTiMaDe spec](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst) for filter query syntax.", + "description": "A filter string, in the format described in section [API Filtering Format Specification](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#api-filtering-format-specification) of the [OPTiMaDe spec](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst).", "required": false, "schema": { "title": "Filter", "type": "string", - "description": "See [the full and latest OPTiMaDe spec](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst) for filter query syntax.", + "description": "A filter string, in the format described in section [API Filtering Format Specification](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#api-filtering-format-specification) of the [OPTiMaDe spec](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst).", "default": "" }, "name": "filter", "in": "query" }, { + "description": "The output format requested (see section [Response Format](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#response-format) in the spec). Defaults to the format string 'json', which specifies the standard output format described in this specification.\n**Example**: http://example.com/optimade/v0.9/structures?response_format=xml", "required": false, "schema": { "title": "Response Format", "type": "string", + "description": "The output format requested (see section [Response Format](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#response-format) in the spec). Defaults to the format string 'json', which specifies the standard output format described in this specification.\n**Example**: http://example.com/optimade/v0.9/structures?response_format=xml", "default": "json" }, "name": "response_format", "in": "query" }, { + "description": "An email address of the user making the request. The email SHOULD be that of a person and not an automatic system.\n**Example**: http://example.com/optimade/v0.9/structures?email_address=user@example.com", "required": false, "schema": { "title": "Email Address", "type": "string", + "description": "An email address of the user making the request. The email SHOULD be that of a person and not an automatic system.\n**Example**: http://example.com/optimade/v0.9/structures?email_address=user@example.com", "format": "email", "default": "" }, @@ -287,86 +313,104 @@ "in": "query" }, { + "description": "A comma-delimited set of fields to be provided in the output. If provided, these fields MUST be returned along with the REQUIRED fields. Other OPTIONAL fields MUST NOT be returned when this parameter is present.\n**Example**: http://example.com/optimade/v0.9/structures?response_fields=last_modified,nsites", "required": false, "schema": { "title": "Response Fields", + "pattern": "([a-z_][a-z_0-9]*(,[a-z_][a-z_0-9]*)*)?", "type": "string", + "description": "A comma-delimited set of fields to be provided in the output. If provided, these fields MUST be returned along with the REQUIRED fields. Other OPTIONAL fields MUST NOT be returned when this parameter is present.\n**Example**: http://example.com/optimade/v0.9/structures?response_fields=last_modified,nsites", "default": "" }, "name": "response_fields", "in": "query" }, { + "description": "If supporting sortable queries, an implementation MUST use the `sort` query parameter with format as specified by [JSON API 1.0](https://jsonapi.org/format/1.0/#fetching-sorting).\n\nAn implementation MAY support multiple sort fields for a single query. If it does, it again MUST conform to the JSON API 1.0 specification.\n\nIf an implementation supports sorting for an [entry listing endpoint](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#entry-listing-endpoints), then the `/info/` endpoint MUST include, for each field name `` in its `data.properties.` response value that can be used for sorting, the key `sortable` with value `true`. If a field name under an entry listing endpoint supporting sorting cannot be used for sorting, the server MUST either leave out the `sortable` key or set it equal to `false` for the specific field name. The set of field names, with `sortable` equal to `true` are allowed to be used in the \"sort fields\" list according to its definition in the JSON API 1.0 specification. The field `sortable` is in addition to each property description (and the OPTIONAL field `unit`). An example is shown in section [Entry Listing Info Endpoints](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#entry-listing-info-endpoints).", "required": false, "schema": { "title": "Sort", + "pattern": "([a-z_][a-z_0-9]*(,[a-z_][a-z_0-9]*)*)?", "type": "string", + "description": "If supporting sortable queries, an implementation MUST use the `sort` query parameter with format as specified by [JSON API 1.0](https://jsonapi.org/format/1.0/#fetching-sorting).\n\nAn implementation MAY support multiple sort fields for a single query. If it does, it again MUST conform to the JSON API 1.0 specification.\n\nIf an implementation supports sorting for an [entry listing endpoint](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#entry-listing-endpoints), then the `/info/` endpoint MUST include, for each field name `` in its `data.properties.` response value that can be used for sorting, the key `sortable` with value `true`. If a field name under an entry listing endpoint supporting sorting cannot be used for sorting, the server MUST either leave out the `sortable` key or set it equal to `false` for the specific field name. The set of field names, with `sortable` equal to `true` are allowed to be used in the \"sort fields\" list according to its definition in the JSON API 1.0 specification. The field `sortable` is in addition to each property description (and the OPTIONAL field `unit`). An example is shown in section [Entry Listing Info Endpoints](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#entry-listing-info-endpoints).", "default": "" }, "name": "sort", "in": "query" }, { + "description": "Sets a numerical limit on the number of entries returned. See [JSON API 1.0](https://jsonapi.org/format/1.0/#fetching-pagination). The API implementation MUST return no more than the number specified. It MAY return fewer. The database MAY have a maximum limit and not accept larger numbers (in which case an error code -- 403 Forbidden -- MUST be returned). The default limit value is up to the API implementation to decide.\n\nA server MUST implement pagination in the case of no user-specified `sort` parameter (via the `links` response field, see section [JSON Response Schema: Common Fields](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#json-response-schema-common-fields)). A server MAY implement pagination in concert with `sort`.", "required": false, "schema": { "title": "Page Limit", "minimum": 0.0, "type": "integer", + "description": "Sets a numerical limit on the number of entries returned. See [JSON API 1.0](https://jsonapi.org/format/1.0/#fetching-pagination). The API implementation MUST return no more than the number specified. It MAY return fewer. The database MAY have a maximum limit and not accept larger numbers (in which case an error code -- 403 Forbidden -- MUST be returned). The default limit value is up to the API implementation to decide.\n\nA server MUST implement pagination in the case of no user-specified `sort` parameter (via the `links` response field, see section [JSON Response Schema: Common Fields](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#json-response-schema-common-fields)). A server MAY implement pagination in concert with `sort`.", "default": 20 }, "name": "page_limit", "in": "query" }, { + "description": "RECOMMENDED for use with _offset-based_ pagination: using `page_offset` and `page_limit` is RECOMMENDED.\n**Example**: Skip 50 structures and fetch up to 100: `/structures?page_offset=50&page_limit=100`.", "required": false, "schema": { "title": "Page Offset", "minimum": 0.0, "type": "integer", + "description": "RECOMMENDED for use with _offset-based_ pagination: using `page_offset` and `page_limit` is RECOMMENDED.\n**Example**: Skip 50 structures and fetch up to 100: `/structures?page_offset=50&page_limit=100`.", "default": 0 }, "name": "page_offset", "in": "query" }, { + "description": "RECOMMENDED for use with _page-based_ pagination: using `page_number` and `page_limit` is RECOMMENDED. It is RECOMMENDED that the first page has number 1, i.e., that `page_number` is 1-based.\n**Example**: Fetch page 2 of up to 50 structures per page: `/structures?page_number=2&page_limit=50`.", "required": false, "schema": { - "title": "Page Page", + "title": "Page Number", "minimum": 0.0, "type": "integer", + "description": "RECOMMENDED for use with _page-based_ pagination: using `page_number` and `page_limit` is RECOMMENDED. It is RECOMMENDED that the first page has number 1, i.e., that `page_number` is 1-based.\n**Example**: Fetch page 2 of up to 50 structures per page: `/structures?page_number=2&page_limit=50`.", "default": 0 }, - "name": "page_page", + "name": "page_number", "in": "query" }, { + "description": "RECOMMENDED for use with _cursor-based_ pagination: using `page_cursor` and `page_limit` is RECOMMENDED.", "required": false, "schema": { "title": "Page Cursor", "minimum": 0.0, "type": "integer", + "description": "RECOMMENDED for use with _cursor-based_ pagination: using `page_cursor` and `page_limit` is RECOMMENDED.", "default": 0 }, "name": "page_cursor", "in": "query" }, { + "description": "RECOMMENDED for use with _value-based_ pagination: using `page_above`/`page_below` and `page_limit` is RECOMMENDED.\n**Example**: Fetch up to 100 structures above sort-field value 4000 (in this example, server chooses to fetch results sorted by increasing id, so `page_above` value refers to an `id` value): `/structures?page_above=4000&page_limit=100`.", "required": false, "schema": { "title": "Page Above", "minimum": 0.0, "type": "integer", + "description": "RECOMMENDED for use with _value-based_ pagination: using `page_above`/`page_below` and `page_limit` is RECOMMENDED.\n**Example**: Fetch up to 100 structures above sort-field value 4000 (in this example, server chooses to fetch results sorted by increasing id, so `page_above` value refers to an `id` value): `/structures?page_above=4000&page_limit=100`.", "default": 0 }, "name": "page_above", "in": "query" }, { + "description": "RECOMMENDED for use with _value-based_ pagination: using `page_above`/`page_below` and `page_limit` is RECOMMENDED.", "required": false, "schema": { "title": "Page Below", "minimum": 0.0, "type": "integer", + "description": "RECOMMENDED for use with _value-based_ pagination: using `page_above`/`page_below` and `page_limit` is RECOMMENDED.", "default": 0 }, "name": "page_below", @@ -423,20 +467,24 @@ "in": "path" }, { + "description": "The output format requested (see section [Response Format](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#response-format) in the spec). Defaults to the format string 'json', which specifies the standard output format described in this specification.\n**Example**: http://example.com/optimade/v0.9/structures?response_format=xml", "required": false, "schema": { "title": "Response Format", "type": "string", + "description": "The output format requested (see section [Response Format](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#response-format) in the spec). Defaults to the format string 'json', which specifies the standard output format described in this specification.\n**Example**: http://example.com/optimade/v0.9/structures?response_format=xml", "default": "json" }, "name": "response_format", "in": "query" }, { + "description": "An email address of the user making the request. The email SHOULD be that of a person and not an automatic system.\n**Example**: http://example.com/optimade/v0.9/structures?email_address=user@example.com", "required": false, "schema": { "title": "Email Address", "type": "string", + "description": "An email address of the user making the request. The email SHOULD be that of a person and not an automatic system.\n**Example**: http://example.com/optimade/v0.9/structures?email_address=user@example.com", "format": "email", "default": "" }, @@ -444,10 +492,13 @@ "in": "query" }, { + "description": "A comma-delimited set of fields to be provided in the output. If provided, these fields MUST be returned along with the REQUIRED fields. Other OPTIONAL fields MUST NOT be returned when this parameter is present.\n**Example**: http://example.com/optimade/v0.9/structures?response_fields=last_modified,nsites", "required": false, "schema": { "title": "Response Fields", + "pattern": "([a-z_][a-z_0-9]*(,[a-z_][a-z_0-9]*)*)?", "type": "string", + "description": "A comma-delimited set of fields to be provided in the output. If provided, these fields MUST be returned along with the REQUIRED fields. Other OPTIONAL fields MUST NOT be returned when this parameter is present.\n**Example**: http://example.com/optimade/v0.9/structures?response_fields=last_modified,nsites", "default": "" }, "name": "response_fields", @@ -495,32 +546,36 @@ "operationId": "get_structures_optimade_v0_structures_get", "parameters": [ { - "description": "See [the full and latest OPTiMaDe spec](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst) for filter query syntax.", + "description": "A filter string, in the format described in section [API Filtering Format Specification](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#api-filtering-format-specification) of the [OPTiMaDe spec](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst).", "required": false, "schema": { "title": "Filter", "type": "string", - "description": "See [the full and latest OPTiMaDe spec](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst) for filter query syntax.", + "description": "A filter string, in the format described in section [API Filtering Format Specification](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#api-filtering-format-specification) of the [OPTiMaDe spec](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst).", "default": "" }, "name": "filter", "in": "query" }, { + "description": "The output format requested (see section [Response Format](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#response-format) in the spec). Defaults to the format string 'json', which specifies the standard output format described in this specification.\n**Example**: http://example.com/optimade/v0.9/structures?response_format=xml", "required": false, "schema": { "title": "Response Format", "type": "string", + "description": "The output format requested (see section [Response Format](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#response-format) in the spec). Defaults to the format string 'json', which specifies the standard output format described in this specification.\n**Example**: http://example.com/optimade/v0.9/structures?response_format=xml", "default": "json" }, "name": "response_format", "in": "query" }, { + "description": "An email address of the user making the request. The email SHOULD be that of a person and not an automatic system.\n**Example**: http://example.com/optimade/v0.9/structures?email_address=user@example.com", "required": false, "schema": { "title": "Email Address", "type": "string", + "description": "An email address of the user making the request. The email SHOULD be that of a person and not an automatic system.\n**Example**: http://example.com/optimade/v0.9/structures?email_address=user@example.com", "format": "email", "default": "" }, @@ -528,86 +583,104 @@ "in": "query" }, { + "description": "A comma-delimited set of fields to be provided in the output. If provided, these fields MUST be returned along with the REQUIRED fields. Other OPTIONAL fields MUST NOT be returned when this parameter is present.\n**Example**: http://example.com/optimade/v0.9/structures?response_fields=last_modified,nsites", "required": false, "schema": { "title": "Response Fields", + "pattern": "([a-z_][a-z_0-9]*(,[a-z_][a-z_0-9]*)*)?", "type": "string", + "description": "A comma-delimited set of fields to be provided in the output. If provided, these fields MUST be returned along with the REQUIRED fields. Other OPTIONAL fields MUST NOT be returned when this parameter is present.\n**Example**: http://example.com/optimade/v0.9/structures?response_fields=last_modified,nsites", "default": "" }, "name": "response_fields", "in": "query" }, { + "description": "If supporting sortable queries, an implementation MUST use the `sort` query parameter with format as specified by [JSON API 1.0](https://jsonapi.org/format/1.0/#fetching-sorting).\n\nAn implementation MAY support multiple sort fields for a single query. If it does, it again MUST conform to the JSON API 1.0 specification.\n\nIf an implementation supports sorting for an [entry listing endpoint](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#entry-listing-endpoints), then the `/info/` endpoint MUST include, for each field name `` in its `data.properties.` response value that can be used for sorting, the key `sortable` with value `true`. If a field name under an entry listing endpoint supporting sorting cannot be used for sorting, the server MUST either leave out the `sortable` key or set it equal to `false` for the specific field name. The set of field names, with `sortable` equal to `true` are allowed to be used in the \"sort fields\" list according to its definition in the JSON API 1.0 specification. The field `sortable` is in addition to each property description (and the OPTIONAL field `unit`). An example is shown in section [Entry Listing Info Endpoints](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#entry-listing-info-endpoints).", "required": false, "schema": { "title": "Sort", + "pattern": "([a-z_][a-z_0-9]*(,[a-z_][a-z_0-9]*)*)?", "type": "string", + "description": "If supporting sortable queries, an implementation MUST use the `sort` query parameter with format as specified by [JSON API 1.0](https://jsonapi.org/format/1.0/#fetching-sorting).\n\nAn implementation MAY support multiple sort fields for a single query. If it does, it again MUST conform to the JSON API 1.0 specification.\n\nIf an implementation supports sorting for an [entry listing endpoint](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#entry-listing-endpoints), then the `/info/` endpoint MUST include, for each field name `` in its `data.properties.` response value that can be used for sorting, the key `sortable` with value `true`. If a field name under an entry listing endpoint supporting sorting cannot be used for sorting, the server MUST either leave out the `sortable` key or set it equal to `false` for the specific field name. The set of field names, with `sortable` equal to `true` are allowed to be used in the \"sort fields\" list according to its definition in the JSON API 1.0 specification. The field `sortable` is in addition to each property description (and the OPTIONAL field `unit`). An example is shown in section [Entry Listing Info Endpoints](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#entry-listing-info-endpoints).", "default": "" }, "name": "sort", "in": "query" }, { + "description": "Sets a numerical limit on the number of entries returned. See [JSON API 1.0](https://jsonapi.org/format/1.0/#fetching-pagination). The API implementation MUST return no more than the number specified. It MAY return fewer. The database MAY have a maximum limit and not accept larger numbers (in which case an error code -- 403 Forbidden -- MUST be returned). The default limit value is up to the API implementation to decide.\n\nA server MUST implement pagination in the case of no user-specified `sort` parameter (via the `links` response field, see section [JSON Response Schema: Common Fields](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#json-response-schema-common-fields)). A server MAY implement pagination in concert with `sort`.", "required": false, "schema": { "title": "Page Limit", "minimum": 0.0, "type": "integer", + "description": "Sets a numerical limit on the number of entries returned. See [JSON API 1.0](https://jsonapi.org/format/1.0/#fetching-pagination). The API implementation MUST return no more than the number specified. It MAY return fewer. The database MAY have a maximum limit and not accept larger numbers (in which case an error code -- 403 Forbidden -- MUST be returned). The default limit value is up to the API implementation to decide.\n\nA server MUST implement pagination in the case of no user-specified `sort` parameter (via the `links` response field, see section [JSON Response Schema: Common Fields](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#json-response-schema-common-fields)). A server MAY implement pagination in concert with `sort`.", "default": 20 }, "name": "page_limit", "in": "query" }, { + "description": "RECOMMENDED for use with _offset-based_ pagination: using `page_offset` and `page_limit` is RECOMMENDED.\n**Example**: Skip 50 structures and fetch up to 100: `/structures?page_offset=50&page_limit=100`.", "required": false, "schema": { "title": "Page Offset", "minimum": 0.0, "type": "integer", + "description": "RECOMMENDED for use with _offset-based_ pagination: using `page_offset` and `page_limit` is RECOMMENDED.\n**Example**: Skip 50 structures and fetch up to 100: `/structures?page_offset=50&page_limit=100`.", "default": 0 }, "name": "page_offset", "in": "query" }, { + "description": "RECOMMENDED for use with _page-based_ pagination: using `page_number` and `page_limit` is RECOMMENDED. It is RECOMMENDED that the first page has number 1, i.e., that `page_number` is 1-based.\n**Example**: Fetch page 2 of up to 50 structures per page: `/structures?page_number=2&page_limit=50`.", "required": false, "schema": { - "title": "Page Page", + "title": "Page Number", "minimum": 0.0, "type": "integer", + "description": "RECOMMENDED for use with _page-based_ pagination: using `page_number` and `page_limit` is RECOMMENDED. It is RECOMMENDED that the first page has number 1, i.e., that `page_number` is 1-based.\n**Example**: Fetch page 2 of up to 50 structures per page: `/structures?page_number=2&page_limit=50`.", "default": 0 }, - "name": "page_page", + "name": "page_number", "in": "query" }, { + "description": "RECOMMENDED for use with _cursor-based_ pagination: using `page_cursor` and `page_limit` is RECOMMENDED.", "required": false, "schema": { "title": "Page Cursor", "minimum": 0.0, "type": "integer", + "description": "RECOMMENDED for use with _cursor-based_ pagination: using `page_cursor` and `page_limit` is RECOMMENDED.", "default": 0 }, "name": "page_cursor", "in": "query" }, { + "description": "RECOMMENDED for use with _value-based_ pagination: using `page_above`/`page_below` and `page_limit` is RECOMMENDED.\n**Example**: Fetch up to 100 structures above sort-field value 4000 (in this example, server chooses to fetch results sorted by increasing id, so `page_above` value refers to an `id` value): `/structures?page_above=4000&page_limit=100`.", "required": false, "schema": { "title": "Page Above", "minimum": 0.0, "type": "integer", + "description": "RECOMMENDED for use with _value-based_ pagination: using `page_above`/`page_below` and `page_limit` is RECOMMENDED.\n**Example**: Fetch up to 100 structures above sort-field value 4000 (in this example, server chooses to fetch results sorted by increasing id, so `page_above` value refers to an `id` value): `/structures?page_above=4000&page_limit=100`.", "default": 0 }, "name": "page_above", "in": "query" }, { + "description": "RECOMMENDED for use with _value-based_ pagination: using `page_above`/`page_below` and `page_limit` is RECOMMENDED.", "required": false, "schema": { "title": "Page Below", "minimum": 0.0, "type": "integer", + "description": "RECOMMENDED for use with _value-based_ pagination: using `page_above`/`page_below` and `page_limit` is RECOMMENDED.", "default": 0 }, "name": "page_below", @@ -664,20 +737,24 @@ "in": "path" }, { + "description": "The output format requested (see section [Response Format](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#response-format) in the spec). Defaults to the format string 'json', which specifies the standard output format described in this specification.\n**Example**: http://example.com/optimade/v0.9/structures?response_format=xml", "required": false, "schema": { "title": "Response Format", "type": "string", + "description": "The output format requested (see section [Response Format](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#response-format) in the spec). Defaults to the format string 'json', which specifies the standard output format described in this specification.\n**Example**: http://example.com/optimade/v0.9/structures?response_format=xml", "default": "json" }, "name": "response_format", "in": "query" }, { + "description": "An email address of the user making the request. The email SHOULD be that of a person and not an automatic system.\n**Example**: http://example.com/optimade/v0.9/structures?email_address=user@example.com", "required": false, "schema": { "title": "Email Address", "type": "string", + "description": "An email address of the user making the request. The email SHOULD be that of a person and not an automatic system.\n**Example**: http://example.com/optimade/v0.9/structures?email_address=user@example.com", "format": "email", "default": "" }, @@ -685,10 +762,13 @@ "in": "query" }, { + "description": "A comma-delimited set of fields to be provided in the output. If provided, these fields MUST be returned along with the REQUIRED fields. Other OPTIONAL fields MUST NOT be returned when this parameter is present.\n**Example**: http://example.com/optimade/v0.9/structures?response_fields=last_modified,nsites", "required": false, "schema": { "title": "Response Fields", + "pattern": "([a-z_][a-z_0-9]*(,[a-z_][a-z_0-9]*)*)?", "type": "string", + "description": "A comma-delimited set of fields to be provided in the output. If provided, these fields MUST be returned along with the REQUIRED fields. Other OPTIONAL fields MUST NOT be returned when this parameter is present.\n**Example**: http://example.com/optimade/v0.9/structures?response_fields=last_modified,nsites", "default": "" }, "name": "response_fields", @@ -2574,16 +2654,78 @@ "dimension_types": { "title": "Dimension Types", "type": "array", - "items": {}, + "items": [ + { + "enum": [ + 0, + 1 + ], + "type": "integer" + }, + { + "enum": [ + 0, + 1 + ], + "type": "integer" + }, + { + "enum": [ + 0, + 1 + ], + "type": "integer" + } + ], "description": "List of three integers.\n For each of the three directions indicated by the three lattice vectors (see property `lattice_vectors`_).\n This list indicates if the direction is periodic (value :val:`1`) or non-periodic (value :val:`0`).\n Note: the elements in this list each refer to the direction of the corresponding entry in property `lattice_vectors`_ and *not* the Cartesian x, y, z directions.\n- **Type**: list of integers.\n- **Requirements/Conventions**:\n\n - **Support**: SHOULD be supported, i.e., SHOULD NOT be :val:`null`. Is REQUIRED in this implementation, i.e., MUST NOT be :val:`null`.\n - **Query**: MUST be a queryable property. Support for equality comparison is REQUIRED, support for other comparison operators are OPTIONAL.\n - MUST be a list of length 3.\n - Each integer element MUST assume only the value 0 or 1.\n\n- **Examples**:\n\n - For a molecule: :val:`[0, 0, 0]`\n - For a wire along the direction specified by the third lattice vector: :val:`[0, 0, 1]`\n - For a 2D surface/slab, periodic on the plane defined by the first and third lattice vectors: :val:`[1, 0, 1]`\n - For a bulk 3D system: :val:`[1, 1, 1]`" }, "lattice_vectors": { "title": "Lattice Vectors", "type": "array", - "items": { - "type": "array", - "items": {} - }, + "items": [ + { + "type": "array", + "items": [ + { + "type": "number" + }, + { + "type": "number" + }, + { + "type": "number" + } + ] + }, + { + "type": "array", + "items": [ + { + "type": "number" + }, + { + "type": "number" + }, + { + "type": "number" + } + ] + }, + { + "type": "array", + "items": [ + { + "type": "number" + }, + { + "type": "number" + }, + { + "type": "number" + } + ] + } + ], "description": "The three lattice vectors in Cartesian coordinates, in \u00e5ngstr\u00f6m (\u00c5).\n- **Type**: list of list of floats.\n- **Requirements/Conventions**:\n\n - **Support**: SHOULD be supported, i.e., SHOULD NOT be :val:`null`. Is REQUIRED in this implementation, i.e., MUST NOT be :val:`null`.\n - **Query**: Support for queries on this property is OPTIONAL.\n If supported, filters MAY support only a subset of comparison operators.\n - MUST be a list of three vectors *a*, *b*, and *c*, where each of the vectors MUST BE a list of the vector's coordinates along the x, y, and z Cartesian coordinates.\n (Therefore, the first index runs over the three lattice vectors and the second index runs over the x, y, z Cartesian coordinates).\n - For databases that do not define an absolute Cartesian system (e.g., only defining the length and angles between vectors), the first lattice vector SHOULD be set along *x* and the second on the *xy*-plane.\n - This property MUST be an array of dimensions 3 times 3 regardless of the elements of :property:`dimension_types`.\n The vectors SHOULD by convention be chosen so the determinant of the :property:`lattice_vectors` matrix is different from zero.\n The vectors in the non-periodic directions have no significance beyond fulfilling these requirements.\n - All three elements of the inner lists of floats MAY be :val:`null` for non-periodic dimensions, i.e., those dimensions for which :property:`dimension_types` is :val:`0`.\n\n- **Examples**:\n\n - :val:`[[4.0,0.0,0.0],[0.0,4.0,0.0],[0.0,1.0,4.0]]` represents a cell, where the first vector is :val:`(4, 0, 0)`, i.e., a vector aligned along the :val:`x` axis of length 4 \u00c5; the second vector is :val:`(0, 4, 0)`; and the third vector is :val:`(0, 1, 4)`." }, "cartesian_site_positions": { @@ -2591,7 +2733,17 @@ "type": "array", "items": { "type": "array", - "items": {} + "items": [ + { + "type": "number" + }, + { + "type": "number" + }, + { + "type": "number" + } + ] }, "description": "Cartesian positions of each site. A site is an atom, a site potentially occupied by an atom, or a placeholder for a virtual mixture of atoms (e.g., in a virtual crystal approximation).\n- **Type**: list of list of floats and/or unknown values\n- **Requirements/Conventions**:\n\n - **Support**: SHOULD be supported, i.e., SHOULD NOT be :val:`null`. Is REQUIRED in this implementation, i.e., MUST NOT be :val:`null`.\n - **Query**: Support for queries on this property is OPTIONAL. If supported, filters MAY support only a subset of comparison operators.\n - It MUST be a list of length N times 3, where N is the number of sites in the structure.\n - An entry MAY have multiple sites at the same Cartesian position (for a relevant use of this, see e.g., the property `assemblies`_).\n - If a component of the position is unknown, the :val:`null` value should be provided instead (see section `Properties with unknown value`_).\n Otherwise, it should be a float value, expressed in angstrom (\u00c5).\n If at least one of the coordinates is unknown, the correct flag in the list property `structure_features`_ MUST be set.\n - **Notes**: (for implementers) While this is unrelated to this OPTiMaDe specification: If you decide to store internally the :property: `cartesian_site_positions` as a float array, you might want to represent :val:`null` values with :field-val:`NaN` values.\n The latter being valid float numbers in the IEEE 754 standard in `IEEE 754-1985 `__ and in the updated version `IEEE 754-2008 `__.\n\n- **Examples**:\n\n - :val:`[[0,0,0],[0,0,2]]` indicates a structure with two sites, one sitting at the origin and one along the (positive) *z*-axis, 2 \u00c5 away from the origin." }, diff --git a/optimade/models/baseinfo.py b/optimade/models/baseinfo.py index a0342476c..d2d442761 100644 --- a/optimade/models/baseinfo.py +++ b/optimade/models/baseinfo.py @@ -37,8 +37,8 @@ def version_must_be_valid(cls, v): if not re.match(r"[0-9]+\.[0-9]+(\.[0-9]+)?", v): raise ValueError(f"version MUST NOT be prefixed by, e.g., 'v'. It is: {v}") try: - _ = tuple(int(val) for val in v.split(".")) - except Exception: + tuple(int(val) for val in v.split(".")) + except ValueError: raise ValueError(f"failed to parse version {v} sections as integers.") return v diff --git a/optimade/models/structures.py b/optimade/models/structures.py index 675471270..d1800e0a4 100644 --- a/optimade/models/structures.py +++ b/optimade/models/structures.py @@ -1,11 +1,12 @@ # pylint: disable=no-self-argument,line-too-long,no-name-in-module +from enum import IntEnum from sys import float_info -from typing import List, Optional +from typing import List, Optional, Tuple, Union from pydantic import Field, BaseModel, validator from .entries import EntryResourceAttributes, EntryResource -from .utils import conlist, CHEMICAL_SYMBOLS, EXTRA_SYMBOLS +from .utils import CHEMICAL_SYMBOLS, EXTRA_SYMBOLS EXTENDED_CHEMICAL_SYMBOLS = CHEMICAL_SYMBOLS + EXTRA_SYMBOLS @@ -17,6 +18,14 @@ EPS = float_info.epsilon +Vector3D = Tuple[Union[float, None], Union[float, None], Union[float, None]] + + +class Periodicity(IntEnum): + APERIODIC = 0 + PERIODIC = 1 + + class Species(BaseModel): """A list describing the species of the sites of this structure. Species can be pure chemical elements, or virtual-crystal atoms representing a statistical occupation of a given site by multiple chemical elements. @@ -307,7 +316,7 @@ class StructureResourceAttributes(EntryResourceAttributes): - A filter that matches an exactly given formula is :filter:`chemical_formula_anonymous="A2B"`.""", ) - dimension_types: conlist(len_eq=3) = Field( + dimension_types: Tuple[Periodicity, Periodicity, Periodicity] = Field( ..., description="""List of three integers. For each of the three directions indicated by the three lattice vectors (see property `lattice_vectors`_). @@ -329,7 +338,7 @@ class StructureResourceAttributes(EntryResourceAttributes): - For a bulk 3D system: :val:`[1, 1, 1]`""", ) - lattice_vectors: Optional[List[conlist(len_eq=3)]] = Field( + lattice_vectors: Optional[Tuple[Vector3D, Vector3D, Vector3D]] = Field( None, description="""The three lattice vectors in Cartesian coordinates, in ångström (Å). - **Type**: list of list of floats. @@ -352,7 +361,7 @@ class StructureResourceAttributes(EntryResourceAttributes): unit="Å", ) - cartesian_site_positions: List[conlist(len_eq=3)] = Field( + cartesian_site_positions: List[Vector3D] = Field( ..., description="""Cartesian positions of each site. A site is an atom, a site potentially occupied by an atom, or a placeholder for a virtual mixture of atoms (e.g., in a virtual crystal approximation). - **Type**: list of list of floats and/or unknown values @@ -630,25 +639,11 @@ def no_spaces_in_reduced(cls, v): raise ValueError(f"Spaces are not allowed, you passed: {v}") return v - @validator("dimension_types") - def must_be_of_length_three(cls, v): - if len(v) != 3: - raise ValueError(f"MUST be of length 3, but is of length: {len(v)}") - for dimension in v: - if dimension not in {0, 1}: - raise ValueError(f"MUST be either 0 or 1, you passed: {v}") - return v - @validator("lattice_vectors", always=True) def required_if_dimension_types_has_one(cls, v, values): if 1 in values.get("dimension_types", []) and v is None: raise ValueError( - f"lattice_vectors is REQUIRED, since dimension_types is not [0, 0, 0] but is {values('dimension_types', 'Not specified')}" - ) - - if len(v) != 3: - raise ValueError( - f"MUST be a 3 x 3 array (list of 3 lists of 3 floats), found instead: {v}" + f"lattice_vectors is REQUIRED, since dimension_types is not [0, 0, 0] but is {values.get('dimension_types', 'Not specified')}" ) for dim_type, vector in zip(values.get("dimension_types", []), v): @@ -660,12 +655,6 @@ def required_if_dimension_types_has_one(cls, v, values): return v - @validator("lattice_vectors", "cartesian_site_positions", each_item=True) - def sites_must_have_length_three(cls, v): - if len(v) != 3: - raise ValueError(f"MUST be a list of length 3. {v} has length {len(v)}.") - return v - @validator("nsites") def validate_nsites(cls, v, values): if v != len(values.get("cartesian_site_positions", [])): diff --git a/optimade/models/toplevel.py b/optimade/models/toplevel.py index 0eef0c409..0feb770a7 100644 --- a/optimade/models/toplevel.py +++ b/optimade/models/toplevel.py @@ -1,10 +1,14 @@ from datetime import datetime from typing import Union, List, Optional, Dict, Any -from pydantic import BaseModel, AnyHttpUrl, Field, EmailStr +from pydantic import ( # pylint: disable=no-name-in-module + BaseModel, + AnyHttpUrl, + Field, + EmailStr, +) from .jsonapi import Link, Meta -from .utils import NonnegativeInt from .baseinfo import BaseInfoResource from .entries import EntryInfoResource, EntryResource from .index_metadb import IndexInfoResource @@ -124,10 +128,11 @@ class ResponseMeta(Meta): description="a string containing the date and time at which the query was exexcuted", ) - data_returned: NonnegativeInt = Field( + data_returned: int = Field( ..., description="an integer containing the number of data objects " "returned for the query.", + ge=0, ) more_data_available: bool = Field( diff --git a/optimade/models/utils.py b/optimade/models/utils.py index f6f800748..db2ee70b0 100644 --- a/optimade/models/utils.py +++ b/optimade/models/utils.py @@ -1,82 +1,4 @@ -from typing import cast, Any, Dict, Type -from pydantic import ConstrainedInt, errors -from pydantic.types import OptionalInt -from pydantic.validators import list_validator - - -__all__ = ("NonnegativeInt", "CHEMICAL_SYMBOLS", "EXTRA_SYMBOLS", "ATOMIC_NUMBERS") - - -class NonnegativeInt(ConstrainedInt): - ge = 0 - - -class ConstrainedListMeta(type): - def __new__( - cls, name: str, bases: Any, dct: Dict[str, Any] - ) -> "ConstrainedList": # noqa - new_cls = cast("ConstrainedList", type.__new__(cls, name, bases, dct)) - - if new_cls.len_gt is not None and new_cls.len_ge is not None: - raise errors.ConfigError( - "bounds len_gt and len_ge cannot be specified at the same time" - ) - if new_cls.len_lt is not None and new_cls.len_le is not None: - raise errors.ConfigError( - "bounds len_lt and len_le cannot be specified at the same time" - ) - if new_cls.len_eq is not None and any( - v is not None - for v in (new_cls.len_gt, new_cls.len_ge, new_cls.len_lt, new_cls.len_le) - ): - raise errors.ConfigError( - "len_eq cannot be specified at the same time as any other constraint" - ) - return new_cls - - -def list_length_validator(v: "List", field: "Field") -> "List": # noqa - field_type: ConstrainedList = field.type_ # type: ignore - if field_type.len_gt is not None and not len(v) > field_type.len_gt: - raise errors.NumberNotGtError(limit_value=field_type.len_gt) - if field_type.len_ge is not None and not len(v) >= field_type.len_ge: - raise errors.NumberNotGeError(limit_value=field_type.len_ge) - if field_type.len_lt is not None and not len(v) < field_type.len_lt: - raise errors.NumberNotLtError(limit_value=field_type.len_lt) - if field_type.len_le is not None and not len(v) <= field_type.len_le: - raise errors.NumberNotLeError(limit_value=field_type.len_le) - if field_type.len_eq is not None and not len(v) == field_type.len_eq: - raise errors.NumberNotLeError(limit_value=field_type.len_eq) - - return v - - -class ConstrainedList(list, metaclass=ConstrainedListMeta): - len_gt: OptionalInt = None - len_ge: OptionalInt = None - len_lt: OptionalInt = None - len_le: OptionalInt = None - len_eq: OptionalInt = None - - @classmethod - def __get_validators__(cls) -> "CallableGenerator": # noqa - yield list_validator - yield list_length_validator - - -def conlist( - *, - len_gt: int = None, - len_ge: int = None, - len_lt: int = None, - len_le: int = None, - len_eq: int = None -) -> Type[list]: - # use kwargs then define conf in a dict to aid with IDE type hinting - namespace = dict( - len_gt=len_gt, len_ge=len_ge, len_lt=len_lt, len_le=len_le, len_eq=len_eq - ) - return type("ConstrainedListValue", (ConstrainedList,), namespace) +__all__ = ("CHEMICAL_SYMBOLS", "EXTRA_SYMBOLS", "ATOMIC_NUMBERS") EXTRA_SYMBOLS = ["X", "vacancy"] diff --git a/optimade/server/deps.py b/optimade/server/deps.py index 4624af3db..6542274f2 100644 --- a/optimade/server/deps.py +++ b/optimade/server/deps.py @@ -2,8 +2,6 @@ from fastapi import Query from pydantic import EmailStr # pylint: disable=no-name-in-module -from optimade.models import NonnegativeInt - from .config import CONFIG @@ -15,18 +13,84 @@ def __init__( *, filter: str = Query( # pylint: disable=redefined-builtin "", - description="""See [the full and latest OPTiMaDe spec](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst) for filter query syntax.""", - ), - response_format: str = Query("json"), - email_address: EmailStr = Query(""), - response_fields: str = Query(""), - sort: str = Query(""), - page_limit: NonnegativeInt = Query(CONFIG.page_limit), - page_offset: NonnegativeInt = Query(0), - page_page: NonnegativeInt = Query(0), - page_cursor: NonnegativeInt = Query(0), - page_above: NonnegativeInt = Query(0), - page_below: NonnegativeInt = Query(0), + description="A filter string, in the format described in section [API Filtering Format Specification]" + "(https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#api-filtering-format-specification) " + "of the [OPTiMaDe spec](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst).", + ), + response_format: str = Query( + "json", + description="The output format requested (see section [Response Format](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/" + "optimade.rst#response-format) in the spec). Defaults to the format string 'json', which specifies the standard output format " + "described in this specification.\n**Example**: http://example.com/optimade/v0.9/structures?response_format=xml", + ), + email_address: EmailStr = Query( + "", + description="An email address of the user making the request. The email SHOULD be that of a person and not an automatic system.\n" + "**Example**: http://example.com/optimade/v0.9/structures?email_address=user@example.com", + ), + response_fields: str = Query( + "", + description="A comma-delimited set of fields to be provided in the output. If provided, these fields MUST be returned along with " + "the REQUIRED fields. Other OPTIONAL fields MUST NOT be returned when this parameter is present.\n" + "**Example**: http://example.com/optimade/v0.9/structures?response_fields=last_modified,nsites", + regex=r"([a-z_][a-z_0-9]*(,[a-z_][a-z_0-9]*)*)?", + ), + sort: str = Query( + "", + description="If supporting sortable queries, an implementation MUST use the `sort` query parameter with format as specified by " + "[JSON API 1.0](https://jsonapi.org/format/1.0/#fetching-sorting).\n\n" + "An implementation MAY support multiple sort fields for a single query. If it does, it again MUST conform to the JSON API 1.0 specification.\n\n" + "If an implementation supports sorting for an [entry listing endpoint](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst" + "#entry-listing-endpoints), then the `/info/` endpoint MUST include, for each field name `` in its " + "`data.properties.` response value that can be used for sorting, the key `sortable` with value `true`. " + "If a field name under an entry listing endpoint supporting sorting cannot be used for sorting, the server MUST either leave out the `sortable` " + "key or set it equal to `false` for the specific field name. The set of field names, with `sortable` equal to `true` are allowed to be used in " + 'the "sort fields" list according to its definition in the JSON API 1.0 specification. The field `sortable` is in addition to each property ' + "description (and the OPTIONAL field `unit`). An example is shown in section " + "[Entry Listing Info Endpoints](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#entry-listing-info-endpoints).", + regex=r"([a-z_][a-z_0-9]*(,[a-z_][a-z_0-9]*)*)?", + ), + page_limit: int = Query( + CONFIG.page_limit, + description="Sets a numerical limit on the number of entries returned. " + "See [JSON API 1.0](https://jsonapi.org/format/1.0/#fetching-pagination). The API implementation MUST return no more than the number specified. " + "It MAY return fewer. The database MAY have a maximum limit and not accept larger numbers (in which case an error code -- 403 Forbidden -- " + "MUST be returned). The default limit value is up to the API implementation to decide.\n\n" + "A server MUST implement pagination in the case of no user-specified `sort` parameter (via the `links` response field, see section " + "[JSON Response Schema: Common Fields](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#json-response-schema-" + "common-fields)). A server MAY implement pagination in concert with `sort`.", + ge=0, + ), + page_offset: int = Query( + 0, + description="RECOMMENDED for use with _offset-based_ pagination: using `page_offset` and `page_limit` is RECOMMENDED.\n" + "**Example**: Skip 50 structures and fetch up to 100: `/structures?page_offset=50&page_limit=100`.", + ge=0, + ), + page_number: int = Query( + 0, + description="RECOMMENDED for use with _page-based_ pagination: using `page_number` and `page_limit` is RECOMMENDED. " + "It is RECOMMENDED that the first page has number 1, i.e., that `page_number` is 1-based.\n" + "**Example**: Fetch page 2 of up to 50 structures per page: `/structures?page_number=2&page_limit=50`.", + ge=0, + ), + page_cursor: int = Query( + 0, + description="RECOMMENDED for use with _cursor-based_ pagination: using `page_cursor` and `page_limit` is RECOMMENDED.", + ge=0, + ), + page_above: int = Query( + 0, + description="RECOMMENDED for use with _value-based_ pagination: using `page_above`/`page_below` and `page_limit` is RECOMMENDED.\n" + "**Example**: Fetch up to 100 structures above sort-field value 4000 (in this example, server chooses to fetch results sorted by increasing id, " + "so `page_above` value refers to an `id` value): `/structures?page_above=4000&page_limit=100`.", + ge=0, + ), + page_below: int = Query( + 0, + description="RECOMMENDED for use with _value-based_ pagination: using `page_above`/`page_below` and `page_limit` is RECOMMENDED.", + ge=0, + ), ): self.filter = filter self.response_format = response_format @@ -35,7 +99,7 @@ def __init__( self.sort = sort self.page_limit = page_limit self.page_offset = page_offset - self.page_page = page_page + self.page_number = page_number self.page_cursor = page_cursor self.page_above = page_above self.page_below = page_below @@ -47,9 +111,24 @@ class SingleEntryQueryParams: def __init__( self, *, - response_format: str = Query("json"), - email_address: EmailStr = Query(""), - response_fields: str = Query(""), + response_format: str = Query( + "json", + description="The output format requested (see section [Response Format](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/" + "optimade.rst#response-format) in the spec). Defaults to the format string 'json', which specifies the standard output format " + "described in this specification.\n**Example**: http://example.com/optimade/v0.9/structures?response_format=xml", + ), + email_address: EmailStr = Query( + "", + description="An email address of the user making the request. The email SHOULD be that of a person and not an automatic system.\n" + "**Example**: http://example.com/optimade/v0.9/structures?email_address=user@example.com", + ), + response_fields: str = Query( + "", + description="A comma-delimited set of fields to be provided in the output. If provided, these fields MUST be returned along with " + "the REQUIRED fields. Other OPTIONAL fields MUST NOT be returned when this parameter is present.\n" + "**Example**: http://example.com/optimade/v0.9/structures?response_fields=last_modified,nsites", + regex=r"([a-z_][a-z_0-9]*(,[a-z_][a-z_0-9]*)*)?", + ), ): self.response_format = response_format self.email_address = email_address diff --git a/optimade/server/entry_collections.py b/optimade/server/entry_collections.py index 19ee97505..5df982a37 100644 --- a/optimade/server/entry_collections.py +++ b/optimade/server/entry_collections.py @@ -7,7 +7,7 @@ from optimade.filterparser import LarkParser from optimade.filtertransformers.mongo import MongoTransformer -from optimade.models import NonnegativeInt, EntryResource +from optimade.models import EntryResource from .config import CONFIG from .deps import EntryListingQueryParams, SingleEntryQueryParams @@ -60,7 +60,7 @@ def get_attribute_fields(self) -> set: @abstractmethod def find( self, params: EntryListingQueryParams - ) -> Tuple[List[EntryResource], NonnegativeInt, bool, set]: + ) -> Tuple[List[EntryResource], int, bool, set]: """ Fetches results and indicates if more data is available. @@ -70,7 +70,7 @@ def find( params (EntryListingQueryParams): entry listing URL query params Returns: - Tuple[List[Entry], NonnegativeInt, bool, set]: (results, data_returned, more_data_available, fields) + Tuple[List[Entry], int, bool, set]: (results, data_returned, more_data_available, fields) """ @@ -112,7 +112,7 @@ def count(self, **kwargs): def find( self, params: Union[EntryListingQueryParams, SingleEntryQueryParams] - ) -> Tuple[List[EntryResource], NonnegativeInt, bool, set]: + ) -> Tuple[List[EntryResource], int, bool, set]: criteria = self._parse_params(params) all_fields = criteria.pop("fields") diff --git a/optimade/server/main.py b/optimade/server/main.py index d55d61ead..41331fd17 100644 --- a/optimade/server/main.py +++ b/optimade/server/main.py @@ -62,7 +62,7 @@ def load_entries(endpoint_name: str, endpoint_collection: MongoCollection): load_entries(name, collection) -# Add varioud middleware +# Add various middleware app.add_middleware(RedirectSlashedURLs) diff --git a/optimade/server/routers/links.py b/optimade/server/routers/links.py index fa119e3a2..59b22fad5 100644 --- a/optimade/server/routers/links.py +++ b/optimade/server/routers/links.py @@ -32,7 +32,7 @@ def get_links(request: Request, params: EntryListingQueryParams = Depends()): setattr(params, str_param, "") for int_param in [ "page_offset", - "page_page", + "page_number", "page_cursor", "page_above", "page_below", diff --git a/setup.cfg b/setup.cfg index b6541be00..065cc1af4 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,2 +1,2 @@ [pycodestyle] -ignore = E501, W503 \ No newline at end of file +ignore = E251,E252,E501,W503 \ No newline at end of file diff --git a/tests/models/test_bad_structures.json b/tests/models/test_bad_structures.json index a3c44f94e..1fec49d69 100644 --- a/tests/models/test_bad_structures.json +++ b/tests/models/test_bad_structures.json @@ -1694,5 +1694,129 @@ ], "structure_features": [], "task_id": "mpf_1" + }, + { + "task_id": "db/1234567", + "type": "structure", + "last_modified": { + "$date": "2019-06-08T05:13:37.331Z" + }, + "band_gap": 1.23456, + "_mp_chemsys": "Ge-Si", + "elements": ["Ge", "Si"], + "nsites": 3, + "nelements": 2, + "elements_ratios": [0.5, 0.5], + "pretty_formula": "GeSi", + "formula_anonymous": "AB", + "dimension_types": [1, 1, 1], + "lattice_vectors": [[4.0,0.0,0.0],[0.0,4.0,0.0],[0.0,1.0,4.0]], + "cartesian_site_positions": [ [0,0,0], [0,0,0], [0,0] ], + "species": [ + {"name": "Si", "chemical_symbols": ["Si"], "concentration": [1.0] }, + {"name": "Ge", "chemical_symbols": ["Ge"], "concentration": [1.0] }, + {"name": "vac", "chemical_symbols": ["vacancy"], "concentration": [1.0] } + ], + "species_at_sites": ["Si", "Ge", "vac"], + "assemblies": [ + { + "sites_in_groups": [ [0], [1], [2] ], + "group_probabilities": [0.3, 0.5, 0.2] + } + ], + "structure_features": ["assemblies"] + }, + { + "task_id": "db/1234567", + "type": "structure", + "last_modified": { + "$date": "2019-06-08T05:13:37.331Z" + }, + "band_gap": 1.23456, + "_mp_chemsys": "Ge-Si", + "elements": ["Ge", "Si"], + "nsites": 3, + "nelements": 2, + "elements_ratios": [0.5, 0.5], + "pretty_formula": "GeSi", + "formula_anonymous": "AB", + "dimension_types": [1, 1, 1], + "lattice_vectors": [[4.0,0.0,0.0],[0.0,4.0,0.0],[0.0,1.0,4.0]], + "cartesian_site_positions": [ [0,0,0], [0,0,0], [0,0,0,0] ], + "species": [ + {"name": "Si", "chemical_symbols": ["Si"], "concentration": [1.0] }, + {"name": "Ge", "chemical_symbols": ["Ge"], "concentration": [1.0] }, + {"name": "vac", "chemical_symbols": ["vacancy"], "concentration": [1.0] } + ], + "species_at_sites": ["Si", "Ge", "vac"], + "assemblies": [ + { + "sites_in_groups": [ [0], [1], [2] ], + "group_probabilities": [0.3, 0.5, 0.2] + } + ], + "structure_features": ["assemblies"] + }, + { + "task_id": "db/1234567", + "type": "structure", + "last_modified": { + "$date": "2019-06-08T05:13:37.331Z" + }, + "band_gap": 1.23456, + "_mp_chemsys": "Ge-Si", + "elements": ["Ge", "Si"], + "nsites": 3, + "nelements": 2, + "elements_ratios": [0.5, 0.5], + "pretty_formula": "GeSi", + "formula_anonymous": "AB", + "dimension_types": [1, 1, 1], + "lattice_vectors": [[4.0,0.0,0.0],[0.0,4.0,0.0],[0.0,1.0]], + "cartesian_site_positions": [ [0,0,0], [0,0,0], [0,0,0] ], + "species": [ + {"name": "Si", "chemical_symbols": ["Si"], "concentration": [1.0] }, + {"name": "Ge", "chemical_symbols": ["Ge"], "concentration": [1.0] }, + {"name": "vac", "chemical_symbols": ["vacancy"], "concentration": [1.0] } + ], + "species_at_sites": ["Si", "Ge", "vac"], + "assemblies": [ + { + "sites_in_groups": [ [0], [1], [2] ], + "group_probabilities": [0.3, 0.5, 0.2] + } + ], + "structure_features": ["assemblies"] + }, + { + "task_id": "db/1234567", + "type": "structure", + "last_modified": { + "$date": "2019-06-08T05:13:37.331Z" + }, + "band_gap": 1.23456, + "_mp_chemsys": "Ge-Si", + "elements": ["Ge", "Si"], + "nsites": 3, + "nelements": 2, + "elements_ratios": [0.5, 0.5], + "pretty_formula": "GeSi", + "formula_anonymous": "AB", + "dimension_types": [1, 1, 1], + "lattice_vectors": [[4.0,0.0,0.0],[0.0,4.0,0.0],[0.0,1.0,4.0,5.0]], + "cartesian_site_positions": [ [0,0,0], [0,0,0], [0,0,0] ], + "species": [ + {"name": "Si", "chemical_symbols": ["Si"], "concentration": [1.0] }, + {"name": "Ge", "chemical_symbols": ["Ge"], "concentration": [1.0] }, + {"name": "vac", "chemical_symbols": ["vacancy"], "concentration": [1.0] } + ], + "species_at_sites": ["Si", "Ge", "vac"], + "assemblies": [ + { + "sites_in_groups": [ [0], [1], [2] ], + "group_probabilities": [0.3, 0.5, 0.2] + } + ], + "structure_features": ["assemblies"] } ] diff --git a/tests/models/test_models.py b/tests/models/test_models.py index b3603b3ff..e0e74c302 100644 --- a/tests/models/test_models.py +++ b/tests/models/test_models.py @@ -4,8 +4,7 @@ import unittest import json -from pydantic import ValidationError, BaseModel, ConfigError -from optimade.models.utils import conlist +from pydantic import ValidationError # pylint: disable=no-name-in-module from optimade.models import ( StructureResource, EntryRelationships, @@ -167,25 +166,3 @@ def test_available_api_versions(): for data in good_urls: AvailableApiVersion(**data) - - -def test_constrained_list(): - class ConListModel(BaseModel): - v: conlist(len_eq=3) - - ConListModel(v=[1, 2, 3]) - with pytest.raises(ValidationError) as exc_info: - ConListModel(v=[1, 2, 3, 4]) - assert exc_info.value.errors() == [ - { - "loc": ("v",), - "msg": "ensure this value is less than or equal to 3", - "type": "value_error.number.not_le", - "ctx": {"limit_value": 3}, - } - ] - - with pytest.raises(ConfigError): - - class ConListModel(BaseModel): # pylint: disable=function-redefined - v: conlist(len_eq=3, len_lt=3) diff --git a/tests/models/test_more_structures.json b/tests/models/test_more_structures.json index 0928ec9c0..d76f66eb3 100644 --- a/tests/models/test_more_structures.json +++ b/tests/models/test_more_structures.json @@ -1,64 +1,95 @@ [ -{ - "task_id": "db/1234567", - "type": "structure", - "last_modified": { - "$date": "2019-06-08T05:13:37.331Z" - }, - "band_gap": 1.23456, - "_mp_chemsys": "Ge-Si", - "elements": ["Ge", "Si"], - "nsites": 3, - "nelements": 2, - "elements_ratios": [0.5, 0.5], - "pretty_formula": "GeSi", - "formula_anonymous": "AB", - "dimension_types": [1, 1, 1], - "lattice_vectors": [[4.0,0.0,0.0],[0.0,4.0,0.0],[0.0,1.0,4.0]], - "cartesian_site_positions": [ [0,0,0], [0,0,0], [0,0,0] ], - "species": [ - {"name": "Si", "chemical_symbols": ["Si"], "concentration": [1.0] }, - {"name": "Ge", "chemical_symbols": ["Ge"], "concentration": [1.0] }, - {"name": "vac", "chemical_symbols": ["vacancy"], "concentration": [1.0] } - ], - "species_at_sites": ["Si", "Ge", "vac"], - "assemblies": [ - { - "sites_in_groups": [ [0], [1], [2] ], - "group_probabilities": [0.3, 0.5, 0.2] - } - ], - "structure_features": ["assemblies"] -}, -{ - "task_id": "db/1234567", - "type": "structure", - "last_modified": { - "$date": "2019-06-08T05:13:37.331Z" - }, - "band_gap": 1.23456, - "_mp_chemsys": "Ge-Si", - "elements": ["Ge", "Si"], - "nelements": 2, - "nsites": 3, - "elements_ratios": [0.5, 0.5], - "pretty_formula": "GeSi", - "formula_anonymous": "AB", - "dimension_types": [1, 0, 1], - "lattice_vectors": [[4.0,0.0,0.0],[null,4.0, null],[0.0,1.0,4.0]], - "cartesian_site_positions": [ [0,0,0], [0,0,0], [0,0,0] ], - "species_at_sites": ["Si", "Ge", "vac"], - "species": [ - {"name": "Si", "chemical_symbols": ["Si"], "concentration": [1.0] }, - {"name": "Ge", "chemical_symbols": ["Ge"], "concentration": [1.0] }, - {"name": "vac", "chemical_symbols": ["vacancy"], "concentration": [1.0] } - ], - "assemblies": [ - { - "sites_in_groups": [ [0], [1], [2] ], - "group_probabilities": [0.3, 0.5, 0.2] - } - ], - "structure_features": ["assemblies"] -} + { + "task_id": "db/1234567", + "type": "structure", + "last_modified": { + "$date": "2019-06-08T05:13:37.331Z" + }, + "band_gap": 1.23456, + "_mp_chemsys": "Ge-Si", + "elements": ["Ge", "Si"], + "nsites": 3, + "nelements": 2, + "elements_ratios": [0.5, 0.5], + "pretty_formula": "GeSi", + "formula_anonymous": "AB", + "dimension_types": [1, 1, 1], + "lattice_vectors": [[4.0,0.0,0.0],[0.0,4.0,0.0],[0.0,1.0,4.0]], + "cartesian_site_positions": [ [0,0,0], [0,0,0], [0,0,0] ], + "species": [ + {"name": "Si", "chemical_symbols": ["Si"], "concentration": [1.0] }, + {"name": "Ge", "chemical_symbols": ["Ge"], "concentration": [1.0] }, + {"name": "vac", "chemical_symbols": ["vacancy"], "concentration": [1.0] } + ], + "species_at_sites": ["Si", "Ge", "vac"], + "assemblies": [ + { + "sites_in_groups": [ [0], [1], [2] ], + "group_probabilities": [0.3, 0.5, 0.2] + } + ], + "structure_features": ["assemblies"] + }, + { + "task_id": "db/1234567", + "type": "structure", + "last_modified": { + "$date": "2019-06-08T05:13:37.331Z" + }, + "band_gap": 1.23456, + "_mp_chemsys": "Ge-Si", + "elements": ["Ge", "Si"], + "nelements": 2, + "nsites": 3, + "elements_ratios": [0.5, 0.5], + "pretty_formula": "GeSi", + "formula_anonymous": "AB", + "dimension_types": [1, 0, 1], + "lattice_vectors": [[4.0,0.0,0.0],[null,4.0, null],[0.0,1.0,4.0]], + "cartesian_site_positions": [ [0,0,0], [0,0,0], [0,0,0] ], + "species_at_sites": ["Si", "Ge", "vac"], + "species": [ + {"name": "Si", "chemical_symbols": ["Si"], "concentration": [1.0] }, + {"name": "Ge", "chemical_symbols": ["Ge"], "concentration": [1.0] }, + {"name": "vac", "chemical_symbols": ["vacancy"], "concentration": [1.0] } + ], + "assemblies": [ + { + "sites_in_groups": [ [0], [1], [2] ], + "group_probabilities": [0.3, 0.5, 0.2] + } + ], + "structure_features": ["assemblies"] + }, + { + "task_id": "db/1234567", + "type": "structure", + "last_modified": { + "$date": "2019-06-08T05:13:37.331Z" + }, + "band_gap": 1.23456, + "_mp_chemsys": "Ge-Si", + "elements": ["Ge", "Si"], + "nelements": 2, + "nsites": 3, + "elements_ratios": [0.5, 0.5], + "pretty_formula": "GeSi", + "formula_anonymous": "AB", + "dimension_types": [1, 0, 1], + "lattice_vectors": [[4.0,0.0,0.0],[null,4.0, null],[0.0,1.0,4.0]], + "cartesian_site_positions": [ [0,null,0], [0,0,0], [0,"nan",0] ], + "species_at_sites": ["Si", "Ge", "vac"], + "species": [ + {"name": "Si", "chemical_symbols": ["Si"], "concentration": [1.0] }, + {"name": "Ge", "chemical_symbols": ["Ge"], "concentration": [1.0] }, + {"name": "vac", "chemical_symbols": ["vacancy"], "concentration": [1.0] } + ], + "assemblies": [ + { + "sites_in_groups": [ [0], [1], [2] ], + "group_probabilities": [0.3, 0.5, 0.2] + } + ], + "structure_features": ["assemblies", "unknown_positions"] + } ]