Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(114)

Side by Side Diff: third_party/logilab/astroid/brain/py2stdlib.py

Issue 776883002: pylint: upgrade to 1.4.0 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools/
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « third_party/logilab/astroid/brain/py2qt4.py ('k') | third_party/logilab/astroid/builder.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 """Astroid hooks for the Python 2 standard library. 1 """Astroid hooks for the Python 2 standard library.
2 2
3 Currently help understanding of : 3 Currently help understanding of :
4 4
5 * hashlib.md5 and hashlib.sha1 5 * hashlib.md5 and hashlib.sha1
6 """ 6 """
7 7
8 import sys 8 import sys
9 from textwrap import dedent 9 from textwrap import dedent
10 10
11 from astroid import ( 11 from astroid import (
12 MANAGER, AsStringRegexpPredicate, 12 MANAGER, AsStringRegexpPredicate,
13 UseInferenceDefault, inference_tip, 13 UseInferenceDefault, inference_tip,
14 YES, InferenceError) 14 YES, InferenceError, register_module_extender)
15 from astroid import exceptions 15 from astroid import exceptions
16 from astroid import nodes 16 from astroid import nodes
17 from astroid.builder import AstroidBuilder 17 from astroid.builder import AstroidBuilder
18 18
19 MODULE_TRANSFORMS = {}
20 PY3K = sys.version_info > (3, 0) 19 PY3K = sys.version_info > (3, 0)
21 PY33 = sys.version_info >= (3, 3) 20 PY33 = sys.version_info >= (3, 3)
22 21
23 # general function 22 # general function
24 23
25 def infer_func_form(node, base_type, context=None, enum=False): 24 def infer_func_form(node, base_type, context=None, enum=False):
26 """Specific inference function for namedtuple or Python 3 enum. """ 25 """Specific inference function for namedtuple or Python 3 enum. """
27 def infer_first(node): 26 def infer_first(node):
28 try: 27 try:
29 value = node.infer(context=context).next() 28 value = next(node.infer(context=context))
30 if value is YES: 29 if value is YES:
31 raise UseInferenceDefault() 30 raise UseInferenceDefault()
32 else: 31 else:
33 return value 32 return value
34 except StopIteration: 33 except StopIteration:
35 raise InferenceError() 34 raise InferenceError()
36 35
37 # node is a CallFunc node, class name as first argument and generated class 36 # node is a CallFunc node, class name as first argument and generated class
38 # attributes as second argument 37 # attributes as second argument
39 if len(node.args) != 2: 38 if len(node.args) != 2:
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 # XXX add __init__(*attributes) method 82 # XXX add __init__(*attributes) method
84 for attr in attributes: 83 for attr in attributes:
85 fake_node = nodes.EmptyNode() 84 fake_node = nodes.EmptyNode()
86 fake_node.parent = class_node 85 fake_node.parent = class_node
87 class_node.instance_attrs[attr] = [fake_node] 86 class_node.instance_attrs[attr] = [fake_node]
88 return class_node, name, attributes 87 return class_node, name, attributes
89 88
90 89
91 # module specific transformation functions ##################################### 90 # module specific transformation functions #####################################
92 91
93 def transform(module): 92 def hashlib_transform():
94 try:
95 tr = MODULE_TRANSFORMS[module.name]
96 except KeyError:
97 pass
98 else:
99 tr(module)
100 MANAGER.register_transform(nodes.Module, transform)
101
102 # module specific transformation functions #####################################
103
104 def hashlib_transform(module):
105 template = ''' 93 template = '''
106 94
107 class %s(object): 95 class %(name)s(object):
108 def __init__(self, value=''): pass 96 def __init__(self, value=''): pass
109 def digest(self): 97 def digest(self):
110 return u'' 98 return %(digest)s
99 def copy(self):
100 return self
111 def update(self, value): pass 101 def update(self, value): pass
112 def hexdigest(self): 102 def hexdigest(self):
113 return u'' 103 return ''
104 @property
105 def name(self):
106 return %(name)r
114 ''' 107 '''
108 algorithms = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512')
109 classes = "".join(
110 template % {'name': hashfunc, 'digest': 'b""' if PY3K else '""'}
111 for hashfunc in algorithms)
112 return AstroidBuilder(MANAGER).string_build(classes)
115 113
116 algorithms = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512')
117 classes = "".join(template % hashfunc for hashfunc in algorithms)
118 114
119 fake = AstroidBuilder(MANAGER).string_build(classes) 115 def collections_transform():
120 116 return AstroidBuilder(MANAGER).string_build('''
121 for hashfunc in algorithms:
122 module.locals[hashfunc] = fake.locals[hashfunc]
123
124 def collections_transform(module):
125 fake = AstroidBuilder(MANAGER).string_build('''
126 117
127 class defaultdict(dict): 118 class defaultdict(dict):
128 default_factory = None 119 default_factory = None
129 def __missing__(self, key): pass 120 def __missing__(self, key): pass
130 121
131 class deque(object): 122 class deque(object):
132 maxlen = 0 123 maxlen = 0
133 def __init__(self, iterable=None, maxlen=None): pass 124 def __init__(self, iterable=None, maxlen=None): pass
134 def append(self, x): pass 125 def append(self, x): pass
135 def appendleft(self, x): pass 126 def appendleft(self, x): pass
136 def clear(self): pass 127 def clear(self): pass
137 def count(self, x): return 0 128 def count(self, x): return 0
138 def extend(self, iterable): pass 129 def extend(self, iterable): pass
139 def extendleft(self, iterable): pass 130 def extendleft(self, iterable): pass
140 def pop(self): pass 131 def pop(self): pass
141 def popleft(self): pass 132 def popleft(self): pass
142 def remove(self, value): pass 133 def remove(self, value): pass
143 def reverse(self): pass 134 def reverse(self): pass
144 def rotate(self, n): pass 135 def rotate(self, n): pass
145 def __iter__(self): return self 136 def __iter__(self): return self
146 137
147 ''') 138 ''')
148 139
149 for klass in ('deque', 'defaultdict'):
150 module.locals[klass] = fake.locals[klass]
151 140
152 def pkg_resources_transform(module): 141 def pkg_resources_transform():
153 fake = AstroidBuilder(MANAGER).string_build(''' 142 return AstroidBuilder(MANAGER).string_build('''
154 143
155 def resource_exists(package_or_requirement, resource_name): 144 def resource_exists(package_or_requirement, resource_name):
156 pass 145 pass
157 146
158 def resource_isdir(package_or_requirement, resource_name): 147 def resource_isdir(package_or_requirement, resource_name):
159 pass 148 pass
160 149
161 def resource_filename(package_or_requirement, resource_name): 150 def resource_filename(package_or_requirement, resource_name):
162 pass 151 pass
163 152
(...skipping 16 matching lines...) Expand all
180 pass 169 pass
181 170
182 def set_extraction_path(path): 171 def set_extraction_path(path):
183 pass 172 pass
184 173
185 def cleanup_resources(force=False): 174 def cleanup_resources(force=False):
186 pass 175 pass
187 176
188 ''') 177 ''')
189 178
190 for func_name, func in fake.locals.items():
191 module.locals[func_name] = func
192 179
193 180 def subprocess_transform():
194 def subprocess_transform(module):
195 if PY3K: 181 if PY3K:
196 communicate = (bytes('string', 'ascii'), bytes('string', 'ascii')) 182 communicate = (bytes('string', 'ascii'), bytes('string', 'ascii'))
197 init = """ 183 init = """
198 def __init__(self, args, bufsize=0, executable=None, 184 def __init__(self, args, bufsize=0, executable=None,
199 stdin=None, stdout=None, stderr=None, 185 stdin=None, stdout=None, stderr=None,
200 preexec_fn=None, close_fds=False, shell=False, 186 preexec_fn=None, close_fds=False, shell=False,
201 cwd=None, env=None, universal_newlines=False, 187 cwd=None, env=None, universal_newlines=False,
202 startupinfo=None, creationflags=0, restore_signals=True, 188 startupinfo=None, creationflags=0, restore_signals=True,
203 start_new_session=False, pass_fds=()): 189 start_new_session=False, pass_fds=()):
204 pass 190 pass
205 """ 191 """
206 else: 192 else:
207 communicate = ('string', 'string') 193 communicate = ('string', 'string')
208 init = """ 194 init = """
209 def __init__(self, args, bufsize=0, executable=None, 195 def __init__(self, args, bufsize=0, executable=None,
210 stdin=None, stdout=None, stderr=None, 196 stdin=None, stdout=None, stderr=None,
211 preexec_fn=None, close_fds=False, shell=False, 197 preexec_fn=None, close_fds=False, shell=False,
212 cwd=None, env=None, universal_newlines=False, 198 cwd=None, env=None, universal_newlines=False,
213 startupinfo=None, creationflags=0): 199 startupinfo=None, creationflags=0):
214 pass 200 pass
215 """ 201 """
216 if PY33: 202 if PY33:
217 wait_signature = 'def wait(self, timeout=None)' 203 wait_signature = 'def wait(self, timeout=None)'
218 else: 204 else:
219 wait_signature = 'def wait(self)' 205 wait_signature = 'def wait(self)'
220 fake = AstroidBuilder(MANAGER).string_build(''' 206 return AstroidBuilder(MANAGER).string_build('''
221 207
222 class Popen(object): 208 class Popen(object):
223 returncode = pid = 0 209 returncode = pid = 0
224 stdin = stdout = stderr = file() 210 stdin = stdout = stderr = file()
225 211
226 %(init)s 212 %(init)s
227 213
228 def communicate(self, input=None): 214 def communicate(self, input=None):
229 return %(communicate)r 215 return %(communicate)r
230 %(wait_signature)s: 216 %(wait_signature)s:
231 return self.returncode 217 return self.returncode
232 def poll(self): 218 def poll(self):
233 return self.returncode 219 return self.returncode
234 def send_signal(self, signal): 220 def send_signal(self, signal):
235 pass 221 pass
236 def terminate(self): 222 def terminate(self):
237 pass 223 pass
238 def kill(self): 224 def kill(self):
239 pass 225 pass
240 ''' % {'init': init, 226 ''' % {'init': init,
241 'communicate': communicate, 227 'communicate': communicate,
242 'wait_signature': wait_signature}) 228 'wait_signature': wait_signature})
243 229
244 for func_name, func in fake.locals.items():
245 module.locals[func_name] = func
246
247
248
249 MODULE_TRANSFORMS['hashlib'] = hashlib_transform
250 MODULE_TRANSFORMS['collections'] = collections_transform
251 MODULE_TRANSFORMS['pkg_resources'] = pkg_resources_transform
252 MODULE_TRANSFORMS['subprocess'] = subprocess_transform
253 230
254 # namedtuple support ########################################################### 231 # namedtuple support ###########################################################
255 232
233 def looks_like_namedtuple(node):
234 func = node.func
235 if type(func) is nodes.Getattr:
236 return func.attrname == 'namedtuple'
237 if type(func) is nodes.Name:
238 return func.name == 'namedtuple'
239 return False
240
256 def infer_named_tuple(node, context=None): 241 def infer_named_tuple(node, context=None):
257 """Specific inference function for namedtuple CallFunc node""" 242 """Specific inference function for namedtuple CallFunc node"""
258 class_node, name, attributes = infer_func_form(node, nodes.Tuple._proxied, 243 class_node, name, attributes = infer_func_form(node, nodes.Tuple._proxied,
259 context=context) 244 context=context)
260 fake = AstroidBuilder(MANAGER).string_build(''' 245 fake = AstroidBuilder(MANAGER).string_build('''
261 class %(name)s(tuple): 246 class %(name)s(tuple):
262 _fields = %(fields)r 247 _fields = %(fields)r
263 def _asdict(self): 248 def _asdict(self):
264 return self.__dict__ 249 return self.__dict__
265 @classmethod 250 @classmethod
(...skipping 12 matching lines...) Expand all
278 # we use UseInferenceDefault, we can't be a generator so return an iterator 263 # we use UseInferenceDefault, we can't be a generator so return an iterator
279 return iter([class_node]) 264 return iter([class_node])
280 265
281 def infer_enum(node, context=None): 266 def infer_enum(node, context=None):
282 """ Specific inference function for enum CallFunc node. """ 267 """ Specific inference function for enum CallFunc node. """
283 enum_meta = nodes.Class("EnumMeta", 'docstring') 268 enum_meta = nodes.Class("EnumMeta", 'docstring')
284 class_node = infer_func_form(node, enum_meta, 269 class_node = infer_func_form(node, enum_meta,
285 context=context, enum=True)[0] 270 context=context, enum=True)[0]
286 return iter([class_node.instanciate_class()]) 271 return iter([class_node.instanciate_class()])
287 272
288 def infer_enum_class(node, context=None): 273 def infer_enum_class(node):
289 """ Specific inference for enums. """ 274 """ Specific inference for enums. """
290 names = set(('Enum', 'IntEnum', 'enum.Enum', 'enum.IntEnum')) 275 names = set(('Enum', 'IntEnum', 'enum.Enum', 'enum.IntEnum'))
291 for basename in node.basenames: 276 for basename in node.basenames:
292 # TODO: doesn't handle subclasses yet. 277 # TODO: doesn't handle subclasses yet. This implementation
278 # is a hack to support enums.
293 if basename not in names: 279 if basename not in names:
294 continue 280 continue
295 if node.root().name == 'enum': 281 if node.root().name == 'enum':
296 # Skip if the class is directly from enum module. 282 # Skip if the class is directly from enum module.
297 break 283 break
298 for local, values in node.locals.items(): 284 for local, values in node.locals.items():
299 if any(not isinstance(value, nodes.AssName) 285 if any(not isinstance(value, nodes.AssName)
300 for value in values): 286 for value in values):
301 continue 287 continue
302 parent = values[0].parent 288
303 real_value = parent.value 289 stmt = values[0].statement()
290 if isinstance(stmt.targets[0], nodes.Tuple):
291 targets = stmt.targets[0].itered()
292 else:
293 targets = stmt.targets
294
304 new_targets = [] 295 new_targets = []
305 for target in parent.targets: 296 for target in targets:
306 # Replace all the assignments with our mocked class. 297 # Replace all the assignments with our mocked class.
307 classdef = dedent(''' 298 classdef = dedent('''
308 class %(name)s(object): 299 class %(name)s(object):
309 @property 300 @property
310 def value(self): 301 def value(self):
311 return %(value)s 302 # Not the best return.
303 return None
312 @property 304 @property
313 def name(self): 305 def name(self):
314 return %(name)r 306 return %(name)r
315 %(name)s = %(value)s 307 ''' % {'name': target.name})
316 ''' % {'name': target.name,
317 'value': real_value.as_string()})
318 fake = AstroidBuilder(MANAGER).string_build(classdef)[target.nam e] 308 fake = AstroidBuilder(MANAGER).string_build(classdef)[target.nam e]
319 fake.parent = target.parent 309 fake.parent = target.parent
320 for method in node.mymethods(): 310 for method in node.mymethods():
321 fake.locals[method.name] = [method] 311 fake.locals[method.name] = [method]
322 new_targets.append(fake.instanciate_class()) 312 new_targets.append(fake.instanciate_class())
323 node.locals[local] = new_targets 313 node.locals[local] = new_targets
324 break 314 break
325 return node 315 return node
326 316
317
327 MANAGER.register_transform(nodes.CallFunc, inference_tip(infer_named_tuple), 318 MANAGER.register_transform(nodes.CallFunc, inference_tip(infer_named_tuple),
328 AsStringRegexpPredicate('namedtuple', 'func')) 319 looks_like_namedtuple)
329 MANAGER.register_transform(nodes.CallFunc, inference_tip(infer_enum), 320 MANAGER.register_transform(nodes.CallFunc, inference_tip(infer_enum),
330 AsStringRegexpPredicate('Enum', 'func')) 321 AsStringRegexpPredicate('Enum', 'func'))
331 MANAGER.register_transform(nodes.Class, infer_enum_class) 322 MANAGER.register_transform(nodes.Class, infer_enum_class)
323 register_module_extender(MANAGER, 'hashlib', hashlib_transform)
324 register_module_extender(MANAGER, 'collections', collections_transform)
325 register_module_extender(MANAGER, 'pkg_resourcds', pkg_resources_transform)
326 register_module_extender(MANAGER, 'subprocess', subprocess_transform)
OLDNEW
« no previous file with comments | « third_party/logilab/astroid/brain/py2qt4.py ('k') | third_party/logilab/astroid/builder.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698