Django Test mock instance of module variable - python

I'm trying to test my Django app which has a proxy API which is instantiated in its own module.
api.py
class ProxyApi(object):
def __init__(self, server_info):
pass
def validate_login(self, credentials):
# call to real api here
api = ProxyAPi()
middlewares.py
from mymodule.api import api
class MyMiddleware(MiddlewareMixin):
def process_request(self, request):
if api.validate_login():
# do something with proxy api
views.py
from mymodule.api import api
class TaskView(LoginRequiredMixin, FormView):
def get(self, request):
if api.validate_login():
# do something with proxy api
tests.py
class InputTasksViewTest(TestCase):
#mock.patch('mymodule.api.ProxyAPi')
def test_add(self, mock_api):
mock_api.validate_login.return_value = True
response = self.client.get(reverse('task'))
The original validate_loginis still called.
I would like to know how to handle the instantiation of ProxyApi while still retaining mocking capacity.

Ok I found my own solution, the problem was that once Django started, it read some files (like models or views or middlewares) that automatically instantiated api variable from import.
I just needed to defer this instantiation so I can mock the ProxyApi object, here's what I did:
api = SimpleLazyObject(lambda: ProxApi())

You have def validate_login(self, credentials): in api
and in middleware you define below code. So How you will send creadentials to API from middleware api.validate_login(<You should send credentials to api as parameter>):
from mymodule.api import api
class MyMiddleware(MiddlewareMixin):
def process_request(self, request):
if api.validate_login():
pass

Related

Flask-Restplus middleware

I have made an api with restplus
from flask_restplus import Namespace, Resource, fields
from flask import request
from flask_restplus import abort
api = Namespace('myproject', description='My API')
#api.route('/run')
class MyProject(Resource):
#api.doc(params={'name':'name'})
def post(self):
#doing stuff
return {'status':'started'}
The point of this route is to run another function and return {'status':'started'} immediatly without waiting for the function to end.
I've found this https://stackoverflow.com/a/51013358/1540114
but I have trouble using it in my project
from what I understood the AfterResponse is a middleware that I can apply to my route
I tried using it like this
....
api = Namespace('myproject', description='My API')
AfterResponse(api)
#api.after_response
def say_hi():
print("hi")
#api.route('/run')
class MyProject(Resource):
....
but it gave me an error stating that api doesn't have a wsgi_app property

Organising an Cloud Endpoint's class methods

I am trying to abstract various endpoint methods in their own modules, and then import them into the main api file. So let's say this is the mail file:
#endpoints.api(name='myapi', version='v1')
class MyApi(remote.Service):
#endpoints.method(SomeMessage, SomeMessage, path='somepath', http_method='GET', name='someName')
def getContent(self, request):
# handle content
return request
How can I abstract this endpoint method in its own module, and import it back to be used with the MyApi class?

Django custom authentication

I am using Django REST Framework in my app. I need authentication but not the default one. I have a model:
class Worker(models.Model):
token = models.CharField(...)
ip = models.GenericIPAddressField(...)
created_date = models.DateTimeField(...)
last_update = models.DateTimeField(...)
Worker sends messages through my API to view WorkerView which inherits from Django REST Framework's APIView. Token is send in request's header:
class WorkerView(APIView):
def post(self, request):
# some not important code
I have an authenticating method:
def authenticate(request):
try:
ip = request.META.get("REMOTE_ADDR", None)
token = request.META.get("HTTP_AUTHORIZATION", None)
...
I thought about two solutions:
Make a mixin class and inherit it in my WorkerView:
class WorkerView(AuthenticationMixin, APIView)
...
Make a class decorator from my authenticate method and use it like this:
#authenticate
class WorkerView(APIView)
But in both cases I need to pass request argument to authenticate method.
How to do that? Or maybe there's a better solution to my problem?
Why don't You create a custom authentication class as defined here?
http://www.django-rest-framework.org/api-guide/authentication/#custom-authentication

Store objects at "request scope" in google app engine

I would like to store some information at the "request scope" when using google app engine (python). What I mean by this is that I would like to initialize some information when a request is first received, and then be able to access it from anywhere for the life of the request (and only from that request).
An example of this would be if I saved the current user's name at request scope after they were authenticated.
How would I go about doing this sort of thing?
Thanks!
A pattern used in app engine itself seems to be threading.local which you can grep for in the SDK code. Making os.environ request local is done like that in runtime/request_environment.py for example.
A rough example:
import threading
class _State(threading.local):
"""State keeps track of request info"""
user = None
_state = _State()
From elsewhere you could authenticate early on in handler code.
from state import _state
if authentication_passed:
_state.user = user
and provide convenience that can be used in other parts of your code
from state import _state
def get_authenticated_user():
user = _state.user
if not user:
raise AuthenticationError()
return user
You need something like this:-
class BaseHandler(webapp2.RequestHandler):
#A function which is useful in order to determine whether user is logged in
def initialize(self, *a, **kw):
#Do the authentication
self.username = username
class MainHandler(BaseHandler):
def get(self):
print self.username
Now if you inherit BaseHandler class all the request will first go through the initialize method of BaseHandler class and since in the BaseHandler class you are setting the username
and MainHandler inherits form BaseHandler you will have the self.username defined and all the request wil go through initialize method.

Google App Engine, define a Preprocessing class

I am trying to define a base request handling class so that the webapp pages may inherit some basic methods and variable which otherwise would be required to be repeatedly be defined for each page of the application. A sort of similar functionality like django preprocessors. This is my base class from which other pages inherit:
class BasePage(webapp.RequestHandler):
def __init__(self):
self.user = users.get_current_user()
self.template_values = {
'user': self.user,
'environ': self, #I don't like the idea of passing the whole environ object to a template
##The below three functions cannot be executed during _init_ because of absence of self.request
#'openid_providers': self.openid_providers(),
#'logout_url': self.get_logout_url(),
#'request': self.get_request(),
}
##A sort of similar functionality like render_to_response in django
def render_template(self, template_name, values = None, *args, **kwargs):
#PATH is the directory containing the templates
if values:
for value in values: self.template_values[value] = values[value]
self.response.out.write(template.render(PATH+template_name, self.template_values, *args, **kwargs))
##Returns request as the name suggests
def logout_url(self):
return users.create_logout_url(self.request.url)
##Returns request as the name suggests
def request(self):
return request
##Returns openid login urls
def openid_providers(self):
#OPENID_POVIDERS is a list of dictionary
for p in OPENID_PROVIDERS:
p['login_url'] = users.create_login_url(self.request.get('next', '/') , p['name'], p['url'])
return OPENID_PROVIDERS
Everything is working fine except that I cannot pass some variables during initialization as self.request is not available. So for a workaround what I did is pass on whole self variable as a template variable.
Is there some other way to provide the template variables (request, logout_url etc) to the templates?
A much simpler solution than bgporter's is to do the common setup in the initialize method of webapp.RequestHandler. Here's an example from work, where we wanted to add a Django-like is_ajax method to the request object:
class BaseHandler(webapp.RequestHandler):
def initialize(self, request, response):
super(BaseHandler, self).initialize(request, response)
# Add a Django-like is_ajax() method to the request object
request.is_ajax = lambda: \
request.environ.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
This method is called to, uh, initialize each request handler with the current request and response objects, before the appropriate get or post (or whatever) methods are called.
I've solved that problem in my AppEngine code by using the Template Method Pattern
Basically, the base class looks like:
class MyBasePage(webapp.RequestHandler):
def __init__(self):
# common setup/init stuff here,
# omitted for this discussion
def Setup(self):
# request handling setup code needed in both GET/POST methods, like
# checking for user login, getting session cookies, etc.
# omitted for this discussion
def get(self, *args):
self.Setup()
# call the derived class' 'DoGet' method that actually has
# the logic inside it
self.DoGet(*args)
def post(self, *args):
self.Setup()
# call the derived class' 'DoPost' method
self.DoPost(*args)
def DoGet(self, *args):
''' derived classes override this method and
put all of their GET logic inside. Base class does nothing.'''
pass
def DoPost(self, *args):
''' derived classes override this method and
put all of their POST logic inside. Base class does nothing.'''
pass
...your derived classes then mostly just need to worry about the guts of those DoGet() and DoPost() methods.

Categories