Skip to content

Commit 75035eb

Browse files
authored
Merge pull request #2 from mjhea0/updates
updated python version, converted to the flask cli, added rq dashboard
2 parents 1615d9f + 85da564 commit 75035eb

File tree

18 files changed

+86
-95
lines changed

18 files changed

+86
-95
lines changed

.python-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.6.1
1+
3.6.4

.travis.yml

Lines changed: 0 additions & 13 deletions
This file was deleted.

Dockerfile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
FROM python:3.6.1
1+
# base image
2+
FROM python:3.6.4-alpine
23

34
# set working directory
45
RUN mkdir -p /usr/src/app
@@ -8,4 +9,4 @@ WORKDIR /usr/src/app
89
ADD ./requirements.txt /usr/src/app/requirements.txt
910

1011
# install requirements
11-
RUN pip install -r requirements.txt
12+
RUN pip install -r requirements.txt

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
The MIT License (MIT)
2-
Copyright (c) 2017 Michael Herman
2+
Copyright (c) 2018 Michael Herman
33

44
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
55

README.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,3 @@ $ docker-compose up -d
1111
```
1212

1313
Open your browser to http://localhost:5001
14-
15-
### Example
16-
17-
![](app.png)

app.png

-156 KB
Binary file not shown.

docker-compose.yml

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,39 @@
1-
version: '2.1'
1+
version: '3.5'
22

33
services:
44

55
web:
66
build: .
77
image: web
88
container_name: web
9-
environment:
10-
- APP_SETTINGS=project.server.config.DevelopmentConfig
119
ports:
1210
- '5001:5000'
13-
command: python manage.py runserver -h 0.0.0.0
11+
command: python manage.py run -h 0.0.0.0
1412
volumes:
1513
- .:/usr/src/app
14+
environment:
15+
- FLASK_DEBUG=1
16+
- APP_SETTINGS=project.server.config.DevelopmentConfig
1617
depends_on:
1718
- redis
1819

1920
worker:
2021
image: web
21-
container_name: worker
22-
environment:
23-
- APP_SETTINGS=project.server.config.DevelopmentConfig
2422
command: python manage.py run_worker
2523
volumes:
2624
- .:/usr/src/app
25+
environment:
26+
- APP_SETTINGS=project.server.config.DevelopmentConfig
2727
depends_on:
2828
- redis
2929

3030
redis:
3131
image: redis:3.2.11
32+
33+
dashboard:
34+
build: ./project/dashboard
35+
image: dashboard
36+
container_name: dashboard
37+
ports:
38+
- '9181:9181'
39+
command: rq-dashboard -H redis

manage.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
# manage.py
22

33

4-
import os
54
import unittest
65

76
import redis
87
from rq import Connection, Worker
9-
from flask_script import Manager
8+
from flask.cli import FlaskGroup
109

11-
from project.server import app
10+
from project.server import create_app
1211

1312

14-
manager = Manager(app)
13+
app = create_app()
14+
cli = FlaskGroup(create_app=create_app)
1515

1616

17-
@manager.command
17+
@cli.command()
1818
def test():
1919
"""Runs the unit tests without test coverage."""
2020
tests = unittest.TestLoader().discover('project/tests', pattern='test*.py')
@@ -24,13 +24,14 @@ def test():
2424
return 1
2525

2626

27-
@manager.command
27+
@cli.command()
2828
def run_worker():
2929
redis_url = app.config['REDIS_URL']
3030
redis_connection = redis.from_url(redis_url)
3131
with Connection(redis_connection):
3232
worker = Worker(app.config['QUEUES'])
3333
worker.work()
3434

35+
3536
if __name__ == '__main__':
36-
manager.run()
37+
cli()

project/client/static/main.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ $('.btn').on('click', function() {
1515
})
1616
.fail((err) => {
1717
console.log(err)
18-
})
19-
})
18+
});
19+
});
2020

2121
function getStatus(taskID) {
2222
$.ajax({
@@ -30,7 +30,7 @@ function getStatus(taskID) {
3030
<td>${res.data.task_status}</td>
3131
<td>${res.data.task_result}</td>
3232
</tr>`
33-
$('#tasks').prepend(html)
33+
$('#tasks').prepend(html);
3434
const taskStatus = res.data.task_status;
3535
if (taskStatus === 'finished' || taskStatus === 'failed') return false;
3636
setTimeout(function() {
@@ -39,6 +39,5 @@ function getStatus(taskID) {
3939
})
4040
.fail((err) => {
4141
console.log(err)
42-
})
42+
});
4343
}
44-

project/client/templates/_base.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<meta name="author" content="">
1010
<meta name="viewport" content="width=device-width,initial-scale=1">
1111
<!-- styles -->
12-
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css">
12+
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
1313
<link href="{{url_for('static', filename='main.css')}}" rel="stylesheet" media="screen">
1414
{% block css %}{% endblock %}
1515
</head>
@@ -25,8 +25,8 @@
2525

2626
<!-- scripts -->
2727
<script src="//code.jquery.com/jquery-3.2.1.min.js"></script>
28-
<script src="//cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js"></script>
29-
<script src="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js"></script>
28+
<script src="//cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
29+
<script src="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
3030
<script src="{{url_for('static', filename='main.js')}}" type="text/javascript"></script>
3131
{% block js %}{% endblock %}
3232

project/dashboard/Dockerfile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
FROM python:3.6.4-alpine
2+
3+
RUN pip install rq-dashboard
4+
5+
EXPOSE 9181
6+
7+
CMD ["rq-dashboard"]

project/server/__init__.py

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,31 @@
77
from flask_bootstrap import Bootstrap
88

99

10-
app = Flask(
11-
__name__,
12-
template_folder='../client/templates',
13-
static_folder='../client/static'
14-
)
10+
# instantiate the extensions
11+
bootstrap = Bootstrap()
1512

1613

17-
app_settings = os.getenv('APP_SETTINGS', 'project.server.config.DevelopmentConfig')
18-
app.config.from_object(app_settings)
14+
def create_app(script_info=None):
1915

20-
bootstrap = Bootstrap(app)
16+
# instantiate the app
17+
app = Flask(
18+
__name__,
19+
template_folder='../client/templates',
20+
static_folder='../client/static'
21+
)
2122

23+
# set config
24+
app_settings = os.getenv('APP_SETTINGS')
25+
app.config.from_object(app_settings)
2226

23-
from project.server.main.views import main_blueprint
24-
app.register_blueprint(main_blueprint)
27+
# set up extensions
28+
bootstrap.init_app(app)
29+
30+
# register blueprints
31+
from project.server.main.views import main_blueprint
32+
app.register_blueprint(main_blueprint)
33+
34+
# shell context for flask cli
35+
app.shell_context_processor({'app': app})
36+
37+
return app

project/server/config.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,18 @@
66

77
class BaseConfig(object):
88
"""Base configuration."""
9-
DEBUG = False
109
WTF_CSRF_ENABLED = True
1110
REDIS_URL = 'redis://redis:6379/0'
1211
QUEUES = ['default']
1312

13+
1414
class DevelopmentConfig(BaseConfig):
1515
"""Development configuration."""
16-
DEBUG = True
1716
WTF_CSRF_ENABLED = False
1817

1918

2019
class TestingConfig(BaseConfig):
2120
"""Testing configuration."""
22-
DEBUG = True
2321
TESTING = True
2422
WTF_CSRF_ENABLED = False
2523
PRESERVE_CONTEXT_ON_EXCEPTION = False
26-
27-
28-
class ProductionConfig(BaseConfig):
29-
"""Production configuration."""
30-
DEBUG = False

project/server/main/tasks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@
66

77
def create_task(task_type):
88
time.sleep(int(task_type) * 10)
9-
return True
9+
return True

project/server/main/views.py

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22

33

44
import redis
5-
from rq import Queue, push_connection, pop_connection
6-
from flask import current_app, render_template, Blueprint, jsonify, request
5+
from rq import Queue, Connection
6+
from flask import render_template, Blueprint, jsonify, \
7+
request, current_app
78

89
from project.server.main.tasks import create_task
910

11+
1012
main_blueprint = Blueprint('main', __name__,)
1113

1214

@@ -18,8 +20,9 @@ def home():
1820
@main_blueprint.route('/tasks', methods=['POST'])
1921
def run_task():
2022
task_type = request.form['type']
21-
q = Queue()
22-
task = q.enqueue(create_task, task_type)
23+
with Connection(redis.from_url(current_app.config['REDIS_URL'])):
24+
q = Queue()
25+
task = q.enqueue(create_task, task_type)
2326
response_object = {
2427
'status': 'success',
2528
'data': {
@@ -31,8 +34,9 @@ def run_task():
3134

3235
@main_blueprint.route('/tasks/<task_id>', methods=['GET'])
3336
def get_status(task_id):
34-
q = Queue()
35-
task = q.fetch_job(task_id)
37+
with Connection(redis.from_url(current_app.config['REDIS_URL'])):
38+
q = Queue()
39+
task = q.fetch_job(task_id)
3640
if task:
3741
response_object = {
3842
'status': 'success',
@@ -41,17 +45,7 @@ def get_status(task_id):
4145
'task_status': task.get_status(),
4246
'task_result': task.result,
4347
}
44-
}
48+
}
4549
else:
4650
response_object = {'status': 'error'}
4751
return jsonify(response_object)
48-
49-
50-
@main_blueprint.before_request
51-
def push_rq_connection():
52-
push_connection(redis.from_url(current_app.config['REDIS_URL']))
53-
54-
55-
@main_blueprint.teardown_request
56-
def pop_rq_connection(exception=None):
57-
pop_connection()

project/tests/base.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33

44
from flask_testing import TestCase
55

6-
from project.server import app
6+
from project.server import create_app
7+
8+
app = create_app()
79

810

911
class BaseTestCase(TestCase):

project/tests/test__config.py

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
# project/server/tests/test_config.py
1+
# project/server/tests/test__config.py
22

33

44
import unittest
55

66
from flask import current_app
77
from flask_testing import TestCase
88

9-
from project.server import app
9+
from project.server import create_app
10+
11+
app = create_app()
1012

1113

1214
class TestDevelopmentConfig(TestCase):
@@ -34,17 +36,5 @@ def test_app_is_testing(self):
3436
self.assertTrue(app.config['WTF_CSRF_ENABLED'] is False)
3537

3638

37-
class TestProductionConfig(TestCase):
38-
39-
def create_app(self):
40-
app.config.from_object('project.server.config.ProductionConfig')
41-
return app
42-
43-
def test_app_is_production(self):
44-
self.assertFalse(current_app.config['TESTING'])
45-
self.assertTrue(app.config['DEBUG'] is False)
46-
self.assertTrue(app.config['WTF_CSRF_ENABLED'] is True)
47-
48-
4939
if __name__ == '__main__':
5040
unittest.main()

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ Flask-Script==2.0.6
44
Flask-Testing==0.6.2
55
Flask-WTF==0.14.2
66
redis==2.10.6
7-
rq==0.8.2
7+
rq==0.10.0

0 commit comments

Comments
 (0)