Skip to content

Commit

Permalink
fix unpacking message, default to modelform fields if no fieldsets, a…
Browse files Browse the repository at this point in the history
…dd tests and testapp
  • Loading branch information
erikvw committed Feb 16, 2024
1 parent 186f211 commit ba85933
Show file tree
Hide file tree
Showing 14 changed files with 579 additions and 23 deletions.
18 changes: 13 additions & 5 deletions edc_form_runners/form_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ def run_all(self) -> None:
for src_obj in tqdm(self.src_qs, total=total):
self.issue_model_cls.objects.filter(**self.unique_opts(src_obj)).delete()
self.run_one(src_obj=src_obj, skip_delete=True)
for model_name, message in self.messages.values():
print(f"{model_name}: {message}")
for k, v in self.messages.items():
print(f"Warning: {k}: {v}")

def run_one(self, src_obj: Model, skip_delete: bool | None = None) -> None:
if not skip_delete:
Expand Down Expand Up @@ -100,9 +100,17 @@ def fieldset_fields(self) -> list[str]:
_, data = fieldset
fields.extend(data.get("fields"))
else:
self.messages.update({self.model_name: "Fieldsets not defined. Using fields."})

fields = getattr(self.modeladmin_cls, "fields", [])
self.messages.update(
{
self.model_name: (
"ModelAdmin fieldsets not defined. Using ModelForm fields."
)
}
)

fields = [
k for k, v in getattr(self.modeladmin_cls.form(), "fields", {}).items()
]
fields = list(set(fields))
return fields

Expand Down
15 changes: 15 additions & 0 deletions edc_form_runners/tests/holidays.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
local_date,label,country
2017-01-02,Public Holiday,botswana
2017-04-14,Good Friday,botswana
2017-04-15,Public Holiday,botswana
2017-04-17,Easter Monday,botswana
2017-05-01,May Day/Labour Day,botswana
2017-05-25,Ascension Day,botswana
2017-07-01,Sir Seretse Khama Day,botswana
2017-07-17,President's Day,botswana
2017-07-18,Public Holiday,botswana
2017-09-30,Botswana Day,botswana
2017-10-02,Public Holiday,botswana
2017-12-25,Christmas Day,botswana
2017-12-26,Boxing Day,botswana
2017-01-01,New Year,botswana
128 changes: 128 additions & 0 deletions edc_form_runners/tests/tests/test_runners.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
from datetime import datetime
from uuid import uuid4
from zoneinfo import ZoneInfo

import time_machine
from django.core.exceptions import ObjectDoesNotExist
from django.test import TestCase, override_settings
from edc_appointment.models import Appointment
from edc_appointment.tests.helper import Helper
from edc_consent.site_consents import site_consents
from edc_facility import import_holidays
from edc_visit_schedule.site_visit_schedules import site_visit_schedules
from edc_visit_tracking.constants import SCHEDULED
from edc_visit_tracking.models import SubjectVisit

from edc_form_runners.exceptions import FormRunnerModelFormNotFound
from edc_form_runners.form_runner import FormRunner
from edc_form_runners.models import Issue
from form_runners_app.consents import consent_v1
from form_runners_app.models import Member, Team, TeamWithDifferentFields, Venue
from form_runners_app.visit_schedules import visit_schedule


@override_settings(SITE_ID=10)
@time_machine.travel(datetime(2019, 6, 11, 8, 00, tzinfo=ZoneInfo("UTC")))
class TestRunners(TestCase):

helper_cls = Helper

@classmethod
def setUpTestData(cls):
import_holidays()
site_consents.registry = {}
site_consents.register(consent_v1)

def setUp(self):
site_consents.registry = {}
site_consents.register(consent_v1)
site_visit_schedules._registry = {}

site_visit_schedules.loaded = False
site_visit_schedules.register(visit_schedule)

self.subject_identifier = "1235"
self.helper = self.helper_cls(subject_identifier=self.subject_identifier)
self.visit_schedule_name = "visit_schedule"
self.schedule_name = "schedule"

self.helper.consent_and_put_on_schedule(
visit_schedule_name="visit_schedule", schedule_name="schedule"
)

def test_appointment(self):
form_runner = FormRunner(model_name="edc_appointment.appointment")
form_runner.run_all()

def test_crfs(self):
for appointment in Appointment.objects.all().order_by("timepoint_datetime"):
subject_visit = SubjectVisit.objects.create(
appointment=appointment,
subject_identifier=self.subject_identifier,
reason=SCHEDULED,
)
TeamWithDifferentFields.objects.create(subject_visit=subject_visit, size=11)
Venue.objects.create(subject_visit=subject_visit, name=uuid4())
team = Team.objects.create(subject_visit=subject_visit, name=uuid4())
Member.objects.create(team=team)
Member.objects.create(team=team)
Member.objects.create(team=team)

# raise on VenueModelAdmin has no custom ModelForm
self.assertRaises(
FormRunnerModelFormNotFound, FormRunner, model_name="form_runners_app.venue"
)

# run to find name field may not be a UUID
# see form validator
form_runner = FormRunner(model_name="form_runners_app.team")
form_runner.run_all()
self.assertEqual(Issue.objects.all().count(), 1)
try:
Issue.objects.get(
label_lower="form_runners_app.team",
visit_code="1000",
visit_code_sequence=0,
field_name="name",
message__icontains="Cannot be a UUID",
)
except ObjectDoesNotExist:
self.fail("Issue model instance unexpectedly does not exist")

# run to find player_name field may not be a UUID
# see form validator
form_runner = FormRunner(model_name="form_runners_app.member")
form_runner.run_all()
try:
Issue.objects.get(
label_lower="form_runners_app.member",
visit_code="1000",
visit_code_sequence=0,
field_name="player_name",
message__icontains="Cannot be a UUID",
)
except ObjectDoesNotExist:
self.fail("Issue model instance unexpectedly does not exist")

# run to assert ignores `name` field because it IS NOT IN admin fieldsets
# even though the model instance field class has blank=False.
form_runner = FormRunner(model_name="form_runners_app.teamwithdifferentfields")
form_runner.run_all()
try:
Issue.objects.get(
label_lower="form_runners_app.teamwithdifferentfields",
field_name="name",
)
except ObjectDoesNotExist:
pass
else:
self.fail("Issue model instance unexpectedly does not exist")
# assert does not ignore `color` field because it IS IN admin fieldsets
# and the model instance field class has blank=False.
try:
Issue.objects.get(
label_lower="form_runners_app.teamwithdifferentfields",
field_name="color",
)
except ObjectDoesNotExist:
self.fail("Issue model instance unexpectedly does not exist")
16 changes: 0 additions & 16 deletions edc_form_runners/tests/urls.py

This file was deleted.

Empty file added form_runners_app/__init__.py
Empty file.
50 changes: 50 additions & 0 deletions form_runners_app/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from django.contrib import admin
from edc_model_admin.admin_site import EdcAdminSite
from edc_model_admin.dashboard import (
ModelAdminCrfDashboardMixin,
ModelAdminDashboardMixin,
)
from edc_model_admin.history import SimpleHistoryAdmin
from edc_sites.admin import SiteModelAdminMixin

from .forms import MemberForm, TeamForm, TeamWithDifferentFieldsForm
from .models import Member, Team, TeamWithDifferentFields, Venue

my_admin_site = EdcAdminSite(name="my_admin_site")


class MemberInlineAdmin(admin.TabularInline):
model = Member
form = MemberForm

extra = 0


@admin.register(Member, site=my_admin_site)
class MembersAdmin(SiteModelAdminMixin, ModelAdminDashboardMixin, SimpleHistoryAdmin):
form = MemberForm


@admin.register(Team, site=my_admin_site)
class TeamAdmin(SiteModelAdminMixin, ModelAdminCrfDashboardMixin, SimpleHistoryAdmin):
form = TeamForm

inlines = [MemberInlineAdmin]

fieldsets = ((None, ({"fields": ("name", "created", "modified")})),)


@admin.register(TeamWithDifferentFields, site=my_admin_site)
class TeamWithDifferentFieldsAdmin(
SiteModelAdminMixin, ModelAdminCrfDashboardMixin, SimpleHistoryAdmin
):
form = TeamWithDifferentFieldsForm

# do not include "name" to show that the field is ignored
# by FormRunner.run even though blank=False
fieldsets = ((None, ({"fields": ("size", "color", "mood")})),)


@admin.register(Venue, site=my_admin_site)
class VenueAdmin(SiteModelAdminMixin, ModelAdminDashboardMixin, SimpleHistoryAdmin):
pass
6 changes: 6 additions & 0 deletions form_runners_app/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig as DjangoAppConfig


class AppConfig(DjangoAppConfig):
name = "form_runners_app"
verbose_name = "form_runners test app"
16 changes: 16 additions & 0 deletions form_runners_app/consents.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from edc_consent.consent_definition import ConsentDefinition
from edc_consent.site_consents import site_consents
from edc_constants.constants import FEMALE, MALE
from edc_protocol.research_protocol_config import ResearchProtocolConfig

consent_v1 = ConsentDefinition(
"form_runners_app.subjectconsent",
version="1",
start=ResearchProtocolConfig().study_open_datetime,
end=ResearchProtocolConfig().study_close_datetime,
age_min=18,
age_is_adult=18,
age_max=64,
gender=[MALE, FEMALE],
)
site_consents.register(consent_v1)
44 changes: 44 additions & 0 deletions form_runners_app/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from django import forms
from edc_form_validators import INVALID_ERROR, FormValidator, FormValidatorMixin

from .models import Member, Team, TeamWithDifferentFields


class MemberFormValidator(FormValidator):
def clean(self) -> None:
if self.cleaned_data.get("player_name") != "not-a-uuid":
self.raise_validation_error({"player_name": "Cannot be a UUID"}, INVALID_ERROR)


class TeamFormValidator(FormValidator):
def clean(self) -> None:
if self.cleaned_data.get("name") != "not-a-uuid":
self.raise_validation_error({"name": "Cannot be a UUID"}, INVALID_ERROR)


class MemberForm(FormValidatorMixin, forms.ModelForm):
form_validator_cls = MemberFormValidator

class Meta:
model = Member
fields = "__all__"


class TeamForm(FormValidatorMixin, forms.ModelForm):
form_validator_cls = TeamFormValidator

class Meta:
model = Team
fields = "__all__"


class TeamWithDifferentFieldsForm(FormValidatorMixin, forms.ModelForm):
form_validator_cls = None

def clean(self):
if self.cleaned_data.get("name") != "not-a-uuid":
raise forms.ValidationError({"name": "Cannot be a UUID"}, INVALID_ERROR)

class Meta:
model = TeamWithDifferentFields
fields = "__all__"
Loading

0 comments on commit ba85933

Please sign in to comment.