def test_long_format_list_with_null(capsys): args = MockArgs(project='f3szh', long_format=True) dates = ['null', 'null'] njson = fake_responses._build_node('nodes') fjson = fake_responses.files_node('f3szh', 'osfstorage', file_names=['hello.txt', 'bye.txt'], file_sizes=['null', 'null'], file_dates_modified=dates) sjson = fake_responses.storage_node('f3szh', ['osfstorage']) def simple_OSFCore_get(url): if url == 'https://api.osf.io/v2//nodes/f3szh/': return FakeResponse(200, njson) elif url == 'https://api.osf.io/v2/nodes/f3szh/files/': return FakeResponse(200, sjson) elif url == 'https://api.osf.io/v2/nodes/f3szh/files/osfstorage/': return FakeResponse(200, fjson) elif url == 'https://api.osf.io/v2//guids/f3szh/': return FakeResponse(200, {'data': {'type': 'nodes'}}) else: print(url) raise ValueError() with patch('osfclient.cli.get_localzone', return_value=tz.tzutc()) as mock_get_localzone: with patch.object(OSFCore, '_get', side_effect=simple_OSFCore_get) as mock_osf_get: list_(args) captured = capsys.readouterr() assert captured.err == '' expected = ['- - - osfstorage/bye.txt', '- - - osfstorage/hello.txt', ''] assert captured.out.split('\n') == expected
def test_fetch_local_file_exists_update_files_differ(OSF_project, os_makedirs): # check that `osf fetch --update` overwrites an existing local file if it # differs from the remote args = MockArgs(project='1234', remote='osfstorage/a/a/a', update=True) def exists(path): if path == ".osfcli.config": return False else: return True def simple_checksum(file_path): return '1' * 32 mock_open_func = mock_open() with patch('osfclient.cli.open', mock_open_func): with patch('osfclient.cli.os.path.exists', side_effect=exists): with patch('osfclient.cli.checksum', side_effect=simple_checksum): fetch(args) OSF_project.assert_called_once_with('1234') # check that the project and the files have been accessed store = OSF_project.return_value.storages[0] assert store._name_mock.return_value == 'osfstorage' # should create a file in the same directory when no local # filename is specified assert mock.call('a', 'wb') in mock_open_func.mock_calls
def test_clone_project(OSF_project): # check that `osf clone` opens files with the right names and modes args = MockArgs(project='1234') mock_open_func = mock_open() with patch('osfclient.cli.open', mock_open_func): with patch('osfclient.cli.makedirs'): with patch('osfclient.cli.os.getenv', side_effect='SECRET'): clone(args) OSF_project.assert_called_once_with('1234') # check that the project and the files have been accessed for store in OSF_project.return_value.storages: assert store._name_mock.called for f in store.files: assert f._path_mock.called fname = f._path_mock.return_value if fname.startswith('/'): fname = fname[1:] full_path = os.path.join('1234', store._name_mock.return_value, fname) assert call(full_path, 'wb') in mock_open_func.mock_calls
def test_fetch_local_file_exists_force_overrides_update( OSF_project, os_makedirs): # check that `osf fetch --force --update` overwrites the local file even if # it matches the remote file (force overrides update) args = MockArgs(project='1234', remote='osfstorage/a/a/a', force=True, update=True) def exists(path): if path == ".osfcli.config": return False else: return True def simple_checksum(file_path): return '0' * 32 mock_open_func = mock_open() with patch('osfclient.cli.open', mock_open_func): with patch('osfclient.cli.os.path.exists', side_effect=exists): with patch('osfclient.cli.checksum', side_effect=simple_checksum): fetch(args) OSF_project.assert_called_once_with('1234') # check that the project and the files have been accessed store = OSF_project.return_value.storages[0] assert store._name_mock.return_value == 'osfstorage' # should create a file in the same directory when no local # filename is specified. # file should be created even though local matches remote and update is # True, because force overrides update assert mock.call('a', 'wb') in mock_open_func.mock_calls
def test_fetch_file_local_name_specified(OSF_project, os_path_exists, os_makedirs): # check that `osf fetch` opens the right files with the right name # and mode when specifying a local filename args = MockArgs(project='1234', remote='osfstorage/a/a/a', local='foobar.txt') mock_open_func = mock_open() with patch('osfclient.cli.open', mock_open_func): fetch(args) OSF_project.assert_called_once_with('1234') # check that the project and the files have been accessed project = OSF_project.return_value store = project._storage_mock.return_value assert store._name_mock.return_value == 'osfstorage' expected = [call._path_mock(), call.write_to(mock_open_func())] assert expected == store.files[0].mock_calls # second file should not have been looked at assert not store.files[1].mock_calls # should create a file in the same directory when no local # filename is specified assert mock.call('foobar.txt', 'wb') in mock_open_func.mock_calls assert not os_makedirs.called
def test_select_project(OSF_project): args = MockArgs(username='******', project='1234', source='foo/bar.txt', destination='bar/bar/foo.txt') def simple_getenv(key): if key == 'OSF_PASSWORD': return 'secret' fake_open = mock_open() with patch('osfclient.cli.open', fake_open): with patch('osfclient.cli.os.getenv', side_effect=simple_getenv): upload(args) assert call('foo/bar.txt', 'rb') in fake_open.mock_calls # the mock project created by calling OSF().project() fake_project = OSF_project.return_value expected = [call('osfstorage')] assert fake_project._storage_mock.mock_calls == expected # assert fake_project.mock_calls == expected expected = [call.create_file('bar/bar/foo.txt', fake_open.return_value, force=False, update=False)] # we should call the create_file method on the return # value of _storage_mock assert fake_project._storage_mock.return_value.mock_calls == expected
def test_move_file_to_file(OSF_project): args = MockArgs(project='1234', username='******', source='osfstorage/a/a/a', target='osfstorage/c/newfile') def simple_getenv(key): if key == 'OSF_PASSWORD': return 'secret' with patch('osfclient.cli.os.getenv', side_effect=simple_getenv): move(args) OSF_project.assert_called_once_with('1234') MockProject = OSF_project.return_value MockStorage = MockProject._storage_mock.return_value for f in MockStorage.files: mock_calls = list(f.mock_calls) if f._path_mock.return_value == '/a/a/a': assert call.move_to( 'osfstorage', [f for f in MockStorage.folders if f.path == '/c'][0], to_filename='newfile', force=False) in mock_calls
def test_password_prompt(): # No password in config should trigger the password prompt # when an username is specified args = MockArgs(project='test', username='******') with patch('getpass.getpass') as getpass: getpass.return_value = 'test_password' osf = cli._setup_osf(args) assert osf.password == 'test_password'
def test_anonymous_doesnt_work(): args = MockArgs(project='1234') with pytest.raises(SystemExit) as e: upload(args) expected = 'To upload a file you need to provide either a username and password or a token.' assert expected in e.value.args[0]
def test_anonymous_doesnt_work(): args = MockArgs(project='1234') with pytest.raises(SystemExit) as e: remove(args) expected = 'remove a file you need to provide a username and password' assert expected in e.value.args[0]
def test_recursive_upload_with_subdir(OSF_project): # test that an extra level of subdirectory is created on the remote side # this is because args.source does not end in a / args = MockArgs(username='******', project='1234', source='foobar', recursive=True, destination='BAR/') def simple_getenv(key): if key == 'OSF_PASSWORD': return 'secret' fake_open = mock_open() fake_storage = OSF_project.return_value.storage.return_value # it is important we use foobar and not foobar/ to match with args.source # to mimick the behaviour of os.walk() dir_contents = [('foobar', None, ['bar.txt', 'abc.txt']), ('foobar/baz', None, ['bar.txt', 'abc.txt'])] with patch('osfclient.cli.open', fake_open): with patch('os.walk', return_value=iter(dir_contents)): with patch('osfclient.cli.os.getenv', side_effect=simple_getenv): with patch('osfclient.cli.os.path.isdir', return_value=True): upload(args) assert call('foobar/bar.txt', 'rb') in fake_open.mock_calls assert call('foobar/abc.txt', 'rb') in fake_open.mock_calls assert call('foobar/baz/bar.txt', 'rb') in fake_open.mock_calls assert call('foobar/baz/abc.txt', 'rb') in fake_open.mock_calls # two directories with two files each -> four calls plus all the # context manager __enter__ and __exit__ calls assert len(fake_open.mock_calls) == 4 + 4 * 2 fake_storage.assert_has_calls([ call.create_file('BAR/foobar/./bar.txt', mock.ANY, update=False, force=False), call.create_file('BAR/foobar/./abc.txt', mock.ANY, update=False, force=False), call.create_file('BAR/foobar/baz/bar.txt', mock.ANY, update=False, force=False), call.create_file('BAR/foobar/baz/abc.txt', mock.ANY, update=False, force=False) ]) # two directories with two files each -> four calls assert len(fake_storage.mock_calls) == 4
def test_get_project(OSF_project): args = MockArgs(project='1234') list_(args) OSF_project.assert_called_once_with('1234') # check that the project and the files have been printed for store in OSF_project.return_value.storages: assert store._name_mock.called for f in store.files: assert f._path_mock.called
def test_might_need_auth_unauthorized(config_from_file): mock_args = MockArgs(project='test', username='******') @cli.might_need_auth def dummy(x): raise UnauthorizedException() with pytest.raises(SystemExit) as e: dummy(mock_args) assert "not authorized to access" in str(e.value)
def test_might_need_auth_no_username(config_from_file): mock_args = MockArgs(project='test') @cli.might_need_auth def dummy(x): raise UnauthorizedException() with pytest.raises(SystemExit) as e: dummy(mock_args) assert "set a username" in str(e.value)
def test_init(config_from_file): mock_open_func = mock_open() with patch('osfclient.cli.open', mock_open_func): with patch('osfclient.cli.input', side_effect=['test-user', '']): cli.init(MockArgs()) assert call('.osfcli.config', 'w') in mock_open_func.mock_calls assert call().write('username = test-user\n') in mock_open_func.mock_calls assert call().write('project = pj2\n') in mock_open_func.mock_calls assert call().write('[osf]\n') in mock_open_func.mock_calls
def test_anonymous_doesnt_work(): args = MockArgs(project='1234') def simple_getenv(key): return None with pytest.raises(SystemExit) as e: with patch('osfclient.cli.os.getenv', side_effect=simple_getenv) as mock_getenv: remove(args) expected = 'remove a file you need to provide a username and password' assert expected in e.value.args[0]
def test_geturl(OSF_project, mock_stdout): # check that `osf geturl` opens the right files with the right name and mode args = MockArgs(project='1234', remote='osfstorage/a/a/a') geturl(args) OSF_project.assert_called_once_with('1234') # check that the project and the files have been accessed store = OSF_project.return_value.storages[0] assert store._name_mock.return_value == 'osfstorage' assert 'https://example.com' in mock_stdout.getvalue()
def test_username_password(MockOSF): args = MockArgs(username='******', project='1234') def simple_getenv(key): if key == 'OSF_PASSWORD': return 'secret' with patch('osfclient.cli.os.getenv', side_effect=simple_getenv) as mock_getenv: list_(args) MockOSF.assert_called_once_with(username='******', password='******') mock_getenv.assert_called_with('OSF_PASSWORD')
def test_config_project(): # No project in args or the config, should sys.exit(1) args = MockArgs(project=None) def simple_config(key): return {} with patch('osfclient.cli.config_from_env', side_effect=simple_config): with pytest.raises(SystemExit) as e: cli._setup_osf(args) expected = ('specify a project ID via the command line, configuration ' 'file or environment variable') assert expected in e.value.args[0]
def test_anonymous_doesnt_use_password(MockOSF): args = MockArgs(project='1234') def simple_getenv(key): return None with patch('osfclient.cli.os.getenv', side_effect=simple_getenv) as mock_getenv: list_(args) # if there is no username we should not try to obtain a password either assert call('OSF_USERNAME') in mock_getenv.mock_calls assert call('OSF_PASSWORD') not in mock_getenv.mock_calls MockOSF.assert_called_once_with(username=None, password=None, token=None)
def test_make_root_folder(OSF_project): args = MockArgs(project='1234', username='******', target='osfstorage/new') def simple_getenv(key): if key == 'OSF_PASSWORD': return 'secret' with patch('osfclient.cli.os.getenv', side_effect=simple_getenv): makefolder(args) OSF_project.assert_called_once_with('1234') MockProject = OSF_project.return_value MockStorage = MockProject._storage_mock.return_value assert call.create_folder('new') in MockStorage.mock_calls
def test_base_url(MockOSF): args = MockArgs(base_url='https://api.test.osf.io/v2/', project='1234') def simple_getenv(key): if key == 'OSF_TOKEN': return 'secret' with patch('osfclient.cli.os.getenv', side_effect=simple_getenv) as mock_getenv: list_(args) MockOSF.assert_called_once_with(username=None, password=None, token='secret', base_url='https://api.test.osf.io/v2/') mock_getenv.assert_called_with('OSF_TOKEN')
def test_might_need_auth_no_username(config_from_file): mock_args = MockArgs(project='test') def simple_getenv(key): return None @cli.might_need_auth def dummy(x): raise UnauthorizedException() with pytest.raises(SystemExit) as e: with patch('osfclient.cli.os.getenv', side_effect=simple_getenv) as mock_getenv: dummy(mock_args) assert "set a username" in str(e.value)
def test_remove_file(OSF_project): args = MockArgs(project='1234', username='******', target='osfstorage/a/a/a') def simple_getenv(key): if key == 'OSF_PASSWORD': return 'secret' with patch('osfclient.cli.os.getenv', side_effect=simple_getenv): remove(args) OSF_project.assert_called_once_with('1234') MockProject = OSF_project.return_value MockStorage = MockProject._storage_mock.return_value for f in MockStorage.files: if f._path_mock.return_value == '/a/a/a': assert call.remove() in f.mock_calls
def test_fetch_file(OSF_project, os_path_exists, os_makedirs): # check that `osf fetch` opens the right files with the right name and mode args = MockArgs(project='1234', remote='osfstorage/a/a/a') mock_open_func = mock_open() with patch('osfclient.cli.open', mock_open_func): fetch(args) OSF_project.assert_called_once_with('1234') # check that the project and the files have been accessed store = OSF_project.return_value.storages[0] assert store._name_mock.return_value == 'osfstorage' # should create a file in the same directory when no local # filename is specified assert mock.call('a', 'wb') in mock_open_func.mock_calls
def test_wrong_storage_name(OSF_project): args = MockArgs(project='1234', username='******', target='DOESNTEXIST/a/a/a') def simple_getenv(key): if key == 'OSF_PASSWORD': return 'secret' with patch('osfclient.cli.os.getenv', side_effect=simple_getenv): remove(args) OSF_project.assert_called_once_with('1234') # the mock storage is called osfstorage, so we should not call remove() MockProject = OSF_project.return_value MockStorage = MockProject._storage_mock.return_value for f in MockStorage.files: if f._path_mock.return_value == '/a/a/a': assert call.remove() not in f.mock_calls
def test_fetch_local_file_exists(OSF_project): # check that `osf fetch` opens the right files with the right name # and mode when specifying a local filename args = MockArgs(project='1234', remote='osfstorage/a/a/a', local='subdir/foobar.txt') def exists(path): if path == ".osfcli.config": return False else: return True with patch('osfclient.cli.os.path.exists', side_effect=exists): with pytest.raises(SystemExit) as e: fetch(args) assert 'already exists, not overwriting' in e.value.args[0]
def test_recursive_requires_directory(OSF_project): # test that we check if source is a directory when using recursive mode args = MockArgs(username='******', project='1234', source='foo/bar.txt', recursive=True, destination='bar/bar/foo.txt') def simple_getenv(key): if key == 'OSF_PASSWORD': return 'secret' with pytest.raises(RuntimeError) as e: with patch('osfclient.cli.os.getenv', side_effect=simple_getenv): with patch('osfclient.cli.os.path.isdir', return_value=False): upload(args) assert 'recursive' in str(e.value) assert 'Expected source (foo/bar.txt)' in str(e.value)
def test_non_existant_file(OSF_project): args = MockArgs(project='1234', username='******', target='osfstorage/DOESNTEXIST/a') def simple_getenv(key): if key == 'OSF_PASSWORD': return 'secret' with patch('osfclient.cli.os.getenv', side_effect=simple_getenv): remove(args) OSF_project.assert_called_once_with('1234') # check that all files in osfstorage are visited but non get deleted MockProject = OSF_project.return_value MockStorage = MockProject._storage_mock.return_value for f in MockStorage.files: assert f._path_mock.called assert call.remove() not in f.mock_calls
def test_fetch_file_local_dir_specified(OSF_project, os_path_exists, os_makedirs): # check that `osf fetch` opens the right files with the right name # and mode when specifying a local filename args = MockArgs(project='1234', remote='osfstorage/a/a/a', local='subdir/foobar.txt') mock_open_func = mock_open() with patch('osfclient.cli.open', mock_open_func): fetch(args) OSF_project.assert_called_once_with('1234') # check that the project and the files have been accessed store = OSF_project.return_value.storages[0] assert store._name_mock.return_value == 'osfstorage' assert (mock.call('subdir/foobar.txt', 'wb') in mock_open_func.mock_calls) assert mock.call('subdir', exist_ok=True) in os_makedirs.mock_calls