From 8efe8ce048afaa1c433d9095b617e53a6ac78ec2 Mon Sep 17 00:00:00 2001 From: Jonas Dittrich <58814480+Kakadus@users.noreply.github.com> Date: Mon, 30 Oct 2023 22:55:25 +0100 Subject: [PATCH] add DJ checks --- evap/evaluation/models.py | 16 ++++++++-------- evap/evaluation/models_logging.py | 26 +++++++++++++------------- evap/staff/importers/base.py | 4 ++-- pyproject.toml | 3 ++- 4 files changed, 25 insertions(+), 24 deletions(-) diff --git a/evap/evaluation/models.py b/evap/evaluation/models.py index 7fa589026d..f528df8999 100644 --- a/evap/evaluation/models.py +++ b/evap/evaluation/models.py @@ -194,10 +194,6 @@ class Visibility(models.IntegerChoices): objects = QuestionnaireManager() - def clean(self): - if self.type == self.Type.CONTRIBUTOR and self.is_locked: - raise ValidationError({"is_locked": _("Contributor questionnaires cannot be locked.")}) - class Meta: ordering = ["type", "order", "pk"] verbose_name = _("questionnaire") @@ -206,6 +202,10 @@ class Meta: def __str__(self): return self.name + def clean(self): + if self.type == self.Type.CONTRIBUTOR and self.is_locked: + raise ValidationError({"is_locked": _("Contributor questionnaires cannot be locked.")}) + def __lt__(self, other): return (self.type, self.order, self.pk) < (other.type, other.order, other.pk) @@ -1470,7 +1470,7 @@ class TextAnswer(Answer): answer = models.TextField(verbose_name=_("answer")) # If the text answer was changed during review, original_answer holds the original text. Otherwise, it's null. - original_answer = models.TextField(verbose_name=_("original answer"), blank=True, null=True) + original_answer = models.TextField(verbose_name=_("original answer"), blank=True, null=True) # noqa: DJ001 class ReviewDecision(models.TextChoices): """ @@ -1613,9 +1613,6 @@ class Infotext(models.Model): content_en = models.TextField(verbose_name=_("content (english)"), blank=True) content = translate(en="content_en", de="content_de") - def is_empty(self): - return not (self.title or self.content) - class Page(models.TextChoices): STUDENT_INDEX = ("student_index", "Student index page") CONTRIBUTOR_INDEX = ("contributor_index", "Contributor index page") @@ -1640,6 +1637,9 @@ class Meta: ), ) + def is_empty(self): + return not (self.title or self.content) + class UserProfileManager(BaseUserManager): def create_user(self, *, email, password=None, first_name=None, last_name=None): diff --git a/evap/evaluation/models_logging.py b/evap/evaluation/models_logging.py index f9cd00332c..e54ebb0f47 100644 --- a/evap/evaluation/models_logging.py +++ b/evap/evaluation/models_logging.py @@ -128,6 +128,19 @@ class LoggedModel(models.Model): class Meta: abstract = True + def save(self, *args, **kw): + # Are we creating a new instance? + # https://docs.djangoproject.com/en/3.0/ref/models/instances/#customizing-model-loading + if self._state.adding: + # we need to attach a logentry to an existing object, so we save this newly created instance first + super().save(*args, **kw) + self.log_instance_create() + else: + # when saving an existing instance, we get changes by comparing to the version from the database + # therefore we save the instance after building the logentry + self.log_instance_change() + super().save(*args, **kw) + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._logentry = None @@ -239,19 +252,6 @@ def _update_log(self, changes, action_type: InstanceActionType, store_in_db=True if store_in_db: self._logentry.save() - def save(self, *args, **kw): - # Are we creating a new instance? - # https://docs.djangoproject.com/en/3.0/ref/models/instances/#customizing-model-loading - if self._state.adding: - # we need to attach a logentry to an existing object, so we save this newly created instance first - super().save(*args, **kw) - self.log_instance_create() - else: - # when saving an existing instance, we get changes by comparing to the version from the database - # therefore we save the instance after building the logentry - self.log_instance_change() - super().save(*args, **kw) - def delete(self, *args, **kw): self.log_instance_delete() self.related_logentries().delete() diff --git a/evap/staff/importers/base.py b/evap/staff/importers/base.py index 2c942ec7a9..7a9ba97f3a 100644 --- a/evap/staff/importers/base.py +++ b/evap/staff/importers/base.py @@ -179,9 +179,9 @@ class InputRow(ABC): # MyPy is currently broken with abstract properties: https://github.com/python/mypy/issues/8996 column_count: int + @abstractmethod def __init__(self, location: ExcelFileLocation, *cells: Iterable[str]): - # this can be an abstractmethod from python3.10 on, before it doesn't work with the derived dataclasses - raise NotImplementedError # pragma: no cover + pass @classmethod def from_cells(cls, location: ExcelFileLocation, cells: Iterable[str]): diff --git a/pyproject.toml b/pyproject.toml index b0ce858771..77f1560c28 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,11 +29,12 @@ extend_skip_glob = ["**/migrations/*"] # * Formsets use PascalCase target-version = "py310" -select = ["F", "E", "B", "W", "N", "UP", "YTT", "FIX", "ASYNC", "A"] +select = ["F", "E", "B", "W", "N", "UP", "YTT", "FIX", "ASYNC", "A", "DJ"] ignore = [ "E501", # line-too-long: black does code formatting for us "FIX004", # hacks should be possible "A003", + "DJ008", ] ignore-init-module-imports = true