Skip to content

Commit

Permalink
Fix an AttributeError when processing decorators (#153)
Browse files Browse the repository at this point in the history
I had assumed that each node in the decorator list was either a Call or
a Name, but it can also be an Attribute when the decorator uses module
notation (e.g. `@module.decorator()`).
  • Loading branch information
jparise authored Jun 16, 2020
1 parent 3a0158b commit 13ca91c
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 2 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
Changes
=======

0.11.1 - 2020-06-16
-------------------

* Fix an AST-related AttributeError when processing decorator lists.


0.11.0 - 2020-06-16
-------------------

Expand Down
13 changes: 11 additions & 2 deletions src/pep8ext_naming.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
except ImportError:
from flake8.util import ast, iter_child_nodes

__version__ = '0.11.0'
__version__ = '0.11.1'

PYTHON_VERSION = sys.version_info[:3]
PY2 = PYTHON_VERSION[0] == 2
Expand Down Expand Up @@ -256,11 +256,20 @@ def set_function_nodes_types(self, nodes, ismetaclass, late_decoration):
node.function_type = late_decoration[node.name]
elif node.decorator_list:
for d in node.decorator_list:
name = d.func.id if isinstance(d, ast.Call) else d.id
name = self.find_decorator_name(d)
if name in self.decorator_to_type:
node.function_type = self.decorator_to_type[name]
break

@classmethod
def find_decorator_name(cls, d):
if isinstance(d, ast.Name):
return d.id
elif isinstance(d, ast.Attribute):
return d.attr
elif isinstance(d, ast.Call):
return cls.find_decorator_name(d.func)

@staticmethod
def find_global_defs(func_def_node):
global_names = set()
Expand Down
23 changes: 23 additions & 0 deletions testsuite/N805.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,29 @@ class C(object):
@myclassmethod('foo')
def bar(cls):
return 42
#: Okay
class PropertySetter(object):
@property
def var(self):
return True
@var.setter
def var(self, value):
self.var = value
#: Okay
class CalledInstanceDecorator(object):
@module.inner.decorator()
def test(self):
pass
#: Okay(--classmethod-decorators=decorator)
class CalledClassDecorator(object):
@module.inner.decorator()
def test(cls):
pass
#: Okay(--staticmethod-decorators=decorator)
class CalledStaticDecorator(object):
@module.inner.decorator()
def test():
pass
#: Okay(--staticmethod-decorators=ecstatik,stcmthd)
class NewStaticMethodDecorators(object):
@ecstatik
Expand Down

0 comments on commit 13ca91c

Please sign in to comment.