Example #1
0
    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)
Example #2
0
 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)
Example #3
0
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
Example #4
0
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)
Example #5
0
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
Example #6
0
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']
Example #7
0
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
Example #8
0
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
Example #10
0
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
Example #12
0
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)
Example #13
0
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'})
Example #15
0
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
Example #16
0
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