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

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

Issue 739393004: Revert "Revert "pylint: upgrade to 1.3.1"" (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/astng/mixins.py ('k') | third_party/logilab/astng/nodes.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
3 # copyright 2003-2010 Sylvain Thenault, all rights reserved.
4 # contact mailto:thenault@gmail.com
5 #
6 # This file is part of logilab-astng.
7 #
8 # logilab-astng is free software: you can redistribute it and/or modify it
9 # under the terms of the GNU Lesser General Public License as published by the
10 # Free Software Foundation, either version 2.1 of the License, or (at your
11 # option) any later version.
12 #
13 # logilab-astng is distributed in the hope that it will be useful, but
14 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
16 # for more details.
17 #
18 # You should have received a copy of the GNU Lesser General Public License along
19 # with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
20 """Module for some node classes. More nodes in scoped_nodes.py
21 """
22
23 import sys
24
25 from logilab.astng import BUILTINS_MODULE
26 from logilab.astng.exceptions import NoDefault
27 from logilab.astng.bases import (NodeNG, Statement, Instance, InferenceContext,
28 _infer_stmts, YES)
29 from logilab.astng.mixins import BlockRangeMixIn, AssignTypeMixin, \
30 ParentAssignTypeMixin, FromImportMixIn
31
32
33 def unpack_infer(stmt, context=None):
34 """recursively generate nodes inferred by the given statement.
35 If the inferred value is a list or a tuple, recurse on the elements
36 """
37 if isinstance(stmt, (List, Tuple)):
38 for elt in stmt.elts:
39 for infered_elt in unpack_infer(elt, context):
40 yield infered_elt
41 return
42 infered = stmt.infer(context).next()
43 if infered is stmt or infered is YES:
44 yield infered
45 return
46 for infered in stmt.infer(context):
47 for inf_inf in unpack_infer(infered, context):
48 yield inf_inf
49
50
51 def are_exclusive(stmt1, stmt2, exceptions=None):
52 """return true if the two given statements are mutually exclusive
53
54 `exceptions` may be a list of exception names. If specified, discard If
55 branches and check one of the statement is in an exception handler catching
56 one of the given exceptions.
57
58 algorithm :
59 1) index stmt1's parents
60 2) climb among stmt2's parents until we find a common parent
61 3) if the common parent is a If or TryExcept statement, look if nodes are
62 in exclusive branches
63 """
64 # index stmt1's parents
65 stmt1_parents = {}
66 children = {}
67 node = stmt1.parent
68 previous = stmt1
69 while node:
70 stmt1_parents[node] = 1
71 children[node] = previous
72 previous = node
73 node = node.parent
74 # climb among stmt2's parents until we find a common parent
75 node = stmt2.parent
76 previous = stmt2
77 while node:
78 if node in stmt1_parents:
79 # if the common parent is a If or TryExcept statement, look if
80 # nodes are in exclusive branches
81 if isinstance(node, If) and exceptions is None:
82 if (node.locate_child(previous)[1]
83 is not node.locate_child(children[node])[1]):
84 return True
85 elif isinstance(node, TryExcept):
86 c2attr, c2node = node.locate_child(previous)
87 c1attr, c1node = node.locate_child(children[node])
88 if c1node is not c2node:
89 if ((c2attr == 'body' and c1attr == 'handlers' and children[ node].catch(exceptions)) or
90 (c2attr == 'handlers' and c1attr == 'body' and previous. catch(exceptions)) or
91 (c2attr == 'handlers' and c1attr == 'orelse') or
92 (c2attr == 'orelse' and c1attr == 'handlers')):
93 return True
94 elif c2attr == 'handlers' and c1attr == 'handlers':
95 return previous is not children[node]
96 return False
97 previous = node
98 node = node.parent
99 return False
100
101
102 class LookupMixIn(object):
103 """Mixin looking up a name in the right scope
104 """
105
106 def lookup(self, name):
107 """lookup a variable name
108
109 return the scope node and the list of assignments associated to the give n
110 name according to the scope where it has been found (locals, globals or
111 builtin)
112
113 The lookup is starting from self's scope. If self is not a frame itself and
114 the name is found in the inner frame locals, statements will be filtered
115 to remove ignorable statements according to self's location
116 """
117 return self.scope().scope_lookup(self, name)
118
119 def ilookup(self, name):
120 """infered lookup
121
122 return an iterator on infered values of the statements returned by
123 the lookup method
124 """
125 frame, stmts = self.lookup(name)
126 context = InferenceContext()
127 return _infer_stmts(stmts, context, frame)
128
129 def _filter_stmts(self, stmts, frame, offset):
130 """filter statements to remove ignorable statements.
131
132 If self is not a frame itself and the name is found in the inner
133 frame locals, statements will be filtered to remove ignorable
134 statements according to self's location
135 """
136 # if offset == -1, my actual frame is not the inner frame but its parent
137 #
138 # class A(B): pass
139 #
140 # we need this to resolve B correctly
141 if offset == -1:
142 myframe = self.frame().parent.frame()
143 else:
144 myframe = self.frame()
145 if not myframe is frame or self is frame:
146 return stmts
147 mystmt = self.statement()
148 # line filtering if we are in the same frame
149 #
150 # take care node may be missing lineno information (this is the case for
151 # nodes inserted for living objects)
152 if myframe is frame and mystmt.fromlineno is not None:
153 assert mystmt.fromlineno is not None, mystmt
154 mylineno = mystmt.fromlineno + offset
155 else:
156 # disabling lineno filtering
157 mylineno = 0
158 _stmts = []
159 _stmt_parents = []
160 for node in stmts:
161 stmt = node.statement()
162 # line filtering is on and we have reached our location, break
163 if mylineno > 0 and stmt.fromlineno > mylineno:
164 break
165 assert hasattr(node, 'ass_type'), (node, node.scope(),
166 node.scope().locals)
167 ass_type = node.ass_type()
168
169 if node.has_base(self):
170 break
171
172 _stmts, done = ass_type._get_filtered_stmts(self, node, _stmts, myst mt)
173 if done:
174 break
175
176 optional_assign = ass_type.optional_assign
177 if optional_assign and ass_type.parent_of(self):
178 # we are inside a loop, loop var assigment is hidding previous
179 # assigment
180 _stmts = [node]
181 _stmt_parents = [stmt.parent]
182 continue
183
184 # XXX comment various branches below!!!
185 try:
186 pindex = _stmt_parents.index(stmt.parent)
187 except ValueError:
188 pass
189 else:
190 # we got a parent index, this means the currently visited node
191 # is at the same block level as a previously visited node
192 if _stmts[pindex].ass_type().parent_of(ass_type):
193 # both statements are not at the same block level
194 continue
195 # if currently visited node is following previously considered
196 # assignement and both are not exclusive, we can drop the
197 # previous one. For instance in the following code ::
198 #
199 # if a:
200 # x = 1
201 # else:
202 # x = 2
203 # print x
204 #
205 # we can't remove neither x = 1 nor x = 2 when looking for 'x'
206 # of 'print x'; while in the following ::
207 #
208 # x = 1
209 # x = 2
210 # print x
211 #
212 # we can remove x = 1 when we see x = 2
213 #
214 # moreover, on loop assignment types, assignment won't
215 # necessarily be done if the loop has no iteration, so we don't
216 # want to clear previous assigments if any (hence the test on
217 # optional_assign)
218 if not (optional_assign or are_exclusive(_stmts[pindex], node)):
219 del _stmt_parents[pindex]
220 del _stmts[pindex]
221 if isinstance(node, AssName):
222 if not optional_assign and stmt.parent is mystmt.parent:
223 _stmts = []
224 _stmt_parents = []
225 elif isinstance(node, DelName):
226 _stmts = []
227 _stmt_parents = []
228 continue
229 if not are_exclusive(self, node):
230 _stmts.append(node)
231 _stmt_parents.append(stmt.parent)
232 return _stmts
233
234 # Name classes
235
236 class AssName(LookupMixIn, ParentAssignTypeMixin, NodeNG):
237 """class representing an AssName node"""
238
239
240 class DelName(LookupMixIn, ParentAssignTypeMixin, NodeNG):
241 """class representing a DelName node"""
242
243
244 class Name(LookupMixIn, NodeNG):
245 """class representing a Name node"""
246
247
248
249
250 ##################### node classes ########################################
251
252 class Arguments(NodeNG, AssignTypeMixin):
253 """class representing an Arguments node"""
254 _astng_fields = ('args', 'defaults')
255 args = None
256 defaults = None
257
258 def __init__(self, vararg=None, kwarg=None):
259 self.vararg = vararg
260 self.kwarg = kwarg
261
262 def _infer_name(self, frame, name):
263 if self.parent is frame:
264 return name
265 return None
266
267 def format_args(self):
268 """return arguments formatted as string"""
269 result = [_format_args(self.args, self.defaults)]
270 if self.vararg:
271 result.append('*%s' % self.vararg)
272 if self.kwarg:
273 result.append('**%s' % self.kwarg)
274 return ', '.join(result)
275
276 def default_value(self, argname):
277 """return the default value for an argument
278
279 :raise `NoDefault`: if there is no default value defined
280 """
281 i = _find_arg(argname, self.args)[0]
282 if i is not None:
283 idx = i - (len(self.args) - len(self.defaults))
284 if idx >= 0:
285 return self.defaults[idx]
286 raise NoDefault()
287
288 def is_argument(self, name):
289 """return True if the name is defined in arguments"""
290 if name == self.vararg:
291 return True
292 if name == self.kwarg:
293 return True
294 return self.find_argname(name, True)[1] is not None
295
296 def find_argname(self, argname, rec=False):
297 """return index and Name node with given name"""
298 if self.args: # self.args may be None in some cases (builtin function)
299 return _find_arg(argname, self.args, rec)
300 return None, None
301
302
303 def _find_arg(argname, args, rec=False):
304 for i, arg in enumerate(args):
305 if isinstance(arg, Tuple):
306 if rec:
307 found = _find_arg(argname, arg.elts)
308 if found[0] is not None:
309 return found
310 elif arg.name == argname:
311 return i, arg
312 return None, None
313
314
315 def _format_args(args, defaults=None):
316 values = []
317 if args is None:
318 return ''
319 if defaults is not None:
320 default_offset = len(args) - len(defaults)
321 for i, arg in enumerate(args):
322 if isinstance(arg, Tuple):
323 values.append('(%s)' % _format_args(arg.elts))
324 else:
325 values.append(arg.name)
326 if defaults is not None and i >= default_offset:
327 values[-1] += '=' + defaults[i-default_offset].as_string()
328 return ', '.join(values)
329
330
331 class AssAttr(NodeNG, ParentAssignTypeMixin):
332 """class representing an AssAttr node"""
333 _astng_fields = ('expr',)
334 expr = None
335
336 class Assert(Statement):
337 """class representing an Assert node"""
338 _astng_fields = ('test', 'fail',)
339 test = None
340 fail = None
341
342 class Assign(Statement, AssignTypeMixin):
343 """class representing an Assign node"""
344 _astng_fields = ('targets', 'value',)
345 targets = None
346 value = None
347
348 class AugAssign(Statement, AssignTypeMixin):
349 """class representing an AugAssign node"""
350 _astng_fields = ('target', 'value',)
351 target = None
352 value = None
353
354 class Backquote(NodeNG):
355 """class representing a Backquote node"""
356 _astng_fields = ('value',)
357 value = None
358
359 class BinOp(NodeNG):
360 """class representing a BinOp node"""
361 _astng_fields = ('left', 'right',)
362 left = None
363 right = None
364
365 class BoolOp(NodeNG):
366 """class representing a BoolOp node"""
367 _astng_fields = ('values',)
368 values = None
369
370 class Break(Statement):
371 """class representing a Break node"""
372
373
374 class CallFunc(NodeNG):
375 """class representing a CallFunc node"""
376 _astng_fields = ('func', 'args', 'starargs', 'kwargs')
377 func = None
378 args = None
379 starargs = None
380 kwargs = None
381
382 def __init__(self):
383 self.starargs = None
384 self.kwargs = None
385
386 class Compare(NodeNG):
387 """class representing a Compare node"""
388 _astng_fields = ('left', 'ops',)
389 left = None
390 ops = None
391
392 def get_children(self):
393 """override get_children for tuple fields"""
394 yield self.left
395 for _, comparator in self.ops:
396 yield comparator # we don't want the 'op'
397
398 def last_child(self):
399 """override last_child"""
400 # XXX maybe if self.ops:
401 return self.ops[-1][1]
402 #return self.left
403
404 class Comprehension(NodeNG):
405 """class representing a Comprehension node"""
406 _astng_fields = ('target', 'iter' ,'ifs')
407 target = None
408 iter = None
409 ifs = None
410
411 optional_assign = True
412 def ass_type(self):
413 return self
414
415 def _get_filtered_stmts(self, lookup_node, node, stmts, mystmt):
416 """method used in filter_stmts"""
417 if self is mystmt:
418 if isinstance(lookup_node, (Const, Name)):
419 return [lookup_node], True
420
421 elif self.statement() is mystmt:
422 # original node's statement is the assignment, only keeps
423 # current node (gen exp, list comp)
424
425 return [node], True
426
427 return stmts, False
428
429
430 class Const(NodeNG, Instance):
431 """represent a constant node like num, str, bool, None, bytes"""
432
433 def __init__(self, value=None):
434 self.value = value
435
436 def getitem(self, index, context=None):
437 if isinstance(self.value, basestring):
438 return Const(self.value[index])
439 raise TypeError('%r (value=%s)' % (self, self.value))
440
441 def has_dynamic_getattr(self):
442 return False
443
444 def itered(self):
445 if isinstance(self.value, basestring):
446 return self.value
447 raise TypeError()
448
449 def pytype(self):
450 return self._proxied.qname()
451
452
453 class Continue(Statement):
454 """class representing a Continue node"""
455
456
457 class Decorators(NodeNG):
458 """class representing a Decorators node"""
459 _astng_fields = ('nodes',)
460 nodes = None
461
462 def __init__(self, nodes=None):
463 self.nodes = nodes
464
465 def scope(self):
466 # skip the function node to go directly to the upper level scope
467 return self.parent.parent.scope()
468
469 class DelAttr(NodeNG, ParentAssignTypeMixin):
470 """class representing a DelAttr node"""
471 _astng_fields = ('expr',)
472 expr = None
473
474
475 class Delete(Statement, AssignTypeMixin):
476 """class representing a Delete node"""
477 _astng_fields = ('targets',)
478 targets = None
479
480
481 class Dict(NodeNG, Instance):
482 """class representing a Dict node"""
483 _astng_fields = ('items',)
484
485 def __init__(self, items=None):
486 if items is None:
487 self.items = []
488 else:
489 self.items = [(const_factory(k), const_factory(v))
490 for k,v in items.iteritems()]
491
492 def pytype(self):
493 return '%s.dict' % BUILTINS_MODULE
494
495 def get_children(self):
496 """get children of a Dict node"""
497 # overrides get_children
498 for key, value in self.items:
499 yield key
500 yield value
501
502 def last_child(self):
503 """override last_child"""
504 if self.items:
505 return self.items[-1][1]
506 return None
507
508 def itered(self):
509 return self.items[::2]
510
511 def getitem(self, key, context=None):
512 for i in xrange(0, len(self.items), 2):
513 for inferedkey in self.items[i].infer(context):
514 if inferedkey is YES:
515 continue
516 if isinstance(inferedkey, Const) and inferedkey.value == key:
517 return self.items[i+1]
518 raise IndexError(key)
519
520
521 class Discard(Statement):
522 """class representing a Discard node"""
523 _astng_fields = ('value',)
524 value = None
525
526
527 class Ellipsis(NodeNG):
528 """class representing an Ellipsis node"""
529
530
531 class EmptyNode(NodeNG):
532 """class representing an EmptyNode node"""
533
534
535 class ExceptHandler(Statement, AssignTypeMixin):
536 """class representing an ExceptHandler node"""
537 _astng_fields = ('type', 'name', 'body',)
538 type = None
539 name = None
540 body = None
541
542 def _blockstart_toline(self):
543 if self.name:
544 return self.name.tolineno
545 elif self.type:
546 return self.type.tolineno
547 else:
548 return self.lineno
549
550 def set_line_info(self, lastchild):
551 self.fromlineno = self.lineno
552 self.tolineno = lastchild.tolineno
553 self.blockstart_tolineno = self._blockstart_toline()
554
555 def catch(self, exceptions):
556 if self.type is None or exceptions is None:
557 return True
558 for node in self.type.nodes_of_class(Name):
559 if node.name in exceptions:
560 return True
561
562
563 class Exec(Statement):
564 """class representing an Exec node"""
565 _astng_fields = ('expr', 'globals', 'locals',)
566 expr = None
567 globals = None
568 locals = None
569
570
571 class ExtSlice(NodeNG):
572 """class representing an ExtSlice node"""
573 _astng_fields = ('dims',)
574 dims = None
575
576 class For(BlockRangeMixIn, AssignTypeMixin, Statement):
577 """class representing a For node"""
578 _astng_fields = ('target', 'iter', 'body', 'orelse',)
579 target = None
580 iter = None
581 body = None
582 orelse = None
583
584 optional_assign = True
585 def _blockstart_toline(self):
586 return self.iter.tolineno
587
588
589 class From(FromImportMixIn, Statement):
590 """class representing a From node"""
591
592 def __init__(self, fromname, names, level=0):
593 self.modname = fromname
594 self.names = names
595 self.level = level
596
597 class Getattr(NodeNG):
598 """class representing a Getattr node"""
599 _astng_fields = ('expr',)
600 expr = None
601
602
603 class Global(Statement):
604 """class representing a Global node"""
605
606 def __init__(self, names):
607 self.names = names
608
609 def _infer_name(self, frame, name):
610 return name
611
612
613 class If(BlockRangeMixIn, Statement):
614 """class representing an If node"""
615 _astng_fields = ('test', 'body', 'orelse')
616 test = None
617 body = None
618 orelse = None
619
620 def _blockstart_toline(self):
621 return self.test.tolineno
622
623 def block_range(self, lineno):
624 """handle block line numbers range for if statements"""
625 if lineno == self.body[0].fromlineno:
626 return lineno, lineno
627 if lineno <= self.body[-1].tolineno:
628 return lineno, self.body[-1].tolineno
629 return self._elsed_block_range(lineno, self.orelse,
630 self.body[0].fromlineno - 1)
631
632
633 class IfExp(NodeNG):
634 """class representing an IfExp node"""
635 _astng_fields = ('test', 'body', 'orelse')
636 test = None
637 body = None
638 orelse = None
639
640
641 class Import(FromImportMixIn, Statement):
642 """class representing an Import node"""
643
644
645 class Index(NodeNG):
646 """class representing an Index node"""
647 _astng_fields = ('value',)
648 value = None
649
650
651 class Keyword(NodeNG):
652 """class representing a Keyword node"""
653 _astng_fields = ('value',)
654 value = None
655
656
657 class List(NodeNG, Instance, ParentAssignTypeMixin):
658 """class representing a List node"""
659 _astng_fields = ('elts',)
660
661 def __init__(self, elts=None):
662 if elts is None:
663 self.elts = []
664 else:
665 self.elts = [const_factory(e) for e in elts]
666
667 def pytype(self):
668 return '%s.list' % BUILTINS_MODULE
669
670 def getitem(self, index, context=None):
671 return self.elts[index]
672
673 def itered(self):
674 return self.elts
675
676
677 class Nonlocal(Statement):
678 """class representing a Nonlocal node"""
679
680 def __init__(self, names):
681 self.names = names
682
683 def _infer_name(self, frame, name):
684 return name
685
686
687 class Pass(Statement):
688 """class representing a Pass node"""
689
690
691 class Print(Statement):
692 """class representing a Print node"""
693 _astng_fields = ('dest', 'values',)
694 dest = None
695 values = None
696
697
698 class Raise(Statement):
699 """class representing a Raise node"""
700 exc = None
701 if sys.version_info < (3, 0):
702 _astng_fields = ('exc', 'inst', 'tback')
703 inst = None
704 tback = None
705 else:
706 _astng_fields = ('exc', 'cause')
707 exc = None
708 cause = None
709
710 def raises_not_implemented(self):
711 if not self.exc:
712 return
713 for name in self.exc.nodes_of_class(Name):
714 if name.name == 'NotImplementedError':
715 return True
716
717
718 class Return(Statement):
719 """class representing a Return node"""
720 _astng_fields = ('value',)
721 value = None
722
723
724 class Set(NodeNG, Instance, ParentAssignTypeMixin):
725 """class representing a Set node"""
726 _astng_fields = ('elts',)
727
728 def __init__(self, elts=None):
729 if elts is None:
730 self.elts = []
731 else:
732 self.elts = [const_factory(e) for e in elts]
733
734 def pytype(self):
735 return '%s.set' % BUILTINS_MODULE
736
737 def itered(self):
738 return self.elts
739
740
741 class Slice(NodeNG):
742 """class representing a Slice node"""
743 _astng_fields = ('lower', 'upper', 'step')
744 lower = None
745 upper = None
746 step = None
747
748 class Starred(NodeNG):
749 """class representing a Starred node"""
750 _astng_fields = ('value',)
751 value = None
752
753
754 class Subscript(NodeNG):
755 """class representing a Subscript node"""
756 _astng_fields = ('value', 'slice')
757 value = None
758 slice = None
759
760
761 class TryExcept(BlockRangeMixIn, Statement):
762 """class representing a TryExcept node"""
763 _astng_fields = ('body', 'handlers', 'orelse',)
764 body = None
765 handlers = None
766 orelse = None
767
768 def _infer_name(self, frame, name):
769 return name
770
771 def _blockstart_toline(self):
772 return self.lineno
773
774 def block_range(self, lineno):
775 """handle block line numbers range for try/except statements"""
776 last = None
777 for exhandler in self.handlers:
778 if exhandler.type and lineno == exhandler.type.fromlineno:
779 return lineno, lineno
780 if exhandler.body[0].fromlineno <= lineno <= exhandler.body[-1].toli neno:
781 return lineno, exhandler.body[-1].tolineno
782 if last is None:
783 last = exhandler.body[0].fromlineno - 1
784 return self._elsed_block_range(lineno, self.orelse, last)
785
786
787 class TryFinally(BlockRangeMixIn, Statement):
788 """class representing a TryFinally node"""
789 _astng_fields = ('body', 'finalbody',)
790 body = None
791 finalbody = None
792
793 def _blockstart_toline(self):
794 return self.lineno
795
796 def block_range(self, lineno):
797 """handle block line numbers range for try/finally statements"""
798 child = self.body[0]
799 # py2.5 try: except: finally:
800 if (isinstance(child, TryExcept) and child.fromlineno == self.fromlineno
801 and lineno > self.fromlineno and lineno <= child.tolineno):
802 return child.block_range(lineno)
803 return self._elsed_block_range(lineno, self.finalbody)
804
805
806 class Tuple(NodeNG, Instance, ParentAssignTypeMixin):
807 """class representing a Tuple node"""
808 _astng_fields = ('elts',)
809
810 def __init__(self, elts=None):
811 if elts is None:
812 self.elts = []
813 else:
814 self.elts = [const_factory(e) for e in elts]
815
816 def pytype(self):
817 return '%s.tuple' % BUILTINS_MODULE
818
819 def getitem(self, index, context=None):
820 return self.elts[index]
821
822 def itered(self):
823 return self.elts
824
825
826 class UnaryOp(NodeNG):
827 """class representing an UnaryOp node"""
828 _astng_fields = ('operand',)
829 operand = None
830
831
832 class While(BlockRangeMixIn, Statement):
833 """class representing a While node"""
834 _astng_fields = ('test', 'body', 'orelse',)
835 test = None
836 body = None
837 orelse = None
838
839 def _blockstart_toline(self):
840 return self.test.tolineno
841
842 def block_range(self, lineno):
843 """handle block line numbers range for for and while statements"""
844 return self. _elsed_block_range(lineno, self.orelse)
845
846
847 class With(BlockRangeMixIn, AssignTypeMixin, Statement):
848 """class representing a With node"""
849 _astng_fields = ('expr', 'vars', 'body')
850 expr = None
851 vars = None
852 body = None
853
854 def _blockstart_toline(self):
855 if self.vars:
856 return self.vars.tolineno
857 else:
858 return self.expr.tolineno
859
860
861 class Yield(NodeNG):
862 """class representing a Yield node"""
863 _astng_fields = ('value',)
864 value = None
865
866 # constants ##############################################################
867
868 CONST_CLS = {
869 list: List,
870 tuple: Tuple,
871 dict: Dict,
872 set: Set,
873 type(None): Const,
874 }
875
876 def _update_const_classes():
877 """update constant classes, so the keys of CONST_CLS can be reused"""
878 klasses = (bool, int, float, complex, str)
879 if sys.version_info < (3, 0):
880 klasses += (unicode, long)
881 if sys.version_info >= (2, 6):
882 klasses += (bytes,)
883 for kls in klasses:
884 CONST_CLS[kls] = Const
885 _update_const_classes()
886
887 def const_factory(value):
888 """return an astng node for a python value"""
889 # since const_factory is called to evaluate content of container (eg list,
890 # tuple), it may be called with some node as argument that should be left
891 # untouched
892 if isinstance(value, NodeNG):
893 return value
894 try:
895 return CONST_CLS[value.__class__](value)
896 except (KeyError, AttributeError):
897 # some constants (like from gtk._gtk) don't have their class in
898 # CONST_CLS, though we can "assert isinstance(value, tuple(CONST_CLS))"
899 if isinstance(value, tuple(CONST_CLS)):
900 return Const(value)
901 node = EmptyNode()
902 node.object = value
903 return node
OLDNEW
« no previous file with comments | « third_party/logilab/astng/mixins.py ('k') | third_party/logilab/astng/nodes.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698