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
Example #2
0
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
Example #4
0
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")
Example #5
0
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
Example #11
0
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"
Example #12
0
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")
Example #13
0
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])
Example #15
0
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
Example #16
0
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"
Example #20
0
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()])
Example #22
0
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"
Example #30
0
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