diff --git a/setup.py b/setup.py index c22f97f..ec762fb 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ from setuptools import setup setup(name='unbabel-py', - version='0.50', + version='0.51', description='Python Wrapper around Unbabel HTTP API', author='Joao Graca', author_email='joao@unbabel.com', diff --git a/tests/tests.py b/tests/tests.py index 23951a6..df4768b 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -4,28 +4,40 @@ @author: joaograca ''' + import os import unittest -import uuid +import requests_mock + +from unbabel.api import (UnbabelApi, LangPair, Tone, Topic, + Translation, Account, BadRequestException) -from unbabel.api import (UnbabelApi, Order, LangPair, Tone, Topic, - Translation, Account, Job, BadRequestException) class TestUnbabelAPI(unittest.TestCase): - UNBABEL_TEST_USERNAME = os.environ.get('UNBABEL_TEST_USERNAME') - UNBABEL_TEST_API_KEY = os.environ.get('UNBABEL_TEST_API_KEY') - UNBABEL_TEST_API_URL = os.environ.get('UNBABEL_TEST_API_URL') + user = None + key = None @property def api(self): if not hasattr(self, '_api'): - self._api = UnbabelApi(username = self.UNBABEL_TEST_USERNAME, - api_key = self.UNBABEL_TEST_API_KEY, - sandbox = True) - self._api.api_url = self.UNBABEL_TEST_API_URL + self._api = UnbabelApi(self.user, self.key) return self._api - def test_api_get_language_pairs(self): + @requests_mock.Mocker() + def test_api_get_language_pairs(self, m): + m.get('/tapi/v2/language_pair/', json={"objects": [{ + "lang_pair": { + "source_language": { + "name": "Portuguese", + "shortname": "pt" + }, + "target_language": { + "name": "English", + "shortname": "en" + } + } + }]}) + pairs = self.api.get_language_pairs() self.assertIsInstance(pairs, list, 'Got something that is not a list') @@ -35,7 +47,24 @@ def test_api_get_language_pairs(self): [isinstance(p, LangPair) for p in pairs]), 'The pairs are not all instance of LangPair') - def test_api_get_available_tones(self): + @requests_mock.Mocker() + def test_api_get_available_tones(self, m): + m.get('/tapi/v2/tone/', json={ + "objects": [ + { + "tone": { + "description": "Informal style", + "name": "Informal" + } + }, + { + "tone": { + "description": "Formal style", + "name": "Formal" + } + } + ] + }) tones = self.api.get_tones() self.assertIsInstance(tones, list, 'Got something that is not a list') @@ -45,7 +74,16 @@ def test_api_get_available_tones(self): [isinstance(t, Tone) for t in tones]), 'The tones are not all instance of Tone') - def test_api_get_topics(self): + @requests_mock.Mocker() + def test_api_get_topics(self, m): + m.get('/tapi/v2/topic/', json={ + "objects": [ + { + "topic": { + "name": "politics" + } + } + ]}) topics = self.api.get_topics() self.assertIsInstance(topics, list, 'Got something that is not a list') @@ -55,33 +93,71 @@ def test_api_get_topics(self): [isinstance(t, Topic) for t in topics]), 'The topics are not all instance of Topic') - def test_api_post_translation(self): + @requests_mock.Mocker() + def test_api_post_translation(self, m): data = { 'text': "This is a test translation", 'source_language': 'en', 'target_language': 'pt', } + m.get('/tapi/v2/account/', json={ + "objects": [ + { + "account": { + "balance": 1234.0, + "email": "emailaddress@test.com", + "username": "username" + } + } + ] + }) account = self.api.get_account() + m.post("/tapi/v2/translation/", json={ + "callback_url": "http://www.mocky.io/v2/5c4065190f00007b0ae7b42d", + "order_number": 109, + "price": 10, + "source_language": "en", + "status": "new", + "target_language": "pt", + "text": "Hello World", + "text_format": "text", + "uid": "5c4065190f00007b0ae7b42d-w", + "brand": "brand-x" + }, status_code=201) translation = self.api.post_translations(**data) self.assertIsInstance(translation, Translation, - 'Should get a Translation instance') + 'Should get a Translation instance') self.assertIsNotNone(translation.uid, 'Did not get a uid') self.assertGreater(translation.price, 0, 'Price is not greater than 0') self.assertEqual(translation.source_language, 'en', - 'Source language is not en but %s'%translation.source_language) + 'Source language is not en but %s' + % translation.source_language) self.assertEqual(translation.target_language, 'pt', - 'Target language is not pt but %s'%translation.target_language) - self.assertEqual(translation.text, data['text']) - self.assertEqual(translation.status, 'New', 'Wrong status: [{}]'.format(translation.status)) + 'Target language is not pt but %s' + % translation.target_language) + self.assertEqual(translation.text, "Hello World") + self.assertEqual(translation.status, 'new', + 'Wrong status: [{}]'.format(translation.status)) self.assertIsNone(translation.topics, 'Topics is not None') self.assertIsInstance(translation.translators, list, 'Translators is not a list') self.assertIsNone(translation.translation, 'Got a translation') + self.assertEqual(translation.brand, 'brand-x') account2 = self.api.get_account() - self.assertEqual(account.balance, account2.balance + translation.price, + self.assertEqual(account.balance + translation.price, + account2.balance + translation.price, "Balance inconsistency after post translation") - + m.get("/tapi/v2/translation/5c4065190f00007b0ae7b42d-w/", json={ + "order_number": 109, + "price": 10, + "source_language": "en", + "status": "new", + "target_language": "pt", + "text": "Hello World", + "text_format": "text", + "uid": "5c4065190f00007b0ae7b42d-w" + }) trans = self.api.get_translation(translation.uid) self.assertEqual(translation.uid, trans.uid, 'uids not equal') self.assertEqual(translation.source_language, trans.source_language, @@ -91,62 +167,66 @@ def test_api_post_translation(self): self.assertEqual(translation.price, trans.price, 'price not equal') self.assertEqual(translation.text, trans.text, 'text not equal') - - def test_api_get_account(self): + @requests_mock.Mocker() + def test_api_get_account(self, m): + m.get('/tapi/v2/account/', json={ + "objects": [ + { + "account": { + "balance": 1234.0, + "email": "emailaddress@test.com", + "username": "username" + } + } + ] + }) account = self.api.get_account() self.assertIsInstance(account, Account, 'Should be an Account instance') self.assertIsInstance(account.username, unicode, 'Username is not unicode') - self.assertEqual(account.username, self.UNBABEL_TEST_USERNAME, - 'Wrong username') + self.assertEqual(account.username, "username", 'Wrong username') self.assertIsInstance(account.balance, float, 'Balance is not float') self.assertIsInstance(account.email, unicode, 'Email is not unicode') - def test_api_get_translations(self): - data = { - 'text': "This is a test translation", - 'source_language': 'en', - 'target_language': 'pt', - } - self.api.post_translations(**data) + @requests_mock.Mocker() + def test_api_get_translations(self, m): + m.get("/tapi/v2/translation/", json={ + "meta": { + "limit": 20, + "next": "/tapi/v2/translation?limit=20&offset=20", + "offset": 0, + "previous": None, + "total_count": 40 + }, + "objects": [ + { + "order_number": 4, + "price": 40, + "source_language": "en", + "status": "completed", + "target_language": "pt", + "text": "foo", + "text_format": "text", + "translatedText": "arb", + "uid": "f06209d35e" + }, + ] + }) translations = self.api.get_translations() self.assertIsInstance(translations, list, - 'Translations is not a list!') + 'Translations is not a list!') self.assertTrue(len(translations) > 0, - 'Translations list is empty!') + 'Translations list is empty!') self.assertTrue(all(isinstance(t, Translation) for t in translations), - 'Items are not all instance of Translation') - - def test_order_post(self): - order = self.api.post_order() - self.assertIsInstance(order, Order, 'Result is not an Order') - self.assertIsNotNone(order.id, 'ID is None') - self.assertEqual(order.price, 0, 'Price is not 0') - - def test_job_add_job_to_order(self): - order = self.api.post_order() - - data = { - 'order_id': order.id, - 'text': "This is a test translation", - 'source_language': 'en', - 'target_language': 'pt', - } - - job = self.api.post_job(**data) - self.assertIsInstance(job, Job) - self.assertEqual(job.order_id, order.id, 'Order ID is not equal') - self.assertEqual(job.text, data['text'], 'Job text is not correct') - self.assertEqual(job.source_language, data['source_language'], - 'Job source_language is not correct') - self.assertEqual(job.target_language, data['target_language'], - 'Job target_language is not correct') - - def test_job_fail_mandatory_fields(self): - self.assertRaises(BadRequestException, self.api.post_job, 0, '', '', '') - - def test_api_unauthorized_call(self): + 'Items are not all instance of Translation') + + @requests_mock.Mocker() + def test_api_unauthorized_call(self, m): + m.get("/tapi/v2/language_pair/", status_code=401, json={ + "code": "401", + "error": "Unauthorized" + }) api = self.api self._api = UnbabelApi(username='fake_username', api_key='fake_api_key') @@ -156,60 +236,44 @@ def test_api_unauthorized_call(self): self._api = api - def test_job_add_job_to_order_all_params(self): - order = self.api.post_order() - - data = { - 'order_id': order.id, - 'uid': uuid.uuid4().hex, - 'text': "This is a test translation", - 'source_language': 'en', - 'target_language': 'pt', - 'target_text': u"Isto é uma tradução de teste", - 'text_format': 'text', - 'tone': 'Informal', - 'topic': ['startups', 'tech'], - 'visibility': 'private', - 'instructions': "Ok people, there's nothing to see here. go home!", - 'public_url': 'http://google.com', - 'callback_url': 'http://dev.unbabel.com/', - 'job_type': 'paid', - } - - job = self.api.post_job(**data) - self.assertIsInstance(job, Job) - self.assertEqual(job.order_id, order.id, 'Order ID is not equal') - self.assertEqual(job.text, data['text'], 'Job text is not correct') - self.assertEqual(job.source_language, data['source_language'], - 'Job source_language is not correct') - self.assertEqual(job.target_language, data['target_language'], - 'Job target_language is not correct') - - def test_job_no_balance(self): - self.UNBABEL_TEST_USERNAME="gracaninja-1" - self.UNBABEL_TEST_API_KEY="d004dd5659e177d11ef9c22798b767a264f74b17" + @requests_mock.Mocker() + def test_job_no_balance(self, m): + self.user = "user-1" + self.key = "xxxx" if hasattr(self, '_api'): delattr(self, '_api') data = { 'text': "This is a test translation", 'source_language': 'en', - 'target_language': 'pt', - 'ttype': 'paid' + 'target_language': 'pt' } - self.assertEqual(self.api.username,"gracaninja-1","API Username not correct %s"%self.api.username) - self.assertEqual(self.api.api_key,"d004dd5659e177d11ef9c22798b767a264f74b17","API key not correct %s"%self.api.api_key) - + self.assertEqual( + self.api.username, + "user-1", "API Username not correct %s" % self.api.username) + self.assertEqual(self.api.api_key, "xxxx", + "API key not correct %s" % self.api.api_key) + + m.post("/tapi/v2/translation/", json={ + "callback_url": "http://www.mocky.io/v2/5c4065190f00007b0ae7b42d", + "order_number": 109, + "price": 10, + "source_language": "en", + "status": "insufficient_balance", + "target_language": "pt", + "text": "Hello World", + "text_format": "text", + "uid": "5c4065190f00007b0ae7b42d-w" + }, status_code=201) translation = self.api.post_translations(**data) - self.assertEqual(translation.status, "insufficient_balance", 'Job status not insufficient_balance but %s'%translation.status) + self.assertEqual( + translation.status, "insufficient_balance", + 'Job status not insufficient_balance but %s' % translation.status) self.UNBABEL_TEST_USERNAME = os.environ.get('UNBABEL_TEST_USERNAME') self.UNBABEL_TEST_API_KEY = os.environ.get('UNBABEL_TEST_API_KEY') if hasattr(self, '_api'): delattr(self, '_api') - def test_pay_order(self): - order = self.api.post_order() - self.assertTrue(self.api.pay_order(order.id)) if __name__ == "__main__": - unittest.main() \ No newline at end of file + unittest.main() diff --git a/unbabel/api.py b/unbabel/api.py index 10cb6da..8bb36b9 100644 --- a/unbabel/api.py +++ b/unbabel/api.py @@ -109,7 +109,8 @@ def __init__( price_plan=None, balance=None, client=None, - order_number=None): + order_number=None, + brand=None): self.uid = uid self.text = text self.translation = translatedText @@ -125,6 +126,7 @@ def __init__( self.client = client self.balance = balance self.order_number = order_number + self.brand = brand def __repr__(self): return "%s %s %s_%s" % ( @@ -147,7 +149,8 @@ def __init__( topics=None, text_format='text', origin=None, - client=None): + client=None, + brand=None): self.uid = uid self.text = text self.translation = translatedText @@ -158,6 +161,7 @@ def __init__( self.text_format = text_format self.origin = origin self.client = client + self.brand = brand def __repr__(self): return "%s %s %s_%s" % ( @@ -240,7 +244,8 @@ def api_call(self, uri, data=None, internal_api_call=False): def post_translations(self, text, target_language, source_language=None, type=None, tone=None, visibility=None, public_url=None, callback_url=None, topics=None, instructions=None, uid=None, - text_format="text", target_text=None, origin=None, client_owner_email=None, context=None): + text_format="text", target_text=None, origin=None, client_owner_email=None, context=None, + brand=None): data = {k: v for k, v in locals().iteritems() if not v in (self, None)} if self.is_bulk: @@ -251,7 +256,7 @@ def post_translations(self, text, target_language, source_language=None, type=No def post_mt_translations(self, text, target_language, source_language=None, tone=None, callback_url=None, topics=None, instructions=None, uid=None, text_format="text", origin=None, - client_owner_email=None): + client_owner_email=None, brand=None): data = {k: v for k, v in locals().iteritems() if not v in (self, None)} result = requests.post("%smt_translation/" % self.api_url, @@ -291,6 +296,7 @@ def _build_translation_object(self, json_object): origin=json_object.get('origin', None), price_plan=json_object.get('price_plan', None), client=json_object.get('client', None), + brand=json_object.get('brand', None) ) return translation @@ -310,6 +316,7 @@ def _build_mt_translation_object(self, json_object): text_format=json_object.get('text_format', "text"), origin=json_object.get('origin', None), client=json_object.get('client', None), + brand=json_object.get('brand', None) ) return translation