diff --git a/.drone.yml b/.drone.yml index 73164af..27243e2 100644 --- a/.drone.yml +++ b/.drone.yml @@ -28,6 +28,12 @@ steps: - pip install codecov - codecov +- name: linting + image: python:3.6 + commands: + - pip install flake8 + - flake8 + --- kind: pipeline name: publish diff --git a/src/humulus/__init__.py b/src/humulus/__init__.py index c88f342..5af77a7 100644 --- a/src/humulus/__init__.py +++ b/src/humulus/__init__.py @@ -13,3 +13,5 @@ # limitations under the License. from humulus.app import create_app + +__all__ = ['create_app', ] diff --git a/src/humulus/app.py b/src/humulus/app.py index 0e078b0..19a8319 100644 --- a/src/humulus/app.py +++ b/src/humulus/app.py @@ -14,8 +14,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os - from flask import Flask, render_template diff --git a/src/humulus/couch.py b/src/humulus/couch.py index 6fd1da1..114bafb 100644 --- a/src/humulus/couch.py +++ b/src/humulus/couch.py @@ -26,6 +26,7 @@ from flask import abort, current_app, g from flask.cli import with_appcontext from slugify import slugify + def get_couch(): """Connect to the configured CouchDB.""" if 'couch' not in g: diff --git a/src/humulus/filters.py b/src/humulus/filters.py index 8064afb..e0b4b79 100644 --- a/src/humulus/filters.py +++ b/src/humulus/filters.py @@ -59,7 +59,7 @@ def recipe_fg(recipe): ) / 200 ) return '{:.3f}'.format( - round(1 + (og - 1 - og_delta)*(1 - attenuation) + og_delta, 3) + round(1 + (og - 1 - og_delta) * (1 - attenuation) + og_delta, 3) ) @@ -123,9 +123,11 @@ def sort_hops(hops, form=False): by_use[hop['use']].append(hop) if form: - key = lambda hop: float(hop.duration.data) + def key(hop): + return float(hop.duration.data) else: - key = lambda hop: float(hop['duration']) + def key(hop): + return float(hop['duration']) hops_sorted = sorted(by_use['FWH'], key=key, reverse=True) hops_sorted.extend(sorted(by_use['Boil'], key=key, reverse=True)) @@ -145,7 +147,7 @@ def ferm_pct(fermentables): total += float(ferm['amount']) # Add a pct to each ferm for ferm in fermentables: - ferm['pct'] = 100*float(ferm['amount'])/total + ferm['pct'] = 100 * float(ferm['amount']) / total return fermentables diff --git a/src/humulus/recipes.py b/src/humulus/recipes.py index fde93f2..525f16c 100644 --- a/src/humulus/recipes.py +++ b/src/humulus/recipes.py @@ -37,8 +37,8 @@ bp = Blueprint('recipes', __name__, url_prefix='/recipes') class FermentableForm(Form): """Form for fermentables. - CSRF is disabled for this form.yeast.form (using `Form as parent class) because it - is never used by itself. + CSRF is disabled for this form.yeast.form (using `Form as parent class) + because it is never used by itself. """ name = StringField('Name', validators=[DataRequired()]) type = SelectField('Type', validators=[DataRequired()], @@ -67,8 +67,8 @@ class FermentableForm(Form): class HopForm(Form): """Form for hops. - CSRF is disabled for this form.yeast.form (using `Form as parent class) because it - is never used by itself. + CSRF is disabled for this form.yeast.form (using `Form as parent class) + because it is never used by itself. """ name = StringField('Name', validators=[DataRequired()]) use = SelectField('Usage', validators=[DataRequired()], @@ -96,8 +96,8 @@ class HopForm(Form): class YeastForm(Form): """Form for yeast. - CSRF is disabled for this form.yeast.form (using `Form as parent class) because it - is never used by itself. + CSRF is disabled for this form.yeast.form (using `Form as parent class) + because it is never used by itself. """ name = StringField('Name', validators=[Optional()]) type = SelectField('Type', default='', @@ -192,10 +192,10 @@ class RecipeForm(FlaskForm): recipe['fermentables'] = [f.doc for f in self.fermentables] recipe['hops'] = [h.doc for h in self.hops] if ( - self.yeast.doc['name'] and - self.yeast.doc['low_attenuation'] != "None" and - self.yeast.doc['high_attenuation'] != "None" - ): + self.yeast.doc['name'] and + self.yeast.doc['low_attenuation'] != "None" and + self.yeast.doc['high_attenuation'] != "None" + ): recipe['yeast'] = self.yeast.doc return recipe @@ -360,7 +360,7 @@ def update(id): 'Your changes have been lost.'.format(recipe['name']) ), 'danger' - ) + ) return redirect(url_for('recipes.info', id=id)) # Copy values from submitted form to the existing recipe and save for key, value in form.doc.items(): diff --git a/src/humulus/styles.py b/src/humulus/styles.py index 1b32a68..388fbb3 100644 --- a/src/humulus/styles.py +++ b/src/humulus/styles.py @@ -65,23 +65,26 @@ def sub_to_doc(sub): doc['ibu']['low'] = (sub.find('./stats/ibu/low').text if sub.find('./stats/ibu/low') is not None else '0') doc['ibu']['high'] = (sub.find('./stats/ibu/high').text - if sub.find('./stats/ibu/high') is not None else '100') + if sub.find('./stats/ibu/high') is not None + else '100') doc['og']['low'] = (sub.find('./stats/og/low').text - if sub.find('./stats/og/low') is not None else '1.0') + if sub.find('./stats/og/low') is not None else '1.0') doc['og']['high'] = (sub.find('./stats/og/high').text if sub.find('./stats/og/high') is not None else '1.2') doc['fg']['low'] = (sub.find('./stats/fg/low').text - if sub.find('./stats/fg/low') is not None else '1.0') + if sub.find('./stats/fg/low') is not None else '1.0') doc['fg']['high'] = (sub.find('./stats/fg/high').text if sub.find('./stats/fg/high') is not None else '1.2') doc['srm']['low'] = (sub.find('./stats/srm/low').text if sub.find('./stats/srm/low') is not None else '0') doc['srm']['high'] = (sub.find('./stats/srm/high').text - if sub.find('./stats/srm/high') is not None else '100') + if sub.find('./stats/srm/high') is not None + else '100') doc['abv']['low'] = (sub.find('./stats/abv/low').text if sub.find('./stats/abv/low') is not None else '0') doc['abv']['high'] = (sub.find('./stats/abv/high').text - if sub.find('./stats/abv/high') is not None else '100') + if sub.find('./stats/abv/high') is not None + else '100') return doc @@ -121,10 +124,10 @@ def get_styles_list(): def import_command(): """CLI command to import BJCP styles.""" url = current_app.config.get( - 'BJCP_STYLES_URL', - ('https://raw.githubusercontent.com/meanphil' - '/bjcp-guidelines-2015/master/styleguide.xml') - ) + 'BJCP_STYLES_URL', + ('https://raw.githubusercontent.com/meanphil' + '/bjcp-guidelines-2015/master/styleguide.xml') + ) import_styles(url) click.echo("Imported BJCP styles.") @@ -153,11 +156,11 @@ def index(): return render_template( 'styles/index.html', - rows=rows[(page-1)*limit:page*limit], + rows=rows[(page - 1) * limit:page * limit], descending=descending, sort_by=sort_by, page=page, - num_pages=math.ceil(len(rows)/limit), + num_pages=math.ceil(len(rows) / limit), limit=limit ) diff --git a/tests/conftest.py b/tests/conftest.py index 52bd0c3..21043e4 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -20,6 +20,7 @@ import pytest from humulus import create_app from humulus.couch import build_couch, get_couch, put_doc + @pytest.fixture def app(): dbname = 'test_{}'.format(str(uuid.uuid4())) @@ -126,7 +127,8 @@ def app(): }) # Add a test style - put_doc({'$type': 'style', + put_doc({ + '$type': 'style', '_id': '1A', 'abv': {'high': '100', 'low': '0'}, 'appearance': 'Good looking', diff --git a/tests/test_auth.py b/tests/test_auth.py index 147b021..ed30b2c 100644 --- a/tests/test_auth.py +++ b/tests/test_auth.py @@ -12,8 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -from flask import session - def test_login(client, auth): # Test GET @@ -43,6 +41,7 @@ def test_login(client, auth): assert session['logged_in'] assert session.permanent + def test_logout(client, auth): # Login auth.login() diff --git a/tests/test_couch.py b/tests/test_couch.py index d276125..33c8805 100644 --- a/tests/test_couch.py +++ b/tests/test_couch.py @@ -12,10 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -import uuid from pathlib import Path -from humulus.couch import * +from humulus.couch import put_doc, get_doc, update_doc, put_designs, get_view def test_put_doc(app): @@ -73,7 +72,7 @@ def test_put_designs(app, monkeypatch): with app.app_context(): # Test initial load of designs - monkeypatch.setattr(Path, 'parent', testpath/'assets/initial') + monkeypatch.setattr(Path, 'parent', testpath / 'assets/initial') put_designs() recipes = get_doc('_design/recipes') @@ -86,7 +85,7 @@ def test_put_designs(app, monkeypatch): assert recipes['_rev'] == rev # Test that changes can be loaded - monkeypatch.setattr(Path, 'parent', testpath/'assets/changed') + monkeypatch.setattr(Path, 'parent', testpath / 'assets/changed') put_designs() recipes = get_doc('_design/recipes') assert 'by-date' in recipes['views'] diff --git a/tests/test_filters.py b/tests/test_filters.py index b6928df..de6bbf7 100644 --- a/tests/test_filters.py +++ b/tests/test_filters.py @@ -14,7 +14,8 @@ from decimal import Decimal -from humulus.filters import * +from humulus.filters import (recipe_abv, recipe_fg, recipe_ibu, sort_hops, + recipe_ibu_ratio, recipe_og, recipe_srm, ferm_pct) from humulus.recipes import HopForm diff --git a/tests/test_recipes.py b/tests/test_recipes.py index 6b1a1fd..b1c69f1 100644 --- a/tests/test_recipes.py +++ b/tests/test_recipes.py @@ -16,7 +16,7 @@ import json from decimal import Decimal from io import BytesIO -from humulus.couch import get_db, get_doc, put_doc +from humulus.couch import get_doc from humulus.recipes import FermentableForm, HopForm, RecipeForm, YeastForm @@ -41,7 +41,6 @@ def test_index(client): response.data ) - # Test sort by name descending response = client.get('/recipes/?descending=true&sort_by=name') assert ( @@ -119,6 +118,7 @@ def test_index(client): response.data ) + def test_create(client, app, auth): """Test success in creating a recipe document.""" # Test GET without login @@ -203,7 +203,7 @@ def test_update(client, app, auth): query_string={'rev': ''}, data=doc) assert response.status_code == 302 with client.session_transaction() as session: - flash_message = dict(session['_flashes']).pop('danger', None) + flash_message = dict(session['_flashes']).pop('danger', None) assert 'Update conflict' in flash_message diff --git a/tests/test_styles.py b/tests/test_styles.py index 4afc118..ca8d5ae 100644 --- a/tests/test_styles.py +++ b/tests/test_styles.py @@ -145,20 +145,21 @@ def test_import_styles(monkeypatch): monkeypatch.setattr('humulus.styles.put_doc', fake_put_doc) import_styles(None) - assert PutRecorder.doc == {'$type': 'style', - '_id': '1A', - 'abv': {'high': '100', 'low': '0'}, - 'appearance': 'Good looking', - 'aroma': 'Smelly', - 'fg': {'high': '1.2', 'low': '1.0'}, - 'flavor': 'Good tasting', - 'ibu': {'high': '100', 'low': '0'}, - 'impression': 'Refreshing', - 'mouthfeel': 'Good feeling', - 'name': 'Test Style', - 'og': {'high': '1.2', 'low': '1.0'}, - 'srm': {'high': '100', 'low': '0'} - } + assert PutRecorder.doc == { + '$type': 'style', + '_id': '1A', + 'abv': {'high': '100', 'low': '0'}, + 'appearance': 'Good looking', + 'aroma': 'Smelly', + 'fg': {'high': '1.2', 'low': '1.0'}, + 'flavor': 'Good tasting', + 'ibu': {'high': '100', 'low': '0'}, + 'impression': 'Refreshing', + 'mouthfeel': 'Good feeling', + 'name': 'Test Style', + 'og': {'high': '1.2', 'low': '1.0'}, + 'srm': {'high': '100', 'low': '0'} + } MockDB.db = {'1A': ''} PutRecorder.doc = None