Pylint dix

This commit is contained in:
Gregory Trullemans 2024-01-14 14:48:31 +01:00
parent 2e22b04643
commit dafcdd6377
26 changed files with 185 additions and 245 deletions

View File

@ -20,7 +20,7 @@ fail-on=
fail-under=10.0 fail-under=10.0
# Files or directories to be skipped. They should be base names, not paths. # Files or directories to be skipped. They should be base names, not paths.
ignore=CVS ignore=CVS, tests.py, tests_tools.py, tests_models.py, tests_views.py, urls.py, migrations
# Add files or directories matching the regex patterns to the ignore-list. The # Add files or directories matching the regex patterns to the ignore-list. The
# regex matches against paths and can be in Posix or Windows format. # regex matches against paths and can be in Posix or Windows format.
@ -80,20 +80,11 @@ confidence=
# --enable=similarities". If you want to run only the classes checker, but have # --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use "--disable=all --enable=classes # no Warning level messages displayed, use "--disable=all --enable=classes
# --disable=W". # --disable=W".
disable=raw-checker-failed, disable=
bad-inline-option,
locally-disabled,
file-ignored,
suppressed-message,
useless-suppression,
deprecated-pragma,
use-symbolic-message-instead,
empty-docstring,
missing-class-docstring, missing-class-docstring,
missing-module-docstring, missing-module-docstring,
missing-function-docstring, missing-function-docstring,
consider-using-f-string, unsupported-binary-operation,
duplicate-code,
# Enable the message, report, category or checker with the given id(s). You can # Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option # either give multiple identifier separated by comma (,) or put this option
@ -571,5 +562,5 @@ preferred-modules=
# Exceptions that will emit a warning when being caught. Defaults to # Exceptions that will emit a warning when being caught. Defaults to
# "BaseException, Exception". # "BaseException, Exception".
overgeneral-exceptions=BaseException, overgeneral-exceptions=builtins.BaseException,
Exception builtins.Exception

View File

@ -1,7 +1,7 @@
from datetime import date
from django.db import models from django.db import models
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.core.validators import MaxValueValidator, MinValueValidator from django.core.validators import MaxValueValidator, MinValueValidator
from datetime import date
from jarvis.tools.models import Markdownizable, Seasonisable from jarvis.tools.models import Markdownizable, Seasonisable
from jarvis.people.models import Gymnast, GENDER_CHOICES from jarvis.people.models import Gymnast, GENDER_CHOICES
@ -175,7 +175,7 @@ class Chrono(Seasonisable):
return f"{self.gymnast} - {self.score} ({self.date} - {self.chrono_type})" return f"{self.gymnast} - {self.score} ({self.date} - {self.chrono_type})"
def timeline_representation(self): def timeline_representation(self):
return f"<li>{self.date:%d %b %Y} - New personel best {CHRONO_TYPE_CHOICE[self.chrono_type][1]}: {self.score}' ({self.tof}')</li>" return f"<li>{self.date:%d %b %Y} - New personel best {CHRONO_TYPE_CHOICE[self.chrono_type][1]}: {self.score}' ({self.tof}')</li>" # pylint: disable=line-too-long
@staticmethod @staticmethod
def compute_tof(value): def compute_tof(value):
@ -246,7 +246,7 @@ class Injury(Markdownizable, Seasonisable):
return f"{self.gymnast} ({self.date})" return f"{self.gymnast} ({self.date})"
def timeline_representation(self): def timeline_representation(self):
return f"<li>{self.date:%d %b %Y} - Accident ({self.skill}): {self.nb_week_off} (weeks off)</li>" return f"<li>{self.date:%d %b %Y} - Accident ({self.skill}): {self.nb_week_off} (weeks off)</li>" # pylint: disable=line-too-long
class LearnedSkill(Seasonisable): class LearnedSkill(Seasonisable):
@ -281,7 +281,7 @@ class LearnedSkill(Seasonisable):
return f"{self.gymnast} - {self.date} - {self.learning_step} - {self.skill}" return f"{self.gymnast} - {self.date} - {self.learning_step} - {self.skill}"
def timeline_representation(self): def timeline_representation(self):
return f"<li>{self.date:%d %b %Y} - learning of {self.skill.long_label} ({self.skill.short_label}): {LEARNING_STEP_CHOICES[self.learning_step][1]}</li>" return f"<li>{self.date:%d %b %Y} - learning of {self.skill.long_label} ({self.skill.short_label}): {LEARNING_STEP_CHOICES[self.learning_step][1]}</li>" # pylint: disable=line-too-long
class Plan(Seasonisable, Markdownizable): class Plan(Seasonisable, Markdownizable):
@ -398,7 +398,7 @@ class WellBeing(Markdownizable, Seasonisable):
updated_at = models.DateTimeField(auto_now=True) updated_at = models.DateTimeField(auto_now=True)
def __str__(self): def __str__(self):
return f"{self.gymnast} - {self.date} : {self.mindstate} | {self.sleep} | {self.stress} | {self.fatigue} | {self.muscle_soreness}" return f"{self.gymnast} - {self.date} : {self.mindstate} | {self.sleep} | {self.stress} | {self.fatigue} | {self.muscle_soreness}" # pylint: disable=line-too-long
@property @property
def get_inversed_stress(self): def get_inversed_stress(self):
@ -482,7 +482,7 @@ class NumberOfRoutineDone(Seasonisable):
) )
def __str__(self): def __str__(self):
return f"{self.gymnast} - {self.routine_type} ({self.routine}) : {self.number_of_try} | {self.number_of_successes}" return f"{self.gymnast} - {self.routine_type} ({self.routine}) : {self.number_of_try} | {self.number_of_successes}" # pylint: disable=line-too-long
class HeightWeight(Seasonisable): class HeightWeight(Seasonisable):
@ -573,7 +573,7 @@ class Intensity(Markdownizable, Seasonisable):
number_of_passes = models.PositiveSmallIntegerField() number_of_passes = models.PositiveSmallIntegerField()
def __str__(self): def __str__(self):
return f"{self.gymnast} - {self.date} : {self.time} - {self.difficulty} - {self.quantity_of_skill} - {self.number_of_passes}" return f"{self.gymnast} - {self.date} : {self.time} - {self.difficulty} - {self.quantity_of_skill} - {self.number_of_passes}" # pylint: disable=line-too-long
@property @property
def mean_time_by_passe(self): def mean_time_by_passe(self):
@ -616,7 +616,7 @@ class SeasonInformation(models.Model):
verbose_name_plural = "Season Informations" verbose_name_plural = "Season Informations"
unique_together = ("gymnast", "season") unique_together = ("gymnast", "season")
CATEGORY_CHOICES_ARRAY = [(key, value) for key, value in CATEGORY_CHOICES.items()] CATEGORY_CHOICES_ARRAY = list(CATEGORY_CHOICES.items())
gymnast = models.ForeignKey( gymnast = models.ForeignKey(
Gymnast, on_delete=models.CASCADE, related_name="season_informations" Gymnast, on_delete=models.CASCADE, related_name="season_informations"
@ -648,7 +648,7 @@ class SeasonInformation(models.Model):
created_at = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(auto_now_add=True)
def __str__(self): def __str__(self):
return f"{self.gymnast} - {self.season} : {self.number_of_training_sessions_per_week} - {self.number_of_hours_per_week} - {self.category} - {self.club}" return f"{self.gymnast} - {self.season} : {self.number_of_training_sessions_per_week} - {self.number_of_hours_per_week} - {self.category} - {self.club}" # pylint: disable=line-too-long
class CompetitivePointsStats(Markdownizable, Seasonisable): class CompetitivePointsStats(Markdownizable, Seasonisable):
@ -704,7 +704,7 @@ class CompetitivePointsStats(Markdownizable, Seasonisable):
) )
def __str__(self): def __str__(self):
return f"{self.age_category} - {self.gender} - {self.routine_type} : {self.total} ({self.statistic_type})" return f"{self.age_category} - {self.gender} - {self.routine_type} : {self.total} ({self.statistic_type})" # pylint: disable=line-too-long
# class Stability(Seasonisable): # class Stability(Seasonisable):

View File

@ -1,3 +1,4 @@
from datetime import date, datetime
from django.shortcuts import render, get_object_or_404 from django.shortcuts import render, get_object_or_404
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_http_methods from django.views.decorators.http import require_http_methods
@ -7,12 +8,15 @@ from django.urls import reverse
from django.conf import settings from django.conf import settings
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.core.mail import send_mail from django.core.mail import send_mail
import pendulum
from jarvis.people.models import Gymnast from jarvis.people.models import Gymnast
from jarvis.planning.models import Event from jarvis.planning.models import Event
from jarvis.objective.models import Skill from jarvis.objective.models import Skill
from jarvis.tools.date_week_transition import from_date_to_week_number
from jarvis.tools.models import Season
from .models import ( from .models import (
CHRONO_TYPE_CHOICE, CHRONO_TYPE_CHOICE,
@ -52,16 +56,6 @@ from .forms import (
NumberOfRoutineDoneForm, NumberOfRoutineDoneForm,
) )
from jarvis.tools.date_week_transition import (
from_date_to_week_number,
from_week_number_to_date,
)
from jarvis.tools.models import Season
from datetime import date, datetime
import pendulum
User = get_user_model() User = get_user_model()
MAIL_HEADER = """ MAIL_HEADER = """
@ -129,7 +123,8 @@ def jump_chrono_details(request, chrono_id):
Args: Args:
chrono_id (int) identifiant chrono chrono_id (int) identifiant chrono
QTF : Est-ce que je ne devrais pas faire un prefetch_related sur mon objet chrono pour optimiser mon affichage ? QTF : Est-ce que je ne devrais pas faire un prefetch_related sur mon objet chrono pour
optimiser mon affichage ?
chrono = Chrono.object.get(pk=chrono_id).prefetch_related('chrono_details') ? chrono = Chrono.object.get(pk=chrono_id).prefetch_related('chrono_details') ?
""" """
@ -175,14 +170,8 @@ def average_jump_chrono_details_for_gymnast(
season, week_number = from_date_to_week_number(today) season, week_number = from_date_to_week_number(today)
else: else:
season = Season(season).label season = Season(season).label
week_number = min(week_number, 52)
if week_number > 52: week_number = max(week_number, 1)
week_number = 52
if week_number < 1:
week_number = 1
date_begin, date_end = from_week_number_to_date(season, week_number)
return average_jump_chrono_details_for_season_and_week( return average_jump_chrono_details_for_season_and_week(
request, request,
@ -225,8 +214,8 @@ def add_jump_chrono_value(request):
if created: if created:
return HttpResponse(200, (row, created)) # devrait être un 201 return HttpResponse(200, (row, created)) # devrait être un 201
else:
return HttpResponse(400, (row, created)) return HttpResponse(400, (row, created))
@login_required @login_required
@ -264,7 +253,8 @@ def average_jump_chrono_details_between_two_date(
date_begin (date) date de début date_begin (date) date de début
date_end (date) date de fin date_end (date) date de fin
QTF : le cast en date devrait être dans un try mais comment gérer correctement l'erreur - si erreur il y a ? QTF : le cast en date devrait être dans un try mais comment gérer correctement l'erreur - si
erreur il y a ?
""" """
if date_end: if date_end:
@ -582,14 +572,14 @@ def note_create_or_update(request, note_id=None, gymnast_id=None):
return HttpResponseRedirect( return HttpResponseRedirect(
reverse("gymnast_details_tab", args=(new_note.gymnast.id, "event")) reverse("gymnast_details_tab", args=(new_note.gymnast.id, "event"))
) )
else:
return render(request, "notes/create.html", {"form": form}) return render(request, "notes/create.html", {"form": form})
else:
last_note = ( last_note = (
Note.objects.filter(gymnast=gymnast_id, status=1).order_by("-date").first() Note.objects.filter(gymnast=gymnast_id, status=1).order_by("-date").first()
) )
if last_note: if last_note:
data["informations"] = last_note.informations data["informations"] = last_note.informations
form = NoteForm(instance=note, initial=data) form = NoteForm(instance=note, initial=data)
context = {"form": form, "note_id": note_id} context = {"form": form, "note_id": note_id}
@ -658,8 +648,8 @@ def chrono_create_or_update(request, chrono_id=None, gymnast_id=None):
return HttpResponseRedirect( return HttpResponseRedirect(
reverse("gymnast_details_tab", args=(new_chrono.gymnast.id, "scores")) reverse("gymnast_details_tab", args=(new_chrono.gymnast.id, "scores"))
) )
else:
return render(request, "chronos/create.html", {"form": form}) return render(request, "chronos/create.html", {"form": form})
form = ChronoForm(instance=chrono, initial=data) form = ChronoForm(instance=chrono, initial=data)
context = {"form": form, "chrono_id": chrono_id} context = {"form": form, "chrono_id": chrono_id}
@ -746,8 +736,8 @@ def learnedskill_create_or_update(request, gymnast_id=None):
return HttpResponseRedirect( return HttpResponseRedirect(
reverse("gymnast_details", args=(form.cleaned_data["gymnast"].id,)) reverse("gymnast_details", args=(form.cleaned_data["gymnast"].id,))
) )
else:
render(request, "followup/learnedskills/create.html", {"form": form}) return render(request, "followup/learnedskills/create.html", {"form": form})
form = LearnedSkillForm(initial=data) form = LearnedSkillForm(initial=data)
context = {"form": form, "gymnast_id": gymnast_id} context = {"form": form, "gymnast_id": gymnast_id}
@ -824,8 +814,8 @@ def score_create_or_update(request, score_id=None, gymnast_id=None):
args=(form.cleaned_data["gymnast"].id, "scores"), args=(form.cleaned_data["gymnast"].id, "scores"),
) )
) )
else:
render(request, "followup/scores/create.html", {"form": form}) return render(request, "followup/scores/create.html", {"form": form})
form = ScoreForm(instance=score, initial=data) form = ScoreForm(instance=score, initial=data)
context = {"form": form, "score_id": score_id} context = {"form": form, "score_id": score_id}
@ -950,8 +940,8 @@ def injury_create_or_update(request, injury_id=None, gymnast_id=None):
) )
return HttpResponseRedirect(reverse("injury_details", args=(injury.pk,))) return HttpResponseRedirect(reverse("injury_details", args=(injury.pk,)))
else:
return render(request, "injuries/create.html", {"form": form}) return render(request, "injuries/create.html", {"form": form})
form = InjuryForm(instance=injury, initial=data) form = InjuryForm(instance=injury, initial=data)
context = {"form": form, "injury_id": injury_id} context = {"form": form, "injury_id": injury_id}
@ -1063,8 +1053,8 @@ def wellbeing_create_or_update(
return HttpResponseRedirect( return HttpResponseRedirect(
reverse("wellbeing_details", args=(wellbeing.pk,)) reverse("wellbeing_details", args=(wellbeing.pk,))
) )
else:
return render(request, "wellbeing/create.html", {"form": form}) return render(request, "wellbeing/create.html", {"form": form})
form = WellBeingForm(instance=wellbeing, initial=data) form = WellBeingForm(instance=wellbeing, initial=data)
context = {"form": form, "wellbeing_id": wellbeing_id} context = {"form": form, "wellbeing_id": wellbeing_id}
@ -1152,7 +1142,7 @@ def heightweight_create_or_update(request, heightweight_id=None, gymnast_id=None
send_mail( send_mail(
f"{gymnast} : Nouveau poids/taille enregistré", f"{gymnast} : Nouveau poids/taille enregistré",
f"Un nouveau poids/taille enregistré pour {gymnast} ({date}) : {height} cm / {weight} kg (BMI: {bmi}).", f"Un nouveau poids/taille enregistré pour {gymnast} ({date}) : {height} cm / {weight} kg (BMI: {bmi}).", # pylint: disable=line-too-long
settings.EMAIL_HOST_USER, settings.EMAIL_HOST_USER,
receiver, receiver,
fail_silently=False, fail_silently=False,
@ -1172,9 +1162,8 @@ def heightweight_create_or_update(request, heightweight_id=None, gymnast_id=None
args=(form.cleaned_data["gymnast"].id, "physiological"), args=(form.cleaned_data["gymnast"].id, "physiological"),
) )
) )
else:
print(form.errors) return render(request, "heightweight/create.html", {"form": form})
return render(request, "heightweight/create.html", {"form": form})
form = HeightWeightForm(instance=heightweight, initial=data) form = HeightWeightForm(instance=heightweight, initial=data)
context = { context = {
@ -1239,8 +1228,8 @@ def increment_routinedone(request):
if form.is_valid(): if form.is_valid():
form.save() form.save()
return HttpResponse(status=200) return HttpResponse(status=200)
else:
return HttpResponse(status=406) return HttpResponse(status=406)
@login_required @login_required
@ -1312,8 +1301,8 @@ def routinedone_create_or_update(request, routinedone_id=None, gymnast_id=None):
args=(form.cleaned_data["gymnast"].id, "routine"), args=(form.cleaned_data["gymnast"].id, "routine"),
) )
) )
else:
return render(request, "routinedone/create.html", {"form": form}) return render(request, "routinedone/create.html", {"form": form})
form = NumberOfRoutineDoneForm(instance=routinedone, initial=data) form = NumberOfRoutineDoneForm(instance=routinedone, initial=data)
context = {"form": form, "routinedone_id": routinedone_id} context = {"form": form, "routinedone_id": routinedone_id}
@ -1385,8 +1374,8 @@ def plan_create_or_update(request, plan_id=None, gymnast_id=None, skill_id=None)
return HttpResponseRedirect( return HttpResponseRedirect(
reverse("gymnast_details", args=(form.cleaned_data["gymnast"].id,)) reverse("gymnast_details", args=(form.cleaned_data["gymnast"].id,))
) )
else:
return render(request, "plan/create.html", {"form": form}) return render(request, "plan/create.html", {"form": form})
form = PlanForm(instance=plan, initial=data) form = PlanForm(instance=plan, initial=data)
context = {"form": form, "plan_id": plan_id} context = {"form": form, "plan_id": plan_id}
@ -1517,8 +1506,8 @@ def intensity_create_or_update(request, intensity_id=None, gymnast_id=None):
args=(form.cleaned_data["gymnast"].id, "routine"), args=(form.cleaned_data["gymnast"].id, "routine"),
) )
) )
else:
return render(request, "intensities/create.html", {"form": form}) return render(request, "intensities/create.html", {"form": form})
form = IntensityForm(instance=intensity, initial=data) form = IntensityForm(instance=intensity, initial=data)
context = {"form": form, "intensity_id": intensity_id} context = {"form": form, "intensity_id": intensity_id}
@ -1588,8 +1577,8 @@ def season_information_create_or_update(
args=(form.cleaned_data["gymnast"].id,), args=(form.cleaned_data["gymnast"].id,),
) )
) )
else:
return render(request, "seasoninformations/create.html", {"form": form}) return render(request, "seasoninformations/create.html", {"form": form})
form = SeasonInformationForm(instance=season_information, initial=data) form = SeasonInformationForm(instance=season_information, initial=data)
context = {"form": form, "season_information_id": season_information_id} context = {"form": form, "season_information_id": season_information_id}

View File

@ -45,7 +45,7 @@ class Place(models.Model):
is_active = models.BooleanField(default=1, verbose_name="Active") is_active = models.BooleanField(default=1, verbose_name="Active")
def __str__(self): def __str__(self):
return "%s (%s)" % (self.name, self.city if self.city else "?") return f"{self.name} ({self.city})"
class Club(models.Model): class Club(models.Model):
@ -70,4 +70,4 @@ class Club(models.Model):
is_active = models.BooleanField(default=1, verbose_name="Active") is_active = models.BooleanField(default=1, verbose_name="Active")
def __str__(self): def __str__(self):
return "%s (%s)" % (self.name, self.place.city if self.place.city else "?") return f"{self.name} ({self.place.city})"

View File

@ -1,5 +1,5 @@
from django.test import TestCase from django.test import TestCase
from django.urls import reverse, resolve from django.urls import resolve
class URLTestCase(TestCase): class URLTestCase(TestCase):

View File

@ -96,8 +96,8 @@ def place_create_or_update(request, place_id=None):
if form.is_valid(): if form.is_valid():
place = form.save() place = form.save()
return HttpResponseRedirect(reverse("place_details", args=(place.pk,))) return HttpResponseRedirect(reverse("place_details", args=(place.pk,)))
else:
return render(request, "places/create.html", {"form": form}) return render(request, "places/create.html", {"form": form})
form = PlaceForm(instance=place, initial=data) form = PlaceForm(instance=place, initial=data)
context = {"form": form, "place_id": place_id} context = {"form": form, "place_id": place_id}

View File

@ -1,10 +1,8 @@
from django.contrib import admin from django.contrib import admin
# from django_extensions.admin import ForeignKeyAutocompleteAdmin # from django_extensions.admin import ForeignKeyAutocompleteAdmin
from django_admin_listfilter_dropdown.filters import ( from django_admin_listfilter_dropdown.filters import (
DropdownFilter, DropdownFilter,
ChoiceDropdownFilter,
RelatedDropdownFilter, RelatedDropdownFilter,
) )

View File

@ -104,13 +104,15 @@ class Educative(Markdownizable):
def __str__(self): def __str__(self):
return f"{self.long_label} ({self.short_label} - {self.difficulty})" return f"{self.long_label} ({self.short_label} - {self.difficulty})"
def breadcrumb(self, path=[]): def breadcrumb(self, path=None):
""" """
Renvoie le breadcrumb pour l'édutatif courant. Renvoie le breadcrumb pour l'édutatif courant.
Exemple : Exemple :
>>> s = Skill.objects.get(pk=44) >>> s = Skill.objects.get(pk=44)
>>> s.breadcrumb() >>> s.breadcrumb()
""" """
if path is None:
path = []
path = [self] + path path = [self] + path
if self.prerequisites.all().count() == 0: if self.prerequisites.all().count() == 0:
@ -145,7 +147,7 @@ class PrerequisiteClosure(models.Model):
path = models.PositiveIntegerField() path = models.PositiveIntegerField()
def __str__(self): def __str__(self):
return f"{self.ancestor.long_label} -> {self.descendant.long_label} ({self.level}|{self.path})" return f"""{self.ancestor.long_label} -> {self.descendant.long_label} ({self.level}|{self.path})""" # pylint: disable=line-too-long
class TouchPosition(models.Model): class TouchPosition(models.Model):
@ -273,8 +275,8 @@ class Routine(Educative):
- la difficulté - la difficulté
- si c'est une routine (série) - si c'est une routine (série)
- si c'est une routine (série) de compétition - si c'est une routine (série) de compétition
A chaque fois qu'on le peut, on garde les informations entrées par les utilisateurs néanmoins on vérifie qu'il A chaque fois qu'on le peut, on garde les informations entrées par les utilisateurs
n'a pas encodé n'importe quoi. néanmoins on vérifie qu'il n'a pas encodé n'importe quoi.
""" """
rank = 0 rank = 0
level = 0 level = 0

View File

@ -42,7 +42,12 @@ class EducativeTestCase(TestCase):
) )
educ_7.prerequisites.add(educ_6) educ_7.prerequisites.add(educ_6)
educ_7.prerequisites.add(educ_1) educ_7.prerequisites.add(educ_1)
# educ_8 = Educative.objects.create(long_label="3/4 Avant vrille", difficulty=0.5, level=1, rank=1) # educ_8 = Educative.objects.create(
# long_label="3/4 Avant vrille",
# difficulty=0.5,
# level=1,
# rank=1
# )
# educ_8.prerequisites.add(educ_6) # educ_8.prerequisites.add(educ_6)
# educ_8.prerequisites.add(educ_2) # educ_8.prerequisites.add(educ_2)
educ_9 = Educative.objects.create( educ_9 = Educative.objects.create(

View File

@ -10,19 +10,19 @@ from jarvis.objective.models import (
class ToolsModels(TestCase): class ToolsModels(TestCase):
def setUp(self): def setUp(self):
""" """ """Set up des variables pour les test."""
touch_position_1 = TouchPosition.objects.create( touch_position_1 = TouchPosition.objects.create(
long_label="debout", short_label="debout", is_default=True long_label="debout", short_label="debout", is_default=True
) )
touch_position_2 = TouchPosition.objects.create( # touch_position_2 = TouchPosition.objects.create(
long_label="quadrupédique", short_label="4 patte", is_default=False # long_label="quadrupédique", short_label="4 patte", is_default=False
) # )
educ_1 = Educative.objects.create( # educ_1 = Educative.objects.create(
long_label="1/2 vrille", short_label="1/2T", difficulty=0.1, level=1, rank=1 # long_label="1/2 vrille", short_label="1/2T", difficulty=0.1, level=1, rank=1
) # )
educ_3 = Educative.objects.create( # educ_3 = Educative.objects.create(
long_label="4 pattes", short_label="4P", difficulty=0.1, level=1, rank=1 # long_label="4 pattes", short_label="4P", difficulty=0.1, level=1, rank=1
) # )
skill_1 = Skill.objects.create( skill_1 = Skill.objects.create(
long_label="Salto arrière groupé", long_label="Salto arrière groupé",
short_label="Arrière o", short_label="Arrière o",
@ -34,29 +34,29 @@ class ToolsModels(TestCase):
landing=touch_position_1, landing=touch_position_1,
difficulty=0.5, difficulty=0.5,
) )
skill_2 = Skill.objects.create( # skill_2 = Skill.objects.create(
long_label="Barani groupé", # long_label="Barani groupé",
short_label="Barani o", # short_label="Barani o",
rotation_type=2, # rotation_type=2,
notation=".41o", # notation=".41o",
rotation=4, # rotation=4,
twist=1, # twist=1,
departure=touch_position_1, # departure=touch_position_1,
landing=touch_position_1, # landing=touch_position_1,
difficulty=0.5, # difficulty=0.5,
) # )
routine_1 = Routine.objects.create( routine_1 = Routine.objects.create(
long_label="BOT Bronze", long_label="BOT Bronze",
short_label="Bronze", short_label="Bronze",
is_active=True, is_active=True,
is_competitive=True, is_competitive=True,
) )
routine_skill_1 = RoutineSkill.objects.create( # routine_skill_1 = RoutineSkill.objects.create(
routine=routine_1, skill=skill_1, rank=1 # routine=routine_1, skill=skill_1, rank=1
) # )
routine_skill_1 = RoutineSkill.objects.create( # routine_skill_1 = RoutineSkill.objects.create(
routine=routine_1, skill=skill_2, rank=2 # routine=routine_1, skill=skill_2, rank=2
) # )
def test_touch_position_to_string(self): def test_touch_position_to_string(self):
touch_position = TouchPosition.objects.get(long_label="debout") touch_position = TouchPosition.objects.get(long_label="debout")

View File

@ -17,9 +17,9 @@ def nb_skill_by_type(max_value, desired_type="level"):
Example: Example:
>>> from jarvis.objective.tools import nb_skill_by_type >>> from jarvis.objective.tools import nb_skill_by_type
>>> nb_skill_by_type(2) >>> nb_skill_by_type(2)
<QuerySet [{'level': 0, 'nb_skill': 23}, {'level': 1, 'nb_skill': 20}, {'level': 2, 'nb_skill': 19}]> <QuerySet [{'level': 0, 'nb_skill': 23}, {'level': 1, 'nb_skill': 20}, {'level': 2, 'nb_skill': 19}]> # pylint: disable=line-too-long
""" """
if desired_type != "level" and desired_type != "rank": if desired_type not in ("level", "rank"):
return None return None
nb_skill_by_level = ( nb_skill_by_level = (
@ -48,7 +48,7 @@ def nb_skill_lte_type(max_value, desired_type="level"):
>>> nb_skill_lte_type(2) >>> nb_skill_lte_type(2)
62 62
""" """
if desired_type != "level" and desired_type != "rank": if desired_type not in ("level", "rank"):
return None return None
if desired_type == "level": if desired_type == "level":
@ -79,7 +79,7 @@ def compute_completude(total_skill, gymnast_nb_known_skills, max_level_skill):
""" """
if total_skill: if total_skill:
percentage = gymnast_nb_known_skills / total_skill percentage = gymnast_nb_known_skills / total_skill
completude = "%s%%" % (int(percentage * 100)) completude = f"{int(percentage * 100)}%"
evaluated_level = int(max_level_skill * percentage) evaluated_level = int(max_level_skill * percentage)
else: else:
completude = None completude = None
@ -125,7 +125,7 @@ def compute_statistics_by_type(
[(1, 5, 2, 40), (2, 5, 4, 80), ] [(1, 5, 2, 40), (2, 5, 4, 80), ]
""" """
if desired_type != "level" and desired_type != "rank": if desired_type not in ("level", "rank"):
return None return None
j = 0 j = 0

View File

@ -24,7 +24,8 @@ from .models import (
@require_http_methods(["POST"]) @require_http_methods(["POST"])
def skill_lookup(request): def skill_lookup(request):
""" """
Récupère la liste des skill à la volée suivant des caractères de recherche entrés. (min 3 caractères) Récupère la liste des skill à la volée suivant des caractères de recherche entrés (min 3
caractères).
""" """
results = [] results = []
pattern = request.POST.get("pattern", None) pattern = request.POST.get("pattern", None)
@ -77,7 +78,7 @@ def skill_listing(request, field=None, expression=None, value=None, level=None):
Q(long_label__icontains=pattern) | Q(short_label__icontains=pattern) Q(long_label__icontains=pattern) | Q(short_label__icontains=pattern)
) )
elif field and expression and value: elif field and expression and value:
kwargs = {"{0}__{1}".format(field, expression): value} kwargs = {f"{field}__{expression}": value}
skill_list = Skill.objects.filter(**kwargs) skill_list = Skill.objects.filter(**kwargs)
elif level is not None: elif level is not None:
skill_list = Skill.objects.filter(level=level) skill_list = Skill.objects.filter(level=level)
@ -149,12 +150,12 @@ def skill_details(request, skill_id):
skill.save() skill.save()
# Je sépare les educatifs de type "skill" et les éducatifs de type "combination" pour mieux gérer l'affichage # Je sépare les educatifs de type "skill" et les éducatifs de type "combination" pour mieux
# Du code bien dégueulasse ! # gérer l'affichage. Du code bien dégueulasse !
# QTF : une idée pour faire ca de manière plus propre, plus élégante ? # QTF : une idée pour faire ca de manière plus propre, plus élégante ?
combination_dict = {} combination_dict = {}
educative_skill = skill.educatives.filter(id__in=(Skill.objects.all())) educative_skill = skill.educatives.filter(id__in=Skill.objects.all())
for educative in skill.educatives.filter(id__in=(Routine.objects.all())): for educative in skill.educatives.filter(id__in=Routine.objects.all()):
combination = Routine.objects.get(pk=educative.id) combination = Routine.objects.get(pk=educative.id)
combination_dict[combination] = [] combination_dict[combination] = []
for educ_skill in combination.routine.skill_links.all(): for educ_skill in combination.routine.skill_links.all():
@ -188,8 +189,7 @@ def skill_create_or_update(request, skill_id=None):
if form.is_valid(): if form.is_valid():
skill = form.save() skill = form.save()
return HttpResponseRedirect(reverse("skill_details", args=(skill.pk,))) return HttpResponseRedirect(reverse("skill_details", args=(skill.pk,)))
else: return render(request, "skill/create.html", {"form": form})
return render(request, "skill/create.html", {"form": form})
form = SkillForm(instance=skill) form = SkillForm(instance=skill)
context = {"form": form, "skill_id": skill_id} context = {"form": form, "skill_id": skill_id}
@ -199,7 +199,8 @@ def skill_create_or_update(request, skill_id=None):
@login_required @login_required
@require_http_methods(["GET"]) @require_http_methods(["GET"])
def competition_routine_listing(request, gymnast_id=None): def competition_routine_listing(request, gymnast_id=None):
"""Récupère la liste des routines (séries) de compétition suivant un pattern si celui-ci est défini """Récupère la liste des routines (séries) de compétition suivant un pattern si celui-ci est
défini.
Args: Args:
gymnast_id (int) identifiant de la classe Gymnast gymnast_id (int) identifiant de la classe Gymnast
@ -379,13 +380,14 @@ def combination_create_or_update(request, combination_id=None):
combination = form.save() combination = form.save()
# ici faire un FOR skill in form_skills_list: # ici faire un FOR skill in form_skills_list:
# record.save() # ca sauve le record dans la table RoutineSkill # record.save() # ca sauve le record dans la table RoutineSkill
# something like this : http://stackoverflow.com/questions/3074938/django-m2m-form-save-through-table # something like this :
# http://stackoverflow.com/questions/3074938/django-m2m-form-save-through-table
# QTF : can you help me ? # QTF : can you help me ?
return HttpResponseRedirect( return HttpResponseRedirect(
reverse("combination_details", args=(combination.pk,)) reverse("combination_details", args=(combination.pk,))
) )
else:
return render(request, "combinations/create.html", {"form": form}) return render(request, "combinations/create.html", {"form": form})
form = CombinationForm(instance=combination) form = CombinationForm(instance=combination)
context = {"form": form, "combination_id": combination_id} context = {"form": form, "combination_id": combination_id}
@ -436,8 +438,8 @@ def link_skill_to_combination(request):
rank=form.cleaned_data["rank"], rank=form.cleaned_data["rank"],
) )
return HttpResponse(200, (link, created)) return HttpResponse(200, (link, created))
else:
return HttpResponse(406) return HttpResponse(406)
@require_http_methods(["POST"]) @require_http_methods(["POST"])

View File

@ -1,10 +1,9 @@
""" Modelisation des gymnastes """ """ Modelisation des gymnastes """
from datetime import date
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.db.models import Count from django.db.models import Count
from django.db import models from django.db import models
from datetime import date
import pendulum import pendulum
from jarvis.objective.models import Skill from jarvis.objective.models import Skill
@ -121,7 +120,7 @@ class Gymnast(Markdownizable):
>>> gymnast.skill_max_for_type("rank") >>> gymnast.skill_max_for_type("rank")
19 19
""" """
if desired_type != "level" and desired_type != "rank": if desired_type not in ("level", "rank"):
return None return None
tmp = ( tmp = (
@ -155,7 +154,7 @@ class Gymnast(Markdownizable):
>>> gymnast.nb_known_skill_by_type("rank") >>> gymnast.nb_known_skill_by_type("rank")
<QuerySet [{'rank': 1, 'nb_known_skill': 2}, {'rank': 2, 'nb_known_skill': 4}, ]> <QuerySet [{'rank': 1, 'nb_known_skill': 2}, {'rank': 2, 'nb_known_skill': 4}, ]>
""" """
if desired_type != "level" and desired_type != "rank": if desired_type not in ("level", "rank"):
return None return None
nb_known_skill_by_type = ( nb_known_skill_by_type = (
@ -237,7 +236,7 @@ class Gymnast(Markdownizable):
on va chercher tous les Skill qui existent et on les compte. on va chercher tous les Skill qui existent et on les compte.
""" """
if desired_type != "level" and desired_type != "rank": if desired_type not in ("level", "rank"):
return None return None
context = {} context = {}

View File

@ -1,4 +1,4 @@
from django.test import TestCase # from django.test import TestCase
# from django.urls import reverse, resolve # from django.urls import reverse, resolve
# from jarvis.profiles.views import profile_update # from jarvis.profiles.views import profile_update

View File

@ -101,11 +101,6 @@ gymnast_urlpatterns = [
views.generate_timeline_report, views.generate_timeline_report,
name="gymnast_timeline_export_from_date", name="gymnast_timeline_export_from_date",
), ),
path(
r"report/evaluation/<int:gymnast_id>/",
views.gymnast_report_evaluation,
name="gymnast_report_evaluation",
),
# path( # path(
# r"resume/<int:gymnast_id>/season/<str:season>/week_number/<int:week_number>/", # r"resume/<int:gymnast_id>/season/<str:season>/week_number/<int:week_number>/",
# views.generate_week_resume, # views.generate_week_resume,

View File

@ -1,3 +1,5 @@
from datetime import date
from statistics import mean
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import Group from django.contrib.auth.models import Group
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
@ -24,8 +26,7 @@ from weasyprint import HTML, CSS
# from weasyprint.fonts import FontConfiguration # from weasyprint.fonts import FontConfiguration
import pendulum import pendulum
from datetime import date
from statistics import mean
from jarvis.followup.models import Event from jarvis.followup.models import Event
from jarvis.followup.forms import GymnastHasRoutineForm from jarvis.followup.forms import GymnastHasRoutineForm
@ -97,9 +98,9 @@ def gymnast_listing(request):
).select_related("gymnast") ).select_related("gymnast")
context = {"season_information_list": season_information_list} context = {"season_information_list": season_information_list}
return render(request, "gymnasts/list.html", context) return render(request, "gymnasts/list.html", context)
else:
gymnast = Gymnast.objects.get(user=request.user) # a mettre dans un TRY gymnast = Gymnast.objects.get(user=request.user) # a mettre dans un TRY
return gymnast_details(request, gymnast.id) return gymnast_details(request, gymnast.id)
@login_required @login_required
@ -199,48 +200,6 @@ def gymnast_report_list(request, gymnast_id):
return render(request, "gymnasts/tabs/tab_documents.html", context) return render(request, "gymnasts/tabs/tab_documents.html", context)
@login_required
@require_http_methods(["GET"])
def gymnast_report_evaluation(request, gymnast_id):
""" """
context = {
"SITE_TITLE": settings.SITE_TITLE,
"CLUB_NAME": settings.CLUB_NAME,
"ADDRESS": settings.ADDRESS,
"CITY": settings.CITY,
"ZIP": settings.ZIP,
"HEAD_COACH": settings.HEAD_COACH,
"MOBILE_PHONE": settings.MOBILE_PHONE,
"HEAD_COACH_EMAIL": settings.HEAD_COACH_EMAIL,
# "week_number": week_number,
# "gymnast": gymnast,
# "today": date_begin,
# "season": season,
# "sorted_records": sorted_records,
}
return render(request, "gymnasts/reports/report_evaluation.html", context)
# response = HttpResponse(content_type="application/pdf")
# response[
# "Content-Disposition"
# ] = "attachment; filename={lastname}-{firstname}-report-timeline.pdf".format(
# lastname=gymnast.last_name,
# firstname=gymnast.first_name,
# )
# html = render_to_string("people/gymnasts/reports/report_timeline.html", context)
# # font_config = FontConfiguration()
# HTML(string=html, base_url=request.build_absolute_uri()).write_pdf(
# response,
# stylesheets=[
# CSS(settings.STATICFILES_DIRS[0] + "/css/gymnast_report.css"),
# CSS(settings.STATICFILES_DIRS[0] + "/css/black-dashboard_report.css"),
# CSS(settings.STATICFILES_DIRS[0] + "/css/font_awesome_all_5.15.3.css"),
# ],
# ) # , font_config=font_config)
# return response
@login_required @login_required
@require_http_methods(["GET"]) @require_http_methods(["GET"])
def gymnast_display_events_and_notes(request, gymnast_id): def gymnast_display_events_and_notes(request, gymnast_id):
@ -507,10 +466,8 @@ def gymnast_create_or_update(request, gymnast_id=None):
# user.set_password(gymnast.last_name.lower() + _ + str(gymnast.birthdate)[-2:]) # user.set_password(gymnast.last_name.lower() + _ + str(gymnast.birthdate)[-2:])
return HttpResponseRedirect(reverse("gymnast_details", args=(gymnast.pk,))) return HttpResponseRedirect(reverse("gymnast_details", args=(gymnast.pk,)))
else:
return render( return render(request, "people/gymnasts/create.html", {"form": gymnast_form})
request, "people/gymnasts/create.html", {"form": gymnast_form}
)
form = GymnastForm(instance=gymnast) form = GymnastForm(instance=gymnast)
context = {"form": form, "gymnast_id": gymnast_id} context = {"form": form, "gymnast_id": gymnast_id}
@ -546,7 +503,7 @@ def gymnast_display_skill(request, gymnast_id):
context.update(gymnast.get_informations_from_type("rank")) context.update(gymnast.get_informations_from_type("rank"))
planned_skill = ( planned_skill = (
Plan.objects.filter(gymnast=gymnast.id, educative__in=(Skill.objects.all())) Plan.objects.filter(gymnast=gymnast.id, educative__in=Skill.objects.all())
.select_related("educative", "educative__skill") .select_related("educative", "educative__skill")
.order_by("-date", "educative__long_label") .order_by("-date", "educative__long_label")
) )
@ -571,11 +528,11 @@ def gymnast_display_skill(request, gymnast_id):
# skill_learned_by_phase = [[]] * 5 # skill_learned_by_phase = [[]] * 5
# print(skill_learned_by_phase) # print(skill_learned_by_phase)
confused_skill = list() confused_skill = []
skill_whith_help = list() skill_whith_help = []
skill_without_help = list() skill_without_help = []
skill_chained = list() skill_chained = []
skill_masterised = list() skill_masterised = []
for learned_skill in learned_skills: for learned_skill in learned_skills:
# print('Add skill for ' + str(learned_skill.learning_step) + ' phase') # print('Add skill for ' + str(learned_skill.learning_step) + ' phase')
# skill_learned_by_phase[learned_skill.learning_step].append(learned_skill.skill) # skill_learned_by_phase[learned_skill.learning_step].append(learned_skill.skill)
@ -840,7 +797,7 @@ def report_choice(request, gymnast_id):
def __mindstate_analyse(gymnast, date_begin, date_end, period, mindstate_score): def __mindstate_analyse(gymnast, date_begin, date_end, period, mindstate_score):
""" """ """Analyse de l'état d'esprit entre deux dates."""
previous_period_date_end = date_begin previous_period_date_end = date_begin
if period == "week": if period == "week":
period_length = 7 period_length = 7
@ -872,7 +829,7 @@ def __mindstate_analyse(gymnast, date_begin, date_end, period, mindstate_score):
def __height_analyse(gymnast, date_begin, date_end, period, height_score): def __height_analyse(gymnast, date_begin, date_end, period, height_score):
""" """ """Analyse de la taille du gymnaste entre deux dates."""
previous_period_date_end = date_begin previous_period_date_end = date_begin
if period == "week": if period == "week":
period_length = 7 period_length = 7
@ -905,7 +862,7 @@ def __height_analyse(gymnast, date_begin, date_end, period, height_score):
def __weight_analyse(gymnast, date_begin, date_end, period, weight_score): def __weight_analyse(gymnast, date_begin, date_end, period, weight_score):
""" """ """Analyse du poids du gymnaste entre deux dates."""
previous_period_date_end = date_begin previous_period_date_end = date_begin
if period == "week": if period == "week":
period_length = 7 period_length = 7
@ -1196,7 +1153,7 @@ def generate_report_for_period(
# PLANNED SKILLS # PLANNED SKILLS
plan_list = ( plan_list = (
Plan.objects.filter(gymnast=gymnast, educative__in=(Skill.objects.all())) Plan.objects.filter(gymnast=gymnast, educative__in=Skill.objects.all())
.filter(Q(is_done=False) | Q(date__gte=date.today())) .filter(Q(is_done=False) | Q(date__gte=date.today()))
.order_by("date") .order_by("date")
.distinct()[:6] .distinct()[:6]
@ -1284,7 +1241,7 @@ def generate_report_for_period(
response = HttpResponse(content_type="application/pdf") response = HttpResponse(content_type="application/pdf")
response[ response[
"Content-Disposition" "Content-Disposition"
] = f"attachment; filename={gymnast.last_name}_{gymnast.first_name}_{period}-report_{date_begin}_{date_end}.pdf" ] = f"attachment; filename={gymnast.last_name}_{gymnast.first_name}_{period}-report_{date_begin}_{date_end}.pdf" # pylint: disable=line-too-long
html = render_to_string("gymnasts/reports/report_periodical.html", context) html = render_to_string("gymnasts/reports/report_periodical.html", context)
@ -1524,5 +1481,5 @@ def generate_timeline_report(
# date_begin = date_begin.date() # date_begin = date_begin.date()
# wellbeing_list = gymnast.wellbeing.objects.filter(season="season", week_number="week_number") # wellbeing_list = gymnast.wellbeing.objects.filter(season="season", week_number="week_number")
# intensity_list = gymnast.intensities.objects.filter(season="season", week_number="week_number") # intensity_list = gymnast.intensities.objects.filter(season="season", week_number="week_number") # pylint: disable=line-too-long
# injury_list = gymnast.injuries.filter(season="season", week_number="week_number") # injury_list = gymnast.injuries.filter(season="season", week_number="week_number")

View File

@ -90,7 +90,7 @@ class Event(Markdownizable, Temporizable):
class EventParticipation(models.Model): class EventParticipation(models.Model):
""" """ """Classe représentant la participation à un évènement."""
class Meta: class Meta:
verbose_name = "Event Participation" verbose_name = "Event Participation"

View File

@ -56,8 +56,8 @@ def event_create_or_update(request, event_id=None):
if form.is_valid(): if form.is_valid():
event = form.save() event = form.save()
return HttpResponseRedirect(reverse("event_details", args=(event.pk,))) return HttpResponseRedirect(reverse("event_details", args=(event.pk,)))
else:
return render(request, "objectives/routines/create.html", {"form": form}) return render(request, "objectives/routines/create.html", {"form": form})
form = EventForm(instance=event, initial=data) form = EventForm(instance=event, initial=data)
context = {"form": form, "event_id": event_id} context = {"form": form, "event_id": event_id}

View File

@ -1,6 +1,6 @@
from django.contrib import admin from django.contrib import admin
from .models import Profile, Notification
from django_admin_listfilter_dropdown.filters import RelatedDropdownFilter from django_admin_listfilter_dropdown.filters import RelatedDropdownFilter
from .models import Profile, Notification
class ProfileAdmin(admin.ModelAdmin): class ProfileAdmin(admin.ModelAdmin):

View File

@ -1,5 +1,5 @@
from django.test import TestCase from django.test import TestCase
from django.urls import reverse, resolve from django.urls import resolve
# from jarvis.profiles.views import profile_update # from jarvis.profiles.views import profile_update

View File

@ -1,7 +1,8 @@
from django.test import RequestFactory, TestCase, Client from django.test import RequestFactory, TestCase, Client
from django.urls import reverse, resolve from django.contrib.auth.models import User, AnonymousUser
# from django.urls import reverse, resolve
from jarvis.profiles.views import profile_update from jarvis.profiles.views import profile_update
from django.contrib.auth.models import AnonymousUser, User
class ViewsTestCase(TestCase): class ViewsTestCase(TestCase):

View File

@ -8,9 +8,9 @@ from django.shortcuts import render, get_object_or_404
from django.views.decorators.http import require_http_methods from django.views.decorators.http import require_http_methods
from django.urls import reverse from django.urls import reverse
from jarvis.people.models import Gymnast
from .forms import ProfileForm from .forms import ProfileForm
from .models import Profile, Notification from .models import Profile, Notification
from jarvis.people.models import Gymnast
User = get_user_model() User = get_user_model()
@ -85,8 +85,8 @@ def notification_add(request):
if created: if created:
return HttpResponse(200, (row, created)) # devrait être un 201 return HttpResponse(200, (row, created)) # devrait être un 201
else:
return HttpResponse(400, (row, created)) return HttpResponse(400, (row, created))
@require_http_methods(["POST"]) @require_http_methods(["POST"])

View File

@ -82,7 +82,7 @@ def from_month_number_to_date(season, month_number):
dash = season.find("-") dash = season.find("-")
if month_number >= 1 and month_number <= 8: if 8 >= month_number >= 1: # and month_number <= 8:
year = int(season[dash + 1 :]) year = int(season[dash + 1 :])
else: else:
year = int(season[:dash]) year = int(season[:dash])
@ -208,7 +208,8 @@ def get_number_of_weeks_between(first_date, second_date):
if first_date.year == second.year: if first_date.year == second.year:
return second.week_of_year - first.week_of_year return second.week_of_year - first.week_of_year
elif second_date.year > first_date.year:
if second_date.year > first_date.year:
return (52 - first.week_of_year) + second.week_of_year return (52 - first.week_of_year) + second.week_of_year
else:
return (52 - second.week_of_year) + first.week_of_year return (52 - second.week_of_year) + first.week_of_year

View File

@ -1,4 +1,7 @@
"""Ensemble des classes d'utilité publique :-)""" """Ensemble des classes d'utilité publique :-)"""
import re
import markdown
import pendulum
from django.db import models from django.db import models
from django.utils import timezone from django.utils import timezone
@ -7,9 +10,6 @@ from .date_week_transition import (
get_number_of_weeks_between, get_number_of_weeks_between,
from_date_to_week_number, from_date_to_week_number,
) )
import markdown
import pendulum
import re
class Season: class Season:
@ -78,7 +78,7 @@ def get_default_date():
class Seasonisable(models.Model): class Seasonisable(models.Model):
""" """ """Classe abstraite définissant des champs commun à tout ce qui est relatif à une saison."""
class Meta: class Meta:
abstract = True abstract = True
@ -224,11 +224,11 @@ def max_even_if_none(value_1, value_2):
if value_1 is not None and value_2 is not None: if value_1 is not None and value_2 is not None:
if value_1 > value_2: if value_1 > value_2:
return value_1 return value_1
else:
return value_2
elif value_1 is not None:
return value_1
elif value_2 is not None:
return value_2 return value_2
else:
return 0 if value_1 is not None:
return value_1
if value_2 is not None:
return value_2
return 0

View File

@ -12,8 +12,10 @@ def submenuitem(context, url, minititle, title):
# css_class = "" + css_class # css_class = "" + css_class
return format_html( return format_html(
'<li><a href="{}"><span class="sidebar-mini-icon">{}</span><span class="sidebar-normal">{}</span></a></li>', f"""<li>
url, <a href="{url}">
minititle, <span class="sidebar-mini-icon">{minititle}</span>
title, <span class="sidebar-normal">{title}</span>
</a>
</li>"""
) )

View File

@ -1,7 +1,7 @@
""" Test du module date_week_transition """ """ Test du module date_week_transition """
from django.test import TestCase
from datetime import datetime from datetime import datetime
import pendulum
from django.test import TestCase
import pytz import pytz
from jarvis.tools.date_week_transition import ( from jarvis.tools.date_week_transition import (
@ -10,12 +10,10 @@ from jarvis.tools.date_week_transition import (
get_number_of_weeks_between, get_number_of_weeks_between,
) )
import pendulum
class FunctionTestCase(TestCase): class FunctionTestCase(TestCase):
def test_from_week_number_to_date(self): def test_from_week_number_to_date(self):
timezone = pytz.timezone("UTC") # timezone = pytz.timezone("UTC")
start_date = datetime(2022, 10, 3, 0, 0, 0, tzinfo=pytz.UTC) start_date = datetime(2022, 10, 3, 0, 0, 0, tzinfo=pytz.UTC)
end_date = datetime(2022, 10, 9, 0, 0, 0, tzinfo=pytz.UTC) end_date = datetime(2022, 10, 9, 0, 0, 0, tzinfo=pytz.UTC)