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.

util.py 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. # Copyright (c) 2015-2016 Cara Vinson <ceridwenv@gmail.com>
  2. # Copyright (c) 2015-2016 Claudiu Popa <pcmanticore@gmail.com>
  3. # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
  4. # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
  5. import sys
  6. import warnings
  7. import importlib
  8. import lazy_object_proxy
  9. import six
  10. def lazy_descriptor(obj):
  11. class DescriptorProxy(lazy_object_proxy.Proxy):
  12. def __get__(self, instance, owner=None):
  13. return self.__class__.__get__(self, instance)
  14. return DescriptorProxy(obj)
  15. def lazy_import(module_name):
  16. return lazy_object_proxy.Proxy(
  17. lambda: importlib.import_module('.' + module_name, 'astroid'))
  18. def reraise(exception):
  19. '''Reraises an exception with the traceback from the current exception
  20. block.'''
  21. six.reraise(type(exception), exception, sys.exc_info()[2])
  22. @object.__new__
  23. class Uninferable(object):
  24. """Special inference object, which is returned when inference fails."""
  25. def __repr__(self):
  26. return 'Uninferable'
  27. __str__ = __repr__
  28. def __getattribute__(self, name):
  29. if name == 'next':
  30. raise AttributeError('next method should not be called')
  31. if name.startswith('__') and name.endswith('__'):
  32. return object.__getattribute__(self, name)
  33. if name == 'accept':
  34. return object.__getattribute__(self, name)
  35. return self
  36. def __call__(self, *args, **kwargs):
  37. return self
  38. def __bool__(self):
  39. return False
  40. __nonzero__ = __bool__
  41. def accept(self, visitor):
  42. func = getattr(visitor, "visit_uninferable")
  43. return func(self)
  44. class BadOperationMessage(object):
  45. """Object which describes a TypeError occurred somewhere in the inference chain
  46. This is not an exception, but a container object which holds the types and
  47. the error which occurred.
  48. """
  49. class BadUnaryOperationMessage(BadOperationMessage):
  50. """Object which describes operational failures on UnaryOps."""
  51. def __init__(self, operand, op, error):
  52. self.operand = operand
  53. self.op = op
  54. self.error = error
  55. @property
  56. def _object_type_helper(self):
  57. helpers = lazy_import('helpers')
  58. return helpers.object_type
  59. def _object_type(self, obj):
  60. # pylint: disable=not-callable; can't infer lazy_import
  61. objtype = self._object_type_helper(obj)
  62. if objtype is Uninferable:
  63. return None
  64. return objtype
  65. def __str__(self):
  66. if hasattr(self.operand, 'name'):
  67. operand_type = self.operand.name
  68. else:
  69. object_type = self._object_type(self.operand)
  70. if hasattr(object_type, 'name'):
  71. operand_type = object_type.name
  72. else:
  73. # Just fallback to as_string
  74. operand_type = object_type.as_string()
  75. msg = "bad operand type for unary {}: {}"
  76. return msg.format(self.op, operand_type)
  77. class BadBinaryOperationMessage(BadOperationMessage):
  78. """Object which describes type errors for BinOps."""
  79. def __init__(self, left_type, op, right_type):
  80. self.left_type = left_type
  81. self.right_type = right_type
  82. self.op = op
  83. def __str__(self):
  84. msg = "unsupported operand type(s) for {}: {!r} and {!r}"
  85. return msg.format(self.op, self.left_type.name, self.right_type.name)
  86. def _instancecheck(cls, other):
  87. wrapped = cls.__wrapped__
  88. other_cls = other.__class__
  89. is_instance_of = wrapped is other_cls or issubclass(other_cls, wrapped)
  90. warnings.warn("%r is deprecated and slated for removal in astroid "
  91. "2.0, use %r instead" % (cls.__class__.__name__,
  92. wrapped.__name__),
  93. PendingDeprecationWarning, stacklevel=2)
  94. return is_instance_of
  95. def proxy_alias(alias_name, node_type):
  96. """Get a Proxy from the given name to the given node type."""
  97. proxy = type(alias_name, (lazy_object_proxy.Proxy,),
  98. {'__class__': object.__dict__['__class__'],
  99. '__instancecheck__': _instancecheck})
  100. return proxy(lambda: node_type)
  101. # Backwards-compatibility aliases
  102. YES = Uninferable