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

Side by Side Diff: third_party/logilab/astng/bases.py

Issue 719313003: Revert "pylint: upgrade to 1.3.1" (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: Created 6 years, 1 month 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
« no previous file with comments | « third_party/logilab/astng/as_string.py ('k') | third_party/logilab/astng/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 # copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. 1 # -*- coding: utf-8 -*-
2 # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr 3 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
4 # copyright 2003-2010 Sylvain Thenault, all rights reserved.
5 # contact mailto:thenault@gmail.com
3 # 6 #
4 # This file is part of astroid. 7 # This file is part of logilab-astng.
5 # 8 #
6 # astroid is free software: you can redistribute it and/or modify it 9 # logilab-astng is free software: you can redistribute it and/or modify it
7 # under the terms of the GNU Lesser General Public License as published by the 10 # under the terms of the GNU Lesser General Public License as published by the
8 # Free Software Foundation, either version 2.1 of the License, or (at your 11 # Free Software Foundation, either version 2.1 of the License, or (at your
9 # option) any later version. 12 # option) any later version.
10 # 13 #
11 # astroid is distributed in the hope that it will be useful, but 14 # logilab-astng is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License 16 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
14 # for more details. 17 # for more details.
15 # 18 #
16 # You should have received a copy of the GNU Lesser General Public License along 19 # You should have received a copy of the GNU Lesser General Public License along
17 # with astroid. If not, see <http://www.gnu.org/licenses/>. 20 # with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
18 """This module contains base classes and functions for the nodes and some 21 """This module contains base classes and functions for the nodes and some
19 inference utils. 22 inference utils.
20 """ 23 """
21 24
22 __docformat__ = "restructuredtext en" 25 __docformat__ = "restructuredtext en"
23 26
24 import sys
25 from contextlib import contextmanager 27 from contextlib import contextmanager
26 28
27 from astroid.exceptions import (InferenceError, AstroidError, NotFoundError, 29 from logilab.common.compat import builtins
28 UnresolvableName, UseInferenceDefault)
29 30
31 from logilab.astng import BUILTINS_MODULE
32 from logilab.astng.exceptions import InferenceError, ASTNGError, \
33 NotFoundError, UnresolvableName
34 from logilab.astng.as_string import as_string
30 35
31 if sys.version_info >= (3, 0): 36 BUILTINS_NAME = builtins.__name__
32 BUILTINS = 'builtins'
33 else:
34 BUILTINS = '__builtin__'
35
36 37
37 class Proxy(object): 38 class Proxy(object):
38 """a simple proxy object""" 39 """a simple proxy object"""
39 40 _proxied = None
40 _proxied = None # proxied object may be set by class or by instance
41 41
42 def __init__(self, proxied=None): 42 def __init__(self, proxied=None):
43 if proxied is not None: 43 if proxied is not None:
44 self._proxied = proxied 44 self._proxied = proxied
45 45
46 def __getattr__(self, name): 46 def __getattr__(self, name):
47 if name == '_proxied': 47 if name == '_proxied':
48 return getattr(self.__class__, '_proxied') 48 return getattr(self.__class__, '_proxied')
49 if name in self.__dict__: 49 if name in self.__dict__:
50 return self.__dict__[name] 50 return self.__dict__[name]
(...skipping 14 matching lines...) Expand all
65 else: 65 else:
66 self.path = path 66 self.path = path
67 self.lookupname = None 67 self.lookupname = None
68 self.callcontext = None 68 self.callcontext = None
69 self.boundnode = None 69 self.boundnode = None
70 70
71 def push(self, node): 71 def push(self, node):
72 name = self.lookupname 72 name = self.lookupname
73 if (node, name) in self.path: 73 if (node, name) in self.path:
74 raise StopIteration() 74 raise StopIteration()
75 self.path.add((node, name)) 75 self.path.add( (node, name) )
76 76
77 def clone(self): 77 def clone(self):
78 # XXX copy lookupname/callcontext ? 78 # XXX copy lookupname/callcontext ?
79 clone = InferenceContext(self.path) 79 clone = InferenceContext(self.path)
80 clone.callcontext = self.callcontext 80 clone.callcontext = self.callcontext
81 clone.boundnode = self.boundnode 81 clone.boundnode = self.boundnode
82 return clone 82 return clone
83 83
84 @contextmanager 84 @contextmanager
85 def restore_path(self): 85 def restore_path(self):
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 raise InferenceError(str(stmt)) 124 raise InferenceError(str(stmt))
125 125
126 126
127 # special inference objects (e.g. may be returned as nodes by .infer()) ####### 127 # special inference objects (e.g. may be returned as nodes by .infer()) #######
128 128
129 class _Yes(object): 129 class _Yes(object):
130 """a yes object""" 130 """a yes object"""
131 def __repr__(self): 131 def __repr__(self):
132 return 'YES' 132 return 'YES'
133 def __getattribute__(self, name): 133 def __getattribute__(self, name):
134 if name == 'next':
135 raise AttributeError('next method should not be called')
136 if name.startswith('__') and name.endswith('__'): 134 if name.startswith('__') and name.endswith('__'):
137 # to avoid inspection pb 135 # to avoid inspection pb
138 return super(_Yes, self).__getattribute__(name) 136 return super(_Yes, self).__getattribute__(name)
139 return self 137 return self
140 def __call__(self, *args, **kwargs): 138 def __call__(self, *args, **kwargs):
141 return self 139 return self
142 140
143 141
144 YES = _Yes() 142 YES = _Yes()
145 143
(...skipping 18 matching lines...) Expand all
164 if lookupclass: 162 if lookupclass:
165 try: 163 try:
166 return values + self._proxied.getattr(name, context) 164 return values + self._proxied.getattr(name, context)
167 except NotFoundError: 165 except NotFoundError:
168 pass 166 pass
169 return values 167 return values
170 168
171 def igetattr(self, name, context=None): 169 def igetattr(self, name, context=None):
172 """inferred getattr""" 170 """inferred getattr"""
173 try: 171 try:
174 # avoid recursively inferring the same attr on the same class
175 if context:
176 context.push((self._proxied, name))
177 # XXX frame should be self._proxied, or not ? 172 # XXX frame should be self._proxied, or not ?
178 get_attr = self.getattr(name, context, lookupclass=False) 173 get_attr = self.getattr(name, context, lookupclass=False)
179 return _infer_stmts(self._wrap_attr(get_attr, context), context, 174 return _infer_stmts(self._wrap_attr(get_attr, context), context,
180 frame=self) 175 frame=self)
181 except NotFoundError: 176 except NotFoundError:
182 try: 177 try:
183 # fallback to class'igetattr since it has some logic to handle 178 # fallback to class'igetattr since it has some logic to handle
184 # descriptors 179 # descriptors
185 return self._wrap_attr(self._proxied.igetattr(name, context), 180 return self._wrap_attr(self._proxied.igetattr(name, context),
186 context) 181 context)
187 except NotFoundError: 182 except NotFoundError:
188 raise InferenceError(name) 183 raise InferenceError(name)
189 184
190 def _wrap_attr(self, attrs, context=None): 185 def _wrap_attr(self, attrs, context=None):
191 """wrap bound methods of attrs in a InstanceMethod proxies""" 186 """wrap bound methods of attrs in a InstanceMethod proxies"""
192 for attr in attrs: 187 for attr in attrs:
193 if isinstance(attr, UnboundMethod): 188 if isinstance(attr, UnboundMethod):
194 if BUILTINS + '.property' in attr.decoratornames(): 189 if BUILTINS_NAME + '.property' in attr.decoratornames():
195 for infered in attr.infer_call_result(self, context): 190 for infered in attr.infer_call_result(self, context):
196 yield infered 191 yield infered
197 else: 192 else:
198 yield BoundMethod(attr, self) 193 yield BoundMethod(attr, self)
199 else: 194 else:
200 yield attr 195 yield attr
201 196
202 def infer_call_result(self, caller, context=None): 197 def infer_call_result(self, caller, context=None):
203 """infer what a class instance is returning when called""" 198 """infer what a class instance is returning when called"""
204 infered = False 199 infered = False
205 for node in self._proxied.igetattr('__call__', context): 200 for node in self._proxied.igetattr('__call__', context):
206 if node is YES:
207 continue
208 for res in node.infer_call_result(caller, context): 201 for res in node.infer_call_result(caller, context):
209 infered = True 202 infered = True
210 yield res 203 yield res
211 if not infered: 204 if not infered:
212 raise InferenceError() 205 raise InferenceError()
213 206
214 def __repr__(self): 207 def __repr__(self):
215 return '<Instance of %s.%s at 0x%s>' % (self._proxied.root().name, 208 return '<Instance of %s.%s at 0x%s>' % (self._proxied.root().name,
216 self._proxied.name, 209 self._proxied.name,
217 id(self)) 210 id(self))
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 244
252 def igetattr(self, name, context=None): 245 def igetattr(self, name, context=None):
253 if name == 'im_func': 246 if name == 'im_func':
254 return iter((self._proxied,)) 247 return iter((self._proxied,))
255 return super(UnboundMethod, self).igetattr(name, context) 248 return super(UnboundMethod, self).igetattr(name, context)
256 249
257 def infer_call_result(self, caller, context): 250 def infer_call_result(self, caller, context):
258 # If we're unbound method __new__ of builtin object, the result is an 251 # If we're unbound method __new__ of builtin object, the result is an
259 # instance of the class given as first argument. 252 # instance of the class given as first argument.
260 if (self._proxied.name == '__new__' and 253 if (self._proxied.name == '__new__' and
261 self._proxied.parent.frame().qname() == '%s.object' % BUILTINS): 254 self._proxied.parent.frame().qname() == '%s.object' % BUILTINS_M ODULE):
262 infer = caller.args[0].infer() if caller.args else [] 255 return (x is YES and x or Instance(x) for x in caller.args[0].infer( ))
263 return ((x is YES and x or Instance(x)) for x in infer)
264 return self._proxied.infer_call_result(caller, context) 256 return self._proxied.infer_call_result(caller, context)
265 257
266 258
267 class BoundMethod(UnboundMethod): 259 class BoundMethod(UnboundMethod):
268 """a special node representing a method bound to an instance""" 260 """a special node representing a method bound to an instance"""
269 def __init__(self, proxy, bound): 261 def __init__(self, proxy, bound):
270 UnboundMethod.__init__(self, proxy) 262 UnboundMethod.__init__(self, proxy)
271 self.bound = bound 263 self.bound = bound
272 264
273 def is_bound(self): 265 def is_bound(self):
274 return True 266 return True
275 267
276 def infer_call_result(self, caller, context): 268 def infer_call_result(self, caller, context):
277 context = context.clone() 269 context = context.clone()
278 context.boundnode = self.bound 270 context.boundnode = self.bound
279 return self._proxied.infer_call_result(caller, context) 271 return self._proxied.infer_call_result(caller, context)
280 272
281 273
282 class Generator(Instance): 274 class Generator(Instance):
283 """a special node representing a generator. 275 """a special node representing a generator"""
284
285 Proxied class is set once for all in raw_building.
286 """
287 def callable(self): 276 def callable(self):
288 return False 277 return True
289 278
290 def pytype(self): 279 def pytype(self):
291 return '%s.generator' % BUILTINS 280 return '%s.generator' % BUILTINS_MODULE
292 281
293 def display_type(self): 282 def display_type(self):
294 return 'Generator' 283 return 'Generator'
295 284
296 def __repr__(self): 285 def __repr__(self):
297 return '<Generator(%s) l.%s at 0x%s>' % (self._proxied.name, self.lineno , id(self)) 286 return '<Generator(%s) l.%s at 0x%s>' % (self._proxied.name, self.lineno , id(self))
298 287
299 def __str__(self): 288 def __str__(self):
300 return 'Generator(%s)' % (self._proxied.name) 289 return 'Generator(%s)' % (self._proxied.name)
301 290
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 infered = True 327 infered = True
339 yield node 328 yield node
340 if not infered: 329 if not infered:
341 raise InferenceError() 330 raise InferenceError()
342 return wrapper 331 return wrapper
343 332
344 333
345 # Node ###################################################################### 334 # Node ######################################################################
346 335
347 class NodeNG(object): 336 class NodeNG(object):
348 """Base Class for all Astroid node classes. 337 """Base Class for all ASTNG node classes.
349 338
350 It represents a node of the new abstract syntax tree. 339 It represents a node of the new abstract syntax tree.
351 """ 340 """
352 is_statement = False 341 is_statement = False
353 optional_assign = False # True for For (and for Comprehension if py <3.0) 342 optional_assign = False # True for For (and for Comprehension if py <3.0)
354 is_function = False # True for Function nodes 343 is_function = False # True for Function nodes
355 # attributes below are set by the builder module or by raw factories 344 # attributes below are set by the builder module or by raw factories
356 lineno = None 345 lineno = None
357 fromlineno = None 346 fromlineno = None
358 tolineno = None 347 tolineno = None
359 col_offset = None 348 col_offset = None
360 # parent node in the tree 349 # parent node in the tree
361 parent = None 350 parent = None
362 # attributes containing child node(s) redefined in most concrete classes: 351 # attributes containing child node(s) redefined in most concrete classes:
363 _astroid_fields = () 352 _astng_fields = ()
364 # instance specific inference function infer(node, context)
365 _explicit_inference = None
366
367 def infer(self, context=None, **kwargs):
368 """main interface to the interface system, return a generator on infered
369 values.
370
371 If the instance has some explicit inference function set, it will be
372 called instead of the default interface.
373 """
374 if self._explicit_inference is not None:
375 # explicit_inference is not bound, give it self explicitly
376 try:
377 return self._explicit_inference(self, context, **kwargs)
378 except UseInferenceDefault:
379 pass
380 return self._infer(context, **kwargs)
381 353
382 def _repr_name(self): 354 def _repr_name(self):
383 """return self.name or self.attrname or '' for nice representation""" 355 """return self.name or self.attrname or '' for nice representation"""
384 return getattr(self, 'name', getattr(self, 'attrname', '')) 356 return getattr(self, 'name', getattr(self, 'attrname', ''))
385 357
386 def __str__(self): 358 def __str__(self):
387 return '%s(%s)' % (self.__class__.__name__, self._repr_name()) 359 return '%s(%s)' % (self.__class__.__name__, self._repr_name())
388 360
389 def __repr__(self): 361 def __repr__(self):
390 return '<%s(%s) l.%s [%s] at 0x%x>' % (self.__class__.__name__, 362 return '<%s(%s) l.%s [%s] at Ox%x>' % (self.__class__.__name__,
391 self._repr_name(), 363 self._repr_name(),
392 self.fromlineno, 364 self.fromlineno,
393 self.root().name, 365 self.root().name,
394 id(self)) 366 id(self))
395 367
396 368
397 def accept(self, visitor): 369 def accept(self, visitor):
370 klass = self.__class__.__name__
398 func = getattr(visitor, "visit_" + self.__class__.__name__.lower()) 371 func = getattr(visitor, "visit_" + self.__class__.__name__.lower())
399 return func(self) 372 return func(self)
400 373
401 def get_children(self): 374 def get_children(self):
402 for field in self._astroid_fields: 375 for field in self._astng_fields:
403 attr = getattr(self, field) 376 attr = getattr(self, field)
404 if attr is None: 377 if attr is None:
405 continue 378 continue
406 if isinstance(attr, (list, tuple)): 379 if isinstance(attr, (list, tuple)):
407 for elt in attr: 380 for elt in attr:
408 yield elt 381 yield elt
409 else: 382 else:
410 yield attr 383 yield attr
411 384
412 def last_child(self): 385 def last_child(self):
413 """an optimized version of list(get_children())[-1]""" 386 """an optimized version of list(get_children())[-1]"""
414 for field in self._astroid_fields[::-1]: 387 for field in self._astng_fields[::-1]:
415 attr = getattr(self, field) 388 attr = getattr(self, field)
416 if not attr: # None or empty listy / tuple 389 if not attr: # None or empty listy / tuple
417 continue 390 continue
418 if isinstance(attr, (list, tuple)): 391 if isinstance(attr, (list, tuple)):
419 return attr[-1] 392 return attr[-1]
420 else: 393 else:
421 return attr 394 return attr
422 return None 395 return None
423 396
424 def parent_of(self, node): 397 def parent_of(self, node):
(...skipping 23 matching lines...) Expand all
448 return self.parent.scope() 421 return self.parent.scope()
449 422
450 def root(self): 423 def root(self):
451 """return the root node of the tree, (i.e. a Module)""" 424 """return the root node of the tree, (i.e. a Module)"""
452 if self.parent: 425 if self.parent:
453 return self.parent.root() 426 return self.parent.root()
454 return self 427 return self
455 428
456 def child_sequence(self, child): 429 def child_sequence(self, child):
457 """search for the right sequence where the child lies in""" 430 """search for the right sequence where the child lies in"""
458 for field in self._astroid_fields: 431 for field in self._astng_fields:
459 node_or_sequence = getattr(self, field) 432 node_or_sequence = getattr(self, field)
460 if node_or_sequence is child: 433 if node_or_sequence is child:
461 return [node_or_sequence] 434 return [node_or_sequence]
462 # /!\ compiler.ast Nodes have an __iter__ walking over child nodes 435 # /!\ compiler.ast Nodes have an __iter__ walking over child nodes
463 if isinstance(node_or_sequence, (tuple, list)) and child in node_or_ sequence: 436 if isinstance(node_or_sequence, (tuple, list)) and child in node_or_ sequence:
464 return node_or_sequence 437 return node_or_sequence
465 else: 438 else:
466 msg = 'Could not find %s in %s\'s children' 439 msg = 'Could not found %s in %s\'s children'
467 raise AstroidError(msg % (repr(child), repr(self))) 440 raise ASTNGError(msg % (repr(child), repr(self)))
468 441
469 def locate_child(self, child): 442 def locate_child(self, child):
470 """return a 2-uple (child attribute name, sequence or node)""" 443 """return a 2-uple (child attribute name, sequence or node)"""
471 for field in self._astroid_fields: 444 for field in self._astng_fields:
472 node_or_sequence = getattr(self, field) 445 node_or_sequence = getattr(self, field)
473 # /!\ compiler.ast Nodes have an __iter__ walking over child nodes 446 # /!\ compiler.ast Nodes have an __iter__ walking over child nodes
474 if child is node_or_sequence: 447 if child is node_or_sequence:
475 return field, child 448 return field, child
476 if isinstance(node_or_sequence, (tuple, list)) and child in node_or_ sequence: 449 if isinstance(node_or_sequence, (tuple, list)) and child in node_or_ sequence:
477 return field, node_or_sequence 450 return field, node_or_sequence
478 msg = 'Could not find %s in %s\'s children' 451 msg = 'Could not found %s in %s\'s children'
479 raise AstroidError(msg % (repr(child), repr(self))) 452 raise ASTNGError(msg % (repr(child), repr(self)))
480 # FIXME : should we merge child_sequence and locate_child ? locate_child 453 # FIXME : should we merge child_sequence and locate_child ? locate_child
481 # is only used in are_exclusive, child_sequence one time in pylint. 454 # is only used in are_exclusive, child_sequence one time in pylint.
482 455
483 def next_sibling(self): 456 def next_sibling(self):
484 """return the next sibling statement""" 457 """return the next sibling statement"""
485 return self.parent.next_sibling() 458 return self.parent.next_sibling()
486 459
487 def previous_sibling(self): 460 def previous_sibling(self):
488 """return the previous sibling statement""" 461 """return the previous sibling statement"""
489 return self.parent.previous_sibling() 462 return self.parent.previous_sibling()
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
558 for child_node in self.get_children(): 531 for child_node in self.get_children():
559 if skip_klass is not None and isinstance(child_node, skip_klass): 532 if skip_klass is not None and isinstance(child_node, skip_klass):
560 continue 533 continue
561 for matching in child_node.nodes_of_class(klass, skip_klass): 534 for matching in child_node.nodes_of_class(klass, skip_klass):
562 yield matching 535 yield matching
563 536
564 def _infer_name(self, frame, name): 537 def _infer_name(self, frame, name):
565 # overridden for From, Import, Global, TryExcept and Arguments 538 # overridden for From, Import, Global, TryExcept and Arguments
566 return None 539 return None
567 540
568 def _infer(self, context=None): 541 def infer(self, context=None):
569 """we don't know how to resolve a statement by default""" 542 """we don't know how to resolve a statement by default"""
570 # this method is overridden by most concrete classes 543 # this method is overridden by most concrete classes
571 raise InferenceError(self.__class__.__name__) 544 raise InferenceError(self.__class__.__name__)
572 545
573 def infered(self): 546 def infered(self):
574 '''return list of infered values for a more simple inference usage''' 547 '''return list of infered values for a more simple inference usage'''
575 return list(self.infer()) 548 return list(self.infer())
576 549
577 def instanciate_class(self): 550 def instanciate_class(self):
578 """instanciate a node if it is a Class node, else return self""" 551 """instanciate a node if it is a Class node, else return self"""
579 return self 552 return self
580 553
581 def has_base(self, node): 554 def has_base(self, node):
582 return False 555 return False
583 556
584 def callable(self): 557 def callable(self):
585 return False 558 return False
586 559
587 def eq(self, value): 560 def eq(self, value):
588 return False 561 return False
589 562
590 def as_string(self): 563 def as_string(self):
591 from astroid.as_string import to_code 564 return as_string(self)
592 return to_code(self)
593 565
594 def repr_tree(self, ids=False): 566 def repr_tree(self, ids=False):
595 from astroid.as_string import dump 567 """print a nice astng tree representation.
596 return dump(self) 568
569 :param ids: if true, we also print the ids (usefull for debugging)"""
570 result = []
571 _repr_tree(self, result, ids=ids)
572 return "\n".join(result)
597 573
598 574
599 class Statement(NodeNG): 575 class Statement(NodeNG):
600 """Statement node adding a few attributes""" 576 """Statement node adding a few attributes"""
601 is_statement = True 577 is_statement = True
602 578
603 def next_sibling(self): 579 def next_sibling(self):
604 """return the next sibling statement""" 580 """return the next sibling statement"""
605 stmts = self.parent.child_sequence(self) 581 stmts = self.parent.child_sequence(self)
606 index = stmts.index(self) 582 index = stmts.index(self)
607 try: 583 try:
608 return stmts[index +1] 584 return stmts[index +1]
609 except IndexError: 585 except IndexError:
610 pass 586 pass
611 587
612 def previous_sibling(self): 588 def previous_sibling(self):
613 """return the previous sibling statement""" 589 """return the previous sibling statement"""
614 stmts = self.parent.child_sequence(self) 590 stmts = self.parent.child_sequence(self)
615 index = stmts.index(self) 591 index = stmts.index(self)
616 if index >= 1: 592 if index >= 1:
617 return stmts[index -1] 593 return stmts[index -1]
594
595 INDENT = " "
596
597 def _repr_tree(node, result, indent='', _done=None, ids=False):
598 """built a tree representation of a node as a list of lines"""
599 if _done is None:
600 _done = set()
601 if not hasattr(node, '_astng_fields'): # not a astng node
602 return
603 if node in _done:
604 result.append( indent + 'loop in tree: %s' % node )
605 return
606 _done.add(node)
607 node_str = str(node)
608 if ids:
609 node_str += ' . \t%x' % id(node)
610 result.append( indent + node_str )
611 indent += INDENT
612 for field in node._astng_fields:
613 value = getattr(node, field)
614 if isinstance(value, (list, tuple) ):
615 result.append( indent + field + " = [" )
616 for child in value:
617 if isinstance(child, (list, tuple) ):
618 # special case for Dict # FIXME
619 _repr_tree(child[0], result, indent, _done, ids)
620 _repr_tree(child[1], result, indent, _done, ids)
621 result.append(indent + ',')
622 else:
623 _repr_tree(child, result, indent, _done, ids)
624 result.append( indent + "]" )
625 else:
626 result.append( indent + field + " = " )
627 _repr_tree(value, result, indent, _done, ids)
628
629
OLDNEW
« no previous file with comments | « third_party/logilab/astng/as_string.py ('k') | third_party/logilab/astng/builder.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698