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

ListObjectVersionsOutputTypeDef CommonPrefixes key can be missing #248

Open
guilhem-dvr opened this issue Mar 6, 2024 · 5 comments
Open
Labels
🐞 bug Something isn't working 🎉 released Changes were included to the latest release 👋 response needed Awaiting response from a reporter

Comments

@guilhem-dvr
Copy link

guilhem-dvr commented Mar 6, 2024

Describe the bug

ListObjectVersionsOutputTypeDef has the key CommonPrefixes typed as a List[CommonPrefixTypeDef], but the key can be missing in the response to list_object_versions.

To Reproduce
Steps to reproduce the behavior:

  1. Install boto3-stubs[s3]
  2. Run mypy/pyright on the following code sample
import boto3

s3_client = boto3.client("s3")
response = s3_client.list_object_versions(
    Bucket="some-bucket", Delimiter="/", Prefix="a/prefix/with/no/common/prefixes/"
)

common_prefixes = response["CommonPrefixes"]
  1. The type checker is fine with this piece of code.

Actual output

The CommonPrefixes is missing from the response and the snippet fails when running on a real-life example.

KeyError: 'CommonPrefixes'

Expected output

There is no expected output, I would have liked my type checker to warn me about a potentially missing key.

Additional context
I'm using macOS 14.2, python 3.9.5, poetry 1.8.1 to manage dependencies, boto3 & boto3-stubs 1.34.31

An example of a response I got from AWS where the key CommonPrefixes is missing.

{
  "DeleteMarkers": [
    {
      "IsLatest": "true",
      "Key": "some/key/to/a/file",
      "LastModified": "",
      "Owner": {
        "ID": "**********"
      },
      "VersionId": "**********"
    }
  ],
  "Delimiter": "/",
  "EncodingType": "url",
  "IsTruncated": "false",
  "KeyMarker": "",
  "MaxKeys": 1000,
  "Name": "bucket-name",
  "Prefix": "some/prefix/",
  "ResponseMetadata": {
    "HTTPHeaders": {
      "content-type": "application/xml",
      "date": "**********",
      "server": "AmazonS3",
      "transfer-encoding": "chunked",
      "x-amz-id-2": "**********",
      "x-amz-request-id": "**********"
    },
    "HTTPStatusCode": 200,
    "HostId": "**********",
    "RequestId": "**********",
    "RetryAttempts": 0
  },
  "VersionIdMarker": ""
}
@vemel
Copy link
Collaborator

vemel commented Apr 16, 2024

Unfortunately, right now there is no way to tell if the key in output shape is optional or not. I am still investigating it.

By the way, you are getting key error because method name is incorrect: list_object_versionslist_object_versions

@guilhem-dvr
Copy link
Author

By the way, you are getting key error because method name is incorrect: list_object_versionslist_object_versions

corrected, but this doesn't change my issue: the key is optional from the S3 response but the type checker misses that.

@vemel
Copy link
Collaborator

vemel commented Apr 16, 2024

I will try to fix it. If you have time you can also take a look at botocore shapes and help me figure out how optional/required keys are marked for output shapes.

One solution would be to use the same key totality as for input shapes. But it is also not an ideal solution, because almost all keys are optional in input shapes.

Another solution would be to somehow figure out which keys are required in output shapes, but I still have no idea how to do it.

@vemel
Copy link
Collaborator

vemel commented Apr 16, 2024

If I use the same rules as for input shapes, this is what I get :

ListObjectVersionsOutputTypeDef = TypedDict(
    "ListObjectVersionsOutputTypeDef",
    {
        "ResponseMetadata": ResponseMetadataTypeDef,
        "IsTruncated": NotRequired[bool],
        "KeyMarker": NotRequired[str],
        "VersionIdMarker": NotRequired[str],
        "NextKeyMarker": NotRequired[str],
        "NextVersionIdMarker": NotRequired[str],
        "Versions": NotRequired[List[ObjectVersionTypeDef]],
        "DeleteMarkers": NotRequired[List[DeleteMarkerEntryTypeDef]],
        "Name": NotRequired[str],
        "Prefix": NotRequired[str],
        "Delimiter": NotRequired[str],
        "MaxKeys": NotRequired[int],
        "CommonPrefixes": NotRequired[List[CommonPrefixTypeDef]],
        "EncodingType": NotRequired[Literal["url"]],
        "RequestCharged": NotRequired[Literal["requester"]],
    },
)

As you see, all keys are marked as not required. I do not think that this is a proper solution.

@vemel
Copy link
Collaborator

vemel commented Apr 25, 2024

The issue has finally been fixed in mypy_boto3_builder 7.24.0 release. I have also released mypy-boto3-s3 1.34.91 with the fix included. Please update and let me know if it works as it should.

@vemel vemel added 👋 response needed Awaiting response from a reporter 🎉 released Changes were included to the latest release labels Apr 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐞 bug Something isn't working 🎉 released Changes were included to the latest release 👋 response needed Awaiting response from a reporter
Projects
None yet
Development

No branches or pull requests

2 participants