def test_eligible(): type_eligibility = TypeEligibility(EligibilityStatus.ELIGIBLE, "Eligible under some statute") time_eligibility = TimeEligibility(EligibilityStatus.ELIGIBLE, "Eligible under some statute", date.today()) charge_eligibility = RecordMerger.compute_charge_eligibility(type_eligibility, [time_eligibility]) assert charge_eligibility.status == ChargeEligibilityStatus.ELIGIBLE_NOW assert charge_eligibility.label == "Eligible Now"
def test_doubly_eligible_b_felony_gets_normal_eligibility_rule(): # This charge is both ManufactureDelivery and also a class B felony. ManufactureDelivery classification takes precedence and the B felony time rule does not apply. manudel_charges = ChargeFactory.create_ambiguous_charge( case_number="1", name="Manufacture/Delivery 1", statute="4759922b", level="Felony Class B", date=Time.LESS_THAN_TWENTY_YEARS_AGO, disposition=DispositionCreator.create(ruling="Convicted", date=Time.LESS_THAN_TWENTY_YEARS_AGO), ) manudel_type_eligilibility = RecordMerger.merge_type_eligibilities(manudel_charges) case_1a = CaseFactory.create(case_number="1", charges=tuple([manudel_charges[0]])) case_1b = CaseFactory.create(case_number="1", charges=tuple([manudel_charges[1]])) subsequent_charge = ChargeFactory.create( case_number="2", disposition=DispositionCreator.create(ruling="Convicted", date=Time.TEN_YEARS_AGO), ) case_2 = CaseFactory.create(case_number="2", charges=tuple([subsequent_charge])) possible_record_1 = Record(tuple([case_1a, case_2])) possible_record_2 = Record(tuple([case_1b, case_2])) expunger_result_1 = Expunger.run(possible_record_1) expunger_result_2 = Expunger.run(possible_record_2) assert manudel_type_eligilibility.status is EligibilityStatus.ELIGIBLE assert expunger_result_1[manudel_charges[0].ambiguous_charge_id].status is EligibilityStatus.ELIGIBLE assert expunger_result_2[manudel_charges[1].ambiguous_charge_id].status is EligibilityStatus.ELIGIBLE
def test_type_eligible_never_becomes_eligible(): type_eligibility = TypeEligibility(EligibilityStatus.ELIGIBLE, "Eligible under some statute") time_eligibility = TimeEligibility(EligibilityStatus.INELIGIBLE, "Never eligible under some statute", date.max()) charge_eligibility = RecordMerger.compute_charge_eligibility(type_eligibility, [time_eligibility]) assert charge_eligibility.status == ChargeEligibilityStatus.INELIGIBLE assert charge_eligibility.label == "Ineligible"
def test_eligible_mrc_with_single_arrest(): three_yr_mrc = ChargeFactory.create( disposition=DispositionCreator.create(ruling="Convicted", date=Time.THREE_YEARS_AGO) ) arrest = ChargeFactory.create(disposition=DispositionCreator.create(ruling="Dismissed", date=Time.THREE_YEARS_AGO)) case = CaseFactory.create(charges=tuple([three_yr_mrc, arrest])) record = Record(tuple([case])) expunger_result = Expunger.run(record) assert expunger_result[arrest.ambiguous_charge_id].status is EligibilityStatus.ELIGIBLE assert ( expunger_result[arrest.ambiguous_charge_id].reason == 'Time eligibility of the arrest matches conviction on the same case (the "friendly" rule)' ) assert expunger_result[arrest.ambiguous_charge_id].date_will_be_eligible == date.today() assert expunger_result[three_yr_mrc.ambiguous_charge_id].status is EligibilityStatus.ELIGIBLE assert expunger_result[three_yr_mrc.ambiguous_charge_id].reason == "Eligible now" assert expunger_result[three_yr_mrc.ambiguous_charge_id].date_will_be_eligible == date.today() merged_record = RecordMerger.merge([record], [expunger_result]) assert ( merged_record.cases[0].charges[0].expungement_result.charge_eligibility.status # type: ignore == ChargeEligibilityStatus.ELIGIBLE_NOW ) assert merged_record.cases[0].charges[0].expungement_result.charge_eligibility.label == "Eligible" # type: ignore assert ( merged_record.cases[0].charges[1].expungement_result.charge_eligibility.status # type: ignore == ChargeEligibilityStatus.ELIGIBLE_NOW ) assert merged_record.cases[0].charges[1].expungement_result.charge_eligibility.label == "Eligible" # type: ignore
def test_type_possibly_eligible_never_becomes_eligible(): type_eligibility = TypeEligibility(EligibilityStatus.NEEDS_MORE_ANALYSIS, "Unrecognized charge") time_eligibility = TimeEligibility(EligibilityStatus.INELIGIBLE, "Never eligible under some statute", date.max()) charge_eligibility = RecordMerger.compute_charge_eligibility(type_eligibility, [time_eligibility]) assert charge_eligibility.status == ChargeEligibilityStatus.INELIGIBLE assert charge_eligibility.label == "Ineligible"
def test_manufacture_delivery_manudel(): charges = ChargeFactory.create_ambiguous_charge( name="Manu/Del Cntrld Sub-SC 1", statute="4759921B", level="Felony Class A", disposition=Dispositions.CONVICTED ) type_eligibility = RecordMerger.merge_type_eligibilities(charges) assert type_eligibility.status is EligibilityStatus.NEEDS_MORE_ANALYSIS assert type_eligibility.reason == "Eligible under 137.226 ⬥ Ineligible by omission from statute"
def test_manufacture_delivery_dismissed(): charges = ChargeFactory.create_ambiguous_charge( name="Manufacture/Delivery", statute="4759922b", level="Felony Class A", disposition=Dispositions.DISMISSED ) type_eligibility = RecordMerger.merge_type_eligibilities(charges) assert type_eligibility.status is EligibilityStatus.ELIGIBLE assert type_eligibility.reason == "Dismissals are generally eligible under 137.225(1)(b)"
def test_ineligible(): type_eligibility = TypeEligibility(EligibilityStatus.INELIGIBLE, "Ineligible under some statute") charge_eligibility = RecordMerger.compute_charge_eligibility( type_eligibility, []) assert charge_eligibility.status == ChargeEligibilityStatus.INELIGIBLE assert charge_eligibility.label == "Ineligible"
def test_type_eligible_but_time_eligibility_missing(): type_eligibility = TypeEligibility(EligibilityStatus.ELIGIBLE, "Eligible under some statute") charge_eligibility = RecordMerger.compute_charge_eligibility( type_eligibility, []) assert charge_eligibility.status == ChargeEligibilityStatus.UNKNOWN assert charge_eligibility.label == "Possibly Eligible"
def test_possibly_type_eligible_but_time_eligibility_missing(): type_eligibility = TypeEligibility(EligibilityStatus.NEEDS_MORE_ANALYSIS, "Unrecognized charge") charge_eligibility = RecordMerger.compute_charge_eligibility( type_eligibility, []) assert charge_eligibility.status == ChargeEligibilityStatus.UNKNOWN assert charge_eligibility.label == "Possibly Eligible"
def test_will_be_eligible(): today = date.today() type_eligibility = TypeEligibility(EligibilityStatus.ELIGIBLE, "Eligible under some statute") time_eligibility = TimeEligibility(EligibilityStatus.INELIGIBLE, "Ineligible under some statute", today) charge_eligibility = RecordMerger.compute_charge_eligibility(type_eligibility, [time_eligibility]) assert charge_eligibility.status == ChargeEligibilityStatus.WILL_BE_ELIGIBLE assert charge_eligibility.label == f"Eligible {today.strftime('%b %-d, %Y')}"
def test_duii_dismissed(): charges = build_charges(statute="813.010", disposition_ruling="Acquitted") duii_type_eligibility = RecordMerger.merge_type_eligibilities(charges) assert duii_type_eligibility.status is EligibilityStatus.NEEDS_MORE_ANALYSIS assert ( duii_type_eligibility.reason == "Diverted DUII – Ineligible under 137.225(8) OR Dismissed Criminal Charge – Dismissals are generally eligible under 137.225(1)(d)" )
def test_duii_diverted(): charges = build_charges(statute="813.011", disposition_ruling="Diverted") duii_type_eligibility = RecordMerger.merge_type_eligibilities(charges) assert duii_type_eligibility.status is EligibilityStatus.NEEDS_MORE_ANALYSIS assert ( duii_type_eligibility.reason == "137.225(8)(b) - Diverted DUIIs are ineligible ⬥ Dismissals are generally eligible under 137.225(1)(b)" )
def test_will_be_eligible(): type_eligibility = TypeEligibility(EligibilityStatus.ELIGIBLE, "Eligible under some statute") time_eligibility = TimeEligibility( EligibilityStatus.INELIGIBLE, "Ineligible under some statute", Time.ONE_YEARS_FROM_NOW ) charge_eligibility = RecordMerger.compute_charge_eligibility(type_eligibility, [time_eligibility]) assert charge_eligibility.status == ChargeEligibilityStatus.WILL_BE_ELIGIBLE assert charge_eligibility.label == f"Eligible {Time.ONE_YEARS_FROM_NOW.strftime('%b %-d, %Y')}"
def test_possibly_eligible(): type_eligibility = TypeEligibility(EligibilityStatus.NEEDS_MORE_ANALYSIS, "Unrecognized charge") time_eligibility = TimeEligibility(EligibilityStatus.ELIGIBLE, "Eligible under for some reason", date.today()) time_eligibility_2 = TimeEligibility(EligibilityStatus.INELIGIBLE, "Ineligible under some statute", date.max()) charge_eligibility = RecordMerger.compute_charge_eligibility( type_eligibility, [time_eligibility, time_eligibility_2] ) assert charge_eligibility.status == ChargeEligibilityStatus.POSSIBLY_ELIGIBILE assert charge_eligibility.label == "Possibly Eligible Now"
def test_manufacture_delivery_manudel_felony_c(): charges = ChargeFactory.create_ambiguous_charge( name="Manu/Del Cntrld Sub-SC 1", statute="4759921B", level="Felony Class C", disposition=Dispositions.CONVICTED) type_eligibility = RecordMerger.merge_type_eligibilities(charges) assert type_eligibility.status is EligibilityStatus.ELIGIBLE assert type_eligibility.reason == "Felony Class C – Eligible under 137.225(1)(b)"
def test_pcs_class_c(): charges = ChargeFactory.create_ambiguous_charge( name="PCS", statute="4759924A", level="Felony Class C", disposition=Dispositions.CONVICTED, ) type_eligibility = RecordMerger.merge_type_eligibilities(charges) assert type_eligibility.status is EligibilityStatus.ELIGIBLE assert type_eligibility.reason == "Felony Class C – Eligible under 137.225(1)(b)"
def test_sex_crimes_with_romeo_and_juliet_exception(sex_crimes_statute): charges = ChargeFactory.create_ambiguous_charge( name="Generic", statute=sex_crimes_statute, level="Misdemeanor Class A", disposition=Dispositions.CONVICTED) type_eligibility = RecordMerger.merge_type_eligibilities(charges) assert isinstance(charges[0], Misdemeanor) assert isinstance(charges[1], RomeoAndJulietIneligibleSexCrime) assert type_eligibility.status is EligibilityStatus.NEEDS_MORE_ANALYSIS assert type_eligibility.reason == "Eligible under 137.225(5)(b) тме Failure to meet requirements under 163A.140(1)"
def test_manufacture_delivery_missing_disposition(): charges = ChargeFactory.create_ambiguous_charge( name="Manufacture/Delivery", statute="4759922b", level="Felony Class A", disposition=None ) type_eligibility = RecordMerger.merge_type_eligibilities(charges) assert type_eligibility.status is EligibilityStatus.NEEDS_MORE_ANALYSIS assert ( type_eligibility.reason == "Always eligible under 137.226 (for convictions) or 137.225(1)(b) (for dismissals) ⬥ Disposition not found. Needs further analysis" )
def analyze_ambiguous_record(ambiguous_record: AmbiguousRecord): charge_id_to_time_eligibilities = [] for record in ambiguous_record: record.errors += ErrorChecker.check(record) # TODO: Fix mutation expunger = Expunger(record) charge_id_to_time_eligibility = expunger.run() charge_id_to_time_eligibilities.append( charge_id_to_time_eligibility) record = RecordMerger.merge(ambiguous_record, charge_id_to_time_eligibilities) return record
def test_subsection_6_dismissed(): charges = ChargeFactory.create_ambiguous_charge( name="Criminal mistreatment in the second degree", statute="163.200", level="Misdemeanor Class A", disposition=Dispositions.DISMISSED, ) type_eligibility = RecordMerger.merge_type_eligibilities(charges) assert isinstance(charges[0], DismissedCharge) assert type_eligibility.status is EligibilityStatus.ELIGIBLE assert type_eligibility.reason == "Dismissals are generally eligible under 137.225(1)(b)"
def test_person_felony_class_b(person_felony_statute): charges = ChargeFactory.create_ambiguous_charge( name="Generic", statute=person_felony_statute, level="Felony Class B", disposition=Dispositions.CONVICTED) type_eligibility = RecordMerger.merge_type_eligibilities(charges) assert any([isinstance(charge, PersonFelonyClassB) for charge in charges]) assert type_eligibility.status in [ EligibilityStatus.NEEDS_MORE_ANALYSIS, EligibilityStatus.INELIGIBLE ] assert "Ineligible under 137.225(5)(a)" in type_eligibility.reason
def test_possibly_will_be_eligible(): type_eligibility = TypeEligibility(EligibilityStatus.NEEDS_MORE_ANALYSIS, "Unrecognized charge") time_eligibility = TimeEligibility( EligibilityStatus.INELIGIBLE, "Ineligible for some reason", Time.ONE_YEARS_FROM_NOW ) time_eligibility_2 = TimeEligibility(EligibilityStatus.INELIGIBLE, "Ineligible under some statute", date.max()) charge_eligibility = RecordMerger.compute_charge_eligibility( type_eligibility, [time_eligibility, time_eligibility_2] ) assert charge_eligibility.status == ChargeEligibilityStatus.POSSIBLY_WILL_BE_ELIGIBLE assert charge_eligibility.label == f"Possibly Eligible {Time.ONE_YEARS_FROM_NOW.strftime('%b %-d, %Y')}"
def test_sex_crimes_with_romeo_and_juliet_exception(sex_crimes_statute): charges = ChargeFactory.create_ambiguous_charge( name="Generic", statute=sex_crimes_statute, level="Misdemeanor Class A", disposition=Dispositions.CONVICTED ) type_eligibility = RecordMerger.merge_type_eligibilities(charges) assert isinstance(charges[0], RomeoAndJulietNMASexCrime) assert isinstance(charges[1], RomeoAndJulietIneligibleSexCrime) assert type_eligibility.status is EligibilityStatus.INELIGIBLE assert ( type_eligibility.reason == "Possibly meets requirements under 137.225(6)(f) - Email [email protected] with subject line '6F' for free and confidential further analysis тме Fails to meet requirements under 137.225(6)(f)" )
def disambiguate_record(ambiguous_record, questions_data): questions_as_list = [ from_dict(data_class=Question, data=question) for id, question in questions_data.items() ] questions = dict( list(map(lambda q: (q.ambiguous_charge_id, q), questions_as_list))) updated_ambiguous_record = RecordMerger.filter_ambiguous_record( ambiguous_record, questions_as_list) record = RecordCreator.analyze_ambiguous_record( updated_ambiguous_record) return questions, record
def test_subsection_6_163165(): charges = ChargeFactory.create_ambiguous_charge( name="Assault in the third degree", statute="163.165", level="Felony Class C", disposition=Dispositions.CONVICTED, ) type_eligibility = RecordMerger.merge_type_eligibilities(charges) assert isinstance(charges[0], FelonyClassC) assert isinstance(charges[1], Subsection6) assert type_eligibility.status is EligibilityStatus.NEEDS_MORE_ANALYSIS assert type_eligibility.reason == "Eligible under 137.225(5)(b) ⬥ Ineligible under 137.225(6)"
def test_subsection_6_163200(): charges = ChargeFactory.create_ambiguous_charge( name="Criminal mistreatment in the second degree", statute="163.200", level="Misdemeanor Class A", disposition=Dispositions.CONVICTED, ) type_eligibility = RecordMerger.merge_type_eligibilities(charges) assert isinstance(charges[0], Subsection6) assert isinstance(charges[1], Misdemeanor) assert type_eligibility.status is EligibilityStatus.NEEDS_MORE_ANALYSIS assert type_eligibility.reason == "Ineligible under 137.225(6) ⬥ Eligible under 137.225(5)(b)"
def test_manufacture_delivery_manufacturing_name(): charges = ChargeFactory.create_ambiguous_charge( name="MANUFACTURING CONTROLLED SUB", statute="4759921A", level="Felony Unclassified", disposition=Dispositions.CONVICTED, ) type_eligibility = RecordMerger.merge_type_eligibilities(charges) assert type_eligibility.status is EligibilityStatus.NEEDS_MORE_ANALYSIS assert ( type_eligibility.reason == "Marijuana Manufacture Delivery – Eligible under 137.226 OR Felony Class A – Ineligible by omission from statute OR Felony Class B – Convictions that fulfill the conditions of 137.225(1)(b) are eligible OR Felony Class C – Eligible under 137.225(1)(b)" )
def test_manufacture_delivery_unrecognized_disposition(): charges = ChargeFactory.create_ambiguous_charge( name="Manufacture/Delivery", statute="4759922b", level="Felony Class B", disposition=Dispositions.UNRECOGNIZED_DISPOSITION, ) type_eligibility = RecordMerger.merge_type_eligibilities(charges) assert type_eligibility.status is EligibilityStatus.NEEDS_MORE_ANALYSIS assert ( type_eligibility.reason == "Marijuana Manufacture Delivery – Always eligible under 137.226 (for convictions) or 137.225(1)(d) (for dismissals) OR Felony Class B – Disposition not recognized. Needs further analysis" )
def test_pcs_heroin(): charges = ChargeFactory.create_ambiguous_charge( name="POSS CONTROLLED SUB HEROIN", statute="4757521A", level="Felony Unclassified", disposition=Dispositions.CONVICTED, ) type_eligibility = RecordMerger.merge_type_eligibilities(charges) assert type_eligibility.status is EligibilityStatus.ELIGIBLE assert ( type_eligibility.reason == "Felony Class B – Convictions that fulfill the conditions of 137.225(1)(b) are eligible OR Felony Class C – Eligible under 137.225(1)(b)" )