python api common response format - python

I have a dictionary which I used to return my response in an API.
It is formatted as this:
response_data = {
'url': '',
'status': '',
'data': ''
}
when I update it inside my function I have to declare it in every function then update a data individually like:
response_data ['url'] = url
response_data ['status'] = status
response_data ['data'] = data
then return it as:
return response_data
Is there a way to not initiate it in every function I made, like a class or function which I can just easily pass the data or edit the data to be passed.
Have tried this, but you have to manually edit the data like what I was doing.
class Response:
response_data = {
'url': '',
'status': '',
'data': ''
}
def set_message(self, key, value):
try:
self.response_data[key] = value
except Exception as e:
raise Exception(e)
response = Response()
response.set_message('success', success)

Related

How to create reports with Python SDK Api

I am trying to create reports with Python on dailymotion but I have error,According to my received error, renponse is empty. I don't get it. I guess, My user coudln't login to dailymotion. Please check error.
{'data': {'askPartnerReportFile': None}, 'errors': [{'message': 'Not authorized to access `askPartnerReportFile` field.', 'path': ['askPartnerReportFile'], 'locations': [{'line': 3, 'column': 9}], **'type': 'not_authorized**'}]}
Traceback (most recent call last):
File "get_reports.py", line 143, in <module>
product='CONTENT',
File "get_reports.py", line 65, in create_report_request
return response.json()['data']['askPartnerReportFile']['reportFile']['reportToken'];
TypeError: 'NoneType' object is not subscriptable
Here is my code;
`
def get_access_token(app_key, app_secret, username, password):
'''
Authenticate on the API in order to get an access token
'''
response = requests.post('https://graphql.api.dailymotion.com/oauth/token', data={
'client_id': app_key,
'client_secret': app_secret,
'username': username,
'password': password,
'grant_type': 'password',
'version': '2'
})
if response.status_code != 200 or not 'access_token' in response.json():
raise Exception('Invalid authentication response')
return response.json()['access_token']
def create_report_request(access_token, dimensions, metrics, start_date, end_date, product, filters = None):
'''
Creating a report request
'''
reportRequest = """
mutation ($input: AskPartnerReportFileInput!) {
askPartnerReportFile(input: $input) {
reportFile {
reportToken
}
}
}
"""
response = requests.post(
'https://graphql.api.dailymotion.com',
json={
'query': reportRequest,
'variables': {
'input': {
'metrics': metrics,
'dimensions': dimensions,
'filters': filters,
'startDate': start_date,
'endDate': end_date,
'product': product,
}
}
},
headers={'Authorization': 'Bearer ' + access_token}
)
print(response.status_code)
if response.status_code != 200 or not 'data' in response.json():
raise Exception('Invalid response')
print(response.json())
return response.json()['data']['askPartnerReportFile']['reportFile']['reportToken'];
def check_report_status(access_token, report_token):
'''
Checking the status of the reporting request
'''
report_request_status_check = """
query PartnerGetReportFile ($reportToken: String!) {
partner {
reportFile(reportToken: $reportToken) {
status
downloadLinks {
edges {
node {
link
}
}
}
}
}
}
"""
response = requests.post(
'https://graphql.api.dailymotion.com',
json={
'query': report_request_status_check,
'variables': {
'reportToken': report_token
}
},
headers={'Authorization': 'Bearer ' + access_token}
)
if response.status_code != 200 or not 'data' in response.json():
raise Exception('Invalid response')
status = response.json()['data']['partner']['reportFile']['status'];
if (status == 'FINISHED'):
download_links = []
for url in map(lambda edge: edge['node']['link'], response.json()['data']['partner']['reportFile']['downloadLinks']['edges']):
download_links.append(url)
return download_links
else:
return None
def download_report(download_links, base_path=None):
'''
Downloading the report files
'''
cpt = 1
if not base_path:
base_path = os.getcwd()
for url in download_links:
r = requests.get(url)
filename = 'report_{}.csv'.format(cpt)
file_path = os.path.join(base_path, filename)
open(file_path, 'wb').write(r.content)
print('Report file {} downloaded: {}'.format(cpt, file_path))
cpt += 1
print('Generating access token...')
access_token = get_access_token(
app_key='******',
app_secret='*******',
username='*****',
password='*****'
)
print('Creating report request...')
report_token = create_report_request(
access_token=access_token,
dimensions=('DAY', 'VIDEO_TITLE'),
metrics=('VIEWS'),
filters={'videoOwnerChannelSlug': 'B******'},
start_date='2022-11-23',
end_date='2022-11-24',
product='CONTENT',
)
download_links = None
while not download_links:
print('Checking report status...')
# Checks every 15secs the report status
time.sleep(15)
download_links = check_report_status(
access_token=access_token,
report_token=report_token
)
download_report(download_links=download_links)
`
I tried to get data dailymotion api.
Thanks
This feature requires a specific API access, which is missing on your API Key, that's why you get the message Not authorized to access askPartnerReportFile field.
As it's a feature restricted to verified-partners, you should reach out to your content manager to ask him this kind of access, or you can try to contact our support

Call GraphQL API with String variable

I want to execute a simple GraphQL query in which I pass a variable.
import requests
import json
var = "whatever"
query = """
query ($var: String!){
styles(locale: "en", styleNumbers: [ $var] ) {
styleOptions {
parms {
parm1
parm2
}
}
}
}
"""
url = 'https://sth_random.io/graphql?'
response = requests.get(url, json={'query': query, '$var': var})
response = response.json()
print(response)
but I am getting the following error:
{'errors': [{'message': 'Variable "$var" of required type "String!" was not provided.', 'locations': [{'line': 2, 'column': 12}]}]}
What am I missing?
Thank you in advance.
The request body should include a variables key that is itself a dictionary of the variable values:
variables = {'var': var}
response = requests.post(url, json={'query': query, 'variables': variables})

get_or_create() creating a new object everytime I run the test case

I am testing my api and everytime am running the test case using python manage.py test api.users.tests --keepdb it is creating a new Language object everytime, instead it should fetch the existing Language object itself as I am not destroying the database.
class ProfileTest(TestCase):
#classmethod
#override_settings(DEBUG=True)
def setUpTestData(cls):
instance, is_created = Language.objects.get_or_create(value='English', locale='en')
url = '/api/v1/auth/login/'
data = {'mobile_number': '9899137678', 'country_code': '91', 'device_id': '123'}
response = Client().post(path=url, data=data)
json_response = response.json()
url = '/api/v1/auth/verify/'
data = {'code': json_response['otp'],
'verification_id': json_response['verification_id'],
'language': instance.id,
'registration_id': '123',
'type': '1',
'device_id': json_response['device_id']}
response = Client().post(path=url, data=data)
json_response = response.json()
token = json_response['token']['access']
token = 'Token ' + token
cls.headers = {
'HTTP_AUTHORIZATION': token,
}
def test_get_user_profile(self):
url = '/api/v1/users/profile/'
response = self.client.get(path=url, **self.headers)
print('\n', response.content, '\n')
self.assertEquals(response.status_code, status.HTTP_200_OK, 'Couldn\'t fetch profile data.')

Getting Call Status with Sinch API

After placing a call with Sinch API using a 'ttsCallout' method, I'm trying to get the status for that call. The calls goes through, I'm receiving its 'callId'. But when it comes to requesting my call's status, I receive 200 OK as a HTTP Response and empty ('null') content.
First, I though something is wrong with my code and the way I form Authorization headers (I use Python, its requests library and basic auth), but then I tried Sinch API explorer (https://www.sinch.com/dashboard/#/api) and it shows the same output to me (see the attached screenshot). Have to notice that this code worked about a month ago, and I was able to get call status.
Also, here is the code I use to communicate to Sinch API.
class CallNotification(Notification):
def __init__(self, data):
self.id = ""
self.call = self.data['call']
self.api_url = self.call['api_url']
self.auth = ("application:" + self.call['auth']['key'], self.call['auth']['secret'])
self.status = {'http': "new", 'result': "none", 'reason': "none"}
def send(self):
request_url = self.api_url + "/callouts"
request = requests.post(request_url,
auth=self.auth,
json={
'method': "ttsCallout",
'ttsCallout': {
'cli': "private",
'destination': {
'type': "number",
'endpoint': self.call['to']
},
'domain': "pstn",
'custom': "customData",
'locale': "en-US",
'text': self.call['message']
}
},
headers={'content-type': 'application/json'})
self.id = json.loads(request.content)['callId']
self.status['http'] = request.reason
return self.status['http']
def getstatus(self):
if not self.status['http'] == "new":
request_url = self.api_url + "/calls/id/" + self.id
request = requests.get(request_url,
auth=self.auth,
headers={'Content-type': 'application/json'})
try:
self.status['result'] = json.loads(request.content)['result']
except TypeError:
self.status['result'] = "Sent/Unknown"
return self.status['result']
Am I doing something wrong? What do I do to get status for a placed call?

Flask: Decorator to verify JSON and JSON Schema

I have a flask application with calls expecting JSON payload. Before each call is processed, I have a 2-step error checking process:
Assert that the payload is a valid JSON
Assert that the JSON payload complies with a specific schema
Which is implemented in the following fashion:
#app.route('/activate', methods=['POST'])
def activate():
request_id = request.__hash__()
# Assert that the payload is a valid JSON
try:
input = request.json
except BadRequest, e:
msg = "payload must be a valid json"
return jsonify({"error": msg}), 400
# JSON Schema Validation
try:
validate(request.json, app.config['activate_schema'])
except ValidationError, e:
return jsonify({"error": e.message}), 400
Since this code is duplicated over many calls, I wonder If I can elegantly move it to a decorator, something in the formof:
#validate_json
#validate_schema(schema=app.config['activate_schema'])
#app.route('/activate', methods=['POST'])
def activate():
....
The problem is that the request argument is implicit: I can refer to it within the function, but it is not a parameter to it. Therefore, I am not sure how to use it within the decorator.
How can I implement the validation checks using Python decorators?
Just use the request context global in your decorator. It is available during any request.
from functools import wraps
from flask import (
current_app,
jsonify,
request,
)
def validate_json(f):
#wraps(f)
def wrapper(*args, **kw):
try:
request.json
except BadRequest, e:
msg = "payload must be a valid json"
return jsonify({"error": msg}), 400
return f(*args, **kw)
return wrapper
def validate_schema(schema_name):
def decorator(f):
#wraps(f)
def wrapper(*args, **kw):
try:
validate(request.json, current_app.config[schema_name])
except ValidationError, e:
return jsonify({"error": e.message}), 400
return f(*args, **kw)
return wrapper
return decorator
Apply these decorators before applying the #route decorator; you want to register the wrapped function, not the original function for the route:
#app.route('/activate', methods=['POST'])
#validate_json
#validate_schema('activate_schema')
def activate():
input = request.json
now you can use #expect_json directly
For Example
from flask import Flask, jsonify, g, url_for
from flask_expects_json import expects_json
# example imports
from models import User
from orm import NotUniqueError
app = Flask(__name__)
schema = {
'type': 'object',
'properties': {
'name': {'type': 'string'},
'email': {'type': 'string'},
'password': {'type': 'string'}
},
'required': ['email', 'password']
}
#app.route('/register', methods=['POST'])
#expects_json(schema)
def register():
# if payload is invalid, request will be aborted with error code 400
# if payload is valid it is stored in g.data
# do something with your data
user = User().from_dict(g.data)
try:
user.save()
except NotUniqueError as e:
# exception path: duplicate database entry
return jsonify(dict(message=e.message)), 409
# happy path: json response
resp = jsonify(dict(auth_token=user.encode_auth_token(), user=user.to_dict()})
resp.headers['Location'] = url_for('users.get_user', user_id=user.id)
return resp, 201
or
from flask import Flask
from flask_expects_json import expects_json
app = Flask(__name__)
schema = {
'type': 'object',
'properties': {
'name': {'type': 'string', "minLength": 4, "maxLength": 15},
'mobile': {'type': 'string', "pattern": "^[1-9]{1}[0-9]{9}$"},
'email': {'type': 'string', "pattern": "[^#]+#[^#]+\.[^#]"},
'password': {'type': 'string', "pattern": "^.*(?=.{8,})(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!##$%^&+=]).*$"}
},
'required': ['name', 'mobile', 'email', 'password']
}
#app.route('/', methods=['POST'])
#expects_json(schema)
def index():
values = request.get_json()
print(values)
return values
get more from here
A late answer, but you're probably looking for something like marshmallow (flask-marshmallow) or toastedmarshmallow.

Categories