python-pure-eval-help-0.2.2-1.oe24090>    f ;G|`u`  *5*eR`k΃sw#~BO 7~vMj %CbLn+`<1Zh-k ™vd{_ _2;R5"MF2hBWl-Y:#0|F]8ޞD ac@q3n PF3˒3̔oAVAǰmEyBF 7CtgL <Ŵ> 'EXWˆ?jE"} }5xq4Kz"i'Ա=:o2 .1l^Q鏂@$K@* Õ3mԢ* "*֍0 I% (  )zi]{Mc&7 jEvx\n4Iw ,fẞcvR43124f2900a8fd07041a1a73881991c0918876b06eaf4845312b5742cdd2b4302735b097877b15240431a055a6a49ec328487d38kUݱ}3# ˫>:?d ' X       @Dp(89 :<FUGtHxI|XY\]^bdefltuvz@DCpython-pure-eval-help0.2.21.oe2409Development documents and examples for pure-eval [![Build Status](https://travis-ci.org/alexmojaki/pure_eval.svg?branch=master)](https://travis-ci.org/alexmojaki/pure_eval) [![Coverage Status](https://coveralls.io/repos/github/alexmojaki/pure_eval/badge.svg?branch=master)](https://coveralls.io/github/alexmojaki/pure_eval?branch=master) [![Supports Python versions 3.5+](https://img.shields.io/pypi/pyversions/pure_eval.svg)](https://pypi.python.org/pypi/pure_eval) This is a Python package that lets you safely evaluate certain AST nodes without triggering arbitrary code that may have unwanted side effects. It can be installed from PyPI: pip install pure_eval To demonstrate usage, suppose we have an object defined as follows: ```python class Rectangle: def __init__(self, width, height): self.width = width self.height = height @property def area(self): print("Calculating area...") return self.width * self.height rect = Rectangle(3, 5) ``` Given the `rect` object, we want to evaluate whatever expressions we can in this source code: ```python source = "(rect.width, rect.height, rect.area)" ``` This library works with the AST, so let's parse the source code and peek inside: ```python import ast tree = ast.parse(source) the_tuple = tree.body[0].value for node in the_tuple.elts: print(ast.dump(node)) ``` Output: ```python Attribute(value=Name(id='rect', ctx=Load()), attr='width', ctx=Load()) Attribute(value=Name(id='rect', ctx=Load()), attr='height', ctx=Load()) Attribute(value=Name(id='rect', ctx=Load()), attr='area', ctx=Load()) ``` Now to actually use the library. First construct an Evaluator: ```python from pure_eval import Evaluator evaluator = Evaluator({"rect": rect}) ``` The argument to `Evaluator` should be a mapping from variable names to their values. Or if you have access to the stack frame where `rect` is defined, you can instead use: ```python evaluator = Evaluator.from_frame(frame) ``` Now to evaluate some nodes, using `evaluator[node]`: ```python print("rect.width:", evaluator[the_tuple.elts[0]]) print("rect:", evaluator[the_tuple.elts[0].value]) ``` Output: ``` rect.width: 3 rect: <__main__.Rectangle object at 0x105b0dd30> ``` OK, but you could have done the same thing with `eval`. The useful part is that it will refuse to evaluate the property `rect.area` because that would trigger unknown code. If we try, it'll raise a `CannotEval` exception. ```python from pure_eval import CannotEval try: print("rect.area:", evaluator[the_tuple.elts[2]]) # fails except CannotEval as e: print(e) # prints CannotEval ``` To find all the expressions that can be evaluated in a tree: ```python for node, value in evaluator.find_expressions(tree): print(ast.dump(node), value) ``` Output: ```python Attribute(value=Name(id='rect', ctx=Load()), attr='width', ctx=Load()) 3 Attribute(value=Name(id='rect', ctx=Load()), attr='height', ctx=Load()) 5 Name(id='rect', ctx=Load()) <__main__.Rectangle object at 0x105568d30> Name(id='rect', ctx=Load()) <__main__.Rectangle object at 0x105568d30> Name(id='rect', ctx=Load()) <__main__.Rectangle object at 0x105568d30> ``` Note that this includes `rect` three times, once for each appearance in the source code. Since all these nodes are equivalent, we can group them together: ```python from pure_eval import group_expressions for nodes, values in group_expressions(evaluator.find_expressions(tree)): print(len(nodes), "nodes with value:", values) ``` Output: ``` 1 nodes with value: 3 1 nodes with value: 5 3 nodes with value: <__main__.Rectangle object at 0x10d374d30> ``` If we want to list all the expressions in a tree, we may want to filter out certain expressions whose values are obvious. For example, suppose we have a function `foo`: ```python def foo(): pass ``` If we refer to `foo` by its name as usual, then that's not interesting: ```python from pure_eval import is_expression_interesting node = ast.parse('foo').body[0].value print(ast.dump(node)) print(is_expression_interesting(node, foo)) ``` Output: ```python Name(id='foo', ctx=Load()) False ``` But if we refer to it by a different name, then it's interesting: ```python node = ast.parse('bar').body[0].value print(ast.dump(node)) print(is_expression_interesting(node, foo)) ``` Output: ```python Name(id='bar', ctx=Load()) True ``` In general `is_expression_interesting` returns False for the following values: - Literals (e.g. `123`, `'abc'`, `[1, 2, 3]`, `{'a': (), 'b': ([1, 2], [3])}`) - Variables or attributes whose name is equal to the value's `__name__`, such as `foo` above or `self.foo` if it was a method. - Builtins (e.g. `len`) referred to by their usual name. To make things easier, you can combine finding expressions, grouping them, and filtering out the obvious ones with: ```python evaluator.interesting_expressions_grouped(root) ``` To get the source code of an AST node, I recommend [asttokens](https://github.com/gristlabs/asttokens). Here's a complete example that brings it all together: ```python from asttokens import ASTTokens from pure_eval import Evaluator source = """ x = 1 d = {x: 2} y = d[x] """ names = {} exec(source, names) atok = ASTTokens(source, parse=True) for nodes, value in Evaluator(names).interesting_expressions_grouped(atok.tree): print(atok.get_text(nodes[0]), "=", value) ``` Output: ```python x = 1 d = {1: 2} y = 2 d[x] = 2 ```fgdc-64g.compass-ciMIThttp://openeuler.orgUnspecifiedhttp://github.com/alexmojaki/pure_evallinuxnoarchAforootrootpython-pure-eval-0.2.2-1.oe2409.src.rpmpython-pure-eval-helppython3-pure-eval-doc    rpmlib(CompressedFileNames)rpmlib(FileDigests)rpmlib(PayloadFilesHavePrefix)rpmlib(PayloadIsXz)3.0.4-14.6.0-14.0-15.2-14.18.2dgdPython_Bot - 0.2.2-1- Package Spec generateddc-64g.compass-ci 17269392390.2.2-1.oe2409python-pure-eval/usr/share/doc/-O2 -g -grecord-gcc-switches -pipe -fstack-protector-strong -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/generic-hardened-cc1 -fasynchronous-unwind-tables -fstack-clash-protectioncpioxz2noarch-openEuler-linux-gnudirectory/©ބ:Xutf-8798db767a2a0523e00aa3ff4336199a9a0b3533f642cea8c0f9e1b941604ef0d765a84d56cddbbf0bae7e11e49fcab049287b93b5309ec23313ac5bbc084d602?`7zXZ !#, [] b2u jӫ`(y0&ac8@DSrshvZze `rF.!8/ 1PRk'aHbѬݘ}ϻqvZlݻI;S #1:Żص YZ