def test_extraneous_word_token_before_api_token(self): extraneous_word_token = "Token " + TOKEN client = Client(api_token=extraneous_word_token, api_root=API_ROOT) s102 = client.fetch(query="/test/acts/47/1") assert s102["start_date"] == "1935-04-01" assert s102["end_date"] is None assert s102["heading"] == "Short title"
def test_client() -> Client: client = Client(api_token=TOKEN, api_root=API_ROOT) client.coverage["/us/usc"] = { "latest_heading": "United States Code (USC)", "first_published": datetime.date(1926, 6, 30), "earliest_in_db": datetime.date(2013, 7, 18), "latest_in_db": datetime.date(2020, 8, 8), } client.coverage["/test/acts"] = { "latest_heading": "Test Acts", "first_published": datetime.date(1935, 4, 1), "earliest_in_db": datetime.date(1935, 4, 1), "latest_in_db": datetime.date(2013, 7, 18), } return client
class TestLinkedEnactment: client = Client(api_token=TOKEN, api_root=API_ROOT) @pytest.mark.vcr def test_text_sequence_for_linked_enactment(self, test_client): enactment = test_client.read(query="/test", date="2020-01-01") assert "for documentation." in enactment.text_sequence()[0].text enactment.select("for documentation.") assert enactment.selected_text() == "…for documentation." def test_linked_enactment_without_children(self): enactment = LinkedEnactment( node="/test/golden", heading="The Golden Rule", content="Do unto others as you would have them do to you.", selection="Do unto others", start_date=date(1, 1, 1), ) assert enactment.children == [] assert enactment.selected_text() == "Do unto others…" def test_error_blank_content(self): with pytest.raises(ValueError): LinkedEnactment( node="/test/unwritten", heading="The Unwritten Rule", textversion=TextVersion(content=""), start_date=date(2001, 1, 1), )
class TestLoadCrossReference: client = Client(api_token=TOKEN, api_root=API_ROOT) def test_load_citation(self, citation_to_6c): schema = CrossReferenceSchema() result = schema.load(citation_to_6c) assert result.target_uri == "/test/acts/47/6C" assert ( str(result) == 'CrossReference(target_uri="/test/acts/47/6C", reference_text="Section 6C")' )
class TestDump: client = Client(api_token=TOKEN) def test_dump_json(self, fake_beard_client): provision = fake_beard_client.read_from_json( {"node": "/test/acts/47/6A"}) dumped_provision = provision.json() assert '"node": "/test/acts/47/6A"' in dumped_provision @pytest.mark.vcr def test_round_trip_dict(self, fake_beard_client): provision = fake_beard_client.read_from_json( {"node": "/test/acts/47/6A"}) dumped_provision = provision.dict() new = Enactment(**dumped_provision) assert new.node == "/test/acts/47/6A"
class TestLoadLinkedEnactment: client = Client(api_token=TOKEN, api_root=API_ROOT) def test_load_linked_enactment(self): schema = LinkedEnactmentSchema() data = { "type": "Enactment", "children": [ "https://authorityspoke.com/api/v1/us/const/", "https://authorityspoke.com/api/v1/us/usc/", ], "content": "", "end_date": None, "heading": "United States Legislation", "node": "/us", "parent": None, "start_date": "1776-07-04", "url": "https://authorityspoke.com/api/v1/us/const/", } result = schema.load(data) assert result.children[ 0] == "https://authorityspoke.com/api/v1/us/const/" @pytest.mark.vcr def test_text_sequence_for_linked_enactment(self, test_client): schema = LinkedEnactmentSchema() enactment = test_client.read(query="/test", date="2020-01-01") assert "for documentation." in enactment.text_sequence()[0].text assert "for documentation." in enactment.selected_text() enactment.select("for documentation.") assert enactment.selected_text() == "…for documentation." dumped = schema.dump(enactment) loaded = schema.load(dumped) assert loaded.selected_text() == "…for documentation."
class TestTextSelection: client = Client(api_token=TOKEN) def test_code_from_selector(self, fake_usc_client): enactment = fake_usc_client.read("/us/usc/t17/s103") assert enactment.code == "usc" def test_usc_selection(self, make_selector, fake_usc_client): enactment = fake_usc_client.read("/us/usc/t17/s103") selector = make_selector["preexisting material"] enactment.select(selector) assert enactment.level == CodeLevel.STATUTE assert enactment.jurisdiction == "us" assert enactment.code == "usc" def test_omit_terminal_slash(self, fake_usc_client): statute = fake_usc_client.read_from_json({ "exact": "process, system,", "node": "us/usc/t17/s102/b/" }) assert not statute.node.endswith("/") def test_add_omitted_initial_slash(self, fake_usc_client): statute = fake_usc_client.read_from_json({ "exact": "process, system,", "node": "us/usc/t17/s102/b/" }) assert statute.node.startswith("/") def test_whitespace_when_selecting_with_suffix(self, e_copyright): """Overwrite existing selector and test for trailing whitespace.""" copyright_selector = TextQuoteSelector(suffix="idea, procedure,") e_copyright.select(copyright_selector) assert e_copyright.selected_text() == ( "In no case does copyright protection " + "for an original work of authorship extend to any…") def test_section_text_from_path(self, fake_usc_client): copyright_exceptions = fake_usc_client.read_from_json( {"node": "/us/usc/t17/s102/b"}) assert copyright_exceptions.text.startswith( "In no case does copyright protection " + "for an original work of authorship extend to any") def test_exact_text_not_in_selection(self, fake_usc_client): passage = fake_usc_client.read_from_json({ "node": "/us/const/amendment/XV/1", }) selector = TextQuoteSelector(exact="due process") with pytest.raises(TextSelectionError): passage.select(selector) def test_multiple_non_Factor_selectors_for_Holding(self): """ The Holding-level TextQuoteSelectors should be built from this: "text": [ "Census data therefore do not|trigger|copyright", "|may|possess the requisite originality" ] """ client = FakeClient.from_file("usc.json") holdings = loaders.read_anchored_holdings_from_file( "holding_feist.yaml", client=client) assert len(holdings.holdings[6].anchors.quotes) == 2
class TestCodes: client = Client(api_token=TOKEN) def test_cfr_repr(self): oracle_dictionary = loaders.load_holdings("holding_oracle.yaml") regulation = oracle_dictionary[10]["enactments_despite"][1] enactment = EnactmentPassage(**regulation) assert enactment.level == CodeLevel.REGULATION assert "/cfr/" in repr(enactment) @pytest.mark.vcr @pytest.mark.default_cassette("test_us_code_title.yaml") def test_us_code_title(self): enactment = self.client.read("/us/usc") assert enactment.heading.startswith("United States Code") assert enactment.level == CodeLevel.STATUTE @pytest.mark.vcr @pytest.mark.default_cassette("test_const_code_title.yaml") def test_const_code_title(self): enactment = self.client.read("/us/const") assert enactment.heading.startswith("United States Constitution") assert enactment.level == CodeLevel.CONSTITUTION @pytest.mark.vcr @pytest.mark.default_cassette("test_acts_code_title.yaml") def test_acts_code_title(self): enactment = self.client.read("/test/acts") assert enactment.heading.startswith("Acts of Australia") assert enactment.level == CodeLevel.STATUTE def test_code_select_text(self, fake_beard_client): enactment = fake_beard_client.read("/test/acts/47/1") assert enactment.text.startswith("This Act may be cited") def test_code_select_text_chapeau(self, fake_beard_client): enactment = fake_beard_client.read("/test/acts/47/4") passage = enactment.select() assert passage.selected_text().startswith("In this Act, beard means") def test_get_bill_of_rights_effective_date(self, fake_usc_client): enactment = fake_usc_client.read("/us/const/amendment/V") assert enactment.start_date == datetime.date(1791, 12, 15) def test_text_interval_constitution_section(self, fake_usc_client): enactment = fake_usc_client.read("/us/const/article/I/8/8") passage = enactment.select() # The entire 317-character section is selected. ranges = passage.selection.ranges() assert ranges[0].start == 0 assert ranges[0].end == 172 passage.select(TextPositionSelector(start=68, end=81)) assert passage.selected_text() == "…limited Times…" def test_text_interval_beyond_end_of_section(self, fake_usc_client): """No longer raises an error, just selects to the end of the text.""" enactment = fake_usc_client.read("/us/const/article/I/8/8") selector = TextPositionSelector(start=68, end=400) passage = enactment.select(selector) assert passage.selected_text().startswith("…limited Times") assert passage.selected_text().endswith(enactment.text[-10:]) def test_bad_section(self, fake_usc_client): """ The path is a section that doesn't exist in USC. """ with pytest.raises(LegislicePathError): enactment = fake_usc_client.read("/us/usc/article/I/3/7") def test_text_interval_bad_selector(self, make_selector, make_response): client = FakeClient(responses=make_response) enactment = client.read("/us/const/amendment/IV") with pytest.raises(TextSelectionError): _ = enactment.convert_selection_to_set( make_selector["bad_selector"])
class TestLoadRules: """ Tests loading Rules, possibly for linking to legislation without reference to any Opinion or Holding. """ client = Client(api_token=TOKEN) def test_loading_rules(self, fake_beard_client): beard_rules = loaders.read_holdings_from_file("beard_rules.yaml", client=fake_beard_client) assert (beard_rules[0].outputs[0].predicate.content == "${the_suspected_beard} was a beard") def test_imported_rule_is_type_rule(self, fake_beard_client): beard_rules = loaders.read_holdings_from_file("beard_rules.yaml", client=fake_beard_client) assert isinstance(beard_rules[0].rule, Rule) def test_rule_short_string(self, fake_beard_client): beard_rules = loaders.read_holdings_from_file("beard_rules.yaml", client=fake_beard_client) assert beard_rules[0].rule.short_string.lower().startswith("the rule") def test_index_names_from_sibling_inputs(self): raw_rules = loaders.load_holdings("beard_rules.yaml") indexed_rules, mentioned = name_index.index_names( raw_rules[0]["inputs"]) key = "the suspected beard occurred on or below the chin" assert mentioned[key]["terms"][0] == "the suspected beard" def test_rule_with_exhibit_as_context_factor(self, fake_beard_client): rules = loaders.read_holdings_from_file("beard_rules.yaml", client=fake_beard_client) exhibit = rules[5].inputs[0].terms[2] assert isinstance(exhibit, Exhibit) def test_read_rules_without_regime(self, fake_beard_client): beard_rules = loaders.read_holdings_from_file("beard_rules.yaml", client=fake_beard_client) assert beard_rules[0].inputs[0].short_string == ( "the fact that <the suspected beard> was facial hair") def test_correct_context_after_loading_rules(self, fake_beard_client): beard_rules = loaders.read_holdings_from_file("beard_rules.yaml", client=fake_beard_client) elements_of_offense = beard_rules[11] assert len(elements_of_offense.despite) == 1 assert (elements_of_offense.despite[0].generic_terms()[0].name == "the Department of Beards") def test_load_any_enactments(self, fake_beard_client): """Test bug where holding's enactment's aren't loaded.""" beard_dictionary = loaders.load_holdings("beard_rules.yaml") shorter = [beard_dictionary[0]] beard_rules = readers.read_holdings(shorter, client=fake_beard_client) expected = "facial hair no shorter than 5 millimetres" assert expected in beard_rules[0].enactments[0].selected_text() @pytest.mark.vcr def test_generic_terms_after_adding_rules(self, fake_beard_client): beard_dictionary = loaders.load_holdings("beard_rules.yaml") beard_rules = readers.read_holdings(beard_dictionary, client=fake_beard_client) loan_is_transfer = beard_rules[7] elements_of_offense = beard_rules[11] loan_without_exceptions = (loan_is_transfer + elements_of_offense.inputs[1] + elements_of_offense.inputs[2] + elements_of_offense.enactments[1]) loan_establishes_offense = loan_without_exceptions + elements_of_offense assert str(loan_establishes_offense.outputs[0]) == ( "the fact that <the defendant> committed the offense of improper " "transfer of beardcoin") assert len(loan_establishes_offense.despite) == 1 assert (loan_establishes_offense.despite[0].generic_terms()[0].name == "the Department of Beards")
def test_no_api_token(self): bad_client = Client() with pytest.raises(LegisliceTokenError): bad_client.fetch(query="/test/acts/47/1")
class TestDownloadJSON: client = Client(api_token=TOKEN, api_root=API_ROOT) @pytest.mark.vcr() def test_fetch_section(self, test_client): url = self.client.url_from_enactment_path("/test/acts/47/1") response = self.client._fetch_from_url(url=url) # Test that there was no redirect from the API assert not response.history section = response.json() assert section["start_date"] == "1935-04-01" assert section["end_date"] is None assert section["heading"] == "Short title" def test_download_from_wrong_domain_raises_error(self, test_client): url = self.client.url_from_enactment_path("/test/acts/47/1") wrong_url = url.replace("authorityspoke.com", "pythonforlaw.com") with pytest.raises(ValueError): self.client._fetch_from_url(url=wrong_url) @pytest.mark.vcr() def test_fetch_current_section_with_date(self, test_client): url = self.client.url_from_enactment_path("/test/acts/47/6D", date=datetime.date( 2020, 1, 1)) response = self.client._fetch_from_url(url=url) # Test that there was no redirect from the API assert not response.history waiver = response.json() assert waiver["url"].endswith("acts/47/6D@2020-01-01/") assert waiver["children"][0]["start_date"] == "2013-07-18" @pytest.mark.vcr() def test_wrong_api_token(self): bad_client = Client(api_token="wr0ngToken") with pytest.raises(LegisliceTokenError): bad_client.fetch(query="/test/acts/47/1") @pytest.mark.vcr() def test_no_api_token(self): bad_client = Client() with pytest.raises(LegisliceTokenError): bad_client.fetch(query="/test/acts/47/1") @pytest.mark.vcr() def test_extraneous_word_token_before_api_token(self): extraneous_word_token = "Token " + TOKEN client = Client(api_token=extraneous_word_token, api_root=API_ROOT) s102 = client.fetch(query="/test/acts/47/1") assert s102["start_date"] == "1935-04-01" assert s102["end_date"] is None assert s102["heading"] == "Short title" @pytest.mark.vcr() def test_fetch_past_section_with_date(self, test_client): waiver = test_client.fetch(query="/test/acts/47/6D", date=datetime.date(1940, 1, 1)) assert waiver["url"].endswith("acts/47/6D@1940-01-01/") assert waiver["children"][0]["start_date"] == "1935-04-01" @pytest.mark.vcr() def test_fetch_cross_reference_to_old_version(self, test_client): """Test that statute can be fetched with a post-enactment date it was in effect.""" reference = CrossReference( target_uri="/test/acts/47/8", target_url= "https://authorityspoke.com/api/v1/test/acts/47/8@1935-04-01/", reference_text="section 8", ) enactment = test_client.fetch_cross_reference(query=reference, date=datetime.date( 1950, 1, 1)) assert enactment["start_date"] == "1935-04-01" assert enactment["url"].endswith("@1950-01-01/") @pytest.mark.vcr() def test_omit_terminal_slash(self, test_client): statute = test_client.fetch(query="us/usc/t17/s102/b/") assert not statute["node"].endswith("/") @pytest.mark.vcr() def test_add_omitted_initial_slash(self, test_client): statute = test_client.fetch(query="us/usc/t17/s102/b/") assert statute["node"].startswith("/")
class TestTextAnchors: client = Client(api_token=TOKEN) def test_read_holding_with_no_anchor(self, make_analysis): raw_analysis = make_analysis["no anchors"] reading = OpinionReading() anchored_holdings = readers.read_holdings_with_anchors(raw_analysis) reading.posit( holdings=anchored_holdings.holdings, named_anchors=anchored_holdings.named_anchors, enactment_anchors=anchored_holdings.enactment_anchors, ) assert not reading.holding_anchors[0].positions assert not reading.holding_anchors[0].quotes def test_holding_without_enactments_or_regime(self, raw_holding): expanded = text_expansion.expand_shorthand( raw_holding["bradley_house"]) built = readers.read_holdings([expanded]) new_factor = built[0].outputs[0].to_effect.terms[0] assert new_factor.name == "Bradley" def test_posit_one_holding_with_anchor(self, raw_holding, make_response): mock_client = FakeClient(responses=make_response) holdings = readers.read_holdings([raw_holding["bradley_house"]], client=mock_client) reading = OpinionReading() reading.posit_holding( holdings[0], holding_anchors=TextQuoteSelector( exact="some text supporting this holding"), ) assert (reading.anchored_holdings.holdings[-1].anchors.quotes[0].exact == "some text supporting this holding") def test_mentioned_context_changing(self): """ The "mentioned" context should not change while data is being loaded with the schema. This is to test that the "content" field of a value in the "mentioned" dict isn't changed to replace the name of a Factor with bracketed text. """ holdings = [ { "inputs": { "type": "fact", "content": "{Bradley} lived at Bradley's house", }, "outputs": { "type": "evidence", "exhibit": { "offered_by": { "type": "entity", "name": "the People" } }, "to_effect": { "type": "fact", "name": "fact that Bradley committed a crime", "content": "Bradley committed a crime", }, "name": "evidence of Bradley's guilt", "absent": True, }, }, { "inputs": "fact that Bradley committed a crime", "outputs": { "type": "fact", "content": "Bradley committed a tort" }, }, ] expanded = text_expansion.expand_shorthand(holdings) built = readers.read_holdings(expanded) new_factor = built[0].outputs[0].to_effect.terms[0] assert new_factor.name == "Bradley" def test_holdings_with_allegation_and_exhibit(self): """ Testing the error message: The number of items in 'terms' must be 1, to match predicate.context_slots for '{} committed an attempted robbery' for 'fact that defendant committed an attempted robbery' This was another bug involving mutation of the "mentioned" context object during deserialization. Fixed by having FactSchema.get_references_from_mentioned call add_found_context with deepcopy(obj) instead of obj for the "factor" parameter """ holdings = [ { "inputs": [ { "type": "Exhibit", "name": "officer's testimony that defendant was addicted to heroin", "form": "testimony", "offered_by": { "type": "Entity", "name": "The People of California", }, "statement": { "type": "Fact", "name": "fact that defendant was addicted to heroin", "content": "the {defendant} was addicted to heroin", }, "statement_attribution": { "type": "entity", "name": "parole officer", }, }, { "type": "Allegation", "name": "the attempted robbery charge", "pleading": { "type": "Pleading", "filer": { "type": "Entity", "name": "The People of California", }, }, "fact": { "type": "Fact", "name": "fact that defendant committed an attempted robbery", "content": "defendant committed an attempted robbery", }, }, ], "despite": [{ "type": "Fact", "content": "officer's testimony that defendant was addicted to heroin, was relevant to show the defendant had a motive to commit an attempted robbery", }], "outputs": [{ "type": "Fact", "content": "the probative value of officer's testimony that defendant was addicted to heroin, in indicating fact that defendant committed an attempted robbery, was outweighed by unfair prejudice to defendant", }], "mandatory": True, }, { "inputs": [{ "type": "Fact", "content": "the probative value of officer's testimony that defendant was addicted to heroin, in indicating fact that defendant committed an attempted robbery, was outweighed by unfair prejudice to defendant", }], "despite": [{ "type": "Fact", "content": "officer's testimony that defendant was addicted to heroin was relevant to show defendant had a motive to commit an attempted robbery", }], "outputs": [{ "type": "Evidence", "name": "evidence of officer's testimony that defendant was addicted to heroin", "exhibit": "officer's testimony that defendant was addicted to heroin", "to_effect": "fact that defendant committed an attempted robbery", "absent": True, }], "mandatory": True, }, ] expanded = text_expansion.expand_shorthand(holdings) built = readers.read_holdings(expanded) allegation = built[0].inputs[1] assert allegation.fact.terms[0].name == "defendant" def test_select_enactment_text_by_default(self, make_response): mock_client = FakeClient(responses=make_response) holding_dict = { "outputs": [{ "type": "fact", "content": "the Lotus menu command hierarchy was copyrightable", }], "enactments": { "enactment": { "node": "/us/usc/t17/s410/c" } }, } holding = readers.read_holdings([holding_dict], client=mock_client) assert holding[0].enactments[0].selected_text().startswith( "In any judicial") def test_enactment_has_subsection(self, make_response): mock_client = FakeClient(responses=make_response) to_read = load_holdings("holding_lotus.yaml") holdings = readers.read_holdings(to_read, client=mock_client) assert holdings[8].enactments[0].node.split("/")[-1] == "b" def test_enactment_text_limited_to_subsection(self, make_response): mock_client = FakeClient(responses=make_response) to_read = load_holdings("holding_lotus.yaml") holdings = readers.read_holdings(to_read, client=mock_client) assert "architectural works" not in str(holdings[8].enactments[0]) @pytest.mark.xfail def test_imported_holding_same_as_test_object(self, real_holding, make_opinion): """ These objects were once the same, but now the JSON treats "lived at" at "operated" as separate Factors. """ watt = make_opinion["watt_majority"] watt.posit(load_holdings("holding_watt.yaml")) assert watt.holdings[0] == real_holding["h1"] def test_same_enactment_objects_equal(self, make_response): """ Don't expect the holdings imported from the JSON to exactly match the holdings created for testing in conftest. """ mock_client = FakeClient(responses=make_response) to_read = load_holdings("holding_watt.yaml") holdings = readers.read_holdings(to_read, client=mock_client) assert holdings[0].enactments[0].means(holdings[1].enactments[0]) def test_same_enactment_in_two_opinions(self, make_response): mock_client = FakeClient(responses=make_response) to_read = load_holdings("holding_brad.yaml") brad_holdings = readers.read_holdings(to_read, client=mock_client) to_read = load_holdings("holding_watt.yaml") watt_holdings = readers.read_holdings(to_read, client=mock_client) assert any(watt_holdings[0].enactments[0].means(brad_enactment) for brad_enactment in brad_holdings[0].enactments) def test_same_object_for_enactment_in_import(self, make_response): """ The JSON for Bradley repeats identical fields to create the same Factor for multiple Rules, instead of using the "name" field as a shortcut. This tests whether the loaded objects turn out equal. """ mock_client = FakeClient(responses=make_response) to_read = load_holdings("holding_brad.yaml") holdings = readers.read_holdings(to_read, client=mock_client) assert any(holdings[6].inputs[0].means(x) for x in holdings[5].inputs) def test_fact_from_loaded_holding(self, make_response): to_read = load_holdings("holding_watt.yaml") mock_client = FakeClient(responses=make_response) holdings = readers.read_holdings(to_read, client=mock_client) new_fact = holdings[0].inputs[1] assert "lived at <Hideaway Lodge>" in str(new_fact) assert isinstance(new_fact.terms[0], Entity) def test_fact_with_quantity(self, make_response): to_read = load_holdings("holding_watt.yaml") mock_client = FakeClient(responses=make_response) holdings = readers.read_holdings(to_read, client=mock_client) new_fact = holdings[1].inputs[3] assert "was no more than 35 foot" in str(new_fact) def test_use_int_not_pint_without_dimension(self, make_response): mock_client = FakeClient(responses=make_response) to_read = load_holdings("holding_brad.yaml") loaded_holdings = readers.read_holdings(to_read, client=mock_client) anchored_holdings = AnchoredHoldings(holdings=[ HoldingWithAnchors(holding=item) for item in loaded_holdings ]) reading = OpinionReading(anchored_holdings=anchored_holdings) expectation_not_reasonable = list(reading.holdings)[6] assert "dimensionless" not in str(expectation_not_reasonable) assert expectation_not_reasonable.inputs[0].predicate.quantity == 3 def test_opinion_posits_holding(self, make_response): mock_client = FakeClient(responses=make_response) to_read = load_holdings("holding_brad.yaml") holdings = readers.read_holdings(to_read, client=mock_client) reading = OpinionReading() reading.posit(holdings[0]) assert "warrantless search and seizure" in reading.holdings[ 0].short_string def test_opinion_posits_holding_tuple_context(self, make_entity, make_response): """ Having the Watt case posit a holding from the Brad case, but with generic factors from Watt. """ mock_client = FakeClient(responses=make_response) to_read = load_holdings("holding_brad.yaml") brad_holdings = readers.read_holdings(to_read, client=mock_client) context_holding = brad_holdings[6].new_context( [make_entity["watt"], make_entity["trees"], make_entity["motel"]]) reading = OpinionReading() reading.posit(context_holding) holding_string = reading.holdings[-1].short_string assert ( "the number of marijuana plants in <the stockpile of trees> was at least 3" in holding_string) def test_opinion_posits_holding_dict_context(self, make_entity, make_response): """ Having the Watt case posit a holding from the Brad case, but replacing one generic factor with a factor from Watt. """ mock_client = FakeClient(responses=make_response) to_read = load_holdings("holding_brad.yaml") holdings = readers.read_holdings(to_read, client=mock_client) breading = OpinionReading() breading.clear_holdings() breading.posit(holdings) expectation_not_reasonable = breading.holdings[6] changes = ContextRegister() changes.insert_pair( key=expectation_not_reasonable.generic_terms()[0], value=make_entity["watt"], ) context_holding = expectation_not_reasonable.new_context(changes) wreading = OpinionReading() wreading.clear_holdings() wreading.posit(context_holding) string = str(context_holding) assert "<Wattenburg> lived at <Bradley's house>" in string assert "<Wattenburg> lived at <Bradley's house>" in str( wreading.holdings[-1]) def test_holding_with_non_generic_value(self, make_entity, make_response): """ This test originally required a ValueError, but why should it? """ mock_client = FakeClient(responses=make_response) reading = OpinionReading() to_read = load_holdings("holding_brad.yaml") holdings = readers.read_holdings(to_read, client=mock_client) reading.posit(holdings) expectation_not_reasonable = reading.holdings[6] generic_patch = expectation_not_reasonable.generic_terms()[1] changes = ContextRegister() changes.insert_pair(generic_patch, make_entity["trees_specific"]) context_change = expectation_not_reasonable.new_context(changes) string = context_change.short_string assert "plants in the stockpile of trees was at least 3" in string def test_error_because_string_does_not_match_factor_name( self, make_response): rule_holding = { "inputs": ["this factor hasn't been mentioned"], "outputs": [{ "type": "fact", "content": "{the dog} bit {the man}" }], "enactments": [{ "enactment": { "node": "/us/const/amendment/IV" } }], "mandatory": True, } mock_client = FakeClient(responses=make_response) with pytest.raises(ValidationError): readers.read_holdings([rule_holding], client=mock_client) def test_error_classname_does_not_exist(self): rule_dict = { "inputs": [{ "type": "RidiculousFakeClassName", "content": "officers' search of the yard was a warrantless search and seizure", }], "outputs": [{ "type": "fact", "content": "the dog bit the man" }], } with pytest.raises(ValidationError): readers.read_holdings([rule_dict]) def test_repeating_read_holdings_has_same_result(self, make_analysis): raw = make_analysis["minimal"] holdings = readers.read_holdings_with_anchors(raw).holdings holdings_again = readers.read_holdings_with_anchors(raw).holdings assert all( left.holding.means(right.holding) for left, right in zip(holdings, holdings_again)) def test_posit_holding_with_selector(self, make_analysis, make_opinion): anchored_holdings = readers.read_holdings_with_anchors( make_analysis["minimal"]) brad = make_opinion["brad_majority"] reading = OpinionReading(opinion_type="majority", opinion_author=brad.author) reading.posit(anchored_holdings.holdings) assert reading.holding_anchors[0].quotes[ 0].exact == "open fields or grounds"
class TestHoldingImport: client = Client(api_token=TOKEN) def test_import_some_holdings(self): """ Now generates 10, instead of 12, because the "exclusive" Holding is stored with that flag instead of generating Holdings that it implies. """ lotus_holdings = load_holdings("holding_lotus.yaml") assert len(lotus_holdings) == 10 def test_import_enactments_and_anchors(self, make_opinion_with_holding, make_response): """ Testing issue that caused enactment expansion to fail only when text anchors were loaded. """ raw_holdings = [ { "inputs": { "type": "fact", "content": "{Rural's telephone directory} was a fact", "name": "Rural's telephone directory was a fact", "anchors": { "quotes": [ { "exact": "facts", "prefix": "The first is that" }, { "exact": "as to facts", "prefix": "No one may claim originality", }, { "exact": "facts", "prefix": "no one may copyright" }, ] }, }, "outputs": { "type": "fact", "content": "Rural's telephone directory was copyrightable", "truth": False, "anchors": { "quotes": [ { "exact": "copyrightable", "prefix": "first is that facts are not", }, "The sine qua non of|copyright|", { "exact": "no one may copyright", "suffix": "facts" }, ] }, }, "enactments": [ { "name": "securing for authors", "enactment": { "node": "/us/const/article/I/8/8", "exact": ("To promote the Progress of Science and useful Arts, " "by securing for limited Times to Authors"), }, }, { "name": "right to writings", "enactment": { "node": "/us/const/article/I/8/8", "exact": "the exclusive Right to their respective Writings", }, }, ], "mandatory": True, "universal": True, }, { "outputs": { "type": "fact", "content": "Rural's telephone directory was copyrightable", }, "enactments": ["securing for authors", "right to writings"], "mandatory": True, "anchors": { "quotes": ["compilations of facts|generally are|"] }, }, ] mock_client = FakeClient(responses=make_response) f_anchored_holdings = readers.read_holdings_with_anchors( record=raw_holdings, client=mock_client) feist = make_opinion_with_holding["feist_majority"] feist.clear_holdings() feist.posit( f_anchored_holdings.holdings, named_anchors=f_anchored_holdings.named_anchors, enactment_anchors=f_anchored_holdings.enactment_anchors, ) assert feist.holdings[0].enactments[ 0].node == "/us/const/article/I/8/8" assert feist.holdings[1].enactments[ 0].node == "/us/const/article/I/8/8" def test_read_holdings_and_then_get_anchors(self, make_response): """ Test whether read_holdings mutates raw_holding and makes it impossible to get text anchors. """ mock_client = FakeClient(responses=make_response) raw_holdings = load_holdings("holding_oracle.yaml") loaded = readers.read_holdings_with_anchors(raw_holdings, client=mock_client) assert isinstance(loaded.holdings[0], HoldingWithAnchors) assert isinstance(loaded.named_anchors[1].anchors.quotes[0], TextQuoteSelector) def test_load_and_posit_holdings_with_anchors(self, make_response): """ Test that Opinion.posit can take a HoldingsIndexed as the only argument. Trying to combine several tasks that normally happen together, into a single command. """ mock_client = FakeClient(responses=make_response) oracle_holdings_with_anchors = loaders.read_anchored_holdings_from_file( "holding_oracle.yaml", client=mock_client) reading = OpinionReading() reading.posit(oracle_holdings_with_anchors) assert len(reading.holdings) == 20 def test_decision_posits_holdings_with_anchors(self, make_response): mock_client = FakeClient(responses=make_response) oracle_holdings_with_anchors = loaders.read_anchored_holdings_from_file( "holding_oracle.yaml", client=mock_client) reading = DecisionReading(decision=Decision( decision_date=date(2019, 1, 1))) reading.posit(oracle_holdings_with_anchors) assert len(reading.holdings) == 20 def test_pass_holdings_to_decision_reading_constructor( self, make_decision, make_response): mock_client = FakeClient(responses=make_response) oracle = make_decision["oracle"] oracle_holdings = read_holdings_from_file("holding_oracle.yaml", client=mock_client) oracle_reading = DecisionReading(decision=oracle) oracle_reading.posit(oracle_holdings) assert (oracle_reading.opinion_readings[0].holdings[0].enactments[0]. node == "/us/usc/t17/s102/a")
class TestLoadEnactment: client = Client(api_token=TOKEN, api_root=API_ROOT) def test_load_nested_enactment(self, section6d): schema = EnactmentSchema() result = schema.load(section6d) assert result.heading.startswith("Waiver") def test_enactment_with_nested_selectors(self, section_11_subdivided): schema = ExpandableEnactmentSchema() section_11_subdivided["selection"] = [{"start": 0}] for child in section_11_subdivided["children"]: child["selection"] = [] section_11_subdivided["children"][1]["selection"] = [{ "start": 0, "end": 12 }] result = schema.load(section_11_subdivided) answer = "The Department of Beards may issue licenses to such…hairdressers…" assert result.selected_text() == answer def test_enactment_with_True_as_selector(self, section_11_subdivided): schema = ExpandableEnactmentSchema() section_11_subdivided["selection"] = True section_11_subdivided["children"][1]["selection"] = [{ "start": 0, "end": 12 }] result = schema.load(section_11_subdivided) answer = "The Department of Beards may issue licenses to such…hairdressers…" assert result.selected_text() == answer def test_enactment_with_False_as_selector(self, section_11_subdivided): schema = ExpandableEnactmentSchema() section_11_subdivided["selection"] = False section_11_subdivided["children"][1]["selection"] = [{ "start": 0, "end": 12 }] result = schema.load(section_11_subdivided) answer = "…hairdressers…" assert result.selected_text() == answer def test_selector_not_wrapped_in_list(self, section_11_together): schema = ExpandableEnactmentSchema() section_11_together["selection"] = {"start": 4, "end": 24} result = schema.load(section_11_together) assert result.selected_text() == "…Department of Beards…" def test_load_with_text_quote_selector(self, section_11_together): schema = ExpandableEnactmentSchema() section_11_together["selection"] = [{"exact": "Department of Beards"}] result = schema.load(section_11_together) assert result.selected_text() == "…Department of Beards…" @pytest.mark.vcr() def test_load_enactment_with_text_anchor(self, provision_with_text_anchor, test_client): schema = ExpandableEnactmentSchema() record = test_client.update_enactment_from_api( provision_with_text_anchor) result = schema.load(record) assert result.anchors[0].exact == "17 U.S.C. § 102(a)" def test_enactment_does_not_fail_for_excess_selector( self, section_11_subdivided): """Test selector that extends into the text of a subnode.""" exact = "The Department of Beards may issue licenses to such barbers" section_11_subdivided["exact"] = exact schema = ExpandableEnactmentSchema(many=False) enactment = schema.load(section_11_subdivided) assert enactment.selected_text() == exact + "…" def test_load_enactment_missing_textversion_field( self, fourth_a_no_text_version): schema = ExpandableEnactmentSchema(many=False) enactment = schema.load(fourth_a_no_text_version) assert enactment.text.startswith("The right of the people") def test_node_field_needed_to_load_enactment(self): barbers_without_node = { "heading": "", "content": "barbers,", "children": [], "end_date": None, "start_date": "2013-07-18", "url": "https://authorityspoke.com/api/v1/test/acts/47/11/i@2020-01-01", } with pytest.raises(ValueError): _ = enactment_needs_api_update(barbers_without_node) def test_nest_selector_fields_before_loading(self, test_client, fourth_a): fourth_a["selection"] = [{"start": 10, "end": 20}] fourth_a["suffix"] = ", and no Warrants shall issue" schema = ExpandableEnactmentSchema() updated = schema.move_selector_fields(fourth_a) assert updated["selection"][1][ "suffix"] == ", and no Warrants shall issue" def test_load_enactment_with_cross_reference(self): data = { "heading": "", "content": "The Department of Beards shall waive the collection of beard tax upon issuance of beardcoin under Section 6C where the reason the maintainer wears a beard is due to bona fide religious, cultural, or medical reasons.", "start_date": "2013-07-18", "node": "/test/acts/47/6D/1", "children": [], "end_date": None, "url": "http://127.0.0.1:8000/api/v1/test/acts/47/6D/1@2020-01-01/", "citations": [{ "target_uri": "/test/acts/47/6C", "target_url": "http://127.0.0.1:8000/api/v1/test/acts/47/6C@2020-01-01/", "target_node": 1660695, "reference_text": "Section 6C", }], } schema = EnactmentSchema(many=False) enactment = schema.load(data) assert len(enactment._cross_references) == 1 def test_load_enactment_with_nested_cross_reference(self): data = { "heading": "Waiver of beard tax in special circumstances", "content": "", "start_date": "1935-04-01", "node": "/test/acts/47/6D", "children": [{ "heading": "", "content": "The Department of Beards shall waive the collection of beard tax upon issuance of beardcoin under Section 6C where the reason the maintainer wears a beard is due to bona fide religious, cultural, or medical reasons.", "start_date": "2013-07-18", "node": "/test/acts/47/6D/1", "children": [], "end_date": None, "url": "http://127.0.0.1:8000/api/v1/test/acts/47/6D/1@2020-01-01", "citations": [{ "target_uri": "/test/acts/47/6C", "target_url": "http://127.0.0.1:8000/api/v1/test/acts/47/6C@2020-01-01", "target_node": 1660695, "reference_text": "Section 6C", }], }], "end_date": None, "url": "http://127.0.0.1:8000/api/v1/test/acts/47/6D@2020-01-01", "citations": [], "parent": "http://127.0.0.1:8000/api/v1/test/acts/47@2020-01-01", } schema = EnactmentSchema(many=False) enactment = schema.load(data) refs = enactment.children[0]._cross_references assert len(refs) == 1
import os from dotenv import load_dotenv import pytest from legislice.download import Client from authorityspoke import Entity, Fact, Predicate, Holding load_dotenv() LEGISLICE_API_TOKEN = os.getenv("LEGISLICE_API_TOKEN") CLIENT = Client(api_token=LEGISLICE_API_TOKEN) class TestAddHoldings: """ Test creating Holdings based on United States v. Harmon. No. 2019-0395 (D.D.C. 2020) (December 24th, 2020) """ @pytest.mark.vcr def test_create_and_add_holdings(self): offense_statute = CLIENT.read("/us/usc/t18/s1960/a") no_license = Fact( predicate=Predicate( content="$business was licensed as a money transmitting business", truth=False, ), terms=Entity(name="Helix"),
class TestEnactments: client = Client(api_token=TOKEN) def test_make_enactment(self, e_search_clause): search_clause = e_search_clause assert search_clause.selected_text().endswith("shall not be violated…") def test_create_enactment_with_init(self, fake_beard_client): """ Using the __init__ method of the Enactment class, instead of readers.read_enactment or the Enactment marshmallow schema. """ beard_definition = fake_beard_client.read("/test/acts/47/4/") assert beard_definition.text.startswith("In this Act, beard") def test_make_enactment_from_selector_without_code(self, fake_usc_client): selector = TextQuoteSelector(suffix=" to their respective") art_3 = fake_usc_client.read("/us/const/article/I/8/8") passage = art_3.select(selector) assert passage.text.startswith("To promote") assert passage.selected_text().endswith("exclusive Right…") def test_make_enactment_from_dict_with_reader(self, fake_usc_client): fourth_a = fake_usc_client.read_from_json( {"node": "/us/const/amendment/IV"}) assert fourth_a.text.endswith( "and the persons or things to be seized.") def test_passage_from_imported_statute(self, fake_usc_client): oracle = loaders.load_decision("oracle_h.json") oracle_decision = Decision(**oracle) reading = DecisionReading(decision=oracle_decision) loaded = loaders.load_holdings("holding_oracle.yaml") holdings = readers.read_holdings(loaded, client=fake_usc_client) reading.posit(holdings) despite_text = str(list(reading.holdings)[5]) assert "In no case does copyright protection " in despite_text def test_chapeau_and_subsections_from_uslm_code(self, fake_beard_client): definition = fake_beard_client.read_from_json( {"node": "/test/acts/47/4"}) assert definition.text.strip().endswith("below the nose.") def test_cite_path_in_str(self, e_search_clause): assert "/us/const/amendment/IV" in str(e_search_clause) def test_unequal_to_statement(self, watt_factor, e_copyright): stole_predicate = Predicate(content="$defendant stole $object") stole_fact = Fact( predicate=stole_predicate, terms=[Entity(name="Alice"), Entity(name="the gold bar")], ) assert not stole_fact.means(e_copyright) with pytest.raises(TypeError): e_copyright.means(watt_factor["f1"]) def test_equal_enactment_text(self, e_due_process_5, e_due_process_14): assert e_due_process_5.means(e_due_process_14) def test_not_gt_if_equal(self, e_search_clause): assert e_search_clause == e_search_clause assert e_search_clause.means(e_search_clause) assert not e_search_clause > e_search_clause def test_enactment_subset_or_equal(self, e_due_process_5, e_due_process_14): assert e_due_process_5 >= e_due_process_14 def test_unequal_enactment_text(self, e_search_clause, e_fourth_a): e_fourth_a.select_all() assert e_search_clause != e_fourth_a def test_enactment_subset(self, e_search_clause, e_fourth_a): e_fourth_a.select_all() assert e_search_clause < e_fourth_a def test_comparison_to_factor_false(self, e_due_process_5, watt_factor): f1 = watt_factor["f1"] assert not e_due_process_5 == f1 def test_implication_of_factor_fails(self, e_due_process_5, watt_factor): f1 = watt_factor["f1"] with pytest.raises(TypeError): assert not e_due_process_5 > f1 def test_implication_by_factor_fails(self, e_due_process_5, watt_factor): f1 = watt_factor["f1"] with pytest.raises(TypeError): assert not e_due_process_5 < f1 def test_read_constitution_for_effective_date(self, fake_usc_client): ex_post_facto_provision = fake_usc_client.read_from_json( {"node": "/us/const/article/I/8/8"}) assert ex_post_facto_provision.start_date == datetime.date(1788, 9, 13) def test_bill_of_rights_effective_date(self, e_search_clause): # December 15, 1791 assert e_search_clause.start_date == datetime.date(1791, 12, 15) def test_date_and_text_from_path_and_regime(self, fake_usc_client): """ This tests assigning the full text of the section as the text of the Enactment, even though no ``exact``, ``prefix``, or ``suffix` parameter was passed to the TextQuoteSelector constructor. """ amendment_12 = fake_usc_client.read_from_json( {"node": "/us/const/amendment/XIV"}) assert amendment_12.start_date == datetime.date(1868, 7, 28) assert "All persons born" in amendment_12.text def test_compare_effective_dates(self, e_due_process_5, e_due_process_14): assert e_due_process_14.start_date > e_due_process_5.start_date def test_invalid_selector_text(self, make_selector): enactment = Enactment( node="/us/const/amendment/IV", heading="", content="Not the same text as in the selector", start_date="2000-01-01", ) with pytest.raises(TextSelectionError): enactment.select(make_selector["bad_selector"]) # Addition def test_add_overlapping_enactments(self, e_search_clause, e_warrants_clause): combined = e_search_clause + e_warrants_clause passage = ("against unreasonable searches and seizures, " + "shall not be violated, " + "and no Warrants shall issue,") assert passage in combined.text def test_add_shorter_plus_longer(self, e_fourth_a, e_search_clause): e_fourth_a.select_all() combined = e_search_clause + e_fourth_a assert combined.selected_text() == e_fourth_a.selected_text() assert combined.means(e_fourth_a) def test_add_longer_plus_shorter(self, e_fourth_a, e_search_clause): e_fourth_a.select_all() combined = e_fourth_a + e_search_clause assert combined.selected_text() == e_fourth_a.selected_text() assert combined.means(e_fourth_a) def test_consolidate_adjacent_passages(self, make_response): client = FakeClient(responses=make_response) copyright_clause = client.read("/us/const/article/I/8/8") copyright_statute = client.read("/us/usc/t17/s102/b") passage = copyright_clause.select(None) securing_for_authors = passage + ( "To promote the Progress of Science and " "useful Arts, by securing for limited Times to Authors") and_inventors = passage + "and Inventors" right_to_writings = passage + "the exclusive Right to their respective Writings" to_combine = [ copyright_statute, securing_for_authors, and_inventors, right_to_writings, ] combined = EnactmentGroup(passages=to_combine) assert len(combined) == 2 assert any( law.selected_text().startswith("To promote the Progress") and law.selected_text().endswith("their respective Writings…") for law in combined) def test_do_not_consolidate_from_different_sections(self, make_response): client = FakeClient(responses=make_response) due_process_5 = client.read("/us/const/amendment/V") due_process_14 = client.read("/us/const/amendment/XIV") due_process_5.select( "life, liberty, or property, without due process of law") due_process_14.select( "life, liberty, or property, without due process of law") combined = EnactmentGroup(passages=[due_process_5, due_process_14]) assert len(combined) == 2 def test_cannot_add_fact_to_enactment(self, watt_factor, e_search_clause): with pytest.raises(ValidationError): print(e_search_clause + watt_factor["f3"]) def test_cannot_add_enactment_to_statement(self, e_search_clause): statement = Fact( predicate=Predicate(content="$person committed a murder"), terms=Entity(name="Al"), ) with pytest.raises(TypeError): statement + e_search_clause def test_cannot_add_statement_to_enactment(self, e_search_clause): statement = Fact( predicate=Predicate(content="$person committed a murder"), terms=Entity(name="Al"), ) with pytest.raises(ValidationError): e_search_clause + statement def test_cant_add_enactment_that_is_not_ancestor_or_descendant( self, e_search_clause, e_copyright): with pytest.raises(ValueError): e_search_clause + e_copyright
class TestLoadAndSelect: client = Client() client.coverage["/us/usc"] = { "earliest_in_db": date(1750, 1, 1), "first_published": date(1750, 1, 1), } response = { "heading": "", "start_date": "2013-07-18", "node": "/us/usc/t18/s1960/b/1", "text_version": { "id": 943740, "url": "https://authorityspoke.com/api/v1/textversions/943740/", "content": "the term “unlicensed money transmitting business” means a money transmitting business which affects interstate or foreign commerce in any manner or degree and—", }, "url": "https://authorityspoke.com/api/v1/us/usc/t18/s1960/b/1/", "end_date": None, "children": [ { "heading": "", "start_date": "2013-07-18", "node": "/us/usc/t18/s1960/b/1/A", "text_version": { "id": 943737, "url": "https://authorityspoke.com/api/v1/textversions/943737/", "content": "is operated without an appropriate money transmitting license in a State where such operation is punishable as a misdemeanor or a felony under State law, whether or not the defendant knew that the operation was required to be licensed or that the operation was so punishable;", }, "url": "https://authorityspoke.com/api/v1/us/usc/t18/s1960/b/1/A/", "end_date": None, "children": [], "citations": [], }, { "heading": "", "start_date": "2013-07-18", "node": "/us/usc/t18/s1960/b/1/B", "text_version": { "id": 943738, "url": "https://authorityspoke.com/api/v1/textversions/943738/", "content": "fails to comply with the money transmitting business registration requirements under section 5330 of title 31, United States Code, or regulations prescribed under such section; or", }, "url": "https://authorityspoke.com/api/v1/us/usc/t18/s1960/b/1/B/", "end_date": None, "children": [], "citations": [], }, { "heading": "", "start_date": "2013-07-18", "node": "/us/usc/t18/s1960/b/1/C", "text_version": { "id": 943739, "url": "https://authorityspoke.com/api/v1/textversions/943739/", "content": "otherwise involves the transportation or transmission of funds that are known to the defendant to have been derived from a criminal offense or are intended to be used to promote or support unlawful activity;", }, "url": "https://authorityspoke.com/api/v1/us/usc/t18/s1960/b/1/C/", "end_date": None, "children": [], "citations": [], }, ], "citations": [], "parent": "https://authorityspoke.com/api/v1/us/usc/t18/s1960/b/", } def test_select_text_with_end_param(self): law = self.client.read_from_json(self.response) law.select(end="or a felony under State law") assert law.selected_text().endswith("or a felony under State law…") def test_end_param_has_no_effect_when_nothing_selected(self): law = self.client.read_from_json(self.response) law.select(selection=False, end="or a felony under State law") assert law.selected_text() == ""
class TestExclusiveFlag: client = Client(api_token=TOKEN) def test_holding_flagged_exclusive( self, e_securing_exclusive_right_to_writings, e_copyright_requires_originality, make_response, ): """ Test that "exclusive" flag doesn't mess up the holding where it's placed. Test whether the Feist opinion object includes a holding with the output "Rural's telephone directory was copyrightable" and the input "Rural's telephone directory was original", when that holding was marked "exclusive" in the JSON. `originality_rule` will be a little broader because it's based on less Enactment text """ fake_client = FakeClient(responses=make_response) holdings = read_holdings_from_file("holding_feist.yaml", client=fake_client) directory = Entity(name="Rural's telephone directory") original = Fact( predicate=Predicate(content="$work was an original work"), terms=directory) copyrightable = Fact( predicate=Predicate(content="$work was copyrightable"), terms=directory) originality_enactments = [ e_securing_exclusive_right_to_writings, e_copyright_requires_originality, ] originality_rule = Rule( procedure=Procedure(outputs=copyrightable, inputs=original), mandatory=False, universal=False, enactments=originality_enactments, ) assert any( originality_rule.implies(feist_holding.rule) for feist_holding in holdings) def test_fact_containing_wrong_type(self, make_response): mock_client = FakeClient(responses=make_response) to_read = load_holdings("holding_feist.yaml") to_read[0]["outputs"]["type"] = "wrong_type" with pytest.raises(ValidationError): readers.read_holdings([to_read[0]], client=mock_client) def test_type_field_removed_from_factor(self, make_response): mock_client = FakeClient(responses=make_response) to_read = load_holdings("holding_feist.yaml") holdings = readers.read_holdings([to_read[0]], client=mock_client) assert holdings[0].inputs[0].__dict__.get("type") is None @pytest.mark.xfail def test_holding_inferred_from_exclusive(self, make_enactment, make_response): """ Test whether the Feist opinion object includes a holding that was inferred from an entry in the JSON saying that the "exclusive" way to reach the output "Rural's telephone directory was copyrightable" is to have the input "Rural's telephone directory was original". The inferred holding says that in the absence of the input "Rural's telephone directory was original", the court MUST ALWAYS find the output to be absent as well. Marked xfail because the "exclusive" flag no longer causes inferred Holdings to be expanded. Instead, it now should generate inferred Rules that aren't expanded during data loading. """ mock_client = FakeClient(responses=make_response) to_read = load_holdings("holding_feist.yaml") feist_holdings = readers.read_holdings(to_read["holdings"], client=mock_client) directory = Entity(name="Rural's telephone directory") not_original = Fact(Predicate(content="{} was an original work"), directory, absent=True) not_copyrightable = Fact(Predicate(content="{} was copyrightable"), directory, absent=True) no_originality_procedure = Procedure(outputs=not_copyrightable, inputs=not_original) no_originality_rule = Rule( no_originality_procedure, mandatory=True, universal=True, enactments=[ make_enactment["securing_for_authors"], make_enactment["right_to_writings"], make_enactment["copyright_requires_originality"], ], ) assert feist_holdings[4].rule.means(no_originality_rule) def test_exclusive_does_not_result_in_more_holdings(self, make_response): """ The intended behavior is now for the Holding to assert that its Rule is the "exclusive" way to reach the outputs, and to have an additional function that can generate additional Rules that can be inferred from the exclusive flag. "Implies" and "contradict" methods will be able to look at the Holding's generated Rules as well as its original Rule. """ mock_client = FakeClient(responses=make_response) feist_json = load_holdings("holding_feist.yaml") feist_holdings = readers.read_holdings(feist_json, client=mock_client) assert len(feist_holdings) == len(feist_json)
def test_wrong_api_token(self): bad_client = Client(api_token="wr0ngToken") with pytest.raises(LegisliceTokenError): bad_client.fetch(query="/test/acts/47/1")
from nettlesome.predicates import Predicate from nettlesome.quantities import Comparison, Q_ from nettlesome.statements import Statement import pytest from authorityspoke.facts import Fact from authorityspoke.holdings import Holding from authorityspoke.procedures import Procedure from authorityspoke.rules import Rule from authorityspoke.io import loaders, readers from authorityspoke.io.fake_enactments import FakeClient load_dotenv() TOKEN = os.getenv("LEGISLICE_API_TOKEN") legislice_client = Client(api_token=TOKEN) class TestRules: def test_enactment_type_in_str(self, make_holding): assert "const" in str(make_holding["h1"]).lower() def test_no_blank_line_in_str(self, make_holding): assert "\n\n" not in str(make_holding["h2"]) def test_enactment_text_in_str(self, make_holding): assert "secure in their persons" in str(make_holding["h1"]) def test_None_not_in_str(self, make_holding): assert "None" not in str(make_holding["h2"])
class TestStatuteRules: """ Tests from the statute_rules Jupyter Notebook. """ client = Client(api_token=TOKEN) def test_greater_than_implies_equal(self, beard_response, make_beard_rule): client = FakeClient(responses=beard_response) beard_dictionary = loaders.load_holdings("beard_rules.yaml") beard_dictionary[0]["inputs"][1][ "content"] = "the length of the suspected beard was = 8 millimetres" longer_hair_rule = readers.read_holdings([beard_dictionary[0]], client=client) assert make_beard_rule[0].implies(longer_hair_rule[0]) def test_reset_inputs_to_create_contradiction(self, beard_response, make_beard_rule): """Test missing 'False' truth value in output of long_means_not_beard""" ear_rule = make_beard_rule[1] client = FakeClient(responses=beard_response) beard_rule_data = loaders.load_holdings("beard_rules.yaml")[:2] changed_holdings = readers.read_holdings(beard_rule_data, client=client) long_means_not_beard = changed_holdings[1] long_means_not_beard.set_despite( [ear_rule.inputs[0], ear_rule.inputs[2]]) fact = Fact( content="the length of ${the_suspected_beard} was >= 12 inches", terms=[Entity(name="the suspected beard")], ) long_means_not_beard.set_inputs(fact) long_means_not_beard.set_outputs( long_means_not_beard.outputs[0].negated()) long_means_not_beard.rule.mandatory = True assert long_means_not_beard.contradicts(ear_rule) def test_greater_than_contradicts_not_greater(self, beard_response, make_beard_rule): client = FakeClient(responses=beard_response) beard_dictionary = loaders.load_holdings("beard_rules.yaml") beard_dictionary[1]["inputs"][1][ "content"] = "the length of the suspected beard was >= 12 inches" beard_dictionary[1]["outputs"][0]["truth"] = False beard_dictionary[1]["mandatory"] = True long_hair_is_not_a_beard = readers.read_holdings([beard_dictionary[1]], client=client) assert make_beard_rule[1].contradicts(long_hair_is_not_a_beard[0]) def test_contradictory_fact_about_beard_length(self, fake_beard_client, make_beard_rule): beard_dictionary = loaders.load_holdings("beard_rules.yaml") long_means_not_beard = readers.read_holdings( beard_dictionary[1], client=fake_beard_client)[0].rule long_means_not_beard.set_despite( [long_means_not_beard.inputs[0], long_means_not_beard.inputs[2]]) long_means_not_beard.set_inputs([long_means_not_beard.inputs[1]]) long_means_not_beard.set_outputs( [long_means_not_beard.outputs[0].negated()]) long_means_not_beard.mandatory = True assert make_beard_rule[1].contradicts(long_means_not_beard) assert long_means_not_beard.contradicts(make_beard_rule[1]) @pytest.mark.parametrize( ("facial_hair_over_5mm, facial_hair_on_or_below_chin, " "facial_hair_uninterrupted, outcome"), ( [False, False, True, False], [False, False, False, False], [False, True, False, False], [False, True, True, False], [True, False, True, True], [True, False, False, False], [True, True, True, True], [True, True, None, True], [True, None, True, True], ), ) def test_is_beard_implied( self, facial_hair_over_5mm, facial_hair_on_or_below_chin, facial_hair_uninterrupted, outcome, fake_beard_client, make_beard_rule, ): beard = Entity(name="a facial feature") sec_4 = fake_beard_client.read("/test/acts/47/4/") was_facial_hair = Predicate(content="$thing was facial hair") fact_was_facial_hair = Fact(predicate=was_facial_hair, terms=beard) hypothetical = Rule( procedure=Procedure( inputs=[ fact_was_facial_hair, Fact( predicate=Comparison( content="the length of $thing was", sign=">=", expression=Q_("5 millimeters"), truth=facial_hair_over_5mm, ), terms=beard, ), Fact( predicate=Predicate( content="$thing occurred on or below the chin", truth=facial_hair_on_or_below_chin, ), terms=beard, ), Fact( predicate=Predicate( content= "$thing existed in an uninterrupted line from the front " "of one ear to the front of the other ear below the nose", truth=facial_hair_uninterrupted, ), terms=beard, ), ], outputs=Fact(predicate=Predicate(content="$thing was a beard"), terms=beard), ), enactments=sec_4, ) meets_chin_test = make_beard_rule[0].implies(hypothetical) meets_ear_test = make_beard_rule[1].implies(hypothetical) assert outcome == meets_chin_test or meets_ear_test def test_adding_definition_of_transfer(self, make_beard_rule): loan_is_transfer = make_beard_rule[7] elements_of_offense = make_beard_rule[11] loan_without_exceptions = (loan_is_transfer + elements_of_offense.inputs[1] + elements_of_offense.inputs[2] + elements_of_offense.enactments[1]) combined = loan_without_exceptions + elements_of_offense assert combined
class TestEnactmentImport: client = Client(api_token=TOKEN) test_enactment = { "heading": "", "text_version": "Except as otherwise provided by statute, all relevant evidence is admissible.", "name": "s351", "node": "/us-ca/code/evid/s351", "start_date": "1966-01-01", } def test_enactment_from_dict(self, fake_usc_client): enactment = fake_usc_client.read_from_json(self.test_enactment) assert "all relevant evidence is admissible" in enactment.text def test_enactment_with_anchor(self, fake_usc_client, make_response): fourteenth_dp = make_response["/us/const/amendment/XIV"]["1868-07-28"][ "children"][0] enactment = fake_usc_client.read_from_json(fourteenth_dp) passage = enactment.select("nor shall any State deprive any person") assert passage.selected_text().startswith("…nor shall any State") @pytest.mark.vcr def test_enactment_import_from_yaml(self): holding_brad = load_holdings("holding_brad.yaml") holdings = readers.read_holdings(holding_brad, client=self.client) enactments = holdings[0].enactments assert any(law.selected_text().endswith("shall not be violated…") for law in enactments) def test_enactment_import_from_holding(self): holding_cardenas = load_holdings("holding_cardenas.yaml") holdings = readers.read_holdings(holding_cardenas) enactment_list = holdings[0].enactments assert any("all relevant evidence is admissible" in enactment.text for enactment in enactment_list) @pytest.mark.vcr def test_enactment_does_not_fail_for_excess_selector( self, fake_beard_client): """ Test selector that extends into the text of a subnode. Demonstrates that the API has downloaded the entire text of the provision and included it in the Enactment object. """ exact = ( "In this Act, beard means any facial hair no shorter " "than 5 millimetres in length that: occurs on or below the chin") record = { "enactment": { "node": "/test/acts/47/4" }, "selection": { "quotes": { "exact": exact } }, } client = self.client passage = client.read_passage_from_json(record) assert passage.selected_text() == exact + "…" assert "in an uninterrupted line" in passage.enactment.children[ 1].content