#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2020, Bruno Sanchez, Mauricio Koraj, Vanessa Daza,
# Juan B Cabral, Mariano Dominguez, Marcelo Lares,
# Nadia Luczywo, Dante Paz, Rodrigo Quiroga,
# Martín de los Ríos, Federico Stasyszyn,
# Cristian Giuppone.
# License: BSD-3-Clause
# Full Text: https://raw.githubusercontent.com/ivco19/libs/master/LICENSE
# =============================================================================
# DOCS
# =============================================================================
"""WTF Forms for arcovid19
"""
__all__ = ["InfectionCurveForm"]
# =============================================================================
# IMPORTS
# =============================================================================
import inspect
import flask_wtf as fwtf
import wtforms as wtf
from wtforms.fields import html5
import wtforms.validators as vldt
from flask_babel import lazy_gettext as _
import attr
from numpydoc import docscrape
from ..models import InfectionCurve
from .. import cases
# =============================================================================
# CUSTOM FIELD
# =============================================================================
class FloatField(wtf.FloatField):
widget = wtf.widgets.html5.NumberInput()
# =============================================================================
# CONSTANTS
# =============================================================================
PYTYPE_TO_WTF = {
bool: wtf.BooleanField,
int: html5.IntegerField,
str: wtf.StringField,
float: FloatField,
}
DEFAULT_VALIDATORS = [vldt.InputRequired()]
DEFAULT_RENDER_KW = {"class": "form-control form-control-sm"}
# =============================================================================
# INFECTION FORM
# =============================================================================
def make_InfectionCurveForm():
# here gone all the fields
form_fields = {}
# this gonna store all the model choices
models, methods = [], []
for mname, method in vars(InfectionCurve).items():
if mname.startswith("do_") and callable(method):
label = _(mname.split("_", 1)[-1])
models.append((mname, label))
methods.append(method)
# add the model select to the form
form_fields["model"] = wtf.SelectField(
_("Model"),
choices=models,
description=_("Compartimental model"),
render_kw={"class": "custom-select custom-select-sm"},
default=models[0][0],
)
# now we add the same parameters for all the methods
for method in methods:
# extract all the fields doc from the method documentation
mtd_docs = docscrape.FunctionDoc(method)
docs = {
p.name.split(":")[0]: " ".join(p.desc).strip()
for p in mtd_docs.get("Parameters")
}
# extract all the parameters
params = inspect.signature(method).parameters
for idx, param in enumerate(params.values()):
if idx == 0 or param.name in form_fields:
continue
# extract doc
description = docs.get(param.name)
# extract the label from the name
label = " ".join(param.name.split("_")).title()
# add all the validators
validators = list(DEFAULT_VALIDATORS)
# add the classes to the field element
render_kw = dict(DEFAULT_RENDER_KW)
render_kw["data-ptype"] = "model-param"
# the default
default = param.default
# the type based on the default
Field = PYTYPE_TO_WTF.get(type(default), wtf.StringField)
# create the field
ffield = Field(
_(label),
description=_(description),
default=default,
validators=validators,
render_kw=render_kw,
)
form_fields[param.name] = ffield
# extract all the fields doc from the class documentation
class_docs = docscrape.ClassDoc(InfectionCurve)
docs = {
p.name.split(":")[0]: " ".join(p.desc).strip()
for p in class_docs.get("Parameters")
}
# create one field for attribute
for aname, afield in attr.fields_dict(InfectionCurve).items():
# extract doc
description = docs.get(aname)
# extract the label from the field name
label = " ".join(aname.split("_")).title()
# add all the validators
validators = list(DEFAULT_VALIDATORS)
# add the classes to the field element
render_kw = dict(DEFAULT_RENDER_KW)
render_kw["data-ptype"] = "curve-param"
# determine the field type
Field = PYTYPE_TO_WTF.get(afield.type, wtf.StringField)
# create the field
ffield = Field(
_(label),
description=_(description),
default=afield.default,
validators=validators,
render_kw=render_kw,
)
form_fields[aname] = ffield
# create the form itself
form = type("InfectionCurveForm", (fwtf.FlaskForm,), form_fields)
return form
InfectionCurveForm = make_InfectionCurveForm()
del make_InfectionCurveForm
# =============================================================================
# CASES FORMS
# =============================================================================
def make_CasesForm():
form_fields = {}
form_fields["all_country"] = wtf.BooleanField(
_("Argentina"),
default="checked",
render_kw={"class": "form-check-input"},
description=_("Data for the entire country"),
)
form_fields["province"] = wtf.SelectMultipleField(
_("Province"),
choices=cases.CODE_TO_POVINCIA.items(),
description=_("Province to plot"),
render_kw={"class": "custom-select"},
)
form_fields["all_status"] = wtf.BooleanField(
_("All Status"),
default="checked",
render_kw={"class": "form-check-input"},
description=_("Show all the status"),
)
status_choices = {}
for k, v in cases.STATUS.items():
if v not in status_choices:
status_choices[v] = _(k)
form_fields["status"] = wtf.SelectMultipleField(
_("Status"),
choices=status_choices.items(),
description=_("Status of the patients"),
render_kw={"class": "custom-select"},
)
# create the form itself
form = type("CasesForm", (fwtf.FlaskForm,), form_fields)
return form
CasesForm = make_CasesForm()
del make_CasesForm