
    #HJjf                       d Z ddlmZ ddlZddlZddlZddlmZmZm	Z	m
Z
 ddlZddlZddlZ	 ddlZddlZerddlmZ ddlmZ ddlmZmZ dd	lmZ dd
lmZ ej<                  j>                  j@                  ej<                  j>                  jB                  z  ej<                  j>                  jD                  z  Z# ejH                  e%      Z&e'e(e)fZ*	 dZ+	 dZ,	 dZ-	 dZ.	  G d de	      Z/ddZ0ddZ1dde-e,e.f	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZ2	 	 	 	 	 	 	 	 d dZ3 G d d      Z4 G d dejj                        Z6 G d dejj                        Z7 G d dejj                        Z8y# e$ r dZY 6w xY w)!zPImplements file-like objects for reading and writing to/from Azure Blob Storage.    )annotationsN)TYPE_CHECKINGAny	TypedDictcastT)TracebackType)IO)ReadableBufferWriteableBuffer)Self)TransportParamsazurei   i  @    c                  ,    e Zd ZU ded<   ded<   ded<   y)	_AzureUristrschemecontainer_idblob_idN)__name__
__module____qualname____annotations__     Z/Users/ahmed/devFolder/claude-voice/.venv/lib/python3.12/site-packages/smart_open/azure.pyr   r   >   s    KLr   r   c                    t         j                  j                  |       }|j                  t        k(  sJ |j
                  }|j                  j                  d      }|sd}|}n|}|}t        ||dS )zAParse an ``azure://`` URI into its container and blob components./z$root)r   r   r   )
smart_openutilssafe_urlsplitr   SCHEMEnetlocpathlstrip)uri_as_stringsrfirstsecondr   r   s         r   	parse_urir*   D   sk    				'	'	6B99IIEWW^^C F lwOOr   c                    t        |       }t        j                  j                  t        |      }t	        |d   |d   |fi |S )zIOpen an Azure Blob Storage URI using the given mode and transport params.r   r   )r*   r   r    check_kwargsopen)urimodetransport_params
parsed_urikwargss        r   open_urir3   V   sB    3J**41ABF
>*Jy,A4R6RRr   c                   |sd}t        |      |t        j                  j                  k(  r)t	        | |||t        j                  j
                  |      S |t        j                  j                  k(  rt        | ||||      S |t        j                  j                  k(  rt        | ||||      S d|d}t        |      )az  Open an Azure Blob Storage blob for reading or writing.

    Args:
        container_id: The name of the container this object resides in.
        blob_id: The name of the blob within the bucket.
        mode: The mode for opening the object.  Must be either "rb", "wb", or "ab".
        client: The Azure Blob Storage client to use when working with
            azure-storage-blob. May be a BlobServiceClient, ContainerClient, or
            BlobClient.
        blob_kwargs: Additional parameters to pass to
            ``BlobClient.commit_block_list`` (for "wb") or
            ``BlobClient.upload_blob`` (for "ab"). For writing only.
        buffer_size: The buffer size to use when performing I/O. For reading only.
        min_part_size: The minimum part size for multipart uploads. For writing
            only.
        max_concurrency: The number of parallel connections with which to
            download. For reading only.

    Returns:
        A file-like object for reading from or writing to the blob.

    Raises:
        ValueError: If no client is provided.
        NotImplementedError: If the requested mode is not supported.
    z/you must specify the client to connect to Azure)buffer_sizeline_terminatormax_concurrency)blob_kwargsmin_part_sizez$Azure Blob Storage support for mode z not implemented)
ValueErrorr   	constantsREAD_BINARYReaderBINARY_NEWLINEWRITE_BINARYWriterAPPEND_BINARYAppendWriterNotImplementedError)	r   r   r/   clientr8   r5   r9   r7   msgs	            r   r-   r-   ]   s    F ?oz##///#&00??+
 	
 z##000lGV\ijjz##111'6{R_
 	
 18H
IC
c
""r   c                   | }t        |d      r|j                  |      }t        |d      r,|j                  |k7  rd|j                  d|}t        |      t        |d      r|j	                  |      }t        d|      S )z<Return an Azure BlobClient for the given container and blob.get_container_clientcontainer_namezClient for z doesn't match container get_blob_clientazure.storage.blob.BlobClient)hasattrrG   rH   r:   rI   r   )rD   	containerblobobjrE   s        r   _get_blob_clientrO      s     Cs*+&&y1s$%#*<*<	*IC..11J9-Xos%&!!$'/55r   c                  2    e Zd ZdZddZddZd	d
dZd
dZy)
_RawReaderz Read an Azure Blob Storage file.c                <    || _         || _        d| _        || _        y Nr   )_blob_size	_position_concurrency)selfrM   sizeconcurrencys       r   __init__z_RawReader.__init__   s    

'r   c                (    || _         | j                   S )zSeek to the specified position (byte offset) in the Azure Blob Storage blob.

        Args:
            position: The byte offset from the beginning of the blob.

        Returns:
            The position after seeking.
        rV   )rX   positions     r   seekz_RawReader.seek   s     "~~r   c                    | j                   | j                  k\  ry| j                  |      }| xj                   t        |      z  c_         |S )Nr   )rV   rU   _download_blob_chunklen)rX   rY   binarys      r   readz_RawReader.read   s<    >>TZZ'**40#f+%r   c                   | j                   | j                  k(  ry|dk(  r2| j                  j                  | j                  | j                        }n2| j                  j                  | j                  | j                  |      }t
        j                  d| j                         t        |t        j                  j                  j                        r|j                         }n|j                         }t        d|      S )Nr   )offsetr7   )rg   r7   lengthz$reading with a max concurrency of %dbytes)rU   rV   rT   download_blobrW   loggerdebug
isinstancer   storagerM   StorageStreamDownloaderreadallrd   r   )rX   rY   streamrc   s       r   ra   z_RawReader._download_blob_chunk   s    ::'
 2:ZZ--T^^UYUfUf-gFZZ--~~t7H7HQU . F 	;T=N=NOfemm00HHI^^%F[[]FGV$$r   N)rM   rJ   rY   intrZ   rr   returnNone)r^   rr   rs   rr   rf   rY   rr   rs   ri   )r   r   r   __doc__r[   r_   rd   ra   r   r   r   rQ   rQ      s    *(
%r   rQ   c                  ^   e Zd ZU dZded<   dZded<   eej                  j                  e
f	 	 	 	 	 	 	 	 	 	 	 	 	 ddZddZedd	       Zdd
ZddZddZej                  j$                  fddZddZd d!dZd"d#dZd"d#dZd$dZd"d%dZd"d&dZd"d'dZd(dZ	 	 	 	 	 	 	 	 d)dZd*dZd*dZy)+r=   a  Reads bytes from Azure Blob Storage.

    Implements the io.BufferedIOBase interface of the standard library.

    Args:
        container: The name of the container the blob resides in.
        blob: The name of the blob within the container.
        client: The Azure Blob Storage client. May be a BlobServiceClient,
            ContainerClient, or BlobClient.
        buffer_size: The buffer size to use when performing I/O.
        line_terminator: The line terminator to use when reading lines.
        max_concurrency: The number of parallel connections with which to
            download.

    Raises:
        azure.core.exceptions.ResourceNotFoundError: Raised when the blob to read
            from does not exist.
    r   nameN$azure.storage.blob.BlobClient | NonerT   c                   || _         || _        t        |||      | _        | j                  1d| d| }t        j
                  j                  j                  |      	 | j                  j                         d   | _	        t        | j                  | j                  |      | _        d| _        t        j                  j!                  |      | _        || _        y # t        $ r
 d| _	        Y kw xY w)Nzblob z not found in rY   r   )_container_name
_blob_namerO   rT   r   core
exceptionsResourceNotFoundErrorget_blob_propertiesrU   KeyErrorrQ   _raw_readerrV   r   
bytebuffer
ByteBuffer_current_part_line_terminator)rX   rL   rM   rD   r5   r6   r7   rE   s           r   r[   zReader.__init__   s      )%fi>
::$~i[9C**''==cBB	779&ADJ /9TZZQ`.a'22==kJ /  	DJ	s   "C C-,C-c                d    t         j                  d       | j                  sd| _        d| _        yy)zFlush and close this stream.close: calledN)rk   rl   closedrT   r   rX   s    r   closezReader.close  s)    _%{{DJ#D r   c                    | j                   du S z$Return True if the stream is closed.NrT   r   s    r   r   zReader.closed       zzT!!r   c                     y)z+Return True if the stream can be read from.Tr   r   s    r   readablezReader.readable      r   c                     y)z2Return True; we support `seek` but not `truncate`.Tr   r   s    r   seekablezReader.seekable!  r   r   c                "    t         j                  Unsupported.ioUnsupportedOperationr   s    r   detachzReader.detach(      %%%r   c                0   t         j                  d||       |t        j                  j                  vr+d| dt        j                  j                  }t        |      |t        j                  j                  k(  r|}n<|t        j                  j                  k(  r| j                  |z   }n| j                  |z   }|| j                  kD  r`|| j                  z
  t        | j                        k  r;| j                  j                  || j                  z
         || _        | j                  S | j                  }|J || _        |j                  |       t         j                  d| j                         | j                  j                          | j                  S )a"  Seek to the specified position.

        Args:
            offset: The offset in bytes.
            whence: Where the offset is from.

        Returns:
            The position after seeking.

        Raises:
            ValueError: If ``whence`` is not one of the accepted values.
        z seeking to offset: %r whence: %rzinvalid whence z, expected one of zcurrent_pos: %r)rk   rl   r   r;   WHENCE_CHOICESr:   WHENCE_STARTWHENCE_CURRENTrV   rU   rb   r   rd   r   r_   empty)rX   rg   whencerE   new_position
raw_readers         r   r_   zReader.seek,  sM    	7H--<<<#F8+=j>R>R>a>a=deCS/!Z))666!Lz++:::>>F2L::.L $..(\DNN-JcRVRdRdNe-e##L4>>$AB)DN>>!%%
%%%%%&7  "~~r   c                    | j                   S )z,Return the current position within the file.r]   r   s    r   tellzReader.tellU  s    ~~r   c                "    t         j                  r   r   rX   rY   s     r   truncatezReader.truncateY  r   r   c                   |d}| j                   }|J |dk(  ry|dk  r2| j                  | _        | j                         |j	                         z   S t        | j                        |k\  r| j                  |      S | j                  | j                  k(  r| j                         S | j                  |       | j                  |      S )z6Read up to size bytes from the object and return them.rf   r   r   )r   rU   rV   _read_from_bufferrd   rb   r   _fill_buffer)rX   rY   r   s      r   rd   zReader.read]  s    <D%%
%%%19!8!ZZDN))+joo.???
 t!!"d*))$//>>TZZ'))++$%%d++r   c                &    | j                  |      S )zThis is the same as read().)rY   )rd   r   s     r   read1zReader.read1u  s    yydy##r   c                    t        |      j                  d      }| j                  t        |            }|sy||dt        |       t        |      S )zDRead up to len(b) bytes into b, and return the number of bytes read.Br   N)
memoryviewr   rd   rb   )rX   bmvdatas       r   readintozReader.readintoy  sG    ]$yyR!;SY4yr   c                ^   |d}|dk7  rd}t        |      t        j                         }| j                  | j                  k(  rt        | j                        dk(  s| j                  j                  | j                        }|j                  |       | xj                  t        |      z  c_        |j                  | j                        r	 |j                         S | j                          | j                  | j                  k(  st        | j                        dk(  s|j                         S )zCRead up to and including the next newline.  Returns the bytes read.rf   z(limits other than -1 not implemented yetr   )rC   r   BytesIOrV   rU   rb   r   readliner   writeendswithr   getvalue)rX   limitrE   line	line_parts        r   r   zReader.readline  s    =EB;<C%c**
 zz|>>TZZ/C8J8J4Kq4P**33D4I4IJIJJy!NNc)n,N!!$"7"78 }}  >>TZZ/C8J8J4Kq4P }}r   c                    |dk\  r|nt        | j                        }| j                  j                  |      }| xj                  t        |      z  c_        |S )z:Remove at most size bytes from our buffer and return them.r   )rb   r   rd   rV   )rX   rY   parts      r   r   zReader._read_from_buffer  sG    qytc$*<*<&=!!&&t,#d)#r   c                   | j                   }|J t        || j                  j                        }t	        | j                        |k  r| j
                  | j                  k7  rr| j                  j                  t        d|            }|dk(  rt        j                  d       yt	        | j                        |k  r| j
                  | j                  k7  rry )Nz	IO[bytes]r   z reached EOF while filling bufferT)r   maxr   _chunk_sizerb   rV   rU   fillr   rk   rl   )rX   rY   r   
bytes_reads       r   r   zReader._fill_buffer  s    %%
%%%4++778$$$%,4::1M++00k:1NOJQ?@ $$$%,4::1M r   c                    | S )z!Enter the reader context manager.r   r   s    r   	__enter__zReader.__enter__      r   c                $    | j                          y)z!Close the reader on context exit.N)r   rX   exc_typeexc_valexc_tbs       r   __exit__zReader.__exit__  s     	

r   c                j    d| j                   j                   d| j                  d| j                  dS )z8Return a short human-readable description of the reader.(, )	__class__r   r|   r}   r   s    r   __str__zReader.__str__  5    4>>**+2d.B.B-ERGZZ[\\r   c                h    | j                   j                   d| j                  d| j                  dS )z3Return an unambiguous representation of the reader.(container=, blob=r   r   r   s    r   __repr__zReader.__repr__  6    ..))*+d6J6J5MWUYUdUdTgghiir   )rL   r   rM   r   rD   _AzureClientr5   rr   r6   ri   r7   rr   rs   rt   rs   rt   rs   boolrs   zio.RawIOBaserg   rr   r   rr   rs   rr   rs   rr   NrY   
int | Noners   rr   ru   )rY   r   rs   ri   )r   r   rs   rr   )r   r   rs   ri   rv   )rY   rr   rs   zbool | Noners   r   r   ztype[BaseException] | Noner   zBaseException | Noner   zTracebackType | Noners   rt   rs   r   ) r   r   r   rw   r   rT   DEFAULT_BUFFER_SIZEr   r;   r>   DEFAULT_MAX_CONCURRENCYr[   r   propertyr   r   r   r   r   r_   r   r   rd   r   r   r   r   r   r   r   r   r   r   r   r   r=   r=      s   & I26E/6 /!+!5!5!D!D600 0 	0
 0 0 0 
0<$ " "& /9.B.B.O.O 'R&,0$4
, & %	
 
]jr   r=   c                     e Zd ZU dZded<   dZded<   def	 	 	 	 	 	 	 	 	 	 	 ddZddZdd	Z	dd
Z
edd       ZddZddZej                   j"                  fddZdddZddZddZd dZddZd!dZ	 	 	 	 	 	 	 	 d"dZd#dZd#dZy)$r@   zqWrites bytes to Azure Blob Storage.

    Implements the io.BufferedIOBase interface of the standard library.
    r   ry   Nrz   rT   c                    || _         || _        |xs i | _        || _        d| _        d| _        d| _        t        j                         | _	        g | _
        t        |||      | _        y rS   )r|   r}   _blob_kwargs_min_part_size_total_size_total_parts_bytes_uploadedr   r   r   _block_listrO   rT   rX   rL   rM   rD   r8   r9   s         r   r[   zWriter.__init__  sf      )'-2+ ZZ\?A%fi>
r   c                     yz>No-op flush; data is buffered until `close` or `_upload_part`.Nr   r   s    r   flushzWriter.flush      r   c                    t         j                  d|        | j                  sg | _        d| _        t         j                  d|        y)zDo not commit block list on abort.

        Uploaded (uncommitted) blocks will be garbage collected after 7 days.

        See also https://stackoverflow.com/a/69673084/5511061.
        z %s: terminating multipart uploadNz%s: terminated multipart upload)rk   rl   r   r   rT   r   s    r   	terminatezWriter.terminate  s8     	7>{{!DDJ6=r   c                   t         j                  d       | j                  s| j                  }|J t         j                  d|        	 | j                  j                         dkD  r| j                           |j                  | j                  fi | j                   g | _        d| _        t         j                  d|        yy# g | _        d| _        w xY w)z4Commit the buffered block list and close the stream.r   Nz%s: completing multipart uploadr   z%s: completed multipart upload)
rk   rl   r   rT   r   r   _upload_partcommit_block_listr   r   )rX   rM   s     r   r   zWriter.close  s    _%{{::D###LL:DA"%%**,q0%%'&&&t'7'7M4;L;LM#% !
LL94@  $& !
s   	AC Cc                    | j                   du S r   r   r   s    r   r   zWriter.closed  r   r   c                     yz+Return True if the stream supports writing.Tr   r   s    r   writablezWriter.writable
  r   r   c                     yz<Return True; we support `tell` but not `seek` or `truncate`.Tr   r   s    r   r   zWriter.seekable  r   r   c                "    t         j                  r   r   rX   rg   r   s      r   r_   zWriter.seek  r   r   c                "    t         j                  r   r   r   s     r   r   zWriter.truncate  r   r   c                    | j                   S z#Return the current stream position.r   r   s    r   r   zWriter.tell      r   c                0    d}t        j                  |      r   zdetach() not supportedr   rX   rE   s     r   r   zWriter.detach!      &%%c**r   c                \   t        |t              s dt        dt        |      }t        |      t	        t        |            }| j                  j                  |       | xj                  |z  c_        | j                  j                         | j                  k\  r| j                          |S )zWrite the given bytes (binary string) to the Azure Blob Storage file.

        There's buffering happening under the covers, so this may not actually
        do any HTTP transfer right away.
        input must be one of , got: rm   _BINARY_TYPEStype	TypeErrorrb   r   r   r   r   r   r   r   rX   r   rE   rh   s       r   r   zWriter.write&  s     !]+)-):'$q'MCC. Z]#  #F"""$(;(;;r   c                h   | j                   }|J | j                  dz   }| j                  j                         }| j                  |z   dz
  }t        |      j                  d      }t        j                  |j                               }| j                  j                  d       |j                  || j                  j                  |             | j                  j                  t        j                   j"                  j%                  |             t&        j)                  d|||dz         | xj                  dz  c_        | xj                  |z  c_        t+        j,                  | j                  j                               | _        | j                  j                  dt*        j.                         y )Nr       r   )block_idz+uploading part #%i, %i bytes (total %.3fGB)g      A)rT   r   r   r   r   r   zfillbase64	b64encodeencoder_   stage_blockrd   r   appendr   rn   rM   	BlobBlockrk   infor   r   SEEK_END)rX   rM   part_numcontent_length
range_stopzero_padded_part_numr  s          r   r   zWriter._upload_part9  sb   zz$$q(++002))N:Q>

  #8}227;##$8$?$?$AB"4#5#5#:#:>#JKMM((((;	
 	9"		
 	Q.ZZ(:(:(?(?(AB2;;/r   c                    | S )z!Enter the writer context manager.r   r   s    r   r   zWriter.__enter__X  r   r   c                J    || j                          y| j                          y)z.Close or terminate the writer on context exit.Nr   r   r   s       r   r   zWriter.__exit__\       NNJJLr   c                j    d| j                   j                   d| j                  d| j                  dS )z8Return a short human-readable description of the writer.r   r   r   r   r   s    r   r   zWriter.__str__h  r   r   c                    | j                   j                   d| j                  d| j                  d| j                  dS )z3Return an unambiguous representation of the writer.r   r   z, min_part_size=r   )r   r   r|   r}   r   r   s    r   r   zWriter.__repr__l  s[    ..))*+d6J6J5MWUYUdUdTggwx|  yL  yL  xO  OP  Q  	Qr   rL   r   rM   r   rD   r   r8   dict[str, Any] | Noner9   rr   rs   rt   r   r   r   r   r   r   r   r   r
   rs   rr   r   r   r   r   r   r   rw   r   rT   _DEFAULT_MIN_PART_SIZEr[   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@     s    
 I26E/6 .23?? ? 	?
 +? ? 
?(M> A  " " /9.B.B.O.O && +
&0>
,
 &
 %	

 

]Qr   r@   c                     e Zd ZU dZded<   dZded<   def	 	 	 	 	 	 	 	 	 	 	 ddZddZdd	Z	dd
Z
edd       ZddZddZej                   j"                  fddZdddZddZddZd dZddZd!dZ	 	 	 	 	 	 	 	 d"dZd#dZd#dZy)$rB   zqAppend bytes to Azure Blob Storage.

    Implements the io.BufferedIOBase interface of the standard library.
    r   ry   Nrz   rT   c                    || _         || _        |xs i | _        || _        d| _        t        j                         | _        t        |||      | _	        y rS   )
r|   r}   r   r   r   r   r   r   rO   rT   r   s         r   r[   zAppendWriter.__init__z  sN      )'-2+ZZ\%fi>
r   c                     yr   r   r   s    r   r   zAppendWriter.flush  r   r   c                ^    | j                   s!t        j                         | _        d| _        yy)z4AppendBlob cannot be aborted, so we do nothing here.N)r   r   r   r   rT   r   s    r   r   zAppendWriter.terminate  s#    {{!#DDJ r   c                    | j                   s6	 | j                  j                         dkD  r| j                          d| _        yy# d| _        w xY w)zDNo action needed here, as the AppendBlob is automatically committed.r   N)r   r   r   r   rT   r   s    r   r   zAppendWriter.close  sH    {{"%%**,q0%%'!
 
 "
s   -A 	Ac                    | j                   du S r   r   r   s    r   r   zAppendWriter.closed  r   r   c                     yr  r   r   s    r   r  zAppendWriter.writable  r   r   c                     yr  r   r   s    r   r   zAppendWriter.seekable  r   r   c                "    t         j                  r   r   r  s      r   r_   zAppendWriter.seek  r   r   c                "    t         j                  r   r   r   s     r   r   zAppendWriter.truncate  r   r   c                    | j                   S r	  r
  r   s    r   r   zAppendWriter.tell  r  r   c                0    d}t        j                  |      r  r   r  s     r   r   zAppendWriter.detach  r  r   c                \   t        |t              s dt        dt        |      }t        |      t	        t        |            }| j                  j                  |       | xj                  |z  c_        | j                  j                         | j                  k\  r| j                          |S )z@Append `b` to the AppendBlob, buffering until ``min_part_size``.r  r  r  r  s       r   r   zAppendWriter.write  s    !]+)-):'$q'MCC. Z]#  #F"""$(;(;;r   c                "   | j                   }|J | j                  j                         } |j                  d|t        j
                  j                  j                  j                  dd| j                   t        j                         | _        y )NF)r   	blob_type	overwriter   )rT   r   r   upload_blobr   rn   rM   BlobType
APPENDBLOBr   r   r   )rX   rM   r   s      r   r   zAppendWriter._upload_part  s    zz!!**, 	
mm((11<<	
 		
  ZZ\r   c                    | S )z(Enter the append writer context manager.r   r   s    r   r   zAppendWriter.__enter__  r   r   c                J    || j                          y| j                          y)z5Close or terminate the append writer on context exit.Nr*  r   s       r   r   zAppendWriter.__exit__  r+  r   c                j    d| j                   j                   d| j                  d| j                  dS )z?Return a short human-readable description of the append writer.r   r   r   r   r   s    r   r   zAppendWriter.__str__  r   r   c                h    | j                   j                   d| j                  d| j                  dS )z:Return an unambiguous representation of the append writer.r   r   r   r   r   s    r   r   zAppendWriter.__repr__  r   r   r.  r   r   r   r   r   r   r   r0  r   r   r   r1  r   r   r   rB   rB   q  s    
 I26E/6 .23?? ? 	?
 +? ? 
?"M" " " /9.B.B.O.O && +


*
,
 &
 %	

 

]jr   rB   )r&   r   rs   r   )r.   r   r/   r   r0   r   rs   io.BufferedIOBase)r   r   r   r   r/   r   rD   z_AzureClient | Noner8   r/  r5   rr   r9   rr   r7   rr   rs   rJ  )rD   r   rL   r   rM   r   rs   rJ   )9rw   
__future__r   r  r   loggingtypingr   r   r   r   smart_open.bytebufferr   smart_open.constantssmart_open.utilsazure.core.exceptionsr   azure.storage.blobImportErrorMISSING_DEPStypesr   r	   	_typeshedr
   r   typing_extensionsr   smart_open._typingr   rn   rM   BlobServiceClientContainerClient
BlobClientr   	getLoggerr   rk   ri   	bytearrayr   r  r"   r2  r   r   r   r*   r3   r-   rO   rQ   BufferedIOBaser=   r@   rB   r   r   r   <module>r_     s   W "  	  6 6     #9&2 	,,
--


,
,	-
--


'
'	(  
		8	$	:. Y	 H%  Q!    D	 P$S #')-*/27#7#7# 7#  	7#
 '7# 7# 7# 7# 7#t666 6 #	6(.% .%bfjR fjRiQR iQXxj2$$ xjs  Ls   E" "E-,E-