Importing a Flask-security instance into my views module breaks my webapp
Asked Answered
C

2

11

I'm writing the sign up/sign in system for a ecommerce site, and using flask-security (http://pythonhosted.org/Flask-Security/) to handle the signup feature. Part of the basic setup requires the following signup.py module:

from flask.ext.security import SQLAlchemyUserDatastore, Security
from app.models import User, Role
from app import app, db

# Setup Flask Security
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security = Security(app, user_datastore)

I then have to import the user_datastore and security objects into my views.py module as follows:

from app.signup import user_datastore, security

The thing is, as soon as I include the above import statement into my views module, my whole app crashes, and I get the following traceback error when I try to run my unit or behavior tests (edited for readability)

======================================================================
ERROR: Failure: AttributeError ('_FakeSignal' object has no attribute 'connect_via')
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Library/Python/2.7/site-packages/nose/loader.py", line 413, in loadTestsFromName
    addr.filename, addr.module)
  File "/Library/Python/2.7/site-packages/nose/importer.py", line 47, in importFromPath
    return self.importFromDir(dir_path, fqname)
  File "/Library/Python/2.7/site-packages/nose/importer.py", line 94, in importFromDir
    mod = load_module(part_fqname, fh, filename, desc)
  File "/Users/faiyamrahman/programming/Python/WebApps/NibsNWhiskeyFull/tests/test_database.py", line 6, in <module>
    from app import app, db, models
  File "/Users/faiyamrahman/programming/Python/WebApps/NibsNWhiskeyFull/app/__init__.py", line 9, in <module>
    from app import views, models
  File "/Users/faiyamrahman/programming/Python/WebApps/NibsNWhiskeyFull/app/views.py", line 7, in <module>
    from app.signup import user_datastore
  File "/Users/faiyamrahman/programming/Python/WebApps/NibsNWhiskeyFull/app/signup.py", line 7, in <module>
    security = Security(app, user_datastore)
  File "/Users/faiyamrahman/programming/Python/WebApps/NibsNWhiskeyFull/flask/lib/python2.7/site-packages/flask_security/core.py", line 346, in __init__
    self._state = self.init_app(app, datastore, **kwargs)
  File "/Users/faiyamrahman/programming/Python/WebApps/NibsNWhiskeyFull/flask/lib/python2.7/site-packages/flask_security/core.py", line 368, in init_app
    identity_loaded.connect_via(app)(_on_identity_loaded)
AttributeError: '_FakeSignal' object has no attribute 'connect_via'

I have no idea what this means. I've tried reading the flask-security documentation, but I don't understand why it's happening. Thanks to anyone who takes a stab at this!

Crin answered 4/12, 2013 at 16:48 Comment(0)
I
16

Short Answer: You are missing blinker library. EDIT: You confirmed that your virtual environment could not find blinker and you re-installed it.

Long Answer:

I think the error is coming from Flask Signals. Look at this code from signals:

signals_available = False
try:
    from blinker import Namespace
    signals_available = True
except ImportError:
    class Namespace(object):
        def signal(self, name, doc=None):
            return _FakeSignal(name, doc)

So I think that the code tries to find the blinker library and in your case, it is not able to import it and hence it tries to use the _FakeSignal class.

The _FakeSignal class does not have a connect_via attribute defined as you can see below

class _FakeSignal(object):
    """If blinker is unavailable, create a fake class with the same
    interface that allows sending of signals but will fail with an
    error on anything else.  Instead of doing anything on send, it
    will just ignore the arguments and do nothing instead.
    """

    def __init__(self, name, doc=None):
        self.name = name
        self.__doc__ = doc
    def _fail(self, *args, **kwargs):
        raise RuntimeError('signalling support is unavailable '
                           'because the blinker library is '
                           'not installed.')
    send = lambda *a, **kw: None
    connect = disconnect = has_receivers_for = receivers_for = \
        temporarily_connected_to = connected_to = _fail
    del _fail

The connect_via attribute that Flask-Security is trying to load is actually provided by the blinker library and since no blinker, no connect_via. Hence it fails.

So you should install blinker first. However, I think that Flask-Security code should also check for blinker before trying to use connect_via.

Interstice answered 4/12, 2013 at 17:59 Comment(7)
Hey thanks for your response. This seems reasonable, but I both pip installed and pip updated blinker. It turns out my virtual environment already had blinker loaded. So I'm still getting the same error message.Crin
which version of blinker ? I believe you need to have 1.1 or higherInterstice
I've got blinker version 1.3Crin
ok. but clearly, somehow Flask Signals cannot import it and hence it falls back to _FakeSignal object. You need to check your virtual env. configs etc. Flask Signals should be able to find blinker which it cannot from this error message that you are getting. good luckInterstice
You might want to try this directly in your virtual environment: "from blinker import Namespace" and see if it worksInterstice
You're right. I tried installing blinker to my root bin folder and it worked. For some reason, my app can't find blinker in the virtualenviornment. Thanks!Crin
Oddly enough, when i open up a python shell directly from my virtualenv, both "import blinker" and "from blinker import Namespace" work.Crin
S
0

To future internet people:

I had the same error but with a different cause. I'm using anaconda's virtual environments, and I think that conflicted with flask's auto-reload system (it had failed to load correctly once and fixing the error did not change anything, even editing the blinker.py file). Opening a new console to run in fixed it.

Sorry I don't have more information to give, but hopefully that helps someone.

Squashy answered 5/6, 2019 at 18:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.