From ea74facfa04cfd106040b9ac059fe0595511b2bd Mon Sep 17 00:00:00 2001 From: KeNaCo Date: Wed, 6 Jan 2016 23:19:17 +0100 Subject: [PATCH 01/14] set version to 1.6.3.dev1 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 1aafcc6..6beb279 100644 --- a/setup.py +++ b/setup.py @@ -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', From 60789823ae5bd6f0b484829b97af270615f5b98f Mon Sep 17 00:00:00 2001 From: KeNaCo Date: Wed, 6 Jan 2016 21:59:41 +0100 Subject: [PATCH 02/14] provide config for tox to local multiplne python versions testing --- tox.ini | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 tox.ini diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..3c16049 --- /dev/null +++ b/tox.ini @@ -0,0 +1,16 @@ +[tox] +envlist = py26,py27 + +[testenv] +deps = nose + mock + httplib2 + Flask-SQLAlchemy + Flask-MongoEngine + Flask-Peewee + python-twitter + http://github.com/pythonforfacebook/facebook-sdk/tarball/master + foursquare + oauth2client + google-api-python-client +commands = nosetests [] From 7be1a9e691d09cf9c321546587fefb77c1bb2fce Mon Sep 17 00:00:00 2001 From: KeNaCo Date: Thu, 7 Jan 2016 00:03:01 +0100 Subject: [PATCH 03/14] Add future library, fixes backbort importlib to py2.6 --- flask_social/__init__.py | 7 +++++-- setup.py | 1 + tox.ini | 21 +++++++++++---------- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/flask_social/__init__.py b/flask_social/__init__.py index f3400fa..5f6d129 100644 --- a/flask_social/__init__.py +++ b/flask_social/__init__.py @@ -12,8 +12,11 @@ __version__ = '1.6.2' +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 diff --git a/setup.py b/setup.py index 6beb279..141de11 100644 --- a/setup.py +++ b/setup.py @@ -34,6 +34,7 @@ include_package_data=True, platforms='any', install_requires=[ + 'future>=0.15.2', 'Flask-Security>=1.6.9', 'Flask-OAuthlib==0.5.0' ], diff --git a/tox.ini b/tox.ini index 3c16049..ccf80bc 100644 --- a/tox.ini +++ b/tox.ini @@ -3,14 +3,15 @@ envlist = py26,py27 [testenv] deps = nose - mock - httplib2 - Flask-SQLAlchemy - Flask-MongoEngine - Flask-Peewee - python-twitter - http://github.com/pythonforfacebook/facebook-sdk/tarball/master - foursquare - oauth2client - google-api-python-client + future + mock + httplib2 + Flask-SQLAlchemy + Flask-MongoEngine + Flask-Peewee + python-twitter + http://github.com/pythonforfacebook/facebook-sdk/tarball/master + foursquare + oauth2client + google-api-python-client commands = nosetests [] From 62c3f9f06759c86f93ca7e6fa29431389043f258 Mon Sep 17 00:00:00 2001 From: KeNaCo Date: Thu, 7 Jan 2016 00:14:29 +0100 Subject: [PATCH 04/14] Fixes is_authenticated property issue, according this set Flask-Security>=1.7.5 --- setup.py | 2 +- tests/test_app/templates/_nav.html | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 141de11..5deb41d 100644 --- a/setup.py +++ b/setup.py @@ -35,7 +35,7 @@ platforms='any', install_requires=[ 'future>=0.15.2', - 'Flask-Security>=1.6.9', + 'Flask-Security>=1.7.5', 'Flask-OAuthlib==0.5.0' ], test_suite='nose.collector', diff --git a/tests/test_app/templates/_nav.html b/tests/test_app/templates/_nav.html index 0aeab1d..26cfc77 100644 --- a/tests/test_app/templates/_nav.html +++ b/tests/test_app/templates/_nav.html @@ -1,11 +1,11 @@ -{%- if current_user.is_authenticated() -%} +{%- if current_user.is_authenticated -%}

Hello {{ current_user.email }}

{%- endif %}
  • Index
  • Profile
  • - {%- if current_user.is_authenticated() -%} + {%- if current_user.is_authenticated -%} Log out {%- else -%} Log in From 31abcd5083d2388a1283ce94e3c35f55cbc2f1e8 Mon Sep 17 00:00:00 2001 From: KeNaCo Date: Thu, 7 Jan 2016 00:40:10 +0100 Subject: [PATCH 05/14] Missing version uprate in __init__ --- flask_social/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flask_social/__init__.py b/flask_social/__init__.py index f3400fa..ad2cd64 100644 --- a/flask_social/__init__.py +++ b/flask_social/__init__.py @@ -10,7 +10,7 @@ :license: MIT, see LICENSE for more details. """ -__version__ = '1.6.2' +__version__ = '1.6.3.dev1' from .core import Social from .datastore import SQLAlchemyConnectionDatastore, \ From bc3cf9af2401a123948e7a148b990526bd479dd0 Mon Sep 17 00:00:00 2001 From: KeNaCo Date: Fri, 8 Jan 2016 00:16:07 +0100 Subject: [PATCH 06/14] MySQL-python requirement removed from travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6eaab61..df5b6d4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ python: 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 nose simplejson Flask-SQLAlchemy Flask-MongoEngine Flask-Peewee Flask-Mail mock --quiet --use-mirrors - pip install oauth2client google-api-python-client foursquare python-twitter --quiet --use-mirrors - pip install http://github.com/pythonforfacebook/facebook-sdk/tarball/master --quiet From 3bba3fc87df50cf8e5b01525c0625d6c01b9c61e Mon Sep 17 00:00:00 2001 From: KeNaCo Date: Thu, 7 Jan 2016 01:17:07 +0100 Subject: [PATCH 07/14] Add python versions 3.3, 3.4, 3.5 to test configs --- .travis.yml | 3 +++ tox.ini | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index df5b6d4..016fb98 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,9 @@ language: python python: - "2.6" - "2.7" + - "3.3" + - "3.4" + - "3.5" install: - pip install . --quiet --use-mirrors diff --git a/tox.ini b/tox.ini index ccf80bc..ffdd42b 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py26,py27 +envlist = py26,py27,py33,py34,py35 [testenv] deps = nose From e28e31169405b698ae52e3a3ed8f1f2a335616fc Mon Sep 17 00:00:00 2001 From: KeNaCo Date: Thu, 7 Jan 2016 23:26:07 +0100 Subject: [PATCH 08/14] Test with python-twitter==3.0.rc1, lower version dont have python3 support --- .travis.yml | 4 ++-- tox.ini | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 016fb98..677cc90 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,9 +9,9 @@ python: 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 --quiet --use-mirrors - - pip install oauth2client google-api-python-client foursquare python-twitter --quiet --use-mirrors + - pip install oauth2client google-api-python-client foursquare --quiet --use-mirrors + - 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: diff --git a/tox.ini b/tox.ini index ffdd42b..06c1008 100644 --- a/tox.ini +++ b/tox.ini @@ -9,7 +9,7 @@ deps = nose Flask-SQLAlchemy Flask-MongoEngine Flask-Peewee - python-twitter + https://github.com/bear/python-twitter/archive/v3.0.zip http://github.com/pythonforfacebook/facebook-sdk/tarball/master foursquare oauth2client From 673d0dc34cb2d43150ed674720e7b72038dd29f5 Mon Sep 17 00:00:00 2001 From: KeNaCo Date: Thu, 7 Jan 2016 23:47:53 +0100 Subject: [PATCH 09/14] Fix urlparse renamed to urllib.parse in python 3.x, used {}.items instead of .iteritems --- flask_social/providers/foursquare.py | 5 ++--- flask_social/utils.py | 4 +++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/flask_social/providers/foursquare.py b/flask_social/providers/foursquare.py index 57a4f73..77399cf 100644 --- a/flask_social/providers/foursquare.py +++ b/flask_social/providers/foursquare.py @@ -12,7 +12,7 @@ from __future__ import absolute_import import foursquare -import urlparse +from urllib.parse import urljoin config = { 'id': 'foursquare', @@ -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'], diff --git a/flask_social/utils.py b/flask_social/utils.py index fd37021..acea74f 100644 --- a/flask_social/utils.py +++ b/flask_social/utils.py @@ -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. @@ -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 From 1ba6faab9f6e75961f5ba69b88a133c8caab9691 Mon Sep 17 00:00:00 2001 From: KeNaCo Date: Thu, 7 Jan 2016 23:57:11 +0100 Subject: [PATCH 10/14] Fix tests fails because of byte-string incompatibility in py3.x --- tests/functional_tests.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/functional_tests.py b/tests/functional_tests.py index 136ecce..70ec9d7 100644 --- a/tests/functional_tests.py +++ b/tests/functional_tests.py @@ -81,7 +81,8 @@ def authenticate(self, email="matt@lp.com", 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) From 047018f1af805bdc893e2282e5f51d2628433ee5 Mon Sep 17 00:00:00 2001 From: KeNaCo Date: Fri, 8 Jan 2016 00:26:24 +0100 Subject: [PATCH 11/14] Update travis config --- .travis.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 677cc90..e82a9ea 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,9 +8,10 @@ python: - "3.5" install: - - pip install . --quiet --use-mirrors - - pip install nose simplejson Flask-SQLAlchemy Flask-MongoEngine Flask-Peewee Flask-Mail mock --quiet --use-mirrors - - pip install oauth2client google-api-python-client foursquare --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 From be566f35991120927f446a097fff5ab0d9d6c49e Mon Sep 17 00:00:00 2001 From: KeNaCo Date: Mon, 25 Jan 2016 21:35:29 +0100 Subject: [PATCH 12/14] Add some developer info to README; extend ignored file with .tox folder --- .gitignore | 3 ++- README.rst | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index b8e085d..7aae853 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.tox/* .DS_Store *.pyc *.egg @@ -8,4 +9,4 @@ config.py build _build -dist +dist \ No newline at end of file diff --git a/README.rst b/README.rst index 7528f7f..47dd022 100644 --- a/README.rst +++ b/README.rst @@ -23,3 +23,9 @@ Resources - `Development Version `_ - `Example Application `_ + +Developers info +--------------- + +- `Easy way for local testing is Tox `_ +- `Tests required MongoDB avaliable on localhost `_ From 951e653ca15713641e9fccaced5332f860ca35ab Mon Sep 17 00:00:00 2001 From: KeNaCo Date: Tue, 26 Jan 2016 00:05:24 +0100 Subject: [PATCH 13/14] Flask factory pattern - tests #73 --- tests/functional_tests.py | 5 +++++ tests/test_app/__init__.py | 13 +++++++++---- tests/test_app/sqlalchemy.py | 8 ++++---- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/tests/functional_tests.py b/tests/functional_tests.py index 70ec9d7..b79ded0 100644 --- a/tests/functional_tests.py +++ b/tests/functional_tests.py @@ -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', @@ -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 @@ -279,5 +283,6 @@ def test_remove_connection(self, class MongoEngineTwitterSocialTests(TwitterSocialTests): APP_TYPE = 'mongo' + class PeeweeTwitterSocialTests(TwitterSocialTests): APP_TYPE = 'peewee' diff --git a/tests/test_app/__init__.py b/tests/test_app/__init__.py index 9de208a..61717d2 100644 --- a/tests/test_app/__init__.py +++ b/tests/test_app/__init__.py @@ -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 @@ -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 diff --git a/tests/test_app/sqlalchemy.py b/tests/test_app/sqlalchemy.py index 88cac7a..a2bc489 100644 --- a/tests/test_app/sqlalchemy.py +++ b/tests/test_app/sqlalchemy.py @@ -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): @@ -53,7 +54,7 @@ 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(): @@ -61,7 +62,6 @@ def before_first_request(): db.create_all() populate_data() - app.get_user = lambda: User.query.first() return app From 641571ced475a7894c02bdd2611b5d1e088b307f Mon Sep 17 00:00:00 2001 From: KeNaCo Date: Tue, 26 Jan 2016 01:24:05 +0100 Subject: [PATCH 14/14] Fix #73 - Flask factory pattern --- flask_social/core.py | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/flask_social/core.py b/flask_social/core.py index 47fc741..12ec1af 100644 --- a/flask_social/core.py +++ b/flask_social/core.py @@ -10,7 +10,11 @@ """ 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 @@ -18,6 +22,9 @@ 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']) @@ -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(): @@ -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 @@ -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)