Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python returning type error on wrong line

I'm not sure if the issue I'm experiencing is my lack of experience with Python or if it's a bug in the interpreter, but I think I'm getting a TypeError message on the wrong line.

Please explain to me why this is happening if it's not a bug. My code is as follows:

#!/usr/bin/env python3

from awacs.aws import Policy, Principal, Statement
from troposphere import Template
from troposphere.iam import Role

t = Template()

t.add_resource(Role(
    "SESLambdaRole",
    AssumeRolePolicyDocument = Policy(
        Version = "2012-10-17",
        Statement = [
            Statement(
                Effect = "Allow",
                Resource = "arn:aws:logs:*:*:*",
                Principal = Principal(
                    "Service",
                    ["lambda.amazonaws.com"]
                    ),
                )
            ]
        )
    ))

print(t.to_json())

This is my output

ubuntu@ip-111-11-11-111:~$ ./ses-lambda-forwarder-resources.py 
Traceback (most recent call last):
  File "./ses-lambda-forwarder-resources.py", line 19, in <module>
    ["lambda.amazonaws.com"]
  File "/home/ubuntu/.local/lib/python3.6/site-packages/awacs/__init__.py", line 113, in __init__
    sup.__init__(None, props=self.props, **kwargs)
  File "/home/ubuntu/.local/lib/python3.6/site-packages/awacs/__init__.py", line 40, in __init__
    self.__setattr__(k, v)
  File "/home/ubuntu/.local/lib/python3.6/site-packages/awacs/__init__.py", line 81, in __setattr__
    self._raise_type(name, value, expected_type)
  File "/home/ubuntu/.local/lib/python3.6/site-packages/awacs/__init__.py", line 90, in _raise_type
    (name, type(value), expected_type))
TypeError: Resource is <class 'str'>, expected <class 'list'>
ubuntu@ip-111-11-11-111:~$ python3 --version
Python 3.6.3

If I change the following line

Resource = "arn:aws:logs:*:*:*",

to

Resource = [ "arn:aws:logs:*:*:*" ],

It works. Why is Python complaining about the line 3 lines below?

like image 672
chizou Avatar asked Feb 09 '18 00:02

chizou


Video Answer


1 Answers

Python doesn't know which actual argument errored, just that it was passed from an expression that stretches across a few lines. It makes a rough guess at the erroring line (which as Ryan points out in the comments seems to be the last non-punctuation line in the expression), and reports the error as coming from there, but it could have come from any part of the expression that errored. For a simpler example, consider:

>>> i = int(
...         '#',
...         base=2
...        )
...
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-6-1e4a194d0c31> in <module>()
      1 i = int(
      2         '#',
----> 3         base=2
      4        )
      5

ValueError: invalid literal for int() with base 2: '#'

The error comes from the int constructor (call begins on line 1), from the '#' argument (line 2), and the expression ends on line 4, but the arrow implicates line 3. All Python really knows is that the error came from the int(...) expression, and it makes a stab at the problem being the final meaningful line of the expression, but it doesn't really know which of the arguments was at fault (the exception raising APIs aren't fine-grained enough to tell Python programmatically which argument is the problem in a way that could help), and the heuristic doesn't work.

The same thing happens with your code; Python knows the Statement constructor raised the exception, and it points to the last non-trivial line of that expression when the error is raised, but it doesn't really know which line contained the problematic argument, and the heuristic gives you misleading information. Luckily, the exception message tells you what is wrong (the Resource argument must be a list), so you can use that context to scan the nearby lines and notice the non-list Resource argument.

like image 133
ShadowRanger Avatar answered Oct 13 '22 01:10

ShadowRanger