Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add jquery frontend #41

Merged
merged 51 commits into from
Jan 5, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
bb43ac6
initial commit of Javascript front end
Jul 29, 2017
329f26d
implement getting list of visualisers from REST API
Jul 29, 2017
c198cd2
clean up index.html for better readability
Jul 29, 2017
80bcaef
dynamically add and remove vis settings boxes
Jul 29, 2017
5bd2aa4
follow a few best practices
Jul 29, 2017
74e5cb8
only update the list once all elements are collected
Jul 29, 2017
ef4b258
cache the visulalizer selector in the beginning and reference
Jul 29, 2017
a6d9f60
trigger change event on visualizer selector once all vis are appended
Jul 29, 2017
320ebdb
refactor AJAX calls into functions for better readability
Jul 29, 2017
7a29cf6
move string containing new li elements into the appropriate scope
Jul 29, 2017
5ac9d39
remove bullet points in front of settings
Jul 30, 2017
c355994
update jquery to the latest version
Jul 31, 2017
d1a5979
implement loading the setting options into the respective fields
Jul 31, 2017
efd5578
make sure elements for appending are properly defined.
Jul 31, 2017
76be7df
reference new layout that doesn't have backend connection
Jul 31, 2017
e99591c
further simplify the html document
Jul 31, 2017
33d4273
remove dependency on utility module from web frontend
Jul 31, 2017
52ee227
implement file uploading
Jul 31, 2017
0536e93
request visualize via REST
Aug 1, 2017
70416b7
add settings to query string
Aug 1, 2017
b7f352e
add block for results
Aug 1, 2017
f2f2cd5
display input image when results come in
Aug 6, 2017
6c381d0
display probabilities
Aug 6, 2017
f0dc64c
empty the probability list after every request
Aug 6, 2017
60580d7
append the output probabilities to the correct section
Aug 6, 2017
cb4e2ae
fix reference to outputs according to latest API contract
Sep 15, 2017
40c12e6
display results based on the old layout
Sep 15, 2017
f401990
add selenium to test front-end
Sep 19, 2017
242d67f
Merge branch 'master' of https://github.com/merantix/picasso into add…
Oct 20, 2017
251fcb5
reduce the web app to only one document / remove layout.html
Oct 20, 2017
2a66fa6
add the REST call to the javascript frontend
Oct 20, 2017
34566dc
add license headers
Oct 20, 2017
e21358a
correct the settings handover from API to backend
Dec 3, 2017
e3c0309
fix class probabilities test
Dec 3, 2017
9c664db
move rest API tests to separate test_* file
Dec 4, 2017
dafc5bf
refactor current website implementation to work with factory pattern
Dec 4, 2017
582aed3
rename app inside create_app to avoid shadowing the actual app
Dec 4, 2017
af9db63
add first selenium integration test for loading the new front page
Dec 4, 2017
019e9f0
Skip Selenium test
Dec 4, 2017
d98b862
use firefox 56 instead of chrome for selenium tests
Dec 6, 2017
394533f
fix requirements aka moving selenium to test_requirements
Dec 6, 2017
6c8d088
move integration test into its own step
Dec 9, 2017
6952f86
fix typos and style warnings
Dec 31, 2017
98aad69
Add basic image verification
Dec 31, 2017
c40daff
verify output images
Dec 31, 2017
8b5c2d7
Do not ask for confirmation when creating conda env
Dec 31, 2017
ef1ace6
remove params from conda create
Dec 31, 2017
21acb3a
verify output images based on settings parameters
Jan 1, 2018
303cfd8
add integration tests to travis
Jan 3, 2018
7b290a0
put unit tests and integration tests into same stage
Jan 3, 2018
6c40f3f
fix build stages according to tutorial
Jan 3, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ dist: trusty
language: python
python: "3.5"


addons:
firefox: latest

before_install:
- wget https://github.com/mozilla/geckodriver/releases/download/v0.19.1/geckodriver-v0.19.1-linux64.tar.gz
- mkdir geckodriver
- tar -xzf geckodriver-v0.19.1-linux64.tar.gz -C geckodriver
- export PATH=$PATH:$PWD/geckodriver

# command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors
install:
# code below is taken from http://conda.pydata.org/docs/travis.html
Expand All @@ -23,7 +33,7 @@ install:
# Useful for debugging any issues with conda
- conda info -a

- conda create -q -n test-environment python=$TRAVIS_PYTHON_VERSION numpy scipy matplotlib pandas pytest h5py
- conda create -n test-environment python=$TRAVIS_PYTHON_VERSION numpy scipy matplotlib pandas pytest h5py
- source activate test-environment

# install PIL for preprocessing tests
Expand All @@ -40,7 +50,10 @@ install:
# install TensorFlow (CPU version).
- pip install tensorflow

script: pytest --cov=picasso
jobs:
include:
- script: pytest -vls --cov=picasso
- script: pytest -vls ./integration_tests/

after_success:
- codecov
7 changes: 4 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,16 @@ lint: ## check style with flake8
flake8 picasso tests

test: ## run tests quickly with the default Python
py.test

py.test ./tests
py.test ./integration_tests


test-all: ## run tests on every Python version with tox
tox

coverage: ## check code coverage quickly with the default Python
coverage run --source picasso -m pytest

coverage report -m
coverage html
$(BROWSER) htmlcov/index.html
Expand Down
33 changes: 33 additions & 0 deletions integration_tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
###############################################################################
# Copyright (c) 2017 Merantix GmbH
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
#
# Contributors:
# Ryan Henderson - initial API and implementation and/or initial
# documentation
###############################################################################
from PIL import Image
import numpy as np
import pytest
from selenium.webdriver import Firefox
from selenium.webdriver.firefox.options import Options

from picasso import create_app


@pytest.fixture
def app():
_app = create_app()
return _app


@pytest.fixture(scope='module')
def webdriver():
options = Options()
options.add_argument('-headless')
driver = Firefox(firefox_options=options)
yield driver
driver.quit()
33 changes: 33 additions & 0 deletions integration_tests/test_selenium.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
###############################################################################
# Copyright (c) 2017 Merantix GmbH
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
#
# Contributors:
# Jan Steinke - Selenium integration tests
###############################################################################

"""
test_selenium
----------------------------------

Integration tests for `picasso` module.
"""

import pytest
from flask import url_for


@pytest.mark.usefixtures('live_server')
class TestIntegration:

def test_page_load(self, webdriver):
url = url_for('frontend.index', _external=True)
webdriver.get(url)
webdriver.find_element_by_id('appstate_checkpoint')


27 changes: 22 additions & 5 deletions picasso/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,33 @@
import os
import sys
from picasso.interfaces.rest import API
from picasso.interfaces.web import frontend
from picasso import picasso

if sys.version_info.major < 3 or (sys.version_info.major == 3 and
sys.version_info.minor < 5):
raise SystemError('Python 3.5+ required, found {}'.format(sys.version))

app = Flask(__name__)
app.config.from_object('picasso.config.Default')
app.register_blueprint(API, url_prefix='/api')

def create_app(debug=False):
_app = Flask(__name__)
_app.debug = debug
_app.config.from_object('picasso.config.Default')
_app.register_blueprint(API, url_prefix='/api')
_app.register_blueprint(frontend, url_prefix='/v2')
_app.register_blueprint(picasso.frontend)

# Use a bogus secret key for debugging ease. No client information is stored;
# the secret key is only necessary for generating the session cookie.
if _app.debug:
_app.secret_key = '...'
else:
_app.secret_key = os.urandom(24)

return _app


app = create_app()

if os.getenv('PICASSO_SETTINGS'):
app.config.from_envvar('PICASSO_SETTINGS')
Expand All @@ -38,5 +57,3 @@
' and '
'https://picasso.readthedocs.io/en/latest/settings.html'
.format(__version__))

import picasso.picasso
48 changes: 36 additions & 12 deletions picasso/interfaces/rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@

import os
import shutil
import logging
from tempfile import mkdtemp

from PIL import Image
from werkzeug.utils import secure_filename
from flask import (
Expand All @@ -32,6 +35,29 @@
)

API = Blueprint('api', __name__)
logger = logging.getLogger(__name__)


@API.before_request
def initialize_new_session():
"""Check session and initialize if necessary

Before every request, check the user session. If no session exists, add
one and provide temporary locations for images

"""
if 'image_uid_counter' in session and 'image_list' in session:
logger.debug('images are already being tracked')
else:
# reset image list counter for the session
session['image_uid_counter'] = 0
session['image_list'] = []
if 'img_input_dir' in session and 'img_output_dir' in session:
logger.debug('temporary image directories already exist')
else:
# make image upload directory
session['img_input_dir'] = mkdtemp()
session['img_output_dir'] = mkdtemp()


@API.route('/', methods=['GET'])
Expand Down Expand Up @@ -66,7 +92,7 @@ def images():
if request.method == 'POST':
file_upload = request.files['file']
if file_upload:
image = {}
image = dict()
image['filename'] = secure_filename(file_upload.filename)
full_path = os.path.join(session['img_input_dir'],
image['filename'])
Expand Down Expand Up @@ -99,12 +125,8 @@ def visualizers():
@API.route('/visualizers/<vis_name>', methods=['GET'])
def visualizers_information(vis_name):
vis = get_visualizations()[vis_name]
if hasattr(vis, 'ALLOWED_SETTINGS'):
settings = vis.ALLOWED_SETTINGS
else:
settings = {}

return jsonify(settings=settings)
return jsonify(settings=vis.ALLOWED_SETTINGS)


@API.route('/visualize', methods=['GET'])
Expand All @@ -120,23 +142,25 @@ def visualize():
image_uid = request.args.get('image')
vis_name = request.args.get('visualizer')
vis = get_visualizations()[vis_name]
if hasattr(vis, 'settings'):
for key in vis.settings.keys():
if vis.ALLOWED_SETTINGS:
for key in vis.ALLOWED_SETTINGS.keys():
if request.args.get(key) is not None:
session['settings'][key] = request.args.get(key)
else:
session['settings'][key] = vis.settings[key][0]
session['settings'][key] = vis.ALLOWED_SETTINGS[key][0]
else:
logger.debug('Selected Visualizer {0} has no settings.'.format(vis_name))
inputs = []
for image in session['image_list']:
if image['uid'] == int(image_uid):
full_path = os.path.join(session['img_input_dir'],
image['filename'])
entry = {}
entry = dict()
entry['filename'] = image['filename']
entry['data'] = Image.open(full_path)
inputs.append(entry)
if 'settings' in session:
vis.update_settings(session['settings'])

vis.update_settings(session['settings'])
output = vis.make_visualization(
inputs, output_dir=session['img_output_dir'])
return jsonify(output[0])
Expand Down
28 changes: 28 additions & 0 deletions picasso/interfaces/web.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
###############################################################################
# Copyright (c) 2017 Merantix GmbH
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
#
# Contributors:
# Jan Steinke - Restful API
###############################################################################
"""Flask blueprint for interfacing with picasso via web.

This is used by the main flask application to provide a web front-end based on the REST api.
"""

from flask import (
render_template,
Blueprint
)

frontend = Blueprint('frontend', __name__)


@frontend.route('/')
def index():
return render_template('v2/index.html')

Loading