
    'ff5                         d Z dZdZdZg dZd Zd'd	Zd(dZd)dZdddddddZ		 	 d*dZ
d+dZd,dZd-dZ	 	 d.dZ	 	 d/dZddi dfdZ	 	 d/d Z	 	 d0d#Z	 	 d1d$Zd2d%Z	 	 d/d&ZdS )3z@ezCLI : a toolbox for easy development of Command Line InterfacezChristophe Schlickz1.5z
2019-12-01)convertparseinjectgridpauseuserlooptimerinspecttestcoderead_txt	write_txtread_blk	write_blkread_csv	write_csvread_ini	write_inic                 J    t          | ddi          S # t          $ r | cY S w xY w)zconvert each literal expression in 'string' into its canonical data type

  - 'string' may contain an arbitrary sequence of comma-separated expressions
  - any non-convertible literal expression is simply returned as a string
  __builtins__ )eval	Exception)strings    E/net/cremi/pblasi100p/Bureau/espaces/www/pai/python/SOL-A/G1/ezCLI.pyr   r      s4     6N2.///	!!!6MMM!s    ""r    =c                    d } ||                                  ||          }|rt          |t                    r ||                                 ||          }t          t	          |                                          t	          |                                          z             }|                                |                                z
  }d|v rt          d          t          |          r%t          dd
                    |          z            |                                dhk    r|S |d         }t          |          dk    r|d         n|S )a  parse 'string' and return a tuple of values or a dictionary of named values

  string:str = input string to be parsed into values and/or named values
  default:str = optional string storing default values and named values
  vsep:str = separator string used between values 
  nsep:str = separator string used between name and value

  Note: almost arbitrary strings may be used for vsep and nsep, except
  that they cannot start with any of the 8 delimiters: ' " ( ) [ ] { }
  c                    g t          |          t          |          ddf\  }}}}}dt          d          t          d          t          |           f\  }}	}
}t          |          D ]\  }}|dk    r
|dv rd|z
  }|d	k    r
|d
v rd|z
  }%||v r|s|                    |           A||v rI|sG|                    |          |                    |d                   k    r|                                 | |||z            |k    r|s|s|	g|z  ||||z   <   | |||z            |k    r|s|s|
g|z  ||||z   <   dg id d                    |                              |	          D             }}|D ]}|	                    |
          s;|d                             t          |                                                     R|                    |
          ^ }}d |D             |                                }}|D ]!}t          |          |t          |          <   "|d         s|d= nt          |d                   |d<   |S )z>split 'string' into a dictionary of values and/or named valuesz([{z)]}          'r      r#   "r      r&   r   c                     g | ]}||S  r)   .0items     r   
<listcomp>z.parse.<locals>.splitstring.<locals>.<listcomp>:   s    NNNDN4NNN    c                 ^    g | ]*}|                                 |                                 +S r)   stripr+   names     r   r-   z.parse.<locals>.splitstring.<locals>.<listcomp>>   s-    CCCTdjjllCDJJLLCCCr.   )lenchrlist	enumerateappendfindpopjoinsplitcountr   r1   tuple)r   vsepnsepstackvlennlenenterleavestatevmodnmodcodencdicitemsr,   namesvalr3   s                       r   splitstringzparse.<locals>.splitstring#   sx    ')#d))SYYu&L#E4ueR#b''4<<?E4t$ 	% 	%1	
ceunnagee88%::e:U\\!____::e:::a==EJJuRy1111599;;;!AdF(t##E#%#QqvX!AdF(t##E#%#QqvX RNNBGGDMM,?,?,E,ENNNC ; ;ZZNs2w~~gdjjll.C.CDDDhJJt$$kucCCUCCCSYY[[Se::$gcllWT]]++:r7 #B#b'NN#b'Jr.   r   z"only named values are allowed herezunallowed names %r,r#   r   )r1   
isinstancestrdictr6   rM   keys
ValueErrorr4   	NameErrorr;   )r   defaultr?   r@   rP   rL   diffs          r   r   r      s+     B 	FLLNND$//# K'#P++gmmood4*P*P
tGMMOO$$tCIIKK'8'88
9
9C88::&D	Tzz$HIII	TJ)$8388D>>$IJJJXXZZB4B##c((a--AS8r.   ###Tc                     t          |rt          |          nd          }|D ],}|                     |t          |          |         d          } -| S )ad  replace all instances of 'pattern' in 'string' by items of 'cells'

  string:str = arbitrary string including several instances of 'pattern'
  cells:list = list of values that are sequentially injected in 'string' 
  pattern:str = string defining replacement pattern for injection
  trunc:bool = truncate (or not) cell content to the length of 'pattern'
  Nr#   )slicer4   replacerS   )r   cellspatterntrunccells        r   r   r   N   sQ     /G4
0
0%JJdfnnWc$ii6FJJVV	-r.   FNc                   	
 t          |           t          t          t           |                     c		fd| D             } t          d | D                       nk    rfd| D             } g d}|d|z  |z                                d          }d 
 
	
fd	|D             d
gz   d          }t	          |dd         | dz                                d          }|rdfdD             d	         d t          dz             D             }fd|D             }dd                    fdD                       z   g|dd<   d t          ||          D             }d                    |          S )a  return a string containing a 2D grid representation for 'matrix'

  matrix:list|tuple = 2D matrix containing arbitrary data in cells
  inner:bool = draw (or not) inner lines of the grid
  outer:bool = draw (or not) outer lines of the grid
  label:bool = add (or not) labels (letters for cols, digits for rows)
  size:int = horizontal size for each cell (default = compute best size)

  Note: the width of each cell is truncated to 'size' when provided
  c                 b    g | ]+}t                    D ]}|||d z            r||         nd,S )r#   r   )range)r+   linecolcolss      r   r-   zgrid.<locals>.<listcomp>g   s\     7 7 7%++7 7#& c#a%i0DIIb 7 7 7 7r.   c              3   N   K   | ] }t          t          |                    V  !d S Nr4   rS   )r+   rO   s     r   	<genexpr>zgrid.<locals>.<genexpr>j   s.      ..c#c((mm......r.   Nc                    g | ]}t          |t          t          f          s*t          |          d                                        n<t          |          d                                                                      S ri   )rR   intfloatrS   centerrjust)r+   rO   sizewidths     r   r-   zgrid.<locals>.<listcomp>n   s     N N N?B 1;3E{0K0K ;CHHUdUO""4(((S%4%&&u--44T::N N Nr.   )z    
, #  
,    
,    
u%     │ 
, #│ 
,──┼─
,  │ 
u/   ┌──┐
,│# │
,│  │
,└──┘
u5   ┌─┬┐
,│#││
,├─┼┤
,└─┴┘
r&   rQ   c                     | d         | d         |z  | d         z   |dz
  z  z   | d         |z  z   | d         z   | d         z   S )Nr   r#   r&         r)   )lstpqs      r   <lambda>zgrid.<locals>.<lambda>y   sG    3q63q6!8CF?QqS"99#a&(B3q6I#a&P r.   c                 *    g | ]} |          S r)   r)   )r+   framerg   repeatrq   s     r   r-   zgrid.<locals>.<listcomp>z   s'    ???&&d++???r.   r   r#   r'   #
z ABCDEFGHIJKLMNOQRSTUVWXYZc                 X    g | ]&}d d         D ]}||z                                    'S )r#   Nr0   )r+   abclabels      r   r-   zgrid.<locals>.<listcomp>~   s:    @@@VABBZ@@qskkmm@@@@r.   c                 B    g | ]}d D ]}|r|rt          |          ndS ))r#   r   r   )rS   r+   r   r   s      r   r-   zgrid.<locals>.<listcomp>   s9    OOOQOOA(a(c!fffSOOOOr.   c                 R    g | ]#}d t          t                              |fz  $S )z%*s rj   )r+   rrowss     r   r-   zgrid.<locals>.<listcomp>   s/    ;;;qfCII**;;;r.   r   c              3   B   K   | ]}|                               V  d S ri   )ro   )r+   rK   rq   s     r   rk   zgrid.<locals>.<genexpr>   s-       @ @A$ @ @ @ @ @ @r.   r   c                     g | ]
\  }}||z   S r)   r)   r   s      r   r-   zgrid.<locals>.<listcomp>   s     ///SQqQqS///r.   )r4   maxmapr<   r   rd   r;   zip)matrixinnerouterlabelrq   framesr{   rlabelr   rg   r|   r   rr   s       `   @@@@@r   r   r   Z   s&    6{{CC00*$7 7 7 77 7 7& ..v...
.
.%	\%44t||TUN N N N NFLN N N&E E E& 5

%
%c
*
*%PP&
&?????????Da
N
N%
ssVSX
.
.
4
4T
:
:%
 0)F@@@@V@@@$GFOO%Q--OOOF;;;;F;;;F @ @ @ @ @ @ @@@@AE!A#J//C..///E	5		r.   r~   )sependaskpromptokc                 D   |sd                     dd          }d |D             }fdt          |fz             D             d}}|D ]V}t          |t          ||                   | |d |dz   }	 t	          |          }	|	                                |v r|	c S |	sn-WdS )	a  'pause' is similar to 'print', but offers pause for user confirmation

  args:tuple = tuple of objects to be displayed sequentially on screen
  sep:str = string inserted between each object in 'args'
  end:str = string inserted after the last object, before the prompt
  ask:object = special value in 'args' that triggers prompt for user
  prompt:str = string displayed each time the 'ask' value is found
  ok:str|list|set|tuple = strings corresponding to allowed answers for
    the user input. All other strings are considered as invalid answers

  The function loops over the arguments in 'args' and displays them on
  screen, as the standard 'print' function. However, each time the
  special value stored in 'ask' is encountered, the 'prompt' string is
  displayed and the function pauses and waits for user confirmation.
  
  If the user enters an empty string (i.e. just hit the <ENTER> key),
  the display loop continues with the next object. If the user enters
  another string, the display loop is interrupted if this string is
  present in the 'ok' set. The prompt is repeated until the user enters
  either a string from 'ok' or an empty string. The function returns
  the string entered by the user or None if no interruption has occured
z' <ENTER> TO CONTINUE, <SPACE> TO BREAK O   u   ─c                 6    h | ]}|                                 S r)   )lowerr*   s     r   	<setcomp>zpause.<locals>.<setcomp>   s     $$$

$$$r.   c                 &    g | ]\  }}|k    |S r)   r)   )r+   rJ   argr   s      r   r-   zpause.<locals>.<listcomp>   s"    FFF#3#::!:::r.   N)r   r   r#   )ro   r7   printr\   inputr   )
r   r   r   r   r   argsstopsstartstopanswers
     `       r   r   r      s    . 
 K6==bJJF$$$$$"FFFF4;!7!7FFF%  d	4eD!!"5555tAvuV}}f	2		f}}}U  r.   r'   c                     ddl m} d }	d }
 d  t           fdd                                D                       }d	}|d
|dd         z  }|" |	 |	|d         |d                   |          }|d}||}|d}|r |
|           |r9|dz  }t	          d|                                z            }|                                dv r|r|rt          d          rn|                                dv r |
|           y|                                dv r |
|             |          }t          ||rdnd           n}# t          $ rp}t          |t                    rd|z  }n7d                     |                                            dd                   }t          |           |dz  }Y d}~nd}~ww xY w|9|r |
|           dS dS )a  command line loop with automatic user input processing and error checking 

  process:func = processing function called for each command line input
  prompt:str = message string displayed when waiting for user input
  hello:str = hello string displayed before starting the interactive loop
  bye:str = goodbye string displayed after ending the interactive loop
  usage:str = usage string displayed when user enters '?' or 'help'
  about:str = about string displayed when user enters '!' or 'about'
  safe:bool = ask (or not) for user confirmation before breaking loop
  n:int = number of iterations for interactive loop (default = infinite)
  r   )
format_excc                 D    |                      d          | r|rdndz   |z   S )Nr~   r   r0   )sts     r   ry   zuserloop.<locals>.<lambda>   s(    aggdmmq'>Q'>ttB?!C r.   c                 r    t          d                    d|                     d          df                    S )Nr~   u   ────────────────────────────────────────────────────────────────────────────────)r   r;   r1   r   s    r   ry   zuserloop.<locals>.<lambda>   s+    E$))[!''$--$MNNOO r.   Nc                     | S ri   r)   r   s    r   ry   zuserloop.<locals>.<lambda>   s    ! r.   c              3   T   K   | ]"}j                             d |z  d          V  #dS )z__%s__r   N)__globals__get)r+   r   processs     r   rk   zuserloop.<locals>.<genexpr>   sV       @ @ "&&x!|R88 @ @ @ @ @ @r.   z"file author date version doc usagez
Enter 'help' or '?' to display some user instructions
Enter 'about' or '!' to display some info about the application
Enter 'exit' or an empty line to stop the interaction loopz(File: %s
Author: %s
Date: %s
Version: %sru      zEnter command linezSee you later...r#   z<> %s: )r   exitr   r   )?help)!aboutr~   z	Error: %s)	tracebackr   r>   r<   r   r1   r   r   r   r   rR   AssertionErrorr;   
splitlines)r   r   hellobyeusager   saferJ   r   merger{   infohelpercommandoutputeerrors   `                r   r   r      sl    #"""""
C
C%
O
O%_g	 @ @ @ @6<<>>@ @ @ 
@ 
@$C 	 ]9D!HDE
]E%%QQ((00E^!F
]U[S
EE%LLL	 
FAeI677G}}+%%4d4u}}}4u}},&&eh}}-''ux''""E&f6Ldd"$M$M$M$M$M   	A~	&	& >aIIjjll5577<==EElllAFAAAAAA 	
 
 	%%*****s   ) E
 

GA&F??G  c                    ddl m} ddlm}  |            d         d         j         |            d         d         j        }}t          t          |                                          t          |                                          z             }|                                 } | 	                    d          | 
                    d          }	}| d|         d| |dz   |	         z   d	z   }}
	 t          |
|          }t          ||          } ||  nT# t          $ r, |g} ||  n # t          $ r t          d
| z            w xY wY nt          $ r t          d
| z            w xY w |            }t          d           t!          |          D ]} ||  | |            z  }|
dt#          |          dd         d} |st%          |          S t'          d| t%          |          |fz             dS )a  measure time required for 'n' successive executions of 'fcall'

  fcall:str = string defining the function call 'f(args)' to measure
    'f(args)' is evaluated in the namespace of the caller function, so
    'args' may contain expressions with either literals or binded names
  show:bool = display measured time on screen or return it as an float
  n:int = number of function calls performed during time measure

  Note: when the execution of 'fcall' fails, a 'RuntimeError' is raised   
  r   rA   )timer#   ()N[]zincorrect function call %rzP..TIMER IS RUNNING....TIMER IS RUNNING....TIMER IS RUNNING....TIMER IS RUNNING..r'   z#Timing for %s = %.3g sec (%s calls))r	   rA   r   	f_globalsf_localsrT   r6   rM   r1   r9   rfindr   	TypeErrorr   RuntimeErrorr   rd   rS   absr   )fcallshowrJ   rA   r   global_nameslocal_names	namespacerw   rx   r3   r   fchronos                 r   r   r      s&    #eggajm5uuwwqz!}7M,4**,,--[5F5F5H5H0I0IIJJ)
++--%uzz#C0@0@1RaRy#ac!e,s2$MT9Ad4&;&;tQQXXX	 O O O4NNNL)E)MNNNN !	LLL,'Ce'KLLLL466&5122288aQQXXXDDFF&c$ii"ooo>E	!c&kk!-FQ0GGHHHHHs*   /%D 
E&D('E&(EE&
E&P   c           	          ddl m} d d  |            d         d         j         |            d         d         j        }}t	          |                                          t	          |                                          z   }h dh dt          fd|D                       t           t                    r fd	D              n-d
  	                    d          D              fd D               st          d          fd D             }t          t          t                               fd D             }	|z
  dz
  dddz   z  z   fd|D             }
t          t          d t!          |	|
          D                                 }|rt#          |ddind                    |          S )ay  inspect the values for a set of comma-separated variable names

  names:str = string containing a set of comma-separated variable names
    'names' gets a special meaning when it is set to bool instead of str
    - names=False: displays all non-hidden local and global variables
    - names=True: also displays hidden local and global variables
      where hidden names means all names starting with the '__' prefix
  show:bool = display values on screen or return them as a single string
  wrap:bool = wrap or truncate values exceeding maximal field width
  field:int = maximal field width before applying wrapping or truncating 
  r   r   c                 L    | d|dz  dz
           dz   | | dz  dz   d         z   S )zAremove the middle part of 'val' to get a string of length 'width'Nr&   z ... rt   r)   )rO   rr   s     r   r`   zinspect.<locals>.trunc  s6    {q
{g%UFAIaKLL(999r.   c                 (   g t          |           d}}}||z
  |k    rE|                     d|||z             }|                    | ||                    |dz   }||z
  |k    E|                    | |d                    |                    |          S )z>split and wrap 'val' to get a set of strings of length 'width'r   r   r#   N)r4   r   r8   r;   )rO   rr   offsetsplitsrJ   rw   rx   s          r   r<   zinspect.<locals>.split  s    s3xxqAF
A#++
))CAeG
$
$afmmC!H&=&=&=1Q3q A#++
MM#abb'6;;v#6#66r.   r#   >   typemethodmodulefunction	generatorbuiltin_function_or_method>   __spec__
__cached__
__loader__r   c                 `    g | ]*}|d          vrt          |d                   j        v(|+S r"   )r   __name__)r+   r,   discard_namesdiscard_typess     r   r-   zinspect.<locals>.<listcomp>"  sK     E E ETd1g].J.JT!W.mCC CCCr.   c                 B    g | ]}s|                     d           |S )__)
startswith)r+   r3   rN   s     r   r-   zinspect.<locals>.<listcomp>%  s/    NNNd5N8M8MNTNNNr.   c                 6    g | ]}|                                 S r)   r0   r2   s     r   r-   zinspect.<locals>.<listcomp>(  s     777dTZZ\\777r.   rQ   c                     g | ]}|v |	S r)   r)   r+   r3   r   s     r   r-   zinspect.<locals>.<listcomp>)  s#    999dty'8'8T'8'8'8r.   zno valid names to inspectc                      g | ]
}|         S r)   r)   r   s     r   r-   zinspect.<locals>.<listcomp>,  s    ...IdO...r.   c                 :    g | ]}|                               S r)   )ljust)r+   r3   lsizes     r   r-   zinspect.<locals>.<listcomp>/  s%    
/
/
/4::e
/
/
/r.   rt   r~   r   c                     g | ]f}t          t          |                    k    rt          |          n4s t          |                    n t          |                    gS r)   )r4   repr)r+   rO   r   rsizer<   r`   wraps     r   r-   zinspect.<locals>.<listcomp>3  s     O O O@C DII%//49996<UU499e5L5L5L!E$s))UF;;O O Or.   c              3   @   K   | ]}d                      |          V  dS z = Nr;   r*   s     r   rk   zinspect.<locals>.<genexpr>6  s.      FFT

4((FFFFFFr.   r   )r	   rA   r   r   r6   rM   rT   rR   boolr<   rW   r   r   r4   r>   sortedr   r   r;   )rN   r   r   fieldrA   r   r   rM   valueslhandrhandfieldsr   r   r   r   r   r   r<   r`   s   ` `         @@@@@@@@r   r	   r	      s}    : : :7 7 7 $eggajm5uuwwqz!}7M,
|!!##
$
$tK,=,=,?,?'@'@
@%2 2 2-GGG- E E E E EU E E E F F)t :NNNNiNNNEE 87ekk#&6&6777E9999e999E	<i ;<<<.......&
c#enn

%
/
/
/
/
/
/
/%
+a-%#uQw-&O O O O O O O OGMO O O% FFSu5E5EFFFFFGG&%)	@	!D	!	!	!tyy/@/@@r.   c           
         d }d }ddl m}  |            d         d         j         |            d         d         j        }}t	          t          |                                          t          |                                          z             } ||                     d                    D ]}	|	rt          |		                    d          rdnd	|	            ||	|          \  }
}|@t          |t                    r|rd}
t          |
dk    r1t          dd||dz             dd
                             dd          n|           t          d          r d
S d
S )a  loop over all statements of 'code' and eval/exec sequentially

  code:str = input string defining a sequence of Python statements
  wrap:bool = wrap or truncate values exceeding maximal field width
  field:int = maximal field width before applying wrapping or truncating 
  c                    dt          |                                           } }t          |           D ]R\  }}|dk    r|dv rd}t          d          | |<   $|dk    r
|dv rd|z
  }4|dk    r
|dv rd	|z
  }D|d
k    r|dk    rd}Sd d                    |                               t          d                    D             S )zEsplit 'code' at all newline characters, except those found in stringsr   r~   )r   rt   r!   r"   r#   r$   r%   r&   r}   rt   c                 6    g | ]}|                                 S r)   r0   )r+   re   s     r   r-   z/testcode.<locals>.splitcode.<locals>.<listcomp>O  s     AAATDJJLLAAAr.   r   )r6   lstripr7   r5   r;   r<   )rI   rF   rJ   rK   s       r   	splitcodeztestcode.<locals>.splitcodeA  s    T$++--((4E
 $ . .1	
du~~quCFF$q''88%88%88

AE BARWWT]]%8%8Q%@%@AAAAr.   c                 ,   dt          | |          fS # t          $ rI dt          | |          fcY S # t          $ r'}dt	          |          j        d|fcY d}~cY S d}~ww xY wt          $ r%}dt	          |          j        d|fcY d}~S d}~ww xY w)zCeval/exec 'statement', according to names and values in 'namespace'r#   r   r'   z: N)r   SyntaxErrorexecr   r   r   )	statementr   r   s      r   evalexecztestcode.<locals>.evalexecQ  s    4	9---	- I I IT)Y//////HHHBDGG4D4D4Daa(H$HHHHHHHHHHFFF"$q''2B2B2BAA&F"FFFFFFFFsF    
B1B
A"AA"BA""B.BBBr   r   r#   r~   r}   r   z>>> NrO   F   z
      r   )r	   rA   r   r   rT   r6   rM   r1   r   r   rR   rS   r]   r   )rI   r   r  r  r  rA   r   r   r   re   moderO   s               r   r
   r
   9  s   B B B G G G #eggajm5uuwwqz!}7M,4**,,--[5F5F5H5H0I0IIJJ)i

4(()) 	 	d DOOC00<bbf<ddCDDD(4++idC	h	C		//ataxx E5$a004<<ZMMM " " " "	2	 	r.   r   r#   utf8c           	      
   	 t          | d|          5 }|                                }|d         dk    r
|dd         }|r|                                }|||fdk    r|cddd           S ||fdk    r|dz   r|dz   nd}|                    |                    |          t          |||                             cddd           S # 1 swxY w Y   dS # t          $ r" dd	lm}	 t          d
 |	|           z            w xY w)ax  read a slice of lines from a TXT file and return a multi-line string

  filename:str = input filename
    filename may include absolute or relative path using '/' separators
  (start,stop,step):(int,int,int) = standard slice parameters for lines
    default values for (start,stop,step) returns the whole file content
    default values for (stop,step) returns the line at index 'start'
    any other combination returns the lines in slice(start,stop,step)
  sep:str = line separator string
  strip:bool = strip (or not) leading and trailing whitespaces
  encoding:str = standard Python codec identifier (e.g. 'latin1' or 'utf8')
  r   encodingr   u   ﻿r#   NNr   r#   r"   realpathzcannot read file '%s')	openreadr1   r;   r<   r\   OSErroros.pathr  )
filenamer   r   stepr   r1   r  filetextr  s
             r   r   r   l  s   
@	hh	/	/	/ ?4YY[[d	aH		T!""Xd	#tzz||
T	j	(	(	? ? ? ? ? ? ? ?
 t		q&BeAggdtXXdjjooeE$t&<&<=>>? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 
 @ @ @      
)HHX,>,>>
?
??@s<   C AC	C ,AC	<C 	CC CC ,Dc                    |||fdk    rt          | |                              |          }||fdk    r|dk     r|t          |          z   dz   n|x}}|                    |          |t          |||          <   |                    |          }	 t          | d|          5 }|                    |           |cddd           S # 1 swxY w Y   dS # t          $ r" ddlm	}	 t          d	 |	|           z            w xY w)
a  replace or insert a multi-line string in the content of a text file

  filename:str = output filename
    filename may include absolute or relative path using '/' separators
  string:str = string to be written in file
  (start,stop,step):(int,int,int) = standard slice parameters for lines
    default values for (start,stop,step) replaces the whole file content
    default values for (stop,step) inserts string at line index 'start'
    any other combination replaces the lines in slice(start,stop,step)
  sep:str = line separator string
  encoding:str = standard Python codec identifier (e.g. 'latin1' or 'utf8')

  Note: the function always returns the whole file content as a string  
  r  r  r"   r   r#   wNr  zcannot write file '%s')
r   r<   r4   r\   r;   r  writer  r  r  )
r  r   r   r   r   r   r  linesr!  r  s
             r   r   r     s|     D*$$X11177<<ET{e05		ec%jj(1,,uEed&,ll3&7&7E%tT
"
"#XXe__FA	hh	/	/	/ (4
jj( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (	 A A A      
*XXh-?-??
@
@@As0   C $C;C CC CC ,Dc                    d }t          dd|fdt          fgt          |                                          z             }g t	          | ||          }}|                    |          D ]i}|D ]4}	|	r0||	         r(|                    |	          r ||	         |          } n5|d         r |d         |          }|r|                    |           j|S )aQ  return the content of a BLK file and process blocks by a set of filters

  filename:str = input filename
  sep:str = block separator string
  strip:bool = strip (or not) leading and trailing whitespaces
  filters:dict = dictionary of block filters as 'prefix:operator' items
    'prefix' are prefix strings characterizing the type of each block 
    'operator' are functions used to decode each block of a given type
    'None:operator' registers the filter used for block without a prefix
    'prefix:None' registers identity function as the filter for 'prefix'  
  encoding:str = standard Python codec identifier (e.g. 'latin1' or 'utf8')

  With default parse configuration, all blocks starting with '#' are
  removed, all space-indended blocks are returned after processing by
  'convert', and all other blocks, are simply returned unchanged.
  c                     d S ri   r)   blocks    r   ry   zread_blk.<locals>.<lambda>  s    t r.   )NNr}   r   )r1   r  N)rT   r   r6   rM   r   r<   r   r8   )
r  r   r1   filtersr  voidblocksr"  r*  keys
             r   r   r     s    $ 
	$+s4j#g7$w}}:O:OOPP'XhehGGG$&zz# # #e 5 5	 + +%"2"23"7"7 +U##UU	4e 4 4"fmmE"""	-r.   c           	          t          |t                    r|                    |          }nt          |t          t          f          s|g}t          | |                    d |D                       |||||          S )a  replace or insert a set of blocks in the content of a BLK file

  filename:str = output filename
  blocks:str|list|tuple = set of blocks to be written in file
    if blocks:str, it is written unchanged as a slice in file
    if blocks:list|tuple, each item is written as a new block in file
  (start,stop,step):(int,int,int) = standard slice parameters
    default values for (start,stop,step) replaces the whole file content
    default values for (stop,step) inserts blocks at line index 'start'
    any other combination replaces the lines in slice(start,stop,step)
  sep:str = block separator string
  encoding:str = standard Python codec identifier (e.g. 'latin1' or 'utf8')

  Note: the function always returns the whole file content as a string  
  c              3   P   K   | ]!}t          |t                    rd nd|V  "dS )r   r   N)rR   rS   )r+   r*  s     r   rk   zwrite_blk.<locals>.<genexpr>  s\       &* &* 7As6K6K 1	1e' &* &* &* &* &* &*r.   )rR   rS   r<   r6   r>   r   r;   )r  r-  r   r   r   r   r  s          r   r   r     s    " s >fll3&7&7VVfd5\**=fXF	8SXX &* &*"(&* &* &* * *+0$c8
M 
M Mr.   rQ   

c                    	 d 		fd}t          | |||dd|          }t          |          dk    r|n|d         S )a  return the content of a CSV file converted to a 1D, 2D or 3D matrix

  filename:str = input filename
  raw:bool = return cells as strings or apply 'convert' to each cell
  colsep:str = col separator string
  rowsep:str = row separator string
  sep:str = block separator string
  strip:bool = strip (or not) leading and trailing whitespaces
  encoding:str = standard Python codec identifier (e.g. 'latin1' or 'utf8')
  c                     fd|                      |          D             }t          |          dk    r|n|d         S )zDextract the CSV data stored in 'string' and return a 1D or 2D matrixc                 |    g | ]8}|                     d           fd|                              D             9S )r}   c                 ~    g | ]9}r|                                 n t          |                                           :S r)   )r1   r   )r+   ra   raws     r   r-   z4read_csv.<locals>.csv.<locals>.<listcomp>.<listcomp>  sJ     - - -  #=tzz|||

(=(= - - -r.   )r   r<   )r+   rowcolsepr6  s     r   r-   z)read_csv.<locals>.csv.<locals>.<listcomp>  sj     * * *14^^C((* - - - -))F++- - - * * *r.   r#   r   )r<   r4   )r   r6  r8  rowsepr   s    ``  r   csvzread_csv.<locals>.csv  s]    * * * * *8>V8L8L* * *F [[A%%666!94r.   c                       |           S ri   r)   )r*  r8  r:  r6  r9  s    r   ry   zread_csv.<locals>.<lambda>  s    SSVV<< r.   N)Nr}   r#   r   )r   r4   )
r  r6  r8  r9  r   r1   r  
csv_filterr   r:  s
    ```     @r   r   r     si    5 5 5 =<<<<<<*Hc5
*E*ExPP&v;;!##2r.   c	           	        
 d 

fd}	 
|          rt          |          }nt          
fd|D                       r)                    t          t           |                    }nWt          
fd |	|          D                       r#                    
fd|D                       }n
fd|D             }t	          | ||||||          S )aF  replace or insert a 1D, 2D or 3D matrix in the content of a CSV file

  filename:str = output filename
  matrix:str|list|tuple = matrix to be written in file
    if matrix:str, it is written unchanged at 'start' line index
    if matrix:list|tuple, it is first converted into a CSV string
  (start,stop,step):(int,int,int) = standard slice parameters for lines
    default values for (start,stop,step) replaces the whole file content
    default values for (stop,step) inserts matrix at line index 'start'
    any other combination replaces the lines in slice(start,stop,step)
  colsep:str = col separator string  
  rowsep:str = row separator string
  sep:str = block separator string
  encoding:str = standard Python codec identifier (e.g. 'latin1' or 'utf8')

  Note: the function always returns the whole file content as a string  
  c                 <    t          | t          t          f           S ri   )rR   r6   r>   )datas    r   ry   zwrite_csv.<locals>.<lambda>  s    JtT%L999 r.   c                 <    t          fd| D             g           S )Nc              3   R   K   | ]!} |          r|gnt          |          V  "d S ri   )r6   r+   msingles     r   rk   z.write_csv.<locals>.<lambda>.<locals>.<genexpr>  s<      EEA71##QEEEEEEr.   )sum)matrD  s    r   ry   zwrite_csv.<locals>.<lambda>  s&    SEEEEEEErJJ r.   c              3   .   K   | ]} |          V  d S ri   r)   rB  s     r   rk   zwrite_csv.<locals>.<genexpr>
  s+      
%
%66!99
%
%
%
%
%
%r.   c              3   .   K   | ]} |          V  d S ri   r)   rB  s     r   rk   zwrite_csv.<locals>.<genexpr>  s+      
+
+66!99
+
+
+
+
+
+r.   c              3      K   | ]F} |          rt          |          n'                    t          t           |                    V  Gd S ri   rS   r;   r   r+   r7  r8  rD  s     r   rk   zwrite_csv.<locals>.<genexpr>  sb       , ,  &,VC[[OSfkk#c#,,6O6O , , , , , ,r.   c                     g | ]>} |          rt          |          n!                    fd |D                       ?S )c              3      K   | ]F} |          rt          |          n'                    t          t           |                    V  Gd S ri   rJ  rK  s     r   rk   z'write_csv.<locals>.<listcomp>.<genexpr>  sg       7= 7=14 DJ6#;; 8-s3xxx;;s3s||,,7= 7= 7= 7= 7= 7=r.   )rS   r;   )r+   blkr8  r9  rD  s     r   r-   zwrite_csv.<locals>.<listcomp>  s     P P PAD !&++ =c#hhh6;; 7= 7= 7= 7= 7=8;7= 7= 7= ,= ,= P P Pr.   )rS   allr;   r   r   )r  r   r   r   r   r8  r9  r   r  flatrD  s        ``   @r   r   r     sA   ( :9&	J	J	J	J$VF^^ 	P[[FF

%
%
%
%f
%
%
%%% P[[S))FF

+
+
+
+dd6ll
+
+
+++ P[[ , , , , ,$*, , , , ,FFP P P P P PHNP P PF 
8VUD$X	F	FFr.   c                 H   d }d }d }|||d}di idddf\  }	}
}}t          | |||          dgz   D ]\  }}|dk    r<|r|r|nt          |          |	|
         |<   |                                dd}}}
i |	|
<   ng|d	k    r|d	z   |                                z   }nF|r|r|nt          |          |	|
         |<   |                                |                                }}|r|st          |d
|           t          |	          dk    r	|	d         }	n|	d         s|	d= |	S )a[  return the content of an INI file converted to a 2-level dictionary

  filename:str = input filename
  raw:bool = return values as strings or apply 'convert' to each value
  sep:str = line separator string
  strip:bool = strip (or not) leading and trailing whitespaces
  encoding:str = standard Python codec identifier (e.g. 'latin1' or 'utf8')
  c                 n    d|                      d          d                              d          d         fS )N:r   r#   r   r   )r<   r)  s    r   ry   zread_ini.<locals>.<lambda>  s/    sEKK$4$4Q$7$=$=c$B$B1$EF r.   c                 
    d| fS )Nr   r)   r)  s    r   ry   zread_ini.<locals>.<lambda>!  s
    sEl r.   c                 >    |                      d          d d d         S )Nr   r&   )	partitionr)  s    r   ry   zread_ini.<locals>.<lambda>#  s    us33CCaC8 r.   )Nr   r   r   )r+  r1   r  )r   r   rS  r   z	 in file r#   )r   r   r1   r  rstripr  r4   )r  r6  r   r1   r  sect_filtercont_filterprop_filterr+  rM   sectionr3   valuer  r  s                  r   r   r     sy    GF+**+99+;K@@'!#BR 3%$x(02 2 25<I> = =leU||	Fs&FeeuW~d#"[[]]BUtgRE'NN	#ckELLNN*ee	Fs&FeeuW~d#LLNNELLNNEd =T =555((;<<<ZZ1__eBiee9#%)	,r.   c           	          d }d t          |t                    r: ||          rd|i}d                    fd |          D                       }nt          |          }t	          | ||||||          S )a  replace or insert a set of items in the content of an INI file

  filename:str = output filename
  items:str|dict = set of items to be written in file
    if items:str, it is written unchanged at 'start' line index
    if items:dict, it is first converted into an INI string
  (start,stop,step):(int,int,int) = standard slice parameters for lines
    default values for (start,stop,step) replaces the whole file content
    default values for (stop,step) inserts items at line index 'start'
    any other combination replaces the lines in slice(start,stop,step)
  sep:str = line separator string
  encoding:str = standard Python codec identifier (e.g. 'latin1' or 'utf8')

  Note: the function always returns the whole file content as a string
  c                 Z    t          d |                                 D                        S )Nc              3   @   K   | ]}t          |t                    V  d S ri   )rR   rT   )r+   ds     r   rk   z.write_ini.<locals>.<lambda>.<locals>.<genexpr>I  s,      "L"L!:a#5#5"L"L"L"L"L"Lr.   )anyr  rL   s    r   ry   zwrite_ini.<locals>.<lambda>I  s(    s"L"Lszz||"L"L"LLLL r.   c                 D    t          |                                           S ri   )r  rM   rb  s    r   ry   zwrite_ini.<locals>.<lambda>K  s    fSYY[[)) r.   r   r~   c              3      K   | ]9\  }}|rd |z  ndd                     d  |          D                       z   V  :dS )z
[%s]
r   r~   c              3   *   K   | ]\  }}|d |V  dS r   r)   )r+   rJ   vs      r   rk   z&write_ini.<locals>.<genexpr>.<genexpr>N  sM       F, F,!qqqG F, F, F, F, F, F,r.   Nr   )r+   sectproporders      r   rk   zwrite_ini.<locals>.<genexpr>N  s       L L0:d -18zD((bDII F, F,$uT{{F, F, F, =, =, , L L L L L Lr.   )rR   rT   r;   rS   r   )	r  rM   r   r   r   r   r  
nosectionsri  s	           @r   r   r   7  s    $ ML*
)
)%d z%-2u+%II L L L L>CeEllL L L L LEEE

	8UE4sH	E	EEr.   )r   r   r   )rZ   T)TTFN)NNNNNNFr'   )Tr   )FTTr   )Tr   )Nr   r#   r~   Tr  )Nr   r#   r~   r  )FrQ   r~   r1  Tr  )Nr   r#   rQ   r~   r1  r  )Fr~   Tr  )__doc__
__author____version____date____all__r   r   r   r   r   r   r   r	   r
   r   r   r   r   r   r   r   r   r)   r.   r   <module>rp     s   F F"
F F F" " "59 59 59 59n
 
 
 
* * * *^ d2#          D 9=131 1 1 1lI I I I>7A 7A 7A 7Ar. . . .f DH@ @ @ @4 AEA A A A:  tR&    < AEM M M M, @F"(3 3 3 32 :;<B#G #G #G #GJ       D @DF F F F F Fr.   