Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: update microsoft provider api #63

Merged
merged 2 commits into from
Jan 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions translate/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
class InvalidProviderError(Exception):
pass

class TranslationError(Exception):
pass
3 changes: 2 additions & 1 deletion translate/providers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ class BaseProvider:
name = ''
base_url = ''

def __init__(self, to_lang, from_lang='en', secret_access_key=None, **kwargs):
def __init__(self, to_lang, from_lang='en', secret_access_key=None, region=None, **kwargs):
self.headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebit/535.19'
'(KHTML, like Gecko) Chrome/18.0.1025.168 Safari/535.19'}
self.from_lang = from_lang
self.to_lang = to_lang
self.secret_access_key = secret_access_key
self.region = region

@abstractmethod
def get_translation(self, params):
Expand Down
70 changes: 21 additions & 49 deletions translate/providers/microsoft.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,50 +3,12 @@
from datetime import timedelta
from datetime import datetime

from lxml import etree
import requests
import json

from .base import BaseProvider
from ..constants import TRANSLATION_FROM_DEFAULT


class AzureAuthClient:
"""
Provides a client for obtaining an OAuth token from the authentication service
for Microsoft Translator in Azure Cognitive Services.

PS:
token field is used to store the last token obtained from the token service
the cached token is re-used until the time specified in reuse_token_until.
"""
base_url = 'https://api.cognitive.microsoft.com/sts/v1.0/issueToken'

def __init__(self, client_secret):
self.client_secret = client_secret
self.token = None
self.reuse_token_until = None

def get_access_token(self):
'''
Returns an access token for the specified subscription.

This method uses a cache to limit the number of requests to the token service.
A fresh token can be re-used during its lifetime of 10 minutes. After a successful
request to the token service, this method caches the access token. Subsequent
invocations of the method return the cached token for the next 5 minutes. After
5 minutes, a new token is fetched from the token service and the cache is updated.
'''

if (self.token is None) or (datetime.utcnow() > self.reuse_token_until):
headers = {'Ocp-Apim-Subscription-Key': self.client_secret}
response = requests.post(self.base_url, headers=headers)
response.raise_for_status()

self.token = response.content
self.reuse_token_until = datetime.utcnow() + timedelta(minutes=5)

return self.token.decode('utf-8')

from ..exceptions import TranslationError

class MicrosoftProvider(BaseProvider):
'''
Expand All @@ -55,23 +17,33 @@ class MicrosoftProvider(BaseProvider):
Documentation: http://docs.microsofttranslator.com/text-translate.html
'''
name = 'Microsoft'
base_url = 'http://api.microsofttranslator.com/v2/Http.svc/Translate'
base_url = 'https://api.cognitive.microsofttranslator.com/translate'

def _make_request(self, text):
auth_client = AzureAuthClient(self.secret_access_key)
access_token = 'Bearer {}'.format(auth_client.get_access_token())
self.headers.update({"Authorization ": access_token})
self.headers.update({"Ocp-Apim-Subscription-Key": self.secret_access_key})
if self.region is not None:
self.headers.update({"Ocp-Apim-Subscription-Region": "westeurope"})

params = {
'to': self.to_lang,
'api-version': '3.0'
}

data = [{
'text': text
}]

params = {'text': text, 'to': self.to_lang}
if self.from_lang != TRANSLATION_FROM_DEFAULT:
params['from'] = self.from_lang

response = requests.get(self.base_url, params=params, headers=self.headers)
response = requests.post(self.base_url, params=params, headers=self.headers, json=data)

return response.text
return json.loads(response.text)

def get_translation(self, text):
data = self._make_request(text)

translation = etree.fromstring(data.encode('utf-8'))
return translation.text
if "error" in data:
raise TranslationError(data["error"]["message"])

return data[0]["translations"][0]["text"]
3 changes: 2 additions & 1 deletion translate/translate.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@


class Translator:
def __init__(self, to_lang, from_lang='en', provider=None, secret_access_key=None, **kwargs):
def __init__(self, to_lang, from_lang='en', provider=None, secret_access_key=None, region=None, **kwargs):
self.available_providers = list(PROVIDERS_CLASS.keys())
self.from_lang = from_lang
self.to_lang = to_lang
Expand All @@ -31,6 +31,7 @@ def __init__(self, to_lang, from_lang='en', provider=None, secret_access_key=Non
from_lang=from_lang,
to_lang=to_lang,
secret_access_key=secret_access_key,
region=region,
**kwargs
)

Expand Down