From db3025737387ee85101212cf529bd75390ff4c22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=2E=20Fernando=20S=C3=A1nchez?= Date: Tue, 10 Jan 2017 11:10:10 +0100 Subject: [PATCH] Flake8, Semver, Pre-commit * Added pre-commit: http://pre-commit.com * Fixed flake8 errors * Added flake8 pre-commit hooks * Added pre-commit to Makefile * Changed VERSION numbering * Changed versioning to match PEP-0440 --- Makefile | 6 +++++- app.py | 43 -------------------------------------- docs/conf.py | 1 + requirements.txt | 1 + senpy/VERSION | 2 +- senpy/__init__.py | 21 ++++++++++++++++--- senpy/__main__.py | 3 +-- senpy/api.py | 3 +-- senpy/blueprints.py | 16 +++----------- senpy/extensions.py | 4 +--- senpy/models.py | 12 +++++------ senpy/plugins.py | 3 +-- senpy/plugins/rand/rand.py | 1 - setup.cfg | 5 +++++ setup.py | 20 +++++++++--------- tests/test_blueprints.py | 4 ++-- tests/test_cli.py | 1 - tests/test_extensions.py | 1 + tests/test_models.py | 7 +------ tests/test_plugins.py | 4 ---- tests/test_schemas.py | 3 +-- 21 files changed, 59 insertions(+), 102 deletions(-) delete mode 100644 app.py diff --git a/Makefile b/Makefile index b3f6a13..9ebe4f0 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,10 @@ yapf: yapf -i -r senpy yapf -i -r tests +dev: + pip install --user pre-commit + pre-commit install + dockerfiles: $(addprefix Dockerfile-,$(PYVERSIONS)) ln -s Dockerfile-$(PYMAIN) Dockerfile @@ -75,4 +79,4 @@ pip_test: $(addprefix pip_test-,$(PYVERSIONS)) run: build docker run --rm -p 5000:5000 -ti '$(REPO)/$(NAME):$(VERSION)-python$(PYMAIN)' -.PHONY: test test-% build-% build test test_pip run yapf +.PHONY: test test-% build-% build test test_pip run yapf dev diff --git a/app.py b/app.py deleted file mode 100644 index ac6f9bf..0000000 --- a/app.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright 2014 J. Fernando Sánchez Rada - Grupo de Sistemas Inteligentes -# DIT, UPM -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -This is a helper for development. If you want to run Senpy use: - - python -m senpy -""" -from gevent.monkey import patch_all; patch_all() -import gevent -import config -from flask import Flask -from senpy.extensions import Senpy -import logging -import os -from gevent.wsgi import WSGIServer - -logging.basicConfig(level=logging.DEBUG) - -app = Flask(__name__) -mypath = os.path.dirname(os.path.realpath(__file__)) -sp = Senpy(app, os.path.join(mypath, "plugins"), default_plugins=True) -sp.activate_all() - -if __name__ == '__main__': - import logging - logging.basicConfig(level=config.DEBUG) - app.debug = config.DEBUG - http_server = WSGIServer(('', config.SERVER_PORT), app) - http_server.serve_forever() diff --git a/docs/conf.py b/docs/conf.py index 165ccf3..e9a9823 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +# flake8: noqa # # Senpy documentation build configuration file, created by # sphinx-quickstart on Tue Feb 24 08:57:32 2015. diff --git a/requirements.txt b/requirements.txt index 8a94cf5..f8401eb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,3 +9,4 @@ future jsonschema jsonref PyYAML +semver diff --git a/senpy/VERSION b/senpy/VERSION index 2337036..c2de2e8 100644 --- a/senpy/VERSION +++ b/senpy/VERSION @@ -1 +1 @@ -pre-0.7.0 +0.7.0-dev1 diff --git a/senpy/__init__.py b/senpy/__init__.py index 0947220..c2489c7 100644 --- a/senpy/__init__.py +++ b/senpy/__init__.py @@ -17,9 +17,24 @@ """ Sentiment analysis server in Python """ - -import os - +from __future__ import print_function from .version import __version__ +try: + import semver + __version_info__ = semver.parse_version_info(__version__) + + if __version_info__.prerelease: + import logging + logger = logging.getLogger(__name__) + msg = 'WARNING: You are using a pre-release version of {} ({})'.format( + __name__, __version__) + if len(logging.root.handlers) > 0: + logger.info(msg) + else: + import sys + print(msg, file=sys.stderr) +except ImportError: + print('semver not installed. Not doing version checking') + __all__ = ['api', 'blueprints', 'cli', 'extensions', 'models', 'plugins'] diff --git a/senpy/__main__.py b/senpy/__main__.py index e32e3ea..3d95f6d 100644 --- a/senpy/__main__.py +++ b/senpy/__main__.py @@ -24,7 +24,6 @@ from flask import Flask from senpy.extensions import Senpy from gevent.wsgi import WSGIServer from gevent.monkey import patch_all -import gevent import logging import os import argparse @@ -77,7 +76,7 @@ def main(): '-i', action='store_true', default=False, - help='Do not run a server, only install the dependencies of the plugins.' + help='Do not run a server, only install plugin dependencies' ) args = parser.parse_args() logging.basicConfig() diff --git a/senpy/api.py b/senpy/api.py index 10d30fe..0609e26 100644 --- a/senpy/api.py +++ b/senpy/api.py @@ -1,9 +1,8 @@ from future.utils import iteritems +from .models import Error import logging logger = logging.getLogger(__name__) -from .models import Error - API_PARAMS = { "algorithm": { "aliases": ["algorithm", "a", "algo"], diff --git a/senpy/blueprints.py b/senpy/blueprints.py index d34d566..c1a2f30 100644 --- a/senpy/blueprints.py +++ b/senpy/blueprints.py @@ -17,12 +17,12 @@ """ Blueprints for Senpy """ -from flask import Blueprint, request, current_app, render_template, url_for, jsonify +from flask import (Blueprint, request, current_app, + render_template, url_for, jsonify) from .models import Error, Response, Plugins, read_schema -from .api import NIF_PARAMS, WEB_PARAMS, parse_params +from .api import WEB_PARAMS, parse_params from functools import wraps -import json import logging logger = logging.getLogger(__name__) @@ -105,9 +105,7 @@ def plugins(): @api_blueprint.route('/plugins//', methods=['POST', 'GET']) @basic_api def plugin(plugin=None, action="list"): - filt = {} sp = current_app.senpy - plugs = sp.filter_plugins(name=plugin) if plugin == 'default' and sp.default_plugin: response = sp.default_plugin plugin = response.name @@ -123,11 +121,3 @@ def plugin(plugin=None, action="list"): return Response(message="Ok") else: return Error(message="action '{}' not allowed".format(action)) - - -if __name__ == '__main__': - import config - - app.register_blueprint(api_blueprint) - app.debug = config.DEBUG - app.run(host='0.0.0.0', port=5000) diff --git a/senpy/extensions.py b/senpy/extensions.py index ba30d1e..fe36249 100644 --- a/senpy/extensions.py +++ b/senpy/extensions.py @@ -6,7 +6,7 @@ import gevent from gevent import monkey monkey.patch_all() -from .plugins import SenpyPlugin, SentimentPlugin, EmotionPlugin +from .plugins import SentimentPlugin from .models import Error from .blueprints import api_blueprint, demo_blueprint from .api import API_PARAMS, NIF_PARAMS, parse_params @@ -21,7 +21,6 @@ import sys import imp import logging import traceback -import gevent import yaml import pip @@ -230,7 +229,6 @@ class Senpy(object): return None, None module = info["module"] name = info["name"] - requirements = info.get("requirements", []) sys.path.append(root) (fp, pathname, desc) = imp.find_module(module, [root, ]) try: diff --git a/senpy/models.py b/senpy/models.py index 3de3c74..348ed87 100644 --- a/senpy/models.py +++ b/senpy/models.py @@ -1,9 +1,9 @@ ''' -Senpy Models. +Senpy Models. This implementation should mirror the JSON schema definition. -For compatibility with Py3 and for easier debugging, this new version drops introspection -and adds all arguments to the models. +For compatibility with Py3 and for easier debugging, this new version drops +introspection and adds all arguments to the models. ''' from __future__ import print_function from six import string_types @@ -124,9 +124,9 @@ class SenpyMixin(object): context = self.context.copy() if hasattr(self, 'prefix'): # This sets @base for the document, which will be used in - # all relative URIs will. For example, if a uri is "Example" and - # prefix =s "http://example.com", the absolute URI after expanding - # with JSON-LD will be "http://example.com/Example" + # all relative URIs. For example, if a uri is "Example" and + # prefix =s "http://example.com", the absolute URI after + # expanding with JSON-LD will be "http://example.com/Example" prefix_context = {"@base": self.prefix} if isinstance(context, list): diff --git a/senpy/plugins.py b/senpy/plugins.py index d18e923..a35fae9 100644 --- a/senpy/plugins.py +++ b/senpy/plugins.py @@ -6,7 +6,7 @@ import os.path import pickle import logging import tempfile -from .models import Response, PluginModel, Error +from .models import PluginModel, Error logger = logging.getLogger(__name__) @@ -50,7 +50,6 @@ class SentimentPlugin(SenpyPlugin): class EmotionPlugin(SenpyPlugin): def __init__(self, info, *args, **kwargs): - resp = super(EmotionPlugin, self).__init__(info, *args, **kwargs) self.minEmotionValue = float(info.get("minEmotionValue", 0)) self.maxEmotionValue = float(info.get("maxEmotionValue", 0)) self["@type"] = "onyx:EmotionAnalysis" diff --git a/senpy/plugins/rand/rand.py b/senpy/plugins/rand/rand.py index dff55a6..a6f7639 100644 --- a/senpy/plugins/rand/rand.py +++ b/senpy/plugins/rand/rand.py @@ -1,4 +1,3 @@ -import json import random from senpy.plugins import SentimentPlugin diff --git a/setup.cfg b/setup.cfg index 91932ab..178ba5f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -2,3 +2,8 @@ description-file = README.rst [aliases] test=pytest +[flake8] +# because of the way that future works, we need to call install_aliases before +# finishing the imports. flake8 thinks that we're doing the imports too late, +# but it's actually ok +ignore = E402 diff --git a/setup.py b/setup.py index 5383bbb..a47fa6d 100644 --- a/setup.py +++ b/setup.py @@ -4,8 +4,10 @@ from pip.req import parse_requirements # parse_requirements() returns generator of pip.req.InstallRequirement objects try: - install_reqs = parse_requirements("requirements.txt", session=pip.download.PipSession()) - test_reqs = parse_requirements("test-requirements.txt", session=pip.download.PipSession()) + install_reqs = parse_requirements( + "requirements.txt", session=pip.download.PipSession()) + test_reqs = parse_requirements( + "test-requirements.txt", session=pip.download.PipSession()) except AttributeError: install_reqs = parse_requirements("requirements.txt") test_reqs = parse_requirements("test-requirements.txt") @@ -28,17 +30,15 @@ extendable, so new algorithms and sources can be used. author='J. Fernando Sanchez', author_email='balkian@gmail.com', url='https://github.com/gsi-upm/senpy', # use the URL to the github repo - download_url='https://github.com/gsi-upm/senpy/archive/{}.tar.gz' .format(__version__), + download_url='https://github.com/gsi-upm/senpy/archive/{}.tar.gz'.format( + __version__), keywords=['eurosentiment', 'sentiment', 'emotions', 'nif'], classifiers=[], install_requires=install_reqs, tests_require=test_reqs, - setup_requires=['pytest-runner',], + setup_requires=['pytest-runner', ], include_package_data=True, entry_points={ - 'console_scripts': [ - 'senpy = senpy.__main__:main', - 'senpy-cli = senpy.cli:main' - ] - } -) + 'console_scripts': + ['senpy = senpy.__main__:main', 'senpy-cli = senpy.cli:main'] + }) diff --git a/tests/test_blueprints.py b/tests/test_blueprints.py index 71a4c7d..0527af1 100644 --- a/tests/test_blueprints.py +++ b/tests/test_blueprints.py @@ -103,7 +103,7 @@ class BlueprintsTest(TestCase): self.assertCode(resp, 200) js = parse_resp(resp) assert "is_activated" in js - assert js["is_activated"] == False + assert not js["is_activated"] resp = self.client.get("/api/plugins/Dummy/activate") self.assertCode(resp, 200) sleep(0.5) @@ -111,7 +111,7 @@ class BlueprintsTest(TestCase): self.assertCode(resp, 200) js = parse_resp(resp) assert "is_activated" in js - assert js["is_activated"] == True + assert js["is_activated"] def test_default(self): """ Show only one plugin""" diff --git a/tests/test_cli.py b/tests/test_cli.py index 067fb3c..27c9ae6 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,4 +1,3 @@ -import os import logging from functools import partial diff --git a/tests/test_extensions.py b/tests/test_extensions.py index 0263a9f..de95e3e 100644 --- a/tests/test_extensions.py +++ b/tests/test_extensions.py @@ -44,6 +44,7 @@ class ExtensionsTest(TestCase): assert name == 'TestPip' assert module import noop + dir(noop) def test_installing(self): """ Enabling a plugin """ diff --git a/tests/test_models.py b/tests/test_models.py index 6ec8021..7460274 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,21 +1,16 @@ -import os import logging import jsonschema import json -import os from unittest import TestCase -from senpy.models import Response, Entry, Results, Sentiment, EmotionSet, Emotion, Error +from senpy.models import Entry, Results, Sentiment, EmotionSet, Error from senpy.plugins import SenpyPlugin from pprint import pprint class ModelsTest(TestCase): def test_jsonld(self): - ctx = os.path.normpath( - os.path.join(__file__, "..", "..", "..", "senpy", "schemas", - "context.jsonld")) prueba = {"id": "test", "analysis": [], "entries": []} r = Results(**prueba) print("Response's context: ") diff --git a/tests/test_plugins.py b/tests/test_plugins.py index c56d7ff..52f49d4 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -1,15 +1,11 @@ #!/bin/env python import os -import logging import pickle import shutil import tempfile -import json -import os from unittest import TestCase -from flask import Flask from senpy.models import Results, Entry from senpy.plugins import SentimentPlugin, ShelfMixin diff --git a/tests/test_schemas.py b/tests/test_schemas.py index 759bd7b..1ddfdb8 100644 --- a/tests/test_schemas.py +++ b/tests/test_schemas.py @@ -6,8 +6,7 @@ import os from os import path from fnmatch import fnmatch -import pyld -from jsonschema import validate, RefResolver, Draft4Validator, ValidationError +from jsonschema import RefResolver, Draft4Validator, ValidationError root_path = path.join(path.dirname(path.realpath(__file__)), '..') schema_folder = path.join(root_path, 'senpy', 'schemas')