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.

brain_functools.py 2.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. # Copyright (c) 2016 Claudiu Popa <pcmanticore@gmail.com>
  2. """Astroid hooks for understanding functools library module."""
  3. import astroid
  4. from astroid import BoundMethod
  5. from astroid import extract_node
  6. from astroid import helpers
  7. from astroid.interpreter import objectmodel
  8. from astroid import MANAGER
  9. LRU_CACHE = 'functools.lru_cache'
  10. class LruWrappedModel(objectmodel.FunctionModel):
  11. """Special attribute model for functions decorated with functools.lru_cache.
  12. The said decorators patches at decoration time some functions onto
  13. the decorated function.
  14. """
  15. @property
  16. def py__wrapped__(self):
  17. return self._instance
  18. @property
  19. def pycache_info(self):
  20. cache_info = extract_node('''
  21. from functools import _CacheInfo
  22. _CacheInfo(0, 0, 0, 0)
  23. ''')
  24. class CacheInfoBoundMethod(BoundMethod):
  25. def infer_call_result(self, caller, context=None):
  26. yield helpers.safe_infer(cache_info)
  27. return CacheInfoBoundMethod(proxy=self._instance, bound=self._instance)
  28. @property
  29. def pycache_clear(self):
  30. node = extract_node('''def cache_clear(self): pass''')
  31. return BoundMethod(proxy=node, bound=self._instance.parent.scope())
  32. def _transform_lru_cache(node, context=None):
  33. # TODO: this is not ideal, since the node should be immutable,
  34. # but due to https://github.com/PyCQA/astroid/issues/354,
  35. # there's not much we can do now.
  36. # Replacing the node would work partially, because,
  37. # in pylint, the old node would still be available, leading
  38. # to spurious false positives.
  39. node.special_attributes = LruWrappedModel()(node)
  40. return
  41. def _looks_like_lru_cache(node):
  42. """Check if the given function node is decorated with lru_cache."""
  43. if not node.decorators:
  44. return False
  45. for decorator in node.decorators.nodes:
  46. if not isinstance(decorator, astroid.Call):
  47. continue
  48. func = helpers.safe_infer(decorator.func)
  49. if func in (None, astroid.Uninferable):
  50. continue
  51. if isinstance(func, astroid.FunctionDef) and func.qname() == LRU_CACHE:
  52. return True
  53. return False
  54. MANAGER.register_transform(astroid.FunctionDef, _transform_lru_cache,
  55. _looks_like_lru_cache)