pythonpython-typingmypypydantic

How can I specify the data structure so requirements of mypy and pydantic are satisfied


from pydantic import BaseModel, Field
from typing import List, Optional
from datetime import datetime

class Vault(BaseModel):
    VaultARN: str
    VaultName: str
    CreationDate: datetime
    LastInventoryDate: Optional[datetime] = None
    NumberOfArchives: int
    SizeInBytes: int

class VaultListResponse(BaseModel):
    VaultList: List[Vault]

# Example data
data = {
    "VaultList": [
        {
            "VaultARN": "arn:aws:glacier:eu-central-1:801680170242:vaults/ab_2017_bis_2022",
            "VaultName": "ab_2017_bis_2022",
            "CreationDate": "2022-07-05T08:37:25.552Z",
            "LastInventoryDate": "2024-09-14T18:54:58.863Z",
            "NumberOfArchives": 5712,
            "SizeInBytes": 28571666494
        },
        {
            "VaultARN": "arn:aws:glacier:eu-central-1:801680170242:vaults/photos-161218",
            "VaultName": "photos-161218",
            "CreationDate": "2016-12-18T15:03:19.426Z",
            "LastInventoryDate": "2024-09-14T18:54:52.853Z",
            "NumberOfArchives": 28418,
            "SizeInBytes": 94052378166
        }
    ]
}

# Pass the entire dictionary to the VaultListResponse constructor
vault_list_response = VaultListResponse(**data)
print(vault_list_response)

the code works but mypy give me an error which I canot get rid off: Argument 1 to "VaultListResponse" has incompatible type "**dict[str, list[dict[str, object]]]"; expected "list[Vault]"mypyarg-type

How can I specify the structure of data so it satisfies also mypy


Solution

  • Try

    data = {
        "VaultList": [
            Vault(**{
                "VaultARN": "arn:aws:glacier:eu-central-1:801680170242:vaults/ab_2017_bis_2022",
                "VaultName": "ab_2017_bis_2022",
                "CreationDate": "2022-07-05T08:37:25.552Z",
                "LastInventoryDate": "2024-09-14T18:54:58.863Z",
                "NumberOfArchives": 5712,
                "SizeInBytes": 28571666494
            }),
            Vault(**{
                "VaultARN": "arn:aws:glacier:eu-central-1:801680170242:vaults/photos-161218",
                "VaultName": "photos-161218",
                "CreationDate": "2016-12-18T15:03:19.426Z",
                "LastInventoryDate": "2024-09-14T18:54:52.853Z",
                "NumberOfArchives": 28418,
                "SizeInBytes": 94052378166
            })
        ]
    }
    

    or

    vault_list_response = VaultListResponse.model_validate(data)
    print(vault_list_response)
    

    With the second you'd simply lose the type checking on the arguments. But sometimes that's what you need. Don't know if thats your case though.