Пример #1
0
 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"
Пример #2
0
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
Пример #3
0
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),
            )
Пример #4
0
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")'
        )
Пример #5
0
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"
Пример #6
0
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."
Пример #7
0
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
Пример #8
0
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"])
Пример #9
0
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")
Пример #10
0
 def test_no_api_token(self):
     bad_client = Client()
     with pytest.raises(LegisliceTokenError):
         bad_client.fetch(query="/test/acts/47/1")
Пример #11
0
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("/")
Пример #12
0
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"
Пример #13
0
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")
Пример #14
0
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
Пример #15
0
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"),
Пример #16
0
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
Пример #17
0
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() == ""
Пример #18
0
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)
Пример #19
0
 def test_wrong_api_token(self):
     bad_client = Client(api_token="wr0ngToken")
     with pytest.raises(LegisliceTokenError):
         bad_client.fetch(query="/test/acts/47/1")
Пример #20
0
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"])
Пример #21
0
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
Пример #22
0
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