Skip to content

Commit 5436a4c

Browse files
author
Adam Wight
committed
Create infrastructure to install and run
Mostly copied from ORES, although we should be extracting into a shared library.
1 parent 1b45451 commit 5436a4c

File tree

10 files changed

+255
-1
lines changed

10 files changed

+255
-1
lines changed

.codecov.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
codecov:
2+
notify:
3+
require_ci_to_pass: no
4+
5+
coverage:
6+
status:
7+
patch: off

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
*.pyc
2+
__pycache__
3+
/*.egg-info

config/00-main.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@ actions:
1616
new_judgement:
1717
groups: []
1818
set_judgement_preference:
19-
groups: []
19+
groups:
2020
- autoconfirmed

jade/about.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
__name__ = "jade"
2+
__version__ = "0.0.1"
3+
__author__ = "Aaron Halfaker"
4+
__author_email__ = "[email protected]"
5+
__description__ = "Judgment and Dialog Engine"
6+
__url__ = "https://github.com/wiki-ai/jade"
7+
__license__ = "MIT"

jade/applications/util.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# TODO: Dedupe with utilities and application framework from ores?
2+
import glob
3+
import os.path
4+
import yamlconf
5+
import logging
6+
import logging.config
7+
import sys
8+
9+
DEFAULT_DIRS = ["config/", "/etc/jade/"]
10+
DEFAULT_LOGGING_CONFIG = "logging_config.yaml"
11+
DEFAULT_FORMAT = "%(asctime)s %(levelname)s:%(name)s -- %(message)s"
12+
13+
14+
logger = logging.getLogger(__name__)
15+
16+
17+
def build_config(config_dirs=DEFAULT_DIRS, **kwargs):
18+
# Loads files in alphabetical order based on the bare filename
19+
config_file_paths = []
20+
for directory in config_dirs:
21+
dir_glob = os.path.join(directory, "*.yaml")
22+
config_file_paths.extend((os.path.basename(path), path)
23+
for path in glob.glob(dir_glob))
24+
config_file_paths.sort()
25+
logger.info("Loading configs from {0}".format(config_file_paths))
26+
config = yamlconf.load(*(open(p) for fn, p in config_file_paths))
27+
28+
return config
29+
30+
31+
def configure_logging(verbose=False, debug=False, logging_config=None,
32+
**kwargs):
33+
# Load logging config if specified. If no config file is specified, we
34+
# make a half-hearted attempt to find a distributed logging_config.yaml
35+
# in the current working directory.
36+
if logging_config is None:
37+
if os.path.exists(DEFAULT_LOGGING_CONFIG):
38+
logging_config = DEFAULT_LOGGING_CONFIG
39+
40+
if logging_config is not None:
41+
with open(logging_config) as f:
42+
logging_config = yamlconf.load(f)
43+
logging.config.dictConfig(logging_config)
44+
45+
# Secret sauce: if running from the console, mirror logs there.
46+
if sys.stdin.isatty():
47+
handler = logging.StreamHandler(stream=sys.stderr)
48+
formatter = logging.Formatter(fmt=DEFAULT_FORMAT)
49+
handler.setFormatter(formatter)
50+
logging.getLogger().addHandler(handler)
51+
52+
else:
53+
# Configure fallback logging.
54+
logging.basicConfig(level=logging.INFO, format=DEFAULT_FORMAT)
55+
56+
if debug:
57+
logging.getLogger().setLevel(logging.DEBUG)

jade/applications/wsgi.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import docopt_subcommands as dsc
2+
from jade.wsgi import server
3+
4+
from .util import build_config, configure_logging
5+
6+
7+
@dsc.command()
8+
def server_command(args):
9+
"""
10+
usage:
11+
{program} server (-h | --help)
12+
{program} server [--host=<name>] [--port=<num>] [--config-dir=<path>]...
13+
[--processes=<num>] [--debug] [--verbose]
14+
[--logging-config=<path>]
15+
16+
Runs a WSGI-based web server that hosts JADE.
17+
18+
Options:
19+
-h --help Print this documentation
20+
--host=<name> The hostname to listen on [default: 0.0.0.0]
21+
--port=<num> The port number to start the server on
22+
[default: 8080]
23+
--config-dir=<path> The path to a directory containing configuration
24+
[default: config/]
25+
--logging-config=<path> The path to a logging configuration file
26+
--processes=<num> The number of parallel processes to handle
27+
[default: 16]
28+
--debug Print debug logging information
29+
--verbose Print verbose extraction information
30+
"""
31+
host = args['--host']
32+
port = int(args['--port'])
33+
processes = int(args['--processes'])
34+
verbose = args['--verbose']
35+
debug = args['--debug']
36+
37+
run(host, port, processes,
38+
verbose=verbose, debug=debug,
39+
logging_config=args['--logging-config'],
40+
config_dirs=args['--config-dir'])
41+
42+
43+
def run(host, port, processes, **kwargs):
44+
application = build(**kwargs)
45+
application.debug = True
46+
application.run(host=host, port=port, processes=processes, debug=True)
47+
48+
49+
def build(**kwargs):
50+
configure_logging(**kwargs)
51+
config = build_config(**kwargs)
52+
return server.configure(config)

jade/jade.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"""
2+
Console access to JADE
3+
4+
Usage:
5+
jade [-h | --help]
6+
jade server
7+
8+
Available commands:
9+
server Start the web server.
10+
11+
Options:
12+
--help Show this usage message.
13+
"""
14+
import docopt_subcommands as dsc
15+
import sys
16+
17+
from .applications import wsgi
18+
19+
20+
def main():
21+
dsc.main(program='jade', version='jade v1')

jade/wsgi/preprocessors.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# TODO: dedupe with ores code
2+
from functools import wraps
3+
4+
from flask import current_app, make_response, request
5+
6+
7+
def minifiable(route):
8+
@wraps(route)
9+
def minifiable_route(*args, **kwargs):
10+
# Change the config
11+
current_app.config['JSONIFY_PRETTYPRINT_REGULAR'] = \
12+
False if request.args.get('format') == 'json' else True
13+
14+
# Generate a response
15+
response = route(*args, **kwargs)
16+
17+
# Explicitly return to default now that the result is generated
18+
current_app.config['JSONIFY_PRETTYPRINT_REGULAR'] = True
19+
20+
return response
21+
22+
return minifiable_route
23+
24+
25+
def nocache(route):
26+
@wraps(route)
27+
def nocache_route(*args, **kwargs):
28+
response = make_response(route(*args, **kwargs))
29+
response.headers['Cache-Control'] = \
30+
"no-store, no-cache, max-age=0"
31+
response.headers['Pragma'] = 'no-cache'
32+
# Unix epoch
33+
response.headers['Expires'] = 'Thu, 01 Jan 1970 00:00:00 GMT'
34+
return response
35+
36+
return nocache_route

requirements.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Note that cryptography < 1.9 is incompatible with openssl-1.1.0f
2+
cryptography >= 1.9.0, < 1.9.999
3+
docopt
4+
docopt_subcommands
5+
flask_swaggerui
6+
Flask >= 0.12.2, < 0.12.999
7+
jwt
8+
mwapi
9+
yamlconf

setup.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import os
2+
import re
3+
import sys
4+
import platform
5+
from setuptools import find_packages, setup
6+
7+
about_path = os.path.join(os.path.dirname(__file__), "jade/about.py")
8+
exec(compile(open(about_path).read(), about_path, "exec"))
9+
10+
if sys.version_info <= (3, 0):
11+
print("JADE needs Python 3 to run properly. Your version is "
12+
+ platform.python_version())
13+
sys.exit(1)
14+
15+
16+
def read(fname):
17+
return open(os.path.join(os.path.dirname(__file__), fname)).read()
18+
19+
20+
def requirements(fname):
21+
"""
22+
Generator to parse requirements.txt file
23+
24+
Supports bits of extended pip format (git urls)
25+
"""
26+
with open(fname) as f:
27+
for line in f:
28+
match = re.search('#egg=(.*)$', line)
29+
if match:
30+
yield match.groups()[0]
31+
else:
32+
yield line.strip()
33+
34+
35+
setup(
36+
python_requires=">=3",
37+
name=__name__, # noqa
38+
version=__version__, # noqa
39+
author=__author__, # noqa
40+
author_email=__author_email__, # noqa
41+
description=__description__, # noqa
42+
url=__url__, # noqa
43+
license=__license__, # noqa
44+
entry_points={
45+
'console_scripts': [
46+
'jade = jade.jade:main',
47+
],
48+
},
49+
packages=find_packages(),
50+
include_package_data=True,
51+
long_description=read('README.md'),
52+
install_requires=list(requirements("requirements.txt")),
53+
classifiers=[
54+
"Development Status :: 3 - Alpha",
55+
"Programming Language :: Python",
56+
"Programming Language :: Python :: 3",
57+
"Environment :: Other Environment",
58+
"Intended Audience :: Developers",
59+
"License :: OSI Approved :: MIT License",
60+
"Operating System :: OS Independent"
61+
],
62+
)

0 commit comments

Comments
 (0)