]> git.parisson.com Git - django-social-auth.git/commitdiff
Refactored loading of BACKENDS to provide a proper entry point (get_backends) respons...
authorStephen McDonald <steve@jupo.org>
Thu, 29 Dec 2011 01:40:54 +0000 (12:40 +1100)
committerStephen McDonald <steve@jupo.org>
Thu, 29 Dec 2011 01:40:54 +0000 (12:40 +1100)
social_auth/backends/__init__.py
social_auth/context_processors.py
social_auth/utils.py

index 83713ca4eaf353d4da4f713958132a54a632acc3..8baaf7af81d82ed0f93cd24d44fbb342f6a1a50f 100644 (file)
@@ -618,12 +618,12 @@ if setting('SOCIAL_AUTH_IMPORT_BACKENDS'):
 # Cache for discovered backends.
 BACKENDS = {}
 
-def get_backend(name, *args, **kwargs):
-    """Returns a backend by name. Backends are stored in the BACKENDS
-    cache dict. If not found, each of the modules referenced in
+def get_backends(force_load=False):
+    """
+    Entry point to the BACKENDS cache. If BACKENDS hasn't been
+    populated, each of the modules referenced in
     AUTHENTICATION_BACKENDS is imported and checked for a BACKENDS
-    definition. If the named backend is found in the module's BACKENDS
-    definition, it's then stored in the cache for future access.
+    definition and if enabled, added to the cache.
 
     Previously all backends were attempted to be loaded at
     import time of this module, which meant that backends that subclass
@@ -633,24 +633,35 @@ def get_backend(name, *args, **kwargs):
 
     This new approach ensures that backends are allowed to subclass from
     bases in this module and still be picked up.
+
+    A force_load boolean arg is also provided so that get_backend
+    below can retry a requested backend that may not yet be discovered.
+    """
+    if not BACKENDS or force_load:
+        for auth_backend in settings.AUTHENTICATION_BACKENDS:
+            module = import_module(auth_backend.rsplit(".", 1)[0])
+            backends = getattr(module, "BACKENDS", {})
+            for name, backend in backends.items():
+                if backend.enabled():
+                    BACKENDS[name] = backend
+    return BACKENDS
+
+
+def get_backend(name, *args, **kwargs):
+    """Returns a backend by name. Backends are stored in the BACKENDS
+    cache dict. If not found, each of the modules referenced in
+    AUTHENTICATION_BACKENDS is imported and checked for a BACKENDS
+    definition. If the named backend is found in the module's BACKENDS
+    definition, it's then stored in the cache for future access.
     """
     try:
         # Cached backend which has previously been discovered.
         return BACKENDS[name](*args, **kwargs)
     except KeyError:
-        pass
-    # Look for a BACKENDS definition on each of the modules for
-    # AUTHENTICATION_BACKENDS.
-    for auth_backend in settings.AUTHENTICATION_BACKENDS:
-        module = import_module(auth_backend.rsplit(".", 1)[0])
-        backends = getattr(module, "BACKENDS", {})
+        # Force a reload of BACKENDS to ensure a missing
+        # backend hasn't been missed.
+        get_backends(force_load=True)
         try:
-            backend = backends[name]
+            return BACKENDS[name](*args, **kwargs)
         except KeyError:
-            pass
-        else:
-            # If the backend is enabled, add it to the cache and
-            # return it.
-            if backend.enabled():
-                BACKENDS[name] = backend
-                return backend(*args, **kwargs)
+            return None
index d1e9f1807a50477a15f4c9a0502c22e91ace0cef..47bf4c65e7dc70e73b4f4ca96df0163ae5d27246 100644 (file)
@@ -1,4 +1,4 @@
-from social_auth.backends import BACKENDS
+from social_auth.backends import get_backends
 from social_auth.utils import group_backend_by_type
 from social_auth.models import User
 
@@ -34,7 +34,7 @@ def social_auth_by_name_backends(request):
     with a hyphen have the hyphen replaced with an underscore, e.g.
     google-oauth2 becomes google_oauth2 when referenced in templates.
     """
-    keys = BACKENDS.keys()
+    keys = get_backends().keys()
     accounts = dict(zip(keys, [None] * len(keys)))
 
     if isinstance(request.user, User) and request.user.is_authenticated():
@@ -56,7 +56,7 @@ def backends_data(user):
     If user is not authenticated, then first list is empty, and there's no
     difference between the second and third lists.
     """
-    available = BACKENDS.keys()
+    available = get_backends().keys()
     values = {'associated': [],
               'not_associated': available,
               'backends': available}
index 9e3ea49073681e0af39fde95aea558ff04a2fcff..ec5c09e92d543cee243e9dd37af6570766b6c0fc 100644 (file)
@@ -65,12 +65,12 @@ def group_backend_by_type(items, key=lambda x: x):
 
     # Beware of cyclical imports!
     from social_auth.backends import \
-        BACKENDS, OpenIdAuth, BaseOAuth, BaseOAuth2
+        get_backends, OpenIdAuth, BaseOAuth, BaseOAuth2
 
     result = defaultdict(list)
 
     for item in items:
-        backend = BACKENDS[key(item)]
+        backend = get_backends()[key(item)]
         if issubclass(backend, OpenIdAuth):
             result['openid'].append(item)
         elif issubclass(backend, BaseOAuth2):