def _raise_on_unsuccessful_request(self, network_response, expect_json_response, method, url): """ Raise an exception if the request was unsuccessful. :param network_response: The network response which is being tested for success. :type network_response: :class:`NetworkResponse` :param expect_json_response: Whether or not the response content should be json. :type expect_json_response: `bool` :param method: The HTTP verb used to make the request. :type method: `unicode` :param url: The request URL. :type url: `unicode` """ if not network_response.ok: response_json = {} try: response_json = network_response.json() except ValueError: pass raise BoxAPIException( status=network_response.status_code, headers=network_response.headers, code=response_json.get('code', None), message=response_json.get('message', None), request_id=response_json.get('request_id', None), url=url, method=method, context_info=response_json.get('context_info', None), network_response=network_response) if expect_json_response and not self._is_json_response( network_response): raise BoxAPIException( status=network_response.status_code, headers=network_response.headers, message= 'Non-json response received, while expecting json response.', url=url, method=method, network_response=network_response)
def test_box_list_folders_returns_error_if_invalid_path( self, mock_metadata): mock_metadata.side_effect = BoxAPIException(status=404, message='File not found') url = self.project.api_url_for('box_folder_list', folder_id='lolwut') res = self.app.get(url, auth=self.user.auth, expect_errors=True) assert_equal(res.status_code, httplib.NOT_FOUND)
def test_update_contents_does_preflight_check_if_specified( test_file, mock_file_path, preflight_check, file_size, preflight_fails, mock_box_session, ): with patch.object(File, 'preflight_check', return_value=None): kwargs = {'file_path': mock_file_path} if preflight_check: kwargs['preflight_check'] = preflight_check kwargs['preflight_expected_size'] = file_size if preflight_fails: test_file.preflight_check.side_effect = BoxAPIException(400) with pytest.raises(BoxAPIException): test_file.update_contents(**kwargs) else: test_file.update_contents(**kwargs) if preflight_check: assert test_file.preflight_check.called_once_with(size=file_size) if preflight_fails: assert not mock_box_session.post.called else: assert mock_box_session.post.called else: assert not test_file.preflight_check.called
def test_box_api_exception(): status = 'status' code = 400 message = 'message' request_id = 12345 headers = {'header': 'value'} url = 'https://example.com' method = 'GET' box_exception = BoxAPIException( status, code=code, message=message, request_id=request_id, headers=headers, url=url, method=method, ) assert box_exception.status == status assert box_exception.code == code assert box_exception.message == message assert box_exception.request_id == request_id assert box_exception._headers == headers # pylint:disable=protected-access assert box_exception.url == url assert box_exception.method == method assert str(box_exception) == ''' Message: {0} Status: {1} Code: {2} Request id: {3} Headers: {4} URL: {5} Method: {6}'''.format(message, status, code, request_id, headers, url, method)
def test_upload_does_preflight_check_if_specified( mock_box_session, test_folder, mock_file_path, preflight_check, preflight_fails, file_size, ): with patch.object(Folder, 'preflight_check', return_value=None): kwargs = {'file_path': mock_file_path, 'file_name': 'foo.txt'} mock_box_session.post = MagicMock() if preflight_check: kwargs['preflight_check'] = preflight_check kwargs['preflight_expected_size'] = file_size if preflight_fails: test_folder.preflight_check.side_effect = BoxAPIException(400) with pytest.raises(BoxAPIException): test_folder.upload(**kwargs) else: test_folder.upload(**kwargs) if preflight_check: assert test_folder.preflight_check.called_once_with(size=file_size, name='foo.txt') _assert_post_called_correctly(mock_box_session, preflight_fails) else: assert not test_folder.preflight_check.called
def test_set_classification_succeeds(test_item_and_response, mock_box_session): # pylint:disable=redefined-outer-name test_item, _ = test_item_and_response metadata_response = { 'Box__Security__Classification__Key': 'Public', } expected_url = '{0}/{1}s/{2}/metadata/enterprise/securityClassification-6VMVochwUWo'.format( API.BASE_API_URL, test_item.object_type, test_item.object_id, ) post_data = { 'Box__Security__Classification__Key': 'Public', } put_data = [{ 'op': 'add', 'path': '/Box__Security__Classification__Key', 'value': 'Public', }] post_headers = {b'Content-Type': b'application/json'} put_headers = {b'Content-Type': b'application/json-patch+json'} mock_box_session.post.side_effect = [BoxAPIException(status=409)] mock_box_session.put.return_value.json.return_value = metadata_response metadata = test_item.set_classification('Public') mock_box_session.post.assert_called_once_with(expected_url, data=json.dumps(post_data), headers=post_headers) mock_box_session.put.assert_called_once_with(expected_url, data=json.dumps(put_data), headers=put_headers) assert metadata is metadata_response['Box__Security__Classification__Key']
def test_upload( test_folder, mock_box_session, mock_content_response, mock_upload_response, mock_file_path, mock_object_id, upload_using_accelerator, mock_accelerator_response_for_new_uploads, mock_new_upload_accelerator_url, upload_using_accelerator_fails, is_stream, ): expected_url = '{0}/files/content'.format(API.UPLOAD_URL) if upload_using_accelerator: if upload_using_accelerator_fails: mock_box_session.options.side_effect = BoxAPIException(400) else: mock_box_session.options.return_value = mock_accelerator_response_for_new_uploads expected_url = mock_new_upload_accelerator_url mock_box_session.post.return_value = mock_upload_response if is_stream: mock_file_stream = BytesIO(mock_content_response.content) new_file = test_folder.upload_stream( mock_file_stream, basename(mock_file_path), upload_using_accelerator=upload_using_accelerator, ) else: mock_file = mock_open(read_data=mock_content_response.content) mock_file_stream = mock_file.return_value with patch('boxsdk.object.folder.open', mock_file, create=True): new_file = test_folder.upload( mock_file_path, upload_using_accelerator=upload_using_accelerator, ) mock_files = {'file': ('unused', mock_file_stream)} data = { 'attributes': json.dumps({ 'name': basename(mock_file_path), 'parent': { 'id': mock_object_id } }) } mock_box_session.post.assert_called_once_with(expected_url, expect_json_response=False, files=mock_files, data=data) assert isinstance(new_file, File) assert new_file.object_id == mock_object_id assert 'id' in new_file assert new_file['id'] == mock_object_id assert not hasattr(new_file, 'entries') assert 'entries' not in new_file
def test_update_contents( test_file, mock_box_session, mock_content_response, mock_upload_response, mock_file_path, etag, upload_using_accelerator, mock_accelerator_response_for_update, mock_accelerator_upload_url_for_update, upload_using_accelerator_fails, if_match_header, is_stream, ): expected_url = test_file.get_url('content').replace( API.BASE_API_URL, API.UPLOAD_URL) if upload_using_accelerator: if upload_using_accelerator_fails: mock_box_session.options.side_effect = BoxAPIException(400) else: mock_box_session.options.return_value = mock_accelerator_response_for_update expected_url = mock_accelerator_upload_url_for_update mock_box_session.post.return_value = mock_upload_response if is_stream: mock_file_stream = BytesIO(mock_content_response.content) new_file = test_file.update_contents_with_stream( mock_file_stream, etag=etag, upload_using_accelerator=upload_using_accelerator, ) else: mock_file = mock_open(read_data=mock_content_response.content) mock_file_stream = mock_file.return_value with patch('boxsdk.object.file.open', mock_file, create=True): new_file = test_file.update_contents( mock_file_path, etag=etag, upload_using_accelerator=upload_using_accelerator, ) mock_files = {'file': ('unused', mock_file_stream)} mock_box_session.post.assert_called_once_with( expected_url, expect_json_response=False, files=mock_files, headers=if_match_header, ) assert isinstance(new_file, File) assert new_file.object_id == test_file.object_id assert 'id' in new_file assert new_file['id'] == test_file.object_id assert not hasattr(new_file, 'entries') assert 'entries' not in new_file
def test_set_user_status(test_terms_of_service, mock_user, mock_box_session): expected_post_url = "{0}/terms_of_service_user_statuses".format( API.BASE_API_URL) expected_put_url = "{0}/terms_of_service_user_statuses/{1}".format( API.BASE_API_URL, test_terms_of_service.object_id) post_value = json.dumps({ 'tos': { 'type': test_terms_of_service.object_type, 'id': test_terms_of_service.object_id, }, 'is_accepted': True, 'user': { 'type': mock_user.object_type, 'id': mock_user.object_id, }, }) put_value = json.dumps({'is_accepted': True}) mock_box_session.post.side_effect = [ BoxAPIException(status=409, message="Conflict") ] mock_box_session.get.return_value.json.return_value = { 'entries': [ { 'type': 'terms_of_service_user_status', 'id': '42', }, ], } mock_box_session.put.return_value.json.return_value = { 'type': 'terms_of_service_user_status', 'id': '12345', 'tos': { 'type': test_terms_of_service.object_type, 'id': test_terms_of_service.object_id, }, 'is_accepted': True, } new_terms_of_service_user_status = test_terms_of_service.set_user_status( True, mock_user) mock_box_session.post.assert_called_once_with(expected_post_url, data=post_value) mock_box_session.put.assert_called_once_with(expected_put_url, data=put_value, headers=None, params=None) assert isinstance(new_terms_of_service_user_status, TermsOfServiceUserStatus) assert new_terms_of_service_user_status.type == 'terms_of_service_user_status' assert new_terms_of_service_user_status.id == '12345' assert new_terms_of_service_user_status.tos[ 'type'] == test_terms_of_service.object_type assert new_terms_of_service_user_status.tos[ 'id'] == test_terms_of_service.object_id assert new_terms_of_service_user_status.is_accepted is True
def test_get_classification_raises_exception(test_item_and_response, mock_box_session): # pylint:disable=redefined-outer-name test_item, _ = test_item_and_response expected_url = '{0}/{1}s/{2}/metadata/enterprise/securityClassification-6VMVochwUWo'.format( API.BASE_API_URL, test_item.object_type, test_item.object_id, ) mock_box_session.get.side_effect = [BoxAPIException(status=500)] with pytest.raises(BoxAPIException): test_item.get_classification() mock_box_session.get.assert_called_once_with(expected_url)
def test_resume_in_process(test_file, mock_upload_session): file_size = 7 part_bytes = b'abcdefg' stream = io.BytesIO(part_bytes) first_part = { 'part_id': 'CFEB4BA9', 'offset': 0, 'size': 2, 'sha1': '2iNhTgJGmg18e9G9q1ycR0sZBNw=', } second_part = { 'part_id': '4DBB872D', 'offset': 2, 'size': 2, 'sha1': 'A0d4GYoEXB7YC+JxzdApt2h09vw=', } third_part = { 'part_id': '6F2D3486', 'offset': 4, 'size': 2, 'sha1': '+CIFFHGVe3u+u4qwiP6b1tFPQmE=', } fourth_part = { 'part_id': '4DBC872D', 'offset': 6, 'size': 1, 'sha1': 'VP0XESCfscB4EJI3QTLGbnniJBs=', } parts = [first_part, second_part, third_part, fourth_part] mock_iterator = MagicMock(LimitOffsetBasedDictCollection) mock_iterator.__iter__.return_value = [first_part, second_part, third_part] mock_upload_session.get_parts.return_value = mock_iterator mock_upload_session.upload_part_bytes.side_effect = [third_part] mock_upload_session.commit.return_value = test_file chunked_uploader = ChunkedUploader(mock_upload_session, stream, file_size) mock_upload_session.upload_part_bytes.side_effect = [ first_part, second_part, BoxAPIException(502), fourth_part ] try: chunked_uploader.start() except BoxAPIException: uploaded_file = chunked_uploader.resume() calls = [call(offset=6, part_bytes=b'g', total_size=7)] mock_upload_session.upload_part_bytes.assert_has_calls(calls, any_order=False) mock_upload_session.commit.assert_called_once_with( content_sha1=b'/\xb5\xe14\x19\xfc\x89$he\xe7\xa3$\xf4v\xecbN\x87@', parts=parts) assert uploaded_file is test_file
def test_get_classification_not_found(test_item_and_response, mock_box_session): # pylint:disable=redefined-outer-name test_item, _ = test_item_and_response expected_url = '{0}/{1}s/{2}/metadata/enterprise/securityClassification-6VMVochwUWo'.format( API.BASE_API_URL, test_item.object_type, test_item.object_id, ) mock_box_session.get.side_effect = [ BoxAPIException(status=404, code="instance_not_found") ] metadata = test_item.get_classification() assert metadata is None mock_box_session.get.assert_called_once_with(expected_url)
def test_set_classification_fails(test_item_and_response, mock_box_session): # pylint:disable=redefined-outer-name test_item, _ = test_item_and_response expected_url = '{0}/{1}s/{2}/metadata/enterprise/securityClassification-6VMVochwUWo'.format( API.BASE_API_URL, test_item.object_type, test_item.object_id, ) post_data = { 'Box__Security__Classification__Key': 'Public', } post_headers = {b'Content-Type': b'application/json'} mock_box_session.post.side_effect = [BoxAPIException(status=500)] with pytest.raises(BoxAPIException): test_item.set_classification('Public') mock_box_session.post.assert_called_once_with(expected_url, data=json.dumps(post_data), headers=post_headers)
def test_set( mock_box_session, test_object, metadata_scope, metadata_template, metadata_response, ): post_data = { 'case_status': 'in-progress', } post_value = json.dumps(post_data) put_value = json.dumps([{ 'op': 'add', 'path': '/case_status', 'value': 'in-progress', }]) mock_box_session.post.side_effect = [BoxAPIException(status=409, message="Conflict")] mock_box_session.put.return_value.json.return_value = metadata_response metadata = test_object.metadata(metadata_scope, metadata_template) response = metadata.set(post_data) assert response is metadata_response mock_box_session.post.assert_called_once_with(metadata.get_url(), data=post_value, headers={b'Content-Type': b'application/json'}) mock_box_session.put.assert_called_once_with(metadata.get_url(), data=put_value, headers={b'Content-Type': b'application/json-patch+json'})
def test_update_contents( test_file, mock_box_session, mock_content_response, mock_upload_response, mock_file_path, etag, sha1, upload_using_accelerator, mock_accelerator_response_for_update, mock_accelerator_upload_url_for_update, upload_using_accelerator_fails, if_match_sha1_header, is_stream, ): # pylint:disable=too-many-locals file_new_name = 'new_file_name' content_modified_at = '1970-01-01T11:11:11+11:11' additional_attributes = {'attr': 123} expected_url = test_file.get_url('content').replace(API.BASE_API_URL, API.UPLOAD_URL) if upload_using_accelerator: if upload_using_accelerator_fails: mock_box_session.options.side_effect = BoxAPIException(400) else: mock_box_session.options.return_value = mock_accelerator_response_for_update expected_url = mock_accelerator_upload_url_for_update mock_box_session.post.return_value = mock_upload_response if is_stream: mock_file_stream = BytesIO(mock_content_response.content) new_file = test_file.update_contents_with_stream( mock_file_stream, etag=etag, upload_using_accelerator=upload_using_accelerator, file_name=file_new_name, content_modified_at=content_modified_at, additional_attributes=additional_attributes, sha1=sha1, ) else: mock_file = mock_open(read_data=mock_content_response.content) mock_file_stream = mock_file.return_value with patch('boxsdk.object.file.open', mock_file, create=True): new_file = test_file.update_contents( mock_file_path, etag=etag, upload_using_accelerator=upload_using_accelerator, file_name=file_new_name, content_modified_at=content_modified_at, additional_attributes=additional_attributes, sha1=sha1, ) mock_files = {'file': ('unused', mock_file_stream)} attributes = { 'name': file_new_name, 'content_modified_at': content_modified_at, } # Using `update` to mirror the actual impl, since the attributes could otherwise come through in a different order # in Python 2 tests attributes.update(additional_attributes) data = {'attributes': json.dumps(attributes)} mock_box_session.post.assert_called_once_with( expected_url, expect_json_response=False, files=mock_files, data=data, headers=if_match_sha1_header, ) assert isinstance(new_file, File) assert new_file.object_id == test_file.object_id assert 'id' in new_file assert new_file['id'] == test_file.object_id assert not hasattr(new_file, 'entries') assert 'entries' not in new_file
def test_upload( test_folder, mock_box_session, mock_content_response, mock_upload_response, mock_file_path, mock_object_id, upload_using_accelerator, mock_accelerator_response_for_new_uploads, mock_new_upload_accelerator_url, upload_using_accelerator_fails, is_stream, etag, sha1, if_match_sha1_header, ): # pylint:disable=too-many-locals file_description = 'Test File Description' content_created_at = '1970-01-01T00:00:00+00:00' content_modified_at = '1970-01-01T11:11:11+11:11' additional_attributes = {'attr': 123} expected_url = '{0}/files/content'.format(API.UPLOAD_URL) if upload_using_accelerator: if upload_using_accelerator_fails: mock_box_session.options.side_effect = BoxAPIException(400) else: mock_box_session.options.return_value = mock_accelerator_response_for_new_uploads expected_url = mock_new_upload_accelerator_url mock_box_session.post.return_value = mock_upload_response if is_stream: mock_file_stream = BytesIO(mock_content_response.content) new_file = test_folder.upload_stream( mock_file_stream, basename(mock_file_path), file_description, upload_using_accelerator=upload_using_accelerator, content_created_at=content_created_at, content_modified_at=content_modified_at, additional_attributes=additional_attributes, sha1=sha1, etag=etag, ) else: mock_file = mock_open(read_data=mock_content_response.content) mock_file_stream = mock_file.return_value with patch('boxsdk.object.folder.open', mock_file, create=True): new_file = test_folder.upload( mock_file_path, file_description=file_description, upload_using_accelerator=upload_using_accelerator, content_created_at=content_created_at, content_modified_at=content_modified_at, additional_attributes=additional_attributes, sha1=sha1, etag=etag, ) mock_files = {'file': ('unused', mock_file_stream)} attributes = { 'name': basename(mock_file_path), 'parent': { 'id': mock_object_id }, 'description': file_description, 'content_created_at': content_created_at, 'content_modified_at': content_modified_at, } # Using `update` to mirror the actual impl, since the attributes could otherwise come through in a different order # in Python 2 tests attributes.update(additional_attributes) data = {'attributes': json.dumps(attributes)} mock_box_session.post.assert_called_once_with(expected_url, expect_json_response=False, files=mock_files, data=data, headers=if_match_sha1_header) assert isinstance(new_file, File) assert new_file.object_id == mock_object_id assert 'id' in new_file assert new_file['id'] == mock_object_id assert new_file.description == file_description assert not hasattr(new_file, 'entries') assert 'entries' not in new_file