1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
# Copyright (c) 2015-2016 Cara Vinson <ceridwenv@gmail.com>
# Copyright (c) 2015-2016 Claudiu Popa <pcmanticore@gmail.com>
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
import importlib
import platform
import sys
import warnings
import lazy_object_proxy
import six
import wrapt
JYTHON = platform.python_implementation() == 'Jython'
try:
from functools import singledispatch as _singledispatch
except ImportError:
from singledispatch import singledispatch as _singledispatch
def singledispatch(func):
old_generic_func = _singledispatch(func)
@wrapt.decorator
def wrapper(func, instance, args, kws):
return old_generic_func.dispatch(type(args[0]))(*args, **kws)
new_generic_func = wrapper(func)
new_generic_func.register = old_generic_func.register
new_generic_func.dispatch = old_generic_func.dispatch
new_generic_func.registry = old_generic_func.registry
new_generic_func._clear_cache = old_generic_func._clear_cache
return new_generic_func
def lazy_descriptor(obj):
class DescriptorProxy(lazy_object_proxy.Proxy):
def __get__(self, instance, owner=None):
return self.__class__.__get__(self, instance)
return DescriptorProxy(obj)
def lazy_import(module_name):
return lazy_object_proxy.Proxy(
lambda: importlib.import_module('.' + module_name, 'astroid'))
def reraise(exception):
'''Reraises an exception with the traceback from the current exception
block.'''
six.reraise(type(exception), exception, sys.exc_info()[2])
def generate_warning(message, warning):
return lambda strings: warnings.warn(message % strings, warning,
stacklevel=3)
rename_warning = generate_warning("%r is deprecated and slated for removal in "
"astroid 2.0, use %r instead",
PendingDeprecationWarning)
attr_to_method_warning = generate_warning("%s is deprecated and slated for "
" removal in astroid 1.6, use the "
"method '%s' instead.",
PendingDeprecationWarning)
@object.__new__
class Uninferable(object):
"""Special inference object, which is returned when inference fails."""
def __repr__(self):
return 'Uninferable'
__str__ = __repr__
def __getattribute__(self, name):
if name == 'next':
raise AttributeError('next method should not be called')
if name.startswith('__') and name.endswith('__'):
return object.__getattribute__(self, name)
if name == 'accept':
return object.__getattribute__(self, name)
return self
def __call__(self, *args, **kwargs):
return self
def __bool__(self):
return False
__nonzero__ = __bool__
def accept(self, visitor):
func = getattr(visitor, "visit_uninferable")
return func(self)
class BadOperationMessage(object):
"""Object which describes a TypeError occurred somewhere in the inference chain
This is not an exception, but a container object which holds the types and
the error which occurred.
"""
class BadUnaryOperationMessage(BadOperationMessage):
"""Object which describes operational failures on UnaryOps."""
def __init__(self, operand, op, error):
self.operand = operand
self.op = op
self.error = error
def __str__(self):
operand_type = self.operand.name
msg = "bad operand type for unary {}: {}"
return msg.format(self.op, operand_type)
class BadBinaryOperationMessage(BadOperationMessage):
"""Object which describes type errors for BinOps."""
def __init__(self, left_type, op, right_type):
self.left_type = left_type
self.right_type = right_type
self.op = op
def __str__(self):
msg = "unsupported operand type(s) for {}: {!r} and {!r}"
return msg.format(self.op, self.left_type.name, self.right_type.name)
def _instancecheck(cls, other):
wrapped = cls.__wrapped__
other_cls = other.__class__
is_instance_of = wrapped is other_cls or issubclass(other_cls, wrapped)
rename_warning((cls.__class__.__name__, wrapped.__name__))
return is_instance_of
def proxy_alias(alias_name, node_type):
"""Get a Proxy from the given name to the given node type."""
proxy = type(alias_name, (lazy_object_proxy.Proxy,),
{'__class__': object.__dict__['__class__'],
'__instancecheck__': _instancecheck})
return proxy(lambda: node_type)
# Backwards-compatibility aliases
YES = Uninferable
def register_implementation(base):
"""Register an implementation for the given *base*
The given base class is expected to have a `register` method,
similar to what `abc.ABCMeta` provides when used.
"""
def wrapped(impl):
base.register(impl)
return impl
return wrapped
|