o
    ,ige                     @  s  d Z ddlmZ 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	Z	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mZ ddlmZmZmZmZmZmZmZmZmZmZmZmZm Z m!Z!m"Z" ddl#m$Z% ddl&Z&ddl'Z'ddl(m)Z) ddl*m+Z+ dd	l,m-Z. e/e0Z1G d
d de2Z3G dd de3Z4G dd de3Z5G dd de3Z6G dd de3Z7G dd de3Z8G dd de3Z9G dd de3Z:G dd de3Z;G dd de<Z=G dd de=Z>ddd$d%Z?dd'd(Z@dd,d-ZAdd1d2ZBdd6d7ZCejDd8d9dd=d>ZEdd@dAZFddBdCZGddEdFZHddIdJZIddLdMZJddNdOZKddPdQZLejDd8d9ddSdTZMddWdXZNdd[d\ZOejDd]d9	dd^d_ddedfZPejDd8d9dddhdiZQG djdk dkejRZSG dldm dmejRZTG dndo doe+ZUeV ZWejXddudvZYddxdyZZejX	ddd~dZ[ejX	ddddZ\dddZ]e dZ^	ddddZ_dddZ`dddZadddZbe)dZcG dd deZddddZedddZfdddZgejDdd9dddZhddddZidddZjdS )zGeneric utility functions.    )annotationsN)FutureThreadPoolExecutor)AnyCallableDict	GeneratorIterableIteratorListLiteralMappingOptionalSequenceTupleTypeVarUnioncast)parse)	ParamSpec)Retry)schemasc                   @     e Zd ZdZdS )LangSmithErrorz=An error occurred while communicating with the LangSmith API.N__name__
__module____qualname____doc__ r   r   i/var/www/eduai.edurigo.com/doc_train/edurigo_ai/Puru/venv/lib/python3.10/site-packages/langsmith/utils.pyr   0       r   c                   @  r   )LangSmithAPIErrorz9Internal server error while communicating with LangSmith.Nr   r   r   r   r    r"   4   r!   r"   c                   @  r   )LangSmithRequestTimeoutz*Client took too long to send request body.Nr   r   r   r   r    r#   8   r!   r#   c                   @  r   )LangSmithUserErrorzAUser error caused an exception when communicating with LangSmith.Nr   r   r   r   r    r$   <   r!   r$   c                   @  r   )LangSmithRateLimitErrorz7You have exceeded the rate limit for the LangSmith API.Nr   r   r   r   r    r%   @   r!   r%   c                   @  r   )LangSmithAuthErrorz-Couldn't authenticate with the LangSmith API.Nr   r   r   r   r    r&   D   r!   r&   c                   @  r   )LangSmithNotFoundErrorz%Couldn't find the requested resource.Nr   r   r   r   r    r'   H   r!   r'   c                   @  r   )LangSmithConflictErrorzThe resource already exists.Nr   r   r   r   r    r(   L   r!   r(   c                   @  r   )LangSmithConnectionErrorz&Couldn't connect to the LangSmith API.Nr   r   r   r   r    r)   P   r!   r)   c                   @  r   )LangSmithWarningzBase class for warnings.Nr   r   r   r   r    r*   W   r!   r*   c                   @  r   )LangSmithMissingAPIKeyWarningzWarning for missing API key.Nr   r   r   r   r    r+   [   r!   r+   ctxOptional[dict]returnUnion[bool, Literal['local']]c                 C  sT   ddl m}m} | p| }|d dur|d S | rdS tdtddd	d	}|d
kS )z"Return True if tracing is enabled.r   )get_current_run_treeget_tracing_contextenabledNT
TRACING_V2TRACING defaulttrue)langsmith.run_helpersr0   r1   get_env_var)r,   r0   r1   tc
var_resultr   r   r    tracing_is_enabled_   s   
r=   boolc                   C  s   t ddddkS )z"Return True if testing is enabled.TEST_TRACKINGr5   r6   falser:   r   r   r   r    test_tracking_is_disabledr   s   rB   
arg_groupsTuple[str, ...]r   c                    s   d fdd}|S )z7Validate specified keyword args are mutually exclusive.funcr   r.   c                   s   t  d fdd}|S )Nargsr   kwargsr.   c                    s\    fddD }dd t |D }|r'fdd|D }tdd| | i  S )z3Validate exactly one arg in each group is not None.c                   s"   g | ]}t  fd d|D qS )c                 3  s"    | ]}  |d urdV  qd S )N   )get).0argrG   r   r    	<genexpr>        zJxor_args.<locals>.decorator.<locals>.wrapper.<locals>.<listcomp>.<genexpr>)sum)rJ   	arg_grouprL   r   r    
<listcomp>~   s    z@xor_args.<locals>.decorator.<locals>.wrapper.<locals>.<listcomp>c                 S  s   g | ]
\}}|d kr|qS rH   r   )rJ   icountr   r   r    rQ      s    c                   s   g | ]	}d   | qS ), )join)rJ   rS   rC   r   r    rQ          zFExactly one argument in each of the following groups must be defined: rU   )	enumerate
ValueErrorrV   )rF   rG   countsinvalid_groupsinvalid_group_names)rC   rE   rL   r    wrapper{   s   
z,xor_args.<locals>.decorator.<locals>.wrapper)rF   r   rG   r   r.   r   )	functoolswraps)rE   r^   rW   )rE   r    	decoratorz   s   zxor_args.<locals>.decoratorN)rE   r   r.   r   r   )rC   ra   r   rW   r    xor_argsw   s   rb   response(Union[requests.Response, httpx.Response]Nonec              
   C  sz   z|    W dS  tjy } z
tt|| j|d}~w tjy< } ztjt| d| j | j| d|d}~ww )z&Raise an error with the response text.Nz: )requestrc   )raise_for_statusrequests	HTTPErrorstrtexthttpxHTTPStatusErrorrf   )rc   er   r   r    raise_for_status_with_text   s   ro   enuUnion[enum.Enum, str]rj   c                 C  s   t | tjr	| jS | S )zGet the value of a string enum.)
isinstanceenumEnumvalue)rp   r   r   r    get_enum_value   s   rv   rH   )maxsizelevelintmessagec                 C  s   t | | dS )z4Log a message at the specified level, but only once.N)_LOGGERlog)rx   rz   r   r   r    log_once   s   r}   Mapping[str, Any]c                 C  sd   | st dd| v r"d| vrt d|  d| d d dd S d	| vr.t d
|  d| d	 S )NMessage is empty.lcid*Unexpected format for serialized message: z Message does not have an id.Messager5   type&Unexpected format for stored message: z Message does not have a type.)rZ   replacelowerrz   r   r   r    _get_message_type   s   

r   c                 C  sT   | st dd| v rd| vrt d|  d| d S d| vr&t d|  d| d S )	Nr   r   rG   r   z Message does not have kwargs.datar   z Message does not have data.)rZ   r   r   r   r    _get_message_fields   s   

r   Dict[str, Any]c                 C  s   t | }t| }||dS )z&Extract message from a message object.r   r   )r   r   )rz   message_typemessage_datar   r   r    _convert_message   s   
r   inputsList[Dict[str, Any]]c                 C  s@   d| v rdd | d D S d| v rt | d gS td|  d)aG  Extract messages from the given inputs dictionary.

    Args:
        inputs (Mapping[str, Any]): The inputs dictionary.

    Returns:
        List[Dict[str, Any]]: A list of dictionaries representing
            the extracted messages.

    Raises:
        ValueError: If no message(s) are found in the inputs dictionary.
    messagesc                 S  s   g | ]}t |qS r   )r   )rJ   rz   r   r   r    rQ          z,get_messages_from_inputs.<locals>.<listcomp>rz   z-Could not find message(s) in run with inputs .)r   rZ   )r   r   r   r    get_messages_from_inputs   s
   r   outputsc                 C  sr   d| vrt d|  d| d }t|dkr#t dt| d| d|d }d|vr3t d	| d
t|d S )a'  Retrieve the message generation from the given outputs.

    Args:
        outputs (Mapping[str, Any]): The outputs dictionary.

    Returns:
        Dict[str, Any]: The message generation.

    Raises:
        ValueError: If no generations are found or if multiple generations are present.
    generations,No generations found in in run with output: r   rH   z3Chat examples expect exactly one generation. Found z generations: r   rz   z"Unexpected format for generation: z%. Generation does not have a message.)rZ   lenr   r   r   first_generationr   r   r    #get_message_generation_from_outputs   s"   
r   c                 C  sT   d| v r| d S d| v r"| d }t |dkr|d S td|  dtd|  d)	zRetrieve the prompt from the given inputs.

    Args:
        inputs (Mapping[str, Any]): The inputs dictionary.

    Returns:
        str: The prompt.

    Raises:
        ValueError: If the prompt is not found or if multiple prompts are present.
    promptpromptsrH   r   z$Multiple prompts in run with inputs z!. Please create example manually.z)Could not find prompt in run with inputs r   )r   rZ   )r   r   r   r   r    get_prompt_from_inputs
  s   
r   c                 C  s`   d| vrt d|  d| d }t|dkrt d| |d }d|vr,t d| |d S )	z(Get the LLM generation from the outputs.r   r   r   rH   zMultiple generations in run: r   rk   zNo text in generation: )rZ   r   r   r   r   r    get_llm_generation_from_outputs#  s   r   	List[str]c                   C  sz   zt jg dt jt jd ddgW S  t jtfy<   zt jddgt jt jd dgW  Y S  t jtfy;   tdw w )z7Get the correct docker compose command for this system.)dockercompose	--version)stdoutstderrr   r   zdocker-composer   zNeither 'docker compose' nor 'docker-compose' commands are available. Please install the Docker server following the instructions for your operating system at https://docs.docker.com/engine/install/)
subprocess
check_callDEVNULLCalledProcessErrorFileNotFoundErrorrZ   r   r   r   r    get_docker_compose_command0  s*   
r   ls_schemas.BaseMessageLikedictc                 C  s<   | j d| jid}| jrt| jdkri | j|d d< |S )z*Convert a LangChain message to an example.contentr   r   r   additional_kwargs)r   r   r   r   )rz   	convertedr   r   r    convert_langchain_messageK  s   r   objobjectc                 C  s@   t tt| ddttt| ddtt| dott| dtgS )zCheck if the given object is similar to BaseMessage.

    Args:
        obj (object): The object to check.

    Returns:
        bool: True if the object is similar to BaseMessage, False otherwise.
    r   Nr   r   )allrr   getattrrj   r   hasattr)r   r   r   r    is_base_message_likeW  s   	r   d   )	LANGSMITH	LANGCHAIN)
namespacesnamer7   Optional[str]r   r   c                  s<    fdd|D }|D ] t j }|dur|  S q|S )a+  Retrieve an environment variable from a list of namespaces.

    Args:
        name (str): The name of the environment variable.
        default (Optional[str], optional): The default value to return if the
            environment variable is not found. Defaults to None.
        namespaces (Tuple, optional): A tuple of namespaces to search for the
            environment variable. Defaults to ("LANGSMITH", "LANGCHAINs").

    Returns:
        Optional[str]: The value of the environment variable if found,
            otherwise the default value.
    c                   s   g | ]	}| d   qS )_r   )rJ   	namespacer   r   r    rQ   }  rX   zget_env_var.<locals>.<listcomp>N)osenvironrI   )r   r7   r   namesru   r   r   r    r:   i  s   r:   Tc              	   C  s&   t jdtdtd| rdndddS )z,Get the project name for a LangSmith tracer.HOSTED_LANGSERVE_PROJECT_NAMEPROJECTSESSIONr7   Nr6   )r   r   rI   r:   )return_default_valuer   r   r    get_tracer_project  s   r   c                      s.   e Zd ZdZdd fdd	ZdddZ  ZS )FilterPoolFullWarningzFFilter urrllib3 warnings logged when the connection pool isn't reused.r5   r   rj   hostr.   re   c                   s   t  | || _dS )zInitialize the FilterPoolFullWarning filter.

        Args:
            name (str, optional): The name of the filter. Defaults to "".
            host (str, optional): The host to filter. Defaults to "".
        N)super__init___host)selfr   r   	__class__r   r    r     s   
zFilterPoolFullWarning.__init__r>   c                 C  s   |  }d|vr
dS | j|vS )zJurllib3.connectionpool:Connection pool is full, discarding connection: ...z.Connection pool is full, discarding connectionT)
getMessager   r   recordmsgr   r   r    filter  s   
zFilterPoolFullWarning.filter)r5   r5   )r   rj   r   rj   r.   re   r.   r>   )r   r   r   r   r   r   __classcell__r   r   r   r    r     s    
r   c                   @  s   e Zd ZdZdddZdS )FilterLangSmithRetryz!Filter for retries from this lib.r.   r>   c                 C  s   |  }d|vS )z!Filter retries from this library.LangSmithRetry)r   r   r   r   r    r     s   zFilterLangSmithRetry.filterNr   )r   r   r   r   r   r   r   r   r    r     s    r   c                   @  r   )r   z&Wrapper to filter logs with this name.Nr   r   r   r   r    r     r!   r   loggerlogging.LoggerfiltersSequence[logging.Filter]Generator[None, None, None]c                 c  s    t  |D ]}| | qW d   n1 sw   Y  z3dV  W t # |D ]}z| | W q' ty>   td Y q'w W d   dS 1 sJw   Y  dS t " |D ]}z| | W qV tym   td Y qVw W d   w 1 sxw   Y  w )zTemporarily adds specified filters to a logger.

    Parameters:
    - logger: The logger to which the filters will be added.
    - filters: A sequence of logging.Filter objects to be temporarily added
        to the logger.
    NzFailed to remove filter)_FILTER_LOCK	addFilterremoveFilterBaseExceptionr{   warning)r   r   r   r   r   r    filter_logs  s2   (r   cachec                 C  s   | dur| S t dddS )zGet the testing cache directory.

    Args:
        cache (Optional[str]): The cache path.

    Returns:
        Optional[str]: The cache path if provided, otherwise the value
        from the LANGSMITH_TEST_CACHE environment variable.
    N
TEST_CACHEr6   rA   )r   r   r   r    get_cache_dir  s   
r   pathUnion[str, pathlib.Path]ignore_hostsOptional[Sequence[str]]c                 #  s    zddl }W n ty   tdw ddlm} |  d fdd	}tj| \}}|j|	d
s8|	dr:dnd|dg dddg|d}|
| dV  W d   dS 1 s[w   Y  dS )Use a cache for requests.r   NzNvcrpy is required to use caching. Install with:pip install -U "langsmith[vcr]")_patchrf   r   r.   c                   s(   rt  fddD rd S i  _ S )Nc                 3  s    | ]	} j |V  qd S N)url
startswith)rJ   r   rf   r   r    rM     s    z>with_cache.<locals>._filter_request_headers.<locals>.<genexpr>)anyheadersr   r   r   r    _filter_request_headers  s   z+with_cache.<locals>._filter_request_headersz.yamlz.ymlyamljsonnew_episodes)urimethodr   bodyauthorizationz
Set-Cookie)
serializercassette_library_dirrecord_modematch_onfilter_headersbefore_record_request)rf   r   r.   r   )vcrImportErrorlangsmith._internalr   patch_urllib3r   r   splitVCRendswithuse_cassette)r   r   r  r	  r   	cache_dir
cache_filels_vcrr   r   r    
with_cache  s6   "r  "Optional[Union[str, pathlib.Path]]c                 c  sJ    | dur t | | dV  W d   dS 1 sw   Y  dS dV  dS )r   N)r  )r   r   r   r   r    with_optional_cache  s   "
r  c                  C  s&   t jt  } dd | D }d|S )Nc                 S  s   g | ]}d |vr|qS )z
langsmith/r   )rJ   liner   r   r    rQ   #  s    z_format_exc.<locals>.<listcomp>r5   )	tracebackformat_exceptionsysexc_inforV   )tb_linesfiltered_linesr   r   r    _format_exc   s   
r  T   valmemoDict[int, Any]	max_depth_depthc                   s   t | }t|dd }|d urz|W S  ty   Y nw  kr#| S t| tr5 fdd|  D S t| trE fdd| D S t| trWt fdd| D S t| trg fdd	| D S | S )
N__deepcopy__c              	     s2   i | ]\}}t | d  t | d  qS rR   _middle_copy)rJ   kvr"  r!  r  r   r    
<dictcomp>8  s    z _middle_copy.<locals>.<dictcomp>c                   s   g | ]}t | d  qS rR   r$  rJ   itemr(  r   r    rQ   ?      z _middle_copy.<locals>.<listcomp>c                 3  s"    | ]}t | d  V  qdS )rH   Nr$  r*  r(  r   r    rM   A  rN   z_middle_copy.<locals>.<genexpr>c                   s   h | ]}t | d  qS rR   r$  r*  r(  r   r    	<setcomp>C  r,  z_middle_copy.<locals>.<setcomp>)	r   r   r   rr   r   itemslisttupleset)r  r  r!  r"  clscopierr   r(  r    r%  *  s*   




r%  c              
   C  sR   i }zt | |W S  ty( } ztdt| t| |W  Y d}~S d}~ww )zDeep copy a value with a compromise for uncopyable objects.

    Args:
        val: The value to be deep copied.

    Returns:
        The deep copied value.
    zFailed to deepcopy input: %sN)copydeepcopyr   r{   debugreprr%  )r  r  rn   r   r   r    deepish_copyH  s   	r8  current_versiontarget_versionc                 C  s(   ddl m} || }||}||kS )zGCheck if the current version is greater or equal to the target version.r   )version)	packagingr;  r   )r9  r:  r;  currenttargetr   r   r    is_version_greater_or_equal]  s   

r?  
identifierTuple[str, str, str]c                 C  s   | r|  ddks| ds| drtd|  | dd}|d }t|dkr.|d nd}d|v rL|dd\}}|r@|sGtd|  |||fS |sUtd|  d||fS )aE  Parse a string in the format of owner/name:hash, name:hash, owner/name, or name.

    Args:
        identifier (str): The prompt identifier to parse.

    Returns:
        Tuple[str, str, str]: A tuple containing (owner, name, hash).

    Raises:
        ValueError: If the identifier doesn't match the expected formats.
    /rH   zInvalid identifier format: :r   latest-)rT   r   r  rZ   r
  r   )r@  parts
owner_namecommitownerr   r   r   r    parse_prompt_identifierf  s&   

rJ  Pc                      s8   e Zd ZdZd fd
dZdddd fddZ  ZS )ContextThreadPoolExecutorz?ThreadPoolExecutor that copies the context to the child thread.rE   Callable[P, T]rF   P.argsrG   P.kwargsr.   	Future[T]c                   s6   t  ttdtf tjt j	|g|R i |S )aC  Submit a function to the executor.

        Args:
            func (Callable[..., T]): The function to submit.
            *args (Any): The positional arguments to the function.
            **kwargs (Any): The keyword arguments to the function.

        Returns:
            Future[T]: The future for the function.
        .)
r   submitr   r   r  r_   partialcontextvarscopy_contextrun)r   rE   rF   rG   r   r   r    rQ    s   

z ContextThreadPoolExecutor.submitNrH   timeout	chunksizefnCallable[..., T]	iterablesIterable[Any]rW  Optional[float]rX  ry   Iterator[T]c                  sF   dd t t|d D  d fdd	}t j|g|R ||d
S )a  Return an iterator equivalent to stdlib map.

        Each function will receive its own copy of the context from the parent thread.

        Args:
            fn: A callable that will take as many arguments as there are
                passed iterables.
            timeout: The maximum number of seconds to wait. If None, then there
                is no limit on the wait time.
            chunksize: The size of the chunks the iterable will be broken into
                before being passed to a child process. This argument is only
                used by ProcessPoolExecutor; it is ignored by
                ThreadPoolExecutor.

        Returns:
            An iterator equivalent to: map(func, *iterables) but the calls may
            be evaluated out-of-order.

        Raises:
            TimeoutError: If the entire result iterator could not be generated
                before the given timeout.
            Exception: If fn(*args) raises for any values.
        c                 S  s   g | ]}t  qS r   )rS  rT  )rJ   r   r   r   r    rQ     r   z1ContextThreadPoolExecutor.map.<locals>.<listcomp>r   rF   r   r.   r  c                    s      jg| R  S r   )poprU  )rF   contextsrY  r   r    _wrapped_fn  s   z2ContextThreadPoolExecutor.map.<locals>._wrapped_fnrV  N)rF   r   r.   r  )ranger   r   map)r   rY  rW  rX  r[  rb  r   r`  r    rd    s   zContextThreadPoolExecutor.map)rE   rM  rF   rN  rG   rO  r.   rP  )
rY  rZ  r[  r\  rW  r]  rX  ry   r.   r^  )r   r   r   r   rQ  rd  r   r   r   r   r    rL    s    rL  api_urlc                 C  s@   | p
t ttddd}| std| dddS )zBGet the LangSmith API URL from the environment or the given value.ENDPOINTzhttps://api.smith.langchain.comr6   z!LangSmith API URL cannot be empty"'rB  )r   rj   r:   stripr$   rstrip)re  _api_urlr   r   r    get_api_url  s   rl  api_keyc                 C  s@   | dur| nt ddd}|du s| sdS | ddS )z8Get the API key from the environment or the given value.NAPI_KEYr6   rg  rh  )r:   ri  )rm  api_key_r   r   r    get_api_key  s   rp  r   c                 C  sV   zt | jdd }t|}|dkp|dp|dW S  tjy*   Y dS w )zCheck if the URL is localhost.

    Parameters
    ----------
    url : str
        The URL to check.

    Returns:
    -------
    bool
        True if the URL is localhost, False otherwise.
    rC  r   z	127.0.0.1z0.0.0.0z::F)urllib_parseurlsplitnetlocr
  socketgethostbynamer   gaierror)r   rs  ipr   r   r    _is_localhost  s   
rx     web_urlc                 C  s   | r| S t |}t|rd}|S t|jdr/t|jddd }t |j|d}|S t|jdrMt|jddd }t |j|d}|S t|j	
drYd}|S t|j	
d	red
}|S t|j	
drqd}|S d}|S )z1Get the host URL based on the web URL or API URL.zhttp://localhostz/apirH   r   )r   z/api/v1zeu.zhttps://eu.smith.langchain.comzdev.zhttps://dev.smith.langchain.comzbeta.z https://beta.smith.langchain.comzhttps://smith.langchain.com)rq  urlparserx  rj   r   r  rsplit
urlunparse_replacers  r   )rz  re  
parsed_urllinknew_pathr   r   r    get_host_url  s2   
	r  rY  depthc                 C  s   |dkst | st| S t| dr| jS t| tjr"t| j|d S t| dr>t| dr6t| j	dr6| j	jS t| j
|d S t| S )Nry  r   rH   __call__r   )callablerj   r   r   rr   r_   rR  _get_function_namerE   r   r  )rY  r  r   r   r    r    s   

r  r   c                 C  s&   t | tr|  dkp| dkS t| S )zCheck if the value is truish.

    Args:
        val (Any): The value to check.

    Returns:
        bool: True if the value is truish, False otherwise.
    r8   1)rr   rj   r   r>   )r  r   r   r    	is_truish)  s   
	r  r   )r,   r-   r.   r/   r   )rC   rD   r.   r   )rc   rd   r.   re   )rp   rq   r.   rj   )rx   ry   rz   rj   r.   re   )rz   r~   r.   rj   )rz   r~   r.   r~   )rz   r~   r.   r   )r   r~   r.   r   )r   r~   r.   r   )r   r~   r.   rj   )r   r~   r.   rj   )r.   r   )rz   r   r.   r   )r   r   r.   r>   )r   rj   r7   r   r   r   r.   r   )T)r.   r   )r   r   r   r   r.   r   )r   r   r.   r   )r   r   r   r   r.   r   )r   r  r   r   r.   r   )r.   rj   )r  r   )
r  r  r  r   r!  ry   r"  ry   r.   r  )r  r  r.   r  )r9  rj   r:  rj   r.   r>   )r@  rj   r.   rA  )re  r   r.   rj   )rm  r   r.   r   )r   rj   r.   r>   )rz  r   re  rj   )r   )rY  r   r  ry   r.   rj   )r  r   r.   r>   )kr   
__future__r   
contextlibrS  r4  rs   r_   loggingr   pathlibrt  r   r  	threadingr  concurrent.futuresr   r   typingr   r   r   r   r	   r
   r   r   r   r   r   r   r   r   r   urllibr   rq  rl   rh   typing_extensionsr   urllib3.utilr   	langsmithr   
ls_schemas	getLoggerr   r{   	Exceptionr   r"   r#   r$   r%   r&   r'   r(   r)   UserWarningr*   r+   r=   rB   rb   ro   rv   	lru_cacher}   r   r   r   r   r   r   r   r   r   r   r:   r   Filterr   r   r   RLockr   contextmanagerr   r   r  r  r  r  r%  r8  r?  rJ  rK  rL  rl  rp  rx  r  r  r  r   r   r   r    <module>   s    D



















*



	#
G


