Development of an internal social media platform with personalised dashboards for students
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

async.py 3.1KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. # Copyright (c) 2015-2017 Claudiu Popa <pcmanticore@gmail.com>
  2. # Copyright (c) 2017 Derek Gustafson <degustaf@gmail.com>
  3. # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  4. # For details: https://github.com/PyCQA/pylint/blob/master/COPYING
  5. """Checker for anything related to the async protocol (PEP 492)."""
  6. import sys
  7. import astroid
  8. from astroid import exceptions
  9. from pylint import checkers
  10. from pylint.checkers import utils as checker_utils
  11. from pylint import interfaces
  12. from pylint import utils
  13. class AsyncChecker(checkers.BaseChecker):
  14. __implements__ = interfaces.IAstroidChecker
  15. name = 'async'
  16. msgs = {
  17. 'E1700': ('Yield inside async function',
  18. 'yield-inside-async-function',
  19. 'Used when an `yield` or `yield from` statement is '
  20. 'found inside an async function.',
  21. {'minversion': (3, 5)}),
  22. 'E1701': ("Async context manager '%s' doesn't implement __aenter__ and __aexit__.",
  23. 'not-async-context-manager',
  24. 'Used when an async context manager is used with an object '
  25. 'that does not implement the async context management protocol.',
  26. {'minversion': (3, 5)}),
  27. }
  28. def open(self):
  29. self._ignore_mixin_members = utils.get_global_option(self, 'ignore-mixin-members')
  30. @checker_utils.check_messages('yield-inside-async-function')
  31. def visit_asyncfunctiondef(self, node):
  32. for child in node.nodes_of_class(astroid.Yield):
  33. if child.scope() is node and (sys.version_info[:2] == (3, 5) or
  34. isinstance(child, astroid.YieldFrom)):
  35. self.add_message('yield-inside-async-function', node=child)
  36. @checker_utils.check_messages('not-async-context-manager')
  37. def visit_asyncwith(self, node):
  38. for ctx_mgr, _ in node.items:
  39. infered = checker_utils.safe_infer(ctx_mgr)
  40. if infered is None or infered is astroid.YES:
  41. continue
  42. if isinstance(infered, astroid.Instance):
  43. try:
  44. infered.getattr('__aenter__')
  45. infered.getattr('__aexit__')
  46. except exceptions.NotFoundError:
  47. if isinstance(infered, astroid.Instance):
  48. # If we do not know the bases of this class,
  49. # just skip it.
  50. if not checker_utils.has_known_bases(infered):
  51. continue
  52. # Just ignore mixin classes.
  53. if self._ignore_mixin_members:
  54. if infered.name[-5:].lower() == 'mixin':
  55. continue
  56. else:
  57. continue
  58. self.add_message('not-async-context-manager',
  59. node=node, args=(infered.name, ))
  60. def register(linter):
  61. """required method to auto register this checker"""
  62. linter.register_checker(AsyncChecker(linter))