Index: third_party/pylint/checkers/utils.py |
diff --git a/third_party/pylint/checkers/utils.py b/third_party/pylint/checkers/utils.py |
index d88d6205c7100f4e7e33a0d58f9781507ef5c4d8..f3a7d17625b4b69480be26f9336da7fd34ba5b27 100644 |
--- a/third_party/pylint/checkers/utils.py |
+++ b/third_party/pylint/checkers/utils.py |
@@ -30,6 +30,11 @@ BUILTINS_NAME = builtins.__name__ |
COMP_NODE_TYPES = astroid.ListComp, astroid.SetComp, astroid.DictComp, astroid.GenExpr |
PY3K = sys.version_info[0] == 3 |
+if not PY3K: |
+ EXCEPTIONS_MODULE = "exceptions" |
+else: |
+ EXCEPTIONS_MODULE = "builtins" |
+ |
class NoSuchArgumentError(Exception): |
pass |
@@ -82,11 +87,11 @@ def safe_infer(node): |
""" |
try: |
inferit = node.infer() |
- value = inferit.next() |
+ value = next(inferit) |
except astroid.InferenceError: |
return |
try: |
- inferit.next() |
+ next(inferit) |
return # None if there is ambiguity on the inferred node |
except astroid.InferenceError: |
return # there is some kind of ambiguity |
@@ -152,12 +157,12 @@ def is_defined_before(var_node): |
if ass_node.name == varname: |
return True |
elif isinstance(_node, astroid.With): |
- for expr, vars in _node.items: |
+ for expr, ids in _node.items: |
if expr.parent_of(var_node): |
break |
- if (vars and |
- isinstance(vars, astroid.AssName) and |
- vars.name == varname): |
+ if (ids and |
+ isinstance(ids, astroid.AssName) and |
+ ids.name == varname): |
return True |
elif isinstance(_node, (astroid.Lambda, astroid.Function)): |
if _node.args.is_argument(varname): |
@@ -412,10 +417,85 @@ def get_argument_from_call(callfunc_node, position=None, keyword=None): |
try: |
if position is not None and not isinstance(callfunc_node.args[position], astroid.Keyword): |
return callfunc_node.args[position] |
- except IndexError, error: |
+ except IndexError as error: |
raise NoSuchArgumentError(error) |
if keyword: |
for arg in callfunc_node.args: |
if isinstance(arg, astroid.Keyword) and arg.arg == keyword: |
return arg.value |
raise NoSuchArgumentError |
+ |
+def inherit_from_std_ex(node): |
+ """ |
+ Return true if the given class node is subclass of |
+ exceptions.Exception. |
+ """ |
+ if node.name in ('Exception', 'BaseException') \ |
+ and node.root().name == EXCEPTIONS_MODULE: |
+ return True |
+ return any(inherit_from_std_ex(parent) |
+ for parent in node.ancestors(recurs=False)) |
+ |
+def is_import_error(handler): |
+ """ |
+ Check if the given exception handler catches |
+ ImportError. |
+ |
+ :param handler: A node, representing an ExceptHandler node. |
+ :returns: True if the handler catches ImportError, False otherwise. |
+ """ |
+ names = None |
+ if isinstance(handler.type, astroid.Tuple): |
+ names = [name for name in handler.type.elts |
+ if isinstance(name, astroid.Name)] |
+ elif isinstance(handler.type, astroid.Name): |
+ names = [handler.type] |
+ else: |
+ # Don't try to infer that. |
+ return |
+ for name in names: |
+ try: |
+ for infered in name.infer(): |
+ if (isinstance(infered, astroid.Class) and |
+ inherit_from_std_ex(infered) and |
+ infered.name == 'ImportError'): |
+ return True |
+ except astroid.InferenceError: |
+ continue |
+ |
+def has_known_bases(klass): |
+ """Returns true if all base classes of a class could be inferred.""" |
+ try: |
+ return klass._all_bases_known |
+ except AttributeError: |
+ pass |
+ for base in klass.bases: |
+ result = safe_infer(base) |
+ # TODO: check for A->B->A->B pattern in class structure too? |
+ if (not isinstance(result, astroid.Class) or |
+ result is klass or |
+ not has_known_bases(result)): |
+ klass._all_bases_known = False |
+ return False |
+ klass._all_bases_known = True |
+ return True |
+ |
+def decorated_with_property(node): |
+ """ Detect if the given function node is decorated with a property. """ |
+ if not node.decorators: |
+ return False |
+ for decorator in node.decorators.nodes: |
+ if not isinstance(decorator, astroid.Name): |
+ continue |
+ try: |
+ for infered in decorator.infer(): |
+ if isinstance(infered, astroid.Class): |
+ if (infered.root().name == BUILTINS_NAME and |
+ infered.name == 'property'): |
+ return True |
+ for ancestor in infered.ancestors(): |
+ if (ancestor.name == 'property' and |
+ ancestor.root().name == BUILTINS_NAME): |
+ return True |
+ except astroid.InferenceError: |
+ pass |