def test_case(example_sentence): char = Charge( "Eating w/ mouth open", "M2", "14 section 23", "Guilty Plea", sentences=[example_sentence]) case = Case( status="Open", county="Erie", docket_number="12-CP-02", otn="112000111", dc="11222", charges=[char], total_fines=200, fines_paid=1, judge="Smooth Operator", judge_address="1234 Other St., PA", disposition_date=None, arrest_date=None, complaint_date=None, affiant="Sheriff Smelly", arresting_agency="Upsidedown County", arresting_agency_address="1234 Main St., PA", ) assert case.status == "Open"
def example_charge(example_sentence): return Charge( "Eating w/ mouth open", "M2", "14 section 23", "Guilty Plea", disposition_date=date(2010,1,1), sentences=[example_sentence])
def test_guess_grade(statute, grade): dummy_charge = Charge(offense="", grade="", statute=statute, sentences=[], disposition="") guess_list = guess_grade(dummy_charge) most_likely = guess_list[-1] assert most_likely[0] == grade
def get_charges(stree: etree) -> List[Charge]: """ Find a list of the charges in a parsed docket. """ # find the charges in the Charges section charges = stree.xpath("//section[@name='section_charges']//charge") # charges is temporarily a list of tuples of [(sequence_num, Charge)] charges = [(xpath_or_blank(charge, "./seq_num"), Charge( offense=xpath_or_blank(charge, "./statute_description"), grade=xpath_or_blank(charge, "./grade"), statute=xpath_or_blank(charge, "./statute"), disposition="Unknown", disposition_date=None, sentences=[], )) for charge in charges] # figure out the disposition dates by looking for a final disposition date that matches a charge. final_disposition_events = stree.xpath( "//section[@name='section_disposition_sentencing']//case_event[case_event_desc_and_date/is_final[contains(text(),'Final Disposition')]]" ) for final_disp_event in final_disposition_events: final_disp_date = xpath_date_or_blank(final_disp_event, ".//case_event_date") applies_to_sequences = xpath_or_empty_list(final_disp_event, ".//sequence_number") for seq_num in applies_to_sequences: # set the final_disp date for the charge with sequence number seq_num for sn, charge in charges: if sn == seq_num: charge.disposition_date = final_disp_date # Figure out the disposition of each charge from the disposition section. # Do this by finding the last sequence in the disposition section for # the sequence with seq_num. The disposition of the charge is that # sequence's disposition. Sentence is in that xml element too. try: disposition_section = stree.xpath( "//section[@name='section_disposition_sentencing']")[0] for seq_num, charge in charges: try: # seq is the last sequence for the charge seq_num. seq = disposition_section.xpath( f"./disposition_section/disposition_subsection/disposition_details/case_event/sequences/sequence[sequence_number/text()=' {seq_num} ']" )[-1] charge.disposition = xpath_or_blank(seq, "./offense_disposition") charge.sentences = get_sentences(seq) except IndexError: continue except IndexError: pass return [c for i, c in charges]
def from_dict(dct: str) -> Optional[Case]: """Create a Case from a dict""" try: return Case( status = dct.get("status"), county = dct.get("county"), docket_number = dct["docket_number"], # if there's no docket_number at least, this should fail otn = dct.get("otn"), dc = dct.get("dc"), charges = [Charge.from_dict(c) for c in (dct.get("charges") or [])], total_fines = dct.get("total_fines"), fines_paid = dct.get("fines_paid"), complaint_date = dct.get("complaint_date"), arrest_date = dct.get("arrest_date"), disposition_date = dct.get("disposition_date"), judge = dct.get("judge"), judge_address = dct.get("judge_address"), affiant = dct.get("affiant"), arresting_agency = dct.get("arresting_agency"), arresting_agency_address = dct.get("arresting_agency_address"), ) except: return None
def get_md_cases(summary_xml: etree.Element) -> List: """ Return a list of the cases described in this Summary sheet. """ cases = [] case_elements = summary_xml.xpath("//case") for case in case_elements: # in mdj summaries, there's only one "charge" element, not different "open" and "closed" elements. # And there are no sentences recorded. md_charges = [] md_charge_elems = case.xpath(".//charge") for charge in md_charge_elems: charge = Charge( offense=text_or_blank(charge.find("description")), statute=text_or_blank(charge.find("statute")), grade=text_or_blank(charge.find("grade")), disposition=text_or_blank(charge.find("disposition")), sentences=[], ) md_charges.append(charge) cases.append( Case( status=text_or_blank(case.getparent().getparent()), county=text_or_blank(case.getparent().find("county")), docket_number=text_or_blank(case.find("case_basics/docket_num")), otn=text_or_blank(case.find("case_basics/otn_num")), dc=text_or_blank(case.find("case_basics/dc_num")), charges=md_charges, total_fines=None, # a summary docket never has info about this. fines_paid=None, arrest_date=date_or_none( case.find("arrest_disp_actions/arrest_disp/arrest_date") ), disposition_date=date_or_none( case.find("arrest_disp_actions/arrest_disp/disp_date") ), judge=text_or_blank(case.find("arrest_disp_actions/arrest_disp/disp_judge")), ) ) return cases
def get_cp_cases(summary_xml: etree.Element) -> List: """ Return a list of the cases described in this Summary sheet. """ cases = [] case_elements = summary_xml.xpath("//case") for case in case_elements: closed_sequences = case.xpath(".//closed_sequence") closed_charges = [] for seq in closed_sequences: charge = Charge( offense=text_or_blank(seq.find("description")), statute=text_or_blank(seq.find("statute")), grade=text_or_blank(seq.find("grade")), disposition=text_or_blank(seq.find("sequence_disposition")), disposition_date=None, sentences=[], ) for sentence in seq.xpath(".//sentencing_info"): charge.sentences.append( Sentence( sentence_date=date_or_none(sentence.find("sentence_date")), sentence_type=text_or_blank(sentence.find("sentence_type")), sentence_period=text_or_blank( sentence.find("program_period") ), sentence_length=SentenceLength.from_tuples( min_time=( text_or_blank( sentence.find("sentence_length/min_length/time") ), text_or_blank( sentence.find("sentence_length/min_length/unit") ), ), max_time=( text_or_blank( sentence.find("sentence_length/max_length/time") ), text_or_blank( sentence.find("sentence_length/max_length/unit") ), ), ), ) ) closed_charges.append(charge) open_sequences = case.xpath(".//open_sequence") open_charges = [] for seq in open_sequences: charge = Charge( offense=text_or_blank(seq.find("description")), statute=text_or_blank(seq.find("statute")), grade=text_or_blank(seq.find("grade")), disposition=text_or_blank(seq.find("sequence_disposition")), disposition_date=None, sentences=[], ) for sentence in seq.xpath(".//sentencing_info"): charge.sentences.append( Sentence( sentence_date=date_or_none(sentence.find("sentence_date")), sentence_type=text_or_blank(sentence.find("sentence_type")), sentence_period=text_or_blank( sentence.find("program_period") ), sentence_length=SentenceLength.from_tuples( min_time=( text_or_blank( sentence.find("sentence_length/min_length/time") ), text_or_blank( sentence.find("sentence_length/min_length/unit") ), ), max_time=( text_or_blank( sentence.find("sentence_length/max_length/time") ), text_or_blank( sentence.find("sentence_length/max_length/unit") ), ), ), ) ) open_charges.append(charge) new_case = Case( status=text_or_blank(case.getparent().getparent()), county=text_or_blank(case.getparent().find("county")), docket_number=text_or_blank(case.find("case_basics/docket_num")), otn=text_or_blank(case.find("case_basics/otn_num")), dc=text_or_blank(case.find("case_basics/dc_num")), charges=closed_charges + open_charges, total_fines=None, # a summary docket never has info about this. fines_paid=None, arrest_date=date_or_none( either(case.find("arrest_disp_actions/arrest_disp/arrest_date"), case.find("arrest_disp_actions/arrest_trial/arrest_date")) ), disposition_date=date_or_none( case.find("arrest_disp_actions/arrest_disp/disp_date") ), judge=text_or_blank(case.find("arrest_disp_actions/arrest_disp/disp_judge")), ) # In Summaries, the Disposition Date is set on a Case, but it is set on a Charge in Dockets. # So when processing a Summary sheet, if there is a date on the Case, the Charges should # inherit the date on the case. for charge in new_case.charges: if new_case.disposition_date is not None: charge.disposition_date = new_case.disposition_date cases.append(new_case) return cases
def get_cp_cases(summary_xml: etree.Element) -> List: """ Return a list of the cases described in this Summary sheet. """ cases = [] case_elements = summary_xml.xpath("//case") for case in case_elements: closed_sequences = case.xpath(".//closed_sequence") closed_charges = [] for seq in closed_sequences: charge = Charge( offense=text_or_blank(seq.find("description")), statute=text_or_blank(seq.find("statute")), grade=text_or_blank(seq.find("grade")), disposition=text_or_blank(seq.find("sequence_disposition")), sentences=[], ) for sentence in seq.xpath(".//sentencing_info"): charge.sentences.append( Sentence( sentence_date=date_or_none( sentence.find("sentence_date")), sentence_type=text_or_blank( sentence.find("sentence_type")), sentence_period=text_or_blank( sentence.find("program_period")), sentence_length=SentenceLength( min_time=( text_or_blank( sentence.find( "sentence_length/min_length/time")), text_or_blank( sentence.find( "sentence_length/min_length/unit")), ), max_time=( text_or_blank( sentence.find( "sentence_length/max_length/time")), text_or_blank( sentence.find( "sentence_length/max_length/unit")), ), ), )) closed_charges.append(charge) open_sequences = case.xpath(".//open_sequence") open_charges = [] for seq in open_sequences: charge = Charge( offense=text_or_blank(seq.find("description")), statute=text_or_blank(seq.find("statute")), grade=text_or_blank(seq.find("grade")), disposition=text_or_blank(seq.find("sequence_disposition")), sentences=[], ) for sentence in seq.xpath(".//sentencing_info"): charge.sentences.append( Sentence( sentence_date=date_or_none( sentence.find("sentence_date")), sentence_type=text_or_blank( sentence.find("sentence_type")), sentence_period=text_or_blank( sentence.find("program_period")), sentence_length=SentenceLength( min_time=( text_or_blank( sentence.find( "sentence_length/min_length/time")), text_or_blank( sentence.find( "sentence_length/min_length/unit")), ), max_time=( text_or_blank( sentence.find( "sentence_length/max_length/time")), text_or_blank( sentence.find( "sentence_length/max_length/unit")), ), ), )) open_charges.append(charge) cases.append( Case( status=text_or_blank(case.getparent().getparent()), county=text_or_blank(case.getparent().find("county")), docket_number=text_or_blank( case.find("case_basics/docket_num")), otn=text_or_blank(case.find("case_basics/otn_num")), dc=text_or_blank(case.find("case_basics/dc_num")), charges=closed_charges + open_charges, fines_and_costs= None, # a summary docket never has info about this. arrest_date=date_or_none( case.find("arrest_and_disp/arrest_date")), disposition_date=date_or_none( case.find("arrest_and_disp/disp_date")), judge=text_or_blank(case.find("arrest_and_disp/disp_judge")), )) return cases
def example_charge(example_sentence): return Charge("Eating w/ mouth open", "M2", "14 section 23", "Guilty Plea", sentences=[example_sentence])