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

'ClassDef' object has no attribute 'value' #5266

Closed
kastork opened this issue Nov 6, 2021 · 10 comments · Fixed by #5332
Closed

'ClassDef' object has no attribute 'value' #5266

kastork opened this issue Nov 6, 2021 · 10 comments · Fixed by #5332
Labels
Crash 💥 A bug that makes pylint crash
Milestone

Comments

@kastork
Copy link

kastork commented Nov 6, 2021

When parsing the following file:

# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

import json
import pathlib
import tempfile
import unittest

from aws_cdk import aws_dynamodb as dynamodb
from aws_cdk import core as cdk

from api.infrastructure import API
from database.infrastructure import Database


class APITestCase(unittest.TestCase):
    def test_endpoint_url_output_exists(self) -> None:
        with tempfile.TemporaryDirectory() as temp_dir:
            app = cdk.App(outdir=temp_dir)
            stack = cdk.Stack(app, "Stack")
            database = Database(
                stack,
                "Database",
                dynamodb_billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
            )
            API(
                stack,
                "API",
                dynamodb_table=database.table,
                lambda_reserved_concurrency=1,
            )
            cloud_assembly = app.synth()
            template = cloud_assembly.get_stack_by_name(stack.stack_name).template
        self.assertEqual(
            template["Outputs"]["EndpointURL"]["Value"]["Fn::Sub"],
            "https://${RestAPI}.execute-api.${AWS::Region}.${AWS::URLSuffix}/v1/",
        )
        self._cleanup_chalice_config_file(f"{stack.stack_name}/API")

    @staticmethod
    def _cleanup_chalice_config_file(stage_name: str) -> None:
        chalice_config_path = (
            pathlib.Path(__file__)
            .resolve()
            .parent.parent.joinpath("api/runtime/.chalice/config.json")
        )
        with pathlib.Path.open(chalice_config_path, "r+") as chalice_config_file:
            chalice_config = json.load(chalice_config_file)
            try:
                del chalice_config["stages"][stage_name]
            except KeyError:
                return
            else:
                chalice_config_file.seek(0)
                chalice_config_file.truncate()
                json.dump(chalice_config, chalice_config_file, indent=2)


if __name__ == "__main__":
    unittest.main()

pylint crashed with a AttributeError and with the following stacktrace:

Traceback (most recent call last):
  File "/Users/kirk/tmp/py-cdk-experiment/.venv/lib/python3.9/site-packages/pylint/lint/pylinter.py", line 1008, in _check_files
    self._check_file(get_ast, check_astroid_module, file)
  File "/Users/kirk/tmp/py-cdk-experiment/.venv/lib/python3.9/site-packages/pylint/lint/pylinter.py", line 1043, in _check_file
    check_astroid_module(ast_node)
  File "/Users/kirk/tmp/py-cdk-experiment/.venv/lib/python3.9/site-packages/pylint/lint/pylinter.py", line 1180, in check_astroid_module
    retval = self._check_astroid_module(
  File "/Users/kirk/tmp/py-cdk-experiment/.venv/lib/python3.9/site-packages/pylint/lint/pylinter.py", line 1227, in _check_astroid_module
    walker.walk(node)
  File "/Users/kirk/tmp/py-cdk-experiment/.venv/lib/python3.9/site-packages/pylint/utils/ast_walker.py", line 78, in walk
    self.walk(child)
  File "/Users/kirk/tmp/py-cdk-experiment/.venv/lib/python3.9/site-packages/pylint/utils/ast_walker.py", line 78, in walk
    self.walk(child)
  File "/Users/kirk/tmp/py-cdk-experiment/.venv/lib/python3.9/site-packages/pylint/utils/ast_walker.py", line 78, in walk
    self.walk(child)
  [Previous line repeated 1 more time]
  File "/Users/kirk/tmp/py-cdk-experiment/.venv/lib/python3.9/site-packages/pylint/utils/ast_walker.py", line 75, in walk
    callback(astroid)
  File "/Users/kirk/tmp/py-cdk-experiment/.venv/lib/python3.9/site-packages/pylint/checkers/stdlib.py", line 534, in visit_call
    self._check_open_encoded(node, inferred.root().name)
  File "/Users/kirk/tmp/py-cdk-experiment/.venv/lib/python3.9/site-packages/pylint/checkers/stdlib.py", line 629, in _check_open_encoded
    if not mode_arg or "b" not in mode_arg.value:
  File "/Users/kirk/tmp/py-cdk-experiment/.venv/lib/python3.9/site-packages/astroid/bases.py", line 133, in __getattr__
    return getattr(self._proxied, name)
AttributeError: 'ClassDef' object has no attribute 'value'
@cdce8p cdce8p added the Crash 💥 A bug that makes pylint crash label Nov 6, 2021
@cdce8p
Copy link
Member

cdce8p commented Nov 6, 2021

Thanks for the report. Unfortunately, I'm unable to reproduce the crash with just the information you provided.
A few things that would help:

  • A list of all relevant dependencies
  • Used Python, pylint, and astroid version: pylint --version
  • If you are able too, narrow down which lines exactly cause the error. Especially if you're can remove irrelevant imports or complete functions (though try and error). Just from the traceback, it seems to be related to the unspecified-encoding warning. Thus all calls to "open", "read_text", "write_text" might especially be relevant.

@kastork
Copy link
Author

kastork commented Nov 6, 2021

Here's the whole project.

https://github.com/kastork/py-cdk-experiment

@kastork
Copy link
Author

kastork commented Nov 6, 2021

Also, it should be noted that the project this was templated from presumably worked fine with python 3.7 and pylint 2.9.5.

That project is https://github.com/aws-samples/aws-cdk-project-structure-python

@timmartin
Copy link
Contributor

I wasn't able to reproduce a crash. I did the following:

  • Cloned the repo
  • Created a new virtualenv
  • Installed with pip install -r requirements.txt -r requirements-dev.txt
  • Run pylint with PYTHONPATH=$PWD pylint ./tests/test_api_infrastructure.py

This is with python v3.8.11 (and pylint 2.11.1 installed from the requirements-dev.txt).

Which version of Python are you running when you see the crash?

@kastork
Copy link
Author

kastork commented Nov 14, 2021

Python 3.9.8

My only commit to the repository on Nov 6 did the updates to python 3.9.8 and CDK 1.130.0. Their approach is to use pip-compile to manage dependencies from the requirements.in files in multiple folders, and I'm sure there were dependency updates.

I only ran pylint the way their readme did it... by running ./scripts/install-deps.sh and then ./scripts/run-tests.sh.

Note that in the current version of the repository, pylint is commented out in run-tests.sh

@cdce8p
Copy link
Member

cdce8p commented Nov 14, 2021

@kastork Which pylint and astroid version did you use for testing? You only mentioned that it worked fine with 2.9.5 so far.

@timmartin
Copy link
Contributor

The pylint and astroid versions are (I assume) the ones in the requirements-dev.txt in the repository, and are:

astroid==2.8.4
pylint==2.11.1

I've been able to reproduce this in a Python 3.9.8 Docker container by running these exact scripts. I'll try to reduce it down to a more minimal reproduction case.

@timmartin
Copy link
Contributor

I've reproduced this with the latest main branch version of Astroid (and pylint). For some reason, it doesn't happen if I pylint this file on its own:

$ pylint tests/test_api_infrastructure.py

but it does happen if I include one of the api files on the same run:

$ pylint api/infrastructure.py tests/test_api_infrastructure.py

I'll keep looking at this, hopefully it's fairly straightforward now we can reproduce it.

@timmartin
Copy link
Contributor

I have a much simpler reproduction case, as a single file:

import pathlib

with pathlib.Path.open(pathlib.Path('/dev/null'), "r+") as chalice_config_file:
    pass

This doesn't fail if you replace the pathlib.Path.open with just open.

@cdce8p cdce8p linked a pull request Nov 20, 2021 that will close this issue
4 tasks
@cdce8p
Copy link
Member

cdce8p commented Nov 20, 2021

We merged #5332 today that should fix the issue.

@timmartin Your last example is also fixed, although it is invalid. Path.open is not a staticmethod, thus it should be

import pathlib

with pathlib.Path('/dev/null').open("r+") as chalice_config_file:
    pass

@cdce8p cdce8p closed this as completed Nov 20, 2021
@cdce8p cdce8p removed the Blocker 🙅 Blocks the next release label Nov 20, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Crash 💥 A bug that makes pylint crash
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants