You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
senpy/senpy/__main__.py

246 lines
7.4 KiB
Python

#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) 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.
"""
Senpy is a modular sentiment analysis server. This script runs an instance of
the server.
"""
from flask import Flask
from senpy.extensions import Senpy
from senpy.utils import easy_test
from senpy.plugins import list_dependencies
from senpy import config
import logging
import os
import sys
import argparse
import senpy
SERVER_PORT = os.environ.get("PORT", 5000)
def main():
parser = argparse.ArgumentParser(description='Run a Senpy server')
parser.add_argument(
'--level',
'-l',
metavar='logging_level',
type=str,
default="INFO",
help='Logging level')
parser.add_argument(
'--no-proxy-fix',
action='store_true',
default=False,
help='Do not assume senpy will be running behind a proxy (e.g., nginx)')
parser.add_argument(
'--log-format',
metavar='log_format',
type=str,
default='%(asctime)s %(levelname)-10s %(name)-30s \t %(message)s',
help='Logging format')
parser.add_argument(
'--debug',
'-d',
action='store_true',
default=False,
help='Run the application in debug mode')
parser.add_argument(
'--no-default-plugins',
action='store_true',
default=False,
help='Do not load the default plugins')
parser.add_argument(
'--host',
type=str,
default="0.0.0.0",
help='Use 0.0.0.0 to accept requests from any host.')
parser.add_argument(
'--port',
'-p',
type=int,
default=SERVER_PORT,
help='Port to listen on.')
parser.add_argument(
'--plugins-folder',
'-f',
type=str,
action='append',
help='Where to look for plugins.')
parser.add_argument(
'--install',
'-i',
action='store_true',
default=False,
help='Install plugin dependencies before running.')
parser.add_argument(
'--dependencies',
action='store_true',
default=False,
help='List plugin dependencies')
parser.add_argument(
'--strict',
action='store_true',
default=config.strict,
help='Fail if optional plugins cannot be loaded.')
parser.add_argument(
'--test',
'-t',
action='store_true',
default=False,
help='Test all plugins before launching the server')
parser.add_argument(
'--no-run',
action='store_true',
default=False,
help='Do not launch the server.')
parser.add_argument(
'--data-folder',
'--data',
type=str,
default=None,
help='Where to look for data. It be set with the SENPY_DATA environment variable as well.')
parser.add_argument(
'--no-threaded',
action='store_true',
default=False,
help='Run a single-threaded server')
parser.add_argument(
'--no-deps',
'-n',
action='store_true',
default=False,
help='Skip installing dependencies')
parser.add_argument(
'--version',
'-v',
action='store_true',
default=False,
help='Output the senpy version and exit')
parser.add_argument(
'--allow-fail',
'--fail',
action='store_true',
default=False,
help='Do not exit if some plugins fail to activate')
parser.add_argument(
'--enable-cors',
'--cors',
action='store_true',
default=False,
help='Enable CORS for all domains (requires flask-cors to be installed)')
args = parser.parse_args()
print('Senpy version {}'.format(senpy.__version__))
print(sys.version)
if args.version:
exit(1)
rl = logging.getLogger()
rl.setLevel(getattr(logging, args.level))
logger_handler = rl.handlers[0]
# First, generic formatter:
logger_handler.setFormatter(logging.Formatter(args.log_format))
app = Flask(__name__)
app.debug = args.debug
sp = Senpy(app,
plugin_folder=None,
default_plugins=not args.no_default_plugins,
install=args.install,
strict=args.strict,
data_folder=args.data_folder)
folders = list(args.plugins_folder) if args.plugins_folder else []
if not folders:
folders.append(".")
for p in folders:
sp.add_folder(p)
plugins = sp.plugins(plugin_type=None, is_activated=False)
maxname = max(len(x.name) for x in plugins)
maxversion = max(len(str(x.version)) for x in plugins)
print('Found {} plugins:'.format(len(plugins)))
for plugin in plugins:
import inspect
fpath = inspect.getfile(plugin.__class__)
print('\t{: <{maxname}} @ {: <{maxversion}} -> {}'.format(plugin.name,
plugin.version,
fpath,
maxname=maxname,
maxversion=maxversion))
if args.dependencies:
print('Listing dependencies')
missing = []
installed = []
for plug in sp.plugins(is_activated=False):
inst, miss, nltkres = list_dependencies(plug)
if not any([inst, miss, nltkres]):
continue
print(f'Plugin: {plug.id}')
for m in miss:
missing.append(f'{m} # {plug.id}')
for i in inst:
installed.append(f'{i} # {plug.id}')
if installed:
print('Installed packages:')
for i in installed:
print(f'\t{i}')
if missing:
print('Missing packages:')
for m in missing:
print(f'\t{m}')
if args.install:
sp.install_deps()
if args.test:
sp.activate_all(sync=True)
easy_test(sp.plugins(is_activated=True), debug=args.debug)
if args.no_run:
return
sp.activate_all(sync=True)
if sp.strict:
inactive = sp.plugins(is_activated=False)
assert not inactive
print('Senpy version {}'.format(senpy.__version__))
print('Server running on port %s:%d. Ctrl+C to quit' % (args.host,
args.port))
if args.enable_cors:
from flask_cors import CORS
CORS(app)
if not args.no_proxy_fix:
from werkzeug.middleware.proxy_fix import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app)
try:
app.run(args.host,
args.port,
threaded=not args.no_threaded,
debug=app.debug)
except KeyboardInterrupt:
print('Bye!')
sp.deactivate_all()
if __name__ == '__main__':
main()