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

Side by Side Diff: Tools/Scripts/webkitpy/thirdparty/logilab/astng/node_classes.py

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

Powered by Google App Engine
This is Rietveld 408576698