44import filecmp
55import json
66import os
7+ import pty
78import sys
89import unittest
910import uuid
@@ -114,6 +115,63 @@ def _put_test_col(args, uuid=str(uuid.uuid4()), replica='aws'):
114115 with CapturingIO ('stdout' ):
115116 hca .cli .main (args = base_args )
116117
118+ def test_upload_progress_bar (self ):
119+ dirpath = os .path .join (TEST_DIR , 'tutorial' , 'data' ) # arbitrary and small
120+ put_args = ['dss' , 'upload' , '--src-dir' , dirpath , '--replica' ,
121+ 'aws' , '--staging-bucket' , 'org-humancellatlas-dss-cli-test' ]
122+
123+ with self .subTest ("Suppress progress bar if not interactive" ):
124+ with CapturingIO ('stdout' ) as stdout :
125+ hca .cli .main (args = put_args )
126+ # If using CapturingIO, `hca dss upload` should know it's not being
127+ # invoked interactively and as such not show a progress bar. Which
128+ # means that stdout should parse nicely as json
129+ self .assertTrue (json .loads (stdout .captured ()))
130+
131+ @unittest .skipIf (os .name is 'nt' , 'No pty support on Windows' )
132+ def test_upload_progress_bar_interactive (self ):
133+ """Tests upload progress bar with a simulated interactive session"""
134+ dirpath = os .path .join (TEST_DIR , 'tutorial' , 'data' ) # arbitrary and small
135+ put_args = ['dss' , 'upload' , '--src-dir' , dirpath , '--replica' ,
136+ 'aws' , '--staging-bucket' , 'org-humancellatlas-dss-cli-test' ]
137+
138+ # In an interactive session, we should see a progress bar if we
139+ # don't pass `--no-progress`.
140+ with self .subTest ("Show progress bar if interactive" ):
141+ child_pid , fd = pty .fork ()
142+ if child_pid == 0 :
143+ hca .cli .main (args = put_args )
144+ os ._exit (0 )
145+ output = self ._get_child_output (child_pid , fd )
146+ self .assertTrue ('Uploading to aws' in output , output )
147+
148+ with self .subTest ("Don't show progress bar if interactive and not logging INFO" ):
149+ child_pid , fd = pty .fork ()
150+ if child_pid == 0 :
151+ hca .cli .main (args = ['--log-level' , 'WARNING' ] + put_args )
152+ os ._exit (0 )
153+ output = self ._get_child_output (child_pid , fd )
154+ self .assertFalse ('Uploading to aws' in output , output )
155+
156+ with self .subTest ("Don't show progress bar if interactive and --no-progress" ):
157+ child_pid , fd = pty .fork ()
158+ if child_pid == 0 :
159+ hca .cli .main (args = put_args + ['--no-progress' ])
160+ os ._exit (0 )
161+ output = self ._get_child_output (child_pid , fd )
162+ self .assertFalse ('Uploading to aws' in output , output )
163+
164+ @staticmethod
165+ def _get_child_output (child_pid , fd ):
166+ output = ''
167+ while not os .waitpid (child_pid , os .WNOHANG )[0 ]:
168+ try :
169+ output += os .read (fd , 128 ).decode ()
170+ except OSError :
171+ break
172+ os .close (fd )
173+ return output
174+
117175 @staticmethod
118176 @contextlib .contextmanager
119177 def _put_test_bdl (dirpath = os .path .join (TEST_DIR , 'res' , 'bundle' ),
@@ -130,8 +188,8 @@ def _put_test_bdl(dirpath=os.path.join(TEST_DIR, 'res', 'bundle'),
130188 :rtype: dict
131189 :returns: upload response object
132190 """
133- put_args = ['dss' , 'upload' , '--src-dir' , dirpath , '--replica' ,
134- replica , '--staging-bucket' , staging_bucket ]
191+ put_args = ['dss' , 'upload' , '--src-dir' , dirpath , '--replica' ,
192+ replica , '--staging-bucket' , staging_bucket , '--no-progress' ]
135193 with CapturingIO ('stdout' ) as stdout :
136194 hca .cli .main (args = put_args )
137195 rv = json .loads (stdout .captured ())
@@ -168,8 +226,8 @@ def test_collection_download(self):
168226 '--name' , 'collection_test:%s' % bdl ['bundle_uuid' ]
169227 ]
170228 with self ._put_test_col (put_col_args ) as col , \
171- tempfile .TemporaryDirectory () as t1 , \
172- tempfile .TemporaryDirectory () as t2 :
229+ tempfile .TemporaryDirectory () as t1 , \
230+ tempfile .TemporaryDirectory () as t2 :
173231 dl_col_args = ['dss' , 'download-collection' , '--uuid' , col ['uuid' ],
174232 '--replica' , 'aws' , '--download-dir' , t1 ]
175233 hca .cli .main (args = dl_col_args )
0 commit comments