diff --git a/.travis.yml b/.travis.yml index d5ab4bc..649a5c3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,10 +25,12 @@ addons: postgresql: 9.4 +dist: trusty + notifications: email: false -sudo: false +sudo: true language: python diff --git a/invenio_webhooks/_compat.py b/invenio_webhooks/_compat.py new file mode 100644 index 0000000..4a7efd3 --- /dev/null +++ b/invenio_webhooks/_compat.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# +# This file is part of Invenio. +# Copyright (C) 2018 CERN. +# +# Invenio is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# Invenio is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Invenio; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307, USA. +# +# In applying this license, CERN does not +# waive the privileges and immunities granted to it by virtue of its status +# as an Intergovernmental Organization or submit itself to any jurisdiction. + +"""Compatibility module for Flask.""" + +from __future__ import absolute_import + +from distutils.version import LooseVersion as V + +from pkg_resources import get_distribution + +_FLASK_CURRENT_VERSION = V(get_distribution('flask').version) +_FLASK_VERSION_WITH_BUG = V('0.12') + + +def delete_cached_json_for(request): + """Delete `_cached_json` attribute for the given request. + + Bug workaround to delete `_cached_json` attribute when using Flask < 0.12. + More details: https://github.com/pallets/flask/issues/2087 + + Note that starting from Flask 1.0, the private `_cached_json` attribute + has been changed in Flask package, and this code will fail. + """ + if _FLASK_CURRENT_VERSION < _FLASK_VERSION_WITH_BUG: + if hasattr(request, '_cached_json'): + delattr(request, '_cached_json') diff --git a/invenio_webhooks/models.py b/invenio_webhooks/models.py index b819e76..1a18a15 100644 --- a/invenio_webhooks/models.py +++ b/invenio_webhooks/models.py @@ -41,6 +41,7 @@ from sqlalchemy_utils.types import JSONType, UUIDType from . import signatures +from ._compat import delete_cached_json_for from .errors import InvalidPayload, InvalidSignature, ReceiverDoesNotExist from .proxies import current_webhooks @@ -132,8 +133,7 @@ def extract_payload(self): raise InvalidSignature('Invalid Signature') if request.is_json: # Request.get_json() could be first called with silent=True. - if hasattr(request, '_cached_json'): - delattr(request, '_cached_json') + delete_cached_json_for(request) return request.get_json(silent=False, cache=False) elif request.content_type == 'application/x-www-form-urlencoded': return dict(request.form) diff --git a/invenio_webhooks/views.py b/invenio_webhooks/views.py index ab0248c..658d6d5 100644 --- a/invenio_webhooks/views.py +++ b/invenio_webhooks/views.py @@ -85,7 +85,7 @@ def make_response(event): # Default decorators # def error_handler(f): - """Decorator to handle exceptions.""" + """Return a json payload and appropriate status code on expection.""" @wraps(f) def inner(*args, **kwargs): try: diff --git a/setup.cfg b/setup.cfg index 5e98d5d..81c118c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -34,6 +34,9 @@ all_files = 1 [bdist_wheel] universal = 1 +[pydocstyle] +add_ignore = D401 + [compile_catalog] directory = invenio_webhooks/translations/ diff --git a/setup.py b/setup.py index eafa8ea..d35d313 100644 --- a/setup.py +++ b/setup.py @@ -34,14 +34,14 @@ tests_require = [ 'Flask-CeleryExt>=0.2.2', 'SQLAlchemy-Continuum>=1.2.1', - 'check-manifest>=0.25', - 'coverage>=4.0', - 'isort>=4.2.2', - 'pydocstyle>=1.0.0', + 'check-manifest>=0.35', + 'coverage>=4.4.1', + 'isort>=4.3', + 'pydocstyle>=2.0.0', 'pytest-cache>=1.0', - 'pytest-cov>=1.8.0', + 'pytest-cov>=2.5.1', 'pytest-pep8>=1.0.6', - 'pytest>=2.8.0', + 'pytest>=3.3.1', ] extras_require = { @@ -49,16 +49,16 @@ 'celery>=3.1,<4.0', ], 'docs': [ - 'Sphinx>=1.4.2', + 'Sphinx>=1.5.2', ], 'mysql': [ - 'invenio-db[mysql]>=1.0.0b3', + 'invenio-db[mysql]>=1.0.0b8', ], 'postgresql': [ - 'invenio-db[postgresql]>=1.0.0b3', + 'invenio-db[postgresql]>=1.0.0b8', ], 'sqlite': [ - 'invenio-db>=1.0.0b3', + 'invenio-db>=1.0.0b8', ], 'tests': tests_require, } @@ -70,16 +70,18 @@ extras_require['all'].extend(reqs) setup_requires = [ - 'Babel>=1.3', - 'pytest-runner>=2.6.2', + 'Babel>=2.4.0', + 'pytest-runner>=3.0.0,<5', ] install_requires = [ 'Flask-BabelEx>=0.9.2', 'Flask>=0.11.1', + 'SQLAlchemy>=1.1.5', + 'SQLAlchemy-Utils>=0.32.9', 'cryptography>=1.3.1', - 'invenio-accounts>=1.0.0b1', - 'invenio-oauth2server>=1.0.0a13', + 'invenio-accounts>=1.0.0b9', + 'invenio-oauth2server>=1.0.0b4', ] packages = find_packages() diff --git a/tests/conftest.py b/tests/conftest.py index db3d4f7..e5cc42b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -39,7 +39,7 @@ from invenio_accounts import InvenioAccounts from invenio_accounts.views import blueprint as accounts_blueprint from invenio_db import InvenioDB, db -from invenio_oauth2server import InvenioOAuth2Server +from invenio_oauth2server import InvenioOAuth2Server, InvenioOAuth2ServerREST from invenio_oauth2server.models import Token from invenio_oauth2server.views import server_blueprint, settings_blueprint from sqlalchemy_utils.functions import create_database, database_exists, \ @@ -55,6 +55,7 @@ def app(request): """Flask application fixture.""" app = Flask('testapp') app.config.update( + ACCOUNTS_JWT_ENABLE=False, BROKER_TRANSPORT='redis', CELERY_ALWAYS_EAGER=True, CELERY_CACHE_BACKEND='memory', @@ -84,6 +85,7 @@ def app(request): InvenioAccounts(app) app.register_blueprint(accounts_blueprint) InvenioOAuth2Server(app) + InvenioOAuth2ServerREST(app) app.register_blueprint(server_blueprint) app.register_blueprint(settings_blueprint) InvenioWebhooks(app)