Commit db302573 authored by J. Fernando Sánchez's avatar J. Fernando Sánchez

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
parent 7fd69cc6
...@@ -11,6 +11,10 @@ yapf: ...@@ -11,6 +11,10 @@ yapf:
yapf -i -r senpy yapf -i -r senpy
yapf -i -r tests yapf -i -r tests
dev:
pip install --user pre-commit
pre-commit install
dockerfiles: $(addprefix Dockerfile-,$(PYVERSIONS)) dockerfiles: $(addprefix Dockerfile-,$(PYVERSIONS))
ln -s Dockerfile-$(PYMAIN) Dockerfile ln -s Dockerfile-$(PYMAIN) Dockerfile
...@@ -75,4 +79,4 @@ pip_test: $(addprefix pip_test-,$(PYVERSIONS)) ...@@ -75,4 +79,4 @@ pip_test: $(addprefix pip_test-,$(PYVERSIONS))
run: build run: build
docker run --rm -p 5000:5000 -ti '$(REPO)/$(NAME):$(VERSION)-python$(PYMAIN)' 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
#!/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()
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# flake8: noqa
# #
# Senpy documentation build configuration file, created by # Senpy documentation build configuration file, created by
# sphinx-quickstart on Tue Feb 24 08:57:32 2015. # sphinx-quickstart on Tue Feb 24 08:57:32 2015.
......
...@@ -17,9 +17,24 @@ ...@@ -17,9 +17,24 @@
""" """
Sentiment analysis server in Python Sentiment analysis server in Python
""" """
from __future__ import print_function
from .version import __version__
import os try:
import semver
__version_info__ = semver.parse_version_info(__version__)
from .version import __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'] __all__ = ['api', 'blueprints', 'cli', 'extensions', 'models', 'plugins']
...@@ -24,7 +24,6 @@ from flask import Flask ...@@ -24,7 +24,6 @@ from flask import Flask
from senpy.extensions import Senpy from senpy.extensions import Senpy
from gevent.wsgi import WSGIServer from gevent.wsgi import WSGIServer
from gevent.monkey import patch_all from gevent.monkey import patch_all
import gevent
import logging import logging
import os import os
import argparse import argparse
...@@ -77,7 +76,7 @@ def main(): ...@@ -77,7 +76,7 @@ def main():
'-i', '-i',
action='store_true', action='store_true',
default=False, 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() args = parser.parse_args()
logging.basicConfig() logging.basicConfig()
......
from future.utils import iteritems from future.utils import iteritems
from .models import Error
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
from .models import Error
API_PARAMS = { API_PARAMS = {
"algorithm": { "algorithm": {
"aliases": ["algorithm", "a", "algo"], "aliases": ["algorithm", "a", "algo"],
......
...@@ -17,12 +17,12 @@ ...@@ -17,12 +17,12 @@
""" """
Blueprints for Senpy 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 .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 from functools import wraps
import json
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
...@@ -105,9 +105,7 @@ def plugins(): ...@@ -105,9 +105,7 @@ def plugins():
@api_blueprint.route('/plugins/<plugin>/<action>', methods=['POST', 'GET']) @api_blueprint.route('/plugins/<plugin>/<action>', methods=['POST', 'GET'])
@basic_api @basic_api
def plugin(plugin=None, action="list"): def plugin(plugin=None, action="list"):
filt = {}
sp = current_app.senpy sp = current_app.senpy
plugs = sp.filter_plugins(name=plugin)
if plugin == 'default' and sp.default_plugin: if plugin == 'default' and sp.default_plugin:
response = sp.default_plugin response = sp.default_plugin
plugin = response.name plugin = response.name
...@@ -123,11 +121,3 @@ def plugin(plugin=None, action="list"): ...@@ -123,11 +121,3 @@ def plugin(plugin=None, action="list"):
return Response(message="Ok") return Response(message="Ok")
else: else:
return Error(message="action '{}' not allowed".format(action)) 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)
...@@ -6,7 +6,7 @@ import gevent ...@@ -6,7 +6,7 @@ import gevent
from gevent import monkey from gevent import monkey
monkey.patch_all() monkey.patch_all()
from .plugins import SenpyPlugin, SentimentPlugin, EmotionPlugin from .plugins import SentimentPlugin
from .models import Error from .models import Error
from .blueprints import api_blueprint, demo_blueprint from .blueprints import api_blueprint, demo_blueprint
from .api import API_PARAMS, NIF_PARAMS, parse_params from .api import API_PARAMS, NIF_PARAMS, parse_params
...@@ -21,7 +21,6 @@ import sys ...@@ -21,7 +21,6 @@ import sys
import imp import imp
import logging import logging
import traceback import traceback
import gevent
import yaml import yaml
import pip import pip
...@@ -230,7 +229,6 @@ class Senpy(object): ...@@ -230,7 +229,6 @@ class Senpy(object):
return None, None return None, None
module = info["module"] module = info["module"]
name = info["name"] name = info["name"]
requirements = info.get("requirements", [])
sys.path.append(root) sys.path.append(root)
(fp, pathname, desc) = imp.find_module(module, [root, ]) (fp, pathname, desc) = imp.find_module(module, [root, ])
try: try:
......
''' '''
Senpy Models. Senpy Models.
This implementation should mirror the JSON schema definition. This implementation should mirror the JSON schema definition.
For compatibility with Py3 and for easier debugging, this new version drops introspection For compatibility with Py3 and for easier debugging, this new version drops
and adds all arguments to the models. introspection and adds all arguments to the models.
''' '''
from __future__ import print_function from __future__ import print_function
from six import string_types from six import string_types
...@@ -124,9 +124,9 @@ class SenpyMixin(object): ...@@ -124,9 +124,9 @@ class SenpyMixin(object):
context = self.context.copy() context = self.context.copy()
if hasattr(self, 'prefix'): if hasattr(self, 'prefix'):
# This sets @base for the document, which will be used in # This sets @base for the document, which will be used in
# all relative URIs will. For example, if a uri is "Example" and # all relative URIs. For example, if a uri is "Example" and
# prefix =s "http://example.com", the absolute URI after expanding # prefix =s "http://example.com", the absolute URI after
# with JSON-LD will be "http://example.com/Example" # expanding with JSON-LD will be "http://example.com/Example"
prefix_context = {"@base": self.prefix} prefix_context = {"@base": self.prefix}
if isinstance(context, list): if isinstance(context, list):
......
...@@ -6,7 +6,7 @@ import os.path ...@@ -6,7 +6,7 @@ import os.path
import pickle import pickle
import logging import logging
import tempfile import tempfile
from .models import Response, PluginModel, Error from .models import PluginModel, Error
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
...@@ -50,7 +50,6 @@ class SentimentPlugin(SenpyPlugin): ...@@ -50,7 +50,6 @@ class SentimentPlugin(SenpyPlugin):
class EmotionPlugin(SenpyPlugin): class EmotionPlugin(SenpyPlugin):
def __init__(self, info, *args, **kwargs): def __init__(self, info, *args, **kwargs):
resp = super(EmotionPlugin, self).__init__(info, *args, **kwargs)
self.minEmotionValue = float(info.get("minEmotionValue", 0)) self.minEmotionValue = float(info.get("minEmotionValue", 0))
self.maxEmotionValue = float(info.get("maxEmotionValue", 0)) self.maxEmotionValue = float(info.get("maxEmotionValue", 0))
self["@type"] = "onyx:EmotionAnalysis" self["@type"] = "onyx:EmotionAnalysis"
......
import json
import random import random
from senpy.plugins import SentimentPlugin from senpy.plugins import SentimentPlugin
......
...@@ -2,3 +2,8 @@ ...@@ -2,3 +2,8 @@
description-file = README.rst description-file = README.rst
[aliases] [aliases]
test=pytest 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
...@@ -4,8 +4,10 @@ from pip.req import parse_requirements ...@@ -4,8 +4,10 @@ from pip.req import parse_requirements
# parse_requirements() returns generator of pip.req.InstallRequirement objects # parse_requirements() returns generator of pip.req.InstallRequirement objects
try: try:
install_reqs = parse_requirements("requirements.txt", session=pip.download.PipSession()) install_reqs = parse_requirements(
test_reqs = parse_requirements("test-requirements.txt", session=pip.download.PipSession()) "requirements.txt", session=pip.download.PipSession())
test_reqs = parse_requirements(
"test-requirements.txt", session=pip.download.PipSession())
except AttributeError: except AttributeError:
install_reqs = parse_requirements("requirements.txt") install_reqs = parse_requirements("requirements.txt")
test_reqs = parse_requirements("test-requirements.txt") test_reqs = parse_requirements("test-requirements.txt")
...@@ -28,17 +30,15 @@ extendable, so new algorithms and sources can be used. ...@@ -28,17 +30,15 @@ extendable, so new algorithms and sources can be used.
author='J. Fernando Sanchez', author='J. Fernando Sanchez',
author_email='balkian@gmail.com', author_email='balkian@gmail.com',
url='https://github.com/gsi-upm/senpy', # use the URL to the github repo 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'], keywords=['eurosentiment', 'sentiment', 'emotions', 'nif'],
classifiers=[], classifiers=[],
install_requires=install_reqs, install_requires=install_reqs,
tests_require=test_reqs, tests_require=test_reqs,
setup_requires=['pytest-runner',], setup_requires=['pytest-runner', ],
include_package_data=True, include_package_data=True,
entry_points={ entry_points={
'console_scripts': [ 'console_scripts':
'senpy = senpy.__main__:main', ['senpy = senpy.__main__:main', 'senpy-cli = senpy.cli:main']
'senpy-cli = senpy.cli:main' })
]
}
)
...@@ -103,7 +103,7 @@ class BlueprintsTest(TestCase): ...@@ -103,7 +103,7 @@ class BlueprintsTest(TestCase):
self.assertCode(resp, 200) self.assertCode(resp, 200)
js = parse_resp(resp) js = parse_resp(resp)
assert "is_activated" in js assert "is_activated" in js
assert js["is_activated"] == False assert not js["is_activated"]
resp = self.client.get("/api/plugins/Dummy/activate") resp = self.client.get("/api/plugins/Dummy/activate")
self.assertCode(resp, 200) self.assertCode(resp, 200)
sleep(0.5) sleep(0.5)
...@@ -111,7 +111,7 @@ class BlueprintsTest(TestCase): ...@@ -111,7 +111,7 @@ class BlueprintsTest(TestCase):
self.assertCode(resp, 200) self.assertCode(resp, 200)
js = parse_resp(resp) js = parse_resp(resp)
assert "is_activated" in js assert "is_activated" in js
assert js["is_activated"] == True assert js["is_activated"]
def test_default(self): def test_default(self):
""" Show only one plugin""" """ Show only one plugin"""
......
import os
import logging import logging
from functools import partial from functools import partial
......
...@@ -44,6 +44,7 @@ class ExtensionsTest(TestCase): ...@@ -44,6 +44,7 @@ class ExtensionsTest(TestCase):
assert name == 'TestPip' assert name == 'TestPip'
assert module assert module
import noop import noop
dir(noop)
def test_installing(self): def test_installing(self):
""" Enabling a plugin """ """ Enabling a plugin """
......
import os
import logging import logging
import jsonschema import jsonschema
import json import json
import os
from unittest import TestCase 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 senpy.plugins import SenpyPlugin
from pprint import pprint from pprint import pprint
class ModelsTest(TestCase): class ModelsTest(TestCase):
def test_jsonld(self): def test_jsonld(self):
ctx = os.path.normpath(
os.path.join(__file__, "..", "..", "..", "senpy", "schemas",
"context.jsonld"))
prueba = {"id": "test", "analysis": [], "entries": []} prueba = {"id": "test", "analysis": [], "entries": []}
r = Results(**prueba) r = Results(**prueba)
print("Response's context: ") print("Response's context: ")
......
#!/bin/env python #!/bin/env python
import os import os
import logging
import pickle import pickle
import shutil import shutil
import tempfile import tempfile
import json
import os
from unittest import TestCase from unittest import TestCase
from flask import Flask
from senpy.models import Results, Entry from senpy.models import Results, Entry
from senpy.plugins import SentimentPlugin, ShelfMixin from senpy.plugins import SentimentPlugin, ShelfMixin
......
...@@ -6,8 +6,7 @@ import os ...@@ -6,8 +6,7 @@ import os
from os import path from os import path
from fnmatch import fnmatch from fnmatch import fnmatch
import pyld from jsonschema import RefResolver, Draft4Validator, ValidationError
from jsonschema import validate, RefResolver, Draft4Validator, ValidationError
root_path = path.join(path.dirname(path.realpath(__file__)), '..') root_path = path.join(path.dirname(path.realpath(__file__)), '..')
schema_folder = path.join(root_path, 'senpy', 'schemas') schema_folder = path.join(root_path, 'senpy', 'schemas')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment