1
0
mirror of https://github.com/gsi-upm/senpy synced 2025-09-19 04:52:21 +00:00

Compare commits

..

3 Commits
0.2.6 ... 0.2.9

Author SHA1 Message Date
J. Fernando Sánchez
2834967026 Better jsonld support 2014-11-27 11:27:05 +01:00
J. Fernando Sánchez
2f7a8d7267 Fixed setup.py and pip 2014-11-20 20:54:57 +01:00
J. Fernando Sánchez
2b68838514 PEP8 compliance 2014-11-20 19:29:49 +01:00
16 changed files with 183 additions and 153 deletions

4
MANIFEST.in Normal file
View File

@@ -0,0 +1,4 @@
include requirements.txt
include README.md
include senpy/context.jsonld
recursive-include *.senpy

6
app.py
View File

@@ -14,14 +14,16 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
''' """
Simple Sentiment Analysis server for EUROSENTIMENT Simple Sentiment Analysis server for EUROSENTIMENT
This class shows how to use the nif_server module to create custom services. This class shows how to use the nif_server module to create custom services.
''' """
import config import config
from flask import Flask from flask import Flask
from senpy.extensions import Senpy from senpy.extensions import Senpy
import logging
logging.basicConfig(level=logging.DEBUG)
app = Flask(__name__) app = Flask(__name__)

1
dev-requirements.txt Normal file
View File

@@ -0,0 +1 @@
mock

View File

@@ -1,9 +0,0 @@
from senpy.plugins import SenpyPlugin
class Prueba(SenpyPlugin):
def __init__(self, **kwargs):
super(Prueba, self).__init__(name="prueba",
version="4.0",
**kwargs)
plugin = Prueba()

View File

@@ -1,11 +1,10 @@
import requests import requests
import json import json
import sys
from senpy.plugins import SentimentPlugin from senpy.plugins import SentimentPlugin
from senpy.models import Response, Opinion, Entry from senpy.models import Response, Opinion, Entry
class Sentiment140Plugin(SentimentPlugin): class Sentiment140Plugin(SentimentPlugin):
EXTRA_PARAMS = { EXTRA_PARAMS = {
"language": {"aliases": ["language", "l"], "language": {"aliases": ["language", "l"],
@@ -13,6 +12,7 @@ class Sentiment140Plugin(SentimentPlugin):
"options": ["es", "en", "auto"], "options": ["es", "en", "auto"],
} }
} }
def __init__(self, **kwargs): def __init__(self, **kwargs):
super(Sentiment140Plugin, self).__init__(name="sentiment140", super(Sentiment140Plugin, self).__init__(name="sentiment140",
version="2.0", version="2.0",
@@ -22,23 +22,21 @@ class Sentiment140Plugin(SentimentPlugin):
def analyse(self, **params): def analyse(self, **params):
lang = params.get("language", "auto") lang = params.get("language", "auto")
res = requests.post("http://www.sentiment140.com/api/bulkClassifyJson", res = requests.post("http://www.sentiment140.com/api/bulkClassifyJson",
json.dumps({ json.dumps({"language": lang,
"language": lang, "data": [{"text": params["input"]}]
"data": [{"text": params["input"]}]} }
)) )
)
response = Response() response = Response()
polarityValue = int(res.json()["data"][0]["polarity"]) * 25 polarity_value = int(res.json()["data"][0]["polarity"]) * 25
polarity = "marl:Neutral" polarity = "marl:Neutral"
if polarityValue > 50: if polarity_value > 50:
polarity = "marl:Positive" polarity = "marl:Positive"
elif polarityValue < 50: elif polarity_value < 50:
polarity = "marl:Negative" polarity = "marl:Negative"
entry = Entry(text=params["input"]) entry = Entry(text=params["input"])
opinion = Opinion(polarity=polarity, polarityValue=polarityValue) opinion = Opinion(hasPolarity=polarity, polarityValue=polarity_value)
entry.opinions.append(opinion) entry.opinions.append(opinion)
entry.language = lang entry.language = lang
response.entries.append(entry) response.entries.append(entry)

View File

@@ -1,5 +1,4 @@
Flask==0.10.1 Flask==0.10.1
gunicorn==19.0.0 gunicorn==19.0.0
requests==2.4.1 requests==2.4.1
Flask-Plugins==1.4
GitPython==0.3.2.RC1 GitPython==0.3.2.RC1

View File

@@ -14,21 +14,12 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
''' """
Sentiment analysis server in Python Sentiment analysis server in Python
''' """
VERSION = "0.2.6"
import extensions import extensions
import blueprints import blueprints
import plugins import plugins
__version__ = "0.2.8"
if __name__ == '__main__':
from flask import Flask
app = Flask(__name__)
sp = extensions.Senpy()
sp.init_app(app)
app.debug = config.DEBUG
app.run()

View File

@@ -14,14 +14,15 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
''' """
Simple Sentiment Analysis server Blueprints for Senpy
''' """
import json import json
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
from flask import Blueprint, render_template, request, jsonify, current_app from flask import Blueprint, request, jsonify, current_app
nif_blueprint = Blueprint("NIF Sentiment Analysis Server", __name__) nif_blueprint = Blueprint("NIF Sentiment Analysis Server", __name__)
@@ -31,8 +32,8 @@ BASIC_PARAMS = {
}, },
} }
def get_params(req, params=BASIC_PARAMS): def get_params(req, params=BASIC_PARAMS):
indict = None
if req.method == 'POST': if req.method == 'POST':
indict = req.form indict = req.form
elif req.method == 'GET': elif req.method == 'GET':
@@ -41,37 +42,37 @@ def get_params(req, params=BASIC_PARAMS):
raise ValueError("Invalid data") raise ValueError("Invalid data")
outdict = {} outdict = {}
wrongParams = {} wrong_params = {}
for param, options in params.iteritems(): for param, options in params.iteritems():
for alias in options["aliases"]: for alias in options["aliases"]:
if alias in indict: if alias in indict:
outdict[param] = indict[alias] outdict[param] = indict[alias]
if param not in outdict: if param not in outdict:
if options.get("required", False): if options.get("required", False):
wrongParams[param] = params[param] wrong_params[param] = params[param]
else: else:
if "default" in options: if "default" in options:
outdict[param] = options["default"] outdict[param] = options["default"]
else: else:
if "options" in params[param] and \ if "options" in params[param] and outdict[param] not in params[param]["options"]:
outdict[param] not in params[param]["options"]: wrong_params[param] = params[param]
wrongParams[param] = params[param] if wrong_params:
if wrongParams: message = {"status": "failed",
message = {"status": "failed", "message": "Missing or invalid parameters"} "message": "Missing or invalid parameters",
message["parameters"] = outdict "parameters": outdict,
message["errors"] = {param:error for param, error in wrongParams.iteritems()} "errors": {param: error for param, error in wrong_params.iteritems()}
}
raise ValueError(json.dumps(message)) raise ValueError(json.dumps(message))
return outdict return outdict
def basic_analysis(params): def basic_analysis(params):
response = {"@context": ["http://demos.gsi.dit.upm.es/eurosentiment/static/context.jsonld", response = {"@context": ["http://demos.gsi.dit.upm.es/eurosentiment/static/context.jsonld",
{ {
"@base": "{}#".format(request.url.encode('utf-8')) "@base": "{}#".format(request.url.encode('utf-8'))
} }
], ],
"analysis": [{ "analysis": [{"@type": "marl:SentimentAnalysis"}],
"@type": "marl:SentimentAnalysis"
}],
"entries": [] "entries": []
} }
if "language" in params: if "language" in params:
@@ -83,8 +84,9 @@ def basic_analysis(params):
}) })
return response return response
@nif_blueprint.route('/', methods=['POST', 'GET']) @nif_blueprint.route('/', methods=['POST', 'GET'])
def home(entries=None): def home():
try: try:
algo = get_params(request).get("algorithm", None) algo = get_params(request).get("algorithm", None)
specific_params = current_app.senpy.parameters(algo) specific_params = current_app.senpy.parameters(algo)
@@ -96,11 +98,13 @@ def home(entries=None):
except Exception as ex: except Exception as ex:
return jsonify(status="400", message=ex.message) return jsonify(status="400", message=ex.message)
@nif_blueprint.route("/default") @nif_blueprint.route("/default")
def default(): def default():
return current_app.senpy.default_plugin return current_app.senpy.default_plugin
#return plugins(action="list", plugin=current_app.senpy.default_algorithm) #return plugins(action="list", plugin=current_app.senpy.default_algorithm)
@nif_blueprint.route('/plugins/', methods=['POST', 'GET']) @nif_blueprint.route('/plugins/', methods=['POST', 'GET'])
@nif_blueprint.route('/plugins/<plugin>', methods=['POST', 'GET']) @nif_blueprint.route('/plugins/<plugin>', methods=['POST', 'GET'])
@nif_blueprint.route('/plugins/<plugin>/<action>', methods=['POST', 'GET']) @nif_blueprint.route('/plugins/<plugin>/<action>', methods=['POST', 'GET'])
@@ -113,7 +117,7 @@ def plugins(plugin=None, action="list"):
return "Plugin not found", 400 return "Plugin not found", 400
if action == "list": if action == "list":
with_params = request.args.get("params", "") == "1" with_params = request.args.get("params", "") == "1"
dic = {plug:plugs[plug].jsonable(with_params) for plug in plugs} dic = {plug: plugs[plug].jsonable(with_params) for plug in plugs}
return jsonify(dic) return jsonify(dic)
if action == "disable": if action == "disable":
current_app.senpy.disable_plugin(plugin) current_app.senpy.disable_plugin(plugin)
@@ -127,9 +131,11 @@ def plugins(plugin=None, action="list"):
else: else:
return "action '{}' not allowed".format(action), 400 return "action '{}' not allowed".format(action), 400
if __name__ == '__main__': if __name__ == '__main__':
import config import config
from flask import Flask from flask import Flask
app = Flask(__name__) app = Flask(__name__)
app.register_blueprint(nif_blueprint) app.register_blueprint(nif_blueprint)
app.debug = config.DEBUG app.debug = config.DEBUG

View File

@@ -8,25 +8,26 @@
"nif": "http://persistence.uni-leipzig.org/nlp2rdf/ontologies/nif-core#", "nif": "http://persistence.uni-leipzig.org/nlp2rdf/ontologies/nif-core#",
"onyx": "http://www.gsi.dit.upm.es/ontologies/onyx/ns#", "onyx": "http://www.gsi.dit.upm.es/ontologies/onyx/ns#",
"emotions": { "emotions": {
"@id": "onyx:hasEmotionSet", "@container": "@set",
"@type": "onyx:EmotionSet" "@id": "onyx:hasEmotionSet"
}, },
"opinions": { "opinions": {
"@container": "@list", "@container": "@set",
"@id": "marl:hasOpinion", "@id": "marl:hasOpinion"
"@type": "marl:Opinion"
}, },
"prov": "http://www.w3.org/ns/prov#", "prov": "http://www.w3.org/ns/prov#",
"rdfs": "http://www.w3.org/2000/01/rdf-schema#", "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
"analysis": { "analysis": {
"@container": "@set",
"@id": "prov:wasInformedBy" "@id": "prov:wasInformedBy"
}, },
"entries": { "entries": {
"@container": "@set",
"@id": "prov:generated" "@id": "prov:generated"
}, },
"strings": { "strings": {
"@reverse": "nif:hasContext", "@container": "@set",
"@type": "nif:String" "@reverse": "nif:hasContext"
}, },
"date": "date":
{ {

View File

@@ -1,3 +1,5 @@
"""
"""
import os import os
import sys import sys
import imp import imp
@@ -55,7 +57,6 @@ class Senpy(object):
else: else:
return False return False
def analyse(self, **params): def analyse(self, **params):
algo = None algo = None
logger.debug("analysing with params: {}".format(params)) logger.debug("analysing with params: {}".format(params))
@@ -69,12 +70,12 @@ class Senpy(object):
resp.analysis.append(plug.jsonable()) resp.analysis.append(plug.jsonable())
return resp return resp
else: else:
return {"status": 400, "message": "The algorithm '{}' is not valid".format(algo) } return {"status": 400, "message": "The algorithm '{}' is not valid".format(algo)}
@property @property
def default_plugin(self): def default_plugin(self):
candidates = self.filter_plugins(enabled=True) candidates = self.filter_plugins(enabled=True)
if len(candidates)>1: if len(candidates) > 0:
candidate = candidates.keys()[0] candidate = candidates.keys()[0]
logger.debug("Default: {}".format(candidate)) logger.debug("Default: {}".format(candidate))
return candidate return candidate
@@ -97,7 +98,8 @@ class Senpy(object):
del self.plugins[plugin] del self.plugins[plugin]
self.plugins[nplug.name] = nplug self.plugins[nplug.name] = nplug
def _load_plugin(self, plugin, search_folder, enabled=True): @staticmethod
def _load_plugin(plugin, search_folder, enabled=True):
logger.debug("Loading plugins") logger.debug("Loading plugins")
sys.path.append(search_folder) sys.path.append(search_folder)
(fp, pathname, desc) = imp.find_module(plugin) (fp, pathname, desc) = imp.find_module(plugin)
@@ -118,14 +120,14 @@ class Senpy(object):
logger.debug("Exception importing {}: {}".format(plugin, ex)) logger.debug("Exception importing {}: {}".format(plugin, ex))
return tmp return tmp
def _load_plugins(self): def _load_plugins(self):
plugins = {} plugins = {}
for search_folder in self._search_folders: for search_folder in self._search_folders:
for item in os.listdir(search_folder): for item in os.listdir(search_folder):
if os.path.isdir(os.path.join(search_folder, item)) \ if os.path.isdir(os.path.join(search_folder, item)) \
and os.path.exists( and os.path.exists(os.path.join(search_folder,
os.path.join(search_folder, item, "__init__.py")): item,
"__init__.py")):
plugin = self._load_plugin(item, search_folder) plugin = self._load_plugin(item, search_folder)
if plugin: if plugin:
plugins[plugin.name] = plugin plugins[plugin.name] = plugin
@@ -140,12 +142,6 @@ class Senpy(object):
for plugin in self.plugins: for plugin in self.plugins:
self.enable_plugin(plugin) self.enable_plugin(plugin)
def enable_plugin(self, item):
self.plugins[item].enabled = True
def disable_plugin(self, item):
self.plugins[item].enabled = False
@property @property
def plugins(self): def plugins(self):
""" Return the plugins registered for a given application. """ """ Return the plugins registered for a given application. """
@@ -157,27 +153,20 @@ class Senpy(object):
def filter_plugins(self, **kwargs): def filter_plugins(self, **kwargs):
""" Filter plugins by different criteria """ """ Filter plugins by different criteria """
def matches(plug): def matches(plug):
res = all(getattr(plug, k, None) == v for (k, v) in kwargs.items()) res = all(getattr(plug, k, None) == v for (k, v) in kwargs.items())
logger.debug("matching {} with {}: {}".format(plug.name, logger.debug("matching {} with {}: {}".format(plug.name,
kwargs, kwargs,
res)) res))
return res return res
if not kwargs: if not kwargs:
return self.plugins return self.plugins
else: else:
return {n:p for n, p in self.plugins.items() if matches(p)} return {n: p for n, p in self.plugins.items() if matches(p)}
def sentiment_plugins(self): def sentiment_plugins(self):
""" Return only the sentiment plugins """ """ Return only the sentiment plugins """
return {p:plugin for p, plugin in self.plugins.items() if return {p: plugin for p, plugin in self.plugins.items() if
isinstance(plugin, SentimentPlugin)} isinstance(plugin, SentimentPlugin)}
if __name__ == '__main__':
from flask import Flask
app = Flask(__name__)
sp = Senpy()
sp.init_app(APP)
with APP.app_context():
sp._load_plugins()

View File

@@ -2,58 +2,85 @@ import json
import os import os
from collections import defaultdict from collections import defaultdict
class Leaf(defaultdict): class Leaf(defaultdict):
def __init__(self, ofclass=list): def __init__(self, context=None, ofclass=list):
super(Leaf, self).__init__(ofclass) super(Leaf, self).__init__(ofclass)
if context:
self.context = context
def __getattr__(self, name): def __getattr__(self, name):
if name is not "context":
return super(Leaf, self).__getitem__(name) return super(Leaf, self).__getitem__(name)
return self["@context"]
def __setattr__(self, name, value): def __setattr__(self, name, value):
self[name] = value name = "@context" if name is "context" else name
self[name] = self.get_context(value)
def __delattr__(self, name): def __delattr__(self, name):
return super(Leaf, self).__delitem__(name) return super(Leaf, self).__delitem__(name)
@staticmethod
def get_context(context):
if isinstance(context, list):
contexts = []
for c in context:
contexts.append(Response.get_context(c))
return contexts
elif isinstance(context, dict):
return context
elif isinstance(context, basestring):
try:
with open(context) as f:
return json.loads(f.read())
except IOError:
return context
class Response(Leaf): class Response(Leaf):
def __init__(self, context=None): def __init__(self, context=None, *args, **kwargs):
super(Response, self).__init__()
self["analysis"] = []
self["entries"] = []
if context is None: if context is None:
context = "{}/context.jsonld".format(os.path.dirname( context = "{}/context.jsonld".format(os.path.dirname(
os.path.realpath(__file__))) os.path.realpath(__file__)))
if isinstance(context, dict): super(Response, self).__init__(*args, context=context, **kwargs)
self["@context"] = context self["analysis"] = []
if isinstance(context, basestring): self["entries"] = []
try:
with open(context) as f:
self["@context"] = json.loads(f.read())
except IOError:
self["@context"] = context
class Entry(Leaf): class Entry(Leaf):
def __init__(self, text=None, emotionSets=None, opinions=None, **kwargs): def __init__(self, text=None, emotion_sets=None, opinions=None, **kwargs):
super(Entry, self).__init__(**kwargs) super(Entry, self).__init__(**kwargs)
if text: if text:
self.text = text self.text = text
if emotionSets: if emotion_sets:
self.emotionSets = emotionSets self.emotionSets = emotion_sets
if opinions: if opinions:
self.opinions = opinions self.opinions = opinions
class Opinion(Leaf): class Opinion(Leaf):
def __init__(self, polarityValue=None, polarity=None, **kwargs): opinionContext = {
super(Opinion, self).__init__(**kwargs) "@vocab": "http://www.gsi.dit.upm.es/ontologies/marl/ns#"
}
def __init__(self, polarityValue=None, hasPolarity=None, *args, **kwargs):
super(Opinion, self).__init__(context=self.opinionContext,
*args,
**kwargs)
if polarityValue is not None: if polarityValue is not None:
self.polarityValue = polarityValue self.polarityValue = polarityValue
if polarity is not None: if hasPolarity is not None:
self.polarity = polarity self.hasPolarity = hasPolarity
class EmotionSet(Leaf): class EmotionSet(Leaf):
def __init__(self, emotions=[], **kwargs): emotionContext = {
super(EmotionSet, self).__init__(**kwargs) "@vocab": "http://www.gsi.dit.upm.es/ontologies/onyx/ns#"
}
def __init__(self, emotions=None, *args, **kwargs):
if not emotions:
emotions = []
super(EmotionSet, self).__init__(context=self.emotionContext,
*args,
**kwargs)
self.emotions = emotions or [] self.emotions = emotions or []

View File

@@ -32,6 +32,7 @@ PARAMS = {"input": {"aliases": ["i", "input"],
}, },
} }
class SenpyPlugin(object): class SenpyPlugin(object):
def __init__(self, name=None, version=None, extraparams=None, params=None): def __init__(self, name=None, version=None, extraparams=None, params=None):
logger.debug("Initialising {}".format(name)) logger.debug("Initialising {}".format(name))
@@ -60,7 +61,7 @@ class SenpyPlugin(object):
"@id": "{}_{}".format(self.name, self.version), "@id": "{}_{}".format(self.name, self.version),
"enabled": self.enabled, "enabled": self.enabled,
} }
if self.repo: if hasattr(self, "repo") and self.repo:
resp["repo"] = self.repo.remotes[0].url resp["repo"] = self.repo.remotes[0].url
if parameters: if parameters:
resp["parameters"] = self.params resp["parameters"] = self.params
@@ -68,14 +69,15 @@ class SenpyPlugin(object):
resp["extra_parameters"] = self.extraparams resp["extra_parameters"] = self.extraparams
return resp return resp
class SentimentPlugin(SenpyPlugin): class SentimentPlugin(SenpyPlugin):
def __init__(self, def __init__(self,
minPolarityValue=0, min_polarity_value=0,
maxPolarityValue=1, max_polarity_value=1,
**kwargs): **kwargs):
super(SentimentPlugin, self).__init__(**kwargs) super(SentimentPlugin, self).__init__(**kwargs)
self.minPolarityValue = minPolarityValue self.minPolarityValue = min_polarity_value
self.maxPolarityValue = maxPolarityValue self.maxPolarityValue = max_polarity_value
def jsonable(self, *args, **kwargs): def jsonable(self, *args, **kwargs):
resp = super(SentimentPlugin, self).jsonable(*args, **kwargs) resp = super(SentimentPlugin, self).jsonable(*args, **kwargs)
@@ -83,16 +85,17 @@ class SentimentPlugin(SenpyPlugin):
resp["marl:minPolarityValue"] = self.minPolarityValue resp["marl:minPolarityValue"] = self.minPolarityValue
return resp return resp
class EmotionPlugin(SenpyPlugin): class EmotionPlugin(SenpyPlugin):
def __init__(self, def __init__(self,
minEmotionValue=0, min_emotion_value=0,
maxEmotionValue=1, max_emotion_value=1,
emotionCategory=None, emotion_category=None,
**kwargs): **kwargs):
super(EmotionPlugin, self).__init__(**kwargs) super(EmotionPlugin, self).__init__(**kwargs)
self.minEmotionValue = minEmotionValue self.minEmotionValue = min_emotion_value
self.maxEmotionValue = maxEmotionValue self.maxEmotionValue = max_emotion_value
self.emotionCategory = emotionCategory self.emotionCategory = emotion_category
def jsonable(self, *args, **kwargs): def jsonable(self, *args, **kwargs):
resp = super(EmotionPlugin, self).jsonable(*args, **kwargs) resp = super(EmotionPlugin, self).jsonable(*args, **kwargs)

View File

@@ -1,18 +1,31 @@
from setuptools import setup from setuptools import setup
import senpy from pip.req import parse_requirements
# parse_requirements() returns generator of pip.req.InstallRequirement objects
install_reqs = parse_requirements("requirements.txt")
# reqs is a list of requirement
# e.g. ['django==1.5.1', 'mezzanine==1.4.6']
reqs = [str(ir.req) for ir in install_reqs]
VERSION = "0.2.9"
print(reqs)
setup( setup(
name = 'senpy', name='senpy',
packages = ['senpy'], # this must be the same as the name above packages=['senpy'], # this must be the same as the name above
version = senpy.VERSION, version=VERSION,
description = ''' description='''
A sentiment analysis server implementation. Designed to be \ A sentiment analysis server implementation. Designed to be \
extendable, so new algorithms and sources can be used. 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/balkian/senpy', # use the URL to the github repo url='https://github.com/balkian/senpy', # use the URL to the github repo
download_url = 'https://github.com/balkian/senpy/archive/{}.tar.gz'.format(senpy.VERSION), download_url='https://github.com/balkian/senpy/archive/{}.tar.gz'.format(VERSION),
keywords = ['eurosentiment', 'sentiment', 'emotions', 'nif'], # arbitrary keywords keywords=['eurosentiment', 'sentiment', 'emotions', 'nif'], # arbitrary keywords
classifiers = [], classifiers=[],
install_requires=reqs,
include_package_data = True,
) )

View File

@@ -0,0 +1 @@

View File

@@ -1,5 +1,7 @@
import os import os
import logging import logging
try: try:
import unittest.mock as mock import unittest.mock as mock
except ImportError: except ImportError:
@@ -8,10 +10,12 @@ from senpy.extensions import Senpy
from flask import Flask from flask import Flask
from flask.ext.testing import TestCase from flask.ext.testing import TestCase
def check_dict(indic, template): def check_dict(indic, template):
return all(item in indic.items() for item in template.items()) return all(item in indic.items() for item in template.items())
class Blueprints_Test(TestCase):
class BlueprintsTest(TestCase):
def create_app(self): def create_app(self):
self.app = Flask("test_extensions") self.app = Flask("test_extensions")
self.senpy = Senpy() self.senpy = Senpy()
@@ -20,7 +24,6 @@ class Blueprints_Test(TestCase):
self.senpy.add_folder(self.dir) self.senpy.add_folder(self.dir)
return self.app return self.app
def test_home(self): def test_home(self):
""" Calling with no arguments should ask the user for more arguments """ """ Calling with no arguments should ask the user for more arguments """
resp = self.client.get("/") resp = self.client.get("/")

View File

@@ -1,5 +1,6 @@
import os import os
import logging import logging
try: try:
import unittest.mock as mock import unittest.mock as mock
except ImportError: except ImportError:
@@ -9,7 +10,7 @@ from flask import Flask
from flask.ext.testing import TestCase from flask.ext.testing import TestCase
class Extensions_Test(TestCase): class ExtensionsTest(TestCase):
def create_app(self): def create_app(self):
self.app = Flask("test_extensions") self.app = Flask("test_extensions")
self.senpy = Senpy() self.senpy = Senpy()
@@ -22,16 +23,16 @@ class Extensions_Test(TestCase):
""" Initialising the app with the extension. """ """ Initialising the app with the extension. """
assert hasattr(self.app, "senpy") assert hasattr(self.app, "senpy")
tapp = Flask("temp app") tapp = Flask("temp app")
tsen = Senpy(tapp) self.senpy.init_app(tapp)
assert hasattr(tapp, "senpy") assert hasattr(tapp, "senpy")
def test_discovery(self): def test_discovery(self):
""" Discovery of plugins in given folders. """ """ Discovery of plugins in given folders. """
# noinspection PyProtectedMember
assert self.dir in self.senpy._search_folders assert self.dir in self.senpy._search_folders
print self.senpy.plugins print self.senpy.plugins
assert "dummy" in self.senpy.plugins assert "dummy" in self.senpy.plugins
def test_enabling(self): def test_enabling(self):
""" Enabling a plugin """ """ Enabling a plugin """
self.senpy.enable_plugin("dummy") self.senpy.enable_plugin("dummy")
@@ -41,7 +42,7 @@ class Extensions_Test(TestCase):
""" Disabling a plugin """ """ Disabling a plugin """
self.senpy.enable_plugin("dummy") self.senpy.enable_plugin("dummy")
self.senpy.disable_plugin("dummy") self.senpy.disable_plugin("dummy")
assert self.senpy.plugins["dummy"].enabled == False assert not self.senpy.plugins["dummy"].enabled
def test_default(self): def test_default(self):
""" Default plugin should be set """ """ Default plugin should be set """
@@ -63,7 +64,7 @@ class Extensions_Test(TestCase):
def test_filtering(self): def test_filtering(self):
""" Filtering plugins """ """ Filtering plugins """
assert len(self.senpy.filter_plugins(name="dummy"))>0 assert len(self.senpy.filter_plugins(name="dummy")) > 0
assert not len(self.senpy.filter_plugins(name="notdummy")) assert not len(self.senpy.filter_plugins(name="notdummy"))
assert self.senpy.filter_plugins(name="dummy", enabled=True) assert self.senpy.filter_plugins(name="dummy", enabled=True)
self.senpy.disable_plugin("dummy") self.senpy.disable_plugin("dummy")