
    3 d8V                        d Z ddlZddlZddlZddlZddlmZ ddlmZ ddlm	Z	 ddl
mZmZmZmZmZmZ ddlmZmZ ddlmZmZ dd	lmZ dd
lmZmZ ddlmZmZ ddlm Z m!Z! ddl"m#Z# ddl$m%Z% ddl&m'Z' ddl(m)Z) ddl*m+Z+ ddl,m-Z-m.Z. ddl/m0Z0m1Z1  ej2        e3          Z4ddddZ5 G d d          Z6 G d de          Z7 ee7           G d d                      Z8 ee7           G d d                      Z9 ee7           G d d                       Z: G d! d"e8          Z; G d# d$e8          Z< G d% d&e8          Z= G d' d(          Z> G d) d*          Z?dS )+zK
Feed Exports extension

See documentation in docs/topics/feed-exports.rst
    N)datetime)Path)NamedTemporaryFile)IOAnyCallableOptionalTupleUnion)unquoteurlparse)deferthreads)file_uri_to_path)	Interfaceimplementer)Spidersignals)NotConfiguredScrapyDeprecationWarning)PostProcessingManager)is_botocore_available)*feed_complete_default_values_from_settings)ftp_store_file)failure_to_exc_info)create_instanceload_object)get_func_argswithout_none_values feed_optionspreargsc                    t          |           }d|v r||d<   n#t          j        | j         dt                      | g |||R i |S )Nr"   z does not support the 'feed_options' keyword argument. Add a 'feed_options' parameter to its signature to remove this warning. This parameter will become mandatory in a future version of Scrapy.category)r   warningswarn__qualname__r   )builderurir"   r#   argskwargsargument_namess          <lib/python3.11/site-packages/scrapy/extensions/feedexport.pybuild_storager0   "   s    "7++N' 	
!-~# ! ! ! .	
 	
 	
 	
 72G2S242226222    c                   `    e Zd ZU dZee         ed<   eed<   dee         ddfdZde	de
fdZdS )	
ItemFilterz
    This will be used by FeedExporter to decide if an item should be allowed
    to be exported to a particular feed.

    :param feed_options: feed specific options passed from FeedExporter
    :type feed_options: dict
    r"   item_classesreturnNc                     || _         |5t          d |                    d          pdD                       | _        d S t                      | _        d S )Nc              3   4   K   | ]}t          |          V  d S N)r   ).0
item_classs     r/   	<genexpr>z&ItemFilter.__init__.<locals>.<genexpr>@   s>       & & J''& & & & & &r1   r4   r    )r"   tuplegetr4   )selfr"   s     r/   __init__zItemFilter.__init__=   sm    ( 	( % & &"."2"2>"B"B"Hb& & & ! !D
 !&Dr1   itemc                 >    | j         rt          || j                   S dS )a'  
        Return ``True`` if `item` should be exported or ``False`` otherwise.

        :param item: scraped item which user wants to check if is acceptable
        :type item: :ref:`Scrapy items <topics-items>`
        :return: `True` if accepted, `False` otherwise
        :rtype: bool
        T)r4   
isinstance)r>   r@   s     r/   acceptszItemFilter.acceptsG   s'      	7dD$5666tr1   )__name__
__module__r)   __doc__r	   dict__annotations__r
   r?   r   boolrC   r    r1   r/   r3   r3   1   s           4.   (Xd^ ( ( ( ( (C D      r1   r3   c                   *    e Zd ZdZdddZd Zd ZdS )IFeedStoragez/Interface that all Feed Storages must implementNr"   c                    dS )zxInitialize the storage with the parameters given in the URI and the
        feed-specific options (see :setting:`FEEDS`)Nr    )r+   r"   s     r/   r?   zIFeedStorage.__init__X         r1   c                     dS )ztOpen the storage for the given spider. It must return a file-like
        object that will be used for the exportersNr    )spiders    r/   openzIFeedStorage.open\   rN   r1   c                     dS )zStore the given file streamNr    )files    r/   storezIFeedStorage.store`   rN   r1   )rD   rE   r)   rF   r?   rQ   rT   r    r1   r/   rK   rK   U   sT        99&* 8 8 8 8 86 6 6* * * * *r1   rK   c                        e Zd Zd Zd Zd ZdS )BlockingFeedStoragec                     |j         j        d         }|r@t          |                                          st	          dt          |          z             t          d|          S )NFEED_TEMPDIRzNot a Directory: zfeed-)prefixdir)crawlersettingsr   is_dirOSErrorstrr   )r>   rP   paths      r/   rQ   zBlockingFeedStorage.openf   s_    ~&~6 	;T

))++ 	;-D		9:::!d;;;;r1   c                 6    t          j        | j        |          S r8   )r   deferToThread_store_in_threadr>   rS   s     r/   rT   zBlockingFeedStorage.storem   s    $T%:DAAAr1   c                     t           r8   )NotImplementedErrorrd   s     r/   rc   z$BlockingFeedStorage._store_in_threadp   s    !!r1   N)rD   rE   r)   rQ   rT   rc   r    r1   r/   rV   rV   d   sD        < < <B B B" " " " "r1   rV   c                   (    e Zd ZddddZd Zd ZdS )StdoutFeedStorageNrL   c                    |st           j        j        }|| _        |r4|                    dd          du rt
                              d           d S d S d S )N	overwriteFTzStandard output (stdout) storage does not support overwriting. To suppress this warning, remove the overwrite option from your FEEDS setting, or set it to False.)sysstdoutbuffer_stdoutr=   loggerwarning)r>   r+   rn   r"   s       r/   r?   zStdoutFeedStorage.__init__v   sx     	(j'G 	L,,[%@@DH 	NN    	 	 	 	r1   c                     | j         S r8   )rn   )r>   rP   s     r/   rQ   zStdoutFeedStorage.open   s
    |r1   c                     d S r8   r    rd   s     r/   rT   zStdoutFeedStorage.store   s    r1   r8   )rD   rE   r)   r?   rQ   rT   r    r1   r/   rh   rh   t   sR        
$ 
 
 
 
 
      r1   rh   c                   8    e Zd ZdddZdee         fdZd ZdS )FileFeedStorageNrL   c                t    t          |          | _        |pi }|                    dd          rdnd| _        d S )Nrj   Fwbab)r   r`   r=   
write_mode)r>   r+   r"   s      r/   r?   zFileFeedStorage.__init__   s?    $S))	#)r"."2"2;"F"FP$$Dr1   r5   c                     t          | j                  j        }|r*|                                s|                    d           t          | j                                      | j                  S )NT)parents)r   r`   parentexistsmkdirrQ   rx   )r>   rP   dirnames      r/   rQ   zFileFeedStorage.open   s]    ty//( 	(7>>++ 	(MM$M'''DI##DO444r1   c                 .    |                                  d S r8   )closerd   s     r/   rT   zFileFeedStorage.store   s    

r1   )rD   rE   r)   r?   r   r   rQ   rT   r    r1   r/   rt   rt      sc        ,0 Q Q Q Q Q
5bg 5 5 5 5    r1   rt   c                   H    e Zd Z	 	 	 	 dddddZeddd            Zd ZdS )S3FeedStorageN)r"   session_tokenc                   t                      st          d          t          |          }|j        | _        |j        p|| _        |j        p|| _        || _	        |j
        dd          | _        || _        || _        dd l}	|	j                                        }
|
                    d| j        | j        | j	        | j                  | _        |r4|                    dd          du rt(                              d	           d S d S d S )
Nzmissing botocore library   r   s3)aws_access_key_idaws_secret_access_keyaws_session_tokenendpoint_urlrj   TFzS3 does not support appending to files. To suppress this warning, remove the overwrite option from your FEEDS setting or set it to True.)r   r   r   hostname
bucketnameusername
access_keypassword
secret_keyr   r`   keynameaclr   botocore.sessionsessionget_sessioncreate_client	s3_clientr=   ro   rp   )r>   r+   r   r   r   r   r"   r   ubotocorer   s              r/   r?   zS3FeedStorage.__init__   s.    %&& 	< :;;;SMM**2
*2
*vabbz("..00 .."o"&/"0* / 
 
  	L,,[$??5H 	NND    	 	 	 	r1   rL   c          
          t          | ||j        d         |j        d         |j        d         |j        d         pd |j        d         pd |          S )NAWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYAWS_SESSION_TOKENFEED_STORAGE_S3_ACLAWS_ENDPOINT_URL)r   r   r   r   r   r"   )r0   r\   clsr[   r+   r"   s       r/   from_crawlerzS3FeedStorage.from_crawler   sh    '(;<'(?@!*+>? !67?4 )*<=E%	
 	
 	
 		
r1   c                     |                     d           | j        r	d| j        ini } | j        j        d| j        | j        |d| |                                 d S )Nr   ACL)BucketKeyBodyr    )seekr   r   
put_objectr   r   r   )r>   rS   r-   s      r/   rc   zS3FeedStorage._store_in_thread   sr    		!&*h6%""B!! 	
?4	
 	
CI	
 	
 	
 	

r1   )NNNNrD   rE   r)   r?   classmethodr   rc   r    r1   r/   r   r      s         $ $ $ $ $ $L 8< 

 

 

 

 [

    r1   r   c                   0    e Zd Zd Zed             Zd ZdS )GCSFeedStoragec                     || _         || _        t          |          }|j        | _        |j        dd          | _        d S )Nr   )
project_idr   r   r   bucket_namer`   	blob_name)r>   r+   r   r   r   s        r/   r?   zGCSFeedStorage.__init__   s:    $SMM:r1   c                 L     | ||j         d         |j         d         pd           S )NGCS_PROJECT_IDFEED_STORAGE_GCS_ACL)r\   )r   r[   r+   s      r/   r   zGCSFeedStorage.from_crawler   s6    s-.34<
 
 	
r1   c                     |                     d           ddlm}  || j                  }|                    | j                  }|                    | j                  }|                    || j	                   d S )Nr   )Client)project)predefined_acl)
r   google.cloud.storager   r   
get_bucketr   blobr   upload_from_filer   )r>   rS   r   clientbucketr   s         r/   rc   zGCSFeedStorage._store_in_thread   s    		!//////000""4#344{{4>**d48<<<<<r1   Nr   r    r1   r/   r   r      sM        $ $ $ 
 
 [
= = = = =r1   r   c                   >    e Zd ZddddZeddd            Zd ZdS )FTPFeedStorageFNrL   c                "   t          |          }|j        | _        t          |j        pd          | _        |j        | _        t          |j        pd          | _        |j        | _        || _	        | p|
                    dd          | _        d S )N21 rj   T)r   r   hostintportr   r   r   r`   use_active_moder=   rj   )r>   r+   r   r"   r   s        r/   r?   zFTPFeedStorage.__init__   s~    SMMJ	$''	

 0b11F	.))P\-=-=k4-P-Pr1   c                X    t          | ||j                            d          |          S )NFEED_STORAGE_FTP_ACTIVErL   )r0   r\   getboolr   s       r/   r   zFTPFeedStorage.from_crawler   s7    $$%>??%	
 
 
 	
r1   c           
      z    t          | j        || j        | j        | j        | j        | j        | j                   d S )N)r`   rS   r   r   r   r   r   rj   )r   r`   r   r   r   r   r   rj   rd   s     r/   rc   zFTPFeedStorage._store_in_thread  sJ    ]] 0n		
 		
 		
 		
 		
 		
r1   )Fr   r    r1   r/   r   r      sq        Q4 Q Q Q Q Q 8< 
 
 
 
 [


 

 

 

 

r1   r   c                        e Zd Zd Zd Zd ZdS )	_FeedSlotc
                     || _         || _        || _        || _        || _        || _        || _        || _        |	| _        d| _	        d| _
        d S )Nr   F)rS   exporterstoragebatch_idformatstore_emptyuri_templater+   filter	itemcount
_exporting)
r>   rS   r   r   r+   r   r   r   r   r   s
             r/   r?   z_FeedSlot.__init__  sW     	  &(r1   c                 X    | j         s"| j                                         d| _         d S d S )NT)r   r   start_exportingr>   s    r/   r   z_FeedSlot.start_exporting-  s5     	#M))+++"DOOO	# 	#r1   c                 X    | j         r"| j                                         d| _         d S d S )NF)r   r   finish_exportingr   s    r/   r   z_FeedSlot.finish_exporting2  s5    ? 	$M**,,,#DOOO	$ 	$r1   N)rD   rE   r)   r?   r   r   r    r1   r/   r   r     sA             4# # #
$ $ $ $ $r1   r   c            
           e Zd Zed             Zd Zd Zd Zd Zd Z	d Z
d Zd	 Zd
 Zd Zd Zd Zd Zd Zd Z	 ddedeeeeeegef         f                  dee         defdZd ZdS )FeedExporterc                     | |          }|j                             |j        t           j                   |j                             |j        t           j                   |j                             |j        t           j                   |S r8   )r   connectopen_spiderspider_openedclose_spiderspider_closeditem_scraped)r   r[   r   s      r/   r   zFeedExporter.from_crawler9  sn    3w<< 4g6KLLL 5w7LMMM 5w7KLLLr1   c                    || _         |j        | _        i | _        g | _        i | _        | j        d         s| j        d         st
          | j        d         rt          j        dt          d           t          | j        d                   }d| j        
                    dd          i}t          || j                  | j        |<   |                     |          | j        |<   | j                            d                                          D ]N\  }}t          |          }t          || j                  | j        |<   |                     |          | j        |<   O|                     d	          | _        |                     d
          | _        | j                                        D ]_\  }}|                     ||          st
          |                                 st
          |                     |d                   st
          `d S )NFEEDSFEED_URIzThe `FEED_URI` and `FEED_FORMAT` settings have been deprecated in favor of the `FEEDS` setting. Please see the `FEEDS` setting docs for more details   )r&   
stacklevelr   FEED_FORMAT	jsonlinesFEED_STORAGESFEED_EXPORTERS)r[   r\   feedsslotsfiltersr   r'   r(   r   r_   r=   r   _load_filtergetdictitems_load_componentsstorages	exporters_storage_supported_settings_are_valid_exporter_supported)r>   r[   r+   r"   s       r/   r?   zFeedExporter.__init__A  s   (

}W% 	 dmJ.G 	  =$ 	@M\1	    dmJ/00C$dm&7&7{&S&STLHdm DJsO !% 1 1, ? ?DL "&!6!6w!?!?!E!E!G!G 	@ 	@Cc((CHdm DJsO !% 1 1, ? ?DL--o>>../?@@!%!1!1!3!3 	$ 	$C**3== $##++-- $##++L,BCC $##$	$ 	$r1   c           
          | j                                         D ]V\  }}|                     ||d                   }| j                            |                     d||z  |||                     Wd S )N
uri_paramsr   r   r+   r"   rP   r   )r   r   _get_uri_paramsr   append_start_new_batch)r>   rP   r+   r"   r   s        r/   r   zFeedExporter.open_spiderm  s    !%!1!1!3!3 
	 
	C--fl<6PQQJJ%%j(!-!!$ &     
	 
	r1   c                     g }| j         D ]-}|                     ||          }|                    |           .|rt          j        |          nd S r8   )r   _close_slotr   r   DeferredList)r>   rP   deferred_listslotds        r/   r   zFeedExporter.close_spiderz  s_    J 	$ 	$D  v..A  ####4AKu!-000tKr1   c                    |                                  |j        s+|j        s$t          j        |j        j        |j                  S |j         d|j         d|j	         }t          j        |j        j        |j                  }|
                    | j        ||t          |j                  j                   |                    | j        ||t          |j                  j                   |S )Nz feed (z items) in: )r   r   r   r   maybeDeferredr   rT   rS   r   r+   addCallback_handle_store_successtyperD   
addErrback_handle_store_error)r>   r  rP   logmsgr  s        r/   r  zFeedExporter._close_slot  s    ~ 	Fd&6 	F &t|'949EEEKNNNNDHNN 2DI>>	&T\8J8J8S	
 	
 	
 	
$ffd4<6H6H6Q	
 	
 	
 r1   c                     t                               d|t          |          d|i           | j        j                            d|            d S )NzError storing %srP   )exc_infoextrazfeedexport/failed_count/)ro   errorr   r[   stats	inc_valuer>   fr  rP   	slot_types        r/   r  z FeedExporter._handle_store_error  s`    (++V$	 	 	
 	
 	
 	$$%K	%K%KLLLLLr1   c                     t                               d|d|i           | j        j                            d|            d S )Nz	Stored %srP   )r  zfeedexport/success_count/)ro   infor[   r  r  r  s        r/   r
  z"FeedExporter._handle_store_success  sG    K&/ABBB$$%L%L%LMMMMMr1   c                    |                      ||          }|                    |          }d|v rt          |d         ||          } | j        d
||d         |d         |d         |d         d|d         }t	          |||||d         |d         ||| j        |         		  	        }	|	j        r|	                                 |	S )a  
        Redirect the output data stream to a new file.
        Execute multiple times if FEED_EXPORT_BATCH_ITEM_COUNT setting or FEEDS.batch_item_count is specified
        :param batch_id: sequence number of current batch
        :param uri: uri of the new batch to start
        :param feed_options: dict with parameters of feed
        :param spider: user spider
        :param uri_template: template of uri which contains %(batch_time)s or %(batch_id)d to create new uri
        postprocessingr   fieldsencodingindent)rS   r   fields_to_exportr  r  item_export_kwargsr   )	rS   r   r   r+   r   r   r   r   r   r    )_get_storagerQ   r   _get_exporterr   r   r   r   )
r>   r   r+   r"   rP   r   r   rS   r   r  s
             r/   r   zFeedExporter._start_new_batch  s    ##C66||F##|+ 	(-.l D &4% 
))(3!*-)
 
 /0
 
 )$]3%<-

 

 

  	#  """r1   c           
         g }| j         D ]V}|j                            |          s|                    |           3|                                 |j                            |           |xj        dz  c_        | j        |j	                 d         r|j        | j        |j	                 d         k    r| 
                    || j        |j	                 d         |          }|                     ||           |                    |                     |j        dz   |j	        |z  | j        |j	                 ||j	                             A|                    |           X|| _         d S )Nr   batch_item_countr   r   )r   r   rC   r   r   r   export_itemr   r   r   r   r  r   r   )r>   r@   rP   r   r  r   s         r/   r   zFeedExporter.item_scraped  s   J 	# 	#D;&&t,,      """M%%d+++NNaNN 
4,-.@A#Ndj1B&CDV&WW# "11DJt'89,G 
   v...))!%!2 -
:%)Z0A%B%%)%6 *      T""""


r1   c                     t          | j                            |                    }i }|                                D ](\  }}	 t	          |          ||<   # t
          $ r Y %w xY w|S r8   )r   r\   getwithbaser   r   r   )r>   setting_prefixconfr  kvs         r/   r   zFeedExporter._load_components  sz    "4=#<#<^#L#LMMJJLL 	 	DAq"1~~!    s   A
A$#A$c                 V    || j         v rdS t                              dd|i           d S )NTzUnknown feed format: %(format)sr   )r   ro   r  )r>   r   s     r/   r   z FeedExporter._exporter_supported  s6    T^# 	4668JKKKKKr1   c                     | j                                         D ]@\  }}|d         r3t          j        d|          st                              d|            dS AdS )z
        If FEED_EXPORT_BATCH_ITEM_COUNT setting or FEEDS.batch_item_count is specified uri has to contain
        %(batch_time)s or %(batch_id)d to distinguish different files of partial output
        r$  z%\(batch_time\)s|%\(batch_id\)a  %%(batch_time)s or %%(batch_id)d must be in the feed URI (%s) if FEED_EXPORT_BATCH_ITEM_COUNT setting or FEEDS.batch_item_count is specified and greater than 0. For more info see: https://docs.scrapy.org/en/latest/topics/feed-exports.html#feed-export-batch-item-countFT)r   r   researchro   r  )r>   r   valuess      r/   r   z FeedExporter._settings_are_valid  s~    
 %)J$4$4$6$6 
	 
	 L&() 	")1<3 3 	 n !	   uutr1   c                 2   t          |          j        }|| j        v r\	 |                     ||           dS # t          $ r6}t
                              d|t          |          d           Y d }~d S d }~ww xY wt
                              dd|i           d S )NTz<Disabled feed storage scheme: %(scheme)s. Reason: %(reason)s)schemereasonz'Unknown feed storage scheme: %(scheme)sr2  )r   r2  r   r!  r   ro   r  r_   )r>   r+   r"   r2  es        r/   r   zFeedExporter._storage_supported
  s    #%T]" 
	X!!#|444t    U%Q88         LLBXvDVWWWWWs   7 
A7+A22A7c           	      N    t          || j        t          | dd           g|R i |S )Nr[   )r   r\   getattr)r>   objclsr,   r-   s       r/   _get_instancezFeedExporter._get_instance  sC    DM74D#A#A
DH
 
 
LR
 
 	
r1   c                 <     | j         | j        |         |g|R i |S r8   )r8  r   )r>   rS   r   r,   r-   s        r/   r"  zFeedExporter._get_exporter  s.    !t!$."8$PPPPPPPr1   c                 f   | j         t                    j                 }t          | dd          }fd}|r$t	          |d          r ||j        |          }d}n6t	          |d          r ||j        | j                  }d}n ||          }d}|t          |j	         d| d          |S )	zFork of create_instance specific to feed storage classes

        It supports not passing the *feed_options* parameters to classes that
        do not support it, and issuing a deprecation warning instead.
        r[   Nc                 *    t          | |          S )Nr!   )r0   )r*   r#   r"   r+   s     r/   build_instancez1FeedExporter._get_storage.<locals>.build_instance)  s#     <   r1   r   from_settings__new__.z returned None)
r   r   r2  r6  hasattrr   r=  r\   	TypeErrorr)   )r>   r+   r"   feedclsr[   r<  instancemethod_names    ``     r/   r!  zFeedExporter._get_storage   s     - 45$	400	 	 	 	 	 	
  	$ww77 	$%~g&:GDDH(KKWo.. 	$%~g&;T]KKH)KK%~g..H#K 	Sw3QQkQQQRRRr1   NrP   uri_params_functionr  r5   c                 &   i }t          |          D ]}t          ||          ||<   t          j                    }|                    d                                                              dd          |d<   |                                                    dd          |d<   |
|j        dz   nd|d<   |                                }|rt          |          nd	 } |||          }	|	||k    rt          j
        d
t                     |	|	n|S )Nr   )microsecond:-time
batch_timer   r   c                     | S r8   r    )params_s     r/   <lambda>z.FeedExporter._get_uri_params.<locals>.<lambda>L  s    6 r1   zModifying the params dictionary in-place in the function defined in the FEED_URI_PARAMS setting or in the uri_params key of the FEEDS setting is deprecated. The function must return a new dictionary instead.r%   )rZ   r6  r   utcnowreplace	isoformatr   copyr   r'   r(   r   )
r>   rP   rE  r  rM  r*  utc_noworiginal_paramsuripar_function
new_paramss
             r/   r   zFeedExporter._get_uri_params;  s@    V 	+ 	+A**F1II/## Q77AACCKKCQTUUv&0022::3DD|26IT]Q..z ++-- #*K+,,,)) 	
 %_VV44
 	F!: 	M 2    (?zz?r1   c                 h    t          |                    dt                              } ||          S )Nitem_filter)r   r=   r3   )r>   r"   item_filter_classs      r/   r   zFeedExporter._load_filterY  s1    '(8(8
(S(STT  ...r1   r8   )rD   rE   r)   r   r   r?   r   r   r  r  r
  r   r   r   r   r   r   r8  r"  r!  r   r	   r   r_   r   rG   r   r   r   r    r1   r/   r   r   8  s         [*$ *$ *$X  L L L  "M M MN N N& & &P     D  L L L
  $X X X
 
 

Q Q Q  > %)	@ @@ &eC4.$:N1O,O&PQ@ y!	@
 
@ @ @ @</ / / / /r1   r   )@rF   loggingr.  rk   r'   r   pathlibr   tempfiler   typingr   r   r   r	   r
   r   urllib.parser   r   twisted.internetr   r   	w3lib.urlr   zope.interfacer   r   scrapyr   r   scrapy.exceptionsr   r    scrapy.extensions.postprocessingr   scrapy.utils.botor   scrapy.utils.confr   scrapy.utils.ftpr   scrapy.utils.logr   scrapy.utils.miscr   r   scrapy.utils.pythonr   r   	getLoggerrD   ro   r0   r3   rK   rV   rh   rt   r   r   r   r   r   r    r1   r/   <module>rm     s     				 



              ' ' ' ' ' ' < < < < < < < < < < < < < < < < * * * * * * * * + + + + + + + + & & & & & & 1 1 1 1 1 1 1 1 " " " " " " " " E E E E E E E E B B B B B B 3 3 3 3 3 3 H H H H H H + + + + + + 0 0 0 0 0 0 : : : : : : : : B B B B B B B B		8	$	$ 59" 3 3 3 3 3! ! ! ! ! ! ! !H* * * * *9 * * * \" " " " " " " " \       ( \        : : : : :' : : :z= = = = =( = = =4
 
 
 
 
( 
 
 
B#$ #$ #$ #$ #$ #$ #$ #$Ld/ d/ d/ d/ d/ d/ d/ d/ d/ d/r1   