[Python-modules-commits] [python-social-auth] 44/131: add support peewee for flask

Wolfgang Borgert debacle at moszumanska.debian.org
Sat Dec 24 15:16:59 UTC 2016


This is an automated email from the git hooks/post-receive script.

debacle pushed a commit to tag v0.2.20
in repository python-social-auth.

commit 4273876cefa5b6d6e384c66188f6f64683990013
Author: alexpantyukhin <apantykhin at gmail.com>
Date:   Wed Jun 1 19:54:45 2016 +0500

    add support peewee for flask
---
 examples/flask_peewee_example/__init__.py         |  62 +++++++
 examples/flask_peewee_example/manage.py           |  26 +++
 examples/flask_peewee_example/models/__init__.py  |   4 +
 examples/flask_peewee_example/models/user.py      |  24 +++
 examples/flask_peewee_example/requirements.txt    |   7 +
 examples/flask_peewee_example/routes/__init__.py  |   2 +
 examples/flask_peewee_example/routes/main.py      |  22 +++
 examples/flask_peewee_example/settings.py         |  55 ++++++
 examples/flask_peewee_example/templates/base.html |  14 ++
 examples/flask_peewee_example/templates/done.html |  24 +++
 examples/flask_peewee_example/templates/home.html |  85 +++++++++
 social/apps/flask_app/peewee/__init__.py          |   0
 social/apps/flask_app/peewee/models.py            |  48 ++++++
 social/storage/peewee_orm.py                      | 199 ++++++++++++++++++++++
 14 files changed, 572 insertions(+)

diff --git a/examples/flask_peewee_example/__init__.py b/examples/flask_peewee_example/__init__.py
new file mode 100644
index 0000000..4c2543f
--- /dev/null
+++ b/examples/flask_peewee_example/__init__.py
@@ -0,0 +1,62 @@
+import sys
+
+from flask import Flask, g
+from flask.ext import login
+
+sys.path.append('../..')
+
+from social.apps.flask_app.routes import social_auth
+from social.apps.flask_app.template_filters import backends
+from social.apps.flask_app.peewee.models import *
+from peewee import *
+
+# App
+app = Flask(__name__)
+app.config.from_object('flask_example.settings')
+
+try:
+    app.config.from_object('flask_example.local_settings')
+except ImportError:
+    pass
+
+from models.user import database_proxy, User
+
+# DB
+database = SqliteDatabase('test.db')
+database_proxy.initialize(database)
+
+app.register_blueprint(social_auth)
+init_social(app, database)
+
+login_manager = login.LoginManager()
+login_manager.login_view = 'main'
+login_manager.login_message = ''
+login_manager.init_app(app)
+
+from flask_example import models
+from flask_example import routes
+
+
+ at login_manager.user_loader
+def load_user(userid):
+    try:
+        us = User.get(User.id == userid)
+        return us
+    except User.DoesNotExist:
+        pass
+
+
+ at app.before_request
+def global_user():
+    g.user = login.current_user._get_current_object()
+
+
+ at app.context_processor
+def inject_user():
+    try:
+        return {'user': g.user}
+    except AttributeError:
+        return {'user': None}
+
+
+app.context_processor(backends)
diff --git a/examples/flask_peewee_example/manage.py b/examples/flask_peewee_example/manage.py
new file mode 100644
index 0000000..9270586
--- /dev/null
+++ b/examples/flask_peewee_example/manage.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+import sys
+
+from flask.ext.script import Server, Manager, Shell
+
+sys.path.append('..')
+
+from flask_example import app, database
+
+
+manager = Manager(app)
+manager.add_command('runserver', Server())
+manager.add_command('shell', Shell(make_context=lambda: {
+    'app': app
+}))
+
+
+ at manager.command
+def syncdb():
+    from flask_example.models.user import User
+    from social.apps.flask_app.peewee.models import FlaskStorage
+
+    database.create_tables([User, FlaskStorage.user, FlaskStorage.nonce, FlaskStorage.association, FlaskStorage.code])
+
+if __name__ == '__main__':
+    manager.run()
diff --git a/examples/flask_peewee_example/models/__init__.py b/examples/flask_peewee_example/models/__init__.py
new file mode 100644
index 0000000..2253824
--- /dev/null
+++ b/examples/flask_peewee_example/models/__init__.py
@@ -0,0 +1,4 @@
+from flask_example.models import user
+from social.apps.flask_app.peewee import models
+# create a peewee database instance -- our models will use this database to
+# persist information
diff --git a/examples/flask_peewee_example/models/user.py b/examples/flask_peewee_example/models/user.py
new file mode 100644
index 0000000..a46f559
--- /dev/null
+++ b/examples/flask_peewee_example/models/user.py
@@ -0,0 +1,24 @@
+from peewee import *
+from datetime import datetime
+from flask.ext.login import UserMixin
+
+database_proxy = Proxy()
+
+
+# model definitions -- the standard "pattern" is to define a base model class
+# that specifies which database to use.  then, any subclasses will automatically
+# use the correct storage.
+class BaseModel(Model):
+    class Meta:
+        database = database_proxy
+
+# the user model specifies its fields (or columns) declaratively, like django
+class User(BaseModel, UserMixin):
+    username = CharField(unique=True)
+    password = CharField(null=True)
+    email = CharField(null=True)
+    active = BooleanField(default=True)
+    join_date = DateTimeField(default=datetime.now)
+
+    class Meta:
+        order_by = ('username',)
diff --git a/examples/flask_peewee_example/requirements.txt b/examples/flask_peewee_example/requirements.txt
new file mode 100644
index 0000000..e52656b
--- /dev/null
+++ b/examples/flask_peewee_example/requirements.txt
@@ -0,0 +1,7 @@
+Peewee
+Flask
+Flask-Login
+Flask-Script
+Werkzeug
+pysqlite
+Jinja2
diff --git a/examples/flask_peewee_example/routes/__init__.py b/examples/flask_peewee_example/routes/__init__.py
new file mode 100644
index 0000000..d3586e8
--- /dev/null
+++ b/examples/flask_peewee_example/routes/__init__.py
@@ -0,0 +1,2 @@
+from flask_example.routes import main
+from social.apps.flask_app import routes
diff --git a/examples/flask_peewee_example/routes/main.py b/examples/flask_peewee_example/routes/main.py
new file mode 100644
index 0000000..5e0dd9c
--- /dev/null
+++ b/examples/flask_peewee_example/routes/main.py
@@ -0,0 +1,22 @@
+from flask import render_template, redirect
+from flask.ext.login import login_required, logout_user
+
+from flask_example import app
+
+
+ at app.route('/')
+def main():
+    return render_template('home.html')
+
+
+ at login_required
+ at app.route('/done/')
+def done():
+    return render_template('done.html')
+
+
+ at app.route('/logout')
+def logout():
+    """Logout view"""
+    logout_user()
+    return redirect('/')
diff --git a/examples/flask_peewee_example/settings.py b/examples/flask_peewee_example/settings.py
new file mode 100644
index 0000000..419c575
--- /dev/null
+++ b/examples/flask_peewee_example/settings.py
@@ -0,0 +1,55 @@
+from os.path import dirname, abspath
+
+SECRET_KEY = 'random-secret-key'
+SESSION_COOKIE_NAME = 'psa_session'
+DEBUG = True
+DEBUG_TB_INTERCEPT_REDIRECTS = False
+SESSION_PROTECTION = 'strong'
+
+SOCIAL_AUTH_STORAGE = 'social.apps.flask_app.peewee.models.FlaskStorage'
+SOCIAL_AUTH_LOGIN_URL = '/'
+SOCIAL_AUTH_LOGIN_REDIRECT_URL = '/done/'
+SOCIAL_AUTH_USER_MODEL = 'flask_example.models.user.User'
+SOCIAL_AUTH_AUTHENTICATION_BACKENDS = (
+    'social.backends.open_id.OpenIdAuth',
+    'social.backends.google.GoogleOpenId',
+    'social.backends.google.GoogleOAuth2',
+    'social.backends.google.GoogleOAuth',
+    'social.backends.twitter.TwitterOAuth',
+    'social.backends.yahoo.YahooOpenId',
+    'social.backends.stripe.StripeOAuth2',
+    'social.backends.persona.PersonaAuth',
+    'social.backends.facebook.FacebookOAuth2',
+    'social.backends.facebook.FacebookAppOAuth2',
+    'social.backends.yahoo.YahooOAuth',
+    'social.backends.angel.AngelOAuth2',
+    'social.backends.behance.BehanceOAuth2',
+    'social.backends.bitbucket.BitbucketOAuth',
+    'social.backends.box.BoxOAuth2',
+    'social.backends.linkedin.LinkedinOAuth',
+    'social.backends.github.GithubOAuth2',
+    'social.backends.foursquare.FoursquareOAuth2',
+    'social.backends.instagram.InstagramOAuth2',
+    'social.backends.live.LiveOAuth2',
+    'social.backends.vk.VKOAuth2',
+    'social.backends.dailymotion.DailymotionOAuth2',
+    'social.backends.disqus.DisqusOAuth2',
+    'social.backends.dropbox.DropboxOAuth',
+    'social.backends.eveonline.EVEOnlineOAuth2',
+    'social.backends.evernote.EvernoteSandboxOAuth',
+    'social.backends.fitbit.FitbitOAuth2',
+    'social.backends.flickr.FlickrOAuth',
+    'social.backends.livejournal.LiveJournalOpenId',
+    'social.backends.soundcloud.SoundcloudOAuth2',
+    'social.backends.thisismyjam.ThisIsMyJamOAuth1',
+    'social.backends.stocktwits.StocktwitsOAuth2',
+    'social.backends.tripit.TripItOAuth',
+    'social.backends.clef.ClefOAuth2',
+    'social.backends.twilio.TwilioAuth',
+    'social.backends.xing.XingOAuth',
+    'social.backends.yandex.YandexOAuth2',
+    'social.backends.podio.PodioOAuth2',
+    'social.backends.reddit.RedditOAuth2',
+    'social.backends.mineid.MineIDOAuth2',
+    'social.backends.wunderlist.WunderlistOAuth2',
+)
diff --git a/examples/flask_peewee_example/templates/base.html b/examples/flask_peewee_example/templates/base.html
new file mode 100644
index 0000000..86db504
--- /dev/null
+++ b/examples/flask_peewee_example/templates/base.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<html>
+  <head>
+    <title>Social</title>
+    <link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.0/css/bootstrap-combined.min.css" rel="stylesheet" media="screen">
+  </head>
+  <body>
+    {% block content %}{% endblock %}
+    {% block scripts %}{% endblock %}
+
+    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
+    <script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.0/js/bootstrap.min.js" type="text/javascript"></script>
+  </body>
+</html>
diff --git a/examples/flask_peewee_example/templates/done.html b/examples/flask_peewee_example/templates/done.html
new file mode 100644
index 0000000..ccabf53
--- /dev/null
+++ b/examples/flask_peewee_example/templates/done.html
@@ -0,0 +1,24 @@
+{% extends "base.html" %}
+
+{% block content %}
+<p>You are logged in as {{ user.username }}!</p>
+
+<p>Associated:</p>
+{% for assoc in backends.associated %}
+  <div>
+    {{ assoc.provider }}
+    <form method="post" action="{{ url_for("social.disconnect", backend=assoc.provider, association_id=assoc.id) }}">
+      <button>Disconnect</button>
+    </form>
+  </div>
+{% endfor %}
+
+<p>Associate:</p>
+<ul>
+  {% for name in backends.not_associated %}
+    <li>
+      <a href="{{ url_for("social.auth", backend=name) }}">{{ name }}</a>
+    </li>
+  {% endfor %}
+</ul>
+{% endblock %}
diff --git a/examples/flask_peewee_example/templates/home.html b/examples/flask_peewee_example/templates/home.html
new file mode 100644
index 0000000..1c7f9bc
--- /dev/null
+++ b/examples/flask_peewee_example/templates/home.html
@@ -0,0 +1,85 @@
+{% extends "base.html" %}
+
+{% block content %}
+<a href="{{ url_for("social.auth", backend="google-oauth2") }}">Google OAuth2</a> <br />
+<a href="{{ url_for("social.auth", backend="google-oauth") }}">Google OAuth</a> <br />
+<a href="{{ url_for("social.auth", backend="google") }}">Google OpenId</a> <br />
+<a href="{{ url_for("social.auth", backend="twitter") }}">Twitter OAuth</a> <br />
+<a href="{{ url_for("social.auth", backend="yahoo") }}">Yahoo OpenId</a> <br />
+<a href="{{ url_for("social.auth", backend="yahoo-oauth") }}">Yahoo OAuth</a> <br />
+<a href="{{ url_for("social.auth", backend="stripe") }}">Stripe OAuth2</a> <br />
+<a href="{{ url_for("social.auth", backend="facebook") }}">Facebook OAuth2</a> <br />
+<a href="{{ url_for("social.auth", backend="facebook-app") }}">Facebook App</a> <br />
+<a href="{{ url_for("social.auth", backend="angel") }}">Angel OAuth2</a> <br />
+<a href="{{ url_for("social.auth", backend="behance") }}">Behance OAuth2</a> <br />
+<a href="{{ url_for("social.auth", backend="bitbucket") }}">Bitbucket OAuth</a> <br />
+<a href="{{ url_for("social.auth", backend="box") }}">Box OAuth2</a> <br />
+<a href="{{ url_for("social.auth", backend="linkedin") }}">LinkedIn OAuth</a> <br />
+<a href="{{ url_for("social.auth", backend="github") }}">Github OAuth2</a> <br />
+<a href="{{ url_for("social.auth", backend="foursquare") }}">Foursquare OAuth2</a> <br />
+<a href="{{ url_for("social.auth", backend="instagram") }}">Instagram OAuth2</a> <br />
+<a href="{{ url_for("social.auth", backend="live") }}">Live OAuth2</a> <br />
+<a href="{{ url_for("social.auth", backend="vk-oauth2") }}">VK.com OAuth2</a> <br />
+<a href="{{ url_for("social.auth", backend="dailymotion") }}">Dailymotion OAuth2</a> <br />
+<a href="{{ url_for("social.auth", backend="disqus") }}">Disqus OAuth2</a> <br />
+<a href="{{ url_for("social.auth", backend="dropbox") }}">Dropbox OAuth</a> <br />
+<a href="{{ url_for("social.auth", backend="evernote-sandbox") }}">Evernote OAuth (sandbox mode)</a> <br />
+<a href="{{ url_for("social.auth", backend="fitbit") }}">Fitbit OAuth</a> <br />
+<a href="{{ url_for("social.auth", backend="flickr") }}">Flickr OAuth</a> <br />
+<a href="{{ url_for("social.auth", backend="soundcloud") }}">Soundcloud OAuth2</a> <br />
+<a href="{{ url_for("social.auth", backend="thisismyjam") }}">ThisIsMyJam OAuth1</a> <br />
+<a href="{{ url_for("social.auth", backend="stocktwits") }}">Stocktwits OAuth2</a> <br />
+<a href="{{ url_for("social.auth", backend="tripit") }}">Tripit OAuth</a> <br />
+<a href="{{ url_for("social.auth", backend="clef") }}">Clef OAuth2</a> <br />
+<a href="{{ url_for("social.auth", backend="twilio") }}">Twilio</a> <br />
+<a href="{{ url_for("social.auth", backend="xing") }}">Xing OAuth</a> <br />
+<a href="{{ url_for("social.auth", backend="yandex-oauth2") }}">Yandex OAuth2</a> <br />
+<a href="{{ url_for("social.auth", backend="podio") }}">Podio OAuth2</a> <br />
+<a href="{{ url_for("social.auth", backend="mineid") }}">MineID OAuth2</a> <br />
+
+<form action="{{ url_for("social.auth", backend="openid") }}" method="post">
+  <div>
+    <label for="openid_identifier">OpenId provider</label>
+    <input id="openid_identifier" type="text" value="" name="openid_identifier" />
+    <input type="submit" value="Login" />
+  </div>
+</form>
+
+<form action="{{ url_for("social.auth", backend="livejournal") }}" method="post">
+  <div>
+    <label for="openid_lj_identifier">LiveJournal ID</label>
+    <input id="openid_lj_identifier" type="text" value="" name="openid_lj_user" />
+    <input type="submit" value="Login" />
+  </div>
+</form>
+
+<form method="post" action="{{ url_for("social.complete", backend="persona") }}">
+  <input type="hidden" name="assertion" value="" />
+  <a rel="nofollow" id="persona" href="#">Persona</a>
+</form>
+{% endblock %}
+
+{% block scripts %}
+<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js" type="text/javascript"></script>
+<script src="https://login.persona.org/include.js" type="text/javascript"></script>
+<script type="text/javascript">
+$(function () {
+    $('#persona').on('click', function (e) {
+        e.preventDefault();
+        var self = $(this);
+
+        navigator.id.get(function (assertion) {
+            if (assertion) {
+                self.parent('form')
+                        .find('input[type=hidden]')
+                        .attr('value', assertion)
+                        .end()
+                    .submit();
+            } else {
+                alert('Some error occurred');
+            }
+        });
+    });
+});
+</script>
+{% endblock %}
diff --git a/social/apps/flask_app/peewee/__init__.py b/social/apps/flask_app/peewee/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/social/apps/flask_app/peewee/models.py b/social/apps/flask_app/peewee/models.py
new file mode 100644
index 0000000..774ced6
--- /dev/null
+++ b/social/apps/flask_app/peewee/models.py
@@ -0,0 +1,48 @@
+"""Flask SQLAlchemy ORM models for Social Auth"""
+from peewee import Model, ForeignKeyField, Proxy
+
+from social.utils import setting_name, module_member
+from social.storage.peewee_orm import PeeweeUserMixin, \
+                                           PeeweeAssociationMixin, \
+                                           PeeweeNonceMixin, \
+                                           PeeweeCodeMixin, \
+                                           BasePeeweeStorage, \
+                                           database_proxy
+
+
+class FlaskStorage(BasePeeweeStorage):
+    user = None
+    nonce = None
+    association = None
+    code = None
+
+
+def init_social(app, db):
+    User = module_member(app.config[setting_name('USER_MODEL')])
+
+    database_proxy.initialize(db)
+
+    class UserSocialAuth(PeeweeUserMixin):
+        """Social Auth association model"""
+        user = ForeignKeyField(User, related_name='social_auth')
+
+        @classmethod
+        def user_model(cls):
+            return User
+
+    class Nonce(PeeweeNonceMixin):
+        """One use numbers"""
+        pass
+
+    class Association(PeeweeAssociationMixin):
+        """OpenId account association"""
+        pass
+
+    class Code(PeeweeCodeMixin):
+        pass
+
+    # Set the references in the storage class
+    FlaskStorage.user = UserSocialAuth
+    FlaskStorage.nonce = Nonce
+    FlaskStorage.association = Association
+    FlaskStorage.code = Code
diff --git a/social/storage/peewee_orm.py b/social/storage/peewee_orm.py
new file mode 100644
index 0000000..66d0d49
--- /dev/null
+++ b/social/storage/peewee_orm.py
@@ -0,0 +1,199 @@
+import six
+import base64
+
+from peewee import CharField, Model, Proxy, IntegrityError
+from playhouse.kv import JSONField
+
+from social.storage.base import UserMixin, AssociationMixin, NonceMixin, \
+    CodeMixin, BaseStorage
+
+
+def get_query_by_dict_param(cls, params):
+    q = True
+    for field_name, value in params.iteritems():
+        query_item = cls._meta.fields[field_name] == value
+        
+        q = q & query_item
+
+        return q
+
+
+database_proxy = Proxy()
+
+
+class BaseModel(Model):
+    class Meta:
+        database = database_proxy
+
+
+class PeeweeUserMixin(UserMixin, BaseModel):
+    provider = CharField()
+    extra_data = JSONField(null=True)
+    uid = CharField()
+    user = None
+
+    @classmethod
+    def changed(cls, user):
+        user.save()
+
+    def set_extra_data(self, extra_data=None):
+        if super(PeeweeUserMixin, self).set_extra_data(extra_data):
+            self.save()
+
+    @classmethod
+    def username_max_length(cls):
+        username_field = cls.username_field()
+        field = getattr(cls.user_model(), username_field)
+        return field.max_length
+
+    @classmethod
+    def username_field(cls):
+        return getattr(cls.user_model(), 'USERNAME_FIELD', 'username')
+
+    @classmethod
+    def allowed_to_disconnect(cls, user, backend_name, association_id=None):
+        if association_id is not None:
+            qs = cls.select().where(cls.id != association_id)
+        else:
+            qs = cls.select().where(cls.provider != backend_name)
+        qs = qs.where(cls.user == user)
+
+        if hasattr(user, 'has_usable_password'):
+            valid_password = user.has_usable_password()
+        else:
+            valid_password = True
+        return valid_password or qs.count() > 0
+
+    @classmethod
+    def disconnect(cls, entry):
+        entry.delete_instance()
+
+    @classmethod
+    def user_exists(cls, *args, **kwargs):
+        """
+        Return True/False if a User instance exists with the given arguments.
+        """
+        user_model = cls.user_model()
+
+        q = get_query_by_dict_param(user_model, kwargs)
+
+        return user_model.select().where(q).count() > 0
+
+    @classmethod
+    def get_username(cls, user):
+        return getattr(user, cls.username_field(), None)
+
+    @classmethod
+    def create_user(cls, *args, **kwargs):
+        username_field = cls.username_field()
+        if 'username' in kwargs and username_field not in kwargs:
+            kwargs[username_field] = kwargs.pop('username')
+        return cls.user_model().create(*args, **kwargs)
+
+    @classmethod
+    def get_user(cls, pk, **kwargs):
+        if pk:
+            kwargs = {'id': pk}
+        try:
+            return cls.user_model().select().get(get_query_by_dict_param(cls.user_model(), kwargs))
+        except cls.user_model().DoesNotExist:
+            return None
+
+    @classmethod
+    def get_users_by_email(cls, email):
+        user_model = cls.user_model()
+        return user_model.select().where(user_model.email == email)
+
+    @classmethod
+    def get_social_auth(cls, provider, uid):
+        if not isinstance(uid, six.string_types):
+            uid = str(uid)
+        try:
+            return cls.select().where(cls.provider == provider, cls.uid == uid).get()
+        except cls.DoesNotExist:
+            return None
+
+    @classmethod
+    def get_social_auth_for_user(cls, user, provider=None, id=None):
+        qs = cls.select().where(cls.user == user)
+        if provider:
+            qs = qs.where(cls.provider == provider)
+        if id:
+            qs = qs.where(cls.id == id)
+        return list(qs)
+
+    @classmethod
+    def create_social_auth(cls, user, uid, provider):
+        if not isinstance(uid, six.string_types):
+            uid = str(uid)
+        return cls.create(user=user, uid=uid, provider=provider)
+
+
+class PeeweeNonceMixin(NonceMixin, BaseModel):
+    server_url = CharField()
+    timestamp = CharField()
+    salt = CharField()
+
+    @classmethod
+    def use(cls, server_url, timestamp, salt):
+        return cls.select().get_or_create(cls.server_url == server_url,
+                                          cls.timestamp == timestamp,
+                                          cls.salt == salt)
+
+
+class PeeweeAssociationMixin(AssociationMixin, BaseModel):
+    server_url = CharField()
+    handle = CharField()
+    secret = CharField()  # base64 encoded
+    issued = CharField()
+    lifetime = CharField()
+    assoc_type = CharField()
+
+
+    @classmethod
+    def store(cls, server_url, association):
+        try:
+            assoc = cls.select().get(cls.server_url == server_url,
+                                     cls.handle == association.handle)
+        except cls.DoesNotExist:
+            assoc = cls(server_url=server_url,
+                        handle=association.handle)
+
+        assoc.secret = base64.encodestring(association.secret)
+        assoc.issued = association.issued
+        assoc.lifetime = association.lifetime
+        assoc.assoc_type = association.assoc_type
+        assoc.save()
+
+    @classmethod
+    def get(cls, *args, **kwargs):
+        q = get_query_by_dict_param(cls, kwargs)
+        return cls.select().where(q)
+
+    @classmethod
+    def remove(cls, ids_to_delete):
+        cls.select().where(cls.id << ids_to_delete).delete()
+
+
+class PeeweeCodeMixin(CodeMixin, BaseModel):
+    email = CharField()
+    code = CharField()  # base64 encoded
+    issued = CharField()
+
+    @classmethod
+    def get_code(cls, code):
+        try:
+            return cls.select().get(cls.code == code)
+        except cls.DoesNotExist:
+            return None
+
+
+class BasePeeweeStorage(BaseStorage):
+    user = PeeweeUserMixin
+    nonce = PeeweeNonceMixin
+    association = PeeweeAssociationMixin
+    code = PeeweeCodeMixin
+
+    @classmethod
+    def is_integrity_error(cls, exception):
+        return exception.__class__ is IntegrityError

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-social-auth.git



More information about the Python-modules-commits mailing list