
    +#hnd                         d dl Z d dlZd dlZd dlZd dlZd dlZd dlmZ d dlmZm	Z	m
Z
mZmZmZ  G d de      Z G d d      Z G d d	e      Z G d
 de      Zy)    N)Mapping)AnyDictListOptionalSetTuplec                       e Zd ZdZy)InterpreterErrorzAn error raised when the interpreter cannot evaluate a Python
    expression, due to syntax error or unsupported operations.
    N)__name__
__module____qualname____doc__     _/var/www/html/sandstorm/venv/lib/python3.12/site-packages/dspy/primitives/python_interpreter.pyr   r      s     	r   r   c                   ~   e Zd ZdZ	 d-deeef   deee      ddfdZ		 	 	 d.dedeeeef      d	eeeef      d
e
def
dZd/dZej                  dej                   defd       Zdej$                  defdZdej(                  defdZdej,                  defdZdej0                  fdZdej4                  fdZdej8                  fdZd Zdej>                  fdZ dejB                  fd Z"d!ejF                  ddfd"Z$d#ejJ                  fd$Z&d%efd&Z'd'ejP                  fd(Z)d)ejT                  fd*Z+d+edefd,Z,y)0PythonInterpreteraU  A customized python interpreter to control the execution of
    LLM-generated codes. The interpreter makes sure the code can only execute
    functions given in action space and import white list. It also supports
    fuzzy variable matching to receive uncertain input variable name.

    .. highlight:: none

    This class is adapted from the Camel adaptation https://github.com/camel-ai/
    camel/blob/9a9d71874944e9736c55cdaed3df469a8becec05/camel/utils/python_interpreter.py 
    which adapts from the hugging face implementation `python_interpreter.py 
    <https://github.com/huggingface/transformers/blob/8f093fb799246f7dd9104ff44728da0c53a9f67a
    /src/transformers/tools/python_interpreter.py>`_. The original license applies::

        Copyright 2023 The HuggingFace Inc. team. All rights reserved.

        Licensed under the Apache License, Version 2.0 (the "License");
        you may not use this file except in compliance with the License.
        You may obtain a copy of the License at

            http://www.apache.org/licenses/LICENSE-2.0

        Unless required by applicable law or agreed to in writing, software
        distributed under the License is distributed on an "AS IS" BASIS,
        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
        implied. See the License for the specific language governing
        permissions and limitations under the License.

    Camel's modifications:
    "We have modified the original code to suit our requirements. We have
    encapsulated the original functions within a class and saved the
    interpreter state after execution. We have added support for "import"
    statements, "for" statements, and several binary and unary operators. We
    have added import white list to keep `import` statement safe. Additionally,
    we have modified the variable matching logic and introduced the
    :obj:`fuzz_state` for fuzzy matching."

    DSPy's modifications:
    "We expanded upon the Camel libraries modifications by adding additional 
    support for "Mapping" statements, "conditional" operators, and including
    the "CodePrompt" and "TextPrompt" classes for code execution.
    

    Modifications copyright (C) 2023 CAMEL-AI.org

    Args:
        action_space (Dict[str, Any]): A dictionary that maps action names to
            their corresponding functions or objects. The interpreter can only
            execute functions that are either directly listed in this
            dictionary or are member functions of objects listed in this
            dictionary. The concept of :obj:`action_space` is derived from
            EmbodiedAgent, representing the actions that an agent is capable of
            performing.
        import_white_list (Optional[List[str]], optional): A list that stores
            the Python modules or functions that can be imported in the code.
            All submodules and functions of the modules listed in this list are
            importable. Any other import statements will be rejected. The
            module and its submodule or function name are separated by a period
            (:obj:`.`). (default: :obj:`None`)
    Naction_spaceimport_white_listreturnc                 t    || _         | j                   j                         | _        i | _        |xs g | _        y N)r   copystate
fuzz_stater   )selfr   r   s      r   __init__zPythonInterpreter.__init__d   s4    (&&++-
*,!2!8br   coder   r   
keep_statec           	      @   || j                   j                  |       || j                  j                  |       	 t        j                  |      }d}t        |j                        D ]  \  }	}
	 | j                  |
      }||} |s| j                          |S # t
        $ rC}|j                         |j                  dz
     }t        d|j                   d| d|       d}~ww xY w# t        $ r*}|s| j                          d|	 d| }t        |      d}~ww xY w)a!   Execute the input python codes in a security environment.

        Args:
            code (str): Generated python code to be executed.
            state (Optional[Dict[str, Any]], optional): External variables that
                may be used in the generated code. (default: :obj:`None`)
            fuzz_state (Optional[Dict[str, Any]], optional): External variables
                that do not have certain variable names. The interpreter will
                use fuzzy matching to access these variables. For example, if
                :obj:`fuzz_state` has a variable :obj:`image`, the generated
                code can use :obj:`input_image` to access it. (default:
                :obj:`None`)
            keep_state (bool, optional):  If :obj:`True`, :obj:`state` and
                :obj:`fuzz_state` will be kept for later execution. Otherwise,
                they will be cleared. (default: :obj:`True`)

        Returns:
            Any: The value of the last statement (excluding "import") in the
                code. For this interpreter, the value of an expression is its
                value, the value of an "assign" statement is the assigned
                value, and the value of an "if" and "for" block statement is
                the value of the last statement in the block.
        N   zSyntax error in code at line z: z
Error: z'Evaluation of the code stopped at node z. See:
)r   updater   astparseSyntaxError
splitlineslinenor   	enumeratebody_execute_astclear_state)r   r   r   r   r    
expressione
error_lineresultidxnodeline_resultmsgs                r   executezPythonInterpreter.executek   s;   4 JJe$!OO"":.	i4J
 ":??3 	%IC	,"//5 &$	% -  	i*188a<8J"%B188*BzlZcdecf#ghh	i $ ,!$$&@ F  !s$ 's++,s/   B /C*	C'$>C""C'*	D3%DDc                 P    | j                   j                         | _        i | _        y)z-Initialize :obj:`state` and :obj:`fuzz_state`N)r   r   r   r   r   s    r   r,   zPythonInterpreter.clear_state   s    &&++-
r   r-   c           
      n
   t        |t        j                        r| j                  |      S t        |t        j                        r1| j                  |j                        }t        ||j                        S t        |t        j                        r| j                  |      S t        |t        j                        r| j                  |      S t        |t        j                        r| j                  |      S t        |t        j                        r| j!                  |      S t        |t        j"                        r|j                  S t        |t        j$                        rri }t'        |j(                  |j*                        D ]K  \  }}|$| j                  |      || j                  |      <   ,|j-                  | j                  |             M |S t        |t        j.                        r| j                  |j                        S t        |t        j0                        r| j3                  |      S t        |t        j4                        r| j                  |j                        S t        |t        j6                        r|| j8                  |j:                  <   y t        |t        j<                        r| j?                  |      S t        |t        j@                        r| jC                  |       y t        |t        jD                        r| jG                  |       y tI        t        d      r5t        |t        jJ                        r| j                  |j                        S t        |t        jL                        rAdjO                  |j*                  D cg c]  }tQ        | j                  |             c}      S t        |t        jR                        r)|jT                  D cg c]  }| j                  |       c}S t        |t        jV                        r| jY                  |      S t        |t        jZ                        r| j                  |j                        S t        |t        j\                        r| j_                  |      S t        |t        j`                        r2tc        |jT                  D cg c]  }| j                  |       c}      S t        |t        jd                        r| jg                  |      S ti        |jj                  jl                   d      c c}w c c}w c c}w )NIndex  is not supported.)7
isinstancer$   Assign_execute_assign	Attributer+   valuegetattrattr	AugAssign_execute_augassignBinOp_execute_binopCall_execute_callCompare_execute_conditionConstantr   zipkeysvaluesr#   ExprFor_execute_forFormattedValueFunctionDefr   nameIf_execute_ifImport_execute_import
ImportFrom_execute_import_fromhasattrr9   	JoinedStrjoinstrr   eltsName_execute_nameReturn	Subscript_execute_subscriptr	   tupleUnaryOp_execute_unaryopr   	__class__r   )r   r-   r@   r0   kvelts          r   r+   zPythonInterpreter._execute_ast   s   j#**- ''
33
CMM2%%j&6&67E5*//22
CMM2**:66
CII.&&z22
CHH-%%j11
CKK0**:66
CLL1###
CHH-FJOOZ->->? 81=373D3DQ3GF4,,Q/0MM$"3"3A"67	8
 M
CHH-$$Z%5%566
CGG,$$Z00
C$6$67 $$Z%5%566
COO4*4DJJz'
CFF+##J//
CJJ/  ,
CNN3%%j1S'"z*cii'H$$Z%5%566
CMM2774>4E4EFqT&&q)*FH H
CHH-6@ooFsD%%c*FF
CHH-%%j11
CJJ/$$Z%5%566
CMM2**:66
CII.JOOLS$++C0LMM
CKK0((44 #''0011CDF F) G G Ms   !T()T-<T2assignc                     |j                   }| j                  |j                        }|D ]  }| j                  ||        |S r   )targetsr+   r@   _assign)r   rl   rn   r0   targets        r   r>   z!PythonInterpreter._execute_assign   sA    ..""6<<0 	)FLL(	)r   rp   r@   c                 b   t        |t        j                        r|| j                  |j                  <   y t        |t        j
                        rt        |t              s#t        d|j                  j                   d      t        |j                        t        |      k7  r.t        dt        |j                         dt        |       d      t        |j                  |      D ]#  \  }}|| j                  | j                  |      <   % y t        d|j                  j                   d      )NzExpected type tuple, but gotz	 instead.z	Expected z values but got .z?Unsupported variable type. Expected ast.Name or ast.Tuple, got )r<   r$   r`   r   idr	   re   r   rh   r   lenr_   rL   r+   )r   rp   r@   trj   s        r   ro   zPythonInterpreter._assign  s   fchh'$)DJJvyy!		*eU+&)E*///*B*B)C9(N O O6;;3u:-&FKK 01 2E
|1&' ' FKK/ 5134

4,,Q/05 # &A&,&6&6&?&?%@	$K L Lr   callc                    | j                  |j                        }|j                  D cg c]  }| j                  |       }}|j                  D ci c](  }|j                  | j                  |j
                        * }}t        |t        j                        r| j                  j                         }t        |j                  j                  D cg c]  }|j                   c}|      D ]  \  }	}
|
| j                  |	<    d }|j                  D ]/  }| j                  |      }t        |t        j                        s/ n || _	        |S  ||i |S c c}w c c}w c c}w r   )r+   funcargskeywordsargr@   r<   r$   rS   r   r   rL   r*   rb   )r   rv   callable_funcr{   ry   keywordkwargs	old_stateparam
param_name	arg_valuer0   stmts                r   rH   zPythonInterpreter._execute_call  sA   ))$))426))<3!!#&<<  ==
 KK**7==99
 
 mS__5

)I),]EWEWE\E\-]Eeii-]_c)d 3%
I)2

:&3F%** **40dCJJ/ #DJMd-f--! =
 .^s   E-EE	augassignc                    | j                   |j                  j                     }| j                  |j                        }t        |t        t        f      rt        |t        t        f      s#t        dt        |       dt        |             t        |j                  t        j                        r||z   }nt        |j                  t        j                        r||z
  }nmt        |j                  t        j                        r||z  }nCt        |j                  t        j                        r||z  }nt        d|j                   d      | j!                  |j                  |       |S )Nz(Invalid types for augmented assignment: z, zAugmented assignment operator  is not supported)r   rp   rs   r+   r@   r<   intfloatr   typeopr$   AddSubMultDivro   )r   r   current_valueincrement_value	new_values        r   rD   z$PythonInterpreter._execute_augassign,  s   

9#3#3#6#67++IOO<=3,7JY\^cXd<e"%MdS`NaMbbdeijyezd{#|}}illCGG,%7I	cgg.%7I	chh/%7I	cgg.%7I #%CILL>Qb#cddY%%y1r   	subscriptc                 R   | j                  |j                        }| j                  |j                        }t        |j                  t
        j                        s,t        |j                  j                  j                   d      t        |t        t        f      r|t        |         S ||v r||   S t        |t              rSt        |t              rCt        j                   |t        |j#                                     }t%        |      dkD  r||d      S t        d| d| d      )Nz  is not supported for subscript.r   zCould not index z with 'z'.)r+   slicer@   r<   ctxr$   Loadr   rh   r   listre   r   r^   r   difflibget_close_matchesrM   rt   )r   r   indexr@   close_matchess        r   rd   z$PythonInterpreter._execute_subscript?  s   !!)//2!!)//2)--2"==**334 5   edE]+U$$E><eS!j&@#55e6:5::<6HJM=!A%]1-..!1%wbIJJr   rT   c                 z   |j                   t        t              v rt        t        |j                         S t	        |j
                  t        j                        r|j                   S t	        |j
                  t        j                        r| j                  |j                         S t        |j
                   d      )Nr;   )rs   dirbuiltinsrA   r<   r   r$   Storer   _get_value_from_stater   )r   rT   s     r   ra   zPythonInterpreter._execute_nameR  s|    77c(m#477+
+dhh		*77N#((+--dgg66"dhhZ/A#BCCr   c                    t        |t        j                        rt        |j                  t        j                        r3|j
                  D cg c]  }| j                  |       }}t        |      S t        |j                  t        j                        r3|j
                  D cg c]  }| j                  |       }}t        |      S t        d|j                   d      t        |t        j                        r#t        |j                        dkD  rt        d      t        |j                        dkD  rt        d      | j                  |j                        }|j                  d   }| j                  |j                  d         }t        |t        j                         r||k(  S t        |t        j"                        r||k7  S t        |t        j$                        r||k  S t        |t        j&                        r||k  S t        |t        j(                        r||kD  S t        |t        j*                        r||k\  S t        |t        j,                        r||u S t        |t        j.                        r||uS t        |t        j0                        r||v S t        |t        j2                        r||vS t        d      c c}w c c}w )NzBoolean operator r   r"   z2Cannot evaluate conditions with multiple operatorsr   zUnsupported condition type)r<   r$   BoolOpr   AndrN   r+   allOranyr   rI   rt   opsleftcomparatorsEqNotEqLtLtEGtGtEIsIsNotInNotIn)r   	conditionr@   resultsr   
comparatorrights          r   rJ   z$PythonInterpreter._execute_condition\  s@   i,),,0AJAQAQR4,,U3RR7|#ILL#&&1AJAQAQR4,,U3RR7|#&):9<<.HY'Z[[	3;;/9==!A%&'[\\y}}!"DF F  0]]1%
!!)"7"7":;j#&&)5= 
CII.5= 
CFF+%<
CGG,5= 
CFF+%<
CGG,5= 
CFF+5= 
CII.u$$
CFF+5= 
CII.u$$"#?@@K S Ss   K$Kif_statementc                     d }| j                  |j                        r)|j                  D ]  }| j                  |      }||} |S |j                  D ]  }| j                  |      }||} |S r   )rJ   testr*   r+   orelse)r   r   r0   liner3   s        r   rV   zPythonInterpreter._execute_if  s    ""<#4#45$)) )"//5*(F) 	 %++ )"//5*(F) r   for_statementc                     d }| j                  |j                        D ]E  }| j                  |j                  |       |j                  D ]  }| j                  |      }||} G |S r   )r+   iterro   rp   r*   )r   r   r0   r@   r   r3   s         r   rQ   zPythonInterpreter._execute_for  sr    &&}'9'9: 	)ELL--u5%** )"//5*(F)	) r   import_modulec                     |j                   D ]c  }| j                  |j                         |j                  xs |j                  }t	        j
                  |j                        | j                  |<   e y r   )names_validate_importrT   asname	importlibr   r   )r   r   modulealiass       r   rX   z!PythonInterpreter._execute_import  sZ    #)) 	EF!!&++.MM0V[[E ) 7 7 DDJJu	Er   import_fromc                 f   |j                   t        d      |j                  D ]  }|j                   d|j                   z   }| j	                  |       t        j                  |j                         }|j                  xs |j                  }t        ||j                        | j                  |<    y )Nz!"from . import" is not supported.rr   )
r   r   r   rT   r   r   r   r   rA   r   )r   r   import_name	full_nameimported_moduler   s         r   rZ   z&PythonInterpreter._execute_import_from  s    %"#HII&,, 	KK#**q1A1A0B-CCI!!),'55k6H6HIO&&:+*:*:E '9I9I JDJJu	Kr   r   c                     d}d}|j                  d      D ]#  }||dk(  r|nd| z  }|| j                  v s!d} y  |st        d| d      y )Nr:   Frr   TzLIt is not permitted to import modules than module white list (try to import z).)splitr   r   )r   r   tmp_name
found_namerT   s        r   r   z"PythonInterpreter._validate_import  s{    
OOC( 	DBavJ>H4111!
		 " &L&/[$4 5 5 r   binopc                    | j                  |j                        }|j                  }| j                  |j                        }t	        |t
        j                        r||z   S t	        |t
        j                        r||z
  S t	        |t
        j                        r||z  S t	        |t
        j                        r||z  S t	        |t
        j                        r||z  S t	        |t
        j                        r||z  S t	        |t
        j                        r||z  S t	        |t
        j                        r||z  S t	        |t
        j                        r||z	  S t	        |t
        j                        r||z  S t!        d|       NzOperator not supported: )r+   r   r   r   r<   r$   r   r   r   r   FloorDivModPowLShiftRShiftMatMultr   )r   r   r   operatorr   s        r   rF   z PythonInterpreter._execute_binop  s6     ,88!!%++.h(%<#''*%<#((+%<#''*%<#,,/5= #''*%<#''*;#**-5= #**-5= #++.%<"%=hZ#HIIr   unaryopc                    | j                  |j                        }|j                  }t        |t        j
                        r|S t        |t        j                        r| S t        |t        j                        r| S t        d|       r   )	r+   operandr   r<   r$   UAddUSubNotr   )r   r   r   r   s       r   rg   z"PythonInterpreter._execute_unaryop  sr    ##GOO4::h)8O#((+8O#''*;"%=hZ#HIIr   keyc                     || j                   v r| j                   |   S || j                  v r| j                  |   S t        d| d      )NzThe variable `z` is not defined.)r   r   r   )r   r   s     r   r   z'PythonInterpreter._get_value_from_state  sL    $**::c?"DOO#??3''"^C58I#JKKr   r   )NNT)r   N)-r   r   r   r   r   r^   r   r   r   r   boolr5   r,   typingno_type_checkr$   ASTr+   r=   r>   exprro   rG   rH   rC   rD   rc   rd   r`   ra   rJ   rU   rV   rP   rQ   rW   rX   rY   rZ   r   rE   rF   rf   rg   r   r   r   r   r   r   '   s   :z ;?9T#s(^ 9$,T#Y$79CG9 DH7;#'7C 7c3h(@ 7$T#s(^47 7,/7r OFsww OF3 OF OFbcjj S Lchh Ls L$.#(( .s .*CMM &KCMM K&D#(( D(AT 	#'' 	ESZZ ED EK K5# 5JCII J8J JL L Lr   r   c                   L     e Zd ZdZedee   fd       Zdededd f fdZ	 xZ
S )
TextPrompta-  A class that represents a text prompt. The :obj:`TextPrompt` class
    extends the built-in :obj:`str` class to provide a property for retrieving
    the set of keywords in the prompt.

    Attributes:
        key_words (set): A set of strings representing the keywords in the
            prompt.
    r   c                 d    t        j                  d      }|j                  |       }t        |      S )zAReturns a set of strings representing the keywords in the prompt.z\{([^{}]+)\})recompilefindallset)r   patternfounds      r   	key_wordszTextPrompt.key_words  s*     **_-%5zr   ry   r~   c                     | j                   D ci c]  }|d| z   dz    }}|j                  |       t        t        |   |i |      S c c}w )a  Overrides the built-in :obj:`str.format` method to allow for
        default values in the format string. This is used to allow formatting
        the partial string.

        Args:
            *args (Any): Variable length argument list.
            **kwargs (Any): Arbitrary keyword arguments.

        Returns:
            TextPrompt: A new :obj:`TextPrompt` object with the format string
                replaced with the formatted string.
        {})r   r#   r   superformat)r   ry   r~   r   default_kwargsrh   s        r   r   zTextPrompt.format   s[     @D~~N#su~33NNf%%'.$A.ABB Os   A)r   r   r   r   propertyr   r^   r   r   r   __classcell__rh   s   @r   r   r     sK     3s8  CC C3 C< C Cr   r   c            	            e Zd ZdZdededd f fdZedee   fd       Z	deddfd	Z
	 	 dd
ee   deeeef      deeef   fdZ xZS )
CodePromptzA class that represents a code prompt. It extends the :obj:`TextPrompt`
    class with a :obj:`code_type` property.

    Attributes:
        code_type (str, optional): The type of code. Defaults to None.
    ry   r~   r   c                 `    |j                  dd      }t        |   | g|i |}||_        |S )zCreates a new instance of the :obj:`CodePrompt` class.

        Args:
            *args (Any): Positional arguments.
            **kwargs (Any): Keyword arguments.

        Returns:
            CodePrompt: The created :obj:`CodePrompt` instance.
        	code_typeN)popr   __new__
_code_type)clsry   r~   r   instancerh   s        r   r   zCodePrompt.__new__  s:     JJ{D1	7?3888'r   c                     | j                   S )zaReturns the type of code.

        Returns:
            Optional[str]: The type of code.
        r  r7   s    r   r   zCodePrompt.code_type(  s     r   r   Nc                     || _         y)z]Sets the type of code.

        Args:
            code_type (str): The type of code.
        Nr  )r   r   s     r   set_code_typezCodePrompt.set_code_type1  s     $r   interpreteruser_variablec                 ^    |st        t                     }|j                  | |d      }||fS )a  Executes the code string by a given python interpreter.

        Args:
            interpreter (PythonInterpreter, optional): interpreter to be used
                during code execution. (default: :obj:`None`)
            user_variable (Optional[Dict[str, Any]]): variables that can be
                used in the code, which applying fuzzy matching, such as images
                or documents. (default: :obj:`None`)

        Returns:
            Tuple[Any, PythonInterpreter]: A tuple containing the execution
                result and the used interpreter. The execution result
                represents the value of the last statement (excluding "import")
                in the code. This value could potentially be the desired result
                of the LLM-generated code.
    )r   T)r   r    )r   globalsr5   )r   r  r	  execution_ress       r   r5   zCodePrompt.execute9  s:    * +CK#++D]7; , =k))r   )NN)r   r   r   r   r   r   r   r   r^   r   r  r   r   r	   r5   r   r   s   @r   r   r     s    C 3 <  8C=  $s $t $ :>26*#$56*S#X/* 
s%%	&*r   r   )r$   r   r   r   r   r   collections.abcr   r   r   r   r   r   r	   
ValueErrorr   r   r^   r   r   r   r   r   <module>r     s^        	  # 	z 	EL ELN!C !CFA* A*r   