<commit_before>from __future__ import unicode_literals
import mock
try:
    import unittest2 as unittest # Python2.6
except ImportError:
    import unittest

import openphoto

class TestPhotos(unittest.TestCase):
    TEST_HOST = "test.example.com"

    TEST_PHOTOS = [{"id": "1a",
                    "tags": ["tag1", "tag2"],
                    "totalPages": 1,
                    "totalRows": 2},
                   {"id": "2b",
                    "tags": ["tag3", "tag4"],
                    "totalPages": 1,
                    "totalRows": 2}]

    def setUp(self):
        self.client = openphoto.OpenPhoto(host=self.TEST_HOST)

    @staticmethod
    def _return_value(result, message="", code=200):
        return {"message": message, "code": code, "result": result}

class TestPhotosList(TestPhotos):
    @mock.patch.object(openphoto.OpenPhoto, 'get')
    def test_list(self, mock_get):
        photos = self.TEST_PHOTOS
        mock_get.return_value = self._return_value(photos)

        result = self.client.photos.list()
        mock_get.assert_called_with("/photos/list.json")
        self.assertEqual(len(result), 2)
        self.assertEqual(result[0].id, "1a")
        self.assertEqual(result[0].tags, ["tag1", "tag2"])
        self.assertEqual(result[1].id, "2b")
        self.assertEqual(result[1].tags, ["tag3", "tag4"])

class TestPhotosUpdate(TestPhotos):
    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_update(self, mock_post):
        mock_post.return_value = self._return_value(True)
        result = self.client.photos.update(["1a", "2b"], title="Test")
        mock_post.assert_called_with("/photos/update.json",
                                     ids=["1a", "2b"], title="Test")
        self.assertEqual(result, True)

    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_update_failure_raises_exception(self, mock_post):
        mock_post.return_value = self._return_value(False)
        with self.assertRaises(openphoto.OpenPhotoError):
            self.client.photos.update(["1a", "2b"], title="Test")

class TestPhotosDelete(TestPhotos):
    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_delete(self, mock_post):
        mock_post.return_value = self._return_value(True)
        result = self.client.photos.delete(["1a", "2b"])
        mock_post.assert_called_with("/photos/delete.json", ids=["1a", "2b"])
        self.assertEqual(result, True)

    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_delete_failure_raises_exception(self, mock_post):
        mock_post.return_value = self._return_value(False)
        with self.assertRaises(openphoto.OpenPhotoError):
            self.client.photos.delete(["1a", "2b"])

class TestPhotoDelete(TestPhotos):
    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_delete(self, mock_post):
        mock_post.return_value = self._return_value(True)
        result = self.client.photo.delete("1a")
        mock_post.assert_called_with("/photo/1a/delete.json")
        self.assertEqual(result, True)

    # TODO: photo.delete should raise exception on failure
    @unittest.expectedFailure
    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_delete_failure_raises_exception(self, mock_post):
        mock_post.return_value = self._return_value(False)
        with self.assertRaises(openphoto.OpenPhotoError):
            self.client.photo.delete("1a")

    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_object_delete(self, mock_post):
        mock_post.return_value = self._return_value(True)
        photo = openphoto.objects.Photo(self.client, self.TEST_PHOTOS[0])
        result = photo.delete()
        mock_post.assert_called_with("/photo/1a/delete.json")
        self.assertEqual(result, True)

    # TODO: photo.delete should raise exception on failure
    @unittest.expectedFailure
    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_object_delete_failure_raises_exception(self, mock_post):
        mock_post.return_value = self._return_value(False)
        photo = openphoto.objects.Photo(self.client, self.TEST_PHOTOS[0])
        with self.assertRaises(openphoto.OpenPhotoError):
            photo.delete()
<commit_msg>Additional photo API unit tests<commit_after>from __future__ import unicode_literals
import os
import base64
import mock
try:
    import unittest2 as unittest # Python2.6
except ImportError:
    import unittest

import openphoto

class TestPhotos(unittest.TestCase):
    TEST_HOST = "test.example.com"
    TEST_FILE = os.path.join("tests", "unit", "data", "test_file.txt")
    TEST_PHOTOS_DICT = [{"id": "1a", "tags": ["tag1", "tag2"],
                         "totalPages": 1, "totalRows": 2},
                        {"id": "2b", "tags": ["tag3", "tag4"],
                         "totalPages": 1, "totalRows": 2}]
    def setUp(self):
        self.client = openphoto.OpenPhoto(host=self.TEST_HOST)
        self.TEST_PHOTOS = [openphoto.objects.Photo(self.client, photo)
                            for photo in self.TEST_PHOTOS_DICT]

    @staticmethod
    def _return_value(result, message="", code=200):
        return {"message": message, "code": code, "result": result}

class TestPhotosList(TestPhotos):
    @mock.patch.object(openphoto.OpenPhoto, 'get')
    def test_photos_list(self, mock):
        mock.return_value = self._return_value(self.TEST_PHOTOS_DICT)

        result = self.client.photos.list()
        mock.assert_called_with("/photos/list.json")
        self.assertEqual(len(result), 2)
        self.assertEqual(result[0].id, "1a")
        self.assertEqual(result[0].tags, ["tag1", "tag2"])
        self.assertEqual(result[1].id, "2b")
        self.assertEqual(result[1].tags, ["tag3", "tag4"])

class TestPhotosUpdate(TestPhotos):
    # TODO: photos.update should accept a list of Photo objects
    @unittest.expectedFailure
    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_photos_update(self, mock):
        mock.return_value = self._return_value(True)
        result = self.client.photos.update(self.TEST_PHOTOS, title="Test")
        mock.assert_called_with("/photos/update.json",
                                     ids=["1a", "2b"], title="Test")
        self.assertEqual(result, True)

    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_photos_update_ids(self, mock):
        mock.return_value = self._return_value(True)
        result = self.client.photos.update(["1a", "2b"], title="Test")
        mock.assert_called_with("/photos/update.json",
                                     ids=["1a", "2b"], title="Test")
        self.assertEqual(result, True)

    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_photos_update_failure_raises_exception(self, mock):
        mock.return_value = self._return_value(False)
        with self.assertRaises(openphoto.OpenPhotoError):
            self.client.photos.update(self.TEST_PHOTOS, title="Test")

class TestPhotosDelete(TestPhotos):
    # TODO: photos.delete should accept a list of Photo objects
    @unittest.expectedFailure
    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_photos_delete(self, mock):
        mock.return_value = self._return_value(True)
        result = self.client.photos.delete(self.TEST_PHOTOS)
        mock.assert_called_with("/photos/delete.json", ids=["1a", "2b"])
        self.assertEqual(result, True)

    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_photos_delete_ids(self, mock):
        mock.return_value = self._return_value(True)
        result = self.client.photos.delete(["1a", "2b"])
        mock.assert_called_with("/photos/delete.json", ids=["1a", "2b"])
        self.assertEqual(result, True)

    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_photos_delete_failure_raises_exception(self, mock):
        mock.return_value = self._return_value(False)
        with self.assertRaises(openphoto.OpenPhotoError):
            self.client.photos.delete(self.TEST_PHOTOS)

class TestPhotoDelete(TestPhotos):
    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_photo_delete(self, mock):
        mock.return_value = self._return_value(True)
        result = self.client.photo.delete(self.TEST_PHOTOS[0])
        mock.assert_called_with("/photo/1a/delete.json")
        self.assertEqual(result, True)

    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_photo_delete_id(self, mock):
        mock.return_value = self._return_value(True)
        result = self.client.photo.delete("1a")
        mock.assert_called_with("/photo/1a/delete.json")
        self.assertEqual(result, True)

    # TODO: photo.delete should raise exception on failure
    @unittest.expectedFailure
    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_photo_delete_failure_raises_exception(self, mock):
        mock.return_value = self._return_value(False)
        with self.assertRaises(openphoto.OpenPhotoError):
            self.client.photo.delete(self.TEST_PHOTOS[0])

    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_photo_object_delete(self, mock):
        mock.return_value = self._return_value(True)
        result = self.TEST_PHOTOS[0].delete()
        mock.assert_called_with("/photo/1a/delete.json")
        self.assertEqual(result, True)

    # TODO: photo.delete should raise exception on failure
    @unittest.expectedFailure
    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_photo_object_delete_failure_raises_exception(self, mock):
        mock.return_value = self._return_value(False)
        with self.assertRaises(openphoto.OpenPhotoError):
            self.TEST_PHOTOS[0].delete()

class TestPhotoEdit(TestPhotos):
    @mock.patch.object(openphoto.OpenPhoto, 'get')
    def test_photo_edit(self, mock):
        mock.return_value = self._return_value({"markup": "<form/>"})
        result = self.client.photo.edit(self.TEST_PHOTOS[0])
        mock.assert_called_with("/photo/1a/edit.json")
        self.assertEqual(result, "<form/>")

    @mock.patch.object(openphoto.OpenPhoto, 'get')
    def test_photo_edit_id(self, mock):
        mock.return_value = self._return_value({"markup": "<form/>"})
        result = self.client.photo.edit("1a")
        mock.assert_called_with("/photo/1a/edit.json")
        self.assertEqual(result, "<form/>")

    @mock.patch.object(openphoto.OpenPhoto, 'get')
    def test_photo_object_edit(self, mock):
        mock.return_value = self._return_value({"markup": "<form/>"})
        result = self.TEST_PHOTOS[0].edit()
        mock.assert_called_with("/photo/1a/edit.json")
        self.assertEqual(result, "<form/>")

class TestPhotoReplace(TestPhotos):
    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_photo_replace(self, mock):
        with self.assertRaises(NotImplementedError):
            self.client.photo.replace(self.TEST_PHOTOS[0], self.TEST_FILE)

    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_photo_replace_id(self, mock):
        with self.assertRaises(NotImplementedError):
            self.client.photo.replace("1a", self.TEST_FILE)

    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_photo_object_replace(self, mock):
        with self.assertRaises(NotImplementedError):
            self.TEST_PHOTOS[0].replace(self.TEST_FILE)

    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_photo_replace_encoded(self, mock):
        with self.assertRaises(NotImplementedError):
            self.client.photo.replace_encoded(self.TEST_PHOTOS[0], self.TEST_FILE)

    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_photo_replace_encoded_id(self, mock):
        with self.assertRaises(NotImplementedError):
            self.client.photo.replace_encoded("1a", self.TEST_FILE)

    # TODO: replace_encoded parameter should be called photo_file,
    #       not encoded_photo
    @unittest.expectedFailure
    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_photo_object_replace_encoded(self, mock):
        with self.assertRaises(NotImplementedError):
            self.TEST_PHOTOS[0].replace_encoded(photo_file=self.TEST_FILE)

class TestPhotoUpdate(TestPhotos):
    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_photo_update(self, mock):
        mock.return_value = self._return_value(self.TEST_PHOTOS_DICT[1])
        result = self.client.photo.update(self.TEST_PHOTOS[0], title="Test")
        mock.assert_called_with("/photo/1a/update.json", title="Test")
        self.assertEqual(result.get_fields(), self.TEST_PHOTOS_DICT[1])

    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_photo_update_id(self, mock):
        mock.return_value = self._return_value(self.TEST_PHOTOS_DICT[1])
        result = self.client.photo.update("1a", title="Test")
        mock.assert_called_with("/photo/1a/update.json", title="Test")
        self.assertEqual(result.get_fields(), self.TEST_PHOTOS_DICT[1])

    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_photo_object_update(self, mock):
        mock.return_value = self._return_value(self.TEST_PHOTOS_DICT[1])
        photo = self.TEST_PHOTOS[0]
        photo.update(title="Test")
        mock.assert_called_with("/photo/1a/update.json", title="Test")
        self.assertEqual(photo.get_fields(), self.TEST_PHOTOS_DICT[1])

class TestPhotoView(TestPhotos):
    @mock.patch.object(openphoto.OpenPhoto, 'get')
    def test_photo_view(self, mock):
        mock.return_value = self._return_value(self.TEST_PHOTOS_DICT[1])
        result = self.client.photo.view(self.TEST_PHOTOS[0], returnSizes="20x20")
        mock.assert_called_with("/photo/1a/view.json", returnSizes="20x20")
        self.assertEqual(result.get_fields(), self.TEST_PHOTOS_DICT[1])

    @mock.patch.object(openphoto.OpenPhoto, 'get')
    def test_photo_view_id(self, mock):
        mock.return_value = self._return_value(self.TEST_PHOTOS_DICT[1])
        result = self.client.photo.view("1a", returnSizes="20x20")
        mock.assert_called_with("/photo/1a/view.json", returnSizes="20x20")
        self.assertEqual(result.get_fields(), self.TEST_PHOTOS_DICT[1])

    @mock.patch.object(openphoto.OpenPhoto, 'get')
    def test_photo_object_view(self, mock):
        mock.return_value = self._return_value(self.TEST_PHOTOS_DICT[1])
        photo = self.TEST_PHOTOS[0]
        photo.view(returnSizes="20x20")
        mock.assert_called_with("/photo/1a/view.json", returnSizes="20x20")
        self.assertEqual(photo.get_fields(), self.TEST_PHOTOS_DICT[1])

class TestPhotoUpload(TestPhotos):
    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_photo_upload(self, mock):
        mock.return_value = self._return_value(self.TEST_PHOTOS_DICT[0])
        result = self.client.photo.upload(self.TEST_FILE, title="Test")
        # It's not possible to compare the file object,
        # so check each parameter individually
        endpoint = mock.call_args[0]
        title = mock.call_args[1]["title"]
        files = mock.call_args[1]["files"]
        self.assertEqual(endpoint, ("/photo/upload.json",))
        self.assertEqual(title, "Test")
        self.assertIn("photo", files)
        self.assertEqual(result.get_fields(), self.TEST_PHOTOS_DICT[0])

    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_photo_upload_encoded(self, mock):
        encoded_file = base64.b64encode(open(self.TEST_FILE, "rb").read())
        mock.return_value = self._return_value(self.TEST_PHOTOS_DICT[0])
        result = self.client.photo.upload_encoded(self.TEST_FILE, title="Test")
        mock.assert_called_with("/photo/upload.json",
                                    photo=encoded_file, title="Test")
        self.assertEqual(result.get_fields(), self.TEST_PHOTOS_DICT[0])

class TestPhotoDynamicUrl(TestPhotos):
    @mock.patch.object(openphoto.OpenPhoto, 'get')
    def test_photo_dynamic_url(self, mock):
        with self.assertRaises(NotImplementedError):
            self.client.photo.dynamic_url(self.TEST_PHOTOS[0])

    @mock.patch.object(openphoto.OpenPhoto, 'get')
    def test_photo_dynamic_url_id(self, mock):
        with self.assertRaises(NotImplementedError):
            self.client.photo.dynamic_url("1a")

    @mock.patch.object(openphoto.OpenPhoto, 'get')
    def test_photo_object_dynamic_url(self, mock):
        with self.assertRaises(NotImplementedError):
            self.TEST_PHOTOS[0].dynamic_url()

class TestPhotoNextPrevious(TestPhotos):
    @mock.patch.object(openphoto.OpenPhoto, 'get')
    def test_photo_next_previous(self, mock):
        mock.return_value = self._return_value(
            {"next": [self.TEST_PHOTOS_DICT[0]],
             "previous": [self.TEST_PHOTOS_DICT[1]]})
        result = self.client.photo.next_previous(self.TEST_PHOTOS[0])
        mock.assert_called_with("/photo/1a/nextprevious.json")
        self.assertEqual(result["next"][0].get_fields(),
                         self.TEST_PHOTOS_DICT[0])
        self.assertEqual(result["previous"][0].get_fields(),
                         self.TEST_PHOTOS_DICT[1])

    @mock.patch.object(openphoto.OpenPhoto, 'get')
    def test_photo_next_previous_id(self, mock):
        mock.return_value = self._return_value(
            {"next": [self.TEST_PHOTOS_DICT[0]],
             "previous": [self.TEST_PHOTOS_DICT[1]]})
        result = self.client.photo.next_previous("1a")
        mock.assert_called_with("/photo/1a/nextprevious.json")
        self.assertEqual(result["next"][0].get_fields(),
                         self.TEST_PHOTOS_DICT[0])
        self.assertEqual(result["previous"][0].get_fields(),
                         self.TEST_PHOTOS_DICT[1])

    @mock.patch.object(openphoto.OpenPhoto, 'get')
    def test_photo_object_next_previous(self, mock):
        mock.return_value = self._return_value(
            {"next": [self.TEST_PHOTOS_DICT[0]],
             "previous": [self.TEST_PHOTOS_DICT[1]]})
        result = self.TEST_PHOTOS[0].next_previous()
        mock.assert_called_with("/photo/1a/nextprevious.json")
        self.assertEqual(result["next"][0].get_fields(),
                         self.TEST_PHOTOS_DICT[0])
        self.assertEqual(result["previous"][0].get_fields(),
                         self.TEST_PHOTOS_DICT[1])

    @mock.patch.object(openphoto.OpenPhoto, 'get')
    def test_photo_next(self, mock):
        mock.return_value = self._return_value(
            {"next": [self.TEST_PHOTOS_DICT[0]]})
        result = self.client.photo.next_previous(self.TEST_PHOTOS[0])
        mock.assert_called_with("/photo/1a/nextprevious.json")
        self.assertEqual(result["next"][0].get_fields(),
                         self.TEST_PHOTOS_DICT[0])
        self.assertNotIn("previous", result)

    @mock.patch.object(openphoto.OpenPhoto, 'get')
    def test_photo_previous(self, mock):
        mock.return_value = self._return_value(
            {"previous": [self.TEST_PHOTOS_DICT[1]]})
        result = self.client.photo.next_previous(self.TEST_PHOTOS[0])
        mock.assert_called_with("/photo/1a/nextprevious.json")
        self.assertEqual(result["previous"][0].get_fields(),
                         self.TEST_PHOTOS_DICT[1])
        self.assertNotIn("next", result)

    @mock.patch.object(openphoto.OpenPhoto, 'get')
    def test_photo_multiple_next_previous(self, mock):
        mock.return_value = self._return_value(
            {"next": [self.TEST_PHOTOS_DICT[0], self.TEST_PHOTOS_DICT[0]],
             "previous": [self.TEST_PHOTOS_DICT[1], self.TEST_PHOTOS_DICT[1]]})
        result = self.client.photo.next_previous(self.TEST_PHOTOS[0])
        mock.assert_called_with("/photo/1a/nextprevious.json")
        self.assertEqual(result["next"][0].get_fields(),
                         self.TEST_PHOTOS_DICT[0])
        self.assertEqual(result["next"][1].get_fields(),
                         self.TEST_PHOTOS_DICT[0])
        self.assertEqual(result["previous"][0].get_fields(),
                         self.TEST_PHOTOS_DICT[1])
        self.assertEqual(result["previous"][1].get_fields(),
                         self.TEST_PHOTOS_DICT[1])

class TestPhotoTransform(TestPhotos):
    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_transform(self, mock):
        mock.return_value = self._return_value(self.TEST_PHOTOS_DICT[1])
        result = self.client.photo.transform(self.TEST_PHOTOS[0], rotate="90")
        mock.assert_called_with("/photo/1a/transform.json", rotate="90")
        self.assertEqual(result.get_fields(), self.TEST_PHOTOS_DICT[1])

    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_transform_id(self, mock):
        mock.return_value = self._return_value(self.TEST_PHOTOS_DICT[1])
        result = self.client.photo.transform("1a", rotate="90")
        mock.assert_called_with("/photo/1a/transform.json", rotate="90")
        self.assertEqual(result.get_fields(), self.TEST_PHOTOS_DICT[1])

    @mock.patch.object(openphoto.OpenPhoto, 'post')
    def test_object_transform(self, mock):
        mock.return_value = self._return_value(self.TEST_PHOTOS_DICT[1])
        photo = self.TEST_PHOTOS[0]
        photo.transform(rotate="90")
        mock.assert_called_with("/photo/1a/transform.json", rotate="90")
        self.assertEqual(photo.get_fields(), self.TEST_PHOTOS_DICT[1])
{'fraction_non_alphanumeric': 0.13430092832571508, 'fraction_numerical': 0.011309551859007587, 'mean_word_length': 3.312538102011786, 'pattern_counts': {'":': 35, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '485343', 'n_tokens_mistral': 6901, 'n_tokens_neox': 6741, 'n_words': 924}