Пример #1
0
    def test_portion_overlapping_with_month(self):

        self.assertEqual(
            None,
            self.negative_day_range.portion_overlapping_with_month(2019, 2))

        self.assertEqual(
            None, self.zero_day_range.portion_overlapping_with_month(2019, 2))

        self.assertEqual(
            self.one_day_range,
            self.one_day_range.portion_overlapping_with_month(2019, 2))

        self.assertEqual(
            self.single_month_range,
            self.single_month_range.portion_overlapping_with_month(2019, 2))

        self.assertEqual(
            DateRange(lower_bound_inclusive_date=datetime.date(2019, 2, 3),
                      upper_bound_exclusive_date=datetime.date(2019, 3, 1)),
            self.multi_month_range.portion_overlapping_with_month(2019, 2))

        self.assertEqual(
            DateRange(lower_bound_inclusive_date=datetime.date(2019, 3, 1),
                      upper_bound_exclusive_date=datetime.date(2019, 4, 1)),
            self.multi_month_range.portion_overlapping_with_month(2019, 3))

        self.assertEqual(
            DateRange(lower_bound_inclusive_date=datetime.date(2019, 4, 1),
                      upper_bound_exclusive_date=datetime.date(2019, 4, 10)),
            self.multi_month_range.portion_overlapping_with_month(2019, 4))
Пример #2
0
    def is_fully_incarcerated_for_range(self,
                                        range_to_cover: DateRange) -> bool:
        """Returns True if this person is incarcerated for the full duration of the date range."""

        months_range_overlaps = range_to_cover.get_months_range_overlaps_at_all(
        )

        if not months_range_overlaps:
            return False

        months_without_complete_incarceration = []
        for year, month in months_range_overlaps:
            was_incarcerated_all_month = (
                year, month) in self.months_fully_incarcerated
            if not was_incarcerated_all_month:
                months_without_complete_incarceration.append((year, month))

        for year, month in months_without_complete_incarceration:
            overlapping_periods = self.month_to_overlapping_incarceration_periods[
                year][month]

            range_portion_overlapping_month = range_to_cover.portion_overlapping_with_month(
                year, month)
            if not range_portion_overlapping_month:
                raise ValueError(
                    f'Expecting only months that overlap with the range, month ({year}, {month}) does not.'
                )

            remaining_ranges_to_cover = self._get_portions_of_range_not_covered_by_periods_subset(
                range_portion_overlapping_month, overlapping_periods)
            if remaining_ranges_to_cover:
                return False

        return True
Пример #3
0
    def setUp(self) -> None:
        self.negative_day_range = DateRange(
            lower_bound_inclusive_date=datetime.date(2019, 2, 3),
            upper_bound_exclusive_date=datetime.date(2019, 2, 2),
        )

        self.zero_day_range = DateRange(
            lower_bound_inclusive_date=datetime.date(2019, 2, 3),
            upper_bound_exclusive_date=datetime.date(2019, 2, 3),
        )

        self.one_day_range = DateRange(
            lower_bound_inclusive_date=datetime.date(2019, 2, 3),
            upper_bound_exclusive_date=datetime.date(2019, 2, 4),
        )

        self.single_month_range = DateRange(
            lower_bound_inclusive_date=datetime.date(2019, 2, 1),
            upper_bound_exclusive_date=datetime.date(2019, 3, 1),
        )

        self.multi_month_range = DateRange(
            lower_bound_inclusive_date=datetime.date(2019, 2, 3),
            upper_bound_exclusive_date=datetime.date(2019, 4, 10),
        )
Пример #4
0
    def test_exactly_overlapping_ranges(self):
        range_1 = DateRange.for_month(2019, 2)
        range_2 = DateRange.for_month(2019, 2)

        time_range_diff = DateRangeDiff(range_1, range_2)

        self.assertEqual(range_1, time_range_diff.overlapping_range)
        self.assertEqual([], time_range_diff.range_1_non_overlapping_parts)
        self.assertEqual([], time_range_diff.range_2_non_overlapping_parts)
Пример #5
0
    def test_non_overlapping_ranges(self) -> None:
        range_1 = DateRange.for_month(2019, 2)
        range_2 = DateRange.for_month(2019, 3)

        time_range_diff = DateRangeDiff(range_1, range_2)

        self.assertEqual(None, time_range_diff.overlapping_range)
        self.assertEqual([range_1], time_range_diff.range_1_non_overlapping_parts)
        self.assertEqual([range_2], time_range_diff.range_2_non_overlapping_parts)
Пример #6
0
    def test_partially_overlapping_ranges(self):
        range_1 = DateRange(datetime.date(2019, 2, 5),
                            datetime.date(2019, 5, 2))
        range_2 = DateRange(datetime.date(2019, 3, 1),
                            datetime.date(2019, 6, 5))

        time_range_diff = DateRangeDiff(range_1, range_2)

        self.assertEqual(
            DateRange(datetime.date(2019, 3, 1), datetime.date(2019, 5, 2)),
            time_range_diff.overlapping_range)
        self.assertEqual(
            [DateRange(datetime.date(2019, 2, 5), datetime.date(2019, 3, 1))],
            time_range_diff.range_1_non_overlapping_parts)
        self.assertEqual(
            [DateRange(datetime.date(2019, 5, 2), datetime.date(2019, 6, 5))],
            time_range_diff.range_2_non_overlapping_parts)

        time_range_diff = DateRangeDiff(range_2, range_1)
        self.assertEqual(
            DateRange(datetime.date(2019, 3, 1), datetime.date(2019, 5, 2)),
            time_range_diff.overlapping_range)
        self.assertEqual(
            [DateRange(datetime.date(2019, 5, 2), datetime.date(2019, 6, 5))],
            time_range_diff.range_1_non_overlapping_parts)
        self.assertEqual(
            [DateRange(datetime.date(2019, 2, 5), datetime.date(2019, 3, 1))],
            time_range_diff.range_2_non_overlapping_parts)
Пример #7
0
    def _months_excluded_from_supervision_population(
            self) -> Set[Tuple[int, int]]:
        """For each StateIncarcerationPeriod, identifies months where the person was incarcerated for every day during
        that month. Returns a set of months in the format (year, month) for which the person spent the entire month in a
        prison, where the incarceration prevents the person from being counted simultaneously in the supervision
        population.
        """
        months_excluded_from_supervision_population: Set[Tuple[int,
                                                               int]] = set()

        for (incarceration_period
             ) in self.incarceration_periods_not_under_supervision_authority:
            months_overlaps_at_all = (incarceration_period.duration.
                                      get_months_range_overlaps_at_all())

            for year, month in months_overlaps_at_all:
                overlapping_periods = (
                    self.
                    month_to_overlapping_ips_not_under_supervision_authority[
                        year][month])

                remaining_ranges_to_cover = (
                    self._get_portions_of_range_not_covered_by_periods_subset(
                        DateRange.for_month(year, month), overlapping_periods))
                if not remaining_ranges_to_cover:
                    months_excluded_from_supervision_population.add(
                        (year, month))

        return months_excluded_from_supervision_population
    def run_is_excluded_from_supervision_population_for_range_check(
        self,
        incarceration_periods: List[StateIncarcerationPeriod],
        range_start_num_days_from_periods_start: int,
        range_end_num_days_from_periods_end: int,
        is_excluded_from_supervision_population: bool,
    ):
        """Runs a test for the is_excluded_from_supervision_population function with the given parameters."""
        period_range_start = incarceration_periods[0].admission_date
        if not period_range_start:
            raise ValueError("Expected admission date")

        period_range_end = date_or_tomorrow(incarceration_periods[-1].release_date)

        lower_bound_inclusive = period_range_start + timedelta(
            days=range_start_num_days_from_periods_start
        )
        upper_bound_exclusive = period_range_end + timedelta(
            days=range_end_num_days_from_periods_end
        )

        index = IncarcerationPeriodIndex(incarceration_periods)

        time_range = DateRange(
            lower_bound_inclusive_date=lower_bound_inclusive,
            upper_bound_exclusive_date=upper_bound_exclusive,
        )
        if is_excluded_from_supervision_population:
            self.assertTrue(
                index.is_excluded_from_supervision_population_for_range(time_range)
            )
        else:
            self.assertFalse(
                index.is_excluded_from_supervision_population_for_range(time_range)
            )
    def run_is_fully_incarcerated_for_range_check(
            self, incarceration_periods: List[StateIncarcerationPeriod],
            range_start_num_days_from_periods_start: int,
            range_end_num_days_from_periods_end: int,
            is_fully_incarcerated: bool):
        period_range_start = incarceration_periods[0].admission_date
        if not period_range_start:
            raise ValueError("Expected admission date")

        period_range_end = date_or_tomorrow(
            incarceration_periods[-1].release_date)

        lower_bound_inclusive = period_range_start + timedelta(
            days=range_start_num_days_from_periods_start)
        upper_bound_exclusive = period_range_end + timedelta(
            days=range_end_num_days_from_periods_end)

        index = IncarcerationPeriodIndex(incarceration_periods)

        time_range = DateRange(
            lower_bound_inclusive_date=lower_bound_inclusive,
            upper_bound_exclusive_date=upper_bound_exclusive)
        if is_fully_incarcerated:
            self.assertTrue(index.is_fully_incarcerated_for_range(time_range))
        else:
            self.assertFalse(index.is_fully_incarcerated_for_range(time_range))
Пример #10
0
 def test_for_year_of_date_early_month(self) -> None:
     year_range = DateRange.for_year_of_date(datetime.date(2019, 1, 25))
     self.assertEqual(
         (datetime.date(2019, 1, 1), datetime.date(2020, 1, 1)),
         (
             year_range.lower_bound_inclusive_date,
             year_range.upper_bound_exclusive_date,
         ),
     )
Пример #11
0
 def test_for_year_of_date(self):
     year_range = DateRange.for_year_of_date(datetime.date(2019, 12, 4))
     self.assertEqual(
         (datetime.date(2019, 1, 1), datetime.date(2020, 1, 1)),
         (
             year_range.lower_bound_inclusive_date,
             year_range.upper_bound_exclusive_date,
         ),
     )
Пример #12
0
    def duration(self) -> DateRange:
        """Generates a DateRange for the days covered by the supervision period.  Since DateRange is never open,
        if the supervision period is still active, then the exclusive upper bound of the range is set to tomorrow.
        """
        if not self.start_date:
            raise ValueError(
                f'Expected start date for period {self.supervision_period_id}, found None'
            )

        return DateRange.from_maybe_open_range(start_date=self.start_date,
                                               end_date=self.termination_date)
Пример #13
0
    def test_range_fully_overlaps_other(self) -> None:
        range_1 = DateRange(datetime.date(2019, 2, 5), datetime.date(2019, 5, 2))
        range_2 = DateRange(datetime.date(2019, 3, 1), datetime.date(2019, 3, 5))

        time_range_diff = DateRangeDiff(range_1, range_2)

        self.assertEqual(range_2, time_range_diff.overlapping_range)
        self.assertEqual(
            [
                DateRange(datetime.date(2019, 2, 5), datetime.date(2019, 3, 1)),
                DateRange(datetime.date(2019, 3, 5), datetime.date(2019, 5, 2)),
            ],
            time_range_diff.range_1_non_overlapping_parts,
        )
        self.assertEqual([], time_range_diff.range_2_non_overlapping_parts)

        time_range_diff = DateRangeDiff(range_2, range_1)
        self.assertEqual(range_2, time_range_diff.overlapping_range)
        self.assertEqual([], time_range_diff.range_1_non_overlapping_parts)
        self.assertEqual(
            [
                DateRange(datetime.date(2019, 2, 5), datetime.date(2019, 3, 1)),
                DateRange(datetime.date(2019, 3, 5), datetime.date(2019, 5, 2)),
            ],
            time_range_diff.range_2_non_overlapping_parts,
        )
    def test_no_periods(self):

        index = IncarcerationPeriodIndex([])
        self.assertFalse(
            index.is_fully_incarcerated_for_range(
                DateRange(lower_bound_inclusive_date=date(2019, 1, 2),
                          upper_bound_exclusive_date=date(2020, 2, 1))))

        self.assertFalse(
            index.is_fully_incarcerated_for_range(
                DateRange(lower_bound_inclusive_date=date(2019, 1, 1),
                          upper_bound_exclusive_date=date(2019, 2, 1))))

        self.assertFalse(
            index.is_fully_incarcerated_for_range(
                DateRange(lower_bound_inclusive_date=date(2019, 1, 1),
                          upper_bound_exclusive_date=date(2019, 1, 2))))

        self.assertFalse(
            index.is_fully_incarcerated_for_range(
                DateRange(lower_bound_inclusive_date=date(2019, 1, 1),
                          upper_bound_exclusive_date=date(2019, 1, 1))))
Пример #15
0
    def violation_history_window_pre_commitment_from_supervision(
        self,
        admission_date: datetime.date,
        sorted_and_filtered_violation_responses: List[
            StateSupervisionViolationResponse],
        default_violation_history_window_months: int,
    ) -> DateRange:
        """Returns the window of time before a commitment from supervision in which we
        should consider violations for the violation history prior to the admission.

        Default behavior is to use the date of the last violation response recorded
        prior to the |admission_date| as the upper bound of the window, with a lower
        bound that is |default_violation_history_window_months| before that date.

        Should be overridden by state-specific implementations if necessary.
        """
        # We will use the date of the last response prior to the admission as the
        # window cutoff.
        responses_before_admission = violation_responses_in_window(
            violation_responses=sorted_and_filtered_violation_responses,
            upper_bound_exclusive=admission_date + relativedelta(days=1),
            lower_bound_inclusive=None,
        )

        violation_history_end_date = admission_date

        if responses_before_admission:
            # If there were violation responses leading up to the incarceration
            # admission, then we want the violation history leading up to the last
            # response_date instead of the admission_date on the
            # incarceration_period
            last_response = responses_before_admission[-1]

            if not last_response.response_date:
                # This should never happen, but is here to silence mypy warnings
                # about empty response_dates.
                raise ValueError(
                    "Not effectively filtering out responses without valid"
                    " response_dates.")
            violation_history_end_date = last_response.response_date

        violation_window_lower_bound_inclusive = (
            violation_history_end_date -
            relativedelta(months=default_violation_history_window_months))
        violation_window_upper_bound_exclusive = (violation_history_end_date +
                                                  relativedelta(days=1))

        return DateRange(
            lower_bound_inclusive_date=violation_window_lower_bound_inclusive,
            upper_bound_exclusive_date=violation_window_upper_bound_exclusive,
        )
Пример #16
0
    def is_excluded_from_supervision_population_for_range(
            self, range_to_cover: DateRange) -> bool:
        """Returns True if this person is incarcerated for the full duration of the date range."""

        months_range_overlaps = range_to_cover.get_months_range_overlaps_at_all(
        )

        if not months_range_overlaps:
            return False

        months_without_exclusion_from_supervision = []
        for year, month in months_range_overlaps:
            was_incarcerated_all_month = (
                year,
                month,
            ) in self.months_excluded_from_supervision_population
            if not was_incarcerated_all_month:
                months_without_exclusion_from_supervision.append((year, month))

        for year, month in months_without_exclusion_from_supervision:
            overlapping_periods = (
                self.month_to_overlapping_ips_not_under_supervision_authority[
                    year][month])

            range_portion_overlapping_month = (
                range_to_cover.portion_overlapping_with_month(year, month))
            if not range_portion_overlapping_month:
                raise ValueError(
                    f"Expecting only months that overlap with the range, month ({year}, {month}) does not."
                )

            remaining_ranges_to_cover = (
                self._get_portions_of_range_not_covered_by_periods_subset(
                    range_portion_overlapping_month, overlapping_periods))
            if remaining_ranges_to_cover:
                return False

        return True
    def test_no_periods(self):

        index = IncarcerationPeriodIndex([])
        self.assertFalse(
            index.is_excluded_from_supervision_population_for_range(
                DateRange(
                    lower_bound_inclusive_date=date(2019, 1, 2),
                    upper_bound_exclusive_date=date(2020, 2, 1),
                )
            )
        )

        self.assertFalse(
            index.is_excluded_from_supervision_population_for_range(
                DateRange(
                    lower_bound_inclusive_date=date(2019, 1, 1),
                    upper_bound_exclusive_date=date(2019, 2, 1),
                )
            )
        )

        self.assertFalse(
            index.is_excluded_from_supervision_population_for_range(
                DateRange(
                    lower_bound_inclusive_date=date(2019, 1, 1),
                    upper_bound_exclusive_date=date(2019, 1, 2),
                )
            )
        )

        self.assertFalse(
            index.is_excluded_from_supervision_population_for_range(
                DateRange(
                    lower_bound_inclusive_date=date(2019, 1, 1),
                    upper_bound_exclusive_date=date(2019, 1, 1),
                )
            )
        )
Пример #18
0
    def test_default_violation_history_window_pre_commitment_from_supervision_filter_after(
        self, ):
        state_code = "US_XX"

        supervision_violation_response_1 = (
            StateSupervisionViolationResponse.new_with_defaults(
                state_code=state_code,
                supervision_violation_response_id=123,
                response_type=StateSupervisionViolationResponseType.
                VIOLATION_REPORT,
                response_date=date(2008, 12, 7),
            ))

        supervision_violation_response_2 = (
            StateSupervisionViolationResponse.new_with_defaults(
                supervision_violation_response_id=234,
                response_type=StateSupervisionViolationResponseType.
                VIOLATION_REPORT,
                state_code=state_code,
                response_date=date(2009, 11, 13),
            ))

        # This is after the admission_date
        supervision_violation_response_3 = (
            StateSupervisionViolationResponse.new_with_defaults(
                state_code=state_code,
                supervision_violation_response_id=345,
                response_type=StateSupervisionViolationResponseType.
                VIOLATION_REPORT,
                response_date=date(2012, 12, 1),
            ))

        violation_window = UsXxCommitmentFromSupervisionDelegate(
        ).violation_history_window_pre_commitment_from_supervision(
            admission_date=date(2009, 12, 14),
            sorted_and_filtered_violation_responses=[
                supervision_violation_response_1,
                supervision_violation_response_2,
                supervision_violation_response_3,
            ],
            default_violation_history_window_months=
            VIOLATION_HISTORY_WINDOW_MONTHS,
        )

        expected_violation_window = DateRange(
            lower_bound_inclusive_date=date(2008, 11, 13),
            upper_bound_exclusive_date=date(2009, 11, 14),
        )

        self.assertEqual(expected_violation_window, violation_window)
Пример #19
0
    def test_default_violation_history_window_pre_commitment_from_supervision_no_responses(
        self, ):
        violation_window = UsXxCommitmentFromSupervisionDelegate(
        ).violation_history_window_pre_commitment_from_supervision(
            admission_date=date(2009, 12, 14),
            sorted_and_filtered_violation_responses=[],
            default_violation_history_window_months=
            VIOLATION_HISTORY_WINDOW_MONTHS,
        )

        expected_violation_window = DateRange(
            lower_bound_inclusive_date=date(2008, 12, 14),
            upper_bound_exclusive_date=date(2009, 12, 15),
        )

        self.assertEqual(expected_violation_window, violation_window)
Пример #20
0
    def test_us_nd_violation_history_window_pre_commitment_from_supervision(
        self, ) -> None:
        violation_window = UsNdCommitmentFromSupervisionDelegate(
        ).violation_history_window_pre_commitment_from_supervision(
            admission_date=date(2000, 1, 1),
            sorted_and_filtered_violation_responses=[],
            default_violation_history_window_months=0,
        )

        expected_violation_window = DateRange(
            # 90 days before
            lower_bound_inclusive_date=date(1999, 10, 3),
            # 90 days, including admission_date
            upper_bound_exclusive_date=date(2000, 3, 31),
        )

        self.assertEqual(expected_violation_window, violation_window)
Пример #21
0
    def duration(self) -> DateRange:
        """Generates a DateRange for the days covered by the incarceration period.  Since DateRange is never open,
        if the incarceration period is still active, then the exclusive upper bound of the range is set to tomorrow.
        """
        if not self.admission_date:
            raise ValueError(
                f'Expected start date for period {self.incarceration_period_id}, found None'
            )

        if (not self.release_date
                and self.status != StateIncarcerationPeriodStatus.IN_CUSTODY):
            raise ValueError(
                "Unexpected missing release date. _infer_missing_dates_and_statuses is not properly"
                " setting missing dates.")

        return DateRange.from_maybe_open_range(start_date=self.admission_date,
                                               end_date=self.release_date)
Пример #22
0
    def _months_fully_incarcerated(self) -> Set[Tuple[int, int]]:
        """For each StateIncarcerationPeriod, identifies months where the person was incarcerated for every day during
        that month. Returns a set of months in the format (year, month) for which the person spent the entire month in a
        prison.
        """
        months_fully_incarcerated: Set[Tuple[int, int]] = set()

        for incarceration_period in self.incarceration_periods:
            months_overlaps_at_all = incarceration_period.duration.get_months_range_overlaps_at_all(
            )

            for year, month in months_overlaps_at_all:
                overlapping_periods = self.month_to_overlapping_incarceration_periods[
                    year][month]

                remaining_ranges_to_cover = self._get_portions_of_range_not_covered_by_periods_subset(
                    DateRange.for_month(year, month), overlapping_periods)
                if not remaining_ranges_to_cover:
                    months_fully_incarcerated.add((year, month))

        return months_fully_incarcerated
Пример #23
0
    def violation_history_window_pre_commitment_from_supervision(
        self,
        admission_date: datetime.date,
        sorted_and_filtered_violation_responses: List[
            StateSupervisionViolationResponse],
        default_violation_history_window_months: int,
    ) -> DateRange:
        """For US_ND we look for violation responses with a response_date within 90 days
        of a commitment from supervision admission to incarceration. 90 days is an
        arbitrary buffer for which we accept discrepancies between the
        SupervisionViolationResponse response_date and the StateIncarcerationPeriod's
        admission_date.
        """

        violation_window_lower_bound_inclusive = admission_date - relativedelta(
            days=90)
        violation_window_upper_bound_exclusive = admission_date + relativedelta(
            days=90)
        return DateRange(
            lower_bound_inclusive_date=violation_window_lower_bound_inclusive,
            upper_bound_exclusive_date=violation_window_upper_bound_exclusive,
        )
Пример #24
0
    @classmethod
    def get_or_default(cls, text: Optional[str]) -> 'SnapshotType':
        if text is None:
            return SnapshotType.DAY
        return cls(text)

    DAY = 'DAY'
    FIRST_DAY_OF_MONTH = 'FIRST_DAY_OF_MONTH'
    LAST_DAY_OF_MONTH = 'LAST_DAY_OF_MONTH'


SNAPSHOT_CONVERTERS: Dict[SnapshotType, DateRangeConverterType] = {
    SnapshotType.DAY:
    DateRange.for_day,
    SnapshotType.FIRST_DAY_OF_MONTH:
    lambda date: DateRange.for_day(first_day_of_month(date)),
    SnapshotType.LAST_DAY_OF_MONTH:
    lambda date: DateRange.for_day(last_day_of_month(date)),
}


class Metric:
    @property
    @abstractmethod
    def filters(self) -> List[Dimension]:
        """Any dimensions where the data only represents a subset of values for that dimension.

        For instance, a table for the population metric may only cover data for the prison population, not those on
        parole or probation. In that case filters would contain PopulationType.PRISON.
        """
Пример #25
0
def should_include_in_release_cohort(
        status: StateIncarcerationPeriodStatus, release_date: Optional[date],
        release_reason: Optional[ReleaseReason],
        next_incarceration_period: Optional[StateIncarcerationPeriod]) -> bool:
    """Identifies whether a period of incarceration with the given features should be included in the release
    cohort."""
    # If the person is still in custody, there is no release to include in a cohort.
    if status == StateIncarcerationPeriodStatus.IN_CUSTODY:
        return False

    if not release_date:
        # If the person is not in custody, there should be a release_date.
        # This should not happen after validation. Throw error.
        raise ValueError("release_date is not set where it should be.")

    if not release_reason:
        # If there is no recorded release reason, then we cannot classify this as a valid release for the cohort
        return False

    if next_incarceration_period:
        time_range_release = DateRange.for_day(release_date)
        if DateRangeDiff(time_range_release,
                         next_incarceration_period.duration).overlapping_range:
            # If the release overlaps with the following incarceration period, this is not an actual release from
            # incarceration
            return False

        if next_incarceration_period.release_date and release_date == next_incarceration_period.release_date:
            # This release shares a release_date with the next incarceration period. Do not include this release.
            return False

    if release_reason in [ReleaseReason.DEATH, ReleaseReason.EXECUTION]:
        # If the person was released from this incarceration period because they died or were executed, do not include
        # them in the release cohort.
        return False
    if release_reason == ReleaseReason.ESCAPE:
        # If the person was released from this incarceration period because they escaped, do not include them in the
        # release cohort.
        return False
    if release_reason == ReleaseReason.RELEASED_FROM_TEMPORARY_CUSTODY:
        # If the person was released from a period of temporary custody, do not include them in the release_cohort.
        return False
    if release_reason == ReleaseReason.RELEASED_IN_ERROR:
        # If the person was released from this incarceration period due to an error, do not include them in the
        # release cohort.
        return False
    if release_reason == ReleaseReason.TRANSFER:
        # If the person was released from this incarceration period because they were transferred elsewhere, do not
        # include them in the release cohort.
        return False
    if release_reason == ReleaseReason.TRANSFERRED_OUT_OF_STATE:
        # Releases where the person has been transferred out of state don't really count as true releases.
        return False
    if release_reason == ReleaseReason.COURT_ORDER:
        # If the person was released from this incarceration period due to a court order, do not include them in the
        # release cohort.
        return False
    if release_reason in (ReleaseReason.EXTERNAL_UNKNOWN,
                          ReleaseReason.INTERNAL_UNKNOWN):
        # We do not have enough information to determine whether this release qualifies for inclusion in the release
        # cohort.
        return False
    if release_reason in (ReleaseReason.COMMUTED, ReleaseReason.COMPASSIONATE,
                          ReleaseReason.CONDITIONAL_RELEASE,
                          ReleaseReason.PARDONED,
                          ReleaseReason.RELEASED_FROM_ERRONEOUS_ADMISSION,
                          ReleaseReason.SENTENCE_SERVED,
                          ReleaseReason.VACATED):
        return True

    raise ValueError("Enum case not handled for "
                     "StateIncarcerationPeriodReleaseReason of type:"
                     f" {release_reason}.")
Пример #26
0
class TestDateRange(unittest.TestCase):
    """Tests for DateRange"""
    def setUp(self) -> None:
        self.negative_day_range = DateRange(
            lower_bound_inclusive_date=datetime.date(2019, 2, 3),
            upper_bound_exclusive_date=datetime.date(2019, 2, 2))

        self.zero_day_range = DateRange(
            lower_bound_inclusive_date=datetime.date(2019, 2, 3),
            upper_bound_exclusive_date=datetime.date(2019, 2, 3))

        self.one_day_range = DateRange(
            lower_bound_inclusive_date=datetime.date(2019, 2, 3),
            upper_bound_exclusive_date=datetime.date(2019, 2, 4))

        self.single_month_range = DateRange(
            lower_bound_inclusive_date=datetime.date(2019, 2, 1),
            upper_bound_exclusive_date=datetime.date(2019, 3, 1))

        self.multi_month_range = DateRange(
            lower_bound_inclusive_date=datetime.date(2019, 2, 3),
            upper_bound_exclusive_date=datetime.date(2019, 4, 10))

    def test_get_months_range_overlaps_at_all(self):
        self.assertEqual(
            [], self.negative_day_range.get_months_range_overlaps_at_all())
        self.assertEqual(
            [], self.zero_day_range.get_months_range_overlaps_at_all())
        self.assertEqual([(2019, 2)],
                         self.one_day_range.get_months_range_overlaps_at_all())
        self.assertEqual(
            [(2019, 2)],
            self.single_month_range.get_months_range_overlaps_at_all())
        self.assertEqual(
            [(2019, 2), (2019, 3), (2019, 4)],
            self.multi_month_range.get_months_range_overlaps_at_all())

    def test_portion_overlapping_with_month(self):

        self.assertEqual(
            None,
            self.negative_day_range.portion_overlapping_with_month(2019, 2))

        self.assertEqual(
            None, self.zero_day_range.portion_overlapping_with_month(2019, 2))

        self.assertEqual(
            self.one_day_range,
            self.one_day_range.portion_overlapping_with_month(2019, 2))

        self.assertEqual(
            self.single_month_range,
            self.single_month_range.portion_overlapping_with_month(2019, 2))

        self.assertEqual(
            DateRange(lower_bound_inclusive_date=datetime.date(2019, 2, 3),
                      upper_bound_exclusive_date=datetime.date(2019, 3, 1)),
            self.multi_month_range.portion_overlapping_with_month(2019, 2))

        self.assertEqual(
            DateRange(lower_bound_inclusive_date=datetime.date(2019, 3, 1),
                      upper_bound_exclusive_date=datetime.date(2019, 4, 1)),
            self.multi_month_range.portion_overlapping_with_month(2019, 3))

        self.assertEqual(
            DateRange(lower_bound_inclusive_date=datetime.date(2019, 4, 1),
                      upper_bound_exclusive_date=datetime.date(2019, 4, 10)),
            self.multi_month_range.portion_overlapping_with_month(2019, 4))