
    L                        S r SSKJr  SSKJr  SSKJr  SSKrSSKrSSKrSSKrSSK	r	SSK
r
 " S S\5      r " S S	\5      r " S
 S\5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      rS rg)a  Table formatting library.

We define a TableFormatter interface, and create subclasses for
several different print formats, including formats intended for both
human and machine consumption:

Human Consumption
-----------------

 PrettyFormatter: This prints ASCII-art bordered tables. Inspired
   by the prettytable python library. Example:

     +-----+---------------+
     | foo | longer header |
     +-----+---------------+
     | a   |             3 |
     |         ...         |
     | abc |           123 |
     +-----+---------------+

 SparsePrettyFormatter: This is a PrettyFormatter which simply
   doesn't print most of the border. Example:

      foo   longer header
     ----- ---------------
      a                 3
              ...
      abc             123

 PrettyJsonFormatter: Prints JSON output in a format easily
   read by a human. Example:

     [
       {
         "foo": "a",
         "longer header": 3
       },
       ...
       {
         "foo": "abc",
         "longer header": 123
       }
     ]

Machine Consumption
-------------------

  CsvFormatter: Prints output in CSV form, with minimal
    quoting, '\n' separation between lines, and including
    a header line. Example:

     foo,longer header
     a,3
     ...
     abc,123

  JsonFormatter: Prints JSON output in the most compact
    form possible. Example:

    [{"foo":"a","longer header":3},...,{"foo":"abc","longer header":123}]

Additional formatters can be added by subclassing TableFormatter and
overriding the following methods:
  __len__, __unicode__, AddRow, column_names, AddColumn

Formatters that require non-empty output to be valid should override
`_empty_output_meaningful`
For example JsonFormatter must emit '[]' to produce valid json.
    )absolute_import)division)print_functionNc                       \ rS rSrSrg)FormatterExceptiond    N)__name__
__module____qualname____firstlineno____static_attributes__r	       platform/bq/table_formatter.pyr   r   d   s    r   r   c                       \ rS rSrSrSrS rS rS rS r	S r
S	 rSS jrS rS rS rS rS r\S 5       rSS jrSS jrSrg
)TableFormatterh   zInterface for table formatters.Fc                 p    U R                   [        :X  a  [        S5      eUR                  SS5      U l        g)a  Initializes the base class.

Keyword arguments:
  skip_header_when_empty: If true, does not print the table's header
    if there are zero rows. This argument has no effect on
    PrettyJsonFormatter. Ignored by the Print method, but respected if
    calling str or unicode on the formatter itself. Print will emit nothing
    if there are zero rows, unless the format being emitted requires text
    to be valid (eg json).
z0Cannot instantiate abstract class TableFormatterskip_header_when_emptyFN)	__class__r   NotImplementedErrorgetr   )selfkwdss     r   __init__TableFormatter.__init__l   s4     ~~'
<> >"&((+CU"KDr   c                 *    [        [        U 5      5      $ N)boollenr   s    r   __nonzero__TableFormatter.__nonzero__|   s    D	?r   c                     [        S5      e)Nz'__len__ must be implemented by subclassr   r!   s    r   __len__TableFormatter.__len__   s    
G
HHr   c                 J    U R                  [        R                  " 5       5      $ r   )_EncodedStrsysgetdefaultencodingr!   s    r   __str__TableFormatter.__str__   s    C22455r   c                     [        S5      e)Nz+__unicode__ must be implemented by subclassr%   r!   s    r   __unicode__TableFormatter.__unicode__   s    
K
LLr   c                 `    U R                  5       R                  US5      R                  U5      $ )Nbackslashreplace)r/   encodedecode)r   encodings     r   r)   TableFormatter._EncodedStr   s.    $$X%799?9IJr   Nc                     U (       d  U R                   (       aV  U(       a  UO[        R                  n[        R                  R                  =(       d    Sn[	        U R                  U5      US9  g g )Nutf8)file)_empty_output_meaningfulr*   stdoutr5   printr)   )r   outputr9   r5   s       r   PrintTableFormatter.Print   sJ    t,, V3::d$$.hDX&T2 -r   c                     [        S5      e)z.Add a new row (an iterable) to this formatter.z&AddRow must be implemented by subclassr%   r   rows     r   AddRowTableFormatter.AddRow   s    
F
GGr   c                 8    U H  nU R                  U5        M     g)zAdd all rows to this table.NrC   r   rowsrB   s      r   AddRowsTableFormatter.AddRows   s    
kk# r   c                 ^    UR                  S/ 5      S:X  a  SOSnU R                  US   US9  g)z.Add a field as a new column to this formatter.typeSTRINGlrname)alignN)r   	AddColumn)r   fieldrQ   s      r   AddFieldTableFormatter.AddField   s1     99VR(H4C#ENN5=N.r   c                 8    U H  nU R                  U5        M     g)z+Convenience method to add a list of fields.N)rT   )r   fieldsrS   s      r   	AddFieldsTableFormatter.AddFields   s    
mmE r   c           	          U R                  U R                   Vs/ s H  o!R                  US5      PM     sn5        gs  snf )z2Add a dict as a row by using column names as keys. N)rC   column_namesr   )r   drP   s      r   AddDictTableFormatter.AddDict   s0    KKT->->?->TtR->?@?s   =c                     [        S5      e)z0Return the ordered list of column names in self.z,column_names must be implemented by subclassr%   r!   s    r   r\   TableFormatter.column_names   s     L
MMr   c                     [        S5      e)z#Add a new column to this formatter.z)AddColumn must be implemented by subclassr%   )r   column_namerQ   r   s       r   rR   TableFormatter.AddColumn   s    
I
JJr   c                     U=(       d    0 /[        U5      -  n[        X5       H  u  p4U R                  " U40 UD6  M     g)z*Add a series of columns to this formatter.N)r    ziprR   )r   r\   kwdssrc   r   s        r   
AddColumnsTableFormatter.AddColumns   s;    -bTC--E 5
nn[)D) 6r   )r   r   )rO   )r
   r   r   r   __doc__r:   r   r"   r&   r,   r/   r)   r>   rC   rI   rT   rX   r^   propertyr\   rR   rh   r   r	   r   r   r   r   h   sn    '"L I6MJ
3H
/
A N NK*r   r   c                      ^  \ rS rSrSrU 4S jrS rS r\SS j5       r	\S 5       r
\SS j5       r SS	 jrS
 rS rS rS rS rSS jr\S 5       rSrU =r$ )PrettyFormatter   z2Formats output as an ASCII-art table with borders.c                   > [         [        U ]
  " S	0 UD6  UR                  SS5      U l        UR                  SS5      U l        UR                  SS5      U l        / U l        / U l        / U l	        / U l
        / U l        SU l        g)
a  Initialize a new PrettyFormatter.

Keyword arguments:
  junction_char: (default: +) Character to use for table junctions.
  horizontal_char: (default: -) Character to use for horizontal lines.
  vertical_char: (default: |) Character to use for vertical lines.
junction_char+horizontal_char-vertical_char|   Nr	   )superrm   r   r   rp   rr   rt   rH   row_heights_column_namescolumn_widthscolumn_alignmentsheader_heightr   r   r   s     r   r   PrettyFormatter.__init__   s     
/4)1D1/37D88$5s;D/37DDIDDDDDr   c                 ,    [        U R                  5      $ r   )r    rH   r!   s    r   r&   PrettyFormatter.__len__   s    tyy>r   c                     U (       d  U R                   (       dC  [        R                  " U R                  5       U R	                  5       U R                  5       5      nO/ nSR                  U5      $ N
)r   	itertoolschainFormatHeader
FormatRowsFormatHrulejoinr   liness     r   r/   PrettyFormatter.__unicode__   sR    4..oo



t0$2B2B2DFe e99Ur   c                     X:  a  [        S5      eU S-  US-  :H  nX-
  S-  nU(       a  XD4$ U(       a  XDS-   4$ US-   U4$ )aJ  Compute information for centering a string in a fixed space.

Given two integers interval and size, with size <= interval, this
function computes two integers left_padding and right_padding with
  left_padding + right_padding + size = interval
and
  |left_padding - right_padding| <= 1.

In the case that interval and size have different parity,
left_padding will be larger iff left_justify is True. (That is,
iff the string should be left justified in the "center" space.)

Args:
  interval: Size of the fixed space.
  size: Size of the string to center in that space.
  left_justify: (optional, default: True) Whether the string
    should be left-justified in the center space.

Returns:
  left_padding, right_padding: The size of the left and right
    margins for centering the string.

Raises:
  FormatterException: If size > interval.
z!Illegal state in table formatting   rv   )r   )intervalsizeleft_justifysame_paritypaddings        r   CenteredPaddingPrettyFormatter.CenteredPadding   s^    6 BCCa<TAX.K1$G	k!!q['!!r   c                 j    S[        US5      -  n[        U 5      U::  a  U $ U SU[        U5      -
   U-   $ )z0Abbreviate a string to at most width characters..   N)minr    )swidthsuffixs      r   
AbbreviatePrettyFormatter.Abbreviate  s?     3ua= FA%1EQ';F(;%<v%EEr   c                 $   U R                  5       =(       d    S/ Vs/ s H  n[        R                  XQ5      PM     nn[        U5      U:  a  [	        S[        U5      < SU< 35      eUS:X  a,  / n[
        R                  " SUS-   -  U[        U5      -
  5      nOUS:X  a\  [        R                  U[        U5      5      u  p[
        R                  " SUS-   -  U	5      n[
        R                  " SUS-   -  U
5      nOAUS:X  a,  / n[
        R                  " SUS-   -  U[        U5      -
  5      nO[        S	U< 35      e/ nU H  nUS:X  aP  [        R                  U[        R                  " U5      5      u  pUR                  SSU-  < U< SU-  < S35        MY  US
;   aD  SU[        R                  " U5      -
  -  nSnUS:X  a  XU4-  nOXU4-  nUR                  U5        M  [	        SU< 35      e   [
        R                  " X{U5      $ s  snf )a+  Format an entry into a list of strings for a fixed cell size.

Given a (possibly multi-line) entry and a cell height and width,
we split the entry into a list of lines and format each one into
the given width and alignment. We then pad the list with
additional blank lines of the appropriate width so that the
resulting list has exactly cell_height entries. Each entry
is also padded with one space on either side.

We abbreviate strings for width, but we require that the
number of lines in entry is at most cell_height.

Args:
  entry: String to format, which may have newlines.
  cell_width: Maximum width for lines in the cell.
  cell_height: Number of lines in the cell.
  align: Alignment to use for lines of text.
  valign: Vertical alignment in the cell. One of 't',
    'c', or 'b' (top, center, and bottom, respectively).

Returns:
  An iterator yielding exactly cell_height lines, each of
  exact width cell_width + 2, corresponding to this cell.

Raises:
  FormatterException: If there are too many lines in entry.
  ValueError: If the valign is invalid.
r[   zToo many lines (z) for a cell of size t r   cbzUnknown value for valign: )rN   rO   z %s%s rN   zUnknown alignment: )
splitlinesrm   r   r    r   r   repeatr   
ValueErrorwcwidthwcswidthappendr   )entry
cell_widthcell_heightrQ   valignlineentry_lines	top_linesbottom_linestop_paddingbottom_paddingcontent_linesleft_paddingright_paddingr   fmtr=   s                    r   
FormatCellPrettyFormatter.FormatCell  s   @ %%'/B4//D 	""44/   ;+%
k
K ) * *}i%%cZ!^&<&1C4D&DFl	3$3$C$C
s;'%)!k""3*q.#9;Gi%%cZ!^&<nMl	3l""3*q.#9#.[1A#ACi ABBM	#&5&E&E((.'0#,cM&9; 	<Jg&6&6t&<<=C<(&4(&V$ E!CDD   ??9\BBOs   Hc                    ^ ^ U=(       d    T R                   nU=(       d    T R                  nUU 4S jn[        [        XQXC5      6 nU 4S jU 5       $ )a{  Format a row into a list of strings.

Given a list of entries, which must be the same length as the
number of columns in this table, and a desired row height, we
generate a list of strings corresponding to the printed
representation of that row.

Args:
  entries: List of entries to format.
  row_height: Number of printed lines corresponding to this row.
  column_alignments: (optional, default self.column_alignments)
    The alignment to use for each column.
  column_widths: (optional, default self.column_widths) The widths
    of each column.

Returns:
  An iterator over the strings in the printed representation
  of this row.
c                 N   > TR                   R                  [        U 5      UTUS9$ )N)r   rQ   )r   r   str)r   r   rQ   
row_heightr   s      r   <lambda>+PrettyFormatter.FormatRow.<locals>.<lambda>l  s(    1J1JE
Ez 2K 2@r   c              3      >#    U  H8  nTR                   R                  [        R                  " S /US /5      5      v   M:     g7f)r[   N)rt   r   r   r   ).0cellsr   s     r   	<genexpr>,PrettyFormatter.FormatRow.<locals>.<genexpr>p  s=      '% ##IOORD%"$FGG%s   A A)r{   rz   rf   map)r   entriesr   r{   rz   curried_formatprinted_rowss   ` `    r   	FormatRowPrettyFormatter.FormatRowS  sU    * *CT-C-C!7T%7%7M@N	^m	GIL'%' 'r   c                 x    [         R                  " S5      nU R                  U R                  U R                  US9$ )z8Return an iterator over the row(s) for the column names.r   )r{   )r   r   r   r\   r|   )r   alignss     r   HeaderLinesPrettyFormatter.HeaderLiness  s;    c"F>>$++T-?-?,2  4 4r   c                     S U R                    5       nU R                  R                  [        R                  " S/US/5      5      /$ )z1Return a list containing an hrule for this table.c              3   t   #    U  H.  nS R                  [        R                  " SUS-   5      5      v   M0     g7f)r[   rs   r   N)r   r   r   )r   r   s     r   r   .PrettyFormatter.FormatHrule.<locals>.<genexpr>{  s4      0.5 wwy''UQY788.s   68r[   )rz   rp   r   r   r   )r   r   s     r   r   PrettyFormatter.FormatHruley  sB    0 ..0G##IOORD'B4$HIJJr   c                     [         R                  " U R                  5       U R                  5       U R                  5       5      $ )z?Return an iterator over the lines for the header of this table.)r   r   r   r   r!   s    r   r   PrettyFormatter.FormatHeader  s7    ??D,,.0@0@0BD Dr   c                 z    [         R                  " [        U R                  U R                  U R
                  5      6 $ )z3Return an iterator over all the rows in this table.)r   r   r   r   rH   rx   r!   s    r   r   PrettyFormatter.FormatRows  s(    ??C		4;K;KLMMr   c                    [        U5      [        U R                  5      :w  a  [        S[        U5      < 35      eU Vs/ s H&  n[        U5      R	                  5       =(       d    S/PM(     nnU R
                  R                  [        S U 5       5      5        S U 5       n[        X@R                  5       VVs/ s H  u  pV[        XV5      PM     snnU l	        U R                  R                  U5        gs  snf s  snnf )zAdd a row to this table.

Args:
  row: A list of length equal to the number of columns in this table.

Raises:
  FormatterException: If the row length is invalid.
zInvalid row length: r[   c              3   8   #    U  H  n[        U5      v   M     g 7fr   )r    )r   r   s     r   r   )PrettyFormatter.AddRow.<locals>.<genexpr>  s     C
uE


s   c              3   F   #    U  H  n[        S  U 5       5      v   M     g7f)c              3   N   #    U  H  n[         R                  " U5      v   M     g 7fr   r   r   r   r   s     r   r   3PrettyFormatter.AddRow.<locals>.<genexpr>.<genexpr>  s     5utGT""u   #%N)max)r   r   s     r   r   r     s"      OCM%5u555:s   !N)r    r\   r   r   r   rx   r   r   rf   rz   rH   )r   rB   r   
split_rowsrz   r   currents          r   rC   PrettyFormatter.AddRow  s     3x3t(())3s8EFFADE3u:((*2rd2JECC
CCDOCMOM "-1C1CDDNE 	EDD 	IIS Fs   -C6:C;c                    U (       a  [        S5      eUS;  a  [        SU< 35      e[        U5      R                  5       =(       d    S/nU R                  R	                  [        S U 5       5      5        U R                  R	                  U5        U R                  R	                  U5        [        [        U5      U R                  5      U l	        g)a  Add a column to this table.

Args:
  column_name: Name for the new column.
  align: (optional, default: 'l') Alignment for the new column entries.

Raises:
  FormatterException: If the table already has any rows, or if the
    provided alignment is invalid.
/Cannot add a new column to an initialized table)rN   r   rO   zInvalid column alignment: r[   c              3   N   #    U  H  n[         R                  " U5      v   M     g 7fr   r   r   s     r   r   ,PrettyFormatter.AddColumn.<locals>.<genexpr>  s     !KUT'"2"24"8"8Ur   N)
r   r   r   rz   r   r   r{   r\   r    r|   )r   rc   rQ   r   r   s        r   rR   PrettyFormatter.AddColumn  s     
;= =O#HII'')1bTEc!KU!KKL!!%([)SZ););<Dr   c                     U R                   $ r   ry   r!   s    r   r\   PrettyFormatter.column_names  s    r   )	ry   r{   rz   r|   rr   rp   rx   rH   rt   )T)rv   r   r   )NN)rN   )r
   r   r   r   rj   r   r&   r/   staticmethodr   r   r   r   r   r   r   r   rC   rR   rk   r\   r   __classcell__r   s   @r   rm   rm      s    :* #" #"J F F
 DC DCN 7;'@4KD
N*=,  r   rm   c                   8   ^  \ rS rSrSrU 4S jrS rS rSrU =r	$ )SparsePrettyFormatteri  z;Formats output as a table with a header and separator line.c                 Z   > SSS.nUR                  U5        [        [        U ]  " S0 UD6  g)z'Initialize a new SparsePrettyFormatter.r   )rp   rt   Nr	   )updaterw   r   r   )r   r   default_kwdsr   s      r   r   SparsePrettyFormatter.__init__  s1    %(%(*L	
/?,?r   c                     U (       d  U R                   (       d4  [        R                  " U R                  5       U R	                  5       5      nO/ nSR                  U5      $ r   )r   r   r   r   r   r   r   s     r   r/   !SparsePrettyFormatter.__unicode__  sA    4..ood//14??3DEee99Ur   c                 h    [         R                  " U R                  5       U R                  5       5      $ )z8Return an iterator over the header lines for this table.)r   r   r   r   r!   s    r   r   "SparsePrettyFormatter.FormatHeader  s%    ??4++-t/?/?/ABBr   r	   )
r
   r   r   r   rj   r   r/   r   r   r   r   s   @r   r   r     s    C@C Cr   r   c                   `   ^  \ rS rSrSrU 4S jrS rS rS rS r	\
S 5       rS	 rS
 rSrU =r$ )CsvFormatteri  zFormats output as CSV with header lines.

The resulting CSV file includes a header line, uses Unix-style
newlines, and only quotes those entries which require it, namely
those that contain quotes, newlines, or commas.
c                    > [         [        U ]
  " S0 UD6  [        R                  " 5       U l        / U l        [        R                  " U R
                  [        R                  SS9U l
        g )Nr   )quotinglineterminatorr	   )rw   r   r   ioStringIO_buffer_headercsvwriterQUOTE_MINIMAL_tabler}   s     r   r   CsvFormatter.__init__  sK    	,&..;;=DLDL**c//FDKr   c                 H    [        U R                  R                  5       5      $ r   )r   r   tellr!   s    r   r"   CsvFormatter.__nonzero__  s    !!#$$r   c                 H    [        U R                  R                  5       5      $ r   )r   r   getvaluer!   s    r   __bool__CsvFormatter.__bool__  s    %%'((r   c                 F    [        [        U 5      R                  5       5      $ r   )r    r   r   r!   s    r   r&   CsvFormatter.__len__  s    s4y##%&&r   c                     U (       d  U R                   (       d6  SR                  U R                  5      U R                  R	                  5       /nO/ nSR                  U5      R                  5       $ )N,r   )r   r   r  r   r  rstripr   s     r   r/   CsvFormatter.__unicode__  sP    4..xx%t||'<'<'>?ee 99U""$$r   c                      U R                   S S  $ r   )r  r!   s    r   r\   CsvFormatter.column_names  s    <<?r   c                 ^    U (       a  [        S5      eU R                  R                  U5        g Nr   )r   r  r   r   rc   r   s      r   rR   CsvFormatter.AddColumn  s'    
;= =LL$r   c                 :    U R                   R                  U5        g r   )r  writerowrA   s     r   rC   CsvFormatter.AddRow  s    KKr   )r   r  r  )r
   r   r   r   rj   r   r"   r  r&   r/   rk   r\   rR   rC   r   r   r   s   @r   r   r     sE    F%)'%  % r   r   c                   X   ^  \ rS rSrSrSrU 4S jrS rS r\	S 5       r
S rS	 rS
rU =r$ )JsonFormatteri  z)Formats output in maximally compact JSON.Tc                 J   > [         [        U ]
  " S0 UD6  / U l        / U l        g Nr	   )rw   r  r   _field_namesr  r}   s     r   r   JsonFormatter.__init__  s$    	-'/$/DDKr   c                 ,    [        U R                  5      $ r   )r    r  r!   s    r   r&   JsonFormatter.__len__  s    t{{r   c                 D    [         R                  " U R                  SSSS9$ )N)r  :TF)
separators	sort_keysensure_asciijsondumpsr  r!   s    r   r/   JsonFormatter.__unicode__	  s"    ::
dP Pr   c                      U R                   S S  $ r   )r!  r!   s    r   r\   JsonFormatter.column_names  s    Qr   c                 ^    U (       a  [        S5      eU R                  R                  U5        g r  )r   r!  r   r  s      r   rR   JsonFormatter.AddColumn  s)    
;= =[)r   c                     [        U5      [        U R                  5      :w  a  [        SU< 35      eU R                  R	                  [        [        U R                  U5      5      5        g )NzInvalid row: )r    r!  r   r  r   dictrf   rA   s     r   rC   JsonFormatter.AddRow  sK    
3x3t(())C9::KKtC 1 13789r   )r!  r  )r
   r   r   r   rj   r:   r   r&   r/   rk   r\   rR   rC   r   r   r   s   @r   r  r    s?    1!
P    *: :r   r  c                       \ rS rSrSrS rSrg)PrettyJsonFormatteri  z%Formats output in human-legible JSON.c                 F    [         R                  " U R                  SSSSS9$ )N)z, z: Tr   F)r'  r(  indentr)  r*  r!   s    r   r/   PrettyJsonFormatter.__unicode__   s&    :: r   r	   N)r
   r   r   r   rj   r/   r   r	   r   r   r6  r6    s
    -r   r6  c                   `   ^  \ rS rSrSrU 4S jrS rS rS rS r	S r
\S	 5       rS
 rSrU =r$ )NullFormatteri)  z'Formatter that prints no output at all.c                 J   > [         [        U ]
  " S0 UD6  / U l        / U l        g r   )rw   r;  r   ry   _rowsr}   s     r   r   NullFormatter.__init__,  s$    	-'/$/DDJr   c                 ,    [        U R                  5      $ r   )r   r=  r!   s    r   r"   NullFormatter.__nonzero__1  s    

r   c                 ,    [        U R                  5      $ r   )r    r=  r!   s    r   r&   NullFormatter.__len__4  s    tzz?r   c                     g)Nr[   r	   r!   s    r   r/   NullFormatter.__unicode__7  s    r   c                 :    U R                   R                  U5        g r   )r=  r   rA   s     r   rC   NullFormatter.AddRow:  s    JJcr   c                 8    U H  nU R                  U5        M     g r   rF   rG   s      r   rI   NullFormatter.AddRows=  s    
kk# r   c                      U R                   S S  $ r   r   r!   s    r   r\   NullFormatter.column_namesA  s    a  r   c                 :    U R                   R                  U5        g r   )ry   r   r  s      r   rR   NullFormatter.AddColumnE  s    k*r   )ry   r=  )r
   r   r   r   rj   r   r"   r&   r/   rC   rI   rk   r\   rR   r   r   r   s   @r   r;  r;  )  sB    /
 ! !+ +r   r;  c                     U S:X  a  [        5       nU$ U S:X  a  [        5       nU$ U S:X  a  [        5       nU$ U S:X  a  [        5       nU$ U S:X  a  [	        5       nU$ U S:X  a  [        5       nU$ [        SU -  5      e)z-Map a format name to a TableFormatter object.r  prettyr+  
prettyjsonsparsenonezUnknown format: %s)r   rm   r  r6  r   r;  r   )table_formattable_formatters     r   GetFormatterrT  I  s    U"nO 
 x%'O 
 v#oO 
 |#)+O 
 x+-O
 
	 v#oO 
 1L@
AAr   )rj   
__future__r   r   r   r  r   r   r+  r*   r   	Exceptionr   objectr   rm   r   r   r  r6  r;  rT  r	   r   r   <module>rX     s   DP '  % 
 	   
  R*V R*jxn xvCO C,,> ,^:N :@	- 	+N +@r   