Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
from typing import Optional
from .dates_add_days import parse_iso_date ← from dates.add-days ^1.0.0 · built alongside by fune
from .education_attendance_rate_data import ABSENCE_THRESHOLDS, ABSENCE_THRESHOLDS_HISTORY, ABSENCE_THRESHOLDS_HORIZON ← this capability’s own data, compiled from data/absence-thresholds.json into the same file by fune build
from .education_attendance_rate_types import AttendanceRate
from .math_round_div import round_div ← from math.round-div ^1.0.0 · built alongside by fune
def _is_int(value: object) -> bool:
return isinstance(value, int) and not isinstance(value, bool)
def _threshold_on(measure: str, on_date: str) -> Optional[int]:
for r in ABSENCE_THRESHOLDS:
if r.measure == measure and on_date >= r.valid_from and (r.valid_to is None or on_date <= r.valid_to):
return r.basis_points
return None
def attendance_rate(possible_sessions: int, missed_sessions: int, on_date: str) -> AttendanceRate:
"""Attendance and absence in basis points, and the DfE absence flags.
The flags compare missed x 10000 with possible x threshold, exactly: a
rate of 9.996% rounds to 10.00% but is not persistent absence.
"""
if not _is_int(possible_sessions) or possible_sessions < 1:
raise ValueError("possibleSessions must be a whole number of 1 or more, received %s" % (possible_sessions,))
if not _is_int(missed_sessions) or missed_sessions < 0 or missed_sessions > possible_sessions:
raise ValueError(
"missedSessions must be a whole number from 0 to possibleSessions (%s), received %s"
% (possible_sessions, missed_sessions)
)
parse_iso_date(on_date)
persistent = _threshold_on("persistent", on_date)
if persistent is None:
if ABSENCE_THRESHOLDS_HISTORY != "full" and ABSENCE_THRESHOLDS_HORIZON is not None and on_date < ABSENCE_THRESHOLDS_HORIZON:
raise ValueError(
"no persistent absence definition on %s: this build was installed with history=%s, so it only carries rules from %s. "
"Reinstall with history=full for earlier years." % (on_date, ABSENCE_THRESHOLDS_HISTORY, ABSENCE_THRESHOLDS_HORIZON)
)
raise ValueError("no persistent absence definition on %s" % (on_date,))
severe = _threshold_on("severe", on_date)
absence = round_div(missed_sessions * 10000, possible_sessions, "half-up")
return AttendanceRate(
attendance_basis_points=10000 - absence,
absence_basis_points=absence,
persistently_absent=missed_sessions * 10000 >= possible_sessions * persistent,
severely_absent=None if severe is None else missed_sessions * 10000 >= possible_sessions * severe,
)