11"""
22"""
33import copy
4- import glob
54import shutil
6- import time
5+ import stat
76from pathlib import Path
87
98import pandas as pd
9+ import paramiko
1010import pytest
1111import ssh_test_utils
1212import test_utils
1313from file_conflicts_pathtable import get_pathtable
14- from pytest import ssh_config
14+ # from pytest import ssh_config
1515
16+ from datashuttle .utils import ssh
17+
18+ TEST_SSH = True # TODO: base on whether docker / singularity is installed.
1619
1720class TestFileTransfer :
1821 @pytest .fixture (
1922 scope = "class" ,
20- params = [ # Set running SSH or local filesystem (see docstring).
21- False ,
23+ params = [
24+ # False,
2225 pytest .param (
2326 True ,
2427 marks = pytest .mark .skipif (
25- ssh_config .TEST_SSH is False ,
26- reason = "TEST_SSH is set to False." ,
28+ TEST_SSH is False , reason = "TEST_SSH is set to False."
2729 ),
2830 ),
2931 ],
3032 )
31- def pathtable_and_project (self , request , tmpdir_factory ):
33+ def project_and_test_information (self , request , tmpdir_factory ):
3234 """
3335 Create a project for SSH testing. Setup
3436 the project as normal, and switch configs
@@ -72,44 +74,24 @@ def pathtable_and_project(self, request, tmpdir_factory):
7274 testing_ssh = request .param
7375 tmp_path = tmpdir_factory .mktemp ("test" )
7476
75- if testing_ssh :
76- base_path = ssh_config .FILESYSTEM_PATH
77- central_path = ssh_config .SERVER_PATH
78- else :
79- base_path = tmp_path / "test with space"
80- central_path = base_path
77+ base_path = tmp_path / "test with space"
8178 test_project_name = "test_file_conflicts"
8279
8380 project , cwd = test_utils .setup_project_fixture (
8481 base_path , test_project_name
8582 )
8683
8784 if testing_ssh :
88- ssh_test_utils .setup_project_for_ssh (
89- project ,
90- test_utils .make_test_path (
91- central_path , test_project_name , "central"
92- ),
93- ssh_config .CENTRAL_HOST_ID ,
94- ssh_config .USERNAME ,
95- )
96-
97- # Initialise the SSH connection
85+ ssh_test_utils .build_docker_image (project )
9886 ssh_test_utils .setup_hostkeys (project )
99- shutil .copy (ssh_config .SSH_KEY_PATH , project .cfg .file_path .parent )
10087
10188 pathtable = get_pathtable (project .cfg ["local_path" ])
10289 self .create_all_pathtable_files (pathtable )
103- project .testing_ssh = testing_ssh
10490
105- yield [pathtable , project ]
91+ yield [pathtable , project , testing_ssh ]
10692
10793 test_utils .teardown_project (cwd , project )
10894
109- if testing_ssh :
110- for result in glob .glob (ssh_config .FILESYSTEM_PATH ):
111- shutil .rmtree (result )
112-
11395 # -------------------------------------------------------------------------
11496 # Utils
11597 # -------------------------------------------------------------------------
@@ -156,14 +138,14 @@ def central_from_local(self, path_):
156138 ["histology" , "behav" , "all_ses_level_non_datatype" ],
157139 ],
158140 )
159- @pytest .mark .parametrize ("upload_or_download" , ["upload" , "download" ])
141+ # @pytest.mark.parametrize("upload_or_download", ["upload", "download"])
160142 def test_all_data_transfer_options (
161143 self ,
162- pathtable_and_project ,
144+ project_and_test_information ,
163145 sub_names ,
164146 ses_names ,
165147 datatype ,
166- upload_or_download ,
148+ # upload_or_download,
167149 ):
168150 """
169151 Parse the arguments to filter the pathtable, getting
@@ -175,31 +157,31 @@ def test_all_data_transfer_options(
175157 on setting up and swapping local / central paths for
176158 upload / download tests.
177159 """
178- pathtable , project = pathtable_and_project
160+ pathtable , project , testing_ssh = project_and_test_information
179161
180- transfer_function = test_utils .handle_upload_or_download (
181- project ,
182- upload_or_download ,
183- swap_last_folder_only = project . testing_ssh ,
184- )[0 ]
162+ # transfer_function = test_utils.handle_upload_or_download(
163+ # project,
164+ # upload_or_download,
165+ # swap_last_folder_only=testing_ssh,
166+ # )[0]
185167
186- transfer_function (sub_names , ses_names , datatype , init_log = False )
168+ project .upload (sub_names , ses_names , datatype , init_log = False )
169+ # transfer_function(sub_names, ses_names, datatype, init_log=False)
187170
188- if upload_or_download == "download" :
189- test_utils .swap_local_and_central_paths (
190- project , swap_last_folder_only = project . testing_ssh
191- )
171+ # if upload_or_download == "download":
172+ # test_utils.swap_local_and_central_paths(
173+ # project, swap_last_folder_only=testing_ssh
174+ # )
192175
193- sub_names = self .parse_arguments (pathtable , sub_names , "sub" )
194- ses_names = self .parse_arguments (pathtable , ses_names , "ses" )
195- datatype = self .parse_arguments (pathtable , datatype , "datatype" )
176+ parsed_sub_names = self .parse_arguments (pathtable , sub_names , "sub" )
177+ parsed_ses_names = self .parse_arguments (pathtable , ses_names , "ses" )
178+ parsed_datatype = self .parse_arguments (pathtable , datatype , "datatype" )
196179
197- # Filter pathtable to get files that were expected
198- # to be transferred
180+ # Filter pathtable to get files that were expected to be transferred
199181 (
200182 sub_ses_dtype_arguments ,
201183 extra_arguments ,
202- ) = self .make_pathtable_search_filter (sub_names , ses_names , datatype )
184+ ) = self .make_pathtable_search_filter (parsed_sub_names , parsed_ses_names , parsed_datatype )
203185
204186 datatype_folders = self .query_table (pathtable , sub_ses_dtype_arguments )
205187 extra_folders = self .query_table (pathtable , extra_arguments )
@@ -214,28 +196,90 @@ def test_all_data_transfer_options(
214196
215197 # When transferring with SSH, there is a delay before
216198 # filesystem catches up
217- if project . testing_ssh :
218- time .sleep (0.5 )
199+ # if testing_ssh:
200+ # time.sleep(0.5)
219201
220202 # Check what paths were actually moved
221203 # (through the local filesystem), and test
222- path_to_search = (
223- self .central_from_local (project .cfg ["local_path" ]) / "rawdata"
224- )
225- all_transferred = path_to_search .glob ("**/*" )
226- paths_to_transferred_files = list (
227- filter (Path .is_file , all_transferred )
228- )
204+ def sftp_recursive_search (sftp , path_ , all_filenames ):
205+ try :
206+ sftp .stat (path_ )
207+ except FileNotFoundError :
208+ return
209+
210+ for file_or_folder in sftp .listdir_attr (path_ ):
211+ if stat .S_ISDIR (file_or_folder .st_mode ):
212+ sftp_recursive_search (
213+ sftp ,
214+ path_ + "/" + file_or_folder .filename ,
215+ all_filenames ,
216+ )
217+ else :
218+ all_filenames .append (path_ + "/" + file_or_folder .filename )
219+
220+ with paramiko .SSHClient () as client :
221+ ssh .connect_client (client , project .cfg )
222+
223+ sftp = client .open_sftp ()
224+
225+ all_filenames = []
226+
227+ sftp_recursive_search (
228+ sftp ,
229+ (project .cfg ["central_path" ] / "rawdata" ).as_posix (),
230+ all_filenames ,
231+ )
229232
230- assert sorted (paths_to_transferred_files ) == sorted (
231- expected_transferred_paths
232- )
233+ paths_to_transferred_files = []
234+ for path_ in all_filenames :
235+ parts = Path (path_ ).parts
236+ paths_to_transferred_files .append (
237+ Path (* parts [parts .index ("rawdata" ) :])
238+ )
239+
240+ expected_transferred_paths_ = []
241+ for path_ in expected_transferred_paths :
242+ parts = Path (path_ ).parts
243+ expected_transferred_paths_ .append (
244+ Path (* parts [parts .index ("rawdata" ) :])
245+ )
246+
247+ assert sorted (paths_to_transferred_files ) == sorted (
248+ expected_transferred_paths_
249+ )
250+
251+ project .upload_all ()
252+ shutil .rmtree (project .cfg ["local_path" ] / "rawdata" ) # TOOD: var
253+
254+ breakpoint ()
255+
256+ true_local_path = project .cfg ["local_path" ]
257+ tmp_local_path = project .cfg ["local_path" ] / "tmp_local"
258+ tmp_local_path .mkdirs ()
259+ project .update_config ("local_path" , tmp_local_path )
260+
261+ project .download (sub_names , ses_names , datatype , init_log = False ) # TODO: why is this connecting so many times?
262+
263+ all_transferred = list ((project .cfg ["local_path" ] / "rawdata" ).glob ("**/*" ))
264+ all_transferred = [path_ for path_ in all_transferred if path_ .is_file ()]
265+
266+ paths_to_transferred_files = []
267+ for path_ in all_transferred : # TODO: rename all filenames
268+ parts = Path (path_ ).parts
269+ paths_to_transferred_files .append (
270+ Path (* parts [parts .index ("rawdata" ):])
271+ )
272+
273+ assert sorted (paths_to_transferred_files ) == sorted (expected_transferred_paths_ )
274+
275+ shutil .rmtree (project .cfg ["local_path" ]) # TOOD: var
276+
277+ project .update_config ("local_path" , true_local_path )
278+
279+ with paramiko .SSHClient () as client :
280+ ssh .connect_client (client , project .cfg )
233281
234- # Teardown here, because we have session scope.
235- try :
236- shutil .rmtree (self .central_from_local (project .cfg ["local_path" ]))
237- except FileNotFoundError :
238- pass
282+ client .exec_command (f"rm -rf { (project .cfg ['central_path' ] / 'rawdata' ).as_posix ()} " ) # TODO: own function as need to do on teardown)
239283
240284 # ---------------------------------------------------------------------------------------------------------------
241285 # Utils
0 commit comments