2

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.

4

2 回答 2

4

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)
于 2012-04-03T08:27:02.660 回答
1

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.

于 2012-04-03T05:29:42.183 回答