From 8f99b798bb5b3b2bf46511f2477e7b7dac8f541f Mon Sep 17 00:00:00 2001 From: Joachim Lusiardi Date: Wed, 13 Apr 2016 08:30:13 +0200 Subject: [PATCH 1/3] reworked docker file for faster build times --- Dockerfile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 1c82b2f..08db488 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,11 @@ FROM debian8_python3 -ADD app /app -RUN pip3 install -r /app/requirements.txt; \ +COPY app/requirements.txt /requirements.txt +RUN pip3 install -r /requirements.txt; \ mkdir /data +ADD app /app + VOLUME ["/data"] EXPOSE 5000 ENTRYPOINT python3 /app/main.py From fb521194f7e1b42f3b7170e40e48e0fb66c07b56 Mon Sep 17 00:00:00 2001 From: Joachim Lusiardi Date: Thu, 14 Apr 2016 07:32:06 +0200 Subject: [PATCH 2/3] Reduce services feature and reformatting --- app/db/__init__.py | 42 +++++--------- app/main.py | 76 +++++++++++++------------- app/schema.sql | 9 --- app/templates/layout.html | 26 +-------- app/templates/manual.html | 1 - app/templates/newPitStopForm.html | 1 - app/templates/pitstops.html | 1 - app/templates/services.html | 91 ------------------------------- app/templates/statistics.html | 1 - 9 files changed, 51 insertions(+), 197 deletions(-) delete mode 100644 app/templates/services.html diff --git a/app/db/__init__.py b/app/db/__init__.py index 9b8c840..f999b01 100644 --- a/app/db/__init__.py +++ b/app/db/__init__.py @@ -1,51 +1,39 @@ -''' +""" -@author: shing19m -''' +@author: jlusiardi +""" from datetime import datetime import sqlite3 class Db(object): - ''' + """ classdocs - ''' - + """ def __init__(self, db_file): - ''' + """ Constructor - ''' + """ self.db = sqlite3.connect(db_file) def __del__(self): self.db.close() - def getAllPitStops(self): + def get_all_pit_stops(self): return self._perform_query('select * from pitstops order by id asc') - def getAllServices(self): - return self._perform_query('select * from services') - - def getLastPitStop(self): + def get_last_pit_stop(self): pitstops = self._perform_query('select * from pitstops order by id desc limit 1') if len(pitstops) == 0: return {'date': datetime.strftime(datetime.now(), '%Y-%m-%d'), 'odometer': 0, 'litres': 0} return pitstops[0] - - def get_service_warning_info(self): - info = self._perform_query('select (odometer_planned - (select odometer from pitstops order by id desc limit 1)) km_left, tasks from services where date is null order by odometer_planned asc limit 1;') - if len(info) == 0: - return None - return info[0] - - def get_next_undone_service(self): - services = self._perform_query('select * from services where date is null limit 1') - if len(services) == 0: - return None - return services[0] + + def add_pit_stop(self, date, odometer, litres): + self.db.execute('insert into pitstops (date, odometer, litres) values (?, ?, ?)', [date, odometer, litres]) + self.db.commit() def get_salt_for_user(self, user): salt = self._perform_query_param('select salt from users where name = ?', [user]) @@ -81,10 +69,6 @@ class Db(object): result.append(row_result) return result - def addPitStop(self, date, odometer, litres): - self.db.execute('insert into pitstops (date, odometer, litres) values (?, ?, ?)', [date, odometer, litres]) - self.db.commit() - def init_db(self, resource): with resource as f: sql_commands = f.read() diff --git a/app/main.py b/app/main.py index 4fc72fe..16a8fdb 100644 --- a/app/main.py +++ b/app/main.py @@ -12,16 +12,16 @@ from functools import wraps import db -#from db import Db app = Flask(__name__) DATABASE = '/data/rollerverbrauch.db' DEBUG = True SECRET_KEY = 'development key' app.config.from_object(__name__) + def check_auth(username, password): salt = g.db2.get_salt_for_user(username) - if salt == None: + if salt is None: return False m = hashlib.sha256(password.encode('utf-8')) m = hashlib.sha256((m.hexdigest()+salt).encode('utf-8')) @@ -31,11 +31,13 @@ def check_auth(username, password): app.logger.error("digest: " + digest) return ok + def authenticate(): resp = make_response(render_template('login_required.html'), 401) resp.headers['WWW-Authenticate'] = 'Basic realm="Login Required"' return resp + def requires_auth(f): @wraps(f) def decorated(*args, **kwargs): @@ -45,50 +47,45 @@ def requires_auth(f): return f(*args, **kwargs) return decorated + @app.before_request def before_request(): g.db2 = db.Db(app.config['DATABASE']) g.data = {} - add_service_warning(g.data) + @app.teardown_request def teardown_request(exception): pass + @app.route('/') @requires_auth def index(): return redirect(url_for('get_pit_stops')) -@app.route('/services') -@requires_auth -def get_services(): - data = g.db2.getAllServices() - data.reverse() - g.data['services'] = data - return render_template('services.html', data=g.data) @app.route('/pitstops', methods=['POST']) @requires_auth def create_pit_stop(): - last_pitstop = g.db2.getLastPitStop() - errorMsg = {} + last_pitstop = g.db2.get_last_pit_stop() + error_msg = {} date = request.form['date'] try: date = datetime.strptime(date, '%Y-%m-%d').strftime('%Y-%m-%d') except ValueError: - errorMsg['date'] = 'invalid date, only YYYY-MM-DD is allowed' + error_msg['date'] = 'invalid date, only YYYY-MM-DD is allowed' date = request.form['date'] odometer = request.form['odometer'] try: odometer = int(odometer) except ValueError: - errorMsg['odometer'] = 'Illegal Value, only Integers allowed' + error_msg['odometer'] = 'Illegal Value, only Integers allowed' odometer = None if odometer is not None and odometer <= last_pitstop['odometer']: - errorMsg['odometer'] = 'Illegal Value, new Value must be bigger as given value' + error_msg['odometer'] = 'Illegal Value, new Value must be bigger as given value' odometer = request.form['odometer'] if odometer is None: odometer = request.form['odometer'] @@ -97,76 +94,77 @@ def create_pit_stop(): try: litres = float(litres) except ValueError: - errorMsg['litres'] = 'Illegal Value, only floating point allowed' + error_msg['litres'] = 'Illegal Value, only floating point allowed' litres = None if litres is not None and litres <= 0: - errorMsg['litres'] = 'Litres must not be 0' + error_msg['litres'] = 'Litres must not be 0' litres = request.form['litres'] if litres is None: litres = request.form['litres'] # error checking here - if len(errorMsg) > 0: - data = {'last': {'date': date, 'odometer': odometer, 'litres': litres}, 'error': errorMsg} + if len(error_msg) > 0: + data = {'last': {'date': date, 'odometer': odometer, 'litres': litres}, 'error': error_msg} return render_template('newPitStopForm.html', data=data) - g.db2.addPitStop(date, odometer, litres) + g.db2.add_pit_stop(date, odometer, litres) return redirect(url_for('get_pit_stops')) + @app.route('/pitstops/createForm', methods=['GET']) @requires_auth def create_pit_stop_form(): - values = g.db2.getLastPitStop() + values = g.db2.get_last_pit_stop() values['date'] = time.strftime("%Y-%m-%d") g.data['last'] = values g.data['error'] = None return render_template('newPitStopForm.html', data=g.data) -def add_service_warning(data): - service_info = g.db2.get_service_warning_info() - data['service_info'] = service_info @app.route('/pitstops', methods=['GET']) @requires_auth def get_pit_stops(): - data = prepare_pit_stops(g.db2.getAllPitStops()) + data = prepare_pit_stops(g.db2.get_all_pit_stops()) g.data['pitstops'] = data return render_template('pitstops.html', data=g.data) + @app.route('/manual', methods=['GET']) @requires_auth def get_manual(): return render_template('manual.html', data=g.data) + @app.route('/statistics', methods=['GET']) @requires_auth def get_statistics(): - pitstops = g.db2.getAllPitStops() + pitstops = g.db2.get_all_pit_stops() count = len(pitstops) distance = 0 - sumLitres = 0 - averageDistance = 0 - averageLitresFuelled = 0 - averageLitresUsed = 0 + sum_litres = 0 + average_distance = 0 + average_litres_fuelled = 0 + average_litres_used = 0 if count > 0: - sumLitres = 0 + sum_litres = 0 for pitstop in pitstops: - sumLitres += pitstop['litres'] - averageLitresFuelled = sumLitres/count + sum_litres += pitstop['litres'] + average_litres_fuelled = sum_litres/count if count > 1: distance = pitstops[-1]['odometer'] - pitstops[0]['odometer'] - averageDistance = distance/(count - 1) - averageLitresUsed = 100 * (sumLitres-pitstops[0]['litres'])/distance + average_distance = distance/(count - 1) + average_litres_used = 100 * (sum_litres-pitstops[0]['litres'])/distance g.data['distance'] = distance g.data['count'] = count - g.data['litres'] = sumLitres - g.data['averageDistance'] = averageDistance - g.data['averageListresFuelled'] = averageLitresFuelled - g.data['averageListresUsed'] = averageLitresUsed + g.data['litres'] = sum_litres + g.data['averageDistance'] = average_distance + g.data['averageListresFuelled'] = average_litres_fuelled + g.data['averageListresUsed'] = average_litres_used return render_template('statistics.html', data=g.data) + def prepare_pit_stops(pitstops): for index in range(1, len(pitstops)): last = pitstops[index - 1] diff --git a/app/schema.sql b/app/schema.sql index c841005..c280175 100644 --- a/app/schema.sql +++ b/app/schema.sql @@ -6,15 +6,6 @@ create table pitstops ( `litres` REAL NOT NULL ); -drop table if exists services; -CREATE TABLE `services` ( - `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - `date` TEXT, - `odometer_planned` INTEGER NOT NULL, - `odometer_done` INTEGER, - `tasks` TEXT NOT NULL -); - drop table if exists users; create table `users` ( `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, diff --git a/app/templates/layout.html b/app/templates/layout.html index 94d6b2c..2688f76 100644 --- a/app/templates/layout.html +++ b/app/templates/layout.html @@ -1,30 +1,6 @@ -{% macro alert_level(km_left) -%} - {% if km_left == None %} - alert-success - {% elif km_left < 0 %} - alert-danger - {% elif km_left < 300 %} - alert-warning - {% else %} - alert-success - {% endif %} -{%- endmacro %} - -{% macro service_warning() -%} - {% if data != None and data.service_info != None and 'km_left' in data.service_info %} - - {% endif %} -{%- endmacro %} - {% macro navigation() -%}
  • Create Pitstop
  • Statistics
  • -
  • Services
  • Manual
  • {%- endmacro %} @@ -36,7 +12,7 @@ - Rollerverbrauch + Rollerverbrauch 0.1 diff --git a/app/templates/manual.html b/app/templates/manual.html index b63b5bc..a397e1a 100644 --- a/app/templates/manual.html +++ b/app/templates/manual.html @@ -12,7 +12,6 @@ {%- endmacro %} {% block body %} - {{ service_warning() }}
    diff --git a/app/templates/newPitStopForm.html b/app/templates/newPitStopForm.html index 71aaa96..190e0eb 100644 --- a/app/templates/newPitStopForm.html +++ b/app/templates/newPitStopForm.html @@ -1,7 +1,6 @@ {% extends "layout.html" %} {% block body %} - {{ service_warning() }} diff --git a/app/templates/pitstops.html b/app/templates/pitstops.html index eb4f74f..093b226 100644 --- a/app/templates/pitstops.html +++ b/app/templates/pitstops.html @@ -1,7 +1,6 @@ {% extends "layout.html" %} {% block body %} - {{ service_warning() }}
    diff --git a/app/templates/services.html b/app/templates/services.html deleted file mode 100644 index 99aa60b..0000000 --- a/app/templates/services.html +++ /dev/null @@ -1,91 +0,0 @@ -{% extends "layout.html" %} - -{% macro print_service_header() -%} - - - - - -{%- endmacro %} - -{% macro print_service(service) -%} - - - - - -{%- endmacro %} - -{% block body %} - {{ service_warning() }} -
    - -
    -
    -
    -
    - Odometer
    - (planned
    - done) -
    - Date
    - (done) -
    - Tasks -
    - {{service.odometer_planned}} km
    - {% if service.odometer_done %} - {{service.odometer_done}} km - {% else %} - -- km - {% endif %} -
    - {% if service.date %} - {{service.date}} - {% else %} - -- - {% endif %} - - - {% for task in service.tasks.split(',') %} - {{task}}
    - {% endfor %} -
    - {{ print_service_header() }} - {% for service in data['services'] | reverse() %} - {% if not service.odometer_done %} - {{ print_service(service) }} - {% endif %} - {% endfor %} -
    -
    - -
    -
    - - {{ print_service_header() }} - {% for service in data['services'] %} - {% if service.odometer_done %} - {{ print_service(service) }} - {% endif %} - {% endfor %} -
    -
    -
    - - - - -{% endblock %} \ No newline at end of file diff --git a/app/templates/statistics.html b/app/templates/statistics.html index dd3913c..dd75d98 100644 --- a/app/templates/statistics.html +++ b/app/templates/statistics.html @@ -1,7 +1,6 @@ {% extends "layout.html" %} {% block body %} - {{ service_warning() }}
    From 059c86b449bb8302ca6d1b9dea5c6c383b44942e Mon Sep 17 00:00:00 2001 From: Joachim Lusiardi Date: Thu, 14 Apr 2016 19:53:49 +0200 Subject: [PATCH 3/3] add .gitignore file --- .gitignore | 181 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..179dd1d --- /dev/null +++ b/.gitignore @@ -0,0 +1,181 @@ +### Python template +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# Flask instance folder +instance/ + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# IPython Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# dotenv +.env + +# virtualenv +venv/ +ENV/ + +# Spyder project settings +.spyderproject + +# Rope project settings +.ropeproject + +### Python template +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# Flask instance folder +instance/ + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# IPython Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# dotenv +.env + +# virtualenv +venv/ +ENV/ + +# Spyder project settings +.spyderproject + +# Rope project settings +.ropeproject + +# Created by .ignore support plugin (hsz.mobi)