Skip to content

Commit cae4ff1

Browse files
Add support for visual_search Admin API
1 parent 047d02a commit cae4ff1

File tree

4 files changed

+47
-4
lines changed

4 files changed

+47
-4
lines changed

cloudinary/api.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,26 @@ def resources_by_context(key, value=None, **options):
155155
return call_api("get", uri, params, **options)
156156

157157

158+
def visual_search(image_url=None, image_asset_id=None, text=None, **options):
159+
"""
160+
Find images based on their visual content.
161+
162+
:param image_url: The URL of an image.
163+
:type image_url: str
164+
:param image_asset_id: The asset_id of an image in your account.
165+
:type image_asset_id: str
166+
:param text: A textual description, e.g., "cat"
167+
:type text: str
168+
:param options: Additional options
169+
:type options: dict, optional
170+
:return: Resources (assets) that were found
171+
:rtype: Response
172+
"""
173+
uri = ["resources", "visual_search"]
174+
params = {"image_url": image_url, "image_asset_id": image_asset_id, "text": text}
175+
return call_api("get", uri, params, **options)
176+
177+
158178
def resource(public_id, **options):
159179
resource_type = options.pop("resource_type", "image")
160180
upload_type = options.pop("type", "upload")

cloudinary/utils.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@
106106
"categorization",
107107
"detection",
108108
"similarity_search",
109+
"visual_search",
109110
"background_removal",
110111
"upload_preset",
111112
"phash",

test/test_api.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
import cloudinary
1111
from cloudinary import api, uploader, utils
1212
from cloudinary.utils import fq_public_id
13-
from test.helper_test import SUFFIX, TEST_IMAGE, get_uri, get_headers, get_params, get_list_param, get_param, TEST_DOC, get_method, \
14-
UNIQUE_TAG, api_response_mock, ignore_exception, cleanup_test_resources_by_tag, cleanup_test_transformation, \
15-
cleanup_test_resources, UNIQUE_TEST_FOLDER, EVAL_STR, get_json_body
13+
from test.helper_test import SUFFIX, TEST_IMAGE, get_uri, get_headers, get_params, get_list_param, get_param, \
14+
TEST_DOC, get_method, UNIQUE_TAG, api_response_mock, ignore_exception, cleanup_test_resources_by_tag, \
15+
cleanup_test_transformation, cleanup_test_resources, UNIQUE_TEST_FOLDER, EVAL_STR, get_json_body, REMOTE_TEST_IMAGE
1616
from cloudinary.exceptions import BadRequest, NotFound
1717

1818
MOCK_RESPONSE = api_response_mock()
@@ -284,6 +284,22 @@ def test06b_resources_direction(self, mocker):
284284
self.assertTrue(get_uri(args).endswith('/resources/image/tags/{}'.format(API_TEST_TAG)))
285285
self.assertEqual(get_params(args)['direction'], 'desc')
286286

287+
@patch('urllib3.request.RequestMethods.request')
288+
@unittest.skipUnless(cloudinary.config().api_secret, "requires api_key/api_secret")
289+
def test_visual_search(self, mocker):
290+
""" should allow using visual search """
291+
mocker.return_value = MOCK_RESPONSE
292+
293+
api.visual_search(REMOTE_TEST_IMAGE, API_TEST_ASSET_ID, "sample image")
294+
295+
args, kwargs = mocker.call_args
296+
self.assertTrue(get_uri(args).endswith('/resources/visual_search'))
297+
298+
params = get_params(args)
299+
self.assertEqual(REMOTE_TEST_IMAGE, params['image_url'])
300+
self.assertEqual(API_TEST_ASSET_ID, params['image_asset_id'])
301+
self.assertEqual("sample image", params['text'])
302+
287303
@patch('urllib3.request.RequestMethods.request')
288304
@unittest.skipUnless(cloudinary.config().api_secret, "requires api_key/api_secret")
289305
def test_extra_headers(self, mocker):

test/test_uploader.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -953,7 +953,13 @@ def test_various_upload_parameters(self, request_mock):
953953
"""Should support various parameters in upload and explicit"""
954954
request_mock.return_value = MOCK_RESPONSE
955955

956-
options = {'cinemagraph_analysis': True, 'accessibility_analysis':True, 'media_metadata':True}
956+
options = {
957+
'cinemagraph_analysis': True,
958+
'accessibility_analysis': True,
959+
'media_metadata': True,
960+
'visual_search': True,
961+
}
962+
957963
uploader.upload(TEST_IMAGE, **options)
958964

959965
params = get_params(request_mock.call_args[0])

0 commit comments

Comments
 (0)