Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update model descriptions and openapi.json for 1.0.0-rc2 #351

Merged
merged 8 commits into from
Jun 25, 2020
Merged
56 changes: 28 additions & 28 deletions openapi/index_openapi.json

Large diffs are not rendered by default.

140 changes: 70 additions & 70 deletions openapi/openapi.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion optimade/models/baseinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class BaseInfoAttributes(BaseModel):
default=False,
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).",
"(i.e., the default is for `is_index` to be false).",
ml-evs marked this conversation as resolved.
Show resolved Hide resolved
)

@validator("entry_types_by_format", check_fields=False)
Expand Down
112 changes: 58 additions & 54 deletions optimade/models/entries.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,125 +52,129 @@ class EntryResourceAttributes(Attributes):

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

- **Type**: string.
- **Requirements/Conventions**:

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

- **Examples**:
ml-evs marked this conversation as resolved.
Show resolved Hide resolved

- :val:`"8bd3e750-b477-41a0-9b11-3a799f21b44f"`
- :val:`"fjeiwoj,54;@=%<>#32"` (Strings that are not URL-safe are allowed.)""",
- `"8bd3e750-b477-41a0-9b11-3a799f21b44f"`
- `"fjeiwoj,54;@=%<>#32"` (Strings that are not URL-safe are allowed.)""",
)

last_modified: datetime = Field(
...,
description="""Date and time representing when the entry was last modified.

- **Type**: timestamp.
- **Requirements/Conventions**:

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

- **Example**:

- As part of JSON response format: :VAL:`"2007-04-05T14:30Z"` (i.e., encoded as an `RFC 3339 Internet Date/Time Format <https://tools.ietf.org/html/rfc3339#section-5.6>`__ string.)""",
- As part of JSON response format: `"2007-04-05T14:30:20Z"` (i.e., encoded as an [RFC 3339 Internet Date/Time Format](https://tools.ietf.org/html/rfc3339#section-5.6) string.)""",
)


class EntryResource(Resource):

id: str = Field(
...,
description="""An entry's ID as defined in section `Definition of Terms`_.
description="""An entry's ID as defined in section Definition of Terms.
CasperWA marked this conversation as resolved.
Show resolved Hide resolved

- **Type**: string.
- **Requirements/Conventions**:

- **Support**: REQUIRED, MUST NOT be :val:`null`.
- **Query**: MUST be a queryable property with support for all mandatory filter features.
- **Response**: REQUIRED in the response.
- See section `Definition of Terms`_.
- **Requirements/Conventions**:
- **Support**: MUST be supported by all implementations, MUST NOT be `null`.
CasperWA marked this conversation as resolved.
Show resolved Hide resolved
- **Query**: MUST be a queryable property with support for all mandatory filter features.
- **Response**: REQUIRED in the response.

- **Examples**:

- :val:`"db/1234567"`
- :val:`"cod/2000000"`
- :val:`"cod/2000000@1234567"`
- :val:`"nomad/L1234567890"`
- :val:`"42"`""",
- `"db/1234567"`
- `"cod/2000000"`
- `"cod/2000000@1234567"`
- `"nomad/L1234567890"`
- `"42"`""",
)

type: str = Field(
...,
description="""The name of the type of an entry.

- **Type**: string.
- **Requirements/Conventions**:

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

- **Example**: :val:`"structures"`""",
- **Example**: `"structures"`""",
)

attributes: EntryResourceAttributes = Field(
...,
description="""a dictionary, containing key-value pairs representing the entry's properties, except for type and id.

Database-provider-specific properties need to include the database-provider-specific prefix
(see appendix `Database-Provider-Specific Namespace Prefixes`_).""",
description="""A dictionary, containing key-value pairs representing the entry's properties, except for `type` and `id`.
Database-provider-specific properties need to include the database-provider-specific prefix (see section on Database-Provider-Specific Namespace Prefixes).""",
ml-evs marked this conversation as resolved.
Show resolved Hide resolved
)

relationships: Optional[EntryRelationships] = Field(
None,
description="""a dictionary containing references to other entries according to the description in section `Relationships`_
encoded as `JSON API Relationships <https://jsonapi.org/format/1.0/#document-resource-object-relationships>`__.
The OPTIONAL human-readable description of the relationship MAY be provided in the :field:`description` field inside the :field:`meta` dictionary.""",
description="""A dictionary containing references to other entries according to the description in section Relationships encoded as [JSON API Relationships](https://jsonapi.org/format/1.0/#document-resource-object-relationships).
ml-evs marked this conversation as resolved.
Show resolved Hide resolved
The OPTIONAL human-readable description of the relationship MAY be provided in the `description` field inside the `meta` dictionary of the JSON API resource identifier object.""",
)


class EntryInfoProperty(BaseModel):

description: str = Field(..., description="description of the entry property")
description: str = Field(
..., description="A human-readable description of the entry property"
)

unit: Optional[str] = Field(
None, description="the physical unit of the entry property"
None,
description="""The physical unit of the entry property.
It is RECOMMENDED that non-standard (non-SI) units are described in the description for the property.""",
)

sortable: Optional[bool] = Field(
None,
description='defines whether the entry property can be used for sorting with the "sort" parameter. '
"If the entry listing endpoint supports sorting, this key MUST be present for sortable properties with value `true`.",
description="""Defines whether the entry property can be used for sorting with the "sort" parameter.
ml-evs marked this conversation as resolved.
Show resolved Hide resolved
If the entry listing endpoint supports sorting, this key MUST be present for sortable properties with value `true`.""",
)

type: Optional[DataType] = Field(
None,
description="Data type of value. Must equal a valid OPTIMADE data type as listed and defined under 'Data types'.",
description="""String.
The type of the property's value.
ml-evs marked this conversation as resolved.
Show resolved Hide resolved

This MUST be any of the types defined in the Data types section.
ml-evs marked this conversation as resolved.
Show resolved Hide resolved
For the purpose of compatibility with future versions of this specification, a client MUST accept values that are not `string` values specifying any of the OPTIMADE Data types, but MUST then also disregard the `type` field.
ml-evs marked this conversation as resolved.
Show resolved Hide resolved
Note, if the value is a nested type, only the outermost type should be reported.
E.g., for the entry resource `structures`, the `species` property is defined as a list of dictionaries, hence its `type` value would be `list`.
Data type of value. Must equal a valid OPTIMADE data type as listed and defined under 'Data types'.""",
ml-evs marked this conversation as resolved.
Show resolved Hide resolved
)


class EntryInfoResource(BaseModel):

formats: List[str] = Field(..., description="list of available output formats.")
formats: List[str] = Field(
..., description="List of output formats available for this type of entry."
)

description: str = Field(..., description="description of the entry")
description: str = Field(..., description="Description of the entry")
ml-evs marked this conversation as resolved.
Show resolved Hide resolved

properties: Dict[str, EntryInfoProperty] = Field(
...,
description="a dictionary describing queryable properties for this "
"entry type, where each key is a property ID.",
description="A dictionary describing queryable properties for this entry type, where each key is a property name.",
)

output_fields_by_format: Dict[str, List[str]] = Field(
...,
description="a dictionary of available output fields for this entry "
"type, where the keys are the values of the `formats` list "
"and the values are the keys of the `properties` dictionary.",
description="Dictionary of available output fields for this entry type, where the keys are the values of the `formats` list and the values are the keys of the `properties` dictionary.",
)
12 changes: 5 additions & 7 deletions optimade/models/index_metadb.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class IndexInfoAttributes(BaseInfoAttributes):
const=True,
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).",
"(i.e., the default is for `is_index` to be false).",
ml-evs marked this conversation as resolved.
Show resolved Hide resolved
)


Expand All @@ -45,8 +45,8 @@ class IndexRelationship(BaseModel):

data: Union[None, RelatedLinksResource] = Field(
...,
description="JSON API resource linkage. It MUST be either null or contain "
"a single Links identifier object with the fields 'id' and 'type'",
description="""JSON API resource linkage.
ml-evs marked this conversation as resolved.
Show resolved Hide resolved
It MUST be either `null` or contain a single Links identifier object with the fields `id` and `type`""",
CasperWA marked this conversation as resolved.
Show resolved Hide resolved
)


Expand All @@ -56,8 +56,6 @@ class IndexInfoResource(BaseInfoResource):
attributes: IndexInfoAttributes = Field(...)
relationships: Union[None, Dict[DefaultRelationship, IndexRelationship]] = Field(
...,
description="Reference to the child identifier object under the links endpoint "
"that the provider has chosen as their 'default' OPTIMADE API database. "
"A client SHOULD present this database as the first choice when an end-user "
"chooses this provider.",
description="""Reference to the child identifier object under the `links` endpoint that the provider has chosen as their 'default' OPTIMADE API database.
ml-evs marked this conversation as resolved.
Show resolved Hide resolved
A client SHOULD present this database as the first choice when an end-user chooses this provider.""",
)
9 changes: 6 additions & 3 deletions optimade/models/jsonapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,10 @@ class BaseResource(BaseModel):

class RelationshipLinks(BaseModel):
"""A resource object **MAY** contain references to other resource objects (\"relationships\").
Relationships may be to-one or to-many. Relationships can be specified by including a member in a resource's links object."""
Relationships may be to-one or to-many.
Relationships can be specified by including a member in a resource's links object.

"""

self: Optional[Union[AnyUrl, Link]] = Field(None, description="A link to itself")
ml-evs marked this conversation as resolved.
Show resolved Hide resolved
related: Optional[Union[AnyUrl, Link]] = Field(
CasperWA marked this conversation as resolved.
Show resolved Hide resolved
Expand Down Expand Up @@ -237,7 +240,7 @@ def check_illegal_attributes_fields(cls, values):


class Resource(BaseResource):
"""Resource objects appear in a JSON:API document to represent resources."""
"""Resource objects appear in a JSON API document to represent resources."""
CasperWA marked this conversation as resolved.
Show resolved Hide resolved

links: Optional[ResourceLinks] = Field(
None, description="a links object containing links related to the resource."
Expand All @@ -252,7 +255,7 @@ class Resource(BaseResource):
)
relationships: Optional[Relationships] = Field(
None,
description="a relationships object describing relationships between the resource and other JSON:API resources.",
description="Relationships object describing relationships between the resource and other JSON API resources.",
)


Expand Down
22 changes: 10 additions & 12 deletions optimade/models/links.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,11 @@ class LinksResourceAttributes(Attributes):

name: str = Field(
...,
description="Human-readable name for the OPTIMADE API implementation "
"a client may provide in a list to an end-user.",
description="Human-readable name for the OPTIMADE API implementation, e.g., for use in clients to show the name to the end-user.",
)
description: str = Field(
...,
description="Human-readable description for the OPTIMADE API implementation "
"a client may provide in a list to an end-user.",
description="Human-readable description for the OPTIMADE API implementation, e.g., for use in clients to show a description to the end-user.",
)
base_url: Union[AnyUrl, Link, None] = Field(
...,
Expand All @@ -61,27 +59,28 @@ class LinksResourceAttributes(Attributes):

link_type: LinkType = Field(
...,
description="The link type of the represented resource in relation to this implementation. MUST be one of these values: 'child', 'root', 'external', 'providers'.",
description="""The link type of the represented resource in relation to this implementation.
CasperWA marked this conversation as resolved.
Show resolved Hide resolved
MUST be one of these values: 'child', 'root', 'external', 'providers'.""",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
MUST be one of these values: 'child', 'root', 'external', 'providers'.""",
MUST be one of the values listed in section [Link Types](https://github.com/Materials-Consortia/OPTiMaDe/blob/v1.0.0-rc.2/optimade.rst#link-types).""",

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? Do you think we'll add any more link types to make this change worth it? Otherwise this info is not present directly in the openapi schemas

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be as an Enum.
And this is simply changing it to the description in the spec.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it's indeed in the schema through the Aggregate Enum class.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the way I've recently been adding "Literal"s :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do you want to handle this then, if we're not doing internal links? Happy to keep it as is, even if its a bit redundant with the enum?

Copy link
Member

@CasperWA CasperWA Jun 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will do as we do for all the other descriptions, mention a section in the spec, but leave out the link (or add it) and leave it up to #366 to add it properly.

I.e., replicate the spec description - so applying my suggestion (either with or without the markdown hyperlink).

)

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

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

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

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

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


Expand All @@ -96,8 +95,7 @@ class LinksResource(EntryResource):

attributes: LinksResourceAttributes = Field(
...,
description="a dictionary containing key-value pairs representing the "
"entry's properties.",
description="A dictionary containing key-value pairs representing the entry's properties.",
ml-evs marked this conversation as resolved.
Show resolved Hide resolved
)

@root_validator(pre=True)
Expand Down
26 changes: 13 additions & 13 deletions optimade/models/optimade_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ class OptimadeError(jsonapi.Error):

class Warnings(OptimadeError):
"""OPTIMADE-specific warning class based on OPTIMADE-specific JSON API Error.

From the specification:

A warning resource object is defined similarly to a JSON API
Expand All @@ -142,6 +143,7 @@ class Warnings(OptimadeError):
unrecognized search attributes or deprecated features.

Note: Must be named "Warnings", since "Warning" is a built-in Python class.

"""

type: str = Field(
Expand Down Expand Up @@ -236,24 +238,23 @@ class ResponseMeta(jsonapi.Meta):

ml-evs marked this conversation as resolved.
Show resolved Hide resolved
api_version: str = Field(
...,
description="a string containing the version of the API "
"implementation, e.g. v0.9.5",
description="A string containing the version of the API implementation, e.g. v0.9.5",
)

time_stamp: datetime = Field(
...,
description="a string containing the date and time at which the query was exexcuted",
description="A timestamp containing the date and time at which the query was executed.",
)

data_returned: int = Field(
...,
description="an integer containing the number of data objects "
"returned for the query.",
description="An integer containing the total number of data resource objects returned for the current `filter` query, independent of pagination.",
ge=0,
)

more_data_available: bool = Field(
..., description="`false` if all data has been returned, and `true` " "if not."
...,
description="`false` if all data resource objects for this `filter` query have been returned in the response or if it is the last page of a paginated response, and `true` otherwise.",
)

provider: Provider = Field(
Expand All @@ -262,8 +263,7 @@ class ResponseMeta(jsonapi.Meta):

data_available: Optional[int] = Field(
None,
description="an integer containing the total number of data "
"objects available in the database",
description="An integer containing the total number of data resource objects available in the database for the endpoint.",
)

last_id: Optional[str] = Field(
Expand All @@ -280,11 +280,11 @@ class ResponseMeta(jsonapi.Meta):

warnings: Optional[List[Warnings]] = Field(
None,
description="List of warning resource objects representing non-critical errors or warnings. "
"A warning resource object is defined similarly to a JSON API error object, but MUST also include the field type, "
'which MUST have the value "warning". The field detail MUST be present and SHOULD contain a non-critical message, '
"e.g., reporting unrecognized search attributes or deprecated features. The field status, representing a HTTP "
"response status code, MUST NOT be present for a warning resource object. This is an exclusive field for error resource objects.",
description="""A list of warning resource objects representing non-critical errors or warnings.
A warning resource object is defined similarly to a [JSON API error object](http://jsonapi.org/format/1.0/#error-objects), but MUST also include the field `type`, which MUST have the value `"warning"`.
The field `detail` MUST be present and SHOULD contain a non-critical message, e.g., reporting unrecognized search attributes or deprecated features.
The field `status`, representing a HTTP response status code, MUST NOT be present for a warning resource object.
This is an exclusive field for error resource objects.""",
uniqueItems=True,
)

Expand Down