
    -Ph!L                       d dl mZ d dlZd dlmZ d dlmZ d dlmZm	Z	m
Z
mZm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 d dlmZmZmZmZmZmZmZ d d	lm Z  d d
l!m"Z" d dl#m$Z$ erbd 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/m0Z0 d dl1m2Z2 d dl3m4Z4 d dl5m6Z6 d dl7m8Z8 d dl9m:Z: d dlm;Z; d dl<m=Z= d dl>m?Z? d dl@mAZB d dl#mCZCmDZDmEZE  ejF        eG          5  d dlmHZH ddd           n# 1 swxY w Y    G d de$d                   ZIdS )    )annotationsN)reduce)and_)TYPE_CHECKINGAnyIteratorMappingSequence)FunctionExpressionStarExpression)DeferredTimeZonecolevaluate_exprsgenerate_partition_by_sqllitnative_to_narwhals_dtype)ImplementationVersiongenerate_temporary_column_namenot_implementedparse_columns_to_dropparse_versionvalidate_backend_version
get_duckdb)InvalidOperationError)CompliantLazyFrame)
ModuleType)
Expression)DuckDBPyType)SelfTypeIs)CompliantDataFrameAny)
DuckDBExprDuckDBGroupByDuckDBNamespaceDuckDBInterchangeSeries)_FullContext)	LazyFrame)DType	DataFrame)AsofJoinStrategyJoinStrategyLazyUniqueKeepStrategy)SQLExpressionc                     e Zd Zej        Zdpd	Zedqd            Ze	drd            Z
dsdZdtdZdtdZdudZdvdZdwd!Zdxd#Zdyd(Zdzd+Zd{d-Zd|d0Zd|d1Zd}d6Zd7d8d~d:Zd|d;Zdd=Zedd?            ZeddA            ZddCZddEZddFZ ddGZ!ddLZ"ddOZ#ddWZ$dd\Z%dd]Z&ddaZ'ddfZ(ddgZ)ddhZ*ddmZ+ e,j-        dn          Z. e,j-        do          Z/ e,            Z0d7S )DuckDBLazyFramedfduckdb.DuckDBPyRelationbackend_versiontuple[int, ...]versionr   returnNonec                   || _         || _        || _        d | _        d | _        t          | j        | j                   d S N)_native_frame_version_backend_version_cached_native_schema_cached_columnsr   _implementation)selfr6   r8   r:   s       Z/var/www/html/test/jupyter/venv/lib/python3.11/site-packages/narwhals/_duckdb/dataframe.py__init__zDuckDBLazyFrame.__init__A   sG     79 /EI"15 !5t7LMMMMM    objduckdb.DuckDBPyRelation | AnyTypeIs[duckdb.DuckDBPyRelation]c                6    t          | t          j                  S r>   )
isinstanceduckdbDuckDBPyRelation)rI   s    rF   
_is_nativezDuckDBLazyFrame._is_nativeO   s    #v6777rH   datacontextr+   r!   c              2     | ||j         |j                  S Nr8   r:   )rA   r@   )clsrQ   rR   s      rF   from_nativezDuckDBLazyFrame.from_nativeS   s*     s'":GDT
 
 
 	
rH   argsr   kwdsILazyFrame[duckdb.DuckDBPyRelation] | DataFrameV1[duckdb.DuckDBPyRelation]c                    | j         t          j        u r| j                             | d          S ddlm}  || d          S )Nlazy)levelr   r.   interchange)r@   r   MAIN	lazyframenarwhals.stable.v1r/   )rE   rX   rY   DataFrameV1s       rF   to_narwhalszDuckDBLazyFrame.to_narwhals[   sU     =GL((=**4v*>>>??????{4}5555rH   c                N    | j         t          j        urd}t          |          | S )Nz=__narwhals_dataframe__ is not implemented for DuckDBLazyFrame)r@   r   V1AttributeError)rE   msgs     rF   __narwhals_dataframe__z&DuckDBLazyFrame.__narwhals_dataframe__e   s)    =
**QC %%%rH   c                    | S r>    rE   s    rF   __narwhals_lazyframe__z&DuckDBLazyFrame.__narwhals_lazyframe__l   s    rH   r   c                    t                      S r>   r   rk   s    rF   __native_namespace__z$DuckDBLazyFrame.__native_namespace__o   s    ||rH   r(   c                <    ddl m}  || j        | j                  S )Nr   r'   rU   )narwhals._duckdb.namespacer(   rA   r@   )rE   r(   s     rF   __narwhals_namespace__z&DuckDBLazyFrame.__narwhals_namespace__r   s7    >>>>>> 14=
 
 
 	
rH   namestrr*   c                b    ddl m}  || j                            |          | j                  S )Nr   r)   )r:   )narwhals._duckdb.seriesr*   nativeselectr@   )rE   rr   r*   s      rF   
get_columnzDuckDBLazyFrame.get_columny   s<    CCCCCC&&t{'9'9$'?'?WWWWrH   Iterator[Expression]c              #  @   K   | j         D ]}t          |          V  d S r>   )columnsr   )rE   rr   s     rF   _iter_columnszDuckDBLazyFrame._iter_columns~   s2      L 	 	Dd))OOOO	 	rH   backend(ModuleType | Implementation | str | Nonekwargsr#   c                "   ||t           j        u rBdd l}ddlm}  || j                                        t          |          | j        d          S |t           j	        u rMdd l
}ddlm}  || j                                        t           j	        t          |          | j        d          S |t           j        u rAdd l}ddlm}  || j                                        t          |          | j                  S d	| }	t'          |	          )
Nr   )ArrowDataFrameT)r8   r:   validate_column_names)PandasLikeDataFrame)implementationr8   r:   r   )PolarsDataFramerU   zUnsupported `backend` value: )r   PYARROWpyarrownarwhals._arrow.dataframer   rv   arrowr   r@   PANDASpandasnarwhals._pandas_like.dataframer   r6   POLARSpolarsnarwhals._polars.dataframer   pl
ValueError)
rE   r}   r   par   pdr   r   r   rg   s
             rF   collectzDuckDBLazyFrame.collect   s`    ?g)???    @@@@@@!>!!## -b 1 1&*	    n+++KKKKKK&&  -4 -b 1 1&*    n+++BBBBBB"?  -2C2CT]    8g77oorH   nintc                \    |                      | j                            |                    S r>   )_with_nativerv   limit)rE   r   s     rF   headzDuckDBLazyFrame.head   s&      !2!21!5!5666rH   column_namesc                F    |                       | j        j        |           S r>   )r   rv   rw   )rE   r   s     rF   simple_selectzDuckDBLazyFrame.simple_select   s#      !3!3\!BCCCrH   exprsr$   c                    d t          | g|R  D             }|                     | j                            |                    S )Nc                >    g | ]\  }}|                     |          S rj   alias.0rr   vals      rF   
<listcomp>z-DuckDBLazyFrame.aggregate.<locals>.<listcomp>   s&    SSSsSYYt__SSSrH   )r   r   rv   	aggregaterE   r   	selections      rF   r   zDuckDBLazyFrame.aggregate   sI    SSnT6RE6R6R6RSSS	  !6!6y!A!ABBBrH   c                t    d t          | g|R  D             }|                      | j        j        |           S )Nc              3  F   K   | ]\  }}|                     |          V  d S r>   r   r   s      rF   	<genexpr>z)DuckDBLazyFrame.select.<locals>.<genexpr>   s0      SSsSYYt__SSSSSSrH   )r   r   rv   rw   r   s      rF   rw   zDuckDBLazyFrame.select   sF    SSnT6RE6R6R6RSSS	  !3!3Y!?@@@rH   r{   Sequence[str]strictboolc                   t          | ||          fd| j        D             }|                      | j        j        |           S )N)r   c              3  $   K   | ]
}|v|V  d S r>   rj   )r   rr   columns_to_drops     rF   r   z'DuckDBLazyFrame.drop.<locals>.<genexpr>   s-      RRdd/6Q6QT6Q6Q6Q6QRRrH   )r   r{   r   rv   rw   )rE   r{   r   r   r   s       @rF   dropzDuckDBLazyFrame.drop   sS    /gfMMMRRRRdlRRR	  !3!3Y!?@@@rH   N)r}   Implementation | Nonec               ,    |d}t          |          | S )Nz.`backend` argument is not supported for DuckDB)r   )rE   r}   rg   s      rF   r\   zDuckDBLazyFrame.lazy   s     
 BCS//!rH   c                   t          t          | g|R            fd| j        D             }|                    d                                 D                        |                      | j        j        |           S )Nc                    g | ]=}|v r(                     |                              |          nt          |          >S rj   )popr   r   )r   rr   new_columns_maps     rF   r   z0DuckDBLazyFrame.with_columns.<locals>.<listcomp>   s`     
 
 
  && %%++D111T
 
 
rH   c              3  F   K   | ]\  }}|                     |          V  d S r>   r   )r   rr   values      rF   r   z/DuckDBLazyFrame.with_columns.<locals>.<genexpr>   s2      SSKD%ekk$''SSSSSSrH   )dictr   r{   extenditemsr   rv   rw   )rE   r   resultr   s      @rF   with_columnszDuckDBLazyFrame.with_columns   s    ~d;U;;;<<
 
 
 
 	
 
 
 	SS?;P;P;R;RSSSSSS  !3!3V!<===rH   	predicatec                ~     ||           d         }|                      | j                            |                    S )Nr   )r   rv   filter)rE   r   masks      rF   r   zDuckDBLazyFrame.filter   s8    yq!  !3!3D!9!9:::rH   dict[str, DType]c                      j         1t          t           j         j        j                             _         t           j                   fdt           j        j         j        j                  D             S )Nc                D    i | ]\  }}|t          |j                  S rj   )r   r@   )r   column_nameduckdb_dtypedeferred_time_zonerE   s      rF   
<dictcomp>z*DuckDBLazyFrame.schema.<locals>.<dictcomp>   sF     
 
 
 *\ 1dm-? 
 
 
rH   )rB   r   zipr{   rv   typesr   )rE   r   s   `@rF   schemazDuckDBLazyFrame.schema   s    %- *.c$,@Q.R.R)S)SD&-dk::
 
 
 
 
 .11DdkFW-X-X	
 
 
 	
rH   	list[str]c                v    | j         ,| j        t          | j                  n| j        j        | _         | j         S r>   )rC   rB   listr   rv   r{   rk   s    rF   r{   zDuckDBLazyFrame.columns   sC    ' -9 T[!!![(  
 ##rH   pd.DataFramec                    dd l }t          |          dk    r| j                                        S d|j         }t          |          )Nr   )   r   r   z5Conversion to pandas requires 'pandas>=1.0.0', found )r   r   rv   r6   __version__NotImplementedError)rE   r   rg   s      rF   	to_pandaszDuckDBLazyFrame.to_pandas   sP    	));>>###Z".ZZC%c***rH   pa.Tablec                4    | j                                         S r>   )rv   r   rk   s    rF   to_arrowzDuckDBLazyFrame.to_arrow   s    {  """rH   c                F    |                      | j        || j                  S )N)r:   r8   )	__class__rv   rA   )rE   r:   s     rF   _with_versionzDuckDBLazyFrame._with_version   s)    ~~K$:O  
 
 	
rH   c                F    |                      || j        | j                  S rT   )r   rA   r@   )rE   r6   s     rF   r   zDuckDBLazyFrame._with_native  s)    ~~ 5t}  
 
 	
rH   keys$Sequence[str] | Sequence[DuckDBExpr]drop_null_keysr&   c               *    ddl m}  || ||          S )Nr   r%   )r   )narwhals._duckdb.group_byr&   )rE   r   r   r&   s       rF   group_byzDuckDBLazyFrame.group_by  s-     	<;;;;;}T4GGGGrH   mappingMapping[str, str]c                |    | j         }fd|j        D             }|                      | j         j        |           S )Nc              3     K   | ]?}|v r(t          |                              |                   nt          |          V  @d S r>   )r   r   )r   rr   r   s     rF   r   z)DuckDBLazyFrame.rename.<locals>.<genexpr>  s`       
 
 /3gooCIIOOGDM***3t99
 
 
 
 
 
rH   )rv   r{   r   rw   )rE   r   r6   r   s    `  rF   renamezDuckDBLazyFrame.rename  sW    [
 
 
 


 
 
	   !3!3Y!?@@@rH   otherhowr1   left_onSequence[str] | Noneright_onsuffixc               h   |dk    rdn|}|dk    rj| j         dk     rd| j          }t          |          | j                            d                              |j                            d                    }n|J |J d t          ||          D             }	t          t          |	          }
| j                            d                              |j                            d          |
|	          }|d
v rd | j	        D             }|j	        D ]}|| j	        v }|dk    r)|s'|
                    t          d| d                     :|dk    s|rD|||vr>|
                    t          d| d                              | |                      |||vr"|
                    t          |                      |j        |                     | j        j                  }n2|                    d                              | j        j                  }|                     |          S )Nfulloutercross)r   r      z;'duckdb>=1.1.4' is required for cross-join, found version: lhsrhsc              3  l   K   | ]/\  }}t          d | d          t          d| d          k    V  0dS lhs.""rhs."Nr   r   leftrights      rF   r   z'DuckDBLazyFrame.join.<locals>.<genexpr>+  sc        D% ODOOO$$,<E,<,<,<(=(==     rH   )	conditionr   >   r   r   innerr   c                4    g | ]}t          d | d          S )r   r   r   )r   xs     rF   r   z(DuckDBLazyFrame.join.<locals>.<listcomp>8  s(    >>>Ac,!,,,''>>>rH   r   r   lhs.*)rA   r   rv   	set_aliasr   r   r   r   joinr{   appendr   r   rw   r   )rE   r   r   r   r   r   
native_howrg   relitr   rw   rr   
col_in_lhsress                  rF   r  zDuckDBLazyFrame.join  sr    !$vWW3
  $y00kTXTikk)#...+''..44U\5K5KE5R5RSSCC &&&''' #&w#9#9  B %+4$4$4I+''..33&&u--#	 4  C <<<>>>>>F 	- 	-#'4<#7
(((MM#odooo"6"67777 G++ ,$,$4H8L8LMM#odooo"6"6"<"<=Nf=N=N"O"OPPPP%X)=)=MM#d)),,,#*f%//0ABBCC**W%%//0ABBC  %%%rH   by_leftby_rightstrategyr0   c          	     T   | j         }|j         }	g }
|0|.|
                    d t          ||          D                        ng x}}|dk    r<|
                    t	          d| d          t	          d| d          k               nS|dk    r<|
                    t	          d| d          t	          d| d          k               nd}t          |          t          t          |
          }dg}|	j        D ]k}||j        v r(|||h|vr|                    d| d	| | d           3|||h|vr/|                    t          t	          |                               ld
d
                    |           d| d}|                     t          j        |                    S )Nc              3  l   K   | ]/\  }}t          d | d          t          d| d          k    V  0dS r   r   r   s      rF   r   z,DuckDBLazyFrame.join_asof.<locals>.<genexpr>X  sc        D% ODOOO$$,<E,<,<,<(=(==     rH   backwardr   r   r   forwardzKOnly 'backward' and 'forward' strategies are currently supported for DuckDBr  z" as "z
            SELECT ,zD
            FROM lhs
            ASOF LEFT JOIN rhs
            ON z
            )rv   r   r   r  r   r   r   r   r{   rs   r  r   rN   sql)rE   r   r   r   r  r  r  r   r   r   
conditionsrg   r   rw   rr   querys                   rF   	join_asofzDuckDBLazyFrame.join_asofI  s'    kl')
8#7  #&w#9#9      
 "$#Ghz!!c"4'"4"4"455=PX=P=P=P9Q9QQRRRR""c"4'"4"4"455=PX=P=P=P9Q9QQRRRR_C%c*** &tZ 8 8	K 	. 	.Ds{"" D0EH0E$E$EAdAA$AAAABBBB!T(1FX1F%F%Fc#d))nn---HHV$$  	     E!2!2333rH   c                    | j         S r>   )r   rk   s    rF   collect_schemazDuckDBLazyFrame.collect_schemax  s
    {rH   subsetkeepr2   c                  |dk    r|n|p| j         x}r|| j        dk     rd}t          |          |                     |          x}r|t	          d| j                   }t	          dg | j         |          }t          | }|dk    r|n|}	t          t          d           d| d                              |          }
t          t          d	t                                 d| d                              |          }| 
                    | j                            t                      |
|                              t          |	          t          d
          k                                  t          ||g                              S | 
                    | j                            d                    | j                                       S )Nany)r      zZAt least version 1.3 of DuckDB is required for `unique` operation
with `subset` specified.   none
row_numberz over ()countr   )exclude, )r{   rA   r   _check_columns_existr   r   r3   r   r   r   r   rv   rw   r   r   r   uniquer  )rE   r  r  subset_rg   erroridx_name
count_namepartition_by_sqlrr   idx_expr
count_exprs               rF   r(  zDuckDBLazyFrame.unique{  s    !%ffF4JdlK7 	$v--/  *#...11':::u 5aFFH7;TT\;T8;TUUJ87D!%::XD$%l33OO<LOOO eHoo  '%g~/?/?@@\\IY\\\ eJ  $$"">#3#3XzJJD		SVV+,,
H/EFFFGG  
   !3!3DIIdl4K4K!L!LMMMrH   by
descendingbool | Sequence[bool]
nulls_lastc                  t          |t                    r|gt          |          z  }|rd t          ||          D             }nd t          ||          D             }|                      | j        j        |           S )Nc              3     K   | ]]\  }}|s!t          |                                          n2t          |                                                                          V  ^d S r>   )r   r3  descr   rr   r6  s      rF   r   z'DuckDBLazyFrame.sort.<locals>.<genexpr>  sr        D$ /3UD		$$&&&D		8H8H8S8S8U8U     rH   c              3     K   | ]]\  }}|s!t          |                                          n2t          |                                                                          V  ^d S r>   )r   nulls_firstr6  r7  s      rF   r   z'DuckDBLazyFrame.sort.<locals>.<genexpr>  sr        D$ 04WD		%%'''T9I9I9U9U9W9W     rH   )rM   r   lenr   r   rv   sort)rE   r1  r3  r0  r
  s        rF   r;  zDuckDBLazyFrame.sort  s    j$'' 	0$B/J 		 "%b*"5"5  BB
 "%b*"5"5  B   !1!12!6777rH   c                    ||n| j         }t          t          d |D                       }|                     | j                            |                    S )Nc              3  X   K   | ]%}t          |                                          V  &d S r>   )r   	isnotnullr   rr   s     rF   r   z-DuckDBLazyFrame.drop_nulls.<locals>.<genexpr>  s4      &Q&Qs4yy':':'<'<&Q&Q&Q&Q&Q&QrH   )r{   r   r   r   rv   r   )rE   r  r)  keep_conditions       rF   
drop_nullszDuckDBLazyFrame.drop_nulls  sT    ".&&DL&Q&Q&Q&Q&QRR  !3!3N!C!CDDDrH   c                   | j         j        }|                                 }D ]*}||         }||j        k    rd| d}t	          |          +t                    dk    rd}t          |          t          d                   | j        }| j	        }
                                t          d          z  t          d          k    }	 |                    |	          j        fd|D              }
 |                    |	           j        fd|D              }|                     |
                    |                    S )	Nz-`explode` operation not supported for dtype `z`, expected List typer   zExploding on multiple columns is not supported with DuckDB backend since we cannot guarantee that the exploded columns have matching element counts.r   r:  c              3  j   K   | ]-}|v r#t          d                               |          n|V  .dS )unnestN)r   r   )r   rr   col_to_exploder{   s     rF   r   z*DuckDBLazyFrame.explode.<locals>.<genexpr>  sb          7?? #8^<<BB4HHH     rH   c              3  h   K   | ],}|v r"t          d                               |          n|V  -d S r>   )r   r   )r   rr   r{   s     rF   r   z*DuckDBLazyFrame.explode.<locals>.<genexpr>  sV         *.D		%%%d     rH   )r@   dtypesr  Listr   r:  r   r   rv   r{   r>  r   r   r   rw   r   union)rE   r{   rG  r   rr   dtyperg   r	  original_columnsnot_null_conditionnon_null_relnull_relrE  s    `          @rF   explodezDuckDBLazyFrame.explode  s   %$$&& 	1 	1D4LE##)E ) ) )  ,C000 $ w<<1^  &c***WQZk<+5577:L>;
 ;
 
FF =szz"455<     -	  
 :3::11229   ,  
   !3!3H!=!=>>>rH   onindexvariable_name
value_namec                h  
 |g n|
|
fd| j         D             n|}|dk    rd}t          |          |dk    rd}t          |          d                    d |D                       }| j        }d| d| d	| d
}	|                      t          j        |	          j        g 
||           S )Nc                    g | ]}|v|	S rj   rj   )r   cindex_s     rF   r   z+DuckDBLazyFrame.unpivot.<locals>.<listcomp>  s    :::Q!6//q///rH    z:`variable_name` cannot be empty string for duckdb backend.z7`value_name` cannot be empty string for duckdb backend.r&  c              3  N   K   | ] }t          t          |                    V  !d S r>   )rs   r   r?  s     rF   r   z*DuckDBLazyFrame.unpivot.<locals>.<genexpr>  s.      >>$s3t99~~>>>>>>rH   z(
            unpivot rel
            on z(
            into
                name "z"
                value "z"
            )r{   r   r  rv   r   rN   r  rw   )rE   rP  rQ  rR  rS  on_rg   
unpivot_onr	  r  rW  s             @rF   unpivotzDuckDBLazyFrame.unpivot  s    }%>@j::::$,::::bBNC%c***KC%c***YY>>#>>>>>
k  %	 
 #     $FJu$&J&J&Jz&JK
 
 	
rH   zO`LazyFrame.gather_every` is deprecated and will be removed in a future version.zG`LazyFrame.tail` is deprecated and will be removed in a future version.)r6   r7   r8   r9   r:   r   r;   r<   )rI   rJ   r;   rK   )rQ   r7   rR   r+   r;   r!   )rX   r   rY   r   r;   rZ   )r;   r!   )r;   r   )r;   r(   )rr   rs   r;   r*   )r;   ry   )r}   r~   r   r   r;   r#   )r   r   r;   r!   )r   rs   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;   r   )r;   r   )r:   r   r;   r!   )r6   r7   r;   r!   )r   r   r   r   r;   r&   )r   r   r;   r!   )r   r!   r   r1   r   r   r   r   r   rs   r;   r!   )r   r!   r   rs   r   rs   r  r   r  r   r  r0   r   rs   r;   r!   )r  r   r  r2   r;   r!   )r0  rs   r1  r2  r3  r   r;   r!   )r  r   r;   r!   )r{   r   r;   r!   )
rP  r   rQ  r   rR  rs   rS  rs   r;   r!   )1__name__
__module____qualname__r   DUCKDBrD   rG   staticmethodrP   classmethodrW   rc   rh   rl   rn   rq   rx   r|   r   r   r   r   rw   r   r\   r   r   propertyr   r{   r   r   r   r   r   r   r  r  r  r(  r;  rA  rO  r\  r   
deprecatedgather_everytailwith_row_indexrj   rH   rF   r5   r5   8   s        %+ON N N N 8 8 8 \8 
 
 
 [
6 6 6 6         
 
 
 
X X X X
   & & & &P7 7 7 7D D D DC C C CA A A AA A A A
 8<      	> 	> 	> 	>; ; ; ;
 
 
 
 X
 $ $ $ X$+ + + +# # # #
 
 
 


 
 
 

H H H HA A A A0& 0& 0& 0&d-4 -4 -4 -4^   N N N N<8 8 8 8E E E E
*? *? *? *?X
 
 
 
B .?-Y L &?%Q D %_&&NNNrH   r5   )r$   r7   rZ   )J
__future__r   
contextlib	functoolsr   operatorr   typingr   r   r   r	   r
   rN   r   r   narwhals._duckdb.utilsr   r   r   r   r   r   narwhals._utilsr   r   r   r   r   r   r   narwhals.dependenciesr   narwhals.exceptionsr   narwhals.typingr   r   r   r   r   r   r   r   duckdb.typingr    typing_extensionsr!   r"   narwhals._compliant.typingr#   narwhals._duckdb.exprr$   r   r&   rp   r(   ru   r*   r+   narwhals.dataframer,   narwhals.dtypesr-   ra   r/   rb   r0   r1   r2   suppressImportErrorr3   r5   rj   rH   rF   <module>rz     sg   " " " " " "                 B B B B B B B B B B B B B B  5 5 5 5 5 5 5 5                                 - , , , , , 5 5 5 5 5 5 . . . . . . W      !!!!!!******........@@@@@@000000777777::::::??????,,,,,,,,,,,,%%%%%%;;;;;;VVVVVVVVVVZ%% % %$$$$$$% % % % % % % % % % % % % % %H' H' H' H' H'	UH' H' H' H' H's   C,,C03C0