diff options
author | Mads Kiilerich <mads@kiilerich.com> | 2009-01-18 16:04:44 +0100 |
---|---|---|
committer | Mads Kiilerich <mads@kiilerich.com> | 2009-01-18 16:04:44 +0100 |
commit | 466af879a36bad38c830c0c09ee10d7a93ae9624 (patch) | |
tree | 42a3a5cb74578f823229428bc2d709669e429987 | |
parent | 45694b2338d18291cb3d1931cd0434cab8aa65e6 (diff) | |
download | pylint-466af879a36bad38c830c0c09ee10d7a93ae9624.tar.gz |
Decorators of methods should see the class namespace
- just like default values does but the body doesn't.
Fixes
https://www.logilab.net/elo/ticket/3711 - bug finding decorator arguments
https://www.logilab.net/elo/ticket/5626 - name resolution bug inside classes
-rw-r--r-- | checkers/utils.py | 12 | ||||
-rw-r--r-- | checkers/variables.py | 8 | ||||
-rw-r--r-- | test/input/func_noerror_decorator_scope.py | 16 |
3 files changed, 31 insertions, 5 deletions
diff --git a/checkers/utils.py b/checkers/utils.py index 036a4cd..860999d 100644 --- a/checkers/utils.py +++ b/checkers/utils.py @@ -136,7 +136,17 @@ def is_func_default(node): node in parent.defaults: return 1 return is_func_default(parent) - + +def is_func_decorator(node): + """return true if the name is used in function decorator + """ + parent = node.parent + if parent is None: + return 0 + if isinstance(parent, astng.Decorators): + return 1 + return is_func_decorator(parent) + def is_ancestor_name(frame, node): """return True if `frame` is a astng.Class node with `node` in the subtree of its bases attribute diff --git a/checkers/variables.py b/checkers/variables.py index a3b1501..d57df66 100644 --- a/checkers/variables.py +++ b/checkers/variables.py @@ -24,7 +24,7 @@ from logilab.astng.lookup import builtin_lookup from pylint.interfaces import IASTNGChecker from pylint.checkers import BaseChecker -from pylint.checkers.utils import is_error, is_builtin, is_func_default, \ +from pylint.checkers.utils import is_error, is_builtin, is_func_default, is_func_decorator, \ is_ancestor_name, assign_parent, are_exclusive, \ is_defined_before #, is_parent, FOR_NODE_TYPES @@ -326,10 +326,10 @@ builtins. Remember that you should avoid to define new builtins when possible.' name = node.name stmt = node.statement() frame = stmt.scope() - # if the name node is used as a function default argument's value, then + # if the name node is used as a function default argument's value or as a decorator, then # start from the parent frame of the function instead of the function - # frame - if is_func_default(node) or is_ancestor_name(frame, node): + # frame - and thus open an inner class scope + if is_func_default(node) or is_func_decorator(node) or is_ancestor_name(frame, node): start_index = len(self._to_consume) - 2 else: start_index = len(self._to_consume) - 1 diff --git a/test/input/func_noerror_decorator_scope.py b/test/input/func_noerror_decorator_scope.py new file mode 100644 index 0000000..1d21522 --- /dev/null +++ b/test/input/func_noerror_decorator_scope.py @@ -0,0 +1,16 @@ +"""Test that decorators sees the class namespace - just like +function default values does but function body doesn't. + +https://www.logilab.net/elo/ticket/3711 - bug finding decorator arguments +https://www.logilab.net/elo/ticket/5626 - name resolution bug inside classes +""" + +class Test: + + ident = lambda x: x + + @ident(ident) + def f(self, val=ident(7), f=ident): + return f(val) + +print Test().f() |