Pergunta

I was trying to change the os.environ dict to simulate a logged in user on Google App Engine, as documented at https://stackoverflow.com/a/6230083/1241454.

from google.appengine.api import users
import webapp2
import os

class TestPage(webapp2.RequestHandler):
    def get(self):
        os.environ['USER_EMAIL'] = 'a@b.c'
        user = users.get_current_user()
        self.response.out.write(user.email())

This doesn't work. get_current_user() returns None in the above example for me, at least when running on the dev server. I get the same result when using testbed.setup_env() rather than directly editing os.environ. However, the below does work:

from google.appengine.api import users
import webapp2
import os

class TestPage(webapp2.RequestHandler):
    def get(self):
        os.environ['USER_EMAIL'] = 'a@b.c'
        reload(users)
        user = users.get_current_user()
        self.response.out.write(user.email())

The only change was reloading the users module after changing os.environ. Is this expected behavior, or is something wrong with my App Engine set up? My understanding is that Python / App Engine should load only one copy of the os module loaded into the system, not two.

Any ideas? This is very confusing to me.

Foi útil?

Solução

To clarify, os.environ is the WSGI environment (or CGI for Python 2.5) that is being passed to your WSGI-compatible framework (in your case, webapp2) for the request that you are processing - so just one environ per request.

You can see an example of what all the WSGI values are by visiting http://foo-shop.appspot.com - this is a simple WSGI app on Python 2.7 that shows all WSGI values. And all the USER_* values seem to be specific to using Google accounts for auth. There is no mention of them at http://www.wsgi.org/en/latest/definitions.html.

At https://developers.google.com/appengine/docs/python/tools/localunittesting#Changing_the_Default_Environment_Variables, the docs recommend using self.setup_env() to go changing environ variables specifically for testing...and I think testing only. That's not something that an application should be doing in a non-testing circumstance.

Outras dicas

You're almost there. What you need is to pass overwrite=True to testbed.setup_env().

I'd normally create a "helper" method, e.g. login_user, something like this:

def login_user(self, email, user_id, is_admin=False):
    self.testbed.setup_env(user_email=email or '', overwrite=True)
    self.testbed.setup_env(user_id=str(user_id) or '', overwrite=True)
    self.testbed.setup_env(user_is_admin='1' if is_admin else '0', overwrite=True)

def logout_user(self):
    self.login_user(None, None)

Also works for OAuth (in case you need that too):

def login_user(self, email, user_id, is_admin=False):
    self.testbed.setup_env(oauth_error_code='', overwrite=True)
    self.testbed.setup_env(oauth_email=email, overwrite=True)
    self.testbed.setup_env(oauth_user_id=str(user_id) or '', overwrite=True)
    self.testbed.setup_env(oauth_auth_domain='example.com', overwrite=True)
    self.testbed.setup_env(oauth_is_admin='1' if is_admin else '0', overwrite=True)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top