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

Document interfaces better in/for swagger #1487

Open
3 tasks
yarikoptic opened this issue Feb 8, 2023 · 2 comments
Open
3 tasks

Document interfaces better in/for swagger #1487

yarikoptic opened this issue Feb 8, 2023 · 2 comments
Labels
documentation Changes only affect the documentation maintenance Action to maintain the system (neither a bugfix nor an enhancement)

Comments

@yarikoptic
Copy link
Member

@yarikoptic yarikoptic added the documentation Changes only affect the documentation label Feb 8, 2023
@satra
Copy link
Member

satra commented Feb 8, 2023

coincidentally i used:

docker run -it --rm koxudaxi/datamodel-code-generator --url https://dandi.readme.io/openapi/608964cff0a9550031c4ff59 --output-model-type pydantic.BaseModel

to create this:

Generated objects
# generated by datamodel-codegen:
#   filename:  https://dandi.readme.io/openapi/608964cff0a9550031c4ff59
#   timestamp: 2023-02-08T23:04:46+00:00

from __future__ import annotations

from datetime import datetime
from enum import Enum
from typing import Any, Dict, List, Optional
from uuid import UUID

from pydantic import AnyUrl, BaseModel, Field, conint, constr


class AssetDetail(BaseModel):
    asset_id: Optional[UUID] = Field(None, title='Asset id')
    blob: Optional[UUID] = Field(None, title='Blob')
    zarr: Optional[UUID] = Field(None, title='Zarr')
    path: constr(min_length=1, max_length=512) = Field(..., title='Path')
    size: Optional[str] = Field(None, title='Size')
    created: Optional[datetime] = Field(None, title='Created')
    modified: Optional[datetime] = Field(None, title='Modified')
    metadata: Optional[Dict[str, Any]] = Field(None, title='Metadata')


class Digest(BaseModel):
    algorithm: constr(min_length=1) = Field(..., title='Algorithm')
    value: constr(min_length=1) = Field(..., title='Value')


class AssetBlob(BaseModel):
    blob_id: UUID = Field(..., title='Blob id')
    etag: constr(
        regex=r'^[0-9a-f]{32}(-[1-9][0-9]*)?$', min_length=1, max_length=40
    ) = Field(..., title='Etag')
    sha256: Optional[constr(regex=r'^[0-9a-f]{64}$', max_length=64)] = Field(
        None, title='Sha256'
    )
    size: conint(ge=0, le=9223372036854775808) = Field(..., title='Size')


class EmbargoStatus(Enum):
    EMBARGOED = 'EMBARGOED'
    UNEMBARGOING = 'UNEMBARGOING'
    OPEN = 'OPEN'


class DandisetList(BaseModel):
    identifier: Optional[str] = Field(None, title='Identifier')
    created: Optional[datetime] = Field(None, title='Created')
    modified: Optional[datetime] = Field(None, title='Modified')
    contact_person: Optional[str] = Field(None, title='Contact person')
    embargo_status: Optional[EmbargoStatus] = Field(None, title='Embargo status')
    most_recent_published_version: Optional[str] = Field(
        None, title='Most recent published version'
    )
    draft_version: Optional[str] = Field(None, title='Draft version')


class VersionMetadata(BaseModel):
    metadata: Optional[Dict[str, Any]] = Field(None, title='Metadata')
    name: constr(min_length=1, max_length=300) = Field(..., title='Name')


class Dandiset(BaseModel):
    identifier: Optional[str] = Field(None, title='Identifier')
    created: Optional[datetime] = Field(None, title='Created')
    modified: Optional[datetime] = Field(None, title='Modified')
    contact_person: Optional[str] = Field(None, title='Contact person')
    embargo_status: Optional[EmbargoStatus] = Field(None, title='Embargo status')


class Status(Enum):
    Pending = 'Pending'
    Validating = 'Validating'
    Valid = 'Valid'
    Invalid = 'Invalid'
    Publishing = 'Publishing'
    Published = 'Published'


class Version(BaseModel):
    version: constr(
        regex=r'^(0\.\d{6}\.\d{4})|draft$', min_length=1, max_length=13
    ) = Field(..., title='Version')
    name: constr(min_length=1, max_length=300) = Field(..., title='Name')
    asset_count: Optional[str] = Field(None, title='Asset count')
    size: Optional[str] = Field(None, title='Size')
    status: Optional[Status] = Field(None, title='Status')
    created: Optional[datetime] = Field(None, title='Created')
    modified: Optional[datetime] = Field(None, title='Modified')
    dandiset: Dandiset


class DandisetDetail(BaseModel):
    identifier: Optional[str] = Field(None, title='Identifier')
    created: Optional[datetime] = Field(None, title='Created')
    modified: Optional[datetime] = Field(None, title='Modified')
    contact_person: Optional[str] = Field(None, title='Contact person')
    embargo_status: Optional[EmbargoStatus] = Field(None, title='Embargo status')
    most_recent_published_version: Optional[Version] = None
    draft_version: Optional[Version] = None


class User(BaseModel):
    username: constr(regex=r'^[\w.@+-]+$', min_length=1) = Field(..., title='Username')


class VersionDetail(BaseModel):
    version: constr(
        regex=r'^(0\.\d{6}\.\d{4})|draft$', min_length=1, max_length=13
    ) = Field(..., title='Version')
    name: constr(min_length=1, max_length=300) = Field(..., title='Name')
    asset_count: Optional[str] = Field(None, title='Asset count')
    size: Optional[str] = Field(None, title='Size')
    status: constr(min_length=1) = Field(..., title='Status')
    created: Optional[datetime] = Field(None, title='Created')
    modified: Optional[datetime] = Field(None, title='Modified')
    dandiset: Dandiset
    asset_validation_errors: Optional[str] = Field(
        None, title='Asset validation errors'
    )
    version_validation_errors: Dict[str, Any] = Field(
        ..., title='Version validation errors'
    )
    metadata: Optional[Dict[str, Any]] = Field(None, title='Metadata')
    contact_person: Optional[str] = Field(None, title='Contact person')


class Asset(BaseModel):
    asset_id: Optional[UUID] = Field(None, title='Asset id')
    blob: Optional[UUID] = Field(None, title='Blob')
    zarr: Optional[UUID] = Field(None, title='Zarr')
    path: constr(min_length=1, max_length=512) = Field(..., title='Path')
    size: Optional[str] = Field(None, title='Size')
    created: Optional[datetime] = Field(None, title='Created')
    modified: Optional[datetime] = Field(None, title='Modified')
    metadata: Optional[Dict[str, Any]] = Field(None, title='Metadata')


class AssetRequest(BaseModel):
    metadata: Dict[str, Any] = Field(..., title='Metadata')
    blob_id: Optional[UUID] = Field(None, title='Blob id')
    zarr_id: Optional[UUID] = Field(None, title='Zarr id')


class AssetFile(BaseModel):
    asset_id: Optional[UUID] = Field(None, title='Asset id')
    url: AnyUrl = Field(..., title='Url')


class AssetPaths(BaseModel):
    path: constr(min_length=1, max_length=512) = Field(..., title='Path')
    version: int = Field(..., title='Version')
    aggregate_files: Optional[conint(ge=0, le=9223372036854775808)] = Field(
        None, title='Aggregate files'
    )
    aggregate_size: Optional[conint(ge=0, le=9223372036854775808)] = Field(
        None, title='Aggregate size'
    )
    asset: AssetFile


class Status1(Enum):
    Pending = 'Pending'
    Validating = 'Validating'
    Valid = 'Valid'
    Invalid = 'Invalid'


class AssetValidation(BaseModel):
    status: Optional[Status1] = Field(None, title='Status')
    validation_errors: Optional[Dict[str, Any]] = Field(None, title='Validation errors')


class ApiService(BaseModel):
    url: constr(min_length=1) = Field(..., title='Url')


class ApiServices(BaseModel):
    api: ApiService
    webui: ApiService
    jupyterhub: ApiService


class ApiInfo(BaseModel):
    schema_version: constr(min_length=1) = Field(..., title='Schema version')
    schema_url: AnyUrl = Field(..., title='Schema url')
    version: constr(min_length=1) = Field(..., title='Version')
    services: ApiServices
    cli_minimal_version: constr(min_length=1) = Field(
        ..., alias='cli-minimal-version', title='Cli-minimal-version'
    )
    cli_bad_versions: List[constr(min_length=1)] = Field(..., alias='cli-bad-versions')


class UploadInitializationRequest(BaseModel):
    contentSize: conint(ge=1) = Field(..., title='Contentsize')
    digest: Digest
    dandiset: constr(regex=r'\d{6}', min_length=1) = Field(..., title='Dandiset')


class PartInitializationResponse(BaseModel):
    part_number: conint(ge=1) = Field(..., title='Part number')
    size: conint(ge=1) = Field(..., title='Size')
    upload_url: AnyUrl = Field(..., title='Upload url')


class UploadInitializationResponse(BaseModel):
    upload_id: constr(min_length=1) = Field(..., title='Upload id')
    parts: List[PartInitializationResponse]


class PartCompletionRequest(BaseModel):
    part_number: conint(ge=1) = Field(..., title='Part number')
    size: conint(ge=1) = Field(..., title='Size')
    etag: constr(min_length=1) = Field(..., title='Etag')


class UploadCompletionRequest(BaseModel):
    parts: List[PartCompletionRequest]


class UploadCompletionResponse(BaseModel):
    complete_url: AnyUrl = Field(..., title='Complete url')
    body: constr(min_length=1) = Field(..., title='Body')


class UserDetail(BaseModel):
    username: constr(regex=r'^[\w.@+-]+$', min_length=1) = Field(..., title='Username')
    name: constr(regex=r'^[\w.@+-]+$', min_length=1) = Field(..., title='Name')
    admin: bool = Field(..., title='Admin')
    status: constr(min_length=1) = Field(..., title='Status')


class Status2(Enum):
    Pending = 'Pending'
    Ingesting = 'Ingesting'
    Complete = 'Complete'


class ZarrList(BaseModel):
    name: constr(min_length=1, max_length=512) = Field(..., title='Name')
    dandiset: constr(regex=r'^\d{6}$', min_length=1) = Field(..., title='Dandiset')
    zarr_id: Optional[UUID] = Field(None, title='Zarr id')
    status: Optional[Status2] = Field(None, title='Status')
    checksum: Optional[constr(min_length=1)] = Field(None, title='Checksum')
    upload_in_progress: bool = Field(..., title='Upload in progress')
    file_count: Optional[int] = Field(None, title='File count')
    size: Optional[int] = Field(None, title='Size')


class Zarr(BaseModel):
    name: constr(min_length=1, max_length=512) = Field(..., title='Name')
    dandiset: constr(regex=r'^\d{6}$', min_length=1) = Field(..., title='Dandiset')
    zarr_id: Optional[UUID] = Field(None, title='Zarr id')
    status: Optional[Status2] = Field(None, title='Status')
    checksum: Optional[constr(min_length=1)] = Field(None, title='Checksum')
    upload_in_progress: Optional[str] = Field(None, title='Upload in progress')
    file_count: Optional[int] = Field(None, title='File count')
    size: Optional[int] = Field(None, title='Size')


class ZarrDeleteFileRequest(BaseModel):
    path: constr(min_length=1) = Field(..., title='Path')


class ZarrUploadFileRequest(BaseModel):
    path: constr(min_length=1) = Field(..., title='Path')
    etag: constr(min_length=1) = Field(..., title='Etag')


class ZarrUploadBatch(BaseModel):
    path: constr(min_length=1) = Field(..., title='Path')
    upload_url: AnyUrl = Field(..., title='Upload url')

could perhaps be used to even detect diffs of the schema. it doesn’t work directly with our swagger endpoint since it doesn’t (yet) generate an openapi 3.0 compatible spec.

@jwodder
Copy link
Member

jwodder commented Feb 9, 2023

there is some other end point returning both asset and version validation result and not having clear types description according to @jwodder

That's the /dandisets/{dandiset__pk}/versions/{version}/info/ endpoint:

Screen Shot 2023-02-08 at 19 24 02

Also, that endpoint states that contact_person is returned at the top level, but I haven't seen that.

@waxlamp waxlamp added the maintenance Action to maintain the system (neither a bugfix nor an enhancement) label Feb 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Changes only affect the documentation maintenance Action to maintain the system (neither a bugfix nor an enhancement)
Projects
None yet
Development

No branches or pull requests

4 participants