U
    Qht                     @  s  U 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
mZmZ ddlmZmZmZ ddlZddlmZmZmZmZ ddlmZmZmZmZ ejd	k redZeeZndd
lmZ ddlmZ erddlm Z  edddddddZ!ddddddZ"dddddZ#dddddZ$dddddZ%dd dd!d"Z&dddd#d$Z'dd%dd&d'Z(dddd(d)Z)dd%dd*d+Z*dddd,d-Z+dddd.d/Z,dddd0d1Z-dddd2d3Z.ej/fZ0d4e1d5< ejd	kre0ej/fZ0dddd6d7Z2ej3fZ4d8e1d9< ejd:kr.e4ej3fZ4dd;dd<d=Z5dddd>d?Z6e7d@Z8ddddAdBZ9ddddCdDZ:ddddEdFZ;ddddGdHZ<ddddIdJZ=ddddKdLZ>ejfZ?dMe1dN< e@e	dOre?e	jfZ?ddPdQdRdSZAdeejBd ejBd fZCde1dT< ddddUdVZDddddWdXZEejdYk rNddddZd[ZFndd\lGmHZH dd]dd^d[ZFejd	k rdddd_d`ZIdaddbdcddZJn dddded`ZIddddfddZJejdYk rejKfZLde1dg< n:ejd	k rejKejMfZLde1dg< nejKejMejNfZLde1dg< ejOZPde1dh< didjdkdlddmdndodpZQdddqdrdsZRddtdudvdwdxdydzZSddtdadvd{dxd|d}ZTddd~dddddZUddd~dddddZVedddddd~dddddZWddd~ddddddZXddd~ddddddZYddd~ddddddZZdddddZ[ddddddd~dd{dddZ\ejdk shd	ej  krddk rn nddjddddddddZ]nej^Z]ejd	krej_Z_nej`dddmdmdd{dddZ_dS )zoLogic for interacting with type annotations, mostly extensions, shims and hacks to wrap Python's typing module.    )annotationsN)	lru_cachepartial)TYPE_CHECKINGAnyCallable)TypeIs
deprecatedget_args
get_origin   )GlobalsNamespaceMappingNamespace
NsResolverget_module_ns_of   
   )EllipsisType)NoneType)	BaseModel)maxsizestrztuple[Any, ...])namereturnc                   s0   t  fddttfD }|s,td |S )zVGet the member named `name` from both `typing` and `typing-extensions` (if it exists).c                 3  s"   | ]}t | rt| V  qd S N)hasattrgetattr).0moduler    F./venv/lib/python3.8/site-packages/pydantic/_internal/_typing_extra.py	<genexpr>#   s     
 z1_get_typing_objects_by_name_of.<locals>.<genexpr>z>Neither `typing` nor `typing_extensions` has an object called )tupletypingtyping_extensions
ValueError)r   resultr!   r    r"   _get_typing_objects_by_name_of    s    r)   objectbool)objr   r   c                 C  s    t |D ]}| |kr dS qdS )zmReturn whether `obj` is the member of the typing modules (includes the `typing-extensions` one) named `name`.TF)r)   )r,   r   thingr!   r!   r"   _is_typing_name,   s    r.   r   )tpr   c                C  s   t | ddS )zReturn whether the provided argument is the `Any` special form.

    ```python {test="skip" lint="skip"}
    is_any(Any)
    #> True
    ```
    r   r    r.   r/   r!   r!   r"   is_any5   s    r2   c                C  s   t t| ddS )zReturn whether the provided argument is a `Union` special form.

    ```python {test="skip" lint="skip"}
    is_union(Union[int, str])
    #> True
    is_union(int | str)
    #> False
    ```
    Unionr    r.   r   r1   r!   r!   r"   is_union@   s    
r5   c                C  s   t t| ddS )zReturn whether the provided argument is a `Literal` special form.

    ```python {test="skip" lint="skip"}
    is_literal(Literal[42])
    #> True
    ```
    Literalr    r4   r1   r!   r!   r"   
is_literalM   s    r7   z	list[Any]c                C  s$   t | s| gS t| }dd |D S )zCReturn the values contained in the provided `Literal` special form.c                 S  s   g | ]}t |D ]}|qqS r!   )literal_values)r   valuexr!   r!   r"   
<listcomp>`   s     
  z"literal_values.<locals>.<listcomp>)r7   r
   )r/   valuesr!   r!   r"   r8   Z   s    r8   c                C  s   t t| ddS )zReturn whether the provided argument is a `Annotated` special form.

    ```python {test="skip" lint="skip"}
    is_annotated(Annotated[int, ...])
    #> True
    ```
    Z	Annotatedr    r4   r1   r!   r!   r"   is_annotatedc   s    r=   z
Any | Nonec                C  s   t | rt| d S dS )z;Return the type of the `Annotated` special form, or `None`.r   N)r=   r
   r1   r!   r!   r"   annotated_typen   s    r>   c                C  s   t t| ddS )zReturn whether the provided argument is a `Unpack` special form.

    ```python {test="skip" lint="skip"}
    is_unpack(Unpack[Ts])
    #> True
    ```
    ZUnpackr    r4   r1   r!   r!   r"   	is_unpacks   s    r?   c                C  s   t | rt| d S dS )z@Return the type wrapped by the `Unpack` special form, or `None`.r   N)r?   r
   r1   r!   r!   r"   unpack_type~   s    r@   c                C  s   t | ddS )zReturn whether the provided argument is the `Self` special form.

    ```python {test="skip" lint="skip"}
    is_self(Self)
    #> True
    ```
    ZSelfr    r0   r1   r!   r!   r"   is_self   s    rA   c                C  s(   t jdk rt| dS tt| ddS dS )zReturn whether the provided argument is a `NewType`.

    ```python {test="skip" lint="skip"}
    is_new_type(NewType('MyInt', int))
    #> True
    ```
    r   Z__supertype__ZNewTyper    N)sysversion_infor   r.   typer1   r!   r!   r"   is_new_type   s    

rE   c                C  s   | t jjkpt| t jjkS )zReturn whether the provided argument is the `Hashable` class.

    ```python {test="skip" lint="skip"}
    is_hashable(Hashable)
    #> True
    ```
    )collectionsabcHashabler   r1   r!   r!   r"   is_hashable   s    
rI   c                C  s   | t jjkpt| t jjkS )a  Return whether the provided argument is a `Callable`, parametrized or not.

    ```python {test="skip" lint="skip"}
    is_callable(Callable[[int], str])
    #> True
    is_callable(typing.Callable)
    #> True
    is_callable(collections.abc.Callable)
    #> True
    ```
    )rF   rG   r   r   r1   r!   r!   r"   is_callable   s    rJ   z-tuple[type[typing_extensions.ParamSpec], ...]_PARAMSPEC_TYPESc                C  s
   t | tS )zReturn whether the provided argument is a `ParamSpec`.

    ```python {test="skip" lint="skip"}
    P = ParamSpec('P')
    is_paramspec(P)
    #> True
    ```
    )
isinstancerK   r1   r!   r!   r"   is_paramspec   s    	rM   z1tuple[type[typing_extensions.TypeAliasType], ...]_TYPE_ALIAS_TYPES)r      z'TypeIs[typing_extensions.TypeAliasType]c                C  s
   t | tS )a  Return whether the provided argument is an instance of `TypeAliasType`.

    ```python {test="skip" lint="skip"}
    type Int = int
    is_type_alias_type(Int)
    #> True
    Str = TypeAliasType('Str', str)
    is_type_alias_type(Str)
    #> True
    ```
    )rL   rN   r1   r!   r!   r"   is_type_alias_type   s    rP   c                C  s   t | ddpt t| ddS )a  Return whether the provided argument is a `ClassVar` special form, parametrized or not.

    Note that in most cases, you will want to use the `is_classvar_annotation` function,
    which is used to check if an annotation (in the context of a Pydantic model or dataclass)
    should be treated as being a class variable.

    ```python {test="skip" lint="skip"}
    is_classvar(ClassVar[int])
    #> True
    is_classvar(ClassVar)
    #> True
    ZClassVarr    r4   r1   r!   r!   r"   is_classvar   s    rQ   z(((\w+\.)?Annotated\[)?(\w+\.)?ClassVar\[c                C  sb   t | s t|  }dk	r$t |r$dS d}t| tjr:| j}t| trH| }|dk	r^t|r^dS dS )a?  Return whether the provided argument represents a class variable annotation.

    Although not explicitly stated by the typing specification, `ClassVar` can be used
    inside `Annotated` and as such, this function checks for this specific scenario.

    Because this function is used to detect class variables before evaluating forward references
    (or because evaluation failed), we also implement a naive regex match implementation. This is
    required because class variables are inspected before fields are collected, so we try to be
    as accurate as possible.
    NTF)	rQ   r>   rL   r%   
ForwardRef__forward_arg__r   _classvar_rematch)r/   ZanntpZstr_annr!   r!   r"   is_classvar_annotation   s     
rV   c                C  s   t | ddpt t| ddS )zReturn whether the provided argument is a `Final` special form, parametrized or not.

    ```python {test="skip" lint="skip"}
    is_finalvar(Final[int])
    #> True
    is_finalvar(Final)
    #> True
    ZFinalr    r4   r1   r!   r!   r"   is_finalvar  s    
rW   c                C  s   t t| ddS )zReturn whether the provided argument is a `Required` special form.

    ```python {test="skip" lint="skip"}
    is_required(Required[int])
    #> True
    ZRequiredr    r4   r1   r!   r!   r"   is_required  s    rX   c                C  s   t t| ddS )zReturn whether the provided argument is a `NotRequired` special form.

    ```python {test="skip" lint="skip"}
    is_required(Required[int])
    #> True
    ZNotRequiredr    r4   r1   r!   r!   r"   is_not_required(  s    rY   c                C  s   t | ddS )zReturn whether the provided argument is the `NoReturn` special form.

    ```python {test="skip" lint="skip"}
    is_no_return(NoReturn)
    #> True
    ```
    ZNoReturnr    r0   r1   r!   r!   r"   is_no_return2  s    rZ   c                C  s   t | ddS )zReturn whether the provided argument is the `Never` special form.

    ```python {test="skip" lint="skip"}
    is_never(Never)
    #> True
    ```
    ZNeverr    r0   r1   r!   r!   r"   is_never=  s    r[   z.tuple[type[typing_extensions.deprecated], ...]_DEPRECATED_TYPESr	   zTypeIs[deprecated])r,   r   c                C  s
   t | tS )zrReturn whether the argument is an instance of the `warnings.deprecated` class or the `typing_extensions` backport.)rL   r\   )r,   r!   r!   r"   is_deprecated_instanceM  s    r]   _NONE_TYPESc                C  s   | t kS )a  Return whether the argument represents the `None` type as part of an annotation.

    ```python {test="skip" lint="skip"}
    is_none_type(None)
    #> True
    is_none_type(NoneType)
    #> True
    is_none_type(Literal[None])
    #> True
    is_none_type(type[None])
    #> False
    )r^   r1   r!   r!   r"   is_none_typeU  s    r_   c                C  s    ddl m} || tot| dS )zReturn whether the provided argument is a named tuple class.

    The class can be created using `typing.NamedTuple` or `collections.namedtuple`.
    Parametrized generic classes are *not* assumed to be named tuples.
    r   )lenient_issubclass_fields)Z_utilsr`   r$   r   )r/   r`   r!   r!   r"   is_namedtuplee  s    rb   r   	   c                C  s   dS )EReturn whether the provided argument is the `zoneinfo.ZoneInfo` type.Fr!   r1   r!   r!   r"   is_zoneinfo_typer  s    rf   ZoneInfozTypeIs[type[ZoneInfo]]c                C  s   | t kS )re   rg   r1   r!   r!   r"   rf   y  s    c                C  s   t | ddS )zAReturn whether the provided argument is the `Union` special form.r3   r    r0   r1   r!   r!   r"   origin_is_union  s    ri   z	type[Any])type_r   c                 C  s   t | tjS r   )rL   r%   _GenericAlias)rj   r!   r!   r"   is_generic_alias  s    rl   c                C  s   t | ddp| tjkS )zTReturn whether the provided argument is the `Union` special form or the `UnionType`.r3   r    )r.   types	UnionTyper1   r!   r!   r"   ri     s    c                C  s   t | tjtjfS r   )rL   rm   GenericAliasr%   rk   r1   r!   r!   r"   rl     s    WithArgsTypestyping_base   F)parent_depthforceintzdict[str, Any] | None)rs   rt   r   c                 C  s4   t | }|r|jS |jdks*|jjdkr.dS |jS )a  We allow use of items in parent namespace to get around the issue with `get_type_hints` only looking in the
    global module namespace. See https://github.com/pydantic/pydantic/issues/2678#issuecomment-1008139014 -> Scope
    and suggestion at the end of the next comment by @gvanrossum.

    WARNING 1: it matters exactly where this is called. By default, this function will build a namespace from the
    parent of where it is called.

    WARNING 2: this only looks in the parent namespace, not other parents since (AFAIK) there's no way to collect a
    dict of exactly what's in scope. Using `f_back` would work sometimes but would be very wrong and confusing in many
    other cases. See https://discuss.python.org/t/is-there-a-way-to-access-parent-nested-namespaces/20659.

    There are some cases where we want to force fetching the parent namespace, ex: during a `model_rebuild` call.
    In this case, we want both the namespace of the class' module, if applicable, and the parent namespace of the
    module where the rebuild is called.

    In other cases, like during initial schema build, if a class is defined at the top module level, we don't need to
    fetch that module's namespace, because the class' __module__ attribute can be used to access the parent namespace.
    This is done in `_namespace_utils.get_module_ns_of`. Thus, there's no need to cache the parent frame namespace in this case.
    Nz<module>)rB   	_getframef_localsf_backf_codeco_name)rs   rt   framer!   r!   r"   parent_frame_namespace  s    
r|   )argr   c                 C  s(   | dkrt S t| tr$t| dddS | S )a  Convert `None` to `NoneType` and strings to `ForwardRef` instances.

    This is a backport of the private `typing._type_convert` function. When
    evaluating a type, `ForwardRef._evaluate` ends up being called, and is
    responsible for making this conversion. However, we still have to apply
    it for the first argument passed to our type evaluation functions, similarly
    to the `typing.get_type_hints` function.
    NFTis_argumentis_class)r   rL   r   _make_forward_ref)r}   r!   r!   r"   _type_convert  s
    	
r   )ns_resolverztype[BaseModel]zNsResolver | Nonezdict[str, tuple[Any, bool]])r,   r   r   c          	      C  s   i }|pt  }t| jD ]}|jd}|rt|tjr:q||t |j	\}}|
 D ]Z\}}|drzt|||||< W q tk
r   |df||< Y qX qXt|||||< qXW 5 Q R X q|S )a  Collect annotations from a Pydantic model class, including those from parent classes.

    Args:
        obj: The Pydantic model to inspect.
        ns_resolver: A namespace resolver instance to use. Defaults to an empty instance.

    Returns:
        A dictionary mapping annotation names to a two-tuple: the first element is the evaluated
        type or the original annotation if a `NameError` occurred, the second element is a boolean
        indicating if whether the evaluation succeeded.
    __annotations___F)r   reversed__mro____dict__getrL   rm   GetSetDescriptorTypepushtypes_namespaceitems
startswithtry_eval_type	Exception	r,   r   hintsbaseannglobalnslocalnsr   r9   r!   r!   r"   get_model_type_hints  s     


r   zdict[str, Any]c          	   
   C  s   i }|pt  }t| jD ]d}|jd}|rt|tjr:q||2 |j	\}}|
 D ]\}}t|||||< qXW 5 Q R X q|S )zCollect annotations from a class, including those from parent classes.

    Args:
        obj: The class to inspect.
        ns_resolver: A namespace resolver instance to use. Defaults to an empty instance.
    r   )r   r   r   r   r   rL   rm   r   r   r   r   	eval_typer   r!   r!   r"   get_cls_type_hints  s    

r   zGlobalsNamespace | NonezMappingNamespace | Noneztuple[Any, bool])r9   r   r   r   c                 C  s<   t | } zt| ||dfW S  tk
r6   | df Y S X dS )a  Try evaluating the annotation using the provided namespaces.

    Args:
        value: The value to evaluate. If `None`, it will be replaced by `type[None]`. If an instance
            of `str`, it will be converted to a `ForwardRef`.
        localns: The global namespace to use during annotation evaluation.
        globalns: The local namespace to use during annotation evaluation.

    Returns:
        A two-tuple containing the possibly evaluated type and a boolean indicating
            whether the evaluation succeeded or not.
    TFN)r   eval_type_backport	NameErrorr9   r   r   r!   r!   r"   r     s
    r   c                 C  s   t | } t| ||S )a  Evaluate the annotation using the provided namespaces.

    Args:
        value: The value to evaluate. If `None`, it will be replaced by `type[None]`. If an instance
            of `str`, it will be converted to a `ForwardRef`.
        localns: The global namespace to use during annotation evaluation.
        globalns: The local namespace to use during annotation evaluation.
    )r   r   r   r!   r!   r"   r   3  s    r   z?`eval_type_lenient` is deprecated, use `try_eval_type` instead.)categoryc                 C  s   t | ||\}}|S r   )r   )r9   r   r   Zevr   r!   r!   r"   eval_type_lenientD  s    	r   ztuple[Any, ...] | None)r9   r   r   type_paramsr   c              
   C  s   zt | |||W S  tk
r } zRdt|kr0 t| tjs@td| jd}tj	dkrf|
|  n
t||W 5 d}~X Y nX dS )a  An enhanced version of `typing._eval_type` which will fall back to using the `eval_type_backport`
    package if it's installed to let older Python versions use newer typing constructs.

    Specifically, this transforms `X | Y` into `typing.Union[X, Y]` and `list[X]` into `typing.List[X]`
    (as well as all the types made generic in PEP 585) if the original syntax is not supported in the
    current Python version.

    This function will also display a helpful error if the value passed fails to evaluate.
    z"Unable to evaluate type annotation#Unable to evaluate type annotation .)r      N)_eval_type_backport	TypeErrorr   rL   r%   rR   AssertionErrorrS   rB   rC   Zadd_note)r9   r   r   r   emessager!   r!   r"   r   Q  s    

r   c                 C  s   zt | |||W S  tk
r } zht| tjr6t|s8 zddlm} W n( tk
rp   td| jd|Y nX || ||dd W Y S d }~X Y nX d S )Nr   )r   r   a  . If you are making use of the new typing syntax (unions using `|` since Python 3.10 or builtins subscripting since Python 3.9), you should either replace the use of new syntax with the existing `typing` constructs or install the `eval_type_backport` package.F)Ztry_default)	
_eval_typer   rL   r%   rR   is_backport_fixable_errorr   ImportErrorrS   )r9   r   r   r   r   r   r!   r!   r"   r   r  s&    r   c                 C  s.   t jdkrtj| |||dS t| ||S d S )N)r      )r   )rB   rC   r%   r   )r9   r   r   r   r!   r!   r"   r     s    
     r   r   )r   r   c                 C  s.   t | }tjdk r|dp,tjdk o,d|kS )Nr   z#unsupported operand type(s) for |: rc   z' object is not subscriptable)r   rB   rC   r   )r   msgr!   r!   r"   r     s    

r   )include_keysr   r   zCallable[..., Any]zset[str] | None)functionr   r   r   r   c          	      C  s   zt | tr| jj}n| j}W n6 tk
rT   t| }t | trL|d|  | Y S X |dkrft| }d}|dkr~t	| dd}i }|
 D ]L\}}|dk	r||krq|dkrt}nt |trt|}t||||||< q|S )a'  Return type hints for a function.

    This is similar to the `typing.get_type_hints` function, with a few differences:
    - Support `functools.partial` by using the underlying `func` attribute.
    - If `function` happens to be a built-in type (e.g. `int`), assume it doesn't have annotations
      but specify the `return` key as being the actual type.
    - Do not wrap type annotation of a parameter with `Optional` if it has a default value of `None`
      (related bug: https://github.com/python/cpython/issues/90353, only fixed in 3.11+).
    r   NZ__type_params__r!   )rL   r   funcr   AttributeErrorget_type_hintsrD   
setdefaultr   r   r   r   r   r   r   )	r   r   r   r   r   Z
type_hintsr   r   r9   r!   r!   r"   get_function_type_hints  s0    





r   )r   rd      )r   r   r   T)r   ztyping.ForwardRef)r}   r   r   r   c                C  s   t | |S )a5  Wrapper for ForwardRef that accounts for the `is_class` argument missing in older versions.
        The `module` argument is omitted as it breaks <3.9.8, =3.10.0 and isn't used in the calls below.

        See https://github.com/python/cpython/pull/28560 for some background.
        The backport happened on 3.9.8, see:
        https://github.com/pydantic/pydantic/discussions/6244#discussioncomment-6275458,
        and on 3.10.1 for the 3.10 branch, see:
        https://github.com/pydantic/pydantic/issues/6912

        Implemented as EAFP with memory.
        )r%   rR   )r}   r   r   r!   r!   r"   r     s    r   )r,   r   r   include_extrasr   c                 C  sd  t | ddri S t| tri }t| jD ]}|dkrPt tj|jddi }n|}|j	di }t|t
jrri }|dkrtt|n|}|dkr|dkr|| }}| D ]D\}	}
|
dkrtd}
t|
trt|
ddd}
t|
||}
|
||	< qq*|sttdrd	d
 | D S |S |dkrrt| t
jr<| j	}n&| }t|drV|j}q@t |di }|dkr|}n|dkr|}t | dd}|dkrt| tjri S t| dt| }t|}| D ]v\}	}
|
dkrtd}
t|
trt|
t| t
j dd}
t|
||}
|	|kr<||	 dkr<tj|
 }
|
||	< q|rR|S dd
 | D S )a  Taken verbatim from python 3.10.8 unchanged, except:
        * type annotations of the function definition above.
        * prefixing `typing.` where appropriate
        * Use `_make_forward_ref` instead of `typing.ForwardRef` to handle the `is_class` argument.

        https://github.com/python/cpython/blob/aaaf5174241496afca7ce4d4584570190ff972fe/Lib/typing.py#L1773-L1875

        DO NOT CHANGE THIS METHOD UNLESS ABSOLUTELY NECESSARY.
        ======================================================

        Return type hints for an object.

        This is often the same as obj.__annotations__, but it handles
        forward references encoded as string literals, adds Optional[t] if a
        default value equal to None is set and recursively replaces all
        'Annotated[T, ...]' with 'T' (unless 'include_extras=True').

        The argument may be a module, class, method, or function. The annotations
        are returned as a dictionary. For classes, annotations include also
        inherited members.

        TypeError is raised if the argument is not of a type that can contain
        annotations, and an empty dictionary is returned if no annotations are
        present.

        BEWARE -- the behavior of globalns and localns is counterintuitive
        (unless you are familiar with how eval() and exec() work).  The
        search order is locals first, then globals.

        - If no dict arguments are passed, an attempt is made to use the
          globals from obj (or the respective module's globals for classes),
          and these are also used as the locals.  If the object does not appear
          to have globals, an empty dictionary is used.  For classes, the search
          order is globals first then locals.

        - If one dict argument is passed, it is used for both globals and
          locals.

        - If two dict arguments are passed, they specify globals and
          locals, respectively.
        Z__no_type_check__Nr   r   FTr~   _strip_annotationsc                 S  s   i | ]\}}|t |qS r!   r%   r   r   ktr!   r!   r"   
<dictcomp>P  s    z"get_type_hints.<locals>.<dictcomp>__wrapped____globals__z- is not a module, class, method, or function.c                 S  s   i | ]\}}|t |qS r!   r   r   r!   r!   r"   r   }  s      )r   rL   rD   r   r   rB   modulesr   
__module__r   rm   r   dictvarsr   r   r   r   r   r%   
ModuleTyper   Z_allowed_typesr   Z_get_defaultsZOptional)r,   r   r   r   r   r   Zbase_globalsr   Zbase_localsr   r9   Znsobjdefaultsr!   r!   r"   r     st    0









r   )NN)NN)NN)NNN)NNN)NNN)T)NNF)a__doc__Z
__future__r   Zcollections.abcrF   rerB   rm   r%   warnings	functoolsr   r   r   r   r   r&   r   r	   r
   r   Z_namespace_utilsr   r   r   r   rC   rD   r   Ellipsisr   Zpydanticr   r)   r.   r2   r5   r7   r8   r=   r>   r?   r@   rA   rE   rI   rJ   Z	ParamSpecrK   r   rM   ZTypeAliasTyperN   rP   rQ   compilerT   rV   rW   rX   rY   rZ   r[   r\   r   r]   r6   r^   r_   rb   rf   Zzoneinforh   ri   rl   rk   rp   ro   rn   Z_Finalrq   r|   r   r   r   r   r   r   r   r   r   r   r   r   rR   r   Zno_type_checkr!   r!   r!   r"   <module>   s   

		


 $,         #       4*    