django test client trouble - python

I've got a problem... we're writing project using django, and i'm trying to use django.test.client with nose test-framework for tests.
Our code is like this:
from simplejson import loads
from urlparse import urljoin
from django.test.client import Client
TEST_URL = "http://smakly.localhost:9090/"
def test_register():
cln = Client()
ref_data = {"email": "unique#mail.com", "name": "Василий", "website": "http://hot.bear.com", "xhr": "true"}
print urljoin(TEST_URL, "/accounts/register/")
response = loads(cln.post(urljoin(TEST_URL, "/accounts/register/"), ref_data))
print response["message"]
and in nose output I catch:
Traceback (most recent call last):
File "/home/psih/work/svn/smakly/eggs/nose-0.11.1-py2.6.egg/nose/case.py", line 183, in runTest
self.test(*self.arg)
File "/home/psih/work/svn/smakly/src/smakly.tests/smakly/tests/frontend/test_profile.py", line 25, in test_register
response = loads(cln.post(urljoin(TEST_URL, "/accounts/register/"), ref_data))
File "/home/psih/work/svn/smakly/parts/django/django/test/client.py", line 313, in post
response = self.request(**r)
File "/home/psih/work/svn/smakly/parts/django/django/test/client.py", line 225, in request
response = self.handler(environ)
File "/home/psih/work/svn/smakly/parts/django/django/test/client.py", line 69, in __call__
response = self.get_response(request)
File "/home/psih/work/svn/smakly/parts/django/django/core/handlers/base.py", line 78, in get_response
urlconf = getattr(request, "urlconf", settings.ROOT_URLCONF)
File "/home/psih/work/svn/smakly/parts/django/django/utils/functional.py", line 273, in __getattr__
return getattr(self._wrapped, name)
AttributeError: 'Settings' object has no attribute 'ROOT_URLCONF'
My settings.py file does have this attribute.
If I get the data from the server with standard urllib2.urllopen().read() it works in the proper way.
Any ideas how I can solve this case?

Probably want django-nose if you want to use nose.
http://github.com/jbalogh/django-nose
I would recommend using the TestCase class
http://docs.djangoproject.com/en/dev/topics/testing/
http://www.djangoproject.com/documentation/models/test_client/

Shameless self-promotion: exactly for those reasons I made test library that enables you to test application with urllib2.
Docs are there: http://readthedocs.org/docs/django-sane-testing/en/latest/
Example of what You might want to do is, for example, in django-http-digest-tests

Related

eBay and Authlib Unconventional token type

I'm trying to use Authlib library to access new eBay REST API (as Authorization code grant)
Here is my code;
import json
import os
import webbrowser
from time import time
from authlib.integrations.requests_client import OAuth2Session
from rpi_order_data_sync import settings
def auth(seller):
def token_updater(token, seller=seller):
if not os.path.exists(seller):
open(seller, "w").close()
with open(seller, "w") as token_file:
json.dump(token, token_file)
scope = ["https://api.ebay.com/oauth/api_scope/sell.fulfillment.readonly"]
if not os.path.exists(seller):
ebay = OAuth2Session(
settings.E_APP_ID,
settings.E_CERT_ID,
redirect_uri=settings.E_RU_NAME,
scope=scope,
)
uri, state = ebay.create_authorization_url(
"https://auth.sandbox.ebay.com/oauth2/authorize",
)
print("Please go to {} and authorize access.".format(uri))
try:
webbrowser.open_new_tab(uri)
except webbrowser.Error:
pass
authorization_response = input("Please enter callback URL: ") # nosec
token = ebay.fetch_token(
"https://api.sandbox.ebay.com/identity/v1/oauth2/token",
authorization_response=authorization_response,
)
print(token)
token_updater(token)
return ebay
The problem is eBay's token response has an unconventional token type named "User Access Token" instead of "Bearer". Therefore I get this error;
Traceback (most recent call last):
File "/home/thiras/.local/share/virtualenvs/rpi-order-data-sync-tA0i1rrc/lib/python3.8/site-packages/authlib/integrations/requests_client/oauth2_session.py", line 37, in __call__
req.url, req.headers, req.body = self.prepare(
File "/home/thiras/.local/share/virtualenvs/rpi-order-data-sync-tA0i1rrc/lib/python3.8/site-packages/authlib/oauth2/auth.py", line 91, in prepare
sign = self.SIGN_METHODS[token_type.lower()]
KeyError: 'user access token'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/thiras/.local/share/virtualenvs/rpi-order-data-sync-tA0i1rrc/bin/rods", line 11, in <module>
load_entry_point('rpi-order-data-sync', 'console_scripts', 'rods')()
File "/home/thiras/.local/share/virtualenvs/rpi-order-data-sync-tA0i1rrc/lib/python3.8/site-packages/click/core.py", line 829, in __call__
return self.main(*args, **kwargs)
File "/home/thiras/.local/share/virtualenvs/rpi-order-data-sync-tA0i1rrc/lib/python3.8/site-packages/click/core.py", line 782, in main
rv = self.invoke(ctx)
File "/home/thiras/.local/share/virtualenvs/rpi-order-data-sync-tA0i1rrc/lib/python3.8/site-packages/click/core.py", line 1259, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/home/thiras/.local/share/virtualenvs/rpi-order-data-sync-tA0i1rrc/lib/python3.8/site-packages/click/core.py", line 1066, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/home/thiras/.local/share/virtualenvs/rpi-order-data-sync-tA0i1rrc/lib/python3.8/site-packages/click/core.py", line 610, in invoke
return callback(*args, **kwargs)
File "/home/thiras/HDD/freelancer/contentassasin/rpi-order-data-sync/rpi_order_data_sync/main.py", line 132, in sync_ebay_orders
orders = ebay.get(
File "/home/thiras/.local/share/virtualenvs/rpi-order-data-sync-tA0i1rrc/lib/python3.8/site-packages/requests/sessions.py", line 543, in get
return self.request('GET', url, **kwargs)
File "/home/thiras/.local/share/virtualenvs/rpi-order-data-sync-tA0i1rrc/lib/python3.8/site-packages/authlib/integrations/requests_client/oauth2_session.py", line 113, in request
return super(OAuth2Session, self).request(
File "/home/thiras/.local/share/virtualenvs/rpi-order-data-sync-tA0i1rrc/lib/python3.8/site-packages/requests/sessions.py", line 516, in request
prep = self.prepare_request(req)
File "/home/thiras/.local/share/virtualenvs/rpi-order-data-sync-tA0i1rrc/lib/python3.8/site-packages/requests/sessions.py", line 449, in prepare_request
p.prepare(
File "/home/thiras/.local/share/virtualenvs/rpi-order-data-sync-tA0i1rrc/lib/python3.8/site-packages/requests/models.py", line 318, in prepare
self.prepare_auth(auth, url)
File "/home/thiras/.local/share/virtualenvs/rpi-order-data-sync-tA0i1rrc/lib/python3.8/site-packages/requests/models.py", line 549, in prepare_auth
r = auth(self)
File "/home/thiras/.local/share/virtualenvs/rpi-order-data-sync-tA0i1rrc/lib/python3.8/site-packages/authlib/integrations/requests_client/oauth2_session.py", line 41, in __call__
raise UnsupportedTokenTypeError(description=description)
authlib.integrations.base_client.errors.UnsupportedTokenTypeError: unsupported_token_type: Unsupported token_type: 'user access token'
I've noticed Compliance fix for non-standard section at Authlib documentation but couldn't figure out how to do this fix or even possible in this way.
I've found a solution and it also works with requests-oauthlib package. It seems working flawlessly so far. The main struggle was to create a fake request.Response model since request.Response has no setter for .text or .content attributes so modifying them was impossible.
So I've created a FakeResponse class that only mimics .json() method since it was the only method used by Authlib.
class FakeResponse:
""" Fake Class for Request Response class. """
def __init__(self, data):
self.data = data
def json(self):
""" Mocks requests.Response.json(). """
return self.data
After that I've created an access_token_response hook;
def non_compliant_token_type(resp):
data = resp.json()
data["token_type"] = "Bearer"
fake_resp = FakeResponse(data=data)
return fake_resp
Please let me know if you have a better answer or any recommendations to improve it.

Internal Server Error, rather than raised AuthError response from Auth0

I have my flask-restful app.py which contains all of my main functions. I have created a server.py file as instructed from here: https://auth0.com/docs/quickstart/backend/python
In my app.py file from server i import AuthError and requires_auth. I have then put #requires_auth in front of my functions.
When I have a valid jwt, it works perfectly. When the jwt is not valid it fails. Failing is good, because the requests shouldn't work. But the response i get from my api is "Internal Server Error" rather than the detailed response in the raise AuthError section in the server.py file.
I get 2 errors:
Traceback (most recent call last):
File "C:\Users\ME\code\server.py", line 88, in decorated
issuer="https://"+AUTH0_DOMAIN+"/"
File "C:\Users\ME\lib\site-packages\jose\jwt.py", line 150, in decode
options=defaults)
File "C:\Users\ME\lib\site-packages\jose\jwt.py", line 457, in _validate_claims
_validate_exp(claims, leeway=leeway)
File "C:\Users\ME\lib\site-packages\jose\jwt.py", line 299, in _validate_exp
raise ExpiredSignatureError('Signature has expired.')
jose.exceptions.ExpiredSignatureError: Signature has expired.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\ME\lib\site-packages\flask\app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "C:\Users\ME\lib\site-packages\flask\app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "C:\Users\ME\lib\site-packages\flask_restful\__init__.py", line 480, in wrapper
resp = resource(*args, **kwargs)
File "C:\Users\ME\lib\site-packages\flask\views.py", line 88, in view
return self.dispatch_request(*args, **kwargs)
File "C:\Users\ME\lib\site-packages\flask_restful\__init__.py", line 595, in dispatch_request
resp = meth(*args, **kwargs)
File "C:\Users\ME\code\server.py", line 92, in decorated
"description": "token is expired"}, 401)
server.AuthError: ({'code': 'token_expired', 'description': 'token is expired'}, 401)
How do i get the AuthError as the response to the call, rather than just my Internal Server Error?
Thanks!
There is an issue with this specific tutorial in Auth0, it instructs you to include the error handler in auth.py:
#app.errorhandler(AuthError)
def handle_auth_error(ex):
response = jsonify(ex.error)
response.status_code = ex.status_code
return response
Instead, you have to include this handler in your app.py, where you actually use #requires_auth.
Notice that to do so, you need to add relevant imports:
from auth import AuthError
from flask import jsonify
Notice: To be able to import from auth.py you need to add an empty file __init__.py in the same directory.
Try setting app.config[“PROPAGATE_EXCEPTIONS”] = True
Uou could maybe use an errorhandler to explicitly catch those errors and return some explicit json based on them.

Api Request WSDL Python

I am trying to make an api connection via wsdl-soap in Python.
Here are the codes I used.
import zeep
wsdl = 'http://dev.gittigidiyor.com:8080/listingapi/ws/CategoryService?wsdl'
client = zeep.Client(wsdl=wsdl)
send_data=[{
'cat:getCategories' :[
{
'startOffSet' : 0,
'rowCount' : 4,
'withSpecs':'true',
'withDeepest':'true',
'withCatalog':'true',
'lang':'tr'
}
] } ]
print(client.service.getCategories(send_data))
The offical documentation suggests:
WSDL Address: http://dev.gittigidiyor.com:8080/listingapi/ws/CategoryService?wsdl
Service Method Signature: CategoryServiceResponse getCategories(int startOffSet, int rowCount, boolean withSpecs, boolean withDeepest, boolean withCatalog, String lang)
Request Example
<cat:getCategories>
<startOffSet>0</startOffSet>
<rowCount>4</rowCount>
<withSpecs>true</withSpecs>
<withDeepest>true</withDeepest>
<withCatalog>true</withCatalog>
<lang>tr</lang>
</cat:getCategories>
However I can't achieve to get any data from the source. I am getting errors like:
Traceback (most recent call last):
File "/Users/maydin/Desktop/z.py", line 22, in <module>
print(client.service.getCategories(send_data))
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/zeep/proxy.py", line 42, in __call__
self._op_name, args, kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/zeep/wsdl/bindings/soap.py", line 115, in send
options=options)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/zeep/wsdl/bindings/soap.py", line 68, in _create
serialized = operation_obj.create(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/zeep/wsdl/definitions.py", line 200, in create
return self.input.serialize(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/zeep/wsdl/messages/soap.py", line 65, in serialize
self.body.render(body, body_value)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/zeep/xsd/elements/element.py", line 191, in render
self._render_value_item(parent, value, render_path)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/zeep/xsd/elements/element.py", line 215, in _render_value_item
return self.type.render(node, value, None, render_path)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/zeep/xsd/types/complex.py", line 253, in render
element.render(parent, element_value, child_path)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/zeep/xsd/elements/indicators.py", line 241, in render
element.render(parent, element_value, child_path)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/zeep/xsd/elements/element.py", line 185, in render
self.validate(value, render_path)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/zeep/xsd/elements/element.py", line 236, in validate
"Missing element %s" % (self.name), path=render_path)
zeep.exceptions.ValidationError: Missing element rowCount (getCategories.rowCount)
>>>
Any help (new library suggestions, code correction etc.) will be appriciated.
Thanks in advance!
I finally solved my own problem.. The thing that I have missed is that it was needing an authentication layer.
Here are the codes for those who may need to solve similar problems.
from requests import Session
from requests.auth import HTTPBasicAuth
from zeep import Client
from zeep.transports import Transport
session = Session()
session.auth = HTTPBasicAuth('user_name', 'password')
client = Client('wsdl_url',
transport=Transport(session=session))
print(client.service.service_name(parameter1,parameter2,parameter3..))
Here is the source I made use of..

Listing Servers - OpenStack Nova API

I've passed the session object from another class (using Cherrypy cookies) and rebuilt the Nova instance in this class to list the servers. The rebuilt Nova instance works however when I try and create a list of servers, I have an attribute error. There's very little (I found nothing remotely like this issue) out on the internet about this sort of issue.
How do I solve this issue? :)
Code:
import cherrypy
import xmlrpclib
import xml.etree.ElementTree as ET
from keystoneauth1 import loading
from keystoneauth1 import session
import novaclient.client as client
from socket import gethostbyaddr
nova = client.Client("2.1", session=cherrypy.request.cookie.get('sessCookie').value)
serverList = nova.servers.list()
print serverList
Error:
File "/usr/lib/python2.7/site-packages/cherrypy/_cprequest.py", line 656, in respond
response.body = self.handler()
File "/usr/lib/python2.7/site-packages/cherrypy/lib/encoding.py", line 188, in __call__
self.body = self.oldhandler(*args, **kwargs)
File "/usr/lib/python2.7/site-packages/cherrypy/lib/jsontools.py", line 61, in json_handler
value = cherrypy.serving.request._json_inner_handler(*args, **kwargs)
File "/usr/lib/python2.7/site-packages/cherrypy/_cpdispatch.py", line 34, in __call__
return self.callable(*self.args, **self.kwargs)
File "/var/www/frontend/controllers/api/vm.py", line 158, in GET
serverList = nova.servers.list()
File "/usr/lib/python2.7/site-packages/novaclient/v2/servers.py", line 749, in list
"servers")
File "/usr/lib/python2.7/site-packages/novaclient/base.py", line 242, in _list
resp, body = self.api.client.get(url)
File "/usr/lib/python2.7/site-packages/keystoneauth1/adapter.py", line 173, in get
return self.request(url, 'GET', **kwargs)
File "/usr/lib/python2.7/site-packages/novaclient/client.py", line 89, in request
**kwargs)
File "/usr/lib/python2.7/site-packages/keystoneauth1/adapter.py", line 331, in request
resp = super(LegacyJsonAdapter, self).request(*args, **kwargs)
File "/usr/lib/python2.7/site-packages/keystoneauth1/adapter.py", line 98, in request
return self.session.request(url, method, **kwargs)
AttributeError: 'str' object has no attribute 'request'
The value of the session keyword is supposed to be a Keystone session object, but you're passing in a string.
You can read more about working with Keystone sessions here.

Error when using Django Rest Framework's APITestCase

I'm trying to run some tests for my Django-Rest-Framework API but am stuck on an error. When I run the following tests, I get the following errors.
Traceback (most recent call last):
File "C:\Users\Bill\SD\DjangoApps\vidapp\startapp\tests.py", line 21, in test_get_user
response = self.client.get('/user/1/')
File "C:\Anaconda\lib\site-packages\django\test\client.py", line 473, in get
response = super(Client, self).get(path, data=data, **extra)
File "C:\Anaconda\lib\site-packages\django\test\client.py", line 280, in get
return self.request(**r)
File "C:\Anaconda\lib\site-packages\rest_framework\test.py", line 143, in request
return super(APIClient, self).request(**kwargs)
File "C:\Anaconda\lib\site-packages\rest_framework\test.py", line 95, in request
request = super(APIRequestFactory, self).request(**kwargs)
File "C:\Anaconda\lib\site-packages\django\test\client.py", line 444, in request
six.reraise(*exc_info)
File "C:\Anaconda\lib\site-packages\django\core\handlers\base.py", line 114, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
TypeError: __init__() takes exactly 1 argument (2 given)
Test Cases:
class UserTestCase(APITestCase):
def setUp(self):
helper.reset_test_db()
def test_get_user(self):
response = self.client.get('/user/1/')
print response.content
self.assertEqual(response.data, {'fname':'Generic','lname':'Name','token':'token1'})
URL Config:
url(r'^user/new/$', 'startapp.views.new_user'),
url(r'^user/1/$', 'startapp.views.get_1'),
Views:
class get_1(APIView):
def get(self, request):
user = db_models.User.objects.get(pk=1)
if(user is not None):
serial_user = serial.UserSerializer(user)
return Response(serial_user.data)
else:
return Response(status.HTTP_404_NOT_FOUND)
I know the view itself works because I tested that separately. The data is definitely present since helper.reset_test_db() puts it there (I know I should be using fixtures but this is for testing so I went with the simple route). The same error occurs for POST and other commands or when I use Django's TestCase instead of APITestCase. While this is my first time using Django's TestCase, I read both the Django and Django rest documents but can't seem to figure out this issue.
The view in your case is a class-based view.
So you have to add it to the urlconfig with as_view:
url(r'^user/1/$', startapp.views.get_1.as_view()),

Categories