U
    NucT                  )   @   s@  d Z ddlZddlZddlZddlZddlmZ ejd dkZdZ	dZ
dZdd	gZd
ddgZeeeeeeeehZeedseedrdekree ered G dd deZG dd deZG dd deZG dd deZ G dd deZ!G dd deZ"G dd deZ#G dd de$Z%d d! Z&d"d# Z'd$d% Z(d&d' Z)ej*e)ej+ej,ej-e(ej.ej/ej0ej1ej2e'ej3ej4ej5ej6ej7ej8ej9ej:ej;ej<ej=ej>ej?ej@ejAejBejCejDejEejFejGd(d) ejHd*d) ejId+d) ejJd,d) iZKee&eLeMereNneOd-ZPd.d/dd0ZQd.ZRG d1d2 d2eSZTG d3d4 d4eTZUd7d5d6ZVdS )8a8  
SimpleEval - (C) 2013-2019 Daniel Fairhead
-------------------------------------

An short, easy to use, safe and reasonably extensible expression evaluator.
Designed for things like in a website where you want to allow the user to
generate a string, or a number from some other input, without allowing full
eval() or other unsafe or needlessly complex linguistics.

-------------------------------------

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

-------------------------------------

Initial idea copied from J.F. Sebastian on Stack Overflow
( http://stackoverflow.com/a/9558001/1973500 ) with
modifications and many improvements.

-------------------------------------
Contributors:
- corro (Robin Baumgartner) (py3k)
- dratchkov (David R) (nested dicts)
- marky1991 (Mark Young) (slicing)
- T045T (Nils Berg) (!=, py3kstr, obj.
- perkinslr (Logan Perkins) (.__globals__ or .func_ breakouts)
- impala2 (Kirill Stepanov) (massive _eval refactor)
- gk (ugik) (Other iterables than str can DOS too, and can be made)
- daveisfera (Dave Johansen) 'not' Boolean op, Pycharm, pep8, various other fixes
- xaled (Khalid Grandi) method chaining correctly, double-eval bugfix.
- EdwardBetts (Edward Betts) spelling correction.
- charlax (Charles-Axel Dein charlax) Makefile and cleanups
- mommothazaz123 (Andrew Zhu) f"string" support, Python 3.8 support
- lubieowoce (Uryga) various potential vulnerabilities
- JCavallo (Jean Cavallo) names dict shouldn't be modified
- Birne94 (Daniel Birnstiel) for fixing leaking generators.
- patricksurry (Patrick Surry) or should return last value, even if falsy.
- shughes-uk (Samantha Hughes) python w/o 'site' should not fail to import.

-------------------------------------
Basic Usage:

>>> s = SimpleEval()
>>> s.eval("20 + 30")
50

You can add your own functions easily too:

if file.txt contents is "11"

>>> def get_file():
...     with open("file.txt", 'r') as f:
...         return f.read()

>>> s.functions["get_file"] = get_file
>>> s.eval("int(get_file()) + 31")
42

For more information, see the full package documentation on pypi, or the github
repo.

-----------

If you don't need to re-use the evaluator (with it's names, functions, etc),
then you can use the simple_eval() function:

>>> simple_eval("21 + 19")
40

You can pass names, operators and functions to the simple_eval function as
well:

>>> simple_eval("40 + two", names={"two": 2})
42

    N)random   i i'  i 	= _Zfunc_format
format_mapmrohelp__contains__zDISALLOW_FUNCTIONS.add(exec)c                   @   s   e Zd ZdZdS )InvalidExpressionz Generic Exception N__name__
__module____qualname____doc__ r   r   :/tmp/pip-build-cspheihh/reportbro-simpleeval/simpleeval.pyr
      s   r
   c                       s    e Zd ZdZ fddZ  ZS )FunctionNotDefinedz% sorry! That function isn't defined! c                    s6   d ||| _t| d| || _tt| | j d S )Nz1Function '{0}' not defined, for expression '{1}'.	func_name)r   messagesetattr
expressionsuperr
   __init__)selfr   r   	__class__r   r   r      s     zFunctionNotDefined.__init__r   r   r   r   r   __classcell__r   r   r   r   r      s   r   c                       s    e Zd ZdZ fddZ  ZS )NameNotDefinedz a name isn't defined. c                    s0   || _ d||| _|| _tt| | j d S )Nz)'{0}' is not defined for expression '{1}')namer   r   r   r   r
   r   )r   r   r   r   r   r   r      s     zNameNotDefined.__init__r   r   r   r   r   r      s   r   c                   @   s   e Zd ZdZdd ZdS )AttributeDoesNotExistzattribute does not existc                 C   s   d ||| _|| _|| _d S )Nz2Attribute '{0}' does not exist in expression '{1}')r   r   attrr   )r   r!   r   r   r   r   r      s     zAttributeDoesNotExist.__init__N)r   r   r   r   r   r   r   r   r   r       s   r    c                   @   s   e Zd ZdZdS )FeatureNotAvailablez* What you're trying to do is not allowed. Nr   r   r   r   r   r"      s   r"   c                   @   s   e Zd ZdZdS )NumberTooHighzm Sorry! That number is too high. I don't want to spend the
        next 10 years evaluating this expression! Nr   r   r   r   r   r#      s   r#   c                   @   s   e Zd ZdZdS )IterableTooLongz* That iterable is **way** too long, baby. Nr   r   r   r   r   r$      s   r$   c                   @   s   e Zd ZdS )AssignmentAttemptedN)r   r   r   r   r   r   r   r%      s   r%   c                 C   s   t t |  S )z! return a random int below <top> )intr   )topr   r   r   
random_int   s    r(   c                 C   s0   t | tkst |tkr(td| || | S )zA a limited exponent/to-the-power-of function, for safety reasons z*Sorry! I don't want to evaluate {0} ** {1})abs	MAX_POWERr#   r   abr   r   r   
safe_power   s     r.   c                 C   sL   t | dr"|t|  tkr"tdt |drD| t| tkrDtd| | S )z: limit the number of times an iterable can be repeated... __len__z.Sorry, I will not evalute something that long.hasattrlenMAX_STRING_LENGTHr$   r+   r   r   r   	safe_mult   s
    r4   c                 C   s8   t | dr0t |dr0t| t| tkr0td| | S )z iterable length limit again r/   z?Sorry, adding those two together would make something too long.r0   r+   r   r   r   safe_add   s    r5   c                 C   s   t || S Nopcontainsxyr   r   r   <lambda>       r=   c                 C   s   t ||  S r6   r7   r:   r   r   r   r=      r>   c                 C   s   | |kS r6   r   r:   r   r   r   r=      r>   c                 C   s   | |k	S r6   r   r:   r   r   r   r=      r>   )Zrandrandintr&   floatstrTF)TrueFalseNonec                   @   s   e Zd ZdZdZd4ddZdd Zdd	 Zd
d Zdd Z	dd Z
dd Zedd Zedd Zedd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- Zd.d/ Zd0d1 Zd2d3 ZdS )5
SimpleEvalz{ A very simple expression parser.
        >>> s = SimpleEval()
        >>> s.eval("20 + 30 - ( 10 * 5)")
        0
         Nc              $   C   sZ  |st  }|st }|s$t }|| _|| _|| _tj| j	tj
| jtj| jtj| jtj| jtj| jtj| jtj| jtj| jtj| jtj| jtj| jtj | j!tj"| j#tj$| j%tj&| j'tj(| j)tj*| j+i| _,t-tdr| j.| j,tj/< t-tdr| j0| j,tj1< | j2| j,tj3< t-tdr&| j.| j,tj4< t5| _5| j6 D ]}|t7kr6t8d9|q6dS )z
            Create the evaluator instance.  Set up valid operators (+,-, etc)
            functions (add, random, get_val, whatever) and names. NameConstant	JoinedStrConstantz&This function {} is a really bad idea.N):DEFAULT_OPERATORScopyDEFAULT_FUNCTIONSDEFAULT_NAMES	operators	functionsnamesastZExpr
_eval_exprZAssign_eval_assignZ	AugAssign_eval_aug_assignZImport_eval_importZNum	_eval_numZStr	_eval_strName
_eval_nameZUnaryOp_eval_unaryopZBinOp_eval_binopZBoolOp_eval_boolopZCompare_eval_compareZIfExp_eval_ifexpZCall
_eval_callkeyword_eval_keywordZ	Subscript_eval_subscript	Attribute_eval_attributeIndex_eval_indexZSlice_eval_slicenodesr1   _eval_constantrG   _eval_joinedstrrH   _eval_formattedvalueZFormattedValuerI   ATTR_INDEX_FALLBACKvaluesDISALLOW_FUNCTIONSr"   r   )r   rN   rO   rP   fr   r   r   r     sr                      

zSimpleEval.__init__c                 C   s    || _ | t| jd S )zb evaluate an expresssion, using the operators, functions and
            names previously set up. r   )expr_evalrQ   parsestripbodyr   rp   r   r   r   evalR  s    zSimpleEval.evalc                 C   sD   z| j t| }W n( tk
r:   tdt|jY nX ||S )z> The internal evaluator used on each node in the parsed tree. z-Sorry, {0} is not available in this evaluator)rh   typeKeyErrorr"   r   r   )r   nodehandlerr   r   r   rq   ]  s    zSimpleEval._evalc                 C   s   |  |jS r6   rq   valuer   ry   r   r   r   rR   h  s    zSimpleEval._eval_exprc                 C   s    t d| jt | |jS Nz.Assignment ({}) attempted, but this is ignoredwarningswarnr   rp   r%   rq   r|   r}   r   r   r   rS   k  s    zSimpleEval._eval_assignc                 C   s    t d| jt | |jS r~   r   r}   r   r   r   rT   o  s    zSimpleEval._eval_aug_assignc                 C   s   t d| |jS )NzSorry, 'import' is not allowed.)r"   rq   r|   r}   r   r   r   rU   s  s    zSimpleEval._eval_importc                 C   s   | j S r6   )nry   r   r   r   rV   w  s    zSimpleEval._eval_numc                 C   s*   t | jtkr$tdt | jt| jS )Nz?String Literal in statement is too long! ({0}, when {1} is max))r2   sr3   r$   r   r   r   r   r   rW   {  s     zSimpleEval._eval_strc                 C   s6   t | jdr0t| jtkr0tdt| jt| jS )Nr/   z8Literal in statement is too long! ({0}, when {1} is max))r1   r|   r2   r3   r$   r   r   r   r   r   ri     s     zSimpleEval._eval_constantc                 C   s   | j t|j | |jS r6   )rN   rw   r8   rq   Zoperandr}   r   r   r   rZ     s    zSimpleEval._eval_unaryopc                 C   s&   | j t|j | |j| |jS r6   )rN   rw   r8   rq   leftrightr}   r   r   r   r[     s    
zSimpleEval._eval_binopc                 C   sp   t |jtjr8d}|jD ]}| |}|s|  S q|S t |jtjrl|jD ]}| |}|rL|  S qL|S d S )NF)
isinstancer8   rQ   Andrm   rq   Or)r   ry   Zvoutr|   r   r   r   r\     s    





zSimpleEval._eval_boolopc                 C   sV   |  |j}d}t|j|jD ]2\}}|s. qR|}|  |}| jt| ||}q|S )NT)rq   r   zipopsZcomparatorsrN   rw   )r   ry   r   	to_returnZ	operationcompr   r   r   r   r]     s    
zSimpleEval._eval_comparec                 C   s$   |  |jr|  |jS |  |jS r6   )rq   testrt   Zorelser}   r   r   r   r^     s    
zSimpleEval._eval_ifexpc              
      s   t |jtjr |j}npz j|jj }W nL tk
rR   t|jj j	Y n* t
k
rz } ztdW 5 d }~X Y nX |tkrtd| fdd|jD t fdd|jD S )Nz Lambda Functions not implementedzThis function is forbiddenc                 3   s   | ]}  |V  qd S r6   rq   ).0r,   r   r   r   	<genexpr>  s     z(SimpleEval._eval_call.<locals>.<genexpr>c                 3   s   | ]}  |V  qd S r6   r   )r   kr   r   r   r     s     )r   funcrQ   rc   rq   rO   idrx   r   rp   AttributeErrorr"   rn   argsdictkeywords)r   ry   r   er   r   r   r_     s    zSimpleEval._eval_callc                 C   s   |j | |jfS r6   )argrq   r|   r}   r   r   r   ra     s    zSimpleEval._eval_keywordc                 C   s   zDt | jdr| j|j W S t| jr2| |W S td|jW n> tk
r   |j| jkrp| j|j  Y S t|j| j	Y nX d S )N__getitem__zITrying to use name (variable) "{0}" when no "names" defined for evaluator)
r1   rP   r   callabler
   r   rx   rO   r   rp   r}   r   r   r   rY     s    

zSimpleEval._eval_namec                 C   s>   |  |j}|  |j}z
|| W S  tk
r8    Y nX d S r6   )rq   r|   slicerx   )r   ry   	containerkeyr   r   r   rb     s    
zSimpleEval._eval_subscriptc              	   C   s   t D ] }|j|rtd|jq|jtkr@td|j| |j}zt||jW S  t	t
fk
rr   Y nX | jrz||j W S  tt
fk
r   Y nX t|j| jd S )NzJSorry, access to __attributes  or func_ attributes is not available. ({0})z*Sorry, this method is not available. ({0}))DISALLOW_PREFIXESr!   
startswithr"   r   DISALLOW_METHODSrq   r|   getattrr   	TypeErrorrl   rx   r    rp   )r   ry   prefixZnode_evaluatedr   r   r   rd     s0    
zSimpleEval._eval_attributec                 C   s   |  |jS r6   r{   r}   r   r   r   rf     s    zSimpleEval._eval_indexc                 C   sZ   d  } }}|j d k	r"| |j }|jd k	r8| |j}|jd k	rN| |j}t|||S r6   )lowerrq   upperstepr   )r   ry   r   r   r   r   r   r   rg     s    


zSimpleEval._eval_slicec                 C   sN   d}g }|j D ]4}t| |}t|| tkr8td|| qd|S )Nr   z/Sorry, I will not evaluate something this long.rF   )rm   rA   rq   r2   r3   r$   appendjoin)r   ry   lengthZevaluated_valuesr   valr   r   r   rj     s    
zSimpleEval._eval_joinedstrc                 C   s8   |j r,d| |j  d }|| |jS | |jS )Nz{:})format_specrq   r   r|   )r   ry   fmtr   r   r   rk     s    zSimpleEval._eval_formattedvalue)NNN)r   r   r   r   rp   r   rv   rq   rR   rS   rT   rU   staticmethodrV   rW   ri   rZ   r[   r\   r]   r^   r_   ra   rY   rb   rd   rf   rg   rj   rk   r   r   r   r   rE     s:   
=




rE   c                       sV   e Zd ZdZd fdd	Z fddZdd Zd	d
 Zdd Zdd Z	dd Z
  ZS )EvalWithCompoundTypesz
        SimpleEval with additional Compound Types, and their respective
        function editions. (list, tuple, dict, set).
    Nc                    sh   t t| ||| | jjttttd | j	t
j| jt
j| jt
j| jt
j| jt
j| jt
j| ji d S )N)listtupler   set)r   r   r   rO   updater   r   r   r   rh   rQ   Dict
_eval_dictZTuple_eval_tupleZList
_eval_listSet	_eval_setZListComp_eval_comprehensionZGeneratorExp)r   rN   rO   rP   r   r   r   r   %  s*          zEvalWithCompoundTypes.__init__c                    s   d| _ tt| |S )Nr   )
_max_countr   r   rv   ru   r   r   r   rv   7  s    zEvalWithCompoundTypes.evalc                    s    fddt |j|jD S )Nc                    s"   i | ]\}}  |  |qS r   r   )r   r   vr   r   r   
<dictcomp><  s    z4EvalWithCompoundTypes._eval_dict.<locals>.<dictcomp>)r   keysrm   r}   r   r   r   r   ;  s    
z EvalWithCompoundTypes._eval_dictc                    s   t  fdd|jD S )Nc                 3   s   | ]}  |V  qd S r6   r   r   r;   r   r   r   r   @  s     z4EvalWithCompoundTypes._eval_tuple.<locals>.<genexpr>)r   eltsr}   r   r   r   r   ?  s    z!EvalWithCompoundTypes._eval_tuplec                    s   t  fdd|jD S )Nc                 3   s   | ]}  |V  qd S r6   r   r   r   r   r   r   C  s     z3EvalWithCompoundTypes._eval_list.<locals>.<genexpr>)r   r   r}   r   r   r   r   B  s    z EvalWithCompoundTypes._eval_listc                    s   t  fdd|jD S )Nc                 3   s   | ]}  |V  qd S r6   r   r   r   r   r   r   F  s     z2EvalWithCompoundTypes._eval_set.<locals>.<genexpr>)r   r   r}   r   r   r   r   E  s    zEvalWithCompoundTypes._eval_setc              
      s|   g i j tj fdd}j tj|i fddd fdd	 z
   W 5 j tji X S )	Nc                    s   | j  kr | j  S | S )zX
                Here we hide our extra scope for within this comprehension
            )r   r   )extra_namesprevious_name_evallerr   r   eval_names_extraO  s    

zCEvalWithCompoundTypes._eval_comprehension.<locals>.eval_names_extrac                    s<   t | tjr| | j< n t| j|D ]\}}|| q$dS )z
                Recursively (enter, (into, (nested, name), unpacking)) =                              and, (assign, (values, to), each
            N)r   rQ   rX   r   r   r   )targetr|   tr   )r   recurse_targetsr   r   r   Y  s    zBEvalWithCompoundTypes._eval_comprehension.<locals>.recurse_targetsr   c                    s   j |  }|jD ]z} jd7  _jtkr:td|j| tfdd|jD rt	j | d kr~ | d  q
j qd S )N   z)Comprehension generates too many elementsc                 3   s   | ]}  |V  qd S r6   r   )r   Ziffr   r   r   r   l  s     zREvalWithCompoundTypes._eval_comprehension.<locals>.do_generator.<locals>.<genexpr>)
generatorsrq   iterr   MAX_COMPREHENSION_LENGTHr$   r   allZifsr2   r   elt)Zgigi)do_generatorry   r   r   r   r   r   r   d  s    

z?EvalWithCompoundTypes._eval_comprehension.<locals>.do_generator)r   )rh   rQ   rX   r   )r   ry   r   r   )r   r   ry   r   r   r   r   r   r   H  s    
z)EvalWithCompoundTypes._eval_comprehension)NNN)r   r   r   r   r   rv   r   r   r   r   r   r   r   r   r   r   r     s   r   c                 C   s   t |||d}|| S )z  Simply evaluate an expresssion )rN   rO   rP   )rE   rv   )rp   rN   rO   rP   r   r   r   r   simple_evalz  s
    r   )NNN)Wr   rQ   operatorr8   sysr   r   version_infoZPYTHON3r3   r   r*   r   r   rw   r   rv   r   r   reprcompileopenrn   r1   __builtins__addr   exec	Exceptionr
   r   r   r    r"   r#   r$   UserWarningr%   r(   r.   r4   r5   ZAddZSubsubZMultZDivtruedivZFloorDivfloordivZPowZModmodZEqeqZNotEqneZGtgtZLtltZGtEgeZLtEleZNotnot_ZUSubnegZUAddposZInZNotInZIsZIsNotrJ   r&   r@   rA   unicoderL   rM   rl   objectrE   r   r   r   r   r   r   <module>   s   ]

       

	                          [