Skip to content
This repository has been archived by the owner on Feb 22, 2024. It is now read-only.

1.6.3.dev1 #74

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.tox/*
.DS_Store
*.pyc
*.egg
Expand All @@ -8,4 +9,4 @@
config.py
build
_build
dist
dist
12 changes: 8 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@ language: python
python:
- "2.6"
- "2.7"
- "3.3"
- "3.4"
- "3.5"

install:
- pip install . --quiet --use-mirrors
- "if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then pip install importlib --quiet --use-mirrors; fi"
- pip install nose simplejson Flask-SQLAlchemy Flask-MongoEngine Flask-Peewee Flask-Mail mock MySQL-python --quiet --use-mirrors
- pip install oauth2client google-api-python-client foursquare python-twitter --quiet --use-mirrors
- pip install . --quiet
- pip install setuptools nose simplejson Flask-SQLAlchemy Flask-MongoEngine Flask-Peewee Flask-Mail mock --quiet
- pip install oauth2client google-api-python-client
- pip install https://pypi.python.org/packages/source/f/foursquare/foursquare-1!2015.5.26.tar.gz#md5=cf22b486e38dab5ad584521112e405b4
- pip install https://github.com/bear/python-twitter/archive/v3.0.zip
- pip install http://github.com/pythonforfacebook/facebook-sdk/tarball/master --quiet

before_script:
Expand Down
6 changes: 6 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,9 @@ Resources
- `Development Version
<http://github.com/mattupstate/flask-rq/zipball/develop#egg=Flask-Social-dev>`_
- `Example Application <http://flask-social-example.herokuapp.com/>`_

Developers info
---------------

- `Easy way for local testing is Tox <https://testrun.org/tox/latest/index.html>`_
- `Tests required MongoDB avaliable on localhost <https://www.mongodb.org/>`_
9 changes: 6 additions & 3 deletions flask_social/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@
:license: MIT, see LICENSE for more details.
"""

__version__ = '1.6.2'
__version__ = '1.6.3.dev1'

from future import standard_library
standard_library.install_aliases()

from .core import Social
from .datastore import SQLAlchemyConnectionDatastore, \
MongoEngineConnectionDatastore, PeeweeConnectionDatastore
MongoEngineConnectionDatastore, PeeweeConnectionDatastore
from .signals import connection_created, connection_failed, login_failed, \
connection_removed, login_completed
connection_removed, login_completed
37 changes: 28 additions & 9 deletions flask_social/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,21 @@
"""
from importlib import import_module

from flask import current_app
from flask import current_app, _request_ctx_stack
try:
from flask import _app_ctx_stack
except ImportError:
_app_ctx_stack = None
from flask_oauthlib.client import OAuthRemoteApp as BaseRemoteApp
from flask.ext.security import current_user
from werkzeug.local import LocalProxy

from .utils import get_config, update_recursive
from .views import create_blueprint

# Select stack, in flask 0.9 _app_ctx_stack is used
_ctx_stack = _app_ctx_stack or _request_ctx_stack

_security = LocalProxy(lambda: current_app.extensions['security'])

_social = LocalProxy(lambda: current_app.extensions['social'])
Expand Down Expand Up @@ -58,7 +65,7 @@ def get_api(self):
consumer_secret=self.consumer_secret)


def _get_state(app, datastore, providers, **kwargs):
def create_state(app, datastore, providers, **kwargs):
config = get_config(app)

for key in providers.keys():
Expand Down Expand Up @@ -96,14 +103,23 @@ def _get_token():
return None


def get_state(app):
"""Get social state of the app"""
# TODO check if right to use assert
assert 'social' in app.extensions, "The Social extension was not registered to the current application." \
"Please make sure to call init_app() first."
return app.extensions['social']


class Social(object):

def __init__(self, app=None, datastore=None):
self._state = None
self.app = app
self.datastore = datastore

if app is not None and datastore is not None:
self._state = self.init_app(app, datastore)
self.init_app(app, datastore)

def init_app(self, app, datastore=None):
"""Initialize the application with the Social extension
Expand Down Expand Up @@ -132,12 +148,15 @@ def init_app(self, app, datastore=None):
providers[config['id']] = OAuthRemoteApp(**config)
providers[config['id']].tokengetter(_get_token)

state = _get_state(app, datastore, providers)

app.register_blueprint(create_blueprint(state, __name__))
app.extensions['social'] = state
self._state = create_state(app, datastore, providers)

return state
app.register_blueprint(create_blueprint(self._state, __name__))
app.extensions['social'] = self._state

def __getattr__(self, name):
return getattr(self._state, name, None)
if self._state is not None: # shortcut
return getattr(self._state, name, None)
ctx = _ctx_stack.top
if ctx is not None:
self._state = get_state(ctx.app)
return getattr(self._state, name)
5 changes: 2 additions & 3 deletions flask_social/providers/foursquare.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from __future__ import absolute_import

import foursquare
import urlparse
from urllib.parse import urljoin

config = {
'id': 'foursquare',
Expand Down Expand Up @@ -47,8 +47,7 @@ def get_connection_values(response, **kwargs):
api = foursquare.Foursquare(access_token=access_token)
user = api.users()['user']
profile_url = 'http://www.foursquare.com/user/' + user['id']
image_url = urlparse.urljoin(user['photo']['prefix'],
user['photo']['suffix'])
image_url = urljoin(user['photo']['prefix'], user['photo']['suffix'])

return dict(
provider_id=config['id'],
Expand Down
4 changes: 3 additions & 1 deletion flask_social/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,12 @@ def get_connection_values_from_oauth_response(provider, oauth_response):
consumer_key=provider.consumer_key,
consumer_secret=provider.consumer_secret)


def get_token_pair_from_oauth_response(provider, oauth_response):
module = import_module(provider.module)
return module.get_token_pair_from_response(oauth_response)


def get_config(app):
"""Conveniently get the social configuration for the specified
application without the annoying 'SOCIAL_' prefix.
Expand All @@ -68,7 +70,7 @@ def strip_prefix(tup):


def update_recursive(d, u):
for k, v in u.iteritems():
for k, v in u.items():
if isinstance(v, collections.Mapping):
r = update_recursive(d.get(k, {}), v)
d[k] = r
Expand Down
5 changes: 3 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

setup(
name='Flask-Social',
version='1.6.2',
version='1.6.3.dev1',
url='https://github.com/mattupstate/flask-social',
license='MIT',
author='Matthew Wright',
Expand All @@ -34,7 +34,8 @@
include_package_data=True,
platforms='any',
install_requires=[
'Flask-Security>=1.6.9',
'future>=0.15.2',
'Flask-Security>=1.7.5',
'Flask-OAuthlib==0.5.0'
],
test_suite='nose.collector',
Expand Down
8 changes: 7 additions & 1 deletion tests/functional_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from tests.test_app.mongoengine import create_app as create_mongo_app
from tests.test_app.peewee_app import create_app as create_peewee_app


def get_mock_twitter_response():
return {
'oauth_token_secret': 'the_oauth_token_secret',
Expand All @@ -26,18 +27,21 @@ def get_mock_twitter_connection_values():
'image_url': 'https://cdn.twitter.com/something.png'
}


def get_mock_twitter_token_pair():
return {
'access_token': 'the_oauth_token',
'secret': 'the_oauth_token_secret'
}


def get_mock_twitter_updated_token_pair():
return {
'access_token': 'the_updated_oauth_token',
'secret': 'the_updated_oauth_token_secret'
}


class SocialTest(unittest.TestCase):

SOCIAL_CONFIG = None
Expand Down Expand Up @@ -81,7 +85,8 @@ def authenticate(self, email="[email protected]", password="password", endpoint=None,

def assertIn(self, member, container, msg=None):
if hasattr(unittest.TestCase, 'assertIn'):
return unittest.TestCase.assertIn(self, member, container, msg)
# container from bytes -> str
return unittest.TestCase.assertIn(self, member, str(container), msg)

return self.assertTrue(member in container)

Expand Down Expand Up @@ -278,5 +283,6 @@ def test_remove_connection(self,
class MongoEngineTwitterSocialTests(TwitterSocialTests):
APP_TYPE = 'mongo'


class PeeweeTwitterSocialTests(TwitterSocialTests):
APP_TYPE = 'peewee'
13 changes: 9 additions & 4 deletions tests/test_app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@

from flask import Flask, render_template, current_app
from flask.ext.security import login_required
from flask.ext.social import Social
from werkzeug import url_decode


social = Social()


class Config(object):

WTF_CSRF_ENABLED = False
Expand Down Expand Up @@ -86,15 +91,15 @@ def index():
@app.route('/profile')
@login_required
def profile():
twitter = current_app.social.twitter
twitter = social.twitter
twitter.get_api()

return render_template(
'profile.html',
content='Profile Page',
twitter_conn=twitter.get_connection(),
google_conn=current_app.social.google.get_connection(),
facebook_conn=current_app.social.facebook.get_connection(),
foursquare_conn=current_app.social.foursquare.get_connection())
google_conn=social.google.get_connection(),
facebook_conn=social.facebook.get_connection(),
foursquare_conn=social.foursquare.get_connection())

return app
8 changes: 4 additions & 4 deletions tests/test_app/sqlalchemy.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@

from flask.ext.security import Security, UserMixin, RoleMixin, \
SQLAlchemyUserDatastore
from flask.ext.social import Social, SQLAlchemyConnectionDatastore
from flask.ext.social import SQLAlchemyConnectionDatastore
from flask.ext.sqlalchemy import SQLAlchemy

from tests.test_app import create_app as create_base_app, populate_data
from tests.test_app import create_app as create_base_app, populate_data, \
social


def create_app(config=None, debug=True):
Expand Down Expand Up @@ -53,15 +54,14 @@ class Connection(db.Model):
rank = db.Column(db.Integer)

app.security = Security(app, SQLAlchemyUserDatastore(db, User, Role))
app.social = Social(app, SQLAlchemyConnectionDatastore(db, Connection))
social.init_app(app, SQLAlchemyConnectionDatastore(db, Connection))

@app.before_first_request
def before_first_request():
db.drop_all()
db.create_all()
populate_data()


app.get_user = lambda: User.query.first()
return app

Expand Down
4 changes: 2 additions & 2 deletions tests/test_app/templates/_nav.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{%- if current_user.is_authenticated() -%}
{%- if current_user.is_authenticated -%}
<p>Hello {{ current_user.email }}</p>
{%- endif %}
<ul>
<li><a href="{{ url_for('index') }}">Index</a></li>
<li><a href="{{ url_for('profile') }}">Profile</a></li>
<li>
{%- if current_user.is_authenticated() -%}
{%- if current_user.is_authenticated -%}
<a href="{{ url_for('security.logout') }}">Log out</a>
{%- else -%}
<a href="{{ url_for('security.login') }}">Log in</a>
Expand Down
17 changes: 17 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[tox]
envlist = py26,py27,py33,py34,py35

[testenv]
deps = nose
future
mock
httplib2
Flask-SQLAlchemy
Flask-MongoEngine
Flask-Peewee
https://github.com/bear/python-twitter/archive/v3.0.zip
http://github.com/pythonforfacebook/facebook-sdk/tarball/master
foursquare
oauth2client
google-api-python-client
commands = nosetests []