MAKENTNU/web

View on GitHub
src/make_queue/forms/machine.py

Summary

Maintainability
A
35 mins
Test Coverage
import datetime
 
from django import forms
from django.core.exceptions import ValidationError
from django.utils import timezone
from django.utils.text import capfirst
from django.utils.translation import gettext_lazy as _
from js_asset import JS
 
from util.locale_utils import last_week_of_year, year_and_week_to_monday
from util.templatetags.datetime_tags import long_datetime
from web.widgets import MazeMapSearchInput, SemanticChoiceInput
from ..models.machine import Machine, MachineType
 
 
class MachineFormBase(forms.ModelForm):
machine_type = forms.ModelChoiceField(
queryset=MachineType.objects.order_by('priority'),
# `capfirst()` to avoid duplicate translation differing only in case
label=capfirst(_("machine type")),
empty_label=_("Select machine type"),
widget=SemanticChoiceInput(attr_name_to_attr_value_getter={
'has-stream': lambda iterator_value: iterator_value.instance.has_stream if iterator_value else None,
}),
)
info_message_date = Machine._meta.get_field('info_message_date').formfield(disabled=True)
 
class Meta:
model = Machine
fields = '__all__'
widgets = {
'location': MazeMapSearchInput(url_field='location_url'),
'info_message': forms.Textarea(attrs={'rows': 5}),
}
 
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
status_choices = (
Machine.Status.AVAILABLE,
Machine.Status.OUT_OF_ORDER,
Machine.Status.MAINTENANCE,
)
self.fields['status'] = forms.ChoiceField(
choices=[
(c, Machine.STATUS_CHOICES_DICT[c])
for c in status_choices
],
widget=SemanticChoiceInput(attrs={'required': True}),
)
self.fields['info_message_date'].widget.format_value = long_datetime
 
Function `clean` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.
def clean(self):
cleaned_data = super().clean()
 
machine_type = cleaned_data.get('machine_type')
stream_name = cleaned_data.get('stream_name')
 
if machine_type:
if machine_type.has_stream:
if not stream_name:
self.add_error(
'stream_name', ValidationError(
_("Stream name cannot be empty when the machine type supports streaming."),
code='invalid_empty_stream_name',
)
)
else:
# Remove the stream name if the machine type does not support streams
cleaned_data['stream_name'] = ""
 
return cleaned_data
 
 
class AddMachineForm(MachineFormBase):
class Media:
js = (
JS('make_queue/js/machine_create.js', attrs={'defer': True}),
)
 
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Don't show the default value of `info_message_date` in the create form, as it might cause confusion
self.fields['info_message_date'].widget.format_value = lambda value: None
 
 
class ChangeMachineForm(MachineFormBase):
machine_type = None
 
class Meta(MachineFormBase.Meta):
exclude = ['machine_type']
 
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
 
if not self.instance.machine_type.has_stream:
self.fields['stream_name'].disabled = True
 
def clean(self):
# Force the machine type before doing any other cleaning
self.cleaned_data['machine_type'] = self.instance.machine_type
cleaned_data = super().clean()
 
if 'info_message' in self.changed_data:
cleaned_data['info_message_date'] = timezone.localtime()
 
return cleaned_data
 
 
class MachineDetailQueryForm(forms.Form):
calendar_year = forms.IntegerField(required=False, min_value=datetime.MINYEAR, max_value=datetime.MAXYEAR)
calendar_week = forms.IntegerField(required=False, min_value=1, max_value=53)
 
def clean(self):
cleaned_data = super().clean()
calendar_year = cleaned_data.get('calendar_year')
calendar_week = cleaned_data.get('calendar_week')
 
Error: invalid syntax (, line 118)
match calendar_year, calendar_week:
case None, int():
raise self._get_all_fields_must_be_set_validation_error()
case int(), None:
raise self._get_all_fields_must_be_set_validation_error()
 
case int(), int():
invalid_week = calendar_week > last_week_of_year(calendar_year)
if not invalid_week:
try:
year_and_week_to_monday(calendar_year, calendar_week)
except ValueError:
invalid_week = True
 
if invalid_week:
raise forms.ValidationError({
'calendar_week': forms.ValidationError(f"{calendar_week} is not a valid week number for the year {calendar_year}.",
code='invalid_calendar_week'),
})
 
return cleaned_data
 
@staticmethod
def _get_all_fields_must_be_set_validation_error():
return forms.ValidationError("Either both 'calendar_year' and 'calendar_week' must be set, or none of them.",
code='all_or_no_fields_must_be_set')