Skip to content
This repository has been archived by the owner on Mar 6, 2022. It is now read-only.

Supporting Python3 #18

Open
wants to merge 51 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
efad6aa
adapting unbabel py to new architecture
Jun 25, 2014
d0ae963
Merge branch 'master' of https://github.com/Unbabel/unbabel-py into n…
Jun 25, 2014
1e04a68
Added status 'insufficient_balance'.
Jun 25, 2014
2f3f6ef
increased version for new architecture
hugofvs Jul 2, 2014
a37ed78
Added missing resources and params.
Jul 4, 2014
d08031b
Added missing params.
Jul 4, 2014
129b938
Fixed failing tests.
Jul 4, 2014
8d86623
Merge branch 'new_architecture' of https://github.com/Unbabel/unbabel-py
gracaninja Jul 4, 2014
562977c
new updates to new architecture
gracaninja Jul 4, 2014
1c6b4f1
change field translation to translationText to match the output from …
gracaninja Jul 7, 2014
9d821f0
small fix on api
gracaninja Jul 7, 2014
1fc2d5a
small bug fix
gracaninja Jul 7, 2014
ab790c0
added target_text to unbabel-py
gracaninja Jul 8, 2014
53158e3
added origin keyword
gracaninja Jul 16, 2014
56ec95f
fixed broken argument ttype to type
gracaninja Aug 12, 2014
49c942d
get_user implemented using the internal api
samkempner Aug 22, 2014
ad29b43
inc version number
samkempner Aug 22, 2014
fc12d76
fixed link to documentation
arne-cl Sep 4, 2014
6a35bb7
changing to unbabel.com
samkempner Sep 15, 2014
0add1ef
incrementing version
samkempner Sep 15, 2014
d052132
www.unbabel.com -> unbabel.com
samkempner Sep 15, 2014
481bcfe
update get translation so that id does not blow up on error
gracaninja Oct 28, 2014
27d547d
added filter to get_translations
gracaninja Nov 5, 2014
b1df5d0
added simple xliff parser
gracaninja Feb 17, 2015
7f1be61
small fixes on xliff to remove languages from headers. Added bs4 to s…
gracaninja Feb 18, 2015
2283480
small hack on building dictionary
gracaninja Mar 31, 2015
ea88066
Merge pull request #2 from arne-cl/patch-1
gracaninja Apr 29, 2015
f839dfd
addec client_owner_email_param
gracaninja Apr 29, 2015
07baa14
Fixes the BeautifulSoup call.
davidgomes Jul 16, 2015
aa5ecbb
Merge pull request #4 from davidgomes/patch-1
hugofvs Jul 16, 2015
9e5ef65
Removed slash from package_dir
hugofvs Jan 12, 2016
747e4ff
Bumped version
hugofvs Jan 12, 2016
a14ad96
Merge pull request #5 from Unbabel/remove_slash
hugofvs Jan 12, 2016
4601c67
added endpoints for progressive translation
gracaninja May 10, 2016
dd5289d
Passing new argument on mt upgrade to overwrite some properties
hugofvs May 27, 2016
33d3372
Merge pull request #6 from Unbabel/feature_mt_endpoint
hugofvs Jun 7, 2016
36273ff
Bugfix raise error when not able to contact Unbabel
nurv Dec 19, 2016
95423fc
Merge pull request #8 from Unbabel/fix/emptyLanguageOnError
hugofvs Dec 19, 2016
d92c178
Bumped setup version
hugofvs Dec 19, 2016
5013cb1
fix #7
Jan 11, 2017
38b25dc
Merge pull request #10 from LLCampos/fix/missing_order_number_attrib
hugofvs Apr 24, 2017
09ec51f
Fix sandbox url
hugofvs Jun 9, 2017
3326f86
Bump version to 0.49
hugofvs Jun 9, 2017
8315c46
PEP8
hugofvs Jun 9, 2017
c875917
Update setup.py
hugofvs Jun 9, 2017
647cfc0
Undo changes to post_mt_translations method
hugofvs Mar 15, 2018
f3ffd18
Bump version to 0.50
hugofvs Mar 15, 2018
f0ead56
Add MIT License to repository
tomaspinho Oct 10, 2018
f03023b
Support Python3
alvations Oct 23, 2018
b88bb89
Cleans up spurious spaces
alvations Oct 23, 2018
50d7714
puts back the logging
alvations Oct 23, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2018 Unbabel

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
20 changes: 13 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Python SDK for the Unbabel REST API
Documentation:
=============

Please visit our documentation page at https://github.com/Unbabel
Please visit our documentation page at https://github.com/Unbabel/unbabel_api



Expand All @@ -23,13 +23,19 @@ Getting started:

## Request a Translation

`api.post_translations(text="This is a test translation",target_language="pt",source_language="en")`
```
api.post_translations(text="This is a test translation",target_language="pt",
source_language="en",
callback_url="http://my-awesome-service.com/unbabel_endpoint")
```

Check out the [API documentation](https://github.com/Unbabel/unbabel_api#translation) for additional options.

## Get a Translation

Returns a translation by its uid.

`t = api.get_translation(uid)`
`t = api.get_translation(uid)`



Expand All @@ -41,18 +47,18 @@ Returns all the translations for a given user.



## Getting Available Language Pairs
## Getting Available Language Pairs

`api.get_language_pairs()`

> [pt_en,
pt_fr,
...
...
it_en,
it_fr,
it_es]
Each element of the list is a **LanguagePair** object that contains a source language and a target language. Each language is an instance of the **Language** class that contains a shortname ( iso639-1 language code ) and a name.

Each element of the list is a **LanguagePair** object that contains a source language and a target language. Each language is an instance of the **Language** class that contains a shortname ( iso639-1 language code ) and a name.

## Getting Available Tones

Expand Down
3 changes: 3 additions & 0 deletions localhost.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
UNBABEL_TEST_USERNAME=gracaninja
UNBABEL_TEST_API_KEY=5a6406e31f77ef779c4024b1579f0f6103944c5e
UNBABEL_TEST_API_URL=http://0.0.0.0:8000/tapi/v2/
5 changes: 5 additions & 0 deletions release_to_pypy.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
http://peterdowns.com/posts/first-time-with-pypi.html

python setup.py register -r pypi

python setup.py sdist upload -r pypi
1 change: 1 addition & 0 deletions requirements.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
requests
beautifulsoup4
2 changes: 2 additions & 0 deletions runtests
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export $(cat .env)
python -m unittest discover -s 'tests/' -p '*test*.py'
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[metadata]
description-file = README.md
description-file = README.md
31 changes: 14 additions & 17 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
from setuptools import setup

setup(name='unbabel-py',
version='0.26',
version='0.50',
description='Python Wrapper around Unbabel HTTP API',
author='Joao Graca',
author_email='[email protected]',
packages=[
'unbabel',
],
package_dir={
'unbabel': 'unbabel/',
},
author_email='[email protected]',
packages=['unbabel'],
package_dir={'unbabel': 'unbabel',},
install_requires=[
'requests',
],
url = 'https://github.com/Unbabel/unbabel-py',
download_url = 'https://github.com/Unbabel/unbabel-py/tarball/0.1',
classifiers = ['Development Status :: 4 - Beta',
'Intended Audience :: Developers',
'Programming Language :: Python ',
'Topic :: Text Processing'
]
'requests',
'beautifulsoup4',
],
url='https://github.com/Unbabel/unbabel-py',
download_url='https://github.com/Unbabel/unbabel-py/archive/0.50.tar.gz',
classifiers=['Development Status :: 4 - Beta',
'Intended Audience :: Developers',
'Programming Language :: Python ',
'Topic :: Text Processing'
]
)
84 changes: 53 additions & 31 deletions tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,18 @@
from unbabel.api import (UnbabelApi, Order, LangPair, Tone, Topic,
Translation, Account, Job, BadRequestException)


UNBABEL_TEST_USERNAME = os.environ.get('UNBABEL_TEST_USERNAME')
UNBABEL_TEST_API_KEY = os.environ.get('UNBABEL_TEST_API_KEY')


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')

@property
def api(self):
if not hasattr(self, '_api'):
self._api = UnbabelApi(username=UNBABEL_TEST_USERNAME,
api_key=UNBABEL_TEST_API_KEY)

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
return self._api

def test_api_get_language_pairs(self):
Expand Down Expand Up @@ -68,11 +68,11 @@ def test_api_post_translation(self):
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')
'Source language is not en but %s'%translation.source_language)
self.assertEqual(translation.target_language, 'pt',
'Target language is not pt')
'Target language is not pt but %s'%translation.target_language)
self.assertEqual(translation.text, data['text'])
self.assertEqual(translation.status, 'new', 'status is not new')
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')
Expand All @@ -90,45 +90,40 @@ def test_api_post_translation(self):
'target language not equal')
self.assertEqual(translation.price, trans.price, 'price not equal')
self.assertEqual(translation.text, trans.text, 'text not equal')
self.assertEqual(translation.status, trans.status, 'status not equal')


def test_api_get_account(self):
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, UNBABEL_TEST_USERNAME,
self.assertEqual(account.username, self.UNBABEL_TEST_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)
translations = self.api.get_translations()
self.assertIsInstance(translations, list, 'Translations is not list')
if not len(translations):
data = {
'text': "This is a test translation",
'source_language': 'en',
'target_language': 'pt',
}
self.api.post_translations(**data)
translations = self.api.get_translations()
self.assertIsInstance(translations, list,
'Translations is not list')
self.assertTrue(
reduce(lambda x, y: x and y,
[isinstance(t, Translation) for t in translations]),
self.assertIsInstance(translations, list,
'Translations is not a list!')
self.assertTrue(len(translations) > 0,
'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.status, 'new', 'Order status is not new')
self.assertEqual(order.price, 0, 'Price is not 0')


def test_job_add_job_to_order(self):
order = self.api.post_order()

Expand All @@ -142,7 +137,6 @@ def test_job_add_job_to_order(self):
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.status, 'built', 'Job status is not built')
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')
Expand Down Expand Up @@ -185,9 +179,37 @@ def test_job_add_job_to_order_all_params(self):
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.status, 'built', 'Job status is not built')
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"
if hasattr(self, '_api'): delattr(self, '_api')

data = {
'text': "This is a test translation",
'source_language': 'en',
'target_language': 'pt',
'ttype': 'paid'
}

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)

translation = self.api.post_translations(**data)
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()
1 change: 1 addition & 0 deletions unbabel/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import unbabel.api

LOG_CONFIG = {
'version': 1,
Expand Down
102 changes: 102 additions & 0 deletions unbabel/abc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
"""Abstract base classes. Mainly Pythonic container objects from JSON."""

class NamedObject(object):
"""Abstract object that has a name and its name is the __repr__ and __str__."""
def __init__(self, name):
self.name
def __repr__(self):
return self.name
def __str__(self):
return self.name


class Language(NamedObject):
def __init__(self, shortname, name):
super(Language, self).__init__(name=name)
self.shortname = shortname


class Tone(NamedObject):
def __init__(self, description, name):
super(Language, self).__init__(name=name)
self.description = description


class Topic(NamedObject):
def __init__(self, name):
super(Language, self).__init__(name=name)


class LangPair(NamedObject):
def __init__(self, source_language, target_language):
name = "{}_{}".format(source_language, target_language)
super(Language, self).__init__(name=name)
self.source_language = source_language
self.target_language = target_language


class Translator(object):
def __init__(self, first_name="", last_name="",
picture_url="", profile_url=""):
self.first_name = first_name
self.last_name = last_name
self.picture_url = picture_url
self.profile_url = profile_url

@classmethod
def from_json(cls, json_object):
return Translator(json_object["first_name"], json_object["last_name"],
json_object["picture_url"], json_object["profile_url"])


class UnicodeReprObject:
"""Abstract object that suports unicode representation objects."""
def __init__(self):
pass
def __repr__(self):
return self._repr
def __str__(self):
return self._repr
def __unicode__(self):
return self._repr


class Account(UnicodeReprObject):
def __init__(self, username, email, balance):
self.username = username
self.email = email
self.balance = balance
# For __unicode__
self._repr = u'email: {email}, balance: {balance}'.format(
email=self.email, balance=self.balance)


class Job(UnicodeReprObject):
def __init__(self, id, uid, order_id, status, source_language,
target_language,
text, price, tone, text_format):
self.id = id
self.uid = uid
self.order_id = order_id
self.status = status
self.text = text
self.price = price
self.source_language = source_language
self.target_language = target_language
self.tone = tone
self.text_format = text_format
# For __unicode__
self._repr = u'order_id: {}, id: {}, status: {}'.format(self.order_id, self.id, self.status)


class Order(UnicodeReprObject):
def __init__(self, id, status, price):
self.id = id
self.status = status
self.price = price
# For __unicode__
self._repr = u'{id} - {status} - {price}'.format(id=self.id, status=self.status, price=self.price)


__all__ = ['Language', 'Tone', 'Topic', 'LangPair',
'Translator', 'Account', 'Job', 'Order']
Loading