Skip to content

Commit

Permalink
update doctests in statute guide
Browse files Browse the repository at this point in the history
  • Loading branch information
mscarey committed May 21, 2021
1 parent 5f78186 commit 0020c54
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 49 deletions.
4 changes: 2 additions & 2 deletions authorityspoke/evidence.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def __str__(self):
+ f'{("asserting " + self.statement.short_string + ", ") if self.statement else ""}'
)
string = super().__str__().format(string)
return string.replace("exhibit", self.form or "exhibit").strip().strip(",")
return string.replace("exhibit", self.form or "exhibit").strip()

@property
def wrapped_string(self):
Expand Down Expand Up @@ -144,7 +144,7 @@ class Evidence(Factor):

def __str__(self):
string = (
f'{("of " + self.exhibit.short_string + ", ") if self.exhibit else ""}'
f'{("of " + self.exhibit.short_string + " ") if self.exhibit else ""}'
+ f'{("which supports " + self.to_effect.short_string) if self.to_effect else ""}'
)
return super().__str__().format(string).strip().replace("Evidence", "evidence")
Expand Down
6 changes: 6 additions & 0 deletions docs/guides/example_holdings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ The text delivered by the
collected from print sources, so it will contain some Optical
Character Recognition errors.

>>> from authorityspoke.io.loaders import load_decision
>>> from authorityspoke.io.readers import read_decision
>>> oracle_download = load_decision("oracle_h.json")
>>> lotus_download = load_decision("lotus_h.json")
>>> oracle = read_decision(oracle_download)
>>> lotus = read_decision(lotus_download)

*Lotus v. Borland* 49 F.3d 807 (1995)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
23 changes: 12 additions & 11 deletions docs/guides/load_yaml_holdings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ documentation <https://saurabh-kumar.com/python-dotenv/#getting-started>`__.
>>> import os
>>> from dotenv import load_dotenv
>>> load_dotenv()
True
>>> CAP_API_KEY = os.getenv('CAP_API_KEY')

Next, we'll create a :class:`~authorityspoke.io.downloads.CAPClient` object,
Expand All @@ -58,7 +59,7 @@ citation of the case we want, we'll use the :meth:`~authorityspoke.io.downloads.
Because we used ``full_case=True``, we have the option to view the full
text of the majority opinion using the command
``licensing_case.majority.text``.


Creating Holdings with Python
-----------------------------
Expand Down Expand Up @@ -216,9 +217,9 @@ Factors and Entities in AuthoritySpoke YAML
The fields ``inputs``, ``outputs``, and ``despite`` should each contain
a list of :class:`~nettlesome.factors.Factor`\s. (If any of them is an empty list with no Factors,
then it can be omitted.) A :class:`~nettlesome.factors.Factor` can be any of several ``type``\ s,
including :class:`~authorityspoke.facts.Fact`\, :class:`~authorityspoke.evidence.Evidence`\,
including :class:`~authorityspoke.facts.Fact`\, :class:`~authorityspoke.evidence.Evidence`\,
:class:`~authorityspoke.evidence.Exhibit`\, :class:`~authorityspoke.pleadings.Pleading`\, or
:class:`~authorityspoke.pleadings.Allegation`\. Let's add one :class:`~nettlesome.factors.Factor`
:class:`~authorityspoke.pleadings.Allegation`\. Let's add one :class:`~nettlesome.factors.Factor`
to the ``inputs`` field of the first :class:`~authorityspoke.holdings.Holding`\.

::
Expand All @@ -236,12 +237,12 @@ factor is being displayed visually as an annotation to the opinion). In
this case, we simply copied the full text of the phrase from the :class:`~authorityspoke.opinions.Opinion`
where the anchor should be
placed. However, as we'll see later, we also could have used the
:class:`~anchorpoint.textselectors.TextQuoteSelector` syntax from
:class:`~anchorpoint.textselectors.TextQuoteSelector` syntax from
the `anchorpoint <https://anchorpoint.readthedocs.io/en/latest/>`__ package.

The pairs of curly brackets in the "content" field above also have
special meaning. A bracketed phrase in a ``content`` field identifies an
:class:`~authorityspoke.entities.Entity`\. Typically
:class:`~authorityspoke.entities.Entity`\. Typically
an ``Entity`` is a person or party, but important
objects or concepts can also be labelled as class ``Entity``. If you
identify a phrase as an ``Entity`` by putting brackets around it, the
Expand Down Expand Up @@ -494,12 +495,12 @@ Assigning Names to Factors and Enactments in YAML
-------------------------------------------------

The YAML data input format is still verbose, but there's one more
feature we can use to shorten it. If a :class:`~nettlesome.factors.Factor`
feature we can use to shorten it. If a :class:`~nettlesome.factors.Factor`
or :class:`~legislice.enactments.Enactment` is going to
be used more than once in the same file, we can add a ``name`` field to
the YAML for that object. Then, anytime the same object needs to be
reused, we can just repeat the object's ``name`` rather than rewriting the
whole object.
whole object.

.. warning::
Similar to the names of Entities as discussed above, any
Expand Down Expand Up @@ -576,10 +577,10 @@ Now when we load a file with this YAML, we'll get both Holdings.
>>> len(both_holdings_with_anchors.holdings)
2

Now that we generated this :class:`~authorityspoke.opinions.AnchoredHoldings` object
containing the data from the YAML file, we can use the posit method to link those
:class:`~authorityspoke.holdings.Holding`\s to the judicial :class:`~authorityspoke.decisions.Decision`
we created from the data we downloaded from the CAP API. Then we can verify that
Now that we generated this :class:`~authorityspoke.opinions.AnchoredHoldings` object
containing the data from the YAML file, we can use the posit method to link those
:class:`~authorityspoke.holdings.Holding`\s to the judicial :class:`~authorityspoke.decisions.Decision`
we created from the data we downloaded from the CAP API. Then we can verify that
those two Holdings are now considered the two holdings of the Decision.

>>> licensing_case.posit(both_holdings_with_anchors)
Expand Down
72 changes: 37 additions & 35 deletions docs/guides/statute_rules.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,20 +54,24 @@ Python instead of loading them from a JSON file. For details, see the
manual <https://authorityspoke.readthedocs.io/en/latest/>`__. Here’s an
example of one JSON rule annotation.

>>> from pprint import pprint
>>> from authorityspoke.io import loaders
>>> beard_dictionary = loaders.load_holdings("beard_rules.json")
>>> beard_dictionary[0]
>>> pprint(beard_dictionary[0], sort_dicts=False)
{'inputs': [{'type': 'fact',
'content': '{the suspected beard} was facial hair'},
{'type': 'fact',
'content': 'the length of the suspected beard was >= 5 millimetres'},
{'type': 'fact',
'content': 'the suspected beard occurred on or below the chin'}],
'content': '{the suspected beard} was facial hair'},
{'type': 'fact',
'content': 'the length of the suspected beard was >= 5 '
'millimetres'},
{'type': 'fact',
'content': 'the suspected beard occurred on or below the chin'}],
'outputs': [{'type': 'fact',
'content': 'the suspected beard was a beard',
'name': 'the fact that the facial hair was a beard'}],
'content': 'the suspected beard was a beard',
'name': 'the fact that the facial hair was a beard'}],
'enactments': [{'node': '/test/acts/47/4',
'exact': 'In this Act, beard means any facial hair no shorter than 5 millimetres in length that: occurs on or below the chin'}],
'exact': 'In this Act, beard means any facial hair no shorter '
'than 5 millimetres in length that: occurs on or '
'below the chin'}],
'universal': True}


Expand All @@ -86,29 +90,28 @@ describe two ways that an object can be defined to be a “beard”.
>>> print(beard_rules[0])
the Rule that the court MAY ALWAYS impose the
RESULT:
the Fact that <the suspected beard> was a beard
the fact that <the suspected beard> was a beard
GIVEN:
the Fact that <the suspected beard> was facial hair
the Fact that the length of <the suspected beard> was at least 5
the fact that <the suspected beard> was facial hair
the fact that the length of <the suspected beard> was at least 5
millimeter
the Fact that <the suspected beard> occurred on or below the chin
the fact that <the suspected beard> occurred on or below the chin
GIVEN the ENACTMENT:
"In this Act, beard means any facial hair no shorter than 5 millimetres in length that: occurs on or below the chin…" (/test/acts/47/4 1935-04-01)


>>> print(beard_rules[1])
the Rule that the court MAY ALWAYS impose the
RESULT:
the Fact that <the suspected beard> was a beard
the fact that <the suspected beard> was a beard
GIVEN:
the Fact that <the suspected beard> was facial hair
the Fact that the length of <the suspected beard> was at least 5
the fact that <the suspected beard> was facial hair
the fact that the length of <the suspected beard> was at least 5
millimeter
the Fact that <the suspected beard> existed in an uninterrupted line
the fact that <the suspected beard> existed in an uninterrupted line
from the front of one ear to the front of the other ear below the nose
GIVEN the ENACTMENTS:
GIVEN the ENACTMENT:
"In this Act, beard means any facial hair no shorter than 5 millimetres in length that:…exists in an uninterrupted line from the front of one ear to the front of the other ear below the nose." (/test/acts/47/4 1935-04-01)
"exists in an uninterrupted line from the front of one ear to the front of the other ear below the nose." (/test/acts/47/4/b 1935-04-01)


The difference between these two Rules is that the first one applies to
Expand Down Expand Up @@ -139,12 +142,12 @@ we can determine that the original “chin rule” implies our new Rule.
>>> print(longer_hair_rule)
the Rule that the court MAY ALWAYS impose the
RESULT:
the Fact that <the suspected beard> was a beard
the fact that <the suspected beard> was a beard
GIVEN:
the Fact that <the suspected beard> was facial hair
the Fact that the length of <the suspected beard> was exactly equal to
the fact that <the suspected beard> was facial hair
the fact that the length of <the suspected beard> was exactly equal to
8 millimeter
the Fact that <the suspected beard> occurred on or below the chin
the fact that <the suspected beard> occurred on or below the chin
GIVEN the ENACTMENT:
"In this Act, beard means any facial hair no shorter than 5 millimetres in length that: occurs on or below the chin…" (/test/acts/47/4 1935-04-01)

Expand All @@ -161,27 +164,26 @@ library). And we can show that this new Rule contradicts a Rule that
came from the Beard Tax Act.

>>> beard_dictionary[1]["despite"] = [
>>> beard_dictionary[1]["inputs"][0],
>>> beard_dictionary[1]["inputs"][2],
>>> ]
... beard_dictionary[1]["inputs"][0],
... beard_dictionary[1]["inputs"][2]]
>>> beard_dictionary[1]["inputs"] = {
"type": "fact",
"content": "the length of the suspected beard was >= 12 inches",
}
... "type": "fact",
... "content": "the length of the suspected beard was >= 12 inches"}
>>> beard_dictionary[1]["outputs"][0]["truth"] = False
>>> beard_dictionary[1]["mandatory"] = True
>>> long_means_not_beard = readers.read_rule(beard_dictionary[1], client=legis_client)
>>> print(long_means_not_beard)
the Rule that the court MUST ALWAYS impose the
RESULT:
the Fact it is false that <the suspected beard> was a beard
the fact it was false that <the suspected beard> was a beard
GIVEN:
the Fact that the length of <the suspected beard> was at least 12 inch
the fact that the length of <the suspected beard> was at least 12 inch
DESPITE:
the Fact that <the suspected beard> was facial hair
GIVEN the ENACTMENTS:
the fact that <the suspected beard> was facial hair
the fact that <the suspected beard> existed in an uninterrupted line
from the front of one ear to the front of the other ear below the nose
GIVEN the ENACTMENT:
"In this Act, beard means any facial hair no shorter than 5 millimetres in length that:…exists in an uninterrupted line from the front of one ear to the front of the other ear below the nose." (/test/acts/47/4 1935-04-01)
"exists in an uninterrupted line from the front of one ear to the front of the other ear below the nose." (/test/acts/47/4/b 1935-04-01)



Expand Down Expand Up @@ -234,7 +236,7 @@ Here are the two Rules we’ll be adding together.
the Fact it is false that <the counterparty> was <the Department of
Beards>
DESPITE:
the Fact that the token attributed to <the Department of Beards>,
the fact that the token attributed to <the Department of Beards>,
asserting the fact that <the Department of Beards> granted an
exemption from the prohibition of wearing beards, was counterfeit
GIVEN the ENACTMENTS:
Expand Down
2 changes: 1 addition & 1 deletion tests/test_exhibits.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def test_exhibit_short_string(self, make_exhibit):
make_exhibit["no_shooting_testimony"].short_string.lower()
== (
"the testimony attributed to <Alice>, asserting "
"the fact it was false that <Alice> shot <Bob>"
"the fact it was false that <Alice> shot <Bob>,"
).lower()
)

Expand Down

0 comments on commit 0020c54

Please sign in to comment.