Getting missing positional argument error when trying to define middleware in Django - django-middleware

I am trying to come up with my first middleware of my own in a Django 1.10 project. And currently running into the following error
TypeError: init() missing 1 required positional argument:
'get_response'
I have defined the middleware in a middleware.py like this:
from zeon.utils import RequestLogThread
class StartRestEndPointMiddleWare(object):
def __init__(self, get_response):
self.get_response = get_response
# One-time configuration and initialization.
def __call__(self, request):
# Code to be executed for each request before
# the view (and later middleware) are called.
request.request_log_id = RequestLogThread('send_contact', request.data).start()
response = self.get_response(request)
# Code to be executed for each request/response after
# the view is called.
return response
I am lost trying to figure out what's wrong, since everything seems to be in accordance with the doc. I would really appreciate any hint.
UPDATE:
I place it into middle_classes:
MIDDLEWARE_CLASSES = [
'zeon.middleware.StartRestEndPointMiddleWare',
]

Django changed the way middleware classes worked in 1.10. New-style middleware classes belong in the MIDDLEWARE list, like this:
MIDDLEWARE = [
'zeon.middleware.StartRestEndPointMiddleWare',
]
When you put your middleware into MIDDLEWARE_CLASSES, it's being treated as an old-style middleware, which works differently. A better error message might have made this more clear.

Related

Hydra - Cannot override value in instantiate

I am developing a project based on the pytorch lightning + hydra template found here https://github.com/ashleve/lightning-hydra-template. I am trying to instantiate a Pytorch dataset object using hydra instantiate, overriding the default cfg value with the DictConfig object. Specifically, I have this config file:
...
training_dataset:
_target_: src.datamodules.components.baseline_datasets.FSD50K
cfg: omegaconf.dictconfig.DictConfig(content={})
mode: "training"
...
While the pytorch lightning datamodule does the following:
class AudioTagDataModule(LightningDataModule):
def __init__(self, cfg: DictConfig):
super().__init__()
self.cfg = cfg
self.save_hyperparameters(logger=False)
def setup(self, stage: Optional[str] = None):
self.trainset = instantiate(self.cfg.datamodule.training_dataset, cfg=self.cfg)
...
The rest of the code is pretty much unmodified from the template. However, when the pytorch dataset is instantiated, I get an error due to the config being empty. Checking in debug, I see that the config value is not being overridden, despite having the same name that was specified in the configs. Could someone provide some guidance on why the override is not working and how to correctly proceed? Thank!
Looking at the AudioTagDataModule, I see that the setup method passes a cfg=self.cfg keyword argument to the instantiate function. This is why the cfg setting from your training_dataset config is not showing up in your instantiated dataset; the keyword argument is taking precedence. Based on the code you posted, it would probably make sense to pass an empty DictConfig to AudioTagDataModule.__init__ instead of defining a cfg key/value in training_dataset.
Another thing: in your yaml file, you'd probably want cfg: {} instead of cfg: omegaconf.dictconfig.DictConfig(content={}), as the latter will result in the python string "omegaconf.dictconfig.DictConfig(content={})" and the former will result in an empty DictConfig.

How do I pass additional params to dispatch()?

An API I'm writing accepts two arguments via URL - e.g /api/targets/foo/bar
app = webapp2.WSGIApplication([
('/api/targets/(\w*?)/(\w*?)$', MainPage),
], debug=True)
This fires off a GET handler:
def get(self, url_1, url_2):
#do some stuff
The cool thing here is that I can reference url_1 (foo) and url_2 (bar) inside my GET handler and they're defined for me.
I have another page which accepts both GET and POST requests. About 90% of what happens is the same in either case, so I've opted to use def dispatch() instead of having two separate handlers.
The problem here is that (even though I still have the regex blocks enclosed in my webapp2.WSGIApplication initialisation) they are no longer passed to the request handler, so I have to define them like this:
url_1= self.request.url.split("/")[3]
url_2= self.request.url.split("/")[4]
Which makes me feel like a peon. If I tell dispatch() to expect those two params, they never arrive - what do I need to do to mimic the get behaviour in dispatch?
It would be shorter to use:
arg_one = self.request.route_args[0]
arg_two = self.request.route_args[1]
Take a look at the webapp2 docs for the Request object, specifically the route_args and route_kwargs towards the bottom of the Request section.
This is an interesting use case. If I were you, I would keep get() and post() separate. If get() and post() share code, then I would move that code to a method of the RequestHandler that can be called from both get() and post(), or move the shared code into another class (I find a lot of my RequestHandlers just call methods on my model classes).
If you still want one method to replace both get() and post(), then instead of using dispatch(), I recommend you set the handler_method for the Route (see here in the docs). I would advise against handling these requests entirely in the dispatch() method, as that is supposed to, at some point, call the "handler method", which defaults to GET/POST/etc. based on the HTTP method, but you can set your own handler method to handle GET and POST and whatever else.
If you set the handler_method, it would look like this:
# note that handler_method is the method name as a string
app = webapp2.WSGIApplication([
('/api/targets/(\w*?)/(\w*?)$', MainPage, handler_method='handle_request'),
], debug=True)
In your handler:
class MainPage(webapp2.RequestHandler):
# note that your method signature MUST have args for the route args,
# or else an exception will occur
def handle_request(self, arg_one, arg_two):
# your code here
if self.request.method == 'GET':
# do GET stuff
elif self.request.method == 'POST':
# do POST stuff
This is nice because it leaves dispatch() unchanged. I like to think of dispatch() as pre- and post-processing to occur before/after calling get()/post()/whatever handler method you specify.

pyramid.util.Request source code

I'm new to Python and I am studying Pyramid to learn how to write good code. I wrote this root factory code:
class RootFactory(object):
def __acl__(self):
return [
(Allow, 'group:alfa', 'alfa'),
]
def __init__(self, request):
print(type(request))
pass
and the result shows that "request" is <class 'pyramid.util.Request'> but if I open the module pyramid.util.py, to see the source code, I do not found the class Request. I think that this class is in the module pyramid.request.py
Could someone explain how this is working?
It's an implementation detail of using config.add_request_method. When adding request methods, a new class object is created using the InstancePropertyHelper which is located in the pyramid.util module. This could probably be fixed, but at the end of the day the actual class we care about is pyramid.request.Request so you should look there for issues.

Tornado async decorators where one depends on another

I'm trying to get my head around Tornado. I'm writing a chat application backed by mongodb and I'm using motor for non-blocking access to it.
What I'm trying to achieve is:
Create a decorator that uses motor to asynchronously pull the user's record from mongo
Validate their credentials (username & token)
Create another decorator that checks that the user_id retrieved in 1. above is permitted access to the chat room. This requires another asynchronous call to mongo with motor to retrieve the 'ChatRoom' record.
Subscribe to the chat room if all is OK
I have decorator 1. working (basically taken from http://tornadogists.org/5251927/):
def authenticated_async(f):
#functools.wraps(f)
#gen.engine
def wrapper(self, *args, **kwargs):
self.current_user = yield gen.Task(self.get_current_user_async)
if self.current_user:
logging.info("User '%s' (%s) successfully authenticated" %
(self.current_user['username'],
self.current_user['_id']))
f(self, *args, **kwargs)
else:
raise tornado.web.HTTPError(401, "User not authenticated, "
"aborting")
return wrapper
The trouble is that for the second decorator, I need to access self.current_user. Because this is set in an asynchronous callback, it's not available when I get into my validation decorator (i.e the validation decorator is called before the auth decorator completes).
Is it just not possible for me to use decorators in this way with asynchronous functions? Do I just need to call the validation method inside the above method after making sure that self.current_user is True so it's more like a callback?
I'd ideally like to have my methods in my Handler wrapped with both of these decorators so I can reuse them elsewhere, i.e.:
class ChatSocketHandler(tornado.websocket.WebSocketHandler):
#gen.coroutine
#validate_invitation_access_async
#authenticated_async
def open(self, invitation_id):
# do stuff here...
Update
In fact, there is no dependency. user_id is provided as a parameter, and that could be used to run both decorators in parallel - one to confirm authentication, the other to see whether the user with that ID is allowed access to the room. The open() method would then only proceed if self.auth_check == True and self.room_check == True.
Could open() ever be called before the async decorators complete though?
You need to switch the order of the decorators so your validate_invitation_access_async wrapper has access to current_user:
#authenticated_async
#validate_invitation_access_async
def open(self, invitation_id):
# do stuff here...
Then the wrapper inside validate_invitation_access_async is the "f" in authenticated_async: it's called after self.current_user is set. Note that you don't need an additional gen.engine decorator, all the wrappers are already engines. Your wrapper could be like:
def validate_invitation_access_async(f):
#gen.engine
def wrapper(self, *args, **kwargs):
# ... use Motor to see if user is authorized ...
# if not, log and redirect. otherwise:
f(self, *args, **kwargs)
You should also update your code to use Tornado 3's gen.coroutine instead of gen.engine: it's much cleaner. But I leave that as an exercise.

Cloud Endpoints - Google Glass object has no attribute 'mirror_service'

I'm attempting to incorporate cloud enpoints into my app, I'm currently using the Python Quickstart for proof of concept. I'm having an issue when I attempt to call a method to send a card to my glass. Below is my code, please ignore the indentation is missing.
#endpoints.api(name='tasks', version='v1',
description='API for TaskAlert Management',
allowed_client_ids=[CLIENT_ID, endpoints.API_EXPLORER_CLIENT_ID])
class TaskAlertApi(remote.Service):
#endpoints.method(Task, Task,
name='task.insert',
path='tasker',
http_method='POST')
def insert_task(self, request):
TaskModel(author=request.author, content=request.content, date=request.date).put()
themirror = MainHandler()
themirror._insert_map_with_distance_from_home()
return request
So when "themirror._insert_map_with_distance_from_home()" is called I am getting the following error. Does anyone have any suggestions? I am trying to call this from myappspot.com/_ah/api/explorer.
in _insert_map_with_distance_from_home
self.mirror_service.timeline().insert(body=body).execute()
AttributeError: 'MainHandler' object has no attribute 'mirror_service'
I'm afraid you will have to rethink your code quite a bit for this but I'll try to get the basics explained here.
The main problem is that the MainHandler does quite a bit when actually receiving a HTTP request. The most important thing is what happens in the #util.auth_required decorator of the MainHandler's get method, which actually creates the mirror_service, authenticated for the current user. When you access the MainHandler directly from your code, none of this actually happens, so there is no mirror_service available (which results in the error you get).
Since the way endpoints are called is quite different from the way normal RequestHandlers are called, you also can't rely on stored session credentials or similar to match an Endpoints User to the Mirror User.
Basically what you would have to do is to create a new mirror_service inside of your endpoint method.
For this you will have to call your API authenticated (adding the Mirror API scopes to the authentication scopes). You can then extract the used access_token from the request header and use this access_token to create OAuth2Credentials to create the mirror_service.
Some code snippets without promises of completeness since it's hard to tell without knowing your actual code:
import os
from oauth2client.client import AccessTokenCredentials
# extract the token from request
if "HTTP_AUTHORIZATION" in os.environ:
(tokentype, token) = os.environ["HTTP_AUTHORIZATION"].split(" ")
# create simple OAuth2Credentials using the token
credentials = AccessTokenCredentials(token, 'my-user-agent/1.0')
# create mirror_service (using the method from util.py from the quickstart(
mirror_service = create_service('mirror', 'v1', credentials)
Of course you would then also have to change the _insert_map_with_distance_from_home to use this mirror_service object, but moving this method away from your MainHandler would make more sense in this context anyway.

Resources