Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(2)

Side by Side Diff: Lib/ast.py

Issue 15452: Improve the security model for logging listener()
Patch Set: Created 7 years, 4 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Doc/library/ast.rst ('k') | Lib/logging/config.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 """ 1 """
2 ast 2 ast
3 ~~~ 3 ~~~
4 4
5 The `ast` module helps Python applications to process trees of the Python 5 The `ast` module helps Python applications to process trees of the Python
6 abstract syntax grammar. The abstract syntax itself might change with 6 abstract syntax grammar. The abstract syntax itself might change with
7 each Python release; this module helps to find out programmatically what 7 each Python release; this module helps to find out programmatically what
8 the current grammar looks like and allows modifications of it. 8 the current grammar looks like and allows modifications of it.
9 9
10 An abstract syntax tree can be generated by passing `ast.PyCF_ONLY_AST` as 10 An abstract syntax tree can be generated by passing `ast.PyCF_ONLY_AST` as
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
308 continue 308 continue
309 new_values.append(value) 309 new_values.append(value)
310 old_value[:] = new_values 310 old_value[:] = new_values
311 elif isinstance(old_value, AST): 311 elif isinstance(old_value, AST):
312 new_node = self.visit(old_value) 312 new_node = self.visit(old_value)
313 if new_node is None: 313 if new_node is None:
314 delattr(node, field) 314 delattr(node, field)
315 else: 315 else:
316 setattr(node, field, new_node) 316 setattr(node, field, new_node)
317 return node 317 return node
318
319
320 class Evaluator(object):
321 builtin_names = {
322 'None': None,
323 'False': False,
324 'True': True,
325 }
326
327 operators = {
328 'add': lambda x, y: x + y,
329 'bitand': lambda x, y: x & y,
330 'bitor': lambda x, y: x | y,
331 'bitxor': lambda x, y: x ^ y,
332 'div': lambda x, y: x / y,
333 'eq': lambda x, y: x == y,
334 'floordiv': lambda x, y: x // y,
335 'gt': lambda x, y: x > y,
336 'gte': lambda x, y: x >= y,
337 'in': lambda x, y: x in y,
338 'invert': lambda x: ~x,
339 'lshift': lambda x, y: x << y,
340 'lt': lambda x, y: x < y,
341 'lte': lambda x, y: x <= y,
342 'mod': lambda x, y: x % y,
343 'mult': lambda x, y: x * y,
344 'not': lambda x: not x,
345 'noteq': lambda x, y: x != y,
346 'notin': lambda x, y: x not in y,
347 'pow': lambda x, y: x ** y,
348 'rshift': lambda x, y: x >> y,
349 'sub': lambda x, y: x - y,
350 'uadd': lambda x: +x,
351 'usub': lambda x: -x,
352 }
353
354 handlers = {}
355
356 def __init__(self, context=None, allow_imports=False):
357 self.context = context or {}
358 self.source = None
359 self.allow_imports = allow_imports
360
361 def get_fragment(self, offset):
362 fragment_len = 10
363 s = 'at position %d: %r' % (offset, self.source[offset:offset + fragment _len])
364 if offset + fragment_len < len(self.source):
365 s += '...'
366 return s
367
368 def evaluate(self, node, filename=None):
369 if isinstance(node, str):
370 self.source = node
371 kwargs = dict(mode='eval')
372 if filename:
373 kwargs['filename'] = filename
374 try:
375 node = parse(node, **kwargs)
376 except SyntaxError as e:
377 s = self.get_fragment(e.offset)
378 raise ValueError('syntax error %s' % s)
379 node_type = node.__class__.__name__.lower()
380 if node_type in self.handlers:
381 handler = self.handlers[node_type]
382 else:
383 handler = getattr(self, 'do_%s' % node_type, None)
384 if handler is None:
385 if self.source is None:
386 s = '(source not available)'
387 else:
388 s = self.get_fragment(node.col_offset)
389 raise ValueError("don't know how to evaluate %r %s" % (
390 node_type, s))
391 return handler(node)
392
393 def do_attribute(self, node):
394 container = self.evaluate(node.value)
395 return getattr(container, node.attr)
396
397 def do_binop(self, node):
398 op = node.op.__class__.__name__.lower()
399 if op not in self.operators:
400 raise ValueError('unsupported operation: %r' % op)
401 lhs = self.evaluate(node.left)
402 rhs = self.evaluate(node.right)
403 return self.operators[op](lhs, rhs)
404
405 def do_boolop(self, node):
406 result = self.evaluate(node.values[0])
407 is_or = node.op.__class__ is Or
408 is_and = node.op.__class__ is And
409 assert is_or or is_and
410 if (is_and and result) or (is_or and not result):
411 for n in node.values[1:]:
412 result = self.evaluate(n)
413 if (is_or and result) or (is_and and not result):
414 break
415 return result
416
417 def do_compare(self, node):
418 lhs = self.evaluate(node.left)
419 result = True
420 for op, right in zip(node.ops, node.comparators):
421 op = op.__class__.__name__.lower()
422 if op not in self.operators:
423 raise ValueError('unsupported operation: %r' % op)
424 rhs = self.evaluate(right)
425 result = self.operators[op](lhs, rhs)
426 if not result:
427 break
428 lhs = rhs
429 return result
430
431 def do_dict(self, node):
432 e = self.evaluate
433 return dict((e(k), e(v)) for k, v in zip(node.keys, node.values))
434
435 def do_ellipsis(self, node):
436 return __builtins__['Ellipsis']
437
438 def do_expr(self, node):
439 return self.evaluate(node.value)
440
441 do_index = do_expr
442
443 def do_expression(self, node):
444 return self.evaluate(node.body)
445
446 def do_extslice(self, node):
447 e = self.evaluate
448 return tuple((e(n) for n in node.dims))
449
450 def do_list(self, node):
451 return list([self.evaluate(n) for n in node.elts])
452
453 def do_set(self, node):
454 return set([self.evaluate(n) for n in node.elts])
455
456 def do_name(self, node):
457 if node.id in self.builtin_names:
458 result = self.builtin_names[node.id]
459 elif node.id in self.context:
460 result = self.context[node.id]
461 else:
462 if not self.allow_imports:
463 raise ValueError('unknown name: %r' % node.id)
464 try:
465 result = __import__(node.id)
466 except ImportError:
467 raise ValueError('unknown name: %r' % node.id)
468 return result
469
470 def do_num(self, node):
471 return node.n
472
473 def do_slice(self, node):
474 if node.lower is None:
475 lower = None
476 else:
477 lower = self.evaluate(node.lower)
478 if node.upper is None:
479 upper = None
480 else:
481 upper = self.evaluate(node.upper)
482 if node.step is None:
483 step = None
484 else:
485 step = self.evaluate(node.step)
486 return __builtins__['slice'](lower, upper, step)
487
488 def do_str(self, node):
489 return node.s
490
491 do_bytes = do_str
492
493 def do_subscript(self, node):
494 assert node.ctx.__class__ is Load
495 val = self.evaluate(node.value)
496 if not isinstance(node.slice, (Index, Slice, Ellipsis, ExtSlice)):
497 raise ValueError('Unable to get subscript: %r',
498 node.slice.__class__.__name__)
499 indices = self.evaluate(node.slice)
500 if isinstance(node.slice, ExtSlice):
501 result = val[(indices)]
502 else:
503 result = val.__getitem__(indices)
504 return result
505
506 def do_tuple(self, node):
507 return tuple([self.evaluate(n) for n in node.elts])
508
509 def do_unaryop(self, node):
510 op = node.op.__class__.__name__.lower()
511 operand = self.evaluate(node.operand)
512 if op not in self.operators:
513 raise ValueError('unsupported operation: %r' % op)
514 return self.operators[op](operand)
515
516 evaluator = Evaluator
517
518 def lookup_eval(source, context, allow_imports=False):
519 return evaluator(context, allow_imports=allow_imports).evaluate(source, '<lo okup_eval>')
OLDNEW
« no previous file with comments | « Doc/library/ast.rst ('k') | Lib/logging/config.py » ('j') | no next file with comments »

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+