def test_bill_duplicate_actions_ordering(): create_jurisdiction() create_org() def _problem_bill(): bill = ScrapeBill( "HB 1", "1900", "Axe & Tack Tax Act", classification="tax bill", chamber="lower", ) # two identical actions, and one differs bill.add_action("identical action", "1900-04-01", chamber="lower") bill.add_action("different action", "1900-04-01", chamber="lower") bill.add_action("identical action", "1900-04-01", chamber="lower") return bill # import bill bill = _problem_bill() result = BillImporter("jid").import_data([bill.as_dict()]) assert result["bill"]["insert"] == 1 assert result["bill"]["update"] == 0 assert result["bill"]["noop"] == 0 bill = _problem_bill() result = BillImporter("jid").import_data([bill.as_dict()]) assert result["bill"]["insert"] == 0 assert result["bill"]["update"] == 0 assert result["bill"]["noop"] == 1
def do_import(juris, args): # import inside here because to avoid loading Django code unnecessarily from openstates.importers import ( JurisdictionImporter, BillImporter, VoteEventImporter, ) datadir = os.path.join(settings.SCRAPED_DATA_DIR, args.module) juris_importer = JurisdictionImporter(juris.jurisdiction_id) bill_importer = BillImporter(juris.jurisdiction_id) vote_event_importer = VoteEventImporter(juris.jurisdiction_id, bill_importer) report = {} with transaction.atomic(): print("import jurisdictions...") report.update(juris_importer.import_directory(datadir)) if settings.ENABLE_BILLS: print("import bills...") report.update(bill_importer.import_directory(datadir)) if settings.ENABLE_VOTES: print("import vote events...") report.update(vote_event_importer.import_directory(datadir)) # compile info on all sessions that were updated in this run seen_sessions = set() seen_sessions.update(bill_importer.get_seen_sessions()) seen_sessions.update(vote_event_importer.get_seen_sessions()) for session in seen_sessions: generate_session_report(session) return report
def test_resolve_person_case_insensitive(): create_jurisdiction() bi = BillImporter("jid") org = Organization.objects.get(jurisdiction_id="jid", classification="legislature") p = Person.objects.create(name="John McGuirk") p.memberships.create(organization=org) assert bi.resolve_person('~{"name": "JohN mCgUIrk"}') == p.id
def test_full_vote_event(): j = create_jurisdiction() j.legislative_sessions.create(name="1900", identifier="1900") sp1 = ScrapePerson("John Smith", primary_org="lower") sp2 = ScrapePerson("Adam Smith", primary_org="lower") org = ScrapeOrganization(name="House", classification="lower") bill = ScrapeBill("HB 1", "1900", "Axe & Tack Tax Act", from_organization=org._id) vote_event = ScrapeVoteEvent( legislative_session="1900", motion_text="passage", start_date="1900-04-01", classification="passage:bill", result="pass", bill_chamber="lower", bill="HB 1", organization=org._id, ) vote_event.set_count("yes", 20) vote_event.yes("John Smith") vote_event.no("Adam Smith") oi = OrganizationImporter("jid") oi.import_data([org.as_dict()]) pi = PersonImporter("jid") pi.import_data([sp1.as_dict(), sp2.as_dict()]) mi = MembershipImporter("jid", pi, oi, DumbMockImporter()) mi.import_data([sp1._related[0].as_dict(), sp2._related[0].as_dict()]) bi = BillImporter("jid", oi, pi) bi.import_data([bill.as_dict()]) VoteEventImporter("jid", pi, oi, bi).import_data([vote_event.as_dict()]) assert VoteEvent.objects.count() == 1 ve = VoteEvent.objects.get() assert ve.legislative_session == LegislativeSession.objects.get() assert ve.motion_classification == ["passage:bill"] assert ve.bill == Bill.objects.get() count = ve.counts.get() assert count.option == "yes" assert count.value == 20 votes = list(ve.votes.all()) assert len(votes) == 2 for v in ve.votes.all(): if v.voter_name == "John Smith": assert v.option == "yes" assert v.voter == Person.objects.get(name="John Smith") else: assert v.option == "no" assert v.voter == Person.objects.get(name="Adam Smith")
def test_vote_event_bill_actions_two_stage(): # this test is very similar to what we're testing in test_vote_event_bill_actions w/ # ve3 and ve4, that two bills that reference the same action won't conflict w/ the # OneToOneField, but in this case we do it in two stages so that the conflict is found # even if the votes weren't in the same scrape create_jurisdiction() bill = ScrapeBill("HB 1", "1900", "Axe & Tack Tax Act", chamber="lower") bill.add_action(description="passage", date="1900-04-02", chamber="lower") ve1 = ScrapeVoteEvent( legislative_session="1900", motion_text="passage", start_date="1900-04-02", classification="passage:bill", result="pass", bill_chamber="lower", bill="HB 1", bill_action="passage", chamber="lower", ) ve2 = ScrapeVoteEvent( legislative_session="1900", motion_text="passage", start_date="1900-04-02", classification="passage:bill", result="pass", bill_chamber="lower", bill="HB 1", bill_action="passage", chamber="lower", ) # disambiguate them ve1.pupa_id = "one" ve2.pupa_id = "two" bi = BillImporter("jid") bi.import_data([bill.as_dict()]) # first imports just fine VoteEventImporter("jid", bi).import_data([ve1.as_dict()]) votes = list(VoteEvent.objects.all()) assert len(votes) == 1 assert votes[0].bill_action is not None # when second is imported, ensure that action stays pinned to first just as it would # have if they were both in same import VoteEventImporter("jid", bi).import_data([ve1.as_dict(), ve2.as_dict()]) votes = list(VoteEvent.objects.all()) assert len(votes) == 2 assert votes[0].bill_action is not None assert votes[1].bill_action is None
def test_resolve_bill_by_date_transformers(): j = create_jurisdiction() session = j.legislative_sessions.create( name="2021", identifier="2021", start_date="2021-01-01", end_date="2021-12-31", ) bi = BillImporter("jid") b = Bill.objects.create(identifier="HB 1", title="Some Bill", legislative_session=session) assert bi.resolve_bill("hb1", date="2021-05-06") == b.id
def test_deduplication_identical_object(): create_jurisdiction() p1 = ScrapeBill("HB 1", "2020", "Title").as_dict() p2 = ScrapeBill("HB 1", "2020", "Title").as_dict() BillImporter("jid").import_data([p1, p2]) assert Bill.objects.count() == 1
def test_invalid_fields(): create_jurisdiction() p1 = ScrapeBill("HB 1", "2020", "Title").as_dict() p1["newfield"] = "shouldn't happen" with pytest.raises(DataImportError): BillImporter("jid").import_data([p1])
def test_bill_sponsor_by_identifier(): create_jurisdiction() org = create_org() bill = ScrapeBill("HB 1", "1900", "Axe & Tack Tax Act", classification="tax bill", chamber="lower") bill.add_sponsorship_by_identifier( name="SNODGRASS", classification="sponsor", entity_type="person", primary=True, identifier="TOTALLY_REAL_ID", scheme="TOTALLY_REAL_SCHEME", ) za_db = Person.objects.create(name="Zadock Snodgrass") za_db.identifiers.create(identifier="TOTALLY_REAL_ID", scheme="TOTALLY_REAL_SCHEME") Membership.objects.create(person_id=za_db.id, organization_id=org.id) BillImporter("jid").import_data([bill.as_dict()]) obj = Bill.objects.get() (entry, ) = obj.sponsorships.all() assert entry.person.name == "Zadock Snodgrass"
def test_bill_sponsor_limit_lookup_within_session(): j = create_jurisdiction() org = create_org() j.legislative_sessions.create(identifier="2021", name="2021", start_date="2021", end_date="2022") old_bill = ScrapeBill("HB 1", "1900", "Axe & Tack Tax Act", classification="tax bill", chamber="lower") old_bill.add_sponsorship( name="Springfield", classification="sponsor", entity_type="person", primary=True, ) new_bill = ScrapeBill( "HB 9000", "2021", "Laser Regulations", classification="tax bill", chamber="lower", ) new_bill.add_sponsorship( name="Springfield", classification="sponsor", entity_type="person", primary=True, ) jeb = Person.objects.create(name="Jebediah Springfield", birth_date="1850-01-01", family_name="Springfield") Membership.objects.create(person_id=jeb.id, organization_id=org.id, end_date="1910-01-01") futuro = Person.objects.create(name="Futuro Springfield", birth_date="2000-01-01", family_name="Springfield") Membership.objects.create(person_id=futuro.id, organization_id=org.id, start_date="2020-04-01") BillImporter("jid").import_data([old_bill.as_dict(), new_bill.as_dict()]) # get old bill and ensure Jeb is sponsor old_bill_obj = Bill.objects.get(identifier="HB 1") (entry, ) = old_bill_obj.sponsorships.all() assert entry.person.name == jeb.name # get new bill and ensure Futuro is sponsor new_bill_obj = Bill.objects.get(identifier="HB 9000") (entry, ) = new_bill_obj.sponsorships.all() assert entry.person.name == futuro.name
def test_fix_bill_id(): j = create_jurisdiction() j.legislative_sessions.create(name="1900", identifier="1900") org1 = ScrapeOrganization(name="House", classification="lower") bill = ScrapeBill("HB 1", "1900", "Test Bill ID", classification="bill", chamber="lower") oi = OrganizationImporter("jid") oi.import_data([org1.as_dict()]) from openstates.settings import IMPORT_TRANSFORMERS IMPORT_TRANSFORMERS["bill"] = { "identifier": lambda x: re.sub(r"([A-Z]*)\s*0*([-\d]+)", r"\1 \2", x, 1) } bi = BillImporter("jid", oi, DumbMockImporter()) bi.import_data([bill.as_dict()]) ve = ScrapeVoteEvent( legislative_session="1900", motion_text="passage", start_date="1900-04-02", classification="passage:bill", result="fail", bill_chamber="lower", bill="HB1", identifier="4", bill_action="passage", organization=org1._id, ) VoteEventImporter("jid", DumbMockImporter(), oi, bi).import_data([ve.as_dict()]) IMPORT_TRANSFORMERS["bill"] = {} ve = VoteEvent.objects.get() ve.bill.identifier == "HB 1"
def test_full_vote_event(): create_jurisdiction() bill = ScrapeBill("HB 1", "1900", "Axe & Tack Tax Act", chamber="lower") vote_event = ScrapeVoteEvent( legislative_session="1900", motion_text="passage", start_date="1900-04-01", classification="passage:bill", result="pass", bill_chamber="lower", bill="HB 1", chamber="lower", ) vote_event.set_count("yes", 20) vote_event.yes("John Smith") vote_event.no("Adam Smith") Person.objects.create(name="John Smith") Person.objects.create(name="Adam Smith") for person in Person.objects.all(): person.memberships.create(organization=Organization.objects.get( classification="lower")) bi = BillImporter("jid") bi.import_data([bill.as_dict()]) VoteEventImporter("jid", bi).import_data([vote_event.as_dict()]) assert VoteEvent.objects.count() == 1 ve = VoteEvent.objects.get() assert ve.legislative_session == LegislativeSession.objects.get() assert ve.motion_classification == ["passage:bill"] assert ve.bill == Bill.objects.get() count = ve.counts.get() assert count.option == "yes" assert count.value == 20 votes = list(ve.votes.all()) assert len(votes) == 2 for v in ve.votes.all(): if v.voter_name == "John Smith": assert v.option == "yes" assert v.voter == Person.objects.get(name="John Smith") else: assert v.option == "no" assert v.voter == Person.objects.get(name="Adam Smith")
def test_exception_on_identical_objects_in_import_stream(): create_jurisdiction() # these two objects aren't identical, but refer to the same thing # at the moment we consider this an error (but there may be a better way to handle this?) b1 = ScrapeBill("HB 1", "2020", "Title", chamber="upper").as_dict() b2 = ScrapeBill("HB 1", "2020", "Title", chamber="lower").as_dict() with pytest.raises(Exception): BillImporter("jid").import_data([b1, b2])
def test_invalid_fields_related_item(): create_jurisdiction() p1 = ScrapeBill("HB 1", "2020", "Title") p1.add_source("http://example.com") p1 = p1.as_dict() p1["sources"][0]["test"] = 3 with pytest.raises(DataImportError): BillImporter("jid").import_data([p1])
def test_vote_event_bill_clearing(): # ensure that we don't wind up with vote events sitting around forever on bills as # changes make it look like there are multiple vote events j = create_jurisdiction() session = j.legislative_sessions.create(name="1900", identifier="1900") org = Organization.objects.create(id="org-id", name="House", classification="lower", jurisdiction=j) bill = Bill.objects.create( id="bill-1", identifier="HB 1", legislative_session=session, from_organization=org, ) Bill.objects.create( id="bill-2", identifier="HB 2", legislative_session=session, from_organization=org, ) oi = OrganizationImporter("jid") dmi = DumbMockImporter() bi = BillImporter("jid", dmi, oi) vote_event1 = ScrapeVoteEvent( legislative_session="1900", start_date="2013", classification="anything", result="passed", motion_text="a vote on somthing", # typo intentional bill=bill.identifier, bill_chamber="lower", chamber="lower", ) vote_event2 = ScrapeVoteEvent( legislative_session="1900", start_date="2013", classification="anything", result="passed", motion_text="a vote on something else", bill=bill.identifier, bill_chamber="lower", chamber="lower", ) # have to use import_data so postimport is called VoteEventImporter("jid", dmi, oi, bi).import_data( [vote_event1.as_dict(), vote_event2.as_dict()]) assert VoteEvent.objects.count() == 2 # a typo is fixed, we don't want 3 vote events now vote_event1.motion_text = "a vote on something" VoteEventImporter("jid", dmi, oi, bi).import_data( [vote_event1.as_dict(), vote_event2.as_dict()]) assert VoteEvent.objects.count() == 2
def test_vote_event_bill_id_dedupe(): create_jurisdiction() bill = Bill.objects.create( id="bill-1", identifier="HB 1", legislative_session=LegislativeSession.objects.get(), from_organization=Organization.objects.get(classification="lower"), ) bill2 = Bill.objects.create( id="bill-2", identifier="HB 2", legislative_session=LegislativeSession.objects.get(), from_organization=Organization.objects.get(classification="lower"), ) vote_event = ScrapeVoteEvent( legislative_session="1900", start_date="2013", classification="anything", result="passed", motion_text="a vote on something", bill=bill.identifier, bill_chamber="lower", chamber="lower", ) bi = BillImporter("jid") _, what = VoteEventImporter("jid", bi).import_item(vote_event.as_dict()) assert what == "insert" assert VoteEvent.objects.count() == 1 # same exact vote event, no changes _, what = VoteEventImporter("jid", bi).import_item(vote_event.as_dict()) assert what == "noop" assert VoteEvent.objects.count() == 1 # new info, update vote_event.result = "failed" _, what = VoteEventImporter("jid", bi).import_item(vote_event.as_dict()) assert what == "update" assert VoteEvent.objects.count() == 1 # new vote event, insert vote_event = ScrapeVoteEvent( legislative_session="1900", start_date="2013", classification="anything", result="passed", motion_text="a vote on something", bill=bill2.identifier, bill_chamber="lower", chamber="lower", ) _, what = VoteEventImporter("jid", bi).import_item(vote_event.as_dict()) assert what == "insert" assert VoteEvent.objects.count() == 2
def test_bill_update(): create_jurisdiction() create_org() bill = ScrapeBill("HB 1", "1900", "First Bill", chamber="lower") _, what = BillImporter("jid").import_item(bill.as_dict()) assert what == "insert" _, what = BillImporter("jid").import_item(bill.as_dict()) assert what == "noop" # ensure no new object was created assert Bill.objects.count() == 1 # test basic update bill = ScrapeBill("HB 1", "1900", "1st Bill", chamber="lower") _, what = BillImporter("jid").import_item(bill.as_dict()) assert what == "update" assert Bill.objects.get().title == "1st Bill"
def test_exception_on_identical_objects_in_import_stream(): create_jurisdiction() # the first two objects aren't identical, but refer to the same thing # at the moment we drop both objects (because we can't know which one is correct) b1 = ScrapeBill("HB 1", "2020", "Title", chamber="upper").as_dict() b2 = ScrapeBill("HB 1", "2020", "Title", chamber="lower").as_dict() b3 = ScrapeBill("HB 2", "2020", "Bill Title").as_dict() BillImporter("jid").import_data([b1, b2, b3]) assert Bill.objects.count() == 1
def test_fix_bill_id(): create_jurisdiction() create_org() bill = ScrapeBill("hb1", "1900", "Test Bill ID", classification="bill", chamber="lower") from openstates.settings import IMPORT_TRANSFORMERS IMPORT_TRANSFORMERS["bill"] = { "identifier": fix_bill_id, } bi = BillImporter("jid") bi.import_data([bill.as_dict()]) IMPORT_TRANSFORMERS["bill"] = {} b = Bill.objects.get() assert b.identifier == "HB 1"
def test_vote_event_pupa_identifier_dedupe(): j = create_jurisdiction() j.legislative_sessions.create(name="1900", identifier="1900") Organization.objects.create(id="org-id", name="Legislature", classification="legislature", jurisdiction=j) vote_event = ScrapeVoteEvent( legislative_session="1900", start_date="2013", classification="anything", result="passed", motion_text="a vote on something", identifier="Roll Call No. 1", ) vote_event.pupa_id = "foo" dmi = DumbMockImporter() oi = OrganizationImporter("jid") bi = BillImporter("jid", dmi, oi) _, what = VoteEventImporter("jid", dmi, oi, bi).import_item(vote_event.as_dict()) assert what == "insert" assert VoteEvent.objects.count() == 1 # same exact vote event, no changes _, what = VoteEventImporter("jid", dmi, oi, bi).import_item(vote_event.as_dict()) assert what == "noop" assert VoteEvent.objects.count() == 1 # new info, update vote_event.result = "failed" _, what = VoteEventImporter("jid", dmi, oi, bi).import_item(vote_event.as_dict()) assert what == "update" assert VoteEvent.objects.count() == 1 # new bill identifier, update vote_event.identifier = "First Roll Call" _, what = VoteEventImporter("jid", dmi, oi, bi).import_item(vote_event.as_dict()) assert what == "update" assert VoteEvent.objects.count() == 1 # new identifier, insert vote_event.pupa_id = "bar" _, what = VoteEventImporter("jid", dmi, oi, bi).import_item(vote_event.as_dict()) assert what == "insert" assert VoteEvent.objects.count() == 2
def test_duplicate_bill_different_chamber(): create_jurisdiction() create_org() Organization.objects.create(id="upper-id", name="Senate", classification="upper", jurisdiction_id="jid") b1 = ScrapeBill("HB 1", "1900", "Axe & Tack Tax Act", chamber="lower") b2 = ScrapeBill("HB 1", "1900", "Axe & Tack Tax Act", chamber="upper") with pytest.raises(DuplicateItemError): BillImporter("jid").import_data([b1.as_dict(), b2.as_dict()])
def do_import(juris: State, args: argparse.Namespace) -> dict[str, typing.Any]: # import inside here because to avoid loading Django code unnecessarily from openstates.importers import ( JurisdictionImporter, BillImporter, VoteEventImporter, EventImporter, ) from openstates.data.models import Jurisdiction as DatabaseJurisdiction datadir = os.path.join(settings.SCRAPED_DATA_DIR, args.module) juris_importer = JurisdictionImporter(juris.jurisdiction_id) bill_importer = BillImporter(juris.jurisdiction_id) vote_event_importer = VoteEventImporter(juris.jurisdiction_id, bill_importer) event_importer = EventImporter(juris.jurisdiction_id, vote_event_importer) report = {} with transaction.atomic(): print("import jurisdictions...") report.update(juris_importer.import_directory(datadir)) print("import bills...") report.update(bill_importer.import_directory(datadir)) print("import vote events...") report.update(vote_event_importer.import_directory(datadir)) print("import events...") report.update(event_importer.import_directory(datadir)) DatabaseJurisdiction.objects.filter(id=juris.jurisdiction_id).update( latest_bill_update=datetime.datetime.utcnow()) # compile info on all sessions that were updated in this run seen_sessions = set() seen_sessions.update(bill_importer.get_seen_sessions()) seen_sessions.update(vote_event_importer.get_seen_sessions()) for session in seen_sessions: generate_session_report(session) return report
def test_bill_chamber_param(): create_jurisdiction() org = create_org() bill = ScrapeBill("HB 1", "1900", "Axe & Tack Tax Act", classification="tax bill", chamber="lower") BillImporter("jid").import_data([bill.as_dict()]) assert Bill.objects.get().from_organization_id == org.id
def test_fix_bill_id(): create_jurisdiction() create_org() bill = ScrapeBill("HB1", "1900", "Test Bill ID", classification="bill", chamber="lower") from openstates.settings import IMPORT_TRANSFORMERS IMPORT_TRANSFORMERS["bill"] = { "identifier": lambda x: re.sub(r"([A-Z]*)\s*0*([-\d]+)", r"\1 \2", x, 1) } bi = BillImporter("jid") bi.import_data([bill.as_dict()]) IMPORT_TRANSFORMERS["bill"] = {} b = Bill.objects.get() assert b.identifier == "HB 1"
def test_fix_bill_id(): create_jurisdiction() bill = ScrapeBill("HB 1", "1900", "Test Bill ID", classification="bill", chamber="lower") from openstates.settings import IMPORT_TRANSFORMERS IMPORT_TRANSFORMERS["bill"] = { "identifier": fix_bill_id, } bi = BillImporter("jid") bi.import_data([bill.as_dict()]) ve = ScrapeVoteEvent( legislative_session="1900", motion_text="passage", start_date="1900-04-02", classification="passage:bill", result="fail", bill_chamber="lower", bill="HB1", identifier="4", bill_action="passage", chamber="lower", ) VoteEventImporter("jid", bi).import_data([ve.as_dict()]) IMPORT_TRANSFORMERS["bill"] = {} ve = VoteEvent.objects.get() ve.bill.identifier == "HB 1"
def test_resolve_json_id(): create_jurisdiction() p1 = ScrapeBill("HB 1", "2020", "Title").as_dict() p2 = ScrapeBill("HB 1", "2020", "Title").as_dict() bi = BillImporter("jid") # do import and get database id p1_id = p1["_id"] p2_id = p2["_id"] bi.import_data([p1, p2]) db_id = Bill.objects.get().id # simplest case assert bi.resolve_json_id(p1_id) == db_id # duplicate should resolve to same id assert bi.resolve_json_id(p2_id) == db_id # a null id should map to None assert bi.resolve_json_id(None) is None # no such id with pytest.raises(UnresolvedIdError): bi.resolve_json_id("this-is-invalid")
def test_bill_action_extras(): create_jurisdiction() create_org() bill = ScrapeBill( "HB 1", "1900", "Axe & Tack Tax Act", classification="tax bill", chamber="lower" ) bill.add_action("sample", "1900-01-01", chamber="lower", extras={"test": 3}) oi = OrganizationImporter("jid") pi = PersonImporter("jid") BillImporter("jid", oi, pi).import_data([bill.as_dict()]) b = Bill.objects.get() assert b.actions.all()[0].extras == {"test": 3}
def test_locked_field_subitem(): create_jurisdiction() bill = ScrapeBill("HB 1", "2020", "Title") bill.add_source("https://example.com") bi = BillImporter("jid") bi.import_data([bill.as_dict()]) # lock the field b = Bill.objects.get() b.locked_fields = ["sources"] b.save() # reimport (without source) bill = ScrapeBill("HB 1", "2020", "Title") bi = BillImporter("jid") bi.import_data([bill.as_dict()]) b = Bill.objects.get() assert b.sources.count() == 1 assert b.locked_fields == ["sources"]
def test_bill_sponsor_limit_lookup(): create_jurisdiction() org = create_org() bill = ScrapeBill( "HB 1", "1900", "Axe & Tack Tax Act", classification="tax bill", chamber="lower" ) bill.add_sponsorship_by_identifier( name="SNODGRASS", classification="sponsor", entity_type="person", primary=True, identifier="TOTALLY_REAL_ID", scheme="TOTALLY_REAL_SCHEME", ) oi = OrganizationImporter("jid") pi = PersonImporter("jid") zs = ScrapePerson(name="Zadock Snodgrass", birth_date="1800-01-01") zs.add_identifier(identifier="TOTALLY_REAL_ID", scheme="TOTALLY_REAL_SCHEME") pi.import_data([zs.as_dict()]) za_db = Person.objects.get() Membership.objects.create(person_id=za_db.id, organization_id=org.id) zs2 = ScrapePerson(name="Zadock Snodgrass", birth_date="1900-01-01") zs2.add_identifier(identifier="TOTALLY_REAL_ID", scheme="TOTALLY_REAL_SCHEME") # This is contrived and perhaps broken, but we're going to check this. # We *really* don't want to *ever* cross jurisdiction bounds. PersonImporter("another-jurisdiction").import_data([zs.as_dict()]) BillImporter("jid", oi, pi).import_data([bill.as_dict()]) obj = Bill.objects.get() (entry,) = obj.sponsorships.all() assert entry.person.name == "Zadock Snodgrass" assert entry.person.birth_date == "1800-01-01"
def test_vote_event_bill_actions_errors(): j = create_jurisdiction() j.legislative_sessions.create(name="1900", identifier="1900") org1 = ScrapeOrganization(name="House", classification="lower") org2 = ScrapeOrganization(name="Senate", classification="upper") bill = ScrapeBill("HB 1", "1900", "Axe & Tack Tax Act", from_organization=org1._id) # for this bill, two identical actions, so vote matching will fail bill.add_action(description="passage", date="1900-04-01", chamber="lower") bill.add_action(description="passage", date="1900-04-01", chamber="lower") # this action is good, but two votes will try to match it bill.add_action(description="passage", date="1900-04-02", chamber="lower") # will match two actions ve1 = ScrapeVoteEvent( legislative_session="1900", motion_text="passage", start_date="1900-04-01", classification="passage:bill", result="pass", bill_chamber="lower", bill="HB 1", identifier="1", bill_action="passage", organization=org1._id, ) # will match no actions ve2 = ScrapeVoteEvent( legislative_session="1900", motion_text="passage", start_date="1900-04-01", classification="passage:bill", result="pass", bill_chamber="lower", bill="HB 1", identifier="2", bill_action="committee result", organization=org1._id, ) # these two votes will both match the same action ve3 = ScrapeVoteEvent( legislative_session="1900", motion_text="passage", start_date="1900-04-02", classification="passage:bill", result="pass", bill_chamber="lower", bill="HB 1", identifier="3", bill_action="passage", organization=org1._id, ) ve4 = ScrapeVoteEvent( legislative_session="1900", motion_text="passage-syz", start_date="1900-04-02", classification="passage:bill", result="fail", bill_chamber="lower", bill="HB 1", identifier="4", bill_action="passage", organization=org1._id, ) oi = OrganizationImporter("jid") oi.import_data([org1.as_dict(), org2.as_dict()]) bi = BillImporter("jid", oi, DumbMockImporter()) bi.import_data([bill.as_dict()]) VoteEventImporter("jid", DumbMockImporter(), oi, bi).import_data( [ve1.as_dict(), ve2.as_dict(), ve3.as_dict(), ve4.as_dict()]) bill = Bill.objects.get() votes = list(VoteEvent.objects.all().order_by("identifier")) # isn't matched, was ambiguous across two actions assert votes[0].bill_action is None # isn't matched, no match in actions assert votes[1].bill_action is None # these both try to match the same action, only first will succeed assert votes[2].bill_action is not None assert votes[3].bill_action is None