1432 """ |
1432 """ |
1433 if isinstance(node, ast.Tuple): |
1433 if isinstance(node, ast.Tuple): |
1434 for elt in node.elts: |
1434 for elt in node.elts: |
1435 self.__visitAssignTarget(elt) |
1435 self.__visitAssignTarget(elt) |
1436 return |
1436 return |
1437 |
1437 |
1438 if isinstance(node, ast.Name): |
1438 if isinstance(node, ast.Name): |
1439 self.assigns[node.id].append(node.lineno) |
1439 self.assigns[node.id].append(node.lineno) |
1440 return |
1440 return |
1441 |
1441 |
1442 self.generic_visit(node) |
1442 self.generic_visit(node) |
1443 |
1443 |
1444 def __checkFunction(self, node): |
1444 def __checkFunction(self, node): |
1445 """ |
1445 """ |
1446 Private method to check a function definition node. |
1446 Private method to check a function definition node. |
1447 |
1447 |
1448 @param node reference to the node to check |
1448 @param node reference to the node to check |
1449 @type ast.AsyncFunctionDef or ast.FunctionDef |
1449 @type ast.AsyncFunctionDef or ast.FunctionDef |
1450 """ |
1450 """ |
1451 if not self.returns or not node.body: |
1451 if not self.returns or not node.body: |
1452 return |
1452 return |
1453 |
1453 |
1454 if len(node.body) == 1 and isinstance(node.body[-1], ast.Return): |
1454 if len(node.body) == 1 and isinstance(node.body[-1], ast.Return): |
1455 # skip functions that consist of `return None` only |
1455 # skip functions that consist of `return None` only |
1456 return |
1456 return |
1457 |
1457 |
1458 if not self.__resultExists(): |
1458 if not self.__resultExists(): |
1459 self.__checkUnnecessaryReturnNone() |
1459 self.__checkUnnecessaryReturnNone() |
1460 return |
1460 return |
1461 |
1461 |
1462 self.__checkImplicitReturnValue() |
1462 self.__checkImplicitReturnValue() |
1463 self.__checkImplicitReturn(node.body[-1]) |
1463 self.__checkImplicitReturn(node.body[-1]) |
1464 |
1464 |
1465 for n in self.returns: |
1465 for n in self.returns: |
1466 if n.value: |
1466 if n.value: |
1467 self.__checkUnnecessaryAssign(n.value) |
1467 self.__checkUnnecessaryAssign(n.value) |
1468 |
1468 |
1469 def __isNone(self, node): |
1469 def __isNone(self, node): |
1470 """ |
1470 """ |
1471 Private method to check, if a node value is None. |
1471 Private method to check, if a node value is None. |
1472 |
1472 |
1473 @param node reference to the node to check |
1473 @param node reference to the node to check |
1474 @type ast.AST |
1474 @type ast.AST |
1475 @return flag indicating the node contains a None value |
1475 @return flag indicating the node contains a None value |
1476 """ |
1476 """ |
1477 return isinstance(node, ast.NameConstant) and node.value is None |
1477 try: |
|
1478 return isinstance(node, ast.NameConstant) and node.value is None |
|
1479 except AttributeError: |
|
1480 # try Py2 |
|
1481 return isinstance(node, ast.Name) and node.id == "None" |
1478 |
1482 |
1479 def __resultExists(self): |
1483 def __resultExists(self): |
1480 """ |
1484 """ |
1481 Private method to check the existance of a return result. |
1485 Private method to check the existance of a return result. |
1482 |
1486 |
1487 value = node.value |
1491 value = node.value |
1488 if value and not self.__isNone(value): |
1492 if value and not self.__isNone(value): |
1489 return True |
1493 return True |
1490 |
1494 |
1491 return False |
1495 return False |
1492 |
1496 |
1493 def __checkImplicitReturnValue(self): |
1497 def __checkImplicitReturnValue(self): |
1494 """ |
1498 """ |
1495 Private method to check for implicit return values. |
1499 Private method to check for implicit return values. |
1496 """ |
1500 """ |
1497 for node in self.returns: |
1501 for node in self.returns: |
1498 if not node.value: |
1502 if not node.value: |
1499 self.violations.append((node, "M832")) |
1503 self.violations.append((node, "M832")) |
1500 |
1504 |
1501 def __checkUnnecessaryReturnNone(self): |
1505 def __checkUnnecessaryReturnNone(self): |
1502 """ |
1506 """ |
1503 Private method to check for an unnecessary 'return None' statement. |
1507 Private method to check for an unnecessary 'return None' statement. |
1504 """ |
1508 """ |
1505 for node in self.returns: |
1509 for node in self.returns: |
1506 if self.__isNone(node.value): |
1510 if self.__isNone(node.value): |
1507 self.violations.append((node, "M831")) |
1511 self.violations.append((node, "M831")) |
1508 |
1512 |
1509 def __checkImplicitReturn(self, node): |
1513 def __checkImplicitReturn(self, node): |
1510 """ |
1514 """ |
1511 Private method to check for an implicit return statement. |
1515 Private method to check for an implicit return statement. |
1512 |
1516 |
1513 @param node reference to the node to check |
1517 @param node reference to the node to check |
1515 """ |
1519 """ |
1516 if isinstance(node, ast.If): |
1520 if isinstance(node, ast.If): |
1517 if not node.body or not node.orelse: |
1521 if not node.body or not node.orelse: |
1518 self.violations.append((node, "M833")) |
1522 self.violations.append((node, "M833")) |
1519 return |
1523 return |
1520 |
1524 |
1521 self.__checkImplicitReturn(node.body[-1]) |
1525 self.__checkImplicitReturn(node.body[-1]) |
1522 self.__checkImplicitReturn(node.orelse[-1]) |
1526 self.__checkImplicitReturn(node.orelse[-1]) |
1523 return |
1527 return |
1524 |
1528 |
1525 if isinstance(node, ast.For) and node.orelse: |
1529 if isinstance(node, ast.For) and node.orelse: |
1526 self.__checkImplicitReturn(node.orelse[-1]) |
1530 self.__checkImplicitReturn(node.orelse[-1]) |
1527 return |
1531 return |
1528 |
1532 |
1529 if isinstance(node, ast.With): |
1533 if isinstance(node, ast.With): |
1530 self.__checkImplicitReturn(node.body[-1]) |
1534 self.__checkImplicitReturn(node.body[-1]) |
1531 return |
1535 return |
1532 |
1536 |
1533 if not isinstance(node, |
1537 try: |
1534 (ast.Return, ast.Raise, ast.While, ast.Try)): |
1538 okNodes = (ast.Return, ast.Raise, ast.While, ast.Try) |
|
1539 except AttributeError: |
|
1540 # Py2 |
|
1541 okNodes = (ast.Return, ast.Raise, ast.While) |
|
1542 if not isinstance(node, okNodes): |
1535 self.violations.append((node, "M833")) |
1543 self.violations.append((node, "M833")) |
1536 |
1544 |
1537 def __checkUnnecessaryAssign(self, node): |
1545 def __checkUnnecessaryAssign(self, node): |
1538 """ |
1546 """ |
1539 Private method to check for an unnecessary assign statement. |
1547 Private method to check for an unnecessary assign statement. |
1540 |
1548 |
1541 @param node reference to the node to check |
1549 @param node reference to the node to check |
1542 @type ast.AST |
1550 @type ast.AST |
1543 """ |
1551 """ |
1544 if not isinstance(node, ast.Name): |
1552 if not isinstance(node, ast.Name): |
1545 return |
1553 return |
1546 |
1554 |
1547 varname = node.id |
1555 varname = node.id |
1548 returnLineno = node.lineno |
1556 returnLineno = node.lineno |
1549 |
1557 |
1550 if varname not in self.assigns: |
1558 if varname not in self.assigns: |
1551 return |
1559 return |
1552 |
1560 |
1553 if varname not in self.refs: |
1561 if varname not in self.refs: |
1554 self.violations.append((node, "M834")) |
1562 self.violations.append((node, "M834")) |
1555 return |
1563 return |
1556 |
1564 |
1557 if self.__hasRefsBeforeNextAssign(varname, returnLineno): |
1565 if self.__hasRefsBeforeNextAssign(varname, returnLineno): |
1558 return |
1566 return |
1559 |
1567 |
1560 self.violations.append((node, "M834")) |
1568 self.violations.append((node, "M834")) |
1561 |
1569 |
1562 def __hasRefsBeforeNextAssign(self, varname, returnLineno): |
1570 def __hasRefsBeforeNextAssign(self, varname, returnLineno): |
1563 """ |
1571 """ |
1564 Private method to check for references before a following assign |
1572 Private method to check for references before a following assign |
1571 @return flag indicating the existence of references |
1579 @return flag indicating the existence of references |
1572 @rtype bool |
1580 @rtype bool |
1573 """ |
1581 """ |
1574 beforeAssign = 0 |
1582 beforeAssign = 0 |
1575 afterAssign = None |
1583 afterAssign = None |
1576 |
1584 |
1577 for lineno in sorted(self.assigns[varname]): |
1585 for lineno in sorted(self.assigns[varname]): |
1578 if lineno > returnLineno: |
1586 if lineno > returnLineno: |
1579 afterAssign = lineno |
1587 afterAssign = lineno |
1580 break |
1588 break |
1581 |
1589 |
1582 if lineno <= returnLineno: |
1590 if lineno <= returnLineno: |
1583 beforeAssign = lineno |
1591 beforeAssign = lineno |
1584 |
1592 |
1585 for lineno in self.refs[varname]: |
1593 for lineno in self.refs[varname]: |
1586 if lineno == returnLineno: |
1594 if lineno == returnLineno: |
1587 continue |
1595 continue |
1588 |
1596 |
1589 if afterAssign: |
1597 if afterAssign: |
1590 if beforeAssign < lineno <= afterAssign: |
1598 if beforeAssign < lineno <= afterAssign: |
1591 return True |
1599 return True |
1592 |
1600 |
1593 elif beforeAssign < lineno: |
1601 elif beforeAssign < lineno: |
1594 return True |
1602 return True |
1595 |
1603 |
1596 return False |
1604 return False |
1597 # |
1605 # |
1598 # eflag: noqa = M702 |
1606 # eflag: noqa = M702 |