Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • AlekSIS/official/AlekSIS-App-Chronos
  • sunweaver/AlekSIS-App-Chronos
  • sggua/AlekSIS-App-Chronos
  • tincmeKdenka/AlekSIS-App-Chronos
  • ligquamacti/AlekSIS-App-Chronos
  • 1crotatilhe/AlekSIS-App-Chronos
  • 1compluningi/AlekSIS-App-Chronos
  • starwardcarfi/AlekSIS-App-Chronos
  • ceohecholeg/AlekSIS-App-Chronos
  • 7quecontranchi/AlekSIS-App-Chronos
  • 8evsubcesza/AlekSIS-App-Chronos
  • unscinKibdzu/AlekSIS-App-Chronos
  • delucPchondmu/AlekSIS-App-Chronos
13 results
Show changes
Commits on Source (16)
Showing
with 213 additions and 94 deletions
......@@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-05-04 15:42+0200\n"
"PO-Revision-Date: 2020-07-26 14:09+0000\n"
"PO-Revision-Date: 2020-09-06 17:49+0000\n"
"Last-Translator: Jonathan Weth <teckids@jonathanweth.de>\n"
"Language-Team: German <https://translate.edugit.org/projects/aleksis/"
"aleksis-app-chronos/de/>\n"
......@@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.0.1\n"
"X-Generator: Weblate 4.1.1\n"
#: forms.py:29
msgid "Options for timetables"
......@@ -226,7 +226,7 @@ msgstr "Absenz"
#: models.py:458
msgid "Absences"
msgstr "Absenzen"
msgstr "Fehlstunden"
#: models.py:466
msgid "Date of exam"
......@@ -472,7 +472,7 @@ msgstr "Stundenplan"
#: templates/chronos/timetable.html:28
msgid "Group teachers:"
msgstr "Grupenlehrkräfte:"
msgstr "Gruppenlehrkräfte:"
#: templates/chronos/timetable.html:55
msgid "Show regular timetable"
......
......@@ -3,19 +3,21 @@
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-05-04 15:42+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"PO-Revision-Date: 2020-08-23 13:49+0000\n"
"Last-Translator: Jonathan Weth <teckids@jonathanweth.de>\n"
"Language-Team: Latin <https://translate.edugit.org/projects/aleksis/"
"aleksis-app-chronos/la/>\n"
"Language: la\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.1.1\n"
#: forms.py:29
msgid "Options for timetables"
......@@ -203,7 +205,7 @@ msgstr ""
#: models.py:415
msgid "Group"
msgstr ""
msgstr "Grex"
#: models.py:431 models.py:470
msgid "Start period"
......
......@@ -36,7 +36,7 @@ class ValidityRangeRelatedQuerySet(QuerySet):
def for_validity_range(
self, validity_range: "ValidityRange"
) -> "ValidityRangeRelatedQuerySet":
return self.filter(validity_range=validity_range)
return self.filter(validity=validity_range)
def for_current_or_all(self) -> "ValidityRangeRelatedQuerySet":
"""Get all objects related to current validity range.
......@@ -114,10 +114,8 @@ class LessonSubstitutionManager(CurrentSiteManager):
class WeekQuerySetMixin:
def annotate_week(self, week: Union[CalendarWeek, int]):
def annotate_week(self, week: Union[CalendarWeek]):
"""Annotate all lessons in the QuerySet with the number of the provided calendar week."""
if isinstance(week, int):
week = CalendarWeek(week=week)
return self.annotate(
_week=models.Value(week.week, models.IntegerField()),
......@@ -201,9 +199,7 @@ class LessonDataQuerySet(models.QuerySet, WeekQuerySetMixin):
def filter_participant(self, person: Union[Person, int]):
"""Filter for all lessons a participant (student) attends."""
return self.filter(
Q(**{self._period_path + "lesson__groups__members": person})
)
return self.filter(Q(**{self._period_path + "lesson__groups__members": person}))
def filter_group(self, group: Union[Group, int]):
"""Filter for all lessons a group (class) regularly attends."""
......@@ -226,6 +222,7 @@ class LessonDataQuerySet(models.QuerySet, WeekQuerySetMixin):
**{
self._subst_path + "teachers": teacher,
self._subst_path + "week": F("_week"),
self._subst_path + "year": F("_year"),
}
)
......@@ -235,7 +232,11 @@ class LessonDataQuerySet(models.QuerySet, WeekQuerySetMixin):
"""Filter for all lessons taking part in a certain room."""
qs1 = self.filter(**{self._period_path + "room": room})
qs2 = self.filter(
**{self._subst_path + "room": room, self._subst_path + "week": F("_week"),}
**{
self._subst_path + "room": room,
self._subst_path + "week": F("_week"),
self._subst_path + "year": F("_year"),
}
)
return qs1.union(qs2)
......@@ -303,6 +304,8 @@ class LessonDataQuerySet(models.QuerySet, WeekQuerySetMixin):
else:
week = reference._week
week = CalendarWeek(week=week, year=reference.lesson.get_year(week))
return self.annotate_week(week).all()[next_index]
......@@ -409,7 +412,7 @@ class SupervisionQuerySet(ValidityRangeRelatedQuerySet, WeekQuerySetMixin):
"""Filter for all supervisions given by a certain teacher."""
if self.count() > 0:
if hasattr(self[0], "_week"):
week = CalendarWeek(week=self[0]._week)
week = CalendarWeek(week=self[0]._week, year=self[0]._year)
else:
week = CalendarWeek.current_week()
......@@ -517,6 +520,8 @@ class ExtraLessonQuerySet(
return self.filter(
week__gte=week_start.week,
week__lte=week_end.week,
year__gte=week_start.year,
year__lte=week_end.year,
period__weekday__gte=start.weekday(),
period__weekday__lte=end.weekday(),
)
......
# Generated by Django 3.0.9 on 2020-08-13 14:06
from django.db import migrations, models
import aleksis.apps.chronos.util.date
def migrate_data(apps, schema_editor):
LessonSubstitution = apps.get_model("chronos", "LessonSubstitution")
ExtraLesson = apps.get_model("chronos", "ExtraLesson")
db_alias = schema_editor.connection.alias
for sub in LessonSubstitution.objects.using(db_alias).all():
year = sub.lesson_period.lesson.validity.date_start.year
if sub.week < int(sub.lesson_period.lesson.validity.date_start.strftime("%V")):
year += 1
sub.year = year
sub.save()
for extra_lesson in ExtraLesson.objects.using(db_alias).all():
year = aleksis.apps.chronos.util.date.get_current_year()
extra_lesson.year = year
extra_lesson.save()
class Migration(migrations.Migration):
dependencies = [
("core", "0003_drop_image_cropping"),
("chronos", "0003_school_term_validity_fixes"),
]
operations = [
migrations.AddField(
model_name="extralesson",
name="year",
field=models.IntegerField(
default=aleksis.apps.chronos.util.date.get_current_year,
verbose_name="Year",
),
),
migrations.AddField(
model_name="lessonsubstitution",
name="year",
field=models.IntegerField(
default=aleksis.apps.chronos.util.date.get_current_year,
verbose_name="Year",
),
),
migrations.RunPython(migrate_data),
]
from datetime import date
from typing import Union
from django.db import models
from django.utils.translation import gettext as _
from calendarweek import CalendarWeek
from aleksis.apps.chronos.util.date import week_weekday_to_date
from aleksis.core.managers import CurrentSiteManagerWithoutMigrations
from aleksis.core.mixins import ExtensibleModel
......@@ -25,3 +31,28 @@ class ValidityRangeRelatedExtensibleModel(ExtensibleModel):
class Meta:
abstract = True
class WeekRelatedMixin:
@property
def date(self) -> date:
return week_weekday_to_date(
self.calendar_week, self.lesson_period.period.weekday
)
@property
def calendar_week(self) -> CalendarWeek:
return CalendarWeek(week=self.week, year=self.year)
class WeekAnnotationMixin:
@property
def week(self) -> Union[CalendarWeek, None]:
"""Get annotated week as `CalendarWeek`.
Defaults to `None` if no week is annotated.
"""
if hasattr(self, "_week"):
return CalendarWeek(week=self._week, year=self._year)
else:
return None
......@@ -3,7 +3,7 @@
from __future__ import annotations
from datetime import date, datetime, time, timedelta
from typing import Dict, Optional, Tuple, Union
from typing import Dict, List, Optional, Tuple, Union
from django.core.exceptions import ValidationError
from django.db import models
......@@ -35,7 +35,12 @@ from aleksis.apps.chronos.managers import (
TeacherPropertiesMixin,
ValidityRangeQuerySet,
)
from aleksis.apps.chronos.mixins import ValidityRangeRelatedExtensibleModel
from aleksis.apps.chronos.mixins import (
ValidityRangeRelatedExtensibleModel,
WeekAnnotationMixin,
WeekRelatedMixin,
)
from aleksis.apps.chronos.util.date import get_current_year
from aleksis.apps.chronos.util.format import format_m2m
from aleksis.core.managers import CurrentSiteManagerWithoutMigrations
from aleksis.core.mixins import ExtensibleModel, SchoolTermRelatedExtensibleModel
......@@ -135,15 +140,12 @@ class TimePeriod(ValidityRangeRelatedExtensibleModel):
return periods
def get_date(self, week: Optional[Union[CalendarWeek, int]] = None) -> date:
def get_date(self, week: Optional[CalendarWeek] = None) -> date:
if isinstance(week, CalendarWeek):
wanted_week = week
else:
year = date.today().year
week_number = week or getattr(self, "_week", None) or CalendarWeek().week
if week_number < SchoolTerm.current.date_start.isocalendar()[1]:
year += 1
year = getattr(self, "_year", None) or date.today().year
week_number = getattr(self, "_week", None) or CalendarWeek().week
wanted_week = CalendarWeek(year=year, week=week_number)
......@@ -252,6 +254,23 @@ class TimePeriod(ValidityRangeRelatedExtensibleModel):
.get("weekday__max")
)
@classproperty
def period_choices(cls) -> List[Tuple[Union[str, int], str]]:
"""Build choice list of periods for usage within Django."""
time_periods = (
cls.objects.filter(weekday=cls.weekday_min)
.for_current_or_all()
.values("period", "time_start", "time_end")
.distinct()
)
period_choices = [("", "")] + [
(period, f"{period}.")
for period in time_periods.values_list("period", flat=True)
]
return period_choices
class Meta:
unique_together = [["weekday", "period", "validity"]]
ordering = ["weekday", "period"]
......@@ -335,12 +354,13 @@ class Lesson(
verbose_name_plural = _("Lessons")
class LessonSubstitution(ExtensibleModel):
class LessonSubstitution(ExtensibleModel, WeekRelatedMixin):
objects = LessonSubstitutionManager.from_queryset(LessonSubstitutionQuerySet)()
week = models.IntegerField(
verbose_name=_("Week"), default=CalendarWeek.current_week
)
year = models.IntegerField(verbose_name=_("Year"), default=get_current_year)
lesson_period = models.ForeignKey(
"LessonPeriod", models.CASCADE, "substitutions", verbose_name=_("Lesson period")
......@@ -379,7 +399,7 @@ class LessonSubstitution(ExtensibleModel):
@property
def date(self):
week = CalendarWeek(week=self.week, year=self.lesson_period.lesson.get_year())
week = CalendarWeek(week=self.week, year=self.year)
return week[self.lesson_period.period.weekday]
def __str__(self):
......@@ -388,7 +408,7 @@ class LessonSubstitution(ExtensibleModel):
class Meta:
unique_together = [["lesson_period", "week"]]
ordering = [
"lesson_period__lesson__validity__date_start",
"year",
"week",
"lesson_period__period__weekday",
"lesson_period__period__period",
......@@ -403,7 +423,7 @@ class LessonSubstitution(ExtensibleModel):
verbose_name_plural = _("Lesson substitutions")
class LessonPeriod(ExtensibleModel):
class LessonPeriod(ExtensibleModel, WeekAnnotationMixin):
label_ = "lesson_period"
objects = LessonPeriodManager.from_queryset(LessonPeriodQuerySet)()
......@@ -429,14 +449,19 @@ class LessonPeriod(ExtensibleModel):
verbose_name=_("Room"),
)
def get_substitution(self, week: Optional[int] = None) -> LessonSubstitution:
wanted_week = week or getattr(self, "_week", None) or CalendarWeek().week
def get_substitution(
self, week: Optional[CalendarWeek] = None
) -> LessonSubstitution:
wanted_week = week or self.week or CalendarWeek()
# We iterate over all substitutions because this can make use of
# prefetching when this model is loaded from outside, in contrast
# to .filter()
for substitution in self.substitutions.all():
if substitution.week == wanted_week:
if (
substitution.week == wanted_week.week
and substitution.year == wanted_week.year
):
return substitution
return None
......@@ -485,17 +510,6 @@ class LessonPeriod(ExtensibleModel):
"""
return LessonPeriod.objects.filter(lesson=self.lesson).next_lesson(self, -1)
@property
def week(self) -> Union[CalendarWeek, None]:
"""Get annotated week as `CalendarWeek`.
Defaults to `None` if no week is annotated.
"""
if hasattr(self, "_week"):
return CalendarWeek(week=self._week, year=self._year)
else:
return None
class Meta:
ordering = [
"lesson__validity__date_start",
......@@ -797,7 +811,7 @@ class Break(ValidityRangeRelatedExtensibleModel):
verbose_name_plural = _("Breaks")
class Supervision(ValidityRangeRelatedExtensibleModel):
class Supervision(ValidityRangeRelatedExtensibleModel, WeekAnnotationMixin):
objects = CurrentSiteManager.from_queryset(SupervisionQuerySet)()
area = models.ForeignKey(
......@@ -816,11 +830,16 @@ class Supervision(ValidityRangeRelatedExtensibleModel):
verbose_name=_("Teacher"),
)
def get_year(self, week: int) -> int:
year = self.validity.date_start.year
if week < int(self.validity.date_start.strftime("%V")):
year += 1
return year
def get_substitution(
self, week: Optional[int] = None
self, week: Optional[CalendarWeek] = None
) -> Optional[SupervisionSubstitution]:
wanted_week = week or getattr(self, "_week", None) or CalendarWeek().week
wanted_week = CalendarWeek(week=wanted_week)
wanted_week = week or self.week or CalendarWeek()
# We iterate over all substitutions because this can make use of
# prefetching when this model is loaded from outside, in contrast
# to .filter()
......@@ -939,7 +958,9 @@ class Event(
verbose_name_plural = _("Events")
class ExtraLesson(SchoolTermRelatedExtensibleModel, GroupPropertiesMixin):
class ExtraLesson(
SchoolTermRelatedExtensibleModel, GroupPropertiesMixin, WeekRelatedMixin
):
label_ = "extra_lesson"
objects = CurrentSiteManager.from_queryset(ExtraLessonQuerySet)()
......@@ -947,6 +968,7 @@ class ExtraLesson(SchoolTermRelatedExtensibleModel, GroupPropertiesMixin):
week = models.IntegerField(
verbose_name=_("Week"), default=CalendarWeek.current_week
)
year = models.IntegerField(verbose_name=_("Year"), default=get_current_year)
period = models.ForeignKey(
"TimePeriod",
models.CASCADE,
......
......@@ -14,8 +14,8 @@ def _css_class_from_lesson_state(
record: Optional[LessonPeriod] = None, table: Optional[LessonsTable] = None
) -> str:
"""Return CSS class depending on lesson state."""
if record.get_substitution(record._week):
if record.get_substitution(record._week).cancelled:
if record.get_substitution():
if record.get_substitution().cancelled:
return "success"
else:
return "warning"
......
......@@ -22,7 +22,7 @@ def week_end(week: CalendarWeek) -> date:
@register.filter
def only_week(qs: QuerySet, week: Optional[CalendarWeek]) -> QuerySet:
wanted_week = week or CalendarWeek()
return qs.filter(week=wanted_week.week)
return qs.filter(week=wanted_week.week, year=wanted_week.year)
@register.simple_tag
......@@ -31,12 +31,12 @@ def weekday_to_date(week: CalendarWeek, weekday: int) -> date:
@register.simple_tag
def period_to_date(week: Union[CalendarWeek, int], period) -> date:
def period_to_date(week: CalendarWeek, period) -> date:
return week_period_to_date(week, period)
@register.simple_tag
def period_to_time_start(week: Union[CalendarWeek, int], period) -> date:
def period_to_time_start(week: CalendarWeek, period) -> date:
return period.get_datetime_start(week)
......
......@@ -61,9 +61,9 @@ def build_timetable(
if is_person:
extra_lessons = ExtraLesson.objects.on_day(date_ref).filter_from_person(obj)
else:
extra_lessons = ExtraLesson.objects.filter(week=date_ref.week).filter_from_type(
type_, obj
)
extra_lessons = ExtraLesson.objects.filter(
week=date_ref.week, year=date_ref.year
).filter_from_type(type_, obj)
# Sort lesson periods in a dict
extra_lessons_per_period = extra_lessons.group_by_periods(is_person=is_person)
......
......@@ -32,5 +32,5 @@ def get_substitution_by_id(request: HttpRequest, id_: int, week: int):
wanted_week = lesson_period.lesson.get_calendar_week(week)
return LessonSubstitution.objects.filter(
week=wanted_week.week, lesson_period=lesson_period
week=wanted_week.week, year=wanted_week.year, lesson_period=lesson_period
).first()
from datetime import date
from typing import List, Tuple, Union
from django.utils import timezone
from calendarweek import CalendarWeek
......@@ -14,7 +16,7 @@ def week_weekday_to_date(week: CalendarWeek, weekday: int) -> date:
return week[weekday]
def week_period_to_date(week: Union[CalendarWeek, int], period) -> date:
def week_period_to_date(week: CalendarWeek, period) -> date:
"""Return the date of a lesson period in a given week."""
return period.get_date(week)
......@@ -31,3 +33,9 @@ def get_weeks_for_year(year: int) -> List[CalendarWeek]:
current_week += 1
return weeks
def get_current_year() -> int:
"""Get current year."""
return timezone.now().year
......@@ -33,7 +33,7 @@ def all_timetables(request: HttpRequest) -> HttpResponse:
teachers = Person.objects.annotate(
lessons_count=Count("lessons_as_teacher")
).filter(lessons_count__gt=0)
groups = Group.objects.annotate(
groups = Group.objects.for_current_school_term_or_all().annotate(
lessons_count=Count("lessons"),
child_lessons_count=Count("child_groups__lessons"),
)
......
......@@ -68,11 +68,11 @@ extras = ["phonenumbers"]
version = ">=3.0,<4.0"
[package.dependencies.django-two-factor-auth]
extras = ["yubikey", "call", "phonenumbers", "sms"]
extras = ["call", "phonenumbers", "yubikey", "sms"]
version = ">=1.11.0,<2.0.0"
[package.dependencies.dynaconf]
extras = ["ini", "toml", "yaml"]
extras = ["toml", "ini", "yaml"]
version = ">=2.0,<3.0"
[package.extras]
......@@ -983,18 +983,15 @@ description = "flake8 plugin that integrates isort ."
name = "flake8-isort"
optional = false
python-versions = "*"
version = "3.0.0"
version = "4.0.0"
[package.dependencies]
flake8 = ">=3.2.1"
testfixtures = "*"
[package.dependencies.isort]
extras = ["pyproject"]
version = ">=4.3.5"
flake8 = ">=3.2.1,<4"
isort = ">=4.3.5,<6"
testfixtures = ">=6.8.0,<7"
[package.extras]
test = ["pytest"]
test = ["pytest (>=4.0.2,<6)", "toml"]
[[package]]
category = "dev"
......@@ -1094,6 +1091,14 @@ zipp = ">=0.5"
docs = ["sphinx", "rst.linker"]
testing = ["packaging", "pep517", "importlib-resources (>=1.3)"]
[[package]]
category = "dev"
description = "iniconfig: brain-dead simple config-ini parsing"
name = "iniconfig"
optional = false
python-versions = "*"
version = "1.0.1"
[[package]]
category = "dev"
description = "A Python utility / library to sort Python imports."
......@@ -1355,24 +1360,25 @@ description = "pytest: simple powerful testing with Python"
name = "pytest"
optional = false
python-versions = ">=3.5"
version = "5.4.3"
version = "6.0.1"
[package.dependencies]
atomicwrites = ">=1.0"
attrs = ">=17.4.0"
colorama = "*"
iniconfig = "*"
more-itertools = ">=4.0.0"
packaging = "*"
pluggy = ">=0.12,<1.0"
py = ">=1.5.0"
wcwidth = "*"
py = ">=1.8.2"
toml = "*"
[package.dependencies.importlib-metadata]
python = "<3.8"
version = ">=0.12"
[package.extras]
checkqa-mypy = ["mypy (v0.761)"]
checkqa_mypy = ["mypy (0.780)"]
testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"]
[[package]]
......@@ -1896,14 +1902,6 @@ brotli = ["brotlipy (>=0.6.0)"]
secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "pyOpenSSL (>=0.14)", "ipaddress"]
socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"]
[[package]]
category = "dev"
description = "Measures the displayed width of unicode strings in a terminal"
name = "wcwidth"
optional = false
python-versions = "*"
version = "0.2.5"
[[package]]
category = "main"
description = "Character encoding aliases for legacy web content"
......@@ -1938,7 +1936,7 @@ docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"]
testing = ["jaraco.itertools", "func-timeout"]
[metadata]
content-hash = "daccd1e77d4c27faa42b2cfbd540acdfaabce5b277fb2e807849df64e18df6ba"
content-hash = "dca6ee2757f8f6d76504c5dfbe91e2bd66a6d74d5ab2e10d43cb84b9486ce254"
python-versions = "^3.7"
[metadata.files]
......@@ -2268,8 +2266,8 @@ flake8-fixme = [
{file = "flake8_fixme-1.1.1-py2.py3-none-any.whl", hash = "sha256:226a6f2ef916730899f29ac140bed5d4a17e5aba79f00a0e3ae1eff1997cb1ac"},
]
flake8-isort = [
{file = "flake8-isort-3.0.0.tar.gz", hash = "sha256:3ce227b5c5342b6d63937d3863e8de8783ae21863cb035cf992cdb0ba5990aa3"},
{file = "flake8_isort-3.0.0-py2.py3-none-any.whl", hash = "sha256:f5322a85cea89998e0df954162fd35a1f1e5b5eb4fc0c79b5975aa2799106baa"},
{file = "flake8-isort-4.0.0.tar.gz", hash = "sha256:2b91300f4f1926b396c2c90185844eb1a3d5ec39ea6138832d119da0a208f4d9"},
{file = "flake8_isort-4.0.0-py2.py3-none-any.whl", hash = "sha256:729cd6ef9ba3659512dee337687c05d79c78e1215fdf921ed67e5fe46cce2f3c"},
]
flake8-mypy = [
{file = "flake8-mypy-17.8.0.tar.gz", hash = "sha256:47120db63aff631ee1f84bac6fe8e64731dc66da3efc1c51f85e15ade4a3ba18"},
......@@ -2306,6 +2304,10 @@ importlib-metadata = [
{file = "importlib_metadata-1.7.0-py2.py3-none-any.whl", hash = "sha256:dc15b2969b4ce36305c51eebe62d418ac7791e9a157911d58bfb1f9ccd8e2070"},
{file = "importlib_metadata-1.7.0.tar.gz", hash = "sha256:90bb658cdbbf6d1735b6341ce708fc7024a3e14e99ffdc5783edea9f9b077f83"},
]
iniconfig = [
{file = "iniconfig-1.0.1-py3-none-any.whl", hash = "sha256:80cf40c597eb564e86346103f609d74efce0f6b4d4f30ec8ce9e2c26411ba437"},
{file = "iniconfig-1.0.1.tar.gz", hash = "sha256:e5f92f89355a67de0595932a6c6c02ab4afddc6fcdc0bfc5becd0d60884d3f69"},
]
isort = [
{file = "isort-5.1.4-py3-none-any.whl", hash = "sha256:ae3007f72a2e9da36febd3454d8be4b175d6ca17eb765841d5fe3d038aede79d"},
{file = "isort-5.1.4.tar.gz", hash = "sha256:145072eedc4927cc9c1f9478f2d83b2fc1e6469df4129c02ef4e8c742207a46c"},
......@@ -2527,8 +2529,8 @@ pyparsing = [
{file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"},
]
pytest = [
{file = "pytest-5.4.3-py3-none-any.whl", hash = "sha256:5c0db86b698e8f170ba4582a492248919255fcd4c79b1ee64ace34301fb589a1"},
{file = "pytest-5.4.3.tar.gz", hash = "sha256:7979331bfcba207414f5e1263b5a0f8f521d0f457318836a7355531ed1a4c7d8"},
{file = "pytest-6.0.1-py3-none-any.whl", hash = "sha256:8b6007800c53fdacd5a5c192203f4e531eb2a1540ad9c752e052ec0f7143dbad"},
{file = "pytest-6.0.1.tar.gz", hash = "sha256:85228d75db9f45e06e57ef9bf4429267f81ac7c0d742cc9ed63d09886a9fe6f4"},
]
pytest-cov = [
{file = "pytest-cov-2.10.0.tar.gz", hash = "sha256:1a629dc9f48e53512fcbfda6b07de490c374b0c83c55ff7a1720b3fccff0ac87"},
......@@ -2600,6 +2602,7 @@ regex = [
{file = "regex-2020.7.14-cp38-cp38-manylinux1_i686.whl", hash = "sha256:5ea81ea3dbd6767873c611687141ec7b06ed8bab43f68fad5b7be184a920dc99"},
{file = "regex-2020.7.14-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:bbb332d45b32df41200380fff14712cb6093b61bd142272a10b16778c418e98e"},
{file = "regex-2020.7.14-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:c11d6033115dc4887c456565303f540c44197f4fc1a2bfb192224a301534888e"},
{file = "regex-2020.7.14-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:75aaa27aa521a182824d89e5ab0a1d16ca207318a6b65042b046053cfc8ed07a"},
{file = "regex-2020.7.14-cp38-cp38-win32.whl", hash = "sha256:d6cff2276e502b86a25fd10c2a96973fdb45c7a977dca2138d661417f3728341"},
{file = "regex-2020.7.14-cp38-cp38-win_amd64.whl", hash = "sha256:7a2dd66d2d4df34fa82c9dc85657c5e019b87932019947faece7983f2089a840"},
{file = "regex-2020.7.14.tar.gz", hash = "sha256:3a3af27a8d23143c49a3420efe5b3f8cf1a48c6fc8bc6856b03f638abc1833bb"},
......@@ -2752,10 +2755,6 @@ urllib3 = [
{file = "urllib3-1.25.10-py2.py3-none-any.whl", hash = "sha256:e7983572181f5e1522d9c98453462384ee92a0be7fac5f1413a1e35c56cc0461"},
{file = "urllib3-1.25.10.tar.gz", hash = "sha256:91056c15fa70756691db97756772bb1eb9678fa585d9184f24534b100dc60f4a"},
]
wcwidth = [
{file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"},
{file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"},
]
webencodings = [
{file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"},
{file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"},
......
......@@ -34,7 +34,7 @@ sphinx = "^3.0"
sphinxcontrib-django = "^0.5.0"
sphinx-autodoc-typehints = "^1.7"
django-stubs = "^1.1"
pytest = "^5.3"
pytest = "^6.0"
pytest-django = "^3.7"
pytest-django-testing-postgresql = "^0.1"
selenium = "^3.141.0"
......@@ -50,7 +50,7 @@ flake8-rst-docstrings = "^0.0.13"
black = "^19.10b0"
flake8-black = "^0.2.0"
isort = "^5.0.0"
flake8-isort = "^3.0.0"
flake8-isort = "^4.0.0"
pytest-cov = "^2.8.1"
pytest-sugar = "^0.9.2"
......