[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