soaplib2.0.0beta + django and 1C connect error - django

I have task get up soap service in Django (for receive data from commerce software)
Have been installed soaplib2.0.0beta and made layer from soap to django (use Django Snippets)
Created some soap-methods and data types. Everything works with suds (lib) test, but receive errors in production.
Erorrs says some column is not unique, but data is okey and method can connect to db (.all().count() test).
I think mistake in layer or nginx's config...
Code of Layer:
# Code of Layer:
class DjangoSoapApp(Application):
def __call__(self, request):
# wrap the soaplib response into a Django response object
django_response = HttpResponse()
def start_response(status, headers):
status, reason = status.split(' ', 1)
django_response.status_code = int(status)
for header, value in headers:
django_response[header] = value
response = super(DjangoSoapApp, self).__call__(request.META, start_response)
django_response.content = '\n'.join(response)
return django_response
Method's code:
# Method's code
class SyncService(DefinitionBase):
#rpc(User, Order, _returns=Array(Response))
def CreateOrder(self, user=None, order=None):
response = []
# response.append(Response(Result = True, Response = "ORDERS: " + str(self.tmp.count())))
# return response
if not user or not order:
response.append(Response(Result = False, Response = "Exception: not send user or order"))
return response
try:
new_user = user_model.objects.get(commerce_uid=user.Id)
response.append(Response(Result = True, Response="Success: Get user %s %s" % (user.Name, user.EMail)))
except Exception as e:
try:
new_user = user_model(
email=user.EMail,
commerce_uid=user.Id,
telephone=user.Phone,
name=user.Name,
username=re.sub(r'\.|\#', '', user.EMail),
isSync = True)
new_user.save()
response.append(Response(Result = True,Response = "Success: Create user %s %s" % (user.Name, user.EMail)))
except Exception as e:
response.append(Response(Result = False, Response = "Exception: user '%s' not found and can't create (%s)" % (user, e)))
return response
try:
new_order = order_model(
user=new_user,
date=order.Date,
time=order.Time,
boat=order.Boat,
amount=order.Quantity,
isSync=True
)
new_order.save()
response.append(Response(Result = True, Response = "Success: Create order %s" % (order)))
except Exception as e:
response.append(Response(Result = False, Response = "Exception: Can't create order '%s' for user '%s' (%s)" % (order, user, e)))
return response
return response
Sample of error:
Exception: user 'Id: 6d73d109-4b7b-453e-819a-94c42a883c09, Name: John Smith 2, Email: email2#email.com, Phone: +749512345679' not found and can't create (column commerce_uid is not unique)

Related

id parameter in get request

I am new to Django and a small detail has been bothering me.I have an api endpoint that returns the details of one patient. I have made a successful get request and tested on postman. It returns data for a particular patient with id = 996(I have hard coded the id). But I need to set it so it can pick the id from params in postman instead of the hard coded one here. How can I set params and append them on the url so that I use the id fed in postman instead of hard coding? Kindly assist
views.py
class PatientDetailsView(GenericAPIView):
authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated]
#classmethod
#encryption_check
def get(self, request, *args, **kwargs):
try:
result = {}
auth = cc_authenticate()
res = getPatientDetails(auth["key"], id)
result = res
return Response(result, status=status.HTTP_200_OK)
except Exception as e:
error = getattr(e, "message", repr(e))
result["errors"] = error
result["status"] = "error"
return Response(result, status=status.HTTP_400_BAD_REQUEST)
api_service.py
def getPatientDetails(auth, id):
print("getting patientdetails from Callcenter")
try:
print(auth)
# print(url)
id= 996
headers = {
"Authorization": f'Token {auth}'
}
url = f'{CC_URL}/patients/v1/details/?id={id}'
print(url)
res = requests.get(url, headers=headers)
print("returning patientdetails response", res.status_code)
return res.json()
except ConnectionError as err:
print("connection exception occurred")
print(err)
return err
urls.py
path("details/", views.PatientDetailsView.as_view(), name="patient_info"),
This is the code I needed
id = request.GET.get('<id>')

Authorization VK API error: u'{"error":"invalid_request","error_description":"Security Error"}'

I'm trying to authorize from my djano-app on vk.com. I'm using requests and client authorization. I'm trying to authorize by this way and getting an error:
{"error":"invalid_request","error_description":"Security Error"}
Internet suggests to re-login on VK in browser, but there isn't any solution for authorization from code.
My code:
class VkApiSingleton(object):
api_version = '5.95'
def __init__(self,
app_id=config.APP_ID,
login=config.ACCOUNT_LOGIN,
pswd=config.ACCOUNT_PASSWORD,
permissions='video,offline,groups'
):
# type: (int, str, str, str) -> None
self.app_id = app_id
self.app_user_login = login
self.app_user_pass = pswd
self.access_token = None
self.user_id = None
self.session = requests.Session()
self.form_parser = FormParser()
self.permissions = permissions
def __new__(cls, *args, **kwargs):
if not hasattr(cls, 'instance'):
cls.instance = super(VkApiSingleton, cls).__new__(cls, *args, **kwargs)
return cls.instance
#property
def get_session(self):
return self.session
def _parse_form(self, response):
# type: (requests.models.Response) -> None
self.form_parser = FormParser()
try:
self.form_parser.feed(str(response.content))
except Exception as err:
logger.exception(
'Error checking HTML form',
extra={'Error body': str(err)}
)
def _submit_form(self, **kwargs):
# type: (dict) -> requests.models.Response
if self.form_parser.method == 'post':
payload = copy.deepcopy(self.form_parser.params)
if kwargs.get('is_login', False):
payload.update({
'email': self.app_user_login,
'pass': self.app_user_pass
})
with self.get_session as session:
try:
return session.post(self.form_parser.url, data=payload)
except Exception as err:
logger.exception(
'Error submitting auth form',
extra={'Error body': str(err)}
)
raise VkApiError('Error submitting auth form: %s' % str(err))
def _log_in(self):
# type: () -> requests.models.Response
response = self._submit_form(is_login=True)
self._parse_form(response)
if response.status_code != 200:
raise VkApiError('Auth error: cant parse HTML form')
if 'pass' in response.text:
logger.error(
'Wrong login or password'
)
raise VkApiError('Wrong login or password')
return response
def _submit_permissions(self, url=None):
# type: () -> requests.models.Response
if 'submit_allow_access' in self.form_parser.params and 'grant_access' in self.form_parser.url:
return self._submit_form(token_url=url)
else:
logger.warning(
'Cant submit permissions for application'
)
def _get_token(self, response):
# type: (requests.models.Response) -> None
try:
params = response.url.split('#')[1].split('&')
self.access_token = params[0].split('=')[1]
self.user_id = params[2].split('=')[1]
except IndexError as err:
logger.error(
'Cant get access_token',
extra={'Error body': str(err)}
)
def auth(self):
auth_url = 'https://oauth.vk.com/authorize?revoke=1'
redirect_uri = 'https://oauth.vk.com/blank.html'
display = 'wap'
request_params = {
'client_id': self.app_id,
'scope': self.permissions,
'redirect_uri': redirect_uri,
'display': display,
'response_type': 'token',
'v': self.api_version
}
with self.get_session as session:
response = session.get(
auth_url,
params=request_params
)
self._parse_form(response)
if not self.form_parser.form_parsed:
raise VkApiError('Invalid HTML form. Check auth_url or params')
else:
login_response = self._log_in()
permissions_response = self._submit_permissions()
self._get_token(login_response)
If someone has a similar problem - I found some reasons of this.
1) Invalid type of authorization - try to use another type of authorization (it describes in official documentation)
2) Too many authorizations.
I solved problem like this:
1) Get token with "offline" permission by "Client Application Authorization"
2) Every time I need to use vk.api method - I am checking my token for expiring with secure method "secure.checkToken" (you need to get Service token to use this method. There are a lot of information in official documentation)
3) If my token expires - i am getting the new one.

TypeError: 'NoneType' object is not subscriptable in Django unittests for message

Am trying to do a unit test for a view that returns a message when some input is duplicated in the database.it gives me the error TypeError: 'NoneType' object is not subscriptable
Here is the view
#login_required
def worker_create(request):
worker_create_form = WorkerCreateForm(request.POST)
if request.method == 'POST':
if worker_create_form.is_valid():
form = worker_create_form.save(commit=False)
phone = form.phone
check_phone = Worker.objects.filter(phone=phone)
if check_phone.count() != 0:
messages.error(request, 'رقم الهاتف مستخدم من قبل')
else:
form.save()
return redirect('worker_list')
else:
worker_create_form = WorkerCreateForm(request.POST)
context = {
'worker_create_form': worker_create_form,
}
return render(request, 'erp_system/worker/create.html', context)
and here are the tests I've created for it
class WorkerCreateTest(TestCase):
def setUp(self):
User.objects.create_user(username='test_user', email='test#gmail.com', password='test_password')
branch = Branch.objects.create(name='test branch')
Worker.objects.create(name="ay btngan ", phone='01207199086', branch=branch)
def test_get_request_unauthenticated(self):
response = self.client.get(reverse('worker_create'))
url = reverse('worker_create')
self.assertRedirects(response, '/login/?next=' + url)
def test_get_request_authenticated(self):
self.client.login(username='test_user', password='test_password')
response = self.client.get(reverse('worker_create'))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed('erp_system/worker/create.html')
def test_post_request_empty_data(self):
self.client.login(username='test_user', password='test_password')
response = self.client.post(reverse('worker_create'), {})
self.assertFormError(response, 'worker_create_form', 'name', 'This field is required.')
self.assertFormError(response, 'worker_create_form', 'phone', 'This field is required.')
self.assertFormError(response, 'worker_create_form', 'branch', 'This field is required.')
def test_post_request_invalid_data(self):
self.client.login(username='test_user', password='test_password')
branch = Branch.objects.create(name='test again ')
name = 'just a name'
for i in range(300):
name += 'h'
response = self.client.post(reverse('worker_create'),
{'name': name, 'phone': '01207199086', 'branch': branch.id})
self.assertEqual(response.status_code, 200)
def test_post_request_duplicated_phone(self):
self.client.login(username='test_user', password='test_password')
branch = Branch.objects.create(name='test again ')
response = self.client.post(reverse('worker_create'),
{'name': 'test worker', 'phone': '01207199086', 'branch': branch.id})
print(response)
messages = list(response.context['messages'])
self.assertEqual(len(messages), 1)
self.assertEqual(str(messages[0]), 'رقم الهاتف مستخدم من قبل')
def test_post_request_valid_data(self):
self.client.login(username='test_user', password='test_password')
branch = Branch.objects.create(name='test branch1234')
name = 'new valid name'
response = self.client.post(reverse('worker_create'),
{'name': name, 'branch': branch.id, 'phone': '0151951115'})
self.assertEqual(response.status_code, 302)
Important
I noticed when I added print(response) that it gives me HttpResponseRedirect not just HttpResponse what means there is no context given. Why it using redirect in here!?
In your test test_post_request_duplicated_phone, you make a POST request to the worker_create, and you expect to retrieve an error, because there exists already a record for the given phone.
The documentation on tests [Django-doc] however mentions that:
A TestCase, on the other hand, does not truncate tables after a test. Instead, it encloses the test code in a database transaction that is rolled back at the end of the test. This guarantees that the rollback at the end of the test restores the database to its initial state.
So that means that, unless you implement some "tricks" to prevent this, the side-effects that one test has (on the database) will be gone when you enter a second test. This makes sense, since reordering the tests should not result in a different outcome.
You can however create such Worker object in your test in advance, and thus make sure that the test will indeed error:
def test_post_request_duplicated_phone(self):
self.client.login(username='test_user', password='test_password')
branch = Branch.objects.create(name='test again ')
Worker.objects.create(name=" just a name ", phone='01207199086', branch=branch)
response = self.client.post(reverse('worker_create'),
{'name': 'test worker', 'phone': '01207199086', 'branch': branch.id})
print(response)
messages = list(response.context['messages'])
self.assertEqual(len(messages), 1)
self.assertEqual(str(messages[0]), 'رقم الهاتف مستخدم من قبل')

Creating a Superset user programmatically

How to go about creating users programmatically in Superset with a defined role?
Say I have an email sign in page. User signs up. After sign up I would like to programmatically create the user with the gamma role into a Superset instance.
I've used a reply from superset git and created the following classes to add users with roles.
You need to have a json file with the users info and the name of the role(s) that you want to apply. Like this:
[
{
"first_name": "a",
"last_name": "b",
"username": "abc",
"email": "abc#def.com",
"password": "123",
"roles": ["generalViewer","databaseXView"]
},
{
"first_name": "b",
"last_name": "c",
"username": "bcd",
"email": "bcd#def.com",
"password": "123",
"roles": ["generalViewer","databaseXView"]
}
]
Because we are using the role name (we can get them from the superset through normal navigation) is needed to setup the database credentials to get the role_id. Also need to setup the login of any user with permissions to create another one.
import requests
import json
from bs4 import BeautifulSoup as bs
from bs4 import Comment
from time import sleep
import psycopg2
from typing import List, Tuple
import pandas as pd
class SupersetApi:
def __init__(self, username=None, password=None):
self.s = requests.session()
self.base_url = "http://123.45.67.890:8088/" #superset server ip
self._csrf = self._getCSRF(self.url('login/'))
self.headers = {'X-CSRFToken': self._csrf, 'Referer': self.url('login/')}
# note: does not use headers because of flask_wtf.csrf.validate_csrf
# if data is dict it is used as form and ends up empty but flask_wtf checks if data ...
payload = {'username': username, 'password': password, 'csrf_token': self._csrf}
self.post('login/', payload, None)
#self.s.post(self.url(), data=payload, headers = {})
def url(self, url_path):
return self.base_url + url_path
def get(self, url_path):
return self.s.get(self.url(url_path), headers=self.headers)
def post(self, url_path, data=None, json_data=None, **kwargs):
kwargs.update({'url': self.url(url_path), 'headers': self.headers})
if data:
data['csrf_token'] = self._csrf
kwargs['data'] = data
if json_data:
kwargs['json'] = json_data
try:
response = self.s.post(**kwargs)
statusCode = response.status_code
if statusCode < 399:
return True, statusCode
else:
print('POST response: {}'.format(statusCode))
return False, statusCode
except Exception as e:
print(e)
return False, e
def _getCSRF(self, url_path):
try:
response = self.s.get(url_path)
response.raise_for_status()
except Exception as e:
print(e)
exit()
soup = bs(response.content, "html.parser")
for tag in soup.find_all('input', id='csrf_token'):
csrf_token = tag['value']
return csrf_token
class PostgresDB:
def __init__(self, db_name: str, db_user: str, db_host: str, db_password: str) -> None:
self.db_name = db_name
self.db_user = db_user
self.db_host = db_host
self.db_password = db_password
self.conn = None
self.cur = None
def connect(self) -> None:
try:
self.conn = psycopg2.connect('dbname={} user={} host={} password={}'.format(
self.db_name, self.db_user, self.db_host, self.db_password))
self.cur = self.conn.cursor()
except Exception as e:
raise Exception('Couldn\'t connect to the database. Error: {}'.format(e))
def commit(self) -> None:
if self.conn is not None:
self.conn.commit()
else:
raise Exception('Connection not opened to commit')
def close_connection(self) -> None:
if self.cur is not None or self.conn is not None:
try:
self.cur.close()
except:
pass
try:
self.conn.close()
except:
pass
else:
print('Connection and Cursor not opened to be closed')
def get_from_ab_role(self, columns: List, filters: str) -> List:
roles_table = 'public.ab_role'
sql_columns = ','.join(columns)
sql = "SELECT {} FROM {} WHERE {}".format(sql_columns, roles_table, filters)
self.cur.execute(sql)
return self.cur.fetchall()
class SupersetUser:
def __init__(self, user_dict: dict, db: 'PostgresDB'):
self.first_name = user_dict.get('first_name')
self.last_name = user_dict.get('last_name')
self.username = user_dict.get('username')
self.email = user_dict.get('email')
self.active = True
self.password = user_dict.get('password')
self.roles = self.get_role_id(db, user_dict.get('roles'))
def get_role_id(self, db: 'PostgresDB', roles: List):
filter = 'name = '
filter = filter + "'{}' ".format(roles[0])
if len(roles) > 1:
for role in roles[1:]:
filter = filter + "OR name = '{}' ".format(role)
ids = []
for id in db.get_from_ab_role(['id'], filter):
ids.append(str(id[0]))
return ids
def create_user(self, superset_api: SupersetApi) -> Tuple:
Error_friendly_message = None
Error_not = True
url_path = 'users/api/create'
payload = {'first_name': self.first_name,
'last_name': self.last_name,
'username': self.username,
'email': self.email,
'active': self.active,
'conf_password': self.password,
'password': self.password,
'roles': self.roles
}
Error_not, http_response_code = superset_api.post(url_path=url_path, json=payload)
if Error_not:
print('User {} created. Corresponding e-mail: {}'.format(self.username, self.email))
return Error_not, Error_friendly_message, http_response_code
elif http_response_code == 500:
Error_not = False
Error_friendly_message = ('Ops! Something went wrong. Probably already exist an '
'user with the same e-mail: {}, or an error with the json variables... '
'All of them must be strings or a list of strings'.format(self.email))
return Error_not, Error_friendly_message, http_response_code
else:
Error_not = False
Error_friendly_message = 'Ops! Something went wrong. Try again.'
return Error_not, Error_friendly_message, http_response_code
#file that contains the users to be created
FILE_NAME = 'users.json'
#need credentials from user with admin role to create new user
ADMIN_USR = 'admin'
ADMIN_PSWD = 'adminpassword'
DB_NAME = 'superset_database'
DB_USER = 'superset_user'
DB_HOST = '123.45.67.890'
DB_PSWD = 'superset_password'
superset = SupersetApi(ADMIN_USR, ADMIN_PSWD)
portgre_db = PostgresDB(DB_NAME, DB_USER, DB_HOST, DB_PSWD)
portgre_db.connect()
try:
with open(FILE_NAME, 'r') as f:
users = json.load(f)
print('File successfully read')
except FileNotFoundError as e:
print(e)
for index, user in enumerate(users):
userRoles = []
superset_user = SupersetUser(user, portgre_db)
Error_not, Error_friendly_message, http_response_code = superset_user.create_user(superset)
if not Error_not:
print('Could\'t create user {}.'.format(superset_user.username))
print(Error_friendly_message)
print('HTTP Response Code: {}'.format(http_response_code))
portgre_db.close_connection()
If you're set on creating users programmatically, then your best bet is probably to look into overriding the SecurityManager of the underlying Flask-App-Builder (F.A.B.) framework - which Superset is based off.
The documentation can be found here: https://github.com/dpgaspar/Flask-AppBuilder/blob/master/docs/security.rst#your-custom-security
That being said - it feels your question is really about how to allow users to self-register in Superset and give them the Gamma role by default.
This is a use-case FAB addresses explicitly, and you should be able to achieve this just through configuration: http://flask-appbuilder.readthedocs.io/en/latest/user_registration.html

Vimeo 'Replace' API Endpoint Not Changing Thumbnail

I am using Vimeo's API for the users of my app to upload videos, or replace their existing video with a new one. I am using a Vimeo Client to help me make the calls in my Django Application. Uploading works without any issues, but when I try to replace an existing video with a new one, the thumbnail stays as the old video. If you play the video, it will play the new one, but the thumbnail never changes.
Model Method that Uploads/Replaces
def vimeo_upload(self):
media_file = self.video_file
if media_file and os.path.exists(media_file.path):
v = vimeo.VimeoClient(token=settings.VIMEO_ACCESS_TOKEN, key=settings.VIMEO_API_KEY,
secret=settings.VIMEO_API_SECRET)
if self.video_url is None:
try:
video_uri = v.upload(media_file.path)
except AssertionError as exc:
logging.error('Vimeo Error: %s Video: %s' % (exc, media_file.path))
else:
self.video_url = video_uri
else:
try:
v.replace(video_uri=self.video_url, filename=media_file.path)
except Exception as exc:
self.video_url = None
logging.error('Vimeo Replace Error: %s Video: %s' % (exc, media_file.path))
# set the video title, description, etc.
if self.video_url:
try:
# convert locale from en-us form to en
v.patch(self.video_url, data={'description': self.customer.full_name, })
except Exception as exc:
logging.error('Vimeo Patch Error: %s Video: %s' % (exc, media_file.path))
Vimeo Client Model, and UploadVideoMixin
class UploadVideoMixin(object):
"""Handle uploading a new video to the Vimeo API."""
UPLOAD_ENDPOINT = '/me/videos'
REPLACE_ENDPOINT = '{video_uri}/files'
def upload(self, filename, upgrade_to_1080=False):
"""Upload the named file to Vimeo."""
ticket = self.post(
self.UPLOAD_ENDPOINT,
data={'type': 'streaming',
'upgrade_to_1080': 'true' if upgrade_to_1080 else 'false'},
params={'fields': 'upload_link,complete_uri'})
return self._perform_upload(filename, ticket)
def replace(self, video_uri, filename, upgrade_to_1080=False):
"""Replace the video at the given uri with the named source file."""
uri = self.REPLACE_ENDPOINT.format(video_uri=video_uri)
ticket = self.put(
uri,
data={'type': 'streaming',
'upgrade_to_1080': 'true' if upgrade_to_1080 else 'false'},
params={'fields': 'upload_link,complete_uri'})
return self._perform_upload(filename, ticket)
def _perform_upload(self, filename, ticket):
"""Take an upload ticket and perform the actual upload."""
if ticket.status_code != 201:
raise UploadTicketCreationFailure(ticket, "Failed to create an upload ticket")
ticket = ticket.json()
# Perform the actual upload.
target = ticket['upload_link']
last_byte = 0
# Try to get size of obj by path. If provided obj is not a file path
# find the size of file-like object.
try:
size = os.path.getsize(filename)
with io.open(filename, 'rb') as f:
while last_byte < size:
try:
self._make_pass(target, f, size, last_byte)
except requests.exceptions.Timeout:
# If there is a timeout here, we are okay with it, since
# we'll check and resume.
pass
last_byte = self._get_progress(target, size)
except TypeError:
size = len(filename.read())
f = filename
while last_byte < size:
try:
self._make_pass(target, f, size, last_byte)
except requests.exceptions.Timeout:
# If there is a timeout here, we are okay with it, since
# we'll check and resume.
pass
last_byte = self._get_progress(target, size)
# Perform the finalization and get the location.
finalized_resp = self.delete(ticket['complete_uri'])
if finalized_resp.status_code != 201:
raise VideoCreationFailure(finalized_resp, "Failed to create the video")
return finalized_resp.headers.get('Location', None)
def _get_progress(self, upload_target, filesize):
"""Test the completeness of the upload."""
progress_response = self.put(
upload_target,
headers={'Content-Range': 'bytes */*'})
range_recv = progress_response.headers.get('Range', None)
_, last_byte = range_recv.split('-')
return int(last_byte)
def _make_pass(self, upload_target, f, size, last_byte):
"""Make a pass at uploading.
This particular function may do many things. If this is a large upload
it may terminate without having completed the upload. This can also
occur if there are network issues or any other interruptions. These
can be recovered from by checking with the server to see how much it
has and resuming the connection.
"""
response = self.put(
upload_target,
timeout=None,
headers={
'Content-Length': str(size),
'Content-Range': 'bytes: %d-%d/%d' % (last_byte, size, size)
}, data=f)
if response.status_code != 200:
raise VideoUploadFailure(response, "Unexpected status code on upload")
class VimeoClient(ClientCredentialsMixin, AuthorizationCodeMixin, UploadMixin):
"""Client handle for the Vimeo API."""
API_ROOT = "https://api.vimeo.com"
HTTP_METHODS = set(('head', 'get', 'post', 'put', 'patch', 'options', 'delete'))
ACCEPT_HEADER = "application/vnd.vimeo.*;version=3.2"
USER_AGENT = "pyvimeo 0.3.10; (http://developer.vimeo.com/api/docs)"
def __init__(self, token=None, key=None, secret=None, *args, **kwargs):
"""Prep the handle with the authentication information."""
self.token = token
self.app_info = (key, secret)
self._requests_methods = dict()
# Make sure we have enough info to be useful.
assert token is not None or (key is not None and secret is not None)
# Internally we back this with an auth mechanism for Requests.
#property
def token(self):
return self._token.token
#token.setter
def token(self, value):
self._token = _BearerToken(value) if value else None
def __getattr__(self, name):
"""This is where we get the function for the verb that was just
requested.
From here we can apply the authentication information we have.
"""
if name not in self.HTTP_METHODS:
raise AttributeError("%r is not an HTTP method" % name)
# Get the Requests based function to use to preserve their defaults.
request_func = getattr(requests, name, None)
if request_func is None:
raise AttributeError(
"%r could not be found in the backing lib" % name
)
#wraps(request_func)
def caller(url, jsonify=True, **kwargs):
"""Hand off the call to Requests."""
headers = kwargs.get('headers', dict())
headers['Accept'] = self.ACCEPT_HEADER
headers['User-Agent'] = self.USER_AGENT
if jsonify \
and 'data' in kwargs \
and isinstance(kwargs['data'], (dict, list)):
kwargs['data'] = json.dumps(kwargs['data'])
headers['Content-Type'] = 'application/json'
kwargs['timeout'] = kwargs.get('timeout', (1, 30))
kwargs['auth'] = kwargs.get('auth', self._token)
kwargs['headers'] = headers
if not url[:4] == "http":
url = self.API_ROOT + url
response = request_func(url, **kwargs)
if response.status_code == 429:
raise APIRateLimitExceededFailure(
response, 'Too many API requests'
)
return response
return caller
class _BearerToken(requests.auth.AuthBase):
"""Model the bearer token and apply it to the request."""
def __init__(self, token):
self.token = token
def __call__(self, request):
request.headers['Authorization'] = 'Bearer ' + self.token
return request