
    f3fie                     ,   U d 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
 ddlmZ ddlmZmZ ddlmZmZmZmZ ddlmZ g d	Zd
dgZi eeeeZi Zeeeeedf      f   ed<   de	d   deeedf      fdZ deedf   deeef   ddfdZ!deedf   deeef   ddfdZ"e#e   Z$	 eeedf   eeef   gdf   Z%	 dee$   deeedf   eedf   f   deeedf      fdZ& G d d      Z' e       dddddde"ddedee$   e	d   z  deeef   dz  d e(e   dz  d!e)d"eeedf   eedf   f   dz  d#e)d$e%dz  defd%       Z* e       dddddde"dd&edee$   e	d   z  deeef   dz  d e(e   dz  d!e)d"eeedf   eedf   f   dz  d#e)d$e%dz  defd'       Z+y)(a
  Load LangChain objects from JSON strings or objects.

## How it works

Each `Serializable` LangChain object has a unique identifier (its "class path"), which
is a list of strings representing the module path and class name. For example:

- `AIMessage` -> `["langchain_core", "messages", "ai", "AIMessage"]`
- `ChatPromptTemplate` -> `["langchain_core", "prompts", "chat", "ChatPromptTemplate"]`

When deserializing, the class path from the JSON `'id'` field is checked against an
allowlist. If the class is not in the allowlist, deserialization raises a `ValueError`.

## Security model

The `allowed_objects` parameter controls which classes can be deserialized:

- **`'core'` (default)**: Allow classes defined in the serialization mappings for
    langchain_core.
- **`'all'`**: Allow classes defined in the serialization mappings. This
    includes core LangChain types (messages, prompts, documents, etc.) and trusted
    partner integrations. See `langchain_core.load.mapping` for the full list.
- **Explicit list of classes**: Only those specific classes are allowed.

For simple data types like messages and documents, the default allowlist is safe to use.
These classes do not perform side effects during initialization.

!!! note "Side effects in allowed classes"

    Deserialization calls `__init__` on allowed classes. If those classes perform side
    effects during initialization (network calls, file operations, etc.), those side
    effects will occur. The allowlist prevents instantiation of classes outside the
    allowlist, but does not sandbox the allowed classes themselves.

Import paths are also validated against trusted namespaces before any module is
imported.

### Injection protection (escape-based)

During serialization, plain dicts that contain an `'lc'` key are escaped by wrapping
them: `{"__lc_escaped__": {...}}`. During deserialization, escaped dicts are unwrapped
and returned as plain dicts, NOT instantiated as LC objects.

This is an allowlist approach: only dicts explicitly produced by
`Serializable.to_json()` (which are NOT escaped) are treated as LC objects;
everything else is user data.

Even if an attacker's payload includes `__lc_escaped__` wrappers, it will be unwrapped
to plain dicts and NOT instantiated as malicious objects.

## Examples

```python
from langchain_core.load import load
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.messages import AIMessage, HumanMessage

# Use default allowlist (classes from mappings) - recommended
obj = load(data)

# Allow only specific classes (most restrictive)
obj = load(
    data,
    allowed_objects=[
        ChatPromptTemplate,
        AIMessage,
        HumanMessage,
    ],
)
```
    N)CallableIterable)AnyLiteralcast)beta)_is_escaped_dict_unescape_value)_JS_SERIALIZABLE_MAPPING_OG_SERIALIZABLE_MAPPINGOLD_CORE_NAMESPACES_MAPPINGSERIALIZABLE_MAPPING)Serializable)	langchainlangchain_corelangchain_communitylangchain_anthropiclangchain_groqlangchain_google_genailangchain_awslangchain_openailangchain_google_vertexailangchain_mistralailangchain_fireworkslangchain_xailangchain_sambanovalangchain_perplexityr   r   ._default_class_paths_cacheallowed_object_modeallcorereturnc                     | t         v r	t         |    S t               }t        j                         D ]5  \  }}| dk(  r	|d   dk7  r|j	                  |       |j	                  |       7 |t         | <   t         |    S )a  Get the default allowed class paths from the serialization mappings.

    This uses the mappings as the source of truth for what classes are allowed
    by default. Both the legacy paths (keys) and current paths (values) are included.

    Args:
        allowed_object_mode: either `'all'` or `'core'`.

    Returns:
        Set of class path tuples that are allowed by default.
    r"   r   r   )r   setALL_SERIALIZABLE_MAPPINGSitemsadd)r   allowed_pathskeyvalues       V/var/www/auto_recruiter/arenv/lib/python3.12/site-packages/langchain_core/load/load.py _get_default_allowed_class_pathsr-   |   s     88)*=>>*-%M/557 !
U&(U1X9I-I#% 	! 7D23%&9::    
class_pathkwargsc                 J    | }|j                  d      dk(  rd}t        |      y)a  Block jinja2 templates during deserialization for security.

    Jinja2 templates can execute arbitrary code, so they are blocked by default when
    deserializing objects with `template_format='jinja2'`.

    Note:
        We intentionally do NOT check the `class_path` here to keep this simple and
        future-proof. If any new class is added that accepts `template_format='jinja2'`,
        it will be automatically blocked without needing to update this function.

    Args:
        class_path: The class path tuple being deserialized (unused).
        kwargs: The kwargs dict for the class constructor.

    Raises:
        ValueError: If `template_format` is `'jinja2'`.
    template_formatjinja2zJinja2 templates are not allowed during deserialization for security reasons. Use 'f-string' template format instead, or explicitly allow jinja2 by providing a custom init_validator.N)get
ValueError)r/   r0   _msgs       r,   _block_jinja2_templatesr8      s6    * 	Azz#$0; 	
 o 1r.   c                     t        | |       y)ak  Default init validator that blocks jinja2 templates.

    This is the default validator used by `load()` and `loads()` when no custom
    validator is provided.

    Args:
        class_path: The class path tuple being deserialized.
        kwargs: The kwargs dict for the class constructor.

    Raises:
        ValueError: If template_format is `'jinja2'`.
    N)r8   )r/   r0   s     r,   default_init_validatorr:      s      J/r.   allowed_objectsimport_mappingsc                 \   t        |       }t               }|D ]  }t        |t              rt	        |t
              sd}t        |      t        |j                               }|j                  |       |j                         D ]%  \  }}t        |      |k(  s|j                  |       '  |S )a  Return allowed class paths from an explicit list of classes.

    A class path is a tuple of strings identifying a serializable class, derived from
    `Serializable.lc_id()`. For example: `('langchain_core', 'messages', 'AIMessage')`.

    Args:
        allowed_objects: Iterable of `Serializable` subclasses to allow.
        import_mappings: Mapping of legacy class paths to current class paths.

    Returns:
        Set of allowed class paths.

    Example:
        ```python
        # Allow a specific class
        _compute_allowed_class_paths([MyPrompt], {}) ->
            {("langchain_core", "prompts", "MyPrompt")}

        # Include legacy paths that map to the same class
        import_mappings = {("old", "Prompt"): ("langchain_core", "prompts", "MyPrompt")}
        _compute_allowed_class_paths([MyPrompt], import_mappings) ->
            {("langchain_core", "prompts", "MyPrompt"), ("old", "Prompt")}
        ```
    z5allowed_objects must contain Serializable subclasses.)listr%   
isinstancetype
issubclassr   	TypeErrortuplelc_idr(   r'   )	r;   r<   allowed_objects_listallowed_class_pathsallowed_objr7   r/   mapping_keymapping_values	            r,   _compute_allowed_class_pathsrJ      s    8  003+ 5+t,J5
 JCC. ;,,./

+*9*?*?*A 	5&K]#z1#''4	55 r.   c                       e Zd ZdZ	 	 	 	 	 ddeddee   ed   z  dee	e	f   dz  de
e	   dz  d	ed
eee	df   ee	df   f   dz  dededz  ddfdZdee	ef   defdZy)ReviverzReviver for JSON objects.

    Used as the `object_hook` for `json.loads` to reconstruct LangChain objects from
    their serialized JSON representation.

    Only classes in the allowlist can be instantiated.
    NFignore_unserializable_fieldsinit_validatorr;   r    secrets_mapvalid_namespacessecrets_from_envadditional_import_mappings.rN   rO   r#   c                J   || _         |xs i | _        |r
g t        |nt        | _        |xs i | _        | j                  ri t
        | j                  nt
        | _        |dv rt        t        d|            j                         | _
        | j                  r~| j                  j                         D ];  \  }}	| j                  j                  |       | j                  j                  |	       = n%t        t        d|      | j                        | _
        || _        || _        y)a  Initialize the reviver.

        Args:
            allowed_objects: Allowlist of classes that can be deserialized.
                - `'core'` (default): Allow classes defined in the serialization
                    mappings for `langchain_core`.
                - `'all'`: Allow classes defined in the serialization mappings.

                    This includes core LangChain types (messages, prompts, documents,
                    etc.) and trusted partner integrations. See
                    `langchain_core.load.mapping` for the full list.
                - Explicit list of classes: Only those specific classes are allowed.
            secrets_map: A map of secrets to load.
                If a secret is not found in the map, it will be loaded from the
                environment if `secrets_from_env` is `True`.
            valid_namespaces: Additional namespaces (modules) to allow during
                deserialization, beyond the default trusted namespaces.
            secrets_from_env: Whether to load secrets from the environment.
            additional_import_mappings: A dictionary of additional namespace mappings.

                You can use this to override default mappings or add new mappings.

                When `allowed_objects` is `None` (using defaults), paths from these
                mappings are also added to the allowed class paths.
            ignore_unserializable_fields: Whether to ignore unserializable fields.
            init_validator: Optional callable to validate kwargs before instantiation.

                If provided, this function is called with `(class_path, kwargs)` where
                `class_path` is the class path tuple and `kwargs` is the kwargs dict.
                The validator should raise an exception if the object should not be
                deserialized, otherwise return `None`.

                Defaults to `default_init_validator` which blocks jinja2 templates.
        r    zLiteral['all', 'core']zIterable[AllowedObject]N)rR   rP   DEFAULT_NAMESPACESrQ   rS   r&   r<   r-   r   copyrF   r'   r(   rJ   rN   rO   )
selfr;   rP   rQ   rR   rS   rN   rO   r*   r+   s
             r,   __init__zReviver.__init__  s5   \ !1&,"   5 4#34# 	
 +E*J' ..	+11
 + 	 o-01?C$& $ .."&"A"A"G"G"I 8JC,,005,,0078 (D.@$BVBV(D$ -I),r.   r+   c                    |j                  d      dk(  r|j                  d      dk(  rz|j                  d      i|d   \  }|| j                  v r| j                  |   S | j                  r8|t        j                  v r&t        j                  |   rt        j                  |   S y|j                  d      dk(  rB|j                  d      dk(  r.|j                  d      | j
                  ryd| }t        |      |j                  d      dk(  r~|j                  d      d	k(  ri|j                  d      W|d   ^ }}t        |d         }| j                  || j                  vrd
|d}t        |      |d   | j                  vs|dgk(  rd| }t        |      || j                  v r| j                  |   }|dd |d   }}n|d   t        v rd| d}t        |      |}|d   | j                  vrd| }t        |      t        j                  dj                  |            }	t!        |	|      }
t#        |
t$              sd| }t        |      |j                  di       }| j&                  | j'                  ||        |
di |S |S )a  Revive the value.

        Args:
            value: The value to revive.

        Returns:
            The revived value.

        Raises:
            ValueError: If the namespace is invalid.
            ValueError: If trying to deserialize something that cannot
                be deserialized in the current version of langchain-core.
            NotImplementedError: If the object is not implemented and
                `ignore_unserializable_fields` is False.
        lc   r@   secretidNnot_implementedz?Trying to load an object that doesn't implement serialization: constructorzDeserialization of a,   is not allowed. The default (allowed_objects='core') only permits core langchain-core classes. To allow trusted partner integrations, use allowed_objects='all'. Alternatively, pass an explicit list of allowed classes via allowed_objects=[...]. See langchain_core.load.mapping for the full allowlist.r   r   zInvalid namespace: zbTrying to deserialize something that cannot be deserialized in current version of langchain-core: .r0    )r4   rP   rR   osenvironrN   NotImplementedErrorrC   rF   r5   rQ   r<   DISALLOW_LOAD_FROM_PATH	importlibimport_modulejoingetattrrA   r   rO   )rW   r+   r*   r7   	namespacenamerH   import_path
import_dirmodclsr0   s               r,   __call__zReviver.__call__i  s   " IIdOq 		&!X-		$+$KESd&&&'',,$$

):rzz#zz#& IIdOq 		&!%66		$+00""'*  &c** IIdOq 		&!]2		$+!&tid,K ((4t'?'?? *+ 9N N  !o% !D$9$99-+E73 o%d222"22;?#.s#3[_D
1!88M"m1& 
 !o% '
 !}D$9$99+E73 o%))#((:*>?C#t$C c<0+E73 o% YYx,F"".##K8== r.   )r"   NNFN)__name__
__module____qualname____doc__r:   r   AllowedObjectr   dictstrr>   boolrC   InitValidatorrX   r   rq   rb   r.   r,   rL   rL     s     MS-1-1!&R- .3/ER-!-07=3IIR- #s(^d*R- s)d*	R-
 R- %)sCx%S/)I$J
%R- '+R- &,R- 
R-hmd38n m mr.   rL   r"   Fr;   rP   rQ   rR   rS   rN   rO   textrP   rQ   rR   rS   rN   rO   c          
      R    t        j                  |       }t        ||||||||      S )a	  Revive a LangChain class from a JSON string.

    Equivalent to `load(json.loads(text))`.

    Only classes in the allowlist can be instantiated. The default allowlist includes
    core LangChain types (messages, prompts, documents, etc.). See
    `langchain_core.load.mapping` for the full list.

    !!! warning "Beta feature"

        This is a beta feature. Please be wary of deploying experimental code to
        production unless you've taken appropriate precautions.

    Args:
        text: The string to load.
        allowed_objects: Allowlist of classes that can be deserialized.

            - `'core'` (default): Allow classes defined in the serialization mappings
                for `langchain_core`.
            - `'all'`: Allow classes defined in the serialization mappings.

                This includes core LangChain types (messages, prompts, documents, etc.)
                and trusted partner integrations. See `langchain_core.load.mapping` for
                the full list.

            - Explicit list of classes: Only those specific classes are allowed.
            - `[]`: Disallow all deserialization (will raise on any object).
        secrets_map: A map of secrets to load.

            If a secret is not found in the map, it will be loaded from the environment
            if `secrets_from_env` is `True`.
        valid_namespaces: Additional namespaces (modules) to allow during
            deserialization, beyond the default trusted namespaces.
        secrets_from_env: Whether to load secrets from the environment.
        additional_import_mappings: A dictionary of additional namespace mappings.

            You can use this to override default mappings or add new mappings.

            When `allowed_objects` is `None` (using defaults), paths from these
            mappings are also added to the allowed class paths.
        ignore_unserializable_fields: Whether to ignore unserializable fields.
        init_validator: Optional callable to validate kwargs before instantiation.

            If provided, this function is called with `(class_path, kwargs)` where
            `class_path` is the class path tuple and `kwargs` is the kwargs dict.
            The validator should raise an exception if the object should not be
            deserialized, otherwise return `None`.

            Defaults to `default_init_validator` which blocks jinja2 templates.

    Returns:
        Revived LangChain objects.

    Raises:
        ValueError: If an object's class path is not in the `allowed_objects` allowlist.
    r{   )jsonloadsload)	r|   r;   rP   rQ   rR   rS   rN   rO   raw_objs	            r,   r   r     s8    J jjG'))#=%A%	 	r.   objc          	      `   	 t        |||||||      	dt        dt        f	fd |       S )a  Revive a LangChain class from a JSON object.

    Use this if you already have a parsed JSON object, eg. from `json.load` or
    `orjson.loads`.

    Only classes in the allowlist can be instantiated. The default allowlist includes
    core LangChain types (messages, prompts, documents, etc.). See
    `langchain_core.load.mapping` for the full list.

    !!! warning "Beta feature"

        This is a beta feature. Please be wary of deploying experimental code to
        production unless you've taken appropriate precautions.

    Args:
        obj: The object to load.
        allowed_objects: Allowlist of classes that can be deserialized.

            - `'core'` (default): Allow classes defined in the serialization mappings
                for `langchain_core`.
            - `'all'`: Allow classes defined in the serialization mappings.

                This includes core LangChain types (messages, prompts, documents, etc.)
                and trusted partner integrations. See `langchain_core.load.mapping` for
                the full list.

            - Explicit list of classes: Only those specific classes are allowed.
            - `[]`: Disallow all deserialization (will raise on any object).
        secrets_map: A map of secrets to load.

            If a secret is not found in the map, it will be loaded from the environment
            if `secrets_from_env` is `True`.
        valid_namespaces: Additional namespaces (modules) to allow during
            deserialization, beyond the default trusted namespaces.
        secrets_from_env: Whether to load secrets from the environment.
        additional_import_mappings: A dictionary of additional namespace mappings.

            You can use this to override default mappings or add new mappings.

            When `allowed_objects` is `None` (using defaults), paths from these
            mappings are also added to the allowed class paths.
        ignore_unserializable_fields: Whether to ignore unserializable fields.
        init_validator: Optional callable to validate kwargs before instantiation.

            If provided, this function is called with `(class_path, kwargs)` where
            `class_path` is the class path tuple and `kwargs` is the kwargs dict.
            The validator should raise an exception if the object should not be
            deserialized, otherwise return `None`.

            Defaults to `default_init_validator` which blocks jinja2 templates.

    Returns:
        Revived LangChain objects.

    Raises:
        ValueError: If an object's class path is not in the `allowed_objects` allowlist.

    Example:
        ```python
        from langchain_core.load import load, dumpd
        from langchain_core.messages import AIMessage

        msg = AIMessage(content="Hello")
        data = dumpd(msg)

        # Deserialize using default allowlist
        loaded = load(data)

        # Or with explicit allowlist
        loaded = load(data, allowed_objects=[AIMessage])

        # Or extend defaults with additional mappings
        loaded = load(
            data,
            additional_import_mappings={
                ("my_pkg", "MyClass"): ("my_pkg", "module", "MyClass"),
            },
        )
        ```
    rM   r   r#   c                    t        | t              rGt        |       rt        |       S | j	                         D ci c]  \  }}| |       }}} |      S t        | t
              r| D cg c]
  } |       c}S | S c c}}w c c}w )N)r?   rw   r	   r
   r'   r>   )r   kv
loaded_objo_loadrevivers        r,   r   zload.<locals>._load  s    c4   $&s++ 36))+>$!Q!U1X+>J>:&&c4 &)*E!H**
	 ? +s   B-B)rL   r   )
r   r;   rP   rQ   rR   rS   rN   rO   r   r   s
           @@r,   r   r   +  sD    x "%A%G3 3  :r.   ),ru   rg   r~   rc   collections.abcr   r   typingr   r   r   langchain_core._apir   langchain_core.load._validationr	   r
   langchain_core.load.mappingr   r   r   r    langchain_core.load.serializabler   rU   rf   r&   r   rw   rx   r%   rC   __annotations__r-   r8   r:   r@   rv   rz   rJ   rL   r>   ry   r   r   rb   r.   r,   <module>r      so  FP   	 . % % $ M  : &  
!  	  ?A Dc%S/&:!:; @; /;sCx;8c3hcN 
>0c3h0cN0 
0& \"
 %S/4S>:D@A	,m,,%S/5c?:;, 	sCx,^J JZ  IO)-)-"PT).+AN
N m,w}/EEN c3h$&	N
 3i$&N N !%U38_eCHo%E F MN #'N "D(N 	N Nb  IO)-)-"PT).+As	s m,w}/EEs c3h$&	s
 3i$&s s !%U38_eCHo%E F Ms #'s "D(s 	s sr.   