From 6fdeb96d648b56ce8845f425cb7d35c2d334565a Mon Sep 17 00:00:00 2001 From: Roland Geider Date: Sat, 27 Jan 2024 10:30:02 +0100 Subject: [PATCH] Initial formatting with ruff --- .github/workflows/formatter.yml | 3 + extras/scripts/filter-fixtures.py | 20 +- manage.py | 1 + wger/celery_configuration.py | 4 +- wger/config/apps.py | 2 +- wger/config/migrations/0001_initial.py | 28 +- .../migrations/0002_auto_20190618_1617.py | 5 +- .../migrations/0003_delete_languageconfig.py | 5 +- wger/config/models/gym_config.py | 5 +- wger/config/tests/test_custom_header.py | 1 - wger/config/urls.py | 2 +- wger/config/views/gym_config.py | 1 + wger/core/api/endpoints.py | 4 +- wger/core/api/serializers.py | 20 +- wger/core/api/views.py | 68 +-- wger/core/apps.py | 2 +- wger/core/demo.py | 6 +- wger/core/forms.py | 98 ++-- .../core/management/commands/add-user-rest.py | 9 +- wger/core/management/commands/clear-cache.py | 32 +- .../management/commands/delete-temp-users.py | 5 +- .../commands/dummy-generator-users.py | 6 +- .../extract-i18n-flutter-exercises.py | 21 +- wger/core/management/commands/extract-i18n.py | 47 +- .../management/commands/list-users-api.py | 6 +- wger/core/management/commands/set-site-url.py | 2 +- .../management/commands/update-user-cache.py | 8 +- wger/core/migrations/0001_initial.py | 147 +++-- .../migrations/0002_auto_20141225_1512.py | 14 +- .../migrations/0003_auto_20150217_1554.py | 14 +- .../migrations/0004_auto_20150217_1914.py | 3 +- .../migrations/0005_auto_20151025_2236.py | 9 +- .../migrations/0006_auto_20151025_2237.py | 12 +- wger/core/migrations/0007_repetitionunit.py | 3 +- wger/core/migrations/0008_weightunit.py | 3 +- .../migrations/0009_auto_20160303_2340.py | 1 - .../migrations/0010_auto_20170403_0144.py | 8 +- .../migrations/0011_auto_20201201_0653.py | 3 +- .../migrations/0012_auto_20210210_1228.py | 3 +- .../migrations/0013_auto_20210726_1729.py | 1 - .../0013_userprofile_email_verified.py | 1 - .../migrations/0014_merge_20210818_1735.py | 1 - .../0015_alter_language_short_name.py | 1 - .../0016_alter_language_short_name.py | 6 +- wger/core/models/cache.py | 2 +- wger/core/models/days_of_week.py | 3 +- wger/core/models/language.py | 5 +- wger/core/models/license.py | 9 +- wger/core/models/profile.py | 64 +-- wger/core/models/rep_unit.py | 3 +- wger/core/models/weight_unit.py | 3 +- wger/core/signals.py | 3 +- wger/core/templatetags/wger_extras.py | 19 +- wger/core/tests/api_base_test.py | 41 +- wger/core/tests/base_testcase.py | 8 +- wger/core/tests/test_change_password.py | 1 - wger/core/tests/test_daysofweek.py | 3 +- wger/core/tests/test_delete_user.py | 5 +- wger/core/tests/test_feedback.py | 9 +- wger/core/tests/test_generator.py | 1 - wger/core/tests/test_index.py | 13 +- wger/core/tests/test_language.py | 3 +- wger/core/tests/test_license.py | 3 +- wger/core/tests/test_permission_api.py | 1 - wger/core/tests/test_preferences.py | 40 +- wger/core/tests/test_registration.py | 16 +- wger/core/tests/test_repetition_unit.py | 9 +- wger/core/tests/test_robots_txt.py | 1 - wger/core/tests/test_sitemap.py | 3 - wger/core/tests/test_user_login.py | 22 +- .../core/tests/test_user_rest_registration.py | 51 +- wger/core/tests/test_weight_unit.py | 9 +- wger/core/urls.py | 18 +- wger/core/views/languages.py | 1 + wger/core/views/license.py | 1 + wger/core/views/misc.py | 9 +- wger/core/views/repetition_units.py | 1 + wger/core/views/user.py | 105 ++-- wger/core/views/weight_units.py | 1 + wger/exercises/api/endpoints.py | 14 +- wger/exercises/api/permissions.py | 6 +- wger/exercises/api/serializers.py | 157 ++--- wger/exercises/api/views.py | 79 +-- wger/exercises/apps.py | 3 +- wger/exercises/forms.py | 5 +- .../commands/change-exercise-author.py | 6 +- .../commands/delete-unused-exercises.py | 1 - .../commands/download-exercise-images.py | 3 +- .../commands/download-exercise-videos.py | 4 +- .../management/commands/exercise-cleanup.py | 9 +- .../commands/exercises-health-check.py | 22 +- .../commands/read-exercise-cleanup.py | 39 +- .../commands/submitted-exercises.py | 1 - .../management/commands/sync-exercises.py | 6 +- .../commands/warmup-exercise-api-cache.py | 8 +- wger/exercises/migrations/0001_initial.py | 84 ++- .../migrations/0002_auto_20150307_1841.py | 3 +- .../migrations/0003_auto_20160921_2000.py | 5 +- .../migrations/0004_auto_20170404_0114.py | 12 +- .../migrations/0005_auto_20190618_1617.py | 11 +- .../migrations/0006_auto_20201203_0203.py | 5 +- .../migrations/0007_auto_20201203_1042.py | 41 -- .../exercises/migrations/0008_exercisebase.py | 35 +- .../migrations/0009_auto_20201211_0139.py | 5 +- .../migrations/0010_auto_20201211_0205.py | 1 - .../migrations/0011_auto_20201214_0033.py | 536 +++--------------- .../migrations/0012_auto_20210327_1219.py | 3 +- .../migrations/0013_auto_20210503_1232.py | 5 +- .../migrations/0014_exerciseimage_style.py | 9 +- .../migrations/0015_exercise_videos.py | 38 +- .../migrations/0016_exercisealias.py | 7 +- .../migrations/0017_muscle_name_en.py | 3 +- .../0018_delete_pending_exercises.py | 5 +- .../0019_exercise_crowdsourcing_changes.py | 115 ++-- ...alexerciseimage_historicalexercisevideo.py | 87 ++- wger/exercises/migrations/0021_deletionlog.py | 13 +- ..._alter_exercise_license_author_and_more.py | 41 +- .../migrations/0023_make_uuid_unique.py | 1 - .../migrations/0024_license_information.py | 18 +- .../0026_deletionlog_replaced_by.py | 2 +- ..._alter_deletionlog_replaced_by_and_more.py | 77 ++- .../0028_add_uuid_alias_and_comments.py | 48 +- wger/exercises/models/base.py | 9 +- wger/exercises/models/category.py | 5 +- wger/exercises/models/comment.py | 3 +- wger/exercises/models/equipment.py | 3 +- wger/exercises/models/exercise.py | 3 +- wger/exercises/models/exercise_alias.py | 1 + wger/exercises/models/image.py | 42 +- wger/exercises/models/muscle.py | 6 +- wger/exercises/models/video.py | 4 +- wger/exercises/signals.py | 1 - wger/exercises/sitemap.py | 2 +- wger/exercises/sync.py | 31 +- wger/exercises/tests/test_categories.py | 7 +- .../tests/test_change_exercise_author.py | 14 +- wger/exercises/tests/test_deletion_log.py | 4 +- wger/exercises/tests/test_equipment.py | 5 +- .../tests/test_exercise_api_cache.py | 6 +- wger/exercises/tests/test_exercise_base.py | 10 +- .../tests/test_exercise_base_model.py | 5 +- .../exercises/tests/test_exercise_comments.py | 9 +- wger/exercises/tests/test_exercise_images.py | 1 + .../tests/test_exercise_translation.py | 40 +- wger/exercises/tests/test_history.py | 4 +- .../tests/test_management_commands.py | 26 +- wger/exercises/tests/test_muscles.py | 16 +- wger/exercises/tests/test_sync.py | 8 - wger/exercises/urls.py | 12 +- wger/exercises/views/categories.py | 3 +- wger/exercises/views/exercises.py | 5 +- wger/exercises/views/history.py | 7 +- wger/exercises/views/muscles.py | 1 + wger/gallery/api/views.py | 3 +- wger/gallery/apps.py | 2 +- wger/gallery/migrations/0001_initial.py | 13 +- wger/gallery/models/image.py | 6 +- wger/gallery/urls.py | 2 +- wger/gallery/views/images.py | 2 + wger/gym/apps.py | 2 +- wger/gym/forms.py | 18 +- wger/gym/helpers.py | 6 +- .../commands/dummy-generator-gyms.py | 61 +- .../management/commands/gym-user-config.py | 1 + .../management/commands/inactive-members.py | 6 +- wger/gym/migrations/0001_initial.py | 86 ++- .../gym/migrations/0002_auto_20151003_1944.py | 6 +- .../gym/migrations/0003_auto_20151003_2008.py | 41 +- .../gym/migrations/0004_auto_20151003_2357.py | 1 - .../gym/migrations/0005_auto_20151023_1522.py | 5 +- .../gym/migrations/0006_auto_20160214_1013.py | 9 +- .../gym/migrations/0007_auto_20170123_0920.py | 12 +- .../gym/migrations/0008_auto_20190618_1617.py | 3 +- wger/gym/models/admin_user_note.py | 3 +- wger/gym/models/contract.py | 19 +- wger/gym/models/gym.py | 8 +- wger/gym/models/gym_config.py | 2 +- wger/gym/models/user_config.py | 3 +- wger/gym/models/user_document.py | 9 +- wger/gym/tests/test_admin_user_notes.py | 2 + wger/gym/tests/test_contract_options.py | 1 + wger/gym/tests/test_contract_types.py | 1 + wger/gym/tests/test_contracts.py | 2 + wger/gym/tests/test_export.py | 5 +- wger/gym/tests/test_generator.py | 1 - wger/gym/tests/test_gym.py | 5 +- wger/gym/tests/test_user.py | 5 +- wger/gym/tests/test_user_documents.py | 1 + wger/gym/urls.py | 20 +- wger/gym/views/admin_notes.py | 1 + wger/gym/views/contract.py | 1 + wger/gym/views/contract_option.py | 1 + wger/gym/views/contract_type.py | 1 + wger/gym/views/document.py | 1 + wger/gym/views/export.py | 8 +- wger/gym/views/gym.py | 60 +- wger/mailer/apps.py | 2 +- wger/mailer/migrations/0001_initial.py | 7 +- .../migrations/0002_auto_20190618_1617.py | 3 +- .../migrations/0003_auto_20201201_0653.py | 3 +- wger/mailer/models/log.py | 2 +- wger/mailer/tests/test_gym_emails.py | 1 + wger/mailer/urls.py | 2 +- wger/mailer/views/gym.py | 15 +- wger/manager/api/serializers.py | 14 +- wger/manager/api/views.py | 37 +- wger/manager/apps.py | 2 +- wger/manager/forms.py | 39 +- wger/manager/helpers.py | 30 +- .../commands/dummy-generator-workout-diary.py | 11 +- .../commands/dummy-generator-workout-plans.py | 9 +- .../management/commands/email-reminders.py | 25 +- wger/manager/managers.py | 4 - wger/manager/migrations/0001_initial.py | 137 +++-- .../migrations/0002_auto_20150202_2040.py | 1 - .../migrations/0004_auto_20150609_1603.py | 5 +- .../migrations/0005_auto_20160303_2008.py | 18 +- .../migrations/0006_auto_20160303_2138.py | 1 - .../migrations/0007_auto_20160311_2258.py | 1 - .../migrations/0008_auto_20190618_1617.py | 5 +- .../migrations/0009_auto_20201202_1559.py | 29 +- .../migrations/0010_auto_20210102_1446.py | 29 +- .../migrations/0011_remove_set_exercises.py | 3 +- .../migrations/0012_auto_20210430_1449.py | 13 +- wger/manager/migrations/0013_set_comment.py | 1 - .../migrations/0014_auto_20210717_1858.py | 1 - .../migrations/0015_auto_20211028_1113.py | 8 +- .../migrations/0016_move_to_exercise_base.py | 11 +- .../0017_alter_workoutlog_exercise_base.py | 183 ++++-- wger/manager/models/day.py | 19 +- wger/manager/models/log.py | 4 +- wger/manager/models/schedule.py | 15 +- wger/manager/models/schedule_step.py | 3 +- wger/manager/models/session.py | 21 +- wger/manager/models/set.py | 11 +- wger/manager/models/setting.py | 6 +- wger/manager/models/workout.py | 18 +- wger/manager/tests/test_copy_workout.py | 1 - wger/manager/tests/test_day.py | 2 +- wger/manager/tests/test_generator.py | 1 - wger/manager/tests/test_ical.py | 24 +- wger/manager/tests/test_pdf.py | 40 +- wger/manager/tests/test_schedule.py | 94 ++- wger/manager/tests/test_schedule_step.py | 3 +- wger/manager/tests/test_set.py | 20 +- wger/manager/tests/test_weight_log.py | 68 +-- wger/manager/tests/test_workout.py | 3 +- wger/manager/tests/test_workout_canonical.py | 115 ++-- wger/manager/tests/test_workout_session.py | 18 +- wger/manager/urls.py | 18 +- wger/manager/views/ical.py | 11 +- wger/manager/views/log.py | 23 +- wger/manager/views/pdf.py | 8 +- wger/manager/views/schedule.py | 16 +- wger/manager/views/set.py | 12 +- wger/manager/views/workout.py | 25 +- wger/manager/views/workout_session.py | 3 +- wger/measurements/api/views.py | 4 +- wger/measurements/apps.py | 2 +- .../dummy-generator-measurement-categories.py | 60 +- .../commands/dummy-generator-measurements.py | 16 +- wger/measurements/migrations/0001_initial.py | 23 +- .../migrations/0002_auto_20210722_1042.py | 1 - wger/measurements/models/category.py | 3 +- wger/measurements/models/measurement.py | 5 +- wger/measurements/tests/test_generator.py | 1 - wger/nutrition/api/endpoints.py | 4 +- wger/nutrition/api/filtersets.py | 2 - wger/nutrition/api/serializers.py | 4 + wger/nutrition/api/views.py | 41 +- wger/nutrition/apps.py | 2 +- wger/nutrition/consts.py | 15 +- wger/nutrition/forms.py | 99 ++-- wger/nutrition/helpers.py | 23 +- .../commands/download-ingredient-images.py | 3 +- .../commands/dummy-generator-nutrition.py | 18 +- .../commands/import-off-products.py | 17 +- .../management/commands/sync-ingredients.py | 3 +- wger/nutrition/migrations/0001_initial.py | 161 +++--- .../migrations/0002_auto_20170101_1538.py | 7 +- .../migrations/0003_auto_20170118_2308.py | 1 - .../migrations/0004_auto_20200819_2310.py | 6 +- wger/nutrition/migrations/0005_logitem.py | 21 +- .../migrations/0006_auto_20201201_0653.py | 1 - .../migrations/0007_auto_20201214_0013.py | 7 +- .../migrations/0008_auto_20210102_1446.py | 3 +- wger/nutrition/migrations/0009_meal_name.py | 6 +- .../nutrition/migrations/0010_logitem_meal.py | 3 +- .../migrations/0011_alter_logitem_datetime.py | 1 - .../0012_alter_ingredient_license_author.py | 6 +- .../migrations/0013_ingredient_image.py | 22 +- ...alter_ingredient_creation_date_and_more.py | 1 - ...tritionplan_language_alter_logitem_meal.py | 2 +- ...019_alter_image_license_author_and_more.py | 18 +- wger/nutrition/models/image.py | 2 +- wger/nutrition/models/ingredient.py | 16 +- wger/nutrition/models/ingredient_category.py | 5 +- .../models/ingredient_weight_unit.py | 2 +- wger/nutrition/models/log.py | 8 +- wger/nutrition/models/meal.py | 4 +- wger/nutrition/models/meal_item.py | 2 +- wger/nutrition/models/plan.py | 70 +-- wger/nutrition/models/weight_unit.py | 2 +- wger/nutrition/off.py | 2 +- wger/nutrition/sitemap.py | 2 +- wger/nutrition/sync.py | 8 +- wger/nutrition/tests/test_bmi.py | 45 +- .../tests/test_calories_calculator.py | 53 +- wger/nutrition/tests/test_generator.py | 1 - wger/nutrition/tests/test_ingredient.py | 42 +- .../tests/test_ingredient_overview.py | 23 +- wger/nutrition/tests/test_meal.py | 3 +- wger/nutrition/tests/test_meal_item.py | 1 + .../nutrition/tests/test_nutritional_cache.py | 3 +- .../tests/test_nutritional_values.py | 8 +- wger/nutrition/tests/test_off.py | 7 +- wger/nutrition/tests/test_plan.py | 3 +- wger/nutrition/tests/test_sync.py | 2 - wger/nutrition/tests/test_tasks.py | 8 +- wger/nutrition/tests/test_weight_unit.py | 6 +- .../tests/test_weight_unit_ingredient.py | 3 +- wger/nutrition/urls.py | 61 +- wger/nutrition/views/bmi.py | 184 ++---- wger/nutrition/views/calculator.py | 4 +- wger/nutrition/views/ingredient.py | 8 +- wger/nutrition/views/plan.py | 75 +-- wger/software/urls.py | 6 +- wger/software/views.py | 7 +- wger/tasks.py | 88 ++- wger/urls.py | 34 +- wger/utils/constants.py | 2 +- wger/utils/context_processor.py | 8 +- wger/utils/generic_views.py | 11 +- wger/utils/helpers.py | 8 +- wger/utils/language.py | 8 +- wger/utils/managers.py | 2 - wger/utils/middleware.py | 16 +- wger/utils/models.py | 8 +- wger/utils/pdf.py | 42 +- wger/utils/permissions.py | 8 +- wger/utils/tests/test_url.py | 30 +- wger/utils/units.py | 2 +- wger/utils/url.py | 4 +- wger/utils/widgets.py | 30 +- wger/weight/api/serializers.py | 1 + wger/weight/api/views.py | 3 +- wger/weight/forms.py | 5 +- wger/weight/helpers.py | 17 +- .../commands/dummy-generator-body-weight.py | 12 +- .../commands/email-weight-reminder.py | 9 +- wger/weight/migrations/0001_initial.py | 13 +- .../migrations/0002_auto_20150604_2139.py | 7 +- .../migrations/0003_auto_20160416_1030.py | 5 +- wger/weight/models.py | 12 +- wger/weight/tests/test_csv_import.py | 15 +- .../tests/test_email_weight_reminder.py | 13 +- wger/weight/tests/test_entry.py | 5 +- wger/weight/tests/test_generator.py | 1 - wger/weight/views.py | 2 + wger/wsgi.py | 2 +- 360 files changed, 2844 insertions(+), 3559 deletions(-) diff --git a/.github/workflows/formatter.yml b/.github/workflows/formatter.yml index 78d46fb35..5f87c3fdb 100644 --- a/.github/workflows/formatter.yml +++ b/.github/workflows/formatter.yml @@ -16,6 +16,9 @@ jobs: - name: Checkout code uses: actions/checkout@v4 + - name: Get dependencies + run: pip install ruff isort + - name: Format the code run: ruff format diff --git a/extras/scripts/filter-fixtures.py b/extras/scripts/filter-fixtures.py index 63930fd37..84c254c82 100644 --- a/extras/scripts/filter-fixtures.py +++ b/extras/scripts/filter-fixtures.py @@ -62,11 +62,23 @@ filter_dump(('nutrition.logitem',), 'nutrition_diary.json') filter_dump(('exercises.muscle',), 'muscles.json') filter_dump(('exercises.exercisecategory',), 'categories.json') filter_dump(('exercises.exerciseimage',), 'exercise-images.json') -filter_dump(('exercises.exercisebase', 'exercises.variation',), 'exercise-base-data.json') filter_dump( - ('exercises.exercise', 'exercises.exercisecomment', 'exercises.alias'), - 'translations.json') -filter_dump(('exercises.equipment', 'exercises.equipment',), 'equipment.json') + ( + 'exercises.exercisebase', + 'exercises.variation', + ), + 'exercise-base-data.json', +) +filter_dump( + ('exercises.exercise', 'exercises.exercisecomment', 'exercises.alias'), 'translations.json' +) +filter_dump( + ( + 'exercises.equipment', + 'exercises.equipment', + ), + 'equipment.json', +) # # Gym diff --git a/manage.py b/manage.py index e716ec749..873291be6 100644 --- a/manage.py +++ b/manage.py @@ -12,6 +12,7 @@ from wger.tasks import ( setup_django_environment, ) + if __name__ == '__main__': # If user passed the settings flag ignore the default wger settings if not any('--settings' in s for s in sys.argv): diff --git a/wger/celery_configuration.py b/wger/celery_configuration.py index 1564e05eb..31abeb634 100644 --- a/wger/celery_configuration.py +++ b/wger/celery_configuration.py @@ -21,8 +21,8 @@ import os from celery import Celery -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings") -app = Celery("wger") +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings') +app = Celery('wger') # read config from Django settings, the CELERY namespace would make celery # config keys has `CELERY` prefix diff --git a/wger/config/apps.py b/wger/config/apps.py index 45467eee7..1171e0619 100644 --- a/wger/config/apps.py +++ b/wger/config/apps.py @@ -20,7 +20,7 @@ from django.apps import AppConfig class ConfigConfig(AppConfig): name = 'wger.config' - verbose_name = "Config" + verbose_name = 'Config' def ready(self): import wger.config.signals diff --git a/wger/config/migrations/0001_initial.py b/wger/config/migrations/0001_initial.py index 1a1055351..5ea6e2831 100644 --- a/wger/config/migrations/0001_initial.py +++ b/wger/config/migrations/0001_initial.py @@ -4,7 +4,6 @@ from django.db import models, migrations class Migration(migrations.Migration): - dependencies = [ ('gym', '0001_initial'), ('core', '0001_initial'), @@ -18,23 +17,22 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ( 'default_gym', models.ForeignKey( blank=True, to='gym.Gym', - help_text= - 'Select the default gym for this installation. This will assign all new registered users to this gym and update all existing users without a gym.', + help_text='Select the default gym for this installation. This will assign all new registered users to this gym and update all existing users without a gym.', null=True, verbose_name='Default gym', - on_delete=models.CASCADE - ) + on_delete=models.CASCADE, + ), ), ], options={}, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.CreateModel( name='LanguageConfig', @@ -43,15 +41,15 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ( 'item', models.CharField( max_length=2, editable=False, - choices=[(b'1', 'Exercises'), (b'2', 'Ingredients')] - ) + choices=[(b'1', 'Exercises'), (b'2', 'Ingredients')], + ), ), ('show', models.BooleanField(default=1)), ( @@ -60,8 +58,8 @@ class Migration(migrations.Migration): related_name='language_source', editable=False, to='core.Language', - on_delete=models.CASCADE - ) + on_delete=models.CASCADE, + ), ), ( 'language_target', @@ -69,13 +67,13 @@ class Migration(migrations.Migration): related_name='language_target', editable=False, to='core.Language', - on_delete=models.CASCADE - ) + on_delete=models.CASCADE, + ), ), ], options={ 'ordering': ['item', 'language_target'], }, - bases=(models.Model, ), + bases=(models.Model,), ), ] diff --git a/wger/config/migrations/0002_auto_20190618_1617.py b/wger/config/migrations/0002_auto_20190618_1617.py index 4af38a6a1..f5db88f52 100644 --- a/wger/config/migrations/0002_auto_20190618_1617.py +++ b/wger/config/migrations/0002_auto_20190618_1617.py @@ -5,7 +5,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('config', '0001_initial'), ] @@ -18,7 +17,9 @@ class Migration(migrations.Migration): choices=[ ('1', 'Exercises'), ('2', 'Ingredients'), - ], editable=False, max_length=2 + ], + editable=False, + max_length=2, ), ), ] diff --git a/wger/config/migrations/0003_delete_languageconfig.py b/wger/config/migrations/0003_delete_languageconfig.py index 3ccd0904e..3d3c8f008 100644 --- a/wger/config/migrations/0003_delete_languageconfig.py +++ b/wger/config/migrations/0003_delete_languageconfig.py @@ -4,11 +4,12 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ ('config', '0002_auto_20190618_1617'), ] operations = [ - migrations.DeleteModel(name='LanguageConfig', ), + migrations.DeleteModel( + name='LanguageConfig', + ), ] diff --git a/wger/config/models/gym_config.py b/wger/config/models/gym_config.py index c84ce85dc..6992add28 100644 --- a/wger/config/models/gym_config.py +++ b/wger/config/models/gym_config.py @@ -52,7 +52,7 @@ class GymConfig(models.Model): ), null=True, blank=True, - on_delete=models.CASCADE + on_delete=models.CASCADE, ) """ Default gym for the wger installation @@ -62,14 +62,13 @@ class GymConfig(models.Model): """ Return a more human-readable representation """ - return "Default gym {0}".format(self.default_gym) + return 'Default gym {0}'.format(self.default_gym) def save(self, *args, **kwargs): """ Perform additional tasks """ if self.default_gym: - # All users that have no gym set in the profile are edited UserProfile.objects.filter(gym=None).update(gym=self.default_gym) diff --git a/wger/config/tests/test_custom_header.py b/wger/config/tests/test_custom_header.py index 111d6daf1..a369a842b 100644 --- a/wger/config/tests/test_custom_header.py +++ b/wger/config/tests/test_custom_header.py @@ -29,7 +29,6 @@ class GymNameHeaderTestCase(WgerTestCase): """ def check_header(self, gym=None): - response = self.client.get(reverse('core:dashboard')) self.assertEqual(response.context['custom_header'], gym) diff --git a/wger/config/urls.py b/wger/config/urls.py index e2b9a8f0b..47ae23276 100644 --- a/wger/config/urls.py +++ b/wger/config/urls.py @@ -34,6 +34,6 @@ patterns_gym_config = [ urlpatterns = [ path( 'gym-config/', - include((patterns_gym_config, 'gym_config'), namespace="gym_config"), + include((patterns_gym_config, 'gym_config'), namespace='gym_config'), ), ] diff --git a/wger/config/views/gym_config.py b/wger/config/views/gym_config.py index 6796cf42e..b78679bbb 100644 --- a/wger/config/views/gym_config.py +++ b/wger/config/views/gym_config.py @@ -34,6 +34,7 @@ class GymConfigUpdateView(WgerFormMixin, UpdateView): """ Generic view to edit the gym config table """ + model = GymConfig fields = ['default_gym'] permission_required = 'config.change_gymconfig' diff --git a/wger/core/api/endpoints.py b/wger/core/api/endpoints.py index 947b78508..3af78bdba 100644 --- a/wger/core/api/endpoints.py +++ b/wger/core/api/endpoints.py @@ -1,2 +1,2 @@ -LANGUAGE_ENDPOINT = "language" -LICENSE_ENDPOINT = "license" +LANGUAGE_ENDPOINT = 'language' +LICENSE_ENDPOINT = 'license' diff --git a/wger/core/api/serializers.py b/wger/core/api/serializers.py index 545d79d3c..a527d2c20 100644 --- a/wger/core/api/serializers.py +++ b/wger/core/api/serializers.py @@ -46,9 +46,9 @@ class UserprofileSerializer(serializers.ModelSerializer): Workout session serializer """ - email = serializers.EmailField(source="user.email", read_only=True) - username = serializers.EmailField(source="user.username", read_only=True) - date_joined = serializers.EmailField(source="user.date_joined", read_only=True) + email = serializers.EmailField(source='user.email', read_only=True) + username = serializers.EmailField(source='user.username', read_only=True) + date_joined = serializers.EmailField(source='user.date_joined', read_only=True) class Meta: model = UserProfile @@ -86,7 +86,8 @@ class UserprofileSerializer(serializers.ModelSerializer): class UserLoginSerializer(serializers.ModelSerializer): - """ Serializer to map to User model in relation to api user""" + """Serializer to map to User model in relation to api user""" + email = serializers.CharField(required=False) username = serializers.CharField(required=False) password = serializers.CharField(required=True, min_length=8) @@ -102,9 +103,9 @@ class UserLoginSerializer(serializers.ModelSerializer): super().__init__(instance, data, **kwargs) def validate(self, data): - email = data.get("email", None) - username = data.get("username", None) - password = data.get("password", None) + email = data.get('email', None) + username = data.get('username', None) + password = data.get('password', None) if email is None and username is None: raise serializers.ValidationError('Please provide an "email" or a "username"') @@ -122,9 +123,10 @@ class UserLoginSerializer(serializers.ModelSerializer): class UserRegistrationSerializer(serializers.ModelSerializer): email = serializers.EmailField( - required=False, validators=[ + required=False, + validators=[ UniqueValidator(queryset=User.objects.all()), - ] + ], ) username = serializers.CharField( required=True, diff --git a/wger/core/api/views.py b/wger/core/api/views.py index 15e4b24e4..6a73e8ed1 100644 --- a/wger/core/api/views.py +++ b/wger/core/api/views.py @@ -88,6 +88,7 @@ class UserProfileViewSet(viewsets.ModelViewSet): returns the data for the currently logged-in user's profile. To update the profile, use a POST request with the new data, not a PATCH. """ + serializer_class = UserprofileSerializer permission_classes = ( IsAuthenticated, @@ -99,7 +100,7 @@ class UserProfileViewSet(viewsets.ModelViewSet): Only allow access to appropriate objects """ # REST API generation - if getattr(self, "swagger_fake_view", False): + if getattr(self, 'swagger_fake_view', False): return UserProfile.objects.none() return UserProfile.objects.filter(user=self.request.user) @@ -159,10 +160,7 @@ class UserProfileViewSet(viewsets.ModelViewSet): send_email(request.user) return Response( - { - 'status': 'sent', - 'message': f'A verification email was sent to {request.user.email}' - } + {'status': 'sent', 'message': f'A verification email was sent to {request.user.email}'} ) @@ -170,7 +168,8 @@ class ApplicationVersionView(viewsets.ViewSet): """ Returns the application's version """ - permission_classes = (AllowAny, ) + + permission_classes = (AllowAny,) @staticmethod @extend_schema( @@ -187,7 +186,8 @@ class PermissionView(viewsets.ViewSet): """ Checks whether the user has a django permission """ - permission_classes = (AllowAny, ) + + permission_classes = (AllowAny,) @staticmethod @extend_schema( @@ -200,12 +200,13 @@ class PermissionView(viewsets.ViewSet): ), ], responses={ - 201: - inline_serializer(name='PermissionResponse', fields={ - 'result': BooleanField(), - }), - 400: - OpenApiResponse( + 201: inline_serializer( + name='PermissionResponse', + fields={ + 'result': BooleanField(), + }, + ), + 400: OpenApiResponse( description="Please pass a permission name in the 'permission' parameter" ), }, @@ -230,7 +231,8 @@ class RequiredApplicationVersionView(viewsets.ViewSet): Returns the minimum required version of flutter app to access this server such as 1.4.2 or 3.0.0 """ - permission_classes = (AllowAny, ) + + permission_classes = (AllowAny,) @staticmethod @extend_schema( @@ -250,7 +252,8 @@ class UserAPILoginView(viewsets.ViewSet): Note that it is recommended to use token authorization instead. """ - permission_classes = (AllowAny, ) + + permission_classes = (AllowAny,) queryset = User.objects.all() serializer_class = UserLoginSerializer throttle_scope = 'login' @@ -261,12 +264,11 @@ class UserAPILoginView(viewsets.ViewSet): @extend_schema( parameters=[], responses={ - status.HTTP_200_OK: - inline_serializer( + status.HTTP_200_OK: inline_serializer( name='loginSerializer', fields={'token': CharField()}, ), - } + }, ) def post(self, request): serializer = self.serializer_class(data=request.data, request=request) @@ -292,8 +294,8 @@ class UserAPILoginView(viewsets.ViewSet): data={'token': token.key}, status=status.HTTP_200_OK, headers={ - "Deprecation": "Sat, 01 Oct 2022 23:59:59 GMT", - } + 'Deprecation': 'Sat, 01 Oct 2022 23:59:59 GMT', + }, ) @@ -301,7 +303,8 @@ class UserAPIRegistrationViewSet(viewsets.ViewSet): """ API endpoint """ - permission_classes = (AllowRegisterUser, ) + + permission_classes = (AllowRegisterUser,) serializer_class = UserRegistrationSerializer def get_queryset(self): @@ -313,12 +316,11 @@ class UserAPIRegistrationViewSet(viewsets.ViewSet): @extend_schema( parameters=[], responses={ - status.HTTP_200_OK: - inline_serializer( + status.HTTP_200_OK: inline_serializer( name='loginSerializer', fields={'token': CharField()}, ), - } + }, ) def post(self, request): data = request.data @@ -333,11 +335,8 @@ class UserAPIRegistrationViewSet(viewsets.ViewSet): send_email(user) return Response( - { - 'message': 'api user successfully registered', - 'token': token.key - }, - status=status.HTTP_201_CREATED + {'message': 'api user successfully registered', 'token': token.key}, + status=status.HTTP_201_CREATED, ) @@ -345,6 +344,7 @@ class LanguageViewSet(viewsets.ReadOnlyModelViewSet): """ API endpoint for the languages used in the application """ + queryset = Language.objects.all() serializer_class = LanguageSerializer ordering_fields = '__all__' @@ -361,16 +361,18 @@ class DaysOfWeekViewSet(viewsets.ReadOnlyModelViewSet): This has historical reasons, and it's better and easier to just define a simple enum """ + queryset = DaysOfWeek.objects.all() serializer_class = DaysOfWeekSerializer ordering_fields = '__all__' - filterset_fields = ('day_of_week', ) + filterset_fields = ('day_of_week',) class LicenseViewSet(viewsets.ReadOnlyModelViewSet): """ API endpoint for license objects """ + queryset = License.objects.all() serializer_class = LicenseSerializer ordering_fields = '__all__' @@ -385,17 +387,19 @@ class RepetitionUnitViewSet(viewsets.ReadOnlyModelViewSet): """ API endpoint for repetition units objects """ + queryset = RepetitionUnit.objects.all() serializer_class = RepetitionUnitSerializer ordering_fields = '__all__' - filterset_fields = ('name', ) + filterset_fields = ('name',) class RoutineWeightUnitViewSet(viewsets.ReadOnlyModelViewSet): """ API endpoint for weight units objects """ + queryset = WeightUnit.objects.all() serializer_class = RoutineWeightUnitSerializer ordering_fields = '__all__' - filterset_fields = ('name', ) + filterset_fields = ('name',) diff --git a/wger/core/apps.py b/wger/core/apps.py index 233a390b7..e4fedcc37 100644 --- a/wger/core/apps.py +++ b/wger/core/apps.py @@ -18,7 +18,7 @@ from django.apps import AppConfig class CoreConfig(AppConfig): name = 'wger.core' - verbose_name = "Core" + verbose_name = 'Core' def ready(self): import wger.core.signals diff --git a/wger/core/demo.py b/wger/core/demo.py index 22b2051bc..983043e64 100644 --- a/wger/core/demo.py +++ b/wger/core/demo.py @@ -122,7 +122,7 @@ def create_demo_entries(user): workout=workout, reps=reps, weight=18 - reps + random.randint(1, 4), - date=datetime.date.today() - datetime.timedelta(weeks=i) + date=datetime.date.today() - datetime.timedelta(weeks=i), ) weight_log.append(log) @@ -142,7 +142,7 @@ def create_demo_entries(user): workout=workout, reps=reps, weight=30 - reps + random.randint(1, 4), - date=datetime.date.today() - datetime.timedelta(weeks=i) + date=datetime.date.today() - datetime.timedelta(weeks=i), ) weight_log.append(log) @@ -162,7 +162,7 @@ def create_demo_entries(user): workout=workout, reps=reps, weight=110 - reps + random.randint(1, 10), - date=datetime.date.today() - datetime.timedelta(weeks=i) + date=datetime.date.today() - datetime.timedelta(weeks=i), ) weight_log.append(log) diff --git a/wger/core/forms.py b/wger/core/forms.py index 6549bba4b..8deebfbb5 100644 --- a/wger/core/forms.py +++ b/wger/core/forms.py @@ -72,7 +72,7 @@ class UserLoginForm(AuthenticationForm): Row( Column('username', css_class='col-6'), Column('password', css_class='col-6'), - css_class='form-row' + css_class='form-row', ) ) @@ -89,8 +89,8 @@ class UserLoginForm(AuthenticationForm): return self.cleaned_data def authenticate(self, request): - username = self.cleaned_data.get("username") - password = self.cleaned_data.get("password") + username = self.cleaned_data.get('username') + password = self.cleaned_data.get('password') if username and password: self.user_cache = authenticate( @@ -108,20 +108,20 @@ class UserPreferencesForm(forms.ModelForm): first_name = forms.CharField(label=_('First name'), required=False) last_name = forms.CharField(label=_('Last name'), required=False) email = EmailField( - label=_("Email"), - help_text=_("Used for password resets and, optionally, e-mail reminders."), - required=False + label=_('Email'), + help_text=_('Used for password resets and, optionally, e-mail reminders.'), + required=False, ) birthdate = forms.DateField( - label=_("Date of Birth"), + label=_('Date of Birth'), required=False, widget=forms.DateInput( attrs={ 'type': 'date', - "max": str(date.today().replace(year=date.today().year - 10)), - "min": str(date.today().replace(year=date.today().year - 100)) + 'max': str(date.today().replace(year=date.today().year - 10)), + 'min': str(date.today().replace(year=date.today().year - 100)), }, - ) + ), ) class Meta: @@ -145,42 +145,46 @@ class UserPreferencesForm(forms.ModelForm): self.helper.form_class = 'wger-form' self.helper.layout = Layout( Fieldset( - _("Personal data"), 'email', + _('Personal data'), + 'email', Row( Column('first_name', css_class='col-6'), Column('last_name', css_class='col-6'), - css_class='form-row' - ), 'birthdate', HTML("
") + css_class='form-row', + ), + 'birthdate', + HTML('
'), ), Fieldset( - _("Workout reminders"), + _('Workout reminders'), 'workout_reminder_active', 'workout_reminder', 'workout_duration', - HTML("
"), + HTML('
'), ), Fieldset( - _("Other settings"), - "ro_access", - "notification_language", - "weight_unit", - "show_comments", - "show_english_ingredients", - "num_days_weight_reminder", - ), ButtonHolder(Submit('submit', _("Save"), css_class='btn-success btn-block')) + _('Other settings'), + 'ro_access', + 'notification_language', + 'weight_unit', + 'show_comments', + 'show_english_ingredients', + 'num_days_weight_reminder', + ), + ButtonHolder(Submit('submit', _('Save'), css_class='btn-success btn-block')), ) class UserEmailForm(forms.ModelForm): email = EmailField( - label=_("Email"), - help_text=_("Used for password resets and, optionally, email reminders."), - required=False + label=_('Email'), + help_text=_('Used for password resets and, optionally, email reminders.'), + required=False, ) class Meta: model = User - fields = ('email', ) + fields = ('email',) def clean_email(self): """ @@ -192,7 +196,7 @@ class UserEmailForm(forms.ModelForm): we want to check that nobody else has that e-mail address. """ - email = self.cleaned_data["email"] + email = self.cleaned_data['email'] if not email: return email try: @@ -203,7 +207,7 @@ class UserEmailForm(forms.ModelForm): except User.DoesNotExist: return email - raise ValidationError(_("This e-mail address is already in use.")) + raise ValidationError(_('This e-mail address is already in use.')) class UserPersonalInformationForm(UserEmailForm): @@ -222,10 +226,11 @@ class PasswordConfirmationForm(Form): This can be used to make sure the user really wants to perform a dangerous action. The form must be initialised with a user object. """ + password = CharField( - label=_("Password"), + label=_('Password'), widget=PasswordInput, - help_text=_('Please enter your current password.') + help_text=_('Please enter your current password.'), ) def __init__(self, user, data=None): @@ -234,7 +239,7 @@ class PasswordConfirmationForm(Form): self.helper = FormHelper() self.helper.layout = Layout( 'password', - ButtonHolder(Submit('submit', _("Delete"), css_class='btn-danger btn-block')) + ButtonHolder(Submit('submit', _('Delete'), css_class='btn-danger btn-block')), ) def clean_password(self): @@ -244,7 +249,7 @@ class PasswordConfirmationForm(Form): password = self.cleaned_data.get('password', None) if not self.user.check_password(password): raise ValidationError(_('Invalid password')) - return self.cleaned_data.get("password") + return self.cleaned_data.get('password') class RegistrationForm(UserCreationForm, UserEmailForm): @@ -263,13 +268,15 @@ class RegistrationForm(UserCreationForm, UserEmailForm): self.helper = FormHelper() self.helper.form_class = 'wger-form' self.helper.layout = Layout( - 'username', 'email', + 'username', + 'email', Row( Column('password1', css_class='col-md-6 col-12'), Column('password2', css_class='col-md-6 col-12'), - css_class='form-row' - ), 'captcha', - ButtonHolder(Submit('submitBtn', _("Register"), css_class='btn-success btn-block')) + css_class='form-row', + ), + 'captcha', + ButtonHolder(Submit('submitBtn', _('Register'), css_class='btn-success btn-block')), ) @@ -283,16 +290,17 @@ class RegistrationFormNoCaptcha(UserCreationForm, UserEmailForm): self.helper = FormHelper() self.helper.form_class = 'wger-form' self.helper.layout = Layout( - 'username', 'email', + 'username', + 'email', Row( Column('password1', css_class='col-md-6 col-12'), Column('password2', css_class='col-md-6 col-12'), - css_class='form-row' + css_class='form-row', ), ButtonHolder( - Submit('submit', _("Register"), css_class='btn-success col-sm-6 col-12'), - css_class='text-center' - ) + Submit('submit', _('Register'), css_class='btn-success col-sm-6 col-12'), + css_class='text-center', + ), ) @@ -300,12 +308,13 @@ class FeedbackRegisteredForm(forms.Form): """ Feedback form used for logged-in users """ + contact = forms.CharField( max_length=50, min_length=10, label=_('Contact'), help_text=_('Some way of answering you (e-mail, etc.)'), - required=False + required=False, ) comment = forms.CharField( @@ -314,7 +323,7 @@ class FeedbackRegisteredForm(forms.Form): widget=widgets.Textarea, label=_('Comment'), help_text=_('What do you want to say?'), - required=True + required=True, ) @@ -322,6 +331,7 @@ class FeedbackAnonymousForm(FeedbackRegisteredForm): """ Feedback form used for anonymous users (has additionally a reCAPTCHA field) """ + captcha = ReCaptchaField( widget=ReCaptchaV3, label='reCaptcha', diff --git a/wger/core/management/commands/add-user-rest.py b/wger/core/management/commands/add-user-rest.py index 771116ed7..73172103b 100644 --- a/wger/core/management/commands/add-user-rest.py +++ b/wger/core/management/commands/add-user-rest.py @@ -9,7 +9,6 @@ Custom command permitting users to create user accounts class Command(BaseCommand): - help = 'Permit user to create user accounts' # Named (optional arguments) @@ -32,15 +31,15 @@ class Command(BaseCommand): if options['disable']: user.userprofile.can_add_user = False self.stdout.write( - self.style. - SUCCESS(f"{options['name']} is now DISABLED from adding users via the API") + self.style.SUCCESS( + f"{options['name']} is now DISABLED from adding users via the API" + ) ) else: user.userprofile.can_add_user = True self.stdout.write( - self.style. - SUCCESS(f"{options['name']} is now ALLOWED to add users via the API") + self.style.SUCCESS(f"{options['name']} is now ALLOWED to add users via the API") ) user.userprofile.save() diff --git a/wger/core/management/commands/clear-cache.py b/wger/core/management/commands/clear-cache.py index e49bb4d46..07fa5f8f2 100644 --- a/wger/core/management/commands/clear-cache.py +++ b/wger/core/management/commands/clear-cache.py @@ -36,17 +36,18 @@ class Command(BaseCommand): Clears caches (HTML, etc.) """ - help = 'Clears the application cache. You *must* pass an option selecting ' \ - 'what exactly you want to clear. See available options.' + help = ( + 'Clears the application cache. You *must* pass an option selecting ' + 'what exactly you want to clear. See available options.' + ) def add_arguments(self, parser): - parser.add_argument( '--clear-template', action='store_true', dest='clear_template', default=False, - help='Clear only template caches' + help='Clear only template caches', ) parser.add_argument( @@ -54,7 +55,7 @@ class Command(BaseCommand): action='store_true', dest='clear_workout', default=False, - help='Clear only the workout canonical view' + help='Clear only the workout canonical view', ) parser.add_argument( @@ -62,7 +63,7 @@ class Command(BaseCommand): action='store_true', dest='clear_all', default=False, - help='Clear ALL cached entries' + help='Clear ALL cached entries', ) def handle(self, **options): @@ -71,7 +72,8 @@ class Command(BaseCommand): """ if ( - not options['clear_template'] and not options['clear_workout'] + not options['clear_template'] + and not options['clear_workout'] and not options['clear_all'] ): raise CommandError('Please select what cache you need to delete, see help') @@ -79,20 +81,20 @@ class Command(BaseCommand): # Exercises, cached template fragments if options['clear_template']: if int(options['verbosity']) >= 2: - self.stdout.write("*** Clearing templates") + self.stdout.write('*** Clearing templates') for user in User.objects.all(): if int(options['verbosity']) >= 2: - self.stdout.write(f"* Processing user {user.username}") + self.stdout.write(f'* Processing user {user.username}') for entry in WorkoutLog.objects.filter(user=user).dates('date', 'year'): - if int(options['verbosity']) >= 3: - self.stdout.write(f" Year {entry.year}") - for month in WorkoutLog.objects.filter(user=user, date__year=entry.year - ).dates('date', 'month'): + self.stdout.write(f' Year {entry.year}') + for month in WorkoutLog.objects.filter(user=user, date__year=entry.year).dates( + 'date', 'month' + ): if int(options['verbosity']) >= 3: - self.stdout.write(f" Month {entry.month}") + self.stdout.write(f' Month {entry.month}') reset_workout_log(user.id, entry.year, entry.month) for day in WorkoutLog.objects.filter( user=user, @@ -100,7 +102,7 @@ class Command(BaseCommand): date__month=month.month, ).dates('date', 'day'): if int(options['verbosity']) >= 3: - self.stdout.write(f" Day {day.day}") + self.stdout.write(f' Day {day.day}') reset_workout_log(user.id, entry.year, entry.month, day) # Workout canonical form diff --git a/wger/core/management/commands/delete-temp-users.py b/wger/core/management/commands/delete-temp-users.py index 00fe93d83..b44377b53 100644 --- a/wger/core/management/commands/delete-temp-users.py +++ b/wger/core/management/commands/delete-temp-users.py @@ -31,14 +31,13 @@ class Command(BaseCommand): help = 'Deletes all temporary users older than 1 week' def handle(self, **options): - profile_list = UserProfile.objects.filter(is_temporary=True) counter = 0 for profile in profile_list: delta = now() - profile.user.date_joined - if (delta >= datetime.timedelta(7)): + if delta >= datetime.timedelta(7): counter += 1 profile.user.delete() - self.stdout.write(f"Deleted {counter} temporary users") + self.stdout.write(f'Deleted {counter} temporary users') diff --git a/wger/core/management/commands/dummy-generator-users.py b/wger/core/management/commands/dummy-generator-users.py index c1f88fddd..b82489d9a 100644 --- a/wger/core/management/commands/dummy-generator-users.py +++ b/wger/core/management/commands/dummy-generator-users.py @@ -44,14 +44,13 @@ class Command(BaseCommand): help = 'Dummy generator for users' def add_arguments(self, parser): - parser.add_argument( '--nr-entries', action='store', default=20, dest='number_users', type=int, - help='The number of users to generate (default: 20)' + help='The number of users to generate (default: 20)', ) parser.add_argument( @@ -60,11 +59,10 @@ class Command(BaseCommand): default='auto', dest='add_to_gym', type=str, - help='Gym to assign the users to. Allowed values: auto, none, . Default: auto' + help='Gym to assign the users to. Allowed values: auto, none, . Default: auto', ) def handle(self, **options): - faker = Faker() self.stdout.write(f"** Generating {options['number_users']} users") diff --git a/wger/core/management/commands/extract-i18n-flutter-exercises.py b/wger/core/management/commands/extract-i18n-flutter-exercises.py index 7be5e593a..d22cd0828 100644 --- a/wger/core/management/commands/extract-i18n-flutter-exercises.py +++ b/wger/core/management/commands/extract-i18n-flutter-exercises.py @@ -21,8 +21,8 @@ from wger.exercises.models import Exercise class Command(BaseCommand): help = ( - "Helper command to extract translations for the exercises used in the flutter repo for " - "the screenshots for the play store" + 'Helper command to extract translations for the exercises used in the flutter repo for ' + 'the screenshots for the play store' ) uuids = { @@ -31,7 +31,7 @@ class Command(BaseCommand): 'deadLift': 'ee8e8db4-2d82-49e1-ab7f-891e9a354934', 'crunches': 'b186f1f8-4957-44dc-bf30-d0b00064ce6f', 'curls': '1ae6a28d-10e7-4ecf-af4f-905f8193e2c6', - 'raises': '63375f5b-2d81-471c-bea4-fc3d207e96cb' + 'raises': '63375f5b-2d81-471c-bea4-fc3d207e96cb', } def handle(self, **options): @@ -39,7 +39,7 @@ class Command(BaseCommand): languages = [] for exercise_key in self.uuids.keys(): - self.stdout.write(f"Extracting translations for {exercise_key}") + self.stdout.write(f'Extracting translations for {exercise_key}') uuid = self.uuids[exercise_key] translations = Exercise.objects.filter(exercise_base__uuid=uuid) @@ -47,14 +47,14 @@ class Command(BaseCommand): variables = [] for translation in translations: - variable_name = f"{exercise_key}{translation.language.short_name.upper()}" + variable_name = f'{exercise_key}{translation.language.short_name.upper()}' variables.append(variable_name) if translation.language not in languages: languages.append(translation.language) self.stdout.write( - f"- translation {translation.language.short_name}: {translation.name}" + f'- translation {translation.language.short_name}: {translation.name}' ) out.append( @@ -70,22 +70,23 @@ class Command(BaseCommand): ); """ ) - self.stdout.write("") + self.stdout.write('') out.append(f'final {exercise_key}Translations = [{",".join(variables)}];') for language in languages: out.insert( - 0, f"""const tLanguage{language.id} = Language( + 0, + f"""const tLanguage{language.id} = Language( id: {language.id}, shortName: '{language.short_name}', fullName: '{language.full_name}', - );""" + );""", ) out.insert(0, "import 'package:wger/models/exercises/language.dart';") out.insert(0, "import 'package:wger/models/exercises/translation.dart';") - out.insert(0, "// Autogenerated by extract-i18n-flutter-exercises.py do not edit!") + out.insert(0, '// Autogenerated by extract-i18n-flutter-exercises.py do not edit!') # # Write to output diff --git a/wger/core/management/commands/extract-i18n.py b/wger/core/management/commands/extract-i18n.py index 043c08437..70f538ef3 100644 --- a/wger/core/management/commands/extract-i18n.py +++ b/wger/core/management/commands/extract-i18n.py @@ -38,22 +38,25 @@ class Command(BaseCommand): help = 'Write the translatable strings from the database to a file' def handle(self, **options): - # Replace whitespace and other problematic characters with underscores def cleanup_name(text: str) -> str: - return text.lower(). \ - replace(' ', '_'). \ - replace('-', '_'). \ - replace('/', '_'). \ - replace('(', '_'). \ - replace(')', '_') + return ( + text.lower() + .replace(' ', '_') + .replace('-', '_') + .replace('/', '_') + .replace('(', '_') + .replace(')', '_') + ) # Collect all translatable items - data = [i for i in ExerciseCategory.objects.all()] \ - + [i for i in Equipment.objects.all()] \ - + [i.name_en for i in Muscle.objects.all() if i.name_en] \ - + [i for i in RepetitionUnit.objects.all()] \ - + [i for i in WeightUnit.objects.all()] + data = ( + [i for i in ExerciseCategory.objects.all()] + + [i for i in Equipment.objects.all()] + + [i.name_en for i in Muscle.objects.all() if i.name_en] + + [i for i in RepetitionUnit.objects.all()] + + [i for i in WeightUnit.objects.all()] + ) # Make entries unique and sort alphabetically data = sorted(set([i.__str__() for i in data])) @@ -70,7 +73,7 @@ class Command(BaseCommand): # # React - copy the file to src/i18n.tsx in the React repo with open('wger/i18n.tsx', 'w') as f: - out = ''' + out = """ // This code is autogenerated in the backend repo in extract-i18n.py do not edit! // Translate dynamic strings that are returned from the server @@ -82,13 +85,13 @@ class Command(BaseCommand): // eslint-disable-next-line @typescript-eslint/no-unused-vars const DummyComponent = () => { - const [t] = useTranslation();''' + const [t] = useTranslation();""" for i in data: out += f't("server.{cleanup_name(i.__str__())}");\n' - out += ''' + out += """ return (

); - };''' + };""" f.write(out) self.stdout.write(self.style.SUCCESS(f'Wrote content to wger/i18n.tsx')) @@ -106,7 +109,7 @@ class Command(BaseCommand): # Copy to lib/helpers/i18n.dart in the flutter repo with open('wger/i18n.dart', 'w') as f: - out = ''' + out = """ /// This code is autogenerated in the backend repo in extract-i18n.py do not edit! /// Translate dynamic strings that are returned from the server @@ -121,19 +124,19 @@ class Command(BaseCommand): import 'package:logging/logging.dart'; String getTranslation(String value, BuildContext context) { - switch (value) {''' + switch (value) {""" for i in data: - out += f''' + out += f""" case '{i}': return AppLocalizations.of(context).{cleanup_name(i.__str__())}; - ''' + """ - out += ''' + out += """ default: log('Could not translate the server string $value', level: Level.WARNING.value); return value; } - }''' + }""" f.write(out) self.stdout.write(self.style.SUCCESS('Wrote content to wger/i18n.dart')) diff --git a/wger/core/management/commands/list-users-api.py b/wger/core/management/commands/list-users-api.py index 9490ae9e2..38b883a04 100644 --- a/wger/core/management/commands/list-users-api.py +++ b/wger/core/management/commands/list-users-api.py @@ -11,13 +11,11 @@ List users registered via the API class Command(BaseCommand): - help = 'List all users registered via REST, grouped by app-user' def handle(self, *args, **options): - for app_profile in UserProfile.objects.filter(can_add_user=True): - self.stdout.write(self.style.SUCCESS(f"Users created by {app_profile.user.username}:")) + self.stdout.write(self.style.SUCCESS(f'Users created by {app_profile.user.username}:')) for user_profile in UserProfile.objects.filter(added_by=app_profile.user): - self.stdout.write(f"- {user_profile.user.username}") + self.stdout.write(f'- {user_profile.user.username}') diff --git a/wger/core/management/commands/set-site-url.py b/wger/core/management/commands/set-site-url.py index 3ee98c1d7..0eb6079c6 100644 --- a/wger/core/management/commands/set-site-url.py +++ b/wger/core/management/commands/set-site-url.py @@ -35,4 +35,4 @@ class Command(BaseCommand): site.domain = domain site.name = settings.SITE_URL site.save() - self.stdout.write(self.style.SUCCESS(f"Set site URL to {domain}")) + self.stdout.write(self.style.SUCCESS(f'Set site URL to {domain}')) diff --git a/wger/core/management/commands/update-user-cache.py b/wger/core/management/commands/update-user-cache.py index 6b0b354e9..1a8151db7 100644 --- a/wger/core/management/commands/update-user-cache.py +++ b/wger/core/management/commands/update-user-cache.py @@ -25,9 +25,11 @@ class Command(BaseCommand): Updates the user cache table """ - help = 'Update the user cache-table. This is only needed when the python' \ - 'code used to calculate any of the cached entries is changed and ' \ - 'the ones in the database need to be updated to reflect the new logic.' + help = ( + 'Update the user cache-table. This is only needed when the python' + 'code used to calculate any of the cached entries is changed and ' + 'the ones in the database need to be updated to reflect the new logic.' + ) def handle(self, **options): """ diff --git a/wger/core/migrations/0001_initial.py b/wger/core/migrations/0001_initial.py index e735f0992..202fadb61 100644 --- a/wger/core/migrations/0001_initial.py +++ b/wger/core/migrations/0001_initial.py @@ -6,7 +6,6 @@ import django.core.validators class Migration(migrations.Migration): - dependencies = [ ('gym', '0001_initial'), migrations.swappable_dependency(settings.AUTH_USER_MODEL), @@ -20,14 +19,14 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ('day_of_week', models.CharField(max_length=9, verbose_name='Day of the week')), ], options={ 'ordering': ['pk'], }, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.CreateModel( name='Language', @@ -36,7 +35,7 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ('short_name', models.CharField(max_length=2, verbose_name='Language short name')), ('full_name', models.CharField(max_length=30, verbose_name='Language full name')), @@ -44,7 +43,7 @@ class Migration(migrations.Migration): options={ 'ordering': ['full_name'], }, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.CreateModel( name='License', @@ -53,12 +52,12 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ('full_name', models.CharField(max_length=60, verbose_name='Full name')), ( 'short_name', - models.CharField(max_length=15, verbose_name='Short name, e.g. CC-BY-SA 3') + models.CharField(max_length=15, verbose_name='Short name, e.g. CC-BY-SA 3'), ), ( 'url', @@ -66,14 +65,14 @@ class Migration(migrations.Migration): help_text='Link to license text or other information', null=True, verbose_name='Link', - blank=True - ) + blank=True, + ), ), ], options={ 'ordering': ['full_name'], }, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.CreateModel( name='UserProfile', @@ -82,7 +81,7 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ('is_temporary', models.BooleanField(default=False, editable=False)), ( @@ -90,52 +89,48 @@ class Migration(migrations.Migration): models.BooleanField( default=True, help_text='Check to show exercise comments on the workout view', - verbose_name='Show exercise comments' - ) + verbose_name='Show exercise comments', + ), ), ( 'show_english_ingredients', models.BooleanField( default=True, - help_text= - 'Check to also show ingredients in English while creating\na nutritional plan. These ingredients are extracted from a list provided\nby the US Department of Agriculture. It is extremely complete, with around\n7000 entries, but can be somewhat overwhelming and make the search difficult.', - verbose_name='Also use ingredients in English' - ) + help_text='Check to also show ingredients in English while creating\na nutritional plan. These ingredients are extracted from a list provided\nby the US Department of Agriculture. It is extremely complete, with around\n7000 entries, but can be somewhat overwhelming and make the search difficult.', + verbose_name='Also use ingredients in English', + ), ), ( 'workout_reminder_active', models.BooleanField( default=False, - help_text= - 'Check to activate automatic reminders for workouts. You need to provide a valid email for this to work.', - verbose_name='Activate workout reminders' - ) + help_text='Check to activate automatic reminders for workouts. You need to provide a valid email for this to work.', + verbose_name='Activate workout reminders', + ), ), ( 'workout_reminder', models.IntegerField( default=14, - help_text= - 'The number of days you want to be reminded before a workout expires.', + help_text='The number of days you want to be reminded before a workout expires.', verbose_name='Remind before expiration', validators=[ django.core.validators.MinValueValidator(1), - django.core.validators.MaxValueValidator(30) - ] - ) + django.core.validators.MaxValueValidator(30), + ], + ), ), ( 'workout_duration', models.IntegerField( default=12, - help_text= - 'Default duration in weeks of workouts not in a schedule. Used for email workout reminders.', + help_text='Default duration in weeks of workouts not in a schedule. Used for email workout reminders.', verbose_name='Default duration of workouts', validators=[ django.core.validators.MinValueValidator(1), - django.core.validators.MaxValueValidator(30) - ] - ) + django.core.validators.MaxValueValidator(30), + ], + ), ), ('last_workout_notification', models.DateField(null=True, editable=False)), ( @@ -143,21 +138,20 @@ class Migration(migrations.Migration): models.BooleanField( default=True, help_text='Check to activate timer pauses between exercises.', - verbose_name='Use pauses in workout timer' - ) + verbose_name='Use pauses in workout timer', + ), ), ( 'timer_pause', models.IntegerField( default=90, - help_text= - 'Default duration in seconds of pauses used by the timer in the gym mode.', + help_text='Default duration in seconds of pauses used by the timer in the gym mode.', verbose_name='Default duration of workout pauses', validators=[ django.core.validators.MinValueValidator(10), - django.core.validators.MaxValueValidator(400) - ] - ) + django.core.validators.MaxValueValidator(400), + ], + ), ), ( 'age', @@ -167,9 +161,9 @@ class Migration(migrations.Migration): verbose_name='Age', validators=[ django.core.validators.MinValueValidator(10), - django.core.validators.MaxValueValidator(100) - ] - ) + django.core.validators.MaxValueValidator(100), + ], + ), ), ( 'height', @@ -179,9 +173,9 @@ class Migration(migrations.Migration): verbose_name='Height (cm)', validators=[ django.core.validators.MinValueValidator(140), - django.core.validators.MaxValueValidator(230) - ] - ) + django.core.validators.MaxValueValidator(230), + ], + ), ), ( 'gender', @@ -189,8 +183,8 @@ class Migration(migrations.Migration): default=b'1', max_length=1, null=True, - choices=[(b'1', 'Male'), (b'2', 'Female')] - ) + choices=[(b'1', 'Male'), (b'2', 'Female')], + ), ), ( 'sleep_hours', @@ -201,9 +195,9 @@ class Migration(migrations.Migration): verbose_name='Hours of sleep', validators=[ django.core.validators.MinValueValidator(4), - django.core.validators.MaxValueValidator(10) - ] - ) + django.core.validators.MaxValueValidator(10), + ], + ), ), ( 'work_hours', @@ -214,9 +208,9 @@ class Migration(migrations.Migration): verbose_name='Work', validators=[ django.core.validators.MinValueValidator(1), - django.core.validators.MaxValueValidator(15) - ] - ) + django.core.validators.MaxValueValidator(15), + ], + ), ), ( 'work_intensity', @@ -226,8 +220,8 @@ class Migration(migrations.Migration): max_length=1, help_text='Approximately', null=True, - verbose_name='Physical intensity' - ) + verbose_name='Physical intensity', + ), ), ( 'sport_hours', @@ -238,9 +232,9 @@ class Migration(migrations.Migration): verbose_name='Sport', validators=[ django.core.validators.MinValueValidator(1), - django.core.validators.MaxValueValidator(30) - ] - ) + django.core.validators.MaxValueValidator(30), + ], + ), ), ( 'sport_intensity', @@ -250,8 +244,8 @@ class Migration(migrations.Migration): max_length=1, help_text='Approximately', null=True, - verbose_name='Physical intensity' - ) + verbose_name='Physical intensity', + ), ), ( 'freetime_hours', @@ -262,9 +256,9 @@ class Migration(migrations.Migration): verbose_name='Free time', validators=[ django.core.validators.MinValueValidator(1), - django.core.validators.MaxValueValidator(15) - ] - ) + django.core.validators.MaxValueValidator(15), + ], + ), ), ( 'freetime_intensity', @@ -274,8 +268,8 @@ class Migration(migrations.Migration): max_length=1, help_text='Approximately', null=True, - verbose_name='Physical intensity' - ) + verbose_name='Physical intensity', + ), ), ( 'calories', @@ -286,9 +280,9 @@ class Migration(migrations.Migration): verbose_name='Total daily calories', validators=[ django.core.validators.MinValueValidator(1500), - django.core.validators.MaxValueValidator(5000) - ] - ) + django.core.validators.MaxValueValidator(5000), + ], + ), ), ( 'weight_unit', @@ -296,8 +290,8 @@ class Migration(migrations.Migration): default=b'kg', max_length=2, verbose_name='Weight unit', - choices=[(b'kg', 'Metric (kilogram)'), (b'lb', 'Imperial (pound)')] - ) + choices=[(b'kg', 'Metric (kilogram)'), (b'lb', 'Imperial (pound)')], + ), ), ( 'gym', @@ -306,8 +300,8 @@ class Migration(migrations.Migration): editable=False, to='gym.Gym', null=True, - on_delete=models.CASCADE - ) + on_delete=models.CASCADE, + ), ), ( 'notification_language', @@ -315,19 +309,18 @@ class Migration(migrations.Migration): default=2, verbose_name='Notification language', to='core.Language', - help_text= - 'Language to use when sending you email notifications, e.g. email reminders for workouts. This does not affect the language used on the website.', - on_delete=models.CASCADE - ) + help_text='Language to use when sending you email notifications, e.g. email reminders for workouts. This does not affect the language used on the website.', + on_delete=models.CASCADE, + ), ), ( 'user', models.OneToOneField( editable=False, to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE - ) + ), ), ], options={}, - bases=(models.Model, ), + bases=(models.Model,), ), ] diff --git a/wger/core/migrations/0002_auto_20141225_1512.py b/wger/core/migrations/0002_auto_20141225_1512.py index 685c379cb..062602226 100644 --- a/wger/core/migrations/0002_auto_20141225_1512.py +++ b/wger/core/migrations/0002_auto_20141225_1512.py @@ -4,7 +4,6 @@ from django.db import models, migrations class Migration(migrations.Migration): - dependencies = [ ('core', '0001_initial'), ] @@ -14,10 +13,9 @@ class Migration(migrations.Migration): model_name='userprofile', name='ro_access', field=models.BooleanField( - help_text= - 'Allow anonymous users to access your workouts and logs in a read-only mode. You can then share the links to social media.', + help_text='Allow anonymous users to access your workouts and logs in a read-only mode. You can then share the links to social media.', verbose_name='Allow read-only access', - default=False + default=False, ), preserve_default=True, ), @@ -30,7 +28,7 @@ class Migration(migrations.Migration): max_length=1, help_text='Approximately', default='1', - verbose_name='Physical intensity' + verbose_name='Physical intensity', ), preserve_default=True, ), @@ -51,7 +49,7 @@ class Migration(migrations.Migration): max_length=1, help_text='Approximately', default='2', - verbose_name='Physical intensity' + verbose_name='Physical intensity', ), preserve_default=True, ), @@ -62,7 +60,7 @@ class Migration(migrations.Migration): choices=[('kg', 'Metric (kilogram)'), ('lb', 'Imperial (pound)')], verbose_name='Weight unit', max_length=2, - default='kg' + default='kg', ), preserve_default=True, ), @@ -75,7 +73,7 @@ class Migration(migrations.Migration): max_length=1, help_text='Approximately', default='1', - verbose_name='Physical intensity' + verbose_name='Physical intensity', ), preserve_default=True, ), diff --git a/wger/core/migrations/0003_auto_20150217_1554.py b/wger/core/migrations/0003_auto_20150217_1554.py index 9311d6e42..b8b99b551 100644 --- a/wger/core/migrations/0003_auto_20150217_1554.py +++ b/wger/core/migrations/0003_auto_20150217_1554.py @@ -5,7 +5,6 @@ import django.core.validators class Migration(migrations.Migration): - dependencies = [ ('core', '0002_auto_20141225_1512'), ] @@ -18,7 +17,7 @@ class Migration(migrations.Migration): verbose_name='Automatic reminders for weight entries', max_length=30, null=True, - help_text='Number of days after the last weight entry (enter 0 to deactivate)' + help_text='Number of days after the last weight entry (enter 0 to deactivate)', ), preserve_default=True, ), @@ -30,8 +29,8 @@ class Migration(migrations.Migration): null=True, validators=[ django.core.validators.MinValueValidator(10), - django.core.validators.MaxValueValidator(100) - ] + django.core.validators.MaxValueValidator(100), + ], ), preserve_default=True, ), @@ -43,8 +42,8 @@ class Migration(migrations.Migration): null=True, validators=[ django.core.validators.MinValueValidator(140), - django.core.validators.MaxValueValidator(230) - ] + django.core.validators.MaxValueValidator(230), + ], ), preserve_default=True, ), @@ -54,8 +53,7 @@ class Migration(migrations.Migration): field=models.BooleanField( verbose_name='Allow external access', default=False, - help_text= - 'Allow external users to access your workouts and logs in a read-only mode. You need to set this before you can share links e.g. to social media.' + help_text='Allow external users to access your workouts and logs in a read-only mode. You need to set this before you can share links e.g. to social media.', ), preserve_default=True, ), diff --git a/wger/core/migrations/0004_auto_20150217_1914.py b/wger/core/migrations/0004_auto_20150217_1914.py index cef2d29a1..b1e4aa9bf 100644 --- a/wger/core/migrations/0004_auto_20150217_1914.py +++ b/wger/core/migrations/0004_auto_20150217_1914.py @@ -4,7 +4,6 @@ from django.db import models, migrations class Migration(migrations.Migration): - dependencies = [ ('core', '0003_auto_20150217_1554'), ] @@ -17,7 +16,7 @@ class Migration(migrations.Migration): default=0, verbose_name='Automatic reminders for weight entries', max_length=30, - help_text='Number of days after the last weight entry (enter 0 to deactivate)' + help_text='Number of days after the last weight entry (enter 0 to deactivate)', ), preserve_default=True, ), diff --git a/wger/core/migrations/0005_auto_20151025_2236.py b/wger/core/migrations/0005_auto_20151025_2236.py index 5227c795e..a6f5bd47d 100644 --- a/wger/core/migrations/0005_auto_20151025_2236.py +++ b/wger/core/migrations/0005_auto_20151025_2236.py @@ -6,7 +6,6 @@ from django.conf import settings class Migration(migrations.Migration): - dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), ('core', '0004_auto_20150217_1914'), @@ -20,14 +19,14 @@ class Migration(migrations.Migration): 'id', models.AutoField( auto_created=True, primary_key=True, serialize=False, verbose_name='ID' - ) + ), ), ('last_activity', models.DateField(null=True)), ( 'user', models.OneToOneField( editable=False, to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE - ) + ), ), ], ), @@ -40,8 +39,8 @@ class Migration(migrations.Migration): help_text='Number of days after the last weight entry (enter 0 to deactivate)', validators=[ django.core.validators.MinValueValidator(0), - django.core.validators.MaxValueValidator(30) - ] + django.core.validators.MaxValueValidator(30), + ], ), ), ] diff --git a/wger/core/migrations/0006_auto_20151025_2237.py b/wger/core/migrations/0006_auto_20151025_2237.py index b1388844c..f1989f8d5 100644 --- a/wger/core/migrations/0006_auto_20151025_2237.py +++ b/wger/core/migrations/0006_auto_20151025_2237.py @@ -7,13 +7,12 @@ def create_usercache(apps, schema_editor): """ Creates a usercache table for all users """ - User = apps.get_model("auth", "User") - Usercache = apps.get_model("core", "Usercache") - WorkoutLog = apps.get_model("manager", "WorkoutLog") - WorkoutSession = apps.get_model("manager", "WorkoutSession") + User = apps.get_model('auth', 'User') + Usercache = apps.get_model('core', 'Usercache') + WorkoutLog = apps.get_model('manager', 'WorkoutLog') + WorkoutSession = apps.get_model('manager', 'WorkoutSession') for user in User.objects.all(): - # # This is the logic of get_user_last_activity at the time this migration # was created. @@ -46,13 +45,12 @@ def delete_usercache(apps, schema_editor): """ Deletes the usercache table for all users """ - Usercache = apps.get_model("core", "Usercache") + Usercache = apps.get_model('core', 'Usercache') for cache in Usercache.objects.all(): cache.delete() class Migration(migrations.Migration): - dependencies = [ ('core', '0005_auto_20151025_2236'), ('auth', '0006_require_contenttypes_0002'), diff --git a/wger/core/migrations/0007_repetitionunit.py b/wger/core/migrations/0007_repetitionunit.py index f954f3ead..fad2071b0 100644 --- a/wger/core/migrations/0007_repetitionunit.py +++ b/wger/core/migrations/0007_repetitionunit.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('core', '0006_auto_20151025_2237'), ] @@ -17,7 +16,7 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, primary_key=True, auto_created=True - ) + ), ), ('name', models.CharField(verbose_name='Name', max_length=100)), ], diff --git a/wger/core/migrations/0008_weightunit.py b/wger/core/migrations/0008_weightunit.py index 2d0fec73f..557f04315 100644 --- a/wger/core/migrations/0008_weightunit.py +++ b/wger/core/migrations/0008_weightunit.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('core', '0007_repetitionunit'), ] @@ -17,7 +16,7 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ('name', models.CharField(verbose_name='Name', max_length=100)), ], diff --git a/wger/core/migrations/0009_auto_20160303_2340.py b/wger/core/migrations/0009_auto_20160303_2340.py index f6ccfaf40..081c07d67 100644 --- a/wger/core/migrations/0009_auto_20160303_2340.py +++ b/wger/core/migrations/0009_auto_20160303_2340.py @@ -28,7 +28,6 @@ def insert_data(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ('core', '0008_weightunit'), ] diff --git a/wger/core/migrations/0010_auto_20170403_0144.py b/wger/core/migrations/0010_auto_20170403_0144.py index 729d81e14..ef29247cc 100644 --- a/wger/core/migrations/0010_auto_20170403_0144.py +++ b/wger/core/migrations/0010_auto_20170403_0144.py @@ -6,7 +6,6 @@ import wger.core.models class Migration(migrations.Migration): - dependencies = [ ('core', '0009_auto_20160303_2340'), ] @@ -18,17 +17,16 @@ class Migration(migrations.Migration): field=models.DateField( null=True, validators=[wger.core.models.profile.birthdate_validator], - verbose_name='Date of Birth' + verbose_name='Date of Birth', ), ), migrations.AlterField( model_name='license', name='full_name', field=models.CharField( - help_text= - 'If a license has been localized, e.g. the Creative Commons licenses for the different countries, add them as separate entries here.', + help_text='If a license has been localized, e.g. the Creative Commons licenses for the different countries, add them as separate entries here.', max_length=60, - verbose_name='Full name' + verbose_name='Full name', ), ), ] diff --git a/wger/core/migrations/0011_auto_20201201_0653.py b/wger/core/migrations/0011_auto_20201201_0653.py index bd4258de7..f7fe6810b 100644 --- a/wger/core/migrations/0011_auto_20201201_0653.py +++ b/wger/core/migrations/0011_auto_20201201_0653.py @@ -5,7 +5,6 @@ import django.db.models.deletion class Migration(migrations.Migration): - dependencies = [ ('gym', '0008_auto_20190618_1617'), ('core', '0010_auto_20170403_0144'), @@ -20,7 +19,7 @@ class Migration(migrations.Migration): editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, - to='gym.gym' + to='gym.gym', ), ), ] diff --git a/wger/core/migrations/0012_auto_20210210_1228.py b/wger/core/migrations/0012_auto_20210210_1228.py index d2acf82f7..efa5f2502 100644 --- a/wger/core/migrations/0012_auto_20210210_1228.py +++ b/wger/core/migrations/0012_auto_20210210_1228.py @@ -6,7 +6,6 @@ import django.db.models.deletion class Migration(migrations.Migration): - dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), ('core', '0011_auto_20201201_0653'), @@ -21,7 +20,7 @@ class Migration(migrations.Migration): null=True, on_delete=django.db.models.deletion.CASCADE, related_name='added_by', - to=settings.AUTH_USER_MODEL + to=settings.AUTH_USER_MODEL, ), ), migrations.AddField( diff --git a/wger/core/migrations/0013_auto_20210726_1729.py b/wger/core/migrations/0013_auto_20210726_1729.py index b49c30a0f..7393f543e 100644 --- a/wger/core/migrations/0013_auto_20210726_1729.py +++ b/wger/core/migrations/0013_auto_20210726_1729.py @@ -4,7 +4,6 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ ('core', '0012_auto_20210210_1228'), ] diff --git a/wger/core/migrations/0013_userprofile_email_verified.py b/wger/core/migrations/0013_userprofile_email_verified.py index 6c36e89dd..6bee15e9f 100644 --- a/wger/core/migrations/0013_userprofile_email_verified.py +++ b/wger/core/migrations/0013_userprofile_email_verified.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('core', '0012_auto_20210210_1228'), ] diff --git a/wger/core/migrations/0014_merge_20210818_1735.py b/wger/core/migrations/0014_merge_20210818_1735.py index de7bc9114..09d56f7d0 100644 --- a/wger/core/migrations/0014_merge_20210818_1735.py +++ b/wger/core/migrations/0014_merge_20210818_1735.py @@ -4,7 +4,6 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ ('core', '0013_auto_20210726_1729'), ('core', '0013_userprofile_email_verified'), diff --git a/wger/core/migrations/0015_alter_language_short_name.py b/wger/core/migrations/0015_alter_language_short_name.py index 88c7c2062..2924affc5 100644 --- a/wger/core/migrations/0015_alter_language_short_name.py +++ b/wger/core/migrations/0015_alter_language_short_name.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('core', '0014_merge_20210818_1735'), ] diff --git a/wger/core/migrations/0016_alter_language_short_name.py b/wger/core/migrations/0016_alter_language_short_name.py index 30656bf86..92ed14d3a 100644 --- a/wger/core/migrations/0016_alter_language_short_name.py +++ b/wger/core/migrations/0016_alter_language_short_name.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('core', '0015_alter_language_short_name'), ] @@ -14,10 +13,7 @@ class Migration(migrations.Migration): model_name='language', name='short_name', field=models.CharField( - help_text='ISO 639-1', - max_length=2, - unique=True, - verbose_name='Language short name' + help_text='ISO 639-1', max_length=2, unique=True, verbose_name='Language short name' ), ), ] diff --git a/wger/core/models/cache.py b/wger/core/models/cache.py index dd2639bc4..0a7c6d125 100644 --- a/wger/core/models/cache.py +++ b/wger/core/models/cache.py @@ -41,4 +41,4 @@ class UserCache(models.Model): """ Return a more human-readable representation """ - return f"Cache for user {self.user}" + return f'Cache for user {self.user}' diff --git a/wger/core/models/days_of_week.py b/wger/core/models/days_of_week.py index 2fb4b90d1..5d5547424 100644 --- a/wger/core/models/days_of_week.py +++ b/wger/core/models/days_of_week.py @@ -32,8 +32,9 @@ class DaysOfWeek(models.Model): """ Order by day-ID, this is needed for some DBs """ + ordering = [ - "pk", + 'pk', ] def __str__(self): diff --git a/wger/core/models/language.py b/wger/core/models/language.py index a7c63da95..f22f1f89a 100644 --- a/wger/core/models/language.py +++ b/wger/core/models/language.py @@ -43,8 +43,9 @@ class Language(models.Model): """ Set Meta options """ + ordering = [ - "full_name", + 'full_name', ] # @@ -54,7 +55,7 @@ class Language(models.Model): """ Return a more human-readable representation """ - return f"{self.full_name} ({self.short_name})" + return f'{self.full_name} ({self.short_name})' def get_absolute_url(self): """ diff --git a/wger/core/models/license.py b/wger/core/models/license.py index 524da1324..2ccfccac4 100644 --- a/wger/core/models/license.py +++ b/wger/core/models/license.py @@ -31,7 +31,7 @@ class License(models.Model): 'If a license has been localized, e.g. the Creative ' 'Commons licenses for the different countries, add ' 'them as separate entries here.' - ) + ), ) """Full name""" @@ -45,7 +45,7 @@ class License(models.Model): verbose_name=_('Link'), help_text=_('Link to license text or other information'), blank=True, - null=True + null=True, ) """URL to full license text or other information""" @@ -53,8 +53,9 @@ class License(models.Model): """ Set Meta options """ + ordering = [ - "full_name", + 'full_name', ] # @@ -64,7 +65,7 @@ class License(models.Model): """ Return a more human-readable representation """ - return f"{self.full_name} ({self.short_name})" + return f'{self.full_name} ({self.short_name})' # # Own methods diff --git a/wger/core/models/profile.py b/wger/core/models/profile.py index 8edda7b73..581adcc7d 100644 --- a/wger/core/models/profile.py +++ b/wger/core/models/profile.py @@ -116,8 +116,7 @@ class UserProfile(models.Model): show_comments = models.BooleanField( verbose_name=_('Show exercise comments'), - help_text=_('Check to show exercise comments on the ' - 'workout view'), + help_text=_('Check to show exercise comments on the ' 'workout view'), default=True, ) """ @@ -134,7 +133,7 @@ a nutritional plan. These ingredients are extracted from a list provided by the US Department of Agriculture. It is extremely complete, with around 7000 entries, but can be somewhat overwhelming and make the search difficult.""" ), - default=True + default=True, ) workout_reminder_active = models.BooleanField( @@ -145,15 +144,14 @@ by the US Department of Agriculture. It is extremely complete, with around 'to provide a valid email for this ' 'to work.' ), - default=False + default=False, ) workout_reminder = IntegerField( verbose_name=_('Remind before expiration'), - help_text=_('The number of days you want to be reminded ' - 'before a workout expires.'), + help_text=_('The number of days you want to be reminded ' 'before a workout expires.'), default=14, - validators=[MinValueValidator(1), MaxValueValidator(30)] + validators=[MinValueValidator(1), MaxValueValidator(30)], ) workout_duration = IntegerField( verbose_name=_('Default duration of workouts'), @@ -163,7 +161,7 @@ by the US Department of Agriculture. It is extremely complete, with around 'reminders.' ), default=12, - validators=[MinValueValidator(1), MaxValueValidator(30)] + validators=[MinValueValidator(1), MaxValueValidator(30)], ) last_workout_notification = models.DateField(editable=False, blank=False, null=True) """ @@ -183,7 +181,7 @@ by the US Department of Agriculture. It is extremely complete, with around 'language used on the website.' ), default=2, - on_delete=models.CASCADE + on_delete=models.CASCADE, ) @property @@ -216,7 +214,7 @@ by the US Department of Agriculture. It is extremely complete, with around verbose_name=_('Age'), blank=False, null=True, - validators=[MinValueValidator(10), MaxValueValidator(100)] + validators=[MinValueValidator(10), MaxValueValidator(100)], ) """The user's age""" @@ -232,7 +230,7 @@ by the US Department of Agriculture. It is extremely complete, with around verbose_name=_('Height (cm)'), blank=False, validators=[MinValueValidator(140), MaxValueValidator(230)], - null=True + null=True, ) """The user's height""" @@ -251,7 +249,7 @@ by the US Department of Agriculture. It is extremely complete, with around default=7, blank=False, null=True, - validators=[MinValueValidator(4), MaxValueValidator(10)] + validators=[MinValueValidator(4), MaxValueValidator(10)], ) """The average hours of sleep per day""" @@ -261,7 +259,7 @@ by the US Department of Agriculture. It is extremely complete, with around default=8, blank=False, null=True, - validators=[MinValueValidator(1), MaxValueValidator(15)] + validators=[MinValueValidator(1), MaxValueValidator(15)], ) """The average hours at work per day""" @@ -272,7 +270,7 @@ by the US Department of Agriculture. It is extremely complete, with around choices=INTENSITY, default=INTENSITY_LOW, blank=False, - null=True + null=True, ) """Physical intensity of work""" @@ -282,7 +280,7 @@ by the US Department of Agriculture. It is extremely complete, with around default=3, blank=False, null=True, - validators=[MinValueValidator(1), MaxValueValidator(30)] + validators=[MinValueValidator(1), MaxValueValidator(30)], ) """The average hours performing sports per week""" @@ -293,7 +291,7 @@ by the US Department of Agriculture. It is extremely complete, with around choices=INTENSITY, default=INTENSITY_MEDIUM, blank=False, - null=True + null=True, ) """Physical intensity of sport activities""" @@ -303,7 +301,7 @@ by the US Department of Agriculture. It is extremely complete, with around default=8, blank=False, null=True, - validators=[MinValueValidator(1), MaxValueValidator(15)] + validators=[MinValueValidator(1), MaxValueValidator(15)], ) """The average hours of free time per day""" @@ -314,7 +312,7 @@ by the US Department of Agriculture. It is extremely complete, with around choices=INTENSITY, default=INTENSITY_LOW, blank=False, - null=True + null=True, ) """Physical intensity during free time""" @@ -324,7 +322,7 @@ by the US Department of Agriculture. It is extremely complete, with around default=2500, blank=False, null=True, - validators=[MinValueValidator(1500), MaxValueValidator(5000)] + validators=[MinValueValidator(1500), MaxValueValidator(5000)], ) """Basic caloric intake based on physical activity""" @@ -346,18 +344,15 @@ by the US Department of Agriculture. It is extremely complete, with around 'logs in a read-only mode. You need to set this ' 'before you can share links e.g. to social media.' ), - default=False + default=False, ) """Allow anonymous read-only access""" num_days_weight_reminder = models.IntegerField( - verbose_name=_('Automatic reminders for weight ' - 'entries'), - help_text=_('Number of days after the last ' - 'weight entry (enter 0 to ' - 'deactivate)'), + verbose_name=_('Automatic reminders for weight ' 'entries'), + help_text=_('Number of days after the last ' 'weight entry (enter 0 to ' 'deactivate)'), validators=[MinValueValidator(0), MaxValueValidator(30)], - default=0 + default=0, ) """Number of Days for email weight reminder""" @@ -415,17 +410,16 @@ by the US Department of Agriculture. It is extremely complete, with around """ Make sure the total amount of hours is 24 """ - if ( - (self.sleep_hours and self.freetime_hours and self.work_hours) - and (self.sleep_hours + self.freetime_hours + self.work_hours) > 24 - ): + if (self.sleep_hours and self.freetime_hours and self.work_hours) and ( + self.sleep_hours + self.freetime_hours + self.work_hours + ) > 24: raise ValidationError(_('The sum of all hours has to be 24')) def __str__(self): """ Return a more human-readable representation """ - return f"Profile for user {self.user}" + return f'Profile for user {self.user}' @property def use_metric(self): @@ -521,11 +515,9 @@ by the US Department of Agriculture. It is extremely complete, with around """ Create a new weight entry as needed """ - if ( - not WeightEntry.objects.filter(user=self.user).exists() or ( - datetime.date.today() - WeightEntry.objects.filter(user=self.user).latest().date - > datetime.timedelta(days=3) - ) + if not WeightEntry.objects.filter(user=self.user).exists() or ( + datetime.date.today() - WeightEntry.objects.filter(user=self.user).latest().date + > datetime.timedelta(days=3) ): entry = WeightEntry() entry.weight = weight diff --git a/wger/core/models/rep_unit.py b/wger/core/models/rep_unit.py index 0e2979799..5cbeda557 100644 --- a/wger/core/models/rep_unit.py +++ b/wger/core/models/rep_unit.py @@ -28,8 +28,9 @@ class RepetitionUnit(models.Model): """ Set Meta options """ + ordering = [ - "name", + 'name', ] name = models.CharField(max_length=100, verbose_name=_('Name')) diff --git a/wger/core/models/weight_unit.py b/wger/core/models/weight_unit.py index 44f5e345b..0c1f22351 100644 --- a/wger/core/models/weight_unit.py +++ b/wger/core/models/weight_unit.py @@ -28,8 +28,9 @@ class WeightUnit(models.Model): """ Set Meta options """ + ordering = [ - "name", + 'name', ] name = models.CharField(max_length=100, verbose_name=_('Name')) diff --git a/wger/core/signals.py b/wger/core/signals.py index 3a8ae80be..22fc56cf7 100644 --- a/wger/core/signals.py +++ b/wger/core/signals.py @@ -61,8 +61,7 @@ def set_user_age(sender, instance, **kwargs): today = datetime.date.today() birthday = instance.birthdate instance.age = ( - today.year - birthday.year - - ((today.month, today.day) < (birthday.month, birthday.day)) + today.year - birthday.year - ((today.month, today.day) < (birthday.month, birthday.day)) ) diff --git a/wger/core/templatetags/wger_extras.py b/wger/core/templatetags/wger_extras.py index ecb1043fb..bc61124c3 100644 --- a/wger/core/templatetags/wger_extras.py +++ b/wger/core/templatetags/wger_extras.py @@ -72,7 +72,6 @@ def pagination(paginator, page): # we muck around here to remove the pages not inmediately 'around' the current # one, otherwise we end up with a useless block with 300 pages. if paginator.num_pages > PAGINATION_MAX_TOTAL_PAGES: - start_page = page.number - PAGINATION_PAGES_AROUND_CURRENT for i in range(page.number - PAGINATION_PAGES_AROUND_CURRENT, page.number + 1): if i > 0: @@ -111,7 +110,7 @@ def render_muscles(muscles=None, muscles_sec=None): """ Renders the given muscles """ - out = {"backgrounds": []} + out = {'backgrounds': []} if not muscles and not muscles_sec: return out @@ -124,13 +123,15 @@ def render_muscles(muscles=None, muscles_sec=None): out_secondary = muscles_sec if isinstance(muscles_sec, Iterable) else [muscles_sec] if out_main: - front_back = "front" if out_main[0].is_front else "back" + front_back = 'front' if out_main[0].is_front else 'back' else: - front_back = "front" if out_secondary[0].is_front else "back" + front_back = 'front' if out_secondary[0].is_front else 'back' - out['backgrounds'] = [i.image_url_main for i in out_main] \ - + [i.image_url_secondary for i in out_secondary] \ - + [static(f"images/muscles/muscular_system_{front_back}.svg")] + out['backgrounds'] = ( + [i.image_url_main for i in out_main] + + [i.image_url_secondary for i in out_secondary] + + [static(f'images/muscles/muscular_system_{front_back}.svg')] + ) return out @@ -203,12 +204,12 @@ def trans_weight_unit(unit, user=None): if unit == 'kg': return _('kg') if unit == 'g': - return pgettext("weight unit, i.e. grams", "g") + return pgettext('weight unit, i.e. grams', 'g') else: if unit == 'kg': return _('lb') if unit == 'g': - return pgettext("weight unit, i.e. ounces", "oz") + return pgettext('weight unit, i.e. ounces', 'oz') @register.filter diff --git a/wger/core/tests/api_base_test.py b/wger/core/tests/api_base_test.py index c8ca8793c..becfe6ad6 100644 --- a/wger/core/tests/api_base_test.py +++ b/wger/core/tests/api_base_test.py @@ -231,7 +231,7 @@ class ApiPostTestCase: response = self.client.post(self.url_detail, data=self.data) self.assertIn( response.status_code, - (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN) + (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN), ) # Authorized user (owner) @@ -239,7 +239,7 @@ class ApiPostTestCase: response = self.client.post(self.url_detail, data=self.data) self.assertIn( response.status_code, - (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN) + (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN), ) # Different logged in user @@ -247,7 +247,7 @@ class ApiPostTestCase: response = self.client.post(self.url_detail, data=self.data) self.assertIn( response.status_code, - (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN) + (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN), ) def test_post(self): @@ -279,7 +279,7 @@ class ApiPostTestCase: response = self.client.post(self.url, data=self.data) self.assertIn( response.status_code, - (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN) + (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN), ) # Logged in user @@ -287,7 +287,7 @@ class ApiPostTestCase: response = self.client.post(self.url, data=self.data) self.assertIn( response.status_code, - (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN) + (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN), ) # Different logged in user @@ -298,7 +298,7 @@ class ApiPostTestCase: else: self.assertIn( response.status_code, - (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN) + (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN), ) def test_post_special_endpoints(self): @@ -362,7 +362,7 @@ class ApiPatchTestCase: response = self.client.patch(self.url_detail, data=self.data) self.assertIn( response.status_code, - (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN) + (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN), ) # Authorized user (owner) @@ -370,7 +370,7 @@ class ApiPatchTestCase: response = self.client.patch(self.url_detail, data=self.data) self.assertIn( response.status_code, - (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN) + (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN), ) # Different logged in user @@ -381,7 +381,7 @@ class ApiPatchTestCase: else: self.assertIn( response.status_code, - (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN) + (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN), ) def test_patch(self): @@ -398,7 +398,7 @@ class ApiPatchTestCase: response = self.client.patch(self.url, data=self.data) self.assertIn( response.status_code, - (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN) + (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN), ) # Logged in user @@ -488,7 +488,7 @@ class ApiPutTestCase: response = self.client.put(self.url_detail, data=self.data) self.assertIn( response.status_code, - (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN) + (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN), ) # Authorized user (owner) @@ -496,7 +496,7 @@ class ApiPutTestCase: response = self.client.put(self.url_detail, data=self.data) self.assertIn( response.status_code, - (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN) + (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN), ) # Different logged in user @@ -507,7 +507,7 @@ class ApiPutTestCase: else: self.assertIn( response.status_code, - (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN) + (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN), ) def test_put(self): @@ -525,7 +525,7 @@ class ApiPutTestCase: response = self.client.put(self.url, data=self.data) self.assertIn( response.status_code, - (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN) + (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN), ) # Authorized user (owner) @@ -601,7 +601,7 @@ class ApiDeleteTestCase: response = self.client.delete(self.url_detail) self.assertIn( response.status_code, - (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN) + (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN), ) # Logged in user @@ -609,7 +609,7 @@ class ApiDeleteTestCase: response = self.client.delete(self.url_detail) self.assertIn( response.status_code, - (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN) + (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN), ) # Different logged in user @@ -617,7 +617,7 @@ class ApiDeleteTestCase: response = self.client.delete(self.url_detail) self.assertIn( response.status_code, - (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN) + (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN), ) def test_delete(self): @@ -643,7 +643,7 @@ class ApiDeleteTestCase: response = self.client.delete(self.url) self.assertIn( response.status_code, - (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN) + (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN), ) # Authorized user (owner) @@ -651,7 +651,7 @@ class ApiDeleteTestCase: response = self.client.delete(self.url) self.assertIn( response.status_code, - (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN) + (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN), ) # Different logged in user @@ -659,7 +659,7 @@ class ApiDeleteTestCase: response = self.client.delete(self.url) self.assertIn( response.status_code, - (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN) + (status.HTTP_405_METHOD_NOT_ALLOWED, status.HTTP_403_FORBIDDEN), ) def test_delete_special_endpoints(self): @@ -700,6 +700,7 @@ class ApiBaseResourceTestCase( All logic happens in the Api*TestCase classes """ + pass diff --git a/wger/core/tests/base_testcase.py b/wger/core/tests/base_testcase.py index b4234768f..8ba556ab0 100644 --- a/wger/core/tests/base_testcase.py +++ b/wger/core/tests/base_testcase.py @@ -185,15 +185,15 @@ class BaseTestCase: shutil.copy( 'wger/exercises/tests/protestschwein.jpg', - self.media_root + '/exercise-images/1/protestschwein.jpg' + self.media_root + '/exercise-images/1/protestschwein.jpg', ) shutil.copy( 'wger/exercises/tests/wildschwein.jpg', - self.media_root + '/exercise-images/1/wildschwein.jpg' + self.media_root + '/exercise-images/1/wildschwein.jpg', ) shutil.copy( 'wger/exercises/tests/wildschwein.jpg', - self.media_root + '/exercise-images/2/wildschwein.jpg' + self.media_root + '/exercise-images/2/wildschwein.jpg', ) @@ -253,7 +253,6 @@ class WgerTestCase(BaseTestCase, TestCase): # Uploaded image or file, compare the filename elif current_field_class in ('ImageFieldFile', 'FieldFile'): - # We can only compare the extensions, since the names can be changed # Ideally we would check that the byte length is the same self.assertEqual(pathlib.Path(field.name).suffix, pathlib.Path(value.name).suffix) @@ -564,7 +563,6 @@ class WgerAccessTestCase(WgerTestCase): anonymous_fail = True def access(self, fail=True): - # Only perform the checks on derived classes if self.__class__.__name__ == 'WgerAccessTestCase': return diff --git a/wger/core/tests/test_change_password.py b/wger/core/tests/test_change_password.py index 674909bbb..c94bd2d17 100644 --- a/wger/core/tests/test_change_password.py +++ b/wger/core/tests/test_change_password.py @@ -32,7 +32,6 @@ class ChangePasswordTestCase(WgerTestCase): """ def change_password(self, fail=True): - # Fetch the change passwort page response = self.client.get(reverse('core:user:change-password')) diff --git a/wger/core/tests/test_daysofweek.py b/wger/core/tests/test_daysofweek.py index 9bb7becd6..372f19087 100644 --- a/wger/core/tests/test_daysofweek.py +++ b/wger/core/tests/test_daysofweek.py @@ -28,13 +28,14 @@ class DaysOfWeekRepresentationTestCase(WgerTestCase): """ Test that the representation of an object is correct """ - self.assertEqual(f"{DaysOfWeek.objects.get(pk=1)}", 'Monday') + self.assertEqual(f'{DaysOfWeek.objects.get(pk=1)}', 'Monday') class DaysOfWeekApiTestCase(api_base_test.ApiBaseResourceTestCase): """ Tests the days of week resource """ + pk = 1 resource = DaysOfWeek private_resource = False diff --git a/wger/core/tests/test_delete_user.py b/wger/core/tests/test_delete_user.py index e707b675c..17c232743 100644 --- a/wger/core/tests/test_delete_user.py +++ b/wger/core/tests/test_delete_user.py @@ -86,8 +86,9 @@ class DeleteUserByAdminTestCase(WgerTestCase): self.assertEqual(User.objects.filter(username='test').count(), 1) if fail: self.assertIn( - response.status_code, (302, 403), - f'Unexpected status code for user {self.current_user}' + response.status_code, + (302, 403), + f'Unexpected status code for user {self.current_user}', ) else: self.assertEqual( diff --git a/wger/core/tests/test_feedback.py b/wger/core/tests/test_feedback.py index bfbacac65..c203124d3 100644 --- a/wger/core/tests/test_feedback.py +++ b/wger/core/tests/test_feedback.py @@ -55,10 +55,11 @@ class FeedbackTestCase(WgerTestCase): # Correctly filled in reCaptcha response = self.client.post( - reverse('core:feedback'), { + reverse('core:feedback'), + { 'comment': 'A very long and interesting comment', - 'g-recaptcha-response': 'PASSED' - } + 'g-recaptcha-response': 'PASSED', + }, ) self.assertEqual(response.status_code, 302) @@ -82,7 +83,7 @@ class FeedbackTestCase(WgerTestCase): self.user_login('test') self.send_feedback() - @skip("Failing due to recaptcha issues") + @skip('Failing due to recaptcha issues') def test_send_feedback_logged_out(self): """ Tests the feedback form as a logged out user diff --git a/wger/core/tests/test_generator.py b/wger/core/tests/test_generator.py index 6c3a588c0..efa497236 100644 --- a/wger/core/tests/test_generator.py +++ b/wger/core/tests/test_generator.py @@ -22,7 +22,6 @@ from wger.gym.models import Gym class UserGeneratorTestCase(WgerTestCase): - def test_generator(self): # Arrange User.objects.all().delete() diff --git a/wger/core/tests/test_index.py b/wger/core/tests/test_index.py index 07192dbf5..f0f7e12a5 100644 --- a/wger/core/tests/test_index.py +++ b/wger/core/tests/test_index.py @@ -60,11 +60,14 @@ class DashboardTestCase(WgerTestCase): # # 2. Add a weight entry # - self.client.post(reverse('weight:add'), { - 'weight': 100, - 'date': '2012-01-01', - 'user': 1, - }) + self.client.post( + reverse('weight:add'), + { + 'weight': 100, + 'date': '2012-01-01', + 'user': 1, + }, + ) response = self.client.get(reverse('core:dashboard')) self.assertEqual(response.status_code, 200) diff --git a/wger/core/tests/test_language.py b/wger/core/tests/test_language.py index 4018619aa..27e2fe85d 100644 --- a/wger/core/tests/test_language.py +++ b/wger/core/tests/test_language.py @@ -39,7 +39,7 @@ class LanguageRepresentationTestCase(WgerTestCase): """ Test that the representation of an object is correct """ - self.assertEqual(f"{Language.objects.get(pk=1)}", 'Deutsch (de)') + self.assertEqual(f'{Language.objects.get(pk=1)}', 'Deutsch (de)') class LanguageOverviewTest(WgerAccessTestCase): @@ -95,6 +95,7 @@ class LanguageApiTestCase(api_base_test.ApiBaseResourceTestCase): """ Tests the language overview resource """ + pk = 1 resource = Language private_resource = False diff --git a/wger/core/tests/test_license.py b/wger/core/tests/test_license.py index 4c45781c8..9fe9d5534 100644 --- a/wger/core/tests/test_license.py +++ b/wger/core/tests/test_license.py @@ -35,7 +35,7 @@ class LicenseRepresentationTestCase(WgerTestCase): Test that the representation of an object is correct """ self.assertEqual( - f"{License.objects.get(pk=1)}", + f'{License.objects.get(pk=1)}', 'A cool and free license - Germany (ACAFL - DE)', ) @@ -83,6 +83,7 @@ class LicenseApiTestCase(api_base_test.ApiBaseResourceTestCase): """ Tests the license resource """ + pk = 1 resource = License private_resource = False diff --git a/wger/core/tests/test_permission_api.py b/wger/core/tests/test_permission_api.py index 0c98540dd..acc114074 100644 --- a/wger/core/tests/test_permission_api.py +++ b/wger/core/tests/test_permission_api.py @@ -22,7 +22,6 @@ from wger.core.tests.base_testcase import BaseTestCase class CheckPermissionApiTestCase(BaseTestCase, ApiBaseTestCase): - url = '/api/v2/check-permission/' error_message = "Please pass a permission name in the 'permission' parameter" diff --git a/wger/core/tests/test_preferences.py b/wger/core/tests/test_preferences.py index eb259dd95..19756e09c 100644 --- a/wger/core/tests/test_preferences.py +++ b/wger/core/tests/test_preferences.py @@ -51,7 +51,8 @@ class PreferencesTestCase(WgerTestCase): # Change some preferences response = self.client.post( - reverse('core:user:preferences'), { + reverse('core:user:preferences'), + { 'show_comments': True, 'show_english_ingredients': True, 'email': 'my-new-email@example.com', @@ -62,7 +63,7 @@ class PreferencesTestCase(WgerTestCase): 'num_days_weight_reminder': 10, 'weight_unit': 'kg', 'birthdate': '02/25/1987', - } + }, ) self.assertEqual(response.status_code, 302) @@ -76,7 +77,8 @@ class PreferencesTestCase(WgerTestCase): # Change some preferences response = self.client.post( - reverse('core:user:preferences'), { + reverse('core:user:preferences'), + { 'show_comments': False, 'show_english_ingredients': True, 'email': '', @@ -87,7 +89,7 @@ class PreferencesTestCase(WgerTestCase): 'num_days_weight_reminder': 10, 'weight_unit': 'lb', 'birthdate': '02/25/1987', - } + }, ) self.assertEqual(response.status_code, 302) @@ -105,23 +107,25 @@ class PreferencesTestCase(WgerTestCase): # Member2 has a contract user = User.objects.get(username='member2') self.assertEqual( - user.userprofile.address, { + user.userprofile.address, + { 'phone': '01234-567890', 'zip_code': '00000', 'street': 'Gassenstr. 14', 'city': 'The City', - } + }, ) # Test has no contracts user = User.objects.get(username='test') self.assertEqual( - user.userprofile.address, { + user.userprofile.address, + { 'phone': '', 'zip_code': '', 'street': '', 'city': '', - } + }, ) @@ -246,8 +250,8 @@ class PreferencesCalculationsTestCase(WgerTestCase): bmi = user.userprofile.calculate_bmi() self.assertEqual( bmi, - user.userprofile.weight.quantize(TWOPLACES) / - decimal.Decimal(1.80 * 1.80).quantize(TWOPLACES) + user.userprofile.weight.quantize(TWOPLACES) + / decimal.Decimal(1.80 * 1.80).quantize(TWOPLACES), ) def test_basal_metabolic_rate(self): @@ -263,7 +267,7 @@ class PreferencesCalculationsTestCase(WgerTestCase): self.assertEqual(bmr, 1860) # Female - user.userprofile.gender = "2" + user.userprofile.gender = '2' bmr = user.userprofile.calculate_basal_metabolic_rate() self.assertEqual(bmr, 1694) @@ -281,29 +285,25 @@ class PreferencesCalculationsTestCase(WgerTestCase): user = User.objects.get(pk=2) self.assertEqual( - user.userprofile.calculate_activities(), - decimal.Decimal(1.57).quantize(TWOPLACES) + user.userprofile.calculate_activities(), decimal.Decimal(1.57).quantize(TWOPLACES) ) # Gender has no influence - user.userprofile.gender = "2" + user.userprofile.gender = '2' self.assertEqual( - user.userprofile.calculate_activities(), - decimal.Decimal(1.57).quantize(TWOPLACES) + user.userprofile.calculate_activities(), decimal.Decimal(1.57).quantize(TWOPLACES) ) # Change some of the parameters user.userprofile.work_intensity = '3' self.assertEqual( - user.userprofile.calculate_activities(), - decimal.Decimal(1.80).quantize(TWOPLACES) + user.userprofile.calculate_activities(), decimal.Decimal(1.80).quantize(TWOPLACES) ) user.userprofile.work_intensity = '2' user.userprofile.sport_intensity = '2' self.assertEqual( - user.userprofile.calculate_activities(), - decimal.Decimal(1.52).quantize(TWOPLACES) + user.userprofile.calculate_activities(), decimal.Decimal(1.52).quantize(TWOPLACES) ) diff --git a/wger/core/tests/test_registration.py b/wger/core/tests/test_registration.py index be2f3f3ec..3804229f8 100644 --- a/wger/core/tests/test_registration.py +++ b/wger/core/tests/test_registration.py @@ -134,23 +134,23 @@ class RegistrationTestCase(WgerTestCase): self.user_logout() # First password is missing - registration_data['password1'] = "" + registration_data['password1'] = '' response = self.client.post(reverse('core:user:registration'), registration_data) self.assertFalse(response.context['form'].is_valid()) self.user_logout() # Second password is missing - registration_data['password2'] = "" + registration_data['password2'] = '' response = self.client.post(reverse('core:user:registration'), registration_data) self.assertFalse(response.context['form'].is_valid()) self.user_logout() # Username is too long long_user = ( - "my_username_is_" - "wayyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" - "_toooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" - "_loooooooooooooooooooooooooooooooooooooooooooooooooooooooooong" + 'my_username_is_' + 'wayyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy' + '_toooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo' + '_loooooooooooooooooooooooooooooooooooooooooooooooooooooooooong' ) registration_data['username'] = long_user response = self.client.post(reverse('core:user:registration'), registration_data) @@ -158,13 +158,13 @@ class RegistrationTestCase(WgerTestCase): self.user_logout() # Username contains invalid symbol - registration_data['username'] = "username!" + registration_data['username'] = 'username!' response = self.client.post(reverse('core:user:registration'), registration_data) self.assertFalse(response.context['form'].is_valid()) self.user_logout() # Username is missing - registration_data['username'] = "" + registration_data['username'] = '' response = self.client.post(reverse('core:user:registration'), registration_data) self.assertFalse(response.context['form'].is_valid()) self.user_logout() diff --git a/wger/core/tests/test_repetition_unit.py b/wger/core/tests/test_repetition_unit.py index 09887299d..35b2f8813 100644 --- a/wger/core/tests/test_repetition_unit.py +++ b/wger/core/tests/test_repetition_unit.py @@ -34,7 +34,7 @@ class RepresentationTestCase(WgerTestCase): """ Test that the representation of an object is correct """ - self.assertEqual(f"{RepetitionUnit.objects.get(pk=1)}", 'Repetitions') + self.assertEqual(f'{RepetitionUnit.objects.get(pk=1)}', 'Repetitions') class OverviewTest(WgerAccessTestCase): @@ -54,7 +54,7 @@ class AddTestCase(WgerAddTestCase): object_class = RepetitionUnit url = 'core:repetition-unit:add' data = {'name': 'Furlongs'} - user_success = 'admin', + user_success = ('admin',) user_fail = ( 'general_manager1', 'general_manager2', @@ -75,7 +75,7 @@ class DeleteTestCase(WgerDeleteTestCase): pk = 1 object_class = RepetitionUnit url = 'core:repetition-unit:delete' - user_success = 'admin', + user_success = ('admin',) user_fail = ( 'general_manager1', 'general_manager2', @@ -97,7 +97,7 @@ class EditTestCase(WgerEditTestCase): object_class = RepetitionUnit url = 'core:repetition-unit:edit' data = {'name': 'Furlongs'} - user_success = 'admin', + user_success = ('admin',) user_fail = ( 'general_manager1', 'general_manager2', @@ -114,6 +114,7 @@ class ApiTestCase(api_base_test.ApiBaseResourceTestCase): """ Tests the unit resource """ + pk = 1 resource = RepetitionUnit private_resource = False diff --git a/wger/core/tests/test_robots_txt.py b/wger/core/tests/test_robots_txt.py index ea684f826..09d10a53d 100644 --- a/wger/core/tests/test_robots_txt.py +++ b/wger/core/tests/test_robots_txt.py @@ -26,7 +26,6 @@ class RobotsTxtTestCase(WgerTestCase): """ def test_robots(self): - response = self.client.get(reverse('robots')) for lang in Language.objects.all(): self.assertTrue(f'wger.de/{lang.short_name}/sitemap.xml' in str(response.content)) diff --git a/wger/core/tests/test_sitemap.py b/wger/core/tests/test_sitemap.py index 31724382b..c4f776f3b 100644 --- a/wger/core/tests/test_sitemap.py +++ b/wger/core/tests/test_sitemap.py @@ -25,13 +25,11 @@ class SitemapTestCase(WgerTestCase): """ def test_sitemap_index(self): - response = self.client.get(reverse('sitemap')) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.context['sitemaps']), 2) def test_sitemap_exercises(self): - response = self.client.get( reverse('django.contrib.sitemaps.views.sitemap', kwargs={'section': 'exercises'}) ) @@ -39,7 +37,6 @@ class SitemapTestCase(WgerTestCase): self.assertEqual(len(response.context['urlset']), 11) def test_sitemap_ingredients(self): - response = self.client.get( reverse('django.contrib.sitemaps.views.sitemap', kwargs={'section': 'nutrition'}) ) diff --git a/wger/core/tests/test_user_login.py b/wger/core/tests/test_user_login.py index 8d8da67db..a9f00c85d 100644 --- a/wger/core/tests/test_user_login.py +++ b/wger/core/tests/test_user_login.py @@ -37,7 +37,6 @@ def _build_mock_user(gym_name, is_trainer=False): @mock.patch('wger.core.views.user.django_login') class TrainerLoginTestCase(WgerTestCase): - def test_trainer_is_allowed_to_login_to_non_trainer_in_same_gym(self, _): request_user = _build_mock_user('same-gym', is_trainer=True) request = _build_mock_request(request_user) @@ -92,10 +91,7 @@ class UserApiLoginApiTestCase(BaseTestCase, ApiBaseTestCase): def test_login_username_success(self): response = self.client.post( self.url, - { - 'username': 'admin', - 'password': 'adminadmin' - }, + {'username': 'admin', 'password': 'adminadmin'}, ) result = response.data @@ -109,16 +105,13 @@ class UserApiLoginApiTestCase(BaseTestCase, ApiBaseTestCase): self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual( result['non_field_errors'], - [ErrorDetail(string='Username or password unknown', code='invalid')] + [ErrorDetail(string='Username or password unknown', code='invalid')], ) def test_login_email_success(self): response = self.client.post( self.url, - { - 'email': 'admin@example.com', - 'password': 'adminadmin' - }, + {'email': 'admin@example.com', 'password': 'adminadmin'}, ) result = response.data @@ -127,17 +120,14 @@ class UserApiLoginApiTestCase(BaseTestCase, ApiBaseTestCase): def test_login_email_fail(self): response = self.client.post( - self.url, { - 'email': 'admin@example.com', - 'password': 'adminadmin123' - } + self.url, {'email': 'admin@example.com', 'password': 'adminadmin123'} ) result = response.data self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual( result['non_field_errors'], - [ErrorDetail(string='Username or password unknown', code='invalid')] + [ErrorDetail(string='Username or password unknown', code='invalid')], ) def test_no_parameters(self): @@ -147,5 +137,5 @@ class UserApiLoginApiTestCase(BaseTestCase, ApiBaseTestCase): self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual( result['non_field_errors'], - [ErrorDetail(string='Please provide an "email" or a "username"', code='invalid')] + [ErrorDetail(string='Please provide an "email" or a "username"', code='invalid')], ) diff --git a/wger/core/tests/test_user_rest_registration.py b/wger/core/tests/test_user_rest_registration.py index 0a9105ecc..691a75151 100644 --- a/wger/core/tests/test_user_rest_registration.py +++ b/wger/core/tests/test_user_rest_registration.py @@ -19,7 +19,6 @@ from wger.core.tests.base_testcase import WgerTestCase class CreateUserCommand(WgerTestCase): - def setUp(self): super(CreateUserCommand, self).setUp() self.out = StringIO() @@ -68,20 +67,17 @@ class CreateUserCommand(WgerTestCase): count_before = User.objects.count() response = self.client.post( - reverse('api_register'), { - 'username': 'restapi', - 'email': 'abc@cde.fg', - 'password': 'AekaiLe0ga' - }, - Authorization=f'Token {token.key}' + reverse('api_register'), + {'username': 'restapi', 'email': 'abc@cde.fg', 'password': 'AekaiLe0ga'}, + Authorization=f'Token {token.key}', ) count_after = User.objects.count() self.assertEqual(response.status_code, HTTP_201_CREATED) new_user = User.objects.get(username='restapi') token = Token.objects.get(user=new_user) - self.assertEqual(response.data["message"], "api user successfully registered") - self.assertEqual(response.data["token"], token.key) + self.assertEqual(response.data['message'], 'api user successfully registered') + self.assertEqual(response.data['token'], token.key) self.assertEqual(count_after, count_before + 1) def test_post_valid_api_user_creation_no_email(self): @@ -93,19 +89,17 @@ class CreateUserCommand(WgerTestCase): count_before = User.objects.count() response = self.client.post( - reverse('api_register'), { - 'username': 'restapi', - 'password': 'AekaiLe0ga' - }, - Authorization=f'Token {token.key}' + reverse('api_register'), + {'username': 'restapi', 'password': 'AekaiLe0ga'}, + Authorization=f'Token {token.key}', ) count_after = User.objects.count() self.assertEqual(response.status_code, HTTP_201_CREATED) new_user = User.objects.get(username='restapi') token = Token.objects.get(user=new_user) - self.assertEqual(response.data["message"], "api user successfully registered") - self.assertEqual(response.data["token"], token.key) + self.assertEqual(response.data['message'], 'api user successfully registered') + self.assertEqual(response.data['token'], token.key) self.assertEqual(count_after, count_before + 1) def test_post_not_allowed_api_user_creation(self): @@ -115,11 +109,8 @@ class CreateUserCommand(WgerTestCase): count_before = User.objects.count() response = self.client.post( - reverse('api_register'), { - 'username': 'restapi', - 'email': 'abc@cde.fg', - 'password': 'AekaiLe0ga' - } + reverse('api_register'), + {'username': 'restapi', 'email': 'abc@cde.fg', 'password': 'AekaiLe0ga'}, ) count_after = User.objects.count() @@ -149,12 +140,9 @@ class CreateUserCommand(WgerTestCase): token = Token.objects.get(user=user) response = self.client.post( - reverse('api_register'), { - 'username': 'restapi', - 'email': 'example.com', - 'password': 'AekaiLe0ga' - }, - Authorization=f'Token {token.key}' + reverse('api_register'), + {'username': 'restapi', 'email': 'example.com', 'password': 'AekaiLe0ga'}, + Authorization=f'Token {token.key}', ) self.assertEqual(response.status_code, HTTP_400_BAD_REQUEST) @@ -167,12 +155,9 @@ class CreateUserCommand(WgerTestCase): token = Token.objects.get(user=user) response = self.client.post( - reverse('api_register'), { - 'username': 'restapi', - 'email': 'admin@example.com', - 'password': 'AekaiLe0ga' - }, - Authorization=f'Token {token.key}' + reverse('api_register'), + {'username': 'restapi', 'email': 'admin@example.com', 'password': 'AekaiLe0ga'}, + Authorization=f'Token {token.key}', ) self.assertEqual(response.status_code, HTTP_400_BAD_REQUEST) diff --git a/wger/core/tests/test_weight_unit.py b/wger/core/tests/test_weight_unit.py index c8d72dea9..4d83c0311 100644 --- a/wger/core/tests/test_weight_unit.py +++ b/wger/core/tests/test_weight_unit.py @@ -34,7 +34,7 @@ class RepresentationTestCase(WgerTestCase): """ Test that the representation of an object is correct """ - self.assertEqual(f"{WeightUnit.objects.get(pk=1)}", 'kg') + self.assertEqual(f'{WeightUnit.objects.get(pk=1)}', 'kg') class OverviewTest(WgerAccessTestCase): @@ -54,7 +54,7 @@ class AddTestCase(WgerAddTestCase): object_class = WeightUnit url = 'core:weight-unit:add' data = {'name': 'Furlongs'} - user_success = 'admin', + user_success = ('admin',) user_fail = ( 'general_manager1', 'general_manager2', @@ -75,7 +75,7 @@ class DeleteTestCase(WgerDeleteTestCase): pk = 1 object_class = WeightUnit url = 'core:weight-unit:delete' - user_success = 'admin', + user_success = ('admin',) user_fail = ( 'general_manager1', 'general_manager2', @@ -97,7 +97,7 @@ class EditTestCase(WgerEditTestCase): object_class = WeightUnit url = 'core:weight-unit:edit' data = {'name': 'Furlongs'} - user_success = 'admin', + user_success = ('admin',) user_fail = ( 'general_manager1', 'general_manager2', @@ -114,6 +114,7 @@ class ApiTestCase(api_base_test.ApiBaseResourceTestCase): """ Tests the unit resource """ + pk = 1 resource = WeightUnit private_resource = False diff --git a/wger/core/urls.py b/wger/core/urls.py index d96e4b270..65dc5faca 100644 --- a/wger/core/urls.py +++ b/wger/core/urls.py @@ -69,7 +69,7 @@ patterns_user = [ path( 'login', views.LoginView.as_view(template_name='user/login.html', authentication_form=UserLoginForm), - name='login' + name='login', ), path('logout', user.logout, name='logout'), path('delete', user.delete, name='delete'), @@ -85,7 +85,6 @@ patterns_user = [ path('/edit', user.UserEditView.as_view(), name='edit'), path('/overview', user.UserDetailView.as_view(), name='overview'), path('list', user.UserListView.as_view(), name='list'), - # Password reset is implemented by Django, no need to cook our own soup here # (besides the templates) path( @@ -191,17 +190,14 @@ patterns_weight_units = [ # Actual patterns # urlpatterns = [ - # The landing page path('', misc.index, name='index'), - # The dashboard path('dashboard', misc.dashboard, name='dashboard'), - # Others path( 'imprint', - TemplateView.as_view(template_name="misc/about.html"), + TemplateView.as_view(template_name='misc/about.html'), name='imprint', ), path( @@ -209,12 +205,12 @@ urlpatterns = [ misc.FeedbackClass.as_view(), name='feedback', ), - path('language/', include((patterns_language, 'language'), namespace="language")), - path('user/', include((patterns_user, 'user'), namespace="user")), - path('license/', include((patterns_license, 'license'), namespace="license")), + path('language/', include((patterns_language, 'language'), namespace='language')), + path('user/', include((patterns_user, 'user'), namespace='user')), + path('license/', include((patterns_license, 'license'), namespace='license')), path( 'repetition-unit/', - include((patterns_repetition_units, 'repetition-unit'), namespace="repetition-unit") + include((patterns_repetition_units, 'repetition-unit'), namespace='repetition-unit'), ), - path('weight-unit/', include((patterns_weight_units, 'weight-unit'), namespace="weight-unit")), + path('weight-unit/', include((patterns_weight_units, 'weight-unit'), namespace='weight-unit')), ] diff --git a/wger/core/views/languages.py b/wger/core/views/languages.py index 28636df88..05ee09c09 100644 --- a/wger/core/views/languages.py +++ b/wger/core/views/languages.py @@ -50,6 +50,7 @@ class LanguageListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): """ Show an overview of all languages """ + model = Language template_name = 'language/overview.html' context_object_name = 'language_list' diff --git a/wger/core/views/license.py b/wger/core/views/license.py index 3dea79e1c..23b213e46 100644 --- a/wger/core/views/license.py +++ b/wger/core/views/license.py @@ -49,6 +49,7 @@ class LicenseListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): """ Overview of all available licenses """ + model = License permission_required = 'core.add_license' template_name = 'license/list.html' diff --git a/wger/core/views/misc.py b/wger/core/views/misc.py index 8abb98890..8a59a62dc 100644 --- a/wger/core/views/misc.py +++ b/wger/core/views/misc.py @@ -75,11 +75,8 @@ def demo_entries(request): return HttpResponseRedirect(reverse('software:features')) if ( - ( - (not request.user.is_authenticated or request.user.userprofile.is_temporary) - and not request.session['has_demo_data'] - ) - ): + not request.user.is_authenticated or request.user.userprofile.is_temporary + ) and not request.session['has_demo_data']: # If we reach this from a page that has no user created by the # middleware, do that now if not request.user.is_authenticated: @@ -96,7 +93,7 @@ def demo_entries(request): 'logs, (body) weight and nutrition plan entries so you can ' 'better see what this site can do. Feel free to edit or ' 'delete them!' - ) + ), ) return HttpResponseRedirect(reverse('core:dashboard')) diff --git a/wger/core/views/repetition_units.py b/wger/core/views/repetition_units.py index 03a532298..0f0698247 100644 --- a/wger/core/views/repetition_units.py +++ b/wger/core/views/repetition_units.py @@ -50,6 +50,7 @@ class ListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): """ Overview of all available setting units """ + model = RepetitionUnit permission_required = 'core.add_repetitionunit' template_name = 'repetition_unit/list.html' diff --git a/wger/core/views/user.py b/wger/core/views/user.py index 4a9a8cbea..c096741e4 100644 --- a/wger/core/views/user.py +++ b/wger/core/views/user.py @@ -113,7 +113,7 @@ def login(request): Small wrapper around the django login view """ - next_url = "?next=" + request.GET.get('next') if request.GET.get('next') else '' + next_url = '?next=' + request.GET.get('next') if request.GET.get('next') else '' form = UserLoginForm form.helper.form_action = reverse('core:user:login') + next_url @@ -135,12 +135,13 @@ def delete(request, user_pk=None): # Forbidden if the user has not enough rights, doesn't belong to the # gym or is an admin as well. General admins can delete all users. - if not request.user.has_perm('gym.manage_gyms') \ - and (not request.user.has_perm('gym.manage_gym') - or request.user.userprofile.gym_id != user.userprofile.gym_id - or user.has_perm('gym.manage_gym') - or user.has_perm('gym.gym_trainer') - or user.has_perm('gym.manage_gyms')): + if not request.user.has_perm('gym.manage_gyms') and ( + not request.user.has_perm('gym.manage_gym') + or request.user.userprofile.gym_id != user.userprofile.gym_id + or user.has_perm('gym.manage_gym') + or user.has_perm('gym.gym_trainer') + or user.has_perm('gym.manage_gyms') + ): return HttpResponseForbidden() else: user = request.user @@ -150,11 +151,9 @@ def delete(request, user_pk=None): if request.method == 'POST': form = PasswordConfirmationForm(data=request.POST, user=request.user) if form.is_valid(): - user.delete() messages.success( - request, - _('Account "{0}" was successfully deleted').format(user.username) + request, _('Account "{0}" was successfully deleted').format(user.username) ) if not user_pk: @@ -178,15 +177,15 @@ def trainer_login(request, user_pk): orig_user_pk = request.user.pk # No changing if identity is not set - if not request.user.has_perm('gym.gym_trainer') \ - and not request.session.get('trainer.identity'): + if not request.user.has_perm('gym.gym_trainer') and not request.session.get('trainer.identity'): return HttpResponseForbidden() # Changing between trainers or managers is not allowed - if request.user.has_perm('gym.gym_trainer') \ - and (user.has_perm('gym.gym_trainer') - or user.has_perm('gym.manage_gym') - or user.has_perm('gym.manage_gyms')): + if request.user.has_perm('gym.gym_trainer') and ( + user.has_perm('gym.gym_trainer') + or user.has_perm('gym.manage_gym') + or user.has_perm('gym.manage_gyms') + ): return HttpResponseForbidden() # Changing is only allowed between the same gym @@ -201,7 +200,8 @@ def trainer_login(request, user_pk): # Check if we're switching back to our original account own = False if ( - user.has_perm('gym.gym_trainer') or user.has_perm('gym.manage_gym') + user.has_perm('gym.gym_trainer') + or user.has_perm('gym.manage_gym') or user.has_perm('gym.manage_gyms') ): own = True @@ -209,7 +209,7 @@ def trainer_login(request, user_pk): # Note: when logging without authenticating, it is necessary to set the # authentication backend if own: - del (request.session['trainer.identity']) + del request.session['trainer.identity'] django_login(request, user, 'django.contrib.auth.backends.ModelBackend') if not own: @@ -248,8 +248,9 @@ def registration(request): template_data.update(csrf(request)) # Don't show captcha if the global parameter is false - FormClass = RegistrationForm if settings.WGER_SETTINGS['USE_RECAPTCHA'] \ - else RegistrationFormNoCaptcha + FormClass = ( + RegistrationForm if settings.WGER_SETTINGS['USE_RECAPTCHA'] else RegistrationFormNoCaptcha + ) # Redirect regular users, in case they reached the registration page if request.user.is_authenticated and not request.user.userprofile.is_temporary: @@ -313,7 +314,6 @@ def preferences(request): # Process the preferences form if request.method == 'POST': - form = UserPreferencesForm(data=request.POST, instance=request.user.userprofile) form.user = request.user @@ -325,7 +325,7 @@ def preferences(request): data = { 'first_name': request.user.first_name, 'last_name': request.user.last_name, - 'email': request.user.email + 'email': request.user.email, } form = UserPreferencesForm(initial=data, instance=request.user.userprofile) @@ -336,7 +336,6 @@ def preferences(request): email_form = UserPersonalInformationForm(data=request.POST, instance=request.user) if email_form.is_valid() and redirect: - # If the user changes the email, it is no longer verified if user_email != email_form.instance.email: logger.debug('resetting verified flag') @@ -366,6 +365,7 @@ class UserDeactivateView( """ Deactivates a user """ + permanent = False model = User permission_required = ('gym.manage_gym', 'gym.manage_gyms', 'gym.gym_trainer') @@ -379,8 +379,9 @@ class UserDeactivateView( if not request.user.is_authenticated: return HttpResponseForbidden() - if (request.user.has_perm('gym.manage_gym') or request.user.has_perm('gym.gym_trainer')) \ - and edit_user.userprofile.gym_id != request.user.userprofile.gym_id: + if ( + request.user.has_perm('gym.manage_gym') or request.user.has_perm('gym.gym_trainer') + ) and edit_user.userprofile.gym_id != request.user.userprofile.gym_id: return HttpResponseForbidden() return super(UserDeactivateView, self).dispatch(request, *args, **kwargs) @@ -401,6 +402,7 @@ class UserActivateView( """ Activates a previously deactivated user """ + permanent = False model = User permission_required = ('gym.manage_gym', 'gym.manage_gyms', 'gym.gym_trainer') @@ -414,8 +416,9 @@ class UserActivateView( if not request.user.is_authenticated: return HttpResponseForbidden() - if (request.user.has_perm('gym.manage_gym') or request.user.has_perm('gym.gym_trainer')) \ - and edit_user.userprofile.gym_id != request.user.userprofile.gym_id: + if ( + request.user.has_perm('gym.manage_gym') or request.user.has_perm('gym.gym_trainer') + ) and edit_user.userprofile.gym_id != request.user.userprofile.gym_id: return HttpResponseForbidden() return super(UserActivateView, self).dispatch(request, *args, **kwargs) @@ -454,9 +457,11 @@ class UserEditView( if not user.is_authenticated: return HttpResponseForbidden() - if user.has_perm('gym.manage_gym') \ - and not user.has_perm('gym.manage_gyms') \ - and user.userprofile.gym != self.get_object().userprofile.gym: + if ( + user.has_perm('gym.manage_gym') + and not user.has_perm('gym.manage_gyms') + and user.userprofile.gym != self.get_object().userprofile.gym + ): return HttpResponseForbidden() return super(UserEditView, self).dispatch(request, *args, **kwargs) @@ -502,6 +507,7 @@ class UserDetailView(LoginRequiredMixin, WgerMultiplePermissionRequiredMixin, De """ User overview for gyms """ + model = User permission_required = ('gym.manage_gym', 'gym.manage_gyms', 'gym.gym_trainer') template_name = 'user/overview.html' @@ -519,9 +525,11 @@ class UserDetailView(LoginRequiredMixin, WgerMultiplePermissionRequiredMixin, De if not user.is_authenticated: return HttpResponseForbidden() - if (user.has_perm('gym.manage_gym') or user.has_perm('gym.gym_trainer')) \ - and not user.has_perm('gym.manage_gyms') \ - and user.userprofile.gym != self.get_object().userprofile.gym: + if ( + (user.has_perm('gym.manage_gym') or user.has_perm('gym.gym_trainer')) + and not user.has_perm('gym.manage_gyms') + and user.userprofile.gym != self.get_object().userprofile.gym + ): return HttpResponseForbidden() return super(UserDetailView, self).dispatch(request, *args, **kwargs) @@ -539,14 +547,16 @@ class UserDetailView(LoginRequiredMixin, WgerMultiplePermissionRequiredMixin, De { 'workout': workout, 'logs': logs.dates('date', 'day').count(), - 'last_log': logs.last() + 'last_log': logs.last(), } ) context['workouts'] = out - context['weight_entries'] = WeightEntry.objects.filter(user=self.object) \ - .order_by('-date')[:5] - context['nutrition_plans'] = NutritionPlan.objects.filter(user=self.object) \ - .order_by('-creation_date')[:5] + context['weight_entries'] = WeightEntry.objects.filter(user=self.object).order_by('-date')[ + :5 + ] + context['nutrition_plans'] = NutritionPlan.objects.filter(user=self.object).order_by( + '-creation_date' + )[:5] context['session'] = WorkoutSession.objects.filter(user=self.object).order_by('-date')[:10] context['admin_notes'] = AdminUserNote.objects.filter(member=self.object)[:5] context['contracts'] = Contract.objects.filter(member=self.object)[:5] @@ -563,8 +573,9 @@ class UserListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): """ Overview of all users in the instance """ + model = User - permission_required = ('gym.manage_gyms', ) + permission_required = ('gym.manage_gyms',) template_name = 'user/list.html' def get_queryset(self): @@ -592,7 +603,7 @@ class UserListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): _('Last activity'), _('Gym'), ], - 'users': context['object_list']['members'] + 'users': context['object_list']['members'], } return context @@ -600,7 +611,7 @@ class UserListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): class WgerPasswordChangeView(PasswordChangeView): template_name = 'form.html' success_url = reverse_lazy('core:user:preferences') - title = gettext_lazy("Change password") + title = gettext_lazy('Change password') def get_form(self, form_class=None): form = super(WgerPasswordChangeView, self).get_form(form_class) @@ -611,8 +622,9 @@ class WgerPasswordChangeView(PasswordChangeView): Row( Column('new_password1', css_class='col-6'), Column('new_password2', css_class='col-6'), - css_class='form-row' - ), ButtonHolder(Submit('submit', _("Save"), css_class='btn-success btn-block')) + css_class='form-row', + ), + ButtonHolder(Submit('submit', _('Save'), css_class='btn-success btn-block')), ) return form @@ -627,7 +639,7 @@ class WgerPasswordResetView(PasswordResetView): form = super(WgerPasswordResetView, self).get_form(form_class) form.helper = FormHelper() form.helper.form_class = 'wger-form' - form.helper.add_input(Submit('submit', _("Save"), css_class='btn-success btn-block')) + form.helper.add_input(Submit('submit', _('Save'), css_class='btn-success btn-block')) return form @@ -639,7 +651,7 @@ class WgerPasswordResetConfirmView(PasswordResetConfirmView): form = super(WgerPasswordResetConfirmView, self).get_form(form_class) form.helper = FormHelper() form.helper.form_class = 'wger-form' - form.helper.add_input(Submit('submit', _("Save"), css_class='btn-success btn-block')) + form.helper.add_input(Submit('submit', _('Save'), css_class='btn-success btn-block')) return form @@ -648,8 +660,7 @@ def confirm_email(request): if not request.user.userprofile.email_verified: send_email(request.user) messages.success( - request, - _('A verification email was sent to %(email)s') % {'email': request.user.email} + request, _('A verification email was sent to %(email)s') % {'email': request.user.email} ) return HttpResponseRedirect(reverse('core:dashboard')) diff --git a/wger/core/views/weight_units.py b/wger/core/views/weight_units.py index a3587f0ba..6dd723537 100644 --- a/wger/core/views/weight_units.py +++ b/wger/core/views/weight_units.py @@ -50,6 +50,7 @@ class ListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): """ Overview of all available weight units """ + model = WeightUnit permission_required = 'core.add_weightunit' template_name = 'weight_unit/list.html' diff --git a/wger/exercises/api/endpoints.py b/wger/exercises/api/endpoints.py index 5dd966f0a..8c19119db 100644 --- a/wger/exercises/api/endpoints.py +++ b/wger/exercises/api/endpoints.py @@ -1,7 +1,7 @@ -EXERCISE_ENDPOINT = "exercisebaseinfo" -DELETION_LOG_ENDPOINT = "deletion-log" -CATEGORY_ENDPOINT = "exercisecategory" -MUSCLE_ENDPOINT = "muscle" -EQUIPMENT_ENDPOINT = "equipment" -IMAGE_ENDPOINT = "exerciseimage" -VIDEO_ENDPOINT = "video" +EXERCISE_ENDPOINT = 'exercisebaseinfo' +DELETION_LOG_ENDPOINT = 'deletion-log' +CATEGORY_ENDPOINT = 'exercisecategory' +MUSCLE_ENDPOINT = 'muscle' +EQUIPMENT_ENDPOINT = 'equipment' +IMAGE_ENDPOINT = 'exerciseimage' +VIDEO_ENDPOINT = 'video' diff --git a/wger/exercises/api/permissions.py b/wger/exercises/api/permissions.py index c54b7bafb..2523e195f 100644 --- a/wger/exercises/api/permissions.py +++ b/wger/exercises/api/permissions.py @@ -35,7 +35,6 @@ class CanContributeExercises(BasePermission): DELETE_METHODS = ['DELETE'] def has_permission(self, request, view): - # Everybody can read if request.method in self.SAFE_METHODS: return True @@ -46,9 +45,8 @@ class CanContributeExercises(BasePermission): # Creating or updating if request.method in self.ADD_METHODS: - return ( - request.user.userprofile.is_trustworthy - or request.user.has_perm('exercises.add_exercise') + return request.user.userprofile.is_trustworthy or request.user.has_perm( + 'exercises.add_exercise' ) # Only admins are allowed to delete entries diff --git a/wger/exercises/api/serializers.py b/wger/exercises/api/serializers.py index fe8d73f45..c9ef15538 100644 --- a/wger/exercises/api/serializers.py +++ b/wger/exercises/api/serializers.py @@ -88,6 +88,7 @@ class ExerciseImageSerializer(serializers.ModelSerializer): """ ExerciseImage serializer """ + author_history = serializers.ListSerializer(child=serializers.CharField(), read_only=True) exercise_base_uuid = serializers.ReadOnlyField(source='exercise_base.uuid') @@ -115,6 +116,7 @@ class ExerciseVideoSerializer(serializers.ModelSerializer): """ ExerciseVideo serializer """ + exercise_base_uuid = serializers.ReadOnlyField(source='exercise_base.uuid') author_history = serializers.ListSerializer(child=serializers.CharField(), read_only=True) @@ -147,6 +149,7 @@ class ExerciseVideoInfoSerializer(serializers.ModelSerializer): """ ExerciseVideo serializer for the info endpoint """ + author_history = serializers.ListSerializer(child=serializers.CharField(), read_only=True) class Meta: @@ -245,6 +248,7 @@ class MuscleSerializer(serializers.ModelSerializer): """ Muscle serializer """ + image_url_main = serializers.CharField() image_url_secondary = serializers.CharField() @@ -267,6 +271,7 @@ class ExerciseSerializer(serializers.ModelSerializer): The fields from the new ExerciseBase are retrieved here as to retain compatibility with the old model where all the fields where in Exercise. """ + category = serializers.PrimaryKeyRelatedField(queryset=ExerciseCategory.objects.all()) muscles = serializers.PrimaryKeyRelatedField(many=True, queryset=Muscle.objects.all()) muscles_secondary = serializers.PrimaryKeyRelatedField(many=True, queryset=Muscle.objects.all()) @@ -277,21 +282,21 @@ class ExerciseSerializer(serializers.ModelSerializer): class Meta: model = Exercise fields = ( - "id", - "uuid", - "name", - "exercise_base", - "description", - "created", - "category", - "muscles", - "muscles_secondary", - "equipment", - "language", - "license", - "license_author", - "variations", - "author_history", + 'id', + 'uuid', + 'name', + 'exercise_base', + 'description', + 'created', + 'category', + 'muscles', + 'muscles_secondary', + 'equipment', + 'language', + 'license', + 'license_author', + 'variations', + 'author_history', ) @@ -299,6 +304,7 @@ class ExerciseTranslationBaseInfoSerializer(serializers.ModelSerializer): """ Exercise translation serializer for the base info endpoint """ + id = serializers.IntegerField(required=False, read_only=True) uuid = serializers.UUIDField(required=False, read_only=True) exercise_base = serializers.PrimaryKeyRelatedField( @@ -312,22 +318,22 @@ class ExerciseTranslationBaseInfoSerializer(serializers.ModelSerializer): class Meta: model = Exercise fields = ( - "id", - "uuid", - "name", - "exercise_base", - "description", - "created", - "language", - "aliases", - "notes", - "license", - "license_title", - "license_object_url", - "license_author", - "license_author_url", - "license_derivative_source_url", - "author_history", + 'id', + 'uuid', + 'name', + 'exercise_base', + 'description', + 'created', + 'language', + 'aliases', + 'notes', + 'license', + 'license_title', + 'license_object_url', + 'license_author', + 'license_author_url', + 'license_derivative_source_url', + 'author_history', ) @@ -335,6 +341,7 @@ class ExerciseTranslationSerializer(serializers.ModelSerializer): """ Exercise translation serializer """ + id = serializers.IntegerField(required=False, read_only=True) uuid = serializers.UUIDField(required=False, read_only=True) exercise_base = serializers.PrimaryKeyRelatedField( @@ -345,13 +352,13 @@ class ExerciseTranslationSerializer(serializers.ModelSerializer): class Meta: model = Exercise fields = ( - "id", - "uuid", - "name", - "exercise_base", - "description", - "created", - "language", + 'id', + 'uuid', + 'name', + 'exercise_base', + 'description', + 'created', + 'language', 'license_author', ) @@ -402,25 +409,25 @@ class ExerciseInfoSerializer(serializers.ModelSerializer): model = Exercise depth = 1 fields = [ - "id", - "name", - "aliases", - "uuid", - "exercise_base_id", - "description", - "created", - "category", - "muscles", - "muscles_secondary", - "equipment", - "language", - "license", - "license_author", - "images", - "videos", - "comments", - "variations", - "author_history", + 'id', + 'name', + 'aliases', + 'uuid', + 'exercise_base_id', + 'description', + 'created', + 'category', + 'muscles', + 'muscles_secondary', + 'equipment', + 'language', + 'license', + 'license_author', + 'images', + 'videos', + 'comments', + 'variations', + 'author_history', ] @@ -445,24 +452,24 @@ class ExerciseBaseInfoSerializer(serializers.ModelSerializer): model = ExerciseBase depth = 1 fields = [ - "id", - "uuid", - "created", - "last_update", - "last_update_global", - "category", - "muscles", - "muscles_secondary", - "equipment", - "license", - "license_author", - "images", - "exercises", - "variations", - "images", - "videos", - "author_history", - "total_authors_history", + 'id', + 'uuid', + 'created', + 'last_update', + 'last_update_global', + 'category', + 'muscles', + 'muscles_secondary', + 'equipment', + 'license', + 'license_author', + 'images', + 'exercises', + 'variations', + 'images', + 'videos', + 'author_history', + 'total_authors_history', ] def to_representation(self, instance): diff --git a/wger/exercises/api/views.py b/wger/exercises/api/views.py index 322fca10b..d7e5b040f 100644 --- a/wger/exercises/api/views.py +++ b/wger/exercises/api/views.py @@ -99,9 +99,10 @@ class ExerciseBaseViewSet(ModelViewSet): For a read-only endpoint with all the information of an exercise, see /api/v2/exercisebaseinfo/ """ + queryset = ExerciseBase.translations.all() serializer_class = ExerciseBaseSerializer - permission_classes = (CanContributeExercises, ) + permission_classes = (CanContributeExercises,) ordering_fields = '__all__' filterset_fields = ( 'category', @@ -148,8 +149,9 @@ class ExerciseTranslationViewSet(ModelViewSet): """ API endpoint for editing or adding exercise translation objects. """ + queryset = Exercise.objects.all() - permission_classes = (CanContributeExercises, ) + permission_classes = (CanContributeExercises,) serializer_class = ExerciseTranslationSerializer ordering_fields = '__all__' filterset_fields = ( @@ -171,7 +173,7 @@ class ExerciseTranslationViewSet(ModelViewSet): tags=HTML_TAG_WHITELIST, attributes=HTML_ATTRIBUTES_WHITELIST, css_sanitizer=CSSSanitizer(allowed_css_properties=HTML_STYLES_WHITELIST), - strip=True + strip=True, ) super().perform_create(serializer) @@ -200,7 +202,7 @@ class ExerciseTranslationViewSet(ModelViewSet): tags=HTML_TAG_WHITELIST, attributes=HTML_ATTRIBUTES_WHITELIST, css_sanitizer=CSSSanitizer(allowed_css_properties=HTML_STYLES_WHITELIST), - strip=True + strip=True, ) super().perform_update(serializer) @@ -217,8 +219,9 @@ class ExerciseViewSet(viewsets.ReadOnlyModelViewSet): This is only kept for backwards compatibility and will be removed in the future """ + queryset = Exercise.objects.all() - permission_classes = (CanContributeExercises, ) + permission_classes = (CanContributeExercises,) serializer_class = ExerciseSerializer ordering_fields = '__all__' filterset_fields = ( @@ -257,13 +260,13 @@ class ExerciseViewSet(viewsets.ReadOnlyModelViewSet): try: qs = qs.filter(exercise_base__category_id=int(category)) except ValueError: - logger.info(f"Got {category} as category ID") + logger.info(f'Got {category} as category ID') if muscles: try: qs = qs.filter(exercise_base__muscles__in=[int(m) for m in muscles.split(',')]) except ValueError: - logger.info(f"Got {muscles} as muscle IDs") + logger.info(f'Got {muscles} as muscle IDs') if muscles_secondary: try: @@ -276,13 +279,13 @@ class ExerciseViewSet(viewsets.ReadOnlyModelViewSet): try: qs = qs.filter(exercise_base__equipment__in=[int(e) for e in equipment.split(',')]) except ValueError: - logger.info(f"Got {equipment} as equipment IDs") + logger.info(f'Got {equipment} as equipment IDs') if license: try: qs = qs.filter(exercise_base__license_id=int(license)) except ValueError: - logger.info(f"Got {license} as license ID") + logger.info(f'Got {license} as license ID') return qs @@ -306,14 +309,11 @@ class ExerciseViewSet(viewsets.ReadOnlyModelViewSet): ], # yapf: disable responses={ - 200: - inline_serializer( + 200: inline_serializer( name='ExerciseSearchResponse', fields={ - 'value': - CharField(), - 'data': - inline_serializer( + 'value': CharField(), + 'data': inline_serializer( name='ExerciseSearchItemResponse', fields={ 'id': IntegerField(), @@ -321,12 +321,12 @@ class ExerciseViewSet(viewsets.ReadOnlyModelViewSet): 'name': CharField(), 'category': CharField(), 'image': CharField(), - 'image_thumbnail': CharField() - } - ) - } + 'image_thumbnail': CharField(), + }, + ), + }, ) - } + }, # yapf: enable ) @api_view(['GET']) @@ -345,11 +345,12 @@ def search(request): return Response(response) languages = [load_language(l) for l in language_codes.split(',')] - translations = Exercise.objects \ - .filter(Q(name__icontains=q) | Q(alias__alias__icontains=q)) \ - .filter(language__in=languages) \ - .order_by('exercise_base__category__name', 'name') \ + translations = ( + Exercise.objects.filter(Q(name__icontains=q) | Q(alias__alias__icontains=q)) + .filter(language__in=languages) + .order_by('exercise_base__category__name', 'name') .distinct() + ) for translation in translations: image = None @@ -372,8 +373,8 @@ def search(request): 'name': translation.name, 'category': _(translation.category.name), 'image': image, - 'image_thumbnail': thumbnail - } + 'image_thumbnail': thumbnail, + }, } results.append(result_json) response['suggestions'] = results @@ -436,10 +437,11 @@ class EquipmentViewSet(viewsets.ReadOnlyModelViewSet): """ API endpoint for equipment objects """ + queryset = Equipment.objects.all() serializer_class = EquipmentSerializer ordering_fields = '__all__' - filterset_fields = ('name', ) + filterset_fields = ('name',) @method_decorator(cache_page(settings.WGER_SETTINGS['EXERCISE_CACHE_TTL'])) def dispatch(self, request, *args, **kwargs): @@ -454,20 +456,22 @@ class DeletionLogViewSet(viewsets.ReadOnlyModelViewSet): as well when performing a sync (e.g. because many exercises where submitted at once or an image was uploaded that hasn't a CC license) """ + queryset = DeletionLog.objects.all() serializer_class = DeletionLogSerializer ordering_fields = '__all__' - filterset_fields = ('model_type', ) + filterset_fields = ('model_type',) class ExerciseCategoryViewSet(viewsets.ReadOnlyModelViewSet): """ API endpoint for exercise categories objects """ + queryset = ExerciseCategory.objects.all() serializer_class = ExerciseCategorySerializer ordering_fields = '__all__' - filterset_fields = ('name', ) + filterset_fields = ('name',) @method_decorator(cache_page(settings.WGER_SETTINGS['EXERCISE_CACHE_TTL'])) def dispatch(self, request, *args, **kwargs): @@ -481,7 +485,7 @@ class ExerciseImageViewSet(ModelViewSet): queryset = ExerciseImage.objects.all() serializer_class = ExerciseImageSerializer - permission_classes = (CanContributeExercises, ) + permission_classes = (CanContributeExercises,) ordering_fields = '__all__' filterset_fields = ( 'is_main', @@ -509,7 +513,7 @@ class ExerciseImageViewSet(ModelViewSet): t = get_thumbnailer(image.image) thumbnails[alias] = { 'url': t.get_thumbnail(aliases.get(alias)).url, - 'settings': aliases.get(alias) + 'settings': aliases.get(alias), } thumbnails['original'] = image.image.url return Response(thumbnails) @@ -541,9 +545,10 @@ class ExerciseVideoViewSet(ModelViewSet): """ API endpoint for exercise video objects """ + queryset = ExerciseVideo.objects.all() serializer_class = ExerciseVideoSerializer - permission_classes = (CanContributeExercises, ) + permission_classes = (CanContributeExercises,) ordering_fields = '__all__' filterset_fields = ( 'is_main', @@ -579,8 +584,9 @@ class ExerciseCommentViewSet(ModelViewSet): """ API endpoint for exercise comment objects """ + serializer_class = ExerciseCommentSerializer - permission_classes = (CanContributeExercises, ) + permission_classes = (CanContributeExercises,) ordering_fields = '__all__' filterset_fields = ('comment', 'exercise') @@ -620,9 +626,10 @@ class ExerciseAliasViewSet(ModelViewSet): """ API endpoint for exercise aliases objects """ + serializer_class = ExerciseAliasSerializer queryset = Alias.objects.all() - permission_classes = (CanContributeExercises, ) + permission_classes = (CanContributeExercises,) ordering_fields = '__all__' filterset_fields = ('alias', 'exercise') @@ -653,15 +660,17 @@ class ExerciseVariationViewSet(ModelViewSet): """ API endpoint for exercise variation objects """ + serializer_class = ExerciseVariationSerializer queryset = Variation.objects.all() - permission_classes = (CanContributeExercises, ) + permission_classes = (CanContributeExercises,) class MuscleViewSet(viewsets.ReadOnlyModelViewSet): """ API endpoint for muscle objects """ + queryset = Muscle.objects.all() serializer_class = MuscleSerializer ordering_fields = '__all__' diff --git a/wger/exercises/apps.py b/wger/exercises/apps.py index dbd7b6f61..72a99b71d 100644 --- a/wger/exercises/apps.py +++ b/wger/exercises/apps.py @@ -20,12 +20,13 @@ from django.apps import AppConfig class ExerciseConfig(AppConfig): name = 'wger.exercises' - verbose_name = "Exercise" + verbose_name = 'Exercise' def ready(self): import wger.exercises.signals from actstream import registry + registry.register(self.get_model('Alias')) registry.register(self.get_model('Exercise')) registry.register(self.get_model('ExerciseBase')) diff --git a/wger/exercises/forms.py b/wger/exercises/forms.py index 3b8fa699a..c945071e7 100644 --- a/wger/exercises/forms.py +++ b/wger/exercises/forms.py @@ -26,7 +26,6 @@ from wger.exercises.models import ( class ExerciseImageForm(forms.ModelForm): - class Meta: model = ExerciseImage fields = ( @@ -39,7 +38,6 @@ class ExerciseImageForm(forms.ModelForm): class ExerciseVideoForm(forms.ModelForm): - class Meta: model = ExerciseVideo fields = ( @@ -50,7 +48,6 @@ class ExerciseVideoForm(forms.ModelForm): class CommentForm(forms.ModelForm): - class Meta: model = ExerciseComment - exclude = ('exercise', ) + exclude = ('exercise',) diff --git a/wger/exercises/management/commands/change-exercise-author.py b/wger/exercises/management/commands/change-exercise-author.py index f65579f46..029270eec 100644 --- a/wger/exercises/management/commands/change-exercise-author.py +++ b/wger/exercises/management/commands/change-exercise-author.py @@ -40,7 +40,7 @@ class Command(BaseCommand): '--exercise-base-id', action='store', dest='exercise_base_id', - help='The ID of the exercise base' + help='The ID of the exercise base', ) parser.add_argument( '--exercise-id', action='store', dest='exercise_id', help='The ID of the exercise' @@ -77,7 +77,7 @@ class Command(BaseCommand): exercise.license_author = author_name exercise.save() - self.stdout.write(self.style.SUCCESS(f"Exercise and/or exercise base has been updated")) + self.stdout.write(self.style.SUCCESS(f'Exercise and/or exercise base has been updated')) def print_error(self, error_message): - self.stdout.write(self.style.WARNING(f"{error_message}")) + self.stdout.write(self.style.WARNING(f'{error_message}')) diff --git a/wger/exercises/management/commands/delete-unused-exercises.py b/wger/exercises/management/commands/delete-unused-exercises.py index 0f40b5783..678f64d2a 100644 --- a/wger/exercises/management/commands/delete-unused-exercises.py +++ b/wger/exercises/management/commands/delete-unused-exercises.py @@ -38,7 +38,6 @@ class Command(BaseCommand): """ def handle(self, **options): - # Collect all exercise bases that are not used in any workout or log entry out = f'{ExerciseBase.objects.all().count()} exercises currently in the database' self.stdout.write(out) diff --git a/wger/exercises/management/commands/download-exercise-images.py b/wger/exercises/management/commands/download-exercise-images.py index 43a3d9134..b51865830 100644 --- a/wger/exercises/management/commands/download-exercise-images.py +++ b/wger/exercises/management/commands/download-exercise-images.py @@ -52,11 +52,10 @@ class Command(BaseCommand): dest='remote_url', default=settings.WGER_SETTINGS['WGER_INSTANCE'], help=f'Remote URL to fetch the images from (default: WGER_SETTINGS' - f'["WGER_INSTANCE"] - {settings.WGER_SETTINGS["WGER_INSTANCE"]})' + f'["WGER_INSTANCE"] - {settings.WGER_SETTINGS["WGER_INSTANCE"]})', ) def handle(self, **options): - if not settings.MEDIA_ROOT: raise ImproperlyConfigured('Please set MEDIA_ROOT in your settings file') diff --git a/wger/exercises/management/commands/download-exercise-videos.py b/wger/exercises/management/commands/download-exercise-videos.py index 3aa5bc4a8..ed0b95f03 100644 --- a/wger/exercises/management/commands/download-exercise-videos.py +++ b/wger/exercises/management/commands/download-exercise-videos.py @@ -44,12 +44,10 @@ class Command(BaseCommand): action='store', dest='remote_url', default='https://wger.de', - help='Remote URL to fetch the exercises from (default: ' - 'https://wger.de)' + help='Remote URL to fetch the exercises from (default: ' 'https://wger.de)', ) def handle(self, **options): - if not settings.MEDIA_ROOT: raise ImproperlyConfigured('Please set MEDIA_ROOT in your settings file') diff --git a/wger/exercises/management/commands/exercise-cleanup.py b/wger/exercises/management/commands/exercise-cleanup.py index d394e97a6..c34d125c0 100755 --- a/wger/exercises/management/commands/exercise-cleanup.py +++ b/wger/exercises/management/commands/exercise-cleanup.py @@ -40,13 +40,12 @@ class Command(BaseCommand): languages = Language.objects.all() for base in ExerciseBase.objects.all(): - data = { 'base': { 'uuid': base.uuid, 'category': base.category.name, 'equipment': ','.join([e.name for e in base.equipment.all()]), - 'variations': base.variations.id if base.variations else '' + 'variations': base.variations.id if base.variations else '', } } @@ -57,7 +56,7 @@ class Command(BaseCommand): 'description': '', 'aliases': '', 'license': '', - 'author': '' + 'author': '', } exercise = Exercise.objects.filter(exercise_base=base, language=language).first() @@ -73,7 +72,9 @@ class Command(BaseCommand): out.append(data) with open('exercise_cleanup.csv', 'w', newline='') as csvfile: - file_writer = csv.writer(csvfile, ) + file_writer = csv.writer( + csvfile, + ) header = ['base:uuid', 'base:category', 'base:equipment', 'base:variations'] for language in languages: diff --git a/wger/exercises/management/commands/exercises-health-check.py b/wger/exercises/management/commands/exercises-health-check.py index 0bac772d0..c27dd224f 100644 --- a/wger/exercises/management/commands/exercises-health-check.py +++ b/wger/exercises/management/commands/exercises-health-check.py @@ -29,14 +29,17 @@ class Command(BaseCommand): """ Performs some sanity checks on the exercise database """ + english: Language - help = "Performs some sanity checks on the exercise database. " \ - "At the moment this script checks that each exercise:\n" \ - "- has at least one translation\n" \ - "- has a translation in English\n" \ - "- has no duplicate translations\n\n" \ - "Each problem can be fixed individually by using the --delete-* flags\n" + help = ( + 'Performs some sanity checks on the exercise database. ' + 'At the moment this script checks that each exercise:\n' + '- has at least one translation\n' + '- has a translation in English\n' + '- has no duplicate translations\n\n' + 'Each problem can be fixed individually by using the --delete-* flags\n' + ) def create_parser(self, *args, **kwargs): parser = super(Command, self).create_parser(*args, **kwargs) @@ -44,14 +47,13 @@ class Command(BaseCommand): return parser def add_arguments(self, parser): - parser.add_argument( '--delete-untranslated', action='store_true', dest='delete_untranslated', default=False, help="Delete exercises without translations (safe to use since these can't be " - "accessed over the UI)", + 'accessed over the UI)', ) parser.add_argument( @@ -80,7 +82,6 @@ class Command(BaseCommand): ) def handle(self, **options): - delete_untranslated = options['delete_untranslated'] or options['delete_all'] delete_duplicates = options['delete_duplicates'] or options['delete_all'] delete_no_english = options['delete_no_english'] or options['delete_all'] @@ -120,7 +121,8 @@ class Command(BaseCommand): exercise_languages = base.exercises.values_list('language', flat=True) duplicates = [ Language.objects.get(pk=item) - for item, count in collections.Counter(exercise_languages).items() if count > 1 + for item, count in collections.Counter(exercise_languages).items() + if count > 1 ] if not duplicates: diff --git a/wger/exercises/management/commands/read-exercise-cleanup.py b/wger/exercises/management/commands/read-exercise-cleanup.py index eacc3b4c9..815d3736b 100644 --- a/wger/exercises/management/commands/read-exercise-cleanup.py +++ b/wger/exercises/management/commands/read-exercise-cleanup.py @@ -63,7 +63,7 @@ class Command(BaseCommand): action='store_true', dest='process_videos', default=False, - help='Flag indicating whether to process and add videos to the exercises' + help='Flag indicating whether to process and add videos to the exercises', ) parser.add_argument( @@ -71,7 +71,7 @@ class Command(BaseCommand): action='store_true', dest='create_on_new', default=True, - help="Controls whether we create new bases or exercises if they have the UUID 'NEW'" + help="Controls whether we create new bases or exercises if they have the UUID 'NEW'", ) def handle(self, **options): @@ -91,8 +91,9 @@ class Command(BaseCommand): for language in [l.short_name for l in languages]: for column in columns: name = '{0}:{1}'.format(language, column) - assert (name in file_reader.fieldnames - ), '{0} not in {1}'.format(name, file_reader.fieldnames) + assert name in file_reader.fieldnames, '{0} not in {1}'.format( + name, file_reader.fieldnames + ) default_license = License.objects.get(pk=CC_BY_SA_4_ID) @@ -121,10 +122,14 @@ class Command(BaseCommand): self.stdout.write(f' Skipping creating new exercise base...\n') continue - base = ExerciseBase.objects.get_or_create( - uuid=base_uuid, - defaults={'category': ExerciseCategory.objects.get(name=base_category)} - )[0] if not new_base else ExerciseBase() + base = ( + ExerciseBase.objects.get_or_create( + uuid=base_uuid, + defaults={'category': ExerciseCategory.objects.get(name=base_category)}, + )[0] + if not new_base + else ExerciseBase() + ) # Update the base data base.category = ExerciseCategory.objects.get(name=base_category) @@ -200,12 +205,13 @@ class Command(BaseCommand): if not new_translation: continue - translation = Exercise.objects.get_or_create( - uuid=exercise_uuid, defaults={ - 'exercise_base': base, - 'language': language - } - )[0] if not new_translation else Exercise() + translation = ( + Exercise.objects.get_or_create( + uuid=exercise_uuid, defaults={'exercise_base': base, 'language': language} + )[0] + if not new_translation + else Exercise() + ) translation.exercise_base = base translation.language = language translation.name = exercise_name @@ -218,8 +224,9 @@ class Command(BaseCommand): exercise_license = License.objects.get(short_name=exercise_license) except License.DoesNotExist: self.stdout.write( - self.style. - WARNING(f' License does not exist: {exercise_license}!!!\n') + self.style.WARNING( + f' License does not exist: {exercise_license}!!!\n' + ) ) exercise_license = default_license else: diff --git a/wger/exercises/management/commands/submitted-exercises.py b/wger/exercises/management/commands/submitted-exercises.py index ac7582f13..1f921d545 100644 --- a/wger/exercises/management/commands/submitted-exercises.py +++ b/wger/exercises/management/commands/submitted-exercises.py @@ -29,7 +29,6 @@ class Command(BaseCommand): help = 'Read out the user submitted exercise' def handle(self, **options): - exercises = Exercise.objects.all() usernames = [] for exercise in exercises: diff --git a/wger/exercises/management/commands/sync-exercises.py b/wger/exercises/management/commands/sync-exercises.py index 6d87c314e..a49838f77 100644 --- a/wger/exercises/management/commands/sync-exercises.py +++ b/wger/exercises/management/commands/sync-exercises.py @@ -37,6 +37,7 @@ class Command(BaseCommand): """ Synchronizes exercise data from a wger instance to the local database """ + remote_url = settings.WGER_SETTINGS['WGER_INSTANCE'] help = """Synchronizes exercise data from a wger instance to the local database. @@ -58,7 +59,7 @@ class Command(BaseCommand): dest='remote_url', default=settings.WGER_SETTINGS['WGER_INSTANCE'], help=f'Remote URL to fetch the exercises from (default: WGER_SETTINGS' - f'["WGER_INSTANCE"] - {settings.WGER_SETTINGS["WGER_INSTANCE"]})' + f'["WGER_INSTANCE"] - {settings.WGER_SETTINGS["WGER_INSTANCE"]})', ) parser.add_argument( @@ -66,11 +67,10 @@ class Command(BaseCommand): action='store_true', dest='skip_delete', default=False, - help='Skips deleting any entries' + help='Skips deleting any entries', ) def handle(self, **options): - remote_url = options['remote_url'] try: diff --git a/wger/exercises/management/commands/warmup-exercise-api-cache.py b/wger/exercises/management/commands/warmup-exercise-api-cache.py index 3b5a4b1fd..1434907fa 100644 --- a/wger/exercises/management/commands/warmup-exercise-api-cache.py +++ b/wger/exercises/management/commands/warmup-exercise-api-cache.py @@ -31,7 +31,7 @@ class Command(BaseCommand): '--exercise-base-id', action='store', dest='exercise_base_id', - help='The ID of the exercise base, otherwise all exercises will be updated' + help='The ID of the exercise base, otherwise all exercises will be updated', ) parser.add_argument( @@ -39,7 +39,7 @@ class Command(BaseCommand): action='store_true', dest='force', default=False, - help='Force the update of the cache' + help='Force the update of the cache', ) def handle(self, **options): @@ -56,9 +56,9 @@ class Command(BaseCommand): def handle_cache(self, exercise: ExerciseBase, force: bool): if force: - self.stdout.write(f"Force updating cache for exercise base {exercise.uuid}") + self.stdout.write(f'Force updating cache for exercise base {exercise.uuid}') else: - self.stdout.write(f"Warming cache for exercise base {exercise.uuid}") + self.stdout.write(f'Warming cache for exercise base {exercise.uuid}') if force: reset_exercise_api_cache(exercise.uuid) diff --git a/wger/exercises/migrations/0001_initial.py b/wger/exercises/migrations/0001_initial.py index 616ab8ebe..b711607cf 100644 --- a/wger/exercises/migrations/0001_initial.py +++ b/wger/exercises/migrations/0001_initial.py @@ -6,7 +6,6 @@ import wger.exercises.models class Migration(migrations.Migration): - dependencies = [ ('core', '0001_initial'), ] @@ -19,14 +18,14 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ('name', models.CharField(max_length=50, verbose_name='Name')), ], options={ 'ordering': ['name'], }, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.CreateModel( name='Exercise', @@ -35,18 +34,17 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ( 'license_author', models.CharField( - help_text= - 'If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', + help_text='If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', max_length=50, null=True, verbose_name='Author', - blank=True - ) + blank=True, + ), ), ( 'status', @@ -54,27 +52,27 @@ class Migration(migrations.Migration): default=b'1', max_length=2, editable=False, - choices=[(b'1', 'Pending'), (b'2', 'Accepted'), (b'3', 'Declined')] - ) + choices=[(b'1', 'Pending'), (b'2', 'Accepted'), (b'3', 'Declined')], + ), ), ( 'description', models.TextField( max_length=2000, verbose_name='Description', - validators=[django.core.validators.MinLengthValidator(40)] - ) + validators=[django.core.validators.MinLengthValidator(40)], + ), ), ('name', models.CharField(max_length=200, verbose_name='Name')), ( 'creation_date', - models.DateField(auto_now_add=True, verbose_name='Date', null=True) + models.DateField(auto_now_add=True, verbose_name='Date', null=True), ), ], options={ 'ordering': ['name'], }, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.CreateModel( name='ExerciseCategory', @@ -83,7 +81,7 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ('name', models.CharField(max_length=100, verbose_name='Name')), ], @@ -91,7 +89,7 @@ class Migration(migrations.Migration): 'ordering': ['name'], 'verbose_name_plural': 'Exercise Categories', }, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.CreateModel( name='ExerciseComment', @@ -100,15 +98,15 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ( 'comment', models.CharField( help_text='A comment about how to correctly do this exercise.', max_length=200, - verbose_name='Comment' - ) + verbose_name='Comment', + ), ), ( 'exercise', @@ -116,12 +114,12 @@ class Migration(migrations.Migration): editable=False, to='exercises.Exercise', verbose_name='Exercise', - on_delete=models.CASCADE - ) + on_delete=models.CASCADE, + ), ), ], options={}, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.CreateModel( name='ExerciseImage', @@ -130,18 +128,17 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ( 'license_author', models.CharField( - help_text= - 'If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', + help_text='If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', max_length=50, null=True, verbose_name='Author', - blank=True - ) + blank=True, + ), ), ( 'status', @@ -149,31 +146,30 @@ class Migration(migrations.Migration): default=b'1', max_length=2, editable=False, - choices=[(b'1', 'Pending'), (b'2', 'Accepted'), (b'3', 'Declined')] - ) + choices=[(b'1', 'Pending'), (b'2', 'Accepted'), (b'3', 'Declined')], + ), ), ( 'image', models.ImageField( help_text='Only PNG and JPEG formats are supported', upload_to=wger.exercises.models.image.exercise_image_upload_dir, - verbose_name='Image' - ) + verbose_name='Image', + ), ), ( 'is_main', models.BooleanField( default=False, - help_text= - 'Tick the box if you want to set this image as the main one for the exercise (will be shown e.g. in the search). The first image is automatically marked by the system.', - verbose_name='Is main picture' - ) + help_text='Tick the box if you want to set this image as the main one for the exercise (will be shown e.g. in the search). The first image is automatically marked by the system.', + verbose_name='Is main picture', + ), ), ( 'exercise', models.ForeignKey( verbose_name='Exercise', to='exercises.Exercise', on_delete=models.CASCADE - ) + ), ), ( 'license', @@ -181,14 +177,14 @@ class Migration(migrations.Migration): default=2, verbose_name='License', to='core.License', - on_delete=models.CASCADE - ) + on_delete=models.CASCADE, + ), ), ], options={ 'ordering': ['-is_main', 'id'], }, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.CreateModel( name='Muscle', @@ -197,22 +193,22 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ( 'name', models.CharField( help_text='In latin, e.g. "Pectoralis major"', max_length=50, - verbose_name='Name' - ) + verbose_name='Name', + ), ), ('is_front', models.BooleanField(default=1)), ], options={ 'ordering': ['name'], }, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.AddField( model_name='exercise', @@ -262,7 +258,7 @@ class Migration(migrations.Migration): null=True, verbose_name='Secondary muscles', to='exercises.Muscle', - blank=True + blank=True, ), preserve_default=True, ), diff --git a/wger/exercises/migrations/0002_auto_20150307_1841.py b/wger/exercises/migrations/0002_auto_20150307_1841.py index 96ef2a283..5ecf622fc 100644 --- a/wger/exercises/migrations/0002_auto_20150307_1841.py +++ b/wger/exercises/migrations/0002_auto_20150307_1841.py @@ -11,14 +11,13 @@ def generate_uuids(apps, schema_editor): :param schema_editor: :return: """ - Excercise = apps.get_model("exercises", "Exercise") + Excercise = apps.get_model('exercises', 'Exercise') for exercise in Excercise.objects.all(): exercise.uuid = uuid.uuid4() exercise.save() class Migration(migrations.Migration): - dependencies = [ ('exercises', '0001_initial'), ] diff --git a/wger/exercises/migrations/0003_auto_20160921_2000.py b/wger/exercises/migrations/0003_auto_20160921_2000.py index 9022a5229..086ef9818 100644 --- a/wger/exercises/migrations/0003_auto_20160921_2000.py +++ b/wger/exercises/migrations/0003_auto_20160921_2000.py @@ -8,7 +8,7 @@ def copy_name(apps, schema_editor): """ Copies the exercise name to the original name field """ - Excercise = apps.get_model("exercises", "Exercise") + Excercise = apps.get_model('exercises', 'Exercise') for exercise in Excercise.objects.all(): exercise.name_original = exercise.name exercise.save() @@ -31,14 +31,13 @@ def capitalize_name(apps, schema_editor): out.append(word) return ' '.join(out) - Excercise = apps.get_model("exercises", "Exercise") + Excercise = apps.get_model('exercises', 'Exercise') for exercise in Excercise.objects.all(): exercise.name = capitalize(exercise.name_original) exercise.save() class Migration(migrations.Migration): - dependencies = [ ('exercises', '0002_auto_20150307_1841'), ] diff --git a/wger/exercises/migrations/0004_auto_20170404_0114.py b/wger/exercises/migrations/0004_auto_20170404_0114.py index 75f2c63ab..1a193c9fa 100644 --- a/wger/exercises/migrations/0004_auto_20170404_0114.py +++ b/wger/exercises/migrations/0004_auto_20170404_0114.py @@ -6,7 +6,6 @@ import uuid class Migration(migrations.Migration): - dependencies = [ ('exercises', '0003_auto_20160921_2000'), ] @@ -33,7 +32,7 @@ class Migration(migrations.Migration): blank=True, related_name='secondary_muscles', to='exercises.Muscle', - verbose_name='Secondary muscles' + verbose_name='Secondary muscles', ), ), migrations.AlterField( @@ -43,7 +42,7 @@ class Migration(migrations.Migration): choices=[('1', 'Pending'), ('2', 'Accepted'), ('3', 'Declined')], default='1', editable=False, - max_length=2 + max_length=2, ), ), migrations.AlterField( @@ -56,9 +55,8 @@ class Migration(migrations.Migration): name='is_main', field=models.BooleanField( default=False, - help_text= - 'Tick the box if you want to set this image as the main one for the exercise (will be shown e.g. in the search). The first image is automatically marked by the system.', - verbose_name='Main picture' + help_text='Tick the box if you want to set this image as the main one for the exercise (will be shown e.g. in the search). The first image is automatically marked by the system.', + verbose_name='Main picture', ), ), migrations.AlterField( @@ -68,7 +66,7 @@ class Migration(migrations.Migration): choices=[('1', 'Pending'), ('2', 'Accepted'), ('3', 'Declined')], default='1', editable=False, - max_length=2 + max_length=2, ), ), ] diff --git a/wger/exercises/migrations/0005_auto_20190618_1617.py b/wger/exercises/migrations/0005_auto_20190618_1617.py index d4245c269..a4b49f285 100644 --- a/wger/exercises/migrations/0005_auto_20190618_1617.py +++ b/wger/exercises/migrations/0005_auto_20190618_1617.py @@ -5,7 +5,6 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ ('exercises', '0004_auto_20170404_0114'), ] @@ -13,16 +12,10 @@ class Migration(migrations.Migration): operations = [ migrations.AlterModelOptions( name='exercise', - options={ - 'base_manager_name': 'objects', - 'ordering': ['name'] - }, + options={'base_manager_name': 'objects', 'ordering': ['name']}, ), migrations.AlterModelOptions( name='exerciseimage', - options={ - 'base_manager_name': 'objects', - 'ordering': ['-is_main', 'id'] - }, + options={'base_manager_name': 'objects', 'ordering': ['-is_main', 'id']}, ), ] diff --git a/wger/exercises/migrations/0006_auto_20201203_0203.py b/wger/exercises/migrations/0006_auto_20201203_0203.py index 4ad8ab868..0e032c088 100644 --- a/wger/exercises/migrations/0006_auto_20201203_0203.py +++ b/wger/exercises/migrations/0006_auto_20201203_0203.py @@ -5,7 +5,6 @@ import django.db.models.deletion class Migration(migrations.Migration): - dependencies = [ ('exercises', '0005_auto_20190618_1617'), ] @@ -18,7 +17,7 @@ class Migration(migrations.Migration): 'id', models.AutoField( auto_created=True, primary_key=True, serialize=False, verbose_name='ID' - ) + ), ), ], ), @@ -30,7 +29,7 @@ class Migration(migrations.Migration): null=True, on_delete=django.db.models.deletion.CASCADE, to='exercises.variation', - verbose_name='Variations' + verbose_name='Variations', ), ), ] diff --git a/wger/exercises/migrations/0007_auto_20201203_1042.py b/wger/exercises/migrations/0007_auto_20201203_1042.py index fb06b53e4..f02b6833d 100644 --- a/wger/exercises/migrations/0007_auto_20201203_1042.py +++ b/wger/exercises/migrations/0007_auto_20201203_1042.py @@ -6,113 +6,77 @@ exercise_variation_ids = [ # # exercises in English # - # Rows [106, 108, 109, 110, 142, 202, 214, 339, 340, 362, 412, 670], - # Lat Pulldowns [187, 188, 204, 212, 213, 215, 216, 424], - # Deadlifts [105, 161, 209, 328, 351, 381], - # Shoulder Raises [148, 149, 233, 237, 306, 421], - # "Shoulder Press" [119, 123, 152, 155, 190, 227, 228, 229, 329], - # "Calf Raises" [102, 103, 104, 776], - # "Bench Press" [100, 101, 163, 192, 210, 211, 270, 399], - # "Pushups" [168, 182, 260, 302, 790], - # "Chest Fly" [122, 145, 146, 206], - # "Crunches" [91, 92, 93, 94, 176, 416, 95, 170], - # "Kicks" [303, 631, 125, 126, 166], - # "Squats" [111, 160, 185, 191, 300, 342, 346, 355, 387, 389, 407, 650, 795], - # "Lunges" [112, 113, 346, 405], - # "Leg Curls" [117, 118, 154, 792], - # "Leg Press" [114, 115, 130, 788], - # "Bicep Curls" [74, 80, 81, 86, 129, 138, 193, 205, 208, 275, 298, 305, 768], - # "Tricep Extensions" [89, 90, 274, 344], - # "Tricep Presses" [84, 85, 88, 186, 217, 218, 386], - # "Dips" [82, 83, 162, 360], - # # exercises in German # - # Bizeps Curls [44, 26, 242, 24, 3, 815, 222], - # Dips [29, 68], - # French press [58, 25], - # Hammercurls [46, 134], - # Beinpresse [6, 54], - # Beinstrecker [39, 69], - # Kniebeuge [358, 390, 7, 402, 200, 762, 707], - # Beinheben [35, 34], - # Crunches [4, 33, 51, 32, 56], - # Plank [417, 712], - # Bankdrücken [77, 15, 720, 17], - # Butterfly [30, 52], - # Fliegende [18, 73, 722], - # Kabelziehen [252, 252], - # Frontziehen [10, 12], - # Latzug [ 158, @@ -120,20 +84,16 @@ exercise_variation_ids = [ 243, 244, ], - # Rudern [245, 59, 70, 224, 76], - # Frontdrücken [ 19, 153, 66, ], - # Shrugs [8, 137, 67], - # Waden [13, 23, 297], ] @@ -172,7 +132,6 @@ def remove_variations(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ('exercises', '0006_auto_20201203_0203'), ] diff --git a/wger/exercises/migrations/0008_exercisebase.py b/wger/exercises/migrations/0008_exercisebase.py index e4fd7aa84..be82fd909 100644 --- a/wger/exercises/migrations/0008_exercisebase.py +++ b/wger/exercises/migrations/0008_exercisebase.py @@ -6,7 +6,6 @@ import django.db.models.deletion class Migration(migrations.Migration): - dependencies = [ ('core', '0011_auto_20201201_0653'), ('exercises', '0007_auto_20201203_1042'), @@ -20,7 +19,7 @@ class Migration(migrations.Migration): 'id', models.AutoField( auto_created=True, primary_key=True, serialize=False, verbose_name='ID' - ) + ), ), ( 'license_author', @@ -32,8 +31,8 @@ class Migration(migrations.Migration): CC-BY-SA.', max_length=50, null=True, - verbose_name='Author' - ) + verbose_name='Author', + ), ), ( 'status', @@ -41,22 +40,22 @@ class Migration(migrations.Migration): choices=[('1', 'Pending'), ('2', 'Accepted'), ('3', 'Declined')], default='1', editable=False, - max_length=2 - ) + max_length=2, + ), ), ( 'category', models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, to='exercises.exercisecategory', - verbose_name='Category' - ) + verbose_name='Category', + ), ), ( 'equipment', models.ManyToManyField( blank=True, to='exercises.Equipment', verbose_name='Equipment' - ) + ), ), ( 'license', @@ -64,14 +63,14 @@ class Migration(migrations.Migration): default=2, on_delete=django.db.models.deletion.CASCADE, to='core.license', - verbose_name='License' - ) + verbose_name='License', + ), ), ( 'muscles', models.ManyToManyField( blank=True, to='exercises.Muscle', verbose_name='Primary muscles' - ) + ), ), ( 'muscles_secondary', @@ -79,8 +78,8 @@ class Migration(migrations.Migration): blank=True, related_name='secondary_muscles_base', to='exercises.Muscle', - verbose_name='Secondary muscles' - ) + verbose_name='Secondary muscles', + ), ), ( 'variations', @@ -88,8 +87,8 @@ class Migration(migrations.Migration): null=True, on_delete=django.db.models.deletion.CASCADE, to='exercises.variation', - verbose_name='Variations' - ) + verbose_name='Variations', + ), ), ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, verbose_name='UUID')), ], @@ -106,7 +105,7 @@ class Migration(migrations.Migration): on_delete=django.db.models.deletion.CASCADE, related_name='exercises', to='exercises.exercisebase', - verbose_name='ExerciseBase' + verbose_name='ExerciseBase', ), ), migrations.AlterField( @@ -115,7 +114,7 @@ class Migration(migrations.Migration): field=models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, to='exercises.exercisebase', - verbose_name='Exercise' + verbose_name='Exercise', ), ), ] diff --git a/wger/exercises/migrations/0009_auto_20201211_0139.py b/wger/exercises/migrations/0009_auto_20201211_0139.py index 2f5c8dca8..e20916522 100644 --- a/wger/exercises/migrations/0009_auto_20201211_0139.py +++ b/wger/exercises/migrations/0009_auto_20201211_0139.py @@ -8,7 +8,9 @@ def copy_columns(apps, schema_editor): ExerciseBase = apps.get_model('exercises', 'ExerciseBase') for exercise in Exercise.objects.all(): - exercise_base = ExerciseBase.objects.create(category=exercise.category, ) + exercise_base = ExerciseBase.objects.create( + category=exercise.category, + ) exercise_base.equipment.set(exercise.equipment.all()) exercise_base.muscles.set(exercise.muscles.all()) exercise_base.muscles_secondary.set(exercise.muscles_secondary.all()) @@ -24,7 +26,6 @@ def copy_columns(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ('exercises', '0008_exercisebase'), ] diff --git a/wger/exercises/migrations/0010_auto_20201211_0205.py b/wger/exercises/migrations/0010_auto_20201211_0205.py index 56054410b..b8990397c 100644 --- a/wger/exercises/migrations/0010_auto_20201211_0205.py +++ b/wger/exercises/migrations/0010_auto_20201211_0205.py @@ -4,7 +4,6 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ ('exercises', '0009_auto_20201211_0139'), ] diff --git a/wger/exercises/migrations/0011_auto_20201214_0033.py b/wger/exercises/migrations/0011_auto_20201214_0033.py index 79f03571b..3b3be32ba 100644 --- a/wger/exercises/migrations/0011_auto_20201214_0033.py +++ b/wger/exercises/migrations/0011_auto_20201214_0033.py @@ -9,633 +9,280 @@ exercise_mapping = [ { 'en': 'c4856da3-8454-4857-8997-336d06df590f', 'de': '36c27886-b10b-41b6-ac60-f02ee3784041', - 'ru': '993cf4e0-e664-4cc2-aa46-683c6fc7a74f' + 'ru': '993cf4e0-e664-4cc2-aa46-683c6fc7a74f', }, - # 160 b1d6d536-7f4a-4dd3-8b76-62d7a984e115 Pistol Squat # 358 40a0019e-eaf2-491f-a134-9fdd51121358 Einbeinige Kniebeuge (Pistol Squat) - { - 'en': 'b1d6d536-7f4a-4dd3-8b76-62d7a984e115', - 'de': '40a0019e-eaf2-491f-a134-9fdd51121358' - }, - + {'en': 'b1d6d536-7f4a-4dd3-8b76-62d7a984e115', 'de': '40a0019e-eaf2-491f-a134-9fdd51121358'}, # 346 1d90f3a8-56e4-4c15-a4b4-94fc0e114e8c Bulgarian Split Squat # 695 cf21383b-b96a-40b5-b047-b9c3ddcab963 Bulgarian Split Squat - { - 'en': '1d90f3a8-56e4-4c15-a4b4-94fc0e114e8c', - 'de': 'cf21383b-b96a-40b5-b047-b9c3ddcab963' - }, - + {'en': '1d90f3a8-56e4-4c15-a4b4-94fc0e114e8c', 'de': 'cf21383b-b96a-40b5-b047-b9c3ddcab963'}, # 202 eed05679-d1cb-44a2-a17d-dd5b0097c874 Pendelay Rows # 731 196f9a72-7518-45c4-a4f2-d3ba3e0d3b3e Pendelay Rows - { - 'en': 'eed05679-d1cb-44a2-a17d-dd5b0097c874', - 'de': '196f9a72-7518-45c4-a4f2-d3ba3e0d3b3e' - }, - + {'en': 'eed05679-d1cb-44a2-a17d-dd5b0097c874', 'de': '196f9a72-7518-45c4-a4f2-d3ba3e0d3b3e'}, # 130 2966e4a2-4306-4cb5-a2dc-8951cd192555 Leg Press on Hackenschmidt Machine # 402 634dcf89-c346-4af8-8b09-61f238798877 Kniebeuge an Hackenschmidtmaschine - { - 'en': '2966e4a2-4306-4cb5-a2dc-8951cd192555', - 'de': '634dcf89-c346-4af8-8b09-61f238798877' - }, - + {'en': '2966e4a2-4306-4cb5-a2dc-8951cd192555', 'de': '634dcf89-c346-4af8-8b09-61f238798877'}, # 104 e7677699-5e4f-49e6-a645-e8915a203c4d Calf Raises on Hackenschmitt Machine # 23 c7b98fb5-7723-471a-92a1-7b4e892a5468 Wadenheben an Hackenschmidt - { - 'en': 'e7677699-5e4f-49e6-a645-e8915a203c4d', - 'de': 'c7b98fb5-7723-471a-92a1-7b4e892a5468' - }, - + {'en': 'e7677699-5e4f-49e6-a645-e8915a203c4d', 'de': 'c7b98fb5-7723-471a-92a1-7b4e892a5468'}, # 105 22cca8fc-cfaf-4941-b0f7-faf9f2937c52 Deadlifts # 9 521a5e4f-6f35-43e5-9d1c-6e75c4956e96 Kreuzheben - { - 'en': '22cca8fc-cfaf-4941-b0f7-faf9f2937c52', - 'de': '521a5e4f-6f35-43e5-9d1c-6e75c4956e96' - }, - + {'en': '22cca8fc-cfaf-4941-b0f7-faf9f2937c52', 'de': '521a5e4f-6f35-43e5-9d1c-6e75c4956e96'}, # 570 f4dd363c-b49c-419a-b8ae-0d8e18728d8e Sumo Squats # 762 b399006c-bb45-451e-908e-1b279b2a42a6 Sumo Squats (Pilé Squats) Kniebeuge - { - 'en': 'f4dd363c-b49c-419a-b8ae-0d8e18728d8e', - 'de': 'b399006c-bb45-451e-908e-1b279b2a42a6' - }, - + {'en': 'f4dd363c-b49c-419a-b8ae-0d8e18728d8e', 'de': 'b399006c-bb45-451e-908e-1b279b2a42a6'}, # 91 d325dd5c-6833-41c7-8eea-6b95c4871133 Crunches # 4 0e10ac9b-ed1d-42c9-b8cc-123c22ccc5d5 Crunches - { - 'en': 'd325dd5c-6833-41c7-8eea-6b95c4871133', - 'de': '0e10ac9b-ed1d-42c9-b8cc-123c22ccc5d5' - }, - + {'en': 'd325dd5c-6833-41c7-8eea-6b95c4871133', 'de': '0e10ac9b-ed1d-42c9-b8cc-123c22ccc5d5'}, # 92 8d6c13c6-256d-4137-b1c6-b0e817697639 Crunches With Cable # 33 5c47b690-d19f-4523-9c47-47160693eefc Crunches am Seil - { - 'en': '8d6c13c6-256d-4137-b1c6-b0e817697639', - 'de': '5c47b690-d19f-4523-9c47-47160693eefc' - }, - + {'en': '8d6c13c6-256d-4137-b1c6-b0e817697639', 'de': '5c47b690-d19f-4523-9c47-47160693eefc'}, # 94 6709577b-95ec-4053-a822-d5fe1f753966 Crunches on Machine # 51 efbece79-4384-49d1-bb88-e16fcd8de5aa Crunches an Maschine - { - 'en': '6709577b-95ec-4053-a822-d5fe1f753966', - 'de': 'efbece79-4384-49d1-bb88-e16fcd8de5aa' - }, - + {'en': '6709577b-95ec-4053-a822-d5fe1f753966', 'de': 'efbece79-4384-49d1-bb88-e16fcd8de5aa'}, # 307 1b8b1657-40fd-4e3b-97b7-1c79b1079f8e Bear Walk # 718 e4b3da5b-1803-42af-a50e-ffbac3853cd0 Bear Walk - { - 'en': '1b8b1657-40fd-4e3b-97b7-1c79b1079f8e', - 'de': 'e4b3da5b-1803-42af-a50e-ffbac3853cd0' - }, - + {'en': '1b8b1657-40fd-4e3b-97b7-1c79b1079f8e', 'de': 'e4b3da5b-1803-42af-a50e-ffbac3853cd0'}, # 192 5da6340b-22ec-4c1b-a443-eef2f59f92f0 Bench Press # 15 198dcb2e-e35f-4b69-ae8b-e1124d438eae Bankdrücken LH - { - 'en': '5da6340b-22ec-4c1b-a443-eef2f59f92f0', - 'de': '198dcb2e-e35f-4b69-ae8b-e1124d438eae' - }, - + {'en': '5da6340b-22ec-4c1b-a443-eef2f59f92f0', 'de': '198dcb2e-e35f-4b69-ae8b-e1124d438eae'}, # 88 03d821e7-e1ac-4026-903b-d406381cbf76 Bench Press Narrow Grip # 38 4def60e7-ed8d-4a9d-bf76-ceb15ecf9779 Bankdrücken Eng - { - 'en': '03d821e7-e1ac-4026-903b-d406381cbf76', - 'de': '4def60e7-ed8d-4a9d-bf76-ceb15ecf9779' - }, - + {'en': '03d821e7-e1ac-4026-903b-d406381cbf76', 'de': '4def60e7-ed8d-4a9d-bf76-ceb15ecf9779'}, # 97 0ec76f5d-1311-4d6d-bf79-00fa17c3061a Benchpress Dumbbells # 77 06450bcb-03a8-4bd7-8349-ef677ee57ea3 Bankdrücken KH - { - 'en': '0ec76f5d-1311-4d6d-bf79-00fa17c3061a', - 'de': '06450bcb-03a8-4bd7-8349-ef677ee57ea3' - }, - + {'en': '0ec76f5d-1311-4d6d-bf79-00fa17c3061a', 'de': '06450bcb-03a8-4bd7-8349-ef677ee57ea3'}, # 129 8c6c1544-cbf8-403c-ae12-b27b392702f8 Biceps Curl With Cable # 3 ef487de3-f071-41bf-85a6-6e76afe9c732 Bizeps am Kabel - { - 'en': '8c6c1544-cbf8-403c-ae12-b27b392702f8', - 'de': 'ef487de3-f071-41bf-85a6-6e76afe9c732' - }, - + {'en': '8c6c1544-cbf8-403c-ae12-b27b392702f8', 'de': 'ef487de3-f071-41bf-85a6-6e76afe9c732'}, # 80 38919515-ce04-4383-9c3f-5846edd0e844 Biceps Curls With SZ-bar # 44 8277124a-9ef2-442a-9824-7ab4439a5f1f Bizeps Curls Mit ß-Stange - { - 'en': '38919515-ce04-4383-9c3f-5846edd0e844', - 'de': '8277124a-9ef2-442a-9824-7ab4439a5f1f' - }, - + {'en': '38919515-ce04-4383-9c3f-5846edd0e844', 'de': '8277124a-9ef2-442a-9824-7ab4439a5f1f'}, # 74 c56078d2-ae85-4524-a467-d1e143b6df1a Biceps Curls With Barbell # 24 2e3fa138-3894-4f61-959a-d8966804a1a3 Bizeps LH-Curls - { - 'en': 'c56078d2-ae85-4524-a467-d1e143b6df1a', - 'de': '2e3fa138-3894-4f61-959a-d8966804a1a3' - }, - + {'en': 'c56078d2-ae85-4524-a467-d1e143b6df1a', 'de': '2e3fa138-3894-4f61-959a-d8966804a1a3'}, # 275 dfa090e4-77ae-40ed-86c0-4696fe93dcf1 Dumbbell Concentration Curl # 681 ec0c53a5-15b9-4c2f-ac7c-00888db9f8ee Konzentrations-Curls - { - 'en': 'dfa090e4-77ae-40ed-86c0-4696fe93dcf1', - 'de': 'ec0c53a5-15b9-4c2f-ac7c-00888db9f8ee' - }, - + {'en': 'dfa090e4-77ae-40ed-86c0-4696fe93dcf1', 'de': 'ec0c53a5-15b9-4c2f-ac7c-00888db9f8ee'}, # 86 6dcc9adb-939c-4581-9e44-d0d73753997b Hammercurls # 46 ff454f5a-70ee-40fb-9200-5e7e42960ef0 Hammercurls - { - 'en': '6dcc9adb-939c-4581-9e44-d0d73753997b', - 'de': 'ff454f5a-70ee-40fb-9200-5e7e42960ef0' - }, - + {'en': '6dcc9adb-939c-4581-9e44-d0d73753997b', 'de': 'ff454f5a-70ee-40fb-9200-5e7e42960ef0'}, # 138 5baf40e5-ea3c-4f8d-b60a-d294ee2de55b Hammercurls on Cable # 134 06e9de49-ac1b-45c1-b289-475118932434 Hammercurls am Seil - { - 'en': '5baf40e5-ea3c-4f8d-b60a-d294ee2de55b', - 'de': '06e9de49-ac1b-45c1-b289-475118932434' - }, - + {'en': '5baf40e5-ea3c-4f8d-b60a-d294ee2de55b', 'de': '06e9de49-ac1b-45c1-b289-475118932434'}, # 771 bdcae845-6726-457f-8e04-203754a78e1c Reverse Curl # 815 7662a76a-3ea7-4b63-86d9-c0702b554090 Reverse Curls - { - 'en': 'bdcae845-6726-457f-8e04-203754a78e1c', - 'de': '7662a76a-3ea7-4b63-86d9-c0702b554090' - }, - + {'en': 'bdcae845-6726-457f-8e04-203754a78e1c', 'de': '7662a76a-3ea7-4b63-86d9-c0702b554090'}, # 298 fa56d30a-7a8f-4084-aa68-46bd52f97959 Dumbbell Incline Curl # 242 0842e81e-7b90-4d68-8e6b-e9a7c0186b54 Bizeps KH-Curls Schrägbank - { - 'en': 'fa56d30a-7a8f-4084-aa68-46bd52f97959', - 'de': '0842e81e-7b90-4d68-8e6b-e9a7c0186b54' - }, - + {'en': 'fa56d30a-7a8f-4084-aa68-46bd52f97959', 'de': '0842e81e-7b90-4d68-8e6b-e9a7c0186b54'}, # 81 48a59aa8-4568-409c-8afe-f8cb99c558ea Biceps Curls With Dumbbell # 26 8cbbffcc-1989-43de-9200-03869480398c Bizeps KH-Curls - { - 'en': '48a59aa8-4568-409c-8afe-f8cb99c558ea', - 'de': '8cbbffcc-1989-43de-9200-03869480398c' - }, - + {'en': '48a59aa8-4568-409c-8afe-f8cb99c558ea', 'de': '8cbbffcc-1989-43de-9200-03869480398c'}, # 227 53ca25b3-61d9-4f72-bfdb-492b83484ff5 Arnold Shoulder Press # 228 880bff63-6798-4ffc-a818-b2a1ccfec0f7 Arnold Press - { - 'en': '53ca25b3-61d9-4f72-bfdb-492b83484ff5', - 'de': '880bff63-6798-4ffc-a818-b2a1ccfec0f7' - }, - + {'en': '53ca25b3-61d9-4f72-bfdb-492b83484ff5', 'de': '880bff63-6798-4ffc-a818-b2a1ccfec0f7'}, # 150 3721be0c-2a59-4bb9-90d3-695faaf028af Shrugs, Barbells # 137 a63d40df-a872-44e7-87d2-9b58b67d5406 Shrugs (Schulterheben) Mit LH - { - 'en': '3721be0c-2a59-4bb9-90d3-695faaf028af', - 'de': 'a63d40df-a872-44e7-87d2-9b58b67d5406' - }, - + {'en': '3721be0c-2a59-4bb9-90d3-695faaf028af', 'de': 'a63d40df-a872-44e7-87d2-9b58b67d5406'}, # 151 ee61aef0-f0c7-4a7a-882a-3b39312dfffd Shrugs, Dumbbells # 8 6dde45fc-7fdf-4523-a039-9c373677a750 Shrugs (Schulterheben) Mit KH - { - 'en': 'ee61aef0-f0c7-4a7a-882a-3b39312dfffd', - 'de': '6dde45fc-7fdf-4523-a039-9c373677a750' - }, - + {'en': 'ee61aef0-f0c7-4a7a-882a-3b39312dfffd', 'de': '6dde45fc-7fdf-4523-a039-9c373677a750'}, # 387 b229c57f-5363-41e2-add7-c2501a31de0b Wall Squat # 707 7f3e45fa-3b17-4cdb-90d5-cb9957212cbf Wall Squat - { - 'en': 'b229c57f-5363-41e2-add7-c2501a31de0b', - 'de': '7f3e45fa-3b17-4cdb-90d5-cb9957212cbf' - }, - + {'en': 'b229c57f-5363-41e2-add7-c2501a31de0b', 'de': '7f3e45fa-3b17-4cdb-90d5-cb9957212cbf'}, # 93 4bd55b0a-559a-4458-aabd-e66619b63610 Negative Crunches # 32 f5e98b51-6c0e-4c77-94ec-158210669f6d Crunches an Negativbank - { - 'en': '4bd55b0a-559a-4458-aabd-e66619b63610', - 'de': 'f5e98b51-6c0e-4c77-94ec-158210669f6d' - }, - + {'en': '4bd55b0a-559a-4458-aabd-e66619b63610', 'de': 'f5e98b51-6c0e-4c77-94ec-158210669f6d'}, # 330 6572a8e9-083c-4622-8f0c-6107a013a490 Superman # 735 bd58585e-4bf4-46cc-ba38-717a7857e21c Superman - { - 'en': '6572a8e9-083c-4622-8f0c-6107a013a490', - 'de': 'bd58585e-4bf4-46cc-ba38-717a7857e21c' - }, - + {'en': '6572a8e9-083c-4622-8f0c-6107a013a490', 'de': 'bd58585e-4bf4-46cc-ba38-717a7857e21c'}, # 238 7729ffe5-a896-4deb-80e0-f4e6163c0c09 Plank # 417 257cdb33-ba8b-410a-9396-5132b08dc912 Unterarmstütze - Plank - { - 'en': '7729ffe5-a896-4deb-80e0-f4e6163c0c09', - 'de': '257cdb33-ba8b-410a-9396-5132b08dc912' - }, - + {'en': '7729ffe5-a896-4deb-80e0-f4e6163c0c09', 'de': '257cdb33-ba8b-410a-9396-5132b08dc912'}, # 325 a36f852f-a29f-4f93-81b6-1012047ac1ee Side Plank # 715 2c6cd166-40e1-4b68-96b7-c30b31e28b99 Side Plank - { - 'en': 'a36f852f-a29f-4f93-81b6-1012047ac1ee', - 'de': '2c6cd166-40e1-4b68-96b7-c30b31e28b99' - }, - + {'en': 'a36f852f-a29f-4f93-81b6-1012047ac1ee', 'de': '2c6cd166-40e1-4b68-96b7-c30b31e28b99'}, # 116 6e862700-3d63-486c-99ae-744c68d2f753 Good Mornings # 50 a311a463-f219-4741-b4fb-247013dc8dd8 Good Mornings - { - 'en': '6e862700-3d63-486c-99ae-744c68d2f753', - 'de': 'a311a463-f219-4741-b4fb-247013dc8dd8' - }, - + {'en': '6e862700-3d63-486c-99ae-744c68d2f753', 'de': 'a311a463-f219-4741-b4fb-247013dc8dd8'}, # 326 bf9e572d-d138-43e9-a486-a5c6ad9033f8 Full Sit Outs # 710 143cf744-ce94-458c-9c74-1aea6c64cfc7 Full Sit Outs - { - 'en': 'bf9e572d-d138-43e9-a486-a5c6ad9033f8', - 'de': '143cf744-ce94-458c-9c74-1aea6c64cfc7' - }, - + {'en': 'bf9e572d-d138-43e9-a486-a5c6ad9033f8', 'de': '143cf744-ce94-458c-9c74-1aea6c64cfc7'}, # 95 fb750082-7034-4c51-b1e4-dfa0fe2dac8e Sit-ups # 57 60f329dd-f8ab-469a-8a88-39f80275b3a7 Sit Ups - { - 'en': 'fb750082-7034-4c51-b1e4-dfa0fe2dac8e', - 'de': '60f329dd-f8ab-469a-8a88-39f80275b3a7' - }, - + {'en': 'fb750082-7034-4c51-b1e4-dfa0fe2dac8e', 'de': '60f329dd-f8ab-469a-8a88-39f80275b3a7'}, # 83 aa4fcd9b-baee-41cf-b4c5-8462bc43a8be Dips Between Two Benches # 68 011b956d-33b3-4600-9e42-2e7dcbac9fb5 Dips Zwischen 2 Bänke - { - 'en': 'aa4fcd9b-baee-41cf-b4c5-8462bc43a8be', - 'de': '011b956d-33b3-4600-9e42-2e7dcbac9fb5' - }, - + {'en': 'aa4fcd9b-baee-41cf-b4c5-8462bc43a8be', 'de': '011b956d-33b3-4600-9e42-2e7dcbac9fb5'}, # 354 6335de72-146f-4f38-886d-6b8a27db62ff Burpees # 719 5bae16b0-cefb-4fc7-be2b-e31794335c42 Burpees - { - 'en': '6335de72-146f-4f38-886d-6b8a27db62ff', - 'de': '5bae16b0-cefb-4fc7-be2b-e31794335c42' - }, - + {'en': '6335de72-146f-4f38-886d-6b8a27db62ff', 'de': '5bae16b0-cefb-4fc7-be2b-e31794335c42'}, # 289 6add5973-86d0-4543-928a-6bb8b3f34efc Axe Hold # 677 8e9d8968-323d-468c-9174-8cf11a105fad Axe Hold - { - 'en': '6add5973-86d0-4543-928a-6bb8b3f34efc', - 'de': '8e9d8968-323d-468c-9174-8cf11a105fad' - }, - + {'en': '6add5973-86d0-4543-928a-6bb8b3f34efc', 'de': '8e9d8968-323d-468c-9174-8cf11a105fad'}, # 98 3c3857f8-d224-4d5a-8cc1-f4e7982d3475 Butterfly # 30 9df24c6f-016b-4623-8878-f71c235c50fa Butterfly - { - 'en': '3c3857f8-d224-4d5a-8cc1-f4e7982d3475', - 'de': '9df24c6f-016b-4623-8878-f71c235c50fa' - }, - + {'en': '3c3857f8-d224-4d5a-8cc1-f4e7982d3475', 'de': '9df24c6f-016b-4623-8878-f71c235c50fa'}, # 99 08637e04-d995-4c07-b021-a20f26b6fd97 Butterfly Narrow Grip # 52 44b0d79a-5c5b-43df-bf62-3e67148f1c33 Butterfly Eng - { - 'en': '08637e04-d995-4c07-b021-a20f26b6fd97', - 'de': '44b0d79a-5c5b-43df-bf62-3e67148f1c33' - }, - + {'en': '08637e04-d995-4c07-b021-a20f26b6fd97', 'de': '44b0d79a-5c5b-43df-bf62-3e67148f1c33'}, # 124 8715a96e-c8a2-458a-b023-4ea7d82fdab8 Butterfly Reverse # 21 605b4a25-bc1d-4604-bd93-c85b2aaf84ae Butterfly Reverse - { - 'en': '8715a96e-c8a2-458a-b023-4ea7d82fdab8', - 'de': '605b4a25-bc1d-4604-bd93-c85b2aaf84ae' - }, - + {'en': '8715a96e-c8a2-458a-b023-4ea7d82fdab8', 'de': '605b4a25-bc1d-4604-bd93-c85b2aaf84ae'}, # 394 659f3fb9-2370-42fb-9c29-9aaf65c7a7de Facepull # 415 237c8770-4c1f-433d-b8b4-b1ae5c69bbc5 Face Pulls - { - 'en': '659f3fb9-2370-42fb-9c29-9aaf65c7a7de', - 'de': '237c8770-4c1f-433d-b8b4-b1ae5c69bbc5' - }, - + {'en': '659f3fb9-2370-42fb-9c29-9aaf65c7a7de', 'de': '237c8770-4c1f-433d-b8b4-b1ae5c69bbc5'}, # 281 e1881607-9418-4bcc-8c69-2301a579637e L Hold # 753 6ae461d7-daea-4ac7-999b-826fe28263b0 L Hold - { - 'en': 'e1881607-9418-4bcc-8c69-2301a579637e', - 'de': '6ae461d7-daea-4ac7-999b-826fe28263b0' - }, - + {'en': 'e1881607-9418-4bcc-8c69-2301a579637e', 'de': '6ae461d7-daea-4ac7-999b-826fe28263b0'}, # 143 b192c4eb-31c6-458e-b566-d3f38b5aa30c Long-Pulley (low Row) # 37 91fa0487-b137-4bef-86cf-39816cd5ee48 Long-Pulley - { - 'en': 'b192c4eb-31c6-458e-b566-d3f38b5aa30c', - 'de': '91fa0487-b137-4bef-86cf-39816cd5ee48' - }, - + {'en': 'b192c4eb-31c6-458e-b566-d3f38b5aa30c', 'de': '91fa0487-b137-4bef-86cf-39816cd5ee48'}, # 144 bcabc8cf-c005-4630-8853-ef4922e7fd91 Long-Pulley, Narrow # 136 490a615c-4185-4560-88a5-020f3aa40be2 Long-Pulley (eng) - { - 'en': 'bcabc8cf-c005-4630-8853-ef4922e7fd91', - 'de': '490a615c-4185-4560-88a5-020f3aa40be2' - }, - + {'en': 'bcabc8cf-c005-4630-8853-ef4922e7fd91', 'de': '490a615c-4185-4560-88a5-020f3aa40be2'}, # 103 399666e7-30a7-4b86-833d-4422e4c72b61 Sitting Calf Raises # 14 47b4d57a-3bb3-4a03-a522-a0559a254730 Wadenheben Sitzend - { - 'en': '399666e7-30a7-4b86-833d-4422e4c72b61', - 'de': '47b4d57a-3bb3-4a03-a522-a0559a254730' - }, - + {'en': '399666e7-30a7-4b86-833d-4422e4c72b61', 'de': '47b4d57a-3bb3-4a03-a522-a0559a254730'}, # 102 abc4c62e-27b2-4c31-8766-40f8dca84cab Standing Calf Raises # 13 283d4ec5-1b29-41bb-997d-74c30e7a68b5 Wadenheben Stehend - { - 'en': 'abc4c62e-27b2-4c31-8766-40f8dca84cab', - 'de': '283d4ec5-1b29-41bb-997d-74c30e7a68b5' - }, - + {'en': 'abc4c62e-27b2-4c31-8766-40f8dca84cab', 'de': '283d4ec5-1b29-41bb-997d-74c30e7a68b5'}, # 308 074530d6-801a-404b-b3b7-adc207be69be Calf Press Using Leg Press Machine # 745 84afd45e-235a-41c3-8711-ea9f6d08eeb6 Wadendrücken an Beinpresse - { - 'en': '074530d6-801a-404b-b3b7-adc207be69be', - 'de': '84afd45e-235a-41c3-8711-ea9f6d08eeb6' - }, - + {'en': '074530d6-801a-404b-b3b7-adc207be69be', 'de': '84afd45e-235a-41c3-8711-ea9f6d08eeb6'}, # 85 ee00d53e-4482-44aa-b780-bbc570061841 French Press (skullcrusher) Dumbbells # 58 bdf8997a-84ce-434a-ae95-1f9fc50f43bb Frenchpress KH - { - 'en': 'ee00d53e-4482-44aa-b780-bbc570061841', - 'de': 'bdf8997a-84ce-434a-ae95-1f9fc50f43bb' - }, - + {'en': 'ee00d53e-4482-44aa-b780-bbc570061841', 'de': 'bdf8997a-84ce-434a-ae95-1f9fc50f43bb'}, # 84 ee4a350b-c681-407f-a414-6ec243809ec7 French Press (skullcrusher) SZ-bar # 25 9972e42d-43d8-43c0-b547-4638ca3e47be Frenchpress ß-Stange - { - 'en': 'ee4a350b-c681-407f-a414-6ec243809ec7', - 'de': '9972e42d-43d8-43c0-b547-4638ca3e47be' - }, - + {'en': 'ee4a350b-c681-407f-a414-6ec243809ec7', 'de': '9972e42d-43d8-43c0-b547-4638ca3e47be'}, # 788 6c8e863c-f6c2-4ad0-a0e9-5e6d9e6a928b Leg Press # 6 a27cfdd9-5299-49ab-85f5-6e4042657549 Beinpresse - { - 'en': '6c8e863c-f6c2-4ad0-a0e9-5e6d9e6a928b', - 'de': 'a27cfdd9-5299-49ab-85f5-6e4042657549' - }, - + {'en': '6c8e863c-f6c2-4ad0-a0e9-5e6d9e6a928b', 'de': 'a27cfdd9-5299-49ab-85f5-6e4042657549'}, # 115 560e1a20-33e1-45db-ba5b-63f8c51af76d Leg Presses (narrow) # 54 e7d0cc2d-e28b-479f-91d9-7eab7b686fd8 Beinpresse Eng - { - 'en': '560e1a20-33e1-45db-ba5b-63f8c51af76d', - 'de': 'e7d0cc2d-e28b-479f-91d9-7eab7b686fd8' - }, - + {'en': '560e1a20-33e1-45db-ba5b-63f8c51af76d', 'de': 'e7d0cc2d-e28b-479f-91d9-7eab7b686fd8'}, # 112 587c0052-f2bc-48ca-8af9-415175308901 Dumbbell Lunges Standing # 55 27301836-ed7f-4510-83e7-66c0b8041a44 Ausfallschritte Stehend # 363 c38e34a7-5560-46a1-bae4-c4fce9619e55 Výpad Statický { 'en': '587c0052-f2bc-48ca-8af9-415175308901', 'de': '27301836-ed7f-4510-83e7-66c0b8041a44', - 'cs': 'c38e34a7-5560-46a1-bae4-c4fce9619e55' + 'cs': 'c38e34a7-5560-46a1-bae4-c4fce9619e55', }, - # 113 ffd4ce7e-e14f-49d4-9dc9-dc1362631382 Dumbbell Lunges Walking # 5 5675ae61-6597-4806-ae5c-2dda5a5ac03c Ausfallschritte im Gehen - { - 'en': 'ffd4ce7e-e14f-49d4-9dc9-dc1362631382', - 'de': '5675ae61-6597-4806-ae5c-2dda5a5ac03c' - }, - + {'en': 'ffd4ce7e-e14f-49d4-9dc9-dc1362631382', 'de': '5675ae61-6597-4806-ae5c-2dda5a5ac03c'}, # 145 754391c6-39d5-4bb6-a311-68a520f6fd3a Fly With Dumbbells # 18 c0119734-a412-4f34-91f1-cd1c1177fcb8 Fliegende KH Flachbank - { - 'en': '754391c6-39d5-4bb6-a311-68a520f6fd3a', - 'de': 'c0119734-a412-4f34-91f1-cd1c1177fcb8' - }, - + {'en': '754391c6-39d5-4bb6-a311-68a520f6fd3a', 'de': 'c0119734-a412-4f34-91f1-cd1c1177fcb8'}, # 146 acf1f2df-46c4-49a3-8e6c-2979ea4204b1 Fly With Dumbbells, Decline Bench # 73 3b34d81d-7882-46a6-bb83-40f84d3f8300 Fliegende KH Schrägbank - { - 'en': 'acf1f2df-46c4-49a3-8e6c-2979ea4204b1', - 'de': '3b34d81d-7882-46a6-bb83-40f84d3f8300' - }, - + {'en': 'acf1f2df-46c4-49a3-8e6c-2979ea4204b1', 'de': '3b34d81d-7882-46a6-bb83-40f84d3f8300'}, # 409 75ec610d-216a-49fe-b395-c5fd8ee14b53 Reverse Plank # 713 24e5637e-60eb-41f5-b964-31e2af990bfc Reverse Plank - { - 'en': '75ec610d-216a-49fe-b395-c5fd8ee14b53', - 'de': '24e5637e-60eb-41f5-b964-31e2af990bfc' - }, - + {'en': '75ec610d-216a-49fe-b395-c5fd8ee14b53', 'de': '24e5637e-60eb-41f5-b964-31e2af990bfc'}, # 181 f6c4e2fa-226d-46e8-87dc-75fc8cd628bd Chin-ups # 747 9e71d2a3-9021-4270-a7b9-0d8bd28e7394 Chin-ups - { - 'en': 'f6c4e2fa-226d-46e8-87dc-75fc8cd628bd', - 'de': '9e71d2a3-9021-4270-a7b9-0d8bd28e7394' - }, - + {'en': 'f6c4e2fa-226d-46e8-87dc-75fc8cd628bd', 'de': '9e71d2a3-9021-4270-a7b9-0d8bd28e7394'}, # 346 1d90f3a8-56e4-4c15-a4b4-94fc0e114e8c Bulgarian Split Squat # 695 cf21383b-b96a-40b5-b047-b9c3ddcab963 Bulgarian Split Squat - { - 'en': '1d90f3a8-56e4-4c15-a4b4-94fc0e114e8c', - 'de': 'cf21383b-b96a-40b5-b047-b9c3ddcab963' - }, - + {'en': '1d90f3a8-56e4-4c15-a4b4-94fc0e114e8c', 'de': 'cf21383b-b96a-40b5-b047-b9c3ddcab963'}, # 781 7191e015-0c60-4376-9be0-733b9754b7f8 Dips # 29 41b495fd-562e-4d6e-942a-60dc52d5e194 Dips - { - 'en': '7191e015-0c60-4376-9be0-733b9754b7f8', - 'de': '41b495fd-562e-4d6e-942a-60dc52d5e194' - }, - + {'en': '7191e015-0c60-4376-9be0-733b9754b7f8', 'de': '41b495fd-562e-4d6e-942a-60dc52d5e194'}, # 279 88568115-5e88-4afc-b005-e2f7d453ac13 Tricep Dumbbell Kickback # 232 ebe60386-bf33-4f50-87a6-d44c5f454158 Kick-Backs - { - 'en': '88568115-5e88-4afc-b005-e2f7d453ac13', - 'de': 'ebe60386-bf33-4f50-87a6-d44c5f454158' - }, - + {'en': '88568115-5e88-4afc-b005-e2f7d453ac13', 'de': 'ebe60386-bf33-4f50-87a6-d44c5f454158'}, # 128 f57a0c60-7d37-4eb3-a94e-1a90292e8c02 Hyperextensions # 60 913d71cc-ba7a-4902-bfa8-3c5203129d72 Hyperextensions - { - 'en': 'f57a0c60-7d37-4eb3-a94e-1a90292e8c02', - 'de': '913d71cc-ba7a-4902-bfa8-3c5203129d72' - }, - + {'en': 'f57a0c60-7d37-4eb3-a94e-1a90292e8c02', 'de': '913d71cc-ba7a-4902-bfa8-3c5203129d72'}, # 195 9d756e84-6b77-4f17-b21d-7d266d6a8bd2 Push Ups # 172 35871103-6cfe-493f-afe1-8401f88fed84 Liegestütz - { - 'en': '9d756e84-6b77-4f17-b21d-7d266d6a8bd2', - 'de': '35871103-6cfe-493f-afe1-8401f88fed84' - }, - + {'en': '9d756e84-6b77-4f17-b21d-7d266d6a8bd2', 'de': '35871103-6cfe-493f-afe1-8401f88fed84'}, # 260 36ef5f12-6f77-4754-a926-39915e4b57a5 Decline Pushups # 721 e386cd27-aef6-4565-88ad-639b0ea04e3a Negativ Pushups - { - 'en': '36ef5f12-6f77-4754-a926-39915e4b57a5', - 'de': 'e386cd27-aef6-4565-88ad-639b0ea04e3a' - }, - + {'en': '36ef5f12-6f77-4754-a926-39915e4b57a5', 'de': 'e386cd27-aef6-4565-88ad-639b0ea04e3a'}, # 139 88bbdbde-c9b6-45a1-aee9-efc6f02cfab3 Triceps Machine # 27 ca03dd79-4a92-47ef-a461-e67ccc406f82 Trizepsmaschine - { - 'en': '88bbdbde-c9b6-45a1-aee9-efc6f02cfab3', - 'de': 'ca03dd79-4a92-47ef-a461-e67ccc406f82' - }, - + {'en': '88bbdbde-c9b6-45a1-aee9-efc6f02cfab3', 'de': 'ca03dd79-4a92-47ef-a461-e67ccc406f82'}, # 338 20b88059-3958-4184-9134-b48656ad868d Isometric Wipers # 724 666d1c77-d74b-411c-be3e-1e60a02c548d Isometric Wipers - { - 'en': '20b88059-3958-4184-9134-b48656ad868d', - 'de': '666d1c77-d74b-411c-be3e-1e60a02c548d' - }, - + {'en': '20b88059-3958-4184-9134-b48656ad868d', 'de': '666d1c77-d74b-411c-be3e-1e60a02c548d'}, # 90 20a76bd0-1e56-4a4e-bd79-0ab118552bde Triceps Extensions on Cable With Bar # 63 60aab5bf-ff7a-4e50-9e92-1f4813c3da75 Trizeps Seildrücken Mit Stange - { - 'en': '20a76bd0-1e56-4a4e-bd79-0ab118552bde', - 'de': '60aab5bf-ff7a-4e50-9e92-1f4813c3da75' - }, - + {'en': '20a76bd0-1e56-4a4e-bd79-0ab118552bde', 'de': '60aab5bf-ff7a-4e50-9e92-1f4813c3da75'}, # 89 f1b5e525-6232-4d60-a243-9b2cd6c55298 Triceps Extensions on Cable # 1 b83e3d85-a53d-4939-a61c-7baa2e94d358 Trizeps Seildrücken - { - 'en': 'f1b5e525-6232-4d60-a243-9b2cd6c55298', - 'de': 'b83e3d85-a53d-4939-a61c-7baa2e94d358' - }, - + {'en': 'f1b5e525-6232-4d60-a243-9b2cd6c55298', 'de': 'b83e3d85-a53d-4939-a61c-7baa2e94d358'}, # 270 625aefd5-7ba2-40e9-bdc3-7d3ab1bcf3b8 Pause Bench # 725 5009eedc-554f-43ef-852e-77ba45a7297c Pause Bench - { - 'en': '625aefd5-7ba2-40e9-bdc3-7d3ab1bcf3b8', - 'de': '5009eedc-554f-43ef-852e-77ba45a7297c' - }, - + {'en': '625aefd5-7ba2-40e9-bdc3-7d3ab1bcf3b8', 'de': '5009eedc-554f-43ef-852e-77ba45a7297c'}, # 149 79a3a34c-262f-4cae-b827-b5a85b11b860 Lateral Raises on Cable, One Armed # 132 382731d2-ae07-4a3c-a055-09dadd5f12e0 Seitheben am Kabel, Einarmig - { - 'en': '79a3a34c-262f-4cae-b827-b5a85b11b860', - 'de': '382731d2-ae07-4a3c-a055-09dadd5f12e0' - }, - + {'en': '79a3a34c-262f-4cae-b827-b5a85b11b860', 'de': '382731d2-ae07-4a3c-a055-09dadd5f12e0'}, # 148 5345766a-c092-457a-aa21-8ee6ffa855d4 Lateral Raises # 20 72e78f4d-65f7-4ddd-9247-cdc1e133fa80 Seitheben KH - { - 'en': '5345766a-c092-457a-aa21-8ee6ffa855d4', - 'de': '72e78f4d-65f7-4ddd-9247-cdc1e133fa80' - }, - + {'en': '5345766a-c092-457a-aa21-8ee6ffa855d4', 'de': '72e78f4d-65f7-4ddd-9247-cdc1e133fa80'}, # 191 f2e563d2-507b-4586-88c8-77652cd19648 Front Squats # 390 d23d1980-3a50-4d3f-8123-90d7e55c7804 Front Kniebeuge - { - 'en': 'f2e563d2-507b-4586-88c8-77652cd19648', - 'de': 'd23d1980-3a50-4d3f-8123-90d7e55c7804' - }, - + {'en': 'f2e563d2-507b-4586-88c8-77652cd19648', 'de': 'd23d1980-3a50-4d3f-8123-90d7e55c7804'}, # 229 89e6d2ea-9a17-4a77-9a52-d5bcf39d57fd Military Press # 153 47c33837-be38-4ebb-b19a-84c280f5f2b0 Frontdrücken LH - { - 'en': '89e6d2ea-9a17-4a77-9a52-d5bcf39d57fd', - 'de': '47c33837-be38-4ebb-b19a-84c280f5f2b0' - }, - + {'en': '89e6d2ea-9a17-4a77-9a52-d5bcf39d57fd', 'de': '47c33837-be38-4ebb-b19a-84c280f5f2b0'}, # 854 37097633-de80-4271-9b7c-291f359e0ef4 Hip Thrust # 230 981ef1f0-414a-478b-bc1b-9c6afa45bc77 Beckenheben - { - 'en': '37097633-de80-4271-9b7c-291f359e0ef4', - 'de': '981ef1f0-414a-478b-bc1b-9c6afa45bc77' - }, - + {'en': '37097633-de80-4271-9b7c-291f359e0ef4', 'de': '981ef1f0-414a-478b-bc1b-9c6afa45bc77'}, # 177 a24a0521-6391-419c-bd89-795bba0eb5ee Leg Extension # 133 da7fccca-941e-457a-a2eb-d0c56d419938 Beinbeuger Sitzend - { - 'en': 'a24a0521-6391-419c-bd89-795bba0eb5ee', - 'de': 'da7fccca-941e-457a-a2eb-d0c56d419938' - }, - + {'en': 'a24a0521-6391-419c-bd89-795bba0eb5ee', 'de': 'da7fccca-941e-457a-a2eb-d0c56d419938'}, # 109 f82c579e-c069-4dc7-8e36-a3266dfd8e4a Bent Over Rowing # 59 126d719a-4b59-4458-b182-d578cdcfee1a Rudern Vorgebeugt LH - { - 'en': 'f82c579e-c069-4dc7-8e36-a3266dfd8e4a', - 'de': '126d719a-4b59-4458-b182-d578cdcfee1a' - }, - + {'en': 'f82c579e-c069-4dc7-8e36-a3266dfd8e4a', 'de': '126d719a-4b59-4458-b182-d578cdcfee1a'}, # 108 57747eb3-411a-4efd-8842-a45e562320ee Rowing, Seated # 245 788ef0a5-492f-48a7-87dc-b15dda185bb8 Rudern Eng Zum Bauch - { - 'en': '57747eb3-411a-4efd-8842-a45e562320ee', - 'de': '788ef0a5-492f-48a7-87dc-b15dda185bb8' - }, - + {'en': '57747eb3-411a-4efd-8842-a45e562320ee', 'de': '788ef0a5-492f-48a7-87dc-b15dda185bb8'}, # 119 9926e18f-4e2b-4c20-9477-9bfb08d229bc Shoulder Press, Barbell # 266 197600e7-9bb2-448c-baca-244d679e7b07 Schulterdrücken LH - { - 'en': '9926e18f-4e2b-4c20-9477-9bfb08d229bc', - 'de': '197600e7-9bb2-448c-baca-244d679e7b07' - }, - + {'en': '9926e18f-4e2b-4c20-9477-9bfb08d229bc', 'de': '197600e7-9bb2-448c-baca-244d679e7b07'}, # 123 1df6a1b5-7bd2-402f-9d5e-94f9ed6d8b54 Shoulder Press, Dumbbells # 241 0d4390ea-51dc-42dc-94af-ba0e94a73484 Schulterdrücken KH - { - 'en': '1df6a1b5-7bd2-402f-9d5e-94f9ed6d8b54', - 'de': '0d4390ea-51dc-42dc-94af-ba0e94a73484' - }, - + {'en': '1df6a1b5-7bd2-402f-9d5e-94f9ed6d8b54', 'de': '0d4390ea-51dc-42dc-94af-ba0e94a73484'}, # 107 7ce6b090-5099-4cd0-83ae-1a02725c868b Pull-ups # 36 4e741c73-d40a-4fad-b0e0-76edd9bbe8df Klimmzüge - { - 'en': '7ce6b090-5099-4cd0-83ae-1a02725c868b', - 'de': '4e741c73-d40a-4fad-b0e0-76edd9bbe8df' - }, - + {'en': '7ce6b090-5099-4cd0-83ae-1a02725c868b', 'de': '4e741c73-d40a-4fad-b0e0-76edd9bbe8df'}, # 140 d46adbda-7c60-42a0-b1fd-9ec111b35956 Pull Ups on Machine # 48 22897ebe-cf17-44cf-97e6-87566285684d Klimmzüge an Maschine - { - 'en': 'd46adbda-7c60-42a0-b1fd-9ec111b35956', - 'de': '22897ebe-cf17-44cf-97e6-87566285684d' - }, - + {'en': 'd46adbda-7c60-42a0-b1fd-9ec111b35956', 'de': '22897ebe-cf17-44cf-97e6-87566285684d'}, # 87 d147a6c2-ce64-424b-baf3-4ca841a51512 Dumbbells on Scott Machine # 28 d7c553b1-e84d-4dbc-9f6c-05db489b27c8 KH an Scottmaschine - { - 'en': 'd147a6c2-ce64-424b-baf3-4ca841a51512', - 'de': 'd7c553b1-e84d-4dbc-9f6c-05db489b27c8' - }, - + {'en': 'd147a6c2-ce64-424b-baf3-4ca841a51512', 'de': 'd7c553b1-e84d-4dbc-9f6c-05db489b27c8'}, # 100 b72ae8d4-ede6-4480-8fc5-7b80e369f7ed Decline Bench Press Barbell # 17 3ef8a516-d0d4-4078-9b4a-d7783da0fcf7 Negativ Bankdrücken - { - 'en': 'b72ae8d4-ede6-4480-8fc5-7b80e369f7ed', - 'de': '3ef8a516-d0d4-4078-9b4a-d7783da0fcf7' - }, - + {'en': 'b72ae8d4-ede6-4480-8fc5-7b80e369f7ed', 'de': '3ef8a516-d0d4-4078-9b4a-d7783da0fcf7'}, # 101 80d318b3-4b8a-41aa-9c6c-0a2a921fe1e6 Decline Bench Press Dumbbell # 720 341c73d5-2e9a-4f13-89c9-c984c86cc088 Negativ Bankdrücken KH - { - 'en': '80d318b3-4b8a-41aa-9c6c-0a2a921fe1e6', - 'de': '341c73d5-2e9a-4f13-89c9-c984c86cc088' - }, - + {'en': '80d318b3-4b8a-41aa-9c6c-0a2a921fe1e6', 'de': '341c73d5-2e9a-4f13-89c9-c984c86cc088'}, # 318 bd07fc6b-db86-4139-b6de-e328cea0f694 Turkish Get-Up # 717 1546af08-017c-4de5-b13f-cb3a1999733d Turkish Get-Up - { - 'en': 'bd07fc6b-db86-4139-b6de-e328cea0f694', - 'de': '1546af08-017c-4de5-b13f-cb3a1999733d' - }, - + {'en': 'bd07fc6b-db86-4139-b6de-e328cea0f694', 'de': '1546af08-017c-4de5-b13f-cb3a1999733d'}, # 154 cd4fac32-48fb-4237-a263-a44c5108790a Leg Curls (laying) # 22 8f0170a2-5274-4487-a295-1a9baf2c92a3 Beinbeuger Liegend - { - 'en': 'cd4fac32-48fb-4237-a263-a44c5108790a', - 'de': '8f0170a2-5274-4487-a295-1a9baf2c92a3' - }, - + {'en': 'cd4fac32-48fb-4237-a263-a44c5108790a', 'de': '8f0170a2-5274-4487-a295-1a9baf2c92a3'}, # 118 89c98117-dd53-4334-bfa6-72a96525629a Leg Curls (standing) # 72 9075241c-0493-4f2a-a399-a57e3634093e Beinbeuger Stehend - { - 'en': '89c98117-dd53-4334-bfa6-72a96525629a', - 'de': '9075241c-0493-4f2a-a399-a57e3634093e' - }, - + {'en': '89c98117-dd53-4334-bfa6-72a96525629a', 'de': '9075241c-0493-4f2a-a399-a57e3634093e'}, # 263 9f622058-85a4-4272-ad99-e5696e772137 Roman Chair # 714 68f96d3e-9172-468c-9018-06f71a97faff Beinheben am Roman Chair - { - 'en': '9f622058-85a4-4272-ad99-e5696e772137', - 'de': '68f96d3e-9172-468c-9018-06f71a97faff' - }, - + {'en': '9f622058-85a4-4272-ad99-e5696e772137', 'de': '68f96d3e-9172-468c-9018-06f71a97faff'}, # 421 170cc52f-345f-41b3-bdae-8a5e0c9aa449 Bent-over Lateral Raises # 47 e701de98-32c6-4e9d-956d-434cf5bcaaf0 Vorgebeugtes Seitheben - { - 'en': '170cc52f-345f-41b3-bdae-8a5e0c9aa449', - 'de': 'e701de98-32c6-4e9d-956d-434cf5bcaaf0' - }, - + {'en': '170cc52f-345f-41b3-bdae-8a5e0c9aa449', 'de': 'e701de98-32c6-4e9d-956d-434cf5bcaaf0'}, # 185 bdb7bdbb-8930-46e5-8b98-eb13e604553f Squat Jumps # 296 032a38cf-b15a-4761-b684-577e41893f54 Tiefe Hocksprünge - { - 'en': 'bdb7bdbb-8930-46e5-8b98-eb13e604553f', - 'de': '032a38cf-b15a-4761-b684-577e41893f54' - }, + {'en': 'bdb7bdbb-8930-46e5-8b98-eb13e604553f', 'de': '032a38cf-b15a-4761-b684-577e41893f54'}, ] @@ -652,7 +299,7 @@ def create_exercise_mapping(apps, schema_editor): pass # print(exercise_group[lang], "does not exist") - if (len(exercise_objects) > 0): + if len(exercise_objects) > 0: exercise_base_main = exercise_objects[0].exercise_base for exercise in exercise_objects[1:]: ExerciseBase.objects.get(id=exercise.exercise_base.id).delete() @@ -668,7 +315,6 @@ def remove_mappings(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ('exercises', '0010_auto_20201211_0205'), ] diff --git a/wger/exercises/migrations/0012_auto_20210327_1219.py b/wger/exercises/migrations/0012_auto_20210327_1219.py index de1dba97d..b8759d972 100644 --- a/wger/exercises/migrations/0012_auto_20210327_1219.py +++ b/wger/exercises/migrations/0012_auto_20210327_1219.py @@ -7,14 +7,13 @@ import uuid def generate_uuids(apps, schema_editor): """Generate new UUIDs for each exercise image""" - ExcerciseImage = apps.get_model("exercises", "ExerciseImage") + ExcerciseImage = apps.get_model('exercises', 'ExerciseImage') for exercise in ExcerciseImage.objects.all(): exercise.uuid = uuid.uuid4() exercise.save() class Migration(migrations.Migration): - dependencies = [ ('exercises', '0011_auto_20201214_0033'), ] diff --git a/wger/exercises/migrations/0013_auto_20210503_1232.py b/wger/exercises/migrations/0013_auto_20210503_1232.py index ef37b2107..ebc71ae54 100644 --- a/wger/exercises/migrations/0013_auto_20210503_1232.py +++ b/wger/exercises/migrations/0013_auto_20210503_1232.py @@ -5,7 +5,6 @@ import django.db.models.deletion class Migration(migrations.Migration): - dependencies = [ ('exercises', '0012_auto_20210327_1219'), ] @@ -26,7 +25,7 @@ class Migration(migrations.Migration): 'CC-BY-SA.', max_length=50, null=True, - verbose_name='Author' + verbose_name='Author', ), ), migrations.AlterField( @@ -37,7 +36,7 @@ class Migration(migrations.Migration): null=True, on_delete=django.db.models.deletion.CASCADE, to='exercises.variation', - verbose_name='Variations' + verbose_name='Variations', ), ), ] diff --git a/wger/exercises/migrations/0014_exerciseimage_style.py b/wger/exercises/migrations/0014_exerciseimage_style.py index 91dd36424..e391d3c3f 100644 --- a/wger/exercises/migrations/0014_exerciseimage_style.py +++ b/wger/exercises/migrations/0014_exerciseimage_style.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('exercises', '0013_auto_20210503_1232'), ] @@ -15,11 +14,15 @@ class Migration(migrations.Migration): name='style', field=models.CharField( choices=[ - ('1', 'Line'), ('2', '3D'), ('3', 'Low-poly'), ('4', 'Photo'), ('5', 'Other') + ('1', 'Line'), + ('2', '3D'), + ('3', 'Low-poly'), + ('4', 'Photo'), + ('5', 'Other'), ], default='1', help_text='The art style of your image', - max_length=1 + max_length=1, ), ), ] diff --git a/wger/exercises/migrations/0015_exercise_videos.py b/wger/exercises/migrations/0015_exercise_videos.py index 478124198..3d0d874bc 100644 --- a/wger/exercises/migrations/0015_exercise_videos.py +++ b/wger/exercises/migrations/0015_exercise_videos.py @@ -7,7 +7,6 @@ import wger.exercises.models.video class Migration(migrations.Migration): - dependencies = [ ('core', '0013_auto_20210726_1729'), ('exercises', '0014_exerciseimage_style'), @@ -19,11 +18,15 @@ class Migration(migrations.Migration): name='style', field=models.CharField( choices=[ - ('1', 'Line'), ('2', '3D'), ('3', 'Low-poly'), ('4', 'Photo'), ('5', 'Other') + ('1', 'Line'), + ('2', '3D'), + ('3', 'Low-poly'), + ('4', 'Photo'), + ('5', 'Other'), ], default='4', help_text='The art style of your image', - max_length=1 + max_length=1, ), ), migrations.CreateModel( @@ -33,18 +36,17 @@ class Migration(migrations.Migration): 'id', models.AutoField( auto_created=True, primary_key=True, serialize=False, verbose_name='ID' - ) + ), ), ( 'license_author', models.CharField( blank=True, - help_text= - 'If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', + help_text='If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', max_length=50, null=True, - verbose_name='Author' - ) + verbose_name='Author', + ), ), ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, verbose_name='UUID')), ('is_main', models.BooleanField(default=False, verbose_name='Main video')), @@ -53,8 +55,8 @@ class Migration(migrations.Migration): models.FileField( upload_to=wger.exercises.models.video.exercise_video_upload_dir, validators=[wger.exercises.models.video.validate_video], - verbose_name='Video' - ) + verbose_name='Video', + ), ), ('size', models.IntegerField(default=0, editable=False, verbose_name='Size')), ( @@ -64,8 +66,8 @@ class Migration(migrations.Migration): default=0, editable=False, max_digits=12, - verbose_name='Duration' - ) + verbose_name='Duration', + ), ), ('width', models.IntegerField(default=0, editable=False, verbose_name='Width')), ('height', models.IntegerField(default=0, editable=False, verbose_name='Height')), @@ -73,21 +75,21 @@ class Migration(migrations.Migration): 'codec', models.CharField( default='', editable=False, max_length=30, verbose_name='Codec' - ) + ), ), ( 'codec_long', models.CharField( default='', editable=False, max_length=100, verbose_name='Codec, long name' - ) + ), ), ( 'exercise_base', models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, to='exercises.exercisebase', - verbose_name='Exercise' - ) + verbose_name='Exercise', + ), ), ( 'license', @@ -95,8 +97,8 @@ class Migration(migrations.Migration): default=2, on_delete=django.db.models.deletion.CASCADE, to='core.license', - verbose_name='License' - ) + verbose_name='License', + ), ), ], options={ diff --git a/wger/exercises/migrations/0016_exercisealias.py b/wger/exercises/migrations/0016_exercisealias.py index 7d87d47ba..e72b0958b 100644 --- a/wger/exercises/migrations/0016_exercisealias.py +++ b/wger/exercises/migrations/0016_exercisealias.py @@ -5,7 +5,6 @@ import django.db.models.deletion class Migration(migrations.Migration): - dependencies = [ ('exercises', '0015_exercise_videos'), ] @@ -18,7 +17,7 @@ class Migration(migrations.Migration): 'id', models.AutoField( auto_created=True, primary_key=True, serialize=False, verbose_name='ID' - ) + ), ), ('alias', models.CharField(max_length=200, verbose_name='Alias for an exercise')), ( @@ -26,8 +25,8 @@ class Migration(migrations.Migration): models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, to='exercises.exercise', - verbose_name='Exercise' - ) + verbose_name='Exercise', + ), ), ], ), diff --git a/wger/exercises/migrations/0017_muscle_name_en.py b/wger/exercises/migrations/0017_muscle_name_en.py index 35c5ad432..e86cb81af 100644 --- a/wger/exercises/migrations/0017_muscle_name_en.py +++ b/wger/exercises/migrations/0017_muscle_name_en.py @@ -31,7 +31,6 @@ def set_names(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ('exercises', '0016_exercisealias'), ] @@ -44,7 +43,7 @@ class Migration(migrations.Migration): default='', help_text='A more basic name for the muscle', max_length=50, - verbose_name='Alternative name' + verbose_name='Alternative name', ), ), migrations.RunPython(set_names), diff --git a/wger/exercises/migrations/0018_delete_pending_exercises.py b/wger/exercises/migrations/0018_delete_pending_exercises.py index f7aa64767..1c9a3c249 100644 --- a/wger/exercises/migrations/0018_delete_pending_exercises.py +++ b/wger/exercises/migrations/0018_delete_pending_exercises.py @@ -11,7 +11,7 @@ def delete_pending_bases(apps, schema_editor): Note that we can't access STATUS_PENDING here because we are not using a real model. """ - Base = apps.get_model("exercises", "ExerciseBase") + Base = apps.get_model('exercises', 'ExerciseBase') Base.objects.filter(status='1').delete() @@ -22,12 +22,11 @@ def delete_pending_translations(apps, schema_editor): Note that we can't access STATUS_PENDING here because we are not using a real model. """ - Exercise = apps.get_model("exercises", "Exercise") + Exercise = apps.get_model('exercises', 'Exercise') Exercise.objects.filter(status='1').delete() class Migration(migrations.Migration): - dependencies = [ ('core', '0014_merge_20210818_1735'), migrations.swappable_dependency(settings.AUTH_USER_MODEL), diff --git a/wger/exercises/migrations/0019_exercise_crowdsourcing_changes.py b/wger/exercises/migrations/0019_exercise_crowdsourcing_changes.py index bd35b4f5a..ff62497d3 100644 --- a/wger/exercises/migrations/0019_exercise_crowdsourcing_changes.py +++ b/wger/exercises/migrations/0019_exercise_crowdsourcing_changes.py @@ -10,7 +10,6 @@ import uuid class Migration(migrations.Migration): - dependencies = [ ('exercises', '0018_delete_pending_exercises'), ] @@ -54,7 +53,7 @@ class Migration(migrations.Migration): null=True, on_delete=django.db.models.deletion.SET_NULL, to='exercises.variation', - verbose_name='Variations' + verbose_name='Variations', ), ), migrations.AlterField( @@ -63,7 +62,7 @@ class Migration(migrations.Migration): field=models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, to='exercises.exercise', - verbose_name='Exercise' + verbose_name='Exercise', ), ), migrations.CreateModel( @@ -73,15 +72,15 @@ class Migration(migrations.Migration): 'id', models.IntegerField( auto_created=True, blank=True, db_index=True, verbose_name='ID' - ) + ), ), ( 'comment', models.CharField( help_text='A comment about how to correctly do this exercise.', max_length=200, - verbose_name='Comment' - ) + verbose_name='Comment', + ), ), ('history_id', models.AutoField(primary_key=True, serialize=False)), ('history_date', models.DateTimeField(db_index=True)), @@ -89,9 +88,8 @@ class Migration(migrations.Migration): ( 'history_type', models.CharField( - choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], - max_length=1 - ) + choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1 + ), ), ( 'exercise', @@ -102,8 +100,8 @@ class Migration(migrations.Migration): on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='exercises.exercise', - verbose_name='Exercise' - ) + verbose_name='Exercise', + ), ), ( 'history_user', @@ -111,8 +109,8 @@ class Migration(migrations.Migration): null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', - to=settings.AUTH_USER_MODEL - ) + to=settings.AUTH_USER_MODEL, + ), ), ], options={ @@ -130,27 +128,26 @@ class Migration(migrations.Migration): 'id', models.IntegerField( auto_created=True, blank=True, db_index=True, verbose_name='ID' - ) + ), ), ( 'license_author', models.CharField( blank=True, - help_text= - 'If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', + help_text='If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', max_length=50, null=True, - verbose_name='Author' - ) + verbose_name='Author', + ), ), ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, verbose_name='UUID')), ( 'creation_date', - models.DateField(blank=True, editable=False, verbose_name='Date') + models.DateField(blank=True, editable=False, verbose_name='Date'), ), ( 'update_date', - models.DateTimeField(blank=True, editable=False, verbose_name='Date') + models.DateTimeField(blank=True, editable=False, verbose_name='Date'), ), ('history_id', models.AutoField(primary_key=True, serialize=False)), ('history_date', models.DateTimeField(db_index=True)), @@ -158,9 +155,8 @@ class Migration(migrations.Migration): ( 'history_type', models.CharField( - choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], - max_length=1 - ) + choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1 + ), ), ( 'category', @@ -171,8 +167,8 @@ class Migration(migrations.Migration): on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='exercises.exercisecategory', - verbose_name='Category' - ) + verbose_name='Category', + ), ), ( 'history_user', @@ -180,8 +176,8 @@ class Migration(migrations.Migration): null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', - to=settings.AUTH_USER_MODEL - ) + to=settings.AUTH_USER_MODEL, + ), ), ( 'license', @@ -193,8 +189,8 @@ class Migration(migrations.Migration): on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='core.license', - verbose_name='License' - ) + verbose_name='License', + ), ), ( 'variations', @@ -205,8 +201,8 @@ class Migration(migrations.Migration): on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='exercises.variation', - verbose_name='Variations' - ) + verbose_name='Variations', + ), ), ], options={ @@ -224,35 +220,34 @@ class Migration(migrations.Migration): 'id', models.IntegerField( auto_created=True, blank=True, db_index=True, verbose_name='ID' - ) + ), ), ( 'license_author', models.CharField( blank=True, - help_text= - 'If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', + help_text='If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', max_length=50, null=True, - verbose_name='Author' - ) + verbose_name='Author', + ), ), ( 'description', models.TextField( max_length=2000, validators=[django.core.validators.MinLengthValidator(40)], - verbose_name='Description' - ) + verbose_name='Description', + ), ), ('name', models.CharField(max_length=200, verbose_name='Name')), ( 'creation_date', - models.DateField(blank=True, editable=False, null=True, verbose_name='Date') + models.DateField(blank=True, editable=False, null=True, verbose_name='Date'), ), ( 'update_date', - models.DateTimeField(blank=True, editable=False, verbose_name='Date') + models.DateTimeField(blank=True, editable=False, verbose_name='Date'), ), ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, verbose_name='UUID')), ('history_id', models.AutoField(primary_key=True, serialize=False)), @@ -261,9 +256,8 @@ class Migration(migrations.Migration): ( 'history_type', models.CharField( - choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], - max_length=1 - ) + choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1 + ), ), ( 'exercise_base', @@ -275,8 +269,8 @@ class Migration(migrations.Migration): on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='exercises.exercisebase', - verbose_name='ExerciseBase' - ) + verbose_name='ExerciseBase', + ), ), ( 'history_user', @@ -284,8 +278,8 @@ class Migration(migrations.Migration): null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', - to=settings.AUTH_USER_MODEL - ) + to=settings.AUTH_USER_MODEL, + ), ), ( 'language', @@ -296,8 +290,8 @@ class Migration(migrations.Migration): on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='core.language', - verbose_name='Language' - ) + verbose_name='Language', + ), ), ( 'license', @@ -309,8 +303,8 @@ class Migration(migrations.Migration): on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='core.license', - verbose_name='License' - ) + verbose_name='License', + ), ), ], options={ @@ -328,7 +322,7 @@ class Migration(migrations.Migration): 'id', models.IntegerField( auto_created=True, blank=True, db_index=True, verbose_name='ID' - ) + ), ), ('alias', models.CharField(max_length=200, verbose_name='Alias for an exercise')), ('history_id', models.AutoField(primary_key=True, serialize=False)), @@ -337,9 +331,8 @@ class Migration(migrations.Migration): ( 'history_type', models.CharField( - choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], - max_length=1 - ) + choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1 + ), ), ( 'exercise', @@ -350,8 +343,8 @@ class Migration(migrations.Migration): on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='exercises.exercise', - verbose_name='Exercise' - ) + verbose_name='Exercise', + ), ), ( 'history_user', @@ -359,8 +352,8 @@ class Migration(migrations.Migration): null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', - to=settings.AUTH_USER_MODEL - ) + to=settings.AUTH_USER_MODEL, + ), ), ], options={ @@ -383,7 +376,7 @@ class Migration(migrations.Migration): on_delete=django.db.models.deletion.CASCADE, related_name='exercises', to='exercises.exercisebase', - verbose_name='ExerciseBase' + verbose_name='ExerciseBase', ), ), migrations.AlterField( @@ -397,7 +390,7 @@ class Migration(migrations.Migration): on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='exercises.exercisebase', - verbose_name='ExerciseBase' + verbose_name='ExerciseBase', ), ), ] diff --git a/wger/exercises/migrations/0020_historicalexerciseimage_historicalexercisevideo.py b/wger/exercises/migrations/0020_historicalexerciseimage_historicalexercisevideo.py index cf8734d0d..bbc41ea88 100644 --- a/wger/exercises/migrations/0020_historicalexerciseimage_historicalexercisevideo.py +++ b/wger/exercises/migrations/0020_historicalexerciseimage_historicalexercisevideo.py @@ -9,7 +9,6 @@ import wger.exercises.models.video class Migration(migrations.Migration): - dependencies = [ ('core', '0014_merge_20210818_1735'), migrations.swappable_dependency(settings.AUTH_USER_MODEL), @@ -24,18 +23,17 @@ class Migration(migrations.Migration): 'id', models.IntegerField( auto_created=True, blank=True, db_index=True, verbose_name='ID' - ) + ), ), ( 'license_author', models.CharField( blank=True, - help_text= - 'If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', + help_text='If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', max_length=50, null=True, - verbose_name='Author' - ) + verbose_name='Author', + ), ), ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, verbose_name='UUID')), ('is_main', models.BooleanField(default=False, verbose_name='Main video')), @@ -44,8 +42,8 @@ class Migration(migrations.Migration): models.TextField( max_length=100, validators=[wger.exercises.models.video.validate_video], - verbose_name='Video' - ) + verbose_name='Video', + ), ), ('size', models.IntegerField(default=0, editable=False, verbose_name='Size')), ( @@ -55,8 +53,8 @@ class Migration(migrations.Migration): default=0, editable=False, max_digits=12, - verbose_name='Duration' - ) + verbose_name='Duration', + ), ), ('width', models.IntegerField(default=0, editable=False, verbose_name='Width')), ('height', models.IntegerField(default=0, editable=False, verbose_name='Height')), @@ -64,13 +62,13 @@ class Migration(migrations.Migration): 'codec', models.CharField( default='', editable=False, max_length=30, verbose_name='Codec' - ) + ), ), ( 'codec_long', models.CharField( default='', editable=False, max_length=100, verbose_name='Codec, long name' - ) + ), ), ('history_id', models.AutoField(primary_key=True, serialize=False)), ('history_date', models.DateTimeField(db_index=True)), @@ -78,9 +76,8 @@ class Migration(migrations.Migration): ( 'history_type', models.CharField( - choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], - max_length=1 - ) + choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1 + ), ), ( 'exercise_base', @@ -91,8 +88,8 @@ class Migration(migrations.Migration): on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='exercises.exercisebase', - verbose_name='Exercise' - ) + verbose_name='Exercise', + ), ), ( 'history_user', @@ -100,8 +97,8 @@ class Migration(migrations.Migration): null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', - to=settings.AUTH_USER_MODEL - ) + to=settings.AUTH_USER_MODEL, + ), ), ( 'license', @@ -113,8 +110,8 @@ class Migration(migrations.Migration): on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='core.license', - verbose_name='License' - ) + verbose_name='License', + ), ), ], options={ @@ -132,18 +129,17 @@ class Migration(migrations.Migration): 'id', models.IntegerField( auto_created=True, blank=True, db_index=True, verbose_name='ID' - ) + ), ), ( 'license_author', models.CharField( blank=True, - help_text= - 'If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', + help_text='If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', max_length=50, null=True, - verbose_name='Author' - ) + verbose_name='Author', + ), ), ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, verbose_name='UUID')), ( @@ -151,29 +147,31 @@ class Migration(migrations.Migration): models.TextField( help_text='Only PNG and JPEG formats are supported', max_length=100, - verbose_name='Image' - ) + verbose_name='Image', + ), ), ( 'is_main', models.BooleanField( default=False, - help_text= - 'Tick the box if you want to set this image as the main one for the exercise (will be shown e.g. in the search). The first image is automatically marked by the system.', - verbose_name='Main picture' - ) + help_text='Tick the box if you want to set this image as the main one for the exercise (will be shown e.g. in the search). The first image is automatically marked by the system.', + verbose_name='Main picture', + ), ), ( 'style', models.CharField( choices=[ - ('1', 'Line'), ('2', '3D'), ('3', 'Low-poly'), ('4', 'Photo'), - ('5', 'Other') + ('1', 'Line'), + ('2', '3D'), + ('3', 'Low-poly'), + ('4', 'Photo'), + ('5', 'Other'), ], default='4', help_text='The art style of your image', - max_length=1 - ) + max_length=1, + ), ), ('history_id', models.AutoField(primary_key=True, serialize=False)), ('history_date', models.DateTimeField(db_index=True)), @@ -181,9 +179,8 @@ class Migration(migrations.Migration): ( 'history_type', models.CharField( - choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], - max_length=1 - ) + choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1 + ), ), ( 'exercise_base', @@ -194,8 +191,8 @@ class Migration(migrations.Migration): on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='exercises.exercisebase', - verbose_name='Exercise' - ) + verbose_name='Exercise', + ), ), ( 'history_user', @@ -203,8 +200,8 @@ class Migration(migrations.Migration): null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', - to=settings.AUTH_USER_MODEL - ) + to=settings.AUTH_USER_MODEL, + ), ), ( 'license', @@ -216,8 +213,8 @@ class Migration(migrations.Migration): on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='core.license', - verbose_name='License' - ) + verbose_name='License', + ), ), ], options={ diff --git a/wger/exercises/migrations/0021_deletionlog.py b/wger/exercises/migrations/0021_deletionlog.py index a02558c97..10bd677b4 100644 --- a/wger/exercises/migrations/0021_deletionlog.py +++ b/wger/exercises/migrations/0021_deletionlog.py @@ -5,7 +5,6 @@ import uuid class Migration(migrations.Migration): - dependencies = [ ('exercises', '0020_historicalexerciseimage_historicalexercisevideo'), ] @@ -18,17 +17,19 @@ class Migration(migrations.Migration): 'id', models.AutoField( auto_created=True, primary_key=True, serialize=False, verbose_name='ID' - ) + ), ), ( 'model_type', models.CharField( choices=[ - ('base', 'base'), ('translation', 'translation'), ('image', 'image'), - ('video', 'video') + ('base', 'base'), + ('translation', 'translation'), + ('image', 'image'), + ('video', 'video'), ], - max_length=11 - ) + max_length=11, + ), ), ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, verbose_name='UUID')), ('timestamp', models.DateTimeField(auto_now=True)), diff --git a/wger/exercises/migrations/0022_alter_exercise_license_author_and_more.py b/wger/exercises/migrations/0022_alter_exercise_license_author_and_more.py index b58b1c8ff..4f7f083c2 100644 --- a/wger/exercises/migrations/0022_alter_exercise_license_author_and_more.py +++ b/wger/exercises/migrations/0022_alter_exercise_license_author_and_more.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('exercises', '0021_deletionlog'), ] @@ -15,11 +14,10 @@ class Migration(migrations.Migration): name='license_author', field=models.CharField( blank=True, - help_text= - 'If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', + help_text='If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', max_length=60, null=True, - verbose_name='Author' + verbose_name='Author', ), ), migrations.AlterField( @@ -27,11 +25,10 @@ class Migration(migrations.Migration): name='license_author', field=models.CharField( blank=True, - help_text= - 'If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', + help_text='If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', max_length=60, null=True, - verbose_name='Author' + verbose_name='Author', ), ), migrations.AlterField( @@ -39,11 +36,10 @@ class Migration(migrations.Migration): name='license_author', field=models.CharField( blank=True, - help_text= - 'If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', + help_text='If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', max_length=60, null=True, - verbose_name='Author' + verbose_name='Author', ), ), migrations.AlterField( @@ -51,11 +47,10 @@ class Migration(migrations.Migration): name='license_author', field=models.CharField( blank=True, - help_text= - 'If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', + help_text='If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', max_length=60, null=True, - verbose_name='Author' + verbose_name='Author', ), ), migrations.AlterField( @@ -63,11 +58,10 @@ class Migration(migrations.Migration): name='license_author', field=models.CharField( blank=True, - help_text= - 'If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', + help_text='If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', max_length=60, null=True, - verbose_name='Author' + verbose_name='Author', ), ), migrations.AlterField( @@ -75,11 +69,10 @@ class Migration(migrations.Migration): name='license_author', field=models.CharField( blank=True, - help_text= - 'If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', + help_text='If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', max_length=60, null=True, - verbose_name='Author' + verbose_name='Author', ), ), migrations.AlterField( @@ -87,11 +80,10 @@ class Migration(migrations.Migration): name='license_author', field=models.CharField( blank=True, - help_text= - 'If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', + help_text='If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', max_length=60, null=True, - verbose_name='Author' + verbose_name='Author', ), ), migrations.AlterField( @@ -99,11 +91,10 @@ class Migration(migrations.Migration): name='license_author', field=models.CharField( blank=True, - help_text= - 'If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', + help_text='If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', max_length=60, null=True, - verbose_name='Author' + verbose_name='Author', ), ), ] diff --git a/wger/exercises/migrations/0023_make_uuid_unique.py b/wger/exercises/migrations/0023_make_uuid_unique.py index 49d51cb89..0bb67e76a 100644 --- a/wger/exercises/migrations/0023_make_uuid_unique.py +++ b/wger/exercises/migrations/0023_make_uuid_unique.py @@ -5,7 +5,6 @@ import uuid class Migration(migrations.Migration): - dependencies = [ ('exercises', '0022_alter_exercise_license_author_and_more'), ] diff --git a/wger/exercises/migrations/0024_license_information.py b/wger/exercises/migrations/0024_license_information.py index 008a59a2f..f15cba9e0 100644 --- a/wger/exercises/migrations/0024_license_information.py +++ b/wger/exercises/migrations/0024_license_information.py @@ -123,7 +123,7 @@ class Migration(migrations.Migration): field=models.CharField( blank=True, max_length=200, - verbose_name='The original title of this object, if available' + verbose_name='The original title of this object, if available', ), ), migrations.AddField( @@ -329,7 +329,7 @@ class Migration(migrations.Migration): help_text='If you are not the author, enter the name or source here.', max_length=200, null=True, - verbose_name='Author(s)' + verbose_name='Author(s)', ), ), migrations.AlterField( @@ -340,7 +340,7 @@ class Migration(migrations.Migration): help_text='If you are not the author, enter the name or source here.', max_length=200, null=True, - verbose_name='Author(s)' + verbose_name='Author(s)', ), ), migrations.AlterField( @@ -351,7 +351,7 @@ class Migration(migrations.Migration): help_text='If you are not the author, enter the name or source here.', max_length=200, null=True, - verbose_name='Author(s)' + verbose_name='Author(s)', ), ), migrations.AlterField( @@ -362,7 +362,7 @@ class Migration(migrations.Migration): help_text='If you are not the author, enter the name or source here.', max_length=200, null=True, - verbose_name='Author(s)' + verbose_name='Author(s)', ), ), migrations.AlterField( @@ -373,7 +373,7 @@ class Migration(migrations.Migration): help_text='If you are not the author, enter the name or source here.', max_length=200, null=True, - verbose_name='Author(s)' + verbose_name='Author(s)', ), ), migrations.AlterField( @@ -384,7 +384,7 @@ class Migration(migrations.Migration): help_text='If you are not the author, enter the name or source here.', max_length=200, null=True, - verbose_name='Author(s)' + verbose_name='Author(s)', ), ), migrations.AlterField( @@ -395,7 +395,7 @@ class Migration(migrations.Migration): help_text='If you are not the author, enter the name or source here.', max_length=200, null=True, - verbose_name='Author(s)' + verbose_name='Author(s)', ), ), migrations.AlterField( @@ -406,7 +406,7 @@ class Migration(migrations.Migration): help_text='If you are not the author, enter the name or source here.', max_length=200, null=True, - verbose_name='Author(s)' + verbose_name='Author(s)', ), ), ] diff --git a/wger/exercises/migrations/0026_deletionlog_replaced_by.py b/wger/exercises/migrations/0026_deletionlog_replaced_by.py index a31b23c54..2050d09ee 100644 --- a/wger/exercises/migrations/0026_deletionlog_replaced_by.py +++ b/wger/exercises/migrations/0026_deletionlog_replaced_by.py @@ -17,7 +17,7 @@ class Migration(migrations.Migration): editable=False, help_text='UUID of the object ', null=True, - verbose_name='Replaced by' + verbose_name='Replaced by', ), ), ] diff --git a/wger/exercises/migrations/0027_alter_deletionlog_replaced_by_and_more.py b/wger/exercises/migrations/0027_alter_deletionlog_replaced_by_and_more.py index 28083b3a8..f547a1afb 100644 --- a/wger/exercises/migrations/0027_alter_deletionlog_replaced_by_and_more.py +++ b/wger/exercises/migrations/0027_alter_deletionlog_replaced_by_and_more.py @@ -15,10 +15,9 @@ class Migration(migrations.Migration): field=models.UUIDField( default=None, editable=False, - help_text= - 'UUID of the object replaced by the deleted one. At the moment only available for exercise bases', + help_text='UUID of the object replaced by the deleted one. At the moment only available for exercise bases', null=True, - verbose_name='Replaced by' + verbose_name='Replaced by', ), ), migrations.AlterField( @@ -29,7 +28,7 @@ class Migration(migrations.Migration): help_text='If you are not the author, enter the name or source here.', max_length=600, null=True, - verbose_name='Author(s)' + verbose_name='Author(s)', ), ), migrations.AlterField( @@ -42,9 +41,8 @@ class Migration(migrations.Migration): name='license_derivative_source_url', field=models.URLField( blank=True, - help_text= - 'Note that a derivative work is one which is not only based on a previous work, but which also contains sufficient new, creative content to entitle it to its own copyright.', - verbose_name='Link to the original source, if this is a derivative work' + help_text='Note that a derivative work is one which is not only based on a previous work, but which also contains sufficient new, creative content to entitle it to its own copyright.', + verbose_name='Link to the original source, if this is a derivative work', ), ), migrations.AlterField( @@ -58,7 +56,7 @@ class Migration(migrations.Migration): field=models.CharField( blank=True, max_length=300, - verbose_name='The original title of this object, if available' + verbose_name='The original title of this object, if available', ), ), migrations.AlterField( @@ -69,7 +67,7 @@ class Migration(migrations.Migration): help_text='If you are not the author, enter the name or source here.', max_length=600, null=True, - verbose_name='Author(s)' + verbose_name='Author(s)', ), ), migrations.AlterField( @@ -82,9 +80,8 @@ class Migration(migrations.Migration): name='license_derivative_source_url', field=models.URLField( blank=True, - help_text= - 'Note that a derivative work is one which is not only based on a previous work, but which also contains sufficient new, creative content to entitle it to its own copyright.', - verbose_name='Link to the original source, if this is a derivative work' + help_text='Note that a derivative work is one which is not only based on a previous work, but which also contains sufficient new, creative content to entitle it to its own copyright.', + verbose_name='Link to the original source, if this is a derivative work', ), ), migrations.AlterField( @@ -98,7 +95,7 @@ class Migration(migrations.Migration): field=models.CharField( blank=True, max_length=300, - verbose_name='The original title of this object, if available' + verbose_name='The original title of this object, if available', ), ), migrations.AlterField( @@ -109,7 +106,7 @@ class Migration(migrations.Migration): help_text='If you are not the author, enter the name or source here.', max_length=600, null=True, - verbose_name='Author(s)' + verbose_name='Author(s)', ), ), migrations.AlterField( @@ -122,9 +119,8 @@ class Migration(migrations.Migration): name='license_derivative_source_url', field=models.URLField( blank=True, - help_text= - 'Note that a derivative work is one which is not only based on a previous work, but which also contains sufficient new, creative content to entitle it to its own copyright.', - verbose_name='Link to the original source, if this is a derivative work' + help_text='Note that a derivative work is one which is not only based on a previous work, but which also contains sufficient new, creative content to entitle it to its own copyright.', + verbose_name='Link to the original source, if this is a derivative work', ), ), migrations.AlterField( @@ -138,7 +134,7 @@ class Migration(migrations.Migration): field=models.CharField( blank=True, max_length=300, - verbose_name='The original title of this object, if available' + verbose_name='The original title of this object, if available', ), ), migrations.AlterField( @@ -149,7 +145,7 @@ class Migration(migrations.Migration): help_text='If you are not the author, enter the name or source here.', max_length=600, null=True, - verbose_name='Author(s)' + verbose_name='Author(s)', ), ), migrations.AlterField( @@ -162,9 +158,8 @@ class Migration(migrations.Migration): name='license_derivative_source_url', field=models.URLField( blank=True, - help_text= - 'Note that a derivative work is one which is not only based on a previous work, but which also contains sufficient new, creative content to entitle it to its own copyright.', - verbose_name='Link to the original source, if this is a derivative work' + help_text='Note that a derivative work is one which is not only based on a previous work, but which also contains sufficient new, creative content to entitle it to its own copyright.', + verbose_name='Link to the original source, if this is a derivative work', ), ), migrations.AlterField( @@ -178,7 +173,7 @@ class Migration(migrations.Migration): field=models.CharField( blank=True, max_length=300, - verbose_name='The original title of this object, if available' + verbose_name='The original title of this object, if available', ), ), migrations.AlterField( @@ -189,7 +184,7 @@ class Migration(migrations.Migration): help_text='If you are not the author, enter the name or source here.', max_length=600, null=True, - verbose_name='Author(s)' + verbose_name='Author(s)', ), ), migrations.AlterField( @@ -202,9 +197,8 @@ class Migration(migrations.Migration): name='license_derivative_source_url', field=models.URLField( blank=True, - help_text= - 'Note that a derivative work is one which is not only based on a previous work, but which also contains sufficient new, creative content to entitle it to its own copyright.', - verbose_name='Link to the original source, if this is a derivative work' + help_text='Note that a derivative work is one which is not only based on a previous work, but which also contains sufficient new, creative content to entitle it to its own copyright.', + verbose_name='Link to the original source, if this is a derivative work', ), ), migrations.AlterField( @@ -218,7 +212,7 @@ class Migration(migrations.Migration): field=models.CharField( blank=True, max_length=300, - verbose_name='The original title of this object, if available' + verbose_name='The original title of this object, if available', ), ), migrations.AlterField( @@ -229,7 +223,7 @@ class Migration(migrations.Migration): help_text='If you are not the author, enter the name or source here.', max_length=600, null=True, - verbose_name='Author(s)' + verbose_name='Author(s)', ), ), migrations.AlterField( @@ -242,9 +236,8 @@ class Migration(migrations.Migration): name='license_derivative_source_url', field=models.URLField( blank=True, - help_text= - 'Note that a derivative work is one which is not only based on a previous work, but which also contains sufficient new, creative content to entitle it to its own copyright.', - verbose_name='Link to the original source, if this is a derivative work' + help_text='Note that a derivative work is one which is not only based on a previous work, but which also contains sufficient new, creative content to entitle it to its own copyright.', + verbose_name='Link to the original source, if this is a derivative work', ), ), migrations.AlterField( @@ -258,7 +251,7 @@ class Migration(migrations.Migration): field=models.CharField( blank=True, max_length=300, - verbose_name='The original title of this object, if available' + verbose_name='The original title of this object, if available', ), ), migrations.AlterField( @@ -269,7 +262,7 @@ class Migration(migrations.Migration): help_text='If you are not the author, enter the name or source here.', max_length=600, null=True, - verbose_name='Author(s)' + verbose_name='Author(s)', ), ), migrations.AlterField( @@ -282,9 +275,8 @@ class Migration(migrations.Migration): name='license_derivative_source_url', field=models.URLField( blank=True, - help_text= - 'Note that a derivative work is one which is not only based on a previous work, but which also contains sufficient new, creative content to entitle it to its own copyright.', - verbose_name='Link to the original source, if this is a derivative work' + help_text='Note that a derivative work is one which is not only based on a previous work, but which also contains sufficient new, creative content to entitle it to its own copyright.', + verbose_name='Link to the original source, if this is a derivative work', ), ), migrations.AlterField( @@ -298,7 +290,7 @@ class Migration(migrations.Migration): field=models.CharField( blank=True, max_length=300, - verbose_name='The original title of this object, if available' + verbose_name='The original title of this object, if available', ), ), migrations.AlterField( @@ -309,7 +301,7 @@ class Migration(migrations.Migration): help_text='If you are not the author, enter the name or source here.', max_length=600, null=True, - verbose_name='Author(s)' + verbose_name='Author(s)', ), ), migrations.AlterField( @@ -322,9 +314,8 @@ class Migration(migrations.Migration): name='license_derivative_source_url', field=models.URLField( blank=True, - help_text= - 'Note that a derivative work is one which is not only based on a previous work, but which also contains sufficient new, creative content to entitle it to its own copyright.', - verbose_name='Link to the original source, if this is a derivative work' + help_text='Note that a derivative work is one which is not only based on a previous work, but which also contains sufficient new, creative content to entitle it to its own copyright.', + verbose_name='Link to the original source, if this is a derivative work', ), ), migrations.AlterField( @@ -338,7 +329,7 @@ class Migration(migrations.Migration): field=models.CharField( blank=True, max_length=300, - verbose_name='The original title of this object, if available' + verbose_name='The original title of this object, if available', ), ), ] diff --git a/wger/exercises/migrations/0028_add_uuid_alias_and_comments.py b/wger/exercises/migrations/0028_add_uuid_alias_and_comments.py index 1f93b1d72..227548571 100644 --- a/wger/exercises/migrations/0028_add_uuid_alias_and_comments.py +++ b/wger/exercises/migrations/0028_add_uuid_alias_and_comments.py @@ -7,65 +7,65 @@ import uuid def generate_aliases_uuids(apps, schema_editor): """Generate new UUIDs for each alias""" - Alias = apps.get_model("exercises", "Alias") + Alias = apps.get_model('exercises', 'Alias') for alias in Alias.objects.all(): alias.uuid = uuid.uuid4() - alias.save(update_fields=["uuid"]) + alias.save(update_fields=['uuid']) def generate_comments_uuids(apps, schema_editor): """Generate new UUIDs for each comment""" - Comment = apps.get_model("exercises", "ExerciseComment") + Comment = apps.get_model('exercises', 'ExerciseComment') for comment in Comment.objects.all(): comment.uuid = uuid.uuid4() - comment.save(update_fields=["uuid"]) + comment.save(update_fields=['uuid']) class Migration(migrations.Migration): dependencies = [ - ("exercises", "0027_alter_deletionlog_replaced_by_and_more"), + ('exercises', '0027_alter_deletionlog_replaced_by_and_more'), ] operations = [ migrations.AddField( - model_name="exercisecomment", - name="uuid", + model_name='exercisecomment', + name='uuid', field=models.UUIDField( default=uuid.uuid4, editable=False, unique=False, - verbose_name="UUID", + verbose_name='UUID', ), ), migrations.AddField( - model_name="historicalexercisecomment", - name="uuid", + model_name='historicalexercisecomment', + name='uuid', field=models.UUIDField( db_index=True, default=uuid.uuid4, editable=False, - verbose_name="UUID", + verbose_name='UUID', ), ), migrations.AddField( - model_name="alias", - name="uuid", + model_name='alias', + name='uuid', field=models.UUIDField( default=uuid.uuid4, editable=False, unique=False, - verbose_name="UUID", + verbose_name='UUID', ), ), migrations.AddField( - model_name="historicalalias", - name="uuid", + model_name='historicalalias', + name='uuid', field=models.UUIDField( db_index=True, default=uuid.uuid4, editable=False, - verbose_name="UUID", + verbose_name='UUID', ), ), migrations.RunPython( @@ -77,23 +77,23 @@ class Migration(migrations.Migration): reverse_code=migrations.RunPython.noop, ), migrations.AlterField( - model_name="exercisecomment", - name="uuid", + model_name='exercisecomment', + name='uuid', field=models.UUIDField( default=uuid.uuid4, editable=False, unique=True, - verbose_name="UUID", + verbose_name='UUID', ), ), migrations.AlterField( - model_name="alias", - name="uuid", + model_name='alias', + name='uuid', field=models.UUIDField( default=uuid.uuid4, editable=False, unique=True, - verbose_name="UUID", + verbose_name='UUID', ), - ) + ), ] diff --git a/wger/exercises/models/base.py b/wger/exercises/models/base.py index 308273963..fbd02ba7b 100644 --- a/wger/exercises/models/base.py +++ b/wger/exercises/models/base.py @@ -133,7 +133,7 @@ class ExerciseBase(AbstractLicenseModel, AbstractHistoryMixin, models.Model): """ Return a more human-readable representation """ - return f"base {self.uuid} ({self.get_translation()})" + return f'base {self.uuid} ({self.get_translation()})' def get_absolute_url(self): """ @@ -181,10 +181,11 @@ class ExerciseBase(AbstractLicenseModel, AbstractHistoryMixin, models.Model): The latest update datetime of all exercises, videos and images. """ return max( - self.last_update, *[image.last_update for image in self.exerciseimage_set.all()], + self.last_update, + *[image.last_update for image in self.exerciseimage_set.all()], *[video.last_update for video in self.exercisevideo_set.all()], *[translation.last_update for translation in self.exercises.all()], - datetime.datetime(1970, 1, 1, tzinfo=datetime.timezone.utc) + datetime.datetime(1970, 1, 1, tzinfo=datetime.timezone.utc), ) @property @@ -258,7 +259,7 @@ class ExerciseBase(AbstractLicenseModel, AbstractHistoryMixin, models.Model): log = DeletionLog( model_type=DeletionLog.MODEL_BASE, uuid=self.uuid, - comment=f"Exercise base of {self.get_translation(ENGLISH_SHORT_NAME)}", + comment=f'Exercise base of {self.get_translation(ENGLISH_SHORT_NAME)}', replaced_by=replace_by, ) log.save() diff --git a/wger/exercises/models/category.py b/wger/exercises/models/category.py index 07fe238cf..cf1e7f356 100644 --- a/wger/exercises/models/category.py +++ b/wger/exercises/models/category.py @@ -23,6 +23,7 @@ class ExerciseCategory(models.Model): """ Model for an exercise category """ + name = models.CharField( max_length=100, verbose_name=_('Name'), @@ -30,9 +31,9 @@ class ExerciseCategory(models.Model): # Metaclass to set some other properties class Meta: - verbose_name_plural = _("Exercise Categories") + verbose_name_plural = _('Exercise Categories') ordering = [ - "name", + 'name', ] def __str__(self): diff --git a/wger/exercises/models/comment.py b/wger/exercises/models/comment.py index f71f2583e..9b62a4bb3 100644 --- a/wger/exercises/models/comment.py +++ b/wger/exercises/models/comment.py @@ -38,6 +38,7 @@ class ExerciseComment(models.Model): """ Model for an exercise comment """ + uuid = models.UUIDField( default=uuid.uuid4, editable=False, @@ -55,7 +56,7 @@ class ExerciseComment(models.Model): comment = models.CharField( max_length=200, verbose_name=_('Comment'), - help_text=_('A comment about how to correctly do this exercise.') + help_text=_('A comment about how to correctly do this exercise.'), ) history = HistoricalRecords() diff --git a/wger/exercises/models/equipment.py b/wger/exercises/models/equipment.py index 141457096..938097ebd 100644 --- a/wger/exercises/models/equipment.py +++ b/wger/exercises/models/equipment.py @@ -33,8 +33,9 @@ class Equipment(models.Model): """ Set default ordering """ + ordering = [ - "name", + 'name', ] def __str__(self): diff --git a/wger/exercises/models/exercise.py b/wger/exercises/models/exercise.py index 0dbee8375..e0d1721f7 100644 --- a/wger/exercises/models/exercise.py +++ b/wger/exercises/models/exercise.py @@ -45,6 +45,7 @@ class Exercise(AbstractLicenseModel, AbstractHistoryMixin, models.Model): """ Model for an exercise """ + description = models.TextField( max_length=2000, verbose_name=_('Description'), @@ -104,7 +105,7 @@ class Exercise(AbstractLicenseModel, AbstractHistoryMixin, models.Model): class Meta: base_manager_name = 'objects' ordering = [ - "name", + 'name', ] def get_absolute_url(self): diff --git a/wger/exercises/models/exercise_alias.py b/wger/exercises/models/exercise_alias.py index 9ff823a53..331358c82 100644 --- a/wger/exercises/models/exercise_alias.py +++ b/wger/exercises/models/exercise_alias.py @@ -38,6 +38,7 @@ class Alias(models.Model): """ Model for an exercise (name)alias """ + uuid = models.UUIDField( default=uuid.uuid4, editable=False, diff --git a/wger/exercises/models/image.py b/wger/exercises/models/image.py index 548fd99d3..28c0653b5 100644 --- a/wger/exercises/models/image.py +++ b/wger/exercises/models/image.py @@ -40,7 +40,7 @@ def exercise_image_upload_dir(instance, filename): Returns the upload target for exercise images """ ext = pathlib.Path(filename).suffix - return f"exercise-images/{instance.exercise_base.id}/{instance.uuid}{ext}" + return f'exercise-images/{instance.exercise_base.id}/{instance.uuid}{ext}' class ExerciseImage(AbstractLicenseModel, AbstractHistoryMixin, models.Model, BaseImage): @@ -87,11 +87,11 @@ class ExerciseImage(AbstractLicenseModel, AbstractHistoryMixin, models.Model, Ba verbose_name=_('Main picture'), default=False, help_text=_( - "Tick the box if you want to set this image as the " - "main one for the exercise (will be shown e.g. in " - "the search). The first image is automatically " - "marked by the system." - ) + 'Tick the box if you want to set this image as the ' + 'main one for the exercise (will be shown e.g. in ' + 'the search). The first image is automatically ' + 'marked by the system.' + ), ) """A flag indicating whether the image is the exercise's main image""" @@ -128,6 +128,7 @@ class ExerciseImage(AbstractLicenseModel, AbstractHistoryMixin, models.Model, Ba """ Set default ordering """ + ordering = ['-is_main', 'id'] base_manager_name = 'objects' @@ -139,11 +140,12 @@ class ExerciseImage(AbstractLicenseModel, AbstractHistoryMixin, models.Model, Ba ExerciseImage.objects.filter(exercise_base=self.exercise_base).update(is_main=False) self.is_main = True else: - if ExerciseImage.objects.all() \ - .filter(exercise_base=self.exercise_base).count() == 0 \ - or not ExerciseImage.objects.all() \ - .filter(exercise_base=self.exercise_base, is_main=True) \ - .count(): + if ( + ExerciseImage.objects.all().filter(exercise_base=self.exercise_base).count() == 0 + or not ExerciseImage.objects.all() + .filter(exercise_base=self.exercise_base, is_main=True) + .count() + ): self.is_main = True # Api cache @@ -159,12 +161,18 @@ class ExerciseImage(AbstractLicenseModel, AbstractHistoryMixin, models.Model, Ba super().delete(*args, **kwargs) # Make sure there is always a main image - if not ExerciseImage.objects.all().filter(exercise_base=self.exercise_base, is_main=True - ).count() and ExerciseImage.objects.all().filter( - exercise_base=self.exercise_base - ).filter(is_main=False).count(): - image = ExerciseImage.objects.all() \ - .filter(exercise_base=self.exercise_base, is_main=False)[0] + if ( + not ExerciseImage.objects.all() + .filter(exercise_base=self.exercise_base, is_main=True) + .count() + and ExerciseImage.objects.all() + .filter(exercise_base=self.exercise_base) + .filter(is_main=False) + .count() + ): + image = ExerciseImage.objects.all().filter( + exercise_base=self.exercise_base, is_main=False + )[0] image.is_main = True image.save() diff --git a/wger/exercises/models/muscle.py b/wger/exercises/models/muscle.py index 76e678a32..da78b02d3 100644 --- a/wger/exercises/models/muscle.py +++ b/wger/exercises/models/muscle.py @@ -51,18 +51,18 @@ class Muscle(models.Model): # Metaclass to set some other properties class Meta: ordering = [ - "name", + 'name', ] # Image to use when displaying this as a main muscle in an exercise @property def image_url_main(self): - return static(f"images/muscles/main/muscle-{self.id}.svg") + return static(f'images/muscles/main/muscle-{self.id}.svg') # Image to use when displaying this as a secondary muscle in an exercise @property def image_url_secondary(self): - return static(f"images/muscles/secondary/muscle-{self.id}.svg") + return static(f'images/muscles/secondary/muscle-{self.id}.svg') def __str__(self): """ diff --git a/wger/exercises/models/video.py b/wger/exercises/models/video.py index b4dcbbaa0..6dd0fffef 100644 --- a/wger/exercises/models/video.py +++ b/wger/exercises/models/video.py @@ -77,7 +77,7 @@ def exercise_video_upload_dir(instance, filename): Returns the upload target for exercise videos """ ext = pathlib.Path(filename).suffix - return f"exercise-video/{instance.exercise_base.id}/{instance.uuid}{ext}" + return f'exercise-video/{instance.exercise_base.id}/{instance.uuid}{ext}' class ExerciseVideo(AbstractLicenseModel, AbstractHistoryMixin, models.Model): @@ -184,6 +184,7 @@ class ExerciseVideo(AbstractLicenseModel, AbstractHistoryMixin, models.Model): """ Set default ordering """ + ordering = ['-is_main', 'id'] def get_owner_object(self): @@ -203,7 +204,6 @@ class ExerciseVideo(AbstractLicenseModel, AbstractHistoryMixin, models.Model): # Streams are stored in a list, and we don't know which one is the video stream for stream in probe_result['streams']: - if stream['codec_type'] != 'video': continue diff --git a/wger/exercises/signals.py b/wger/exercises/signals.py index 3762a5fda..1a350333a 100644 --- a/wger/exercises/signals.py +++ b/wger/exercises/signals.py @@ -81,7 +81,6 @@ def auto_delete_video_on_delete(sender, instance: ExerciseVideo, **kwargs): Deletes file from filesystem when corresponding ExerciseVideo object is deleted """ if instance.video: - path = pathlib.Path(instance.video.path) if path.exists(): path.unlink() diff --git a/wger/exercises/sitemap.py b/wger/exercises/sitemap.py index 7d686a04c..032cc735f 100644 --- a/wger/exercises/sitemap.py +++ b/wger/exercises/sitemap.py @@ -22,7 +22,7 @@ from wger.exercises.models import Exercise class ExercisesSitemap(Sitemap): - changefreq = "monthly" + changefreq = 'monthly' priority = 0.5 def items(self): diff --git a/wger/exercises/sync.py b/wger/exercises/sync.py index 5a7d7c47d..82e7699f0 100644 --- a/wger/exercises/sync.py +++ b/wger/exercises/sync.py @@ -75,7 +75,6 @@ def sync_exercises( url = make_uri(EXERCISE_ENDPOINT, server_url=remote_url, query={'limit': 100}) for data in get_paginated(url, headers=wger_headers()): - uuid = data['uuid'] created = data['created'] license_id = data['license']['id'] @@ -87,10 +86,7 @@ def sync_exercises( base, base_created = ExerciseBase.objects.update_or_create( uuid=uuid, - defaults={ - 'category_id': category_id, - 'created': created - }, + defaults={'category_id': category_id, 'created': created}, ) print_fn(f"{'created' if base_created else 'updated'} exercise {uuid}") @@ -116,8 +112,10 @@ def sync_exercises( 'language_id': language_id, }, ) - out = f"- {'created' if translation_created else 'updated'} translation " \ - f"{translation.language.short_name} {trans_uuid} - {name}" + out = ( + f"- {'created' if translation_created else 'updated'} translation " + f"{translation.language.short_name} {trans_uuid} - {name}" + ) print_fn(out) # TODO: currently (2024-01-06) we always delete all the comments and the aliases @@ -137,7 +135,7 @@ def sync_exercises( 'uuid': note['uuid'], 'exercise': translation, 'comment': note['comment'], - } + }, ) Alias.objects.filter(exercise=translation).delete() @@ -148,7 +146,7 @@ def sync_exercises( 'uuid': alias['uuid'], 'exercise': translation, 'alias': alias['alias'], - } + }, ) print_fn('') @@ -197,10 +195,7 @@ def sync_licenses( language, created = License.objects.update_or_create( short_name=short_name, - defaults={ - 'full_name': full_name, - 'url': license_url - }, + defaults={'full_name': full_name, 'url': license_url}, ) if created: @@ -328,13 +323,11 @@ def handle_deleted_entries( # Replace exercise in workouts and logs if obj_replaced: - nr_settings = ( - Setting.objects.filter(exercise_base=obj - ).update(exercise_base=obj_replaced) + nr_settings = Setting.objects.filter(exercise_base=obj).update( + exercise_base=obj_replaced ) - nr_logs = ( - WorkoutLog.objects.filter(exercise_base=obj - ).update(exercise_base=obj_replaced) + nr_logs = WorkoutLog.objects.filter(exercise_base=obj).update( + exercise_base=obj_replaced ) obj.delete() diff --git a/wger/exercises/tests/test_categories.py b/wger/exercises/tests/test_categories.py index f3f515307..bdbc34b4f 100644 --- a/wger/exercises/tests/test_categories.py +++ b/wger/exercises/tests/test_categories.py @@ -33,20 +33,20 @@ class ExerciseCategoryRepresentationTestCase(WgerTestCase): """ Test that the representation of an object is correct """ - self.assertEqual("{0}".format(ExerciseCategory.objects.get(pk=1)), 'Category') + self.assertEqual('{0}'.format(ExerciseCategory.objects.get(pk=1)), 'Category') class CategoryOverviewTestCase(WgerAccessTestCase): """ Test that only admins see the edit links """ + url = 'exercise:category:list' anonymous_fail = True user_success = 'admin' user_fail = ( 'manager1', - 'manager2' - 'general_manager1', + 'manager2' 'general_manager1', 'manager3', 'manager4', 'test', @@ -95,6 +95,7 @@ class ExerciseCategoryApiTestCase(api_base_test.ApiBaseResourceTestCase): """ Tests the exercise category overview resource """ + pk = 2 resource = ExerciseCategory private_resource = False diff --git a/wger/exercises/tests/test_change_exercise_author.py b/wger/exercises/tests/test_change_exercise_author.py index 11e04d83f..1d288a0e0 100644 --- a/wger/exercises/tests/test_change_exercise_author.py +++ b/wger/exercises/tests/test_change_exercise_author.py @@ -44,7 +44,7 @@ class ChangeExerciseAuthorTestCase(WgerTestCase): """ Test to ensure command handles a missing exercise parameters """ - args = ["--author-name", "tom"] + args = ['--author-name', 'tom'] call_command('change-exercise-author', *args, stdout=self.out, no_color=True) self.assertIn('Please enter an exercise base or exercise ID', self.out.getvalue()) @@ -53,25 +53,25 @@ class ChangeExerciseAuthorTestCase(WgerTestCase): Test to ensure command can handle an exercise base id passed """ exercise_base = ExerciseBase.objects.get(id=2) - self.assertNotEqual(exercise_base.license_author, "tom") + self.assertNotEqual(exercise_base.license_author, 'tom') - args = ["--author-name", "tom", "--exercise-base-id", "2"] + args = ['--author-name', 'tom', '--exercise-base-id', '2'] call_command('change-exercise-author', *args, stdout=self.out, no_color=True) self.assertIn('Exercise and/or exercise base has been updated', self.out.getvalue()) exercise_base = ExerciseBase.objects.get(id=2) - self.assertEqual(exercise_base.license_author, "tom") + self.assertEqual(exercise_base.license_author, 'tom') def test_can_update_exercise(self): """ Test to ensure command can handle an exercise id passed """ exercise = Exercise.objects.get(id=1) - self.assertNotEqual(exercise.license_author, "tom") + self.assertNotEqual(exercise.license_author, 'tom') - args = ["--author-name", "tom", "--exercise-id", "1"] + args = ['--author-name', 'tom', '--exercise-id', '1'] call_command('change-exercise-author', *args, stdout=self.out, no_color=True) self.assertIn('Exercise and/or exercise base has been updated', self.out.getvalue()) exercise = Exercise.objects.get(id=1) - self.assertEqual(exercise.license_author, "tom") + self.assertEqual(exercise.license_author, 'tom') diff --git a/wger/exercises/tests/test_deletion_log.py b/wger/exercises/tests/test_deletion_log.py index 0dd555ede..e6fc7b299 100644 --- a/wger/exercises/tests/test_deletion_log.py +++ b/wger/exercises/tests/test_deletion_log.py @@ -76,7 +76,7 @@ class DeletionLogTestCase(WgerTestCase): self.assertEqual(DeletionLog.objects.all().count(), 0) base = ExerciseBase.objects.get(pk=1) - base.delete(replace_by="ae3328ba-9a35-4731-bc23-5da50720c5aa") + base.delete(replace_by='ae3328ba-9a35-4731-bc23-5da50720c5aa') # Base is deleted log = DeletionLog.objects.get(pk=1) @@ -93,7 +93,7 @@ class DeletionLogTestCase(WgerTestCase): self.assertEqual(DeletionLog.objects.all().count(), 0) base = ExerciseBase.objects.get(pk=1) - base.delete(replace_by="12345678-1234-1234-1234-1234567890ab") + base.delete(replace_by='12345678-1234-1234-1234-1234567890ab') # Base is deleted log = DeletionLog.objects.get(pk=1) diff --git a/wger/exercises/tests/test_equipment.py b/wger/exercises/tests/test_equipment.py index ad3f09c13..6ddb44b01 100644 --- a/wger/exercises/tests/test_equipment.py +++ b/wger/exercises/tests/test_equipment.py @@ -37,7 +37,7 @@ class EquipmentRepresentationTestCase(WgerTestCase): """ Test that the representation of an object is correct """ - self.assertEqual("{0}".format(Equipment.objects.get(pk=1)), 'Dumbbells') + self.assertEqual('{0}'.format(Equipment.objects.get(pk=1)), 'Dumbbells') class AddEquipmentTestCase(WgerAddTestCase): @@ -79,7 +79,7 @@ class EquipmentListTestCase(WgerTestCase): def test_overview(self): # Add more equipments so we can test the pagination self.user_login('admin') - data = {"name": "A new entry"} + data = {'name': 'A new entry'} for i in range(0, 50): self.client.post(reverse('exercise:equipment:add'), data) @@ -113,6 +113,7 @@ class EquipmentApiTestCase(api_base_test.ApiBaseResourceTestCase): """ Tests the equipment overview resource """ + pk = 1 resource = Equipment private_resource = False diff --git a/wger/exercises/tests/test_exercise_api_cache.py b/wger/exercises/tests/test_exercise_api_cache.py index 429b751b4..07fdeb927 100644 --- a/wger/exercises/tests/test_exercise_api_cache.py +++ b/wger/exercises/tests/test_exercise_api_cache.py @@ -73,7 +73,7 @@ class ExerciseApiCacheTestCase(WgerTestCase): self.assertTrue(cache.get(self.cache_key)) translation = Exercise.objects.get(pk=1) - translation.name = "something else" + translation.name = 'something else' translation.save() self.assertFalse(cache.get(self.cache_key)) @@ -100,7 +100,7 @@ class ExerciseApiCacheTestCase(WgerTestCase): self.assertTrue(cache.get(self.cache_key)) comment = ExerciseComment.objects.get(pk=1) - comment.name = "The Shiba Inu (柴犬) is a breed of hunting dog from Japan" + comment.name = 'The Shiba Inu (柴犬) is a breed of hunting dog from Japan' comment.save() self.assertFalse(cache.get(self.cache_key)) @@ -127,7 +127,7 @@ class ExerciseApiCacheTestCase(WgerTestCase): self.assertTrue(cache.get(self.cache_key)) alias = Alias.objects.get(pk=1) - alias.name = "Hachikō" + alias.name = 'Hachikō' alias.save() self.assertFalse(cache.get(self.cache_key)) diff --git a/wger/exercises/tests/test_exercise_base.py b/wger/exercises/tests/test_exercise_base.py index caa4a964a..584c3b461 100644 --- a/wger/exercises/tests/test_exercise_base.py +++ b/wger/exercises/tests/test_exercise_base.py @@ -99,11 +99,11 @@ class ExerciseCustomApiTestCase(ExerciseCrudApiTestCase): pk = 1 data = { - "category": 3, - "muscles": [1, 3], - "muscles_secondary": [2], - "equipment": [3], - "variations": 4 + 'category': 3, + 'muscles': [1, 3], + 'muscles_secondary': [2], + 'equipment': [3], + 'variations': 4, } def get_resource_name(self): diff --git a/wger/exercises/tests/test_exercise_base_model.py b/wger/exercises/tests/test_exercise_base_model.py index d7a88d563..76c363a4f 100644 --- a/wger/exercises/tests/test_exercise_base_model.py +++ b/wger/exercises/tests/test_exercise_base_model.py @@ -48,6 +48,7 @@ class ExerciseBaseModelTestCase(WgerTestCase): """ Test custom model logic """ + exercise: ExerciseBase def setUp(self): @@ -66,12 +67,12 @@ class ExerciseBaseModelTestCase(WgerTestCase): self.assertEqual( max(*[translation.last_update for translation in self.exercise.exercises.all()]), - datetime.datetime(2022, 2, 2, 5, 45, 11, tzinfo=utc) + datetime.datetime(2022, 2, 2, 5, 45, 11, tzinfo=utc), ) self.assertEqual( max(*[video.last_update for video in self.exercise.exerciseimage_set.all()]), - datetime.datetime(2023, 8, 9, 23, 0, tzinfo=utc) + datetime.datetime(2023, 8, 9, 23, 0, tzinfo=utc), ) def test_exercise_en(self): diff --git a/wger/exercises/tests/test_exercise_comments.py b/wger/exercises/tests/test_exercise_comments.py index 5410047f3..7ac3746b1 100644 --- a/wger/exercises/tests/test_exercise_comments.py +++ b/wger/exercises/tests/test_exercise_comments.py @@ -27,17 +27,18 @@ class ExerciseCommentRepresentationTestCase(WgerTestCase): """ Test that the representation of an object is correct """ - self.assertEqual("{0}".format(ExerciseComment.objects.get(pk=1)), 'test 123') + self.assertEqual('{0}'.format(ExerciseComment.objects.get(pk=1)), 'test 123') class ExerciseCommentApiTestCase(ExerciseCrudApiTestCase): """ Tests the exercise comment overview resource """ + pk = 1 resource = ExerciseComment data = { - "comment": "a cool comment", - "exercise": "1", - "id": 1, + 'comment': 'a cool comment', + 'exercise': '1', + 'id': 1, } diff --git a/wger/exercises/tests/test_exercise_images.py b/wger/exercises/tests/test_exercise_images.py index 91a041a93..728a2f3a5 100644 --- a/wger/exercises/tests/test_exercise_images.py +++ b/wger/exercises/tests/test_exercise_images.py @@ -113,6 +113,7 @@ class ExerciseImagesApiTestCase( """ Tests the exercise image resource """ + pk = 1 private_resource = False resource = ExerciseImage diff --git a/wger/exercises/tests/test_exercise_translation.py b/wger/exercises/tests/test_exercise_translation.py index 4aae9df49..0c8cac8ef 100644 --- a/wger/exercises/tests/test_exercise_translation.py +++ b/wger/exercises/tests/test_exercise_translation.py @@ -50,7 +50,7 @@ class ExerciseRepresentationTestCase(WgerTestCase): """ Test that the representation of an object is correct """ - self.assertEqual("{0}".format(Exercise.objects.get(pk=1)), 'An exercise') + self.assertEqual('{0}'.format(Exercise.objects.get(pk=1)), 'An exercise') class ExercisesTestCase(WgerTestCase): @@ -112,15 +112,13 @@ class ExercisesTestCase(WgerTestCase): class MuscleTemplateTagTest(WgerTestCase): - def test_render_main_muscles(self): """ Test that the tag renders only the main muscles """ context = Context({'muscles': Muscle.objects.get(pk=2)}) - template = Template('{% load wger_extras %}' - '{% render_muscles muscles %}') + template = Template('{% load wger_extras %}' '{% render_muscles muscles %}') rendered_template = template.render(context) self.assertIn('images/muscles/main/muscle-2.svg', rendered_template) self.assertNotIn('images/muscles/secondary/', rendered_template) @@ -131,9 +129,8 @@ class MuscleTemplateTagTest(WgerTestCase): Test that the tag works when giben main muscles and empty secondary ones """ - context = Context({"muscles": Muscle.objects.get(pk=2), "muscles_sec": []}) - template = Template('{% load wger_extras %}' - '{% render_muscles muscles muscles_sec %}') + context = Context({'muscles': Muscle.objects.get(pk=2), 'muscles_sec': []}) + template = Template('{% load wger_extras %}' '{% render_muscles muscles muscles_sec %}') rendered_template = template.render(context) self.assertIn('images/muscles/main/muscle-2.svg', rendered_template) self.assertNotIn('images/muscles/secondary/', rendered_template) @@ -145,8 +142,7 @@ class MuscleTemplateTagTest(WgerTestCase): """ context = Context({'muscles': Muscle.objects.get(pk=1)}) - template = Template('{% load wger_extras %}' - '{% render_muscles muscles_sec=muscles %}') + template = Template('{% load wger_extras %}' '{% render_muscles muscles_sec=muscles %}') rendered_template = template.render(context) self.assertIn('images/muscles/secondary/muscle-1.svg', rendered_template) self.assertNotIn('images/muscles/main/', rendered_template) @@ -158,8 +154,7 @@ class MuscleTemplateTagTest(WgerTestCase): """ context = Context({'muscles_sec': Muscle.objects.get(pk=1), 'muscles': []}) - template = Template('{% load wger_extras %}' - '{% render_muscles muscles muscles_sec %}') + template = Template('{% load wger_extras %}' '{% render_muscles muscles muscles_sec %}') rendered_template = template.render(context) self.assertIn('images/muscles/secondary/muscle-1.svg', rendered_template) self.assertNotIn('images/muscles/main/', rendered_template) @@ -171,8 +166,7 @@ class MuscleTemplateTagTest(WgerTestCase): """ context = Context({'muscles_sec': Muscle.objects.filter(is_front=True), 'muscles': []}) - template = Template('{% load wger_extras %}' - '{% render_muscles muscles muscles_sec %}') + template = Template('{% load wger_extras %}' '{% render_muscles muscles muscles_sec %}') rendered_template = template.render(context) self.assertIn('images/muscles/secondary/muscle-1.svg', rendered_template) self.assertNotIn('images/muscles/secondary/muscle-2.svg', rendered_template) @@ -188,11 +182,10 @@ class MuscleTemplateTagTest(WgerTestCase): context = Context( { 'muscles_sec': Muscle.objects.filter(id__in=[5, 6]), - 'muscles': Muscle.objects.filter(id__in=[1, 4]) + 'muscles': Muscle.objects.filter(id__in=[1, 4]), } ) - template = Template('{% load wger_extras %}' - '{% render_muscles muscles muscles_sec %}') + template = Template('{% load wger_extras %}' '{% render_muscles muscles muscles_sec %}') rendered_template = template.render(context) self.assertIn('images/muscles/main/muscle-1.svg', rendered_template) self.assertNotIn('images/muscles/main/muscle-2.svg', rendered_template) @@ -209,20 +202,18 @@ class MuscleTemplateTagTest(WgerTestCase): """ context = Context({'muscles': [], 'muscles_sec': []}) - template = Template('{% load wger_extras %}' - '{% render_muscles muscles muscles_sec %}') + template = Template('{% load wger_extras %}' '{% render_muscles muscles muscles_sec %}') rendered_template = template.render(context) - self.assertEqual(rendered_template, "\n\n") + self.assertEqual(rendered_template, '\n\n') def test_render_no_parameters(self): """ Test that the tag works when given no parameters """ - template = Template('{% load wger_extras %}' - '{% render_muscles %}') + template = Template('{% load wger_extras %}' '{% render_muscles %}') rendered_template = template.render(Context({})) - self.assertEqual(rendered_template, "\n\n") + self.assertEqual(rendered_template, '\n\n') class WorkoutCacheTestCase(WgerTestCase): @@ -268,6 +259,7 @@ class ExerciseApiTestCase( """ Tests the exercise overview resource """ + pk = 1 resource = Exercise private_resource = False @@ -282,6 +274,7 @@ class ExerciseInfoApiTestCase( """ Tests the exercise info resource """ + pk = 1 private_resource = False overview_cached = True @@ -298,6 +291,7 @@ class ExerciseBaseInfoApiTestCase( """ Tests the exercise base info resource """ + pk = 1 private_resource = False overview_cached = True @@ -313,7 +307,7 @@ class ExerciseCustomApiTestCase(ExerciseCrudApiTestCase): 'name': 'A new name', 'description': 'The wild boar is a suid native to much of Eurasia and North Africa', 'language': 1, - 'exercise_base': 2 + 'exercise_base': 2, } def get_resource_name(self): diff --git a/wger/exercises/tests/test_history.py b/wger/exercises/tests/test_history.py index ed8f9e486..9d93f5116 100644 --- a/wger/exercises/tests/test_history.py +++ b/wger/exercises/tests/test_history.py @@ -76,8 +76,8 @@ class ExerciseHistoryControl(WgerTestCase): 'exercise:history:revert', kwargs={ 'history_pk': most_recent_history.history_id, - 'content_type_id': ContentType.objects.get_for_model(exercise).id - } + 'content_type_id': ContentType.objects.get_for_model(exercise).id, + }, ) ) diff --git a/wger/exercises/tests/test_management_commands.py b/wger/exercises/tests/test_management_commands.py index 1cb65cc33..8d0a5a206 100644 --- a/wger/exercises/tests/test_management_commands.py +++ b/wger/exercises/tests/test_management_commands.py @@ -28,7 +28,6 @@ from wger.exercises.models import ( class TestSyncManagementCommands(SimpleTestCase): - @patch('wger.exercises.sync.handle_deleted_entries') @patch('wger.exercises.sync.sync_muscles') @patch('wger.exercises.sync.sync_languages') @@ -70,7 +69,6 @@ class TestSyncManagementCommands(SimpleTestCase): class TestHealthCheckManagementCommands(WgerTestCase): - def setUp(self): super().setUp() self.out = StringIO() @@ -85,16 +83,16 @@ class TestHealthCheckManagementCommands(WgerTestCase): call_command('exercises-health-check', stdout=self.out) self.assertIn( - "Exercise acad3949-36fb-4481-9a72-be2ddae2bc05 has no translations!", - self.out.getvalue() + 'Exercise acad3949-36fb-4481-9a72-be2ddae2bc05 has no translations!', + self.out.getvalue(), ) - self.assertNotIn("-> deleted", self.out.getvalue()) + self.assertNotIn('-> deleted', self.out.getvalue()) def atest_fix_untranslated(self): Exercise.objects.get(pk=1).delete() call_command('exercises-health-check', '--delete-untranslated', stdout=self.out) - self.assertIn("-> deleted", self.out.getvalue()) + self.assertIn('-> deleted', self.out.getvalue()) self.assertRaises(ExerciseBase.DoesNotExist, ExerciseBase.objects.get, pk=1) def test_find_no_english_translation(self): @@ -102,16 +100,16 @@ class TestHealthCheckManagementCommands(WgerTestCase): call_command('exercises-health-check', stdout=self.out) self.assertIn( - "Exercise acad3949-36fb-4481-9a72-be2ddae2bc05 has no English translation!", - self.out.getvalue() + 'Exercise acad3949-36fb-4481-9a72-be2ddae2bc05 has no English translation!', + self.out.getvalue(), ) - self.assertNotIn("-> deleted", self.out.getvalue()) + self.assertNotIn('-> deleted', self.out.getvalue()) def test_fix_no_english_translation(self): Exercise.objects.get(pk=1).delete() call_command('exercises-health-check', '--delete-no-english', stdout=self.out) - self.assertIn("-> deleted", self.out.getvalue()) + self.assertIn('-> deleted', self.out.getvalue()) self.assertRaises(ExerciseBase.DoesNotExist, ExerciseBase.objects.get, pk=1) def test_find_duplicate_translations(self): @@ -121,10 +119,10 @@ class TestHealthCheckManagementCommands(WgerTestCase): call_command('exercises-health-check', stdout=self.out) self.assertIn( - "Exercise acad3949-36fb-4481-9a72-be2ddae2bc05 has duplicate translations!", - self.out.getvalue() + 'Exercise acad3949-36fb-4481-9a72-be2ddae2bc05 has duplicate translations!', + self.out.getvalue(), ) - self.assertNotIn("-> deleted", self.out.getvalue()) + self.assertNotIn('-> deleted', self.out.getvalue()) def test_fix_duplicate_translations(self): exercise = Exercise.objects.get(pk=1) @@ -132,5 +130,5 @@ class TestHealthCheckManagementCommands(WgerTestCase): exercise.save() call_command('exercises-health-check', '--delete-duplicate-translations', stdout=self.out) - self.assertIn("Deleting all but first fr translation", self.out.getvalue()) + self.assertIn('Deleting all but first fr translation', self.out.getvalue()) self.assertRaises(Exercise.DoesNotExist, Exercise.objects.get, pk=5) diff --git a/wger/exercises/tests/test_muscles.py b/wger/exercises/tests/test_muscles.py index 14f7ab4b0..9687269d6 100644 --- a/wger/exercises/tests/test_muscles.py +++ b/wger/exercises/tests/test_muscles.py @@ -33,13 +33,12 @@ class MuscleRepresentationTestCase(WgerTestCase): """ Test that the representation of an object is correct """ - self.assertEqual("{0}".format(Muscle.objects.get(pk=1)), 'Anterior testoid') + self.assertEqual('{0}'.format(Muscle.objects.get(pk=1)), 'Anterior testoid') # Check image URL properties - self.assertIn("images/muscles/main/muscle-2.svg", Muscle.objects.get(pk=2).image_url_main) + self.assertIn('images/muscles/main/muscle-2.svg', Muscle.objects.get(pk=2).image_url_main) self.assertIn( - "images/muscles/secondary/muscle-1.svg", - Muscle.objects.get(pk=1).image_url_secondary + 'images/muscles/secondary/muscle-1.svg', Muscle.objects.get(pk=1).image_url_secondary ) @@ -47,13 +46,13 @@ class MuscleAdminOverviewTest(WgerAccessTestCase): """ Tests the admin muscle overview page """ + url = 'exercise:muscle:admin-list' anonymous_fail = True user_success = 'admin' user_fail = ( 'manager1', - 'manager2' - 'general_manager1', + 'manager2' 'general_manager1', 'manager3', 'manager4', 'test', @@ -100,6 +99,7 @@ class MuscleApiTestCase(api_base_test.ApiBaseResourceTestCase): """ Tests the muscle overview resource """ + pk = 1 resource = Muscle private_resource = False @@ -112,7 +112,7 @@ class MuscleApiTestCase(api_base_test.ApiBaseResourceTestCase): # Check that image URLs are present in response response = self.client.get(self.url_detail) response_object = response.json() - self.assertIn("images/muscles/main/muscle-1.svg", response_object["image_url_main"]) + self.assertIn('images/muscles/main/muscle-1.svg', response_object['image_url_main']) self.assertIn( - "images/muscles/secondary/muscle-1.svg", response_object["image_url_secondary"] + 'images/muscles/secondary/muscle-1.svg', response_object['image_url_secondary'] ) diff --git a/wger/exercises/tests/test_sync.py b/wger/exercises/tests/test_sync.py index f81707aec..a5cb4df05 100644 --- a/wger/exercises/tests/test_sync.py +++ b/wger/exercises/tests/test_sync.py @@ -45,7 +45,6 @@ from wger.utils.requests import wger_headers class MockLanguageResponse: - def __init__(self): self.status_code = 200 self.content = b'1234' @@ -89,7 +88,6 @@ class MockLanguageResponse: class MockLicenseResponse: - def __init__(self): self.status_code = 200 self.content = b'' @@ -132,7 +130,6 @@ class MockLicenseResponse: class MockCategoryResponse: - def __init__(self): self.status_code = 200 self.content = b'1234' @@ -175,7 +172,6 @@ class MockCategoryResponse: class MockMuscleResponse: - def __init__(self): self.status_code = 200 self.content = b'' @@ -226,7 +222,6 @@ class MockMuscleResponse: class MockEquipmentResponse: - def __init__(self): self.status_code = 200 self.content = b'' @@ -261,7 +256,6 @@ class MockEquipmentResponse: class MockDeletionLogResponse: - def __init__(self): self.status_code = 200 self.content = b'' @@ -329,7 +323,6 @@ class MockDeletionLogResponse: class MockExerciseResponse: - def __init__(self): self.status_code = 200 self.content = b'' @@ -562,7 +555,6 @@ class MockExerciseResponse: class TestSyncMethods(WgerTestCase): - @patch('requests.get', return_value=MockLanguageResponse()) def test_language_sync(self, mock_request): self.assertEqual(Language.objects.count(), 3) diff --git a/wger/exercises/urls.py b/wger/exercises/urls.py index 09a126505..f3e74b0b3 100644 --- a/wger/exercises/urls.py +++ b/wger/exercises/urls.py @@ -39,7 +39,7 @@ patterns_history = [ path( 'admin-control/revert//', history.history_revert, - name='revert' + name='revert', ), ] @@ -150,9 +150,9 @@ patterns_exercise = [ ] urlpatterns = [ - path('muscle/', include((patterns_muscle, 'muscle'), namespace="muscle")), - path('category/', include((patterns_category, 'category'), namespace="category")), - path('equipment/', include((patterns_equipment, 'equipment'), namespace="equipment")), - path('history/', include((patterns_history, 'history'), namespace="history")), - path('', include((patterns_exercise, 'exercise'), namespace="exercise")), + path('muscle/', include((patterns_muscle, 'muscle'), namespace='muscle')), + path('category/', include((patterns_category, 'category'), namespace='category')), + path('equipment/', include((patterns_equipment, 'equipment'), namespace='equipment')), + path('history/', include((patterns_history, 'history'), namespace='history')), + path('', include((patterns_exercise, 'exercise'), namespace='exercise')), ] diff --git a/wger/exercises/views/categories.py b/wger/exercises/views/categories.py index 92d43be20..053531cd5 100644 --- a/wger/exercises/views/categories.py +++ b/wger/exercises/views/categories.py @@ -50,6 +50,7 @@ class ExerciseCategoryListView(LoginRequiredMixin, PermissionRequiredMixin, List """ Overview of all categories, for administration purposes """ + model = ExerciseCategory permission_required = 'exercises.change_exercisecategory' template_name = 'categories/admin-overview.html' @@ -115,7 +116,7 @@ class ExerciseCategoryDeleteView( """ model = ExerciseCategory - fields = ('name', ) + fields = ('name',) success_url = reverse_lazy('exercise:category:list') delete_message_extra = gettext_lazy('This will also delete all exercises in this category.') messages = gettext_lazy('Successfully deleted') diff --git a/wger/exercises/views/exercises.py b/wger/exercises/views/exercises.py index c55a5a78a..52c4cceb5 100644 --- a/wger/exercises/views/exercises.py +++ b/wger/exercises/views/exercises.py @@ -52,10 +52,7 @@ def view(request, id, slug=None): return HttpResponsePermanentRedirect( reverse( - 'exercise:exercise:view-base', kwargs={ - 'pk': exercise.exercise_base_id, - 'slug': slug - } + 'exercise:exercise:view-base', kwargs={'pk': exercise.exercise_base_id, 'slug': slug} ) ) diff --git a/wger/exercises/views/history.py b/wger/exercises/views/history.py index 270401e17..75bacd870 100644 --- a/wger/exercises/views/history.py +++ b/wger/exercises/views/history.py @@ -66,11 +66,10 @@ def control(request): 'history/overview.html', { 'context': out, - # We can't pass the enum to the template, so we have to do this # https://stackoverflow.com/questions/35953132/ - 'verbs': StreamVerbs.__members__ - } + 'verbs': StreamVerbs.__members__, + }, ) @@ -88,7 +87,7 @@ def history_revert(request, history_pk, content_type_id): request.user, verb=StreamVerbs.UPDATED.value, action_object=history.instance, - info='reverted history by admin' + info='reverted history by admin', ) return HttpResponseRedirect(reverse('exercise:history:overview')) diff --git a/wger/exercises/views/muscles.py b/wger/exercises/views/muscles.py index 644838980..321dbd20e 100644 --- a/wger/exercises/views/muscles.py +++ b/wger/exercises/views/muscles.py @@ -49,6 +49,7 @@ class MuscleAdminListView(LoginRequiredMixin, PermissionRequiredMixin, ListView) """ Overview of all muscles, for administration purposes """ + model = Muscle context_object_name = 'muscle_list' permission_required = 'exercises.change_muscle' diff --git a/wger/gallery/api/views.py b/wger/gallery/api/views.py index b69228383..e671dec6a 100644 --- a/wger/gallery/api/views.py +++ b/wger/gallery/api/views.py @@ -38,6 +38,7 @@ class GalleryImageViewSet(viewsets.ModelViewSet): """ API endpoint for gallery image """ + parser_classes = [MultiPartParser, FormParser] permission_classes = [IsAuthenticated] serializer_class = ImageSerializer @@ -54,7 +55,7 @@ class GalleryImageViewSet(viewsets.ModelViewSet): Only allow access to appropriate objects """ # REST API generation - if getattr(self, "swagger_fake_view", False): + if getattr(self, 'swagger_fake_view', False): return Image.objects.none() return Image.objects.filter(user=self.request.user) diff --git a/wger/gallery/apps.py b/wger/gallery/apps.py index 670c4e422..ad0e31209 100644 --- a/wger/gallery/apps.py +++ b/wger/gallery/apps.py @@ -3,4 +3,4 @@ from django.apps import AppConfig class GalleryConfig(AppConfig): name = 'wger.gallery' - verbose_name = "Gallery" + verbose_name = 'Gallery' diff --git a/wger/gallery/migrations/0001_initial.py b/wger/gallery/migrations/0001_initial.py index b90a8f036..db8a9b0dc 100644 --- a/wger/gallery/migrations/0001_initial.py +++ b/wger/gallery/migrations/0001_initial.py @@ -8,7 +8,6 @@ import wger.gallery.models.image class Migration(migrations.Migration): - initial = True dependencies = [ @@ -23,7 +22,7 @@ class Migration(migrations.Migration): 'id', models.AutoField( auto_created=True, primary_key=True, serialize=False, verbose_name='ID' - ) + ), ), ('date', models.DateField(default=datetime.datetime.now, verbose_name='Date')), ( @@ -33,22 +32,22 @@ class Migration(migrations.Migration): help_text='Only PNG and JPEG formats are supported', upload_to=wger.gallery.models.image.gallery_upload_dir, verbose_name='Image', - width_field='width' - ) + width_field='width', + ), ), ('height', models.IntegerField(editable=False)), ('width', models.IntegerField(editable=False)), ( 'description', - models.TextField(blank=True, max_length=1000, verbose_name='Description') + models.TextField(blank=True, max_length=1000, verbose_name='Description'), ), ( 'user', models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, - verbose_name='User' - ) + verbose_name='User', + ), ), ], options={ diff --git a/wger/gallery/models/image.py b/wger/gallery/models/image.py index bdd9859fd..1157b6fee 100644 --- a/wger/gallery/models/image.py +++ b/wger/gallery/models/image.py @@ -30,7 +30,7 @@ def gallery_upload_dir(instance, filename): """ Returns the upload target for exercise images """ - return "gallery/{0}/{1}{2}".format( + return 'gallery/{0}/{1}{2}'.format( instance.user.id, uuid.uuid4(), pathlib.Path(filename).suffix, @@ -38,10 +38,9 @@ def gallery_upload_dir(instance, filename): class Image(models.Model): - class Meta: ordering = [ - "-date", + '-date', ] date = models.DateField(_('Date'), default=datetime.datetime.now) @@ -90,7 +89,6 @@ def auto_delete_file_on_delete(sender, instance: Image, **kwargs): when corresponding `MediaFile` object is deleted. """ if instance.image: - path = pathlib.Path(instance.image.path) if path.exists(): path.unlink() diff --git a/wger/gallery/urls.py b/wger/gallery/urls.py index 73b2f72d1..c2ace26a5 100644 --- a/wger/gallery/urls.py +++ b/wger/gallery/urls.py @@ -50,5 +50,5 @@ patterns_images = [ # All patterns for this app # urlpatterns = [ - path('', include((patterns_images, 'images'), namespace="images")), + path('', include((patterns_images, 'images'), namespace='images')), ] diff --git a/wger/gallery/views/images.py b/wger/gallery/views/images.py index 03021d1a6..087aae60d 100644 --- a/wger/gallery/views/images.py +++ b/wger/gallery/views/images.py @@ -57,6 +57,7 @@ class ImageAddView(WgerFormMixin, CreateView): """ Generic view to add a new weight entry """ + model = Image form_class = ImageForm title = _('Add') @@ -88,6 +89,7 @@ class ImageUpdateView(WgerFormMixin, LoginRequiredMixin, UpdateView): """ Generic view to edit an existing weight entry """ + model = Image form_class = ImageForm diff --git a/wger/gym/apps.py b/wger/gym/apps.py index dd6a783a5..533bd33b5 100644 --- a/wger/gym/apps.py +++ b/wger/gym/apps.py @@ -20,7 +20,7 @@ from django.apps import AppConfig class GymConfig(AppConfig): name = 'wger.gym' - verbose_name = "Gym" + verbose_name = 'Gym' def ready(self): import wger.gym.signals diff --git a/wger/gym/forms.py b/wger/gym/forms.py index 2a584c908..1201bbffe 100644 --- a/wger/gym/forms.py +++ b/wger/gym/forms.py @@ -32,6 +32,7 @@ class GymUserPermissionForm(forms.ModelForm): """ Form used to set the permission group of a gym member """ + USER = 'user' GYM_ADMIN = 'admin' TRAINER = 'trainer' @@ -42,7 +43,7 @@ class GymUserPermissionForm(forms.ModelForm): class Meta: model = User - fields = ('role', ) + fields = ('role',) role = forms.MultipleChoiceField(choices=ROLES, initial=USER) @@ -69,7 +70,7 @@ class GymUserPermissionForm(forms.ModelForm): ) self.helper = FormHelper() self.helper.form_class = 'wger-form' - self.helper.add_input(Submit('submit', _("Save"), css_class='btn-success btn-block')) + self.helper.add_input(Submit('submit', _('Save'), css_class='btn-success btn-block')) class GymUserAddForm(GymUserPermissionForm, UserPersonalInformationForm): @@ -91,15 +92,12 @@ class GymUserAddForm(GymUserPermissionForm, UserPersonalInformationForm): ) username = forms.RegexField( - label=_("Username"), + label=_('Username'), max_length=30, regex=r'^[\w.@+-]+$', - help_text=_("Required. 30 characters or fewer. Letters, digits and " - "@/./+/-/_ only."), + help_text=_('Required. 30 characters or fewer. Letters, digits and ' '@/./+/-/_ only.'), error_messages={ - 'invalid': - _("This value may contain only letters, numbers and " - "@/.//-/_ characters.") + 'invalid': _('This value may contain only letters, numbers and ' '@/.//-/_ characters.') }, ) @@ -108,9 +106,9 @@ class GymUserAddForm(GymUserPermissionForm, UserPersonalInformationForm): Since User.username is unique, this check is redundant, but it sets a nicer error message than the ORM. See #13147. """ - username = self.cleaned_data["username"] + username = self.cleaned_data['username'] try: User._default_manager.get(username=username) except User.DoesNotExist: return username - raise forms.ValidationError(_("A user with that username already exists.")) + raise forms.ValidationError(_('A user with that username already exists.')) diff --git a/wger/gym/helpers.py b/wger/gym/helpers.py index 147d4f7a6..895858dfa 100644 --- a/wger/gym/helpers.py +++ b/wger/gym/helpers.py @@ -57,9 +57,11 @@ def is_any_gym_admin(user): Small utility that checks that the user object has any administrator permissions """ - return user.has_perm('gym.manage_gym')\ - or user.has_perm('gym.manage_gyms')\ + return ( + user.has_perm('gym.manage_gym') + or user.has_perm('gym.manage_gyms') or user.has_perm('gym.gym_trainer') + ) def get_permission_list(user): diff --git a/wger/gym/management/commands/dummy-generator-gyms.py b/wger/gym/management/commands/dummy-generator-gyms.py index aa443230e..233fdb076 100644 --- a/wger/gym/management/commands/dummy-generator-gyms.py +++ b/wger/gym/management/commands/dummy-generator-gyms.py @@ -37,55 +37,54 @@ class Command(BaseCommand): help = 'Dummy generator for gyms' names_first = [ - "1st", - "Body", - "Energy", - "Granite", - "Hardcore", - "Intense", - "Iron", - "Muscle", - "Peak", - "Power", - "Pumping", - "Results", - "Top", + '1st', + 'Body', + 'Energy', + 'Granite', + 'Hardcore', + 'Intense', + 'Iron', + 'Muscle', + 'Peak', + 'Power', + 'Pumping', + 'Results', + 'Top', ] names_second = [ - "Academy", - "Barbells", - "Body", - "Centre", - "Dumbbells", - "Factory", - "Fitness", - "Force", - "Gym", - "Iron", - "Pit", - "Team", - "Workout", + 'Academy', + 'Barbells', + 'Body', + 'Centre', + 'Dumbbells', + 'Factory', + 'Fitness', + 'Force', + 'Gym', + 'Iron', + 'Pit', + 'Team', + 'Workout', ] def add_arguments(self, parser): - parser.add_argument( '--nr-entries', action='store', default=10, dest='number_gyms', type=int, - help='The number of gyms to generate (default: 10)' + help='The number of gyms to generate (default: 10)', ) def handle(self, **options): gym_names_1 = DynamicProvider( - provider_name="gym_names", + provider_name='gym_names', elements=self.names_first, ) gym_names_2 = DynamicProvider( - provider_name="gym_names2", + provider_name='gym_names2', elements=self.names_second, ) @@ -107,7 +106,7 @@ class Command(BaseCommand): if part1 != part2: found = True - name = f"{part1} {part2}" + name = f'{part1} {part2}' gym = Gym() gym.name = name gym_list.append(gym) diff --git a/wger/gym/management/commands/gym-user-config.py b/wger/gym/management/commands/gym-user-config.py index 747424110..36065bbd4 100644 --- a/wger/gym/management/commands/gym-user-config.py +++ b/wger/gym/management/commands/gym-user-config.py @@ -29,6 +29,7 @@ class Command(BaseCommand): """ Check that all gym trainers and users have configurations """ + help = 'Check that all gym trainers and users have configurations' def handle(self, **options): diff --git a/wger/gym/management/commands/inactive-members.py b/wger/gym/management/commands/inactive-members.py index 70bbdcba2..29f3f3466 100644 --- a/wger/gym/management/commands/inactive-members.py +++ b/wger/gym/management/commands/inactive-members.py @@ -32,6 +32,7 @@ class Command(BaseCommand): """ Sends overviews of inactive users to gym trainers """ + help = 'Send out emails to trainers with users that have not shown recent activity' def handle(self, **options): @@ -52,7 +53,7 @@ class Command(BaseCommand): if not weeks: if int(options['verbosity']) >= 2: - self.stdout.write(" Reminders deactivatd, skipping") + self.stdout.write(' Reminders deactivatd, skipping') continue for profile in gym.userprofile_set.all(): @@ -82,7 +83,6 @@ class Command(BaseCommand): if user_list or user_list_no_activity: for trainer in trainer_list: - # Profile might not have email if not trainer.email: continue @@ -96,7 +96,7 @@ class Command(BaseCommand): context = { 'weeks': weeks, 'user_list': user_list, - 'user_list_no_activity': user_list_no_activity + 'user_list_no_activity': user_list_no_activity, } message = render_to_string('gym/email_inactive_members.html', context) mail.send_mail( diff --git a/wger/gym/migrations/0001_initial.py b/wger/gym/migrations/0001_initial.py index 18abb98cb..452aa5d04 100644 --- a/wger/gym/migrations/0001_initial.py +++ b/wger/gym/migrations/0001_initial.py @@ -6,7 +6,6 @@ import wger.gym.models class Migration(migrations.Migration): - dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] @@ -19,7 +18,7 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ('timestamp_created', models.DateTimeField(auto_now_add=True)), ('timestamp_edited', models.DateTimeField(auto_now=True)), @@ -30,8 +29,8 @@ class Migration(migrations.Migration): related_name='adminusernote_member', editable=False, to=settings.AUTH_USER_MODEL, - on_delete=models.CASCADE - ) + on_delete=models.CASCADE, + ), ), ( 'user', @@ -39,14 +38,14 @@ class Migration(migrations.Migration): related_name='adminusernote_user', editable=False, to=settings.AUTH_USER_MODEL, - on_delete=models.CASCADE - ) + on_delete=models.CASCADE, + ), ), ], options={ 'ordering': ['-timestamp_created'], }, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.CreateModel( name='Gym', @@ -55,34 +54,34 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ('name', models.CharField(max_length=60, verbose_name='Name')), ( 'phone', - models.CharField(max_length=20, null=True, verbose_name='Phone', blank=True) + models.CharField(max_length=20, null=True, verbose_name='Phone', blank=True), ), ( 'email', - models.EmailField(max_length=75, null=True, verbose_name='Email', blank=True) + models.EmailField(max_length=75, null=True, verbose_name='Email', blank=True), ), ( 'owner', - models.CharField(max_length=100, null=True, verbose_name='Owner', blank=True) + models.CharField(max_length=100, null=True, verbose_name='Owner', blank=True), ), ( 'zip_code', models.IntegerField( max_length=5, null=True, verbose_name='ZIP code', blank=True - ) + ), ), ( 'city', - models.CharField(max_length=30, null=True, verbose_name='City', blank=True) + models.CharField(max_length=30, null=True, verbose_name='City', blank=True), ), ( 'street', - models.CharField(max_length=30, null=True, verbose_name='Street', blank=True) + models.CharField(max_length=30, null=True, verbose_name='Street', blank=True), ), ], options={ @@ -90,10 +89,10 @@ class Migration(migrations.Migration): 'permissions': ( ('gym_trainer', 'Trainer, can see the users for a gym'), ('manage_gym', 'Admin, can manage users for a gym'), - ('manage_gyms', 'Admin, can administrate the different gyms') + ('manage_gyms', 'Admin, can administrate the different gyms'), ), }, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.CreateModel( name='GymAdminConfig', @@ -102,26 +101,26 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ( 'overview_inactive', models.BooleanField( default=True, help_text='Receive email overviews of inactive members', - verbose_name='Overview inactive members' - ) + verbose_name='Overview inactive members', + ), ), ('gym', models.ForeignKey(editable=False, to='gym.Gym', on_delete=models.CASCADE)), ( 'user', models.OneToOneField( editable=False, to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE - ) + ), ), ], options={}, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.CreateModel( name='GymConfig', @@ -130,17 +129,16 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ( 'weeks_inactive', models.PositiveIntegerField( default=4, - help_text= - 'Number of weeks since the last time a user logged his presence to be considered inactive', + help_text='Number of weeks since the last time a user logged his presence to be considered inactive', max_length=2, - verbose_name='Reminder inactive members' - ) + verbose_name='Reminder inactive members', + ), ), ( 'gym', @@ -148,12 +146,12 @@ class Migration(migrations.Migration): related_name='config', editable=False, to='gym.Gym', - on_delete=models.CASCADE - ) + on_delete=models.CASCADE, + ), ), ], options={}, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.CreateModel( name='GymUserConfig', @@ -162,26 +160,26 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ( 'include_inactive', models.BooleanField( default=True, help_text='Include this user in the email list with inactive members', - verbose_name='Include in inactive overview' - ) + verbose_name='Include in inactive overview', + ), ), ('gym', models.ForeignKey(editable=False, to='gym.Gym', on_delete=models.CASCADE)), ( 'user', models.OneToOneField( editable=False, to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE - ) + ), ), ], options={}, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.CreateModel( name='UserDocument', @@ -190,7 +188,7 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ('timestamp_created', models.DateTimeField(auto_now_add=True)), ('timestamp_edited', models.DateTimeField(auto_now=True)), @@ -198,8 +196,8 @@ class Migration(migrations.Migration): 'document', models.FileField( upload_to=wger.gym.models.user_document.gym_document_upload_dir, - verbose_name='Document' - ) + verbose_name='Document', + ), ), ('original_name', models.CharField(max_length=128, editable=False)), ( @@ -208,8 +206,8 @@ class Migration(migrations.Migration): help_text='Will use file name if nothing provided', max_length=60, verbose_name='Name', - blank=True - ) + blank=True, + ), ), ('note', models.TextField(null=True, verbose_name='Note', blank=True)), ( @@ -218,8 +216,8 @@ class Migration(migrations.Migration): related_name='userdocument_member', editable=False, to=settings.AUTH_USER_MODEL, - on_delete=models.CASCADE - ) + on_delete=models.CASCADE, + ), ), ( 'user', @@ -227,14 +225,14 @@ class Migration(migrations.Migration): related_name='userdocument_user', editable=False, to=settings.AUTH_USER_MODEL, - on_delete=models.CASCADE - ) + on_delete=models.CASCADE, + ), ), ], options={ 'ordering': ['-timestamp_created'], }, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.AlterUniqueTogether( name='gymuserconfig', diff --git a/wger/gym/migrations/0002_auto_20151003_1944.py b/wger/gym/migrations/0002_auto_20151003_1944.py index 9d729ee2f..ff20c20b0 100644 --- a/wger/gym/migrations/0002_auto_20151003_1944.py +++ b/wger/gym/migrations/0002_auto_20151003_1944.py @@ -6,7 +6,6 @@ import datetime class Migration(migrations.Migration): - dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), ('gym', '0001_initial'), @@ -27,10 +26,9 @@ class Migration(migrations.Migration): model_name='gymconfig', name='weeks_inactive', field=models.PositiveIntegerField( - help_text= - 'Number of weeks since the last time a user logged his presence to be considered inactive', + help_text='Number of weeks since the last time a user logged his presence to be considered inactive', default=4, - verbose_name='Reminder inactive members' + verbose_name='Reminder inactive members', ), ), ] diff --git a/wger/gym/migrations/0003_auto_20151003_2008.py b/wger/gym/migrations/0003_auto_20151003_2008.py index 0acd7062b..204060aa7 100644 --- a/wger/gym/migrations/0003_auto_20151003_2008.py +++ b/wger/gym/migrations/0003_auto_20151003_2008.py @@ -6,7 +6,6 @@ from django.conf import settings class Migration(migrations.Migration): - dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), ('gym', '0002_auto_20151003_1944'), @@ -20,7 +19,7 @@ class Migration(migrations.Migration): 'id', models.AutoField( auto_created=True, verbose_name='ID', serialize=False, primary_key=True - ) + ), ), ('timestamp_created', models.DateTimeField(auto_now_add=True)), ('timestamp_edited', models.DateTimeField(auto_now=True)), @@ -32,11 +31,15 @@ class Migration(migrations.Migration): default='3', help_text='How often the amount will be charged to the member', choices=[ - ('1', 'Yearly'), ('2', 'Half yearly'), ('3', 'Monthly'), - ('4', 'Biweekly'), ('5', 'Weekly'), ('6', 'Daily') + ('1', 'Yearly'), + ('2', 'Half yearly'), + ('3', 'Monthly'), + ('4', 'Biweekly'), + ('5', 'Weekly'), + ('6', 'Daily'), ], - max_length=2 - ) + max_length=2, + ), ), ('is_active', models.BooleanField(verbose_name='Contract is active', default=True)), ( @@ -45,35 +48,35 @@ class Migration(migrations.Migration): verbose_name='Start date', blank=True, default=datetime.date.today, - null=True - ) + null=True, + ), ), ('date_end', models.DateField(verbose_name='End date', blank=True, null=True)), ( 'email', - models.EmailField(verbose_name='Email', blank=True, null=True, max_length=254) + models.EmailField(verbose_name='Email', blank=True, null=True, max_length=254), ), ( 'zip_code', - models.CharField(verbose_name='ZIP code', blank=True, null=True, max_length=10) + models.CharField(verbose_name='ZIP code', blank=True, null=True, max_length=10), ), ( 'city', - models.CharField(verbose_name='City', blank=True, null=True, max_length=30) + models.CharField(verbose_name='City', blank=True, null=True, max_length=30), ), ( 'street', - models.CharField(verbose_name='Street', blank=True, null=True, max_length=30) + models.CharField(verbose_name='Street', blank=True, null=True, max_length=30), ), ( 'phone', - models.CharField(verbose_name='Phone', blank=True, null=True, max_length=20) + models.CharField(verbose_name='Phone', blank=True, null=True, max_length=20), ), ( 'profession', models.CharField( verbose_name='Profession', blank=True, null=True, max_length=50 - ) + ), ), ('note', models.TextField(verbose_name='Note', blank=True, null=True)), ], @@ -88,12 +91,12 @@ class Migration(migrations.Migration): 'id', models.AutoField( auto_created=True, verbose_name='ID', serialize=False, primary_key=True - ) + ), ), ('name', models.CharField(verbose_name='Name', max_length=25)), ( 'description', - models.TextField(verbose_name='Description', blank=True, null=True) + models.TextField(verbose_name='Description', blank=True, null=True), ), ('gym', models.ForeignKey(to='gym.Gym', editable=False, on_delete=models.CASCADE)), ], @@ -106,7 +109,7 @@ class Migration(migrations.Migration): blank=True, null=True, to='gym.ContractType', - on_delete=models.CASCADE + on_delete=models.CASCADE, ), ), migrations.AddField( @@ -116,7 +119,7 @@ class Migration(migrations.Migration): editable=False, to=settings.AUTH_USER_MODEL, related_name='contract_member', - on_delete=models.CASCADE + on_delete=models.CASCADE, ), ), migrations.AddField( @@ -126,7 +129,7 @@ class Migration(migrations.Migration): editable=False, to=settings.AUTH_USER_MODEL, related_name='contract_user', - on_delete=models.CASCADE + on_delete=models.CASCADE, ), ), ] diff --git a/wger/gym/migrations/0004_auto_20151003_2357.py b/wger/gym/migrations/0004_auto_20151003_2357.py index 24ddc0233..b24cb28e7 100644 --- a/wger/gym/migrations/0004_auto_20151003_2357.py +++ b/wger/gym/migrations/0004_auto_20151003_2357.py @@ -4,7 +4,6 @@ from django.db import models, migrations class Migration(migrations.Migration): - dependencies = [ ('gym', '0003_auto_20151003_2008'), ] diff --git a/wger/gym/migrations/0005_auto_20151023_1522.py b/wger/gym/migrations/0005_auto_20151023_1522.py index 60d5c7412..6235ff46e 100644 --- a/wger/gym/migrations/0005_auto_20151023_1522.py +++ b/wger/gym/migrations/0005_auto_20151023_1522.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('gym', '0004_auto_20151003_2357'), ] @@ -17,12 +16,12 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ('name', models.CharField(max_length=25, verbose_name='Name')), ( 'description', - models.TextField(null=True, verbose_name='Description', blank=True) + models.TextField(null=True, verbose_name='Description', blank=True), ), ('gym', models.ForeignKey(editable=False, to='gym.Gym', on_delete=models.CASCADE)), ], diff --git a/wger/gym/migrations/0006_auto_20160214_1013.py b/wger/gym/migrations/0006_auto_20160214_1013.py index 02d0970ff..6c07037ad 100644 --- a/wger/gym/migrations/0006_auto_20160214_1013.py +++ b/wger/gym/migrations/0006_auto_20160214_1013.py @@ -7,13 +7,13 @@ def update_permission_names(apps, schema_editor): """ Updates the wording of our three custom gym permissions """ - Permission = apps.get_model("auth", "Permission") + Permission = apps.get_model('auth', 'Permission') for name in [ - 'Trainer, can see the users for a gym', 'Admin, can manage users for a gym', - 'Admin, can administrate the different gyms' + 'Trainer, can see the users for a gym', + 'Admin, can manage users for a gym', + 'Admin, can administrate the different gyms', ]: - permissions = Permission.objects.filter(name=name) if permissions.exists(): permissions[0].name = name.replace(',', ':') @@ -21,7 +21,6 @@ def update_permission_names(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ('gym', '0005_auto_20151023_1522'), ] diff --git a/wger/gym/migrations/0007_auto_20170123_0920.py b/wger/gym/migrations/0007_auto_20170123_0920.py index fb6ce4772..93a3ef197 100644 --- a/wger/gym/migrations/0007_auto_20170123_0920.py +++ b/wger/gym/migrations/0007_auto_20170123_0920.py @@ -5,7 +5,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('gym', '0006_auto_20160214_1013'), ] @@ -18,8 +17,8 @@ class Migration(migrations.Migration): 'permissions': ( ('gym_trainer', 'Trainer: can see the users for a gym'), ('manage_gym', 'Admin: can manage users for a gym'), - ('manage_gyms', 'Admin: can administrate the different gyms') - ) + ('manage_gyms', 'Admin: can administrate the different gyms'), + ), }, ), migrations.AddField( @@ -42,7 +41,7 @@ class Migration(migrations.Migration): field=models.BooleanField( default=True, help_text='Receive email overviews of inactive members', - verbose_name='Overview of inactive members' + verbose_name='Overview of inactive members', ), ), migrations.AlterField( @@ -50,9 +49,8 @@ class Migration(migrations.Migration): name='weeks_inactive', field=models.PositiveIntegerField( default=4, - help_text= - 'Number of weeks since the last time a user logged his presence to be considered inactive', - verbose_name='Reminder of inactive members' + help_text='Number of weeks since the last time a user logged his presence to be considered inactive', + verbose_name='Reminder of inactive members', ), ), ] diff --git a/wger/gym/migrations/0008_auto_20190618_1617.py b/wger/gym/migrations/0008_auto_20190618_1617.py index 9674666c0..81473daca 100644 --- a/wger/gym/migrations/0008_auto_20190618_1617.py +++ b/wger/gym/migrations/0008_auto_20190618_1617.py @@ -5,7 +5,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('gym', '0007_auto_20170123_0920'), ] @@ -17,7 +16,7 @@ class Migration(migrations.Migration): field=models.BooleanField( default=False, help_text='Show the name of the gym in the site header', - verbose_name='Show name in header' + verbose_name='Show name in header', ), ), ] diff --git a/wger/gym/models/admin_user_note.py b/wger/gym/models/admin_user_note.py index dd60bdd75..a141c5c98 100644 --- a/wger/gym/models/admin_user_note.py +++ b/wger/gym/models/admin_user_note.py @@ -29,8 +29,9 @@ class AdminUserNote(m.Model): """ Order by time """ + ordering = [ - "-timestamp_created", + '-timestamp_created', ] user = m.ForeignKey( diff --git a/wger/gym/models/contract.py b/wger/gym/models/contract.py index 37ee3df7f..f7fba4506 100644 --- a/wger/gym/models/contract.py +++ b/wger/gym/models/contract.py @@ -39,8 +39,9 @@ class ContractType(m.Model): """ Order by name """ + ordering = [ - "name", + 'name', ] gym = m.ForeignKey(Gym, editable=False, on_delete=m.CASCADE) @@ -66,7 +67,7 @@ class ContractType(m.Model): """ Return a more human-readable representation """ - return "{}".format(self.name) + return '{}'.format(self.name) def get_owner_object(self): """ @@ -89,8 +90,9 @@ class ContractOption(m.Model): """ Order by name """ + ordering = [ - "name", + 'name', ] gym = m.ForeignKey(Gym, editable=False, on_delete=m.CASCADE) @@ -116,7 +118,7 @@ class ContractOption(m.Model): """ Return a more human-readable representation """ - return "{}".format(self.name) + return '{}'.format(self.name) def get_owner_object(self): """ @@ -138,7 +140,7 @@ class Contract(m.Model): AMOUNT_TYPE_DAILY = '6' AMOUNT_TYPE = ( - (AMOUNT_TYPE_YEARLY, _("Yearly")), + (AMOUNT_TYPE_YEARLY, _('Yearly')), (AMOUNT_TYPE_HALFYEARLY, _('Half yearly')), (AMOUNT_TYPE_MONTHLY, _('Monthly')), (AMOUNT_TYPE_BIWEEKLY, _('Biweekly')), @@ -150,8 +152,9 @@ class Contract(m.Model): """ Order by time """ + ordering = [ - "-date_start", + '-date_start', ] user = m.ForeignKey( @@ -219,7 +222,7 @@ class Contract(m.Model): max_length=2, choices=AMOUNT_TYPE, default=AMOUNT_TYPE_MONTHLY, - help_text=_('How often the amount will be charged to the member') + help_text=_('How often the amount will be charged to the member'), ) """ How often the amount will be charged to the member @@ -311,7 +314,7 @@ class Contract(m.Model): """ Return a more human-readable representation """ - return "#{}".format(self.id) + return '#{}'.format(self.id) def get_absolute_url(self): """ diff --git a/wger/gym/models/gym.py b/wger/gym/models/gym.py index cf95e92da..6c1938dd2 100644 --- a/wger/gym/models/gym.py +++ b/wger/gym/models/gym.py @@ -30,12 +30,12 @@ class Gym(m.Model): class Meta: permissions = ( - ("gym_trainer", _("Trainer: can see the users for a gym")), - ("manage_gym", _("Admin: can manage users for a gym")), - ("manage_gyms", _("Admin: can administrate the different gyms")), + ('gym_trainer', _('Trainer: can see the users for a gym')), + ('manage_gym', _('Admin: can manage users for a gym')), + ('manage_gyms', _('Admin: can administrate the different gyms')), ) ordering = [ - "name", + 'name', ] objects = GymManager() diff --git a/wger/gym/models/gym_config.py b/wger/gym/models/gym_config.py index 333c9f5a4..7c7ce04c1 100644 --- a/wger/gym/models/gym_config.py +++ b/wger/gym/models/gym_config.py @@ -46,7 +46,7 @@ class GymConfig(m.Model): 'Number of weeks since the last time a ' 'user logged his presence to be considered inactive' ), - default=4 + default=4, ) """ Reminder of inactive members diff --git a/wger/gym/models/user_config.py b/wger/gym/models/user_config.py index 850b46fde..36deb15f1 100644 --- a/wger/gym/models/user_config.py +++ b/wger/gym/models/user_config.py @@ -90,8 +90,7 @@ class GymUserConfig(AbstractGymUserConfigModel, m.Model): include_inactive = m.BooleanField( verbose_name=_('Include in inactive overview'), - help_text=_('Include this user in the email list with ' - 'inactive members'), + help_text=_('Include this user in the email list with ' 'inactive members'), default=True, ) """ diff --git a/wger/gym/models/user_document.py b/wger/gym/models/user_document.py index 9383d0ad3..9bdf56352 100644 --- a/wger/gym/models/user_document.py +++ b/wger/gym/models/user_document.py @@ -27,7 +27,7 @@ def gym_document_upload_dir(instance, filename): """ Returns the upload target for documents """ - return "gym/documents/{0}/{1}/{2}".format( + return 'gym/documents/{0}/{1}/{2}'.format( instance.member.userprofile.gym.id, instance.member.id, uuid.uuid4(), @@ -43,8 +43,9 @@ class UserDocument(m.Model): """ Order by time """ + ordering = [ - "-timestamp_created", + '-timestamp_created', ] user = m.ForeignKey(User, editable=False, related_name='userdocument_user', on_delete=m.CASCADE) @@ -106,9 +107,9 @@ class UserDocument(m.Model): Return a more human-readable representation """ if self.name != self.original_name: - return "{} ({})".format(self.name, self.original_name) + return '{} ({})'.format(self.name, self.original_name) else: - return "{}".format(self.name) + return '{}'.format(self.name) def get_owner_object(self): """ diff --git a/wger/gym/tests/test_admin_user_notes.py b/wger/gym/tests/test_admin_user_notes.py index c5fef3d1e..077f9c023 100644 --- a/wger/gym/tests/test_admin_user_notes.py +++ b/wger/gym/tests/test_admin_user_notes.py @@ -30,6 +30,7 @@ class AdminNoteOverviewTest(WgerAccessTestCase): """ Tests accessing the admin notes overview page """ + url = reverse_lazy('gym:admin_note:list', kwargs={'user_pk': 14}) anonymous_fail = True user_success = ( @@ -51,6 +52,7 @@ class AddAdminNoteTestCase(WgerAddTestCase): """ Tests adding a new admin note """ + object_class = AdminUserNote url = reverse_lazy('gym:admin_note:add', kwargs={'user_pk': 14}) data = {'note': 'The note text goes here'} diff --git a/wger/gym/tests/test_contract_options.py b/wger/gym/tests/test_contract_options.py index 569461bf0..4488ed7d9 100644 --- a/wger/gym/tests/test_contract_options.py +++ b/wger/gym/tests/test_contract_options.py @@ -106,6 +106,7 @@ class AccessContractOptionOverviewTestCase(WgerAccessTestCase): """ Test accessing the contract option page """ + url = reverse('gym:contract-option:list', kwargs={'gym_pk': 1}) user_success = ('manager1', 'manager2') user_fail = ( diff --git a/wger/gym/tests/test_contract_types.py b/wger/gym/tests/test_contract_types.py index c5a0fee1e..697c17f2e 100644 --- a/wger/gym/tests/test_contract_types.py +++ b/wger/gym/tests/test_contract_types.py @@ -103,6 +103,7 @@ class AccessContractTypeOverviewTestCase(WgerAccessTestCase): """ Test accessing the contract list page """ + url = reverse('gym:contract_type:list', kwargs={'gym_pk': 1}) user_success = ('manager1', 'manager2') user_fail = ( diff --git a/wger/gym/tests/test_contracts.py b/wger/gym/tests/test_contracts.py index e5eca1064..a1a474d54 100644 --- a/wger/gym/tests/test_contracts.py +++ b/wger/gym/tests/test_contracts.py @@ -51,6 +51,7 @@ class AccessContractTestCase(WgerAccessTestCase): """ Test accessing the detail page of a contract """ + url = reverse('gym:contract:view', kwargs={'pk': 1}) user_success = ('manager1', 'manager2') user_fail = ( @@ -71,6 +72,7 @@ class AccessContractOverviewTestCase(WgerAccessTestCase): """ Test accessing the contract list page """ + url = reverse('gym:contract:list', kwargs={'user_pk': 4}) user_success = ('manager1', 'manager2') user_fail = ( diff --git a/wger/gym/tests/test_export.py b/wger/gym/tests/test_export.py index 3144f6265..5a821bc23 100644 --- a/wger/gym/tests/test_export.py +++ b/wger/gym/tests/test_export.py @@ -42,8 +42,9 @@ class GymMembersCsvExportTestCase(WgerTestCase): self.assertEqual(response['Content-Type'], 'text/csv') today = datetime.date.today() - filename = 'User-data-gym-{gym}-{t.year}-{t.month:02d}-{t.day:02d}.csv'.\ - format(t=today, gym=gym.id) + filename = 'User-data-gym-{gym}-{t.year}-{t.month:02d}-{t.day:02d}.csv'.format( + t=today, gym=gym.id + ) self.assertEqual( response['Content-Disposition'], 'attachment; filename={0}'.format(filename) ) diff --git a/wger/gym/tests/test_generator.py b/wger/gym/tests/test_generator.py index 0ed321779..59f67c261 100644 --- a/wger/gym/tests/test_generator.py +++ b/wger/gym/tests/test_generator.py @@ -21,7 +21,6 @@ from wger.gym.models import Gym class GymGeneratorTestCase(WgerTestCase): - def test_generator(self): # Arrange Gym.objects.all().delete() diff --git a/wger/gym/tests/test_gym.py b/wger/gym/tests/test_gym.py index 0b3dbd86b..af8e28b8e 100644 --- a/wger/gym/tests/test_gym.py +++ b/wger/gym/tests/test_gym.py @@ -38,13 +38,14 @@ class GymRepresentationTestCase(WgerTestCase): """ Test that the representation of an object is correct """ - self.assertEqual("{0}".format(Gym.objects.get(pk=1)), 'Test 123') + self.assertEqual('{0}'.format(Gym.objects.get(pk=1)), 'Test 123') class GymOverviewTest(WgerAccessTestCase): """ Tests accessing the gym overview page """ + url = 'gym:gym:list' anonymous_fail = True user_success = ( @@ -66,6 +67,7 @@ class GymUserOverviewTest(WgerAccessTestCase): """ Tests accessing the gym user overview page """ + url = reverse_lazy('gym:gym:user-list', kwargs={'pk': 1}) anonymous_fail = True user_success = ( @@ -88,6 +90,7 @@ class AddGymTestCase(WgerAddTestCase): """ Tests adding a new gym """ + object_class = Gym url = 'gym:gym:add' data = {'name': 'The name here'} diff --git a/wger/gym/tests/test_user.py b/wger/gym/tests/test_user.py index a7cbff806..6466c1940 100644 --- a/wger/gym/tests/test_user.py +++ b/wger/gym/tests/test_user.py @@ -51,13 +51,14 @@ class GymAddUserTestCase(WgerTestCase): self.assertEqual(response.status_code, 200) response = self.client.post( - reverse('gym:gym:add-user', kwargs={'gym_pk': 1}), { + reverse('gym:gym:add-user', kwargs={'gym_pk': 1}), + { 'first_name': 'Cletus', 'last_name': 'Spuckle', 'username': 'cletus', 'email': 'cletus@spuckle-megacorp.com', 'role': 'admin', - } + }, ) count_after = User.objects.all().count() if fail: diff --git a/wger/gym/tests/test_user_documents.py b/wger/gym/tests/test_user_documents.py index 69be6b33f..8eb3dd70d 100644 --- a/wger/gym/tests/test_user_documents.py +++ b/wger/gym/tests/test_user_documents.py @@ -30,6 +30,7 @@ class UserDocumentOverviewTest(WgerAccessTestCase): """ Tests accessing the user document overview page """ + url = reverse('gym:document:list', kwargs={'user_pk': 14}) anonymous_fail = True user_success = ( diff --git a/wger/gym/urls.py b/wger/gym/urls.py index d799b6ef6..0ce702faf 100644 --- a/wger/gym/urls.py +++ b/wger/gym/urls.py @@ -247,22 +247,22 @@ patterns_export = [ # All patterns for this app # urlpatterns = [ - path('', include((patterns_gym, 'gym'), namespace="gym")), - path('config/', include((patterns_gymconfig, 'config'), namespace="config")), + path('', include((patterns_gym, 'gym'), namespace='gym')), + path('config/', include((patterns_gymconfig, 'config'), namespace='config')), path( - 'admin-config/', include((patterns_adminconfig, 'admin_config'), namespace="admin_config") + 'admin-config/', include((patterns_adminconfig, 'admin_config'), namespace='admin_config') ), - path('user-config/', include((patterns_userconfig, 'user_config'), namespace="user_config")), - path('notes/', include((patterns_admin_notes, 'admin_note'), namespace="admin_note")), - path('document/', include((patterns_documents, 'document'), namespace="document")), - path('contract/', include((patterns_contracts, 'contract'), namespace="contract")), + path('user-config/', include((patterns_userconfig, 'user_config'), namespace='user_config')), + path('notes/', include((patterns_admin_notes, 'admin_note'), namespace='admin_note')), + path('document/', include((patterns_documents, 'document'), namespace='document')), + path('contract/', include((patterns_contracts, 'contract'), namespace='contract')), path( 'contract-type/', - include((patterns_contract_types, 'contract_type'), namespace="contract_type") + include((patterns_contract_types, 'contract_type'), namespace='contract_type'), ), path( 'contract-option/', - include((patterns_contract_options, 'contract-option'), namespace="contract-option") + include((patterns_contract_options, 'contract-option'), namespace='contract-option'), ), - path('export/', include((patterns_export, 'export'), namespace="export")), + path('export/', include((patterns_export, 'export'), namespace='export')), ] diff --git a/wger/gym/views/admin_notes.py b/wger/gym/views/admin_notes.py index 0e9476294..a3c98da4c 100644 --- a/wger/gym/views/admin_notes.py +++ b/wger/gym/views/admin_notes.py @@ -51,6 +51,7 @@ class ListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): """ Overview of all available admin notes """ + model = AdminUserNote permission_required = 'gym.add_adminusernote' template_name = 'admin_notes/list.html' diff --git a/wger/gym/views/contract.py b/wger/gym/views/contract.py index 39465f77b..0d25733d1 100644 --- a/wger/gym/views/contract.py +++ b/wger/gym/views/contract.py @@ -191,6 +191,7 @@ class ListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): """ Overview of all available admin notes """ + model = Contract permission_required = 'gym.add_contract' template_name = 'contract/list.html' diff --git a/wger/gym/views/contract_option.py b/wger/gym/views/contract_option.py index 1994d800e..8d65bcc25 100644 --- a/wger/gym/views/contract_option.py +++ b/wger/gym/views/contract_option.py @@ -164,6 +164,7 @@ class ListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): """ Overview of all available contract options """ + model = ContractOption permission_required = 'gym.add_contractoption' template_name = 'contract_option/list.html' diff --git a/wger/gym/views/contract_type.py b/wger/gym/views/contract_type.py index d0e3c3645..51bb041e9 100644 --- a/wger/gym/views/contract_type.py +++ b/wger/gym/views/contract_type.py @@ -164,6 +164,7 @@ class ListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): """ Overview of all available contract options """ + model = ContractType permission_required = 'gym.add_contracttype' template_name = 'contract_type/list.html' diff --git a/wger/gym/views/document.py b/wger/gym/views/document.py index cf26c5e6c..49bad10a6 100644 --- a/wger/gym/views/document.py +++ b/wger/gym/views/document.py @@ -51,6 +51,7 @@ class ListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): """ Overview of all available admin notes """ + model = UserDocument permission_required = 'gym.add_userdocument' template_name = 'document/list.html' diff --git a/wger/gym/views/export.py b/wger/gym/views/export.py index 28bc90b78..14454af80 100644 --- a/wger/gym/views/export.py +++ b/wger/gym/views/export.py @@ -42,12 +42,10 @@ def users(request, gym_pk): """ gym = get_object_or_404(Gym, pk=gym_pk) - if not request.user.has_perm('gym.manage_gyms') \ - and not request.user.has_perm('gym.manage_gym'): + if not request.user.has_perm('gym.manage_gyms') and not request.user.has_perm('gym.manage_gym'): return HttpResponseForbidden() - if request.user.has_perm('gym.manage_gym') \ - and request.user.userprofile.gym != gym: + if request.user.has_perm('gym.manage_gym') and request.user.userprofile.gym != gym: return HttpResponseForbidden() # Create CSV 'file' @@ -67,7 +65,7 @@ def users(request, gym_pk): _('ZIP code'), _('City'), _('Street'), - _('Phone') + _('Phone'), ] ) for user in Gym.objects.get_members(gym_pk): diff --git a/wger/gym/views/gym.py b/wger/gym/views/gym.py index 70b5893fe..a9edbf637 100644 --- a/wger/gym/views/gym.py +++ b/wger/gym/views/gym.py @@ -88,6 +88,7 @@ class GymListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): """ Overview of all available gyms """ + model = Gym permission_required = 'gym.manage_gyms' template_name = 'gym/list.html' @@ -105,6 +106,7 @@ class GymUserListView(LoginRequiredMixin, WgerMultiplePermissionRequiredMixin, L """ Overview of all users for a specific gym """ + model = User permission_required = ('gym.manage_gym', 'gym.gym_trainer', 'gym.manage_gyms') template_name = 'gym/member_list.html' @@ -113,10 +115,10 @@ class GymUserListView(LoginRequiredMixin, WgerMultiplePermissionRequiredMixin, L """ Only managers and trainers for this gym can access the members """ - if request.user.has_perm('gym.manage_gyms') \ - or ((request.user.has_perm('gym.manage_gym') - or request.user.has_perm('gym.gym_trainer')) - and request.user.userprofile.gym_id == int(self.kwargs['pk'])): + if request.user.has_perm('gym.manage_gyms') or ( + (request.user.has_perm('gym.manage_gym') or request.user.has_perm('gym.gym_trainer')) + and request.user.userprofile.gym_id == int(self.kwargs['pk']) + ): return super(GymUserListView, self).dispatch(request, *args, **kwargs) return HttpResponseForbidden() @@ -138,8 +140,8 @@ class GymUserListView(LoginRequiredMixin, WgerMultiplePermissionRequiredMixin, L 'manage_gym': u.has_perm('gym.manage_gym'), 'manage_gyms': u.has_perm('gym.manage_gyms'), 'gym_trainer': u.has_perm('gym.gym_trainer'), - 'any_admin': is_any_gym_admin(u) - } + 'any_admin': is_any_gym_admin(u), + }, } ) return out @@ -153,9 +155,8 @@ class GymUserListView(LoginRequiredMixin, WgerMultiplePermissionRequiredMixin, L context['admin_count'] = len(context['object_list']['admins']) context['user_count'] = len(context['object_list']['members']) context['user_table'] = { - 'keys': [_('ID'), _('Username'), _('Name'), - _('Last activity')], - 'users': context['object_list']['members'] + 'keys': [_('ID'), _('Username'), _('Name'), _('Last activity')], + 'users': context['object_list']['members'], } return context @@ -182,13 +183,12 @@ def gym_new_user_info(request): if not request.session.get('gym.user'): return HttpResponseRedirect(reverse('gym:gym:list')) - if not request.user.has_perm('gym.manage_gyms') \ - and not request.user.has_perm('gym.manage_gym'): + if not request.user.has_perm('gym.manage_gyms') and not request.user.has_perm('gym.manage_gym'): return HttpResponseForbidden() context = { 'new_user': get_object_or_404(User, pk=request.session['gym.user']['user_pk']), - 'password': request.session['gym.user']['password'] + 'password': request.session['gym.user']['password'], } return render(request, 'gym/new_user.html', context) @@ -204,8 +204,7 @@ def gym_new_user_info_export(request): if not request.session.get('gym.user'): return HttpResponseRedirect(reverse('gym:gym:list')) - if not request.user.has_perm('gym.manage_gyms') \ - and not request.user.has_perm('gym.manage_gym'): + if not request.user.has_perm('gym.manage_gyms') and not request.user.has_perm('gym.manage_gym'): return HttpResponseForbidden() new_user = get_object_or_404(User, pk=request.session['gym.user']['user_pk']) @@ -218,8 +217,11 @@ def gym_new_user_info_export(request): writer.writerow([_('Username'), _('First name'), _('Last name'), _('Gym'), _('Password')]) writer.writerow( [ - new_username, new_user.first_name, new_user.last_name, new_user.userprofile.gym.name, - password + new_username, + new_user.first_name, + new_user.last_name, + new_user.userprofile.gym.name, + password, ] ) @@ -243,12 +245,13 @@ def reset_user_password(request, user_pk): if not request.user.is_authenticated: return HttpResponseForbidden() - if not request.user.has_perm('gym.manage_gyms') \ - and not request.user.has_perm('gym.manage_gym'): + if not request.user.has_perm('gym.manage_gyms') and not request.user.has_perm('gym.manage_gym'): return HttpResponseForbidden() - if request.user.has_perm('gym.manage_gym') \ - and request.user.userprofile.gym != user.userprofile.gym: + if ( + request.user.has_perm('gym.manage_gym') + and request.user.userprofile.gym != user.userprofile.gym + ): return HttpResponseForbidden() password = password_generator() @@ -282,7 +285,6 @@ def gym_permissions_user_edit(request, user_pk): form = GymUserPermissionForm(available_roles=form_group_permission, data=request.POST) if form.is_valid(): - # Remove the user from all gym permission groups member.groups.remove(Group.objects.get(name='gym_member')) member.groups.remove(Group.objects.get(name='gym_trainer')) @@ -357,15 +359,18 @@ class GymAddUserView( if not request.user.is_authenticated: return HttpResponseForbidden() - if not request.user.has_perm('gym.manage_gyms') \ - and not request.user.has_perm('gym.manage_gym'): + if not request.user.has_perm('gym.manage_gyms') and not request.user.has_perm( + 'gym.manage_gym' + ): return HttpResponseForbidden() # Gym managers can edit their own gym only, general gym managers # can edit all gyms - if request.user.has_perm('gym.manage_gym') \ - and not request.user.has_perm('gym.manage_gyms') \ - and request.user.userprofile.gym_id != int(self.kwargs['gym_pk']): + if ( + request.user.has_perm('gym.manage_gym') + and not request.user.has_perm('gym.manage_gyms') + and request.user.userprofile.gym_id != int(self.kwargs['gym_pk']) + ): return HttpResponseForbidden() return super(GymAddUserView, self).dispatch(request, *args, **kwargs) @@ -445,8 +450,7 @@ class GymUpdateView(WgerFormMixin, LoginRequiredMixin, PermissionRequiredMixin, if not request.user.is_authenticated: return HttpResponseForbidden() - if request.user.has_perm('gym.manage_gym') \ - and not request.user.has_perm('gym.manage_gyms'): + if request.user.has_perm('gym.manage_gym') and not request.user.has_perm('gym.manage_gyms'): if request.user.userprofile.gym_id != int(self.kwargs['pk']): return HttpResponseForbidden() return super(GymUpdateView, self).dispatch(request, *args, **kwargs) diff --git a/wger/mailer/apps.py b/wger/mailer/apps.py index 9d2716146..4db9128af 100644 --- a/wger/mailer/apps.py +++ b/wger/mailer/apps.py @@ -20,7 +20,7 @@ from django.apps import AppConfig class Config(AppConfig): name = 'wger.mailer' - verbose_name = "Email" + verbose_name = 'Email' def ready(self): pass diff --git a/wger/mailer/migrations/0001_initial.py b/wger/mailer/migrations/0001_initial.py index 2460ca991..d8a4f9a7b 100644 --- a/wger/mailer/migrations/0001_initial.py +++ b/wger/mailer/migrations/0001_initial.py @@ -5,7 +5,6 @@ from django.conf import settings class Migration(migrations.Migration): - dependencies = [ ('gym', '0004_auto_20151003_2357'), migrations.swappable_dependency(settings.AUTH_USER_MODEL), @@ -19,7 +18,7 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ('email', models.EmailField(max_length=254)), ], @@ -31,7 +30,7 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ('date', models.DateField(auto_now=True)), ('subject', models.CharField(max_length=100)), @@ -41,7 +40,7 @@ class Migration(migrations.Migration): 'user', models.ForeignKey( editable=False, to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE - ) + ), ), ], ), diff --git a/wger/mailer/migrations/0002_auto_20190618_1617.py b/wger/mailer/migrations/0002_auto_20190618_1617.py index f1204a75b..32d999c63 100644 --- a/wger/mailer/migrations/0002_auto_20190618_1617.py +++ b/wger/mailer/migrations/0002_auto_20190618_1617.py @@ -6,7 +6,6 @@ import django.db.models.deletion class Migration(migrations.Migration): - dependencies = [ ('mailer', '0001_initial'), ] @@ -23,7 +22,7 @@ class Migration(migrations.Migration): editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='mailer_log', - to='gym.Gym' + to='gym.Gym', ), ), ] diff --git a/wger/mailer/migrations/0003_auto_20201201_0653.py b/wger/mailer/migrations/0003_auto_20201201_0653.py index e418d3251..6f2051cd5 100644 --- a/wger/mailer/migrations/0003_auto_20201201_0653.py +++ b/wger/mailer/migrations/0003_auto_20201201_0653.py @@ -5,7 +5,6 @@ import django.db.models.deletion class Migration(migrations.Migration): - dependencies = [ ('gym', '0008_auto_20190618_1617'), ('mailer', '0002_auto_20190618_1617'), @@ -19,7 +18,7 @@ class Migration(migrations.Migration): editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='email_log', - to='gym.gym' + to='gym.gym', ), ), ] diff --git a/wger/mailer/models/log.py b/wger/mailer/models/log.py index b85983d72..fb89e6983 100644 --- a/wger/mailer/models/log.py +++ b/wger/mailer/models/log.py @@ -29,7 +29,7 @@ class Log(models.Model): class Meta: ordering = [ - "-date", + '-date', ] date = models.DateField(auto_now=True) diff --git a/wger/mailer/tests/test_gym_emails.py b/wger/mailer/tests/test_gym_emails.py index 90f432a91..e91729319 100644 --- a/wger/mailer/tests/test_gym_emails.py +++ b/wger/mailer/tests/test_gym_emails.py @@ -23,6 +23,7 @@ class AccessContractTestCase(WgerAccessTestCase): """ Test accessing the detail page of a contract """ + url = reverse('email:email:overview', kwargs={'gym_pk': 1}) user_success = ('manager1', 'manager2') user_fail = ( diff --git a/wger/mailer/urls.py b/wger/mailer/urls.py index 0a8d75078..25733797c 100644 --- a/wger/mailer/urls.py +++ b/wger/mailer/urls.py @@ -38,5 +38,5 @@ patterns_email = [ ] urlpatterns = [ - path('', include((patterns_email, 'email'), namespace="email")), + path('', include((patterns_email, 'email'), namespace='email')), ] diff --git a/wger/mailer/views/gym.py b/wger/mailer/views/gym.py index a3d78b294..b1b400f1a 100644 --- a/wger/mailer/views/gym.py +++ b/wger/mailer/views/gym.py @@ -43,7 +43,7 @@ class EmailLogListView(PermissionRequiredMixin, generic.ListView): """ model = Log - context_object_name = "email_list" + context_object_name = 'email_list' template_name = 'mailer/gym/overview.html' permission_required = 'mailer.add_log' gym = None @@ -95,9 +95,11 @@ class EmailListFormPreview(FormPreview): Also, check for permissions here. While it is ugly and doesn't really belong here, it seems it's the best way to do it in a FormPreview """ - if not request.user.is_authenticated or\ - request.user.userprofile.gym_id != self.gym.id or \ - not request.user.has_perm('mailer.change_log'): + if ( + not request.user.is_authenticated + or request.user.userprofile.gym_id != self.gym.id + or not request.user.has_perm('mailer.change_log') + ): return HttpResponseForbidden() context = super(EmailListFormPreview, self).get_context(request, form) @@ -113,8 +115,9 @@ class EmailListFormPreview(FormPreview): mail.send_mail( form.cleaned_data['subject'], form.cleaned_data['body'], - settings.WGER_SETTINGS['EMAIL_FROM'], [admin.email], - fail_silently=False + settings.WGER_SETTINGS['EMAIL_FROM'], + [admin.email], + fail_silently=False, ) return context diff --git a/wger/manager/api/serializers.py b/wger/manager/api/serializers.py index 3d5c6a116..cae87e09d 100644 --- a/wger/manager/api/serializers.py +++ b/wger/manager/api/serializers.py @@ -62,6 +62,7 @@ class WorkoutSessionSerializer(serializers.ModelSerializer): """ Workout session serializer """ + user = serializers.PrimaryKeyRelatedField( read_only=True, default=serializers.CurrentUserDefault() ) @@ -78,7 +79,7 @@ class WorkoutLogSerializer(serializers.ModelSerializer): class Meta: model = WorkoutLog - exclude = ('user', ) + exclude = ('user',) class ScheduleStepSerializer(serializers.ModelSerializer): @@ -98,13 +99,14 @@ class ScheduleSerializer(serializers.ModelSerializer): class Meta: model = Schedule - exclude = ('user', ) + exclude = ('user',) class DaySerializer(serializers.ModelSerializer): """ Workout day serializer """ + training = serializers.PrimaryKeyRelatedField(queryset=Workout.objects.all()) day = serializers.PrimaryKeyRelatedField(queryset=DaysOfWeek.objects.all(), many=True) @@ -117,6 +119,7 @@ class SetSerializer(serializers.ModelSerializer): """ Workout setting serializer """ + exerciseday = serializers.PrimaryKeyRelatedField(queryset=Day.objects.all()) class Meta: @@ -152,6 +155,7 @@ class MusclesCanonicalFormSerializer(serializers.Serializer): """ Serializer for the muscles in the canonical form of a day/workout """ + front = serializers.ListField(child=MuscleSerializer()) back = serializers.ListField(child=MuscleSerializer()) frontsecondary = serializers.ListField(child=MuscleSerializer()) @@ -162,6 +166,7 @@ class WorkoutCanonicalFormExerciseImagesListSerializer(serializers.Serializer): """ Serializer for settings in the canonical form of a workout """ + image = serializers.ReadOnlyField() is_main = serializers.ReadOnlyField() @@ -170,6 +175,7 @@ class WorkoutCanonicalFormExerciseListSerializer(serializers.Serializer): """ Serializer for settings in the canonical form of a workout """ + setting_obj_list = SettingSerializer(many=True) setting_list = serializers.ReadOnlyField() setting_text = serializers.ReadOnlyField() @@ -185,6 +191,7 @@ class WorkoutCanonicalFormExerciseSerializer(serializers.Serializer): """ Serializer for an exercise in the canonical form of a workout """ + obj = SetSerializer() exercise_list = WorkoutCanonicalFormExerciseListSerializer(many=True) is_superset = serializers.BooleanField() @@ -196,6 +203,7 @@ class DaysOfWeekCanonicalFormSerializer(serializers.Serializer): """ Serializer for a days of week in the canonical form of a workout """ + text = serializers.ReadOnlyField() day_list = serializers.ListField(child=DaysOfWeekSerializer()) @@ -204,6 +212,7 @@ class DayCanonicalFormSerializer(serializers.Serializer): """ Serializer for a day in the canonical form of a workout """ + obj = DaySerializer() set_list = WorkoutCanonicalFormExerciseSerializer(many=True) days_of_week = DaysOfWeekCanonicalFormSerializer() @@ -214,6 +223,7 @@ class WorkoutCanonicalFormSerializer(serializers.Serializer): """ Serializer for the canonical form of a workout """ + obj = WorkoutSerializer() day_list = DayCanonicalFormSerializer(many=True) muscles = MusclesCanonicalFormSerializer() diff --git a/wger/manager/api/views.py b/wger/manager/api/views.py index aef224cbf..3026f2503 100644 --- a/wger/manager/api/views.py +++ b/wger/manager/api/views.py @@ -62,6 +62,7 @@ class WorkoutViewSet(viewsets.ModelViewSet): """ API endpoint for routine objects """ + serializer_class = WorkoutSerializer is_private = True ordering_fields = '__all__' @@ -72,7 +73,7 @@ class WorkoutViewSet(viewsets.ModelViewSet): Only allow access to appropriate objects """ # REST API generation - if getattr(self, "swagger_fake_view", False): + if getattr(self, 'swagger_fake_view', False): return Workout.objects.none() return Workout.objects.filter(user=self.request.user) @@ -113,7 +114,7 @@ class WorkoutViewSet(viewsets.ModelViewSet): user=self.request.user, weight_unit__in=(1, 2), repetition_unit=1, - workout=self.get_object() + workout=self.get_object(), ) entry_logs, chart_data = process_log_entries(logs) serialized_logs = {} @@ -126,6 +127,7 @@ class UserWorkoutTemplateViewSet(viewsets.ReadOnlyModelViewSet): """ API endpoint for routine template objects """ + serializer_class = WorkoutTemplateSerializer is_private = True ordering_fields = '__all__' @@ -136,7 +138,7 @@ class UserWorkoutTemplateViewSet(viewsets.ReadOnlyModelViewSet): Only allow access to appropriate objects """ # REST API generation - if getattr(self, "swagger_fake_view", False): + if getattr(self, 'swagger_fake_view', False): return Workout.objects.none() return Workout.templates.filter(user=self.request.user) @@ -152,6 +154,7 @@ class PublicWorkoutTemplateViewSet(viewsets.ModelViewSet): """ API endpoint for public workout templates objects """ + serializer_class = WorkoutSerializer is_private = True ordering_fields = '__all__' @@ -193,7 +196,7 @@ class WorkoutSessionViewSet(WgerOwnerObjectModelViewSet): """ # REST API generation - if getattr(self, "swagger_fake_view", False): + if getattr(self, 'swagger_fake_view', False): return WorkoutSession.objects.none() return WorkoutSession.objects.filter(user=self.request.user) @@ -215,6 +218,7 @@ class ScheduleStepViewSet(WgerOwnerObjectModelViewSet): """ API endpoint for schedule step objects """ + serializer_class = ScheduleStepSerializer is_private = True ordering_fields = '__all__' @@ -230,7 +234,7 @@ class ScheduleStepViewSet(WgerOwnerObjectModelViewSet): Only allow access to appropriate objects """ # REST API generation - if getattr(self, "swagger_fake_view", False): + if getattr(self, 'swagger_fake_view', False): return ScheduleStep.objects.none() return ScheduleStep.objects.filter(schedule__user=self.request.user) @@ -246,6 +250,7 @@ class ScheduleViewSet(viewsets.ModelViewSet): """ API endpoint for schedule objects """ + serializer_class = ScheduleSerializer is_private = True ordering_fields = '__all__' @@ -261,7 +266,7 @@ class ScheduleViewSet(viewsets.ModelViewSet): Only allow access to appropriate objects """ # REST API generation - if getattr(self, "swagger_fake_view", False): + if getattr(self, 'swagger_fake_view', False): return Schedule.objects.none() return Schedule.objects.filter(user=self.request.user) @@ -277,6 +282,7 @@ class DayViewSet(WgerOwnerObjectModelViewSet): """ API endpoint for routine day objects """ + serializer_class = DaySerializer is_private = True ordering_fields = '__all__' @@ -291,7 +297,7 @@ class DayViewSet(WgerOwnerObjectModelViewSet): Only allow access to appropriate objects """ # REST API generation - if getattr(self, "swagger_fake_view", False): + if getattr(self, 'swagger_fake_view', False): return Day.objects.none() return Day.objects.filter(training__user=self.request.user) @@ -307,6 +313,7 @@ class SetViewSet(WgerOwnerObjectModelViewSet): """ API endpoint for workout set objects """ + serializer_class = SetSerializer is_private = True ordering_fields = '__all__' @@ -321,7 +328,7 @@ class SetViewSet(WgerOwnerObjectModelViewSet): Only allow access to appropriate objects """ # REST API generation - if getattr(self, "swagger_fake_view", False): + if getattr(self, 'swagger_fake_view', False): return Set.objects.none() return Set.objects.filter(exerciseday__training__user=self.request.user) @@ -344,6 +351,7 @@ class SettingViewSet(WgerOwnerObjectModelViewSet): """ API endpoint for repetition setting objects """ + serializer_class = SettingSerializer is_private = True ordering_fields = '__all__' @@ -361,7 +369,7 @@ class SettingViewSet(WgerOwnerObjectModelViewSet): Only allow access to appropriate objects """ # REST API generation - if getattr(self, "swagger_fake_view", False): + if getattr(self, 'swagger_fake_view', False): return Setting.objects.none() return Setting.objects.filter(set__exerciseday__training__user=self.request.user) @@ -383,11 +391,18 @@ class WorkoutLogViewSet(WgerOwnerObjectModelViewSet): """ API endpoint for workout log objects """ + serializer_class = WorkoutLogSerializer is_private = True ordering_fields = '__all__' filterset_fields = ( - 'date', 'exercise_base', 'reps', 'weight', 'workout', 'repetition_unit', 'weight_unit' + 'date', + 'exercise_base', + 'reps', + 'weight', + 'workout', + 'repetition_unit', + 'weight_unit', ) def get_queryset(self): @@ -395,7 +410,7 @@ class WorkoutLogViewSet(WgerOwnerObjectModelViewSet): Only allow access to appropriate objects """ # REST API generation - if getattr(self, "swagger_fake_view", False): + if getattr(self, 'swagger_fake_view', False): return WorkoutLog.objects.none() return WorkoutLog.objects.filter(user=self.request.user) diff --git a/wger/manager/apps.py b/wger/manager/apps.py index 863d5e805..f41d241ac 100644 --- a/wger/manager/apps.py +++ b/wger/manager/apps.py @@ -20,7 +20,7 @@ from django.apps import AppConfig class ManagerConfig(AppConfig): name = 'wger.manager' - verbose_name = "Manager" + verbose_name = 'Manager' def ready(self): import wger.manager.signals diff --git a/wger/manager/forms.py b/wger/manager/forms.py index 7d1485108..c64780a13 100644 --- a/wger/manager/forms.py +++ b/wger/manager/forms.py @@ -69,7 +69,6 @@ from wger.utils.widgets import ( class WorkoutForm(ModelForm): - class Meta: model = Workout fields = ( @@ -79,7 +78,6 @@ class WorkoutForm(ModelForm): class WorkoutMakeTemplateForm(ModelForm): - class Meta: model = Workout fields = ( @@ -93,19 +91,18 @@ class WorkoutCopyForm(Form): description = CharField( max_length=1000, help_text=_( - "A short description or goal of the workout. For " + 'A short description or goal of the workout. For ' "example 'Focus on back' or 'Week 1 of program xy'." ), widget=widgets.Textarea, - required=False + required=False, ) class DayForm(ModelForm): - class Meta: model = Day - exclude = ('training', ) + exclude = ('training',) widgets = {'day': TranslatedSelectMultiple()} def __init__(self, *args, **kwargs): @@ -136,11 +133,11 @@ class SetForm(ModelForm): 'You can search for more than one ' 'exercise, they will be grouped ' 'together for a superset.' - ) + ), ) english_results = BooleanField( - label=gettext_lazy("Also search for names in English"), + label=gettext_lazy('Also search for names in English'), initial=True, required=False, ) @@ -151,7 +148,6 @@ class SetForm(ModelForm): class SettingForm(ModelForm): - class Meta: model = Setting exclude = ('set', 'exercise', 'order', 'name') @@ -166,6 +162,7 @@ class WorkoutLogForm(ModelForm): we want. This form is one prime candidate to rework with some modern JS framework, there is a ton of ugly logic like this just to make it work. """ + repetition_unit = ModelChoiceField( queryset=RepetitionUnit.objects.all(), label=_('Unit'), @@ -198,11 +195,10 @@ class WorkoutLogForm(ModelForm): class Meta: model = WorkoutLog - exclude = ('workout', ) + exclude = ('workout',) class WorkoutLogFormHelper(FormHelper): - def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.form_method = 'post' @@ -214,7 +210,7 @@ class WorkoutLogFormHelper(FormHelper): Column('weight', css_class='col-2'), Column('weight_unit', css_class='col-3'), Column('rir', css_class='col-2'), - css_class='form-row' + css_class='form-row', ), ) self.form_show_labels = False @@ -239,13 +235,13 @@ class HelperWorkoutSessionForm(ModelForm): Row( Column('date', css_class='col-6'), Column('impression', css_class='col-6'), - css_class='form-row' + css_class='form-row', ), 'notes', Row( Column('time_start', css_class='col-6'), Column('time_end', css_class='col-6'), - css_class='form-row' + css_class='form-row', ), ) self.helper.form_tag = False @@ -269,7 +265,7 @@ class WorkoutSessionForm(ModelForm): Row( Column('time_start', css_class='col-6'), Column('time_end', css_class='col-6'), - css_class='form-row' + css_class='form-row', ), ) @@ -278,12 +274,13 @@ class WorkoutScheduleDownloadForm(Form): """ Form for the workout schedule download """ + pdf_type = ChoiceField( - label=gettext_lazy("Type"), - choices=(("log", gettext_lazy("Log")), ("table", gettext_lazy("Table"))) + label=gettext_lazy('Type'), + choices=(('log', gettext_lazy('Log')), ('table', gettext_lazy('Table'))), ) - images = BooleanField(label=gettext_lazy("with images"), required=False) - comments = BooleanField(label=gettext_lazy("with comments"), required=False) + images = BooleanField(label=gettext_lazy('with images'), required=False) + comments = BooleanField(label=gettext_lazy('with comments'), required=False) def __init__(self): super(WorkoutScheduleDownloadForm, self).__init__() @@ -292,8 +289,8 @@ class WorkoutScheduleDownloadForm(Form): self.helper.add_input( Submit( 'submit', - _("Download"), + _('Download'), css_class='btn-success btn-block', - css_id="download-pdf-button-schedule" + css_id='download-pdf-button-schedule', ) ) diff --git a/wger/manager/helpers.py b/wger/manager/helpers.py index 5a7481cec..c0d02be29 100644 --- a/wger/manager/helpers.py +++ b/wger/manager/helpers.py @@ -73,10 +73,9 @@ def render_workout_day(day, nr_of_weeks=7, images=False, comments=False, only_ta day_markers.append(len(data)) p = Paragraph( - '%(days)s: %(description)s' % { - 'days': day.days_txt, - 'description': day.description - }, styleSheet["SubHeader"] + '%(days)s: %(description)s' + % {'days': day.days_txt, 'description': day.description}, + styleSheet['SubHeader'], ) data.append([p]) @@ -99,21 +98,20 @@ def render_workout_day(day, nr_of_weeks=7, images=False, comments=False, only_ta # Process the settings setting_out = [] for i in set_obj.reps_smart_text(base).split('–'): - setting_out.append(Paragraph(i, styleSheet["Small"], bulletText='')) + setting_out.append(Paragraph(i, styleSheet['Small'], bulletText='')) # Collect a list of the exercise comments - item_list = [Paragraph('', styleSheet["Small"])] + item_list = [Paragraph('', styleSheet['Small'])] if comments: item_list = [ - ListItem(Paragraph(i.comment, style=styleSheet["ExerciseComments"])) + ListItem(Paragraph(i.comment, style=styleSheet['ExerciseComments'])) for i in exercise.exercisecomment_set.all() ] # Add the exercise's main image - image = Paragraph('', styleSheet["Small"]) + image = Paragraph('', styleSheet['Small']) if images: if base.main_image: - # Make the images somewhat larger when printing only the workout and not # also the columns for weight logs if only_table: @@ -127,7 +125,8 @@ def render_workout_day(day, nr_of_weeks=7, images=False, comments=False, only_ta # Put the name and images and comments together exercise_content = [ - Paragraph(exercise.name, styleSheet["Small"]), image, + Paragraph(exercise.name, styleSheet['Small']), + image, ListFlowable( item_list, bulletType='bullet', @@ -135,11 +134,11 @@ def render_workout_day(day, nr_of_weeks=7, images=False, comments=False, only_ta spaceBefore=7, bulletOffsetY=-3, bulletFontSize=3, - start='square' - ) + start='square', + ), ] - data.append([f"#{set_count}", exercise_content, setting_out] + [''] * nr_of_weeks) + data.append([f'#{set_count}', exercise_content, setting_out] + [''] * nr_of_weeks) set_count += 1 table_style = [ @@ -151,16 +150,14 @@ def render_workout_day(day, nr_of_weeks=7, images=False, comments=False, only_ta ('TOPPADDING', (0, 0), (-1, -1), 3), ('BOTTOMPADDING', (0, 0), (-1, -1), 2), ('INNERGRID', (0, 0), (-1, -1), 0.25, colors.black), - # Header ('BACKGROUND', (0, 0), (-1, 0), header_colour), ('BOX', (0, 0), (-1, -1), 1.25, colors.black), ('BOX', (0, 1), (-1, -1), 1.25, colors.black), ('SPAN', (0, 0), (-1, 0)), - # Cell with 'date' ('SPAN', (0, 1), (2, 1)), - ('ALIGN', (0, 1), (2, 1), 'RIGHT') + ('ALIGN', (0, 1), (2, 1), 'RIGHT'), ] # Combine the cells for exercises on the same superset @@ -204,7 +201,6 @@ class WorkoutCalendar(HTMLCalendar): self.workout_logs = workout_logs def formatday(self, day, weekday): - # days belonging to last or next month are rendered empty if day == 0: return self.day_cell('noday', ' ') diff --git a/wger/manager/management/commands/dummy-generator-workout-diary.py b/wger/manager/management/commands/dummy-generator-workout-diary.py index dc4fe2c70..38fcbc8a2 100644 --- a/wger/manager/management/commands/dummy-generator-workout-diary.py +++ b/wger/manager/management/commands/dummy-generator-workout-diary.py @@ -61,14 +61,13 @@ class Command(BaseCommand): help = 'Dummy generator for workout diary entries' def add_arguments(self, parser): - parser.add_argument( '--diary-entries', action='store', default=30, dest='nr_diary_entries', type=int, - help='The number of workout logs to create per day (default: 30)' + help='The number of workout logs to create per day (default: 30)', ) parser.add_argument( '--user-id', @@ -81,9 +80,9 @@ class Command(BaseCommand): def handle(self, **options): self.stdout.write(f"** Generating {options['nr_diary_entries']} dummy diary entries") - users = [User.objects.get(pk=options['user_id'])] \ - if options['user_id'] \ - else User.objects.all() + users = ( + [User.objects.get(pk=options['user_id'])] if options['user_id'] else User.objects.all() + ) weight_log = [] for user in users: @@ -103,7 +102,7 @@ class Command(BaseCommand): workout=workout, reps=reps, weight=50 - reps + random.randint(1, 10), - date=date + date=date, ) weight_log.append(log) diff --git a/wger/manager/management/commands/dummy-generator-workout-plans.py b/wger/manager/management/commands/dummy-generator-workout-plans.py index 0e5920c84..40941967d 100644 --- a/wger/manager/management/commands/dummy-generator-workout-plans.py +++ b/wger/manager/management/commands/dummy-generator-workout-plans.py @@ -44,14 +44,13 @@ class Command(BaseCommand): help = 'Dummy generator for workout plans' def add_arguments(self, parser): - parser.add_argument( '--plans', action='store', default=10, dest='nr_plans', type=int, - help='The number of workout plans to create per user (default: 10)' + help='The number of workout plans to create per user (default: 10)', ) parser.add_argument( '--user-id', @@ -64,9 +63,9 @@ class Command(BaseCommand): def handle(self, **options): self.stdout.write(f"** Generating {options['nr_plans']} dummy workout plan(s) per user") - users = [User.objects.get(pk=options['user_id'])] \ - if options['user_id'] \ - else User.objects.all() + users = ( + [User.objects.get(pk=options['user_id'])] if options['user_id'] else User.objects.all() + ) for user in users: self.stdout.write(f'- processing user {user.username}') diff --git a/wger/manager/management/commands/email-reminders.py b/wger/manager/management/commands/email-reminders.py index 4316a2d47..ef259cc24 100644 --- a/wger/manager/management/commands/email-reminders.py +++ b/wger/manager/management/commands/email-reminders.py @@ -43,17 +43,16 @@ class Command(BaseCommand): profile_list = UserProfile.objects.filter(workout_reminder_active=True) counter = 0 for profile in profile_list: - # Only continue if the user has provided an email address. # Checking it here so we check for NULL values and emtpy strings if not profile.user.email: continue # Check if we already notified the user and update the profile otherwise - if profile.last_workout_notification and \ - (datetime.date.today() - - profile.last_workout_notification - < datetime.timedelta(weeks=1)): + if profile.last_workout_notification and ( + datetime.date.today() - profile.last_workout_notification + < datetime.timedelta(weeks=1) + ): continue (current_workout, schedule) = Schedule.objects.get_current_workout(profile.user) @@ -61,8 +60,9 @@ class Command(BaseCommand): # No schedules, use the default workout length in user profile if not schedule and current_workout: delta = ( - current_workout.creation_date + - datetime.timedelta(weeks=profile.workout_duration) - datetime.date.today() + current_workout.creation_date + + datetime.timedelta(weeks=profile.workout_duration) + - datetime.date.today() ) if datetime.timedelta(days=profile.workout_reminder) > delta: @@ -78,12 +78,10 @@ class Command(BaseCommand): # non-loop schedule, take the step's duration elif schedule and not schedule.is_loop: - schedule_step = schedule.get_current_scheduled_workout() # Only notify if the step is the last one in the schedule if schedule_step == schedule.schedulestep_set.last(): - delta = schedule.get_end_date() - datetime.date.today() if datetime.timedelta(days=profile.workout_reminder) > delta: if int(options['verbosity']) >= 3: @@ -95,7 +93,7 @@ class Command(BaseCommand): self.send_email(profile.user, current_workout, delta) if counter and int(options['verbosity']) >= 2: - self.stdout.write("Sent {0} email reminders".format(counter)) + self.stdout.write('Sent {0} email reminders'.format(counter)) @staticmethod def send_email(user, workout, delta): @@ -117,14 +115,11 @@ class Command(BaseCommand): 'site': Site.objects.get_current(), 'workout': workout, 'expired': True if delta.days < 0 else False, - 'days': abs(delta.days) + 'days': abs(delta.days), } subject = _('Workout will expire soon') message = loader.render_to_string('workout/email_reminder.tpl', context) mail.send_mail( - subject, - message, - settings.WGER_SETTINGS['EMAIL_FROM'], [user.email], - fail_silently=True + subject, message, settings.WGER_SETTINGS['EMAIL_FROM'], [user.email], fail_silently=True ) diff --git a/wger/manager/managers.py b/wger/manager/managers.py index e4f57d598..438a05db7 100644 --- a/wger/manager/managers.py +++ b/wger/manager/managers.py @@ -53,7 +53,6 @@ class ScheduleManager(models.Manager): # there are no active schedules, just return the last workout except ObjectDoesNotExist: - schedule = False try: active_workout = Workout.objects.filter(user=user).latest('creation_date') @@ -66,18 +65,15 @@ class ScheduleManager(models.Manager): class WorkoutManager(models.Manager): - def get_queryset(self): return super().get_queryset().filter(is_template=False) class WorkoutTemplateManager(models.Manager): - def get_queryset(self): return super().get_queryset().filter(is_template=True) class WorkoutAndTemplateManager(models.Manager): - def get_queryset(self): return super().get_queryset() diff --git a/wger/manager/migrations/0001_initial.py b/wger/manager/migrations/0001_initial.py index 04b91a824..b22c6beb9 100644 --- a/wger/manager/migrations/0001_initial.py +++ b/wger/manager/migrations/0001_initial.py @@ -8,7 +8,6 @@ import django.core.validators class Migration(migrations.Migration): - dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), ('exercises', '0001_initial'), @@ -23,21 +22,20 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ( 'description', models.CharField( - help_text= - 'Ususally a description about what parts are trained, like "Arms" or "Pull Day"', + help_text='Ususally a description about what parts are trained, like "Arms" or "Pull Day"', max_length=100, - verbose_name='Description' - ) + verbose_name='Description', + ), ), ('day', models.ManyToManyField(to='core.DaysOfWeek', verbose_name='Day')), ], options={}, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.CreateModel( name='Schedule', @@ -46,40 +44,37 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ( 'name', models.CharField( - help_text= - "Name or short description of the schedule. For example 'Program XYZ'.", + help_text="Name or short description of the schedule. For example 'Program XYZ'.", max_length=100, - verbose_name='Name' - ) + verbose_name='Name', + ), ), ( 'start_date', wger.utils.fields.Html5DateField( default=datetime.date.today, verbose_name='Start date' - ) + ), ), ( 'is_active', models.BooleanField( default=True, - help_text= - 'Tick the box if you want to mark this schedule as your active one (will be shown e.g. on your dashboard). All other schedules will then be marked as inactive', - verbose_name='Schedule active' - ) + help_text='Tick the box if you want to mark this schedule as your active one (will be shown e.g. on your dashboard). All other schedules will then be marked as inactive', + verbose_name='Schedule active', + ), ), ( 'is_loop', models.BooleanField( default=False, - help_text= - 'Tick the box if you want to repeat the schedules in a loop (i.e. A, B, C, A, B, C, and so on)', - verbose_name='Is loop' - ) + help_text='Tick the box if you want to repeat the schedules in a loop (i.e. A, B, C, A, B, C, and so on)', + verbose_name='Is loop', + ), ), ( 'user', @@ -87,12 +82,12 @@ class Migration(migrations.Migration): editable=False, to=settings.AUTH_USER_MODEL, verbose_name='User', - on_delete=models.CASCADE - ) + on_delete=models.CASCADE, + ), ), ], options={}, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.CreateModel( name='ScheduleStep', @@ -101,7 +96,7 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ( 'duration', @@ -111,22 +106,22 @@ class Migration(migrations.Migration): verbose_name='Duration', validators=[ django.core.validators.MinValueValidator(1), - django.core.validators.MaxValueValidator(25) - ] - ) + django.core.validators.MaxValueValidator(25), + ], + ), ), ('order', models.IntegerField(default=1, max_length=1, verbose_name='Order')), ( 'schedule', models.ForeignKey( verbose_name='schedule', to='manager.Schedule', on_delete=models.CASCADE - ) + ), ), ], options={ 'ordering': ['order'], }, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.CreateModel( name='Set', @@ -135,7 +130,7 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ('order', models.IntegerField(null=True, verbose_name='Order', blank=True)), ( @@ -145,25 +140,25 @@ class Migration(migrations.Migration): verbose_name='Number of sets', validators=[ django.core.validators.MinValueValidator(0), - django.core.validators.MaxValueValidator(10) - ] - ) + django.core.validators.MaxValueValidator(10), + ], + ), ), ( 'exerciseday', models.ForeignKey( verbose_name='Exercise day', to='manager.Day', on_delete=models.CASCADE - ) + ), ), ( 'exercises', - models.ManyToManyField(to='exercises.Exercise', verbose_name='Exercises') + models.ManyToManyField(to='exercises.Exercise', verbose_name='Exercises'), ), ], options={ 'ordering': ['order'], }, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.CreateModel( name='Setting', @@ -172,7 +167,7 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ( 'reps', @@ -180,9 +175,9 @@ class Migration(migrations.Migration): verbose_name='Repetitions', validators=[ django.core.validators.MinValueValidator(0), - django.core.validators.MaxValueValidator(100) - ] - ) + django.core.validators.MaxValueValidator(100), + ], + ), ), ('order', models.IntegerField(verbose_name='Order', blank=True)), ('comment', models.CharField(max_length=100, verbose_name='Comment', blank=True)), @@ -190,19 +185,19 @@ class Migration(migrations.Migration): 'exercise', models.ForeignKey( verbose_name='Exercises', to='exercises.Exercise', on_delete=models.CASCADE - ) + ), ), ( 'set', models.ForeignKey( verbose_name='Sets', to='manager.Set', on_delete=models.CASCADE - ) + ), ), ], options={ 'ordering': ['order', 'id'], }, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.CreateModel( name='Workout', @@ -211,33 +206,32 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ( 'creation_date', - models.DateField(auto_now_add=True, verbose_name='Creation date') + models.DateField(auto_now_add=True, verbose_name='Creation date'), ), ( 'comment', models.CharField( - help_text= - "A short description or goal of the workout. For example 'Focus on back' or 'Week 1 of program xy'.", + help_text="A short description or goal of the workout. For example 'Focus on back' or 'Week 1 of program xy'.", max_length=100, verbose_name='Description', - blank=True - ) + blank=True, + ), ), ( 'user', models.ForeignKey( verbose_name='User', to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE - ) + ), ), ], options={ 'ordering': ['-creation_date'], }, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.CreateModel( name='WorkoutLog', @@ -246,14 +240,14 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ( 'reps', models.IntegerField( verbose_name='Repetitions', - validators=[django.core.validators.MinValueValidator(0)] - ) + validators=[django.core.validators.MinValueValidator(0)], + ), ), ( 'weight', @@ -261,15 +255,15 @@ class Migration(migrations.Migration): verbose_name='Weight', max_digits=5, decimal_places=2, - validators=[django.core.validators.MinValueValidator(0)] - ) + validators=[django.core.validators.MinValueValidator(0)], + ), ), ('date', wger.utils.fields.Html5DateField(verbose_name='Date')), ( 'exercise', models.ForeignKey( verbose_name='Exercise', to='exercises.Exercise', on_delete=models.CASCADE - ) + ), ), ( 'user', @@ -277,20 +271,20 @@ class Migration(migrations.Migration): editable=False, to=settings.AUTH_USER_MODEL, verbose_name='User', - on_delete=models.CASCADE - ) + on_delete=models.CASCADE, + ), ), ( 'workout', models.ForeignKey( verbose_name='Workout', to='manager.Workout', on_delete=models.CASCADE - ) + ), ), ], options={ 'ordering': ['date', 'reps'], }, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.CreateModel( name='WorkoutSession', @@ -299,7 +293,7 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ('date', wger.utils.fields.Html5DateField(verbose_name='Date')), ( @@ -308,19 +302,18 @@ class Migration(migrations.Migration): help_text='Any notes you might want to save about this workout session.', null=True, verbose_name='Notes', - blank=True - ) + blank=True, + ), ), ( 'impression', models.CharField( default=b'2', - help_text= - 'Your impression about this workout session. Did you exercise as well as you could?', + help_text='Your impression about this workout session. Did you exercise as well as you could?', max_length=2, verbose_name='General impression', - choices=[(b'1', 'Bad'), (b'2', 'Neutral'), (b'3', 'Good')] - ) + choices=[(b'1', 'Bad'), (b'2', 'Neutral'), (b'3', 'Good')], + ), ), ('time_start', models.TimeField(null=True, verbose_name='Start time', blank=True)), ('time_end', models.TimeField(null=True, verbose_name='Finish time', blank=True)), @@ -328,19 +321,19 @@ class Migration(migrations.Migration): 'user', models.ForeignKey( verbose_name='User', to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE - ) + ), ), ( 'workout', models.ForeignKey( verbose_name='Workout', to='manager.Workout', on_delete=models.CASCADE - ) + ), ), ], options={ 'ordering': ['date'], }, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.AlterUniqueTogether( name='workoutsession', diff --git a/wger/manager/migrations/0002_auto_20150202_2040.py b/wger/manager/migrations/0002_auto_20150202_2040.py index 9a1e85100..df9258b47 100644 --- a/wger/manager/migrations/0002_auto_20150202_2040.py +++ b/wger/manager/migrations/0002_auto_20150202_2040.py @@ -6,7 +6,6 @@ import sortedm2m.fields class Migration(migrations.Migration): - dependencies = [ ('manager', '0001_initial'), ] diff --git a/wger/manager/migrations/0004_auto_20150609_1603.py b/wger/manager/migrations/0004_auto_20150609_1603.py index 0666b8536..443290f8f 100644 --- a/wger/manager/migrations/0004_auto_20150609_1603.py +++ b/wger/manager/migrations/0004_auto_20150609_1603.py @@ -5,7 +5,6 @@ import django.core.validators class Migration(migrations.Migration): - dependencies = [ ('manager', '0002_auto_20150202_2040'), ] @@ -18,12 +17,12 @@ class Migration(migrations.Migration): decimal_places=2, validators=[ django.core.validators.MinValueValidator(0), - django.core.validators.MaxValueValidator(1500) + django.core.validators.MaxValueValidator(1500), ], max_digits=6, blank=True, null=True, - verbose_name='Weight' + verbose_name='Weight', ), preserve_default=True, ), diff --git a/wger/manager/migrations/0005_auto_20160303_2008.py b/wger/manager/migrations/0005_auto_20160303_2008.py index 5e647f501..5b2f5b3b7 100644 --- a/wger/manager/migrations/0005_auto_20160303_2008.py +++ b/wger/manager/migrations/0005_auto_20160303_2008.py @@ -5,7 +5,6 @@ import django.core.validators class Migration(migrations.Migration): - dependencies = [ ('core', '0007_repetitionunit'), ('manager', '0004_auto_20150609_1603'), @@ -31,9 +30,8 @@ class Migration(migrations.Migration): name='description', field=models.CharField( verbose_name='Description', - help_text= - 'A description of what is done on this day (e.g. "Pull day") or what body parts are trained (e.g. "Arms and abs")', - max_length=100 + help_text='A description of what is done on this day (e.g. "Pull day") or what body parts are trained (e.g. "Arms and abs")', + max_length=100, ), ), migrations.AlterField( @@ -42,8 +40,7 @@ class Migration(migrations.Migration): field=models.BooleanField( verbose_name='Is a loop', default=False, - help_text= - 'Tick the box if you want to repeat the schedules in a loop (i.e. A, B, C, A, B, C, and so on)' + help_text='Tick the box if you want to repeat the schedules in a loop (i.e. A, B, C, A, B, C, and so on)', ), ), migrations.AlterField( @@ -58,8 +55,8 @@ class Migration(migrations.Migration): verbose_name='Amount', validators=[ django.core.validators.MinValueValidator(0), - django.core.validators.MaxValueValidator(100) - ] + django.core.validators.MaxValueValidator(100), + ], ), ), migrations.AlterField( @@ -69,9 +66,8 @@ class Migration(migrations.Migration): verbose_name='General impression', default='2', choices=[('1', 'Bad'), ('2', 'Neutral'), ('3', 'Good')], - help_text= - 'Your impression about this workout session. Did you exercise as well as you could?', - max_length=2 + help_text='Your impression about this workout session. Did you exercise as well as you could?', + max_length=2, ), ), ] diff --git a/wger/manager/migrations/0006_auto_20160303_2138.py b/wger/manager/migrations/0006_auto_20160303_2138.py index 958631d7b..4073255ac 100644 --- a/wger/manager/migrations/0006_auto_20160303_2138.py +++ b/wger/manager/migrations/0006_auto_20160303_2138.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('core', '0009_auto_20160303_2340'), ('manager', '0005_auto_20160303_2008'), diff --git a/wger/manager/migrations/0007_auto_20160311_2258.py b/wger/manager/migrations/0007_auto_20160311_2258.py index 1e7a6b1cb..354aa836d 100644 --- a/wger/manager/migrations/0007_auto_20160311_2258.py +++ b/wger/manager/migrations/0007_auto_20160311_2258.py @@ -25,7 +25,6 @@ def convert_settings(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ('manager', '0006_auto_20160303_2138'), ] diff --git a/wger/manager/migrations/0008_auto_20190618_1617.py b/wger/manager/migrations/0008_auto_20190618_1617.py index 68db7b2fa..8a2356ce3 100644 --- a/wger/manager/migrations/0008_auto_20190618_1617.py +++ b/wger/manager/migrations/0008_auto_20190618_1617.py @@ -6,7 +6,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('manager', '0007_auto_20160311_2258'), ] @@ -18,9 +17,9 @@ class Migration(migrations.Migration): field=models.IntegerField( validators=[ django.core.validators.MinValueValidator(0), - django.core.validators.MaxValueValidator(600) + django.core.validators.MaxValueValidator(600), ], - verbose_name='Amount' + verbose_name='Amount', ), ), ] diff --git a/wger/manager/migrations/0009_auto_20201202_1559.py b/wger/manager/migrations/0009_auto_20201202_1559.py index 5ac70cea8..3cefedd0b 100644 --- a/wger/manager/migrations/0009_auto_20201202_1559.py +++ b/wger/manager/migrations/0009_auto_20201202_1559.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('manager', '0008_auto_20190618_1617'), ] @@ -16,13 +15,21 @@ class Migration(migrations.Migration): field=models.DecimalField( blank=True, choices=[ - (None, '------'), (0, 0), (0.5, 0.5), (1, 1), (1.5, 1.5), (2, 2), (2.5, 2.5), - (3, 3), (3.5, 3.5), (4, 4) + (None, '------'), + (0, 0), + (0.5, 0.5), + (1, 1), + (1.5, 1.5), + (2, 2), + (2.5, 2.5), + (3, 3), + (3.5, 3.5), + (4, 4), ], decimal_places=1, max_digits=3, null=True, - verbose_name='RiR' + verbose_name='RiR', ), ), migrations.AddField( @@ -31,13 +38,21 @@ class Migration(migrations.Migration): field=models.DecimalField( blank=True, choices=[ - (None, '------'), (0, 0), (0.5, 0.5), (1, 1), (1.5, 1.5), (2, 2), (2.5, 2.5), - (3, 3), (3.5, 3.5), (4, 4) + (None, '------'), + (0, 0), + (0.5, 0.5), + (1, 1), + (1.5, 1.5), + (2, 2), + (2.5, 2.5), + (3, 3), + (3.5, 3.5), + (4, 4), ], decimal_places=1, max_digits=3, null=True, - verbose_name='RiR' + verbose_name='RiR', ), ), ] diff --git a/wger/manager/migrations/0010_auto_20210102_1446.py b/wger/manager/migrations/0010_auto_20210102_1446.py index f4c573744..ce7caf66d 100644 --- a/wger/manager/migrations/0010_auto_20210102_1446.py +++ b/wger/manager/migrations/0010_auto_20210102_1446.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('manager', '0009_auto_20201202_1559'), ] @@ -16,12 +15,20 @@ class Migration(migrations.Migration): field=models.CharField( blank=True, choices=[ - (None, '------'), ('0', 0), ('0.5', 0.5), ('1', 1), ('1.5', 1.5), ('2', 2), - ('2.5', 2.5), ('3', 3), ('3.5', 3.5), ('4', 4) + (None, '------'), + ('0', 0), + ('0.5', 0.5), + ('1', 1), + ('1.5', 1.5), + ('2', 2), + ('2.5', 2.5), + ('3', 3), + ('3.5', 3.5), + ('4', 4), ], max_length=3, null=True, - verbose_name='RiR' + verbose_name='RiR', ), ), migrations.AlterField( @@ -30,12 +37,20 @@ class Migration(migrations.Migration): field=models.CharField( blank=True, choices=[ - (None, '------'), ('0', 0), ('0.5', 0.5), ('1', 1), ('1.5', 1.5), ('2', 2), - ('2.5', 2.5), ('3', 3), ('3.5', 3.5), ('4', 4) + (None, '------'), + ('0', 0), + ('0.5', 0.5), + ('1', 1), + ('1.5', 1.5), + ('2', 2), + ('2.5', 2.5), + ('3', 3), + ('3.5', 3.5), + ('4', 4), ], max_length=3, null=True, - verbose_name='RiR' + verbose_name='RiR', ), ), ] diff --git a/wger/manager/migrations/0011_remove_set_exercises.py b/wger/manager/migrations/0011_remove_set_exercises.py index 068a02faf..9189c46dc 100644 --- a/wger/manager/migrations/0011_remove_set_exercises.py +++ b/wger/manager/migrations/0011_remove_set_exercises.py @@ -11,7 +11,7 @@ def increment_order(apps, schema_editor): exercises could be ordered alphabetically. """ - WorkoutSet = apps.get_model("manager", "Set") + WorkoutSet = apps.get_model('manager', 'Set') for workout_set in WorkoutSet.objects.all(): counter = 1 @@ -23,7 +23,6 @@ def increment_order(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ('manager', '0010_auto_20210102_1446'), ] diff --git a/wger/manager/migrations/0012_auto_20210430_1449.py b/wger/manager/migrations/0012_auto_20210430_1449.py index 0fb1954b8..d4aa35158 100644 --- a/wger/manager/migrations/0012_auto_20210430_1449.py +++ b/wger/manager/migrations/0012_auto_20210430_1449.py @@ -16,20 +16,17 @@ class Migration(migrations.Migration): name='description', field=models.TextField( blank=True, - help_text="A short description or goal of the workout. For " + help_text='A short description or goal of the workout. For ' "example 'Focus on back' or 'Week 1 of program xy'.", max_length=1000, - verbose_name='Description' + verbose_name='Description', ), ), migrations.AlterField( model_name='workout', name='name', field=models.CharField( - blank=True, - help_text='The name of the workout', - max_length=100, - verbose_name='Name' + blank=True, help_text='The name of the workout', max_length=100, verbose_name='Name' ), ), migrations.AlterField( @@ -38,9 +35,9 @@ class Migration(migrations.Migration): field=models.IntegerField( validators=[ django.core.validators.MinValueValidator(0), - django.core.validators.MaxValueValidator(600) + django.core.validators.MaxValueValidator(600), ], - verbose_name='Reps' + verbose_name='Reps', ), ), ] diff --git a/wger/manager/migrations/0013_set_comment.py b/wger/manager/migrations/0013_set_comment.py index 3a1922692..2ea8310d4 100644 --- a/wger/manager/migrations/0013_set_comment.py +++ b/wger/manager/migrations/0013_set_comment.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('manager', '0012_auto_20210430_1449'), ] diff --git a/wger/manager/migrations/0014_auto_20210717_1858.py b/wger/manager/migrations/0014_auto_20210717_1858.py index e3eeeba89..996fa01b5 100644 --- a/wger/manager/migrations/0014_auto_20210717_1858.py +++ b/wger/manager/migrations/0014_auto_20210717_1858.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('manager', '0013_set_comment'), ] diff --git a/wger/manager/migrations/0015_auto_20211028_1113.py b/wger/manager/migrations/0015_auto_20211028_1113.py index 9a6d83f55..cc29d5f33 100644 --- a/wger/manager/migrations/0015_auto_20211028_1113.py +++ b/wger/manager/migrations/0015_auto_20211028_1113.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('manager', '0014_auto_20210717_1858'), ] @@ -21,7 +20,7 @@ class Migration(migrations.Migration): field=models.BooleanField( default=False, help_text='A public template is available to other users', - verbose_name='Public template' + verbose_name='Public template', ), ), migrations.AlterField( @@ -29,9 +28,8 @@ class Migration(migrations.Migration): name='is_template', field=models.BooleanField( default=False, - help_text= - 'Marking a workout as a template will freeze it and allow you to make copies of it', - verbose_name='Workout template' + help_text='Marking a workout as a template will freeze it and allow you to make copies of it', + verbose_name='Workout template', ), ), ] diff --git a/wger/manager/migrations/0016_move_to_exercise_base.py b/wger/manager/migrations/0016_move_to_exercise_base.py index 0889ffd96..00687819d 100644 --- a/wger/manager/migrations/0016_move_to_exercise_base.py +++ b/wger/manager/migrations/0016_move_to_exercise_base.py @@ -2,6 +2,7 @@ from django.db import migrations, models import django.db.models.deletion + """ Migration script to move foreign keys in Settings and WorkoutLog from Exercise to ExerciseBase. We first add a nullable FK to ExerciseBase, @@ -28,7 +29,6 @@ def migrate_log_to_exercise_base(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ('exercises', '0019_exercise_crowdsourcing_changes'), ('manager', '0015_auto_20211028_1113'), @@ -43,7 +43,7 @@ class Migration(migrations.Migration): null=True, on_delete=django.db.models.deletion.CASCADE, to='exercises.exercisebase', - verbose_name='Exercises' + verbose_name='Exercises', ), ), migrations.RunPython(migrate_setting_to_exercise_base), @@ -54,14 +54,13 @@ class Migration(migrations.Migration): null=False, on_delete=django.db.models.deletion.CASCADE, to='exercises.exercisebase', - verbose_name='Exercises' + verbose_name='Exercises', ), ), migrations.RemoveField( model_name='setting', name='exercise', ), - # WorkoutLog migrations.AddField( model_name='workoutlog', @@ -70,7 +69,7 @@ class Migration(migrations.Migration): null=True, on_delete=django.db.models.deletion.CASCADE, to='exercises.exercisebase', - verbose_name='Exercises' + verbose_name='Exercises', ), ), migrations.RunPython(migrate_log_to_exercise_base), @@ -81,7 +80,7 @@ class Migration(migrations.Migration): null=False, on_delete=django.db.models.deletion.CASCADE, to='exercises.exercisebase', - verbose_name='Exercises' + verbose_name='Exercises', ), ), migrations.RemoveField( diff --git a/wger/manager/migrations/0017_alter_workoutlog_exercise_base.py b/wger/manager/migrations/0017_alter_workoutlog_exercise_base.py index 6a884fdd2..a39db1491 100644 --- a/wger/manager/migrations/0017_alter_workoutlog_exercise_base.py +++ b/wger/manager/migrations/0017_alter_workoutlog_exercise_base.py @@ -6,72 +6,130 @@ import django.db.models.deletion # Mapping of bases that should be migrated # -> (old_base, new_base) base_mapping = [ - ('201edd07-93f8-474b-8db0-e13e5283ee2b', - '1b9ed9da-46d1-4484-8acc-236379ee823c'), # Kabelziehen Über Kreuz + ( + '201edd07-93f8-474b-8db0-e13e5283ee2b', + '1b9ed9da-46d1-4484-8acc-236379ee823c', + ), # Kabelziehen Über Kreuz ('b7b690a7-2e65-40f9-a9cb-e61501a72fed', 'b16e3e5d-8401-4d2b-919c-15b536f9ec5e'), # Kabelzug ('713ee452-2775-4a68-8a7c-f1d22b5cd469', '00fcf603-b0d0-48d2-9b5e-c7f0d510d46c'), # Rudern eng - ('4ceb1ba5-1ce1-4fe3-b60a-5d0e173a2ab3', - '61950a59-be4e-43cc-abc1-cb52abd15354'), # Leg extension - ('27d322ba-cbf5-44fa-a3bc-1999c6711757', - '058945bb-7fa8-4724-95fb-51ee8df20929'), # Beinstrecker - ('557ae429-100d-4d5b-a173-e5186fa2d9bc', - '13234b53-ea0c-41f1-9069-776865ea8eff'), # Trizepsdrücken KH Über Kopf - ('455fc17f-dc4c-4516-a335-8286958e7a7b', - '09dd3e3c-e53a-4e2c-a2e3-645d334f53e2'), # Triceps Dips - ('a1d4f524-b6ca-4dd3-9998-41200f01b634', - '3db63138-a047-4a4d-b616-1a0b7dfca105'), # Close-grip Bench Press - ('69378ddf-377d-4624-b500-3406682a84e4', - '275fb49f-975c-4d6e-9d63-2c86ed740f40'), # Incline Bench Press - ('64d772ea-f21a-47c1-8660-d6b9366d1900', - '57e17672-52b9-43cf-8d0d-4b3f06a0c0d0'), # Incline Bench Press - Dumbbell + ( + '4ceb1ba5-1ce1-4fe3-b60a-5d0e173a2ab3', + '61950a59-be4e-43cc-abc1-cb52abd15354', + ), # Leg extension + ( + '27d322ba-cbf5-44fa-a3bc-1999c6711757', + '058945bb-7fa8-4724-95fb-51ee8df20929', + ), # Beinstrecker + ( + '557ae429-100d-4d5b-a173-e5186fa2d9bc', + '13234b53-ea0c-41f1-9069-776865ea8eff', + ), # Trizepsdrücken KH Über Kopf + ( + '455fc17f-dc4c-4516-a335-8286958e7a7b', + '09dd3e3c-e53a-4e2c-a2e3-645d334f53e2', + ), # Triceps Dips + ( + 'a1d4f524-b6ca-4dd3-9998-41200f01b634', + '3db63138-a047-4a4d-b616-1a0b7dfca105', + ), # Close-grip Bench Press + ( + '69378ddf-377d-4624-b500-3406682a84e4', + '275fb49f-975c-4d6e-9d63-2c86ed740f40', + ), # Incline Bench Press + ( + '64d772ea-f21a-47c1-8660-d6b9366d1900', + '57e17672-52b9-43cf-8d0d-4b3f06a0c0d0', + ), # Incline Bench Press - Dumbbell ('6a496c73-721d-4ed2-9f7f-337e8ad2b388', '09dd3e3c-e53a-4e2c-a2e3-645d334f53e2'), # Dips - ('133f7a01-dd9f-45d5-af67-1d1af134d99b', - '4af6dbd9-8991-484b-9810-68f117c21edf'), # Bent Over Barbell Row - ('8f7b6fce-4a75-42fc-b217-efe44e349fdc', - '94a5c406-7bcd-47f3-9687-bdf92a763932'), # Einarmiges Rudern KH + ( + '133f7a01-dd9f-45d5-af67-1d1af134d99b', + '4af6dbd9-8991-484b-9810-68f117c21edf', + ), # Bent Over Barbell Row + ( + '8f7b6fce-4a75-42fc-b217-efe44e349fdc', + '94a5c406-7bcd-47f3-9687-bdf92a763932', + ), # Einarmiges Rudern KH ('7a69e726-cdb2-4f0a-b9bd-a9c560d04a03', '7ce443b6-eb84-4f65-b05f-461c1cc8bcc0'), # Calf raises - ('c323d8a4-310f-4381-925c-3893ef5f8422', - '63fbb8e5-6ebc-4def-8844-3e65e097213b'), # Latzug Eng im Untergriff Zur Brust - ('c29884c8-a4fd-4491-8bfd-2dac88aa7184', - '34fc154f-cc8d-4e52-adb7-ff0dad2d0770'), # Latzug Breit Zur Brust - ('9e694c44-2462-430d-8108-6982fd681ade', - '63fbb8e5-6ebc-4def-8844-3e65e097213b'), # Lat Pulldown + ( + 'c323d8a4-310f-4381-925c-3893ef5f8422', + '63fbb8e5-6ebc-4def-8844-3e65e097213b', + ), # Latzug Eng im Untergriff Zur Brust + ( + 'c29884c8-a4fd-4491-8bfd-2dac88aa7184', + '34fc154f-cc8d-4e52-adb7-ff0dad2d0770', + ), # Latzug Breit Zur Brust + ( + '9e694c44-2462-430d-8108-6982fd681ade', + '63fbb8e5-6ebc-4def-8844-3e65e097213b', + ), # Lat Pulldown ('2d806ebb-9aa3-449b-9056-218f5bbbc7f8', 'a2f5b6ef-b780-49c0-8d96-fdaff23e27ce'), # Squat ('a2f5b6ef-b780-49c0-8d96-fdaff23e27ce', 'a2f5b6ef-b780-49c0-8d96-fdaff23e27ce'), # Squat - ('5912d7ed-6a0e-4b4c-b30a-fc9f3f890fc1', - '5912d7ed-6a0e-4b4c-b30a-fc9f3f890fc1'), # Shoulder Press, on Machine + ( + '5912d7ed-6a0e-4b4c-b30a-fc9f3f890fc1', + '5912d7ed-6a0e-4b4c-b30a-fc9f3f890fc1', + ), # Shoulder Press, on Machine ('9b210eb3-6ff0-4a57-8e26-e89da8751c19', '63375f5b-2d81-471c-bea4-fc3d207e96cb'), # Side Raise ('39ba20a7-14c7-44fe-b6c8-6ce9c83b4c38', '52dec48d-25a4-4a78-b66b-ad6a773e143a'), # Power Clean - ('058945bb-7fa8-4724-95fb-51ee8df20929', - '058945bb-7fa8-4724-95fb-51ee8df20929'), # Leg Extension - ('49859097-644a-417a-8cb7-491b7d8bc383', - '53906cd1-61f1-4d56-ac60-e4fcc5824861'), # Adduktoren Maschine - ('b955b629-5c57-4f98-b200-e96e138c300f', - '5f514f9e-6bd9-408e-85b2-c25eb04af33b'), # Beinheben Aufrecht - ('5f8370d9-aa89-4dcc-9d97-d9da86a2f183', - '9b993e99-8701-43f0-84d6-689123183880'), # Beinheben im Hang - ('5b14e0f0-1131-4ad9-9821-5703f1370bc5', - '9e34bc01-9cec-4ee2-a9bb-9c937a471c24'), # Beinheben Liegend - ('e878ecf3-fbb2-4f0e-a546-9769c7ff3241', - '2e7ffff9-e603-4b28-98c8-31d1a6ce8cd9'), # Rumänisches Kreuzheben - ('24b62fb4-0158-486e-89f1-9a5f1db234ef', - '32c129f7-cc28-4ebc-8465-e4fa62e220b1'), # T-Bar Rudern (breit) - ('515cb39c-fead-4b59-a4ba-a10c5b0b8c84', - '9c35594c-bbcc-4656-bdcb-376814c90e96'), # Frontheben am Kabel - ('cfeedd4f-84e3-402c-a105-ec985658c927', - '591992cb-48ee-4b39-b790-e05b4a2c11e3'), # Weighted Step - ('6c86a314-bf0e-4b31-aea7-40891fa5288a', - '2f7149c3-77ce-4313-a59c-aef82b5a730a'), # Lat-Ziehen Mit Gesteckten Armen am Seilzug - ('09ed42ad-5523-424d-bd64-c439694a65fe', - '63375f5b-2d81-471c-bea4-fc3d207e96cb'), # Shoulder Fly - ('73405d63-a539-486e-996e-1e72572fbe5d', - '6e00afb6-272d-44a2-8ae3-e7fa41b50f06'), # Pull-Over KH - ('9ae8772d-570c-4d16-abd4-34f5d5081e4e', - '6f79b381-98a4-40d5-8a45-3bb0558be6fe'), # Seitheben Kurzhantel Vorgebeugt - ('31f51ab6-94a6-436f-9d41-632d85b7e01f', - '141bc870-56be-4749-a3b9-e56d5d5618b4'), # Frontdrücken MP - ('a68c991c-ac42-47c8-9a84-9b288a4a7a76', - '5d40c67d-be59-4092-9c9c-301ca5310e2b'), # Rudern Aufrecht ß-Stange + ( + '058945bb-7fa8-4724-95fb-51ee8df20929', + '058945bb-7fa8-4724-95fb-51ee8df20929', + ), # Leg Extension + ( + '49859097-644a-417a-8cb7-491b7d8bc383', + '53906cd1-61f1-4d56-ac60-e4fcc5824861', + ), # Adduktoren Maschine + ( + 'b955b629-5c57-4f98-b200-e96e138c300f', + '5f514f9e-6bd9-408e-85b2-c25eb04af33b', + ), # Beinheben Aufrecht + ( + '5f8370d9-aa89-4dcc-9d97-d9da86a2f183', + '9b993e99-8701-43f0-84d6-689123183880', + ), # Beinheben im Hang + ( + '5b14e0f0-1131-4ad9-9821-5703f1370bc5', + '9e34bc01-9cec-4ee2-a9bb-9c937a471c24', + ), # Beinheben Liegend + ( + 'e878ecf3-fbb2-4f0e-a546-9769c7ff3241', + '2e7ffff9-e603-4b28-98c8-31d1a6ce8cd9', + ), # Rumänisches Kreuzheben + ( + '24b62fb4-0158-486e-89f1-9a5f1db234ef', + '32c129f7-cc28-4ebc-8465-e4fa62e220b1', + ), # T-Bar Rudern (breit) + ( + '515cb39c-fead-4b59-a4ba-a10c5b0b8c84', + '9c35594c-bbcc-4656-bdcb-376814c90e96', + ), # Frontheben am Kabel + ( + 'cfeedd4f-84e3-402c-a105-ec985658c927', + '591992cb-48ee-4b39-b790-e05b4a2c11e3', + ), # Weighted Step + ( + '6c86a314-bf0e-4b31-aea7-40891fa5288a', + '2f7149c3-77ce-4313-a59c-aef82b5a730a', + ), # Lat-Ziehen Mit Gesteckten Armen am Seilzug + ( + '09ed42ad-5523-424d-bd64-c439694a65fe', + '63375f5b-2d81-471c-bea4-fc3d207e96cb', + ), # Shoulder Fly + ( + '73405d63-a539-486e-996e-1e72572fbe5d', + '6e00afb6-272d-44a2-8ae3-e7fa41b50f06', + ), # Pull-Over KH + ( + '9ae8772d-570c-4d16-abd4-34f5d5081e4e', + '6f79b381-98a4-40d5-8a45-3bb0558be6fe', + ), # Seitheben Kurzhantel Vorgebeugt + ( + '31f51ab6-94a6-436f-9d41-632d85b7e01f', + '141bc870-56be-4749-a3b9-e56d5d5618b4', + ), # Frontdrücken MP + ( + 'a68c991c-ac42-47c8-9a84-9b288a4a7a76', + '5d40c67d-be59-4092-9c9c-301ca5310e2b', + ), # Rudern Aufrecht ß-Stange ] @@ -82,9 +140,9 @@ def migrate_bases(apps, schema_editor): Note that we can't access STATUS_PENDING here because we are not using a real model. """ - WorkoutLog = apps.get_model("manager", "WorkoutLog") - Setting = apps.get_model("manager", "Setting") - Base = apps.get_model("exercises", "ExerciseBase") + WorkoutLog = apps.get_model('manager', 'WorkoutLog') + Setting = apps.get_model('manager', 'Setting') + Base = apps.get_model('exercises', 'ExerciseBase') for mapping in base_mapping: try: base_old = Base.objects.get(uuid=mapping[0]) @@ -98,7 +156,6 @@ def migrate_bases(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ('exercises', '0019_exercise_crowdsourcing_changes'), ('manager', '0016_move_to_exercise_base'), @@ -111,7 +168,7 @@ class Migration(migrations.Migration): field=models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, to='exercises.exercisebase', - verbose_name='Exercise' + verbose_name='Exercise', ), ), migrations.RunPython(migrate_bases), diff --git a/wger/manager/models/day.py b/wger/manager/models/day.py index 9c4ef98e4..f2da1eb21 100644 --- a/wger/manager/models/day.py +++ b/wger/manager/models/day.py @@ -128,8 +128,9 @@ class Day(models.Model): elif not muscle.is_front and muscle.id not in muscles_back: muscles_back_secondary.append(muscle) - for setting in Setting.objects.filter(set=set_obj, - exercise_base=base).order_by('order', 'id'): + for setting in Setting.objects.filter(set=set_obj, exercise_base=base).order_by( + 'order', 'id' + ): setting_tmp.append(setting) # "Smart" textual representation @@ -137,7 +138,7 @@ class Day(models.Model): # Exercise comments comment_list = [] - #for i in base.exercisecomment_set.all(): + # for i in base.exercisecomment_set.all(): # comment_list.append(i.comment) # Flag indicating whether any of the settings has saved weight @@ -164,7 +165,7 @@ class Day(models.Model): 'setting_text': setting_text, 'has_weight': has_weight, 'comment_list': comment_list, - 'image_list': exercise_images_tmp + 'image_list': exercise_images_tmp, } ) @@ -195,8 +196,8 @@ class Day(models.Model): 'back': muscles_back, 'front': muscles_front, 'frontsecondary': muscles_front_secondary, - 'backsecondary': muscles_front_secondary - } + 'backsecondary': muscles_front_secondary, + }, } ) @@ -209,13 +210,13 @@ class Day(models.Model): 'obj': self, 'days_of_week': { 'text': ', '.join([str(_(i.day_of_week)) for i in tmp_days_of_week]), - 'day_list': tmp_days_of_week + 'day_list': tmp_days_of_week, }, 'muscles': { 'back': muscles_back, 'front': muscles_front, 'frontsecondary': muscles_front_secondary, - 'backsecondary': muscles_front_secondary + 'backsecondary': muscles_front_secondary, }, - 'set_list': canonical_repr + 'set_list': canonical_repr, } diff --git a/wger/manager/models/log.py b/wger/manager/models/log.py index 28c2af0d0..c16449e90 100644 --- a/wger/manager/models/log.py +++ b/wger/manager/models/log.py @@ -113,13 +113,13 @@ class WorkoutLog(models.Model): # Metaclass to set some other properties class Meta: - ordering = ["date", "reps"] + ordering = ['date', 'reps'] def __str__(self): """ Return a more human-readable representation """ - return "Log entry: {0} - {1} kg on {2}".format(self.reps, self.weight, self.date) + return 'Log entry: {0} - {1} kg on {2}'.format(self.reps, self.weight, self.date) def get_owner_object(self): """ diff --git a/wger/manager/models/schedule.py b/wger/manager/models/schedule.py index 0cdbcbba4..896b32835 100644 --- a/wger/manager/models/schedule.py +++ b/wger/manager/models/schedule.py @@ -54,8 +54,7 @@ class Schedule(models.Model): name = models.CharField( verbose_name=_('Name'), max_length=100, - help_text=_("Name or short description of the schedule. " - "For example 'Program XYZ'."), + help_text=_('Name or short description of the schedule. ' "For example 'Program XYZ'."), ) """Name or short description of the schedule.""" @@ -66,10 +65,10 @@ class Schedule(models.Model): verbose_name=_('Schedule active'), default=True, help_text=_( - "Tick the box if you want to mark this schedule " - "as your active one (will be shown e.g. on your " - "dashboard). All other schedules will then be " - "marked as inactive" + 'Tick the box if you want to mark this schedule ' + 'as your active one (will be shown e.g. on your ' + 'dashboard). All other schedules will then be ' + 'marked as inactive' ), ) """A flag indicating whether the schedule is active (needed for dashboard)""" @@ -78,8 +77,8 @@ class Schedule(models.Model): verbose_name=_('Is a loop'), default=False, help_text=_( - "Tick the box if you want to repeat the schedules " - "in a loop (i.e. A, B, C, A, B, C, and so on)" + 'Tick the box if you want to repeat the schedules ' + 'in a loop (i.e. A, B, C, A, B, C, and so on)' ), ) """A flag indicating whether the schedule should act as a loop""" diff --git a/wger/manager/models/schedule_step.py b/wger/manager/models/schedule_step.py index c95b00392..0f540d0f0 100644 --- a/wger/manager/models/schedule_step.py +++ b/wger/manager/models/schedule_step.py @@ -42,8 +42,9 @@ class ScheduleStep(models.Model): """ Set default ordering """ + ordering = [ - "order", + 'order', ] schedule = models.ForeignKey(Schedule, verbose_name=_('schedule'), on_delete=models.CASCADE) diff --git a/wger/manager/models/session.py b/wger/manager/models/session.py index bb18e1a94..80ac0c7f0 100644 --- a/wger/manager/models/session.py +++ b/wger/manager/models/session.py @@ -39,7 +39,7 @@ class WorkoutSession(models.Model): IMPRESSION_GOOD = '3' IMPRESSION = ( - (IMPRESSION_BAD, _("Bad")), + (IMPRESSION_BAD, _('Bad')), (IMPRESSION_NEUTRAL, _('Neutral')), (IMPRESSION_GOOD, _('Good')), ) @@ -73,8 +73,7 @@ class WorkoutSession(models.Model): verbose_name=_('Notes'), null=True, blank=True, - help_text=_('Any notes you might want to save about this workout ' - 'session.') + help_text=_('Any notes you might want to save about this workout ' 'session.'), ) """ User notes about the workout @@ -86,9 +85,8 @@ class WorkoutSession(models.Model): choices=IMPRESSION, default=IMPRESSION_NEUTRAL, help_text=_( - 'Your impression about this workout session. ' - 'Did you exercise as well as you could?' - ) + 'Your impression about this workout session. ' 'Did you exercise as well as you could?' + ), ) """ The user's general impression of workout @@ -108,16 +106,17 @@ class WorkoutSession(models.Model): """ Return a more human-readable representation """ - return "{0} - {1}".format(self.workout, self.date) + return '{0} - {1}'.format(self.workout, self.date) class Meta: """ Set other properties """ + ordering = [ - "date", + 'date', ] - unique_together = ("date", "user") + unique_together = ('date', 'user') def clean(self): """ @@ -125,10 +124,10 @@ class WorkoutSession(models.Model): """ if (not self.time_end and self.time_start) or (self.time_end and not self.time_start): - raise ValidationError(_("If you enter a time, you must enter both start and end time.")) + raise ValidationError(_('If you enter a time, you must enter both start and end time.')) if self.time_end and self.time_start and self.time_start > self.time_end: - raise ValidationError(_("The start time cannot be after the end time.")) + raise ValidationError(_('The start time cannot be after the end time.')) def get_owner_object(self): """ diff --git a/wger/manager/models/set.py b/wger/manager/models/set.py index 22617eeb4..a356e7b8b 100644 --- a/wger/manager/models/set.py +++ b/wger/manager/models/set.py @@ -38,6 +38,7 @@ class Set(models.Model): """ Model for a set of exercises """ + DEFAULT_SETS = 4 MAX_SETS = 10 @@ -62,14 +63,14 @@ class Set(models.Model): # Metaclass to set some other properties class Meta: ordering = [ - "order", + 'order', ] def __str__(self): """ Return a more human-readable representation """ - return "Set-ID {0}".format(self.id) + return 'Set-ID {0}'.format(self.id) def get_owner_object(self): """ @@ -160,9 +161,9 @@ class Set(models.Model): """ if setting.rir: - rir = f"{setting.rir} RiR" + rir = f'{setting.rir} RiR' else: - rir = "" + rir = '' return rir def get_reps_reprentation(setting, rep_unit): @@ -173,7 +174,7 @@ class Set(models.Model): "Until Failure" unit """ if setting.repetition_unit_id != 2: - reps = "{0} {1}".format(setting.reps, rep_unit).strip() + reps = '{0} {1}'.format(setting.reps, rep_unit).strip() else: reps = '∞' return reps diff --git a/wger/manager/models/setting.py b/wger/manager/models/setting.py index 8c658c06b..fc8886402 100644 --- a/wger/manager/models/setting.py +++ b/wger/manager/models/setting.py @@ -81,7 +81,7 @@ class Setting(models.Model): decimal_places=2, blank=True, null=True, - validators=[MinValueValidator(0), MaxValueValidator(1500)] + validators=[MinValueValidator(0), MaxValueValidator(1500)], ) """Planed weight for the repetitions""" @@ -112,13 +112,13 @@ class Setting(models.Model): # Metaclass to set some other properties class Meta: - ordering = ["order", "id"] + ordering = ['order', 'id'] def __str__(self): """ Return a more human-readable representation """ - return f"setting {self.id} for exercise base {self.exercise_base_id} in set {self.set_id}" + return f'setting {self.id} for exercise base {self.exercise_base_id} in set {self.set_id}' def save(self, *args, **kwargs): """ diff --git a/wger/manager/models/workout.py b/wger/manager/models/workout.py index c0400db6c..dc7041b91 100644 --- a/wger/manager/models/workout.py +++ b/wger/manager/models/workout.py @@ -47,8 +47,9 @@ class Workout(models.Model): """ Meta class to set some other properties """ + ordering = [ - "-creation_date", + '-creation_date', ] creation_date = models.DateField(_('Creation date'), auto_now_add=True) @@ -56,14 +57,14 @@ class Workout(models.Model): verbose_name=_('Name'), max_length=100, blank=True, - help_text=_("The name of the workout"), + help_text=_('The name of the workout'), ) description = models.TextField( verbose_name=_('Description'), max_length=1000, blank=True, help_text=_( - "A short description or goal of the workout. For " + 'A short description or goal of the workout. For ' "example 'Focus on back' or 'Week 1 of program " "xy'." ), @@ -71,8 +72,7 @@ class Workout(models.Model): is_template = models.BooleanField( verbose_name=_('Workout template'), help_text=_( - 'Marking a workout as a template will freeze it and allow you to ' - 'make copies of it' + 'Marking a workout as a template will freeze it and allow you to ' 'make copies of it' ), default=False, null=False, @@ -96,7 +96,7 @@ class Workout(models.Model): """ return reverse( 'manager:template:view' if self.is_template else 'manager:workout:view', - kwargs={'pk': self.id} + kwargs={'pk': self.id}, ) def __str__(self): @@ -106,7 +106,7 @@ class Workout(models.Model): if self.name: return self.name else: - return "{0} ({1})".format(_('Workout'), self.creation_date) + return '{0} ({1})'.format(_('Workout'), self.creation_date) def clean(self): if self.is_public and not self.is_template: @@ -180,9 +180,9 @@ class Workout(models.Model): 'front': muscles_front, 'back': muscles_back, 'frontsecondary': muscles_front_secondary, - 'backsecondary': muscles_back_secondary + 'backsecondary': muscles_back_secondary, }, - 'day_list': day_canonical_repr + 'day_list': day_canonical_repr, } # Save to cache cache.set(cache_mapper.get_workout_canonical(self.pk), workout_canonical_form) diff --git a/wger/manager/tests/test_copy_workout.py b/wger/manager/tests/test_copy_workout.py index 02bf77653..d03c11ddc 100644 --- a/wger/manager/tests/test_copy_workout.py +++ b/wger/manager/tests/test_copy_workout.py @@ -74,7 +74,6 @@ class CopyWorkoutTestCase(WgerTestCase): sets_copy = days_copy[i].set_set.all() for j in range(days_original[i].set_set.count()): - self.assertEqual(sets_original[j].sets, sets_copy[j].sets) self.assertEqual(sets_original[j].order, sets_copy[j].order) self.assertEqual(sets_original[j].comment, sets_copy[j].comment) diff --git a/wger/manager/tests/test_day.py b/wger/manager/tests/test_day.py index b467cb11a..2eaf31ad1 100644 --- a/wger/manager/tests/test_day.py +++ b/wger/manager/tests/test_day.py @@ -35,7 +35,7 @@ class DayRepresentationTestCase(WgerTestCase): """ Test that the representation of an object is correct """ - self.assertEqual("{0}".format(Day.objects.get(pk=1)), 'A day') + self.assertEqual('{0}'.format(Day.objects.get(pk=1)), 'A day') class AddWorkoutDayTestCase(WgerAddTestCase): diff --git a/wger/manager/tests/test_generator.py b/wger/manager/tests/test_generator.py index 386b508e9..f7701ef8f 100644 --- a/wger/manager/tests/test_generator.py +++ b/wger/manager/tests/test_generator.py @@ -24,7 +24,6 @@ from wger.manager.models import ( class RoutineGeneratorTestCase(WgerTestCase): - def test_generator_routines(self): # Arrange Workout.objects.all().delete() diff --git a/wger/manager/tests/test_ical.py b/wger/manager/tests/test_ical.py index cb49f8266..6feceb594 100644 --- a/wger/manager/tests/test_ical.py +++ b/wger/manager/tests/test_ical.py @@ -64,11 +64,7 @@ class WorkoutICalExportTestCase(WgerTestCase): user = User.objects.get(username='test') uid, token = make_token(user) response = self.client.get( - reverse('manager:workout:ical', kwargs={ - 'pk': 3, - 'uidb64': uid, - 'token': token - }) + reverse('manager:workout:ical', kwargs={'pk': 3, 'uidb64': uid, 'token': token}) ) self.assertEqual(response.status_code, 200) @@ -89,11 +85,7 @@ class WorkoutICalExportTestCase(WgerTestCase): uid = 'AB' token = 'abc-11223344556677889900' response = self.client.get( - reverse('manager:workout:ical', kwargs={ - 'pk': 3, - 'uidb64': uid, - 'token': token - }) + reverse('manager:workout:ical', kwargs={'pk': 3, 'uidb64': uid, 'token': token}) ) self.assertEqual(response.status_code, 403) @@ -161,11 +153,7 @@ class ScheduleICalExportTestCase(WgerTestCase): user = User.objects.get(username='test') uid, token = make_token(user) response = self.client.get( - reverse('manager:schedule:ical', kwargs={ - 'pk': 2, - 'uidb64': uid, - 'token': token - }) + reverse('manager:schedule:ical', kwargs={'pk': 2, 'uidb64': uid, 'token': token}) ) self.assertEqual(response.status_code, 200) @@ -186,11 +174,7 @@ class ScheduleICalExportTestCase(WgerTestCase): uid = 'AB' token = 'abc-11223344556677889900' response = self.client.get( - reverse('manager:schedule:ical', kwargs={ - 'pk': 2, - 'uidb64': uid, - 'token': token - }) + reverse('manager:schedule:ical', kwargs={'pk': 2, 'uidb64': uid, 'token': token}) ) self.assertEqual(response.status_code, 403) diff --git a/wger/manager/tests/test_pdf.py b/wger/manager/tests/test_pdf.py index 79118dfbb..117f8aa1c 100644 --- a/wger/manager/tests/test_pdf.py +++ b/wger/manager/tests/test_pdf.py @@ -34,11 +34,7 @@ class WorkoutPdfLogExportTestCase(WgerTestCase): user = User.objects.get(username='test') uid, token = make_token(user) response = self.client.get( - reverse('manager:workout:pdf-log', kwargs={ - 'id': 3, - 'uidb64': uid, - 'token': token - }) + reverse('manager:workout:pdf-log', kwargs={'id': 3, 'uidb64': uid, 'token': token}) ) self.assertEqual(response.status_code, 200) @@ -57,11 +53,7 @@ class WorkoutPdfLogExportTestCase(WgerTestCase): uid = 'AB' token = 'abc-11223344556677889900' response = self.client.get( - reverse('manager:workout:pdf-log', kwargs={ - 'id': 3, - 'uidb64': uid, - 'token': token - }) + reverse('manager:workout:pdf-log', kwargs={'id': 3, 'uidb64': uid, 'token': token}) ) self.assertEqual(response.status_code, 403) @@ -93,10 +85,7 @@ class WorkoutPdfLogExportTestCase(WgerTestCase): """ response = self.client.get( - reverse('manager:workout:pdf-log', kwargs={ - 'id': 3, - 'comments': 0 - }) + reverse('manager:workout:pdf-log', kwargs={'id': 3, 'comments': 0}) ) if fail: @@ -119,10 +108,7 @@ class WorkoutPdfLogExportTestCase(WgerTestCase): """ response = self.client.get( - reverse('manager:workout:pdf-log', kwargs={ - 'id': 3, - 'images': 1 - }) + reverse('manager:workout:pdf-log', kwargs={'id': 3, 'images': 1}) ) if fail: @@ -145,11 +131,7 @@ class WorkoutPdfLogExportTestCase(WgerTestCase): """ response = self.client.get( - reverse('manager:workout:pdf-log', kwargs={ - 'id': 3, - 'images': 1, - 'comments': 1 - }) + reverse('manager:workout:pdf-log', kwargs={'id': 3, 'images': 1, 'comments': 1}) ) if fail: @@ -208,11 +190,7 @@ class WorkoutPdfTableExportTestCase(WgerTestCase): user = User.objects.get(username='test') uid, token = make_token(user) response = self.client.get( - reverse('manager:workout:pdf-table', kwargs={ - 'id': 3, - 'uidb64': uid, - 'token': token - }) + reverse('manager:workout:pdf-table', kwargs={'id': 3, 'uidb64': uid, 'token': token}) ) self.assertEqual(response.status_code, 200) @@ -234,11 +212,7 @@ class WorkoutPdfTableExportTestCase(WgerTestCase): uid = 'AB' token = 'abc-11223344556677889900' response = self.client.get( - reverse('manager:workout:pdf-table', kwargs={ - 'id': 3, - 'uidb64': uid, - 'token': token - }) + reverse('manager:workout:pdf-table', kwargs={'id': 3, 'uidb64': uid, 'token': token}) ) self.assertEqual(response.status_code, 403) diff --git a/wger/manager/tests/test_schedule.py b/wger/manager/tests/test_schedule.py index 1ce9a28b3..0d031d2af 100644 --- a/wger/manager/tests/test_schedule.py +++ b/wger/manager/tests/test_schedule.py @@ -92,8 +92,8 @@ class ScheduleRepresentationTestCase(WgerTestCase): Test that the representation of an object is correct """ self.assertEqual( - "{0}".format(Schedule.objects.get(pk=1)), - 'my cool schedule that i found on the internet' + '{0}'.format(Schedule.objects.get(pk=1)), + 'my cool schedule that i found on the internet', ) @@ -110,7 +110,7 @@ class CreateScheduleTestCase(WgerAddTestCase): 'name': 'My cool schedule', 'start_date': datetime.date.today(), 'is_active': True, - 'is_loop': True + 'is_loop': True, } @@ -138,7 +138,7 @@ class EditScheduleTestCase(WgerEditTestCase): 'name': 'An updated name', 'start_date': datetime.date.today(), 'is_active': True, - 'is_loop': True + 'is_loop': True, } @@ -473,7 +473,7 @@ class SchedulePdfExportTestCase(WgerTestCase): Test exporting a schedule as a pdf """ - def export_pdf_token(self, pdf_type="log"): + def export_pdf_token(self, pdf_type='log'): """ Helper function to test exporting a workout as a pdf using tokens """ @@ -483,11 +483,7 @@ class SchedulePdfExportTestCase(WgerTestCase): response = self.client.get( reverse( 'manager:schedule:pdf-{0}'.format(pdf_type), - kwargs={ - 'pk': 1, - 'uidb64': uid, - 'token': token - } + kwargs={'pk': 1, 'uidb64': uid, 'token': token}, ) ) @@ -495,7 +491,7 @@ class SchedulePdfExportTestCase(WgerTestCase): self.assertEqual(response['Content-Type'], 'application/pdf') self.assertEqual( response['Content-Disposition'], - 'attachment; filename=Schedule-1-{0}.pdf'.format(pdf_type) + 'attachment; filename=Schedule-1-{0}.pdf'.format(pdf_type), ) # Approximate size only @@ -508,16 +504,12 @@ class SchedulePdfExportTestCase(WgerTestCase): response = self.client.get( reverse( 'manager:schedule:pdf-{0}'.format(pdf_type), - kwargs={ - 'pk': 1, - 'uidb64': uid, - 'token': token - } + kwargs={'pk': 1, 'uidb64': uid, 'token': token}, ) ) self.assertEqual(response.status_code, 403) - def export_pdf(self, fail=False, pdf_type="log"): + def export_pdf(self, fail=False, pdf_type='log'): """ Helper function to test exporting a workout as a pdf """ @@ -533,14 +525,14 @@ class SchedulePdfExportTestCase(WgerTestCase): self.assertEqual(response['Content-Type'], 'application/pdf') self.assertEqual( response['Content-Disposition'], - 'attachment; filename=Schedule-1-{0}.pdf'.format(pdf_type) + 'attachment; filename=Schedule-1-{0}.pdf'.format(pdf_type), ) # Approximate size only self.assertGreater(int(response['Content-Length']), 29000) self.assertLess(int(response['Content-Length']), 35000) - def export_pdf_with_comments(self, fail=False, pdf_type="log"): + def export_pdf_with_comments(self, fail=False, pdf_type='log'): """ Helper function to test exporting a workout as a pdf, with exercise coments """ @@ -550,13 +542,7 @@ class SchedulePdfExportTestCase(WgerTestCase): response = self.client.get( reverse( 'manager:schedule:pdf-{0}'.format(pdf_type), - kwargs={ - 'pk': 3, - 'images': 0, - 'comments': 1, - 'uidb64': uid, - 'token': token - } + kwargs={'pk': 3, 'images': 0, 'comments': 1, 'uidb64': uid, 'token': token}, ) ) @@ -567,14 +553,14 @@ class SchedulePdfExportTestCase(WgerTestCase): self.assertEqual(response['Content-Type'], 'application/pdf') self.assertEqual( response['Content-Disposition'], - 'attachment; filename=Schedule-3-{0}.pdf'.format(pdf_type) + 'attachment; filename=Schedule-3-{0}.pdf'.format(pdf_type), ) # Approximate size only self.assertGreater(int(response['Content-Length']), 29000) self.assertLess(int(response['Content-Length']), 35000) - def export_pdf_with_images(self, fail=False, pdf_type="log"): + def export_pdf_with_images(self, fail=False, pdf_type='log'): """ Helper function to test exporting a workout as a pdf, with exercise images """ @@ -583,13 +569,7 @@ class SchedulePdfExportTestCase(WgerTestCase): response = self.client.get( reverse( 'manager:schedule:pdf-{0}'.format(pdf_type), - kwargs={ - 'pk': 3, - 'images': 1, - 'comments': 0, - 'uidb64': uid, - 'token': token - } + kwargs={'pk': 3, 'images': 1, 'comments': 0, 'uidb64': uid, 'token': token}, ) ) @@ -600,14 +580,14 @@ class SchedulePdfExportTestCase(WgerTestCase): self.assertEqual(response['Content-Type'], 'application/pdf') self.assertEqual( response['Content-Disposition'], - 'attachment; filename=Schedule-3-{0}.pdf'.format(pdf_type) + 'attachment; filename=Schedule-3-{0}.pdf'.format(pdf_type), ) # Approximate size only self.assertGreater(int(response['Content-Length']), 29000) self.assertLess(int(response['Content-Length']), 35000) - def export_pdf_with_images_and_comments(self, fail=False, pdf_type="log"): + def export_pdf_with_images_and_comments(self, fail=False, pdf_type='log'): """ Helper function to test exporting a workout as a pdf, with images and comments """ @@ -617,13 +597,7 @@ class SchedulePdfExportTestCase(WgerTestCase): response = self.client.get( reverse( 'manager:schedule:pdf-{0}'.format(pdf_type), - kwargs={ - 'pk': 3, - 'images': 1, - 'comments': 1, - 'uidb64': uid, - 'token': token - } + kwargs={'pk': 3, 'images': 1, 'comments': 1, 'uidb64': uid, 'token': token}, ) ) @@ -634,7 +608,7 @@ class SchedulePdfExportTestCase(WgerTestCase): self.assertEqual(response['Content-Type'], 'application/pdf') self.assertEqual( response['Content-Disposition'], - 'attachment; filename=Schedule-3-{0}.pdf'.format(pdf_type) + 'attachment; filename=Schedule-3-{0}.pdf'.format(pdf_type), ) # Approximate size only @@ -691,16 +665,15 @@ class SchedulePdfExportTestCase(WgerTestCase): self.export_pdf_with_images_and_comments(fail=False) self.export_pdf_token() - -# #####TABLE##### + # #####TABLE##### def test_export_pdf_table_anonymous(self): """ Tests exporting a workout as a pdf as an anonymous user """ - self.export_pdf(fail=True, pdf_type="table") - self.export_pdf_token(pdf_type="table") + self.export_pdf(fail=True, pdf_type='table') + self.export_pdf_token(pdf_type='table') def test_export_pdf_table_owner(self): """ @@ -708,8 +681,8 @@ class SchedulePdfExportTestCase(WgerTestCase): """ self.user_login('test') - self.export_pdf(fail=False, pdf_type="table") - self.export_pdf_token(pdf_type="table") + self.export_pdf(fail=False, pdf_type='table') + self.export_pdf_token(pdf_type='table') def test_export_pdf_table_other(self): """ @@ -717,38 +690,39 @@ class SchedulePdfExportTestCase(WgerTestCase): """ self.user_login('admin') - self.export_pdf(fail=True, pdf_type="table") - self.export_pdf_token(pdf_type="table") + self.export_pdf(fail=True, pdf_type='table') + self.export_pdf_token(pdf_type='table') def test_export_pdf_table_with_comments(self, fail=False): """ Tests exporting a workout as a pdf as the owner user with comments """ self.user_login('test') - self.export_pdf_with_comments(fail=False, pdf_type="table") - self.export_pdf_token(pdf_type="table") + self.export_pdf_with_comments(fail=False, pdf_type='table') + self.export_pdf_token(pdf_type='table') def test_export_pdf_table_with_images(self, fail=False): """ Tests exporting a workout as a pdf as the owner user with images """ self.user_login('test') - self.export_pdf_with_images(fail=False, pdf_type="table") - self.export_pdf_token(pdf_type="table") + self.export_pdf_with_images(fail=False, pdf_type='table') + self.export_pdf_token(pdf_type='table') def test_export_pdf_table_with_images_and_comments(self, fail=False): """ Tests exporting a workout as a pdf as the owner user with images andcomments """ self.user_login('test') - self.export_pdf_with_images_and_comments(fail=False, pdf_type="table") - self.export_pdf_token(pdf_type="table") + self.export_pdf_with_images_and_comments(fail=False, pdf_type='table') + self.export_pdf_token(pdf_type='table') class ScheduleApiTestCase(api_base_test.ApiBaseResourceTestCase): """ Tests the schedule overview resource """ + pk = 1 resource = Schedule private_resource = True @@ -756,5 +730,5 @@ class ScheduleApiTestCase(api_base_test.ApiBaseResourceTestCase): 'name': 'An updated name', 'start_date': datetime.date.today(), 'is_active': True, - 'is_loop': True + 'is_loop': True, } diff --git a/wger/manager/tests/test_schedule_step.py b/wger/manager/tests/test_schedule_step.py index d2cc32e8c..61c95326e 100644 --- a/wger/manager/tests/test_schedule_step.py +++ b/wger/manager/tests/test_schedule_step.py @@ -38,7 +38,7 @@ class ScheduleStepRepresentationTestCase(WgerTestCase): """ Test that the representation of an object is correct """ - self.assertEqual("{0}".format(ScheduleStep.objects.get(pk=1)), 'A test workout') + self.assertEqual('{0}'.format(ScheduleStep.objects.get(pk=1)), 'A test workout') class ScheduleStepTestCase(WgerTestCase): @@ -96,6 +96,7 @@ class ScheduleStepApiTestCase(api_base_test.ApiBaseResourceTestCase): """ Tests the schedule step overview resource """ + pk = 4 resource = ScheduleStep private_resource = True diff --git a/wger/manager/tests/test_set.py b/wger/manager/tests/test_set.py index 52a918bfd..f9cdf5c00 100644 --- a/wger/manager/tests/test_set.py +++ b/wger/manager/tests/test_set.py @@ -236,11 +236,11 @@ class TestSetOrderTestCase(WgerTestCase): order = () for day_set in day.set_set.select_related(): - order += (day_set.id, ) + order += (day_set.id,) return order - @skip("Fix later") + @skip('Fix later') def test_set_order(self, logged_in=False): """ Helper function that add some sets and checks the order @@ -252,7 +252,7 @@ class TestSetOrderTestCase(WgerTestCase): for i in range(0, 7): self.add_set([exercises[i]]) prev = self.get_order() - orig += (i + 4, ) + orig += (i + 4,) self.assertEqual(orig, prev) @@ -268,10 +268,7 @@ class TestSetAddFormset(WgerTestCase): """ base = ExerciseBase.objects.get(pk=1) response = self.client.get( - reverse('manager:set:get-formset', kwargs={ - 'base_pk': 1, - 'reps': 4 - }) + reverse('manager:set:get-formset', kwargs={'base_pk': 1, 'reps': 4}) ) self.assertEqual(response.status_code, 200) @@ -308,7 +305,8 @@ class SetEditEditTestCase(WgerTestCase): # Try to edit the object response = self.client.post( - reverse('manager:set:edit', kwargs={'pk': 3}), { + reverse('manager:set:edit', kwargs={'pk': 3}), + { 'exercise2-TOTAL_FORMS': 1, 'exercise2-INITIAL_FORMS': 1, 'exercise2-MAX_NUM_FORMS': 1, @@ -318,7 +316,7 @@ class SetEditEditTestCase(WgerTestCase): 'exercise2-0-repetition_unit': 2, 'exercise2-0-weight_unit': 3, 'exercise2-0-rir': '1.5', - } + }, ) entry_after = Set.objects.get(pk=3) @@ -485,8 +483,7 @@ class SetSmartReprTestCase(WgerTestCase): setting_text = set_obj.reps_smart_text(ExerciseBase.objects.get(pk=1)) self.assertEqual( setting_text, - '8 (90 kg, 3 RiR) – 10 (80 kg, 2.5 RiR) – ' - '10 (80 kg, 2 RiR) – 12 (80 kg, 1 RiR)', + '8 (90 kg, 3 RiR) – 10 (80 kg, 2.5 RiR) – ' '10 (80 kg, 2 RiR) – 12 (80 kg, 1 RiR)', ) def test_synthetic_settings(self): @@ -537,6 +534,7 @@ class SetApiTestCase(api_base_test.ApiBaseResourceTestCase): """ Tests the set overview resource """ + pk = 3 resource = Set private_resource = True diff --git a/wger/manager/tests/test_weight_log.py b/wger/manager/tests/test_weight_log.py index 12ea4f9c4..5dd514e13 100644 --- a/wger/manager/tests/test_weight_log.py +++ b/wger/manager/tests/test_weight_log.py @@ -282,7 +282,8 @@ class WeightLogEntryEditTestCase(WgerTestCase): date_before = WorkoutLog.objects.get(pk=1).date response = self.client.post( - reverse('manager:log:edit', kwargs={'pk': 1}), { + reverse('manager:log:edit', kwargs={'pk': 1}), + { 'date': '2012-01-01', 'reps': 10, 'repetition_unit': 2, @@ -290,7 +291,7 @@ class WeightLogEntryEditTestCase(WgerTestCase): 'weight': 10, 'exercise_base': 1, 'rir': 2, - } + }, ) date_after = WorkoutLog.objects.get(pk=1).date @@ -356,12 +357,7 @@ class WorkoutLogCacheTestCase(WgerTestCase): self.client.get( reverse( 'manager:workout:calendar-day', - kwargs={ - 'username': 'admin', - 'year': 2012, - 'month': 10, - 'day': 1 - } + kwargs={'username': 'admin', 'year': 2012, 'month': 10, 'day': 1}, ) ) self.assertTrue(cache.get(cache_mapper.get_workout_log_list(log_hash))) @@ -376,11 +372,7 @@ class WorkoutLogCacheTestCase(WgerTestCase): self.client.get( reverse( - 'manager:workout:calendar', kwargs={ - 'username': 'admin', - 'year': 2012, - 'month': 10 - } + 'manager:workout:calendar', kwargs={'username': 'admin', 'year': 2012, 'month': 10} ) ) self.assertTrue(cache.get(cache_mapper.get_workout_log_list(log_hash))) @@ -396,12 +388,7 @@ class WorkoutLogCacheTestCase(WgerTestCase): self.client.get( reverse( 'manager:workout:calendar-day', - kwargs={ - 'username': 'admin', - 'year': 2012, - 'month': 10, - 'day': 1 - } + kwargs={'username': 'admin', 'year': 2012, 'month': 10, 'day': 1}, ) ) self.assertTrue(cache.get(cache_mapper.get_workout_log_list(log_hash))) @@ -417,12 +404,7 @@ class WorkoutLogCacheTestCase(WgerTestCase): self.client.get( reverse( 'manager:workout:calendar-day', - kwargs={ - 'username': 'admin', - 'year': 2012, - 'month': 10, - 'day': 1 - } + kwargs={'username': 'admin', 'year': 2012, 'month': 10, 'day': 1}, ) ) @@ -444,12 +426,7 @@ class WorkoutLogCacheTestCase(WgerTestCase): self.client.get( reverse( 'manager:workout:calendar-day', - kwargs={ - 'username': 'admin', - 'year': 2012, - 'month': 10, - 'day': 1 - } + kwargs={'username': 'admin', 'year': 2012, 'month': 10, 'day': 1}, ) ) @@ -471,12 +448,7 @@ class WorkoutLogCacheTestCase(WgerTestCase): self.client.get( reverse( 'manager:workout:calendar-day', - kwargs={ - 'username': 'admin', - 'year': 2012, - 'month': 10, - 'day': 1 - } + kwargs={'username': 'admin', 'year': 2012, 'month': 10, 'day': 1}, ) ) @@ -497,12 +469,7 @@ class WorkoutLogCacheTestCase(WgerTestCase): self.client.get( reverse( 'manager:workout:calendar-day', - kwargs={ - 'username': 'admin', - 'year': 2012, - 'month': 10, - 'day': 1 - } + kwargs={'username': 'admin', 'year': 2012, 'month': 10, 'day': 1}, ) ) @@ -517,15 +484,16 @@ class WorkoutLogApiTestCase(api_base_test.ApiBaseResourceTestCase): """ Tests the workout log overview resource """ + pk = 5 resource = WorkoutLog private_resource = True data = { - "exercise_base": 1, - "workout": 3, - "reps": 3, - "repetition_unit": 1, - "weight_unit": 2, - "weight": 2, - "date": datetime.date.today() + 'exercise_base': 1, + 'workout': 3, + 'reps': 3, + 'repetition_unit': 1, + 'weight_unit': 2, + 'weight': 2, + 'date': datetime.date.today(), } diff --git a/wger/manager/tests/test_workout.py b/wger/manager/tests/test_workout.py index 82ab02c82..9928300a1 100644 --- a/wger/manager/tests/test_workout.py +++ b/wger/manager/tests/test_workout.py @@ -129,8 +129,9 @@ class WorkoutApiTestCase(api_base_test.ApiBaseResourceTestCase): """ Tests the workout overview resource """ + pk = 3 resource = Workout private_resource = True - special_endpoints = ('canonical_representation', ) + special_endpoints = ('canonical_representation',) data = {'name': 'A new comment'} diff --git a/wger/manager/tests/test_workout_canonical.py b/wger/manager/tests/test_workout_canonical.py index e344424c3..b958fdbbf 100644 --- a/wger/manager/tests/test_workout_canonical.py +++ b/wger/manager/tests/test_workout_canonical.py @@ -35,6 +35,7 @@ class WorkoutCanonicalFormTestCase(WgerTestCase): """ Tests the canonical form for a workout """ + maxDiff = None def test_canonical_form(self): @@ -52,64 +53,51 @@ class WorkoutCanonicalFormTestCase(WgerTestCase): image1 = '/media/exercise-images/1/protestschwein.jpg' image2 = '/media/exercise-images/1/wildschwein.jpg' self.assertEqual( - workout.canonical_representation['muscles'], { + workout.canonical_representation['muscles'], + { 'back': [muscle2], 'frontsecondary': [muscle1], 'backsecondary': [muscle1], - 'front': [muscle1] - } + 'front': [muscle1], + }, ) self.assertEqual(workout.canonical_representation['obj'], workout) canonical_form = { - 'days_of_week': { - 'day_list': [DaysOfWeek.objects.get(pk=2)], - 'text': 'Tuesday' - }, + 'days_of_week': {'day_list': [DaysOfWeek.objects.get(pk=2)], 'text': 'Tuesday'}, 'muscles': { 'back': [muscle2], 'frontsecondary': [], 'backsecondary': [], - 'front': [muscle1] + 'front': [muscle1], }, - 'obj': - Day.objects.get(pk=1), + 'obj': Day.objects.get(pk=1), 'set_list': [ { 'exercise_list': [ { - 'obj': - ExerciseBase.objects.get(pk=1), + 'obj': ExerciseBase.objects.get(pk=1), 'image_list': [ - { - 'image': image1, - 'is_main': True - }, { - 'image': image2, - 'is_main': False - } + {'image': image1, 'is_main': True}, + {'image': image2, 'is_main': False}, ], 'comment_list': [], - 'has_weight': - False, + 'has_weight': False, 'setting_obj_list': [setting_1], - 'setting_text': - '2 \xd7 8 (3 RiR)', + 'setting_text': '2 \xd7 8 (3 RiR)', } ], - 'is_superset': - False, + 'is_superset': False, 'muscles': { 'back': [muscle2], 'frontsecondary': [], 'backsecondary': [], - 'front': [muscle1] + 'front': [muscle1], }, - 'obj': - Set.objects.get(pk=1), - 'settings_computed': [setting1] * 2 + 'obj': Set.objects.get(pk=1), + 'settings_computed': [setting1] * 2, } - ] + ], } days_test_data = workout.canonical_representation['day_list'][0] @@ -122,46 +110,37 @@ class WorkoutCanonicalFormTestCase(WgerTestCase): self.assertEqual(days_test_data['set_list'][0][key], canonical_form['set_list'][0][key]) canonical_form = { - 'days_of_week': { - 'day_list': [DaysOfWeek.objects.get(pk=4)], - 'text': 'Thursday' - }, - 'obj': - Day.objects.get(pk=2), + 'days_of_week': {'day_list': [DaysOfWeek.objects.get(pk=4)], 'text': 'Thursday'}, + 'obj': Day.objects.get(pk=2), 'muscles': { 'back': [muscle2], 'frontsecondary': [muscle1], 'backsecondary': [muscle1], - 'front': [] + 'front': [], }, 'set_list': [ { 'exercise_list': [ { 'obj': ExerciseBase.objects.get(pk=2), - 'image_list': [{ - 'image': image2, - 'is_main': False - }], + 'image_list': [{'image': image2, 'is_main': False}], 'comment_list': [], 'has_weight': True, 'setting_obj_list': [setting_2], 'setting_text': '4 \xd7 10 (15 kg)', } ], - 'is_superset': - False, + 'is_superset': False, 'muscles': { 'back': [muscle2], 'frontsecondary': [muscle1], 'backsecondary': [muscle1], - 'front': [] + 'front': [], }, - 'obj': - Set.objects.get(pk=2), - 'settings_computed': [setting2] * 4 + 'obj': Set.objects.get(pk=2), + 'settings_computed': [setting2] * 4, } - ] + ], } days_test_data = workout.canonical_representation['day_list'][1] self.assertEqual(days_test_data['days_of_week'], canonical_form['days_of_week']) @@ -173,17 +152,9 @@ class WorkoutCanonicalFormTestCase(WgerTestCase): # Check that the content is the same canonical_form = { - 'days_of_week': { - 'day_list': [DaysOfWeek.objects.get(pk=5)], - 'text': 'Friday' - }, + 'days_of_week': {'day_list': [DaysOfWeek.objects.get(pk=5)], 'text': 'Friday'}, 'obj': Day.objects.get(pk=4), - 'muscles': { - 'back': [], - 'front': [], - 'frontsecondary': [], - 'backsecondary': [] - }, + 'muscles': {'back': [], 'front': [], 'frontsecondary': [], 'backsecondary': []}, 'set_list': [], } self.assertEqual(workout.canonical_representation['day_list'][2], canonical_form) @@ -201,18 +172,17 @@ class WorkoutCanonicalFormTestCase(WgerTestCase): setting = Setting.objects.get(pk=3) image2 = '/media/exercise-images/1/wildschwein.jpg' self.assertEqual( - day.canonical_representation['days_of_week'], { - 'day_list': [weekday1, weekday2], - 'text': 'Wednesday, Friday' - } + day.canonical_representation['days_of_week'], + {'day_list': [weekday1, weekday2], 'text': 'Wednesday, Friday'}, ) self.assertEqual( - day.canonical_representation['muscles'], { + day.canonical_representation['muscles'], + { 'back': [muscle2], 'frontsecondary': [muscle1], 'backsecondary': [muscle1], - 'front': [] - } + 'front': [], + }, ) self.assertEqual(day.canonical_representation['obj'], day) @@ -221,27 +191,22 @@ class WorkoutCanonicalFormTestCase(WgerTestCase): 'exercise_list': [ { 'obj': ExerciseBase.objects.get(pk=2), - 'image_list': [{ - 'image': image2, - 'is_main': False - }], + 'image_list': [{'image': image2, 'is_main': False}], 'comment_list': [], 'has_weight': False, 'setting_obj_list': [Setting.objects.get(pk=3)], 'setting_text': '4 \xd7 10', } ], - 'is_superset': - False, + 'is_superset': False, 'muscles': { 'back': [muscle2], 'frontsecondary': [muscle1], 'backsecondary': [muscle1], - 'front': [] + 'front': [], }, - 'obj': - Set.objects.get(pk=3), - 'settings_computed': [setting] * 4 + 'obj': Set.objects.get(pk=3), + 'settings_computed': [setting] * 4, } ] diff --git a/wger/manager/tests/test_workout_session.py b/wger/manager/tests/test_workout_session.py index 6c14d3bb3..c655dd4ef 100644 --- a/wger/manager/tests/test_workout_session.py +++ b/wger/manager/tests/test_workout_session.py @@ -57,8 +57,8 @@ class AddWorkoutSessionTestCase(WgerAddTestCase): 'workout_pk': 1, 'year': datetime.date.today().year, 'month': datetime.date.today().month, - 'day': datetime.date.today().day - } + 'day': datetime.date.today().day, + }, ) data = { 'user': 1, @@ -67,7 +67,7 @@ class AddWorkoutSessionTestCase(WgerAddTestCase): 'notes': 'Some interesting and deep insights', 'impression': '3', 'time_start': datetime.time(10, 0), - 'time_end': datetime.time(13, 0) + 'time_end': datetime.time(13, 0), } @@ -86,7 +86,7 @@ class EditWorkoutSessionTestCase(WgerEditTestCase): 'notes': 'My new insights', 'impression': '3', 'time_start': datetime.time(10, 0), - 'time_end': datetime.time(13, 0) + 'time_end': datetime.time(13, 0), } @@ -105,7 +105,7 @@ class WorkoutSessionModelTestCase(WgerTestCase): session.date = datetime.date.today() self.assertEqual( '{0}'.format(session), - '{0} - {1}'.format(Workout.objects.get(pk=1), datetime.date.today()) + '{0} - {1}'.format(Workout.objects.get(pk=1), datetime.date.today()), ) @@ -136,10 +136,7 @@ class WorkoutSessionDeleteLogsTestCase(WgerTestCase): self.assertEqual(count_before, 1) response = self.client.post( - reverse('manager:session:delete', kwargs={ - 'pk': 1, - 'logs': 'logs' - }) + reverse('manager:session:delete', kwargs={'pk': 1, 'logs': 'logs'}) ) self.assertEqual(response.status_code, 302) self.assertEqual(WorkoutSession.objects.all().count(), 3) @@ -259,6 +256,7 @@ class WorkoutSessionApiTestCase(api_base_test.ApiBaseResourceTestCase): """ Tests the workout overview resource """ + pk = 4 resource = WorkoutSession private_resource = True @@ -268,5 +266,5 @@ class WorkoutSessionApiTestCase(api_base_test.ApiBaseResourceTestCase): 'notes': 'My new insights', 'impression': '3', 'time_start': datetime.time(10, 0), - 'time_end': datetime.time(13, 0) + 'time_end': datetime.time(13, 0), } diff --git a/wger/manager/urls.py b/wger/manager/urls.py index 6268e1d18..bba566601 100644 --- a/wger/manager/urls.py +++ b/wger/manager/urls.py @@ -54,7 +54,7 @@ patterns_log = [ '/delete', log.WorkoutLogDeleteView.as_view(), name='delete', - ) + ), ] # sub patterns for templates @@ -372,12 +372,12 @@ patterns_step = [ ] urlpatterns = [ - path('', include((patterns_workout, 'workout'), namespace="workout")), - path('template/', include((patterns_templates, 'template'), namespace="template")), - path('log/', include((patterns_log, 'log'), namespace="log")), - path('day/', include((patterns_day, 'day'), namespace="day")), - path('set/', include((patterns_set, 'set'), namespace="set")), - path('session/', include((patterns_session, 'session'), namespace="session")), - path('schedule/', include((patterns_schedule, 'schedule'), namespace="schedule")), - path('schedule/step/', include((patterns_step, 'step'), namespace="step")), + path('', include((patterns_workout, 'workout'), namespace='workout')), + path('template/', include((patterns_templates, 'template'), namespace='template')), + path('log/', include((patterns_log, 'log'), namespace='log')), + path('day/', include((patterns_day, 'day'), namespace='day')), + path('set/', include((patterns_set, 'set'), namespace='set')), + path('session/', include((patterns_session, 'session'), namespace='session')), + path('schedule/', include((patterns_schedule, 'schedule'), namespace='schedule')), + path('schedule/step/', include((patterns_step, 'step'), namespace='step')), ] diff --git a/wger/manager/views/ical.py b/wger/manager/views/ical.py index 6c46d584c..0f43c5bdd 100644 --- a/wger/manager/views/ical.py +++ b/wger/manager/views/ical.py @@ -91,7 +91,6 @@ def get_events_workout(calendar, workout, duration, start_date=None): site = Site.objects.get_current() for day in workout.day_set.all(): - # Make the description of the event with the day's exercises description_list = [] for set_obj in day.set_set.all(): @@ -137,8 +136,9 @@ def export(request, pk, uidb64=None, token=None): # Send the file to the user response = HttpResponse(content_type='text/calendar') - response['Content-Disposition'] = \ - 'attachment; filename=Calendar-workout-{0}.ics'.format(workout.pk) + response['Content-Disposition'] = 'attachment; filename=Calendar-workout-{0}.ics'.format( + workout.pk + ) response.write(calendar.to_ical()) response['Content-Length'] = len(response.content) return response @@ -171,8 +171,9 @@ def export_schedule(request, pk, uidb64=None, token=None): # Send the file to the user response = HttpResponse(content_type='text/calendar') - response['Content-Disposition'] = \ - 'attachment; filename=Calendar-schedule-{0}.ics'.format(schedule.pk) + response['Content-Disposition'] = 'attachment; filename=Calendar-schedule-{0}.ics'.format( + schedule.pk + ) response.write(calendar.to_ical()) response['Content-Length'] = len(response.content) return response diff --git a/wger/manager/views/log.py b/wger/manager/views/log.py index dd5a39556..45e4fb084 100644 --- a/wger/manager/views/log.py +++ b/wger/manager/views/log.py @@ -83,6 +83,7 @@ class WorkoutLogUpdateView(WgerFormMixin, UpdateView, LoginRequiredMixin): """ Generic view to edit an existing workout log weight entry """ + model = WorkoutLog form_class = WorkoutLogForm @@ -126,7 +127,6 @@ def add(request, pk): for set_set in day.set_set.all(): for base in set_set.exercise_bases: - # Maximum possible values total_sets += int(set_set.sets) counter_before = counter @@ -137,7 +137,7 @@ def add(request, pk): exercise_base_list[base.id] = { 'obj': base, 'sets': int(set_set.sets), - 'form_ids': form_id_range + 'form_ids': form_id_range, } counter += 1 @@ -151,7 +151,6 @@ def add(request, pk): ) # Process the request if request.method == 'POST': - # Make a copy of the POST data and go through it. The reason for this is # that the form expects a value for the exercise which is not present in # the form (for space and usability reasons) @@ -187,7 +186,6 @@ def add(request, pk): # Log entries (only the ones with actual content) log_instances = [i for i in formset.save(commit=False) if i.reps] for log_instance in log_instances: - # Set the weight unit in kg if not hasattr(log_instance, 'weight_unit'): log_instance.weight_unit = WeightUnit.objects.get(pk=1) @@ -212,11 +210,9 @@ def add(request, pk): formset = WorkoutLogFormSet( queryset=WorkoutLog.objects.none(), initial=[ - { - 'weight_unit': user_weight_unit, - 'repetition_unit': 1 - } for x in range(0, total_sets) - ] + {'weight_unit': user_weight_unit, 'repetition_unit': 1} + for x in range(0, total_sets) + ], ) # Depending on whether there is already a workout session for today, update @@ -231,7 +227,7 @@ def add(request, pk): for base in exercise_base_list: form_id_from = min(exercise_base_list[base]['form_ids']) form_id_to = max(exercise_base_list[base]['form_ids']) - exercise_base_list[base]['forms'] = formset[form_id_from:form_id_to + 1] + exercise_base_list[base]['forms'] = formset[form_id_from : form_id_to + 1] context = { 'day': day, @@ -240,7 +236,7 @@ def add(request, pk): 'helper': WorkoutLogFormHelper(), 'session_form': session_form, 'form': session_form, - 'form_action': request.path + 'form_action': request.path, } return render(request, 'log/add.html', context) @@ -257,7 +253,6 @@ class WorkoutLogDetailView(DetailView, LoginRequiredMixin): owner_user = None def get_context_data(self, **kwargs): - # Call the base implementation first to get a context context = super(WorkoutLogDetailView, self).get_context_data(**kwargs) is_owner = self.owner_user == self.request.user @@ -279,7 +274,7 @@ class WorkoutLogDetailView(DetailView, LoginRequiredMixin): user=self.owner_user, weight_unit__in=(1, 2), repetition_unit=1, - workout=self.object + workout=self.object, ) entry_log, chart_data = process_log_entries(logs) if entry_log: @@ -349,7 +344,7 @@ def day(request, username, year, month, day): try: date = datetime.date(int(year), int(month), int(day)) except ValueError as e: - logger.error("Error on date: {0}".format(e)) + logger.error('Error on date: {0}'.format(e)) return HttpResponseForbidden() context['logs'] = group_log_entries(user, date.year, date.month, date.day) context['date'] = date diff --git a/wger/manager/views/pdf.py b/wger/manager/views/pdf.py index 3597da9f1..2ad54d906 100644 --- a/wger/manager/views/pdf.py +++ b/wger/manager/views/pdf.py @@ -84,7 +84,7 @@ def workout_log(request, id, images=False, comments=False, uidb64=None, token=No bottomMargin=0.5 * cm, title=_('Workout'), author='wger Workout Manager', - subject=_('Workout for %s') % request.user.username + subject=_('Workout for %s') % request.user.username, ) # container for the 'Flowable' objects @@ -96,7 +96,7 @@ def workout_log(request, id, images=False, comments=False, uidb64=None, token=No # Set the title p = Paragraph( - f'{workout.name}', styleSheet["HeaderBold"] + f'{workout.name}', styleSheet['HeaderBold'] ) elements.append(p) elements.append(Spacer(10 * cm, 0.5 * cm)) @@ -160,7 +160,7 @@ def workout_view(request, id, images=False, comments=False, uidb64=None, token=N bottomMargin=0.5 * cm, title=_('Workout'), author='wger Workout Manager', - subject=_('Workout for %s') % request.user.username + subject=_('Workout for %s') % request.user.username, ) # container for the 'Flowable' objects @@ -173,7 +173,7 @@ def workout_view(request, id, images=False, comments=False, uidb64=None, token=N # Set the title p = Paragraph( '%(description)s' % {'description': workout}, - styleSheet["HeaderBold"] + styleSheet['HeaderBold'], ) elements.append(p) elements.append(Spacer(10 * cm, 1.5 * cm)) diff --git a/wger/manager/views/schedule.py b/wger/manager/views/schedule.py index 84fd1cea2..e7074b162 100644 --- a/wger/manager/views/schedule.py +++ b/wger/manager/views/schedule.py @@ -81,8 +81,8 @@ def overview(request): """ template_data = {} - template_data['schedules'] = ( - Schedule.objects.filter(user=request.user).order_by('-is_active', '-start_date') + template_data['schedules'] = Schedule.objects.filter(user=request.user).order_by( + '-is_active', '-start_date' ) return render(request, 'schedule/overview.html', template_data) @@ -150,14 +150,14 @@ def export_pdf_log(request, pk, images=False, comments=False, uidb64=None, token bottomMargin=0.5 * cm, title=_('Workout'), author='wger Workout Manager', - subject='Schedule for {0}'.format(request.user.username) + subject='Schedule for {0}'.format(request.user.username), ) # container for the 'Flowable' objects elements = [] # Set the title - p = Paragraph('{0}'.format(schedule), styleSheet["HeaderBold"]) + p = Paragraph('{0}'.format(schedule), styleSheet['HeaderBold']) elements.append(p) elements.append(Spacer(10 * cm, 0.5 * cm)) @@ -165,7 +165,7 @@ def export_pdf_log(request, pk, images=False, comments=False, uidb64=None, token for step in schedule.schedulestep_set.all(): p = Paragraph( '{0} {1}'.format(step.duration, _('Weeks')), - styleSheet["HeaderBold"], + styleSheet['HeaderBold'], ) elements.append(p) elements.append(Spacer(10 * cm, 0.5 * cm)) @@ -220,14 +220,14 @@ def export_pdf_table(request, pk, images=False, comments=False, uidb64=None, tok bottomMargin=0.5 * cm, title=_('Workout'), author='wger Workout Manager', - subject='Schedule for {0}'.format(request.user.username) + subject='Schedule for {0}'.format(request.user.username), ) # container for the 'Flowable' objects elements = [] # Set the title - p = Paragraph('{0}'.format(schedule), styleSheet["HeaderBold"]) + p = Paragraph('{0}'.format(schedule), styleSheet['HeaderBold']) elements.append(p) elements.append(Spacer(10 * cm, 0.5 * cm)) @@ -235,7 +235,7 @@ def export_pdf_table(request, pk, images=False, comments=False, uidb64=None, tok for step in schedule.schedulestep_set.all(): p = Paragraph( '{0} {1}'.format(step.duration, _('Weeks')), - styleSheet["HeaderBold"], + styleSheet['HeaderBold'], ) elements.append(p) elements.append(Spacer(10 * cm, 0.5 * cm)) diff --git a/wger/manager/views/set.py b/wger/manager/views/set.py index ef6c143b1..400fce968 100644 --- a/wger/manager/views/set.py +++ b/wger/manager/views/set.py @@ -61,7 +61,7 @@ SettingFormset = modelformset_factory( fields=SETTING_FORMSET_FIELDS, can_delete=False, can_order=False, - extra=1 + extra=1, ) @@ -80,7 +80,7 @@ def create(request, day_pk): form = SetForm(initial={'sets': Set.DEFAULT_SETS}) # If the form and all formsets validate, save them - if request.method == "POST": + if request.method == 'POST': form = SetForm(request.POST) if form.is_valid(): for base in form.cleaned_data['exercises']: @@ -145,7 +145,7 @@ def get_formset(request, base_pk, reps=Set.DEFAULT_SETS): ) context = {'formset': formset, 'helper': WorkoutLogFormHelper(), 'base': base} - return render(request, "set/formset.html", context) + return render(request, 'set/formset.html', context) @login_required @@ -179,10 +179,10 @@ def edit(request, pk): SettingFormsetEdit = modelformset_factory( Setting, form=SettingForm, - fields=SETTING_FORMSET_FIELDS + ('id', ), + fields=SETTING_FORMSET_FIELDS + ('id',), can_delete=False, can_order=True, - extra=0 + extra=0, ) formsets = [] @@ -191,7 +191,7 @@ def edit(request, pk): formset = SettingFormsetEdit(queryset=queryset, prefix='exercise{0}'.format(base.id)) formsets.append({'base': base, 'formset': formset}) - if request.method == "POST": + if request.method == 'POST': formsets = [] for base in set_obj.exercise_bases: formset = SettingFormsetEdit(request.POST, prefix='exercise{0}'.format(base.id)) diff --git a/wger/manager/views/workout.py b/wger/manager/views/workout.py index 98c3cbc00..5241bf59c 100644 --- a/wger/manager/views/workout.py +++ b/wger/manager/views/workout.py @@ -75,29 +75,29 @@ logger = logging.getLogger(__name__) @login_required def template_overview(request): - """ - - """ + """ """ return render( - request, 'workout/overview.html', { + request, + 'workout/overview.html', + { 'workouts': Workout.templates.filter(user=request.user), 'title': _('Your templates'), - 'template_overview': True - } + 'template_overview': True, + }, ) @login_required def public_template_overview(request): - """ - - """ + """ """ return render( - request, 'workout/overview.html', { + request, + 'workout/overview.html', + { 'workouts': Workout.templates.filter(is_public=True), 'title': _('Public templates'), - 'template_overview': True - } + 'template_overview': True, + }, ) @@ -159,7 +159,6 @@ def copy_workout(request, pk): workout_form = WorkoutCopyForm(request.POST) if workout_form.is_valid(): - # Copy workout workout_copy: Workout = copy.copy(workout) workout_copy.pk = None diff --git a/wger/manager/views/workout_session.py b/wger/manager/views/workout_session.py index 63c9147f0..2ce7b17e3 100644 --- a/wger/manager/views/workout_session.py +++ b/wger/manager/views/workout_session.py @@ -61,6 +61,7 @@ class WorkoutSessionUpdateView(WgerFormMixin, LoginRequiredMixin, UpdateView): """ Generic view to edit an existing workout session entry """ + model = WorkoutSession form_class = WorkoutSessionForm @@ -78,6 +79,7 @@ class WorkoutSessionAddView(WgerFormMixin, LoginRequiredMixin, CreateView): """ Generic view to add a new workout session entry """ + model = WorkoutSession form_class = WorkoutSessionForm @@ -149,7 +151,6 @@ class WorkoutSessionDeleteView(WgerDeleteMixin, LoginRequiredMixin, DeleteView): return super().form_valid(form) def get_context_data(self, **kwargs): - logs = '' if not self.kwargs.get('logs') else self.kwargs['logs'] context = super(WorkoutSessionDeleteView, self).get_context_data(**kwargs) context['title'] = _('Delete {0}?').format(self.object) diff --git a/wger/measurements/api/views.py b/wger/measurements/api/views.py index 17bc5d98e..71292a814 100644 --- a/wger/measurements/api/views.py +++ b/wger/measurements/api/views.py @@ -52,7 +52,7 @@ class CategoryViewSet(viewsets.ModelViewSet): Only allow access to appropriate objects """ # REST API generation - if getattr(self, "swagger_fake_view", False): + if getattr(self, 'swagger_fake_view', False): return Category.objects.none() return Category.objects.filter(user=self.request.user) @@ -85,7 +85,7 @@ class MeasurementViewSet(viewsets.ModelViewSet): Only allow access to appropriate objects """ # REST API generation - if getattr(self, "swagger_fake_view", False): + if getattr(self, 'swagger_fake_view', False): return Measurement.objects.none() return Measurement.objects.filter(category__user=self.request.user) diff --git a/wger/measurements/apps.py b/wger/measurements/apps.py index 04124fc04..991c5c9a3 100644 --- a/wger/measurements/apps.py +++ b/wger/measurements/apps.py @@ -4,4 +4,4 @@ from django.apps import AppConfig class MeasurementsConfig(AppConfig): default_auto_field = 'django.db.models.BigAutoField' name = 'wger.measurements' - verbose_name = "Measurements" + verbose_name = 'Measurements' diff --git a/wger/measurements/management/commands/dummy-generator-measurement-categories.py b/wger/measurements/management/commands/dummy-generator-measurement-categories.py index 3bc1ae427..5e9a1da0e 100644 --- a/wger/measurements/management/commands/dummy-generator-measurement-categories.py +++ b/wger/measurements/management/commands/dummy-generator-measurement-categories.py @@ -32,60 +32,30 @@ class Command(BaseCommand): """ Dummy generator for measurement categories """ + categories = [ - { - "name": "Biceps", - "unit": "cm" - }, - { - "name": "Quads", - "unit": "cm" - }, - { - "name": "Body fat", - "unit": "%" - }, - { - "name": "Smartness", - "unit": "IQ" - }, - { - "name": "Hotness", - "unit": "°C" - }, - { - "name": "Strength", - "unit": "KN" - }, - { - "name": "Height", - "unit": "cm" - }, - { - "name": "Facebook friends", - "unit": "" - }, - { - "name": "Tonnes moved", - "unit": "T" - }, - { - "name": "Weight of my dog", - "unit": "lb" - }, + {'name': 'Biceps', 'unit': 'cm'}, + {'name': 'Quads', 'unit': 'cm'}, + {'name': 'Body fat', 'unit': '%'}, + {'name': 'Smartness', 'unit': 'IQ'}, + {'name': 'Hotness', 'unit': '°C'}, + {'name': 'Strength', 'unit': 'KN'}, + {'name': 'Height', 'unit': 'cm'}, + {'name': 'Facebook friends', 'unit': ''}, + {'name': 'Tonnes moved', 'unit': 'T'}, + {'name': 'Weight of my dog', 'unit': 'lb'}, ] help = 'Dummy generator for measurement categories' def add_arguments(self, parser): - parser.add_argument( '--nr-categories', action='store', default=5, dest='nr_categories', type=int, - help='The number of measurement categories to create per user (default: 5, max: 10)' + help='The number of measurement categories to create per user (default: 5, max: 10)', ) parser.add_argument( '--user-id', @@ -100,9 +70,9 @@ class Command(BaseCommand): f"** Generating {options['nr_categories']} dummy measurement categories per user" ) - users = [User.objects.get(pk=options['user_id'])] \ - if options['user_id'] \ - else User.objects.all() + users = ( + [User.objects.get(pk=options['user_id'])] if options['user_id'] else User.objects.all() + ) if options['nr_categories'] > 10: print(options['nr_categories']) diff --git a/wger/measurements/management/commands/dummy-generator-measurements.py b/wger/measurements/management/commands/dummy-generator-measurements.py index 0815b5c55..a28e552d9 100644 --- a/wger/measurements/management/commands/dummy-generator-measurements.py +++ b/wger/measurements/management/commands/dummy-generator-measurements.py @@ -39,14 +39,13 @@ class Command(BaseCommand): help = 'Dummy generator for measurement entries' def add_arguments(self, parser): - parser.add_argument( '--nr-measurements', action='store', default=40, dest='nr_measurements', type=int, - help='The number of measurement entries per category (default: 40)' + help='The number of measurement entries per category (default: 40)', ) parser.add_argument( '--category-id', @@ -66,16 +65,17 @@ class Command(BaseCommand): def handle(self, **options): self.stdout.write(f"** Generating {options['nr_measurements']} dummy measurements per user") - users = [User.objects.get(pk=options['user_id'])] \ - if options['user_id'] \ - else User.objects.all() + users = ( + [User.objects.get(pk=options['user_id'])] if options['user_id'] else User.objects.all() + ) new_entries = [] for user in users: - - categories = [Category.objects.get(pk=options['category_id'])] \ - if options['category_id'] \ + categories = ( + [Category.objects.get(pk=options['category_id'])] + if options['category_id'] else Category.objects.filter(user=user) + ) self.stdout.write(f'- processing user {user.username}') diff --git a/wger/measurements/migrations/0001_initial.py b/wger/measurements/migrations/0001_initial.py index 51fe05135..2a94efdad 100644 --- a/wger/measurements/migrations/0001_initial.py +++ b/wger/measurements/migrations/0001_initial.py @@ -9,7 +9,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - initial = True dependencies = [ @@ -24,7 +23,7 @@ class Migration(migrations.Migration): 'id', models.BigAutoField( auto_created=True, primary_key=True, serialize=False, verbose_name='ID' - ) + ), ), ('name', models.CharField(max_length=100, verbose_name='Name')), ('unit', models.CharField(max_length=30, verbose_name='Unit')), @@ -33,8 +32,8 @@ class Migration(migrations.Migration): models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, - verbose_name='User' - ) + verbose_name='User', + ), ), ], options={ @@ -48,7 +47,7 @@ class Migration(migrations.Migration): 'id', models.BigAutoField( auto_created=True, primary_key=True, serialize=False, verbose_name='ID' - ) + ), ), ('date', models.DateField(default=datetime.datetime.now, verbose_name='Date')), ( @@ -58,10 +57,10 @@ class Migration(migrations.Migration): max_digits=6, validators=[ django.core.validators.MinValueValidator(0), - django.core.validators.MaxValueValidator(5000) + django.core.validators.MaxValueValidator(5000), ], - verbose_name='Value' - ) + verbose_name='Value', + ), ), ('notes', models.CharField(blank=True, max_length=100, verbose_name='Description')), ( @@ -69,16 +68,16 @@ class Migration(migrations.Migration): models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, to='measurements.category', - verbose_name='User' - ) + verbose_name='User', + ), ), ( 'user', models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, - verbose_name='User' - ) + verbose_name='User', + ), ), ], options={ diff --git a/wger/measurements/migrations/0002_auto_20210722_1042.py b/wger/measurements/migrations/0002_auto_20210722_1042.py index 69a5dc7a0..865a2029e 100644 --- a/wger/measurements/migrations/0002_auto_20210722_1042.py +++ b/wger/measurements/migrations/0002_auto_20210722_1042.py @@ -4,7 +4,6 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ ('measurements', '0001_initial'), ] diff --git a/wger/measurements/models/category.py b/wger/measurements/models/category.py index 5e44e313a..d52144ef8 100644 --- a/wger/measurements/models/category.py +++ b/wger/measurements/models/category.py @@ -21,10 +21,9 @@ from django.utils.translation import gettext_lazy as _ class Category(models.Model): - class Meta: ordering = [ - "-name", + '-name', ] user = models.ForeignKey( diff --git a/wger/measurements/models/measurement.py b/wger/measurements/models/measurement.py index 5a181a307..dcecad700 100644 --- a/wger/measurements/models/measurement.py +++ b/wger/measurements/models/measurement.py @@ -31,11 +31,10 @@ from wger.measurements.models import Category class Measurement(models.Model): - class Meta: unique_together = ('date', 'category') ordering = [ - "-date", + '-date', ] category = models.ForeignKey( @@ -56,7 +55,7 @@ class Measurement(models.Model): validators=[ MinValueValidator(0), MaxValueValidator(5000), - ] + ], ) notes = models.CharField( diff --git a/wger/measurements/tests/test_generator.py b/wger/measurements/tests/test_generator.py index 3ec1acab0..4ef40ec0e 100644 --- a/wger/measurements/tests/test_generator.py +++ b/wger/measurements/tests/test_generator.py @@ -24,7 +24,6 @@ from wger.measurements.models import ( class MeasurementGeneratorTestCase(WgerTestCase): - def test_generator_categories(self): # Arrange Category.objects.all().delete() diff --git a/wger/nutrition/api/endpoints.py b/wger/nutrition/api/endpoints.py index 4e0fe8e49..3e7f8301e 100644 --- a/wger/nutrition/api/endpoints.py +++ b/wger/nutrition/api/endpoints.py @@ -1,2 +1,2 @@ -IMAGE_ENDPOINT = "ingredient-image" -INGREDIENTS_ENDPOINT = "ingredient" +IMAGE_ENDPOINT = 'ingredient-image' +INGREDIENTS_ENDPOINT = 'ingredient' diff --git a/wger/nutrition/api/filtersets.py b/wger/nutrition/api/filtersets.py index 35f22fa45..3e9a0d45a 100644 --- a/wger/nutrition/api/filtersets.py +++ b/wger/nutrition/api/filtersets.py @@ -9,7 +9,6 @@ from wger.nutrition.models import ( class LogItemFilterSet(filters.FilterSet): - class Meta: model = LogItem fields = { @@ -22,7 +21,6 @@ class LogItemFilterSet(filters.FilterSet): class IngredientFilterSet(filters.FilterSet): - class Meta: model = Ingredient fields = { diff --git a/wger/nutrition/api/serializers.py b/wger/nutrition/api/serializers.py index 450040366..2f8dffc30 100644 --- a/wger/nutrition/api/serializers.py +++ b/wger/nutrition/api/serializers.py @@ -203,6 +203,7 @@ class MealItemSerializer(serializers.ModelSerializer): """ MealItem serializer """ + meal = serializers.PrimaryKeyRelatedField(label='Nutrition plan', queryset=Meal.objects.all()) class Meta: @@ -267,6 +268,7 @@ class MealSerializer(serializers.ModelSerializer): """ Meal serializer """ + plan = serializers.PrimaryKeyRelatedField( label='Nutrition plan', queryset=NutritionPlan.objects.all(), @@ -281,6 +283,7 @@ class NutritionalValuesSerializer(serializers.Serializer): """ Nutritional values serializer """ + energy = serializers.FloatField() protein = serializers.FloatField() carbohydrates = serializers.FloatField() @@ -342,6 +345,7 @@ class NutritionPlanInfoSerializer(serializers.ModelSerializer): """ Nutritional plan info serializer """ + meals = MealInfoSerializer(source='meal_set', many=True) class Meta: diff --git a/wger/nutrition/api/views.py b/wger/nutrition/api/views.py index 77895c487..64b1fcfca 100644 --- a/wger/nutrition/api/views.py +++ b/wger/nutrition/api/views.py @@ -86,6 +86,7 @@ class IngredientViewSet(viewsets.ReadOnlyModelViewSet): API endpoint for ingredient objects. For a read-only endpoint with all the information of an ingredient, see /api/v2/ingredientinfo/ """ + serializer_class = IngredientSerializer ordering_fields = '__all__' filterset_class = IngredientFilterSet @@ -129,14 +130,13 @@ class IngredientViewSet(viewsets.ReadOnlyModelViewSet): 'fat_saturated': 0, 'fibres': 0, 'sodium': 0, - 'errors': [] + 'errors': [], } ingredient = self.get_object() form = UnitChooserForm(request.GET) if form.is_valid(): - # Create a temporary MealItem object if form.cleaned_data['unit']: unit_id = form.cleaned_data['unit'].id @@ -160,6 +160,7 @@ class IngredientInfoViewSet(IngredientViewSet): Read-only info API endpoint for ingredient objects. Returns nested data structures for more easy parsing. """ + serializer_class = IngredientInfoSerializer @@ -181,24 +182,21 @@ class IngredientInfoViewSet(IngredientViewSet): ), ], responses={ - 200: - inline_serializer( + 200: inline_serializer( name='IngredientSearchResponse', fields={ - 'value': - CharField(), - 'data': - inline_serializer( + 'value': CharField(), + 'data': inline_serializer( name='IngredientSearchItemResponse', fields={ 'id': IntegerField(), 'name': CharField(), 'category': CharField(), 'image': CharField(), - 'image_thumbnail': CharField() - } - ) - } + 'image_thumbnail': CharField(), + }, + ), + }, ) }, ) @@ -241,8 +239,8 @@ def search(request): 'id': ingredient.id, 'name': ingredient.name, 'image': image, - 'image_thumbnail': thumbnail - } + 'image_thumbnail': thumbnail, + }, } results.append(ingredient_json) json_response['suggestions'] = results @@ -254,6 +252,7 @@ class ImageViewSet(viewsets.ReadOnlyModelViewSet): """ API endpoint for ingredient images """ + queryset = Image.objects.all() serializer_class = IngredientImageSerializer ordering_fields = '__all__' @@ -268,6 +267,7 @@ class WeightUnitViewSet(viewsets.ReadOnlyModelViewSet): """ API endpoint for weight unit objects """ + queryset = WeightUnit.objects.all() serializer_class = WeightUnitSerializer ordering_fields = '__all__' @@ -278,6 +278,7 @@ class IngredientWeightUnitViewSet(viewsets.ReadOnlyModelViewSet): """ API endpoint for many-to-many table ingredient-weight unit objects """ + queryset = IngredientWeightUnit.objects.all() serializer_class = IngredientWeightUnitSerializer ordering_fields = '__all__' @@ -294,6 +295,7 @@ class NutritionPlanViewSet(viewsets.ModelViewSet): API endpoint for nutrition plan objects. For a read-only endpoint with all the information of nutritional plan(s), see /api/v2/nutritionplaninfo/ """ + serializer_class = NutritionPlanSerializer is_private = True ordering_fields = '__all__' @@ -308,7 +310,7 @@ class NutritionPlanViewSet(viewsets.ModelViewSet): Only allow access to appropriate objects """ # REST API generation - if getattr(self, "swagger_fake_view", False): + if getattr(self, 'swagger_fake_view', False): return NutritionPlan.objects.none() return NutritionPlan.objects.filter(user=self.request.user) @@ -335,6 +337,7 @@ class NutritionPlanInfoViewSet(NutritionPlanViewSet): Read-only info API endpoint for nutrition plan objects. Returns nested data structures for more easy parsing. """ + serializer_class = NutritionPlanInfoSerializer @@ -342,6 +345,7 @@ class MealViewSet(WgerOwnerObjectModelViewSet): """ API endpoint for meal objects """ + serializer_class = MealSerializer is_private = True ordering_fields = '__all__' @@ -356,7 +360,7 @@ class MealViewSet(WgerOwnerObjectModelViewSet): Only allow access to appropriate objects """ # REST API generation - if getattr(self, "swagger_fake_view", False): + if getattr(self, 'swagger_fake_view', False): return Meal.objects.none() return Meal.objects.filter(plan__user=self.request.user) @@ -386,6 +390,7 @@ class MealItemViewSet(WgerOwnerObjectModelViewSet): """ API endpoint for meal item objects """ + serializer_class = MealItemSerializer is_private = True ordering_fields = '__all__' @@ -402,7 +407,7 @@ class MealItemViewSet(WgerOwnerObjectModelViewSet): Only allow access to appropriate objects """ # REST API generation - if getattr(self, "swagger_fake_view", False): + if getattr(self, 'swagger_fake_view', False): return MealItem.objects.none() return MealItem.objects.filter(meal__plan__user=self.request.user) @@ -442,7 +447,7 @@ class LogItemViewSet(WgerOwnerObjectModelViewSet): Only allow access to appropriate objects """ # REST API generation - if getattr(self, "swagger_fake_view", False): + if getattr(self, 'swagger_fake_view', False): return LogItem.objects.none() return LogItem.objects.select_related('plan').filter(plan__user=self.request.user) diff --git a/wger/nutrition/apps.py b/wger/nutrition/apps.py index 62f4cbcf7..c82e8d2a5 100644 --- a/wger/nutrition/apps.py +++ b/wger/nutrition/apps.py @@ -20,7 +20,7 @@ from django.apps import AppConfig class NutritionConfig(AppConfig): name = 'wger.nutrition' - verbose_name = "Nutrition" + verbose_name = 'Nutrition' def ready(self): import wger.nutrition.signals diff --git a/wger/nutrition/consts.py b/wger/nutrition/consts.py index 12be31d3e..d5c4f2d95 100644 --- a/wger/nutrition/consts.py +++ b/wger/nutrition/consts.py @@ -18,18 +18,9 @@ MEALITEM_WEIGHT_GRAM = '1' MEALITEM_WEIGHT_UNIT = '2' ENERGY_FACTOR = { - 'protein': { - 'kg': 4, - 'lb': 113 - }, - 'carbohydrates': { - 'kg': 4, - 'lb': 113 - }, - 'fat': { - 'kg': 9, - 'lb': 225 - } + 'protein': {'kg': 4, 'lb': 113}, + 'carbohydrates': {'kg': 4, 'lb': 113}, + 'fat': {'kg': 9, 'lb': 225}, } """ Simple approximation of energy (kcal) provided per gram or ounce diff --git a/wger/nutrition/forms.py b/wger/nutrition/forms.py index b4b5c46e3..85e4df1c7 100644 --- a/wger/nutrition/forms.py +++ b/wger/nutrition/forms.py @@ -57,14 +57,15 @@ class UnitChooserForm(forms.Form): """ A small form to select an amount and a unit for an ingredient """ + amount = forms.DecimalField( - decimal_places=2, label=gettext_lazy("Amount"), max_digits=5, localize=True + decimal_places=2, label=gettext_lazy('Amount'), max_digits=5, localize=True ) unit = forms.ModelChoiceField( queryset=IngredientWeightUnit.objects.none(), - label=gettext_lazy("Unit"), - empty_label="g", - required=False + label=gettext_lazy('Unit'), + empty_label='g', + required=False, ) def __init__(self, *args, **kwargs): @@ -88,7 +89,7 @@ class UnitChooserForm(forms.Form): Row( Column('amount', css_class='col-6'), Column('unit', css_class='col-6'), - css_class='form-row' + css_class='form-row', ) ) self.helper.form_tag = False @@ -106,16 +107,18 @@ class BmiForm(forms.ModelForm): class Meta: model = UserProfile - fields = ('height', ) + fields = ('height',) def __init__(self, *args, **kwargs): super(BmiForm, self).__init__(*args, **kwargs) if 'initial' in kwargs: # if the form is rendering for the first time - self['height'].label = _('Height (cm)' - ) if kwargs['initial']['use_metric'] else _('Height (in)') - self['weight'].label = _('Weight (kg)' - ) if kwargs['initial']['use_metric'] else _('Weight (lbs)') + self['height'].label = ( + _('Height (cm)') if kwargs['initial']['use_metric'] else _('Height (in)') + ) + self['weight'].label = ( + _('Weight (kg)') if kwargs['initial']['use_metric'] else _('Weight (lbs)') + ) self.helper = FormHelper() self.helper.form_action = reverse('nutrition:bmi:calculate') @@ -125,8 +128,9 @@ class BmiForm(forms.ModelForm): Row( Column('height', css_class='col-6'), Column('weight', css_class='col-6'), - css_class='form-row' - ), ButtonHolder(Submit('submit', _("Calculate"), css_class='btn-success')) + css_class='form-row', + ), + ButtonHolder(Submit('submit', _('Calculate'), css_class='btn-success')), ) @@ -134,6 +138,7 @@ class BmrForm(forms.ModelForm): """ Form for the basal metabolic rate """ + weight = forms.DecimalField(widget=Html5NumberInput()) class Meta: @@ -144,10 +149,10 @@ class BmrForm(forms.ModelForm): super(BmrForm, self).__init__(*args, **kwargs) self.helper = FormHelper() self.helper.layout = Layout( - "age", - "height", - "gender", - "weight", + 'age', + 'height', + 'gender', + 'weight', ) self.helper.form_tag = False @@ -173,22 +178,22 @@ class PhysicalActivitiesForm(forms.ModelForm): super(PhysicalActivitiesForm, self).__init__(*args, **kwargs) self.helper = FormHelper() self.helper.layout = Layout( - "sleep_hours", + 'sleep_hours', Row( Column('work_hours', css_class='col-6'), Column('work_intensity', css_class='col-6'), - css_class='form-row' + css_class='form-row', ), Row( Column('sport_hours', css_class='col-6'), Column('sport_intensity', css_class='col-6'), - css_class='form-row' + css_class='form-row', ), Row( Column('freetime_hours', css_class='col-6'), Column('freetime_intensity', css_class='col-6'), - css_class='form-row' - ) + css_class='form-row', + ), ) self.helper.form_tag = False @@ -200,10 +205,9 @@ class DailyCaloriesForm(forms.ModelForm): base_calories = forms.IntegerField( label=_('Basic caloric intake'), - help_text=_('Your basic caloric intake as calculated for ' - 'your data'), + help_text=_('Your basic caloric intake as calculated for ' 'your data'), required=False, - widget=Html5NumberInput() + widget=Html5NumberInput(), ) additional_calories = forms.IntegerField( label=_('Additional calories'), @@ -214,12 +218,12 @@ class DailyCaloriesForm(forms.ModelForm): ), initial=0, required=False, - widget=Html5NumberInput() + widget=Html5NumberInput(), ) class Meta: model = UserProfile - fields = ('calories', ) + fields = ('calories',) def __init__(self, *args, **kwargs): super(DailyCaloriesForm, self).__init__(*args, **kwargs) @@ -231,7 +235,7 @@ class DailyCaloriesForm(forms.ModelForm): class MealItemForm(forms.ModelForm): weight_unit = forms.ModelChoiceField( queryset=IngredientWeightUnit.objects.none(), - empty_label="g", + empty_label='g', required=False, ) ingredient = forms.ModelChoiceField( @@ -241,11 +245,11 @@ class MealItemForm(forms.ModelForm): ingredient_searchfield = forms.CharField( required=False, - label=gettext_lazy("Ingredient"), + label=gettext_lazy('Ingredient'), ) english_results = BooleanField( - label=gettext_lazy("Also search for names in English"), + label=gettext_lazy('Also search for names in English'), initial=True, required=False, ) @@ -273,18 +277,21 @@ class MealItemForm(forms.ModelForm): # Filter the available ingredients if ingredient_id: - self.fields['weight_unit'].queryset = \ - IngredientWeightUnit.objects.filter(ingredient_id=ingredient_id) + self.fields['weight_unit'].queryset = IngredientWeightUnit.objects.filter( + ingredient_id=ingredient_id + ) self.helper = FormHelper() self.helper.layout = Layout( - 'ingredient', 'ingredient_searchfield', 'english_results', + 'ingredient', + 'ingredient_searchfield', + 'english_results', HTML('
'), Row( Column('amount', css_class='col-6'), Column('weight_unit', css_class='col-6'), - css_class='form-row' - ) + css_class='form-row', + ), ) @@ -295,13 +302,9 @@ class MealLogItemForm(MealItemForm): datetime = forms.DateTimeField( input_formats=[datetime_format], widget=forms.DateTimeInput( - attrs={ - 'type': 'datetime-local', - 'class': 'form-control', - 'value': now - }, + attrs={'type': 'datetime-local', 'class': 'form-control', 'value': now}, format=datetime_format, - ) + ), ) class Meta: @@ -317,16 +320,18 @@ class MealLogItemForm(MealItemForm): super(MealLogItemForm, self).__init__(*args, **kwargs) self.helper.layout = Layout( - 'ingredient', 'ingredient_searchfield', 'english_results', + 'ingredient', + 'ingredient_searchfield', + 'english_results', Row( Column('amount', css_class='col-6'), Column('weight_unit', css_class='col-6'), - ), Row(Column('datetime', css_class='col-6'), css_class='form-row') + ), + Row(Column('datetime', css_class='col-6'), css_class='form-row'), ) class IngredientForm(forms.ModelForm): - class Meta: model = Ingredient fields = [ @@ -352,25 +357,25 @@ class IngredientForm(forms.ModelForm): Row( Column('name', css_class='col-6'), Column('brand', css_class='col-6'), - css_class='form-row' + css_class='form-row', ), 'energy', 'protein', Row( Column('carbohydrates', css_class='col-6'), Column('carbohydrates_sugar', css_class='col-6'), - css_class='form-row' + css_class='form-row', ), Row( Column('fat', css_class='col-6'), Column('fat_saturated', css_class='col-6'), - css_class='form-row' + css_class='form-row', ), 'fibres', 'sodium', Row( Column('license', css_class='col-6'), Column('license_author', css_class='col-6'), - css_class='form-row' + css_class='form-row', ), ) diff --git a/wger/nutrition/helpers.py b/wger/nutrition/helpers.py index 09b4f68e8..39d3879d4 100644 --- a/wger/nutrition/helpers.py +++ b/wger/nutrition/helpers.py @@ -61,7 +61,7 @@ class BaseMealItem: if self.get_unit_type() == MEALITEM_WEIGHT_GRAM: item_weight = self.amount else: - item_weight = (self.amount * self.weight_unit.amount * self.weight_unit.gram) + item_weight = self.amount * self.weight_unit.amount * self.weight_unit.gram values.energy = self.ingredient.energy * item_weight / 100 values.protein = self.ingredient.protein * item_weight / 100 @@ -125,16 +125,19 @@ class NutritionalValues: energy=self.energy + other.energy, protein=self.protein + other.protein, carbohydrates=self.carbohydrates + other.carbohydrates, - carbohydrates_sugar=self.carbohydrates_sugar + - other.carbohydrates_sugar if self.carbohydrates_sugar and other.carbohydrates_sugar else - self.carbohydrates_sugar or other.carbohydrates_sugar, + carbohydrates_sugar=self.carbohydrates_sugar + other.carbohydrates_sugar + if self.carbohydrates_sugar and other.carbohydrates_sugar + else self.carbohydrates_sugar or other.carbohydrates_sugar, fat=self.fat + other.fat, - fat_saturated=self.fat_saturated + other.fat_saturated if self.fat_saturated - and other.fat_saturated else self.fat_saturated or other.fat_saturated, - fibres=self.fibres + - other.fibres if self.fibres and other.fibres else self.fibres or other.fibres, - sodium=self.sodium + - other.sodium if self.sodium and other.sodium else self.sodium or other.sodium, + fat_saturated=self.fat_saturated + other.fat_saturated + if self.fat_saturated and other.fat_saturated + else self.fat_saturated or other.fat_saturated, + fibres=self.fibres + other.fibres + if self.fibres and other.fibres + else self.fibres or other.fibres, + sodium=self.sodium + other.sodium + if self.sodium and other.sodium + else self.sodium or other.sodium, ) @property diff --git a/wger/nutrition/management/commands/download-ingredient-images.py b/wger/nutrition/management/commands/download-ingredient-images.py index 32cc87b6b..1c6cd7add 100644 --- a/wger/nutrition/management/commands/download-ingredient-images.py +++ b/wger/nutrition/management/commands/download-ingredient-images.py @@ -52,11 +52,10 @@ class Command(BaseCommand): dest='remote_url', default=settings.WGER_SETTINGS['WGER_INSTANCE'], help=f'Remote URL to fetch the ingredients from (default: WGER_SETTINGS' - f'["WGER_INSTANCE"] - {settings.WGER_SETTINGS["WGER_INSTANCE"]})' + f'["WGER_INSTANCE"] - {settings.WGER_SETTINGS["WGER_INSTANCE"]})', ) def handle(self, **options): - if not settings.MEDIA_ROOT: raise ImproperlyConfigured('Please set MEDIA_ROOT in your settings file') diff --git a/wger/nutrition/management/commands/dummy-generator-nutrition.py b/wger/nutrition/management/commands/dummy-generator-nutrition.py index 97a613bf4..61eccc4bd 100644 --- a/wger/nutrition/management/commands/dummy-generator-nutrition.py +++ b/wger/nutrition/management/commands/dummy-generator-nutrition.py @@ -47,14 +47,13 @@ class Command(BaseCommand): help = 'Dummy generator for nutritional plans' def add_arguments(self, parser): - parser.add_argument( '--plans', action='store', default=10, dest='nr_plans', type=int, - help='The number of nutritional plans to create per user (default: 10)' + help='The number of nutritional plans to create per user (default: 10)', ) parser.add_argument( '--diary-entries', @@ -62,7 +61,7 @@ class Command(BaseCommand): default=20, dest='nr_diary_entries', type=int, - help='The number of nutrition logs to create per day (default: 20)' + help='The number of nutrition logs to create per day (default: 20)', ) parser.add_argument( '--diary-dates', @@ -83,8 +82,9 @@ class Command(BaseCommand): def handle(self, **options): self.stdout.write(f"** Generating {options['nr_plans']} dummy nutritional plan(s) per user") - users = [User.objects.get(pk=options['user_id']) - ] if options['user_id'] else User.objects.all() + users = ( + [User.objects.get(pk=options['user_id'])] if options['user_id'] else User.objects.all() + ) ingredients = [i for i in Ingredient.objects.order_by('?').all()[:100]] meals_per_plan = 4 @@ -99,7 +99,7 @@ class Command(BaseCommand): plan = NutritionPlan( description=f'Dummy nutritional plan - {uid[1]}', creation_date=start_date, - user=user + user=user, ) plan.save() @@ -112,7 +112,7 @@ class Command(BaseCommand): meal = Meal( plan=plan, order=order, - time=datetime.time(hour=randint(0, 23), minute=randint(0, 59)) + time=datetime.time(hour=randint(0, 23), minute=randint(0, 59)), ) meal.save() @@ -123,7 +123,7 @@ class Command(BaseCommand): ingredient=choice(ingredients), weight_unit=None, order=order, - amount=randint(10, 250) + amount=randint(10, 250), ) meal_item.save() order = order + 1 @@ -141,7 +141,7 @@ class Command(BaseCommand): datetime=date, ingredient=choice(ingredients), weight_unit=None, - amount=randint(10, 300) + amount=randint(10, 300), ) diary_entries.append(log) diff --git a/wger/nutrition/management/commands/import-off-products.py b/wger/nutrition/management/commands/import-off-products.py index 6d82b8a1c..06397f26d 100644 --- a/wger/nutrition/management/commands/import-off-products.py +++ b/wger/nutrition/management/commands/import-off-products.py @@ -43,6 +43,7 @@ class Command(BaseCommand): """ Import an Open Food facts Dump """ + mode = Mode.UPDATE bulk_size = 500 completeness = 0.7 @@ -58,7 +59,7 @@ class Command(BaseCommand): type=str, help='Script mode, "insert" or "update". Insert will insert the ingredients as new ' 'entries in the database, while update will try to update them if they are ' - 'already present. Deault: insert' + 'already present. Deault: insert', ) parser.add_argument( '--completeness', @@ -67,11 +68,10 @@ class Command(BaseCommand): dest='completeness', type=float, help='Completeness threshold for importing the products. Products in OFF have ' - 'completeness score that ranges from 0 to 1.1. Default: 0.7' + 'completeness score that ranges from 0 to 1.1. Default: 0.7', ) def handle(self, **options): - try: # Third Party from pymongo import MongoClient @@ -101,16 +101,8 @@ class Command(BaseCommand): counter = Counter() for product in db.products.find( - { - 'lang': { - "$in": list(languages.keys()) - }, - 'completeness': { - "$gt": self.completeness - } - } + {'lang': {'$in': list(languages.keys())}, 'completeness': {'$gt': self.completeness}} ): - try: ingredient_data = extract_info_from_off(product, languages[product['lang']]) except KeyError as e: @@ -167,7 +159,6 @@ class Command(BaseCommand): # Update existing entries else: try: - # Update an existing product (look-up key is the code) or create a new # one. While this might not be the most efficient query (there will always # be a SELECT first), it's ok because this script is run very rarely. diff --git a/wger/nutrition/management/commands/sync-ingredients.py b/wger/nutrition/management/commands/sync-ingredients.py index f149607a1..4f4a92fa8 100644 --- a/wger/nutrition/management/commands/sync-ingredients.py +++ b/wger/nutrition/management/commands/sync-ingredients.py @@ -38,6 +38,7 @@ class Command(BaseCommand): """ Synchronizes ingredient data from a wger instance to the local database """ + remote_url = settings.WGER_SETTINGS['WGER_INSTANCE'] help = """Synchronizes ingredient data from a wger instance to the local database""" @@ -49,7 +50,7 @@ class Command(BaseCommand): dest='remote_url', default=settings.WGER_SETTINGS['WGER_INSTANCE'], help=f'Remote URL to fetch the ingredients from (default: WGER_SETTINGS' - f'["WGER_INSTANCE"] - {settings.WGER_SETTINGS["WGER_INSTANCE"]})' + f'["WGER_INSTANCE"] - {settings.WGER_SETTINGS["WGER_INSTANCE"]})', ) def handle(self, **options): diff --git a/wger/nutrition/migrations/0001_initial.py b/wger/nutrition/migrations/0001_initial.py index 620b74ecf..d2e5cb17e 100644 --- a/wger/nutrition/migrations/0001_initial.py +++ b/wger/nutrition/migrations/0001_initial.py @@ -7,7 +7,6 @@ import django.core.validators class Migration(migrations.Migration): - dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), ('core', '0001_initial'), @@ -21,18 +20,17 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ( 'license_author', models.CharField( - help_text= - 'If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', + help_text='If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', max_length=50, null=True, verbose_name='Author', - blank=True - ) + blank=True, + ), ), ( 'status', @@ -41,17 +39,20 @@ class Migration(migrations.Migration): max_length=2, editable=False, choices=[ - (b'1', 'Pending'), (b'2', 'Accepted'), (b'3', 'Declined'), - (b'4', 'Submitted by administrator'), (b'5', 'System ingredient') - ] - ) + (b'1', 'Pending'), + (b'2', 'Accepted'), + (b'3', 'Declined'), + (b'4', 'Submitted by administrator'), + (b'5', 'System ingredient'), + ], + ), ), ('creation_date', models.DateField(auto_now_add=True, verbose_name='Date')), ('update_date', models.DateField(auto_now=True, verbose_name='Date')), ('name', models.CharField(max_length=200, verbose_name='Name')), ( 'energy', - models.IntegerField(help_text='In kcal per 100g', verbose_name='Energy') + models.IntegerField(help_text='In kcal per 100g', verbose_name='Energy'), ), ( 'protein', @@ -62,9 +63,9 @@ class Migration(migrations.Migration): decimal_places=3, validators=[ django.core.validators.MinValueValidator(0), - django.core.validators.MaxValueValidator(100) - ] - ) + django.core.validators.MaxValueValidator(100), + ], + ), ), ( 'carbohydrates', @@ -75,9 +76,9 @@ class Migration(migrations.Migration): decimal_places=3, validators=[ django.core.validators.MinValueValidator(0), - django.core.validators.MaxValueValidator(100) - ] - ) + django.core.validators.MaxValueValidator(100), + ], + ), ), ( 'carbohydrates_sugar', @@ -85,14 +86,14 @@ class Migration(migrations.Migration): decimal_places=3, validators=[ django.core.validators.MinValueValidator(0), - django.core.validators.MaxValueValidator(100) + django.core.validators.MaxValueValidator(100), ], max_digits=6, blank=True, help_text='In g per 100g of product', null=True, - verbose_name='Sugar content in carbohydrates' - ) + verbose_name='Sugar content in carbohydrates', + ), ), ( 'fat', @@ -103,9 +104,9 @@ class Migration(migrations.Migration): decimal_places=3, validators=[ django.core.validators.MinValueValidator(0), - django.core.validators.MaxValueValidator(100) - ] - ) + django.core.validators.MaxValueValidator(100), + ], + ), ), ( 'fat_saturated', @@ -113,14 +114,14 @@ class Migration(migrations.Migration): decimal_places=3, validators=[ django.core.validators.MinValueValidator(0), - django.core.validators.MaxValueValidator(100) + django.core.validators.MaxValueValidator(100), ], max_digits=6, blank=True, help_text='In g per 100g of product', null=True, - verbose_name='Saturated fat content in fats' - ) + verbose_name='Saturated fat content in fats', + ), ), ( 'fibres', @@ -128,14 +129,14 @@ class Migration(migrations.Migration): decimal_places=3, validators=[ django.core.validators.MinValueValidator(0), - django.core.validators.MaxValueValidator(100) + django.core.validators.MaxValueValidator(100), ], max_digits=6, blank=True, help_text='In g per 100g of product', null=True, - verbose_name='Fibres' - ) + verbose_name='Fibres', + ), ), ( 'sodium', @@ -143,14 +144,14 @@ class Migration(migrations.Migration): decimal_places=3, validators=[ django.core.validators.MinValueValidator(0), - django.core.validators.MaxValueValidator(100) + django.core.validators.MaxValueValidator(100), ], max_digits=6, blank=True, help_text='In g per 100g of product', null=True, - verbose_name='Sodium' - ) + verbose_name='Sodium', + ), ), ( 'language', @@ -158,8 +159,8 @@ class Migration(migrations.Migration): editable=False, to='core.Language', verbose_name='Language', - on_delete=models.CASCADE - ) + on_delete=models.CASCADE, + ), ), ( 'license', @@ -167,8 +168,8 @@ class Migration(migrations.Migration): default=2, verbose_name='License', to='core.License', - on_delete=models.CASCADE - ) + on_delete=models.CASCADE, + ), ), ( 'user', @@ -178,14 +179,14 @@ class Migration(migrations.Migration): to=settings.AUTH_USER_MODEL, null=True, verbose_name='User', - on_delete=models.CASCADE - ) + on_delete=models.CASCADE, + ), ), ], options={ 'ordering': ['name'], }, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.CreateModel( name='IngredientWeightUnit', @@ -194,7 +195,7 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ('gram', models.IntegerField(verbose_name='Amount in grams')), ( @@ -204,8 +205,8 @@ class Migration(migrations.Migration): help_text='Unit amount, e.g. "1 Cup" or "1/2 spoon"', verbose_name='Amount', max_digits=5, - decimal_places=2 - ) + decimal_places=2, + ), ), ( 'ingredient', @@ -213,12 +214,12 @@ class Migration(migrations.Migration): editable=False, to='nutrition.Ingredient', verbose_name='Ingredient', - on_delete=models.CASCADE - ) + on_delete=models.CASCADE, + ), ), ], options={}, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.CreateModel( name='Meal', @@ -227,25 +228,25 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ( 'order', models.IntegerField( verbose_name='Order', max_length=1, editable=False, blank=True - ) + ), ), ( 'time', wger.utils.fields.Html5TimeField( null=True, verbose_name='Time (approx)', blank=True - ) + ), ), ], options={ 'ordering': ['time'], }, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.CreateModel( name='MealItem', @@ -254,13 +255,13 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ( 'order', models.IntegerField( verbose_name='Order', max_length=1, editable=False, blank=True - ) + ), ), ( 'amount', @@ -270,17 +271,17 @@ class Migration(migrations.Migration): decimal_places=2, validators=[ django.core.validators.MinValueValidator(1), - django.core.validators.MaxValueValidator(1000) - ] - ) + django.core.validators.MaxValueValidator(1000), + ], + ), ), ( 'ingredient', models.ForeignKey( verbose_name='Ingredient', to='nutrition.Ingredient', - on_delete=models.CASCADE - ) + on_delete=models.CASCADE, + ), ), ( 'meal', @@ -288,8 +289,8 @@ class Migration(migrations.Migration): editable=False, to='nutrition.Meal', verbose_name='Nutrition plan', - on_delete=models.CASCADE - ) + on_delete=models.CASCADE, + ), ), ( 'weight_unit', @@ -298,12 +299,12 @@ class Migration(migrations.Migration): blank=True, to='nutrition.IngredientWeightUnit', null=True, - on_delete=models.CASCADE - ) + on_delete=models.CASCADE, + ), ), ], options={}, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.CreateModel( name='NutritionPlan', @@ -312,30 +313,28 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ( 'creation_date', - models.DateField(auto_now_add=True, verbose_name='Creation date') + models.DateField(auto_now_add=True, verbose_name='Creation date'), ), ( 'description', models.TextField( - help_text= - 'A description of the goal of the plan, e.g. "Gain mass" or "Prepare for summer"', + help_text='A description of the goal of the plan, e.g. "Gain mass" or "Prepare for summer"', max_length=2000, verbose_name='Description', - blank=True - ) + blank=True, + ), ), ( 'has_goal_calories', models.BooleanField( default=False, - help_text= - 'Tick the box if you want to mark this plan as having a goal amount of calories. You can use the calculator or enter the value yourself.', - verbose_name='Use daily calories' - ) + help_text='Tick the box if you want to mark this plan as having a goal amount of calories. You can use the calculator or enter the value yourself.', + verbose_name='Use daily calories', + ), ), ( 'language', @@ -343,8 +342,8 @@ class Migration(migrations.Migration): editable=False, to='core.Language', verbose_name='Language', - on_delete=models.CASCADE - ) + on_delete=models.CASCADE, + ), ), ( 'user', @@ -352,14 +351,14 @@ class Migration(migrations.Migration): editable=False, to=settings.AUTH_USER_MODEL, verbose_name='User', - on_delete=models.CASCADE - ) + on_delete=models.CASCADE, + ), ), ], options={ 'ordering': ['-creation_date'], }, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.CreateModel( name='WeightUnit', @@ -368,7 +367,7 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ('name', models.CharField(max_length=200, verbose_name='Name')), ( @@ -377,14 +376,14 @@ class Migration(migrations.Migration): editable=False, to='core.Language', verbose_name='Language', - on_delete=models.CASCADE - ) + on_delete=models.CASCADE, + ), ), ], options={ 'ordering': ['name'], }, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.AddField( model_name='meal', @@ -393,7 +392,7 @@ class Migration(migrations.Migration): editable=False, to='nutrition.NutritionPlan', verbose_name='Nutrition plan', - on_delete=models.CASCADE + on_delete=models.CASCADE, ), preserve_default=True, ), diff --git a/wger/nutrition/migrations/0002_auto_20170101_1538.py b/wger/nutrition/migrations/0002_auto_20170101_1538.py index 5e83a33ce..c01d25bf7 100644 --- a/wger/nutrition/migrations/0002_auto_20170101_1538.py +++ b/wger/nutrition/migrations/0002_auto_20170101_1538.py @@ -8,7 +8,7 @@ def copy_username(apps, schema_editor): """ Copies the exercise name to the original name field """ - Ingredient = apps.get_model("nutrition", "Ingredient") + Ingredient = apps.get_model('nutrition', 'Ingredient') for ingredient in Ingredient.objects.all(): if ingredient.user: ingredient.license_author = ingredient.user.username @@ -21,12 +21,11 @@ def update_status(apps, schema_editor): """ Updates the status of the ingredients """ - Ingredient = apps.get_model("nutrition", "Ingredient") + Ingredient = apps.get_model('nutrition', 'Ingredient') Ingredient.objects.filter(status__in=('5', '4')).update(status=2) class Migration(migrations.Migration): - dependencies = [ ('nutrition', '0001_initial'), ] @@ -51,7 +50,7 @@ class Migration(migrations.Migration): choices=[('1', 'Pending'), ('2', 'Accepted'), ('3', 'Declined')], default='1', editable=False, - max_length=2 + max_length=2, ), ), ] diff --git a/wger/nutrition/migrations/0003_auto_20170118_2308.py b/wger/nutrition/migrations/0003_auto_20170118_2308.py index c3017648b..25da3673b 100644 --- a/wger/nutrition/migrations/0003_auto_20170118_2308.py +++ b/wger/nutrition/migrations/0003_auto_20170118_2308.py @@ -5,7 +5,6 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ ('nutrition', '0002_auto_20170101_1538'), ] diff --git a/wger/nutrition/migrations/0004_auto_20200819_2310.py b/wger/nutrition/migrations/0004_auto_20200819_2310.py index 0b442fb6f..25cfaaee5 100644 --- a/wger/nutrition/migrations/0004_auto_20200819_2310.py +++ b/wger/nutrition/migrations/0004_auto_20200819_2310.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('nutrition', '0003_auto_20170118_2308'), ] @@ -15,10 +14,9 @@ class Migration(migrations.Migration): name='description', field=models.CharField( blank=True, - help_text= - 'A description of the goal of the plan, e.g. "Gain mass" or "Prepare for summer"', + help_text='A description of the goal of the plan, e.g. "Gain mass" or "Prepare for summer"', max_length=80, - verbose_name='Description' + verbose_name='Description', ), ), ] diff --git a/wger/nutrition/migrations/0005_logitem.py b/wger/nutrition/migrations/0005_logitem.py index efce826d6..699f93230 100644 --- a/wger/nutrition/migrations/0005_logitem.py +++ b/wger/nutrition/migrations/0005_logitem.py @@ -7,7 +7,6 @@ import wger.nutrition.models class Migration(migrations.Migration): - dependencies = [ ('nutrition', '0004_auto_20200819_2310'), ] @@ -20,7 +19,7 @@ class Migration(migrations.Migration): 'id', models.AutoField( auto_created=True, primary_key=True, serialize=False, verbose_name='ID' - ) + ), ), ('datetime', models.DateTimeField(auto_now=True)), ('comment', models.TextField(blank=True, null=True, verbose_name='Comment')), @@ -31,18 +30,18 @@ class Migration(migrations.Migration): max_digits=6, validators=[ django.core.validators.MinValueValidator(1), - django.core.validators.MaxValueValidator(1000) + django.core.validators.MaxValueValidator(1000), ], - verbose_name='Amount' - ) + verbose_name='Amount', + ), ), ( 'ingredient', models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, to='nutrition.ingredient', - verbose_name='Ingredient' - ) + verbose_name='Ingredient', + ), ), ( 'plan', @@ -50,8 +49,8 @@ class Migration(migrations.Migration): editable=False, on_delete=django.db.models.deletion.CASCADE, to='nutrition.nutritionplan', - verbose_name='Nutrition plan' - ) + verbose_name='Nutrition plan', + ), ), ( 'weight_unit', @@ -60,8 +59,8 @@ class Migration(migrations.Migration): null=True, on_delete=django.db.models.deletion.CASCADE, to='nutrition.ingredientweightunit', - verbose_name='Weight unit' - ) + verbose_name='Weight unit', + ), ), ], options={ diff --git a/wger/nutrition/migrations/0006_auto_20201201_0653.py b/wger/nutrition/migrations/0006_auto_20201201_0653.py index a51792faf..f7928766d 100644 --- a/wger/nutrition/migrations/0006_auto_20201201_0653.py +++ b/wger/nutrition/migrations/0006_auto_20201201_0653.py @@ -5,7 +5,6 @@ import django.utils.timezone class Migration(migrations.Migration): - dependencies = [ ('nutrition', '0005_logitem'), ] diff --git a/wger/nutrition/migrations/0007_auto_20201214_0013.py b/wger/nutrition/migrations/0007_auto_20201214_0013.py index dff82f3db..e0ec94837 100644 --- a/wger/nutrition/migrations/0007_auto_20201214_0013.py +++ b/wger/nutrition/migrations/0007_auto_20201214_0013.py @@ -6,7 +6,6 @@ import django.db.models.deletion class Migration(migrations.Migration): - dependencies = [ ('nutrition', '0006_auto_20201201_0653'), ] @@ -19,7 +18,7 @@ class Migration(migrations.Migration): 'id', models.AutoField( auto_created=True, primary_key=True, serialize=False, verbose_name='ID' - ) + ), ), ('name', models.CharField(max_length=100, verbose_name='Name')), ], @@ -72,7 +71,7 @@ class Migration(migrations.Migration): field=models.CharField( max_length=200, validators=[django.core.validators.MinLengthValidator(3)], - verbose_name='Name' + verbose_name='Name', ), ), migrations.AddField( @@ -83,7 +82,7 @@ class Migration(migrations.Migration): null=True, on_delete=django.db.models.deletion.CASCADE, to='nutrition.ingredientcategory', - verbose_name='Category' + verbose_name='Category', ), ), ] diff --git a/wger/nutrition/migrations/0008_auto_20210102_1446.py b/wger/nutrition/migrations/0008_auto_20210102_1446.py index 3eba29e55..5fb3cb2b8 100644 --- a/wger/nutrition/migrations/0008_auto_20210102_1446.py +++ b/wger/nutrition/migrations/0008_auto_20210102_1446.py @@ -5,7 +5,6 @@ import django.db.models.deletion class Migration(migrations.Migration): - dependencies = [ ('nutrition', '0007_auto_20201214_0013'), ] @@ -32,7 +31,7 @@ class Migration(migrations.Migration): field=models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, to='nutrition.nutritionplan', - verbose_name='Nutrition plan' + verbose_name='Nutrition plan', ), ), ] diff --git a/wger/nutrition/migrations/0009_meal_name.py b/wger/nutrition/migrations/0009_meal_name.py index 9dddcefb4..26d0c57b5 100644 --- a/wger/nutrition/migrations/0009_meal_name.py +++ b/wger/nutrition/migrations/0009_meal_name.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('nutrition', '0008_auto_20210102_1446'), ] @@ -15,10 +14,9 @@ class Migration(migrations.Migration): name='name', field=models.CharField( blank=True, - help_text= - 'Give meals a textual description / name such as "Breakfast" or "after workout"', + help_text='Give meals a textual description / name such as "Breakfast" or "after workout"', max_length=25, - verbose_name='Name' + verbose_name='Name', ), ), ] diff --git a/wger/nutrition/migrations/0010_logitem_meal.py b/wger/nutrition/migrations/0010_logitem_meal.py index f0c35c6d0..545043b93 100644 --- a/wger/nutrition/migrations/0010_logitem_meal.py +++ b/wger/nutrition/migrations/0010_logitem_meal.py @@ -5,7 +5,6 @@ import django.db.models.deletion class Migration(migrations.Migration): - dependencies = [ ('nutrition', '0009_meal_name'), ] @@ -20,7 +19,7 @@ class Migration(migrations.Migration): on_delete=django.db.models.deletion.CASCADE, related_name='log_items', to='nutrition.meal', - verbose_name='Meal' + verbose_name='Meal', ), ), ] diff --git a/wger/nutrition/migrations/0011_alter_logitem_datetime.py b/wger/nutrition/migrations/0011_alter_logitem_datetime.py index 8733272c9..1f7f7654f 100644 --- a/wger/nutrition/migrations/0011_alter_logitem_datetime.py +++ b/wger/nutrition/migrations/0011_alter_logitem_datetime.py @@ -5,7 +5,6 @@ import django.utils.timezone class Migration(migrations.Migration): - dependencies = [ ('nutrition', '0010_logitem_meal'), ] diff --git a/wger/nutrition/migrations/0012_alter_ingredient_license_author.py b/wger/nutrition/migrations/0012_alter_ingredient_license_author.py index 4b777e802..5e02a3ac4 100644 --- a/wger/nutrition/migrations/0012_alter_ingredient_license_author.py +++ b/wger/nutrition/migrations/0012_alter_ingredient_license_author.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('nutrition', '0011_alter_logitem_datetime'), ] @@ -15,11 +14,10 @@ class Migration(migrations.Migration): name='license_author', field=models.CharField( blank=True, - help_text= - 'If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', + help_text='If you are not the author, enter the name or source here. This is needed for some licenses e.g. the CC-BY-SA.', max_length=60, null=True, - verbose_name='Author' + verbose_name='Author', ), ), ] diff --git a/wger/nutrition/migrations/0013_ingredient_image.py b/wger/nutrition/migrations/0013_ingredient_image.py index 14aa79ab2..17adbd26f 100644 --- a/wger/nutrition/migrations/0013_ingredient_image.py +++ b/wger/nutrition/migrations/0013_ingredient_image.py @@ -18,10 +18,10 @@ def generate_uuids(apps, schema_editor): :param schema_editor: :return: """ - Ingredient = apps.get_model("nutrition", "Ingredient") + Ingredient = apps.get_model('nutrition', 'Ingredient') for ingredient in Ingredient.objects.all(): ingredient.uuid = uuid.uuid4() - ingredient.save(update_fields=["uuid"]) + ingredient.save(update_fields=['uuid']) class Migration(migrations.Migration): @@ -50,7 +50,7 @@ class Migration(migrations.Migration): primary_key=True, serialize=False, verbose_name='ID', - ) + ), ), ( 'license_author', @@ -61,7 +61,7 @@ class Migration(migrations.Migration): max_length=60, null=True, verbose_name='Author', - ) + ), ), ( 'uuid', @@ -70,7 +70,7 @@ class Migration(migrations.Migration): editable=False, unique=True, verbose_name='UUID', - ) + ), ), ( 'image', @@ -80,7 +80,7 @@ class Migration(migrations.Migration): verbose_name='Image', height_field='height', width_field='width', - ) + ), ), ('created', models.DateTimeField(auto_now_add=True)), ('last_update', models.DateTimeField(auto_now=True)), @@ -92,8 +92,8 @@ class Migration(migrations.Migration): models.OneToOneField( null=True, on_delete=django.db.models.deletion.CASCADE, - to='nutrition.ingredient' - ) + to='nutrition.ingredient', + ), ), ( 'license', @@ -101,8 +101,8 @@ class Migration(migrations.Migration): default=2, on_delete=django.db.models.deletion.CASCADE, to='core.license', - verbose_name='License' - ) + verbose_name='License', + ), ), ], options={ @@ -120,5 +120,5 @@ class Migration(migrations.Migration): unique=True, verbose_name='UUID', ), - ) + ), ] diff --git a/wger/nutrition/migrations/0015_alter_ingredient_creation_date_and_more.py b/wger/nutrition/migrations/0015_alter_ingredient_creation_date_and_more.py index bea952636..edcab8884 100644 --- a/wger/nutrition/migrations/0015_alter_ingredient_creation_date_and_more.py +++ b/wger/nutrition/migrations/0015_alter_ingredient_creation_date_and_more.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('nutrition', '0014_license_information'), ] diff --git a/wger/nutrition/migrations/0017_remove_nutritionplan_language_alter_logitem_meal.py b/wger/nutrition/migrations/0017_remove_nutritionplan_language_alter_logitem_meal.py index 4d2e51820..b935be585 100644 --- a/wger/nutrition/migrations/0017_remove_nutritionplan_language_alter_logitem_meal.py +++ b/wger/nutrition/migrations/0017_remove_nutritionplan_language_alter_logitem_meal.py @@ -23,7 +23,7 @@ class Migration(migrations.Migration): on_delete=django.db.models.deletion.SET_NULL, related_name='log_items', to='nutrition.meal', - verbose_name='Meal' + verbose_name='Meal', ), ), migrations.AddField( diff --git a/wger/nutrition/migrations/0019_alter_image_license_author_and_more.py b/wger/nutrition/migrations/0019_alter_image_license_author_and_more.py index 3de146ecc..df9385147 100644 --- a/wger/nutrition/migrations/0019_alter_image_license_author_and_more.py +++ b/wger/nutrition/migrations/0019_alter_image_license_author_and_more.py @@ -17,7 +17,7 @@ class Migration(migrations.Migration): help_text='If you are not the author, enter the name or source here.', max_length=600, null=True, - verbose_name='Author(s)' + verbose_name='Author(s)', ), ), migrations.AlterField( @@ -30,9 +30,8 @@ class Migration(migrations.Migration): name='license_derivative_source_url', field=models.URLField( blank=True, - help_text= - 'Note that a derivative work is one which is not only based on a previous work, but which also contains sufficient new, creative content to entitle it to its own copyright.', - verbose_name='Link to the original source, if this is a derivative work' + help_text='Note that a derivative work is one which is not only based on a previous work, but which also contains sufficient new, creative content to entitle it to its own copyright.', + verbose_name='Link to the original source, if this is a derivative work', ), ), migrations.AlterField( @@ -46,7 +45,7 @@ class Migration(migrations.Migration): field=models.CharField( blank=True, max_length=300, - verbose_name='The original title of this object, if available' + verbose_name='The original title of this object, if available', ), ), migrations.AlterField( @@ -57,7 +56,7 @@ class Migration(migrations.Migration): help_text='If you are not the author, enter the name or source here.', max_length=600, null=True, - verbose_name='Author(s)' + verbose_name='Author(s)', ), ), migrations.AlterField( @@ -70,9 +69,8 @@ class Migration(migrations.Migration): name='license_derivative_source_url', field=models.URLField( blank=True, - help_text= - 'Note that a derivative work is one which is not only based on a previous work, but which also contains sufficient new, creative content to entitle it to its own copyright.', - verbose_name='Link to the original source, if this is a derivative work' + help_text='Note that a derivative work is one which is not only based on a previous work, but which also contains sufficient new, creative content to entitle it to its own copyright.', + verbose_name='Link to the original source, if this is a derivative work', ), ), migrations.AlterField( @@ -86,7 +84,7 @@ class Migration(migrations.Migration): field=models.CharField( blank=True, max_length=300, - verbose_name='The original title of this object, if available' + verbose_name='The original title of this object, if available', ), ), ] diff --git a/wger/nutrition/models/image.py b/wger/nutrition/models/image.py index 6ee39631e..9bbf5462e 100644 --- a/wger/nutrition/models/image.py +++ b/wger/nutrition/models/image.py @@ -33,7 +33,7 @@ def ingredient_image_upload_dir(instance, filename): Returns the upload target for exercise images """ ext = pathlib.Path(filename).suffix - return "ingredients/{0}/{1}{2}".format(instance.ingredient.pk, instance.uuid, ext) + return 'ingredients/{0}/{1}{2}'.format(instance.ingredient.pk, instance.uuid, ext) class Image(AbstractLicenseModel, models.Model, BaseImage): diff --git a/wger/nutrition/models/ingredient.py b/wger/nutrition/models/ingredient.py index 6ab25fdd0..7dc26f786 100644 --- a/wger/nutrition/models/ingredient.py +++ b/wger/nutrition/models/ingredient.py @@ -73,6 +73,7 @@ class Ingredient(AbstractSubmissionModel, AbstractLicenseModel, models.Model): """ An ingredient, with some approximate nutrition values """ + objects = SubmissionManager() """Custom manager""" @@ -85,7 +86,7 @@ class Ingredient(AbstractSubmissionModel, AbstractLicenseModel, models.Model): # Metaclass to set some other properties class Meta: ordering = [ - "name", + 'name', ] # Meta data @@ -305,7 +306,7 @@ class Ingredient(AbstractSubmissionModel, AbstractLicenseModel, models.Model): ' +/-{energy_approx}%)'.format( energy=self.energy, energy_calculated=energy_calculated, - energy_approx=self.ENERGY_APPROXIMATION + energy_approx=self.ENERGY_APPROXIMATION, ) ) ) @@ -345,7 +346,8 @@ class Ingredient(AbstractSubmissionModel, AbstractLicenseModel, models.Model): 'sodium', ): if ( - hasattr(self, i) and hasattr(other, i) + hasattr(self, i) + and hasattr(other, i) and (getattr(self, i, None) != getattr(other, i, None)) ): equal = False @@ -386,14 +388,15 @@ class Ingredient(AbstractSubmissionModel, AbstractLicenseModel, models.Model): context = { 'ingredient': self.name, 'url': url, - 'site': Site.objects.get_current().domain + 'site': Site.objects.get_current().domain, } message = render_to_string('ingredient/email_new.tpl', context) mail.send_mail( subject, message, - settings.WGER_SETTINGS['EMAIL_FROM'], [user.email], - fail_silently=True + settings.WGER_SETTINGS['EMAIL_FROM'], + [user.email], + fail_silently=True, ) def set_author(self, request): @@ -455,6 +458,7 @@ class Ingredient(AbstractSubmissionModel, AbstractLicenseModel, models.Model): # Let celery fetch the image # wger from wger.nutrition.tasks import fetch_ingredient_image_task + fetch_ingredient_image_task.delay(self.pk) @classmethod diff --git a/wger/nutrition/models/ingredient_category.py b/wger/nutrition/models/ingredient_category.py index 040f120ff..356986ee7 100644 --- a/wger/nutrition/models/ingredient_category.py +++ b/wger/nutrition/models/ingredient_category.py @@ -23,13 +23,14 @@ class IngredientCategory(models.Model): """ Model for an Ingredient category """ + name = models.CharField(max_length=100, verbose_name=_('Name')) # Metaclass to set some other properties class Meta: - verbose_name_plural = _("Ingredient Categories") + verbose_name_plural = _('Ingredient Categories') ordering = [ - "name", + 'name', ] def __str__(self): diff --git a/wger/nutrition/models/ingredient_weight_unit.py b/wger/nutrition/models/ingredient_weight_unit.py index ffb6f205b..6bcedc93c 100644 --- a/wger/nutrition/models/ingredient_weight_unit.py +++ b/wger/nutrition/models/ingredient_weight_unit.py @@ -66,7 +66,7 @@ class IngredientWeightUnit(models.Model): Return a more human-readable representation """ - return "{0}{1} ({2}g)".format( + return '{0}{1} ({2}g)'.format( self.amount if self.amount > 1 else '', self.unit.name, self.gram, diff --git a/wger/nutrition/models/log.py b/wger/nutrition/models/log.py index cfde9badc..74a7dbfc6 100644 --- a/wger/nutrition/models/log.py +++ b/wger/nutrition/models/log.py @@ -41,7 +41,7 @@ class LogItem(BaseMealItem, models.Model): # Metaclass to set some other properties class Meta: ordering = [ - "-datetime", + '-datetime', ] plan = models.ForeignKey( @@ -57,9 +57,9 @@ class LogItem(BaseMealItem, models.Model): Meal, verbose_name=_('Meal'), on_delete=models.SET_NULL, - related_name="log_items", + related_name='log_items', blank=True, - null=True + null=True, ) """ The meal this log belongs to (optional) @@ -113,7 +113,7 @@ class LogItem(BaseMealItem, models.Model): """ Return a more human-readable representation """ - return "Diary entry for {}, plan {}".format(self.datetime, self.plan.pk) + return 'Diary entry for {}, plan {}'.format(self.datetime, self.plan.pk) def get_owner_object(self): """ diff --git a/wger/nutrition/models/meal.py b/wger/nutrition/models/meal.py index cbda28edc..b97d8fc3e 100644 --- a/wger/nutrition/models/meal.py +++ b/wger/nutrition/models/meal.py @@ -42,7 +42,7 @@ class Meal(models.Model): # Metaclass to set some other properties class Meta: ordering = [ - "time", + 'time', ] plan = models.ForeignKey( @@ -74,7 +74,7 @@ class Meal(models.Model): """ Return a more human-readable representation """ - return "{0} Meal".format(self.order) + return '{0} Meal'.format(self.order) def get_owner_object(self): """ diff --git a/wger/nutrition/models/meal_item.py b/wger/nutrition/models/meal_item.py index 03b5a96a0..1f9688ae0 100644 --- a/wger/nutrition/models/meal_item.py +++ b/wger/nutrition/models/meal_item.py @@ -77,7 +77,7 @@ class MealItem(BaseMealItem, models.Model): """ Return a more human-readable representation """ - return "{0}g ingredient {1}".format(self.amount, self.ingredient_id) + return '{0}g ingredient {1}'.format(self.amount, self.ingredient_id) def get_owner_object(self): """ diff --git a/wger/nutrition/models/plan.py b/wger/nutrition/models/plan.py index 81dae1f1b..2ef3c0be0 100644 --- a/wger/nutrition/models/plan.py +++ b/wger/nutrition/models/plan.py @@ -44,10 +44,9 @@ class NutritionPlan(models.Model): # Metaclass to set some other properties class Meta: - # Order by creation_date, descending (oldest first) ordering = [ - "-creation_date", + '-creation_date', ] user = models.ForeignKey( @@ -67,8 +66,7 @@ class NutritionPlan(models.Model): blank=True, verbose_name=_('Description'), help_text=_( - 'A description of the goal of the plan, e.g. ' - '"Gain mass" or "Prepare for summer"' + 'A description of the goal of the plan, e.g. ' '"Gain mass" or "Prepare for summer"' ), ) @@ -90,10 +88,10 @@ class NutritionPlan(models.Model): verbose_name=_('Use daily calories'), default=False, help_text=_( - "Tick the box if you want to mark this " - "plan as having a goal amount of calories. " - "You can use the calculator or enter the " - "value yourself." + 'Tick the box if you want to mark this ' + 'plan as having a goal amount of calories. ' + 'You can use the calculator or enter the ' + 'value yourself.' ), ) """A flag indicating whether the plan has a goal amount of calories""" @@ -103,9 +101,9 @@ class NutritionPlan(models.Model): Return a more human-readable representation """ if self.description: - return "{0}".format(self.description) + return '{0}'.format(self.description) else: - return "{0}".format(_("Nutrition plan")) + return '{0}'.format(_('Nutrition plan')) def get_absolute_url(self): """ @@ -124,16 +122,8 @@ class NutritionPlan(models.Model): unit = 'kg' if use_metric else 'lb' result = { 'total': NutritionalValues(), - 'percent': { - 'protein': 0, - 'carbohydrates': 0, - 'fat': 0 - }, - 'per_kg': { - 'protein': 0, - 'carbohydrates': 0, - 'fat': 0 - }, + 'percent': {'protein': 0, 'carbohydrates': 0, 'fat': 0}, + 'per_kg': {'protein': 0, 'carbohydrates': 0, 'fat': 0}, } # Energy @@ -145,20 +135,26 @@ class NutritionPlan(models.Model): # In percent if energy: - result['percent']['protein'] = nutritional_values.protein * \ - ENERGY_FACTOR['protein'][unit] / energy * 100 - result['percent']['carbohydrates'] = nutritional_values.carbohydrates * \ - ENERGY_FACTOR['carbohydrates'][ - unit] / energy * 100 - result['percent']['fat'] = nutritional_values.fat * \ - ENERGY_FACTOR['fat'][unit] / energy * 100 + result['percent']['protein'] = ( + nutritional_values.protein * ENERGY_FACTOR['protein'][unit] / energy * 100 + ) + result['percent']['carbohydrates'] = ( + nutritional_values.carbohydrates + * ENERGY_FACTOR['carbohydrates'][unit] + / energy + * 100 + ) + result['percent']['fat'] = ( + nutritional_values.fat * ENERGY_FACTOR['fat'][unit] / energy * 100 + ) # Per body weight weight_entry = self.get_closest_weight_entry() if weight_entry and weight_entry.weight: result['per_kg']['protein'] = nutritional_values.protein / weight_entry.weight - result['per_kg']['carbohydrates' - ] = nutritional_values.carbohydrates / weight_entry.weight + result['per_kg']['carbohydrates'] = ( + nutritional_values.carbohydrates / weight_entry.weight + ) result['per_kg']['fat'] = nutritional_values.fat / weight_entry.weight nutritional_representation = result @@ -171,10 +167,18 @@ class NutritionPlan(models.Model): Returns None if there are no entries. """ target = self.creation_date - closest_entry_gte = WeightEntry.objects.filter(user=self.user) \ - .filter(date__gte=target).order_by('date').first() - closest_entry_lte = WeightEntry.objects.filter(user=self.user) \ - .filter(date__lte=target).order_by('-date').first() + closest_entry_gte = ( + WeightEntry.objects.filter(user=self.user) + .filter(date__gte=target) + .order_by('date') + .first() + ) + closest_entry_lte = ( + WeightEntry.objects.filter(user=self.user) + .filter(date__lte=target) + .order_by('-date') + .first() + ) if closest_entry_gte is None or closest_entry_lte is None: return closest_entry_gte or closest_entry_lte if abs(closest_entry_gte.date - target) < abs(closest_entry_lte.date - target): diff --git a/wger/nutrition/models/weight_unit.py b/wger/nutrition/models/weight_unit.py index cfa5f27b9..aba3ded75 100644 --- a/wger/nutrition/models/weight_unit.py +++ b/wger/nutrition/models/weight_unit.py @@ -41,7 +41,7 @@ class WeightUnit(models.Model): # Metaclass to set some other properties class Meta: ordering = [ - "name", + 'name', ] def __str__(self): diff --git a/wger/nutrition/off.py b/wger/nutrition/off.py index 9794e9d6c..9e99f141c 100644 --- a/wger/nutrition/off.py +++ b/wger/nutrition/off.py @@ -130,5 +130,5 @@ def extract_info_from_off(product_data, language: int): license_id=ODBL_LICENSE_ID, license_author=authors, license_title=name, - license_object_url=object_url + license_object_url=object_url, ) diff --git a/wger/nutrition/sitemap.py b/wger/nutrition/sitemap.py index eb7158b3f..285ccb1a7 100644 --- a/wger/nutrition/sitemap.py +++ b/wger/nutrition/sitemap.py @@ -22,7 +22,7 @@ from wger.nutrition.models import Ingredient class NutritionSitemap(Sitemap): - changefreq = "monthly" + changefreq = 'monthly' priority = 0.5 def items(self): diff --git a/wger/nutrition/sync.py b/wger/nutrition/sync.py index 6b675e160..3f3f491df 100644 --- a/wger/nutrition/sync.py +++ b/wger/nutrition/sync.py @@ -124,7 +124,7 @@ def fetch_image_from_off(ingredient): # Parse the file name, looks something like this: # https://images.openfoodfacts.org/images/products/00975957/front_en.5.400.jpg - image_id: str = image_url.rpartition("/")[2].partition(".")[0] + image_id: str = image_url.rpartition('/')[2].partition('.')[0] # Retrieve the uploader name try: @@ -135,7 +135,9 @@ def fetch_image_from_off(ingredient): return # Save to DB - url = f'https://world.openfoodfacts.org/cgi/product_image.pl?code={ingredient.code}&id={image_id}' + url = ( + f'https://world.openfoodfacts.org/cgi/product_image.pl?code={ingredient.code}&id={image_id}' + ) uploader_url = f'https://world.openfoodfacts.org/photographer/{uploader_name}' image_data = { 'image': os.path.basename(image_url), @@ -145,7 +147,7 @@ def fetch_image_from_off(ingredient): 'license_author_url': uploader_url, 'license_object_url': url, 'license_derivative_source_url': '', - 'size': len(response.content) + 'size': len(response.content), } try: Image.from_json(ingredient, response, image_data, generate_uuid=True) diff --git a/wger/nutrition/tests/test_bmi.py b/wger/nutrition/tests/test_bmi.py index 836824f68..97814d500 100644 --- a/wger/nutrition/tests/test_bmi.py +++ b/wger/nutrition/tests/test_bmi.py @@ -52,10 +52,7 @@ class BmiTestCase(WgerTestCase): self.user_login('test') response = self.client.post( - reverse('nutrition:bmi:calculate'), { - 'height': 180, - 'weight': 80 - } + reverse('nutrition:bmi:calculate'), {'height': 180, 'weight': 80} ) self.assertEqual(response.status_code, 200) bmi = json.loads(response.content.decode('utf8')) @@ -72,10 +69,7 @@ class BmiTestCase(WgerTestCase): profile = UserProfile.objects.get(user__username='test') profile.save() response = self.client.post( - reverse('nutrition:bmi:calculate'), { - 'height': 115, - 'weight': 76 - } + reverse('nutrition:bmi:calculate'), {'height': 115, 'weight': 76} ) self.assertEqual(response.status_code, 406) response = json.loads(response.content.decode('utf8')) @@ -90,10 +84,7 @@ class BmiTestCase(WgerTestCase): profile = UserProfile.objects.get(user__username='test') profile.save() response = self.client.post( - reverse('nutrition:bmi:calculate'), { - 'height': 250, - 'weight': 82 - } + reverse('nutrition:bmi:calculate'), {'height': 250, 'weight': 82} ) self.assertEqual(response.status_code, 406) response = json.loads(response.content.decode('utf8')) @@ -109,10 +100,7 @@ class BmiTestCase(WgerTestCase): profile.weight_unit = 'lb' profile.save() response = self.client.post( - reverse('nutrition:bmi:calculate'), { - 'height': 73, - 'weight': 176 - } + reverse('nutrition:bmi:calculate'), {'height': 73, 'weight': 176} ) self.assertEqual(response.status_code, 200) bmi = json.loads(response.content.decode('utf8')) @@ -130,10 +118,7 @@ class BmiTestCase(WgerTestCase): profile.weight_unit = 'lb' profile.save() response = self.client.post( - reverse('nutrition:bmi:calculate'), { - 'height': 48, - 'weight': 145 - } + reverse('nutrition:bmi:calculate'), {'height': 48, 'weight': 145} ) self.assertEqual(response.status_code, 406) response = json.loads(response.content.decode('utf8')) @@ -149,10 +134,7 @@ class BmiTestCase(WgerTestCase): profile.weight_unit = 'lb' profile.save() response = self.client.post( - reverse('nutrition:bmi:calculate'), { - 'height': 98, - 'weight': 145 - } + reverse('nutrition:bmi:calculate'), {'height': 98, 'weight': 145} ) self.assertEqual(response.status_code, 406) response = json.loads(response.content.decode('utf8')) @@ -169,10 +151,7 @@ class BmiTestCase(WgerTestCase): # Existing weight entry is old, a new one is created entry1 = WeightEntry.objects.filter(user=user).latest() response = self.client.post( - reverse('nutrition:bmi:calculate'), { - 'height': 180, - 'weight': 80 - } + reverse('nutrition:bmi:calculate'), {'height': 180, 'weight': 80} ) self.assertEqual(response.status_code, 200) entry2 = WeightEntry.objects.filter(user=user).latest() @@ -184,10 +163,7 @@ class BmiTestCase(WgerTestCase): entry1.date = datetime.date.today() entry1.save() response = self.client.post( - reverse('nutrition:bmi:calculate'), { - 'height': 180, - 'weight': 80 - } + reverse('nutrition:bmi:calculate'), {'height': 180, 'weight': 80} ) self.assertEqual(response.status_code, 200) entry2 = WeightEntry.objects.filter(user=user).latest() @@ -197,10 +173,7 @@ class BmiTestCase(WgerTestCase): # No existing entries WeightEntry.objects.filter(user=user).delete() response = self.client.post( - reverse('nutrition:bmi:calculate'), { - 'height': 180, - 'weight': 80 - } + reverse('nutrition:bmi:calculate'), {'height': 180, 'weight': 80} ) self.assertEqual(response.status_code, 200) entry = WeightEntry.objects.filter(user=user).latest() diff --git a/wger/nutrition/tests/test_calories_calculator.py b/wger/nutrition/tests/test_calories_calculator.py index ed2625870..2e3e44f52 100644 --- a/wger/nutrition/tests/test_calories_calculator.py +++ b/wger/nutrition/tests/test_calories_calculator.py @@ -51,21 +51,21 @@ class CaloriesCalculatorTestCase(WgerTestCase): self.user_login('test') response = self.client.post( - reverse('nutrition:calories:activities'), { + reverse('nutrition:calories:activities'), + { 'sleep_hours': 7, 'work_hours': 8, 'work_intensity': 1, 'sport_hours': 6, 'sport_intensity': 3, 'freetime_hours': 8, - 'freetime_intensity': 1 - } + 'freetime_intensity': 1, + }, ) self.assertEqual(response.status_code, 200) result = json.loads(response.content.decode('utf8')) self.assertEqual( - decimal.Decimal(result['factor']), - decimal.Decimal(1.57).quantize(TWOPLACES) + decimal.Decimal(result['factor']), decimal.Decimal(1.57).quantize(TWOPLACES) ) self.assertEqual(decimal.Decimal(result['activities']), decimal.Decimal(2920)) @@ -80,10 +80,7 @@ class CaloriesCalculatorTestCase(WgerTestCase): # Existing weight entry is old, a new one is created entry1 = WeightEntry.objects.filter(user=user).latest() response = self.client.post( - reverse('nutrition:bmi:calculate'), { - 'height': 180, - 'weight': 80 - } + reverse('nutrition:bmi:calculate'), {'height': 180, 'weight': 80} ) self.assertEqual(response.status_code, 200) entry2 = WeightEntry.objects.filter(user=user).latest() @@ -95,10 +92,7 @@ class CaloriesCalculatorTestCase(WgerTestCase): entry1.date = datetime.date.today() entry1.save() response = self.client.post( - reverse('nutrition:bmi:calculate'), { - 'height': 180, - 'weight': 80 - } + reverse('nutrition:bmi:calculate'), {'height': 180, 'weight': 80} ) self.assertEqual(response.status_code, 200) entry2 = WeightEntry.objects.filter(user=user).latest() @@ -108,10 +102,7 @@ class CaloriesCalculatorTestCase(WgerTestCase): # No existing entries WeightEntry.objects.filter(user=user).delete() response = self.client.post( - reverse('nutrition:bmi:calculate'), { - 'height': 180, - 'weight': 80 - } + reverse('nutrition:bmi:calculate'), {'height': 180, 'weight': 80} ) self.assertEqual(response.status_code, 200) entry = WeightEntry.objects.filter(user=user).latest() @@ -125,12 +116,7 @@ class CaloriesCalculatorTestCase(WgerTestCase): self.user_login('test') response = self.client.post( - reverse('nutrition:calories:bmr'), { - 'age': 30, - 'height': 180, - 'gender': 1, - 'weight': 80 - } + reverse('nutrition:calories:bmr'), {'age': 30, 'height': 180, 'gender': 1, 'weight': 80} ) self.assertEqual(response.status_code, 200) result = json.loads(response.content.decode('utf8')) @@ -147,12 +133,7 @@ class CaloriesCalculatorTestCase(WgerTestCase): # Existing weight entry is old, a new one is created entry1 = WeightEntry.objects.filter(user=user).latest() response = self.client.post( - reverse('nutrition:calories:bmr'), { - 'age': 30, - 'height': 180, - 'gender': 1, - 'weight': 80 - } + reverse('nutrition:calories:bmr'), {'age': 30, 'height': 180, 'gender': 1, 'weight': 80} ) self.assertEqual(response.status_code, 200) entry2 = WeightEntry.objects.filter(user=user).latest() @@ -164,12 +145,7 @@ class CaloriesCalculatorTestCase(WgerTestCase): entry1.date = datetime.date.today() entry1.save() response = self.client.post( - reverse('nutrition:calories:bmr'), { - 'age': 30, - 'height': 180, - 'gender': 1, - 'weight': 80 - } + reverse('nutrition:calories:bmr'), {'age': 30, 'height': 180, 'gender': 1, 'weight': 80} ) self.assertEqual(response.status_code, 200) entry2 = WeightEntry.objects.filter(user=user).latest() @@ -179,12 +155,7 @@ class CaloriesCalculatorTestCase(WgerTestCase): # No existing entries WeightEntry.objects.filter(user=user).delete() response = self.client.post( - reverse('nutrition:calories:bmr'), { - 'age': 30, - 'height': 180, - 'gender': 1, - 'weight': 80 - } + reverse('nutrition:calories:bmr'), {'age': 30, 'height': 180, 'gender': 1, 'weight': 80} ) self.assertEqual(response.status_code, 200) entry = WeightEntry.objects.filter(user=user).latest() diff --git a/wger/nutrition/tests/test_generator.py b/wger/nutrition/tests/test_generator.py index eb80843e6..2671339d1 100644 --- a/wger/nutrition/tests/test_generator.py +++ b/wger/nutrition/tests/test_generator.py @@ -21,7 +21,6 @@ from wger.nutrition.models import NutritionPlan class NutritionalPlansGeneratorTestCase(WgerTestCase): - def test_generator(self): # Arrange NutritionPlan.objects.all().delete() diff --git a/wger/nutrition/tests/test_ingredient.py b/wger/nutrition/tests/test_ingredient.py index e0d0c4899..c486a6042 100644 --- a/wger/nutrition/tests/test_ingredient.py +++ b/wger/nutrition/tests/test_ingredient.py @@ -57,7 +57,7 @@ class IngredientRepresentationTestCase(WgerTestCase): """ Test that the representation of an object is correct """ - self.assertEqual("{0}".format(Ingredient.objects.get(pk=1)), 'Test ingredient 1') + self.assertEqual('{0}'.format(Ingredient.objects.get(pk=1)), 'Test ingredient 1') class DeleteIngredientTestCase(WgerDeleteTestCase): @@ -89,7 +89,7 @@ class EditIngredientTestCase(WgerEditTestCase): 'protein': 20, 'carbohydrates': 10, 'license': 2, - 'license_author': 'me!' + 'license_author': 'me!', } def post_test_hook(self): @@ -100,7 +100,7 @@ class EditIngredientTestCase(WgerEditTestCase): ingredient = Ingredient.objects.get(pk=1) self.assertEqual( ingredient.last_update.replace(microsecond=0), - datetime.datetime.now(tz=datetime.timezone.utc).replace(microsecond=0) + datetime.datetime.now(tz=datetime.timezone.utc).replace(microsecond=0), ) @@ -123,7 +123,7 @@ class AddIngredientTestCase(WgerAddTestCase): 'protein': 20, 'carbohydrates': 10, 'license': 2, - 'license_author': 'me!' + 'license_author': 'me!', } def post_test_hook(self): @@ -134,7 +134,7 @@ class AddIngredientTestCase(WgerAddTestCase): ingredient = Ingredient.objects.get(pk=self.pk_after) self.assertEqual( ingredient.created.replace(microsecond=0), - datetime.datetime.now(tz=datetime.timezone.utc).replace(microsecond=0) + datetime.datetime.now(tz=datetime.timezone.utc).replace(microsecond=0), ) self.assertEqual(ingredient.status, Ingredient.STATUS_ACCEPTED) elif self.current_user == 'test': @@ -146,6 +146,7 @@ class IngredientNameShortTestCase(WgerTestCase): """ Tests that ingredient cannot have name with length less than 3 """ + data = { 'name': 'Ui', 'sodium': 2, @@ -157,7 +158,7 @@ class IngredientNameShortTestCase(WgerTestCase): 'protein': 20, 'carbohydrates': 10, 'license': 2, - 'license_author': 'me!' + 'license_author': 'me!', } def test_add_ingredient_short_name(self): @@ -307,11 +308,8 @@ class IngredientValuesTestCase(WgerTestCase): # Get the nutritional values in 1 gram of product response = self.client.get( - reverse('api-ingredient-get-values', kwargs={'pk': 1}), { - 'amount': 1, - 'ingredient': 1, - 'unit': '' - } + reverse('api-ingredient-get-values', kwargs={'pk': 1}), + {'amount': 1, 'ingredient': 1, 'unit': ''}, ) self.assertEqual(response.status_code, 200) @@ -328,17 +326,14 @@ class IngredientValuesTestCase(WgerTestCase): 'fat_saturated': 0.03244, 'fibres': None, 'protein': 0.2563, - 'carbohydrates': 0.00125 - } + 'carbohydrates': 0.00125, + }, ) # Get the nutritional values in 1 unit of product response = self.client.get( - reverse('api-ingredient-get-values', kwargs={'pk': 1}), { - 'amount': 1, - 'ingredient': 1, - 'unit': 2 - } + reverse('api-ingredient-get-values', kwargs={'pk': 1}), + {'amount': 1, 'ingredient': 1, 'unit': 2}, ) self.assertEqual(response.status_code, 200) @@ -355,8 +350,8 @@ class IngredientValuesTestCase(WgerTestCase): 'fat_saturated': 3.61706, 'fibres': None, 'protein': 28.57745, - 'carbohydrates': 0.139375 - } + 'carbohydrates': 0.139375, + }, ) def test_calculate_value_anonymous(self): @@ -452,6 +447,7 @@ class IngredientApiTestCase(api_base_test.ApiBaseResourceTestCase): """ Tests the ingredient API resource """ + pk = 4 resource = Ingredient private_resource = False @@ -483,14 +479,14 @@ class IngredientModelTestCase(WgerTestCase): 'fat_100g': 40, 'saturated-fat_100g': 11, 'sodium_100g': 5, - 'fiber_100g': None + 'fiber_100g': None, }, - } + }, } self.off_response_no_results = { 'status': OFF_SEARCH_PRODUCT_NOT_FOUND, - 'status_verbose': 'product not found' + 'status_verbose': 'product not found', } @patch('openfoodfacts.api.ProductResource.get') diff --git a/wger/nutrition/tests/test_ingredient_overview.py b/wger/nutrition/tests/test_ingredient_overview.py index ea56a9fc5..4cde8d6c3 100644 --- a/wger/nutrition/tests/test_ingredient_overview.py +++ b/wger/nutrition/tests/test_ingredient_overview.py @@ -27,22 +27,21 @@ class OverviewPlanTestCase(WgerTestCase): """ def test_overview(self): - # Add more ingredients so we can test the pagination self.user_login('admin') data = { - "name": "Test ingredient", - "language": 2, - "sodium": 10.54, - "energy": 176, - "fat": 8.19, - "carbohydrates_sugar": 0.0, - "fat_saturated": 3.24, - "fibres": 0.0, - "protein": 25.63, - "carbohydrates": 0.0, + 'name': 'Test ingredient', + 'language': 2, + 'sodium': 10.54, + 'energy': 176, + 'fat': 8.19, + 'carbohydrates_sugar': 0.0, + 'fat_saturated': 3.24, + 'fibres': 0.0, + 'protein': 25.63, + 'carbohydrates': 0.0, 'license': 1, - 'license_author': 'internet' + 'license_author': 'internet', } for i in range(0, 50): self.client.post(reverse('nutrition:ingredient:add'), data) diff --git a/wger/nutrition/tests/test_meal.py b/wger/nutrition/tests/test_meal.py index fa0ff2ca6..766193845 100644 --- a/wger/nutrition/tests/test_meal.py +++ b/wger/nutrition/tests/test_meal.py @@ -25,10 +25,11 @@ class MealApiTestCase(api_base_test.ApiBaseResourceTestCase): """ Tests the meal overview resource """ + pk = 2 resource = Meal private_resource = True - special_endpoints = ('nutritional_values', ) + special_endpoints = ('nutritional_values',) data = { 'time': datetime.time(9, 2), 'plan': 4, diff --git a/wger/nutrition/tests/test_meal_item.py b/wger/nutrition/tests/test_meal_item.py index 2d7ff14f5..f2e9ca8b7 100644 --- a/wger/nutrition/tests/test_meal_item.py +++ b/wger/nutrition/tests/test_meal_item.py @@ -22,6 +22,7 @@ class MealItemApiTestCase(api_base_test.ApiBaseResourceTestCase): """ Tests the meal overview resource """ + pk = 10 resource = MealItem private_resource = True diff --git a/wger/nutrition/tests/test_nutritional_cache.py b/wger/nutrition/tests/test_nutritional_cache.py index 1c0cb72a3..8f9ab3805 100644 --- a/wger/nutrition/tests/test_nutritional_cache.py +++ b/wger/nutrition/tests/test_nutritional_cache.py @@ -14,7 +14,6 @@ from wger.utils.cache import cache_mapper class NutritionalPlanCacheTestCase(WgerTestCase): - def create_nutrition_plan(self): """ Create a nutrition plan and set dummy attributes that are required @@ -23,7 +22,7 @@ class NutritionalPlanCacheTestCase(WgerTestCase): """ plan = NutritionPlan() plan.user = User.objects.create_user(username='example_user_1') - plan.language = Language.objects.get(short_name="en") + plan.language = Language.objects.get(short_name='en') plan.save() meal = Meal() meal.plan = plan diff --git a/wger/nutrition/tests/test_nutritional_values.py b/wger/nutrition/tests/test_nutritional_values.py index 7476fb928..903774ede 100644 --- a/wger/nutrition/tests/test_nutritional_values.py +++ b/wger/nutrition/tests/test_nutritional_values.py @@ -41,7 +41,7 @@ class NutritionalValuesTestCase(SimpleTestCase): fat=60, fat_saturated=50, fibres=40, - sodium=30 + sodium=30, ) values2 = NutritionalValues( energy=10, @@ -51,7 +51,7 @@ class NutritionalValuesTestCase(SimpleTestCase): fat=6, fat_saturated=5, fibres=4, - sodium=3 + sodium=3, ) values3 = values1 + values2 @@ -65,7 +65,7 @@ class NutritionalValuesTestCase(SimpleTestCase): fat=66, fat_saturated=55, fibres=44, - sodium=33 + sodium=33, ), ) @@ -86,6 +86,6 @@ class NutritionalValuesTestCase(SimpleTestCase): fat=0, fat_saturated=20, fibres=30, - sodium=40 + sodium=40, ), ) diff --git a/wger/nutrition/tests/test_off.py b/wger/nutrition/tests/test_off.py index fcb49e496..de652c26e 100644 --- a/wger/nutrition/tests/test_off.py +++ b/wger/nutrition/tests/test_off.py @@ -29,6 +29,7 @@ class ExtractInfoFromOffTestCase(SimpleTestCase): """ Test the extract_info_from_off function """ + off_data1 = {} def setUp(self): @@ -48,8 +49,8 @@ class ExtractInfoFromOffTestCase(SimpleTestCase): 'saturated-fat_100g': 11, 'sodium_100g': 5, 'fiber_100g': None, - 'other_stuff': 'is ignored' - } + 'other_stuff': 'is ignored', + }, } def test_regular_response(self): @@ -77,7 +78,7 @@ class ExtractInfoFromOffTestCase(SimpleTestCase): license_id=ODBL_LICENSE_ID, license_author='open food facts, MrX', license_title='Foo with chocolate', - license_object_url='https://world.openfoodfacts.org/product/1234/' + license_object_url='https://world.openfoodfacts.org/product/1234/', ) self.assertEqual(result, data) diff --git a/wger/nutrition/tests/test_plan.py b/wger/nutrition/tests/test_plan.py index 202e45553..e8f52814a 100644 --- a/wger/nutrition/tests/test_plan.py +++ b/wger/nutrition/tests/test_plan.py @@ -25,9 +25,10 @@ class PlanApiTestCase(api_base_test.ApiBaseResourceTestCase): TODO: setting overview_cached to true since get_nutritional_values is cached, but we don't really use it. This should be removed """ + pk = 4 resource = NutritionPlan private_resource = True overview_cached = False - special_endpoints = ('nutritional_values', ) + special_endpoints = ('nutritional_values',) data = {'description': 'The description'} diff --git a/wger/nutrition/tests/test_sync.py b/wger/nutrition/tests/test_sync.py index 1d474f6e2..0609ec802 100644 --- a/wger/nutrition/tests/test_sync.py +++ b/wger/nutrition/tests/test_sync.py @@ -25,7 +25,6 @@ from wger.utils.requests import wger_headers class MockIngredientResponse: - def __init__(self): self.status_code = 200 self.content = b'1234' @@ -90,7 +89,6 @@ class MockIngredientResponse: class TestSyncMethods(WgerTestCase): - @patch('requests.get', return_value=MockIngredientResponse()) def test_ingredient_sync(self, mock_request): # Arrange diff --git a/wger/nutrition/tests/test_tasks.py b/wger/nutrition/tests/test_tasks.py index 5bb03266d..b35f2bb50 100644 --- a/wger/nutrition/tests/test_tasks.py +++ b/wger/nutrition/tests/test_tasks.py @@ -32,7 +32,6 @@ from wger.utils.requests import wger_headers class MockOffResponse: - def __init__(self): self.status_code = 200 self.content = b'2000' @@ -58,7 +57,6 @@ class MockOffResponse: class MockWgerApiResponse: - def __init__(self): self.status_code = 200 self.content = b'2000' @@ -160,11 +158,11 @@ class FetchIngredientImageTestCase(WgerTestCase): mock_request.assert_any_call( 'https://world.openfoodfacts.org/api/v2/product/5055365635003.json?fields=images,image_front_url', - headers=wger_headers() + headers=wger_headers(), ) mock_request.assert_any_call( 'https://images.openfoodfacts.org/images/products/00975957/front_en.5.400.jpg', - headers=wger_headers() + headers=wger_headers(), ) mock_from_json.assert_called() @@ -199,7 +197,7 @@ class FetchIngredientImageTestCase(WgerTestCase): ) mock_request.assert_any_call( 'http://localhost:8000/media/ingredients/1/188324b5-587f-42d7-9abc-d2ca64c73d45.jpg', - headers=wger_headers() + headers=wger_headers(), ) mock_from_json.assert_called() diff --git a/wger/nutrition/tests/test_weight_unit.py b/wger/nutrition/tests/test_weight_unit.py index fa571a84a..c0c71daef 100644 --- a/wger/nutrition/tests/test_weight_unit.py +++ b/wger/nutrition/tests/test_weight_unit.py @@ -37,7 +37,7 @@ class WeightUnitRepresentationTestCase(WgerTestCase): """ Test that the representation of an object is correct """ - self.assertEqual("{0}".format(WeightUnit.objects.get(pk=1)), 'Scheibe') + self.assertEqual('{0}'.format(WeightUnit.objects.get(pk=1)), 'Scheibe') class AddWeightUnitTestCase(WgerAddTestCase): @@ -77,10 +77,9 @@ class WeightUnitOverviewTestCase(WgerTestCase): """ def test_overview(self): - # Add more ingredient units so we can test the pagination self.user_login('admin') - data = {"name": "A new, cool unit", "language": 2} + data = {'name': 'A new, cool unit', 'language': 2} for i in range(0, 50): self.client.post(reverse('nutrition:weight_unit:add'), data) @@ -114,6 +113,7 @@ class WeightUnitApiTestCase(api_base_test.ApiBaseResourceTestCase): """ Tests the weight unit overview resource """ + pk = 1 resource = WeightUnit private_resource = False diff --git a/wger/nutrition/tests/test_weight_unit_ingredient.py b/wger/nutrition/tests/test_weight_unit_ingredient.py index 627f2f7dc..0dc8dc2d4 100644 --- a/wger/nutrition/tests/test_weight_unit_ingredient.py +++ b/wger/nutrition/tests/test_weight_unit_ingredient.py @@ -42,7 +42,7 @@ class WeightUnitIngredientRepresentationTestCase(WgerTestCase): """ Test that the representation of an object is correct """ - self.assertEqual("{0}".format(IngredientWeightUnit.objects.get(pk=1)), 'Spoon (109g)') + self.assertEqual('{0}'.format(IngredientWeightUnit.objects.get(pk=1)), 'Spoon (109g)') class AddWeightUnitIngredientTestCase(WgerAddTestCase): @@ -124,6 +124,7 @@ class WeightUnitToIngredientApiTestCase(api_base_test.ApiBaseResourceTestCase): """ Tests the weight unit to ingredient API resource """ + pk = 1 resource = IngredientWeightUnit private_resource = False diff --git a/wger/nutrition/urls.py b/wger/nutrition/urls.py index 9b4d2daa5..629f5849f 100644 --- a/wger/nutrition/urls.py +++ b/wger/nutrition/urls.py @@ -190,31 +190,46 @@ patterns_calories = [ ] urlpatterns = [ - path('', include( - (patterns_plan, "plan"), - namespace="plan", - )), - path('ingredient/', include( - (patterns_ingredient, "ingredient"), - namespace="ingredient", - )), - path('unit/', include( - (patterns_weight_unit, "weight_unit"), - namespace="weight_unit", - )), + path( + '', + include( + (patterns_plan, 'plan'), + namespace='plan', + ), + ), + path( + 'ingredient/', + include( + (patterns_ingredient, 'ingredient'), + namespace='ingredient', + ), + ), + path( + 'unit/', + include( + (patterns_weight_unit, 'weight_unit'), + namespace='weight_unit', + ), + ), path( 'unit-to-ingredient/', include( - (patterns_unit_ingredient, "unit_ingredient"), - namespace="unit_ingredient", - ) + (patterns_unit_ingredient, 'unit_ingredient'), + namespace='unit_ingredient', + ), + ), + path( + 'calculator/bmi/', + include( + (patterns_bmi, 'bmi'), + namespace='bmi', + ), + ), + path( + 'calculator/calories/', + include( + (patterns_calories, 'calories'), + namespace='calories', + ), ), - path('calculator/bmi/', include( - (patterns_bmi, "bmi"), - namespace="bmi", - )), - path('calculator/calories/', include( - (patterns_calories, "calories"), - namespace="calories", - )), ] diff --git a/wger/nutrition/views/bmi.py b/wger/nutrition/views/bmi.py index 582fff185..9a2899abd 100644 --- a/wger/nutrition/views/bmi.py +++ b/wger/nutrition/views/bmi.py @@ -47,7 +47,7 @@ def view(request): form_data = { 'height': request.user.userprofile.height, 'weight': request.user.userprofile.weight, - 'use_metric': request.user.userprofile.use_metric + 'use_metric': request.user.userprofile.use_metric, } context['form'] = BmiForm(initial=form_data) return render(request, 'bmi/form.html', context) @@ -111,157 +111,47 @@ def chart_data(request): if request.user.userprofile.use_metric: data = json.dumps( [ - { - 'key': 'filler', - 'height': 150, - 'weight': 30 - }, { - 'key': 'filler', - 'height': 200, - 'weight': 30 - }, { - 'key': 'severe_thinness', - 'height': 150, - 'weight': 35.978 - }, { - 'key': 'severe_thinness', - 'height': 200, - 'weight': 63.960 - }, { - 'key': 'moderate_thinness', - 'height': 150, - 'weight': 38.228 - }, { - 'key': 'moderate_thinness', - 'height': 200, - 'weight': 67.960 - }, { - 'key': 'mild_thinness', - 'height': 150, - 'weight': 41.603 - }, { - 'key': 'mild_thinness', - 'height': 200, - 'weight': 73.960 - }, { - 'key': 'normal_range', - 'height': 150, - 'weight': 56.228 - }, { - 'key': 'normal_range', - 'height': 200, - 'weight': 99.960 - }, { - 'key': 'pre_obese', - 'height': 150, - 'weight': 67.478 - }, { - 'key': 'pre_obese', - 'height': 200, - 'weight': 119.960 - }, { - 'key': 'obese_class_1', - 'height': 150, - 'weight': 78.728 - }, { - 'key': 'obese_class_1', - 'height': 200, - 'weight': 139.960 - }, { - 'key': 'obese_class_2', - 'height': 150, - 'weight': 89.978 - }, { - 'key': 'obese_class_2', - 'height': 200, - 'weight': 159.960 - }, { - 'key': 'obese_class_3', - 'height': 150, - 'weight': 90 - }, { - 'key': 'obese_class_3', - 'height': 200, - 'weight': 190 - } + {'key': 'filler', 'height': 150, 'weight': 30}, + {'key': 'filler', 'height': 200, 'weight': 30}, + {'key': 'severe_thinness', 'height': 150, 'weight': 35.978}, + {'key': 'severe_thinness', 'height': 200, 'weight': 63.960}, + {'key': 'moderate_thinness', 'height': 150, 'weight': 38.228}, + {'key': 'moderate_thinness', 'height': 200, 'weight': 67.960}, + {'key': 'mild_thinness', 'height': 150, 'weight': 41.603}, + {'key': 'mild_thinness', 'height': 200, 'weight': 73.960}, + {'key': 'normal_range', 'height': 150, 'weight': 56.228}, + {'key': 'normal_range', 'height': 200, 'weight': 99.960}, + {'key': 'pre_obese', 'height': 150, 'weight': 67.478}, + {'key': 'pre_obese', 'height': 200, 'weight': 119.960}, + {'key': 'obese_class_1', 'height': 150, 'weight': 78.728}, + {'key': 'obese_class_1', 'height': 200, 'weight': 139.960}, + {'key': 'obese_class_2', 'height': 150, 'weight': 89.978}, + {'key': 'obese_class_2', 'height': 200, 'weight': 159.960}, + {'key': 'obese_class_3', 'height': 150, 'weight': 90}, + {'key': 'obese_class_3', 'height': 200, 'weight': 190}, ] ) else: data = json.dumps( [ - { - 'key': 'filler', - 'height': 150, - 'weight': 66.139 - }, { - 'key': 'filler', - 'height': 200, - 'weight': 66.139 - }, { - 'key': 'severe_thinness', - 'height': 150, - 'weight': 79.317 - }, { - 'key': 'severe_thinness', - 'height': 200, - 'weight': 141.008 - }, { - 'key': 'moderate_thinness', - 'height': 150, - 'weight': 84.277 - }, { - 'key': 'moderate_thinness', - 'height': 200, - 'weight': 149.826 - }, { - 'key': 'mild_thinness', - 'height': 150, - 'weight': 91.718 - }, { - 'key': 'mild_thinness', - 'height': 200, - 'weight': 163.054 - }, { - 'key': 'normal_range', - 'height': 150, - 'weight': 123.960 - }, { - 'key': 'normal_range', - 'height': 200, - 'weight': 220.374 - }, { - 'key': 'pre_obese', - 'height': 150, - 'weight': 148.762 - }, { - 'key': 'pre_obese', - 'height': 200, - 'weight': 264.467 - }, { - 'key': 'obese_class_1', - 'height': 150, - 'weight': 173.564 - }, { - 'key': 'obese_class_1', - 'height': 200, - 'weight': 308.559 - }, { - 'key': 'obese_class_2', - 'height': 150, - 'weight': 198.366 - }, { - 'key': 'obese_class_2', - 'height': 200, - 'weight': 352.651 - }, { - 'key': 'obese_class_3', - 'height': 150, - 'weight': 198.416 - }, { - 'key': 'obese_class_3', - 'height': 200, - 'weight': 352.740 - } + {'key': 'filler', 'height': 150, 'weight': 66.139}, + {'key': 'filler', 'height': 200, 'weight': 66.139}, + {'key': 'severe_thinness', 'height': 150, 'weight': 79.317}, + {'key': 'severe_thinness', 'height': 200, 'weight': 141.008}, + {'key': 'moderate_thinness', 'height': 150, 'weight': 84.277}, + {'key': 'moderate_thinness', 'height': 200, 'weight': 149.826}, + {'key': 'mild_thinness', 'height': 150, 'weight': 91.718}, + {'key': 'mild_thinness', 'height': 200, 'weight': 163.054}, + {'key': 'normal_range', 'height': 150, 'weight': 123.960}, + {'key': 'normal_range', 'height': 200, 'weight': 220.374}, + {'key': 'pre_obese', 'height': 150, 'weight': 148.762}, + {'key': 'pre_obese', 'height': 200, 'weight': 264.467}, + {'key': 'obese_class_1', 'height': 150, 'weight': 173.564}, + {'key': 'obese_class_1', 'height': 200, 'weight': 308.559}, + {'key': 'obese_class_2', 'height': 150, 'weight': 198.366}, + {'key': 'obese_class_2', 'height': 200, 'weight': 352.651}, + {'key': 'obese_class_3', 'height': 150, 'weight': 198.416}, + {'key': 'obese_class_3', 'height': 200, 'weight': 352.740}, ] ) diff --git a/wger/nutrition/views/calculator.py b/wger/nutrition/views/calculator.py index 6112435ae..4d0f78736 100644 --- a/wger/nutrition/views/calculator.py +++ b/wger/nutrition/views/calculator.py @@ -48,13 +48,13 @@ def view(request): 'age': request.user.userprofile.age, 'height': request.user.userprofile.height, 'gender': request.user.userprofile.gender, - 'weight': request.user.userprofile.weight + 'weight': request.user.userprofile.weight, } context = { 'form': BmrForm(initial=form_data), 'form_activities': PhysicalActivitiesForm(instance=request.user.userprofile), - 'form_calories': DailyCaloriesForm(instance=request.user.userprofile) + 'form_calories': DailyCaloriesForm(instance=request.user.userprofile), } return render(request, 'rate/form.html', context) diff --git a/wger/nutrition/views/ingredient.py b/wger/nutrition/views/ingredient.py index 6d2094b71..25659d990 100644 --- a/wger/nutrition/views/ingredient.py +++ b/wger/nutrition/views/ingredient.py @@ -70,6 +70,7 @@ class IngredientListView(ListView): """ Show an overview of all ingredients """ + model = Ingredient template_name = 'ingredient/overview.html' context_object_name = 'ingredients_list' @@ -93,11 +94,7 @@ def view(request, pk, slug=None): context['ingredient'] = ingredient context['image'] = ingredient.get_image(request) context['form'] = UnitChooserForm( - data={ - 'ingredient_id': ingredient.id, - 'amount': 100, - 'unit': None - } + data={'ingredient_id': ingredient.id, 'amount': 100, 'unit': None} ) return render(request, 'ingredient/view.html', context) @@ -150,6 +147,7 @@ class IngredientCreateView(WgerFormMixin, CreateView): """ Generic view to add a new ingredient """ + template_name = 'form.html' model = Ingredient form_class = IngredientForm diff --git a/wger/nutrition/views/plan.py b/wger/nutrition/views/plan.py index 94cdfe4d0..c8558a525 100644 --- a/wger/nutrition/views/plan.py +++ b/wger/nutrition/views/plan.py @@ -141,15 +141,17 @@ def export_pdf(request, id: int): p = Paragraph( '{nr} {meal_nr}'.format( nr=_('Nr.'), meal_nr=i - ), styleSheet["SubHeader"] + ), + styleSheet['SubHeader'], ) else: p = Paragraph( '' '{nr} {meal_nr} - {meal_time}' ''.format( - nr=_('Nr.'), meal_nr=i, meal_time=meal.time.strftime("%H:%M") - ), styleSheet["SubHeader"] + nr=_('Nr.'), meal_nr=i, meal_time=meal.time.strftime('%H:%M') + ), + styleSheet['SubHeader'], ) data.append([p]) @@ -157,14 +159,14 @@ def export_pdf(request, id: int): for item in meal.mealitem_set.select_related(): ingredient_markers.append(len(data)) - p = Paragraph('{0}'.format(item.ingredient.name), styleSheet["Normal"]) + p = Paragraph('{0}'.format(item.ingredient.name), styleSheet['Normal']) if item.get_unit_type() == MEALITEM_WEIGHT_GRAM: unit_name = 'g' else: unit_name = ' × ' + item.weight_unit.unit.name data.append( - [Paragraph("{0:.0f}{1}".format(item.amount, unit_name), styleSheet["Normal"]), p] + [Paragraph('{0:.0f}{1}'.format(item.amount, unit_name), styleSheet['Normal']), p] ) # Add filler @@ -192,7 +194,7 @@ def export_pdf(request, id: int): # There is nothing to output else: t = Paragraph( - _('This is an empty plan, what did you expect on the PDF?'), styleSheet["Normal"] + _('This is an empty plan, what did you expect on the PDF?'), styleSheet['Normal'] ) # Add site logo @@ -202,8 +204,9 @@ def export_pdf(request, id: int): # Set the title (if available) if plan.description: p = Paragraph( - '%(description)s' % - {'description': plan.description}, styleSheet["HeaderBold"] + '%(description)s' + % {'description': plan.description}, + styleSheet['HeaderBold'], ) elements.append(p) @@ -212,7 +215,7 @@ def export_pdf(request, id: int): # append the table to the document elements.append(t) - elements.append(Paragraph(' ', styleSheet["Normal"])) + elements.append(Paragraph(' ', styleSheet['Normal'])) # Create table with nutritional calculations data = [] @@ -220,70 +223,70 @@ def export_pdf(request, id: int): [ Paragraph( '{0}'.format(_('Nutritional data')), - styleSheet["SubHeaderBlack"] + styleSheet['SubHeaderBlack'], ) ] ) data.append( [ - Paragraph(_('Macronutrients'), styleSheet["Normal"]), - Paragraph(_('Total'), styleSheet["Normal"]), - Paragraph(_('Percent of energy'), styleSheet["Normal"]), - Paragraph(_('g per body kg'), styleSheet["Normal"]) + Paragraph(_('Macronutrients'), styleSheet['Normal']), + Paragraph(_('Total'), styleSheet['Normal']), + Paragraph(_('Percent of energy'), styleSheet['Normal']), + Paragraph(_('g per body kg'), styleSheet['Normal']), ] ) data.append( [ - Paragraph(_('Energy'), styleSheet["Normal"]), - Paragraph(str(plan_data['total'].energy), styleSheet["Normal"]) + Paragraph(_('Energy'), styleSheet['Normal']), + Paragraph(str(plan_data['total'].energy), styleSheet['Normal']), ] ) data.append( [ - Paragraph(_('Protein'), styleSheet["Normal"]), - Paragraph(str(plan_data['total'].protein), styleSheet["Normal"]), - Paragraph(str(plan_data['percent']['protein']), styleSheet["Normal"]), - Paragraph(str(plan_data['per_kg']['protein']), styleSheet["Normal"]) + Paragraph(_('Protein'), styleSheet['Normal']), + Paragraph(str(plan_data['total'].protein), styleSheet['Normal']), + Paragraph(str(plan_data['percent']['protein']), styleSheet['Normal']), + Paragraph(str(plan_data['per_kg']['protein']), styleSheet['Normal']), ] ) data.append( [ - Paragraph(_('Carbohydrates'), styleSheet["Normal"]), - Paragraph(str(plan_data['total'].carbohydrates), styleSheet["Normal"]), - Paragraph(str(plan_data['percent']['carbohydrates']), styleSheet["Normal"]), - Paragraph(str(plan_data['per_kg']['carbohydrates']), styleSheet["Normal"]) + Paragraph(_('Carbohydrates'), styleSheet['Normal']), + Paragraph(str(plan_data['total'].carbohydrates), styleSheet['Normal']), + Paragraph(str(plan_data['percent']['carbohydrates']), styleSheet['Normal']), + Paragraph(str(plan_data['per_kg']['carbohydrates']), styleSheet['Normal']), ] ) data.append( [ - Paragraph(" " + _('Sugar content in carbohydrates'), styleSheet["Normal"]), - Paragraph(str(plan_data['total'].carbohydrates_sugar), styleSheet["Normal"]) + Paragraph(' ' + _('Sugar content in carbohydrates'), styleSheet['Normal']), + Paragraph(str(plan_data['total'].carbohydrates_sugar), styleSheet['Normal']), ] ) data.append( [ - Paragraph(_('Fat'), styleSheet["Normal"]), - Paragraph(str(plan_data['total'].fat), styleSheet["Normal"]), - Paragraph(str(plan_data['percent']['fat']), styleSheet["Normal"]), - Paragraph(str(plan_data['per_kg']['fat']), styleSheet["Normal"]) + Paragraph(_('Fat'), styleSheet['Normal']), + Paragraph(str(plan_data['total'].fat), styleSheet['Normal']), + Paragraph(str(plan_data['percent']['fat']), styleSheet['Normal']), + Paragraph(str(plan_data['per_kg']['fat']), styleSheet['Normal']), ] ) data.append( [ - Paragraph(_('Saturated fat content in fats'), styleSheet["Normal"]), - Paragraph(str(plan_data['total'].fat_saturated), styleSheet["Normal"]) + Paragraph(_('Saturated fat content in fats'), styleSheet['Normal']), + Paragraph(str(plan_data['total'].fat_saturated), styleSheet['Normal']), ] ) data.append( [ - Paragraph(_('Fibres'), styleSheet["Normal"]), - Paragraph(str(plan_data['total'].fibres), styleSheet["Normal"]) + Paragraph(_('Fibres'), styleSheet['Normal']), + Paragraph(str(plan_data['total'].fibres), styleSheet['Normal']), ] ) data.append( [ - Paragraph(_('Sodium'), styleSheet["Normal"]), - Paragraph(str(plan_data['total'].sodium), styleSheet["Normal"]) + Paragraph(_('Sodium'), styleSheet['Normal']), + Paragraph(str(plan_data['total'].sodium), styleSheet['Normal']), ] ) diff --git a/wger/software/urls.py b/wger/software/urls.py index d4b756f44..ea8e0207a 100644 --- a/wger/software/urls.py +++ b/wger/software/urls.py @@ -29,7 +29,7 @@ from wger.software import views urlpatterns = [ path( 'terms-of-service', - TemplateView.as_view(template_name="tos.html"), + TemplateView.as_view(template_name='tos.html'), name='tos', ), path( @@ -45,13 +45,13 @@ urlpatterns = [ path( 'about-us', TemplateView.as_view( - template_name="about_us.html", extra_context={'version': get_version()} + template_name='about_us.html', extra_context={'version': get_version()} ), name='about-us', ), path( 'api', - TemplateView.as_view(template_name="api.html"), + TemplateView.as_view(template_name='api.html'), name='api', ), ] diff --git a/wger/software/views.py b/wger/software/views.py index 5127630d3..970efaec3 100644 --- a/wger/software/views.py +++ b/wger/software/views.py @@ -54,10 +54,11 @@ def features(request): } cache.set(CACHE_KEY, context, 60 * 60 * 24 * 7) # one week - FormClass = RegistrationForm if settings.WGER_SETTINGS['USE_RECAPTCHA'] \ - else RegistrationFormNoCaptcha + FormClass = ( + RegistrationForm if settings.WGER_SETTINGS['USE_RECAPTCHA'] else RegistrationFormNoCaptcha + ) form = FormClass() - form.fields['username'].widget.attrs.pop("autofocus", None) + form.fields['username'].widget.attrs.pop('autofocus', None) context['form'] = form context['allow_registration'] = settings.WGER_SETTINGS['ALLOW_REGISTRATION'] diff --git a/wger/tasks.py b/wger/tasks.py index 69ba724b3..7c935d529 100644 --- a/wger/tasks.py +++ b/wger/tasks.py @@ -41,15 +41,11 @@ FIXTURE_URL = 'https://github.com/wger-project/data/raw/master/fixtures/' @task( help={ - 'address': - 'Address to bind to. Default: localhost', - 'port': - 'Port to use. Default: 8000', - 'settings-path': - 'Path to settings file (absolute path). Leave empty for default', - 'extra-args': - 'Additional arguments to pass to the builtin server. Pass as string: ' - '"--arg1 --arg2=value". Default: none' + 'address': 'Address to bind to. Default: localhost', + 'port': 'Port to use. Default: 8000', + 'settings-path': 'Path to settings file (absolute path). Leave empty for default', + 'extra-args': 'Additional arguments to pass to the builtin server. Pass as string: ' + '"--arg1 --arg2=value". Default: none', } ) def start(context, address='localhost', port=8000, settings_path=None, extra_args=''): @@ -60,18 +56,18 @@ def start(context, address='localhost', port=8000, settings_path=None, extra_arg # Find the path to the settings and setup the django environment setup_django_environment(settings_path) - argv = ["", "runserver", '--noreload'] + argv = ['', 'runserver', '--noreload'] if extra_args != '': for argument in extra_args.split(' '): argv.append(argument) - argv.append("{0}:{1}".format(address, port)) + argv.append('{0}:{1}'.format(address, port)) execute_from_command_line(argv) @task( help={ 'settings-path': 'Path to settings file (absolute path). Leave empty for default', - 'database-path': 'Path to sqlite database (absolute path). Leave empty for default' + 'database-path': 'Path to sqlite database (absolute path). Leave empty for default', } ) def bootstrap(context, settings_path=None, database_path=None): @@ -96,8 +92,8 @@ def bootstrap(context, settings_path=None, database_path=None): create_or_reset_admin(context, settings_path=settings_path) # Download JS and CSS libraries - context.run("yarn install") - context.run("yarn build:css:sass") + context.run('yarn install') + context.run('yarn build:css:sass') @task( @@ -105,7 +101,7 @@ def bootstrap(context, settings_path=None, database_path=None): 'settings-path': 'Path to settings file (absolute path). Leave empty for default', 'database-path': 'Path to sqlite database (absolute path). Leave empty for default', 'database-type': 'Database type to use. Supported: sqlite3, postgresql. Default: sqlite3', - 'key-length': 'Length of the generated secret key. Default: 50' + 'key-length': 'Length of the generated secret key. Default: 50', } ) def create_settings( @@ -118,7 +114,7 @@ def create_settings( settings_path = get_path('settings.py') settings_module = os.path.dirname(settings_path) - print("*** Creating settings file at {0}".format(settings_module)) + print('*** Creating settings file at {0}'.format(settings_module)) if database_path is None: database_path = get_path('database.sqlite').as_posix() @@ -163,7 +159,7 @@ def create_settings( dbport=dbport, default_key=secret_key, siteurl=url, - media_folder_path=media_folder_path + media_folder_path=media_folder_path, ) if not os.path.exists(settings_module): @@ -189,16 +185,17 @@ def create_or_reset_admin(context, settings_path=None): # the settings module during import # Django from django.contrib.auth.models import User + try: - User.objects.get(username="admin") + User.objects.get(username='admin') print("*** Password for user admin was reset to 'adminadmin'") except User.DoesNotExist: - print("*** Created default admin user") + print('*** Created default admin user') current_dir = os.path.dirname(os.path.abspath(__file__)) path = os.path.join(current_dir, 'core', 'fixtures/') - call_command("loaddata", path + "users.json") + call_command('loaddata', path + 'users.json') @task(help={'settings-path': 'Path to settings file (absolute path). Leave empty for default'}) @@ -210,7 +207,7 @@ def migrate_db(context, settings_path=None): # Find the path to the settings and setup the django environment setup_django_environment(settings_path) - call_command("migrate") + call_command('migrate') @task(help={'settings-path': 'Path to settings file (absolute path). Leave empty for default'}) @@ -223,37 +220,36 @@ def load_fixtures(context, settings_path=None): setup_django_environment(settings_path) # Gym - call_command("loaddata", "gym.json") + call_command('loaddata', 'gym.json') # Core - call_command("loaddata", "languages.json") - call_command("loaddata", "groups.json") - call_command("loaddata", "users.json") - call_command("loaddata", "licenses.json") - call_command("loaddata", "days_of_week.json") - call_command("loaddata", "setting_repetition_units.json") - call_command("loaddata", "setting_weight_units.json") + call_command('loaddata', 'languages.json') + call_command('loaddata', 'groups.json') + call_command('loaddata', 'users.json') + call_command('loaddata', 'licenses.json') + call_command('loaddata', 'days_of_week.json') + call_command('loaddata', 'setting_repetition_units.json') + call_command('loaddata', 'setting_weight_units.json') # Config - call_command("loaddata", "gym_config.json") + call_command('loaddata', 'gym_config.json') # Manager # Exercises - call_command("loaddata", "equipment.json") - call_command("loaddata", "muscles.json") - call_command("loaddata", "categories.json") - call_command("loaddata", "exercise-base-data.json") - call_command("loaddata", "translations.json") + call_command('loaddata', 'equipment.json') + call_command('loaddata', 'muscles.json') + call_command('loaddata', 'categories.json') + call_command('loaddata', 'exercise-base-data.json') + call_command('loaddata', 'translations.json') # Gym - call_command("loaddata", "gym.json") - call_command("loaddata", "gym-config.json") - call_command("loaddata", "gym-adminconfig.json") + call_command('loaddata', 'gym.json') + call_command('loaddata', 'gym-config.json') + call_command('loaddata', 'gym-adminconfig.json') -@task(help={'settings-path': 'Path to settings file (absolute path). Leave empty for ' - 'default'}) +@task(help={'settings-path': 'Path to settings file (absolute path). Leave empty for ' 'default'}) def load_online_fixtures(context, settings_path=None): """ Downloads fixtures from server and installs them (at the moment only ingredients) @@ -268,8 +264,8 @@ def load_online_fixtures(context, settings_path=None): print(f'Downloading fixture data from {url}...') response = requests.get(url, stream=True) - total_size = int(response.headers.get("content-length", 0)) - size = int(response.headers["content-length"]) / (1024 * 1024) + total_size = int(response.headers.get('content-length', 0)) + size = int(response.headers['content-length']) / (1024 * 1024) print(f'-> fixture size: {size:.3} MB') # Save to temporary file and load the data @@ -281,7 +277,7 @@ def load_online_fixtures(context, settings_path=None): pbar.update(len(data)) f.close() print('Loading downloaded data, this may take a while...') - call_command("loaddata", f.name, '--verbosity=3') + call_command('loaddata', f.name, '--verbosity=3') print('-> removing temp file') print('') os.unlink(f.name) @@ -308,7 +304,7 @@ def config_location(context): # -def get_path(file="settings.py") -> pathlib.Path: +def get_path(file='settings.py') -> pathlib.Path: """ Return the path of the given file relatively to the wger source folder @@ -331,7 +327,7 @@ def setup_django_environment(settings_path): # Find out file path and fine name of settings and setup django settings_file = os.path.basename(settings_path) - settings_module_name = "".join(settings_file.split('.')[:-1]) + settings_module_name = ''.join(settings_file.split('.')[:-1]) if '.' in settings_module_name: print("'.' is not an allowed character in the settings-file") sys.exit(1) @@ -357,7 +353,7 @@ def database_exists(): except DatabaseError: return False except ImproperlyConfigured: - print("Your settings file seems broken") + print('Your settings file seems broken') sys.exit(0) else: return True diff --git a/wger/urls.py b/wger/urls.py index 67f52a016..6f35ca87e 100644 --- a/wger/urls.py +++ b/wger/urls.py @@ -88,7 +88,7 @@ router.register(r'userprofile', core_api_views.UserProfileViewSet, basename='use router.register( r'setting-repetitionunit', core_api_views.RepetitionUnitViewSet, - basename='setting-repetition-unit' + basename='setting-repetition-unit', ) router.register( r'setting-weightunit', core_api_views.RoutineWeightUnitViewSet, basename='setting-weight-unit' @@ -175,15 +175,13 @@ router.register(r'weightunit', nutrition_api_views.WeightUnitViewSet, basename=' router.register( r'ingredientweightunit', nutrition_api_views.IngredientWeightUnitViewSet, - basename='ingredientweightunit' + basename='ingredientweightunit', ) router.register( r'nutritionplan', nutrition_api_views.NutritionPlanViewSet, basename='nutritionplan' ) router.register( - r'nutritionplaninfo', - nutrition_api_views.NutritionPlanInfoViewSet, - basename='nutritionplaninfo' + r'nutritionplaninfo', nutrition_api_views.NutritionPlanInfoViewSet, basename='nutritionplaninfo' ) router.register(r'nutritiondiary', nutrition_api_views.LogItemViewSet, basename='nutritiondiary') router.register(r'meal', nutrition_api_views.MealViewSet, basename='meal') @@ -228,27 +226,27 @@ urlpatterns = i18n_patterns( path('gallery/', include(('wger.gallery.urls', 'gallery'), namespace='gallery')), path( 'measurement/', - include(('wger.measurements.urls', 'measurements'), namespace='measurements') - ), path('email/', include(('wger.mailer.urls', 'email'), namespace='email')), + include(('wger.measurements.urls', 'measurements'), namespace='measurements'), + ), + path('email/', include(('wger.mailer.urls', 'email'), namespace='email')), path('sitemap.xml', index, {'sitemaps': sitemaps}, name='sitemap'), path( 'sitemap-
.xml', - sitemap, {'sitemaps': sitemaps}, - name='django.contrib.sitemaps.views.sitemap' - ) + sitemap, + {'sitemaps': sitemaps}, + name='django.contrib.sitemaps.views.sitemap', + ), ) # # URLs without language prefix # urlpatterns += [ - path('robots.txt', TextTemplateView.as_view(template_name="robots.txt"), name='robots'), - + path('robots.txt', TextTemplateView.as_view(template_name='robots.txt'), name='robots'), # API path('api/v2/exercise/search/', exercises_api_views.search, name='exercise-search'), path('api/v2/ingredient/search/', nutrition_api_views.search, name='ingredient-search'), path('api/v2/', include(router.urls)), - # The api user login path( 'api/v2/login/', core_api_views.UserAPILoginView.as_view({'post': 'post'}), name='api_user' @@ -256,29 +254,27 @@ urlpatterns += [ path( 'api/v2/register/', core_api_views.UserAPIRegistrationViewSet.as_view({'post': 'post'}), - name='api_register' + name='api_register', ), path('api/v2/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'), path('api/v2/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'), path('api/v2/token/verify/', TokenVerifyView.as_view(), name='token_verify'), - # Others path( 'api/v2/version/', core_api_views.ApplicationVersionView.as_view({'get': 'get'}), - name='app_version' + name='app_version', ), path( 'api/v2/check-permission/', core_api_views.PermissionView.as_view({'get': 'get'}), - name='permission' + name='permission', ), path( 'api/v2/min-app-version/', core_api_views.RequiredApplicationVersionView.as_view({'get': 'get'}), - name='min_app_version' + name='min_app_version', ), - # Api documentation path( 'api/v2/schema', diff --git a/wger/utils/constants.py b/wger/utils/constants.py index ce9242860..144be1f2d 100644 --- a/wger/utils/constants.py +++ b/wger/utils/constants.py @@ -41,7 +41,7 @@ DATE_FORMATS = [ # editor. Everything not in these whitelists is stripped. HTML_TAG_WHITELIST = {'b', 'i', 'strong', 'em', 'ul', 'ol', 'li', 'p'} HTML_ATTRIBUTES_WHITELIST = {'*': 'style'} -HTML_STYLES_WHITELIST = ('text-decoration', ) +HTML_STYLES_WHITELIST = ('text-decoration',) # Pagination PAGINATION_OBJECTS_PER_PAGE = 25 diff --git a/wger/utils/context_processor.py b/wger/utils/context_processor.py index 834a59b75..81cb46aff 100644 --- a/wger/utils/context_processor.py +++ b/wger/utils/context_processor.py @@ -79,9 +79,11 @@ def processor(request): # yapf: enable # Pseudo-intelligent navigation here - if '/software/' in request.get_full_path() \ - or '/contact' in request.get_full_path() \ - or '/api/v2' in request.get_full_path(): + if ( + '/software/' in request.get_full_path() + or '/contact' in request.get_full_path() + or '/api/v2' in request.get_full_path() + ): context['active_tab'] = constants.SOFTWARE_TAB elif '/exercise/' in request.get_full_path(): diff --git a/wger/utils/generic_views.py b/wger/utils/generic_views.py index 841996f73..c140161cd 100644 --- a/wger/utils/generic_views.py +++ b/wger/utils/generic_views.py @@ -211,7 +211,7 @@ class WgerFormMixin(ModelFormMixin): def get_form(self, form_class=None): """Return an instance of the form to be used in this view.""" form = super(WgerFormMixin, self).get_form(form_class) - if not hasattr(form, "helper"): + if not hasattr(form, 'helper'): form.helper = FormHelper() form.helper.form_id = slugify(self.request.path) form.helper.form_method = 'post' @@ -238,14 +238,15 @@ class WgerFormMixin(ModelFormMixin): for field in self.clean_html: setattr( - form.instance, field, + form.instance, + field, bleach.clean( getattr(form.instance, field), tags=HTML_TAG_WHITELIST, attributes=HTML_ATTRIBUTES_WHITELIST, css_sanitizer=CSSSanitizer(allowed_css_properties=HTML_STYLES_WHITELIST), - strip=True - ) + strip=True, + ), ) if self.get_messages(): @@ -282,7 +283,7 @@ class WgerDeleteMixin: def get_form(self, form_class=None): """Return an instance of the form to be used in this view.""" form = super(WgerDeleteMixin, self).get_form(form_class) - if not hasattr(form, "helper"): + if not hasattr(form, 'helper'): form.helper = FormHelper() form.helper.form_id = slugify(self.request.path) form.helper.form_method = 'post' diff --git a/wger/utils/helpers.py b/wger/utils/helpers.py index f43081ad4..f66f0d0f7 100644 --- a/wger/utils/helpers.py +++ b/wger/utils/helpers.py @@ -42,7 +42,6 @@ logger = logging.getLogger(__name__) class EmailAuthBackend: - def authenticate(self, request, username=None, password=None): try: user = User.objects.get(email=username) @@ -146,7 +145,7 @@ def check_token(uidb64, token): try: uid = int(urlsafe_base64_decode(uidb64)) except ValueError as e: - logger.info("Could not decode UID: {0}".format(e)) + logger.info('Could not decode UID: {0}'.format(e)) return False try: @@ -169,7 +168,7 @@ def password_generator(length=15): :return: the generated password """ chars = string.ascii_letters + string.digits - random.seed = (os.urandom(1024)) + random.seed = os.urandom(1024) for char in ('I', '1', 'l', 'O', '0', 'o'): chars = chars.replace(char, '') @@ -219,7 +218,7 @@ def normalize_decimal(d): normalized = d.normalize() sign, digits, exponent = normalized.as_tuple() if exponent > 0: - return decimal.Decimal((sign, digits + (0, ) * exponent, 0)) + return decimal.Decimal((sign, digits + (0,) * exponent, 0)) else: return normalized @@ -232,7 +231,6 @@ def random_string(length=32): class BaseImage: - def save_image(self, retrieved_image, json_data: dict): # Save the downloaded image # http://stackoverflow.com/questions/1308386/programmatically-saving-image-to diff --git a/wger/utils/language.py b/wger/utils/language.py index 553561129..1e6aedb0d 100644 --- a/wger/utils/language.py +++ b/wger/utils/language.py @@ -34,9 +34,9 @@ def load_language(language_code=None): """ # Read the first part of a composite language, e.g. 'de-at' - used_language = translation.get_language().split('-')[0] \ - if language_code is None \ - else language_code + used_language = ( + translation.get_language().split('-')[0] if language_code is None else language_code + ) language = cache.get(cache_mapper.get_language_key(used_language)) if language: @@ -55,5 +55,5 @@ def get_language_data(language): return { 'name': language[1], 'code': language[0], - 'path': f'images/icons/flags/{language[0]}.svg' + 'path': f'images/icons/flags/{language[0]}.svg', } diff --git a/wger/utils/managers.py b/wger/utils/managers.py index 5696d8de0..f70717b7e 100644 --- a/wger/utils/managers.py +++ b/wger/utils/managers.py @@ -30,7 +30,6 @@ Custom managers and querysets class SubmissionQuerySet(QuerySet): - def accepted(self): return self.filter(status=AbstractSubmissionModel.STATUS_ACCEPTED) @@ -39,7 +38,6 @@ class SubmissionQuerySet(QuerySet): class SubmissionManager(models.Manager): - def get_queryset(self): return SubmissionQuerySet(self.model, using=self._db) diff --git a/wger/utils/middleware.py b/wger/utils/middleware.py index d86654bb6..fdde69f6a 100644 --- a/wger/utils/middleware.py +++ b/wger/utils/middleware.py @@ -31,7 +31,7 @@ from wger.core.demo import create_temporary_user logger = logging.getLogger(__name__) -SPECIAL_PATHS = ('dashboard', ) +SPECIAL_PATHS = ('dashboard',) def check_current_request(request): @@ -55,7 +55,6 @@ def check_current_request(request): def get_user(request): if not hasattr(request, '_cached_user'): - create_user = check_current_request(request) user = auth.get_user(request) @@ -64,9 +63,12 @@ def get_user(request): request.session['has_demo_data'] = False # Django didn't find a user, so create one now - if settings.WGER_SETTINGS['ALLOW_GUEST_USERS'] and \ - request.method == 'GET' and \ - create_user and not user.is_authenticated: + if ( + settings.WGER_SETTINGS['ALLOW_GUEST_USERS'] + and request.method == 'GET' + and create_user + and not user.is_authenticated + ): logger.debug('creating a new guest user now') user = create_temporary_user(request) django_login(request, user) @@ -83,8 +85,8 @@ class WgerAuthenticationMiddleware(MiddlewareMixin): """ def process_request(self, request): - assert hasattr(request, 'session'), "The Django authentication middleware requires " - "session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert" + assert hasattr(request, 'session'), 'The Django authentication middleware requires ' + 'session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert' "'django.contrib.sessions.middleware.SessionMiddleware'." request.user = SimpleLazyObject(lambda: get_user(request)) diff --git a/wger/utils/models.py b/wger/utils/models.py index 1c1bcf83c..bfd80c8af 100644 --- a/wger/utils/models.py +++ b/wger/utils/models.py @@ -64,7 +64,7 @@ class AbstractLicenseModel(models.Model): max_length=600, blank=True, null=True, - help_text=_('If you are not the author, enter the name or source here.') + help_text=_('If you are not the author, enter the name or source here.'), ) license_author_url = models.URLField( @@ -102,8 +102,10 @@ class AbstractLicenseModel(models.Model): out += f' is licensed under {self.license.short_name}' if self.license_derivative_source_url: - out += f'/ A derivative work from the ' \ - f'original work' + out += ( + f'/ A derivative work from the ' + f'original work' + ) return out diff --git a/wger/utils/pdf.py b/wger/utils/pdf.py index 7d81ab1cc..a995e543b 100644 --- a/wger/utils/pdf.py +++ b/wger/utils/pdf.py @@ -60,7 +60,7 @@ def load_language(): # No luck, load english as our fall-back language except ObjectDoesNotExist: - language = Language.objects.get(short_name="en") + language = Language.objects.get(short_name='en') return language @@ -71,7 +71,7 @@ def render_footer(url, date=None): :return: a Paragraph object """ if not date: - date = datetime.date.today().strftime("%d.%m.%Y") + date = datetime.date.today().strftime('%d.%m.%Y') p = Paragraph( """ @@ -80,7 +80,7 @@ def render_footer(url, date=None): wger Workout Manager {version} """.format(date=date, url=url, version=get_version()), - styleSheet["Normal"] + styleSheet['Normal'], ) return p @@ -110,22 +110,26 @@ pdfmetrics.registerFont( pdfmetrics.registerFont( TTFont( 'OpenSans-Italic', - path_join(settings.SITE_ROOT, 'core/static/fonts/OpenSans-LightItalic.ttf') + path_join(settings.SITE_ROOT, 'core/static/fonts/OpenSans-LightItalic.ttf'), ) ) styleSheet = StyleSheet1() -styleSheet.add(ParagraphStyle( - name='Normal', - fontName='OpenSans', - fontSize=10, - leading=12, -)) -styleSheet.add(ParagraphStyle( - parent=styleSheet['Normal'], - fontSize=8, - name='Small', -)) +styleSheet.add( + ParagraphStyle( + name='Normal', + fontName='OpenSans', + fontSize=10, + leading=12, + ) +) +styleSheet.add( + ParagraphStyle( + parent=styleSheet['Normal'], + fontSize=8, + name='Small', + ) +) styleSheet.add( ParagraphStyle( parent=styleSheet['Normal'], @@ -147,7 +151,7 @@ styleSheet.add( parent=styleSheet['Normal'], name='SubHeader', fontName='OpenSans-Bold', - textColor=colors.white + textColor=colors.white, ) ) styleSheet.add( @@ -155,9 +159,9 @@ styleSheet.add( parent=styleSheet['Normal'], name='SubHeaderBlack', fontName='OpenSans-Bold', - textColor=colors.black + textColor=colors.black, ) ) -header_colour = HexColor(0x24416b) -row_color = HexColor(0xd1def0) +header_colour = HexColor(0x24416B) +row_color = HexColor(0xD1DEF0) diff --git a/wger/utils/permissions.py b/wger/utils/permissions.py index 1a10d167b..969910003 100644 --- a/wger/utils/permissions.py +++ b/wger/utils/permissions.py @@ -67,9 +67,8 @@ class CreateOnlyPermission(permissions.BasePermission): """ def has_permission(self, request, view): - return ( - request.method in ['GET', 'HEAD', 'OPTIONS'] - or (request.user and request.user.is_authenticated and request.method == 'POST') + return request.method in ['GET', 'HEAD', 'OPTIONS'] or ( + request.user and request.user.is_authenticated and request.method == 'POST' ) @@ -81,6 +80,7 @@ class UpdateOnlyPermission(permissions.BasePermission): def has_permission(self, request, view): return ( - request.user and request.user.is_authenticated + request.user + and request.user.is_authenticated and request.method in ['GET', 'HEAD', 'OPTIONS', 'PATCH'] ) diff --git a/wger/utils/tests/test_url.py b/wger/utils/tests/test_url.py index f78ac8ba4..f7dc6fb6a 100644 --- a/wger/utils/tests/test_url.py +++ b/wger/utils/tests/test_url.py @@ -20,47 +20,43 @@ from wger.utils.url import make_uri class TestMakeUri(unittest.TestCase): - def test_make_uri(self): # Test default server_url self.assertEqual( - make_uri("test"), - "https://wger.de/api/v2/test/", + make_uri('test'), + 'https://wger.de/api/v2/test/', ) # Test custom server_url self.assertEqual( - make_uri("test", server_url="https://api.example.com"), - "https://api.example.com/api/v2/test/" + make_uri('test', server_url='https://api.example.com'), + 'https://api.example.com/api/v2/test/', ) # Test with id self.assertEqual( - make_uri("test", id=123), - "https://wger.de/api/v2/test/123/", + make_uri('test', id=123), + 'https://wger.de/api/v2/test/123/', ) # Test with object_method self.assertEqual( - make_uri("test", object_method="create"), - "https://wger.de/api/v2/test/create/", + make_uri('test', object_method='create'), + 'https://wger.de/api/v2/test/create/', ) # Test with query parameters self.assertEqual( - make_uri("endpoint", query={ - "key1": "value1", - "key2": "value2" - }), - "https://wger.de/api/v2/endpoint/?key1=value1&key2=value2", + make_uri('endpoint', query={'key1': 'value1', 'key2': 'value2'}), + 'https://wger.de/api/v2/endpoint/?key1=value1&key2=value2', ) # Test with all parameters self.assertEqual( - make_uri("test", id=123, object_method="create", query={"key1": "value1"}), - "https://wger.de/api/v2/test/123/create/?key1=value1", + make_uri('test', id=123, object_method='create', query={'key1': 'value1'}), + 'https://wger.de/api/v2/test/123/create/?key1=value1', ) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/wger/utils/units.py b/wger/utils/units.py index 4bf767c5f..c01330c2f 100644 --- a/wger/utils/units.py +++ b/wger/utils/units.py @@ -140,7 +140,7 @@ class AbstractHeight(object): height = self.normalize(height) self.height = height - self.is_cm = (mode == 'cm') + self.is_cm = mode == 'cm' @staticmethod def normalize(value): diff --git a/wger/utils/url.py b/wger/utils/url.py index 8c37a3b24..3f9183635 100644 --- a/wger/utils/url.py +++ b/wger/utils/url.py @@ -31,7 +31,7 @@ def make_uri( id: Optional[int] = None, object_method: Optional[str] = None, query: Optional[Dict[str, any]] = None, - server_url: str = settings.WGER_SETTINGS['WGER_INSTANCE'] + server_url: str = settings.WGER_SETTINGS['WGER_INSTANCE'], ): uri_server = urlparse(server_url) query = query or {} @@ -49,7 +49,7 @@ def make_uri( uri_server.netloc, '/'.join(path_list) + '/', '', - '&'.join([f"{key}={value}" for key, value in query.items()]), + '&'.join([f'{key}={value}' for key, value in query.items()]), '', ) ) diff --git a/wger/utils/widgets.py b/wger/utils/widgets.py index 9ce731563..b743f8d46 100644 --- a/wger/utils/widgets.py +++ b/wger/utils/widgets.py @@ -49,6 +49,7 @@ class Html5DateInput(DateInput): """ Custom Input class that is rendered with an HTML5 type="date" """ + template_name = 'forms/html5_date.html' input_type = 'date' @@ -66,6 +67,7 @@ class Html5FormDateField(fields.DateField): """ HTML5 form date field """ + widget = Html5DateInput @@ -76,6 +78,7 @@ class Html5TimeInput(TextInput): This is specially useful in mobile devices and not available with older versions of django. """ + input_type = 'time' @@ -83,6 +86,7 @@ class Html5FormTimeField(fields.TimeField): """ HTML5 form time field """ + widget = Html5TimeInput @@ -98,6 +102,7 @@ class Html5NumberInput(TextInput): This is specially useful in mobile devices and not available with older versions of django. """ + input_type = 'number' @@ -116,8 +121,10 @@ class ExerciseAjaxSelect(SelectMultiple): value = [] output = [ - '
', '', '
', - '
' + '
', + '', + '
', + '
', ] options = self.render_options(choices, value) @@ -138,7 +145,6 @@ class ExerciseAjaxSelect(SelectMultiple): def render_option(self, selected_choices, option_value, option_label): option_value = force_str(option_value) if option_value in selected_choices: - return """
@@ -152,7 +158,7 @@ class ExerciseAjaxSelect(SelectMultiple): """ % { 'value': conditional_escape(force_str(option_label)), 'id': escape(option_value), - 'div_id': uuid.uuid4() + 'div_id': uuid.uuid4(), } else: @@ -165,6 +171,7 @@ class CheckboxChoiceInputTranslated(CheckboxInput): This only translated the text for the select widgets """ + input_type = 'checkbox' def __init__(self, name, value, attrs, choice, index): @@ -180,16 +187,18 @@ class CheckboxChoiceInputTranslatedOriginal(CheckboxInput): This only translated the text for the select widgets, showing the original string as well. """ + input_type = 'checkbox' def __init__(self, name, value, attrs, choice, index): if _(choice[1]) != choice[1]: - choice = (choice[0], "{0} ({1})".format(choice[1], _(choice[1]))) + choice = (choice[0], '{0} ({1})'.format(choice[1], _(choice[1]))) else: choice = (choice[0], _(choice[1])) - super(CheckboxChoiceInputTranslatedOriginal, - self).__init__(name, value, attrs, choice, index) + super(CheckboxChoiceInputTranslatedOriginal, self).__init__( + name, value, attrs, choice, index + ) class CheckboxFieldRendererTranslated(CheckboxSelectMultiple): @@ -214,6 +223,7 @@ class TranslatedSelectMultiple(BootstrapSelectMultiple): """ A SelectMultiple widget that translates the options """ + pass @@ -223,6 +233,7 @@ class TranslatedOriginalSelectMultiple(BootstrapSelectMultipleTranslatedOriginal string as well. This is currently only used in the muscle list, where the translated muscles as well as the latin names are shown. """ + pass @@ -232,5 +243,6 @@ class TranslatedSelect(Select): """ def render_option(self, selected_choices, option_value, option_label): - return super(TranslatedSelect, - self).render_option(selected_choices, option_value, _(option_label)) + return super(TranslatedSelect, self).render_option( + selected_choices, option_value, _(option_label) + ) diff --git a/wger/weight/api/serializers.py b/wger/weight/api/serializers.py index d629f5eba..cd3854a22 100644 --- a/wger/weight/api/serializers.py +++ b/wger/weight/api/serializers.py @@ -26,6 +26,7 @@ class WeightEntrySerializer(serializers.ModelSerializer): """ Weight serializer """ + user = serializers.PrimaryKeyRelatedField( read_only=True, default=serializers.CurrentUserDefault() ) diff --git a/wger/weight/api/views.py b/wger/weight/api/views.py index 0240cd8b6..850ad9efb 100644 --- a/wger/weight/api/views.py +++ b/wger/weight/api/views.py @@ -27,6 +27,7 @@ class WeightEntryViewSet(viewsets.ModelViewSet): """ API endpoint for nutrition plan objects """ + serializer_class = WeightEntrySerializer is_private = True @@ -38,7 +39,7 @@ class WeightEntryViewSet(viewsets.ModelViewSet): Only allow access to appropriate objects """ # REST API generation - if getattr(self, "swagger_fake_view", False): + if getattr(self, 'swagger_fake_view', False): return WeightEntry.objects.none() return WeightEntry.objects.filter(user=self.request.user) diff --git a/wger/weight/forms.py b/wger/weight/forms.py index 1dc29e487..7a3809b3f 100644 --- a/wger/weight/forms.py +++ b/wger/weight/forms.py @@ -50,6 +50,7 @@ class WeightCsvImportForm(Form): """ A helper form with only a textarea """ + csv_input = CharField(widget=Textarea, label=_('Input')) date_format = forms.ChoiceField(choices=CSV_DATE_FORMAT, label=_('Date format')) @@ -58,8 +59,8 @@ class WeightCsvImportForm(Form): self.helper = FormHelper() self.helper.layout = Layout( - "csv_input", - "date_format", + 'csv_input', + 'date_format', ) self.helper.form_tag = False diff --git a/wger/weight/helpers.py b/wger/weight/helpers.py index b14e83ef0..e4a722b75 100644 --- a/wger/weight/helpers.py +++ b/wger/weight/helpers.py @@ -40,7 +40,6 @@ logger = logging.getLogger(__name__) def parse_weight_csv(request, cleaned_data): - try: dialect = csv.Sniffer().sniff(cleaned_data['csv_input']) except csv.Error: @@ -60,8 +59,9 @@ def parse_weight_csv(request, cleaned_data): try: parsed_date = datetime.datetime.strptime(row[0], cleaned_data['date_format']) parsed_weight = decimal.Decimal(row[1].replace(',', '.')) - duplicate_date_in_db = WeightEntry.objects.filter(date=parsed_date, - user=request.user).exists() + duplicate_date_in_db = WeightEntry.objects.filter( + date=parsed_date, user=request.user + ).exists() # within the list there are no duplicate dates unique_among_csv = parsed_date not in entry_dates @@ -130,7 +130,7 @@ def group_log_entries(user, year, month, day=None): 'date': entry.date, 'workout': entry.workout, 'session': entry.get_workout_session(), - 'logs': OrderedDict() + 'logs': OrderedDict(), } if not out[entry.date]['logs'].get(entry.exercise_base): @@ -145,7 +145,7 @@ def group_log_entries(user, year, month, day=None): 'date': entry.date, 'workout': entry.workout, 'session': entry, - 'logs': {} + 'logs': {}, } cache.set(cache_mapper.get_workout_log_list(log_hash), out) @@ -165,7 +165,6 @@ def process_log_entries(logs): # Group by date for entry in logs: - if not entry_log.get(entry.date): entry_log[entry.date] = [] entry_log[entry.date].append(entry) @@ -195,11 +194,7 @@ def process_log_entries(logs): entry_list[entry.reps]['seen'].append((entry.date, entry.reps, entry.weight)) entry_list[entry.reps]['list'].append( - { - 'date': entry.date, - 'weight': entry.weight, - 'reps': entry.reps - } + {'date': entry.date, 'weight': entry.weight, 'reps': entry.reps} ) for rep in entry_list: chart_data.append(entry_list[rep]['list']) diff --git a/wger/weight/management/commands/dummy-generator-body-weight.py b/wger/weight/management/commands/dummy-generator-body-weight.py index b8978ef92..096f8be76 100644 --- a/wger/weight/management/commands/dummy-generator-body-weight.py +++ b/wger/weight/management/commands/dummy-generator-body-weight.py @@ -36,14 +36,13 @@ class Command(BaseCommand): help = 'Dummy generator for weight entries' def add_arguments(self, parser): - parser.add_argument( '--nr-entries', action='store', default=40, dest='nr_entries', type=int, - help='The number of measurement entries per category (default: 40)' + help='The number of measurement entries per category (default: 40)', ) parser.add_argument( '--user-id', @@ -58,9 +57,9 @@ class Command(BaseCommand): base_weight = 80 - users = [User.objects.get(pk=options['user_id'])] \ - if options['user_id'] \ - else User.objects.all() + users = ( + [User.objects.get(pk=options['user_id'])] if options['user_id'] else User.objects.all() + ) print(f"** Generating {options['nr_entries']} weight entries per user") @@ -72,13 +71,12 @@ class Command(BaseCommand): # Weight entries for i in range(options['nr_entries']): - creation_date = datetime.date.today() - datetime.timedelta(days=i) if creation_date not in existing_entries: entry = WeightEntry( user=user, weight=base_weight + 0.5 * i + random.randint(1, 3), - date=creation_date + date=creation_date, ) new_entries.append(entry) diff --git a/wger/weight/management/commands/email-weight-reminder.py b/wger/weight/management/commands/email-weight-reminder.py index 8df8cfcab..414390fc3 100644 --- a/wger/weight/management/commands/email-weight-reminder.py +++ b/wger/weight/management/commands/email-weight-reminder.py @@ -37,11 +37,9 @@ class Command(BaseCommand): help = 'Send out automatic emails to remind the user to enter the weight' def handle(self, **options): - profile_list = UserProfile.objects.filter(num_days_weight_reminder__gt=0) for profile in profile_list: - # Only continue if the user has provided an email address. # Checking it here so we check for NULL values and emtpy strings if not profile.user.email: @@ -74,14 +72,11 @@ class Command(BaseCommand): 'site': Site.objects.get_current(), 'date': last_entry, 'days': datediff, - 'user': user + 'user': user, } subject = _('You have to enter your weight') message = loader.render_to_string('workout/email_weight_reminder.tpl', context) mail.send_mail( - subject, - message, - settings.WGER_SETTINGS['EMAIL_FROM'], [user.email], - fail_silently=True + subject, message, settings.WGER_SETTINGS['EMAIL_FROM'], [user.email], fail_silently=True ) diff --git a/wger/weight/migrations/0001_initial.py b/wger/weight/migrations/0001_initial.py index 298c63856..120586698 100644 --- a/wger/weight/migrations/0001_initial.py +++ b/wger/weight/migrations/0001_initial.py @@ -6,7 +6,6 @@ import django.core.validators class Migration(migrations.Migration): - dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] @@ -19,7 +18,7 @@ class Migration(migrations.Migration): 'id', models.AutoField( verbose_name='ID', serialize=False, auto_created=True, primary_key=True - ) + ), ), ('creation_date', models.DateField(verbose_name='Date')), ( @@ -30,15 +29,15 @@ class Migration(migrations.Migration): decimal_places=2, validators=[ django.core.validators.MinValueValidator(30), - django.core.validators.MaxValueValidator(300) - ] - ) + django.core.validators.MaxValueValidator(300), + ], + ), ), ( 'user', models.ForeignKey( verbose_name='User', to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE - ) + ), ), ], options={ @@ -46,7 +45,7 @@ class Migration(migrations.Migration): 'get_latest_by': 'creation_date', 'verbose_name': 'Weight entry', }, - bases=(models.Model, ), + bases=(models.Model,), ), migrations.AlterUniqueTogether( name='weightentry', diff --git a/wger/weight/migrations/0002_auto_20150604_2139.py b/wger/weight/migrations/0002_auto_20150604_2139.py index 0caee53f6..34007a62d 100644 --- a/wger/weight/migrations/0002_auto_20150604_2139.py +++ b/wger/weight/migrations/0002_auto_20150604_2139.py @@ -4,7 +4,6 @@ from django.db import models, migrations class Migration(migrations.Migration): - dependencies = [ ('weight', '0001_initial'), ] @@ -12,11 +11,7 @@ class Migration(migrations.Migration): operations = [ migrations.AlterModelOptions( name='weightentry', - options={ - 'verbose_name': 'Weight entry', - 'get_latest_by': 'date', - 'ordering': ['date'] - }, + options={'verbose_name': 'Weight entry', 'get_latest_by': 'date', 'ordering': ['date']}, ), migrations.RenameField( model_name='weightentry', diff --git a/wger/weight/migrations/0003_auto_20160416_1030.py b/wger/weight/migrations/0003_auto_20160416_1030.py index 8d605985c..0481e00c4 100644 --- a/wger/weight/migrations/0003_auto_20160416_1030.py +++ b/wger/weight/migrations/0003_auto_20160416_1030.py @@ -5,7 +5,6 @@ import django.core.validators class Migration(migrations.Migration): - dependencies = [ ('weight', '0002_auto_20150604_2139'), ] @@ -19,9 +18,9 @@ class Migration(migrations.Migration): verbose_name='Weight', validators=[ django.core.validators.MinValueValidator(30), - django.core.validators.MaxValueValidator(600) + django.core.validators.MaxValueValidator(600), ], - max_digits=5 + max_digits=5, ), ), ] diff --git a/wger/weight/models.py b/wger/weight/models.py index 0313c9ac6..4cc2c6ae7 100644 --- a/wger/weight/models.py +++ b/wger/weight/models.py @@ -29,12 +29,13 @@ class WeightEntry(models.Model): """ Model for a weight point """ + date = models.DateField(verbose_name=_('Date')) weight = models.DecimalField( verbose_name=_('Weight'), max_digits=5, decimal_places=2, - validators=[MinValueValidator(30), MaxValueValidator(600)] + validators=[MinValueValidator(30), MaxValueValidator(600)], ) user = models.ForeignKey( User, @@ -55,18 +56,19 @@ class WeightEntry(models.Model): """ Metaclass to set some other properties """ + verbose_name = _('Weight entry') ordering = [ - "date", + 'date', ] - get_latest_by = "date" - unique_together = ("date", "user") + get_latest_by = 'date' + unique_together = ('date', 'user') def __str__(self): """ Return a more human-readable representation """ - return "{0}: {1:.2f} kg".format(self.date, self.weight) + return '{0}: {1:.2f} kg'.format(self.date, self.weight) def get_owner_object(self): """ diff --git a/wger/weight/tests/test_csv_import.py b/wger/weight/tests/test_csv_import.py index 25eb8a6b7..ca303f0e1 100644 --- a/wger/weight/tests/test_csv_import.py +++ b/wger/weight/tests/test_csv_import.py @@ -52,11 +52,8 @@ class WeightCsvImportTestCase(WgerTestCase): 26.02.10 71,9 222 19.03.10 72 222""" response = self.client.post( - reverse('weight:import-csv'), { - 'stage': 1, - 'csv_input': csv_input, - 'date_format': '%d.%m.%y' - } + reverse('weight:import-csv'), + {'stage': 1, 'csv_input': csv_input, 'date_format': '%d.%m.%y'}, ) self.assertEqual(response.status_code, 200) @@ -66,12 +63,8 @@ class WeightCsvImportTestCase(WgerTestCase): # 2nd. step response = self.client.post( - reverse('weight:import-csv'), { - 'stage': 2, - 'hash': hash_value, - 'csv_input': csv_input, - 'date_format': '%d.%m.%y' - } + reverse('weight:import-csv'), + {'stage': 2, 'hash': hash_value, 'csv_input': csv_input, 'date_format': '%d.%m.%y'}, ) count_after = WeightEntry.objects.count() diff --git a/wger/weight/tests/test_email_weight_reminder.py b/wger/weight/tests/test_email_weight_reminder.py index 4a2c70a40..a54c9b5b4 100644 --- a/wger/weight/tests/test_email_weight_reminder.py +++ b/wger/weight/tests/test_email_weight_reminder.py @@ -29,14 +29,13 @@ from wger.weight.models import WeightEntry class EmailWeightReminderTestCase(WgerTestCase): - def test_without_email(self): user = User.objects.get(pk=2) user.email = '' user.num_days_weight_reminder = 3 user.save() - call_command("email-weight-reminder") + call_command('email-weight-reminder') self.assertEqual(len(mail.outbox), 0) def test_without_num_days_weight_reminder(self): @@ -47,7 +46,7 @@ class EmailWeightReminderTestCase(WgerTestCase): user.userprofile.num_days_weight_reminder = 0 user.userprofile.save() - call_command("email-weight-reminder") + call_command('email-weight-reminder') self.assertEqual(len(mail.outbox), 0) def test_with_num_days_weight_reminder(self): @@ -58,7 +57,7 @@ class EmailWeightReminderTestCase(WgerTestCase): user.userprofile.num_days_weight_reminder = 3 user.userprofile.save() - call_command("email-weight-reminder") + call_command('email-weight-reminder') self.assertEqual(len(mail.outbox), 1) def test_send_email(self): @@ -73,7 +72,7 @@ class EmailWeightReminderTestCase(WgerTestCase): user.userprofile.num_days_weight_reminder = 1 user.userprofile.save() - call_command("email-weight-reminder") + call_command('email-weight-reminder') self.assertEqual(len(mail.outbox), 1) def test_send_email_zero_days_diff(self): @@ -88,7 +87,7 @@ class EmailWeightReminderTestCase(WgerTestCase): user.userprofile.num_days_weight_reminder = 1 user.userprofile.save() - call_command("email-weight-reminder") + call_command('email-weight-reminder') self.assertEqual(len(mail.outbox), 1) def test_not_send_email(self): @@ -103,5 +102,5 @@ class EmailWeightReminderTestCase(WgerTestCase): user.userprofile.num_days_weight_reminder = 3 user.userprofile.save() - call_command("email-weight-reminder") + call_command('email-weight-reminder') self.assertEqual(len(mail.outbox), 0) diff --git a/wger/weight/tests/test_entry.py b/wger/weight/tests/test_entry.py index 87a5a4d5f..3c0761076 100644 --- a/wger/weight/tests/test_entry.py +++ b/wger/weight/tests/test_entry.py @@ -40,7 +40,7 @@ class MealRepresentationTestCase(WgerTestCase): """ Test that the representation of an object is correct """ - self.assertEqual("{0}".format(WeightEntry.objects.get(pk=1)), '2012-10-01: 77.00 kg') + self.assertEqual('{0}'.format(WeightEntry.objects.get(pk=1)), '2012-10-01: 77.00 kg') class AddWeightEntryTestCase(WgerAddTestCase): @@ -54,7 +54,7 @@ class AddWeightEntryTestCase(WgerAddTestCase): data = { 'weight': decimal.Decimal(81.1).quantize(TWOPLACES), 'date': datetime.date(2013, 2, 1), - 'user': 1 + 'user': 1, } @@ -91,6 +91,7 @@ class WeightEntryTestCase(api_base_test.ApiBaseResourceTestCase): """ Tests the weight entry overview resource """ + pk = 3 resource = WeightEntry private_resource = True diff --git a/wger/weight/tests/test_generator.py b/wger/weight/tests/test_generator.py index f0cf05a56..eac985acf 100644 --- a/wger/weight/tests/test_generator.py +++ b/wger/weight/tests/test_generator.py @@ -21,7 +21,6 @@ from wger.weight.models import WeightEntry class WeightEntryGeneratorTestCase(WgerTestCase): - def test_generator(self): # Arrange WeightEntry.objects.all().delete() diff --git a/wger/weight/views.py b/wger/weight/views.py index 92c54f824..6f5bb4d36 100644 --- a/wger/weight/views.py +++ b/wger/weight/views.py @@ -59,6 +59,7 @@ class WeightAddView(WgerFormMixin, CreateView): """ Generic view to add a new weight entry """ + model = WeightEntry form_class = WeightForm title = gettext_lazy('Add weight entry') @@ -90,6 +91,7 @@ class WeightUpdateView(WgerFormMixin, LoginRequiredMixin, UpdateView): """ Generic view to edit an existing weight entry """ + model = WeightEntry form_class = WeightForm diff --git a/wger/wsgi.py b/wger/wsgi.py index 295ed61c1..182117400 100644 --- a/wger/wsgi.py +++ b/wger/wsgi.py @@ -20,7 +20,7 @@ import os from django.core.wsgi import get_wsgi_application -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings") +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings') # This application object is used by any WSGI server configured to use this # file. This includes Django's development server, if the WSGI_APPLICATION