
                            S r SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKrSSK	r	SSK
r
SSKJr  SS	KJr  SS
KJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJ r   SSKJ!r!  \RD                  r# " S S\$5      r%S(S jr& " S S\$5      r' " S S\'5      r( " S  S!\'5      r) " S" S#\$5      r* " S$ S%\$5      r+ " S& S'\	RX                  5      r-g))zFBase classes for gsutil UI controller, UIThread and MainThreadUIQueue.    )absolute_import)print_function)division)unicode_literals)dequeN)queue)LogPerformanceSummaryParams)LogRetryableError)FileMessage)FinalMessage)MetadataMessage)PerformanceSummaryMessage)ProducerThreadMessage)ProgressMessage)RetryableErrorMessage)SeekAheadMessage)StatusMessage)parallelism_framework_util)DecimalShort)HumanReadableWithDecimalPlaces)MakeHumanReadable)
PrettyTimec                   (    \ rS rSrSrSrSrSrSrSr	g)	EstimationSource2   zenum for total size source.             N)
__name__
__module____qualname____firstlineno____doc__PRODUCER_THREAD_FINALSEEK_AHEAD_THREADPRODUCER_THREAD_ESTIMATEINDIVIDUAL_MESSAGES__static_attributes__r        &platform/gsutil/gslib/ui_controller.pyr   r   2   s%    #    r+   r   c                     [        U US9nUR                  5       n[        [        [	        US   5      5      5      S:  a  [        US   5      U-
  S-
  nUS   SU US'   SSR                  U5      -  $ )zAdjusts proper width for printing num_bytes in readable format.

Args:
  num_bytes: The number of bytes we must display.
  decimal_places: The standard number of decimal places.
Returns:
  String of fixed width representing num_bytes.
)decimal_placesr   i  r   Nz%9s )r   splitintroundfloatlenjoin)	num_bytesr.   human_readablenumber_formatlast_characters        r,   BytesToFixedWidthStringr:   F   s     2)AOQ. &&(-u]1%&	'(D0 q)*^;a?N$Q'8M!	#((=)	**r+   c                       \ rS rSrSr " S S\5      r        SS jrS rS r	S	 r
S
 rS rS rS rS r\R"                  4S jrS r\R"                  4S jrSrg)StatusMessageManagerZ   zGeneral manager for common functions shared by data and metadata managers.

This subclass has the responsibility of having a common constructor and the
same handler for SeekAheadMessages and ProducerThreadMessages.
c                       \ rS rSrSrS rSrg)+StatusMessageManager._ThroughputInformationa   zClass that contains all information needed for throughput calculation.

This _ThroughputInformation is used to track progress and time at several
points of our operation.
c                     Xl         X l        g)zConstructor of _ThroughputInformation.

Args:
  progress: The current progress, in bytes/second or objects/second.
  report_time: Float representing when progress was reported (seconds
      since Epoch).
Nprogresstime)selfrC   report_times      r,   __init__4StatusMessageManager._ThroughputInformation.__init__h   s     mir+   rB   Nr!   r"   r#   r$   r%   rG   r*   r    r+   r,   _ThroughputInformationr?   a   s    	r+   rJ   Nc	                    Xl         X l        X0l        X@l        XPl        X`l        Xpl        Xl        [        R                  U l
        [        R                  U l        SU l        SU l        U R
                  (       a  U R
                  O[        R                  " 5       U l        U R                  U l        U R                  U l        SU l        ['        5       U l        SU l        / SQU l        SU l        SU l        SU l        SU l        SU l        g)a  Instantiates a StatusMessageManager.

Args:
  update_message_period: Minimum period for refreshing and  displaying
                         new information. A non-positive value will ignore
                         any time restrictions imposed by this field, but
                         it will affect throughput and time remaining
                         estimations.
  update_spinner_period: Minimum period for refreshing and displaying the
                         spinner. A non-positive value will ignore
                         any time restrictions imposed by this field.
  sliding_throughput_period: Sliding period for throughput calculation. A
                             non-positive value will make it impossible to
                             calculate the throughput.
  first_throughput_latency: Minimum waiting time before actually displaying
                            throughput info. A non-positive value will
                            ignore any time restrictions imposed by this
                            field.
  quiet_mode: If True, do not print status messages (but still process
              them for analytics reporting as necessary).
  custom_time: If a custom start_time is desired. Used for testing.
  verbose: Tells whether or not the operation is on verbose mode.
  console_width: Width to display on console. This should not adjust the
                 visual output, just the space padding. For proper
                 visualization, we recommend setting this field to at least
                 80.
r   g        )/-\|FN)update_message_periodupdate_spinner_periodsliding_throughput_periodfirst_throughput_latency
quiet_modecustom_timeverboseconsole_widthr   r)   num_objects_sourcetotal_size_sourcenum_objects
total_sizerD   refresh_message_time
start_timerefresh_spinner_time
throughputr   old_progresslast_progress_timespinner_char_listcurrent_spinner_indexobjects_finishedobject_report_changefinal_message)	rE   rP   rQ   rR   rS   rT   rU   rV   rW   s	            r,   rG   StatusMessageManager.__init__s   s    H "7!6%>"$<! O"L&
 /BBD-AADDDO %)$4$4 "&!1!1:>))+ 	//DO $ 9 9D DODD2D!"DDD !&DDr+   c                 4    U R                   U R                     $ )zdReturns the current spinner character.

Returns:
  char_to_print: Char to be printed as the spinner
)rb   rc   rE   s    r,   
GetSpinnerStatusMessageManager.GetSpinner   s     !!$"<"<==r+   c                 X    U R                   S-   [        U R                  5      -  U l         g)z&Updates the current spinner character.r   N)rc   r4   rb   ri   s    r,   UpdateSpinner"StatusMessageManager.UpdateSpinner   s(    #'#=#=#A"%d&<&<"=#>Dr+   c                    UR                   (       a  U R                  [        R                  :  a&  [        R                  U l        UR                  U l        U R
                  [        R                  :  a7  UR                  (       a&  [        R                  U l        UR                  U l        gU R                  [        R                  :  a&  [        R                  U l        UR                  U l        U R
                  [        R                  :  a9  UR                  (       a'  [        R                  U l        UR                  U l        ggg)zeHandles a ProducerThreadMessage.

Args:
  status_message: The ProducerThreadMessage to be processed.
N)	finishedrX   r   r&   rZ   rY   sizer[   r(   rE   status_messages     r,   _HandleProducerThreadMessage1StatusMessageManager._HandleProducerThreadMessage   s     		 	 $4$J$J	J"2"H"H)55

 
 $4$J$J
J


!1!G!G(--"2"K"KK 0 I Id'33d"2"K"KK/HHd&++do 	 	Lr+   c                    SUR                   -  nUR                  (       a_  US[        UR                  5      -  -  nU R                  [        R
                  :  a&  [        R
                  U l        UR                  U l        U R                  [        R
                  :  a&  [        R
                  U l        UR                   U l         US-  nU R                  (       d  UR                  U5        gg)zHandles a SeekAheadMessage.

Args:
  status_message: The SeekAheadMessage to be processed.
  stream: Stream to print messages.
z,Estimated work for this command: objects: %sz, total size: %s
N)
rZ   rq   r   rY   r   r'   r[   rX   rT   write)rE   rs   streamestimate_messages       r,   _HandleSeekAheadMessage,StatusMessageManager._HandleSeekAheadMessage   s     G&223-,^-@-@AB C			#3#E#E	E!1!C!C(--"2"D"DD 0 B Bd'33d??ll#$ r+   c                 *    [        UR                  S9  g)zmHandles a PerformanceSummaryMessage.

Args:
  status_message: The PerformanceSummaryMessage to be processed.
)
uses_sliceN)r	   r~   rr   s     r,    _HandlePerformanceSummaryMessage5StatusMessageManager._HandlePerformanceSummaryMessage   s      >+D+DEr+   c                 8    XR                   -
  U R                  :  $ )zDecides whether enough time has passed to start tracking throughput.

Args:
  cur_time: current time.
Returns:
  Whether or not we should track the throughput.
)r]   rS   rE   cur_times     r,   ShouldTrackThroughput*StatusMessageManager.ShouldTrackThroughput  s     oo%)F)FFFr+   c                     XR                   -
  U R                  :  nU R                  nU=(       d    U R                  =(       a    U$ )zDecides whether or not it is time for printing a new progress.

Args:
  cur_time: current time.
Returns:
  Whether or not we should print the progress.
)r\   rP   rZ   re   )rE   r   sufficient_time_elapsednonzero_reports       r,   ShouldPrintProgress(StatusMessageManager.ShouldPrintProgress  sL      (*C*CC"&"<"< = %%N# &%%<,:<r+   c                 ^    XR                   -
  U R                  :  =(       a    U R                  $ )zDecides whether or not it is time for updating the spinner character.

Args:
  cur_time: Current time.
Returns:
  Whether or not we should update and print the spinner.
)r^   rQ   r[   r   s     r,   ShouldPrintSpinner'StatusMessageManager.ShouldPrintSpinner   s,     00043M3MM  !r+   c                     U R                  5         U R                  (       d#  UR                  U R                  5       S-   5        gg)zPrints a spinner character.

Args:
  stream: Stream to print messages. Usually sys.stderr, but customizable
          for testing.
N)rm   rT   rx   rj   )rE   ry   s     r,   PrintSpinner!StatusMessageManager.PrintSpinner+  s4     	??ll4??$t+, r+   c                 Z   [        U R                  5      S:  a  XR                  S   R                  -
  U R                  :  a^  U R                  R	                  5         [        U R                  5      S:  a+  XR                  S   R                  -
  U R                  :  a  M^  U R                  (       d  gU R                  S   nU R
                  UR                  :X  a  SU l        gX#R                  -
  U R
                  UR                  -
  -  U l        [        SU R                  5      U l        g)af  Updates throughput if the required period for calculation has passed.

The throughput is calculated by taking all the progress (objects or bytes)
processed within the last sliding_throughput_period seconds, and dividing
that by the time period between the oldest progress time within that range
and the last progress measurement, which are defined by oldest_progress[1]
and last_progress_time, respectively. Among the pros of this approach,
a connection break or a sudden change in throughput is quickly noticeable.
Furthermore, using the last throughput measurement rather than the current
time allows us to have a better estimation of the actual throughput.

Args:
  cur_time: Current time to check whether or not it is time for a new
            throughput measurement.
  cur_progress: The current progress, in number of objects finished or in
                bytes.
r   r   N)	r4   r`   rD   rR   popleftra   r_   rC   max)rE   r   cur_progressoldest_progresss       r,   UpdateThroughput%StatusMessageManager.UpdateThroughput6  s   $ t  !A%(5F5Fq5I5N5N*N+++,
! t  !A%(5F5Fq5I5N5N*N+++, ''*O/"6"66do %'?'??///2F2FFHDO !T__-DOr+   c                 4   S[        U R                  5      -  nU R                  (       a  US[        U R                  5      -  -  nU R                  [        U5      -
  nU R                  (       d+  UR                  SU-   S-   [        US5      S-  -   S-   5        gg)zPrints a final message to indicate operation succeeded.

Args:
  stream: Stream to print messages. Usually sys.stderr, but customizable
          for testing.
z#Operation completed over %s objectsz/%srw   .r   r/   N)	r   rZ   r[   r   rW   r4   rT   rx   r   )rE   ry   string_to_printremaining_widths       r,   PrintFinalSummaryMessage-StatusMessageManager.PrintFinalSummaryMessageY  s     =#D$4$456O%8IJ Ko((3+??O??llD?*S0!,s246:; = r+   )rW   rc   rU   rf   rS   ra   rZ   rX   re   rd   r`   rT   r\   r^   rR   rb   r]   r_   r[   rY   rP   rQ   rV   r   333333?   
   FNFP   )r!   r"   r#   r$   r%   objectrJ   rG   rj   rm   rt   r{   r   r   r   r   sysstderrr   r   r   r*   r    r+   r,   r<   r<   Z   s    v & &'%()*(*L\>?
,0%0FG< 	! !$

 	-!.F -0JJ =r+   r<   c                   x   ^  \ rS rSrSr        S
U 4S jjrS rS rS r\	R                  4S jrS rS	rU =r$ )MetadataManagerik  a  Manages shared state for metadata operations.

This manager is specific for metadata operations. Among its main functions,
it receives incoming StatusMessages, storing all necessary data
about the current and past states of the system necessary to display to the
UI. It also provides methods for calculating metrics such as throughput and
estimated time remaining. Finally, it provides methods for displaying messages
to the UI.
c	                 6   > [         [        U ]  UUUUUUUUS9  g)z`Instantiates a MetadataManager.

See argument documentation in StatusMessageManager base class.
rP   rQ   rR   rS   rT   rU   rV   rW   N)superr   rG   
rE   rP   rQ   rR   rS   rT   rU   rV   rW   	__class__s
            r,   rG   MetadataManager.__init__v  s4     
/
/D/D3L2J$.%0!('4  6r+   c                     U R                   $ )zUGets the progress for a MetadataManager.

Returns:
  The number of finished objects.
)rd   ri   s    r,   GetProgressMetadataManager.GetProgress  s        r+   c                 p   U =R                   S-  sl         U R                  [        R                  :  a*  [        R                  U l        U =R                  S-  sl        SU l        UR                  U l        U R                   U R                  :X  a'  U R                  [        R                  :X  a  SU l	        ggg)zYHandles a MetadataMessage.

Args:
  status_message: The MetadataMessage to be processed.
r   TN)
rd   rX   r   r)   rZ   re   rD   ra   r&   rf   rr   s     r,   _HandleMetadataMessage&MetadataManager._HandleMetadataMessage  s     	Q"2"F"FF 0 D Dd
! $D,11D!1!11#3#I#IId 	J 	2r+   c                    SU l         [        U[        5      (       a  U R                  X5        O[        U[        5      (       a  U R                  U5        On[        U[        5      (       a  U R                  U5        OG[        U[        5      (       a  [        U5        O&[        U[        5      (       a  U R                  U5        U R                  R                  U R                  U R                  UR                   5      5        g)zProcesses a message from _MainThreadUIQueue or _UIThread.

Args:
  status_message: The StatusMessage item to be processed.
  stream: Stream to print messages.
FN)re   
isinstancer   r{   r   rt   r   r   r   r
   r   r   r`   appendrJ   rd   rD   rE   rs   ry   s      r,   ProcessMessageMetadataManager.ProcessMessage  s     !&D."233
"">:	N$9	:	:
''7	NO	4	4
!!.1	N$9	:	:'	N$=	>	>
++N;##D$9$9>;N;NOQr+   c           
         U R                   U R                  -
  nU R                  (       a  X R                  -  nOSnU R                  5       nU R                  [
        R                  ::  a  S[        U R                  5      -   S-   [        U R                   5      -   S-   nU R                   U R                  :X  a  SnO;S[        S[        S[        U R                  5      -  U R                   -  5      5      -  nUS	-   nOS[        U R                  5      -   S-   nS
nU R                  U R                  -
  U R                  :  aP  SU R                  -  nU R                  [
        R                  ::  a   U R                  (       a  S[        U5      -   n	OS
n	OS
nS
n	Sn
U
R!                  UUUUU	S9nU R"                  [%        U5      -
  nU R&                  (       d%  UR)                  U[+        US5      S-  -   S-   5        gg)aO  Prints progress and throughput/time estimation.

Prints total number of objects and number of finished objects with the
percentage of work done, potentially including the throughput
(in objects/second) and estimated time remaining.

Args:
  stream: Stream to print messages. Usually sys.stderr, but customizable
          for testing.
N[rL   z	 objects]100%3dc   d   % Done z%.2f objects/sETA z\{char_to_print} {objects_completed} {percentage_completed} {throughput} {time_remaining_str})char_to_printobjects_completedpercentage_completedr_   time_remaining_strr   r/   r   )rZ   rd   r_   rj   rX   r   r'   r   minr1   r3   r\   r]   rS   r(   r   formatrW   r4   rT   rx   r   )rE   ry   total_remainingtime_remainingr   r   
percentager   r_   r   
format_strr   r   s                r,   PrintProgressMetadataManager.PrintProgress  s    &&)>)>>O&8nnOO%M"2"D"DDd.C.C!DDsJ'(8(89:<GH			T22	2
 CeD$9$9::T=M=MMNOP 	 ((2 d.C.C!DD&'!!DOO3

'
'	( $doo5j

!
!%5%N%N
Noo $j&@@j7J ''#+1- ( /O ((3+??O??ll?c/1&=&CDtKL r+   c           	      d    [        U[        [        [        [        [
        [        45      (       a  ggzDetermines whether this manager is suitable for handling status_message.

Args:
  status_message: The StatusMessage object to be analyzed.
Returns:
  True if this message can be properly handled by this manager,
  False otherwise.
TF)r   r   r   r   r   r   r   rr   s     r,   CanHandleMessage MetadataManager.CanHandleMessage  s1     	0/<	 9	;< < r+   )rf   ra   rX   re   r   )r!   r"   r#   r$   r%   rG   r   r   r   r   r   r   r   r*   __classcell__r   s   @r,   r   r   k  sQ     &'%()*(*62! "Q* "% >M@ r+   r   c                      ^  \ rS rSrSr " S S\5      r        SU 4S jjrS rS r	S r
S	 rS
 rS r\R                  4S jrS rSrU =r$ )DataManageri  a  Manages shared state for data operations.

This manager is specific for data operations. Among its main functions,
it receives incoming StatusMessages, storing all necessary data
about the current and past states of the system necessary to display to the
UI. It also provides methods for calculating metrics such as throughput and
estimated time remaining. Finally, it provides methods for displaying messages
to the UI.
c                       \ rS rSrSrS rSrg) DataManager._ProgressInformationi  zClass that contains all progress information needed for a given file.

This _ProgressInformation is used as the value associated with a file_name
in the dict that stores the information about all processed files.
c                 :    SU l         SU l        0 U l        Xl        g)zPConstructor of _ProgressInformation.

Args:
  size: The total size of the file.
r   N)new_progress_sumexisting_progress_sumdictrq   )rE   rq   s     r,   rG   )DataManager._ProgressInformation.__init__   s$      d $%d 
 diir+   )r   r   r   rq   NrI   r    r+   r,   _ProgressInformationr     s    r+   r   c	                    > [         [        U ]  UUUUUUUUS9  SU l        SU l        SU l        SU l        0 U l        SU l        SU l	        SU l
        g)z\Instantiates a DataManager.

See argument documentation in StatusMessageManager base class.
r   Tr   N)r   r   rG   
first_itemtotal_progressnew_progressexisting_progressindividual_file_progresscomponent_totalfinished_componentsexisting_componentsr   s
            r,   rG   DataManager.__init__3  sw     
+
/D/D3L2J$.%0!('4  6 DODDD %'D!D D Dr+   c                     U R                   $ )zbGets the progress for a DataManager.

Returns:
  The number of processed bytes in this operation.
)r   ri   s    r,   r   DataManager.GetProgressZ  s     r+   c                    UR                   (       Gd`  U R                  (       aK  U R                  (       d:  UR                  U l        U R                  U l        U R                  U l        SU l        UR                  R                  nUR                  (       a  UR                  OSUl	        U R                  UR                  5      U R                  U'   U R                  [        R                  :  a*  [        R                  U l        U =R                  S-  sl        U R                   [        R                  :  a4  [        R                  U l        U =R"                  UR                  -  sl        SU l        gU =R&                  S-  sl        UR                  R                  nU R                  U   nUR(                  UR*                  -   nU =R,                  UR                  U-
  -  sl        U =R.                  UR                  U-
  -  sl        UR                  U l        U R                  U	 SU l        U R&                  U R                  :X  a'  U R                  [        R2                  :X  a  SU l        ggg)zgHandles a FileMessage that describes a file.

Args:
  status_message: the FileMessage to be processed.
Fr   r   TN)rp   r   rU   rD   r\   r]   last_throughput_timesrc_url
url_stringrq   r   r   rX   r   r)   rZ   rY   r[   re   rd   r   r   r   r   ra   r&   rf   )rE   rs   	file_namefile_progresstotal_bytes_transferreds        r,   _HandleFileDescription"DataManager._HandleFileDescriptionb  s    """	!1!1$2$7$7!33$($=$=! !((33i3A3F3FN//An151J1J


2d##I. 
	 	 $4$H$H	H #3"F"FA			#3#G#G	G "2!E!E>..."&d q  ((33i33I>m!.!?!?!.!D!D"E ]//2III
=--0GGG . 3 3d

'
'	
2"&d


4#3#3
3

!
!%5%K%K
K! L 4r+   c                 x   UR                   nU[        R                  :H  =(       d    U[        R                  :H  =(       d{    U[        R                  :H  =(       da    U[        R
                  :H  =(       dG    U[        R                  :H  =(       d-    U[        R                  :H  =(       d    U[        R                  :H  $ )zTells whether or not this FileMessage represent a file.

This is needed because FileMessage is used by both files and components.

Args:
  file_message: The FileMessage to be analyzed.
Returns:
  Whether or not this represents a file.
)	message_typer   FILE_DOWNLOADFILE_UPLOADFILE_CLOUD_COPYFILE_DAISY_COPYFILE_LOCAL_COPYFILE_REWRITE	FILE_HASH)rE   file_messager   s      r,   _IsFileDataManager._IsFile  s      ,,LK555 2K3332K7772 K7772 K777	2
 K4442 K1113r+   c                    UR                   [        R                  :X  a  UR                  (       d  U =R                  S-  sl        UR
                  R                  nU R                  U   nUR                  UR                  4nSUR                  4UR                  U'   U=R                  UR                  -  sl        U =R                  UR                  -  sl        U =R                  UR                  -  sl        gUR                   [        R                  :X  d  UR                   [        R                   :X  Ga$  UR                  (       d  U =R"                  S-  sl        UR                   [        R                   :X  a  UR
                  R                  nU R                  U   nU=R                  UR$                  -  sl        UR                  UR                  4nSUR$                  4UR                  U'   U =R                  UR$                  -  sl        U =R                  UR$                  -  sl        ggU =R&                  S-  sl        UR
                  R                  nU R                  U   nUR                  UR                  4nXCR                  ;   a  UR                  U   OSnU =R                  UR                  [)        U5      -
  -  sl        U =R*                  UR                  [)        U5      -
  -  sl        UR,                  U l        U=R0                  UR                  [)        U5      -
  -  sl        UR                  US   -
  US   4UR                  U'   gg)zlHandles a FileMessage that describes a component.

Args:
  status_message: The FileMessage to be processed.
r   r   r   r   N)r   r   EXISTING_COMPONENTrp   r   r   r   r   component_numdst_urlrq   r   r   r   r   COMPONENT_TO_UPLOADCOMPONENT_TO_DOWNLOADr   bytes_already_downloadedr   sumr   rD   ra   r   rE   rs   r   r   keylast_updates         r,   _HandleComponentDescription'DataManager._HandleComponentDescription  s    	##{'E'EE##
!# ((33i33I>m))>+A+ABc!"N$7$7 8m))^-@-@@)
^000
 3 33&&+*I*II&&+*K*KK$$!&&+*K*KK$,,77)77	B-

-
-557
-  --~/E/EF#%&(O(O$P-

S
!


!H!H
H


 
 N$K$K
K
  L 	  A% "**55	55i@++^-C-CD259K9K2K}))#. 	~22S5EEE^003{3CCC"0"5"5&&>+>+>+.{+;,< 	=&#1#6#6Q#G#.q>#33? Lr+   c                 *   UR                   R                  nU R                  U   nUR                  UR                  4nXCR
                  ;   a  UR
                  U   OSnU=R                  US   -  sl        U=R                  UR                  US   -
  -  sl        U =R                  UR                  US   -
  -  sl        U =R                  UR                  US   -
  -  sl	        UR                  US   4UR
                  U'   UR                  U l        g)zHandles a ProgressMessage that tracks progress of a file or component.

Args:
  status_message: The ProgressMessage to be processed.
r  r   r   N)r   r   r   r  r  r   processed_bytesr   r   r   rD   ra   r
  s         r,   _HandleProgressMessage"DataManager._HandleProgressMessage  s    &&11I11)<M
 '')?)?
@C.15G5G.G=%%c* ""k!n4"""~'E'E'21~(6 7" 	>99KNJJ77+a.HH-=={1~NMs,11Dr+   c                    SU l         [        U[        5      (       a  U R                  U5        O[        U[        5      (       a  U R                  X5        O[        U[        5      (       aC  U R                  U5      (       a  U R                  U5        OU R                  U5        [        US9  On[        U[        5      (       a  U R                  U5        OG[        U[        5      (       a  [        U5        O&[        U[        5      (       a  U R!                  U5        U R"                  R%                  U R'                  U R(                  UR*                  5      5        g)zProcesses a message from _MainThreadUIQueue or _UIThread.

Args:
  status_message: The StatusMessage item to be processed.
  stream: Stream to print messages. Here only for SeekAheadThread
F)r   N)re   r   r   rt   r   r{   r   r   r   r  r	   r   r  r   r
   r   r   r`   r   rJ   r   rD   r   s      r,   r   DataManager.ProcessMessage  s    !&D."788
''7	N$4	5	5
"">:	NK	0	0	n	%	%##N3 	((8!~>	NO	4	4
!!.1	N$9	:	:'	N$=	>	>
++N;##D$5$5~7J7JKMr+   c           
         U R                   U R                  -
  nU R                  (       a  X R                  -  nOSnU R                  5       nU R                  [
        R                  ::  a5  S[        U R                  5      -   S-   [        U R                  5      -   S-   nOS[        U R                  5      -   S-   nS[        U R                  5      < S[        U R                   5      < S3nU R                  [
        R                  ::  a^  U R                  U R                  :X  a  SnO;S[        S[        S	[        U R                  5      -  U R                   -  5      5      -  nUS
-   nOSnU R                  U R                   -
  U R"                  :  aY  [        U R                  5      S-   n	U R                  [
        R$                  ::  a   U R                  (       a  S['        U5      -   n
OSn
OSn	Sn
SnUR)                  UUUUU	U
S9nU R*                  [-        U5      -
  nU R.                  (       d%  UR1                  U[3        US5      S-  -   S-   5        gg)a  Prints progress and throughput/time estimation.

If a ProducerThreadMessage or SeekAheadMessage has been provided,
it outputs the number of files completed, number of total files,
the current progress, the total size, and the percentage it
represents.
If none of those have been provided, it only includes the number of files
completed, the current progress and total size (which might be updated),
with no percentage as we do not know if more files are coming.
It may also include time estimation (available only given
ProducerThreadMessage or SeekAheadMessage provided) and throughput. For that
to happen, there is an extra condition of at least first_throughput_latency
seconds having been passed since the UIController started, and that
either the ProducerThread or the SeekAheadThread have estimated total
number of files and total size.

Args:
  stream: Stream to print messages. Usually sys.stderr, but customizable
          for testing.
Nr   rL   z files]]r   r   r   r   r   r   z/sr   zl{char_to_print} {objects_completed}{bytes_progress} {percentage_completed} {throughput} {time_remaining_str})r   r   bytes_progressr   r_   r   r   r/   r   )r[   r   r_   rj   rX   r   r'   r   rd   rZ   r:   rY   r   r1   r3   r\   r]   rS   r(   r   r   rW   r4   rT   rx   r   )rE   ry   r   r   r   r   r  r   r   r_   r   r   r   r   s                 r,   r   DataManager.PrintProgress"  s0   , oo(;(;;O&8nnOO%M"2"D"DDd.C.C!DDsJ'(8(89:<EF T-B-B CCiO $;$5dooFHN !1!C!CC			T22	2
 CeD$7$7884??JKLM 	 ((2!!DOO3

'
'	( +4??;dBj

 
 $4$M$M
Moo $j&@@jNJ ''#+%1- ( /O ((3+??O??ll?c/1&=&CDtKL r+   c           
      n    [        U[        [        [        [        [
        [        [        45      (       a  ggr   )r   r   r   r   r   r   r   r   rr   s     r,   r   DataManager.CanHandleMessagev  s5     .!#   r+   )r   r   r   rf   r   r   r   ra   r   r   rX   re   r\   r]   r   rY   r   r   r   r   FNFN)r!   r"   r#   r$   r%   r   r   rG   r   r   r   r  r  r   r   r   r   r   r*   r   r   s   @r,   r   r     sq    V 6 &'%()*(*!%!N3"j3&63p24$ML "% RMh r+   r   c                   F    \ rS rSrSr        SS jrS	S jrS	S jrSrg)
UIControlleri  zController UI class to integrate _MainThreadUIQueue and _UIThread.

This class receives messages from _MainThreadUIQueue and _UIThread and send
them to an appropriate manager, which will then processes and store data about
them.
Nc	                     Xpl         Xl        X l        X0l        X@l        SU l        XPl        X`l        SU l        / U l	        SU l
        SU l        U(       a  [        US5      U l        gg)aF  Instantiates a UIController.

Args:
  update_message_period: Minimum period for refreshing and  displaying
      new information. A non-positive value will ignore any time
      restrictions imposed by this field.
  update_spinner_period: Minimum period for refreshing and displaying the
      spinner. A non-positive value will ignore any time restrictions
      imposed by this field.
  sliding_throughput_period: Sliding period for throughput calculation. A
      non-positive value will make it impossible to calculate the
      throughput.
  first_throughput_latency: Minimum waiting time before actually displaying
      throughput info. A non-positive value will ignore any time
      restrictions imposed by this field.
  quiet_mode: If True, do not print status messages (but still process
      them for analytics reporting as necessary).
  custom_time: If a custom start_time is desired. Used for testing.
  verbose: Tells whether or not the operation is on verbose mode.
  dump_status_messages_file: File path for logging all received status
      messages, for debugging purposes.
Nr   Fab)rV   rP   rQ   rR   rS   managerrT   rU   rW   early_estimation_messagesprinted_final_messagedump_status_message_fpopen)	rE   rP   rQ   rR   rS   rT   rU   rV   dump_status_messages_files	            r,   rG   UIController.__init__  sm    > L!6!6%>"$<!DL O"D &(D"!&D"&D $()BD$Id! !r+   c                 H   U R                   R                  X5        U R                   R                  U5      (       a~  U R                   R                  U5      (       a3  U R                   R	                  X0R                   R                  5       5        U R                   R                  U5        X0R                   l        U R                   R                  U5      (       a+  U R                   R                  U5        X0R                   l
        [        U[        5      (       d  U R                   R                  (       an  U R                   R                  (       aR  U R                  (       d@  SU l        [!        U R                   R                  S9  U R                   R#                  U5        gggg)a  Processes a message, updates throughput and prints progress.

Args:
  status_message: Message to be processed. Could be None if UIThread cannot
                  retrieve message from status_queue.
  stream: stream to print messages. Usually sys.stderr, but customizable
          for testing.
  cur_time: Message time. Used to determine if it is time to refresh
            output, or calculate throughput.
T)num_objects_transferredN)r   r   r   r   r   r   r   r\   r   r   r^   r   r   rf   rZ   r"  r	   r   )rE   rs   ry   r   s       r,   _HandleMessageUIController._HandleMessage  s    	LL7||''11		+	+H	5	5%%h0H0H0JK
ll  (*2ll'||&&x00
ll'*2ll'	NL	1	1T\\5O5OLL$$T-G-G#'d !"&,,":":<
ll++F3	 .H$ 6Pr+   c                    [        U[        5      (       d  U[        :X  a  U R                  (       d  [	        U R
                  U R                  U R                  U R                  U R                  U R                  U R                  U R                  S9U l        U R                   H  nU R                  UUUR                  S9  M      gU R                   (       a?  U R                   R#                  [%        U5      5        U R                   R#                  S5        U(       d  UR                  nU R                  (       Gdp  [        U[&        5      (       d  [        U[(        5      (       a  U R                  R+                  U5        g[        U[,        5      (       a  [/        U R
                  U R                  U R                  U R                  U R                  U R                  U R                  U R                  S9U l        U R                   H  nU R                  XBU5        M     O[	        U R
                  U R                  U R                  U R                  U R                  U R                  U R                  U R                  S9U l        U R                   H  nU R                  XBU5        M     U R                  R1                  U5      (       d  [        U[2        5      (       d  [        U[4        5      (       a  [	        U R
                  U R                  U R                  U R                  U R                  U R                  U R                  S9U l        U R                   H  nU R                  XBU5        M     OgU R                  XU5        g)a  Coordinates UI manager and calls appropriate function to handle message.

Args:
  status_message: Message to be processed. Could be None if UIThread cannot
                  retrieve message from status_queue.
  stream: Stream to print messages. Usually sys.stderr, but customizable
          for testing.
  cur_time: Message time. Used to determine if it is time to refresh
            output, or calculate throughput.
r   )r   Nrw   )rP   rQ   rR   rS   rU   rV   rW   )r   r   _ZERO_TASKS_TO_DO_ARGUMENTr   r   rP   rQ   rR   rS   rT   rU   rV   rW   r!  r)  rD   r#  rx   strr   r   r   r   r   r   r   r   )rE   rs   ry   r   estimation_messages        r,   CallUIController.Call  s    nm44	5	5dll#"&"<"<"&"<"<&*&D&D%)%B%B((LL,,. #'"@"@


0$'9'>'>  @ #A "" !!''N(;<
!!''-$$h<<<
^%5
6
6
^%:
;
;&&--n=no66'"&"<"<"&"<"<&*&D&D%)%B%B((LL,,. #'"@"@


0(
C #A $"&"<"<"&"<"<&*&D&D%)%B%B((LL,,. #'"@"@


0(
C #A<<((88
^[
1
1
^_
5
5 $"&"<"<"&"<"<&*&D&D%)%B%B((LL,,. #'"@"@


0(
C #A 	9r+   )rW   rU   r#  r!  rS   r   r"  rT   rR   rP   rQ   rV   r  N)	r!   r"   r#   r$   r%   rG   r)  r/  r*   r    r+   r,   r  r    s3     &'%()*(*)-/Jb46Z:r+   r  c                   6   ^  \ rS rSrSrU 4S jrSS jrSrU =r$ )MainThreadUIQueuei=  a  Handles status display and processing in the main thread / master process.

This class emulates a queue to cover main-thread activity before or after
Apply, as well as for the single-threaded, single-process case, i.e.,
_SequentialApply. When multiple threads or processes are used during calls
to Apply, the main thread is waiting for work to complete, and this queue
must remain unused until Apply returns. Code producing arguments for
Apply (such as the NameExpansionIterator) must not post messages to this
queue to avoid race conditions with the UIThread.

This class sends the messages it receives to UIController, which
decides the correct course of action.
c                 B   > [         [        U ]  5         X l        Xl        g)zInstantiates a _MainThreadUIQueue.

Args:
  stream: Stream for printing messages.
  ui_controller: UIController to manage messages.
N)r   r3  rG   ui_controllerry   )rE   ry   r5  r   s      r,   rG   MainThreadUIQueue.__init__L  s     

T+-&Kr+   c                 N    U R                   R                  XR                  5        g r1  )r5  r/  ry   )rE   rs   timeouts      r,   putMainThreadUIQueue.putY  s    NKK8r+   )ry   r5  r1  )	r!   r"   r#   r$   r%   rG   r9  r*   r   r   s   @r,   r3  r3  =  s    
9 9r+   r3  c                   6   ^  \ rS rSrSrSU 4S jjrS rSrU =r$ )UIThreadi_  a  Responsible for centralized printing across multiple processes/threads.

This class pulls status messages that are posted to the centralized status
queue and coordinates displaying status and progress to the user. It is
used only during calls to _ParallelApply, which in turn is called only when
multiple threads and/or processes are used.

This class sends the messages it receives to UIController, which
decides the correct course of action.
c                 z   > [         [        U ]  5         Xl        X l        X@l        X0l        U R                  5         g)zInstantiates a _UIThread.

Args:
  status_queue: Queue for reporting status updates.
  stream: Stream for printing messages.
  ui_controller: UI controller to manage messages.
  timeout: Timeout for getting a message.
N)r   r<  rG   status_queuery   r8  r5  start)rE   r>  ry   r5  r8  r   s        r,   rG   UIThread.__init__k  s1     
(D"$$KL&JJLr+   c                 V      U R                   R                  U R                  S9nU R
                  R                  XR                  5        U[        :X  a  g MV  ! [        R                   a    S n Mp  f = f! [         a(  nU R                  R                  SU-  5         S nAg S nAff = f)N)r8  zException in UIThread: %s
)r>  getr8  QueueEmptyr5  r/  ry   r,  	Exceptionrx   )rE   rs   es      r,   runUIThread.run|  s    ;	,,000F. 	<77
  {{ 	.
	  ;
kk59::;s?   A6 #A /A6 A6 A3/A6 2A33A6 6
B( B##B()r>  ry   r8  r5  r   )	r!   r"   r#   r$   r%   rG   rG  r*   r   r   s   @r,   r<  r<  _  s    	"; ;r+   r<  rI  ).r%   
__future__r   r   r   r   collectionsr   r   	threadingrD   	six.movesr   rC  gslib.metricsr	   r
   gslib.thread_messager   r   r   r   r   r   r   r   r   gslib.utilsr   gslib.utils.unit_utilr   r   r   r   ZERO_TASKS_TO_DO_ARGUMENTr,  r   r   r:   r<   r   r   r  r3  Threadr<  r    r+   r,   <module>rT     s    M & %  '  
   $ 5 + , - 0 : 6 0 6 1 . 2 . @ 3 , 88 v (+(N=6 N=b`* `F{& {|n:6 n:b9 9D*;y *;r+   