diff --git a/indicoio/images/faciallocalization.py b/indicoio/images/faciallocalization.py index 827836e..6c44c18 100644 --- a/indicoio/images/faciallocalization.py +++ b/indicoio/images/faciallocalization.py @@ -4,7 +4,7 @@ from indicoio.utils.image import image_preprocess from indicoio.utils.api import api_handler -def facial_localization(image, cloud=None, batch=False, api_key=None, **kwargs): +def facial_localization(image, cloud=None, batch=False, api_key=None, version=None, **kwargs): """ Given an image, returns a list of faces found within the image. For each face, we return a dictionary containing the upper left corner and lower right corner. @@ -24,8 +24,8 @@ def facial_localization(image, cloud=None, batch=False, api_key=None, **kwargs): :param image: The image to be analyzed. :type image: filepath or ndarray - :rtype: List of faces (dict) found. + :rtype: List of faces (dict) found. """ image = image_preprocess(image, batch=batch) - url_params = {"batch": batch, "api_key": api_key} - return api_handler(image, cloud=cloud, api="faciallocalization", url_params=url_params, **kwargs) \ No newline at end of file + url_params = {"batch": batch, "api_key": api_key, "version": version} + return api_handler(image, cloud=cloud, api="faciallocalization", url_params=url_params, **kwargs) diff --git a/indicoio/images/features.py b/indicoio/images/features.py index d96b85c..fb3bbd7 100644 --- a/indicoio/images/features.py +++ b/indicoio/images/features.py @@ -3,7 +3,7 @@ import requests from indicoio.utils.image import image_preprocess from indicoio.utils.api import api_handler -def facial_features(image, cloud=None, batch=False, api_key=None, **kwargs): +def facial_features(image, cloud=None, batch=False, api_key=None, version=None, **kwargs): """ Given an grayscale input image of a face, returns a 48 dimensional feature vector explaining that face. Useful as a form of feature engineering for face oriented tasks. @@ -26,10 +26,10 @@ def facial_features(image, cloud=None, batch=False, api_key=None, **kwargs): :rtype: List containing feature responses """ image = image_preprocess(image, batch=batch, size=(48,48)) - url_params = {"batch": batch, "api_key": api_key} + url_params = {"batch": batch, "api_key": api_key, "version": version} return api_handler(image, cloud=cloud, api="facialfeatures", url_params=url_params, **kwargs) -def image_features(image, cloud=None, batch=False, api_key=None, **kwargs): +def image_features(image, cloud=None, batch=False, api_key=None, version=None, **kwargs): """ Given an input image, returns a 2048 dimensional sparse feature vector explaining that image. Useful as a form of feature engineering for image oriented tasks. @@ -60,5 +60,5 @@ def image_features(image, cloud=None, batch=False, api_key=None, **kwargs): :rtype: List containing features """ image = image_preprocess(image, batch=batch, size=(64,64)) - url_params = {"batch": batch, "api_key": api_key} + url_params = {"batch": batch, "api_key": api_key, "version": version} return api_handler(image, cloud=cloud, api="imagefeatures", url_params=url_params, **kwargs) diff --git a/indicoio/images/fer.py b/indicoio/images/fer.py index 46639af..0aae9c5 100644 --- a/indicoio/images/fer.py +++ b/indicoio/images/fer.py @@ -4,7 +4,7 @@ from indicoio.utils.api import api_handler from indicoio.utils.image import image_preprocess import indicoio.config as config -def fer(image, cloud=None, batch=False, api_key=None, **kwargs): +def fer(image, cloud=None, batch=False, api_key=None, version=None, **kwargs): """ Given a grayscale input image of a face, returns a probability distribution over emotional state. Input should be in a list of list format, resizing will be attempted internally but for best @@ -31,6 +31,6 @@ def fer(image, cloud=None, batch=False, api_key=None, **kwargs): image = image_preprocess(image, batch=batch, size=None if kwargs.get("detect") else (48, 48) ) - - url_params = {"batch": batch, "api_key": api_key} + + url_params = {"batch": batch, "api_key": api_key, "version": version} return api_handler(image, cloud=cloud, api="fer", url_params=url_params, **kwargs) diff --git a/indicoio/images/filtering.py b/indicoio/images/filtering.py index d5e51cf..657da23 100644 --- a/indicoio/images/filtering.py +++ b/indicoio/images/filtering.py @@ -4,7 +4,7 @@ from indicoio.utils.api import api_handler from indicoio.utils.image import image_preprocess import indicoio.config as config -def content_filtering(image, cloud=None, batch=False, api_key=None, **kwargs): +def content_filtering(image, cloud=None, batch=False, api_key=None, version=None, **kwargs): """ Given a grayscale input image, returns how obcene the image is. Input should be in a list of list format. @@ -25,5 +25,5 @@ def content_filtering(image, cloud=None, batch=False, api_key=None, **kwargs): :rtype: float of nsfwness """ image = image_preprocess(image, batch=batch, min_axis=128) - url_params = {"batch": batch, "api_key": api_key} + url_params = {"batch": batch, "api_key": api_key, "version": version} return api_handler(image, cloud=cloud, api="contentfiltering", url_params=url_params, **kwargs) diff --git a/indicoio/text/keywords.py b/indicoio/text/keywords.py index 4293486..49262cb 100644 --- a/indicoio/text/keywords.py +++ b/indicoio/text/keywords.py @@ -1,7 +1,7 @@ from indicoio.utils.api import api_handler import indicoio.config as config -def keywords(text, cloud=None, batch=False, api_key=None, **kwargs): +def keywords(text, cloud=None, batch=False, api_key=None, version=None, **kwargs): """ Given input text, returns series of keywords and associated scores diff --git a/indicoio/text/lang.py b/indicoio/text/lang.py index fbc03a3..5f3dbc2 100644 --- a/indicoio/text/lang.py +++ b/indicoio/text/lang.py @@ -1,7 +1,7 @@ from indicoio.utils.api import api_handler import indicoio.config as config -def language(text, cloud=None, batch=False, api_key=None, **kwargs): +def language(text, cloud=None, batch=False, api_key=None, version=None, **kwargs): """ Given input text, returns a probability distribution over 33 possible languages of what language the text was written in. @@ -23,5 +23,5 @@ def language(text, cloud=None, batch=False, api_key=None, **kwargs): :type text: str or unicode :rtype: Dictionary of language probability pairs """ - url_params = {"batch": batch, "api_key": api_key} + url_params = {"batch": batch, "api_key": api_key, "version": version} return api_handler(text, cloud=cloud, api="language", url_params=url_params, **kwargs) diff --git a/indicoio/text/ner.py b/indicoio/text/ner.py index 8f2985b..66278f0 100644 --- a/indicoio/text/ner.py +++ b/indicoio/text/ner.py @@ -1,7 +1,7 @@ from indicoio.utils.api import api_handler import indicoio.config as config -def named_entities(text, cloud=None, batch=False, api_key=None, **kwargs): +def named_entities(text, cloud=None, batch=False, api_key=None, version=None, **kwargs): """ Given input text, returns named entities (proper nouns) found in the text @@ -26,5 +26,5 @@ def named_entities(text, cloud=None, batch=False, api_key=None, **kwargs): :type text: str or unicode :rtype: Dictionary of language probability pairs """ - url_params = {"batch": batch, "api_key": api_key} + url_params = {"batch": batch, "api_key": api_key, "version": version} return api_handler(text, cloud=cloud, api="namedentities", url_params=url_params, **kwargs) diff --git a/indicoio/text/sentiment.py b/indicoio/text/sentiment.py index 64607f3..23b90e4 100644 --- a/indicoio/text/sentiment.py +++ b/indicoio/text/sentiment.py @@ -1,6 +1,6 @@ from indicoio.utils.api import api_handler -def political(text, cloud=None, batch=False, api_key=None, **kwargs): +def political(text, cloud=None, batch=False, api_key=None, version=None, **kwargs): """ Given input text, returns a probability distribution over the political alignment of the speaker. @@ -25,10 +25,10 @@ def political(text, cloud=None, batch=False, api_key=None, **kwargs): :type text: str or unicode :rtype: Dictionary of party probability pairs """ - url_params = {"batch": batch, "api_key": api_key} + url_params = {"batch": batch, "api_key": api_key, "version": version} return api_handler(text, cloud=cloud, api="political", url_params=url_params, **kwargs) -def posneg(text, cloud=None, batch=False, api_key=None, **kwargs): +def posneg(text, cloud=None, batch=False, api_key=None, version=None, **kwargs): """ Given input text, returns a scalar estimate of the sentiment of that text. Values are roughly in the range 0 to 1 with 0.5 indicating neutral sentiment. @@ -48,10 +48,10 @@ def posneg(text, cloud=None, batch=False, api_key=None, **kwargs): :type text: str or unicode :rtype: Float """ - url_params = {"batch": batch, "api_key": api_key} + url_params = {"batch": batch, "api_key": api_key, "version": version} return api_handler(text, cloud=cloud, api="sentiment", url_params=url_params, **kwargs) -def sentiment_hq(text, cloud=None, batch=False, api_key=None, **kwargs): +def sentiment_hq(text, cloud=None, batch=False, api_key=None, version=None, **kwargs): """ Given input text, returns a scalar estimate of the sentiment of that text. Values are roughly in the range 0 to 1 with 0.5 indicating neutral sentiment. @@ -71,5 +71,5 @@ def sentiment_hq(text, cloud=None, batch=False, api_key=None, **kwargs): :type text: str or unicode :rtype: Float """ - url_params = {"batch": batch, "api_key": api_key} + url_params = {"batch": batch, "api_key": api_key, "version": version} return api_handler(text, cloud=cloud, api="sentimenthq", url_params=url_params, **kwargs) diff --git a/indicoio/text/tagging.py b/indicoio/text/tagging.py index 87a1cdc..eb9b0ab 100644 --- a/indicoio/text/tagging.py +++ b/indicoio/text/tagging.py @@ -1,7 +1,7 @@ from indicoio.utils.api import api_handler import indicoio.config as config -def text_tags(text, cloud=None, batch=False, api_key=None, **kwargs): +def text_tags(text, cloud=None, batch=False, api_key=None, version=None, **kwargs): """ Given input text, returns a probability distribution over 100 document categories @@ -22,5 +22,5 @@ def text_tags(text, cloud=None, batch=False, api_key=None, **kwargs): :type text: str or unicode :rtype: Dictionary of class probability pairs """ - url_params = {"batch": batch, "api_key": api_key} + url_params = {"batch": batch, "api_key": api_key, "version": version} return api_handler(text, cloud=cloud, api="texttags", url_params=url_params, **kwargs) diff --git a/indicoio/text/twitter_engagement.py b/indicoio/text/twitter_engagement.py index ce6c7a6..830bfd4 100644 --- a/indicoio/text/twitter_engagement.py +++ b/indicoio/text/twitter_engagement.py @@ -1,7 +1,7 @@ from indicoio.utils.api import api_handler import indicoio.config as config -def twitter_engagement(text, cloud=None, batch=False, api_key=None, **kwargs): +def twitter_engagement(text, cloud=None, batch=False, api_key=None, version=None, **kwargs): """ Given input text, returns an engagment score between 0 and 1 @@ -18,5 +18,5 @@ def twitter_engagement(text, cloud=None, batch=False, api_key=None, **kwargs): :type text: str or unicode :rtype: Float of engagement between 0 and 1 """ - url_params = {"batch": batch, "api_key": api_key} + url_params = {"batch": batch, "api_key": api_key, "version": version} return api_handler(text, cloud=cloud, api="twitterengagement", url_params=url_params, **kwargs) diff --git a/indicoio/utils/api.py b/indicoio/utils/api.py index 9907308..0f4119c 100644 --- a/indicoio/utils/api.py +++ b/indicoio/utils/api.py @@ -18,12 +18,13 @@ def api_handler(arg, cloud, api, url_params=None, **kwargs): json_data = json.dumps(data) cloud = cloud or config.cloud host = "%s.indico.domains" % cloud if cloud else config.PUBLIC_API_HOST - url = create_url(host, api, url_params) + + url = create_url(host, api, dict(kwargs, **url_params)) response = requests.post(url, data=json_data, headers=JSON_HEADERS) if response.status_code == 503 and cloud != None: raise IndicoError("Private cloud '%s' does not include api '%s'" % (cloud, api)) - + json_results = response.json() results = json_results.get('results', False) if results is False: @@ -36,11 +37,14 @@ def create_url(host, api, url_params): api_key = url_params.get("api_key") or config.api_key is_batch = url_params.get("batch") apis = url_params.get("apis") + version = url_params.get("version") or url_params.get("v") host_url_seg = config.url_protocol + "//%s" % host api_url_seg = "/%s" % api batch_url_seg = "/batch" if is_batch else "" key_url_seg = "?key=%s" % api_key multi_url_seg = "&apis=%s" % ",".join(apis) if apis else "" + version_seg = ("&version=%s" % str(version)) if version else "" - return host_url_seg + api_url_seg + batch_url_seg + key_url_seg + multi_url_seg + return host_url_seg + api_url_seg + batch_url_seg + key_url_seg \ + + multi_url_seg + version_seg diff --git a/tests/test_configure.py b/tests/test_configure.py index 325a57f..025cca5 100644 --- a/tests/test_configure.py +++ b/tests/test_configure.py @@ -58,11 +58,11 @@ class TestConfigurationFile(unittest.TestCase): """ assert self.settings.cloud() == self.cloud - def test_set_auth_from_config_file(self): + def test_set_auth_from_config_file(self): """ Ensure cloud authentication credentials are read in from file """ - assert self.settings.api_key() == self.api_key + assert self.settings.api_key() == self.api_key class TestPrecedence(unittest.TestCase): @@ -74,7 +74,7 @@ class TestPrecedence(unittest.TestCase): self.file_api_key = "file-api-key" self.file_cloud = "file-cloud" - self.env_api_key = "env-api-key" + self.env_api_key = "env-api-key" self.env_cloud = "env-cloud" config = """ [auth] @@ -97,12 +97,12 @@ class TestPrecedence(unittest.TestCase): """ assert self.settings.cloud() == self.env_cloud - def test_set_auth_from_config_file(self): + def test_set_auth_from_config_file(self): """ - Ensure cloud authentication credentials set in environment variables + Ensure cloud authentication credentials set in environment variables are used over those in config files """ - assert self.settings.api_key() == self.env_api_key + assert self.settings.api_key() == self.env_api_key class TestConfigFilePrecedence(unittest.TestCase): @@ -154,7 +154,7 @@ class TestConfigFilePrecedence(unittest.TestCase): """ assert self.settings.cloud() == self.high_priority_cloud - def test_auth_config_file_priority(self): + def test_auth_config_file_priority(self): """ Ensure the cloud auth priority is handled properly """ diff --git a/tests/test_versioning.py b/tests/test_versioning.py new file mode 100644 index 0000000..706ab89 --- /dev/null +++ b/tests/test_versioning.py @@ -0,0 +1,21 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +import unittest + +from indicoio import config +from indicoio import sentiment + +class TestVersioning(unittest.TestCase): + def setUp(self): + self.api_key = config.api_key + + def test_specify_version(self): + test_data = ['Worst song ever', 'Best song ever'] + response = sentiment(test_data, api_key = self.api_key, version="1") + self.assertIsInstance(response, list) + self.assertEqual(len(response), 2) + self.assertTrue(response[0] < .5) + self.assertTrue(response[1] > .5) + +if __name__ == "__main__": + unittest.main()