diff --git a/CHANGES.txt b/CHANGES.txt index eb5f989..702cc16 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -20,3 +20,4 @@ v0.4.14, Sat Dec 20 -- Fix for batch image features preprocessing, increased tes v0.4.15, Sat Dec 20 -- Bug fix release v0.5.0, Friday Feb 27 -- Updated to support private cloud, allows for indicorc file to reduce redundant authorization calls, README updates v0.5.1, Friday Feb 27 -- More README updates, fixed rst formatting issue, added classifiers +v0.5.2, Tue March 7 -- Required API keys, configuration settings diff --git a/README.md b/README.md index 5f7a5fb..8f564b8 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,36 @@ indicoio-python =============== -A wrapper for a series of APIs made by indico. +A wrapper for the [indico API](http://indico.io). -Check out the main site on: - -http://indico.io - -Our APIs are totally free to use, and ready to be used in your application. No data or training required. +The indico API is free to use, and no training data is required. Installation ------------ -``` +From PyPI: +```bash pip install indicoio ``` -Documentation +Installation ------------ -Available at [indico.readme.io](http://indico.readme.io/v1.0/docs) +From source: +```bash +git clone https://github.com/IndicoDataSolutions/IndicoIo-python.git +python setup.py install +``` -Current APIs +API Keys + Setup +---------------- +For API key registration and setup, checkout our [quickstart guide](https://dash.readme.io/project/indico/v2.0/docs/api-keys). + +Full Documentation ------------ +Detailed documentation and further code examples are available at [indico.reame.io](http://indico.readme.io/v2.0/docs/python). -Right now this wrapper supports the following apps: +Supported APIs: +------------ - Positive/Negative Sentiment Analysis - Political Sentiment Analysis @@ -35,26 +42,21 @@ Right now this wrapper supports the following apps: Examples -------- -``` ->>> import numpy as np +```python +>>> from indicoio import political, sentiment, language, text_tags, fer, facial_features, image_features ->>> from indicoio import political, sentiment, fer, facial_features, language +>>> indicoio.config.api_key = "YOUR_API_KEY" >>> political("Guns don't kill people. People kill people.") {u'Libertarian': 0.47740164630834825, u'Green': 0.08454409540443657, u'Liberal': 0.16617097211030055, u'Conservative': 0.2718832861769146} >>> sentiment('Worst movie ever.') -{u'Sentiment': 0.07062467665597527} +0.07062467665597527 >>> sentiment('Really enjoyed the movie.') -{u'Sentiment': 0.8105182526856075} +0.8105182526856075 ->>> test_text = "Facebook blog posts about Android tech make better journalism than most news outlets." - ->>> tag_dict = text_tags(test_text) - ->>> sorted(tag_dict.keys(), key=lambda x: tag_dict[x], reverse=True)[:3] -[u'startups_and_entrepreneurship', u'investment', u'business'] +>>> text_tags("Facebook blog posts about Android tech make better journalism than most news outlets.") >>> text_tags(test_text, threshold=0.1) # return only keys with value > 0.1 {u'startups_and_entrepreneurship': 0.21888586688354486} @@ -62,73 +64,26 @@ Examples >>> text_tags(test_text, top_n=1) # return only keys with top_n values {u'startups_and_entrepreneurship': 0.21888586688354486} +>>> import numpy as np + >>> test_face = np.linspace(0,50,48*48).reshape(48,48).tolist() >>> fer(test_face) {u'Angry': 0.08843749137458341, u'Sad': 0.39091163159204684, u'Neutral': 0.1947947999669361, u'Surprise': 0.03443785859010413, u'Fear': 0.17574534848440568, u'Happy': 0.11567286999192382} >>> facial_features(test_face) -[0.0, -0.02568680526917187, 0.21645604230056517, -0.1519435786033145, -0.5648621854611555, 3.0607368045577226, 0.11434321880792693, -0.02163810928547493, -0.44224330594186484, 0.3024315632285246, -2.6068048934495276, 2.497798330306638, 3.040558335205844, 0.741045340525325, 0.37198135618478817, -0.33132377802172325, -0.9804190889833034, 0.5046575784709395, -0.5609132323152847, 1.679107064439151, 0.6825037853544341, -1.5977176226648016, 1.8959464303080562, -0.7812860715595836, -2.998394007543733, -0.22637273967347724, -0.9642457010679496, 1.4557274834236749, 2.412244419186633, 2.3151771738421965, 0.7881483386786367, 1.6622850935863422, 0.1304768990234367, 1.9344501393866649, 3.1271558035162914, -0.10250886439220543, 1.4921395116492966, 2.761645355670677, 1.6903473594991179, 1.009209807271491, 0.07273926986120445, -1.4941708135718021, -2.082786362439631, 1.0160924044870847, 2.5326580674673895, -0.8328208491083264, 2.0390177029762935, 3.0342637531932777] +[0.0, -0.02568680526917187, 0.21645604230056517, ..., 3.0342637531932777] ->>> language_dict = language('Quis custodiet ipsos custodes') - ->>> sorted(language_dict.keys(), key=lambda x: language_dict[x], reverse=True)[:5] -[u'Latin', u'Dutch', u'Greek', u'Portuguese', u'Spanish'] - ->>> language_dict +>>> language('Quis custodiet ipsos custodes') {u'Swedish': 0.00033330636691921914, u'Lithuanian': 0.007328693814717631, u'Vietnamese': 0.0002686116137658802, u'Romanian': 8.133913804076592e-06, ...} ``` Batch API Access ---------------- - -If you'd like to use our batch api interface, please check out the [pricing page](https://indico.io/pricing) on our website to find the right plan for you. - -``` +Each `indicoio` function has a corresponding batch function for analyzing many examples with a single request. Simply pass in a list of inputs and receive a list of results in return. +```python >>> from indicoio import batch_sentiment ->>> batch_sentiment(['Text to analyze', 'More text'], auth=("example@example.com", "********")) + +>>> batch_sentiment(['Best day ever', 'Worst day ever']) +[0.9899001220871786, 0.005709885173415242] ``` - -Authentication credentials can also be set as the environment variables `$INDICO_USERNAME` and `$INDICO_PASSWORD` or as `username` and `password` in the indicorc file. - -Private cloud API Access ------------------------- - -If you're looking to use indico's API for high throughput applications, please check out the [pricing page](https://indico.io/pricing) on our website to find the right plan for you. - -``` ->>> from indicoio import sentiment ->>> sentiment("Text to analyze", cloud="example", auth=("example@example.com", "********")) -``` - -The `cloud` parameter redirects API calls to your private cloud hosted at `[cloud].indico.domains` - -Private cloud subdomains can also be set as the environment variable `$INDICO_CLOUD` or as `cloud` in the indicorc file. - -Configuration ------------------------- - -Indicoio-python will search ./.indicorc and $HOME/.indicorc for the optional configuration file. Values in the local configuration file (./.indicorc) take precedence over those found in a global configuration file ($HOME/.indicorc). The indicorc file can be used to set an authentication username and password or a private cloud subdomain, so these arguments don't need to be specified for every api call. All sections are optional. - -Here is an example of a valid indicorc file: - - -``` -[auth] -username = test@example.com -password = secret - -[private_cloud] -cloud = example -``` - -Environment variables take precedence over any configuration found in the indicorc file. -The following environment variables are valid: - -``` -$INDICO_USERNAME -$INDICO_PASSWORD -$INDICO_CLOUD -``` - - Finally, any values explicitly passed in to an api call will override configuration options set in the indicorc file or in an environment variable. diff --git a/README.rst b/README.rst index 5dc46f7..8aa6ee2 100644 --- a/README.rst +++ b/README.rst @@ -1,31 +1,40 @@ indicoio-python =============== -A wrapper for a series of APIs made by indico. +A wrapper for the `indico API `__. -Check out the main site on: - -http://indico.io - -Our APIs are totally free to use, and ready to be used in your -application. No data or training required. +The indico API is free to use, and no training data is required. Installation ------------ -:: +From PyPI: + +.. code:: bash pip install indicoio -Documentation -------------- +From source: -Available at `indico.reame.io `__ +.. code:: bash -Current APIs ------------- + git clone https://github.com/IndicoDataSolutions/IndicoIo-python.git + python setup.py install -Right now this wrapper supports the following apps: +API Keys + Setup +---------------- + +For API key registration and setup, checkout our `quickstart +guide `__. + +Full Documentation +------------------ + +Detailed documentation and further code examples are available at +`indico.reame.io `__. + +Supported APIs: +--------------- - Positive/Negative Sentiment Analysis - Political Sentiment Analysis @@ -38,27 +47,22 @@ Right now this wrapper supports the following apps: Examples -------- -:: +.. code:: python - >>> import numpy as np + >>> from indicoio import political, sentiment, language, text_tags, fer, facial_features, image_features - >>> from indicoio import political, sentiment, fer, facial_features, language + >>> indicoio.config.api_key = "YOUR_API_KEY" >>> political("Guns don't kill people. People kill people.") {u'Libertarian': 0.47740164630834825, u'Green': 0.08454409540443657, u'Liberal': 0.16617097211030055, u'Conservative': 0.2718832861769146} >>> sentiment('Worst movie ever.') - {u'Sentiment': 0.07062467665597527} + 0.07062467665597527 >>> sentiment('Really enjoyed the movie.') - {u'Sentiment': 0.8105182526856075} + 0.8105182526856075 - >>> test_text = "Facebook blog posts about Android tech make better journalism than most news outlets." - - >>> tag_dict = text_tags(test_text) - - >>> sorted(tag_dict.keys(), key=lambda x: tag_dict[x], reverse=True)[:3] - [u'startups_and_entrepreneurship', u'investment', u'business'] + >>> text_tags("Facebook blog posts about Android tech make better journalism than most news outlets.") >>> text_tags(test_text, threshold=0.1) # return only keys with value > 0.1 {u'startups_and_entrepreneurship': 0.21888586688354486} @@ -66,87 +70,30 @@ Examples >>> text_tags(test_text, top_n=1) # return only keys with top_n values {u'startups_and_entrepreneurship': 0.21888586688354486} + >>> import numpy as np + >>> test_face = np.linspace(0,50,48*48).reshape(48,48).tolist() >>> fer(test_face) {u'Angry': 0.08843749137458341, u'Sad': 0.39091163159204684, u'Neutral': 0.1947947999669361, u'Surprise': 0.03443785859010413, u'Fear': 0.17574534848440568, u'Happy': 0.11567286999192382} >>> facial_features(test_face) - [0.0, -0.02568680526917187, 0.21645604230056517, -0.1519435786033145, -0.5648621854611555, 3.0607368045577226, 0.11434321880792693, -0.02163810928547493, -0.44224330594186484, 0.3024315632285246, -2.6068048934495276, 2.497798330306638, 3.040558335205844, 0.741045340525325, 0.37198135618478817, -0.33132377802172325, -0.9804190889833034, 0.5046575784709395, -0.5609132323152847, 1.679107064439151, 0.6825037853544341, -1.5977176226648016, 1.8959464303080562, -0.7812860715595836, -2.998394007543733, -0.22637273967347724, -0.9642457010679496, 1.4557274834236749, 2.412244419186633, 2.3151771738421965, 0.7881483386786367, 1.6622850935863422, 0.1304768990234367, 1.9344501393866649, 3.1271558035162914, -0.10250886439220543, 1.4921395116492966, 2.761645355670677, 1.6903473594991179, 1.009209807271491, 0.07273926986120445, -1.4941708135718021, -2.082786362439631, 1.0160924044870847, 2.5326580674673895, -0.8328208491083264, 2.0390177029762935, 3.0342637531932777] + [0.0, -0.02568680526917187, 0.21645604230056517, ..., 3.0342637531932777] - >>> language_dict = language('Quis custodiet ipsos custodes') - - >>> sorted(language_dict.keys(), key=lambda x: language_dict[x], reverse=True)[:5] - [u'Latin', u'Dutch', u'Greek', u'Portuguese', u'Spanish'] - - >>> language_dict + >>> language('Quis custodiet ipsos custodes') {u'Swedish': 0.00033330636691921914, u'Lithuanian': 0.007328693814717631, u'Vietnamese': 0.0002686116137658802, u'Romanian': 8.133913804076592e-06, ...} Batch API Access ---------------- -If you'd like to use our batch api interface, please check out the -`pricing -page `__ on our -website to find the right plan for you. +Each ``indicoio`` function has a corresponding batch function for +analyzing many examples with a single request. Simply pass in a list of +inputs and receive a list of results in return. -:: +.. code:: python - >>> from indicio import batch_sentiment - >>> batch_sentiment(['Text to analyze', 'More text'], auth=("example@example.com", "********")) + >>> from indicoio import batch_sentiment -Authentication credentials can also be set as the environment variables -``$INDICO_USERNAME`` and ``$INDICO_PASSWORD`` or as ``username`` and -``password`` in the indicorc file. + >>> batch_sentiment(['Best day ever', 'Worst day ever']) + [0.9899001220871786, 0.005709885173415242] -Private cloud API Access ------------------------- - -If you're looking to use indico's API for high throughput applications, -please check out the `pricing -page `__ on our -website to find the right plan for you. - -:: - - >>> from indicio import sentiment - >>> sentiment("Text to analyze", cloud="example", auth=("example@example.com", "********")) - -The ``cloud`` parameter redirects API calls to your private cloud hosted -at ``[cloud].indico.domains`` - -Private cloud subdomains can also be set as the environment variable -``$INDICO_CLOUD`` or as ``cloud`` in the indicorc file. - -Configuration -------------- - -Indicoio-python will search ./.indicorc and -HOME/.indicorc for the optional configuration file. Values in the local configuration file (./.indicorc) take precedence over those found in a global configuration file (`\ HOME/.indicorc). -The indicorc file can be used to set an authentication username and -password or a private cloud subdomain, so these arguments don't need to -be specified for every api call. All sections are optional. - -Here is an example of a valid indicorc file: - -:: - - [auth] - username = test@example.com - password = secret - - [private_cloud] - cloud = example - -Environment variables take precedence over any configuration found in -the indicorc file. The following environment variables are valid: - -:: - - $INDICO_USERNAME - $INDICO_PASSWORD - $INDICO_CLOUD - -Finally, any values explicitly passed in to an api call will override -configuration options set in the indicorc file or in an environment -variable. diff --git a/indicoio/__init__.py b/indicoio/__init__.py index c265775..39d7ee5 100644 --- a/indicoio/__init__.py +++ b/indicoio/__init__.py @@ -2,7 +2,7 @@ from functools import partial JSON_HEADERS = {'Content-type': 'application/json', 'Accept': 'text/plain'} -Version, version, __version__, VERSION = ('0.5.1',) * 4 +Version, version, __version__, VERSION = ('0.5.2',) * 4 from indicoio.text.sentiment import political, posneg from indicoio.text.sentiment import posneg as sentiment diff --git a/indicoio/config.py b/indicoio/config.py index 5633302..7f271e8 100644 --- a/indicoio/config.py +++ b/indicoio/config.py @@ -16,7 +16,7 @@ class Settings(ConfigParser.ConfigParser): for fd in self.files: try: self.readfp(fd) - except AttributeError: + except AttributeError: self.read(fd) self.auth_settings = self.get_section('auth') @@ -33,22 +33,24 @@ class Settings(ConfigParser.ConfigParser): def cloud(self): return ( - os.getenv("INDICO_CLOUD") or - self.private_cloud_settings.get('cloud') or + os.getenv("INDICO_CLOUD") or + self.private_cloud_settings.get('cloud') or None ) - def auth(self): + def api_key(self): return ( - os.getenv("INDICO_USERNAME") or self.auth_settings.get('username'), - os.getenv("INDICO_PASSWORD") or self.auth_settings.get('password') + os.getenv("INDICO_API_KEY") or + self.auth_settings.get('api_key') or + None ) + SETTINGS = Settings(files=[ os.path.expanduser("~/.indicorc"), os.path.join(os.getcwd(), '.indicorc') ]) - -AUTH = SETTINGS.auth() -CLOUD = SETTINGS.cloud() -PUBLIC_API_HOST = 'apiv1.indico.io' +api_key = SETTINGS.api_key() +cloud = SETTINGS.cloud() +PUBLIC_API_HOST = 'apiv2.indico.io' +url_protocol = "https:" diff --git a/indicoio/examples/__init__.py b/indicoio/examples/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/indicoio/images/features.py b/indicoio/images/features.py index 8582c82..ee02526 100644 --- a/indicoio/images/features.py +++ b/indicoio/images/features.py @@ -4,7 +4,7 @@ import numpy as np from indicoio.utils import image_preprocess, api_handler, is_url import indicoio.config as config -def facial_features(image, cloud=config.CLOUD, batch=False, auth=None, **kwargs): +def facial_features(image, cloud=None, batch=False, api_key=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,9 +26,9 @@ def facial_features(image, cloud=config.CLOUD, batch=False, auth=None, **kwargs) :type image: list of lists :rtype: List containing feature responses """ - return api_handler(image, cloud=cloud, api="facialfeatures", batch=batch, auth=auth, **kwargs) + return api_handler(image, cloud=cloud, api="facialfeatures", batch=batch, api_key=api_key, **kwargs) -def image_features(image, cloud=config.CLOUD, batch=False, auth=None, **kwargs): +def image_features(image, cloud=None, batch=False, api_key=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. @@ -58,6 +58,5 @@ def image_features(image, cloud=config.CLOUD, batch=False, auth=None, **kwargs): :type image: numpy.ndarray :rtype: List containing features """ - if not is_url(image, batch=batch): - image = image_preprocess(image, batch=batch) - return api_handler(image, cloud=cloud, api="imagefeatures", batch=batch, auth=auth, **kwargs) + image = image_preprocess(image, batch=batch) + return api_handler(image, cloud=cloud, api="imagefeatures", batch=batch, api_key=api_key, **kwargs) diff --git a/indicoio/images/fer.py b/indicoio/images/fer.py index 4c6af93..2c18867 100644 --- a/indicoio/images/fer.py +++ b/indicoio/images/fer.py @@ -4,7 +4,7 @@ import numpy as np from indicoio.utils import api_handler import indicoio.config as config -def fer(image, cloud=config.CLOUD, batch=False, auth=None, **kwargs): +def fer(image, cloud=None, batch=False, api_key=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 @@ -28,4 +28,4 @@ def fer(image, cloud=config.CLOUD, batch=False, auth=None, **kwargs): :rtype: Dictionary containing emotion probability pairs """ - return api_handler(image, cloud=cloud, api="fer", batch=batch, auth=auth, **kwargs) + return api_handler(image, cloud=cloud, api="fer", batch=batch, api_key=api_key, **kwargs) diff --git a/indicoio/speech/__init__.py b/indicoio/speech/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/indicoio/text/lang.py b/indicoio/text/lang.py index cf6c1e7..547c18b 100644 --- a/indicoio/text/lang.py +++ b/indicoio/text/lang.py @@ -1,7 +1,7 @@ from indicoio.utils import api_handler import indicoio.config as config -def language(text, cloud=config.CLOUD, batch=False, auth=None, **kwargs): +def language(text, cloud=None, batch=False, api_key=None, **kwargs): """ Given input text, returns a probability distribution over 33 possible languages of what language the text was written in. @@ -24,4 +24,4 @@ def language(text, cloud=config.CLOUD, batch=False, auth=None, **kwargs): :rtype: Dictionary of language probability pairs """ - return api_handler(text, cloud=cloud, api="language", batch=batch, auth=auth, **kwargs) + return api_handler(text, cloud=cloud, api="language", batch=batch, api_key=api_key, **kwargs) diff --git a/indicoio/text/sentiment.py b/indicoio/text/sentiment.py index 893fcd7..a89d13c 100644 --- a/indicoio/text/sentiment.py +++ b/indicoio/text/sentiment.py @@ -2,7 +2,7 @@ from indicoio import JSON_HEADERS from indicoio.utils import api_handler import indicoio.config as config -def political(text, cloud=config.CLOUD, batch=False, auth=None, **kwargs): +def political(text, cloud=None, batch=False, api_key=None, **kwargs): """ Given input text, returns a probability distribution over the political alignment of the speaker. @@ -28,9 +28,9 @@ def political(text, cloud=config.CLOUD, batch=False, auth=None, **kwargs): :rtype: Dictionary of party probability pairs """ - return api_handler(text, cloud=cloud, api="political", batch=batch, auth=auth, **kwargs) + return api_handler(text, cloud=cloud, api="political", batch=batch, api_key=api_key, **kwargs) -def posneg(text, cloud=config.CLOUD, batch=False, auth=None, **kwargs): +def posneg(text, cloud=None, batch=False, api_key=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. @@ -51,4 +51,4 @@ def posneg(text, cloud=config.CLOUD, batch=False, auth=None, **kwargs): :rtype: Float """ - return api_handler(text, cloud=cloud, api="sentiment", batch=batch, auth=auth, **kwargs) + return api_handler(text, cloud=cloud, api="sentiment", batch=batch, api_key=api_key, **kwargs) diff --git a/indicoio/text/tagging.py b/indicoio/text/tagging.py index 52500eb..13a7246 100644 --- a/indicoio/text/tagging.py +++ b/indicoio/text/tagging.py @@ -1,7 +1,7 @@ from indicoio.utils import api_handler import indicoio.config as config -def text_tags(text, cloud=config.CLOUD, batch=False, auth=None, **kwargs): +def text_tags(text, cloud=None, batch=False, api_key=None, **kwargs): """ Given input text, returns a probability distribution over 100 document categories @@ -23,4 +23,4 @@ def text_tags(text, cloud=config.CLOUD, batch=False, auth=None, **kwargs): :rtype: Dictionary of class probability pairs """ - return api_handler(text, cloud=cloud, api="texttags", batch=batch, auth=auth, **kwargs) + return api_handler(text, cloud=cloud, api="texttags", batch=batch, api_key=api_key, **kwargs) diff --git a/indicoio/utils/__init__.py b/indicoio/utils/__init__.py index 5944839..01333f0 100644 --- a/indicoio/utils/__init__.py +++ b/indicoio/utils/__init__.py @@ -6,11 +6,12 @@ from skimage.transform import resize from indicoio import JSON_HEADERS from indicoio import config - -def api_handler(arg, cloud, api, batch=False, auth=None, **kwargs): +def api_handler(arg, cloud, api, batch=False, api_key=None, **kwargs): data = {'data': arg} data.update(**kwargs) json_data = json.dumps(data) + if not cloud: + cloud=config.cloud if cloud: host = "%s.indico.domains" % cloud @@ -18,14 +19,15 @@ def api_handler(arg, cloud, api, batch=False, auth=None, **kwargs): # default to indico public cloud host = config.PUBLIC_API_HOST - url = "http://%s/%s" % (host, api) - if batch: - url += "/batch" + if not api_key: + api_key = config.api_key - if not auth: - auth = config.AUTH + url = config.url_protocol + "//%s/%s" % (host, api) + url = url + "/batch" if batch else url + url += "?key=%s" % api_key - response = requests.post(url, data=json_data, headers=JSON_HEADERS, auth=auth) + + response = requests.post(url, data=json_data, headers=JSON_HEADERS) if response.status_code == 503 and cloud != None: raise Exception("Private cloud '%s' does not include api '%s'" % (cloud, api)) diff --git a/setup.py b/setup.py index 185dcc8..42e67e2 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ except ImportError: setup( name="IndicoIo", - version='0.5.1', + version='0.5.2', packages=[ "indicoio", "indicoio.text", diff --git a/tests/test_configure.py b/tests/test_configure.py index 9a11cb3..325a57f 100644 --- a/tests/test_configure.py +++ b/tests/test_configure.py @@ -27,11 +27,9 @@ class TestConfigureEnv(unittest.TestCase): """ Ensure cloud authentication credentials are read in from environment variables """ - username = "test" - password = "password" - os.environ["INDICO_USERNAME"] = username - os.environ["INDICO_PASSWORD"] = password - assert config.SETTINGS.auth() == (username, password) + api_key = "text" + os.environ["INDICO_API_KEY"] = api_key + assert config.SETTINGS.api_key() == api_key class TestConfigurationFile(unittest.TestCase): @@ -40,17 +38,15 @@ class TestConfigurationFile(unittest.TestCase): """ def setUp(self): - self.username = "test" - self.password = "password" + self.api_key = "test" self.cloud = "localhost" config = """ [auth] - username = %s - password = %s + api_key = %s [private_cloud] cloud = %s - """ % (self.username, self.password, self.cloud) + """ % (self.api_key, self.cloud) config_file = StringIO(textwrap.dedent(config)) self.settings = Settings(files=[config_file]) @@ -66,7 +62,7 @@ class TestConfigurationFile(unittest.TestCase): """ Ensure cloud authentication credentials are read in from file """ - assert self.settings.auth() == (self.username, self.password) + assert self.settings.api_key() == self.api_key class TestPrecedence(unittest.TestCase): @@ -75,27 +71,23 @@ class TestPrecedence(unittest.TestCase): """ def setUp(self): - self.file_username = "file-username" - self.file_password = "file-password" + self.file_api_key = "file-api-key" self.file_cloud = "file-cloud" - self.env_username = "env-username" - self.env_password = "env-password" + self.env_api_key = "env-api-key" self.env_cloud = "env-cloud" config = """ [auth] - username = %s - password = %s + api_key = %s [private_cloud] cloud = %s - """ % (self.file_username, self.file_password, self.file_cloud) + """ % (self.file_api_key, self.file_cloud) config_file = StringIO(textwrap.dedent(config)) os.environ = { 'INDICO_CLOUD': self.env_cloud, - 'INDICO_USERNAME': self.env_username, - 'INDICO_PASSWORD': self.env_password + 'INDICO_API_KEY': self.env_api_key } self.settings = Settings(files=[config_file]) @@ -110,7 +102,7 @@ class TestPrecedence(unittest.TestCase): Ensure cloud authentication credentials set in environment variables are used over those in config files """ - assert self.settings.auth() == (self.env_username, self.env_password) + assert self.settings.api_key() == self.env_api_key class TestConfigFilePrecedence(unittest.TestCase): @@ -119,37 +111,31 @@ class TestConfigFilePrecedence(unittest.TestCase): """ def setUp(self): - self.high_priority_username = "high-priority-username" - self.high_priority_password = "high-priority-password" + self.high_priority_api_key = "high-priority-api-key" self.high_priority_cloud = "high-priority-cloud" - self.low_priority_username = "low-priority-username" - self.low_priority_password = "low-priority-password" + self.low_priority_api_key = "low-priority-api-key" self.low_priority_cloud = "low-priority-cloud" high_priority_config = """ [auth] - username = %s - password = %s + api_key = %s [private_cloud] cloud = %s """ % ( - self.high_priority_username, - self.high_priority_password, + self.high_priority_api_key, self.high_priority_cloud ) low_priority_config = """ [auth] username = %s - password = %s [private_cloud] cloud = %s """ % ( - self.low_priority_username, - self.low_priority_password, + self.low_priority_api_key, self.low_priority_cloud ) @@ -172,4 +158,4 @@ class TestConfigFilePrecedence(unittest.TestCase): """ Ensure the cloud auth priority is handled properly """ - assert self.settings.auth() == (self.high_priority_username, self.high_priority_password) + assert self.settings.api_key() == self.high_priority_api_key diff --git a/tests/test_remote.py b/tests/test_remote.py index 27abf0c..75c87a2 100644 --- a/tests/test_remote.py +++ b/tests/test_remote.py @@ -16,36 +16,40 @@ DIR = os.path.dirname(os.path.realpath(__file__)) class BatchAPIRun(unittest.TestCase): def setUp(self): - self.auth = config.AUTH + self.api_key = config.api_key + config.url_protocol = "http:" - if not all(self.auth): + if not all(self.api_key): raise SkipTest + def tearDown(self): + config.url_protocol = "https:" + def test_batch_texttags(self): test_data = ["On Monday, president Barack Obama will be..."] - response = batch_text_tags(test_data, auth=self.auth) + response = batch_text_tags(test_data, api_key=self.api_key) self.assertTrue(isinstance(response, list)) def test_batch_posneg(self): test_data = ['Worst song ever', 'Best song ever'] - response = batch_sentiment(test_data, auth=self.auth) + response = batch_sentiment(test_data, api_key=self.api_key) self.assertTrue(isinstance(response, list)) self.assertTrue(response[0] < 0.5) def test_batch_political(self): test_data = ["Guns don't kill people, people kill people."] - response = batch_political(test_data, auth=self.auth) + response = batch_political(test_data, api_key=self.api_key) self.assertTrue(isinstance(response, list)) def test_batch_fer(self): test_data = [np.random.rand(48, 48).tolist()] - response = batch_fer(test_data, auth=self.auth) + response = batch_fer(test_data, api_key=self.api_key) self.assertTrue(isinstance(response, list)) self.assertTrue(isinstance(response[0], dict)) def test_batch_facial_features(self): test_data = [np.random.rand(48, 48).tolist()] - response = batch_facial_features(test_data, auth=self.auth) + response = batch_facial_features(test_data, api_key=self.api_key) self.assertTrue(isinstance(response, list)) self.assertTrue(isinstance(response[0], list)) self.assertEqual(len(response[0]), 48) @@ -65,21 +69,21 @@ class BatchAPIRun(unittest.TestCase): def test_batch_image_features_greyscale(self): test_data = [np.random.rand(64, 64).tolist()] - response = batch_image_features(test_data, auth=self.auth) + response = batch_image_features(test_data, api_key=self.api_key) self.assertTrue(isinstance(response, list)) self.assertTrue(isinstance(response[0], list)) self.assertEqual(len(response[0]), 2048) def test_batch_image_features_rgb(self): test_data = [np.random.rand(64, 64, 3).tolist()] - response = batch_image_features(test_data, auth=self.auth) + response = batch_image_features(test_data, api_key=self.api_key) self.assertTrue(isinstance(response, list)) self.assertTrue(isinstance(response[0], list)) self.assertEqual(len(response[0]), 2048) def test_batch_language(self): test_data = ['clearly an english sentence'] - response = batch_language(test_data, auth=self.auth) + response = batch_language(test_data, api_key=self.api_key) self.assertTrue(isinstance(response, list)) self.assertTrue(response[0]['English'] > 0.25) @@ -88,7 +92,7 @@ class BatchAPIRun(unittest.TestCase): self.assertRaises(ConnectionError, batch_language, test_data, - auth=self.auth, + api_key=self.api_key, cloud='invalid/cloud') @@ -124,11 +128,11 @@ class FullAPIRun(unittest.TestCase): self.assertTrue(isinstance(response, dict)) self.assertEqual(political_set, set(response.keys())) - test_string = "Save the whales" + test_string = "pro-choice" response = political(test_string) self.assertTrue(isinstance(response, dict)) - assert response['Green'] > 0.5 + assert response['Liberal'] > 0.25 def test_posneg(self): test_string = "Worst song ever." @@ -252,6 +256,39 @@ class FullAPIRun(unittest.TestCase): test_data, cloud='invalid/cloud') + temp_cloud = config.cloud + config.cloud = 'invalid/cloud' + + self.assertEqual(config.cloud, 'invalid/cloud') + self.assertRaises(ConnectionError, + language, + test_data) + + config.cloud = temp_cloud + + self.assertRaises(ConnectionError, + language, + test_data, + cloud='indico-test') + + def test_set_api_key(self): + test_data = 'clearly an english sentence' + self.assertRaises(ValueError, + language, + test_data, + api_key ='invalid_api_key') + + temp_api_key = config.api_key + config.api_key = 'invalid_api_key' + + self.assertEqual(config.api_key, 'invalid_api_key') + self.assertRaises(ValueError, + language, + test_data) + + config.api_key = temp_api_key + + if __name__ == "__main__": unittest.main()