o
    8DiBb                     @   s  d Z ddlZddlZddlZddlZddlmZ dZdZdZ	dZ
eejjZddgZg d	Zeeeeeeeeeh	Zeed
sGeedrLd
ev rLee 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'G dd de(Z)G dd de(Z*d d! Z+d"d# Z,d$d% Z-d&d' Z.d(d) Z/d*d+ Z0i ej1e.ej2ej3ej4e-ej5ej6ej7ej8ej9e/ej:e0ej;e,ej<ej=ej>ej?ej@ejAejBejCejDejEejFejGejHejIejJejKejLejMejNejOejPejQejRejSejTejUejVejWejXd,d- ejYd.d- ejZd/d- ej[d0d- i	Z\ee+ee]e^d1Z_d2d3dd4Z`d2ZaG d5d6 d6ebZcG d7d8 d8ecZdd;d9d:ZedS )<u8  
SimpleEval - (C) 2013-2024 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, star expressions
- patricksurry (Patrick Surry) or should return last value, even if falsy.
- shughes-uk (Samantha Hughes) python w/o 'site' should not fail to import.
- KOLANICH packaging / deployment / setup help & << + >> & other bit ops
- graingert (Thomas Grainger) packaging / deployment / setup help
- bozokopic (Bozo Kopic) Memory leak fix
- daxamin (Dax Amin) Better error for attempting to eval empty string
- smurfix (Matthias Urlichs) Allow clearing functions / operators / etc completely
- koenigsley (Mikhail Yeremeyev) documentation typos correction.
- kurtmckee (Kurt McKee) Infrastructure updates
- edgarrmondragon (Edgar Ramírez-Mondragón) Address Python 3.12+ deprecation warnings
- cedk (Cédric Krier) <ced@b2ck.com> Allow running tests with Werror
- decorator-factory <decorator-factory@protonmail.com> More security fixes
- lkruitwagen (Lucas Kruitwagen) Adding support for dict comprehensions

-------------------------------------
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)randomi i'  i 	= _func_)format
format_mapmrotb_framegi_frameag_framecr_frameexechelp__contains__c                   @      e Zd ZdZdS )InvalidExpressionzGeneric ExceptionN__name__
__module____qualname____doc__ r   r   C/var/www/Datamplify/venv/lib/python3.10/site-packages/simpleeval.pyr          r   c                           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          r   c                       r   )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'      r&   r'   c                       r   )AttributeDoesNotExistzattribute does not existc                    0   d ||| _|| _|| _tt| | j d S )Nz2Attribute '{0}' does not exist in expression '{1}'r   r   attrr   r   r   r    r!   r,   r   r"   r   r   r       s   zAttributeDoesNotExist.__init__r$   r   r   r"   r   r)      r&   r)   c                       r   )OperatorNotDefinedzoperator does not existc                    r*   )Nz1Operator '{0}' does not exist in expression '{1}'r+   r-   r"   r   r   r       s   zOperatorNotDefined.__init__r$   r   r   r"   r   r.      r&   r.   c                   @   r   )FeatureNotAvailablez(What you're trying to do is not allowed.Nr   r   r   r   r   r/      r   r/   c                   @   r   )NumberTooHighzgSorry! That number is too high. I don't want to spend the
    next 10 years evaluating this expression!Nr   r   r   r   r   r0      s    r0   c                   @   r   )IterableTooLongz(That iterable is **way** too long, baby.Nr   r   r   r   r   r1      r   r1   c                   @   r   )AssignmentAttemptedz$Assignment not allowed in SimpleEvalNr   r   r   r   r   r2      r   r2   c                   @   r   )MultipleExpressionsz-Only the first expression parsed will be usedNr   r   r   r   r   r3      r   r3   c                 C   s   t t |  S )zreturn a random int below <top>)intr   )topr   r   r   
random_int   s   r6   c                 C   s0   t | tkst |tkrtd| || | S )z?a limited exponent/to-the-power-of function, for safety reasonsz*Sorry! I don't want to evaluate {0} ** {1})abs	MAX_POWERr0   r   abr   r   r   
safe_power   s   r<   c                 C   sL   t | dr|t|  tkrtdt |dr"| t| tkr"td| | S )z8limit the number of times an iterable can be repeated...__len__z/Sorry, I will not evaluate something that long.hasattrlenMAX_STRING_LENGTHr1   r9   r   r   r   	safe_mult   s
   rB   c                 C   s8   t | drt |drt| t| tkrtd| | S )ziterable length limit againr=   z?Sorry, adding those two together would make something too long.r>   r9   r   r   r   safe_add  s   rC   c                 C   s0   t |tkst | tkrtd| || |? S )zrshift, but with input limitsz*Sorry! I don't want to evaluate {0} >> {1}r7   	MAX_SHIFTMAX_SHIFT_BASEr0   r   r9   r   r   r   safe_rshift     rG   c                 C   s0   t |tkst | tkrtd| || |> S )zlshift, but with input limitsz*Sorry! I don't want to evaluate {0} << {1}rD   r9   r   r   r   safe_lshift  rH   rI   c                 C   s   t || S Nopcontainsxyr   r   r   <lambda>;  s    rQ   c                 C   s   t ||  S rJ   rK   rN   r   r   r   rQ   <  s    c                 C   s   | |u S rJ   r   rN   r   r   r   rQ   =      c                 C   s   | |uS rJ   r   rN   r   r   r   rQ   >  rR   )randrandintr4   floatstrTF)TrueFalseNonec                   @   s   e Zd ZdZdZd8ddZdd Zedd	 Zd9d
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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d0d1 Zd2d3 Zd4d5 Zd6d7 ZdS ):
SimpleEvalzjA very simple expression parser.
    >>> s = SimpleEval()
    >>> s.eval("20 + 30 - ( 10 * 5)")
    0
     Nc                 C   s  |du rt  }|du rt }|du rt }|| _|| _|| _i 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+tj,| j-i| _.t/0 7 t/1d t2tdd }r| j3| j.|< t2tdd }r| j4| j.|< t2tdd }r| j-| j.|< W d   n1 sw   Y  t5| _5| j6 D ]}|t7v rt8d9|qdS )z
        Create the evaluator instance.  Set up valid operators (+,-, etc)
        functions (add, random, get_val, whatever) and names.NignoreNumStrNameConstantz&This function {} is a really bad idea.):DEFAULT_OPERATORScopyDEFAULT_FUNCTIONSDEFAULT_NAMES	operators	functionsnamesastExpr
_eval_exprAssign_eval_assign	AugAssign_eval_aug_assignImport_eval_importName
_eval_nameUnaryOp_eval_unaryopBinOp_eval_binopBoolOp_eval_boolopCompare_eval_compareIfExp_eval_ifexpCall
_eval_callkeyword_eval_keyword	Subscript_eval_subscript	Attribute_eval_attributeIndex_eval_indexSlice_eval_slice	JoinedStr_eval_joinedstrFormattedValue_eval_formattedvalueConstant_eval_constantnodeswarningscatch_warningssimplefiltergetattr	_eval_num	_eval_strATTR_INDEX_FALLBACKvaluesDISALLOW_FUNCTIONSr/   r   )r!   rd   re   rf   r]   r^   r_   fr   r   r   r    [  s~   	


zSimpleEval.__init__c                 C   s
   d | _ d S rJ   )r   r!   r   r   r   __del__  s   
zSimpleEval.__del__c                 C   sF   t |  }|jstdt|jdkrtd| t	 |jd S )z$parse an expression into a node treez#Sorry, cannot evaluate empty string   z@'{}' contains multiple expressions. Only the first will be used.r   )
rg   parsestripbodyr   r@   r   warnr   r3   )exprparsedr   r   r   r     s   
zSimpleEval.parsec                 C   s   || _ | |p| |S )z[evaluate an expression, using the operators, functions and
        names previously set up.)r   _evalr   r!   r   previously_parsedr   r   r   eval  s   zSimpleEval.evalc                 C   s<   z| j t| }W ||S  ty   tdt|jw )z<The internal evaluator used on each node in the parsed tree.z-Sorry, {0} is not available in this evaluator)r   typeKeyErrorr/   r   r   )r!   nodehandlerr   r   r   r     s   zSimpleEval._evalc                 C      |  |jS rJ   r   valuer!   r   r   r   r   ri        zSimpleEval._eval_exprc                 C       t d| jt | |jS Nz.Assignment ({}) attempted, but this is ignoredr   r   r   r   r2   r   r   r   r   r   r   rk        zSimpleEval._eval_assignc                 C   r   r   r   r   r   r   r   rm     r   zSimpleEval._eval_aug_assignc                 C   s   t d)NzSorry, 'import' is not allowed.)r/   r   r   r   r   ro     s   zSimpleEval._eval_importc                 C   s   | j S rJ   )nr   r   r   r   r     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))r@   srA   r1   r   r   r   r   r   r     s   
zSimpleEval._eval_strc                 C   s6   t | jdrt| jtkrtdt| jt| jS )Nr=   z8Literal in statement is too long! ({0}, when {1} is max))r?   r   r@   rA   r1   r   r   r   r   r   r     s   
zSimpleEval._eval_constantc                 C   sB   z
| j t|j }W n ty   t|j| jw || |jS rJ   )rd   r   rL   r   r.   r   r   operandr!   r   operatorr   r   r   rs     s   zSimpleEval._eval_unaryopc                 C   sL   z
| j t|j }W n ty   t|j| jw || |j| |jS rJ   )	rd   r   rL   r   r.   r   r   leftrightr   r   r   r   ru     s   zSimpleEval._eval_binopc                 C   sh   d}t |jtjr|jD ]}| |}|s |S q|S t |jtjr2|jD ]}| |}|r1 |S q%|S )NF)
isinstancerL   rg   Andr   r   Or)r!   r   	to_returnr   r   r   r   rw     s"   



zSimpleEval._eval_boolopc                 C   sX   |  |j}d}t|j|jD ]\}}|s |S |}|  |}| jt| ||}q|S )NT)r   r   zipopscomparatorsrd   r   )r!   r   r   r   	operationcompr   r   r   r   ry     s   
zSimpleEval._eval_comparec                 C   s$   |  |jr|  |jS |  |jS rJ   )r   testr   orelser   r   r   r   r{     s   $zSimpleEval._eval_ifexpc                    s   t |jtjr |j}n+z	 j|jj }W n ty&   t|jj j	 t
y0   tdw |tv r9td| fdd|jD i t fdd|jD S )Nz Lambda Functions not implementedzThis function is forbiddenc                 3       | ]}  |V  qd S rJ   r   ).0r:   r   r   r   	<genexpr>#      z(SimpleEval._eval_call.<locals>.<genexpr>c                 3   r   rJ   r   )r   kr   r   r   r   #  r   )r   funcrg   r   r   re   idr   r   r   AttributeErrorr/   r   argsdictkeywords)r!   r   r   r   r   r   r}     s    zSimpleEval._eval_callc                 C   s   |j | |jfS rJ   )argr   r   r   r   r   r   r   &  s   zSimpleEval._eval_keywordc              	   C   s   z| j |j W S  ttfy   Y nw t| j r(z|  |W S  ty'   Y nw t| j ds6td|j|j| j	v rB| j	|j S t|j| j
)N__getitem__zITrying to use name (variable) "{0}" when no "names" defined for evaluator)rf   r   	TypeErrorr   callabler'   r?   r   r   re   r   r   r   r   r   rq   )  s&   
zSimpleEval._eval_namec                 C   s    |  |j}|  |j}|| S rJ   )r   r   slice)r!   r   	containerkeyr   r   r   r   F  s   zSimpleEval._eval_subscriptc              	   C   s   t D ]}|j|rtd|jq|jtv r td|j| |j}zt||jW S  t	t
fy8   Y nw | jrNz||j W S  tt
fyM   Y nw t|j| j)NzJSorry, access to __attributes  or func_ attributes is not available. ({0})z*Sorry, this method is not available. ({0}))DISALLOW_PREFIXESr,   
startswithr/   r   DISALLOW_METHODSr   r   r   r   r   r   r   r)   r   )r!   r   prefixnode_evaluatedr   r   r   r   M  s0   

zSimpleEval._eval_attributec                 C   r   rJ   r   r   r   r   r   r   l  r   zSimpleEval._eval_indexc                 C   sZ   d  } }}|j d ur| |j }|jd ur| |j}|jd ur'| |j}t|||S rJ   )lowerr   upperstepr   )r!   r   r   r   r   r   r   r   r   o  s   


zSimpleEval._eval_slicec                 C   sN   d}g }|j D ]}t| |}t|| tkrtd|| qd|S )Nr   z/Sorry, I will not evaluate something this long.r[   )r   rV   r   r@   rA   r1   appendjoin)r!   r   lengthevaluated_valuesr   valr   r   r   r   y  s   

zSimpleEval._eval_joinedstrc                 C   s8   |j rd| |j  d }|| |jS | |jS )Nz{:})format_specr   r   r   )r!   r   fmtr   r   r   r     s   zSimpleEval._eval_formattedvalueNNNrJ   ) r   r   r   r   r   r    r   staticmethodr   r   r   ri   rk   rm   ro   r   r   r   rs   ru   rw   ry   r{   r}   r   rq   r   r   r   r   r   r   r   r   r   r   rZ   R  sD    
=

	


	
	

rZ   c                       s\   e Zd ZdZdZd fdd	Zd fdd	Zdd	 Zd
d Zdd Z	dd Z
dd Z  ZS )EvalWithCompoundTypeszz
    SimpleEval with additional Compound Types, and their respective
    function editions. (list, tuple, dict, set).
    r   Nc                    sp   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t
j| ji d S )N)listtupler   set)r   r   r    re   updater   r   r   r   r   rg   Dict
_eval_dictTuple_eval_tupleList
_eval_listSet	_eval_setListComp_eval_comprehensionGeneratorExpDictComp)r!   rd   re   rf   r"   r   r   r      s   zEvalWithCompoundTypes.__init__c                    s   d| _ tt| ||S )Nr   )
_max_countr   r   r   r   r"   r   r   r     s   zEvalWithCompoundTypes.evalc                 C   sN   i }t |j|jD ]\}}|d u r|| | q	| ||| |< q	|S rJ   )r   keysr   r   r   )r!   r   resultr   r   r   r   r   r     s   z EvalWithCompoundTypes._eval_dictc                 C   sD   g }|j D ]}t|tjr|| |j q|| | q|S rJ   )eltsr   rg   Starredextendr   r   r   )r!   r   r   itemr   r   r   r     s   
z EvalWithCompoundTypes._eval_listc                       t  fdd|jD S )Nc                 3   r   rJ   r   r   rO   r   r   r   r     r   z4EvalWithCompoundTypes._eval_tuple.<locals>.<genexpr>)r   r   r   r   r   r   r        z!EvalWithCompoundTypes._eval_tuplec                    r  )Nc                 3   r   rJ   r   r  r   r   r   r     r   z2EvalWithCompoundTypes._eval_set.<locals>.<genexpr>)r   r   r   r   r   r   r     r  zEvalWithCompoundTypes._eval_setc              
      s   t tjr	i ng i jtj fdd}jtj|i fddd fdd	 z   W jtji S jtji w )	Nc                    s   | j  v r
 | j  S | S )zT
            Here we hide our extra scope for within this comprehension
            )r   r   )extra_namesprevious_name_evallerr   r   eval_names_extra  s   

zCEvalWithCompoundTypes._eval_comprehension.<locals>.eval_names_extrac                    s>   t | tjr| | j< dS t| j|D ]	\}}|| qdS )z
                Recursively (enter, (into, (nested, name), unpacking)) =                              and, (assign, (values, to), each
            N)r   rg   rp   r   r   r   )targetr   tv)r  recurse_targetsr   r   r    s
   zBEvalWithCompoundTypes._eval_comprehension.<locals>.recurse_targetsr   c                    s   j |  }|jD ]T} jd7  _jtkrtd|j| tfdd|jD r_t	j | d kr? | d  qt
trQjj< qt
tr_j qd S )Nr   z)Comprehension generates too many elementsc                 3   r   rJ   r   )r   iffr   r   r   r     r   zREvalWithCompoundTypes._eval_comprehension.<locals>.do_generator.<locals>.<genexpr>)
generatorsr   iterr   MAX_COMPREHENSION_LENGTHr1   r	  allifsr@   r   r   r   r   r   r   elt)gigi)do_generatorr   r  r!   r   r   r   r    s   



z?EvalWithCompoundTypes._eval_comprehension.<locals>.do_generator)r   )r   rg   r   r   rp   r   )r!   r   r  r   )r  r  r   r  r  r!   r   r   r     s   z)EvalWithCompoundTypes._eval_comprehensionr   rJ   )r   r   r   r   r   r    r   r   r   r   r   r   r%   r   r   r"   r   r     s    r   c                 C   s   t |||d}|| S )zSimply evaluate an expression)rd   re   rf   )rZ   r   )r   rd   re   rf   r   r   r   r   simple_eval  s   
r  r   )fr   rg   r   rL   sysr   r   rA   r  r8   rE   r4   
float_infomaxrF   r   r   r   r   r   r   r   reprcompileopenr   r   r?   __builtins__addr   	Exceptionr   r   r'   r)   r.   r/   r0   r1   UserWarningr2   r3   r6   r<   rB   rC   rG   rI   AddSubsubMultDivtruedivFloorDivfloordivRShiftLShiftPowModmodEqeqNotEqneGtgtLtltGtEgeLtEleNotnot_USubnegUAddposBitXorxorBitOror_BitAndand_InvertinvertInNotInIsIsNotr`   rU   rV   rb   rc   r   objectrZ   r   r  r   r   r   r   <module>   s    h



	




  :s