pythonboto3python-typingmypyboto

type() function doesn't return correct result for a boto3 sqs object?


I'm using Python 3's type hinting syntax, and I'm writing a small AWS application that uses SQS. I'm trying to hint the type of the Queue. This is how I obtain the type of the Queue:

>>> import boto3
>>> session = boto3.session.Session(
>>>     aws_access_key_id=AWS_ACCESS_KEY,
>>>     aws_secret_access_key=AWS_SECRET_KEY,
>>>     region_name='us-west-2'
>>> )
>>> sqs = session.resource('sqs')
>>> queue=sqs.Queue(AWS_QUEUE_URL)
>>> 
>>> type(queue)
<class 'boto3.resources.factory.sqs.Queue'>

And I write my type-hinted function like this:

def get_session() -> boto3.resources.factory.sqs.Queue:
    ...

But I get an error:

AttributeError: module 'boto3.resources.factory' has no attribute 'sqs'

I've looked through the package myself using dir(...). It seems that factory does not contain sqs, indeed. Thus, I have two questions:


Solution

  • The class of sqs.Queue appears to be generated on the fly every time it's called:

    >>> import boto3
    >>> session = boto3.session.Session(aws_access_key_id='foo', aws_secret_access_key='bar', region_name='us-west-2')
    >>> sqs = session.resource('sqs')
    >>> sqs.Queue
    <bound method sqs.ServiceResource.Queue of sqs.ServiceResource()>
    >>> q = sqs.Queue('blah')
    >>> type(q)
    <class 'boto3.resources.factory.sqs.Queue'>
    >>> q2 = sqs.Queue('bluh')
    >>> type(q) == type(q2)
    False
    

    So that's kind of a bad design choice on boto's end. I think it means it's not possible to reasonably type annotate it, even with forward references.

    Your best bet is to give a type hint for the common base class of all these dynamic classes, boto3.resources.base.ServiceResource:

    >>> type(q).__bases__
    (<class 'boto3.resources.base.ServiceResource'>,)