4

を実行するpy.test --with-gaeと、次のエラーが表示されます (pytest_gae プラグインがインストールされています)。

    def get_current_session():
        """Returns the session associated with the current request."""
>       return _tls.current_session
E       AttributeError: 'thread._local' object has no attribute 'current_session'

gaesessions/__init__.py:50: AttributeError

pytest を使用して Google appengine アプリケーションをテストしています。アプリケーションは、localhost SDK で実行した場合、または GAE サーバーにデプロイした場合に正常に動作します。pytest を gaessions で動作させる方法がわかりません。

私のコードは以下の通りです:

test_handlers.py

from webtest import TestApp
import appengine_config

def pytest_funcarg__anon_user(request):
    from main import app
    app = appengine_config.webapp_add_wsgi_middleware(app)
    return TestApp(app)

def test_session(anon_user):
    from gaesessions import get_current_session
    assert get_current_session()

appengine_config.py

from gaesessions import SessionMiddleware
def webapp_add_wsgi_middleware(app):
    from google.appengine.ext.appstats import recording
    app = recording.appstats_wsgi_middleware(app)
    app = SessionMiddleware(app, cookie_key="replaced-with-this-boring-text")
    return app

gasessions からの関連コード:

# ... more code are not show here ...

_tls = threading.local()


def get_current_session():
    """Returns the session associated with the current request."""
    return _tls.current_session

# ... more code are not show here ...


class SessionMiddleware(object):
    """WSGI middleware that adds session support.

    ``cookie_key`` - A key used to secure cookies so users cannot modify their
    content.  Keys should be at least 32 bytes (RFC2104).  Tip: generate your
    key using ``os.urandom(64)`` but do this OFFLINE and copy/paste the output
    into a string which you pass in as ``cookie_key``.  If you use ``os.urandom()``
    to dynamically generate your key at runtime then any existing sessions will
    become junk every time your app starts up!

    ``lifetime`` - ``datetime.timedelta`` that specifies how long a session may last.  Defaults to 7 days.

    ``no_datastore`` - By default all writes also go to the datastore in case
    memcache is lost.  Set to True to never use the datastore. This improves
    write performance but sessions may be occassionally lost.

    ``cookie_only_threshold`` - A size in bytes.  If session data is less than this
    threshold, then session data is kept only in a secure cookie.  This avoids
    memcache/datastore latency which is critical for small sessions.  Larger
    sessions are kept in memcache+datastore instead.  Defaults to 10KB.
    """
    def __init__(self, app, cookie_key, lifetime=DEFAULT_LIFETIME, no_datastore=False, cookie_only_threshold=DEFAULT_COOKIE_ONLY_THRESH):
        self.app = app
        self.lifetime = lifetime
        self.no_datastore = no_datastore
        self.cookie_only_thresh = cookie_only_threshold
        self.cookie_key = cookie_key
        if not self.cookie_key:
            raise ValueError("cookie_key MUST be specified")
        if len(self.cookie_key) < 32:
            raise ValueError("RFC2104 recommends you use at least a 32 character key.  Try os.urandom(64) to make a key.")

    def __call__(self, environ, start_response):
        # initialize a session for the current user
        _tls.current_session = Session(lifetime=self.lifetime, no_datastore=self.no_datastore, cookie_only_threshold=self.cookie_only_thresh, cookie_key=self.cookie_key)

        # create a hook for us to insert a cookie into the response headers
        def my_start_response(status, headers, exc_info=None):
            _tls.current_session.save()  # store the session if it was changed
            for ch in _tls.current_session.make_cookie_headers():
                headers.append(('Set-Cookie', ch))
            return start_response(status, headers, exc_info)

        # let the app do its thing
        return self.app(environ, my_start_response)
4

1 に答える 1

1

問題は、アプリも呼び出されるまで、gae セッションがまだ呼び出されないことです。アプリは、リクエストを行ったときにのみ呼び出されます。セッション値を確認する前に、リクエスト呼び出しを挿入してみてください。以下の修正された test_handlers.py コードを確認してください。

def test_session(anon_user):
    anon_user.get("/")  # get any url to call the app to create a session.
    from gaesessions import get_current_session
    assert get_current_session()
于 2014-05-07T09:09:46.927 に答える