diff --git a/aleksis/apps/chronos/managers.py b/aleksis/apps/chronos/managers.py index ae8a1162c0b106fbc23e2a72bd50e71513675ced..e6ef49cd8a02bf04c4ea0f34380533b67d801235 100644 --- a/aleksis/apps/chronos/managers.py +++ b/aleksis/apps/chronos/managers.py @@ -1,10 +1,9 @@ from datetime import date, datetime, timedelta from enum import Enum -from typing import Optional, OrderedDict, Union +from typing import Optional, Union from django.db import models from django.db.models import Count, F, Q -from django.http import QueryDict from calendarweek import CalendarWeek @@ -12,6 +11,8 @@ from aleksis.apps.chronos.util.date import week_weekday_from_date from aleksis.core.models import Group, Person from aleksis.core.util.core_helpers import get_site_preferences +from .models import LessonPeriod + class TimetableType(Enum): """Enum for different types of timetables.""" @@ -26,10 +27,10 @@ class TimetableType(Enum): class LessonPeriodManager(models.Manager): - """ Manager adding specific methods to lesson periods. """ + """Manager adding specific methods to lesson periods.""" def get_queryset(self): - """ Ensures all related lesson data is loaded as well. """ + """Ensure all related lesson data is loaded as well.""" return ( super() @@ -40,10 +41,10 @@ class LessonPeriodManager(models.Manager): class LessonSubstitutionManager(models.Manager): - """ Manager adding specific methods to lesson substitutions. """ + """Manager adding specific methods to lesson substitutions.""" def get_queryset(self): - """ Ensures all related lesson data is loaded as well. """ + """Ensure all related lesson data is loaded as well.""" return ( super() @@ -61,7 +62,7 @@ class LessonSubstitutionManager(models.Manager): class WeekQuerySetMixin: def annotate_week(self, week: Union[CalendarWeek, int]): - """ Annotate all lessons in the QuerySet with the number of the provided calendar week. """ + """Annotate all lessons in the QuerySet with the number of the provided calendar week.""" if isinstance(week, CalendarWeek): week_num = week.week @@ -95,7 +96,7 @@ class GroupByPeriodsMixin: class LessonDataQuerySet(models.QuerySet, WeekQuerySetMixin): - """ Overrides default QuerySet to add specific methods for lesson data. """ + """Overrides default QuerySet to add specific methods for lesson data.""" # Overridden in the subclasses. Swaps the paths to the base lesson period # and to any substitutions depending on whether the query is run on a @@ -104,7 +105,7 @@ class LessonDataQuerySet(models.QuerySet, WeekQuerySetMixin): _subst_path = None def within_dates(self, start: date, end: date): - """ Filter for all lessons within a date range. """ + """Filter for all lessons within a date range.""" return self.filter( **{ @@ -114,7 +115,7 @@ class LessonDataQuerySet(models.QuerySet, WeekQuerySetMixin): ) def in_week(self, wanted_week: CalendarWeek): - """ Filter for all lessons within a calendar week. """ + """Filter for all lessons within a calendar week.""" return self.within_dates( wanted_week[0] + timedelta(days=1) * (F(self._period_path + "period__weekday") - 1), @@ -122,7 +123,7 @@ class LessonDataQuerySet(models.QuerySet, WeekQuerySetMixin): ).annotate_week(wanted_week) def on_day(self, day: date): - """ Filter for all lessons on a certain day. """ + """Filter for all lessons on a certain day.""" week, weekday = week_weekday_from_date(day) @@ -133,7 +134,7 @@ class LessonDataQuerySet(models.QuerySet, WeekQuerySetMixin): ) def at_time(self, when: Optional[datetime] = None): - """ Filter for the lessons taking place at a certain point in time. """ + """Filter for the lessons taking place at a certain point in time.""" now = when or datetime.now() week, weekday = week_weekday_from_date(now.date()) @@ -149,7 +150,7 @@ class LessonDataQuerySet(models.QuerySet, WeekQuerySetMixin): ).annotate_week(week) def filter_participant(self, person: Union[Person, int]): - """ Filter for all lessons a participant (student) attends. """ + """Filter for all lessons a participant (student) attends.""" return self.filter( Q(**{self._period_path + "lesson__groups__members": person}) @@ -157,7 +158,7 @@ class LessonDataQuerySet(models.QuerySet, WeekQuerySetMixin): ) def filter_group(self, group: Union[Group, int]): - """ Filter for all lessons a group (class) regularly attends. """ + """Filter for all lessons a group (class) regularly attends.""" if isinstance(group, int): group = Group.objects.get(pk=group) @@ -172,7 +173,7 @@ class LessonDataQuerySet(models.QuerySet, WeekQuerySetMixin): ) def filter_teacher(self, teacher: Union[Person, int]): - """ Filter for all lessons given by a certain teacher. """ + """Filter for all lessons given by a certain teacher.""" qs1 = self.filter(**{self._period_path + "lesson__teachers": teacher}) qs2 = self.filter( @@ -182,7 +183,7 @@ class LessonDataQuerySet(models.QuerySet, WeekQuerySetMixin): return qs1.union(qs2) def filter_room(self, room: Union["Room", int]): - """ Filter for all lessons taking part in a certain room. """ + """Filter for all lessons taking part in a certain room.""" qs1 = self.filter(**{self._period_path + "room": room}) qs2 = self.filter( @@ -235,7 +236,7 @@ class LessonDataQuerySet(models.QuerySet, WeekQuerySetMixin): return lesson_periods def next(self, reference: "LessonPeriod", offset: Optional[int] = 1) -> "LessonPeriod": - """ Get another lesson in an ordered set of lessons. + """Get another lesson in an ordered set of lessons. By default, it returns the next lesson in the set. By passing the offset argument, the n-th next lesson can be selected. By passing a negative number, the n-th @@ -268,20 +269,23 @@ class LessonSubstitutionQuerySet(LessonDataQuerySet): _subst_path = "" def affected_lessons(self): - """ Return all lessons which are affected by selected substitutions """ + """Return all lessons which are affected by selected substitutions.""" from .models import Lesson # noaq return Lesson.objects.filter(lesson_periods__substitutions__in=self) def affected_teachers(self): - """ Return all teachers which are affected by selected substitutions (as substituted or substituting) """ + """Get affected teachers. + + Return all teachers which are affected by + selected substitutions (as substituted or substituting).""" return Person.objects.filter( Q(lessons_as_teacher__in=self.affected_lessons()) | Q(lesson_substitutions__in=self) ).annotate(lessons_count=Count("lessons_as_teacher")) def affected_groups(self): - """ Return all groups which are affected by selected substitutions """ + """Return all groups which are affected by selected substitutions.""" return Group.objects.filter(lessons__in=self.affected_lessons()).annotate( lessons_count=Count("lessons") @@ -295,22 +299,22 @@ class DateRangeQuerySet(models.QuerySet): """ def within_dates(self, start: date, end: date): - """ Filter for all events within a date range. """ + """Filter for all events within a date range.""" return self.filter(date_start__lte=end, date_end__gte=start) def in_week(self, wanted_week: CalendarWeek): - """ Filter for all events within a calendar week. """ + """Filter for all events within a calendar week.""" return self.within_dates(wanted_week[0], wanted_week[6]) def on_day(self, day: date): - """ Filter for all events on a certain day. """ + """Filter for all events on a certain day.""" return self.within_dates(day, day) def at_time(self, when: Optional[datetime] = None): - """ Filter for the events taking place at a certain point in time. """ + """Filter for the events taking place at a certain point in time.""" now = when or datetime.now() @@ -350,7 +354,7 @@ class SupervisionQuerySet(models.QuerySet, WeekQuerySetMixin): ) def filter_by_teacher(self, teacher: Union[Person, int]): - """ Filter for all supervisions given by a certain teacher. """ + """Filter for all supervisions given by a certain teacher.""" if self.count() > 0: if hasattr(self[0], "_week"): @@ -371,21 +375,21 @@ class SupervisionQuerySet(models.QuerySet, WeekQuerySetMixin): class TimetableQuerySet(models.QuerySet): """Common query set methods for objects in timetables. - Models need following fields: - - groups - - teachers - - rooms (_multiple_rooms=True)/room (_multiple_rooms=False) - """ + Models need following fields: + - groups + - teachers + - rooms (_multiple_rooms=True)/room (_multiple_rooms=False) + """ _multiple_rooms = True def filter_participant(self, person: Union[Person, int]): - """ Filter for all objects a participant (student) attends. """ + """Filter for all objects a participant (student) attends.""" return self.filter(Q(groups_members=person)) def filter_group(self, group: Union[Group, int]): - """ Filter for all objects a group (class) attends. """ + """Filter for all objects a group (class) attends.""" if isinstance(group, int): group = Group.objects.get(pk=group) @@ -397,12 +401,12 @@ class TimetableQuerySet(models.QuerySet): return self.filter(Q(groups=group) | Q(groups__parent_groups=group)) def filter_teacher(self, teacher: Union[Person, int]): - """ Filter for all lessons given by a certain teacher. """ + """Filter for all lessons given by a certain teacher.""" return self.filter(teachers=teacher) def filter_room(self, room: Union["Room", int]): - """ Filter for all objects taking part in a certain room. """ + """Filter for all objects taking part in a certain room.""" if self._multiple_rooms: return self.filter(rooms=room) @@ -445,7 +449,7 @@ class EventQuerySet(DateRangeQuerySet, TimetableQuerySet): """QuerySet with custom query methods for events.""" def annotate_day(self, day: date): - """ Annotate all events in the QuerySet with the provided date. """ + """Annotate all events in the QuerySet with the provided date.""" return self.annotate(_date=models.Value(day, models.DateField())) diff --git a/aleksis/apps/chronos/model_extensions.py b/aleksis/apps/chronos/model_extensions.py index 774f992d3bd7ca133df0ec0c3591a397c31fe9f1..91b40aa1324e123555941c846d191e1a35ab00de 100644 --- a/aleksis/apps/chronos/model_extensions.py +++ b/aleksis/apps/chronos/model_extensions.py @@ -12,14 +12,14 @@ from .models import Lesson, LessonPeriod @Person.property def is_teacher(self): - """ Check if the user has lessons as a teacher """ + """Check if the user has lessons as a teacher.""" return self.lesson_periods_as_teacher.exists() @Person.property def timetable_type(self) -> Optional[TimetableType]: - """ Return which type of timetable this user has """ + """Return which type of timetable this user has.""" if self.is_teacher: return TimetableType.TEACHER @@ -31,7 +31,7 @@ def timetable_type(self) -> Optional[TimetableType]: @Person.property def timetable_object(self) -> Optional[Union[Group, Person]]: - """ Return the object which has the user's timetable """ + """Return the object which has the user's timetable.""" type_ = self.timetable_type @@ -45,7 +45,7 @@ def timetable_object(self) -> Optional[Union[Group, Person]]: @Person.property def lessons_as_participant(self): - """ Return a `QuerySet` containing all `Lesson`s this person + """Return a `QuerySet` containing all `Lesson`s this person participates in (as student). .. note:: Only available when AlekSIS-App-Chronos is installed. @@ -60,7 +60,7 @@ def lessons_as_participant(self): @Person.property def lesson_periods_as_participant(self): - """ Return a `QuerySet` containing all `LessonPeriod`s this person + """Return a `QuerySet` containing all `LessonPeriod`s this person participates in (as student). .. note:: Only available when AlekSIS-App-Chronos is installed. @@ -75,7 +75,7 @@ def lesson_periods_as_participant(self): @Person.property def lesson_periods_as_teacher(self): - """ Return a `QuerySet` containing all `Lesson`s this person + """Return a `QuerySet` containing all `Lesson`s this person gives (as teacher). .. note:: Only available when AlekSIS-App-Chronos is installed. diff --git a/aleksis/apps/chronos/models.py b/aleksis/apps/chronos/models.py index a35a9332f1ae26ef5d8a23265814c1df366cf54f..6d7c302747459514e1d3b955b75294da4e049915 100644 --- a/aleksis/apps/chronos/models.py +++ b/aleksis/apps/chronos/models.py @@ -31,11 +31,10 @@ from aleksis.apps.chronos.managers import ( SupervisionQuerySet, TeacherPropertiesMixin, ) -from aleksis.apps.chronos.util.date import week_weekday_from_date from aleksis.apps.chronos.util.format import format_m2m from aleksis.core.mixins import ExtensibleModel -from aleksis.core.models import DashboardWidget, Group, Person -from aleksis.core.util.core_helpers import get_site_preferences, has_person +from aleksis.core.models import DashboardWidget +from aleksis.core.util.core_helpers import has_person class TimePeriod(ExtensibleModel): @@ -77,7 +76,7 @@ class TimePeriod(ExtensibleModel): def get_next_relevant_day( cls, day: Optional[date] = None, time: Optional[time] = None, prev: bool = False ) -> date: - """ Returns next (previous) day with lessons depending on date and time """ + """Return next (previous) day with lessons depending on date and time.""" if day is None: day = timezone.now().date() @@ -105,7 +104,7 @@ class TimePeriod(ExtensibleModel): @classmethod def get_prev_next_by_day(cls, day: date, url: str) -> Tuple[str, str]: - """ Build URLs for previous/next day """ + """Build URLs for previous/next day.""" day_prev = cls.get_next_relevant_day(day - timedelta(days=1), prev=True) day_next = cls.get_next_relevant_day(day + timedelta(days=1)) @@ -235,7 +234,7 @@ class LessonSubstitution(ExtensibleModel): default=False, verbose_name=_("Cancelled for teachers?") ) - comment = models.TextField(verbose_name=_("Comment"), blank=True, null=True) + comment = models.TextField(verbose_name=_("Comment"), blank=True) def clean(self) -> None: if self.subject and self.cancelled: @@ -441,7 +440,7 @@ class Absence(ExtensibleModel): null=True, related_name="+", ) - comment = models.TextField(verbose_name=_("Comment"), blank=True, null=True) + comment = models.TextField(verbose_name=_("Comment"), blank=True) def __str__(self): if self.teacher: @@ -482,7 +481,7 @@ class Exam(ExtensibleModel): ) title = models.CharField(verbose_name=_("Title"), max_length=255) - comment = models.TextField(verbose_name=_("Comment"), blank=True, null=True) + comment = models.TextField(verbose_name=_("Comment"), blank=True) class Meta: ordering = ["date"] @@ -497,7 +496,7 @@ class Holiday(ExtensibleModel): title = models.CharField(verbose_name=_("Title"), max_length=255) date_start = models.DateField(verbose_name=_("Start date"), null=True) date_end = models.DateField(verbose_name=_("End date"), null=True) - comments = models.TextField(verbose_name=_("Comments"), null=True, blank=True) + comments = models.TextField(verbose_name=_("Comments"), blank=True) @classmethod def on_day(cls, day: date) -> Optional["Holiday"]: @@ -674,7 +673,7 @@ class Event(ExtensibleModel, GroupPropertiesMixin, TeacherPropertiesMixin): objects = models.Manager.from_queryset(EventQuerySet)() - title = models.CharField(verbose_name=_("Title"), max_length=255, blank=True, null=True) + title = models.CharField(verbose_name=_("Title"), max_length=255, blank=True) date_start = models.DateField(verbose_name=_("Start date"), null=True) date_end = models.DateField(verbose_name=_("End date"), null=True) @@ -750,7 +749,7 @@ class ExtraLesson(ExtensibleModel, GroupPropertiesMixin): "Room", models.CASCADE, null=True, related_name="extra_lessons", verbose_name=_("Room"), ) - comment = models.CharField(verbose_name=_("Comment"), blank=True, null=True, max_length=255) + comment = models.CharField(verbose_name=_("Comment"), blank=True, max_length=255) def __str__(self): return f"{self.week}, {self.period}, {self.subject}" diff --git a/aleksis/apps/chronos/preferences.py b/aleksis/apps/chronos/preferences.py index 31b1fdb1a521aa8901206b0ed9f1c579a030cef3..10906276220ad376fc55c00c671ac4b1a1df5f6f 100644 --- a/aleksis/apps/chronos/preferences.py +++ b/aleksis/apps/chronos/preferences.py @@ -3,7 +3,10 @@ from django.utils.translation import gettext as _ from dynamic_preferences.preferences import Section from dynamic_preferences.types import BooleanPreference, IntegerPreference -from aleksis.core.registries import person_preferences_registry, site_preferences_registry +from aleksis.core.registries import ( + person_preferences_registry, + site_preferences_registry, +) chronos = Section("chronos", verbose_name=_("Chronos")) @@ -37,7 +40,8 @@ class ShortenGroupsLimit(IntegerPreference): default = 4 verbose_name = _("Limit of groups for shortening of groups") help_text = _( - "If an user activates shortening of groups, they will be collapsed if there are more groups than this limit." + "If an user activates shortening of groups," + "they will be collapsed if there are more groups than this limit." ) diff --git a/aleksis/apps/chronos/rules.py b/aleksis/apps/chronos/rules.py index 6feb45b5f6182800d2979f86ea52909e9d51963e..7ee9d1e0dcfb7b937b24ef82bb1adf36fa10dc46 100644 --- a/aleksis/apps/chronos/rules.py +++ b/aleksis/apps/chronos/rules.py @@ -1,4 +1,4 @@ -from rules import add_perm, always_allow +from rules import add_perm from aleksis.core.util.predicates import ( has_any_object, diff --git a/aleksis/apps/chronos/templatetags/common.py b/aleksis/apps/chronos/templatetags/common.py index cfdec15c8a19e0e2281b89490ce9e133000e741c..5a066c90d7b879356cdf9546f1fa015db6bb4f55 100644 --- a/aleksis/apps/chronos/templatetags/common.py +++ b/aleksis/apps/chronos/templatetags/common.py @@ -20,7 +20,8 @@ class SetVarNode(template.Node): @register.tag(name="set") def set_var(parser, token): - """ + """Set var. + {% set some_var = '123' %} """ parts = token.split_contents() diff --git a/aleksis/apps/chronos/templatetags/week_helpers.py b/aleksis/apps/chronos/templatetags/week_helpers.py index acfb3a3a8859cc50c9e250520d9bcb32f3764ebe..054d3f9e2c3feac25e5067db9df324124a771f88 100644 --- a/aleksis/apps/chronos/templatetags/week_helpers.py +++ b/aleksis/apps/chronos/templatetags/week_helpers.py @@ -4,7 +4,11 @@ from typing import Optional, Union from django import template from django.db.models.query import QuerySet -from aleksis.apps.chronos.util.date import CalendarWeek, week_period_to_date, week_weekday_to_date +from aleksis.apps.chronos.util.date import ( + CalendarWeek, + week_period_to_date, + week_weekday_to_date, +) register = template.Library() diff --git a/aleksis/apps/chronos/util/build.py b/aleksis/apps/chronos/util/build.py index d816403f06f422a8e4d0a4bc99bcca3ba14d76d1..a5290ebbbf2a18013acb98cf17b6be57752847cd 100644 --- a/aleksis/apps/chronos/util/build.py +++ b/aleksis/apps/chronos/util/build.py @@ -3,7 +3,6 @@ from datetime import date from typing import List, Tuple, Union from django.apps import apps -from django.db.models import QuerySet from calendarweek import CalendarWeek diff --git a/aleksis/apps/chronos/util/date.py b/aleksis/apps/chronos/util/date.py index 68bfcd3829f590feb8970aabfc50471408bd9c3a..026439d059f7a77d3ccc9031000f059eff868dca 100644 --- a/aleksis/apps/chronos/util/date.py +++ b/aleksis/apps/chronos/util/date.py @@ -1,11 +1,7 @@ from datetime import date from typing import List, Tuple, Union -from django.utils import timezone -from django.utils.translation import gettext_lazy as _ - from calendarweek import CalendarWeek -from calendarweek.django import i18n_day_names def week_weekday_from_date(when: date) -> Tuple[CalendarWeek, int]: diff --git a/aleksis/apps/chronos/util/format.py b/aleksis/apps/chronos/util/format.py index ee9be702d00506f118974e533dd237f63825fb76..b5bf35c7816882330b3491b2957d2d84f307b3b8 100644 --- a/aleksis/apps/chronos/util/format.py +++ b/aleksis/apps/chronos/util/format.py @@ -2,6 +2,8 @@ from datetime import date from django.utils.formats import date_format +from ..models import TimePeriod + def format_m2m(f, attr: str = "short_name") -> str: """Join a attribute of all elements of a ManyToManyField.""" diff --git a/aleksis/apps/chronos/util/js.py b/aleksis/apps/chronos/util/js.py index 9449fd2c56b69f3478c0606b145f11b69d75e324..d906e9bf85f7b6ec56098fafe2214b0476ba002a 100644 --- a/aleksis/apps/chronos/util/js.py +++ b/aleksis/apps/chronos/util/js.py @@ -2,7 +2,7 @@ from datetime import date, datetime, time def date_unix(value: date) -> int: - """ Converts a date object to an UNIX timestamp """ + """Convert a date object to an UNIX timestamp.""" value = datetime.combine(value, time(hour=0, minute=0)) return int(value.timestamp()) * 1000 diff --git a/aleksis/apps/chronos/util/predicates.py b/aleksis/apps/chronos/util/predicates.py index c011acbdd31614638fdf2bddc38acc70a43cbf43..e310f6cdd7f3a7b0a8a46fcab2be0c57c7d65103 100644 --- a/aleksis/apps/chronos/util/predicates.py +++ b/aleksis/apps/chronos/util/predicates.py @@ -9,7 +9,7 @@ from aleksis.core.models import Group, Person @predicate def has_timetable_perm(user: User, obj: Model) -> bool: - """ Predicate which checks whether the user is allowed to access the requested timetable """ + """Predicate which checks whether the user is allowed to access the requested timetable.""" if obj.model is Group: return obj in user.person.member_of diff --git a/aleksis/apps/chronos/views.py b/aleksis/apps/chronos/views.py index 87621266133799d3e3ffc3580b1076955c3042ec..04e975f7ea3d138baefdb05ec754cff8f13feef2 100644 --- a/aleksis/apps/chronos/views.py +++ b/aleksis/apps/chronos/views.py @@ -1,8 +1,6 @@ -from collections import OrderedDict -from datetime import date, datetime, timedelta -from typing import Optional, Tuple +from datetime import datetime, timedelta +from typing import Optional -from django.contrib.auth.decorators import login_required from django.db.models import Count from django.http import HttpRequest, HttpResponse, HttpResponseNotFound from django.shortcuts import get_object_or_404, redirect, render