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

'Attribute' object has no attribute 'id' #53

Closed
svenevs opened this issue May 5, 2018 · 6 comments
Closed

'Attribute' object has no attribute 'id' #53

svenevs opened this issue May 5, 2018 · 6 comments

Comments

@svenevs
Copy link

svenevs commented May 5, 2018

Here's an interesting one (see last line of traceback):

Traceback (most recent call last):
  File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/multiprocessing/pool.py", line 119, in worker
    result = (True, func(*args, **kwds))
  File "/usr/local/lib/python3.6/site-packages/flake8/checker.py", line 648, in _run_checks
    return checker.run_checks()
  File "/usr/local/lib/python3.6/site-packages/flake8/checker.py", line 579, in run_checks
    self.run_ast_checks()
  File "/usr/local/lib/python3.6/site-packages/flake8/checker.py", line 493, in run_ast_checks
    for (line_number, offset, text, check) in runner:
  File "/usr/local/lib/python3.6/site-packages/pep8ext_naming.py", line 146, in visit_tree
    for error in self.visit_tree(child):
  File "/usr/local/lib/python3.6/site-packages/pep8ext_naming.py", line 142, in visit_tree
    for error in self.visit_node(node):
  File "/usr/local/lib/python3.6/site-packages/pep8ext_naming.py", line 152, in visit_node
    self.tag_class_functions(node)
  File "/usr/local/lib/python3.6/site-packages/pep8ext_naming.py", line 185, in tag_class_functions
    ismetaclass = any(name for name in cls_node.bases if name.id == 'type')
  File "/usr/local/lib/python3.6/site-packages/pep8ext_naming.py", line 185, in <genexpr>
    ismetaclass = any(name for name in cls_node.bases if name.id == 'type')
AttributeError: 'Attribute' object has no attribute 'id'

It is interesting because before I started whittling down the flake8 errors (all I was doing was adding documentation really), pep8-naming was doing OK. Then out of the blue this crash!

I found a similar issue which was resolved by checking if id was available.

Before I start working on a PR that changes any xxx.id to be getattr(xxx, "id", None), since there are a lot more uses of .id in pep8-naming, anything special to look out for?

The file being checked here is actually deliberately breaking pep8-naming conventions, but I was working on the other flake8 errors before I #noqa the classes that intentionally break things. I wonder if that is somehow related (the fact that there are actual errors causing this issue)?

wmfgerrit pushed a commit to wikimedia/pywikibot that referenced this issue May 5, 2018
It's causing failures in pywikibot-core-tox-docker test.
Upstream issue: PyCQA/pep8-naming#53

Bug: T193922
Change-Id: Ifed2becc1b73b4e061fb5a762b36f651a3cbb4b7
@sigmavirus24
Copy link
Member

I need more information about this:

  • What versions of flake8, pep8-naming, and python were you using.

  • Is there a snippet of code that always breaks this?

@sigmavirus24
Copy link
Member

Hm, so I can reproduce this differently with

import six


class Foo:
    def __new__(cls, *args, **kwargs):
        pass

class Bar(six.with_metaclass(Foo)):
    pass

Difference is that it errors with 'Call' object has no attribute 'id'. So I think what we want here is to filter the bases based on some attributes. This check is presently too naive.

I think the following is roughly what's happening in the original report as well:

class Biz:
    pass


class Foo(type):
    otherclass = Biz

    def __new__(cls, foo):
        pass

    def __init__(self, bar):
        pass


class Bar(Foo.otherclass, metaclass=Foo):
    pass

cc @jparise

sigmavirus24 added a commit that referenced this issue May 5, 2018
This should avoid attribute errors for checking the ``id`` attribute on
classes that don't have a basic inheritance declaration.

Closes gh-53
@sigmavirus24
Copy link
Member

@svenevs I think #55 will fix this without catching cases we don't care about

pgjones added a commit to pallets/quart that referenced this issue May 5, 2018
See PyCQA/pep8-naming#53, the latest version
gives rise to an Attribute error.
@svenevs
Copy link
Author

svenevs commented May 5, 2018

Hi @sigmavirus24 you are correct, the fixes there work!

Not so surprisingly, I was using the six.@add_metaclass decorator.

Edit: it turns out I just happened to reinstall python right after the 0.6.0 release (which is not currently tagged btw). 0.5.0 does not have this bug, which is why I thought it was related to me adding documentation.

To be honest, I still have no idea why the error started happening now as opposed to from the beginning...I can share the code with you if you like, but its hundreds of lines of somewhat arcane testing stuff that took a contributor and I weeks to flesh out / get working correctly for a sphinx extension.

The gist of why it is strange:

testing/
    base.py        # defines custom test case and its metaclass
    hierarchies.py # where the actual error is

So hierarchies.py imports the "metaclassed" test case class, but even after removing that entirely the error still occurs in hierarchies.py.

Anyway, long story short since the check was about metaclasses and you reproduced the same issue using an equivalent decorator, I'd consider this solved once you merge #55 -- thanks for the quick response! If you want me to share the code I will, but I don't think it would be worth your time ;)

@fxfitz
Copy link

fxfitz commented May 5, 2018

Any way we could get a 0.6.1 released to remedy this? I would hate to pin my CI to use 0.5.0. :-/

@jparise
Copy link
Member

jparise commented May 7, 2018

Thanks for fixing this, @sigmavirus24!

While reviewing this, I realized we also don't recognize metaclass subclasses as metaclasses:

class MetaBase(type):
    pass

class Meta(MetaBase):
    pass

I spent a little time with the AST, and the challenge is that Meta's bases are only available as ast.Name nodes, which is't enough to determine whether MetaBase derives from type.

Do you know a way to to implement the equivalent of issubclass(Meta, type) in terms of the AST?

bors bot added a commit to duckinator/bork that referenced this issue Oct 1, 2019
49: Pin pep8-naming to latest version 0.8.2 r=nbraud a=pyup-bot


This PR pins [pep8-naming](https://pypi.org/project/pep8-naming) to the latest release **0.8.2**.



<details>
  <summary>Changelog</summary>
  
  
   ### 0.8.2
   ```
   ------------------

* Fix a problem with ``ignore-names`` option initialization.
   ```
   
  
  
   ### 0.8.1
   ```
   ------------------

* ``ignore-names`` now also applies to the N806, N815, and N816 checks.

* ``failureException``, ``longMessage``, and ``maxDiff`` have been added to
  the default ``ignore-names`` list.

* Allow lowercase names to be imported as just ``_``.

* Allow function arguments to be named just ``_``.

* Support Python 2&#39;s tuple syntax in ``except`` clauses.
   ```
   
  
  
   ### 0.8.0
   ```
   ------------------

* Detect N806 errors within ``for`` loops and exception handlers.

* Improve support for non-ASCII characters.

* Detect mixedCased variable names at class (N815) and global (N816) scope.

* Ignore Django&#39;s ``setUpTestData`` method by default.

* Fix column offsets for N803, N804, and N805 under Python 3.

* Detect underscores within class names as N801 errors.

* Don&#39;t flag ``__getattr__`` and ``__dir__`` as N807 errors. (See
  `PEP 562 &lt;https://www.python.org/dev/peps/pep-0562/&gt;`_).

* ``async`` function and method names are now checked.

* Detect N806 errors in generator expressions and comprehensions.

* Detect N81x errors in ``import x as y`` statements.
   ```
   
  
  
   ### 0.7.0
   ```
   ------------------

* Detect N806 in ``with ... as ...:`` statements.

* Detect N806 in multiple assignment statements, e.g., ``Foo, Bar =
  unpacking``.

* Allow class names to be properly ignored.

* Remove spurious &#39;xxx&#39; from error message

* Detect N807 within conditional statements.
   ```
   
  
  
   ### 0.6.1
   ```
   ------------------

* Fix N804 check for ``cls`` used in metaclass methods (See also
  PyCQA/pep8-naming#53)
   ```
   
  
  
   ### 0.6.0
   ```
   ------------------

* Separate check for ``__`` in function names to its own code: N807

* Consider all metaclass methods to be class methods
   ```
   
  
  
   ### 0.5.0
   ```
   ------------------

* Add configurable list of classmethod and staticmethod decorators

* Print the offending name as part of the error message

* Correct N804/N805 for __init_subclass__
   ```
   
  
  
   ### 0.4.1
   ```
   ------------------

* Note to self: Never do releases before ~0600 or coffee on a Sunday.

* Fix option parsing for Flake8 3.0 (store parsed value on class)
   ```
   
  
  
   ### 0.4.0
   ```
   ------------------

* Fix integration with Flake8 3.0.0b1

* Start testing against Python 3.5
   ```
   
  
  
   ### 0.3.3
   ```
   ------------------

* Fix bug where ignored names were not properly split into a list.
   ```
   
  
  
   ### 0.3.2
   ```
   ------------------

* Fix bug trying to call ``split`` on a list.
   ```
   
  
  
   ### 0.3.1
   ```
   ------------------

* Fix optparse exception resulting from trying to register an option twice.
   ```
   
  
  
   ### 0.3.0
   ```
   ------------------

* Relaxed N806 checking for use with namedtuples

* Add ``--ignore-names`` which allows the user to specify a list of names to
  ignore. By default this includes ``setUp``, ``tearDown``, ``setUpClass``,
  and ``tearDownClass``.
   ```
   
  
  
   ### 0.2.2
   ```
   ------------------

* Do not require ``setuptools`` in setup.py.  It works around an issue
  with ``pip`` and Python 3.

* ``__new__`` is now considered as ``classmethod`` implicitly

* Run unit tests on travis-ci.org for python2.6, 2.7, 3.2, and 3.3

* Add unit tests and support running them with setup.py

* Support Python 3.4
   ```
   
  
  
   ### 0.2.1
   ```
   ------------------
* Do not require ``flake8``
   ```
   
  
  
   ### 0.2
   ```
   ----------------

* Rename project ``flint-naming`` to ``pep8-naming``

* Fix a crash when function argument is a tuple of tuples


0.1 - 2013-02-11
----------------

* First release
   ```
   
  
</details>


 

<details>
  <summary>Links</summary>
  
  - PyPI: https://pypi.org/project/pep8-naming
  - Changelog: https://pyup.io/changelogs/pep8-naming/
  - Repo: https://github.com/PyCQA/pep8-naming
</details>



Co-authored-by: pyup-bot <github-bot@pyup.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants